Salome HOME
Preparation of intermediate revision
[modules/geom.git] / src / GEOMImpl / GEOMImpl_IHealingOperations.cxx
1 //  Copyright (C) 2007-2008  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_Stream.hxx>
27
28 #include <GEOMImpl_IHealingOperations.hxx>
29
30 #include <GEOM_PythonDump.hxx>
31
32 #include <GEOMImpl_HealingDriver.hxx>
33 #include <GEOMImpl_Types.hxx>
34 #include <GEOMImpl_IHealing.hxx>
35 #include <GEOMImpl_CopyDriver.hxx>
36
37 #include <ShHealOper_ShapeProcess.hxx>
38
39 #include "utilities.h"
40 #include <OpUtil.hxx>
41 #include <Utils_ExceptHandlers.hxx>
42
43 #include <ShapeAnalysis_FreeBounds.hxx>
44
45 #include <TopoDS_Compound.hxx>
46 #include <TopExp_Explorer.hxx>
47
48 #include <TColStd_HArray1OfExtendedString.hxx>
49 #include <TColStd_HSequenceOfTransient.hxx>
50 #include <TCollection_AsciiString.hxx>
51
52 #include <TDF_Tool.hxx>
53
54 #include <Standard_Failure.hxx>
55 #include <Standard_ErrorHandler.hxx> // CAREFUL ! position of this file is critic : see Lucien PIGNOLONI / OCC
56
57
58 //=============================================================================
59 /*!
60  *   constructor:
61  */
62 //=============================================================================
63
64 GEOMImpl_IHealingOperations::GEOMImpl_IHealingOperations (GEOM_Engine* theEngine, int theDocID)
65 : GEOM_IOperations(theEngine, theDocID)
66 {
67   MESSAGE("GEOMImpl_IHealingOperations::GEOMImpl_IHealingOperations");
68 }
69
70 //=============================================================================
71 /*!
72  *  destructor
73  */
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_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
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_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
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 /*!
382  *  CloseContour
383  */
384 //=============================================================================
385 Handle(GEOM_Object) GEOMImpl_IHealingOperations::CloseContour
386                     (Handle(GEOM_Object) theObject,
387                      const Handle(TColStd_HArray1OfInteger)& theWires,
388                      bool isCommonVertex)
389 {
390   // set error code, check parameters
391   SetErrorCode(KO);
392
393   if (theObject.IsNull())
394   {
395     SetErrorCode("NULL object given");
396     return NULL;
397   }
398
399   Handle(GEOM_Function) aFunction, aLastFunction = theObject->GetLastFunction();
400   if (aLastFunction.IsNull()) return NULL; //There is no function which creates an object to be processed
401
402   // Add a new object
403   Handle(GEOM_Object) aNewObject = GetEngine()->AddObject( GetDocID(), GEOM_COPY );
404
405   //Add the function
406   aFunction = aNewObject->AddFunction(GEOMImpl_HealingDriver::GetID(), CLOSE_CONTOUR);
407
408   if (aFunction.IsNull()) return NULL;
409
410   //Check if the function is set correctly
411   if(aFunction->GetDriverGUID() != GEOMImpl_HealingDriver::GetID()) return NULL;
412
413   // prepare "data container" class IHealing
414   GEOMImpl_IHealing HI(aFunction);
415   HI.SetWires( theWires );
416   HI.SetIsCommonVertex( isCommonVertex );
417   HI.SetOriginal( aLastFunction );
418
419   //Compute the translation
420   try {
421 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
422     OCC_CATCH_SIGNALS;
423 #endif
424     if (!GetSolver()->ComputeFunction(aFunction))
425     {
426       SetErrorCode("Healing driver failed");
427       return NULL;
428     }
429   }
430   catch (Standard_Failure)
431   {
432         Handle(Standard_Failure) aFail = Standard_Failure::Caught();
433     SetErrorCode(aFail->GetMessageString());
434     return NULL;
435   }
436
437   //Make a Python command
438   GEOM::TPythonDump pd (aFunction);
439   pd << aNewObject << " = geompy.CloseContour(" << theObject << ", [";
440
441   // list of wire ids
442   if (!theWires.IsNull())
443   {
444     int i = theWires->Lower(), nb = theWires->Upper();
445     pd << theWires->Value(i++);
446     while (i <= nb)
447       pd << ", " << theWires->Value(i++);
448   }
449   pd << "], " << (int)isCommonVertex << ")";
450
451   SetErrorCode(OK);
452   return aNewObject;
453 }
454
455 //=============================================================================
456 /*!
457  *  RemoveIntWires
458  */
459 //=============================================================================
460 Handle(GEOM_Object) GEOMImpl_IHealingOperations::RemoveIntWires
461        (Handle(GEOM_Object) theObject, const Handle(TColStd_HArray1OfInteger)& theWires)
462 {
463   // set error code, check parameters
464   SetErrorCode(KO);
465
466   if (theObject.IsNull()) // if theWires is NULL it's OK, it means that ALL wires must be removed
467     return NULL;
468
469   Handle(GEOM_Function) aFunction, aLastFunction = theObject->GetLastFunction();
470   if (aLastFunction.IsNull()) return NULL; //There is no function which creates an object to be processed
471
472   // Add a new object
473   Handle(GEOM_Object) aNewObject = GetEngine()->AddObject( GetDocID(), GEOM_COPY );
474
475   //Add the function
476   aFunction = aNewObject->AddFunction(GEOMImpl_HealingDriver::GetID(), REMOVE_INT_WIRES);
477
478   if (aFunction.IsNull()) return NULL;
479
480   //Check if the function is set correctly
481   if (aFunction->GetDriverGUID() != GEOMImpl_HealingDriver::GetID()) return NULL;
482
483   // prepare "data container" class IHealing
484   GEOMImpl_IHealing HI(aFunction);
485   HI.SetWires( theWires );
486   HI.SetOriginal( aLastFunction );
487
488   //Compute the translation
489   try {
490 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
491     OCC_CATCH_SIGNALS;
492 #endif
493     if (!GetSolver()->ComputeFunction(aFunction))
494     {
495       SetErrorCode("Healing driver failed");
496       return NULL;
497     }
498   }
499   catch (Standard_Failure)
500   {
501     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
502     SetErrorCode(aFail->GetMessageString());
503     return NULL;
504   }
505
506   //Make a Python command
507   GEOM::TPythonDump pd (aFunction);
508   pd << aNewObject << " = geompy.SuppressInternalWires(" << theObject << ", [";
509
510   // list of wire ids
511   if (!theWires.IsNull()) {
512     int i = theWires->Lower(), nb = theWires->Upper();
513     for ( ; i <= nb; i++)
514       pd << theWires->Value( i ) << (( i < nb ) ? ", " : "])");
515   } else {
516     pd << "])";
517   }
518
519   SetErrorCode(OK);
520   return aNewObject;
521 }
522
523 //=============================================================================
524 /*!
525  *  FillHoles
526  */
527 //=============================================================================
528 Handle(GEOM_Object) GEOMImpl_IHealingOperations::FillHoles (Handle(GEOM_Object) theObject,
529                                                             const Handle(TColStd_HArray1OfInteger)& theWires)
530 {
531   // set error code, check parameters
532   SetErrorCode(KO);
533
534   if (theObject.IsNull()) // if theWires is NULL it's OK, it means that ALL holes must be removed
535     return NULL;
536
537   Handle(GEOM_Function) aFunction, aLastFunction = theObject->GetLastFunction();
538   if (aLastFunction.IsNull()) return NULL; //There is no function which creates an object to be processed
539
540   // Add a new object
541   Handle(GEOM_Object) aNewObject = GetEngine()->AddObject( GetDocID(), GEOM_COPY );
542
543   //Add the function
544   aFunction = aNewObject->AddFunction(GEOMImpl_HealingDriver::GetID(), FILL_HOLES);
545
546   if (aFunction.IsNull()) return NULL;
547
548   //Check if the function is set correctly
549   if (aFunction->GetDriverGUID() != GEOMImpl_HealingDriver::GetID()) return NULL;
550
551   // prepare "data container" class IHealing
552   GEOMImpl_IHealing HI(aFunction);
553   HI.SetWires( theWires );
554   HI.SetOriginal( aLastFunction );
555
556   //Compute the translation
557   try {
558 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
559     OCC_CATCH_SIGNALS;
560 #endif
561     if (!GetSolver()->ComputeFunction(aFunction))
562     {
563       SetErrorCode("Healing driver failed");
564       return NULL;
565     }
566   }
567   catch (Standard_Failure)
568   {
569         Handle(Standard_Failure) aFail = Standard_Failure::Caught();
570     SetErrorCode(aFail->GetMessageString());
571     return NULL;
572   }
573
574   //Make a Python command
575   GEOM::TPythonDump pd (aFunction);
576   pd << aNewObject << " = geompy.SuppressHoles(" << theObject << ", [";
577
578   // list of wire ids
579   if ( theWires.IsNull() )
580     pd << "])";
581   else {
582     int i = theWires->Lower(), nb = theWires->Upper();
583     for ( ; i <= nb; i++)
584       pd << theWires->Value( i ) << (( i < nb ) ? ", " : "])");
585   }
586
587   SetErrorCode(OK);
588   return aNewObject;
589 }
590
591 //=============================================================================
592 /*!
593  *  Sew
594  */
595 //=============================================================================
596 Handle(GEOM_Object) GEOMImpl_IHealingOperations::Sew (Handle(GEOM_Object) theObject,
597                                                       double theTolerance)
598 {
599   // set error code, check parameters
600   SetErrorCode(KO);
601
602   if (theObject.IsNull())
603     return NULL;
604
605   Handle(GEOM_Function) aFunction, aLastFunction = theObject->GetLastFunction();
606   if (aLastFunction.IsNull()) return NULL; //There is no function which creates an object to be processed
607
608   // Add a new object
609   Handle(GEOM_Object) aNewObject = GetEngine()->AddObject( GetDocID(), GEOM_COPY );
610
611   //Add the function
612   aFunction = aNewObject->AddFunction(GEOMImpl_HealingDriver::GetID(), SEWING);
613
614   if (aFunction.IsNull()) return NULL;
615
616   //Check if the function is set correctly
617   if (aFunction->GetDriverGUID() != GEOMImpl_HealingDriver::GetID()) return NULL;
618
619   // prepare "data container" class IHealing
620   GEOMImpl_IHealing HI(aFunction);
621   HI.SetTolerance( theTolerance );
622   HI.SetOriginal( aLastFunction );
623
624   //Compute the translation
625   try {
626 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
627     OCC_CATCH_SIGNALS;
628 #endif
629     if (!GetSolver()->ComputeFunction(aFunction))
630     {
631       SetErrorCode("Healing driver failed");
632       return NULL;
633     }
634   }
635   catch (Standard_Failure)
636   {
637         Handle(Standard_Failure) aFail = Standard_Failure::Caught();
638     SetErrorCode(aFail->GetMessageString());
639     return NULL;
640   }
641
642   //Make a Python command
643   GEOM::TPythonDump(aFunction) << aNewObject << " = geompy.Sew("
644                                << theObject << ", " << theTolerance << ")";
645
646   SetErrorCode(OK);
647   return aNewObject;
648 }
649
650 //=============================================================================
651 /*!
652  *  DivideEdge
653  */
654 //=============================================================================
655 Handle(GEOM_Object) GEOMImpl_IHealingOperations::DivideEdge (Handle(GEOM_Object) theObject,
656                                                              int theIndex,
657                                                              double theValue,
658                                                              bool isByParameter)
659 {
660   // set error code, check parameters
661   SetErrorCode(KO);
662
663   if (theObject.IsNull())
664     return NULL;
665
666   Handle(GEOM_Function) aFunction, aLastFunction = theObject->GetLastFunction();
667   if (aLastFunction.IsNull()) return NULL; //There is no function which creates an object to be processed
668
669   // Add a new object
670   Handle(GEOM_Object) aNewObject = GetEngine()->AddObject( GetDocID(), GEOM_COPY );
671
672   //Add the function
673   aFunction = aNewObject->AddFunction(GEOMImpl_HealingDriver::GetID(), DIVIDE_EDGE);
674
675   if (aFunction.IsNull()) return NULL;
676
677   //Check if the function is set correctly
678   if (aFunction->GetDriverGUID() != GEOMImpl_HealingDriver::GetID()) return NULL;
679
680   // prepare "data container" class IHealing
681   GEOMImpl_IHealing HI(aFunction);
682   HI.SetIndex( theIndex );
683   HI.SetDevideEdgeValue( theValue );
684   HI.SetIsByParameter( isByParameter );
685   HI.SetOriginal( aLastFunction );
686
687   //Compute the translation
688   try {
689 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
690     OCC_CATCH_SIGNALS;
691 #endif
692     if (!GetSolver()->ComputeFunction(aFunction))
693     {
694       SetErrorCode("Healing driver failed");
695       return NULL;
696     }
697   }
698   catch (Standard_Failure)
699   {
700         Handle(Standard_Failure) aFail = Standard_Failure::Caught();
701     SetErrorCode(aFail->GetMessageString());
702     return NULL;
703   }
704
705   //Make a Python command
706   GEOM::TPythonDump(aFunction) << aNewObject << " = geompy.DivideEdge(" << theObject
707     << ", " << theIndex << ", " << theValue << ", " << (int)isByParameter << ")";
708
709   SetErrorCode(OK);
710   return aNewObject;
711 }
712
713 //=============================================================================
714 /*!
715  *  GetFreeBoundary
716  */
717 //=============================================================================
718 bool GEOMImpl_IHealingOperations::GetFreeBoundary (Handle(GEOM_Object) theObject,
719                                                    Handle(TColStd_HSequenceOfTransient)& theClosed,
720                                                    Handle(TColStd_HSequenceOfTransient)& theOpen )
721 {
722   // set error code, check parameters
723   SetErrorCode(KO);
724
725   if ( theObject.IsNull() || theClosed.IsNull() || theOpen.IsNull() )
726     return false;
727
728   TopoDS_Shape aShape = theObject->GetValue();
729   if ( aShape.IsNull() )
730     return false;
731
732   // get free boundary shapes
733   ShapeAnalysis_FreeBounds anAnalizer( aShape );
734   TopoDS_Compound aClosed = anAnalizer.GetClosedWires();
735   TopoDS_Compound anOpen = anAnalizer.GetOpenWires();
736
737   // iterate through shapes and append them to the return sequence
738   Handle(GEOM_Object) anObj;
739   Handle(GEOM_Function) aFunction;
740   TopExp_Explorer anExp;
741   for ( anExp.Init( aClosed, TopAbs_WIRE ); anExp.More(); anExp.Next() )
742   {
743     anObj = GetEngine()->AddObject( GetDocID(), GEOM_FREE_BOUNDS );
744     aFunction = anObj->AddFunction( GEOMImpl_CopyDriver::GetID(), COPY_WITHOUT_REF );
745     TopoDS_Shape aValueShape = anExp.Current();
746     aFunction->SetValue( aValueShape );
747     theClosed->Append(anObj);
748   }
749   for ( anExp.Init( anOpen, TopAbs_WIRE ); anExp.More(); anExp.Next() )
750   {
751     anObj = GetEngine()->AddObject( GetDocID(), GEOM_FREE_BOUNDS );
752     aFunction = anObj->AddFunction( GEOMImpl_CopyDriver::GetID(), COPY_WITHOUT_REF );
753     TopoDS_Shape aValueShape = anExp.Current();
754     aFunction->SetValue( aValueShape );
755     theOpen->Append(anObj);
756   }
757
758   if(!aFunction.IsNull()) {
759
760     //Make a Python command
761     GEOM::TPythonDump pd (aFunction);
762
763     Standard_Integer i, aLen = theClosed->Length();
764     if (aLen > 0) {
765       pd << "(isDone, [";
766       for (i = 1; i <= aLen; i++) {
767         Handle(GEOM_Object) anObj_i = Handle(GEOM_Object)::DownCast(theClosed->Value(i));
768         pd << anObj_i << ((i < aLen) ? ", " : "");
769       }
770       pd << "], ";
771     } else {
772       pd << "(isDone, empty_list, ";
773     }
774
775     aLen = theOpen->Length();
776     if (aLen > 0) {
777       pd << "[";
778       for (i = 1; i <= aLen; i++) {
779         Handle(GEOM_Object) anObj_i = Handle(GEOM_Object)::DownCast(theOpen->Value(i));
780         pd << anObj_i << ((i < aLen) ? ", " : "");
781       }
782       pd << "]";
783     } else {
784       pd << "empty_list";
785     }
786
787     pd << ") = geompy.GetFreeBoundary(" << theObject << ")";
788   }
789
790   SetErrorCode(OK);
791   return true;
792 }
793
794
795 //=============================================================================
796 /*!
797  *  ChangeOrientation
798  */
799 //=============================================================================
800 Handle(GEOM_Object) GEOMImpl_IHealingOperations::ChangeOrientation (Handle(GEOM_Object) theObject)
801 {
802   // set error code, check parameters
803   SetErrorCode(KO);
804
805   if (theObject.IsNull())
806     return NULL;
807
808   if (!theObject->IsMainShape()) {
809     SetErrorCode("Sub shape cannot be transformed - need to create a copy");
810     return NULL;
811   }
812
813   Handle(GEOM_Function) aFunction, aLastFunction = theObject->GetLastFunction();
814   if (aLastFunction.IsNull()) 
815     return NULL; //There is no function which creates an object to be processed
816
817   //Add the function
818   aFunction = theObject->AddFunction(GEOMImpl_HealingDriver::GetID(), CHANGE_ORIENTATION);
819
820   if (aFunction.IsNull())
821     return NULL;
822
823   //Check if the function is set correctly
824   if (aFunction->GetDriverGUID() != GEOMImpl_HealingDriver::GetID()) return NULL;
825
826   // prepare "data container" class IHealing
827   GEOMImpl_IHealing HI(aFunction);
828   HI.SetOriginal( aLastFunction );
829
830   //Compute the translation
831   try {
832 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
833     OCC_CATCH_SIGNALS;
834 #endif
835     if (!GetSolver()->ComputeFunction(aFunction)) {
836       SetErrorCode("Healing driver failed");
837       return NULL;
838     }
839   }
840   catch (Standard_Failure) {
841     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
842     SetErrorCode(aFail->GetMessageString());
843     return NULL;
844   }
845
846   //Make a Python command
847   GEOM::TPythonDump(aFunction) << "geompy.ChangeOrientationShell("
848                                << theObject << ")";
849
850   SetErrorCode(OK);
851   return theObject;
852 }
853
854
855 //=============================================================================
856 /*!
857  *  ChangeOrientationCopy
858  */
859 //=============================================================================
860 Handle(GEOM_Object) GEOMImpl_IHealingOperations::ChangeOrientationCopy (Handle(GEOM_Object) theObject)
861 {
862   // set error code, check parameters
863   SetErrorCode(KO);
864
865   if (theObject.IsNull())
866     return NULL;
867
868   Handle(GEOM_Function) aFunction, aLastFunction = theObject->GetLastFunction();
869   if (aLastFunction.IsNull())
870     return NULL; //There is no function which creates an object to be processed
871
872   // Add a new object
873   Handle(GEOM_Object) aNewObject = GetEngine()->AddObject( GetDocID(), theObject->GetType() );
874
875   //Add the function
876   aFunction = aNewObject->AddFunction(GEOMImpl_HealingDriver::GetID(), CHANGE_ORIENTATION);
877
878   if (aFunction.IsNull())
879     return NULL;
880
881   //Check if the function is set correctly
882   if (aFunction->GetDriverGUID() != GEOMImpl_HealingDriver::GetID()) return NULL;
883
884   // prepare "data container" class IHealing
885   GEOMImpl_IHealing HI(aFunction);
886   HI.SetOriginal( aLastFunction );
887
888   //Compute the translation
889   try {
890 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
891     OCC_CATCH_SIGNALS;
892 #endif
893     if (!GetSolver()->ComputeFunction(aFunction)) {
894       SetErrorCode("Healing driver failed");
895       return NULL;
896     }
897   }
898   catch (Standard_Failure) {
899     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
900     SetErrorCode(aFail->GetMessageString());
901     return NULL;
902   }
903
904   //Make a Python command
905   GEOM::TPythonDump(aFunction) << aNewObject << " = geompy.ChangeOrientationShellCopy("
906                                << theObject << ")";
907
908   SetErrorCode(OK);
909   return aNewObject;
910 }
911