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