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_PosPoint.hxx"
27 #include "CurveCreator_Section.hxx"
28 #include "CurveCreator_Displayer.h"
29 #include "CurveCreator_Utils.h"
31 #include <AIS_Shape.hxx>
32 #include <AIS_InteractiveObject.hxx>
33 #include <Geom_CartesianPoint.hxx>
36 #include <TopoDS_Edge.hxx>
37 #include <TopoDS_Face.hxx>
38 #include <TopoDS_Wire.hxx>
42 //=======================================================================
43 // function: Constructor
45 //=======================================================================
46 CurveCreator_Curve::CurveCreator_Curve( const CurveCreator::Dimension theDimension )
48 myDimension (theDimension),
58 //=======================================================================
59 // function: Destructor
61 //=======================================================================
62 CurveCreator_Curve::~CurveCreator_Curve()
64 // Delete all allocated data.
68 //=======================================================================
69 // function: getDimension
71 //=======================================================================
72 CurveCreator::Dimension CurveCreator_Curve::getDimension() const
77 //=======================================================================
78 // function: getUniqSectionName
79 // purpose: return unique section name
80 //=======================================================================
81 std::string CurveCreator_Curve::getUniqSectionName() const
83 for( int i = 0 ; i < 1000000 ; i++ ){
85 sprintf( aBuffer, "Section_%d", i+1 );
86 std::string aName(aBuffer);
88 for( j = 0 ; j < mySections.size() ; j++ ){
89 if( mySections[j]->myName == aName )
92 if( j == mySections.size() )
98 //=======================================================================
99 // function: setDisplayer
100 // purpose: set curve changes Displayer
101 //=======================================================================
102 void CurveCreator_Curve::setDisplayer( CurveCreator_Displayer* theDisplayer )
104 myDisplayer = theDisplayer;
107 //=======================================================================
108 // function: getDisplayer
109 // purpose: get curve changes Displayer
110 //=======================================================================
111 CurveCreator_Displayer* CurveCreator_Curve::getDisplayer()
116 //=======================================================================
117 // function: removeDisplayer
118 // purpose: remove the attached Displayer
119 //=======================================================================
120 void CurveCreator_Curve::removeDisplayer()
125 //=======================================================================
128 //=======================================================================
129 bool CurveCreator_Curve::addEmptyDiff()
131 bool isEnabled = false;
133 if (myUndoDepth != 0) {
134 // Forget all Redos after the current one.
137 myListDiffs.erase(myCurrenPos, myListDiffs.end());
140 if (myUndoDepth == -1 || myNbUndos < myUndoDepth) {
141 // Increase the number of undos.
144 // If there are too many differences, remove the first one.
145 myListDiffs.pop_front();
148 // Add new difference.
149 myListDiffs.push_back(CurveCreator_Diff());
150 myCurrenPos = myListDiffs.end();
157 void CurveCreator_Curve::startOperation()
162 void CurveCreator_Curve::finishOperation()
167 //=======================================================================
168 // function: toICoord
170 //=======================================================================
171 int CurveCreator_Curve::toICoord(const int theIPnt) const
173 return theIPnt * myDimension;
176 //=======================================================================
177 // function: setUndoDepth
179 //=======================================================================
180 void CurveCreator_Curve::setUndoDepth(const int theDepth)
183 // Reset all undo/redo data.
187 myCurrenPos = myListDiffs.end();
189 } else if (theDepth == -1) {
190 // There is nothing to do as the depth become unlimited.
192 } else if (theDepth > 0) {
193 // The new "real" depth is set.
194 if (theDepth < myNbRedos) {
195 // The new depth is less then number of redos. Remove the latest redos.
196 int aShift = (myNbRedos - theDepth);
197 ListDiff::iterator aFromPos = myListDiffs.end();
203 myListDiffs.erase(aFromPos, myListDiffs.end());
204 myNbRedos = theDepth;
207 if (theDepth < myNbUndos + myNbRedos) {
208 // The new depth is less then the total number of differences.
209 // Remove the first undos.
210 int aShift = (myNbUndos + myNbRedos - theDepth);
211 ListDiff::iterator aToPos = myListDiffs.begin();
217 myListDiffs.erase(myListDiffs.begin(), aToPos);
218 myNbUndos = theDepth - myNbRedos;
221 myUndoDepth = theDepth;
225 //=======================================================================
226 // function: getUndoDepth
228 //=======================================================================
229 int CurveCreator_Curve::getUndoDepth() const
234 void CurveCreator_Curve::getCoordinates( int theISection, int theIPoint, double& theX, double& theY, double& theZ ) const
236 CurveCreator::Coordinates aCoords = getPoint( theISection, theIPoint );
240 if( getDimension() == CurveCreator::Dim3d ){
245 void CurveCreator_Curve::redisplayCurve()
248 myDisplayer->eraseAll( false );
251 myDisplayer->display( getAISObject( true ), true );
255 //! For internal use only! Undo/Redo are not used here.
256 bool CurveCreator_Curve::moveSectionInternal(const int theISection,
257 const int theNewIndex)
260 if (theISection != theNewIndex) {
261 CurveCreator_Section *aSection = mySections.at(theISection);
264 CurveCreator::Sections::iterator anIter = mySections.begin() + theISection;
266 mySections.erase(anIter);
269 anIter = mySections.begin() + theNewIndex;
270 mySections.insert(anIter, aSection);
276 //=======================================================================
277 // function: moveSection
279 //=======================================================================
280 bool CurveCreator_Curve::moveSection(const int theISection,
281 const int theNewIndex)
284 // Set the difference.
286 if (addEmptyDiff()) {
287 myListDiffs.back().init(this, CurveCreator_Operation::MoveSection,
288 theISection, theNewIndex);
292 res = moveSectionInternal(theISection, theNewIndex);
297 /************ Implementation of INTERFACE methods ************/
299 /***********************************************/
300 /*** Undo/Redo methods ***/
301 /***********************************************/
303 //! Get number of available undo operations
304 int CurveCreator_Curve::getNbUndo() const
309 //! Undo previous operation
310 bool CurveCreator_Curve::undo()
317 myCurrenPos->applyUndo(this);
323 //! Get number of available redo operations
324 int CurveCreator_Curve::getNbRedo() const
329 //! Redo last previously "undone" operation
330 bool CurveCreator_Curve::redo()
334 myCurrenPos->applyRedo(this);
343 /***********************************************/
344 /*** Section methods ***/
345 /***********************************************/
346 //! For internal use only! Undo/Redo are not used here.
347 bool CurveCreator_Curve::clearInternal()
349 // erase curve from the viewer
351 myDisplayer->eraseAll( true );
354 // Delete all allocated data.
356 const int aNbSections = getNbSections();
358 for (; i < aNbSections; i++) {
359 delete mySections[i];
367 //=======================================================================
370 //=======================================================================
371 bool CurveCreator_Curve::clear()
375 // Set the difference.
376 if (addEmptyDiff()) {
377 myListDiffs.back().init(this, CurveCreator_Operation::Clear);
379 res = clearInternal();
384 //! For internal use only! Undo/Redo are not used here.
385 bool CurveCreator_Curve::joinInternal( const int theISectionTo,
386 const int theISectionFrom )
389 CurveCreator_Section *aSection1 = mySections.at(theISectionTo);
390 CurveCreator_Section *aSection2 = mySections.at(theISectionFrom);
392 aSection1->myPoints.insert(aSection1->myPoints.end(),
393 aSection2->myPoints.begin(),
394 aSection2->myPoints.end());
396 res = removeSection(theISectionFrom);
401 //! Join range of sections to one section (join all sections if -1 is passed in theISectionFrom argument)
402 bool CurveCreator_Curve::join( const int theISectionTo,
403 const int theISectionFrom )
407 if ( theISectionTo != theISectionFrom ) {
410 myListDiffs.back().init(this, CurveCreator_Operation::Join, theISectionTo, theISectionFrom);
412 res = joinInternal( theISectionTo, theISectionFrom );
419 //! Get number of sections
420 int CurveCreator_Curve::getNbSections() const
422 return mySections.size();
425 //! For internal use only! Undo/Redo are not used here.
426 int CurveCreator_Curve::addSectionInternal
427 (const std::string& theName, const CurveCreator::SectionType theType,
428 const bool theIsClosed, const CurveCreator::Coordinates &thePoints)
430 CurveCreator_Section *aSection = new CurveCreator_Section;
432 std::string aName = theName;
434 aName = getUniqSectionName();
436 aSection->myName = aName;
437 aSection->myType = theType;
438 aSection->myIsClosed = theIsClosed;
439 aSection->myPoints = thePoints;
440 mySections.push_back(aSection);
442 return mySections.size()-1;
445 //=======================================================================
446 // function: addSection
447 // purpose: adds an empty section
448 //=======================================================================
449 int CurveCreator_Curve::addSection
450 (const std::string& theName, const CurveCreator::SectionType theType,
451 const bool theIsClosed)
453 int resISection = -1;
454 // Set the difference.
456 CurveCreator::Coordinates aCoords; //empty list
457 if (addEmptyDiff()) {
458 myListDiffs.back().init(this, CurveCreator_Operation::AddSection,
459 theName, aCoords, theType, theIsClosed);
462 resISection = addSectionInternal(theName, theType, theIsClosed, aCoords);
467 //=======================================================================
468 // function: addSection
469 // purpose: adds a section with the given points
470 //=======================================================================
471 int CurveCreator_Curve::addSection
472 (const std::string& theName, const CurveCreator::SectionType theType,
473 const bool theIsClosed, const CurveCreator::Coordinates &thePoints)
475 int resISection = -1;
476 // Set the difference.
478 if (addEmptyDiff()) {
479 myListDiffs.back().init(this, CurveCreator_Operation::AddSection,
480 theName, thePoints, theType, theIsClosed);
483 resISection = addSectionInternal(theName, theType, theIsClosed, thePoints);
489 //! For internal use only! Undo/Redo are not used here.
490 bool CurveCreator_Curve::removeSectionInternal( const int theISection )
492 if (theISection == -1) {
493 delete mySections.back();
494 mySections.pop_back();
496 CurveCreator::Sections::iterator anIterRm = mySections.begin() + theISection;
499 mySections.erase(anIterRm);
505 //! Removes the given sections.
506 bool CurveCreator_Curve::removeSection( const int theISection )
509 // Set the difference.
512 myListDiffs.back().init(this, CurveCreator_Operation::RemoveSection, theISection);
514 res = removeSectionInternal( theISection );
521 * Get number of points in specified section or (the total number of points
522 * in Curve if theISection is equal to -1).
524 int CurveCreator_Curve::getNbPoints( const int theISection ) const
528 if (theISection == -1) {
530 const int aNbSections = getNbSections();
532 for (; i < aNbSections; i++) {
533 aNbCoords += mySections[i]->myPoints.size();
536 if ( ( theISection >= 0 ) && ( theISection < mySections.size() ) )
537 aNbCoords = mySections.at(theISection)->myPoints.size();
540 return aNbCoords/myDimension;
543 //! Get "closed" flag of the specified section
544 bool CurveCreator_Curve::isClosed( const int theISection ) const
546 return mySections.at(theISection)->myIsClosed;
549 //! For internal use only! Undo/Redo are not used here.
550 bool CurveCreator_Curve::setClosedInternal( const int theISection,
551 const bool theIsClosed )
553 if (theISection == -1) {
554 int aSize = mySections.size();
557 for (i = 0; i < aSize; i++) {
558 mySections[i]->myIsClosed = theIsClosed;
562 mySections.at(theISection)->myIsClosed = theIsClosed;
569 * Set "closed" flag of the specified section (all sections if
570 * \a theISection is -1).
572 bool CurveCreator_Curve::setClosed( const int theISection,
573 const bool theIsClosed )
576 // Set the difference.
578 if (addEmptyDiff()) {
579 myListDiffs.back().init(this, CurveCreator_Operation::SetClosed,
580 theIsClosed, theISection);
582 res = setClosedInternal( theISection, theIsClosed );
587 //! Returns specified section name
588 std::string CurveCreator_Curve::getSectionName( const int theISection ) const
590 if( ( theISection >= 0 ) && ( theISection < mySections.size() ))
591 return mySections.at(theISection)->myName;
595 //! For internal use only! Undo/Redo are not used here.
596 bool CurveCreator_Curve::setSectionNameInternal( const int theISection,
597 const std::string& theName )
600 if( ( theISection >= 0 ) && ( theISection < mySections.size() )){
601 mySections.at(theISection)->myName = theName;
607 /** Set name of the specified section */
608 bool CurveCreator_Curve::setSectionName( const int theISection,
609 const std::string& theName )
612 // Set the difference.
614 if (addEmptyDiff()) {
615 myListDiffs.back().init(this, CurveCreator_Operation::RenameSection,
616 theName, theISection);
618 res = setSectionNameInternal( theISection, theName );
623 //! Get type of the specified section
624 CurveCreator::SectionType CurveCreator_Curve::getSectionType
625 ( const int theISection ) const
627 return mySections.at(theISection)->myType;
630 //! For internal use only! Undo/Redo are not used here.
631 bool CurveCreator_Curve::setSectionTypeInternal( const int theISection,
632 const CurveCreator::SectionType theType )
634 if (theISection == -1) {
636 const int aNbSections = getNbSections();
638 for (; i < aNbSections; i++) {
639 mySections[i]->myType = theType;
643 if( mySections.at(theISection)->myType != theType ){
644 mySections.at(theISection)->myType = theType;
652 * Set type of the specified section (or all sections
653 * if \a theISection is -1).
655 bool CurveCreator_Curve::setSectionType( const int theISection,
656 const CurveCreator::SectionType theType )
660 // Set the difference.
661 if (addEmptyDiff()) {
662 myListDiffs.back().init(this, CurveCreator_Operation::SetType,
663 theType, theISection);
666 res = setSectionTypeInternal( theISection, theType );
673 /***********************************************/
674 /*** Point methods ***/
675 /***********************************************/
677 //! For internal use only! Undo/Redo are not used here.
678 bool CurveCreator_Curve::addPointsInternal( const CurveCreator::SectionsMap &theSectionsMap )
681 CurveCreator::SectionsMap::const_iterator anIt = theSectionsMap.begin();
682 CurveCreator_Section *aSection = 0;
683 for ( ; anIt != theSectionsMap.end(); anIt++ ) {
684 int anISection = anIt->first;
685 aSection = mySections.at(anISection);
687 CurveCreator::PosPointsList aSectionPoints = anIt->second;
688 CurveCreator::PosPointsList::const_iterator aPntIt = aSectionPoints.begin();
689 for( ; aPntIt != aSectionPoints.end(); aPntIt++ ){
690 int anIPnt = (*aPntIt)->myID;
691 CurveCreator::Coordinates aCoords = (*aPntIt)->myCoords;
692 CurveCreator::Coordinates::iterator anIterPosition;
694 anIterPosition = aSection->myPoints.end();
696 anIterPosition = aSection->myPoints.begin() + toICoord(anIPnt);
697 CurveCreator::Coordinates::const_iterator aFirstPosition =
699 aSection->myPoints.insert(anIterPosition,
700 aCoords.begin(), aCoords.end());
711 * Add one point to the specified section starting from the given theIPnt index
712 * (or at the end of points if \a theIPnt is -1).
714 bool CurveCreator_Curve::addPoints( const CurveCreator::Coordinates& theCoords,
715 const int theISection,
719 CurveCreator::Coordinates aCoords = theCoords;
720 // Set the difference.
722 if (addEmptyDiff()) {
723 CurveCreator_ICurve::SectionToPointCoordsList aList;
724 aList.push_back(std::make_pair(std::make_pair(theISection, theIPnt), theCoords));
725 myListDiffs.back().init(this, CurveCreator_Operation::InsertPoints,
728 CurveCreator::SectionsMap aSectionsMap;
729 CurveCreator::PosPointsList aPoints;
730 CurveCreator_PosPoint* aPosPoint = new CurveCreator_PosPoint( theIPnt, theCoords );
731 aPoints.push_back( aPosPoint );
732 aSectionsMap[theISection] = aPoints;
734 res = addPointsInternal( aSectionsMap );
740 //! For internal use only! Undo/Redo are not used here.
741 bool CurveCreator_Curve::setPointInternal( const CurveCreator::SectionsMap &theSectionsMap )
745 CurveCreator::SectionsMap::const_iterator anIt = theSectionsMap.begin();
746 CurveCreator_Section *aSection = 0;
747 for ( ; anIt != theSectionsMap.end(); anIt++ ) {
748 int anISection = anIt->first;
749 aSection = mySections.at(anISection);
751 CurveCreator::PosPointsList aSectionPoints = anIt->second;
752 CurveCreator::PosPointsList::const_iterator aPntIt = aSectionPoints.begin();
753 for( ; aPntIt != aSectionPoints.end(); aPntIt++ ){
754 int anIPnt = (*aPntIt)->myID;
755 CurveCreator::Coordinates aCoords = (*aPntIt)->myCoords;
756 for ( int i = 0; i < myDimension; i++)
757 aSection->myPoints.at(toICoord(anIPnt) + i) = aCoords[i];
768 //! Set coordinates of specified point
769 bool CurveCreator_Curve::setPoint( const int theISection,
771 const CurveCreator::Coordinates& theNewCoords )
774 // Set the difference.
776 if (addEmptyDiff()) {
777 CurveCreator_ICurve::SectionToPointCoordsList aList;
778 aList.push_back(std::make_pair(std::make_pair(theISection, theIPnt), theNewCoords));
779 myListDiffs.back().init(this, CurveCreator_Operation::SetCoordinates,
782 CurveCreator::SectionsMap aSectionsMap;
783 CurveCreator::PosPointsList aPoints;
784 CurveCreator_PosPoint* aPosPoint = new CurveCreator_PosPoint( theIPnt, theNewCoords );
785 aPoints.push_back( aPosPoint );
786 aSectionsMap[theISection] = aPoints;
788 int aSize1 = getNbPoints( theISection );
789 res = setPointInternal( aSectionsMap );
790 int aSize2 = getNbPoints( theISection );
797 //! Set coordinates of specified points from different sections
798 bool CurveCreator_Curve::setSeveralPoints( const SectionToPointCoordsList &theSectionToPntCoords)
801 // Set the difference.
803 if (addEmptyDiff()) {
804 myListDiffs.back().init(this, CurveCreator_Operation::SetCoordinates,
805 theSectionToPntCoords);
807 CurveCreator::SectionsMap aSectionsMap;
808 CurveCreator::PosPointsList aPosPoints;
809 CurveCreator_ICurve::SectionToPointCoordsList::const_iterator anIt =
810 theSectionToPntCoords.begin(), aLast = theSectionToPntCoords.end();
811 int aSectionId, aPointId;
812 for ( ; anIt != aLast; anIt++ ) {
814 aSectionId = anIt->first.first;
815 aPointId = anIt->first.second;
816 CurveCreator::Coordinates aNewCoords = anIt->second;
817 CurveCreator_PosPoint* aPosPoint =
818 new CurveCreator_PosPoint( aPointId, aNewCoords );
819 if( aSectionsMap.find(aSectionId) != aSectionsMap.end() )
820 aPosPoints = aSectionsMap[aSectionId];
821 aPosPoints.push_back( aPosPoint );
822 aSectionsMap[aSectionId] = aPosPoints;
825 res = setPointInternal( aSectionsMap );
831 //! For internal use only! Undo/Redo are not used here.
832 bool CurveCreator_Curve::removePointsInternal( const SectionToPointList &thePoints )
835 std::map<int, std::list<int> > aConvPoints;
836 convert( thePoints, aConvPoints );
837 std::map<int, std::list<int> >::const_iterator anIt = aConvPoints.begin(),
838 aLast = aConvPoints.end();
839 for ( ; anIt != aLast; anIt++ ) {
840 int aSectionId = anIt->first;
841 aRes = removeSectionPoints(aSectionId, anIt->second);
849 //! Remove point with given id
850 bool CurveCreator_Curve::removePoint( const int theISection, const int theIPnt )
853 // Set the difference.
855 if (addEmptyDiff()) {
856 myListDiffs.back().init(this, CurveCreator_Operation::RemovePoints,
857 theISection, theIPnt);
859 SectionToPointList aListOfSectionsToPoints;
860 aListOfSectionsToPoints.push_back(std::make_pair(theISection, theIPnt));
861 res = removePointsInternal( aListOfSectionsToPoints );
866 //! Remove several points from different sections with given ids
867 bool CurveCreator_Curve::removeSeveralPoints( const SectionToPointList &theSectionToPntIDs)
870 // Set the difference.
872 if (addEmptyDiff()) {
873 myListDiffs.back().init(this, CurveCreator_Operation::RemovePoints,
876 res = removePointsInternal( theSectionToPntIDs );
881 //=======================================================================
882 // function: getCoordinates
884 //=======================================================================
885 CurveCreator::Coordinates CurveCreator_Curve::getPoint( const int theISection,
886 const int theIPnt) const
888 CurveCreator_Section *aSection = mySections.at(theISection);
889 CurveCreator::Coordinates::const_iterator
890 anIter = aSection->myPoints.begin() + toICoord(theIPnt);
891 CurveCreator::Coordinates aResult(anIter, anIter + myDimension);
896 //=======================================================================
897 // function: getPoints
899 //=======================================================================
900 CurveCreator::Coordinates CurveCreator_Curve::getPoints( const int theISection ) const
902 CurveCreator::Coordinates aCoords;
903 if ( ( theISection >= 0 ) && ( theISection < mySections.size() ) )
905 aCoords = mySections.at(theISection)->myPoints;
910 void CurveCreator_Curve::constructAISObject()
913 CurveCreator_Utils::constructShape( this, aShape );
915 myAISShape = new AIS_Shape( aShape );
918 Handle(AIS_InteractiveObject) CurveCreator_Curve::getAISObject( const bool theNeedToBuild ) const
920 if ( !myAISShape && theNeedToBuild ) {
921 CurveCreator_Curve* aCurve = (CurveCreator_Curve*)this;
922 aCurve->constructAISObject();
927 bool CurveCreator_Curve::removeSectionPoints( const int theSectionId,
928 const std::list<int>& thePointIds )
932 CurveCreator_Section *aSection = mySections.at( theSectionId );
936 std::list<int> aSectionPoints = thePointIds;
937 aSectionPoints.sort();
938 std::list<int>::const_reverse_iterator aPntIt = aSectionPoints.rbegin();
939 for ( ; aPntIt != aSectionPoints.rend(); aPntIt++ ) {
940 int aPntIndx = *aPntIt;
941 CurveCreator::Coordinates::iterator aFirstPosition;
942 if ( aPntIndx == -1 )
943 aFirstPosition = aSection->myPoints.end() - getDimension();
945 aFirstPosition = aSection->myPoints.begin() + toICoord( aPntIndx );
946 aSection->myPoints.erase( aFirstPosition, aFirstPosition + getDimension() );
952 void CurveCreator_Curve::convert( const SectionToPointList& thePoints,
953 std::map< int, std::list<int> >& theConvPoints )
955 theConvPoints.clear();
957 SectionToPointList::const_iterator anIt = thePoints.begin(), aLast = thePoints.end();
958 std::list<int> aPoints;
959 int aSectionId, aPointId;
960 for ( ; anIt != aLast; anIt++ ) {
961 aSectionId = anIt->first;
962 aPointId = anIt->second;
964 if ( theConvPoints.find( aSectionId ) != theConvPoints.end() )
965 aPoints = theConvPoints[aSectionId];
966 aPoints.push_back( aPointId );
967 theConvPoints[aSectionId] = aPoints;