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