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