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