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