Salome HOME
Initial version of interface 'CurveCreator_ISection' was created for the curve sections.
[modules/geom.git] / src / CurveCreator / CurveCreator_Curve.cxx
1 // Copyright (C) 2013-2015  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 <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 = (CurveCreator_Section*)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 = (CurveCreator_Section*)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 = (CurveCreator_Section*)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 =
401     (CurveCreator_Section*)getSection( anISectionMain );
402
403   std::list <int> aSectionsToJoin = theSections;
404   aSectionsToJoin.erase( aSectionsToJoin.begin() ); // skip the main section
405   // it is important to sort and reverse the section ids in order to correctly remove them
406   aSectionsToJoin.sort();
407   aSectionsToJoin.reverse();
408
409   std::list<int>::const_iterator anIt = aSectionsToJoin.begin(), aLast = aSectionsToJoin.end();
410   CurveCreator_Section* aSection;
411   for (; anIt != aLast; anIt++) {
412     aSection = (CurveCreator_Section*)getSection( *anIt );
413     aSectionMain->myPoints.insert(aSectionMain->myPoints.end(), aSection->myPoints.begin(),
414                                   aSection->myPoints.end());
415     res = removeSectionInternal(*anIt);
416     if ( !res )
417       break;
418   }
419
420   redisplayCurve();
421   return res;
422 }
423
424 bool CurveCreator_Curve::join( const std::list<int>& theSections )
425 {
426   bool res = false;
427
428   if ( !theSections.empty() )
429   {
430     startOperation();
431     if (addEmptyDiff())
432       myListDiffs.back().init(this, CurveCreator_Operation::Join, theSections);
433
434     res = joinInternal( theSections );
435
436     finishOperation();
437   }
438   return res;
439 }
440
441 //! Get number of sections
442 int CurveCreator_Curve::getNbSections() const
443 {
444   return mySections.size();
445 }
446
447 //! For internal use only! Undo/Redo are not used here.
448 int CurveCreator_Curve::addSectionInternal
449         (const std::string& theName, const CurveCreator::SectionType theType,
450          const bool theIsClosed, const CurveCreator::Coordinates &thePoints)
451 {
452   CurveCreator_Section *aSection = new CurveCreator_Section;
453
454   std::string aName = theName;
455   if( aName.empty() ){
456       aName = getUniqSectionName();
457   }
458   aSection->myName     = aName;
459   aSection->myType     = theType;
460   aSection->myIsClosed = theIsClosed;
461   aSection->myPoints   = thePoints;
462   mySections.push_back(aSection);
463   redisplayCurve();
464   return mySections.size()-1;
465 }
466
467 //=======================================================================
468 // function: addSection
469 // purpose: adds an empty section
470 //=======================================================================
471 int CurveCreator_Curve::addSection
472         (const std::string& theName, const CurveCreator::SectionType theType,
473          const bool theIsClosed)
474 {
475   int resISection = -1;
476   // Set the difference.
477   startOperation();
478   CurveCreator::Coordinates aCoords; //empty list
479   if (addEmptyDiff()) {
480     myListDiffs.back().init(this, CurveCreator_Operation::AddSection,
481                             theName, aCoords, theType, theIsClosed);
482   }
483
484   resISection = addSectionInternal(theName, theType, theIsClosed, aCoords);
485
486   finishOperation();
487   return resISection;
488 }
489 //=======================================================================
490 // function: addSection
491 // purpose: adds a section with the given points
492 //=======================================================================
493 int CurveCreator_Curve::addSection
494         (const std::string& theName, const CurveCreator::SectionType theType,
495          const bool theIsClosed, const CurveCreator::Coordinates &thePoints)
496 {
497   int resISection = -1;
498   // Set the difference.
499   startOperation();
500   if (addEmptyDiff()) {
501     myListDiffs.back().init(this, CurveCreator_Operation::AddSection,
502                             theName, thePoints, theType, theIsClosed);
503   }
504
505   resISection = addSectionInternal(theName, theType, theIsClosed, thePoints);
506
507   finishOperation();
508   return resISection;
509 }
510
511 //! For internal use only! Undo/Redo are not used here.
512 bool CurveCreator_Curve::removeSectionInternal( const int theISection )
513 {
514   if (theISection == -1) {
515     delete mySections.back();
516     mySections.pop_back();
517   } else {
518     CurveCreator::Sections::iterator anIterRm = mySections.begin() + theISection;
519
520     delete *anIterRm;
521     mySections.erase(anIterRm);
522   }
523   redisplayCurve();
524   return true;
525 }
526   
527 //! Removes the given sections.
528 bool CurveCreator_Curve::removeSection( const int theISection )
529 {
530   bool res = false;
531   // Set the difference.
532   startOperation();
533   if (addEmptyDiff())
534     myListDiffs.back().init(this, CurveCreator_Operation::RemoveSection, theISection);
535
536   res = removeSectionInternal( theISection );
537
538   finishOperation();
539   return res;
540 }
541
542 /**
543  *  Get number of points in specified section or (the total number of points
544  *  in Curve if theISection is equal to -1).
545  */
546 int CurveCreator_Curve::getNbPoints( const int theISection ) const
547 {
548   int aNbCoords = 0;
549
550   CurveCreator_Section* aSection;
551   if (theISection == -1) {
552     int i = 0;
553     const int aNbSections = getNbSections();
554
555     for (; i < aNbSections; i++) {
556       aSection = (CurveCreator_Section*)getSection( i );
557       if ( aSection )
558         aNbCoords += aSection->myPoints.size();
559     }
560   } else {
561     aSection = (CurveCreator_Section*)getSection( theISection );
562     if ( aSection )
563       aNbCoords = aSection->myPoints.size();
564   }
565
566   return aNbCoords/myDimension;
567 }
568
569 void CurveCreator_Curve::setSkipSorting( const bool theIsToSkip )
570 {
571   mySkipSorting = theIsToSkip;
572 }
573
574 bool CurveCreator_Curve::canPointsBeSorted()
575 {
576   return false;
577 }
578
579 /**
580  * Saves points coordinates difference.
581  * \param theOldCoords the old points coordinates
582  */
583 void CurveCreator_Curve::saveCoordDiff( const SectionToPointCoordsList &theOldCoords )
584 {
585   // Set the difference.
586   startOperation();
587   if (addEmptyDiff()) {
588     myListDiffs.back().init(this, theOldCoords);
589   }
590   finishOperation();
591 }
592
593 //! Get "closed" flag of the specified section
594 bool CurveCreator_Curve::isClosed( const int theISection ) const
595 {
596   const CurveCreator_Section* aSection =
597     (CurveCreator_Section*)getSection( theISection );
598   return aSection ? aSection->myIsClosed : false;
599 }
600
601 //! For internal use only! Undo/Redo are not used here.
602 bool CurveCreator_Curve::setClosedInternal( const int theISection, 
603                                             const bool theIsClosed )
604 {
605   CurveCreator_Section* aSection = 0;
606   if (theISection == -1) {
607     int aSize = mySections.size();
608     int i;
609
610     for (i = 0; i < aSize; i++) {
611       aSection = (CurveCreator_Section*)getSection( i );
612       if( aSection ) {
613         aSection->myIsClosed = theIsClosed;
614         redisplayCurve();
615       }
616     }
617   } else {
618     aSection = (CurveCreator_Section*)getSection( theISection );
619     if ( aSection ) {
620       aSection->myIsClosed = theIsClosed;
621       redisplayCurve();
622     }
623   }
624   return true;
625 }
626
627 /**
628  *  Set "closed" flag of the specified section (all sections if
629  *  \a theISection is -1).
630  */
631 bool CurveCreator_Curve::setClosed( const int theISection, 
632                                     const bool theIsClosed )
633 {
634   bool res = false;
635   // Set the difference.
636   startOperation();
637   if (addEmptyDiff()) {
638     myListDiffs.back().init(this, CurveCreator_Operation::SetClosed,
639                             theIsClosed, theISection);
640   }
641   res = setClosedInternal( theISection, theIsClosed );
642   finishOperation();
643   return res;
644 }
645
646 //! Returns specified section name
647 std::string CurveCreator_Curve::getSectionName( const int theISection ) const
648 {
649   CurveCreator_Section* aSection = (CurveCreator_Section*)getSection( theISection );
650   return aSection ? aSection->myName : "";
651 }
652
653 //! For internal use only! Undo/Redo are not used here.
654 bool CurveCreator_Curve::setSectionNameInternal( const int theISection, 
655                                                  const std::string& theName )
656 {
657   bool res = false;
658   CurveCreator_Section* aSection = (CurveCreator_Section*)getSection( theISection );
659   if( aSection ) {
660     aSection->myName = theName;
661     res = true;
662   }
663   return res;
664 }
665
666 /** Set name of the specified section */
667 bool CurveCreator_Curve::setSectionName( const int theISection, 
668                                          const std::string& theName )
669 {
670   bool res = false;
671   // Set the difference.
672   startOperation();
673   if (addEmptyDiff()) {
674     myListDiffs.back().init(this, CurveCreator_Operation::RenameSection,
675                             theName, theISection);
676   }
677   res = setSectionNameInternal( theISection, theName );
678   finishOperation();
679   return res;
680 }
681
682 //! Get type of the specified section
683 CurveCreator::SectionType CurveCreator_Curve::getSectionType
684   ( const int theISection ) const
685 {
686   CurveCreator_Section* aSection = (CurveCreator_Section*)getSection( theISection );
687   return aSection ? aSection->myType : CurveCreator::Polyline;
688 }
689
690 //! For internal use only! Undo/Redo are not used here.
691 bool CurveCreator_Curve::setSectionTypeInternal( const int theISection, 
692                                                  const CurveCreator::SectionType theType )
693 {
694   CurveCreator_Section* aSection;
695   if (theISection == -1) {
696     int i = 0;
697     const int aNbSections = getNbSections();
698
699     for (; i < aNbSections; i++) {
700       aSection = (CurveCreator_Section*)getSection( i );
701       if ( aSection )
702         aSection->myType = theType;
703     }
704     redisplayCurve();
705   } else {
706     aSection = (CurveCreator_Section*)getSection( theISection );
707     if ( aSection && aSection->myType != theType ){
708       aSection->myType = theType;
709       redisplayCurve();
710     }
711   }
712   return true;
713 }
714
715 /**
716  *  Set type of the specified section (or all sections
717  *  if \a theISection is -1).
718  */
719 bool CurveCreator_Curve::setSectionType( const int theISection, 
720                                          const CurveCreator::SectionType theType )
721 {
722   bool res = false;
723   startOperation();
724   // Set the difference.
725   if (addEmptyDiff()) {
726     myListDiffs.back().init(this, CurveCreator_Operation::SetType,
727                             theType, theISection);
728   }
729
730   res = setSectionTypeInternal( theISection, theType );
731
732   finishOperation();
733   return res;
734 }
735
736
737 /***********************************************/
738 /***           Point methods                 ***/
739 /***********************************************/
740
741 //! For internal use only! Undo/Redo are not used here.
742 bool CurveCreator_Curve::addPointsInternal( const CurveCreator::SectionsMap &theSectionsMap )
743 {
744   bool res = false;
745   CurveCreator::SectionsMap::const_iterator anIt = theSectionsMap.begin();
746   CurveCreator_Section *aSection = 0;
747   for ( ; anIt != theSectionsMap.end(); anIt++ ) {
748     int anISection = anIt->first;
749     aSection = (CurveCreator_Section*)getSection( anISection );
750     if( aSection ) {
751       CurveCreator::PosPointsList aSectionPoints = anIt->second;
752       CurveCreator::PosPointsList::const_iterator aPntIt = aSectionPoints.begin();
753       for( ; aPntIt != aSectionPoints.end(); aPntIt++ ){
754         int anIPnt = (*aPntIt)->myID;
755         CurveCreator::Coordinates aCoords = (*aPntIt)->myCoords;
756         CurveCreator::Coordinates::iterator anIterPosition;
757         if(anIPnt == -1)
758           anIterPosition = aSection->myPoints.end();
759         else
760           anIterPosition = aSection->myPoints.begin() + toICoord(anIPnt);
761         CurveCreator::Coordinates::const_iterator aFirstPosition = 
762           aCoords.begin();
763         aSection->myPoints.insert(anIterPosition,
764                                   aCoords.begin(), aCoords.end());
765       }
766       res = true;
767     }
768   }
769   if(res)
770     redisplayCurve();
771   return res;
772 }
773
774 /**
775  *  Add one point to the specified section starting from the given theIPnt index
776  *  (or at the end of points if \a theIPnt is -1).
777  */
778 bool CurveCreator_Curve::addPoints( const CurveCreator::Coordinates& theCoords,
779                                     const int theISection,
780                                     const int theIPnt )
781 {
782   bool res = false;
783   CurveCreator::Coordinates aCoords = theCoords;
784   // Set the difference.
785   startOperation();
786   if (addEmptyDiff()) {
787     CurveCreator_ICurve::SectionToPointCoordsList aList;
788     aList.push_back(std::make_pair(std::make_pair(theISection, theIPnt), theCoords));
789     myListDiffs.back().init(this, CurveCreator_Operation::InsertPoints,
790                             aList);
791   }
792   CurveCreator::SectionsMap aSectionsMap;
793   CurveCreator::PosPointsList aPoints;
794   CurveCreator_PosPoint* aPosPoint = new CurveCreator_PosPoint( theIPnt, theCoords );
795   aPoints.push_back( aPosPoint );
796   aSectionsMap[theISection] = aPoints;
797
798   res = addPointsInternal( aSectionsMap );
799
800   finishOperation();
801   return res;
802 }
803
804 //! For internal use only! Undo/Redo are not used here.
805 bool CurveCreator_Curve::setPointInternal( const CurveCreator::SectionsMap &theSectionsMap )
806 {
807   bool res = false;
808   // Update the curve.
809   CurveCreator::SectionsMap::const_iterator anIt = theSectionsMap.begin();
810   CurveCreator_Section *aSection = 0;
811   for ( ; anIt != theSectionsMap.end(); anIt++ ) {
812     int anISection = anIt->first;
813     aSection = (CurveCreator_Section*)getSection( anISection );
814     if( aSection ) { 
815       CurveCreator::PosPointsList aSectionPoints = anIt->second;
816       CurveCreator::PosPointsList::const_iterator aPntIt = aSectionPoints.begin();
817       for( ; aPntIt != aSectionPoints.end(); aPntIt++ ){
818         int anIPnt = (*aPntIt)->myID;
819         CurveCreator::Coordinates aCoords = (*aPntIt)->myCoords;
820         for ( int i = 0; i < myDimension; i++)
821           aSection->myPoints.at(toICoord(anIPnt) + i) = aCoords[i];
822       }
823       res = true;
824     }
825   }
826   if(res)
827     redisplayCurve();
828   
829   return res;
830 }
831
832 //! Set coordinates of specified point
833 bool CurveCreator_Curve::setPoint( const int theISection,
834                                    const int theIPnt,
835                                    const CurveCreator::Coordinates& theNewCoords )
836 {
837   bool res = false;
838   // Set the difference.
839   startOperation();
840   if (addEmptyDiff()) {
841     CurveCreator_ICurve::SectionToPointCoordsList aList;
842     aList.push_back(std::make_pair(std::make_pair(theISection, theIPnt), theNewCoords));
843     myListDiffs.back().init(this, CurveCreator_Operation::SetCoordinates,
844                             aList);
845   }
846   CurveCreator::SectionsMap aSectionsMap;
847   CurveCreator::PosPointsList aPoints;
848   CurveCreator_PosPoint* aPosPoint = new CurveCreator_PosPoint( theIPnt, theNewCoords );
849   aPoints.push_back( aPosPoint );
850   aSectionsMap[theISection] = aPoints;
851
852   int aSize1 = getNbPoints( theISection );
853   res = setPointInternal( aSectionsMap );
854   int aSize2 = getNbPoints( theISection );
855
856   finishOperation();
857
858   return res; 
859 }
860
861 //! Set coordinates of specified points from different sections
862 bool CurveCreator_Curve::setSeveralPoints( const SectionToPointCoordsList &theSectionToPntCoords,
863                                            const bool theIsToSaveDiff )
864 {
865   bool res = false;
866   // Set the difference.
867   startOperation();
868   if (theIsToSaveDiff && addEmptyDiff()) {
869     myListDiffs.back().init(this, CurveCreator_Operation::SetCoordinates,
870                             theSectionToPntCoords);
871   }
872   CurveCreator::SectionsMap aSectionsMap;
873   CurveCreator::PosPointsList aPosPoints;
874   CurveCreator_ICurve::SectionToPointCoordsList::const_iterator anIt = 
875     theSectionToPntCoords.begin(), aLast = theSectionToPntCoords.end();
876   int aSectionId, aPointId;
877   for ( ; anIt != aLast; anIt++ ) {
878     aPosPoints.clear();
879     aSectionId = anIt->first.first;
880     aPointId = anIt->first.second;
881     CurveCreator::Coordinates aNewCoords = anIt->second;
882     CurveCreator_PosPoint* aPosPoint = 
883       new CurveCreator_PosPoint( aPointId, aNewCoords );
884     if( aSectionsMap.find(aSectionId) != aSectionsMap.end() )
885       aPosPoints = aSectionsMap[aSectionId];
886     aPosPoints.push_back( aPosPoint );
887     aSectionsMap[aSectionId] = aPosPoints;
888     
889   }
890   res = setPointInternal( aSectionsMap );
891   finishOperation();
892
893   return res; 
894 }
895
896 //! For internal use only! Undo/Redo are not used here.
897 bool CurveCreator_Curve::removePointsInternal( const SectionToPointList &thePoints )
898 {
899   bool aRes = false;
900   std::map<int, std::list<int> > aConvPoints;
901   convert( thePoints, aConvPoints );
902   std::map<int, std::list<int> >::const_iterator anIt = aConvPoints.begin(),
903                                           aLast = aConvPoints.end();
904   for ( ; anIt != aLast; anIt++ ) {
905     int aSectionId = anIt->first;
906     aRes = removeSectionPoints(aSectionId, anIt->second);
907   }
908   if( aRes)
909     redisplayCurve();
910
911   return aRes;
912 }
913
914 //! Remove point with given id
915 bool CurveCreator_Curve::removePoint( const int theISection, const int theIPnt )
916 {
917   bool res = false;
918   // Set the difference.
919   startOperation();
920   SectionToPointList aListOfSectionsToPoints;
921   aListOfSectionsToPoints.push_back(std::make_pair(theISection, theIPnt));
922   if (addEmptyDiff()) {
923     myListDiffs.back().init(this, CurveCreator_Operation::RemovePoints,
924                             aListOfSectionsToPoints);
925   }
926   res = removePointsInternal( aListOfSectionsToPoints );
927   finishOperation();
928   return res;
929 }
930
931 //! Remove several points from different sections with given ids
932 bool CurveCreator_Curve::removeSeveralPoints( const SectionToPointList &theSectionToPntIDs)
933 {
934   bool res = false;
935   // Set the difference.
936   startOperation();
937   if (addEmptyDiff()) {
938     myListDiffs.back().init(this, CurveCreator_Operation::RemovePoints,
939                             theSectionToPntIDs);
940   }
941   res = removePointsInternal( theSectionToPntIDs );
942   finishOperation();
943   return res;
944 }
945
946   //=======================================================================
947 // function: getCoordinates
948 // purpose:
949 //=======================================================================
950 CurveCreator::Coordinates CurveCreator_Curve::getPoint( const int theISection,
951                                                         const int theIPnt) const
952 {
953   CurveCreator_Section* aSection = (CurveCreator_Section*)getSection( theISection );
954   CurveCreator::Coordinates::const_iterator
955     anIter = aSection->myPoints.begin() + toICoord(theIPnt);
956   CurveCreator::Coordinates aResult(anIter, anIter + myDimension);
957
958   return aResult;
959 }
960
961 //=======================================================================
962 // function: getPoints
963 // purpose:
964 //=======================================================================
965 CurveCreator::Coordinates CurveCreator_Curve::getPoints( const int theISection ) const
966 {
967   CurveCreator_Section* aSection = (CurveCreator_Section*)getSection( theISection );
968   return aSection ? aSection->myPoints : CurveCreator::Coordinates();
969 }
970
971 void CurveCreator_Curve::constructAISObject()
972 {
973   TopoDS_Shape aShape;
974   CurveCreator_Utils::constructShape( this, aShape );
975
976   myAISShape = new AIS_Shape( aShape );
977 }
978
979 Handle(AIS_InteractiveObject) CurveCreator_Curve::getAISObject( const bool theNeedToBuild ) const
980 {
981   if ( !myAISShape && theNeedToBuild ) {
982     CurveCreator_Curve* aCurve = (CurveCreator_Curve*)this;
983     aCurve->constructAISObject();
984   }
985   return myAISShape;
986 }
987
988 bool CurveCreator_Curve::removeSectionPoints( const int theSectionId,
989                                               const std::list<int>& thePointIds )
990 {
991   bool aRes = false;
992
993   CurveCreator_Section* aSection = (CurveCreator_Section*)getSection( theSectionId );
994   if ( !aSection )
995     return aRes;
996
997   std::list<int> aSectionPoints = thePointIds;
998   aSectionPoints.sort();
999   std::list<int>::const_reverse_iterator aPntIt = aSectionPoints.rbegin();
1000   for ( ; aPntIt != aSectionPoints.rend(); aPntIt++ ) {
1001     int aPntIndx = *aPntIt;
1002     CurveCreator::Coordinates::iterator aFirstPosition;
1003     if ( aPntIndx == -1 )
1004       aFirstPosition = aSection->myPoints.end() - getDimension();
1005     else
1006       aFirstPosition = aSection->myPoints.begin() + toICoord( aPntIndx );
1007     aSection->myPoints.erase( aFirstPosition, aFirstPosition + getDimension() );
1008     aRes = true;
1009   }
1010   return aRes;
1011 }
1012
1013 void CurveCreator_Curve::convert( const SectionToPointList& thePoints,
1014                                   std::map< int, std::list<int> >& theConvPoints )
1015 {
1016   theConvPoints.clear();
1017
1018   SectionToPointList::const_iterator anIt = thePoints.begin(), aLast = thePoints.end();
1019   std::list<int> aPoints;
1020   int aSectionId, aPointId;
1021   for ( ; anIt != aLast; anIt++ ) {
1022     aSectionId = anIt->first;
1023     aPointId = anIt->second;
1024     aPoints.clear();
1025     if ( theConvPoints.find( aSectionId ) != theConvPoints.end() )
1026       aPoints = theConvPoints[aSectionId];
1027     aPoints.push_back( aPointId );
1028     theConvPoints[aSectionId] = aPoints;
1029   }
1030 }