Salome HOME
1445652404591bceef50a93a7b96414566101c97
[modules/geom.git] / src / CurveCreator / CurveCreator_Diff.cxx
1 // Copyright (C) 2013-2023  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_Diff.cxx
21 // Author:      Sergey KHROMOV
22
23 #include "CurveCreator_Diff.hxx"
24 #include "CurveCreator_Curve.hxx"
25 #include "CurveCreator_Section.hxx"
26 #include "CurveCreator_Utils.hxx"
27
28 #include <list>
29
30 //=======================================================================
31 // function: Constructor
32 // purpose:
33 //=======================================================================
34 CurveCreator_Diff::CurveCreator_Diff()
35 : myNbUndos (0),
36   myPUndo   (NULL),
37   myPRedo   (NULL)
38 {
39 }
40
41 //=======================================================================
42 // function: Destructor
43 // purpose:
44 //=======================================================================
45 CurveCreator_Diff::~CurveCreator_Diff()
46 {
47   clear();
48 }
49
50 //=======================================================================
51 // function: init
52 // purpose:
53 //=======================================================================
54 bool CurveCreator_Diff::init(const CurveCreator_Curve *theCurve)
55 {
56   CurveCreator_Operation::Type aType = CurveCreator_Operation::Clear;
57   bool isOK = false;
58
59   if (theCurve != NULL) {
60     clear();
61
62     // Set redo.
63     myPRedo = new CurveCreator_Operation;
64
65     if (myPRedo->init(aType)) {
66       isOK = true;
67
68       const int aNbSections = theCurve->getNbSections();
69
70       // Construct undo for Clear command.
71       if (aNbSections > 0) {
72         setNbUndos(aNbSections);
73
74         for (int i = 0; i < aNbSections && isOK; i++) {
75           // Add AddSection command.
76           isOK = addSectionToUndo(theCurve, i, myPUndo[i]);
77         }
78       }
79     }
80
81     if (!isOK) {
82       clear();
83     }
84   }
85
86   return isOK;
87 }
88
89 //=======================================================================
90 // function: init
91 // purpose:
92 //=======================================================================
93 bool CurveCreator_Diff::init(const CurveCreator_Curve *theCurve,
94                              const CurveCreator_Operation::Type theType,
95                              const int theIntParam)
96 {
97   bool isOK = false;
98
99   if (theCurve != NULL) {
100     clear();
101
102     // Set redo.
103     myPRedo = new CurveCreator_Operation;
104
105     if (myPRedo->init(theType, theIntParam)) {
106       // Construct undo for RemoveSection command.
107       // If the last section is removed, one AddSection command is enough.
108       // If not last section is removed, two commands are required: AddSection
109       // and MoveSection.
110       const int aLastIndex = theCurve->getNbSections() - 1;
111
112       if (theIntParam == aLastIndex) {
113         setNbUndos(1);
114       } else {
115         setNbUndos(2);
116       }
117
118       isOK = addSectionToUndo(theCurve, theIntParam, myPUndo[0]);
119
120       if (isOK && theIntParam != aLastIndex) {
121         isOK = myPUndo[1].init(CurveCreator_Operation::MoveSection,
122                                aLastIndex, theIntParam);
123       }
124     }
125
126     if (!isOK) {
127       clear();
128     }
129   }
130
131   return isOK;
132 }
133
134 //=======================================================================
135 // function: init
136 // purpose:
137 //=======================================================================
138 bool CurveCreator_Diff::init(const CurveCreator_Curve *theCurve,
139                              const CurveCreator_Operation::Type theType,
140                              const int theIntParam1,
141                              const int theIntParam2)
142 {
143   bool isOK = false;
144
145   if (theCurve != NULL) {
146     clear();
147
148     // Set redo.
149     myPRedo = new CurveCreator_Operation;
150
151     if (myPRedo->init(theType, theIntParam1, theIntParam2)) {
152       // Construct undo for different commands.
153       switch (theType) {
154         case CurveCreator_Operation::SetType:
155         case CurveCreator_Operation::SetClosed:
156             isOK = setTypeOrClosedToUndo
157               (theCurve, theType, theIntParam1, theIntParam2);
158           break;
159         case CurveCreator_Operation::MoveSection:
160           setNbUndos(1);
161           isOK = myPUndo[0].init(theType, theIntParam2, theIntParam1);
162           break;
163         default:
164           break;
165       }
166     }
167
168     if (!isOK) {
169       clear();
170     }
171   }
172
173   return isOK;
174 }
175
176 bool CurveCreator_Diff::init(const CurveCreator_Curve *theCurve,
177                              const CurveCreator_Operation::Type theType,
178                              const int theIntParam1,
179                              const int theIntParam2[3])
180 {
181   bool isOK = false;
182
183   if (theCurve != NULL)
184   {
185     clear();
186     myPRedo = new CurveCreator_Operation;
187
188     if (myPRedo->init(theType, theIntParam1, theIntParam2))
189     {
190       Quantity_Color aColor =  theCurve->getColorSection(theIntParam1);
191
192       setNbUndos(1);
193       QColor aQColor = CurveCreator_Utils::colorConv(aColor);
194       int colorArr[3] = {aQColor.red(),aQColor.green(), aQColor.blue()};
195
196       isOK = myPUndo[0].init(theType, theIntParam1, colorArr);
197     }
198
199     if (!isOK)
200       clear();
201   }
202
203   return isOK;
204 }
205
206 //=======================================================================
207 // function: init
208 // purpose:
209 //=======================================================================
210 bool CurveCreator_Diff::init(const CurveCreator_Curve *theCurve,
211                              const CurveCreator_Operation::Type theType,
212                              const std::list<int>& theParams)
213 {
214   bool isOK = false;
215
216   if (theCurve != NULL || theParams.empty()) {
217     clear();
218
219     // Set redo.
220     myPRedo = new CurveCreator_Operation;
221
222     if (myPRedo->init(theType, theParams)) {
223       // Construct undo for different commands.
224       switch (theType) {
225         case CurveCreator_Operation::Join:
226           {
227             int aSectionMain = theParams.front();
228             const int aNbPointsMain  = theCurve->getNbPoints(aSectionMain);
229
230             std::list<int> aSectionsToJoin = theParams;
231             aSectionsToJoin.erase( aSectionsToJoin.begin() );
232             // it is important to sort the section indices in order to correct perform undo
233             // for the move sections to the previous positions
234             aSectionsToJoin.sort();
235             // 1rst undo for remove points from the main and n-1 undoes to contain joined sections
236             int aSectionsToJoinNb = aSectionsToJoin.size();
237             int aNbUndos = 2*aSectionsToJoinNb + 1;
238             setNbUndos( aNbUndos );
239
240             // Add joined sections to undo
241             std::list<int>::const_iterator anIt = aSectionsToJoin.begin(),
242                                            aLast = aSectionsToJoin.end();
243             anIt = aSectionsToJoin.begin();
244             int aLastSectionId = -1;
245             for (int i = 0; anIt != aLast && i < aSectionsToJoinNb; anIt++, i++) {
246               int anISection = *anIt;
247               isOK = addSectionToUndo( theCurve, anISection, myPUndo[i*2] );
248               if (isOK) {
249                 isOK = myPUndo[i*2+1].init(CurveCreator_Operation::MoveSection,
250                                            aLastSectionId, anISection);
251                 if (!isOK)
252                   break;
253               }
254             }
255             // Construct undo for RemovePoints command.
256             if (isOK) {
257               int aNbPointsInJoined = 0;
258               anIt = aSectionsToJoin.begin();
259               for ( ; anIt != aLast; anIt++ )
260                 aNbPointsInJoined += theCurve->getNbPoints( *anIt );
261
262               int aJoinedSize = aNbPointsMain + aNbPointsInJoined;
263               CurveCreator_ICurve::SectionToPointList aSectionToPointList;
264               for (int anIPoint = aNbPointsMain; anIPoint < aJoinedSize; anIPoint++)
265                 aSectionToPointList.push_back(std::make_pair(aSectionMain, anIPoint));
266
267               isOK = myPUndo[aNbUndos-1].init(CurveCreator_Operation::RemovePoints, aSectionToPointList);
268             }
269           }
270           break;
271         default:
272           break;
273       }
274     }
275
276     if (!isOK) {
277       clear();
278     }
279   }
280
281   return isOK;
282 }
283
284 //=======================================================================
285 // function: init
286 // purpose:
287 //=======================================================================
288 bool CurveCreator_Diff::init(const CurveCreator_Curve *theCurve,
289                              const CurveCreator_Operation::Type theType,
290                              const std::string& theName,
291                              const CurveCreator::Coordinates &theCoords,
292                              const int theIntParam1,
293                              const int theIntParam2)
294 {
295     bool isOK = false;
296
297     if (theCurve != NULL) {
298       clear();
299
300       // Set redo.
301       myPRedo = new CurveCreator_Operation;
302
303       if (myPRedo->init(theType, theName, theCoords, theIntParam1, theIntParam2)) {
304         // Construct undo for different commands.
305         switch (theType) {
306           case CurveCreator_Operation::AddSection:
307             setNbUndos(1);
308             isOK = myPUndo[0].init(CurveCreator_Operation::RemoveSection, -1);
309             break;
310         default:
311           break;
312         }
313       }
314     }
315     if( !isOK )
316         clear();
317     return isOK;
318 }
319
320 bool CurveCreator_Diff::init(const CurveCreator_Curve *theCurve,
321                              const CurveCreator_Operation::Type theType,
322                              const std::string &theName,
323                              const int theIntParam1 )
324 {
325   bool isOK = false;
326   myPRedo = new CurveCreator_Operation;
327
328   if (myPRedo->init(theType, theName, theIntParam1 )) {
329     // Construct undo for different commands.
330     switch (theType) {
331       case CurveCreator_Operation::RenameSection:
332         setNbUndos(1);
333         isOK = myPUndo[0].init(CurveCreator_Operation::RenameSection,
334                                theCurve->getSectionName(theIntParam1), theIntParam1);
335         break;
336       default:
337         break;
338     }
339   }
340   if( !isOK ){
341     clear();
342   }
343   return isOK;
344 }
345
346 bool CurveCreator_Diff::init(const CurveCreator_Curve *theCurve,
347                              const CurveCreator_Operation::Type theType,
348                              const CurveCreator_ICurve::SectionToPointList &theParamList1)
349 {
350   bool isOK = false;
351
352   if (theCurve != NULL) {
353     clear();
354
355     // Set redo.
356     myPRedo = new CurveCreator_Operation;
357
358     if (myPRedo->init(theType, theParamList1)) {
359       // Construct undo for different commands.
360       switch (theType) {
361         case CurveCreator_Operation::RemovePoints:
362           {
363             // Construct undo for RemovePoints command.
364             CurveCreator_ICurve::SectionToPointCoordsList aSectionToPointCoords;
365             CurveCreator::Coordinates aPointsToAdd;
366             const CurveCreator::Dimension aDim = theCurve->getDimension();
367             CurveCreator_ICurve::SectionToPointList::const_iterator anIt = theParamList1.begin(), aLast = theParamList1.end();
368             std::list<int> aPoints;
369             int aSectionId, aPointId;
370             for ( ; anIt != aLast; anIt++ ) {
371               aPointsToAdd.clear();
372               aSectionId = anIt->first;
373               aPointId = anIt->second;
374               const CurveCreator::Coordinates &aPoints =
375                       theCurve->getCoords(aSectionId);
376               CurveCreator::Coordinates::const_iterator anIterBegin =
377                   aPoints.begin() + (aDim*aPointId);
378               CurveCreator::Coordinates::const_iterator anIterEnd =
379                 anIterBegin + aDim;
380               aPointsToAdd.insert(aPointsToAdd.end(), anIterBegin, anIterEnd);
381               aSectionToPointCoords.push_back(std::make_pair(*anIt, aPointsToAdd));
382             }
383             setNbUndos(1);
384             isOK = myPUndo[0].init(CurveCreator_Operation::InsertPoints,
385                                    aSectionToPointCoords);
386           }
387           break;
388         default:
389           break;
390       }
391     }
392
393     if (!isOK) {
394       clear();
395     }
396   }
397
398   return isOK;
399 }
400
401 bool CurveCreator_Diff::init(const CurveCreator_Curve *theCurve,
402                              const CurveCreator_Operation::Type theType,
403                              const CurveCreator_ICurve::SectionToPointCoordsList &theParamList1)
404 {
405   bool isOK = false;
406
407   if (theCurve != NULL) {
408     clear();
409
410     // Set redo.
411     myPRedo = new CurveCreator_Operation;
412
413     if (myPRedo->init(theType, theParamList1)) {
414       // Construct undo for different commands.
415       switch (theType) {
416         case CurveCreator_Operation::InsertPoints:
417           {
418             // Construct undo for RemovePoints command.
419             CurveCreator_ICurve::SectionToPointList aSectionToPointList;
420             CurveCreator_ICurve::SectionToPointCoordsList::const_iterator anIt = theParamList1.begin(), aLast = theParamList1.end();
421             for ( ; anIt != aLast; anIt++ ) {
422               aSectionToPointList.push_back(anIt->first);
423             }
424             setNbUndos(1);
425             isOK = myPUndo[0].init(CurveCreator_Operation::RemovePoints,
426                                    aSectionToPointList);
427           }
428           break;
429         case CurveCreator_Operation::SetCoordinates:
430           {
431             // Construct undo for SetCoordinates command.
432             CurveCreator_ICurve::SectionToPointCoordsList aSectionToPointOldCoords;
433             CurveCreator_ICurve::SectionToPointCoordsList::const_iterator anIt = theParamList1.begin(), aLast = theParamList1.end();
434             for ( ; anIt != aLast; anIt++ ) {
435               CurveCreator::Coordinates anOldCoords = theCurve->getPoint(anIt->first.first, anIt->first.second);
436               aSectionToPointOldCoords.push_back(std::make_pair(anIt->first, anOldCoords));
437             }
438
439             setNbUndos(1);
440             isOK = myPUndo[0].init(CurveCreator_Operation::SetCoordinates,
441                                    aSectionToPointOldCoords);
442           }
443           break;
444         default:
445           break;
446       }
447     }
448
449     if (!isOK) {
450       clear();
451     }
452   }
453
454   return isOK;
455 }
456
457 bool CurveCreator_Diff::init(const CurveCreator_Curve *theCurve,
458                              const CurveCreator_ICurve::SectionToPointCoordsList &theOldParamList)
459 {
460   bool isOK = false;
461
462   if (theCurve != NULL && theOldParamList.size() > 0) {
463     clear();
464
465     // Set redo.
466     myPRedo = new CurveCreator_Operation;
467
468     // Construct redo for SetCoordinates command.
469     CurveCreator_ICurve::SectionToPointCoordsList aSectionToPointActualCoords;
470     CurveCreator_ICurve::SectionToPointCoordsList::const_iterator anIt =
471       theOldParamList.begin(), aLast = theOldParamList.end();
472     for ( ; anIt != aLast; anIt++ ) {
473       CurveCreator::Coordinates anActualCoords = theCurve->getPoint(anIt->first.first, anIt->first.second);
474       aSectionToPointActualCoords.push_back(std::make_pair(anIt->first, anActualCoords));
475     }
476
477     if (myPRedo->init(CurveCreator_Operation::SetCoordinates, aSectionToPointActualCoords)) {
478       // Undo for SetCoordinates command.
479       setNbUndos(1);
480       isOK = myPUndo[0].init(CurveCreator_Operation::SetCoordinates,
481                              theOldParamList);
482     }
483
484     if (!isOK) {
485       clear();
486     }
487   }
488
489   return isOK;
490 }
491
492 //=======================================================================
493 // function: applyUndo
494 // purpose:
495 //=======================================================================
496 void CurveCreator_Diff::applyUndo(CurveCreator_Curve *theCurve)
497 {
498   if (myNbUndos > 0 && myPUndo != NULL) {
499     for (int i = 0; i < myNbUndos; i++) {
500       myPUndo[i].apply(theCurve);
501     }
502   }
503 }
504
505 //=======================================================================
506 // function: applyRedo
507 // purpose:
508 //=======================================================================
509 void CurveCreator_Diff::applyRedo(CurveCreator_Curve *theCurve)
510 {
511   if (myPRedo != NULL) {
512     myPRedo->apply(theCurve);
513   }
514 }
515
516 //=======================================================================
517 // function: clear
518 // purpose:
519 //=======================================================================
520 void CurveCreator_Diff::clear()
521 {
522   if (myPUndo != NULL) {
523     delete [] myPUndo;
524     myPUndo = NULL;
525   }
526
527   myNbUndos = 0;
528
529   if (myPRedo != NULL) {
530     delete myPRedo;
531     myPRedo = NULL;
532   }
533 }
534
535 //=======================================================================
536 // function: setNbUndos
537 // purpose:
538 //=======================================================================
539 void CurveCreator_Diff::setNbUndos(const int theNbUndos)
540 {
541   myNbUndos = theNbUndos;
542   myPUndo = new CurveCreator_Operation[myNbUndos];
543 }
544
545 //=======================================================================
546 // function: getSectionIndex
547 // purpose:
548 //=======================================================================
549 int CurveCreator_Diff::getSectionIndex(const CurveCreator_Curve *theCurve,
550                                        const int theIndex) const
551 {
552   return (theIndex == -1 ? theCurve->getNbSections() - 1 : theIndex);
553 }
554
555 //=======================================================================
556 // function: addSectionToUndo
557 // purpose:
558 //=======================================================================
559 bool CurveCreator_Diff::addSectionToUndo
560                       (const CurveCreator_Curve *theCurve,
561                        const int theIndex,
562                        CurveCreator_Operation &theOperation) const
563 {
564   const std::string aName = theCurve->getSectionName(theIndex);
565   const CurveCreator::Coordinates &aPnts = theCurve->getCoords(theIndex);
566   const CurveCreator::SectionType aType = theCurve->getSectionType(theIndex);
567   const bool isClosed = theCurve->isClosed(theIndex);
568
569   bool isOK = theOperation.init(CurveCreator_Operation::AddSection,
570                                 aName, aPnts, aType, isClosed);
571
572   return isOK;
573 }
574
575 //=======================================================================
576 // function: setTypeOrClosedToUndo
577 // purpose:
578 //=======================================================================
579 bool CurveCreator_Diff::setTypeOrClosedToUndo
580                             (const CurveCreator_Curve *theCurve,
581                              const CurveCreator_Operation::Type theType,
582                              const int theIntParam1,
583                              const int theIntParam2)
584 {
585   bool isOK = true;
586
587   // Compute number of modified sections.
588   const bool isSetType = (theType == CurveCreator_Operation::SetType);
589   int aNbModif = 0;
590   std::list<int> aListOfInd;
591   int aValue;
592   int i;
593
594   if (theIntParam2 == -1) {
595     // The operation is applied to all sections. We need to collect
596     // really modified sections for undo.
597     const int aNbSections = theCurve->getNbSections();
598
599     if (aNbSections > 0) {
600       // Get sections to be modified.
601       for (i = 0; i < aNbSections; i++) {
602         if (isSetType) {
603           aValue = theCurve->getSectionType(i);
604         } else {
605           aValue = theCurve->isClosed(i);
606         }
607
608         if (theIntParam1 != aValue) {
609           aNbModif++;
610           aListOfInd.push_back(i);
611         }
612       }
613
614       if (aNbSections == aNbModif) {
615         // All sections are modified. We can use one single command
616         // with -1 section index.
617         aNbModif = 1;
618         aListOfInd.clear();
619         aListOfInd.push_back(-1);
620       }
621     }
622   } else {
623     // There is only particular section modified.
624     // Check if there is a real modification required.
625     if (isSetType) {
626       aValue = theCurve->getSectionType(theIntParam2);
627     } else {
628       aValue = theCurve->isClosed(theIntParam2);
629     }
630
631     if (theIntParam1 != aValue) {
632       aNbModif = 1;
633       aListOfInd.push_back(theIntParam2);
634     }
635   }
636
637   if (aNbModif > 0) {
638     // Store the undos
639     std::list<int>::iterator anIter = aListOfInd.begin();
640
641     if (isSetType) {
642       aValue = theCurve->getSectionType(*anIter);
643     } else {
644       aValue = theCurve->isClosed(*anIter);
645     }
646
647     setNbUndos(aNbModif);
648
649     for (i = 0; anIter != aListOfInd.end() && isOK; i++, anIter++) {
650       isOK = myPUndo[i].init(theType, aValue, *anIter);
651     }
652   }
653
654   return isOK;
655 }