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