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