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