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