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