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