Salome HOME
0020628: EDF 1144 GEOM : In TUI, need a function to know the orientation of an edge...
[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  *  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_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
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_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
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_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
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_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
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_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
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   ShapeAnalysis_FreeBounds anAnalizer( aShape );
733   TopoDS_Compound aClosed = anAnalizer.GetClosedWires();
734   TopoDS_Compound anOpen = anAnalizer.GetOpenWires();
735
736   // iterate through shapes and append them to the return sequence
737   Handle(GEOM_Object) anObj;
738   Handle(GEOM_Function) aFunction;
739   TopExp_Explorer anExp;
740   for ( anExp.Init( aClosed, TopAbs_WIRE ); anExp.More(); anExp.Next() )
741   {
742     anObj = GetEngine()->AddObject( GetDocID(), GEOM_FREE_BOUNDS );
743     aFunction = anObj->AddFunction( GEOMImpl_CopyDriver::GetID(), COPY_WITHOUT_REF );
744     TopoDS_Shape aValueShape = anExp.Current();
745     aFunction->SetValue( aValueShape );
746     theClosed->Append(anObj);
747   }
748   for ( anExp.Init( anOpen, TopAbs_WIRE ); anExp.More(); anExp.Next() )
749   {
750     anObj = GetEngine()->AddObject( GetDocID(), GEOM_FREE_BOUNDS );
751     aFunction = anObj->AddFunction( GEOMImpl_CopyDriver::GetID(), COPY_WITHOUT_REF );
752     TopoDS_Shape aValueShape = anExp.Current();
753     aFunction->SetValue( aValueShape );
754     theOpen->Append(anObj);
755   }
756
757   if(!aFunction.IsNull()) {
758
759     //Make a Python command
760     GEOM::TPythonDump pd (aFunction);
761
762     Standard_Integer i, aLen = theClosed->Length();
763     if (aLen > 0) {
764       pd << "(isDone, [";
765       for (i = 1; i <= aLen; i++) {
766         Handle(GEOM_Object) anObj_i = Handle(GEOM_Object)::DownCast(theClosed->Value(i));
767         pd << anObj_i << ((i < aLen) ? ", " : "");
768       }
769       pd << "], ";
770     } else {
771       pd << "(isDone, empty_list, ";
772     }
773
774     aLen = theOpen->Length();
775     if (aLen > 0) {
776       pd << "[";
777       for (i = 1; i <= aLen; i++) {
778         Handle(GEOM_Object) anObj_i = Handle(GEOM_Object)::DownCast(theOpen->Value(i));
779         pd << anObj_i << ((i < aLen) ? ", " : "");
780       }
781       pd << "]";
782     } else {
783       pd << "empty_list";
784     }
785
786     pd << ") = geompy.GetFreeBoundary(" << theObject << ")";
787   }
788
789   SetErrorCode(OK);
790   return true;
791 }
792
793
794 //=============================================================================
795 /*!
796  *  ChangeOrientation
797  */
798 //=============================================================================
799 Handle(GEOM_Object) GEOMImpl_IHealingOperations::ChangeOrientation (Handle(GEOM_Object) theObject)
800 {
801   // set error code, check parameters
802   SetErrorCode(KO);
803
804   if (theObject.IsNull())
805     return NULL;
806
807   if (!theObject->IsMainShape()) {
808     SetErrorCode("Sub shape cannot be transformed - need to create a copy");
809     return NULL;
810   }
811
812   Handle(GEOM_Function) aFunction, aLastFunction = theObject->GetLastFunction();
813   if (aLastFunction.IsNull())
814     return NULL; //There is no function which creates an object to be processed
815
816   //Add the function
817   aFunction = theObject->AddFunction(GEOMImpl_HealingDriver::GetID(), CHANGE_ORIENTATION);
818
819   if (aFunction.IsNull())
820     return NULL;
821
822   //Check if the function is set correctly
823   if (aFunction->GetDriverGUID() != GEOMImpl_HealingDriver::GetID()) return NULL;
824
825   // prepare "data container" class IHealing
826   GEOMImpl_IHealing HI(aFunction);
827   HI.SetOriginal( aLastFunction );
828
829   //Compute the translation
830   try {
831 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
832     OCC_CATCH_SIGNALS;
833 #endif
834     if (!GetSolver()->ComputeFunction(aFunction)) {
835       SetErrorCode("Healing driver failed");
836       return NULL;
837     }
838   }
839   catch (Standard_Failure) {
840     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
841     SetErrorCode(aFail->GetMessageString());
842     return NULL;
843   }
844
845   //Make a Python command
846   GEOM::TPythonDump(aFunction) << "geompy.ChangeOrientationShell("
847                                << theObject << ")";
848
849   SetErrorCode(OK);
850   return theObject;
851 }
852
853
854 //=============================================================================
855 /*!
856  *  ChangeOrientationCopy
857  */
858 //=============================================================================
859 Handle(GEOM_Object) GEOMImpl_IHealingOperations::ChangeOrientationCopy (Handle(GEOM_Object) theObject)
860 {
861   // set error code, check parameters
862   SetErrorCode(KO);
863
864   if (theObject.IsNull())
865     return NULL;
866
867   Handle(GEOM_Function) aFunction, aLastFunction = theObject->GetLastFunction();
868   if (aLastFunction.IsNull())
869     return NULL; //There is no function which creates an object to be processed
870
871   // Add a new object
872   Handle(GEOM_Object) aNewObject = GetEngine()->AddObject( GetDocID(), theObject->GetType() );
873
874   //Add the function
875   aFunction = aNewObject->AddFunction(GEOMImpl_HealingDriver::GetID(), CHANGE_ORIENTATION);
876
877   if (aFunction.IsNull())
878     return NULL;
879
880   //Check if the function is set correctly
881   if (aFunction->GetDriverGUID() != GEOMImpl_HealingDriver::GetID()) return NULL;
882
883   // prepare "data container" class IHealing
884   GEOMImpl_IHealing HI(aFunction);
885   HI.SetOriginal( aLastFunction );
886
887   //Compute the translation
888   try {
889 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
890     OCC_CATCH_SIGNALS;
891 #endif
892     if (!GetSolver()->ComputeFunction(aFunction)) {
893       SetErrorCode("Healing driver failed");
894       return NULL;
895     }
896   }
897   catch (Standard_Failure) {
898     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
899     SetErrorCode(aFail->GetMessageString());
900     return NULL;
901   }
902
903   //Make a Python command
904   GEOM::TPythonDump(aFunction) << aNewObject << " = geompy.ChangeOrientationShellCopy("
905                                << theObject << ")";
906
907   SetErrorCode(OK);
908   return aNewObject;
909 }