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