Salome HOME
83b4c68fc98176050c5a92a258b2ceed92c66f12
[modules/hydro.git] / src / HYDROCurveCreator / CurveCreator_Curve.cxx
1 // Copyright (C) 2013  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License.
7 //
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 // Lesser General Public License for more details.
12 //
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
16 //
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 //
19
20 // File:        CurveCreator_Curve.cxx
21 // Author:      Sergey KHROMOV
22
23 #include "CurveCreator_Curve.hxx"
24
25 #include "CurveCreator.hxx"
26 #include "CurveCreator_Section.hxx"
27 #include "CurveCreator_Listener.hxx"
28
29 #include <stdio.h>
30
31 //=======================================================================
32 // function: Constructor
33 // purpose:
34 //=======================================================================
35 CurveCreator_Curve::CurveCreator_Curve( const CurveCreator::Dimension theDimension )
36 : myIsLocked  (false),
37   myDimension (theDimension),
38   myListener(NULL),
39   myNbUndos   (0),
40   myNbRedos   (0),
41   myUndoDepth (-1),
42   myOpLevel(0)
43 {
44 }
45
46 //=======================================================================
47 // function: Destructor
48 // purpose:
49 //=======================================================================
50 CurveCreator_Curve::~CurveCreator_Curve()
51 {
52   // Delete all allocated data.
53   clear();
54 }
55
56 //=======================================================================
57 // function: getDimension
58 // purpose:
59 //=======================================================================
60 CurveCreator::Dimension CurveCreator_Curve::getDimension() const
61 {
62   return myDimension;
63 }
64
65 //=======================================================================
66 // function: getUniqSectionName
67 // purpose: return unique section name
68 //=======================================================================
69 std::string CurveCreator_Curve::getUniqSectionName() const
70 {
71     for( int i = 0 ; i < 1000000 ; i++ ){
72         char aBuffer[255];
73         sprintf( aBuffer, "Section_%d", i+1 );
74         std::string aName(aBuffer);
75         int j;
76         for( j = 0 ; j < mySections.size() ; j++ ){
77             if( mySections[j]->myName == aName )
78               break;
79         }
80         if( j == mySections.size() )
81             return aName;
82     }
83     return "";
84 }
85
86 //=======================================================================
87 // function: setListener
88 // purpose: set curve changes listener
89 //=======================================================================
90 void CurveCreator_Curve::setListener( CurveCreator_Listener* theListener )
91 {
92   myListener = theListener;
93 }
94
95 //=======================================================================
96 // function: removeListener
97 // purpose: remove the attached listener
98 //=======================================================================
99 void CurveCreator_Curve::removeListener()
100 {
101   myListener = NULL;
102 }
103
104 //=======================================================================
105 // function: addDiff
106 // purpose:
107 //=======================================================================
108 bool CurveCreator_Curve::addEmptyDiff()
109 {
110   bool isEnabled = false;
111
112   if (myUndoDepth != 0) {
113     // Forget all Redos after the current one.
114     if (myNbRedos > 0) {
115       myNbRedos = 0;
116       myListDiffs.erase(myCurrenPos, myListDiffs.end());
117     }
118
119     if (myUndoDepth == -1 || myNbUndos < myUndoDepth) {
120       // Increase the number of undos.
121       myNbUndos++;
122     } else {
123       // If there are too many differences, remove the first one.
124       myListDiffs.pop_front();
125     }
126
127     // Add new difference.
128     myListDiffs.push_back(CurveCreator_Diff());
129     myCurrenPos = myListDiffs.end();
130     isEnabled = true;
131   }
132
133   return isEnabled;
134 }
135
136 void CurveCreator_Curve::startOperation()
137 {
138     myOpLevel++;
139 }
140
141 void CurveCreator_Curve::finishOperation()
142 {
143    myOpLevel--;
144 }
145
146 //=======================================================================
147 // function: toICoord
148 // purpose:
149 //=======================================================================
150 int CurveCreator_Curve::toICoord(const int theIPnt) const
151 {
152   return theIPnt * myDimension;
153 }
154
155 //=======================================================================
156 // function: setUndoDepth
157 // purpose:
158 //=======================================================================
159 void CurveCreator_Curve::setUndoDepth(const int theDepth)
160 {
161   if (theDepth == 0) {
162     // Reset all undo/redo data.
163     myNbUndos = 0;
164     myNbRedos = 0;
165     myListDiffs.clear();
166     myCurrenPos = myListDiffs.end();
167     myUndoDepth = 0;
168   } else if (theDepth == -1) {
169     // There is nothing to do as the depth become unlimited.
170     myUndoDepth = -1;
171   } else if (theDepth > 0) {
172     // The new "real" depth is set.
173     if (theDepth < myNbRedos) {
174       // The new depth is less then number of redos. Remove the latest redos.
175       int aShift = (myNbRedos - theDepth);
176       ListDiff::iterator aFromPos = myListDiffs.end();
177
178       while (aShift--) {
179         aFromPos--;
180       }
181
182       myListDiffs.erase(aFromPos, myListDiffs.end());
183       myNbRedos = theDepth;
184     }
185
186     if (theDepth < myNbUndos + myNbRedos) {
187       // The new depth is less then the total number of differences.
188       // Remove the first undos.
189       int aShift = (myNbUndos + myNbRedos - theDepth);
190       ListDiff::iterator aToPos = myListDiffs.begin();
191
192       while (aShift--) {
193         aToPos++;
194       }
195
196       myListDiffs.erase(myListDiffs.begin(), aToPos);
197       myNbUndos = theDepth - myNbRedos;
198     }
199
200     myUndoDepth = theDepth;
201   }
202 }
203
204 //=======================================================================
205 // function: getUndoDepth
206 // purpose:
207 //=======================================================================
208 int CurveCreator_Curve::getUndoDepth() const
209 {
210   return myUndoDepth;
211 }
212
213 /************   Implementation of INTERFACE methods   ************/
214
215 /***********************************************/
216 /***          Undo/Redo methods              ***/
217 /***********************************************/
218
219 //! Get number of available undo operations
220 int CurveCreator_Curve::getNbUndo() const
221 {
222   return myNbUndos;
223 }
224
225 //! Undo previous operation
226 bool CurveCreator_Curve::undo()
227 {
228   bool res = false;
229   if (myNbUndos > 0) {
230     myNbUndos--;
231     myNbRedos++;
232     myCurrenPos--;
233     myCurrenPos->applyUndo(this);
234     res = true;
235   }
236   return res;
237 }
238
239 //! Get number of available redo operations
240 int CurveCreator_Curve::getNbRedo() const
241 {
242   return myNbRedos;
243 }
244
245 //! Redo last previously "undone" operation
246 bool CurveCreator_Curve::redo()
247 {
248   bool res = false;
249   if (myNbRedos > 0) {
250     myCurrenPos->applyRedo(this);
251     myCurrenPos++;
252     myNbRedos--;
253     myNbUndos++;
254     res = true;
255   }
256   return res;
257 }
258
259 /***********************************************/
260 /***           Section methods               ***/
261 /***********************************************/
262 //=======================================================================
263 // function: clear
264 // purpose:
265 //=======================================================================
266 bool CurveCreator_Curve::clear()
267 {
268   // Delete all allocated data.
269   int i = 0;
270   const int aNbSections = getNbSections();
271
272   for (; i < aNbSections; i++) {
273     delete mySections[i];
274   }
275
276   mySections.clear();
277   if( myListener )
278     myListener->curveChanged();
279   
280   return true;
281 }
282
283 //! Join range of sections to one section (join all sections if -1 is passed in one of arguments)
284 bool CurveCreator_Curve::join( const int theISectionTo, 
285                    const int theISectionFrom )
286 {
287   if (theISectionTo != theISectionFrom) {
288     startOperation();
289     if (addEmptyDiff())
290       myListDiffs.back().init(this, CurveCreator_Operation::Join, theISectionTo, theISectionFrom);
291
292     CurveCreator_Section *aSection1 = mySections.at(theISectionTo);
293     CurveCreator_Section *aSection2 = mySections.at(theISectionFrom);
294
295     aSection1->myPoints.insert(aSection1->myPoints.end(),
296                                aSection2->myPoints.begin(), 
297                                aSection2->myPoints.end());
298
299     removeSection(theISectionFrom);
300     if( myListener )
301       myListener->curveChanged();
302
303     finishOperation();
304     return true;
305   }
306   return false;
307 }
308
309 //! Get number of sections
310 int CurveCreator_Curve::getNbSections() const
311 {
312   return mySections.size();
313 }
314
315 //=======================================================================
316 // function: addSection
317 // purpose: adds an empty section
318 //=======================================================================
319 int CurveCreator_Curve::addSection
320         (const std::string& theName, const CurveCreator::SectionType theType,
321          const bool theIsClosed)
322 {
323   int resISection = -1;
324   // Set the difference.
325   startOperation();
326   if (addEmptyDiff()) {
327     CurveCreator::Coordinates aCoords; //empty list
328     myListDiffs.back().init(this, CurveCreator_Operation::AddSection,
329                             theName, aCoords, theType, theIsClosed);
330   }
331   CurveCreator_Section *aSection = new CurveCreator_Section;
332
333   std::string aName = theName;
334   if( aName.empty() ){
335       aName = getUniqSectionName();
336   }
337   aSection->myName     = aName;
338   aSection->myType     = theType;
339   aSection->myIsClosed = theIsClosed;
340   mySections.push_back(aSection);
341   if( myListener )
342     myListener->sectionAdded( -1 );
343
344   finishOperation();
345   return mySections.size()-1;
346 }
347 //=======================================================================
348 // function: addSection
349 // purpose: adds a section with the given points
350 //=======================================================================
351 int CurveCreator_Curve::addSection
352         (const std::string& theName, const CurveCreator::SectionType theType,
353          const bool theIsClosed, const CurveCreator::Coordinates &thePoints)
354 {
355   int resISection = -1;
356   //// Set the difference.
357   //startOperation();
358   //if (addEmptyDiff()) {
359   //  myListDiffs.back().init(this, CurveCreator_Operation::AddSection,
360   //                          theName, thePoints, theType, theIsClosed);
361   //}
362
363   // create an empty section
364   resISection = addSection(theName, theType, theIsClosed);
365   if( resISection != -1 ) {
366     // attach the given points to created section
367     CurveCreator_Section *aSection = mySections.at(resISection);
368     aSection->myPoints = thePoints;
369   }
370   
371   //finishOperation();
372   return resISection;
373 }
374
375 //! Removes the given sections.
376 bool CurveCreator_Curve::removeSection( const int theISection )
377 {
378   // Set the difference.
379   startOperation();
380   if (addEmptyDiff())
381     myListDiffs.back().init(this, CurveCreator_Operation::RemoveSection, theISection);
382
383   if (theISection == -1) {
384     delete mySections.back();
385     mySections.pop_back();
386   } else {
387     CurveCreator::Sections::iterator anIterRm = mySections.begin() + theISection;
388
389     delete *anIterRm;
390     mySections.erase(anIterRm);
391   }
392   if( myListener )
393     myListener->sectionRemoved(theISection);
394
395   finishOperation();
396   return true;
397 }
398
399 /**
400  *  Get number of points in specified section or (the total number of points
401  *  in Curve if theISection is equal to -1).
402  */
403 int CurveCreator_Curve::getNbPoints( const int theISection ) const
404 {
405   int aNbCoords = 0;
406
407   if (theISection == -1) {
408     int i = 0;
409     const int aNbSections = getNbSections();
410
411     for (; i < aNbSections; i++) {
412       aNbCoords += mySections[i]->myPoints.size();
413     }
414   } else {
415     aNbCoords = mySections.at(theISection)->myPoints.size();
416   }
417
418   return aNbCoords/myDimension;
419 }
420
421 //! Get "closed" flag of the specified section
422 bool CurveCreator_Curve::isClosed( const int theISection ) const
423 {
424   return mySections.at(theISection)->myIsClosed;
425 }
426
427 /**
428  *  Set "closed" flag of the specified section (all sections if
429  *  \a theISection is -1).
430  */
431 bool CurveCreator_Curve::setClosed( const int theISection, 
432                         const bool theIsClosed )
433 {
434   if (theISection == -1) {
435     int aSize = mySections.size();
436     int i;
437
438     for (i = 0; i < aSize; i++) {
439       mySections[i]->myIsClosed = theIsClosed;
440       if( myListener ){
441         myListener->sectionClosed( theISection, theIsClosed );
442       }
443     }
444   } else {
445     mySections.at(theISection)->myIsClosed = theIsClosed;
446     if( myListener ){
447       myListener->sectionClosed( theISection, theIsClosed );
448     }
449   }
450   return true;
451 }
452
453 //! Returns specifyed section name
454 std::string CurveCreator_Curve::getSectionName( const int theISection ) const
455 {
456   if( ( theISection >= 0 ) && ( theISection < mySections.size() ))
457     return mySections.at(theISection)->myName;
458   return "";
459 }
460
461 /** Set name of the specified section */
462 bool CurveCreator_Curve::setSectionName
463   ( const int theISection, const std::string& theName )
464 {
465   if( ( theISection >= 0 ) && ( theISection < mySections.size() )){
466     mySections.at(theISection)->myName = theName;
467     return true;
468   }
469   return false;
470 }
471
472 //! Get type of the specified section
473 CurveCreator::SectionType CurveCreator_Curve::getSectionType
474   ( const int theISection ) const
475 {
476   return mySections.at(theISection)->myType;
477 }
478
479 /**
480  *  Set type of the specified section (or all sections
481  *  if \a theISection is -1).
482  */
483 bool CurveCreator_Curve::setSectionType( const int theISection, 
484                                          const CurveCreator::SectionType theType )
485 {
486   if (theISection == -1) {
487     int i = 0;
488     const int aNbSections = getNbSections();
489
490     for (; i < aNbSections; i++) {
491       mySections[i]->myType = theType;
492     }
493     if( myListener )
494       myListener->curveChanged();
495   } else {
496     if( mySections.at(theISection)->myType != theType ){
497       mySections.at(theISection)->myType = theType;
498       if( myListener )
499         myListener->sectionTypeChanged(theISection);
500     }
501   }
502   return true;
503 }
504
505
506 /***********************************************/
507 /***           Point methods                 ***/
508 /***********************************************/
509
510 /**
511  *  Add one point to the specified section starting from the given theIPnt index
512  *  (or at the end of points if \a theIPnt is -1).
513  */
514 bool CurveCreator_Curve::addPoints( const CurveCreator::Coordinates& theCoords,
515                                     const int theISection,
516                                     const int theIPnt )
517 {
518   bool res = false;
519   CurveCreator::Coordinates aCoords = theCoords;
520   // Set the difference.
521   startOperation();
522   if (addEmptyDiff()) {
523     myListDiffs.back().init(this, CurveCreator_Operation::AddPoints,
524                             theCoords, theISection);
525   }
526   CurveCreator_Section *aSection =
527     (theISection == -1 ? mySections.back() : mySections.at(theISection));
528
529   if( aSection ) {
530     int anICoord = ( theIPnt == -1 ? 0 : toICoord(theIPnt) );
531     CurveCreator::Coordinates::iterator anIterPosition = aSection->myPoints.end();
532     if( theIPnt != -1 )
533       anIterPosition = aSection->myPoints.begin() + toICoord(theIPnt);
534     aSection->myPoints.insert(anIterPosition,
535                               theCoords.begin(), theCoords.end());
536     if( myListener )
537       myListener->pointInserted( theISection, -1 );
538     res = true;
539   }
540   finishOperation();
541   return res;
542 }
543
544    //! Set coordinates of specified point
545 bool CurveCreator_Curve::setPoint( const int theISection,
546                                    const int theIPnt,
547                                    const CurveCreator::Coordinates& theNewCoords )
548 {
549   // Set the difference.
550   startOperation();
551   if (addEmptyDiff()) {
552     myListDiffs.back().init(this, CurveCreator_Operation::SetCoordinates,
553                             theNewCoords, theISection, theIPnt);
554   }
555
556   bool res = false;
557
558   // Update the curve.
559   if (theNewCoords.size() == myDimension) {
560     CurveCreator_Section *aSection = mySections.at(theISection);
561     int i;
562     for (i = 0; i < myDimension; i++) {
563       aSection->myPoints.at(toICoord(theIPnt) + i) = theNewCoords[i];
564     }
565     if( myListener )
566       myListener->pointChanged( theISection, theIPnt );
567     
568     res = true;
569   }
570
571   finishOperation();
572
573   return res; 
574 }
575
576 //! Remove point with given id
577 bool CurveCreator_Curve::removePoint( const int theISection, const int theIPnt )
578 {
579   bool res = false;
580   // Set the difference.
581   startOperation();
582   if (addEmptyDiff()) {
583     myListDiffs.back().init(this, CurveCreator_Operation::RemovePoints,
584                             theISection, theIPnt, 0);
585   }
586   CurveCreator_Section *aSection = mySections.at(theISection);
587   if( aSection ) {
588     CurveCreator::Coordinates::iterator anIterPosition =
589       aSection->myPoints.begin() + toICoord(theIPnt);
590     aSection->myPoints.erase( anIterPosition );
591     if( myListener )
592       myListener->pointRemoved( theISection, theIPnt );
593     res = true;
594   }
595   finishOperation();
596   return res;
597 }
598
599 //=======================================================================
600 // function: getCoordinates
601 // purpose:
602 //=======================================================================
603 CurveCreator::Coordinates CurveCreator_Curve::getPoint( const int theISection,
604                                                         const int theIPnt) const
605 {
606   CurveCreator_Section *aSection = mySections.at(theISection);
607   CurveCreator::Coordinates::const_iterator
608     anIter = aSection->myPoints.begin() + toICoord(theIPnt);
609   CurveCreator::Coordinates aResult(anIter, anIter + myDimension);
610
611   return aResult;
612 }
613
614 //=======================================================================
615 // function: getPoints
616 // purpose:
617 //=======================================================================
618 CurveCreator::Coordinates CurveCreator_Curve::getPoints( const int theISection ) const
619 {
620   return mySections.at(theISection)->myPoints;
621 }
622
623
624 /***********************************************/
625 /***       Presentation methods              ***/
626 /***********************************************/
627 /*  TopoDS_Wire CurveCreator_Curve::constructWire() const
628 {
629 }*/