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