Salome HOME
Fix for bug Bug IPAL20288 (4x: CRASH after trying to build a sketch).
[modules/geom.git] / src / GEOMImpl / GEOMImpl_IHealingOperations.cxx
1 // Copyright (C) 2005  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
2 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
3 // 
4 // This library is free software; you can redistribute it and/or
5 // modify it under the terms of the GNU Lesser General Public
6 // License as published by the Free Software Foundation; either 
7 // version 2.1 of the License.
8 // 
9 // This library is distributed in the hope that it will be useful 
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
12 // Lesser General Public License for more details.
13 //
14 // You should have received a copy of the GNU Lesser General Public  
15 // License along with this library; if not, write to the Free Software 
16 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
17 //
18 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
19 //
20
21
22
23 #ifdef WNT
24 #pragma warning( disable:4786 )
25 #endif
26
27 using namespace std;
28
29 #include <Standard_Stream.hxx>
30
31 #include <GEOMImpl_IHealingOperations.hxx>
32
33 #include <GEOM_PythonDump.hxx>
34
35 #include <GEOMImpl_HealingDriver.hxx>
36 #include <GEOMImpl_Types.hxx>
37 #include <GEOMImpl_IHealing.hxx>
38 #include <GEOMImpl_CopyDriver.hxx>
39
40 #include <ShHealOper_ShapeProcess.hxx>
41
42 #include "utilities.h"
43 #include <OpUtil.hxx>
44 #include <Utils_ExceptHandlers.hxx>
45
46 #include <ShapeAnalysis_FreeBounds.hxx>
47
48 #include <TopoDS_Compound.hxx>
49 #include <TopExp_Explorer.hxx>
50
51 #include <TColStd_HArray1OfExtendedString.hxx>
52 #include <TColStd_HSequenceOfTransient.hxx>
53 #include <TCollection_AsciiString.hxx>
54
55 #include <TDF_Tool.hxx>
56
57 #include <Standard_Failure.hxx>
58 #include <Standard_ErrorHandler.hxx> // CAREFUL ! position of this file is critic : see Lucien PIGNOLONI / OCC
59
60
61 //=============================================================================
62 /*!
63  *   constructor:
64  */
65 //=============================================================================
66
67 GEOMImpl_IHealingOperations::GEOMImpl_IHealingOperations (GEOM_Engine* theEngine, int theDocID)
68 : GEOM_IOperations(theEngine, theDocID)
69 {
70   MESSAGE("GEOMImpl_IHealingOperations::GEOMImpl_IHealingOperations");
71 }
72
73 //=============================================================================
74 /*!
75  *  destructor
76  */
77 //=============================================================================
78
79 GEOMImpl_IHealingOperations::~GEOMImpl_IHealingOperations()
80 {
81   MESSAGE("GEOMImpl_IHealingOperations::~GEOMImpl_IHealingOperations");
82 }
83
84
85 //=============================================================================
86 /*!
87  *  ShapeProcess
88  */
89 //=============================================================================
90 Handle(GEOM_Object) GEOMImpl_IHealingOperations::ShapeProcess (Handle(GEOM_Object) theObject,
91                                   const Handle(TColStd_HArray1OfExtendedString)& theOperators,
92                                   const Handle(TColStd_HArray1OfExtendedString)& theParams,
93                                   const Handle(TColStd_HArray1OfExtendedString)& theValues)
94 {
95   // set error code, check parameters
96   SetErrorCode(KO);
97
98   if (theObject.IsNull())
99     return NULL;
100
101   if (theOperators.IsNull() || theOperators->Length() <= 0) {
102     SetErrorCode("No operators requested");
103     return NULL;
104   }
105
106   Standard_Integer nbParams = 0, nbValues = 0;
107   if (!theParams.IsNull()) {
108     nbParams = theParams->Length();
109   }
110   if (!theValues.IsNull()) {
111     nbValues = theValues->Length();
112   }
113
114   if (nbParams != nbValues) {
115     SetErrorCode("Number of parameter values must be equal to the number of parameters");
116     return NULL;
117   }
118
119   Handle(GEOM_Function) aFunction, aLastFunction = theObject->GetLastFunction();
120   if (aLastFunction.IsNull()) return NULL; //There is no function which creates an object to be processed
121
122   // Add a new object
123   Handle(GEOM_Object) aNewObject = GetEngine()->AddObject( GetDocID(), GEOM_COPY );
124
125   //Add the function
126   aFunction = aNewObject->AddFunction(GEOMImpl_HealingDriver::GetID(), SHAPE_PROCESS);
127
128   if (aFunction.IsNull()) return NULL;
129
130   //Check if the function is set correctly
131   if (aFunction->GetDriverGUID() != GEOMImpl_HealingDriver::GetID()) return NULL;
132
133   // prepare "data container" class IHealing
134   GEOMImpl_IHealing HI(aFunction);
135   HI.SetOriginal(aLastFunction);
136   HI.SetOperators( theOperators );
137   if (nbParams > 0) {
138     HI.SetParameters( theParams );
139     HI.SetValues( theValues );
140   }
141
142   //Compute the translation
143   try {
144 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
145     OCC_CATCH_SIGNALS;
146 #endif
147     if (!GetSolver()->ComputeFunction(aFunction))
148     {
149       SetErrorCode("Shape Healing algorithm failed");
150       return NULL;
151     }
152   }
153   catch (Standard_Failure)
154   {
155     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
156     SetErrorCode(aFail->GetMessageString());
157     return NULL;
158   }
159
160   //Make a Python command
161   GEOM::TPythonDump pd (aFunction);
162   pd << aNewObject << " = geompy.ProcessShape(" << theObject << ", [";
163
164   // list of operators
165   int i = theOperators->Lower(), nb = theOperators->Upper();
166   for ( ; i <= nb; i++) {
167     pd << "\"" << TCollection_AsciiString(theOperators->Value( i )).ToCString()
168       << (( i < nb ) ? "\", " : "\"");
169   }
170   pd << "], [";
171   // list of parameters
172   i = theParams->Lower(); nb = theParams->Upper();
173   for ( ; i <= nb; i++) {
174     pd << "\"" << TCollection_AsciiString(theParams->Value( i )).ToCString()
175       << (( i < nb ) ? "\", " : "\"");
176   }
177   pd << "], [";
178   // list of values
179   i = theValues->Lower(); nb = theValues->Upper();
180   for ( ; i <= nb; i++) {
181     pd << "\"" << TCollection_AsciiString(theValues->Value( i )).ToCString()
182       << (( i < nb ) ? "\", " : "\"");
183   }
184   pd << "])";
185
186   SetErrorCode(OK);
187   return aNewObject;
188 }
189
190 //=============================================================================
191 /*!
192  *  ShapeProcess
193  */
194 //=============================================================================
195 void GEOMImpl_IHealingOperations::GetShapeProcessParameters (list<string>& theOperations,
196                                                              list<string>& theParams,
197                                                              list<string>& theValues)
198 {
199   ShHealOper_ShapeProcess aHealer;
200   TColStd_SequenceOfAsciiString anOperators;
201   int nbOperatorErrors( 0 );
202   if ( aHealer.GetOperators( anOperators ) )
203   {
204     for ( Standard_Integer i = 1; i <= anOperators.Length(); i++ )
205     {
206       string anOperation = anOperators.Value( i ).ToCString();
207       if ( GetOperatorParameters( anOperation, theParams, theValues ) )
208         theOperations.push_back( anOperation );
209       else
210         nbOperatorErrors++;
211     }
212   }
213   else
214   {
215     SetErrorCode("ERROR retrieving operators (GEOMImpl_IHealingOperations)");
216   }
217
218   if ( nbOperatorErrors ) {
219     TCollection_AsciiString aMsg ("ERRORS retrieving ShapeProcess parameters (GEOMImpl_IHealingOperations): nbOperatorErrors = ");
220     aMsg += TCollection_AsciiString( nbOperatorErrors );
221     MESSAGE(aMsg.ToCString());
222   }
223 }
224
225 //=============================================================================
226 /*!
227  *  GetOperatorParameters
228  */
229 //=============================================================================
230 bool GEOMImpl_IHealingOperations::GetOperatorParameters( const string theOperation, 
231                                                          list<string>& theParams,
232                                                          list<string>& theValues )
233 {
234   ShHealOper_ShapeProcess aHealer;
235   int nbParamValueErrors( 0 );
236   list<string> aParams;
237   if ( GetParameters( theOperation, aParams ) ) {
238     for ( list<string>::iterator it = aParams.begin(); it != aParams.end(); ++it ) {
239       TCollection_AsciiString aParam( (Standard_CString)(*it).c_str() );
240       TCollection_AsciiString aValue;
241       if ( aHealer.GetParameter( aParam, aValue ) ) {
242         theParams.push_back( aParam.ToCString() );
243         theValues.push_back( aValue.ToCString() );
244       }
245       else
246         nbParamValueErrors++;
247     }
248   }
249   else
250     return false;
251
252   if ( nbParamValueErrors ) {
253     TCollection_AsciiString aMsg ("ERRORS retrieving ShapeProcess parameter values (GEOMImpl_IHealingOperations): nbParamValueErrors = ");
254     aMsg += TCollection_AsciiString( nbParamValueErrors );
255     MESSAGE(aMsg.ToCString());
256   }
257
258   return true;
259 }
260
261 //=============================================================================
262 /*!
263  *  GetParameters
264  */
265 //=============================================================================
266 bool GEOMImpl_IHealingOperations::GetParameters (const string theOperation,
267                                                  list<string>& theParams)
268 {
269   if ( theOperation == "SplitAngle" ) {
270     theParams.push_back( "SplitAngle.Angle" );
271     theParams.push_back( "SplitAngle.MaxTolerance" );
272
273   } else if ( theOperation == "SplitClosedFaces" ) {
274     theParams.push_back( "SplitClosedFaces.NbSplitPoints" );
275
276   } else if ( theOperation == "FixFaceSize" ) {
277     theParams.push_back( "FixFaceSize.Tolerance" );
278
279   } else if( theOperation == "DropSmallEdges" ) {
280     theParams.push_back( "DropSmallEdges.Tolerance3d" );
281
282   } else if( theOperation == "BSplineRestriction" ) {
283     theParams.push_back( "BSplineRestriction.SurfaceMode" );
284     theParams.push_back( "BSplineRestriction.Curve3dMode" );
285     theParams.push_back( "BSplineRestriction.Curve2dMode" );
286     theParams.push_back( "BSplineRestriction.Tolerance3d" );
287     theParams.push_back( "BSplineRestriction.Tolerance2d" );
288     theParams.push_back( "BSplineRestriction.RequiredDegree" );
289     theParams.push_back( "BSplineRestriction.RequiredNbSegments" );
290     theParams.push_back( "BSplineRestriction.Continuity3d" );
291     theParams.push_back( "BSplineRestriction.Continuity2d" );
292
293   } else if( theOperation == "SplitContinuity" ) {
294     theParams.push_back( "SplitContinuity.Tolerance3d" );
295     theParams.push_back( "SplitContinuity.SurfaceContinuity" );
296     theParams.push_back( "SplitContinuity.CurveContinuity" );
297
298   } else if( theOperation == "ToBezier" ) {
299     theParams.push_back( "ToBezier.SurfaceMode" );
300     theParams.push_back( "ToBezier.Curve3dMode" );
301     theParams.push_back( "ToBezier.Curve2dMode" );
302     theParams.push_back( "ToBezier.MaxTolerance" );
303
304   } else if( theOperation == "SameParameter" ) {
305     theParams.push_back( "SameParameter.Tolerance3d" );
306
307   } else if( theOperation == "FixShape" ) {
308     theParams.push_back( "FixShape.Tolerance3d" );
309     theParams.push_back( "FixShape.MaxTolerance3d" );
310
311   } else {
312     return false;
313   }
314
315   return true;
316 }
317
318 //=============================================================================
319 /*!
320  *  SuppressFaces
321  */
322 //=============================================================================
323 Handle(GEOM_Object) GEOMImpl_IHealingOperations::SuppressFaces
324        (Handle(GEOM_Object) theObject, const Handle(TColStd_HArray1OfInteger)& theFaces)
325 {
326   // set error code, check parameters
327   SetErrorCode(KO);
328
329   if ( theObject.IsNull() ) // if theFaces.IsNull() - it's OK, it means that ALL faces must be removed..
330     return NULL;
331
332   Handle(GEOM_Function) aFunction, aLastFunction = theObject->GetLastFunction();
333   if(aLastFunction.IsNull()) return NULL; //There is no function which creates an object to be processed
334
335   // Add a new object
336   Handle(GEOM_Object) aNewObject = GetEngine()->AddObject( GetDocID(), GEOM_COPY );
337
338   //Add the function
339   aFunction = aNewObject->AddFunction(GEOMImpl_HealingDriver::GetID(), SUPPRESS_FACES);
340
341   if(aFunction.IsNull()) return NULL;
342
343   //Check if the function is set correctly
344   if(aFunction->GetDriverGUID() != GEOMImpl_HealingDriver::GetID()) return NULL;
345
346   // prepare "data container" class IHealing
347   GEOMImpl_IHealing HI(aFunction);
348   HI.SetFaces( theFaces );
349   HI.SetOriginal( aLastFunction );
350
351   //Compute the translation
352   try {
353 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
354     OCC_CATCH_SIGNALS;
355 #endif
356     if (!GetSolver()->ComputeFunction(aFunction))
357     {
358       SetErrorCode("Healing driver failed");
359       return NULL;
360     }
361   }
362   catch (Standard_Failure)
363   {
364         Handle(Standard_Failure) aFail = Standard_Failure::Caught();
365     SetErrorCode(aFail->GetMessageString());
366     return NULL;
367   }
368
369   //Make a Python command
370   GEOM::TPythonDump pd (aFunction);
371   pd << aNewObject << " = geompy.SuppressFaces(" << theObject << ", [";
372
373   // list of face ids
374   int i = theFaces->Lower(), nb = theFaces->Upper();
375   for ( ; i <= nb; i++)
376     pd << theFaces->Value( i ) << (( i < nb ) ? ", " : "])");
377
378   SetErrorCode(OK);
379   return aNewObject;
380 }
381
382
383 //=============================================================================
384 /*!
385  *  CloseContour
386  */
387 //=============================================================================
388 Handle(GEOM_Object) GEOMImpl_IHealingOperations::CloseContour
389                     (Handle(GEOM_Object) theObject,
390                      const Handle(TColStd_HArray1OfInteger)& theWires,
391                      bool isCommonVertex)
392 {
393   // set error code, check parameters
394   SetErrorCode(KO);
395
396   if (theObject.IsNull())
397   {
398     SetErrorCode("NULL object given");
399     return NULL;
400   }
401
402   Handle(GEOM_Function) aFunction, aLastFunction = theObject->GetLastFunction();
403   if (aLastFunction.IsNull()) return NULL; //There is no function which creates an object to be processed
404
405   // Add a new object
406   Handle(GEOM_Object) aNewObject = GetEngine()->AddObject( GetDocID(), GEOM_COPY );
407
408   //Add the function
409   aFunction = aNewObject->AddFunction(GEOMImpl_HealingDriver::GetID(), CLOSE_CONTOUR);
410
411   if (aFunction.IsNull()) return NULL;
412
413   //Check if the function is set correctly
414   if(aFunction->GetDriverGUID() != GEOMImpl_HealingDriver::GetID()) return NULL;
415
416   // prepare "data container" class IHealing
417   GEOMImpl_IHealing HI(aFunction);
418   HI.SetWires( theWires );
419   HI.SetIsCommonVertex( isCommonVertex );
420   HI.SetOriginal( aLastFunction );
421
422   //Compute the translation
423   try {
424 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
425     OCC_CATCH_SIGNALS;
426 #endif
427     if (!GetSolver()->ComputeFunction(aFunction))
428     {
429       SetErrorCode("Healing driver failed");
430       return NULL;
431     }
432   }
433   catch (Standard_Failure)
434   {
435         Handle(Standard_Failure) aFail = Standard_Failure::Caught();
436     SetErrorCode(aFail->GetMessageString());
437     return NULL;
438   }
439
440   //Make a Python command
441   GEOM::TPythonDump pd (aFunction);
442   pd << aNewObject << " = geompy.CloseContour(" << theObject << ", [";
443
444   // list of wire ids
445   if (!theWires.IsNull())
446   {
447     int i = theWires->Lower(), nb = theWires->Upper();
448     pd << theWires->Value(i++);
449     while (i <= nb)
450       pd << ", " << theWires->Value(i++);
451   }
452   pd << "], " << (int)isCommonVertex << ")";
453
454   SetErrorCode(OK);
455   return aNewObject;
456 }
457
458 //=============================================================================
459 /*!
460  *  RemoveIntWires
461  */
462 //=============================================================================
463 Handle(GEOM_Object) GEOMImpl_IHealingOperations::RemoveIntWires
464        (Handle(GEOM_Object) theObject, const Handle(TColStd_HArray1OfInteger)& theWires)
465 {
466   // set error code, check parameters
467   SetErrorCode(KO);
468
469   if (theObject.IsNull()) // if theWires is NULL it's OK, it means that ALL wires must be removed
470     return NULL;
471
472   Handle(GEOM_Function) aFunction, aLastFunction = theObject->GetLastFunction();
473   if (aLastFunction.IsNull()) return NULL; //There is no function which creates an object to be processed
474
475   // Add a new object
476   Handle(GEOM_Object) aNewObject = GetEngine()->AddObject( GetDocID(), GEOM_COPY );
477
478   //Add the function
479   aFunction = aNewObject->AddFunction(GEOMImpl_HealingDriver::GetID(), REMOVE_INT_WIRES);
480
481   if (aFunction.IsNull()) return NULL;
482
483   //Check if the function is set correctly
484   if (aFunction->GetDriverGUID() != GEOMImpl_HealingDriver::GetID()) return NULL;
485
486   // prepare "data container" class IHealing
487   GEOMImpl_IHealing HI(aFunction);
488   HI.SetWires( theWires );
489   HI.SetOriginal( aLastFunction );
490
491   //Compute the translation
492   try {
493 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
494     OCC_CATCH_SIGNALS;
495 #endif
496     if (!GetSolver()->ComputeFunction(aFunction))
497     {
498       SetErrorCode("Healing driver failed");
499       return NULL;
500     }
501   }
502   catch (Standard_Failure)
503   {
504     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
505     SetErrorCode(aFail->GetMessageString());
506     return NULL;
507   }
508
509   //Make a Python command
510   GEOM::TPythonDump pd (aFunction);
511   pd << aNewObject << " = geompy.SuppressInternalWires(" << theObject << ", [";
512
513   // list of wire ids
514   if (!theWires.IsNull()) {
515     int i = theWires->Lower(), nb = theWires->Upper();
516     for ( ; i <= nb; i++)
517       pd << theWires->Value( i ) << (( i < nb ) ? ", " : "])");
518   } else {
519     pd << "])";
520   }
521
522   SetErrorCode(OK);
523   return aNewObject;
524 }
525
526 //=============================================================================
527 /*!
528  *  FillHoles
529  */
530 //=============================================================================
531 Handle(GEOM_Object) GEOMImpl_IHealingOperations::FillHoles (Handle(GEOM_Object) theObject,
532                                                             const Handle(TColStd_HArray1OfInteger)& theWires)
533 {
534   // set error code, check parameters
535   SetErrorCode(KO);
536
537   if (theObject.IsNull()) // if theWires is NULL it's OK, it means that ALL holes must be removed
538     return NULL;
539
540   Handle(GEOM_Function) aFunction, aLastFunction = theObject->GetLastFunction();
541   if (aLastFunction.IsNull()) return NULL; //There is no function which creates an object to be processed
542
543   // Add a new object
544   Handle(GEOM_Object) aNewObject = GetEngine()->AddObject( GetDocID(), GEOM_COPY );
545
546   //Add the function
547   aFunction = aNewObject->AddFunction(GEOMImpl_HealingDriver::GetID(), FILL_HOLES);
548
549   if (aFunction.IsNull()) return NULL;
550
551   //Check if the function is set correctly
552   if (aFunction->GetDriverGUID() != GEOMImpl_HealingDriver::GetID()) return NULL;
553
554   // prepare "data container" class IHealing
555   GEOMImpl_IHealing HI(aFunction);
556   HI.SetWires( theWires );
557   HI.SetOriginal( aLastFunction );
558
559   //Compute the translation
560   try {
561 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
562     OCC_CATCH_SIGNALS;
563 #endif
564     if (!GetSolver()->ComputeFunction(aFunction))
565     {
566       SetErrorCode("Healing driver failed");
567       return NULL;
568     }
569   }
570   catch (Standard_Failure)
571   {
572         Handle(Standard_Failure) aFail = Standard_Failure::Caught();
573     SetErrorCode(aFail->GetMessageString());
574     return NULL;
575   }
576
577   //Make a Python command
578   GEOM::TPythonDump pd (aFunction);
579   pd << aNewObject << " = geompy.SuppressHoles(" << theObject << ", [";
580
581   // list of wire ids
582   if ( theWires.IsNull() )
583     pd << "])";
584   else {
585     int i = theWires->Lower(), nb = theWires->Upper();
586     for ( ; i <= nb; i++)
587       pd << theWires->Value( i ) << (( i < nb ) ? ", " : "])");
588   }
589
590   SetErrorCode(OK);
591   return aNewObject;
592 }
593
594 //=============================================================================
595 /*!
596  *  Sew
597  */
598 //=============================================================================
599 Handle(GEOM_Object) GEOMImpl_IHealingOperations::Sew (Handle(GEOM_Object) theObject,
600                                                       double theTolerance)
601 {
602   // set error code, check parameters
603   SetErrorCode(KO);
604
605   if (theObject.IsNull())
606     return NULL;
607
608   Handle(GEOM_Function) aFunction, aLastFunction = theObject->GetLastFunction();
609   if (aLastFunction.IsNull()) return NULL; //There is no function which creates an object to be processed
610
611   // Add a new object
612   Handle(GEOM_Object) aNewObject = GetEngine()->AddObject( GetDocID(), GEOM_COPY );
613
614   //Add the function
615   aFunction = aNewObject->AddFunction(GEOMImpl_HealingDriver::GetID(), SEWING);
616
617   if (aFunction.IsNull()) return NULL;
618
619   //Check if the function is set correctly
620   if (aFunction->GetDriverGUID() != GEOMImpl_HealingDriver::GetID()) return NULL;
621
622   // prepare "data container" class IHealing
623   GEOMImpl_IHealing HI(aFunction);
624   HI.SetTolerance( theTolerance );
625   HI.SetOriginal( aLastFunction );
626
627   //Compute the translation
628   try {
629 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
630     OCC_CATCH_SIGNALS;
631 #endif
632     if (!GetSolver()->ComputeFunction(aFunction))
633     {
634       SetErrorCode("Healing driver failed");
635       return NULL;
636     }
637   }
638   catch (Standard_Failure)
639   {
640         Handle(Standard_Failure) aFail = Standard_Failure::Caught();
641     SetErrorCode(aFail->GetMessageString());
642     return NULL;
643   }
644
645   //Make a Python command
646   GEOM::TPythonDump(aFunction) << aNewObject << " = geompy.Sew("
647                                << theObject << ", " << theTolerance << ")";
648
649   SetErrorCode(OK);
650   return aNewObject;
651 }
652
653 //=============================================================================
654 /*!
655  *  DivideEdge
656  */
657 //=============================================================================
658 Handle(GEOM_Object) GEOMImpl_IHealingOperations::DivideEdge (Handle(GEOM_Object) theObject,
659                                                              int theIndex,
660                                                              double theValue,
661                                                              bool isByParameter)
662 {
663   // set error code, check parameters
664   SetErrorCode(KO);
665
666   if (theObject.IsNull())
667     return NULL;
668
669   Handle(GEOM_Function) aFunction, aLastFunction = theObject->GetLastFunction();
670   if (aLastFunction.IsNull()) return NULL; //There is no function which creates an object to be processed
671
672   // Add a new object
673   Handle(GEOM_Object) aNewObject = GetEngine()->AddObject( GetDocID(), GEOM_COPY );
674
675   //Add the function
676   aFunction = aNewObject->AddFunction(GEOMImpl_HealingDriver::GetID(), DIVIDE_EDGE);
677
678   if (aFunction.IsNull()) return NULL;
679
680   //Check if the function is set correctly
681   if (aFunction->GetDriverGUID() != GEOMImpl_HealingDriver::GetID()) return NULL;
682
683   // prepare "data container" class IHealing
684   GEOMImpl_IHealing HI(aFunction);
685   HI.SetIndex( theIndex );
686   HI.SetDevideEdgeValue( theValue );
687   HI.SetIsByParameter( isByParameter );
688   HI.SetOriginal( aLastFunction );
689
690   //Compute the translation
691   try {
692 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
693     OCC_CATCH_SIGNALS;
694 #endif
695     if (!GetSolver()->ComputeFunction(aFunction))
696     {
697       SetErrorCode("Healing driver failed");
698       return NULL;
699     }
700   }
701   catch (Standard_Failure)
702   {
703         Handle(Standard_Failure) aFail = Standard_Failure::Caught();
704     SetErrorCode(aFail->GetMessageString());
705     return NULL;
706   }
707
708   //Make a Python command
709   GEOM::TPythonDump(aFunction) << aNewObject << " = geompy.DivideEdge(" << theObject
710     << ", " << theIndex << ", " << theValue << ", " << (int)isByParameter << ")";
711
712   SetErrorCode(OK);
713   return aNewObject;
714 }
715
716 //=============================================================================
717 /*!
718  *  GetFreeBoundary
719  */
720 //=============================================================================
721 bool GEOMImpl_IHealingOperations::GetFreeBoundary (Handle(GEOM_Object) theObject,
722                                                    Handle(TColStd_HSequenceOfTransient)& theClosed,
723                                                    Handle(TColStd_HSequenceOfTransient)& theOpen )
724 {
725   // set error code, check parameters
726   SetErrorCode(KO);
727
728   if ( theObject.IsNull() || theClosed.IsNull() || theOpen.IsNull() )
729     return false;
730
731   TopoDS_Shape aShape = theObject->GetValue();
732   if ( aShape.IsNull() )
733     return false;
734
735   // get free boundary shapes
736   ShapeAnalysis_FreeBounds anAnalizer( aShape );
737   TopoDS_Compound aClosed = anAnalizer.GetClosedWires();
738   TopoDS_Compound anOpen = anAnalizer.GetOpenWires();
739
740   // iterate through shapes and append them to the return sequence
741   Handle(GEOM_Object) anObj;
742   Handle(GEOM_Function) aFunction;
743   TopExp_Explorer anExp;
744   for ( anExp.Init( aClosed, TopAbs_WIRE ); anExp.More(); anExp.Next() )
745   {
746     anObj = GetEngine()->AddObject( GetDocID(), GEOM_FREE_BOUNDS );
747     aFunction = anObj->AddFunction( GEOMImpl_CopyDriver::GetID(), COPY_WITHOUT_REF );
748     TopoDS_Shape aValueShape = anExp.Current();
749     aFunction->SetValue( aValueShape );
750     theClosed->Append(anObj);
751   }
752   for ( anExp.Init( anOpen, TopAbs_WIRE ); anExp.More(); anExp.Next() )
753   {
754     anObj = GetEngine()->AddObject( GetDocID(), GEOM_FREE_BOUNDS );
755     aFunction = anObj->AddFunction( GEOMImpl_CopyDriver::GetID(), COPY_WITHOUT_REF );
756     TopoDS_Shape aValueShape = anExp.Current();
757     aFunction->SetValue( aValueShape );
758     theOpen->Append(anObj);
759   }
760
761   if(!aFunction.IsNull()) {
762
763     //Make a Python command
764     GEOM::TPythonDump pd (aFunction);
765
766     Standard_Integer i, aLen = theClosed->Length();
767     if (aLen > 0) {
768       pd << "(isDone, [";
769       for (i = 1; i <= aLen; i++) {
770         Handle(GEOM_Object) anObj_i = Handle(GEOM_Object)::DownCast(theClosed->Value(i));
771         pd << anObj_i << ((i < aLen) ? ", " : "");
772       }
773       pd << "], ";
774     } else {
775       pd << "(isDone, empty_list, ";
776     }
777
778     aLen = theOpen->Length();
779     if (aLen > 0) {
780       pd << "[";
781       for (i = 1; i <= aLen; i++) {
782         Handle(GEOM_Object) anObj_i = Handle(GEOM_Object)::DownCast(theOpen->Value(i));
783         pd << anObj_i << ((i < aLen) ? ", " : "");
784       }
785       pd << "]";
786     } else {
787       pd << "empty_list";
788     }
789
790     pd << ") = geompy.GetFreeBoundary(" << theObject << ")";
791   }
792
793   SetErrorCode(OK);
794   return true;
795 }
796
797
798 //=============================================================================
799 /*!
800  *  ChangeOrientation
801  */
802 //=============================================================================
803 Handle(GEOM_Object) GEOMImpl_IHealingOperations::ChangeOrientation (Handle(GEOM_Object) theObject)
804 {
805   // set error code, check parameters
806   SetErrorCode(KO);
807
808   if (theObject.IsNull())
809     return NULL;
810
811   if (!theObject->IsMainShape()) {
812     SetErrorCode("Sub shape cannot be transformed - need to create a copy");
813     return NULL;
814   }
815
816   Handle(GEOM_Function) aFunction, aLastFunction = theObject->GetLastFunction();
817   if (aLastFunction.IsNull()) 
818     return NULL; //There is no function which creates an object to be processed
819
820   //Add the function
821   aFunction = theObject->AddFunction(GEOMImpl_HealingDriver::GetID(), CHANGE_ORIENTATION);
822
823   if (aFunction.IsNull())
824     return NULL;
825
826   //Check if the function is set correctly
827   if (aFunction->GetDriverGUID() != GEOMImpl_HealingDriver::GetID()) return NULL;
828
829   // prepare "data container" class IHealing
830   GEOMImpl_IHealing HI(aFunction);
831   HI.SetOriginal( aLastFunction );
832
833   //Compute the translation
834   try {
835 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
836     OCC_CATCH_SIGNALS;
837 #endif
838     if (!GetSolver()->ComputeFunction(aFunction)) {
839       SetErrorCode("Healing driver failed");
840       return NULL;
841     }
842   }
843   catch (Standard_Failure) {
844     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
845     SetErrorCode(aFail->GetMessageString());
846     return NULL;
847   }
848
849   //Make a Python command
850   GEOM::TPythonDump(aFunction) << "geompy.ChangeOrientationShell("
851                                << theObject << ")";
852
853   SetErrorCode(OK);
854   return theObject;
855 }
856
857
858 //=============================================================================
859 /*!
860  *  ChangeOrientationCopy
861  */
862 //=============================================================================
863 Handle(GEOM_Object) GEOMImpl_IHealingOperations::ChangeOrientationCopy (Handle(GEOM_Object) theObject)
864 {
865   // set error code, check parameters
866   SetErrorCode(KO);
867
868   if (theObject.IsNull())
869     return NULL;
870
871   Handle(GEOM_Function) aFunction, aLastFunction = theObject->GetLastFunction();
872   if (aLastFunction.IsNull())
873     return NULL; //There is no function which creates an object to be processed
874
875   // Add a new object
876   Handle(GEOM_Object) aNewObject = GetEngine()->AddObject( GetDocID(), GEOM_COPY );
877
878   //Add the function
879   aFunction = aNewObject->AddFunction(GEOMImpl_HealingDriver::GetID(), CHANGE_ORIENTATION);
880
881   if (aFunction.IsNull())
882     return NULL;
883
884   //Check if the function is set correctly
885   if (aFunction->GetDriverGUID() != GEOMImpl_HealingDriver::GetID()) return NULL;
886
887   // prepare "data container" class IHealing
888   GEOMImpl_IHealing HI(aFunction);
889   HI.SetOriginal( aLastFunction );
890
891   //Compute the translation
892   try {
893 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
894     OCC_CATCH_SIGNALS;
895 #endif
896     if (!GetSolver()->ComputeFunction(aFunction)) {
897       SetErrorCode("Healing driver failed");
898       return NULL;
899     }
900   }
901   catch (Standard_Failure) {
902     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
903     SetErrorCode(aFail->GetMessageString());
904     return NULL;
905   }
906
907   //Make a Python command
908   GEOM::TPythonDump(aFunction) << aNewObject << " = geompy.ChangeOrientationShellCopy("
909                                << theObject << ")";
910
911   SetErrorCode(OK);
912   return aNewObject;
913 }
914