Salome HOME
Migration to OCCT 7.0
[modules/geom.git] / src / CurveCreator / CurveCreator_Curve.cxx
1 // Copyright (C) 2013-2016  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
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, or (at your option) any later version.
7 //
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.
12 //
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
16 //
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 //
19
20 // File:        CurveCreator_Curve.cxx
21 // Author:      Sergey KHROMOV
22
23 #include "CurveCreator_Curve.hxx"
24
25 #include "CurveCreator.hxx"
26 #include "CurveCreator_PosPoint.hxx"
27 #include "CurveCreator_Section.hxx"
28 #include "CurveCreator_Displayer.hxx"
29 #include "CurveCreator_Utils.hxx"
30
31 #include <AIS_Shape.hxx>
32 #include <AIS_InteractiveObject.hxx>
33 #include <Geom_CartesianPoint.hxx>
34 #include <gp_Pnt.hxx>
35 #include <gp_Lin.hxx>
36 #include <TopoDS_Edge.hxx>
37 #include <TopoDS_Face.hxx>
38 #include <TopoDS_Wire.hxx>
39
40 #include <Prs3d_PointAspect.hxx>
41 #include <iostream>
42 #define DEBTRACE(msg) {std::cerr<<std::flush<<__FILE__<<" ["<<__LINE__<<"] : "<<msg<<std::endl<<std::flush;}
43
44 #include <stdio.h>
45
46 //=======================================================================
47 // function: Constructor
48 // purpose:
49 //=======================================================================
50 CurveCreator_Curve::CurveCreator_Curve( const CurveCreator::Dimension theDimension )
51 : myIsLocked  (false),
52   myDimension (theDimension),
53   myDisplayer (NULL),
54   myAISShape  (NULL),
55   myNbUndos   (0),
56   myNbRedos   (0),
57   myUndoDepth (-1),
58   myOpLevel(0),
59   mySkipSorting(false)
60 {
61 }
62
63 //=======================================================================
64 // function: Destructor
65 // purpose:
66 //=======================================================================
67 CurveCreator_Curve::~CurveCreator_Curve()
68 {
69   // Delete all allocated data.
70   clear();
71 }
72
73 //=======================================================================
74 // function: getDimension
75 // purpose:
76 //=======================================================================
77 CurveCreator::Dimension CurveCreator_Curve::getDimension() const
78 {
79   return myDimension;
80 }
81
82 //=======================================================================
83 // function: getUniqSectionName
84 // purpose: return unique section name
85 //=======================================================================
86 std::string CurveCreator_Curve::getUniqSectionName() const
87 {
88     CurveCreator_Section* aSection;
89     for( int i = 0 ; i < 1000000 ; i++ ){
90         char aBuffer[255];
91         sprintf( aBuffer, "Section_%d", i+1 );
92         std::string aName(aBuffer);
93         int j;
94         for( j = 0 ; j < mySections.size() ; j++ ){
95             aSection = (CurveCreator_Section*)getSection( j );
96             if ( aSection && aSection->myName == aName )
97               break;
98         }
99         if( j == mySections.size() )
100             return aName;
101     }
102     return "";
103 }
104
105 //=======================================================================
106 // function: setDisplayer
107 // purpose: set curve changes Displayer
108 //=======================================================================
109 void CurveCreator_Curve::setDisplayer( CurveCreator_Displayer* theDisplayer )
110 {
111   myDisplayer = theDisplayer;
112 }
113
114 //=======================================================================
115 // function: getDisplayer
116 // purpose: get curve changes Displayer
117 //=======================================================================
118 CurveCreator_Displayer* CurveCreator_Curve::getDisplayer()
119 {
120   return myDisplayer;
121 }
122
123 //=======================================================================
124 // function: removeDisplayer
125 // purpose: remove the attached Displayer
126 //=======================================================================
127 void CurveCreator_Curve::removeDisplayer()
128 {
129   myDisplayer = NULL;
130 }
131
132 //=======================================================================
133 // function: addDiff
134 // purpose:
135 //=======================================================================
136 bool CurveCreator_Curve::addEmptyDiff()
137 {
138   bool isEnabled = false;
139
140   if (myUndoDepth != 0) {
141     // Forget all Redos after the current one.
142     if (myNbRedos > 0) {
143       myNbRedos = 0;
144       myListDiffs.erase(myCurrenPos, myListDiffs.end());
145     }
146
147     if (myUndoDepth == -1 || myNbUndos < myUndoDepth) {
148       // Increase the number of undos.
149       myNbUndos++;
150     } else {
151       // If there are too many differences, remove the first one.
152       myListDiffs.pop_front();
153     }
154
155     // Add new difference.
156     myListDiffs.push_back(CurveCreator_Diff());
157     myCurrenPos = myListDiffs.end();
158     isEnabled = true;
159   }
160
161   return isEnabled;
162 }
163
164 void CurveCreator_Curve::startOperation()
165 {
166     myOpLevel++;
167 }
168
169 void CurveCreator_Curve::finishOperation()
170 {
171    myOpLevel--;
172 }
173
174 //=======================================================================
175 // function: toICoord
176 // purpose:
177 //=======================================================================
178 int CurveCreator_Curve::toICoord(const int theIPnt) const
179 {
180   return theIPnt * myDimension;
181 }
182
183 //=======================================================================
184 // function: setUndoDepth
185 // purpose:
186 //=======================================================================
187 void CurveCreator_Curve::setUndoDepth(const int theDepth)
188 {
189   if (theDepth == 0) {
190     // Reset all undo/redo data.
191     myNbUndos = 0;
192     myNbRedos = 0;
193     myListDiffs.clear();
194     myCurrenPos = myListDiffs.end();
195     myUndoDepth = 0;
196   } else if (theDepth == -1) {
197     // There is nothing to do as the depth become unlimited.
198     myUndoDepth = -1;
199   } else if (theDepth > 0) {
200     // The new "real" depth is set.
201     if (theDepth < myNbRedos) {
202       // The new depth is less then number of redos. Remove the latest redos.
203       int aShift = (myNbRedos - theDepth);
204       ListDiff::iterator aFromPos = myListDiffs.end();
205
206       while (aShift--) {
207         aFromPos--;
208       }
209
210       myListDiffs.erase(aFromPos, myListDiffs.end());
211       myNbRedos = theDepth;
212     }
213
214     if (theDepth < myNbUndos + myNbRedos) {
215       // The new depth is less then the total number of differences.
216       // Remove the first undos.
217       int aShift = (myNbUndos + myNbRedos - theDepth);
218       ListDiff::iterator aToPos = myListDiffs.begin();
219
220       while (aShift--) {
221         aToPos++;
222       }
223
224       myListDiffs.erase(myListDiffs.begin(), aToPos);
225       myNbUndos = theDepth - myNbRedos;
226     }
227
228     myUndoDepth = theDepth;
229   }
230 }
231
232 //=======================================================================
233 // function: getUndoDepth
234 // purpose:
235 //=======================================================================
236 int CurveCreator_Curve::getUndoDepth() const
237 {
238   return myUndoDepth;
239 }
240
241 void CurveCreator_Curve::getCoordinates( int theISection, int theIPoint, double& theX, double& theY, double& theZ ) const
242 {
243   CurveCreator::Coordinates aCoords = getPoint( theISection, theIPoint );
244   theX = aCoords[0];
245   theY = aCoords[1];
246   theZ = 0.;
247   if( getDimension() == CurveCreator::Dim3d ){
248     theZ = aCoords[2];
249   }
250 }
251
252 void CurveCreator_Curve::redisplayCurve()
253 {
254   //DEBTRACE("redisplayCurve");
255   if( myDisplayer ) {
256     myDisplayer->eraseAll( false );
257     myAISShape = NULL;
258
259     myDisplayer->display( getAISObject( true ), true );
260   }
261 }
262
263 //! For internal use only! Undo/Redo are not used here.
264 bool CurveCreator_Curve::moveSectionInternal(const int theISection,
265                                              const int theNewIndex)
266 {
267   bool res = false;
268   int aMovedSectionId = theISection >= 0 ? theISection : mySections.size()-1;
269
270   if (aMovedSectionId != theNewIndex) {
271     CurveCreator_Section* aSection = (CurveCreator_Section*)getSection( aMovedSectionId );
272
273     // Remove section
274     CurveCreator::Sections::iterator anIter = mySections.begin() + aMovedSectionId;
275
276     mySections.erase(anIter);
277
278     // Insert section.
279     anIter = mySections.begin() + theNewIndex;
280     mySections.insert(anIter, aSection);
281     res = true;
282   }
283   return res;
284 }
285
286 //=======================================================================
287 // function: moveSection
288 // purpose:
289 //=======================================================================
290 bool CurveCreator_Curve::moveSection(const int theISection,
291                                      const int theNewIndex)
292 {
293   bool res = false;
294   // Set the difference.
295   startOperation();
296   if (addEmptyDiff()) {
297     myListDiffs.back().init(this, CurveCreator_Operation::MoveSection,
298                             theISection, theNewIndex);
299   }
300
301   // Update the curve.
302   res = moveSectionInternal(theISection, theNewIndex);
303   finishOperation();
304   return res;
305 }
306
307 /************   Implementation of INTERFACE methods   ************/
308
309 /***********************************************/
310 /***          Undo/Redo methods              ***/
311 /***********************************************/
312
313 //! Get number of available undo operations
314 int CurveCreator_Curve::getNbUndo() const
315 {
316   return myNbUndos;
317 }
318
319 //! Undo previous operation
320 bool CurveCreator_Curve::undo()
321 {
322   bool res = false;
323   if (myNbUndos > 0) {
324     myNbUndos--;
325     myNbRedos++;
326     myCurrenPos--;
327     myCurrenPos->applyUndo(this);
328     res = true;
329   }
330   return res;
331 }
332
333 //! Get number of available redo operations
334 int CurveCreator_Curve::getNbRedo() const
335 {
336   return myNbRedos;
337 }
338
339 //! Redo last previously "undone" operation
340 bool CurveCreator_Curve::redo()
341 {
342   bool res = false;
343   if (myNbRedos > 0) {
344     myCurrenPos->applyRedo(this);
345     myCurrenPos++;
346     myNbRedos--;
347     myNbUndos++;
348     res = true;
349   }
350   return res;
351 }
352
353 /***********************************************/
354 /***           Section methods               ***/
355 /***********************************************/
356 //! For internal use only! Undo/Redo are not used here.
357 bool CurveCreator_Curve::clearInternal()
358 {
359   // erase curve from the viewer
360   if( myDisplayer ) {
361     myDisplayer->eraseAll( true );
362     myAISShape = NULL;
363   }
364   // Delete all allocated data.
365   int i = 0;
366   const int aNbSections = getNbSections();
367
368   CurveCreator_Section* aSection;
369   for (; i < aNbSections; i++) {
370     aSection = (CurveCreator_Section*)getSection( i );
371     if ( aSection )
372       delete aSection;
373   }
374
375   mySections.clear();
376   
377   return true;
378 }
379
380 //=======================================================================
381 // function: clear
382 // purpose:
383 //=======================================================================
384 bool CurveCreator_Curve::clear()
385 {
386   bool res = false;
387   startOperation();
388   // Set the difference.
389   if (addEmptyDiff()) {
390     myListDiffs.back().init(this);
391   }
392   res = clearInternal();
393   finishOperation();
394   return res;
395 }
396
397 //! For internal use only! Undo/Redo are not used here.
398 bool CurveCreator_Curve::joinInternal( const std::list<int>& theSections )
399 {
400   bool res = false;
401   if ( theSections.empty() )
402     return res;
403
404   int anISectionMain = theSections.front();
405   CurveCreator_Section* aSectionMain =
406     (CurveCreator_Section*)getSection( anISectionMain );
407
408   std::list <int> aSectionsToJoin = theSections;
409   aSectionsToJoin.erase( aSectionsToJoin.begin() ); // skip the main section
410   // it is important to sort and reverse the section ids in order to correctly remove them
411   aSectionsToJoin.sort();
412   aSectionsToJoin.reverse();
413
414   std::list<int>::const_iterator anIt = aSectionsToJoin.begin(), aLast = aSectionsToJoin.end();
415   CurveCreator_Section* aSection;
416   for (; anIt != aLast; anIt++) {
417     aSection = (CurveCreator_Section*)getSection( *anIt );
418     aSectionMain->myPoints.insert(aSectionMain->myPoints.end(), aSection->myPoints.begin(),
419                                   aSection->myPoints.end());
420     res = removeSectionInternal(*anIt);
421     if ( !res )
422       break;
423   }
424
425   redisplayCurve();
426   return res;
427 }
428
429 bool CurveCreator_Curve::join( const std::list<int>& theSections )
430 {
431   bool res = false;
432
433   if ( !theSections.empty() )
434   {
435     startOperation();
436     if (addEmptyDiff())
437       myListDiffs.back().init(this, CurveCreator_Operation::Join, theSections);
438
439     res = joinInternal( theSections );
440
441     finishOperation();
442   }
443   return res;
444 }
445
446 //! Get number of sections
447 int CurveCreator_Curve::getNbSections() const
448 {
449   return mySections.size();
450 }
451
452 //! For internal use only! Undo/Redo are not used here.
453 int CurveCreator_Curve::addSectionInternal
454         (const std::string& theName, const CurveCreator::SectionType theType,
455          const bool theIsClosed, const CurveCreator::Coordinates &thePoints)
456 {
457   CurveCreator_Section *aSection = new CurveCreator_Section;
458
459   std::string aName = theName;
460   if( aName.empty() ){
461       aName = getUniqSectionName();
462   }
463   aSection->myName     = aName;
464   aSection->myType     = theType;
465   aSection->myIsClosed = theIsClosed;
466   aSection->myPoints   = thePoints;
467   mySections.push_back(aSection);
468   redisplayCurve();
469   return mySections.size()-1;
470 }
471
472 //=======================================================================
473 // function: addSection
474 // purpose: adds an empty section
475 //=======================================================================
476 int CurveCreator_Curve::addSection
477         (const std::string& theName, const CurveCreator::SectionType theType,
478          const bool theIsClosed)
479 {
480   int resISection = -1;
481   // Set the difference.
482   startOperation();
483   CurveCreator::Coordinates aCoords; //empty list
484   if (addEmptyDiff()) {
485     myListDiffs.back().init(this, CurveCreator_Operation::AddSection,
486                             theName, aCoords, theType, theIsClosed);
487   }
488
489   resISection = addSectionInternal(theName, theType, theIsClosed, aCoords);
490
491   finishOperation();
492   return resISection;
493 }
494 //=======================================================================
495 // function: addSection
496 // purpose: adds a section with the given points
497 //=======================================================================
498 int CurveCreator_Curve::addSection
499         (const std::string& theName, const CurveCreator::SectionType theType,
500          const bool theIsClosed, const CurveCreator::Coordinates &thePoints)
501 {
502   int resISection = -1;
503   // Set the difference.
504   startOperation();
505   if (addEmptyDiff()) {
506     myListDiffs.back().init(this, CurveCreator_Operation::AddSection,
507                             theName, thePoints, theType, theIsClosed);
508   }
509
510   resISection = addSectionInternal(theName, theType, theIsClosed, thePoints);
511
512   finishOperation();
513   return resISection;
514 }
515
516 //! For internal use only! Undo/Redo are not used here.
517 bool CurveCreator_Curve::removeSectionInternal( const int theISection )
518 {
519   if (theISection == -1) {
520     delete mySections.back();
521     mySections.pop_back();
522   } else {
523     CurveCreator::Sections::iterator anIterRm = mySections.begin() + theISection;
524
525     delete *anIterRm;
526     mySections.erase(anIterRm);
527   }
528   redisplayCurve();
529   return true;
530 }
531   
532 //! Removes the given sections.
533 bool CurveCreator_Curve::removeSection( const int theISection )
534 {
535   bool res = false;
536   // Set the difference.
537   startOperation();
538   if (addEmptyDiff())
539     myListDiffs.back().init(this, CurveCreator_Operation::RemoveSection, theISection);
540
541   res = removeSectionInternal( theISection );
542
543   finishOperation();
544   return res;
545 }
546
547 /**
548  *  Get number of points in specified section or (the total number of points
549  *  in Curve if theISection is equal to -1).
550  */
551 int CurveCreator_Curve::getNbPoints( const int theISection ) const
552 {
553   int aNbCoords = 0;
554
555   CurveCreator_Section* aSection;
556   if (theISection == -1) {
557     int i = 0;
558     const int aNbSections = getNbSections();
559
560     for (; i < aNbSections; i++) {
561       aSection = (CurveCreator_Section*)getSection( i );
562       if ( aSection )
563         aNbCoords += aSection->myPoints.size();
564     }
565   } else {
566     aSection = (CurveCreator_Section*)getSection( theISection );
567     if ( aSection )
568       aNbCoords = aSection->myPoints.size();
569   }
570
571   return aNbCoords/myDimension;
572 }
573
574 void CurveCreator_Curve::setSkipSorting( const bool theIsToSkip )
575 {
576   mySkipSorting = theIsToSkip;
577 }
578
579 bool CurveCreator_Curve::canPointsBeSorted()
580 {
581   return false;
582 }
583
584 /**
585  * Saves points coordinates difference.
586  * \param theOldCoords the old points coordinates
587  */
588 void CurveCreator_Curve::saveCoordDiff( const SectionToPointCoordsList &theOldCoords )
589 {
590   // Set the difference.
591   startOperation();
592   if (addEmptyDiff()) {
593     myListDiffs.back().init(this, theOldCoords);
594   }
595   finishOperation();
596 }
597
598 //! Get "closed" flag of the specified section
599 bool CurveCreator_Curve::isClosed( const int theISection ) const
600 {
601   const CurveCreator_Section* aSection =
602     (CurveCreator_Section*)getSection( theISection );
603   return aSection ? aSection->myIsClosed : false;
604 }
605
606 //! For internal use only! Undo/Redo are not used here.
607 bool CurveCreator_Curve::setClosedInternal( const int theISection, 
608                                             const bool theIsClosed )
609 {
610   CurveCreator_Section* aSection = 0;
611   if (theISection == -1) {
612     int aSize = mySections.size();
613     int i;
614
615     for (i = 0; i < aSize; i++) {
616       aSection = (CurveCreator_Section*)getSection( i );
617       if( aSection ) {
618         aSection->myIsClosed = theIsClosed;
619         redisplayCurve();
620       }
621     }
622   } else {
623     aSection = (CurveCreator_Section*)getSection( theISection );
624     if ( aSection ) {
625       aSection->myIsClosed = theIsClosed;
626       redisplayCurve();
627     }
628   }
629   return true;
630 }
631
632 /**
633  *  Set "closed" flag of the specified section (all sections if
634  *  \a theISection is -1).
635  */
636 bool CurveCreator_Curve::setClosed( const int theISection, 
637                                     const bool theIsClosed )
638 {
639   bool res = false;
640   // Set the difference.
641   startOperation();
642   if (addEmptyDiff()) {
643     myListDiffs.back().init(this, CurveCreator_Operation::SetClosed,
644                             theIsClosed, theISection);
645   }
646   res = setClosedInternal( theISection, theIsClosed );
647   finishOperation();
648   return res;
649 }
650
651 //! Returns specified section name
652 std::string CurveCreator_Curve::getSectionName( const int theISection ) const
653 {
654   CurveCreator_Section* aSection = (CurveCreator_Section*)getSection( theISection );
655   return aSection ? aSection->myName : "";
656 }
657
658 //! For internal use only! Undo/Redo are not used here.
659 bool CurveCreator_Curve::setSectionNameInternal( const int theISection, 
660                                                  const std::string& theName )
661 {
662   bool res = false;
663   CurveCreator_Section* aSection = (CurveCreator_Section*)getSection( theISection );
664   if( aSection ) {
665     aSection->myName = theName;
666     res = true;
667   }
668   return res;
669 }
670
671 /** Set name of the specified section */
672 bool CurveCreator_Curve::setSectionName( const int theISection, 
673                                          const std::string& theName )
674 {
675   bool res = false;
676   // Set the difference.
677   startOperation();
678   if (addEmptyDiff()) {
679     myListDiffs.back().init(this, CurveCreator_Operation::RenameSection,
680                             theName, theISection);
681   }
682   res = setSectionNameInternal( theISection, theName );
683   finishOperation();
684   return res;
685 }
686
687 //! Get type of the specified section
688 CurveCreator::SectionType CurveCreator_Curve::getSectionType
689   ( const int theISection ) const
690 {
691   CurveCreator_Section* aSection = (CurveCreator_Section*)getSection( theISection );
692   return aSection ? aSection->myType : CurveCreator::Polyline;
693 }
694
695 //! For internal use only! Undo/Redo are not used here.
696 bool CurveCreator_Curve::setSectionTypeInternal( const int theISection, 
697                                                  const CurveCreator::SectionType theType )
698 {
699   CurveCreator_Section* aSection;
700   if (theISection == -1) {
701     int i = 0;
702     const int aNbSections = getNbSections();
703
704     for (; i < aNbSections; i++) {
705       aSection = (CurveCreator_Section*)getSection( i );
706       if ( aSection )
707         aSection->myType = theType;
708     }
709     redisplayCurve();
710   } else {
711     aSection = (CurveCreator_Section*)getSection( theISection );
712     if ( aSection && aSection->myType != theType ){
713       aSection->myType = theType;
714       redisplayCurve();
715     }
716   }
717   return true;
718 }
719
720 /**
721  *  Set type of the specified section (or all sections
722  *  if \a theISection is -1).
723  */
724 bool CurveCreator_Curve::setSectionType( const int theISection, 
725                                          const CurveCreator::SectionType theType )
726 {
727   bool res = false;
728   startOperation();
729   // Set the difference.
730   if (addEmptyDiff()) {
731     myListDiffs.back().init(this, CurveCreator_Operation::SetType,
732                             theType, theISection);
733   }
734
735   res = setSectionTypeInternal( theISection, theType );
736
737   finishOperation();
738   return res;
739 }
740
741
742 /***********************************************/
743 /***           Point methods                 ***/
744 /***********************************************/
745
746 //! For internal use only! Undo/Redo are not used here.
747 bool CurveCreator_Curve::addPointsInternal( const CurveCreator::SectionsMap &theSectionsMap )
748 {
749   bool res = false;
750   CurveCreator::SectionsMap::const_iterator anIt = theSectionsMap.begin();
751   CurveCreator_Section *aSection = 0;
752   for ( ; anIt != theSectionsMap.end(); anIt++ ) {
753     int anISection = anIt->first;
754     aSection = (CurveCreator_Section*)getSection( anISection );
755     if( aSection ) {
756       CurveCreator::PosPointsList aSectionPoints = anIt->second;
757       CurveCreator::PosPointsList::const_iterator aPntIt = aSectionPoints.begin();
758       for( ; aPntIt != aSectionPoints.end(); aPntIt++ ){
759         int anIPnt = (*aPntIt)->myID;
760         CurveCreator::Coordinates aCoords = (*aPntIt)->myCoords;
761         CurveCreator::Coordinates::iterator anIterPosition;
762         if(anIPnt == -1)
763           anIterPosition = aSection->myPoints.end();
764         else
765           anIterPosition = aSection->myPoints.begin() + toICoord(anIPnt);
766         CurveCreator::Coordinates::const_iterator aFirstPosition = 
767           aCoords.begin();
768         aSection->myPoints.insert(anIterPosition,
769                                   aCoords.begin(), aCoords.end());
770       }
771       res = true;
772     }
773   }
774   if(res)
775     redisplayCurve();
776   return res;
777 }
778
779 /**
780  *  Add one point to the specified section starting from the given theIPnt index
781  *  (or at the end of points if \a theIPnt is -1).
782  */
783 bool CurveCreator_Curve::addPoints( const CurveCreator::Coordinates& theCoords,
784                                     const int theISection,
785                                     const int theIPnt )
786 {
787   //DEBTRACE("addPoints");
788   bool res = false;
789   CurveCreator::Coordinates aCoords = theCoords;
790   // Set the difference.
791   startOperation();
792   if (addEmptyDiff()) {
793     CurveCreator_ICurve::SectionToPointCoordsList aList;
794     aList.push_back(std::make_pair(std::make_pair(theISection, theIPnt), theCoords));
795     myListDiffs.back().init(this, CurveCreator_Operation::InsertPoints,
796                             aList);
797   }
798   CurveCreator::SectionsMap aSectionsMap;
799   CurveCreator::PosPointsList aPoints;
800   CurveCreator_PosPoint* aPosPoint = new CurveCreator_PosPoint( theIPnt, theCoords );
801   aPoints.push_back( aPosPoint );
802   aSectionsMap[theISection] = aPoints;
803
804   res = addPointsInternal( aSectionsMap );
805
806   finishOperation();
807   return res;
808 }
809
810 //! For internal use only! Undo/Redo are not used here.
811 bool CurveCreator_Curve::setPointInternal( const CurveCreator::SectionsMap &theSectionsMap )
812 {
813   bool res = false;
814   // Update the curve.
815   CurveCreator::SectionsMap::const_iterator anIt = theSectionsMap.begin();
816   CurveCreator_Section *aSection = 0;
817   for ( ; anIt != theSectionsMap.end(); anIt++ ) {
818     int anISection = anIt->first;
819     aSection = (CurveCreator_Section*)getSection( anISection );
820     if( aSection ) { 
821       CurveCreator::PosPointsList aSectionPoints = anIt->second;
822       CurveCreator::PosPointsList::const_iterator aPntIt = aSectionPoints.begin();
823       for( ; aPntIt != aSectionPoints.end(); aPntIt++ ){
824         int anIPnt = (*aPntIt)->myID;
825         CurveCreator::Coordinates aCoords = (*aPntIt)->myCoords;
826         for ( int i = 0; i < myDimension; i++)
827           aSection->myPoints.at(toICoord(anIPnt) + i) = aCoords[i];
828       }
829       res = true;
830     }
831   }
832   if(res)
833     redisplayCurve();
834   
835   return res;
836 }
837
838 //! Set coordinates of specified point
839 bool CurveCreator_Curve::setPoint( const int theISection,
840                                    const int theIPnt,
841                                    const CurveCreator::Coordinates& theNewCoords )
842 {
843   //DEBTRACE("setPoint");
844   bool res = false;
845   // Set the difference.
846   startOperation();
847   if (addEmptyDiff()) {
848     CurveCreator_ICurve::SectionToPointCoordsList aList;
849     aList.push_back(std::make_pair(std::make_pair(theISection, theIPnt), theNewCoords));
850     myListDiffs.back().init(this, CurveCreator_Operation::SetCoordinates,
851                             aList);
852   }
853   CurveCreator::SectionsMap aSectionsMap;
854   CurveCreator::PosPointsList aPoints;
855   CurveCreator_PosPoint* aPosPoint = new CurveCreator_PosPoint( theIPnt, theNewCoords );
856   aPoints.push_back( aPosPoint );
857   aSectionsMap[theISection] = aPoints;
858
859   int aSize1 = getNbPoints( theISection );
860   res = setPointInternal( aSectionsMap );
861   int aSize2 = getNbPoints( theISection );
862
863   finishOperation();
864
865   return res; 
866 }
867
868 //! Set coordinates of specified points from different sections
869 bool CurveCreator_Curve::setSeveralPoints( const SectionToPointCoordsList &theSectionToPntCoords,
870                                            const bool theIsToSaveDiff )
871 {
872   //DEBTRACE("setSeveralPoints");
873   bool res = false;
874   // Set the difference.
875   startOperation();
876   if (theIsToSaveDiff && addEmptyDiff()) {
877     myListDiffs.back().init(this, CurveCreator_Operation::SetCoordinates,
878                             theSectionToPntCoords);
879   }
880   CurveCreator::SectionsMap aSectionsMap;
881   CurveCreator::PosPointsList aPosPoints;
882   CurveCreator_ICurve::SectionToPointCoordsList::const_iterator anIt = 
883     theSectionToPntCoords.begin(), aLast = theSectionToPntCoords.end();
884   int aSectionId, aPointId;
885   for ( ; anIt != aLast; anIt++ ) {
886     aPosPoints.clear();
887     aSectionId = anIt->first.first;
888     aPointId = anIt->first.second;
889     CurveCreator::Coordinates aNewCoords = anIt->second;
890     CurveCreator_PosPoint* aPosPoint = 
891       new CurveCreator_PosPoint( aPointId, aNewCoords );
892     if( aSectionsMap.find(aSectionId) != aSectionsMap.end() )
893       aPosPoints = aSectionsMap[aSectionId];
894     aPosPoints.push_back( aPosPoint );
895     aSectionsMap[aSectionId] = aPosPoints;
896     
897   }
898   res = setPointInternal( aSectionsMap );
899   finishOperation();
900
901   return res; 
902 }
903
904 //! For internal use only! Undo/Redo are not used here.
905 bool CurveCreator_Curve::removePointsInternal( const SectionToPointList &thePoints )
906 {
907   bool aRes = false;
908   std::map<int, std::list<int> > aConvPoints;
909   convert( thePoints, aConvPoints );
910   std::map<int, std::list<int> >::const_iterator anIt = aConvPoints.begin(),
911                                           aLast = aConvPoints.end();
912   for ( ; anIt != aLast; anIt++ ) {
913     int aSectionId = anIt->first;
914     aRes = removeSectionPoints(aSectionId, anIt->second);
915   }
916   if( aRes)
917     redisplayCurve();
918
919   return aRes;
920 }
921
922 //! Remove point with given id
923 bool CurveCreator_Curve::removePoint( const int theISection, const int theIPnt )
924 {
925   bool res = false;
926   // Set the difference.
927   startOperation();
928   SectionToPointList aListOfSectionsToPoints;
929   aListOfSectionsToPoints.push_back(std::make_pair(theISection, theIPnt));
930   if (addEmptyDiff()) {
931     myListDiffs.back().init(this, CurveCreator_Operation::RemovePoints,
932                             aListOfSectionsToPoints);
933   }
934   res = removePointsInternal( aListOfSectionsToPoints );
935   finishOperation();
936   return res;
937 }
938
939 //! Remove several points from different sections with given ids
940 bool CurveCreator_Curve::removeSeveralPoints( const SectionToPointList &theSectionToPntIDs)
941 {
942   bool res = false;
943   // Set the difference.
944   startOperation();
945   if (addEmptyDiff()) {
946     myListDiffs.back().init(this, CurveCreator_Operation::RemovePoints,
947                             theSectionToPntIDs);
948   }
949   res = removePointsInternal( theSectionToPntIDs );
950   finishOperation();
951   return res;
952 }
953
954   //=======================================================================
955 // function: getCoordinates
956 // purpose:
957 //=======================================================================
958 CurveCreator::Coordinates CurveCreator_Curve::getPoint( const int theISection,
959                                                         const int theIPnt) const
960 {
961   //DEBTRACE("getPoint");
962   CurveCreator_Section* aSection = (CurveCreator_Section*)getSection( theISection );
963   CurveCreator::Coordinates::const_iterator
964     anIter = aSection->myPoints.begin() + toICoord(theIPnt);
965   CurveCreator::Coordinates aResult(anIter, anIter + myDimension);
966
967   return aResult;
968 }
969
970 //=======================================================================
971 // function: getPoints
972 // purpose:
973 //=======================================================================
974 CurveCreator::Coordinates CurveCreator_Curve::getPoints( const int theISection ) const
975 {
976   //DEBTRACE("getPoints");
977   CurveCreator_Section* aSection = (CurveCreator_Section*)getSection( theISection );
978   return aSection ? aSection->myPoints : CurveCreator::Coordinates();
979 }
980
981 void CurveCreator_Curve::constructAISObject()
982 {
983   //DEBTRACE("constructAISObject");
984   TopoDS_Shape aShape;
985   CurveCreator_Utils::constructShape( this, aShape );
986
987   myAISShape = new AIS_Shape( aShape );
988   Handle(Prs3d_PointAspect) anAspect = myAISShape->Attributes()->PointAspect();
989   anAspect->SetScale( 3.0 );
990   anAspect->SetTypeOfMarker(Aspect_TOM_O_POINT);
991   anAspect->SetColor(Quantity_NOC_ROYALBLUE4);
992   myAISShape->Attributes()->SetPointAspect( anAspect );
993
994 }
995
996 Handle(AIS_InteractiveObject) CurveCreator_Curve::getAISObject( const bool theNeedToBuild ) const
997 {
998   //DEBTRACE("getAISObject");
999   if ( !myAISShape && theNeedToBuild ) {
1000     CurveCreator_Curve* aCurve = (CurveCreator_Curve*)this;
1001     aCurve->constructAISObject();
1002   }
1003   return myAISShape;
1004 }
1005
1006 bool CurveCreator_Curve::removeSectionPoints( const int theSectionId,
1007                                               const std::list<int>& thePointIds )
1008 {
1009   bool aRes = false;
1010
1011   CurveCreator_Section* aSection = (CurveCreator_Section*)getSection( theSectionId );
1012   if ( !aSection )
1013     return aRes;
1014
1015   std::list<int> aSectionPoints = thePointIds;
1016   aSectionPoints.sort();
1017   std::list<int>::const_reverse_iterator aPntIt = aSectionPoints.rbegin();
1018   for ( ; aPntIt != aSectionPoints.rend(); aPntIt++ ) {
1019     int aPntIndx = *aPntIt;
1020     CurveCreator::Coordinates::iterator aFirstPosition;
1021     if ( aPntIndx == -1 )
1022       aFirstPosition = aSection->myPoints.end() - getDimension();
1023     else
1024       aFirstPosition = aSection->myPoints.begin() + toICoord( aPntIndx );
1025     aSection->myPoints.erase( aFirstPosition, aFirstPosition + getDimension() );
1026     aRes = true;
1027   }
1028   return aRes;
1029 }
1030
1031 void CurveCreator_Curve::convert( const SectionToPointList& thePoints,
1032                                   std::map< int, std::list<int> >& theConvPoints )
1033 {
1034   theConvPoints.clear();
1035
1036   SectionToPointList::const_iterator anIt = thePoints.begin(), aLast = thePoints.end();
1037   std::list<int> aPoints;
1038   int aSectionId, aPointId;
1039   for ( ; anIt != aLast; anIt++ ) {
1040     aSectionId = anIt->first;
1041     aPointId = anIt->second;
1042     aPoints.clear();
1043     if ( theConvPoints.find( aSectionId ) != theConvPoints.end() )
1044       aPoints = theConvPoints[aSectionId];
1045     aPoints.push_back( aPointId );
1046     theConvPoints[aSectionId] = aPoints;
1047   }
1048 }