Salome HOME
8572a116d99433a57ca2b838d3651ada532f8224
[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 (theISectionTo != theISectionFrom) {
529     startOperation();
530     if (addEmptyDiff())
531       myListDiffs.back().init(this, CurveCreator_Operation::Join, theISectionTo, theISectionFrom);
532
533     res = joinInternal( theISectionTo, theISectionFrom );
534
535     finishOperation();
536   }
537   return res;
538 }
539
540 //! Get number of sections
541 int CurveCreator_Curve::getNbSections() const
542 {
543   return mySections.size();
544 }
545
546 //! For internal use only! Undo/Redo are not used here.
547 int CurveCreator_Curve::addSectionInternal
548         (const std::string& theName, const CurveCreator::SectionType theType,
549          const bool theIsClosed, const CurveCreator::Coordinates &thePoints)
550 {
551   CurveCreator_Section *aSection = new CurveCreator_Section;
552
553   std::string aName = theName;
554   if( aName.empty() ){
555       aName = getUniqSectionName();
556   }
557   aSection->myName     = aName;
558   aSection->myType     = theType;
559   aSection->myIsClosed = theIsClosed;
560   aSection->myPoints   = thePoints;
561   mySections.push_back(aSection);
562   redisplayCurve();
563   return mySections.size()-1;
564 }
565
566 //=======================================================================
567 // function: addSection
568 // purpose: adds an empty section
569 //=======================================================================
570 int CurveCreator_Curve::addSection
571         (const std::string& theName, const CurveCreator::SectionType theType,
572          const bool theIsClosed)
573 {
574   int resISection = -1;
575   // Set the difference.
576   startOperation();
577   CurveCreator::Coordinates aCoords; //empty list
578   if (addEmptyDiff()) {
579     myListDiffs.back().init(this, CurveCreator_Operation::AddSection,
580                             theName, aCoords, theType, theIsClosed);
581   }
582
583   resISection = addSectionInternal(theName, theType, theIsClosed, aCoords);
584
585   finishOperation();
586   return resISection;
587 }
588 //=======================================================================
589 // function: addSection
590 // purpose: adds a section with the given points
591 //=======================================================================
592 int CurveCreator_Curve::addSection
593         (const std::string& theName, const CurveCreator::SectionType theType,
594          const bool theIsClosed, const CurveCreator::Coordinates &thePoints)
595 {
596   int resISection = -1;
597   // Set the difference.
598   startOperation();
599   if (addEmptyDiff()) {
600     myListDiffs.back().init(this, CurveCreator_Operation::AddSection,
601                             theName, thePoints, theType, theIsClosed);
602   }
603
604   resISection = addSectionInternal(theName, theType, theIsClosed, thePoints);
605
606   finishOperation();
607   return resISection;
608 }
609
610 //! For internal use only! Undo/Redo are not used here.
611 bool CurveCreator_Curve::removeSectionInternal( const int theISection )
612 {
613   if (theISection == -1) {
614     delete mySections.back();
615     mySections.pop_back();
616   } else {
617     CurveCreator::Sections::iterator anIterRm = mySections.begin() + theISection;
618
619     delete *anIterRm;
620     mySections.erase(anIterRm);
621   }
622   redisplayCurve();
623   return true;
624 }
625   
626 //! Removes the given sections.
627 bool CurveCreator_Curve::removeSection( const int theISection )
628 {
629   bool res = false;
630   // Set the difference.
631   startOperation();
632   if (addEmptyDiff())
633     myListDiffs.back().init(this, CurveCreator_Operation::RemoveSection, theISection);
634
635   res = removeSectionInternal( theISection );
636
637   finishOperation();
638   return res;
639 }
640
641 /**
642  *  Get number of points in specified section or (the total number of points
643  *  in Curve if theISection is equal to -1).
644  */
645 int CurveCreator_Curve::getNbPoints( const int theISection ) const
646 {
647   int aNbCoords = 0;
648
649   if (theISection == -1) {
650     int i = 0;
651     const int aNbSections = getNbSections();
652
653     for (; i < aNbSections; i++) {
654       aNbCoords += mySections[i]->myPoints.size();
655     }
656   } else {
657     if ( ( theISection >= 0 ) && ( theISection < mySections.size() ) )
658       aNbCoords = mySections.at(theISection)->myPoints.size();
659   }
660
661   return aNbCoords/myDimension;
662 }
663
664 //! Get "closed" flag of the specified section
665 bool CurveCreator_Curve::isClosed( const int theISection ) const
666 {
667   return mySections.at(theISection)->myIsClosed;
668 }
669
670 //! For internal use only! Undo/Redo are not used here.
671 bool CurveCreator_Curve::setClosedInternal( const int theISection, 
672                                             const bool theIsClosed )
673 {
674   if (theISection == -1) {
675     int aSize = mySections.size();
676     int i;
677
678     for (i = 0; i < aSize; i++) {
679       mySections[i]->myIsClosed = theIsClosed;
680       redisplayCurve();
681     }
682   } else {
683     mySections.at(theISection)->myIsClosed = theIsClosed;
684     redisplayCurve();
685   }
686   return true;
687 }
688
689 /**
690  *  Set "closed" flag of the specified section (all sections if
691  *  \a theISection is -1).
692  */
693 bool CurveCreator_Curve::setClosed( const int theISection, 
694                                     const bool theIsClosed )
695 {
696   bool res = false;
697   // Set the difference.
698   startOperation();
699   if (addEmptyDiff()) {
700     myListDiffs.back().init(this, CurveCreator_Operation::SetClosed,
701                             theIsClosed, theISection);
702   }
703   res = setClosedInternal( theISection, theIsClosed );
704   finishOperation();
705   return res;
706 }
707
708 //! Returns specified section name
709 std::string CurveCreator_Curve::getSectionName( const int theISection ) const
710 {
711   if( ( theISection >= 0 ) && ( theISection < mySections.size() ))
712     return mySections.at(theISection)->myName;
713   return "";
714 }
715
716 //! For internal use only! Undo/Redo are not used here.
717 bool CurveCreator_Curve::setSectionNameInternal( const int theISection, 
718                                                  const std::string& theName )
719 {
720   bool res = false;
721   if( ( theISection >= 0 ) && ( theISection < mySections.size() )){
722     mySections.at(theISection)->myName = theName;
723     res = true;
724   }
725   return res;
726 }
727
728 /** Set name of the specified section */
729 bool CurveCreator_Curve::setSectionName( const int theISection, 
730                                          const std::string& theName )
731 {
732   bool res = false;
733   // Set the difference.
734   startOperation();
735   if (addEmptyDiff()) {
736     myListDiffs.back().init(this, CurveCreator_Operation::RenameSection,
737                             theName, theISection);
738   }
739   res = setSectionNameInternal( theISection, theName );
740   finishOperation();
741   return res;
742 }
743
744 //! Get type of the specified section
745 CurveCreator::SectionType CurveCreator_Curve::getSectionType
746   ( const int theISection ) const
747 {
748   return mySections.at(theISection)->myType;
749 }
750
751 //! For internal use only! Undo/Redo are not used here.
752 bool CurveCreator_Curve::setSectionTypeInternal( const int theISection, 
753                                                  const CurveCreator::SectionType theType )
754 {
755   if (theISection == -1) {
756     int i = 0;
757     const int aNbSections = getNbSections();
758
759     for (; i < aNbSections; i++) {
760       mySections[i]->myType = theType;
761     }
762     redisplayCurve();
763   } else {
764     if( mySections.at(theISection)->myType != theType ){
765       mySections.at(theISection)->myType = theType;
766       redisplayCurve();
767     }
768   }
769   return true;
770 }
771
772 /**
773  *  Set type of the specified section (or all sections
774  *  if \a theISection is -1).
775  */
776 bool CurveCreator_Curve::setSectionType( const int theISection, 
777                                          const CurveCreator::SectionType theType )
778 {
779   bool res = false;
780   startOperation();
781   // Set the difference.
782   if (addEmptyDiff()) {
783     myListDiffs.back().init(this, CurveCreator_Operation::SetType,
784                             theType, theISection);
785   }
786
787   res = setSectionTypeInternal( theISection, theType );
788
789   finishOperation();
790   return res;
791 }
792
793
794 /***********************************************/
795 /***           Point methods                 ***/
796 /***********************************************/
797
798 //! For internal use only! Undo/Redo are not used here.
799 bool CurveCreator_Curve::addPointsInternal( const CurveCreator::SectionsMap &theSectionsMap )
800 {
801   bool res = false;
802   CurveCreator::SectionsMap::const_iterator anIt = theSectionsMap.begin();
803   CurveCreator_Section *aSection = 0;
804   for ( ; anIt != theSectionsMap.end(); anIt++ ) {
805     int anISection = anIt->first;
806     aSection = mySections.at(anISection);
807     if( aSection ) {
808       CurveCreator::PosPointsList aSectionPoints = anIt->second;
809       CurveCreator::PosPointsList::const_iterator aPntIt = aSectionPoints.begin();
810       for( ; aPntIt != aSectionPoints.end(); aPntIt++ ){
811         int anIPnt = (*aPntIt)->myID;
812         CurveCreator::Coordinates aCoords = (*aPntIt)->myCoords;
813         CurveCreator::Coordinates::iterator anIterPosition;
814         if(anIPnt == -1)
815           anIterPosition = aSection->myPoints.end();
816         else
817           anIterPosition = aSection->myPoints.begin() + toICoord(anIPnt);
818         CurveCreator::Coordinates::const_iterator aFirstPosition = 
819           aCoords.begin();
820         aSection->myPoints.insert(anIterPosition,
821                                   aCoords.begin(), aCoords.end());
822       }
823       res = true;
824     }
825   }
826   if(res)
827     redisplayCurve();
828   return res;
829 }
830
831 /**
832  *  Add one point to the specified section starting from the given theIPnt index
833  *  (or at the end of points if \a theIPnt is -1).
834  */
835 bool CurveCreator_Curve::addPoints( const CurveCreator::Coordinates& theCoords,
836                                     const int theISection,
837                                     const int theIPnt )
838 {
839   bool res = false;
840   CurveCreator::Coordinates aCoords = theCoords;
841   // Set the difference.
842   startOperation();
843   if (addEmptyDiff()) {
844     CurveCreator_ICurve::SectionToPointCoordsList aList;
845     aList.push_back(std::make_pair(std::make_pair(theISection, theIPnt), theCoords));
846     myListDiffs.back().init(this, CurveCreator_Operation::InsertPoints,
847                             aList);
848   }
849   CurveCreator::SectionsMap aSectionsMap;
850   CurveCreator::PosPointsList aPoints;
851   CurveCreator_PosPoint* aPosPoint = new CurveCreator_PosPoint( theIPnt, theCoords );
852   aPoints.push_back( aPosPoint );
853   aSectionsMap[theISection] = aPoints;
854
855   res = addPointsInternal( aSectionsMap );
856
857   finishOperation();
858   return res;
859 }
860
861 //! For internal use only! Undo/Redo are not used here.
862 bool CurveCreator_Curve::setPointInternal( const CurveCreator::SectionsMap &theSectionsMap )
863 {
864   bool res = false;
865   // Update the curve.
866   CurveCreator::SectionsMap::const_iterator anIt = theSectionsMap.begin();
867   CurveCreator_Section *aSection = 0;
868   for ( ; anIt != theSectionsMap.end(); anIt++ ) {
869     int anISection = anIt->first;
870     aSection = mySections.at(anISection);
871     if( aSection ) { 
872       CurveCreator::PosPointsList aSectionPoints = anIt->second;
873       CurveCreator::PosPointsList::const_iterator aPntIt = aSectionPoints.begin();
874       for( ; aPntIt != aSectionPoints.end(); aPntIt++ ){
875         int anIPnt = (*aPntIt)->myID;
876         CurveCreator::Coordinates aCoords = (*aPntIt)->myCoords;
877         for ( int i = 0; i < myDimension; i++)
878           aSection->myPoints.at(toICoord(anIPnt) + i) = aCoords[i];
879       }
880       res = true;
881     }
882   }
883   if(res)
884     redisplayCurve();
885   
886   return res;
887 }
888
889 //! Set coordinates of specified point
890 bool CurveCreator_Curve::setPoint( const int theISection,
891                                    const int theIPnt,
892                                    const CurveCreator::Coordinates& theNewCoords )
893 {
894   bool res = false;
895   // Set the difference.
896   startOperation();
897   if (addEmptyDiff()) {
898     CurveCreator_ICurve::SectionToPointCoordsList aList;
899     aList.push_back(std::make_pair(std::make_pair(theISection, theIPnt), theNewCoords));
900     myListDiffs.back().init(this, CurveCreator_Operation::SetCoordinates,
901                             aList);
902   }
903   CurveCreator::SectionsMap aSectionsMap;
904   CurveCreator::PosPointsList aPoints;
905   CurveCreator_PosPoint* aPosPoint = new CurveCreator_PosPoint( theIPnt, theNewCoords );
906   aPoints.push_back( aPosPoint );
907   aSectionsMap[theISection] = aPoints;
908
909   int aSize1 = getNbPoints( theISection );
910   res = setPointInternal( aSectionsMap );
911   int aSize2 = getNbPoints( theISection );
912
913   finishOperation();
914
915   return res; 
916 }
917
918 //! Set coordinates of specified points from different sections
919 bool CurveCreator_Curve::setSeveralPoints( const SectionToPointCoordsList &theSectionToPntCoords)
920 {
921   return false;
922 }
923
924 //! For internal use only! Undo/Redo are not used here.
925 bool CurveCreator_Curve::removePointsInternal( const SectionToPointList &thePoints )
926 {
927   bool res = false;
928   std::map<int, std::list<int> > aConvPoints;
929   convert( thePoints, aConvPoints );
930   std::map<int, std::list<int> >::const_iterator anIt = aConvPoints.begin(),
931                                           aLast = aConvPoints.end();
932   CurveCreator_Section *aSection = 0;
933   for ( ; anIt != aLast; anIt++ ) {
934     int aSectionId = anIt->first;
935     aSection = mySections.at(aSectionId);
936     if( aSection ) {
937       std::list<int> aSectionPoints = anIt->second;
938       aSectionPoints.sort();
939       std::list<int>::const_reverse_iterator aPntIt = aSectionPoints.rbegin();
940       for( ; aPntIt != aSectionPoints.rend(); aPntIt++ ){
941         int aPntIndx = *aPntIt;
942         CurveCreator::Coordinates::iterator aFirstPosition;
943         if(aPntIndx == -1)
944           aFirstPosition = aSection->myPoints.end() - getDimension();
945         else
946           aFirstPosition = aSection->myPoints.begin() + toICoord(aPntIndx);
947         aSection->myPoints.erase( aFirstPosition, aFirstPosition + getDimension() );
948         res = true;
949       }
950     }
951   }
952   if(res)
953     redisplayCurve();
954   return res;
955 }
956
957 //! Remove point with given id
958 bool CurveCreator_Curve::removePoint( const int theISection, const int theIPnt )
959 {
960   bool res = false;
961   // Set the difference.
962   startOperation();
963   if (addEmptyDiff()) {
964     myListDiffs.back().init(this, CurveCreator_Operation::RemovePoints,
965                             theISection, theIPnt);
966   }
967   SectionToPointList aListOfSectionsToPoints;
968   aListOfSectionsToPoints.push_back(std::make_pair(theISection, theIPnt));
969   res = removePointsInternal( aListOfSectionsToPoints );
970   finishOperation();
971   return res;
972 }
973
974 //! Remove several points from different sections with given ids
975 bool CurveCreator_Curve::removeSeveralPoints( const SectionToPointList &theSectionToPntIDs)
976 {
977   bool res = false;
978   // Set the difference.
979   startOperation();
980   if (addEmptyDiff()) {
981     myListDiffs.back().init(this, CurveCreator_Operation::RemovePoints,
982                             theSectionToPntIDs);
983   }
984   res = removePointsInternal( theSectionToPntIDs );
985   finishOperation();
986   return res;
987 }
988
989   //=======================================================================
990 // function: getCoordinates
991 // purpose:
992 //=======================================================================
993 CurveCreator::Coordinates CurveCreator_Curve::getPoint( const int theISection,
994                                                         const int theIPnt) const
995 {
996   CurveCreator_Section *aSection = mySections.at(theISection);
997   CurveCreator::Coordinates::const_iterator
998     anIter = aSection->myPoints.begin() + toICoord(theIPnt);
999   CurveCreator::Coordinates aResult(anIter, anIter + myDimension);
1000
1001   return aResult;
1002 }
1003
1004 //=======================================================================
1005 // function: getPoints
1006 // purpose:
1007 //=======================================================================
1008 CurveCreator::Coordinates CurveCreator_Curve::getPoints( const int theISection ) const
1009 {
1010   CurveCreator::Coordinates aCoords;
1011   if ( ( theISection >= 0 ) && ( theISection < mySections.size() ) )
1012   {
1013     aCoords = mySections.at(theISection)->myPoints;
1014   }
1015   return aCoords;
1016 }
1017
1018
1019 /***********************************************/
1020 /***       Presentation methods              ***/
1021 /***********************************************/
1022 std::vector<Handle_AIS_InteractiveObject> CurveCreator_Curve::constructWire() const
1023 {
1024   std::vector<Handle_AIS_InteractiveObject> aCurveRepresentation;
1025   std::vector<Handle_AIS_InteractiveObject> aSectionObjects;
1026   for( int iSection = 0 ; iSection < getNbSections() ; iSection++ ){
1027     aSectionObjects = constructSection( iSection );
1028     for( int iObject = 0 ; iObject < aSectionObjects.size() ; iObject++ ){
1029       aCurveRepresentation.push_back( aSectionObjects.at(iObject) );
1030     }
1031   }
1032   return aCurveRepresentation;
1033 }