1 // Copyright (C) 2013 CEA/DEN, EDF R&D, OPEN CASCADE
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License.
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 // Lesser General Public License for more details.
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
20 // File: CurveCreator_Curve.cxx
21 // Author: Sergey KHROMOV
23 #include "CurveCreator_Curve.hxx"
25 #include "CurveCreator.hxx"
26 #include "CurveCreator_Section.hxx"
27 #include "CurveCreator_Displayer.h"
29 #include <AIS_Point.hxx>
30 #include <AIS_Line.hxx>
31 #include <AIS_Shape.hxx>
32 #include <BRepBuilderAPI_MakeEdge.hxx>
33 #include <BRepBuilderAPI_MakeWire.hxx>
34 #include <Geom_CartesianPoint.hxx>
37 #include <TopoDS_Edge.hxx>
38 #include <TopoDS_Face.hxx>
39 #include <TopoDS_Wire.hxx>
40 #include <TColgp_HArray1OfPnt.hxx>
41 #include <GeomAPI_Interpolate.hxx>
45 //=======================================================================
46 // function: Constructor
48 //=======================================================================
49 CurveCreator_Curve::CurveCreator_Curve( const CurveCreator::Dimension theDimension )
51 myDimension (theDimension),
60 //=======================================================================
61 // function: Destructor
63 //=======================================================================
64 CurveCreator_Curve::~CurveCreator_Curve()
66 // Delete all allocated data.
70 //=======================================================================
71 // function: getDimension
73 //=======================================================================
74 CurveCreator::Dimension CurveCreator_Curve::getDimension() const
79 //=======================================================================
80 // function: getUniqSectionName
81 // purpose: return unique section name
82 //=======================================================================
83 std::string CurveCreator_Curve::getUniqSectionName() const
85 for( int i = 0 ; i < 1000000 ; i++ ){
87 sprintf( aBuffer, "Section_%d", i+1 );
88 std::string aName(aBuffer);
90 for( j = 0 ; j < mySections.size() ; j++ ){
91 if( mySections[j]->myName == aName )
94 if( j == mySections.size() )
100 //=======================================================================
101 // function: setDisplayer
102 // purpose: set curve changes Displayer
103 //=======================================================================
104 void CurveCreator_Curve::setDisplayer( CurveCreator_Displayer* theDisplayer )
106 myDisplayer = theDisplayer;
109 //=======================================================================
110 // function: removeDisplayer
111 // purpose: remove the attached Displayer
112 //=======================================================================
113 void CurveCreator_Curve::removeDisplayer()
118 //=======================================================================
121 //=======================================================================
122 bool CurveCreator_Curve::addEmptyDiff()
124 bool isEnabled = false;
126 if (myUndoDepth != 0) {
127 // Forget all Redos after the current one.
130 myListDiffs.erase(myCurrenPos, myListDiffs.end());
133 if (myUndoDepth == -1 || myNbUndos < myUndoDepth) {
134 // Increase the number of undos.
137 // If there are too many differences, remove the first one.
138 myListDiffs.pop_front();
141 // Add new difference.
142 myListDiffs.push_back(CurveCreator_Diff());
143 myCurrenPos = myListDiffs.end();
150 void CurveCreator_Curve::startOperation()
155 void CurveCreator_Curve::finishOperation()
160 //=======================================================================
161 // function: toICoord
163 //=======================================================================
164 int CurveCreator_Curve::toICoord(const int theIPnt) const
166 return theIPnt * myDimension;
169 std::vector<Handle_AIS_InteractiveObject> CurveCreator_Curve::constructSection( int theISection ) const
171 std::vector<Handle_AIS_InteractiveObject> aSectionRepresentation;
173 CurveCreator::SectionType aSectType = getSectionType( theISection );
174 int aSectSize = getNbPoints( theISection );
175 bool aSectIsClosed = isClosed( theISection );
177 if( aSectType == CurveCreator::Polyline )
180 for( ; iPoint < ( aSectSize - 1 ) ; iPoint++ ){
181 Handle_AIS_Point anAISPnt = getAISPoint(theISection, iPoint);
182 aSectionRepresentation.push_back( anAISPnt );
183 Handle_AIS_Line aLine = getAISLine( theISection, iPoint, iPoint+1 );
184 aSectionRepresentation.push_back( aLine );
186 if( aSectSize != 0 ){
187 Handle_AIS_Point anAISPnt = getAISPoint(theISection, iPoint);
188 aSectionRepresentation.push_back( anAISPnt );
189 if( isClosed(theISection) && ( aSectSize > 1 ) ){
190 Handle_AIS_Line aLine = getAISLine( theISection, iPoint, 0 );
191 aSectionRepresentation.push_back( aLine );
195 else if( aSectType == CurveCreator::Spline )
197 std::vector<double> aPoints;
198 for( int iPoint = 0; iPoint < aSectSize; iPoint++ )
200 Handle_AIS_Point anAISPnt = getAISPoint( theISection, iPoint );
201 aSectionRepresentation.push_back( anAISPnt );
203 CurveCreator::Coordinates aCoords = getPoint( theISection, iPoint );
204 double aX = aCoords[0];
205 double aY = aCoords[1];
206 double aZ = aCoords[2];
207 aPoints.push_back( aX );
208 aPoints.push_back( aY );
213 Handle(Geom_BSplineCurve) aBSplineCurve;
214 // fill array for algorithm by the received coordinates
215 int aLen = aPoints.size() / 2;
216 Handle(TColgp_HArray1OfPnt) aHCurvePoints = new TColgp_HArray1OfPnt (1, aLen);
217 std::vector<double>::const_iterator aListIter = aPoints.begin();
218 for (int ind = 1; ind <= aLen; ind++) {
219 gp_Pnt aPnt(gp::Origin());
220 aPnt.SetX(*aListIter);
222 aPnt.SetY(*aListIter);
225 aHCurvePoints->SetValue(ind, aPnt);
228 GeomAPI_Interpolate aGBC(aHCurvePoints, aSectIsClosed, gp::Resolution());
231 aBSplineCurve = aGBC.Curve();
233 TopoDS_Edge anEdge = BRepBuilderAPI_MakeEdge( aBSplineCurve ).Edge();
235 TopoDS_Wire aWire = BRepBuilderAPI_MakeWire( anEdge ).Wire();
237 Handle(AIS_Shape) aShape = new AIS_Shape( aWire );
238 aSectionRepresentation.push_back( aShape );
241 return aSectionRepresentation;
244 //=======================================================================
245 // function: setUndoDepth
247 //=======================================================================
248 void CurveCreator_Curve::setUndoDepth(const int theDepth)
251 // Reset all undo/redo data.
255 myCurrenPos = myListDiffs.end();
257 } else if (theDepth == -1) {
258 // There is nothing to do as the depth become unlimited.
260 } else if (theDepth > 0) {
261 // The new "real" depth is set.
262 if (theDepth < myNbRedos) {
263 // The new depth is less then number of redos. Remove the latest redos.
264 int aShift = (myNbRedos - theDepth);
265 ListDiff::iterator aFromPos = myListDiffs.end();
271 myListDiffs.erase(aFromPos, myListDiffs.end());
272 myNbRedos = theDepth;
275 if (theDepth < myNbUndos + myNbRedos) {
276 // The new depth is less then the total number of differences.
277 // Remove the first undos.
278 int aShift = (myNbUndos + myNbRedos - theDepth);
279 ListDiff::iterator aToPos = myListDiffs.begin();
285 myListDiffs.erase(myListDiffs.begin(), aToPos);
286 myNbUndos = theDepth - myNbRedos;
289 myUndoDepth = theDepth;
293 //=======================================================================
294 // function: getUndoDepth
296 //=======================================================================
297 int CurveCreator_Curve::getUndoDepth() const
302 Handle_AIS_Point CurveCreator_Curve::getAISPoint( int theISection, int theIPoint ) const
305 getCoordinates( theISection, theIPoint, anX, anY, aZ );
306 gp_Pnt aPoint( anX, anY, aZ);
308 AIS_Point* aPnt = new AIS_Point( new Geom_CartesianPoint(aPoint));
312 Handle_AIS_Line CurveCreator_Curve::getAISLine( int theISection, int theIPoint1, int theIPoint2 ) const
315 getCoordinates( theISection, theIPoint1, anX, anY, aZ );
316 gp_Pnt aPoint1( anX, anY, aZ);
318 double anX2, anY2, aZ2;
319 getCoordinates( theISection, theIPoint2, anX2, anY2, aZ2 );
320 //MTN to avoid crash during line construction
321 if( ( anX == anX2 ) && ( anY == anY2 ) && (aZ == aZ2 ) ){
325 gp_Pnt aPoint2( anX2, anY2, aZ2 );
327 AIS_Line* aLine = new AIS_Line( new Geom_CartesianPoint(aPoint1), new Geom_CartesianPoint(aPoint2) );
331 void CurveCreator_Curve::getCoordinates( int theISection, int theIPoint, double& theX, double& theY, double& theZ ) const
333 CurveCreator::Coordinates aCoords = getPoint( theISection, theIPoint );
337 if( getDimension() == CurveCreator::Dim3d ){
342 void CurveCreator_Curve::redisplayCurve()
345 myDisplayer->erase();
346 myDisplayer->display( constructWire() );
350 //! For internal use only! Undo/Redo are not used here.
351 bool CurveCreator_Curve::moveSectionInternal(const int theISection,
352 const int theNewIndex)
355 if (theISection != theNewIndex) {
356 CurveCreator_Section *aSection = mySections.at(theISection);
359 CurveCreator::Sections::iterator anIter = mySections.begin() + theISection;
361 mySections.erase(anIter);
364 anIter = mySections.begin() + theNewIndex;
365 mySections.insert(anIter, aSection);
371 //=======================================================================
372 // function: moveSection
374 //=======================================================================
375 bool CurveCreator_Curve::moveSection(const int theISection,
376 const int theNewIndex)
379 // Set the difference.
381 if (addEmptyDiff()) {
382 myListDiffs.back().init(this, CurveCreator_Operation::MoveSection,
383 theISection, theNewIndex);
387 res = moveSectionInternal(theISection, theNewIndex);
392 /************ Implementation of INTERFACE methods ************/
394 /***********************************************/
395 /*** Undo/Redo methods ***/
396 /***********************************************/
398 //! Get number of available undo operations
399 int CurveCreator_Curve::getNbUndo() const
404 //! Undo previous operation
405 bool CurveCreator_Curve::undo()
412 myCurrenPos->applyUndo(this);
418 //! Get number of available redo operations
419 int CurveCreator_Curve::getNbRedo() const
424 //! Redo last previously "undone" operation
425 bool CurveCreator_Curve::redo()
429 myCurrenPos->applyRedo(this);
438 /***********************************************/
439 /*** Section methods ***/
440 /***********************************************/
441 //! For internal use only! Undo/Redo are not used here.
442 bool CurveCreator_Curve::clearInternal()
444 // erase curve from the viewer
446 myDisplayer->erase();
447 // Delete all allocated data.
449 const int aNbSections = getNbSections();
451 for (; i < aNbSections; i++) {
452 delete mySections[i];
460 //=======================================================================
463 //=======================================================================
464 bool CurveCreator_Curve::clear()
468 // Set the difference.
469 if (addEmptyDiff()) {
470 myListDiffs.back().init(this, CurveCreator_Operation::Clear);
472 res = clearInternal();
477 //! For internal use only! Undo/Redo are not used here.
478 bool CurveCreator_Curve::joinInternal( const int theISectionTo,
479 const int theISectionFrom )
482 CurveCreator_Section *aSection1 = mySections.at(theISectionTo);
483 CurveCreator_Section *aSection2 = mySections.at(theISectionFrom);
485 aSection1->myPoints.insert(aSection1->myPoints.end(),
486 aSection2->myPoints.begin(),
487 aSection2->myPoints.end());
489 res = removeSection(theISectionFrom);
494 //! Join range of sections to one section (join all sections if -1 is passed in one of arguments)
495 bool CurveCreator_Curve::join( const int theISectionTo,
496 const int theISectionFrom )
499 if (theISectionTo != theISectionFrom) {
502 myListDiffs.back().init(this, CurveCreator_Operation::Join, theISectionTo, theISectionFrom);
504 res = joinInternal( theISectionTo, theISectionFrom );
511 //! Get number of sections
512 int CurveCreator_Curve::getNbSections() const
514 return mySections.size();
517 //! For internal use only! Undo/Redo are not used here.
518 int CurveCreator_Curve::addSectionInternal
519 (const std::string& theName, const CurveCreator::SectionType theType,
520 const bool theIsClosed, const CurveCreator::Coordinates &thePoints)
522 CurveCreator_Section *aSection = new CurveCreator_Section;
524 std::string aName = theName;
526 aName = getUniqSectionName();
528 aSection->myName = aName;
529 aSection->myType = theType;
530 aSection->myIsClosed = theIsClosed;
531 aSection->myPoints = thePoints;
532 mySections.push_back(aSection);
534 return mySections.size()-1;
537 //=======================================================================
538 // function: addSection
539 // purpose: adds an empty section
540 //=======================================================================
541 int CurveCreator_Curve::addSection
542 (const std::string& theName, const CurveCreator::SectionType theType,
543 const bool theIsClosed)
545 int resISection = -1;
546 // Set the difference.
548 CurveCreator::Coordinates aCoords; //empty list
549 if (addEmptyDiff()) {
550 myListDiffs.back().init(this, CurveCreator_Operation::AddSection,
551 theName, aCoords, theType, theIsClosed);
554 resISection = addSectionInternal(theName, theType, theIsClosed, aCoords);
559 //=======================================================================
560 // function: addSection
561 // purpose: adds a section with the given points
562 //=======================================================================
563 int CurveCreator_Curve::addSection
564 (const std::string& theName, const CurveCreator::SectionType theType,
565 const bool theIsClosed, const CurveCreator::Coordinates &thePoints)
567 int resISection = -1;
568 // Set the difference.
570 if (addEmptyDiff()) {
571 myListDiffs.back().init(this, CurveCreator_Operation::AddSection,
572 theName, thePoints, theType, theIsClosed);
575 resISection = addSectionInternal(theName, theType, theIsClosed, thePoints);
581 //! For internal use only! Undo/Redo are not used here.
582 bool CurveCreator_Curve::removeSectionInternal( const int theISection )
584 if (theISection == -1) {
585 delete mySections.back();
586 mySections.pop_back();
588 CurveCreator::Sections::iterator anIterRm = mySections.begin() + theISection;
591 mySections.erase(anIterRm);
597 //! Removes the given sections.
598 bool CurveCreator_Curve::removeSection( const int theISection )
601 // Set the difference.
604 myListDiffs.back().init(this, CurveCreator_Operation::RemoveSection, theISection);
606 res = removeSectionInternal( theISection );
613 * Get number of points in specified section or (the total number of points
614 * in Curve if theISection is equal to -1).
616 int CurveCreator_Curve::getNbPoints( const int theISection ) const
620 if (theISection == -1) {
622 const int aNbSections = getNbSections();
624 for (; i < aNbSections; i++) {
625 aNbCoords += mySections[i]->myPoints.size();
628 aNbCoords = mySections.at(theISection)->myPoints.size();
631 return aNbCoords/myDimension;
634 //! Get "closed" flag of the specified section
635 bool CurveCreator_Curve::isClosed( const int theISection ) const
637 return mySections.at(theISection)->myIsClosed;
640 //! For internal use only! Undo/Redo are not used here.
641 bool CurveCreator_Curve::setClosedInternal( const int theISection,
642 const bool theIsClosed )
644 if (theISection == -1) {
645 int aSize = mySections.size();
648 for (i = 0; i < aSize; i++) {
649 mySections[i]->myIsClosed = theIsClosed;
653 mySections.at(theISection)->myIsClosed = theIsClosed;
660 * Set "closed" flag of the specified section (all sections if
661 * \a theISection is -1).
663 bool CurveCreator_Curve::setClosed( const int theISection,
664 const bool theIsClosed )
667 // Set the difference.
669 if (addEmptyDiff()) {
670 myListDiffs.back().init(this, CurveCreator_Operation::SetClosed,
671 theIsClosed, theISection);
673 res = setClosedInternal( theISection, theIsClosed );
678 //! Returns specified section name
679 std::string CurveCreator_Curve::getSectionName( const int theISection ) const
681 if( ( theISection >= 0 ) && ( theISection < mySections.size() ))
682 return mySections.at(theISection)->myName;
686 //! For internal use only! Undo/Redo are not used here.
687 bool CurveCreator_Curve::setSectionNameInternal( const int theISection,
688 const std::string& theName )
691 if( ( theISection >= 0 ) && ( theISection < mySections.size() )){
692 mySections.at(theISection)->myName = theName;
698 /** Set name of the specified section */
699 bool CurveCreator_Curve::setSectionName( const int theISection,
700 const std::string& theName )
703 // Set the difference.
705 if (addEmptyDiff()) {
706 myListDiffs.back().init(this, CurveCreator_Operation::RenameSection,
707 theName, theISection);
709 res = setSectionNameInternal( theISection, theName );
714 //! Get type of the specified section
715 CurveCreator::SectionType CurveCreator_Curve::getSectionType
716 ( const int theISection ) const
718 return mySections.at(theISection)->myType;
721 //! For internal use only! Undo/Redo are not used here.
722 bool CurveCreator_Curve::setSectionTypeInternal( const int theISection,
723 const CurveCreator::SectionType theType )
725 if (theISection == -1) {
727 const int aNbSections = getNbSections();
729 for (; i < aNbSections; i++) {
730 mySections[i]->myType = theType;
734 if( mySections.at(theISection)->myType != theType ){
735 mySections.at(theISection)->myType = theType;
743 * Set type of the specified section (or all sections
744 * if \a theISection is -1).
746 bool CurveCreator_Curve::setSectionType( const int theISection,
747 const CurveCreator::SectionType theType )
751 // Set the difference.
752 if (addEmptyDiff()) {
753 myListDiffs.back().init(this, CurveCreator_Operation::SetType,
754 theType, theISection);
757 res = setSectionTypeInternal( theISection, theType );
764 /***********************************************/
765 /*** Point methods ***/
766 /***********************************************/
768 //! For internal use only! Undo/Redo are not used here.
769 bool CurveCreator_Curve::addPointsInternal( const CurveCreator::Coordinates& theCoords,
770 const std::vector<int> &theISections,
771 const std::vector<int> &theIPnts )
774 if( (theCoords.size()/getDimension()) == theISections.size() == theIPnts.size() ) {
775 for( int ind = 0; ind < theISections.size(); ind++ ) {
776 int anISection = theISections.at(ind);
777 CurveCreator_Section *aSection =
778 (anISection == -1 ? mySections.back() : mySections.at(anISection));
781 int anIPnt = theIPnts.at(ind);
782 CurveCreator::Coordinates::iterator anIterPosition;
784 anIterPosition = aSection->myPoints.end();
786 anIterPosition = aSection->myPoints.begin() + toICoord(anIPnt);
787 CurveCreator::Coordinates::const_iterator aFirstPosition =
788 theCoords.begin() + toICoord(ind);
789 aSection->myPoints.insert(anIterPosition,
791 aFirstPosition + getDimension());
802 * Add one point to the specified section starting from the given theIPnt index
803 * (or at the end of points if \a theIPnt is -1).
805 bool CurveCreator_Curve::addPoints( const CurveCreator::Coordinates& theCoords,
806 const int theISection,
810 CurveCreator::Coordinates aCoords = theCoords;
811 // Set the difference.
813 if (addEmptyDiff()) {
814 myListDiffs.back().init(this, CurveCreator_Operation::InsertPoints,
815 theCoords, theISection, theIPnt);
817 std::vector<int> anISections, anIPnts;
818 anISections.push_back( theISection );
819 anIPnts.push_back( theIPnt );
820 res = addPointsInternal( theCoords, anISections, anIPnts );
825 //! For internal use only! Undo/Redo are not used here.
826 bool CurveCreator_Curve::setPointInternal( const int theISection,
828 const CurveCreator::Coordinates& theNewCoords )
832 if (theNewCoords.size() == myDimension) {
833 CurveCreator_Section *aSection = mySections.at(theISection);
835 for (i = 0; i < myDimension; i++) {
836 aSection->myPoints.at(toICoord(theIPnt) + i) = theNewCoords[i];
845 //! Set coordinates of specified point
846 bool CurveCreator_Curve::setPoint( const int theISection,
848 const CurveCreator::Coordinates& theNewCoords )
851 // Set the difference.
853 if (addEmptyDiff()) {
854 myListDiffs.back().init(this, CurveCreator_Operation::SetCoordinates,
855 theNewCoords, theISection, theIPnt);
857 res = setPointInternal( theISection, theIPnt, theNewCoords );
863 //! For internal use only! Undo/Redo are not used here.
864 bool CurveCreator_Curve::removePointsInternal( const std::vector<int> &theISections,
865 const std::vector<int> &theIPnts )
868 if( theISections.size() == theIPnts.size() ) {
869 for( int ind = 0; ind < theISections.size(); ind++ ) {
870 int anISection = theISections.at(ind);
871 CurveCreator_Section *aSection = mySections.at(anISection);
873 int anIPnt = theIPnts.at(ind);
874 CurveCreator::Coordinates::iterator aFirstPosition;
876 aFirstPosition = aSection->myPoints.end();
878 aFirstPosition = aSection->myPoints.begin() + toICoord(anIPnt);
879 aSection->myPoints.erase( aFirstPosition, aFirstPosition + getDimension() );
889 //! Remove point with given id
890 bool CurveCreator_Curve::removePoint( const int theISection, const int theIPnt )
893 // Set the difference.
895 if (addEmptyDiff()) {
896 myListDiffs.back().init(this, CurveCreator_Operation::RemovePoints,
897 theISection, theIPnt);
899 std::vector<int> anISections, anIPnts;
900 anISections.push_back( theISection );
901 anIPnts.push_back( theIPnt );
902 res = removePointsInternal( anISections, anIPnts );
907 //=======================================================================
908 // function: getCoordinates
910 //=======================================================================
911 CurveCreator::Coordinates CurveCreator_Curve::getPoint( const int theISection,
912 const int theIPnt) const
914 CurveCreator_Section *aSection = mySections.at(theISection);
915 CurveCreator::Coordinates::const_iterator
916 anIter = aSection->myPoints.begin() + toICoord(theIPnt);
917 CurveCreator::Coordinates aResult(anIter, anIter + myDimension);
922 //=======================================================================
923 // function: getPoints
925 //=======================================================================
926 CurveCreator::Coordinates CurveCreator_Curve::getPoints( const int theISection ) const
928 return mySections.at(theISection)->myPoints;
932 /***********************************************/
933 /*** Presentation methods ***/
934 /***********************************************/
935 std::vector<Handle_AIS_InteractiveObject> CurveCreator_Curve::constructWire() const
937 std::vector<Handle_AIS_InteractiveObject> aCurveRepresentation;
938 std::vector<Handle_AIS_InteractiveObject> aSectionObjects;
939 for( int iSection = 0 ; iSection < getNbSections() ; iSection++ ){
940 aSectionObjects = constructSection( iSection );
941 for( int iObject = 0 ; iObject < aSectionObjects.size() ; iObject++ ){
942 aCurveRepresentation.push_back( aSectionObjects.at(iObject) );
945 return aCurveRepresentation;