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