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