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),
56 //=======================================================================
57 // function: Destructor
59 //=======================================================================
60 CurveCreator_Curve::~CurveCreator_Curve()
62 // Delete all allocated data.
66 //=======================================================================
67 // function: getDimension
69 //=======================================================================
70 CurveCreator::Dimension CurveCreator_Curve::getDimension() const
75 //=======================================================================
76 // function: getUniqSectionName
77 // purpose: return unique section name
78 //=======================================================================
79 std::string CurveCreator_Curve::getUniqSectionName() const
81 for( int i = 0 ; i < 1000000 ; i++ ){
83 sprintf( aBuffer, "Section_%d", i+1 );
84 std::string aName(aBuffer);
86 for( j = 0 ; j < mySections.size() ; j++ ){
87 if( mySections[j]->myName == aName )
90 if( j == mySections.size() )
96 //=======================================================================
97 // function: setDisplayer
98 // purpose: set curve changes Displayer
99 //=======================================================================
100 void CurveCreator_Curve::setDisplayer( CurveCreator_Displayer* theDisplayer )
102 myDisplayer = theDisplayer;
105 //=======================================================================
106 // function: getDisplayer
107 // purpose: get curve changes Displayer
108 //=======================================================================
109 CurveCreator_Displayer* CurveCreator_Curve::getDisplayer()
114 //=======================================================================
115 // function: removeDisplayer
116 // purpose: remove the attached Displayer
117 //=======================================================================
118 void CurveCreator_Curve::removeDisplayer()
123 //=======================================================================
126 //=======================================================================
127 bool CurveCreator_Curve::addEmptyDiff()
129 bool isEnabled = false;
131 if (myUndoDepth != 0) {
132 // Forget all Redos after the current one.
135 myListDiffs.erase(myCurrenPos, myListDiffs.end());
138 if (myUndoDepth == -1 || myNbUndos < myUndoDepth) {
139 // Increase the number of undos.
142 // If there are too many differences, remove the first one.
143 myListDiffs.pop_front();
146 // Add new difference.
147 myListDiffs.push_back(CurveCreator_Diff());
148 myCurrenPos = myListDiffs.end();
155 void CurveCreator_Curve::startOperation()
160 void CurveCreator_Curve::finishOperation()
165 //=======================================================================
166 // function: toICoord
168 //=======================================================================
169 int CurveCreator_Curve::toICoord(const int theIPnt) const
171 return theIPnt * myDimension;
174 //=======================================================================
175 // function: setUndoDepth
177 //=======================================================================
178 void CurveCreator_Curve::setUndoDepth(const int theDepth)
181 // Reset all undo/redo data.
185 myCurrenPos = myListDiffs.end();
187 } else if (theDepth == -1) {
188 // There is nothing to do as the depth become unlimited.
190 } else if (theDepth > 0) {
191 // The new "real" depth is set.
192 if (theDepth < myNbRedos) {
193 // The new depth is less then number of redos. Remove the latest redos.
194 int aShift = (myNbRedos - theDepth);
195 ListDiff::iterator aFromPos = myListDiffs.end();
201 myListDiffs.erase(aFromPos, myListDiffs.end());
202 myNbRedos = theDepth;
205 if (theDepth < myNbUndos + myNbRedos) {
206 // The new depth is less then the total number of differences.
207 // Remove the first undos.
208 int aShift = (myNbUndos + myNbRedos - theDepth);
209 ListDiff::iterator aToPos = myListDiffs.begin();
215 myListDiffs.erase(myListDiffs.begin(), aToPos);
216 myNbUndos = theDepth - myNbRedos;
219 myUndoDepth = theDepth;
223 //=======================================================================
224 // function: getUndoDepth
226 //=======================================================================
227 int CurveCreator_Curve::getUndoDepth() const
232 void CurveCreator_Curve::getCoordinates( int theISection, int theIPoint, double& theX, double& theY, double& theZ ) const
234 CurveCreator::Coordinates aCoords = getPoint( theISection, theIPoint );
238 if( getDimension() == CurveCreator::Dim3d ){
243 void CurveCreator_Curve::redisplayCurve()
246 myDisplayer->erase( false );
247 myDisplayer->display( constructWire(), true );
251 //! For internal use only! Undo/Redo are not used here.
252 bool CurveCreator_Curve::moveSectionInternal(const int theISection,
253 const int theNewIndex)
256 if (theISection != theNewIndex) {
257 CurveCreator_Section *aSection = mySections.at(theISection);
260 CurveCreator::Sections::iterator anIter = mySections.begin() + theISection;
262 mySections.erase(anIter);
265 anIter = mySections.begin() + theNewIndex;
266 mySections.insert(anIter, aSection);
272 //=======================================================================
273 // function: moveSection
275 //=======================================================================
276 bool CurveCreator_Curve::moveSection(const int theISection,
277 const int theNewIndex)
280 // Set the difference.
282 if (addEmptyDiff()) {
283 myListDiffs.back().init(this, CurveCreator_Operation::MoveSection,
284 theISection, theNewIndex);
288 res = moveSectionInternal(theISection, theNewIndex);
293 void CurveCreator_Curve::convert( const SectionToPointList& thePoints,
294 std::map< int, std::list<int> >& theConvPoints )
296 theConvPoints.clear();
298 SectionToPointList::const_iterator anIt = thePoints.begin(), aLast = thePoints.end();
299 std::list<int> aPoints;
300 int aSectionId, aPointId;
301 for ( ; anIt != aLast; anIt++ ) {
302 aSectionId = anIt->first;
303 aPointId = anIt->second;
305 if ( theConvPoints.find( aSectionId ) != theConvPoints.end() )
306 aPoints = theConvPoints[aSectionId];
307 aPoints.push_back( aPointId );
308 theConvPoints[aSectionId] = aPoints;
312 /************ Implementation of INTERFACE methods ************/
314 /***********************************************/
315 /*** Undo/Redo methods ***/
316 /***********************************************/
318 //! Get number of available undo operations
319 int CurveCreator_Curve::getNbUndo() const
324 //! Undo previous operation
325 bool CurveCreator_Curve::undo()
332 myCurrenPos->applyUndo(this);
338 //! Get number of available redo operations
339 int CurveCreator_Curve::getNbRedo() const
344 //! Redo last previously "undone" operation
345 bool CurveCreator_Curve::redo()
349 myCurrenPos->applyRedo(this);
358 /***********************************************/
359 /*** Section methods ***/
360 /***********************************************/
361 //! For internal use only! Undo/Redo are not used here.
362 bool CurveCreator_Curve::clearInternal()
364 // erase curve from the viewer
366 myDisplayer->erase( true );
367 // Delete all allocated data.
369 const int aNbSections = getNbSections();
371 for (; i < aNbSections; i++) {
372 delete mySections[i];
380 //=======================================================================
383 //=======================================================================
384 bool CurveCreator_Curve::clear()
388 // Set the difference.
389 if (addEmptyDiff()) {
390 myListDiffs.back().init(this, CurveCreator_Operation::Clear);
392 res = clearInternal();
397 //! For internal use only! Undo/Redo are not used here.
398 bool CurveCreator_Curve::joinInternal( const int theISectionTo,
399 const int theISectionFrom )
402 CurveCreator_Section *aSection1 = mySections.at(theISectionTo);
403 CurveCreator_Section *aSection2 = mySections.at(theISectionFrom);
405 aSection1->myPoints.insert(aSection1->myPoints.end(),
406 aSection2->myPoints.begin(),
407 aSection2->myPoints.end());
409 res = removeSection(theISectionFrom);
414 //! Join range of sections to one section (join all sections if -1 is passed in theISectionFrom argument)
415 bool CurveCreator_Curve::join( const int theISectionTo,
416 const int theISectionFrom )
420 if ( theISectionTo != theISectionFrom ) {
423 myListDiffs.back().init(this, CurveCreator_Operation::Join, theISectionTo, theISectionFrom);
425 res = joinInternal( theISectionTo, theISectionFrom );
432 //! Get number of sections
433 int CurveCreator_Curve::getNbSections() const
435 return mySections.size();
438 //! For internal use only! Undo/Redo are not used here.
439 int CurveCreator_Curve::addSectionInternal
440 (const std::string& theName, const CurveCreator::SectionType theType,
441 const bool theIsClosed, const CurveCreator::Coordinates &thePoints)
443 CurveCreator_Section *aSection = new CurveCreator_Section;
445 std::string aName = theName;
447 aName = getUniqSectionName();
449 aSection->myName = aName;
450 aSection->myType = theType;
451 aSection->myIsClosed = theIsClosed;
452 aSection->myPoints = thePoints;
453 mySections.push_back(aSection);
455 return mySections.size()-1;
458 //=======================================================================
459 // function: addSection
460 // purpose: adds an empty section
461 //=======================================================================
462 int CurveCreator_Curve::addSection
463 (const std::string& theName, const CurveCreator::SectionType theType,
464 const bool theIsClosed)
466 int resISection = -1;
467 // Set the difference.
469 CurveCreator::Coordinates aCoords; //empty list
470 if (addEmptyDiff()) {
471 myListDiffs.back().init(this, CurveCreator_Operation::AddSection,
472 theName, aCoords, theType, theIsClosed);
475 resISection = addSectionInternal(theName, theType, theIsClosed, aCoords);
480 //=======================================================================
481 // function: addSection
482 // purpose: adds a section with the given points
483 //=======================================================================
484 int CurveCreator_Curve::addSection
485 (const std::string& theName, const CurveCreator::SectionType theType,
486 const bool theIsClosed, const CurveCreator::Coordinates &thePoints)
488 int resISection = -1;
489 // Set the difference.
491 if (addEmptyDiff()) {
492 myListDiffs.back().init(this, CurveCreator_Operation::AddSection,
493 theName, thePoints, theType, theIsClosed);
496 resISection = addSectionInternal(theName, theType, theIsClosed, thePoints);
502 //! For internal use only! Undo/Redo are not used here.
503 bool CurveCreator_Curve::removeSectionInternal( const int theISection )
505 if (theISection == -1) {
506 delete mySections.back();
507 mySections.pop_back();
509 CurveCreator::Sections::iterator anIterRm = mySections.begin() + theISection;
512 mySections.erase(anIterRm);
518 //! Removes the given sections.
519 bool CurveCreator_Curve::removeSection( const int theISection )
522 // Set the difference.
525 myListDiffs.back().init(this, CurveCreator_Operation::RemoveSection, theISection);
527 res = removeSectionInternal( theISection );
534 * Get number of points in specified section or (the total number of points
535 * in Curve if theISection is equal to -1).
537 int CurveCreator_Curve::getNbPoints( const int theISection ) const
541 if (theISection == -1) {
543 const int aNbSections = getNbSections();
545 for (; i < aNbSections; i++) {
546 aNbCoords += mySections[i]->myPoints.size();
549 if ( ( theISection >= 0 ) && ( theISection < mySections.size() ) )
550 aNbCoords = mySections.at(theISection)->myPoints.size();
553 return aNbCoords/myDimension;
556 //! Get "closed" flag of the specified section
557 bool CurveCreator_Curve::isClosed( const int theISection ) const
559 return mySections.at(theISection)->myIsClosed;
562 //! For internal use only! Undo/Redo are not used here.
563 bool CurveCreator_Curve::setClosedInternal( const int theISection,
564 const bool theIsClosed )
566 if (theISection == -1) {
567 int aSize = mySections.size();
570 for (i = 0; i < aSize; i++) {
571 mySections[i]->myIsClosed = theIsClosed;
575 mySections.at(theISection)->myIsClosed = theIsClosed;
582 * Set "closed" flag of the specified section (all sections if
583 * \a theISection is -1).
585 bool CurveCreator_Curve::setClosed( const int theISection,
586 const bool theIsClosed )
589 // Set the difference.
591 if (addEmptyDiff()) {
592 myListDiffs.back().init(this, CurveCreator_Operation::SetClosed,
593 theIsClosed, theISection);
595 res = setClosedInternal( theISection, theIsClosed );
600 //! Returns specified section name
601 std::string CurveCreator_Curve::getSectionName( const int theISection ) const
603 if( ( theISection >= 0 ) && ( theISection < mySections.size() ))
604 return mySections.at(theISection)->myName;
608 //! For internal use only! Undo/Redo are not used here.
609 bool CurveCreator_Curve::setSectionNameInternal( const int theISection,
610 const std::string& theName )
613 if( ( theISection >= 0 ) && ( theISection < mySections.size() )){
614 mySections.at(theISection)->myName = theName;
620 /** Set name of the specified section */
621 bool CurveCreator_Curve::setSectionName( const int theISection,
622 const std::string& theName )
625 // Set the difference.
627 if (addEmptyDiff()) {
628 myListDiffs.back().init(this, CurveCreator_Operation::RenameSection,
629 theName, theISection);
631 res = setSectionNameInternal( theISection, theName );
636 //! Get type of the specified section
637 CurveCreator::SectionType CurveCreator_Curve::getSectionType
638 ( const int theISection ) const
640 return mySections.at(theISection)->myType;
643 //! For internal use only! Undo/Redo are not used here.
644 bool CurveCreator_Curve::setSectionTypeInternal( const int theISection,
645 const CurveCreator::SectionType theType )
647 if (theISection == -1) {
649 const int aNbSections = getNbSections();
651 for (; i < aNbSections; i++) {
652 mySections[i]->myType = theType;
656 if( mySections.at(theISection)->myType != theType ){
657 mySections.at(theISection)->myType = theType;
665 * Set type of the specified section (or all sections
666 * if \a theISection is -1).
668 bool CurveCreator_Curve::setSectionType( const int theISection,
669 const CurveCreator::SectionType theType )
673 // Set the difference.
674 if (addEmptyDiff()) {
675 myListDiffs.back().init(this, CurveCreator_Operation::SetType,
676 theType, theISection);
679 res = setSectionTypeInternal( theISection, theType );
686 /***********************************************/
687 /*** Point methods ***/
688 /***********************************************/
690 //! For internal use only! Undo/Redo are not used here.
691 bool CurveCreator_Curve::addPointsInternal( const CurveCreator::SectionsMap &theSectionsMap )
694 CurveCreator::SectionsMap::const_iterator anIt = theSectionsMap.begin();
695 CurveCreator_Section *aSection = 0;
696 for ( ; anIt != theSectionsMap.end(); anIt++ ) {
697 int anISection = anIt->first;
698 aSection = mySections.at(anISection);
700 CurveCreator::PosPointsList aSectionPoints = anIt->second;
701 CurveCreator::PosPointsList::const_iterator aPntIt = aSectionPoints.begin();
702 for( ; aPntIt != aSectionPoints.end(); aPntIt++ ){
703 int anIPnt = (*aPntIt)->myID;
704 CurveCreator::Coordinates aCoords = (*aPntIt)->myCoords;
705 CurveCreator::Coordinates::iterator anIterPosition;
707 anIterPosition = aSection->myPoints.end();
709 anIterPosition = aSection->myPoints.begin() + toICoord(anIPnt);
710 CurveCreator::Coordinates::const_iterator aFirstPosition =
712 aSection->myPoints.insert(anIterPosition,
713 aCoords.begin(), aCoords.end());
724 * Add one point to the specified section starting from the given theIPnt index
725 * (or at the end of points if \a theIPnt is -1).
727 bool CurveCreator_Curve::addPoints( const CurveCreator::Coordinates& theCoords,
728 const int theISection,
732 CurveCreator::Coordinates aCoords = theCoords;
733 // Set the difference.
735 if (addEmptyDiff()) {
736 CurveCreator_ICurve::SectionToPointCoordsList aList;
737 aList.push_back(std::make_pair(std::make_pair(theISection, theIPnt), theCoords));
738 myListDiffs.back().init(this, CurveCreator_Operation::InsertPoints,
741 CurveCreator::SectionsMap aSectionsMap;
742 CurveCreator::PosPointsList aPoints;
743 CurveCreator_PosPoint* aPosPoint = new CurveCreator_PosPoint( theIPnt, theCoords );
744 aPoints.push_back( aPosPoint );
745 aSectionsMap[theISection] = aPoints;
747 res = addPointsInternal( aSectionsMap );
753 //! For internal use only! Undo/Redo are not used here.
754 bool CurveCreator_Curve::setPointInternal( const CurveCreator::SectionsMap &theSectionsMap )
758 CurveCreator::SectionsMap::const_iterator anIt = theSectionsMap.begin();
759 CurveCreator_Section *aSection = 0;
760 for ( ; anIt != theSectionsMap.end(); anIt++ ) {
761 int anISection = anIt->first;
762 aSection = mySections.at(anISection);
764 CurveCreator::PosPointsList aSectionPoints = anIt->second;
765 CurveCreator::PosPointsList::const_iterator aPntIt = aSectionPoints.begin();
766 for( ; aPntIt != aSectionPoints.end(); aPntIt++ ){
767 int anIPnt = (*aPntIt)->myID;
768 CurveCreator::Coordinates aCoords = (*aPntIt)->myCoords;
769 for ( int i = 0; i < myDimension; i++)
770 aSection->myPoints.at(toICoord(anIPnt) + i) = aCoords[i];
781 //! Set coordinates of specified point
782 bool CurveCreator_Curve::setPoint( const int theISection,
784 const CurveCreator::Coordinates& theNewCoords )
787 // Set the difference.
789 if (addEmptyDiff()) {
790 CurveCreator_ICurve::SectionToPointCoordsList aList;
791 aList.push_back(std::make_pair(std::make_pair(theISection, theIPnt), theNewCoords));
792 myListDiffs.back().init(this, CurveCreator_Operation::SetCoordinates,
795 CurveCreator::SectionsMap aSectionsMap;
796 CurveCreator::PosPointsList aPoints;
797 CurveCreator_PosPoint* aPosPoint = new CurveCreator_PosPoint( theIPnt, theNewCoords );
798 aPoints.push_back( aPosPoint );
799 aSectionsMap[theISection] = aPoints;
801 int aSize1 = getNbPoints( theISection );
802 res = setPointInternal( aSectionsMap );
803 int aSize2 = getNbPoints( theISection );
810 //! Set coordinates of specified points from different sections
811 bool CurveCreator_Curve::setSeveralPoints( const SectionToPointCoordsList &theSectionToPntCoords)
814 // Set the difference.
816 if (addEmptyDiff()) {
817 myListDiffs.back().init(this, CurveCreator_Operation::SetCoordinates,
818 theSectionToPntCoords);
820 CurveCreator::SectionsMap aSectionsMap;
821 CurveCreator::PosPointsList aPosPoints;
822 CurveCreator_ICurve::SectionToPointCoordsList::const_iterator anIt =
823 theSectionToPntCoords.begin(), aLast = theSectionToPntCoords.end();
824 int aSectionId, aPointId;
825 for ( ; anIt != aLast; anIt++ ) {
827 aSectionId = anIt->first.first;
828 aPointId = anIt->first.second;
829 CurveCreator::Coordinates aNewCoords = anIt->second;
830 CurveCreator_PosPoint* aPosPoint =
831 new CurveCreator_PosPoint( aPointId, aNewCoords );
832 if( aSectionsMap.find(aSectionId) != aSectionsMap.end() )
833 aPosPoints = aSectionsMap[aSectionId];
834 aPosPoints.push_back( aPosPoint );
835 aSectionsMap[aSectionId] = aPosPoints;
838 res = setPointInternal( aSectionsMap );
844 //! For internal use only! Undo/Redo are not used here.
845 bool CurveCreator_Curve::removePointsInternal( const SectionToPointList &thePoints )
848 std::map<int, std::list<int> > aConvPoints;
849 convert( thePoints, aConvPoints );
850 std::map<int, std::list<int> >::const_iterator anIt = aConvPoints.begin(),
851 aLast = aConvPoints.end();
852 CurveCreator_Section *aSection = 0;
853 for ( ; anIt != aLast; anIt++ ) {
854 int aSectionId = anIt->first;
855 aSection = mySections.at(aSectionId);
857 std::list<int> aSectionPoints = anIt->second;
858 aSectionPoints.sort();
859 std::list<int>::const_reverse_iterator aPntIt = aSectionPoints.rbegin();
860 for( ; aPntIt != aSectionPoints.rend(); aPntIt++ ){
861 int aPntIndx = *aPntIt;
862 CurveCreator::Coordinates::iterator aFirstPosition;
864 aFirstPosition = aSection->myPoints.end() - getDimension();
866 aFirstPosition = aSection->myPoints.begin() + toICoord(aPntIndx);
867 aSection->myPoints.erase( aFirstPosition, aFirstPosition + getDimension() );
877 //! Remove point with given id
878 bool CurveCreator_Curve::removePoint( const int theISection, const int theIPnt )
881 // Set the difference.
883 if (addEmptyDiff()) {
884 myListDiffs.back().init(this, CurveCreator_Operation::RemovePoints,
885 theISection, theIPnt);
887 SectionToPointList aListOfSectionsToPoints;
888 aListOfSectionsToPoints.push_back(std::make_pair(theISection, theIPnt));
889 res = removePointsInternal( aListOfSectionsToPoints );
894 //! Remove several points from different sections with given ids
895 bool CurveCreator_Curve::removeSeveralPoints( const SectionToPointList &theSectionToPntIDs)
898 // Set the difference.
900 if (addEmptyDiff()) {
901 myListDiffs.back().init(this, CurveCreator_Operation::RemovePoints,
904 res = removePointsInternal( theSectionToPntIDs );
909 //=======================================================================
910 // function: getCoordinates
912 //=======================================================================
913 CurveCreator::Coordinates CurveCreator_Curve::getPoint( const int theISection,
914 const int theIPnt) const
916 CurveCreator_Section *aSection = mySections.at(theISection);
917 CurveCreator::Coordinates::const_iterator
918 anIter = aSection->myPoints.begin() + toICoord(theIPnt);
919 CurveCreator::Coordinates aResult(anIter, anIter + myDimension);
924 //=======================================================================
925 // function: getPoints
927 //=======================================================================
928 CurveCreator::Coordinates CurveCreator_Curve::getPoints( const int theISection ) const
930 CurveCreator::Coordinates aCoords;
931 if ( ( theISection >= 0 ) && ( theISection < mySections.size() ) )
933 aCoords = mySections.at(theISection)->myPoints;
939 /***********************************************/
940 /*** Presentation methods ***/
941 /***********************************************/
942 std::vector<Handle_AIS_InteractiveObject> CurveCreator_Curve::constructWire() const
944 std::vector<Handle_AIS_InteractiveObject> aCurveRepresentation;
947 CurveCreator_Utils::constructShape( this, aShape );
949 AIS_Shape* anAISShape = new AIS_Shape( aShape );
950 aCurveRepresentation.push_back( anAISShape );
951 return aCurveRepresentation;