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