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