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 <Geom_CartesianPoint.hxx>
35 #include <TopoDS_Edge.hxx>
36 #include <TopoDS_Face.hxx>
37 #include <TopoDS_Wire.hxx>
41 //=======================================================================
42 // function: Constructor
44 //=======================================================================
45 CurveCreator_Curve::CurveCreator_Curve( const CurveCreator::Dimension theDimension )
47 myDimension (theDimension),
57 //=======================================================================
58 // function: Destructor
60 //=======================================================================
61 CurveCreator_Curve::~CurveCreator_Curve()
63 // Delete all allocated data.
67 //=======================================================================
68 // function: getDimension
70 //=======================================================================
71 CurveCreator::Dimension CurveCreator_Curve::getDimension() const
76 //=======================================================================
77 // function: getUniqSectionName
78 // purpose: return unique section name
79 //=======================================================================
80 std::string CurveCreator_Curve::getUniqSectionName() const
82 for( int i = 0 ; i < 1000000 ; i++ ){
84 sprintf( aBuffer, "Section_%d", i+1 );
85 std::string aName(aBuffer);
87 for( j = 0 ; j < mySections.size() ; j++ ){
88 if( mySections[j]->myName == aName )
91 if( j == mySections.size() )
97 //=======================================================================
98 // function: setDisplayer
99 // purpose: set curve changes Displayer
100 //=======================================================================
101 void CurveCreator_Curve::setDisplayer( CurveCreator_Displayer* theDisplayer )
103 myDisplayer = theDisplayer;
106 //=======================================================================
107 // function: getDisplayer
108 // purpose: get curve changes Displayer
109 //=======================================================================
110 CurveCreator_Displayer* CurveCreator_Curve::getDisplayer()
115 //=======================================================================
116 // function: removeDisplayer
117 // purpose: remove the attached Displayer
118 //=======================================================================
119 void CurveCreator_Curve::removeDisplayer()
124 //=======================================================================
127 //=======================================================================
128 bool CurveCreator_Curve::addEmptyDiff()
130 bool isEnabled = false;
132 if (myUndoDepth != 0) {
133 // Forget all Redos after the current one.
136 myListDiffs.erase(myCurrenPos, myListDiffs.end());
139 if (myUndoDepth == -1 || myNbUndos < myUndoDepth) {
140 // Increase the number of undos.
143 // If there are too many differences, remove the first one.
144 myListDiffs.pop_front();
147 // Add new difference.
148 myListDiffs.push_back(CurveCreator_Diff());
149 myCurrenPos = myListDiffs.end();
156 void CurveCreator_Curve::startOperation()
161 void CurveCreator_Curve::finishOperation()
166 //=======================================================================
167 // function: toICoord
169 //=======================================================================
170 int CurveCreator_Curve::toICoord(const int theIPnt) const
172 return theIPnt * myDimension;
175 //=======================================================================
176 // function: setUndoDepth
178 //=======================================================================
179 void CurveCreator_Curve::setUndoDepth(const int theDepth)
182 // Reset all undo/redo data.
186 myCurrenPos = myListDiffs.end();
188 } else if (theDepth == -1) {
189 // There is nothing to do as the depth become unlimited.
191 } else if (theDepth > 0) {
192 // The new "real" depth is set.
193 if (theDepth < myNbRedos) {
194 // The new depth is less then number of redos. Remove the latest redos.
195 int aShift = (myNbRedos - theDepth);
196 ListDiff::iterator aFromPos = myListDiffs.end();
202 myListDiffs.erase(aFromPos, myListDiffs.end());
203 myNbRedos = theDepth;
206 if (theDepth < myNbUndos + myNbRedos) {
207 // The new depth is less then the total number of differences.
208 // Remove the first undos.
209 int aShift = (myNbUndos + myNbRedos - theDepth);
210 ListDiff::iterator aToPos = myListDiffs.begin();
216 myListDiffs.erase(myListDiffs.begin(), aToPos);
217 myNbUndos = theDepth - myNbRedos;
220 myUndoDepth = theDepth;
224 //=======================================================================
225 // function: getUndoDepth
227 //=======================================================================
228 int CurveCreator_Curve::getUndoDepth() const
233 void CurveCreator_Curve::getCoordinates( int theISection, int theIPoint, double& theX, double& theY, double& theZ ) const
235 CurveCreator::Coordinates aCoords = getPoint( theISection, theIPoint );
239 if( getDimension() == CurveCreator::Dim3d ){
244 void CurveCreator_Curve::redisplayCurve()
247 myDisplayer->erase( false );
249 myDisplayer->display( constructWire(), true );
253 //! For internal use only! Undo/Redo are not used here.
254 bool CurveCreator_Curve::moveSectionInternal(const int theISection,
255 const int theNewIndex)
258 if (theISection != theNewIndex) {
259 CurveCreator_Section *aSection = mySections.at(theISection);
262 CurveCreator::Sections::iterator anIter = mySections.begin() + theISection;
264 mySections.erase(anIter);
267 anIter = mySections.begin() + theNewIndex;
268 mySections.insert(anIter, aSection);
274 //=======================================================================
275 // function: moveSection
277 //=======================================================================
278 bool CurveCreator_Curve::moveSection(const int theISection,
279 const int theNewIndex)
282 // Set the difference.
284 if (addEmptyDiff()) {
285 myListDiffs.back().init(this, CurveCreator_Operation::MoveSection,
286 theISection, theNewIndex);
290 res = moveSectionInternal(theISection, theNewIndex);
295 void CurveCreator_Curve::convert( const SectionToPointList& thePoints,
296 std::map< int, std::list<int> >& theConvPoints )
298 theConvPoints.clear();
300 SectionToPointList::const_iterator anIt = thePoints.begin(), aLast = thePoints.end();
301 std::list<int> aPoints;
302 int aSectionId, aPointId;
303 for ( ; anIt != aLast; anIt++ ) {
304 aSectionId = anIt->first;
305 aPointId = anIt->second;
307 if ( theConvPoints.find( aSectionId ) != theConvPoints.end() )
308 aPoints = theConvPoints[aSectionId];
309 aPoints.push_back( aPointId );
310 theConvPoints[aSectionId] = aPoints;
314 /************ Implementation of INTERFACE methods ************/
316 /***********************************************/
317 /*** Undo/Redo methods ***/
318 /***********************************************/
320 //! Get number of available undo operations
321 int CurveCreator_Curve::getNbUndo() const
326 //! Undo previous operation
327 bool CurveCreator_Curve::undo()
334 myCurrenPos->applyUndo(this);
340 //! Get number of available redo operations
341 int CurveCreator_Curve::getNbRedo() const
346 //! Redo last previously "undone" operation
347 bool CurveCreator_Curve::redo()
351 myCurrenPos->applyRedo(this);
360 /***********************************************/
361 /*** Section methods ***/
362 /***********************************************/
363 //! For internal use only! Undo/Redo are not used here.
364 bool CurveCreator_Curve::clearInternal()
366 // erase curve from the viewer
368 myDisplayer->erase( true );
371 // Delete all allocated data.
373 const int aNbSections = getNbSections();
375 for (; i < aNbSections; i++) {
376 delete mySections[i];
384 //=======================================================================
387 //=======================================================================
388 bool CurveCreator_Curve::clear()
392 // Set the difference.
393 if (addEmptyDiff()) {
394 myListDiffs.back().init(this, CurveCreator_Operation::Clear);
396 res = clearInternal();
401 //! For internal use only! Undo/Redo are not used here.
402 bool CurveCreator_Curve::joinInternal( const int theISectionTo,
403 const int theISectionFrom )
406 CurveCreator_Section *aSection1 = mySections.at(theISectionTo);
407 CurveCreator_Section *aSection2 = mySections.at(theISectionFrom);
409 aSection1->myPoints.insert(aSection1->myPoints.end(),
410 aSection2->myPoints.begin(),
411 aSection2->myPoints.end());
413 res = removeSection(theISectionFrom);
418 //! Join range of sections to one section (join all sections if -1 is passed in theISectionFrom argument)
419 bool CurveCreator_Curve::join( const int theISectionTo,
420 const int theISectionFrom )
424 if ( theISectionTo != theISectionFrom ) {
427 myListDiffs.back().init(this, CurveCreator_Operation::Join, theISectionTo, theISectionFrom);
429 res = joinInternal( theISectionTo, theISectionFrom );
436 //! Get number of sections
437 int CurveCreator_Curve::getNbSections() const
439 return mySections.size();
442 //! For internal use only! Undo/Redo are not used here.
443 int CurveCreator_Curve::addSectionInternal
444 (const std::string& theName, const CurveCreator::SectionType theType,
445 const bool theIsClosed, const CurveCreator::Coordinates &thePoints)
447 CurveCreator_Section *aSection = new CurveCreator_Section;
449 std::string aName = theName;
451 aName = getUniqSectionName();
453 aSection->myName = aName;
454 aSection->myType = theType;
455 aSection->myIsClosed = theIsClosed;
456 aSection->myPoints = thePoints;
457 mySections.push_back(aSection);
459 return mySections.size()-1;
462 //=======================================================================
463 // function: addSection
464 // purpose: adds an empty section
465 //=======================================================================
466 int CurveCreator_Curve::addSection
467 (const std::string& theName, const CurveCreator::SectionType theType,
468 const bool theIsClosed)
470 int resISection = -1;
471 // Set the difference.
473 CurveCreator::Coordinates aCoords; //empty list
474 if (addEmptyDiff()) {
475 myListDiffs.back().init(this, CurveCreator_Operation::AddSection,
476 theName, aCoords, theType, theIsClosed);
479 resISection = addSectionInternal(theName, theType, theIsClosed, aCoords);
484 //=======================================================================
485 // function: addSection
486 // purpose: adds a section with the given points
487 //=======================================================================
488 int CurveCreator_Curve::addSection
489 (const std::string& theName, const CurveCreator::SectionType theType,
490 const bool theIsClosed, const CurveCreator::Coordinates &thePoints)
492 int resISection = -1;
493 // Set the difference.
495 if (addEmptyDiff()) {
496 myListDiffs.back().init(this, CurveCreator_Operation::AddSection,
497 theName, thePoints, theType, theIsClosed);
500 resISection = addSectionInternal(theName, theType, theIsClosed, thePoints);
506 //! For internal use only! Undo/Redo are not used here.
507 bool CurveCreator_Curve::removeSectionInternal( const int theISection )
509 if (theISection == -1) {
510 delete mySections.back();
511 mySections.pop_back();
513 CurveCreator::Sections::iterator anIterRm = mySections.begin() + theISection;
516 mySections.erase(anIterRm);
522 //! Removes the given sections.
523 bool CurveCreator_Curve::removeSection( const int theISection )
526 // Set the difference.
529 myListDiffs.back().init(this, CurveCreator_Operation::RemoveSection, theISection);
531 res = removeSectionInternal( theISection );
538 * Get number of points in specified section or (the total number of points
539 * in Curve if theISection is equal to -1).
541 int CurveCreator_Curve::getNbPoints( const int theISection ) const
545 if (theISection == -1) {
547 const int aNbSections = getNbSections();
549 for (; i < aNbSections; i++) {
550 aNbCoords += mySections[i]->myPoints.size();
553 if ( ( theISection >= 0 ) && ( theISection < mySections.size() ) )
554 aNbCoords = mySections.at(theISection)->myPoints.size();
557 return aNbCoords/myDimension;
560 //! Get "closed" flag of the specified section
561 bool CurveCreator_Curve::isClosed( const int theISection ) const
563 return mySections.at(theISection)->myIsClosed;
566 //! For internal use only! Undo/Redo are not used here.
567 bool CurveCreator_Curve::setClosedInternal( const int theISection,
568 const bool theIsClosed )
570 if (theISection == -1) {
571 int aSize = mySections.size();
574 for (i = 0; i < aSize; i++) {
575 mySections[i]->myIsClosed = theIsClosed;
579 mySections.at(theISection)->myIsClosed = theIsClosed;
586 * Set "closed" flag of the specified section (all sections if
587 * \a theISection is -1).
589 bool CurveCreator_Curve::setClosed( const int theISection,
590 const bool theIsClosed )
593 // Set the difference.
595 if (addEmptyDiff()) {
596 myListDiffs.back().init(this, CurveCreator_Operation::SetClosed,
597 theIsClosed, theISection);
599 res = setClosedInternal( theISection, theIsClosed );
604 //! Returns specified section name
605 std::string CurveCreator_Curve::getSectionName( const int theISection ) const
607 if( ( theISection >= 0 ) && ( theISection < mySections.size() ))
608 return mySections.at(theISection)->myName;
612 //! For internal use only! Undo/Redo are not used here.
613 bool CurveCreator_Curve::setSectionNameInternal( const int theISection,
614 const std::string& theName )
617 if( ( theISection >= 0 ) && ( theISection < mySections.size() )){
618 mySections.at(theISection)->myName = theName;
624 /** Set name of the specified section */
625 bool CurveCreator_Curve::setSectionName( const int theISection,
626 const std::string& theName )
629 // Set the difference.
631 if (addEmptyDiff()) {
632 myListDiffs.back().init(this, CurveCreator_Operation::RenameSection,
633 theName, theISection);
635 res = setSectionNameInternal( theISection, theName );
640 //! Get type of the specified section
641 CurveCreator::SectionType CurveCreator_Curve::getSectionType
642 ( const int theISection ) const
644 return mySections.at(theISection)->myType;
647 //! For internal use only! Undo/Redo are not used here.
648 bool CurveCreator_Curve::setSectionTypeInternal( const int theISection,
649 const CurveCreator::SectionType theType )
651 if (theISection == -1) {
653 const int aNbSections = getNbSections();
655 for (; i < aNbSections; i++) {
656 mySections[i]->myType = theType;
660 if( mySections.at(theISection)->myType != theType ){
661 mySections.at(theISection)->myType = theType;
669 * Set type of the specified section (or all sections
670 * if \a theISection is -1).
672 bool CurveCreator_Curve::setSectionType( const int theISection,
673 const CurveCreator::SectionType theType )
677 // Set the difference.
678 if (addEmptyDiff()) {
679 myListDiffs.back().init(this, CurveCreator_Operation::SetType,
680 theType, theISection);
683 res = setSectionTypeInternal( theISection, theType );
690 /***********************************************/
691 /*** Point methods ***/
692 /***********************************************/
694 //! For internal use only! Undo/Redo are not used here.
695 bool CurveCreator_Curve::addPointsInternal( const CurveCreator::SectionsMap &theSectionsMap )
698 CurveCreator::SectionsMap::const_iterator anIt = theSectionsMap.begin();
699 CurveCreator_Section *aSection = 0;
700 for ( ; anIt != theSectionsMap.end(); anIt++ ) {
701 int anISection = anIt->first;
702 aSection = mySections.at(anISection);
704 CurveCreator::PosPointsList aSectionPoints = anIt->second;
705 CurveCreator::PosPointsList::const_iterator aPntIt = aSectionPoints.begin();
706 for( ; aPntIt != aSectionPoints.end(); aPntIt++ ){
707 int anIPnt = (*aPntIt)->myID;
708 CurveCreator::Coordinates aCoords = (*aPntIt)->myCoords;
709 CurveCreator::Coordinates::iterator anIterPosition;
711 anIterPosition = aSection->myPoints.end();
713 anIterPosition = aSection->myPoints.begin() + toICoord(anIPnt);
714 CurveCreator::Coordinates::const_iterator aFirstPosition =
716 aSection->myPoints.insert(anIterPosition,
717 aCoords.begin(), aCoords.end());
728 * Add one point to the specified section starting from the given theIPnt index
729 * (or at the end of points if \a theIPnt is -1).
731 bool CurveCreator_Curve::addPoints( const CurveCreator::Coordinates& theCoords,
732 const int theISection,
736 CurveCreator::Coordinates aCoords = theCoords;
737 // Set the difference.
739 if (addEmptyDiff()) {
740 CurveCreator_ICurve::SectionToPointCoordsList aList;
741 aList.push_back(std::make_pair(std::make_pair(theISection, theIPnt), theCoords));
742 myListDiffs.back().init(this, CurveCreator_Operation::InsertPoints,
745 CurveCreator::SectionsMap aSectionsMap;
746 CurveCreator::PosPointsList aPoints;
747 CurveCreator_PosPoint* aPosPoint = new CurveCreator_PosPoint( theIPnt, theCoords );
748 aPoints.push_back( aPosPoint );
749 aSectionsMap[theISection] = aPoints;
751 res = addPointsInternal( aSectionsMap );
757 //! For internal use only! Undo/Redo are not used here.
758 bool CurveCreator_Curve::setPointInternal( const CurveCreator::SectionsMap &theSectionsMap )
762 CurveCreator::SectionsMap::const_iterator anIt = theSectionsMap.begin();
763 CurveCreator_Section *aSection = 0;
764 for ( ; anIt != theSectionsMap.end(); anIt++ ) {
765 int anISection = anIt->first;
766 aSection = mySections.at(anISection);
768 CurveCreator::PosPointsList aSectionPoints = anIt->second;
769 CurveCreator::PosPointsList::const_iterator aPntIt = aSectionPoints.begin();
770 for( ; aPntIt != aSectionPoints.end(); aPntIt++ ){
771 int anIPnt = (*aPntIt)->myID;
772 CurveCreator::Coordinates aCoords = (*aPntIt)->myCoords;
773 for ( int i = 0; i < myDimension; i++)
774 aSection->myPoints.at(toICoord(anIPnt) + i) = aCoords[i];
785 //! Set coordinates of specified point
786 bool CurveCreator_Curve::setPoint( const int theISection,
788 const CurveCreator::Coordinates& theNewCoords )
791 // Set the difference.
793 if (addEmptyDiff()) {
794 CurveCreator_ICurve::SectionToPointCoordsList aList;
795 aList.push_back(std::make_pair(std::make_pair(theISection, theIPnt), theNewCoords));
796 myListDiffs.back().init(this, CurveCreator_Operation::SetCoordinates,
799 CurveCreator::SectionsMap aSectionsMap;
800 CurveCreator::PosPointsList aPoints;
801 CurveCreator_PosPoint* aPosPoint = new CurveCreator_PosPoint( theIPnt, theNewCoords );
802 aPoints.push_back( aPosPoint );
803 aSectionsMap[theISection] = aPoints;
805 int aSize1 = getNbPoints( theISection );
806 res = setPointInternal( aSectionsMap );
807 int aSize2 = getNbPoints( theISection );
814 //! Set coordinates of specified points from different sections
815 bool CurveCreator_Curve::setSeveralPoints( const SectionToPointCoordsList &theSectionToPntCoords)
818 // Set the difference.
820 if (addEmptyDiff()) {
821 myListDiffs.back().init(this, CurveCreator_Operation::SetCoordinates,
822 theSectionToPntCoords);
824 CurveCreator::SectionsMap aSectionsMap;
825 CurveCreator::PosPointsList aPosPoints;
826 CurveCreator_ICurve::SectionToPointCoordsList::const_iterator anIt =
827 theSectionToPntCoords.begin(), aLast = theSectionToPntCoords.end();
828 int aSectionId, aPointId;
829 for ( ; anIt != aLast; anIt++ ) {
831 aSectionId = anIt->first.first;
832 aPointId = anIt->first.second;
833 CurveCreator::Coordinates aNewCoords = anIt->second;
834 CurveCreator_PosPoint* aPosPoint =
835 new CurveCreator_PosPoint( aPointId, aNewCoords );
836 if( aSectionsMap.find(aSectionId) != aSectionsMap.end() )
837 aPosPoints = aSectionsMap[aSectionId];
838 aPosPoints.push_back( aPosPoint );
839 aSectionsMap[aSectionId] = aPosPoints;
842 res = setPointInternal( aSectionsMap );
848 //! For internal use only! Undo/Redo are not used here.
849 bool CurveCreator_Curve::removePointsInternal( const SectionToPointList &thePoints )
852 std::map<int, std::list<int> > aConvPoints;
853 convert( thePoints, aConvPoints );
854 std::map<int, std::list<int> >::const_iterator anIt = aConvPoints.begin(),
855 aLast = aConvPoints.end();
856 CurveCreator_Section *aSection = 0;
857 for ( ; anIt != aLast; anIt++ ) {
858 int aSectionId = anIt->first;
859 aSection = mySections.at(aSectionId);
861 std::list<int> aSectionPoints = anIt->second;
862 aSectionPoints.sort();
863 std::list<int>::const_reverse_iterator aPntIt = aSectionPoints.rbegin();
864 for( ; aPntIt != aSectionPoints.rend(); aPntIt++ ){
865 int aPntIndx = *aPntIt;
866 CurveCreator::Coordinates::iterator aFirstPosition;
868 aFirstPosition = aSection->myPoints.end() - getDimension();
870 aFirstPosition = aSection->myPoints.begin() + toICoord(aPntIndx);
871 aSection->myPoints.erase( aFirstPosition, aFirstPosition + getDimension() );
881 //! Remove point with given id
882 bool CurveCreator_Curve::removePoint( const int theISection, const int theIPnt )
885 // Set the difference.
887 if (addEmptyDiff()) {
888 myListDiffs.back().init(this, CurveCreator_Operation::RemovePoints,
889 theISection, theIPnt);
891 SectionToPointList aListOfSectionsToPoints;
892 aListOfSectionsToPoints.push_back(std::make_pair(theISection, theIPnt));
893 res = removePointsInternal( aListOfSectionsToPoints );
898 //! Remove several points from different sections with given ids
899 bool CurveCreator_Curve::removeSeveralPoints( const SectionToPointList &theSectionToPntIDs)
902 // Set the difference.
904 if (addEmptyDiff()) {
905 myListDiffs.back().init(this, CurveCreator_Operation::RemovePoints,
908 res = removePointsInternal( theSectionToPntIDs );
913 //=======================================================================
914 // function: getCoordinates
916 //=======================================================================
917 CurveCreator::Coordinates CurveCreator_Curve::getPoint( const int theISection,
918 const int theIPnt) const
920 CurveCreator_Section *aSection = mySections.at(theISection);
921 CurveCreator::Coordinates::const_iterator
922 anIter = aSection->myPoints.begin() + toICoord(theIPnt);
923 CurveCreator::Coordinates aResult(anIter, anIter + myDimension);
928 //=======================================================================
929 // function: getPoints
931 //=======================================================================
932 CurveCreator::Coordinates CurveCreator_Curve::getPoints( const int theISection ) const
934 CurveCreator::Coordinates aCoords;
935 if ( ( theISection >= 0 ) && ( theISection < mySections.size() ) )
937 aCoords = mySections.at(theISection)->myPoints;
943 /***********************************************/
944 /*** Presentation methods ***/
945 /***********************************************/
946 std::vector<Handle_AIS_InteractiveObject> CurveCreator_Curve::constructWire()
948 std::vector<Handle_AIS_InteractiveObject> aCurveRepresentation;
951 CurveCreator_Utils::constructShape( this, aShape );
953 myAISShape = new AIS_Shape( aShape );
954 aCurveRepresentation.push_back( myAISShape );
955 return aCurveRepresentation;
958 //=======================================================================
959 // function: getAISObject
961 //=======================================================================
962 Handle_AIS_InteractiveObject CurveCreator_Curve::getAISObject() const