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