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: getDisplayer
111 // purpose: get curve changes Displayer
112 //=======================================================================
113 CurveCreator_Displayer* CurveCreator_Curve::getDisplayer()
118 //=======================================================================
119 // function: removeDisplayer
120 // purpose: remove the attached Displayer
121 //=======================================================================
122 void CurveCreator_Curve::removeDisplayer()
127 //=======================================================================
130 //=======================================================================
131 bool CurveCreator_Curve::addEmptyDiff()
133 bool isEnabled = false;
135 if (myUndoDepth != 0) {
136 // Forget all Redos after the current one.
139 myListDiffs.erase(myCurrenPos, myListDiffs.end());
142 if (myUndoDepth == -1 || myNbUndos < myUndoDepth) {
143 // Increase the number of undos.
146 // If there are too many differences, remove the first one.
147 myListDiffs.pop_front();
150 // Add new difference.
151 myListDiffs.push_back(CurveCreator_Diff());
152 myCurrenPos = myListDiffs.end();
159 void CurveCreator_Curve::startOperation()
164 void CurveCreator_Curve::finishOperation()
169 //=======================================================================
170 // function: toICoord
172 //=======================================================================
173 int CurveCreator_Curve::toICoord(const int theIPnt) const
175 return theIPnt * myDimension;
178 std::vector<Handle_AIS_InteractiveObject> CurveCreator_Curve::constructSection( int theISection ) const
180 std::vector<Handle_AIS_InteractiveObject> aSectionRepresentation;
182 CurveCreator::SectionType aSectType = getSectionType( theISection );
183 int aSectSize = getNbPoints( theISection );
184 bool aSectIsClosed = isClosed( theISection );
186 if( aSectType == CurveCreator::Polyline )
189 for( ; iPoint < ( aSectSize - 1 ) ; iPoint++ ){
190 Handle_AIS_Point anAISPnt = getAISPoint(theISection, iPoint);
191 aSectionRepresentation.push_back( anAISPnt );
192 Handle_AIS_Line aLine = getAISLine( theISection, iPoint, iPoint+1 );
193 aSectionRepresentation.push_back( aLine );
195 if( aSectSize != 0 ){
196 Handle_AIS_Point anAISPnt = getAISPoint(theISection, iPoint);
197 aSectionRepresentation.push_back( anAISPnt );
198 if( isClosed(theISection) && ( aSectSize > 1 ) ){
199 Handle_AIS_Line aLine = getAISLine( theISection, iPoint, 0 );
200 aSectionRepresentation.push_back( aLine );
204 else if( aSectType == CurveCreator::Spline )
206 std::vector<double> aPoints;
207 for( int iPoint = 0; iPoint < aSectSize; iPoint++ )
209 Handle_AIS_Point anAISPnt = getAISPoint( theISection, iPoint );
210 aSectionRepresentation.push_back( anAISPnt );
212 CurveCreator::Coordinates aCoords = getPoint( theISection, iPoint );
213 double aX = aCoords[0];
214 double aY = aCoords[1];
215 double aZ = aCoords[2];
216 aPoints.push_back( aX );
217 aPoints.push_back( aY );
222 Handle(Geom_BSplineCurve) aBSplineCurve;
223 // fill array for algorithm by the received coordinates
224 int aLen = aPoints.size() / 2;
225 Handle(TColgp_HArray1OfPnt) aHCurvePoints = new TColgp_HArray1OfPnt (1, aLen);
226 std::vector<double>::const_iterator aListIter = aPoints.begin();
227 for (int ind = 1; ind <= aLen; ind++) {
228 gp_Pnt aPnt(gp::Origin());
229 aPnt.SetX(*aListIter);
231 aPnt.SetY(*aListIter);
234 aHCurvePoints->SetValue(ind, aPnt);
237 GeomAPI_Interpolate aGBC(aHCurvePoints, aSectIsClosed, gp::Resolution());
240 aBSplineCurve = aGBC.Curve();
242 TopoDS_Edge anEdge = BRepBuilderAPI_MakeEdge( aBSplineCurve ).Edge();
244 TopoDS_Wire aWire = BRepBuilderAPI_MakeWire( anEdge ).Wire();
246 Handle(AIS_Shape) aShape = new AIS_Shape( aWire );
247 aSectionRepresentation.push_back( aShape );
250 return aSectionRepresentation;
253 //=======================================================================
254 // function: setUndoDepth
256 //=======================================================================
257 void CurveCreator_Curve::setUndoDepth(const int theDepth)
260 // Reset all undo/redo data.
264 myCurrenPos = myListDiffs.end();
266 } else if (theDepth == -1) {
267 // There is nothing to do as the depth become unlimited.
269 } else if (theDepth > 0) {
270 // The new "real" depth is set.
271 if (theDepth < myNbRedos) {
272 // The new depth is less then number of redos. Remove the latest redos.
273 int aShift = (myNbRedos - theDepth);
274 ListDiff::iterator aFromPos = myListDiffs.end();
280 myListDiffs.erase(aFromPos, myListDiffs.end());
281 myNbRedos = theDepth;
284 if (theDepth < myNbUndos + myNbRedos) {
285 // The new depth is less then the total number of differences.
286 // Remove the first undos.
287 int aShift = (myNbUndos + myNbRedos - theDepth);
288 ListDiff::iterator aToPos = myListDiffs.begin();
294 myListDiffs.erase(myListDiffs.begin(), aToPos);
295 myNbUndos = theDepth - myNbRedos;
298 myUndoDepth = theDepth;
302 //=======================================================================
303 // function: getUndoDepth
305 //=======================================================================
306 int CurveCreator_Curve::getUndoDepth() const
311 Handle_AIS_Point CurveCreator_Curve::getAISPoint( int theISection, int theIPoint ) const
314 getCoordinates( theISection, theIPoint, anX, anY, aZ );
315 gp_Pnt aPoint( anX, anY, aZ);
317 AIS_Point* aPnt = new AIS_Point( new Geom_CartesianPoint(aPoint));
321 Handle_AIS_Line CurveCreator_Curve::getAISLine( int theISection, int theIPoint1, int theIPoint2 ) const
324 getCoordinates( theISection, theIPoint1, anX, anY, aZ );
325 gp_Pnt aPoint1( anX, anY, aZ);
327 double anX2, anY2, aZ2;
328 getCoordinates( theISection, theIPoint2, anX2, anY2, aZ2 );
329 //MTN to avoid crash during line construction
330 if( ( anX == anX2 ) && ( anY == anY2 ) && (aZ == aZ2 ) ){
334 gp_Pnt aPoint2( anX2, anY2, aZ2 );
336 AIS_Line* aLine = new AIS_Line( new Geom_CartesianPoint(aPoint1), new Geom_CartesianPoint(aPoint2) );
340 void CurveCreator_Curve::getCoordinates( int theISection, int theIPoint, double& theX, double& theY, double& theZ ) const
342 CurveCreator::Coordinates aCoords = getPoint( theISection, theIPoint );
346 if( getDimension() == CurveCreator::Dim3d ){
351 void CurveCreator_Curve::redisplayCurve()
354 myDisplayer->erase();
355 myDisplayer->display( constructWire() );
359 //! For internal use only! Undo/Redo are not used here.
360 bool CurveCreator_Curve::moveSectionInternal(const int theISection,
361 const int theNewIndex)
364 if (theISection != theNewIndex) {
365 CurveCreator_Section *aSection = mySections.at(theISection);
368 CurveCreator::Sections::iterator anIter = mySections.begin() + theISection;
370 mySections.erase(anIter);
373 anIter = mySections.begin() + theNewIndex;
374 mySections.insert(anIter, aSection);
380 //=======================================================================
381 // function: moveSection
383 //=======================================================================
384 bool CurveCreator_Curve::moveSection(const int theISection,
385 const int theNewIndex)
388 // Set the difference.
390 if (addEmptyDiff()) {
391 myListDiffs.back().init(this, CurveCreator_Operation::MoveSection,
392 theISection, theNewIndex);
396 res = moveSectionInternal(theISection, theNewIndex);
401 /************ Implementation of INTERFACE methods ************/
403 /***********************************************/
404 /*** Undo/Redo methods ***/
405 /***********************************************/
407 //! Get number of available undo operations
408 int CurveCreator_Curve::getNbUndo() const
413 //! Undo previous operation
414 bool CurveCreator_Curve::undo()
421 myCurrenPos->applyUndo(this);
427 //! Get number of available redo operations
428 int CurveCreator_Curve::getNbRedo() const
433 //! Redo last previously "undone" operation
434 bool CurveCreator_Curve::redo()
438 myCurrenPos->applyRedo(this);
447 /***********************************************/
448 /*** Section methods ***/
449 /***********************************************/
450 //! For internal use only! Undo/Redo are not used here.
451 bool CurveCreator_Curve::clearInternal()
453 // erase curve from the viewer
455 myDisplayer->erase();
456 // Delete all allocated data.
458 const int aNbSections = getNbSections();
460 for (; i < aNbSections; i++) {
461 delete mySections[i];
469 //=======================================================================
472 //=======================================================================
473 bool CurveCreator_Curve::clear()
477 // Set the difference.
478 if (addEmptyDiff()) {
479 myListDiffs.back().init(this, CurveCreator_Operation::Clear);
481 res = clearInternal();
486 //! For internal use only! Undo/Redo are not used here.
487 bool CurveCreator_Curve::joinInternal( const int theISectionTo,
488 const int theISectionFrom )
491 CurveCreator_Section *aSection1 = mySections.at(theISectionTo);
492 CurveCreator_Section *aSection2 = mySections.at(theISectionFrom);
494 aSection1->myPoints.insert(aSection1->myPoints.end(),
495 aSection2->myPoints.begin(),
496 aSection2->myPoints.end());
498 res = removeSection(theISectionFrom);
503 //! Join range of sections to one section (join all sections if -1 is passed in one of arguments)
504 bool CurveCreator_Curve::join( const int theISectionTo,
505 const int theISectionFrom )
508 if (theISectionTo != theISectionFrom) {
511 myListDiffs.back().init(this, CurveCreator_Operation::Join, theISectionTo, theISectionFrom);
513 res = joinInternal( theISectionTo, theISectionFrom );
520 //! Get number of sections
521 int CurveCreator_Curve::getNbSections() const
523 return mySections.size();
526 //! For internal use only! Undo/Redo are not used here.
527 int CurveCreator_Curve::addSectionInternal
528 (const std::string& theName, const CurveCreator::SectionType theType,
529 const bool theIsClosed, const CurveCreator::Coordinates &thePoints)
531 CurveCreator_Section *aSection = new CurveCreator_Section;
533 std::string aName = theName;
535 aName = getUniqSectionName();
537 aSection->myName = aName;
538 aSection->myType = theType;
539 aSection->myIsClosed = theIsClosed;
540 aSection->myPoints = thePoints;
541 mySections.push_back(aSection);
543 return mySections.size()-1;
546 //=======================================================================
547 // function: addSection
548 // purpose: adds an empty section
549 //=======================================================================
550 int CurveCreator_Curve::addSection
551 (const std::string& theName, const CurveCreator::SectionType theType,
552 const bool theIsClosed)
554 int resISection = -1;
555 // Set the difference.
557 CurveCreator::Coordinates aCoords; //empty list
558 if (addEmptyDiff()) {
559 myListDiffs.back().init(this, CurveCreator_Operation::AddSection,
560 theName, aCoords, theType, theIsClosed);
563 resISection = addSectionInternal(theName, theType, theIsClosed, aCoords);
568 //=======================================================================
569 // function: addSection
570 // purpose: adds a section with the given points
571 //=======================================================================
572 int CurveCreator_Curve::addSection
573 (const std::string& theName, const CurveCreator::SectionType theType,
574 const bool theIsClosed, const CurveCreator::Coordinates &thePoints)
576 int resISection = -1;
577 // Set the difference.
579 if (addEmptyDiff()) {
580 myListDiffs.back().init(this, CurveCreator_Operation::AddSection,
581 theName, thePoints, theType, theIsClosed);
584 resISection = addSectionInternal(theName, theType, theIsClosed, thePoints);
590 //! For internal use only! Undo/Redo are not used here.
591 bool CurveCreator_Curve::removeSectionInternal( const int theISection )
593 if (theISection == -1) {
594 delete mySections.back();
595 mySections.pop_back();
597 CurveCreator::Sections::iterator anIterRm = mySections.begin() + theISection;
600 mySections.erase(anIterRm);
606 //! Removes the given sections.
607 bool CurveCreator_Curve::removeSection( const int theISection )
610 // Set the difference.
613 myListDiffs.back().init(this, CurveCreator_Operation::RemoveSection, theISection);
615 res = removeSectionInternal( theISection );
622 * Get number of points in specified section or (the total number of points
623 * in Curve if theISection is equal to -1).
625 int CurveCreator_Curve::getNbPoints( const int theISection ) const
629 if (theISection == -1) {
631 const int aNbSections = getNbSections();
633 for (; i < aNbSections; i++) {
634 aNbCoords += mySections[i]->myPoints.size();
637 aNbCoords = mySections.at(theISection)->myPoints.size();
640 return aNbCoords/myDimension;
643 //! Get "closed" flag of the specified section
644 bool CurveCreator_Curve::isClosed( const int theISection ) const
646 return mySections.at(theISection)->myIsClosed;
649 //! For internal use only! Undo/Redo are not used here.
650 bool CurveCreator_Curve::setClosedInternal( const int theISection,
651 const bool theIsClosed )
653 if (theISection == -1) {
654 int aSize = mySections.size();
657 for (i = 0; i < aSize; i++) {
658 mySections[i]->myIsClosed = theIsClosed;
662 mySections.at(theISection)->myIsClosed = theIsClosed;
669 * Set "closed" flag of the specified section (all sections if
670 * \a theISection is -1).
672 bool CurveCreator_Curve::setClosed( const int theISection,
673 const bool theIsClosed )
676 // Set the difference.
678 if (addEmptyDiff()) {
679 myListDiffs.back().init(this, CurveCreator_Operation::SetClosed,
680 theIsClosed, theISection);
682 res = setClosedInternal( theISection, theIsClosed );
687 //! Returns specified section name
688 std::string CurveCreator_Curve::getSectionName( const int theISection ) const
690 if( ( theISection >= 0 ) && ( theISection < mySections.size() ))
691 return mySections.at(theISection)->myName;
695 //! For internal use only! Undo/Redo are not used here.
696 bool CurveCreator_Curve::setSectionNameInternal( const int theISection,
697 const std::string& theName )
700 if( ( theISection >= 0 ) && ( theISection < mySections.size() )){
701 mySections.at(theISection)->myName = theName;
707 /** Set name of the specified section */
708 bool CurveCreator_Curve::setSectionName( const int theISection,
709 const std::string& theName )
712 // Set the difference.
714 if (addEmptyDiff()) {
715 myListDiffs.back().init(this, CurveCreator_Operation::RenameSection,
716 theName, theISection);
718 res = setSectionNameInternal( theISection, theName );
723 //! Get type of the specified section
724 CurveCreator::SectionType CurveCreator_Curve::getSectionType
725 ( const int theISection ) const
727 return mySections.at(theISection)->myType;
730 //! For internal use only! Undo/Redo are not used here.
731 bool CurveCreator_Curve::setSectionTypeInternal( const int theISection,
732 const CurveCreator::SectionType theType )
734 if (theISection == -1) {
736 const int aNbSections = getNbSections();
738 for (; i < aNbSections; i++) {
739 mySections[i]->myType = theType;
743 if( mySections.at(theISection)->myType != theType ){
744 mySections.at(theISection)->myType = theType;
752 * Set type of the specified section (or all sections
753 * if \a theISection is -1).
755 bool CurveCreator_Curve::setSectionType( const int theISection,
756 const CurveCreator::SectionType theType )
760 // Set the difference.
761 if (addEmptyDiff()) {
762 myListDiffs.back().init(this, CurveCreator_Operation::SetType,
763 theType, theISection);
766 res = setSectionTypeInternal( theISection, theType );
773 /***********************************************/
774 /*** Point methods ***/
775 /***********************************************/
777 //! For internal use only! Undo/Redo are not used here.
778 bool CurveCreator_Curve::addPointsInternal( const CurveCreator::Coordinates& theCoords,
779 const std::vector<int> &theISections,
780 const std::vector<int> &theIPnts )
783 if( (theCoords.size()/getDimension()) == theISections.size() == theIPnts.size() ) {
784 for( int ind = 0; ind < theISections.size(); ind++ ) {
785 int anISection = theISections.at(ind);
786 CurveCreator_Section *aSection =
787 (anISection == -1 ? mySections.back() : mySections.at(anISection));
790 int anIPnt = theIPnts.at(ind);
791 CurveCreator::Coordinates::iterator anIterPosition;
793 anIterPosition = aSection->myPoints.end();
795 anIterPosition = aSection->myPoints.begin() + toICoord(anIPnt);
796 CurveCreator::Coordinates::const_iterator aFirstPosition =
797 theCoords.begin() + toICoord(ind);
798 aSection->myPoints.insert(anIterPosition,
800 aFirstPosition + getDimension());
811 * Add one point to the specified section starting from the given theIPnt index
812 * (or at the end of points if \a theIPnt is -1).
814 bool CurveCreator_Curve::addPoints( const CurveCreator::Coordinates& theCoords,
815 const int theISection,
819 CurveCreator::Coordinates aCoords = theCoords;
820 // Set the difference.
822 if (addEmptyDiff()) {
823 myListDiffs.back().init(this, CurveCreator_Operation::InsertPoints,
824 theCoords, theISection, theIPnt);
826 std::vector<int> anISections, anIPnts;
827 anISections.push_back( theISection );
828 anIPnts.push_back( theIPnt );
829 res = addPointsInternal( theCoords, anISections, anIPnts );
834 //! For internal use only! Undo/Redo are not used here.
835 bool CurveCreator_Curve::setPointInternal( const int theISection,
837 const CurveCreator::Coordinates& theNewCoords )
841 if (theNewCoords.size() == myDimension) {
842 CurveCreator_Section *aSection = mySections.at(theISection);
844 for (i = 0; i < myDimension; i++) {
845 aSection->myPoints.at(toICoord(theIPnt) + i) = theNewCoords[i];
854 //! Set coordinates of specified point
855 bool CurveCreator_Curve::setPoint( const int theISection,
857 const CurveCreator::Coordinates& theNewCoords )
860 // Set the difference.
862 if (addEmptyDiff()) {
863 myListDiffs.back().init(this, CurveCreator_Operation::SetCoordinates,
864 theNewCoords, theISection, theIPnt);
866 res = setPointInternal( theISection, theIPnt, theNewCoords );
872 //! Set coordinates of specified points from different sections
873 bool CurveCreator_Curve::setSeveralPoints( const SectionToPointCoordsList &theSectionToPntCoords)
878 //! For internal use only! Undo/Redo are not used here.
879 bool CurveCreator_Curve::removePointsInternal( const std::vector<int> &theISections,
880 const std::vector<int> &theIPnts )
883 if( theISections.size() == theIPnts.size() ) {
884 for( int ind = 0; ind < theISections.size(); ind++ ) {
885 int anISection = theISections.at(ind);
886 CurveCreator_Section *aSection = mySections.at(anISection);
888 int anIPnt = theIPnts.at(ind);
889 CurveCreator::Coordinates::iterator aFirstPosition;
891 aFirstPosition = aSection->myPoints.end();
893 aFirstPosition = aSection->myPoints.begin() + toICoord(anIPnt);
894 aSection->myPoints.erase( aFirstPosition, aFirstPosition + getDimension() );
904 //! Remove point with given id
905 bool CurveCreator_Curve::removePoint( const int theISection, const int theIPnt )
908 // Set the difference.
910 if (addEmptyDiff()) {
911 myListDiffs.back().init(this, CurveCreator_Operation::RemovePoints,
912 theISection, theIPnt);
914 std::vector<int> anISections, anIPnts;
915 anISections.push_back( theISection );
916 anIPnts.push_back( theIPnt );
917 res = removePointsInternal( anISections, anIPnts );
922 //! Remove several points from different sections with given ids
923 bool CurveCreator_Curve::removeSeveralPoints( const SectionToPointList &theSectionToPntIDs)
928 //=======================================================================
929 // function: getCoordinates
931 //=======================================================================
932 CurveCreator::Coordinates CurveCreator_Curve::getPoint( const int theISection,
933 const int theIPnt) const
935 CurveCreator_Section *aSection = mySections.at(theISection);
936 CurveCreator::Coordinates::const_iterator
937 anIter = aSection->myPoints.begin() + toICoord(theIPnt);
938 CurveCreator::Coordinates aResult(anIter, anIter + myDimension);
943 //=======================================================================
944 // function: getPoints
946 //=======================================================================
947 CurveCreator::Coordinates CurveCreator_Curve::getPoints( const int theISection ) const
949 return mySections.at(theISection)->myPoints;
953 /***********************************************/
954 /*** Presentation methods ***/
955 /***********************************************/
956 std::vector<Handle_AIS_InteractiveObject> CurveCreator_Curve::constructWire() const
958 std::vector<Handle_AIS_InteractiveObject> aCurveRepresentation;
959 std::vector<Handle_AIS_InteractiveObject> aSectionObjects;
960 for( int iSection = 0 ; iSection < getNbSections() ; iSection++ ){
961 aSectionObjects = constructSection( iSection );
962 for( int iObject = 0 ; iObject < aSectionObjects.size() ; iObject++ ){
963 aCurveRepresentation.push_back( aSectionObjects.at(iObject) );
966 return aCurveRepresentation;