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