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