Salome HOME
69b0c38d4fc207f525c5bbc4949f1ba4c95cdfd8
[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 /************   Implementation of INTERFACE methods   ************/
351
352 /***********************************************/
353 /***          Undo/Redo methods              ***/
354 /***********************************************/
355
356 //! Get number of available undo operations
357 int CurveCreator_Curve::getNbUndo() const
358 {
359   return myNbUndos;
360 }
361
362 //! Undo previous operation
363 bool CurveCreator_Curve::undo()
364 {
365   bool res = false;
366   if (myNbUndos > 0) {
367     myNbUndos--;
368     myNbRedos++;
369     myCurrenPos--;
370     myCurrenPos->applyUndo(this);
371     res = true;
372   }
373   return res;
374 }
375
376 //! Get number of available redo operations
377 int CurveCreator_Curve::getNbRedo() const
378 {
379   return myNbRedos;
380 }
381
382 //! Redo last previously "undone" operation
383 bool CurveCreator_Curve::redo()
384 {
385   bool res = false;
386   if (myNbRedos > 0) {
387     myCurrenPos->applyRedo(this);
388     myCurrenPos++;
389     myNbRedos--;
390     myNbUndos++;
391     res = true;
392   }
393   return res;
394 }
395
396 /***********************************************/
397 /***           Section methods               ***/
398 /***********************************************/
399 //! For internal use only! Undo/Redo are not used here.
400 bool CurveCreator_Curve::clearInternal()
401 {
402   // erase curve from the viewer
403   if( myDisplayer )
404     myDisplayer->erase();
405   // Delete all allocated data.
406   int i = 0;
407   const int aNbSections = getNbSections();
408
409   for (; i < aNbSections; i++) {
410     delete mySections[i];
411   }
412
413   mySections.clear();
414   
415   return true;
416 }
417
418 //=======================================================================
419 // function: clear
420 // purpose:
421 //=======================================================================
422 bool CurveCreator_Curve::clear()
423 {
424   bool res = false;
425   startOperation();
426   // Set the difference.
427   if (addEmptyDiff()) {
428     myListDiffs.back().init(this, CurveCreator_Operation::Clear);
429   }
430   res = clearInternal();
431   finishOperation();
432   return res;
433 }
434
435 //! For internal use only! Undo/Redo are not used here.
436 bool CurveCreator_Curve::joinInternal( const int theISectionTo, 
437                                        const int theISectionFrom )
438 {
439   bool res = false;
440   CurveCreator_Section *aSection1 = mySections.at(theISectionTo);
441   CurveCreator_Section *aSection2 = mySections.at(theISectionFrom);
442
443   aSection1->myPoints.insert(aSection1->myPoints.end(),
444                              aSection2->myPoints.begin(), 
445                              aSection2->myPoints.end());
446
447   res = removeSection(theISectionFrom);
448   redisplayCurve();
449   return res;
450 }
451
452 //! Join range of sections to one section (join all sections if -1 is passed in one of arguments)
453 bool CurveCreator_Curve::join( const int theISectionTo, 
454                                const int theISectionFrom )
455 {
456   bool res = false;
457   if (theISectionTo != theISectionFrom) {
458     startOperation();
459     if (addEmptyDiff())
460       myListDiffs.back().init(this, CurveCreator_Operation::Join, theISectionTo, theISectionFrom);
461
462     res = joinInternal( theISectionTo, theISectionFrom );
463
464     finishOperation();
465   }
466   return res;
467 }
468
469 //! Get number of sections
470 int CurveCreator_Curve::getNbSections() const
471 {
472   return mySections.size();
473 }
474
475 //! For internal use only! Undo/Redo are not used here.
476 int CurveCreator_Curve::addSectionInternal
477         (const std::string& theName, const CurveCreator::SectionType theType,
478          const bool theIsClosed, const CurveCreator::Coordinates &thePoints)
479 {
480   CurveCreator_Section *aSection = new CurveCreator_Section;
481
482   std::string aName = theName;
483   if( aName.empty() ){
484       aName = getUniqSectionName();
485   }
486   aSection->myName     = aName;
487   aSection->myType     = theType;
488   aSection->myIsClosed = theIsClosed;
489   aSection->myPoints   = thePoints;
490   mySections.push_back(aSection);
491   redisplayCurve();
492   return mySections.size()-1;
493 }
494
495 //=======================================================================
496 // function: addSection
497 // purpose: adds an empty section
498 //=======================================================================
499 int CurveCreator_Curve::addSection
500         (const std::string& theName, const CurveCreator::SectionType theType,
501          const bool theIsClosed)
502 {
503   int resISection = -1;
504   // Set the difference.
505   startOperation();
506   CurveCreator::Coordinates aCoords; //empty list
507   if (addEmptyDiff()) {
508     myListDiffs.back().init(this, CurveCreator_Operation::AddSection,
509                             theName, aCoords, theType, theIsClosed);
510   }
511
512   resISection = addSectionInternal(theName, theType, theIsClosed, aCoords);
513
514   finishOperation();
515   return resISection;
516 }
517 //=======================================================================
518 // function: addSection
519 // purpose: adds a section with the given points
520 //=======================================================================
521 int CurveCreator_Curve::addSection
522         (const std::string& theName, const CurveCreator::SectionType theType,
523          const bool theIsClosed, const CurveCreator::Coordinates &thePoints)
524 {
525   int resISection = -1;
526   // Set the difference.
527   startOperation();
528   if (addEmptyDiff()) {
529     myListDiffs.back().init(this, CurveCreator_Operation::AddSection,
530                             theName, thePoints, theType, theIsClosed);
531   }
532
533   resISection = addSectionInternal(theName, theType, theIsClosed, thePoints);
534
535   finishOperation();
536   return resISection;
537 }
538
539 //! For internal use only! Undo/Redo are not used here.
540 bool CurveCreator_Curve::removeSectionInternal( const int theISection )
541 {
542   if (theISection == -1) {
543     delete mySections.back();
544     mySections.pop_back();
545   } else {
546     CurveCreator::Sections::iterator anIterRm = mySections.begin() + theISection;
547
548     delete *anIterRm;
549     mySections.erase(anIterRm);
550   }
551   redisplayCurve();
552   return true;
553 }
554   
555 //! Removes the given sections.
556 bool CurveCreator_Curve::removeSection( const int theISection )
557 {
558   bool res = false;
559   // Set the difference.
560   startOperation();
561   if (addEmptyDiff())
562     myListDiffs.back().init(this, CurveCreator_Operation::RemoveSection, theISection);
563
564   res = removeSectionInternal( theISection );
565
566   finishOperation();
567   return res;
568 }
569
570 /**
571  *  Get number of points in specified section or (the total number of points
572  *  in Curve if theISection is equal to -1).
573  */
574 int CurveCreator_Curve::getNbPoints( const int theISection ) const
575 {
576   int aNbCoords = 0;
577
578   if (theISection == -1) {
579     int i = 0;
580     const int aNbSections = getNbSections();
581
582     for (; i < aNbSections; i++) {
583       aNbCoords += mySections[i]->myPoints.size();
584     }
585   } else {
586     aNbCoords = mySections.at(theISection)->myPoints.size();
587   }
588
589   return aNbCoords/myDimension;
590 }
591
592 //! Get "closed" flag of the specified section
593 bool CurveCreator_Curve::isClosed( const int theISection ) const
594 {
595   return mySections.at(theISection)->myIsClosed;
596 }
597
598 //! For internal use only! Undo/Redo are not used here.
599 bool CurveCreator_Curve::setClosedInternal( const int theISection, 
600                                             const bool theIsClosed )
601 {
602   if (theISection == -1) {
603     int aSize = mySections.size();
604     int i;
605
606     for (i = 0; i < aSize; i++) {
607       mySections[i]->myIsClosed = theIsClosed;
608       redisplayCurve();
609     }
610   } else {
611     mySections.at(theISection)->myIsClosed = theIsClosed;
612     redisplayCurve();
613   }
614   return true;
615 }
616
617 /**
618  *  Set "closed" flag of the specified section (all sections if
619  *  \a theISection is -1).
620  */
621 bool CurveCreator_Curve::setClosed( const int theISection, 
622                                     const bool theIsClosed )
623 {
624   bool res = false;
625   // Set the difference.
626   startOperation();
627   if (addEmptyDiff()) {
628     myListDiffs.back().init(this, CurveCreator_Operation::SetClosed,
629                             theIsClosed, theISection);
630   }
631   res = setClosedInternal( theISection, theIsClosed );
632   finishOperation();
633   return res;
634 }
635
636 //! Returns specified section name
637 std::string CurveCreator_Curve::getSectionName( const int theISection ) const
638 {
639   if( ( theISection >= 0 ) && ( theISection < mySections.size() ))
640     return mySections.at(theISection)->myName;
641   return "";
642 }
643
644 //! For internal use only! Undo/Redo are not used here.
645 bool CurveCreator_Curve::setSectionNameInternal( const int theISection, 
646                                                  const std::string& theName )
647 {
648   bool res = false;
649   if( ( theISection >= 0 ) && ( theISection < mySections.size() )){
650     mySections.at(theISection)->myName = theName;
651     res = true;
652   }
653   return res;
654 }
655
656 /** Set name of the specified section */
657 bool CurveCreator_Curve::setSectionName( const int theISection, 
658                                          const std::string& theName )
659 {
660   bool res = false;
661   // Set the difference.
662   startOperation();
663   if (addEmptyDiff()) {
664     myListDiffs.back().init(this, CurveCreator_Operation::RenameSection,
665                             theName, theISection);
666   }
667   res = setSectionNameInternal( theISection, theName );
668   finishOperation();
669   return res;
670 }
671
672 //! Get type of the specified section
673 CurveCreator::SectionType CurveCreator_Curve::getSectionType
674   ( const int theISection ) const
675 {
676   return mySections.at(theISection)->myType;
677 }
678
679 //! For internal use only! Undo/Redo are not used here.
680 bool CurveCreator_Curve::setSectionTypeInternal( const int theISection, 
681                                                  const CurveCreator::SectionType theType )
682 {
683   if (theISection == -1) {
684     int i = 0;
685     const int aNbSections = getNbSections();
686
687     for (; i < aNbSections; i++) {
688       mySections[i]->myType = theType;
689     }
690     redisplayCurve();
691   } else {
692     if( mySections.at(theISection)->myType != theType ){
693       mySections.at(theISection)->myType = theType;
694       redisplayCurve();
695     }
696   }
697   return true;
698 }
699
700 /**
701  *  Set type of the specified section (or all sections
702  *  if \a theISection is -1).
703  */
704 bool CurveCreator_Curve::setSectionType( const int theISection, 
705                                          const CurveCreator::SectionType theType )
706 {
707   bool res = false;
708   startOperation();
709   // Set the difference.
710   if (addEmptyDiff()) {
711     myListDiffs.back().init(this, CurveCreator_Operation::SetType,
712                             theType, theISection);
713   }
714
715   res = setSectionTypeInternal( theISection, theType );
716
717   finishOperation();
718   return res;
719 }
720
721
722 /***********************************************/
723 /***           Point methods                 ***/
724 /***********************************************/
725
726 //! For internal use only! Undo/Redo are not used here.
727 bool CurveCreator_Curve::addPointsInternal( const CurveCreator::Coordinates& theCoords,
728                                             const std::vector<int> &theISections,
729                                             const std::vector<int> &theIPnts  )
730 {
731   bool res = false;
732   if( (theCoords.size()/getDimension()) == theISections.size() == theIPnts.size() ) {
733     for( int ind = 0; ind < theISections.size(); ind++ ) {
734       int anISection = theISections.at(ind);
735       CurveCreator_Section *aSection =
736         (anISection == -1 ? mySections.back() : mySections.at(anISection));
737
738       if( aSection ) {
739         int anIPnt = theIPnts.at(ind);
740         CurveCreator::Coordinates::iterator anIterPosition;
741         if(anIPnt == -1)
742           anIterPosition = aSection->myPoints.end();
743         else
744           anIterPosition = aSection->myPoints.begin() + toICoord(anIPnt);
745         CurveCreator::Coordinates::const_iterator aFirstPosition = 
746           theCoords.begin() + toICoord(ind);        
747         aSection->myPoints.insert(anIterPosition,
748                                   aFirstPosition, 
749                                   aFirstPosition + getDimension());
750         res = true;
751       }
752     }
753     if(res)
754       redisplayCurve();
755   }
756   return res;
757 }
758
759 /**
760  *  Add one point to the specified section starting from the given theIPnt index
761  *  (or at the end of points if \a theIPnt is -1).
762  */
763 bool CurveCreator_Curve::addPoints( const CurveCreator::Coordinates& theCoords,
764                                     const int theISection,
765                                     const int theIPnt )
766 {
767   bool res = false;
768   CurveCreator::Coordinates aCoords = theCoords;
769   // Set the difference.
770   startOperation();
771   if (addEmptyDiff()) {
772     myListDiffs.back().init(this, CurveCreator_Operation::InsertPoints,
773                             theCoords, theISection, theIPnt);
774   }
775   std::vector<int> anISections, anIPnts;
776   anISections.push_back( theISection );
777   anIPnts.push_back( theIPnt );
778   res = addPointsInternal( theCoords, anISections, anIPnts );
779   finishOperation();
780   return res;
781 }
782
783 //! For internal use only! Undo/Redo are not used here.
784 bool CurveCreator_Curve::setPointInternal( const int theISection,
785                                            const int theIPnt,
786                                            const CurveCreator::Coordinates& theNewCoords )
787 {
788   bool res = false;
789   // Update the curve.
790   if (theNewCoords.size() == myDimension) {
791     CurveCreator_Section *aSection = mySections.at(theISection);
792     int i;
793     for (i = 0; i < myDimension; i++) {
794       aSection->myPoints.at(toICoord(theIPnt) + i) = theNewCoords[i];
795     }
796     redisplayCurve();
797     
798     res = true;
799   }
800   return res;
801 }
802
803 //! Set coordinates of specified point
804 bool CurveCreator_Curve::setPoint( const int theISection,
805                                    const int theIPnt,
806                                    const CurveCreator::Coordinates& theNewCoords )
807 {
808   bool res = false;
809   // Set the difference.
810   startOperation();
811   if (addEmptyDiff()) {
812     myListDiffs.back().init(this, CurveCreator_Operation::SetCoordinates,
813                             theNewCoords, theISection, theIPnt);
814   }
815   res = setPointInternal( theISection, theIPnt, theNewCoords );
816   finishOperation();
817
818   return res; 
819 }
820
821 //! For internal use only! Undo/Redo are not used here.
822 bool CurveCreator_Curve::removePointsInternal( const std::vector<int> &theISections, 
823                                                const std::vector<int> &theIPnts )
824 {
825   bool res = false;
826   if( theISections.size() == theIPnts.size() ) {
827     for( int ind = 0; ind < theISections.size(); ind++ ) {
828       int anISection = theISections.at(ind);
829       CurveCreator_Section *aSection = mySections.at(anISection);
830       if( aSection ) {
831         int anIPnt = theIPnts.at(ind);
832         CurveCreator::Coordinates::iterator aFirstPosition;
833         if(anIPnt == -1)
834           aFirstPosition = aSection->myPoints.end();
835         else
836           aFirstPosition = aSection->myPoints.begin() + toICoord(anIPnt);
837         aSection->myPoints.erase( aFirstPosition, aFirstPosition + getDimension() );
838         res = true;
839       }
840     }
841     if(res)
842       redisplayCurve();
843   }
844   return res;
845 }
846
847 //! Remove point with given id
848 bool CurveCreator_Curve::removePoint( const int theISection, const int theIPnt )
849 {
850   bool res = false;
851   // Set the difference.
852   startOperation();
853   if (addEmptyDiff()) {
854     myListDiffs.back().init(this, CurveCreator_Operation::RemovePoints,
855                             theISection, theIPnt);
856   }
857   std::vector<int> anISections, anIPnts;
858   anISections.push_back( theISection );
859   anIPnts.push_back( theIPnt );
860   res = removePointsInternal( anISections, anIPnts );
861   finishOperation();
862   return res;
863 }
864
865 //=======================================================================
866 // function: getCoordinates
867 // purpose:
868 //=======================================================================
869 CurveCreator::Coordinates CurveCreator_Curve::getPoint( const int theISection,
870                                                         const int theIPnt) const
871 {
872   CurveCreator_Section *aSection = mySections.at(theISection);
873   CurveCreator::Coordinates::const_iterator
874     anIter = aSection->myPoints.begin() + toICoord(theIPnt);
875   CurveCreator::Coordinates aResult(anIter, anIter + myDimension);
876
877   return aResult;
878 }
879
880 //=======================================================================
881 // function: getPoints
882 // purpose:
883 //=======================================================================
884 CurveCreator::Coordinates CurveCreator_Curve::getPoints( const int theISection ) const
885 {
886   return mySections.at(theISection)->myPoints;
887 }
888
889
890 /***********************************************/
891 /***       Presentation methods              ***/
892 /***********************************************/
893 std::vector<Handle_AIS_InteractiveObject> CurveCreator_Curve::constructWire() const
894 {
895   std::vector<Handle_AIS_InteractiveObject> aCurveRepresentation;
896   std::vector<Handle_AIS_InteractiveObject> aSectionObjects;
897   for( int iSection = 0 ; iSection < getNbSections() ; iSection++ ){
898     aSectionObjects = constructSection( iSection );
899     for( int iObject = 0 ; iObject < aSectionObjects.size() ; iObject++ ){
900       aCurveRepresentation.push_back( aSectionObjects.at(iObject) );
901     }
902   }
903   return aCurveRepresentation;
904 }