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