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