Salome HOME
rollback IPAL8963 3.0.0: "Incorrect input data" message
[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 using namespace std;
58
59
60 //=============================================================================
61 /*!
62  *   constructor:
63  */
64 //=============================================================================
65
66 GEOMImpl_IHealingOperations::GEOMImpl_IHealingOperations (GEOM_Engine* theEngine, int theDocID)
67 : GEOM_IOperations(theEngine, theDocID)
68 {
69   MESSAGE("GEOMImpl_IHealingOperations::GEOMImpl_IHealingOperations");
70 }
71
72 //=============================================================================
73 /*!
74  *  destructor
75  */
76 //=============================================================================
77
78 GEOMImpl_IHealingOperations::~GEOMImpl_IHealingOperations()
79 {
80   MESSAGE("GEOMImpl_IHealingOperations::~GEOMImpl_IHealingOperations");
81 }
82
83
84 //=============================================================================
85 /*!
86  *  ShapeProcess
87  */
88 //=============================================================================
89 Handle(GEOM_Object) GEOMImpl_IHealingOperations::ShapeProcess (Handle(GEOM_Object) theObject,
90                                   const Handle(TColStd_HArray1OfExtendedString)& theOperators,
91                                   const Handle(TColStd_HArray1OfExtendedString)& theParams,
92                                   const Handle(TColStd_HArray1OfExtendedString)& theValues)
93 {
94   // set error code, check parameters
95   SetErrorCode(KO);
96
97   if (theObject.IsNull())
98     return NULL;
99
100   if (theOperators.IsNull() || theOperators->Length() <= 0) {
101     SetErrorCode("No operators requested");
102     return NULL;
103   }
104
105   Standard_Integer nbParams = 0, nbValues = 0;
106   if (!theParams.IsNull()) {
107     nbParams = theParams->Length();
108   }
109   if (!theValues.IsNull()) {
110     nbValues = theValues->Length();
111   }
112
113   if (nbParams != nbValues) {
114     SetErrorCode("Number of parameter values must be equal to the number of parameters");
115     return NULL;
116   }
117
118   Handle(GEOM_Function) aFunction, aLastFunction = theObject->GetLastFunction();
119   if (aLastFunction.IsNull()) return NULL; //There is no function which creates an object to be processed
120
121   // Add a new object
122   Handle(GEOM_Object) aNewObject = GetEngine()->AddObject( GetDocID(), GEOM_COPY );
123
124   //Add the function
125   aFunction = aNewObject->AddFunction(GEOMImpl_HealingDriver::GetID(), SHAPE_PROCESS);
126
127   if (aFunction.IsNull()) return NULL;
128
129   //Check if the function is set correctly
130   if (aFunction->GetDriverGUID() != GEOMImpl_HealingDriver::GetID()) return NULL;
131
132   // prepare "data container" class IHealing
133   GEOMImpl_IHealing HI(aFunction);
134   HI.SetOriginal(aLastFunction);
135   HI.SetOperators( theOperators );
136   if (nbParams > 0) {
137     HI.SetParameters( theParams );
138     HI.SetValues( theValues );
139   }
140
141   //Compute the translation
142   try {
143 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
144     OCC_CATCH_SIGNALS;
145 #endif
146     if (!GetSolver()->ComputeFunction(aFunction))
147     {
148       SetErrorCode("Shape Healing algorithm failed");
149       return NULL;
150     }
151   }
152   catch (Standard_Failure)
153   {
154     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
155     SetErrorCode(aFail->GetMessageString());
156     return NULL;
157   }
158
159   //Make a Python command
160   GEOM::TPythonDump pd (aFunction);
161   pd << aNewObject << " = geompy.ProcessShape(" << theObject << ", [";
162
163   // list of operators
164   int i = theOperators->Lower(), nb = theOperators->Upper();
165   for ( ; i <= nb; i++) {
166     pd << "\"" << TCollection_AsciiString(theOperators->Value( i )).ToCString()
167       << (( i < nb ) ? "\", " : "\"");
168   }
169   pd << "], [";
170   // list of parameters
171   i = theParams->Lower(); nb = theParams->Upper();
172   for ( ; i <= nb; i++) {
173     pd << "\"" << TCollection_AsciiString(theParams->Value( i )).ToCString()
174       << (( i < nb ) ? "\", " : "\"");
175   }
176   pd << "], [";
177   // list of values
178   i = theValues->Lower(); nb = theValues->Upper();
179   for ( ; i <= nb; i++) {
180     pd << "\"" << TCollection_AsciiString(theValues->Value( i )).ToCString()
181       << (( i < nb ) ? "\", " : "\"");
182   }
183   pd << "])";
184
185   SetErrorCode(OK);
186   return aNewObject;
187 }
188
189 //=============================================================================
190 /*!
191  *  ShapeProcess
192  */
193 //=============================================================================
194 void GEOMImpl_IHealingOperations::GetShapeProcessParameters (list<string>& theOperations,
195                                                              list<string>& theParams,
196                                                              list<string>& theValues)
197 {
198   ShHealOper_ShapeProcess aHealer;
199   TColStd_SequenceOfAsciiString anOperators;
200   int nbOperatorErrors( 0 );
201   if ( aHealer.GetOperators( anOperators ) )
202   {
203     for ( Standard_Integer i = 1; i <= anOperators.Length(); i++ )
204     {
205       string anOperation = anOperators.Value( i ).ToCString();
206       if ( GetOperatorParameters( anOperation, theParams, theValues ) )
207         theOperations.push_back( anOperation );
208       else
209         nbOperatorErrors++;
210     }
211   }
212   else
213   {
214     SetErrorCode("ERROR retrieving operators (GEOMImpl_IHealingOperations)");
215   }
216
217   if ( nbOperatorErrors ) {
218     TCollection_AsciiString aMsg ("ERRORS retrieving ShapeProcess parameters (GEOMImpl_IHealingOperations): nbOperatorErrors = ");
219     aMsg += TCollection_AsciiString( nbOperatorErrors );
220     MESSAGE(aMsg.ToCString());
221   }
222 }
223
224 //=============================================================================
225 /*!
226  *  GetOperatorParameters
227  */
228 //=============================================================================
229 bool GEOMImpl_IHealingOperations::GetOperatorParameters( const string theOperation, 
230                                                          list<string>& theParams,
231                                                          list<string>& theValues )
232 {
233   ShHealOper_ShapeProcess aHealer;
234   int nbParamValueErrors( 0 );
235   list<string> aParams;
236   if ( GetParameters( theOperation, aParams ) ) {
237     for ( list<string>::iterator it = aParams.begin(); it != aParams.end(); ++it ) {
238       TCollection_AsciiString aParam( (Standard_CString)(*it).c_str() );
239       TCollection_AsciiString aValue;
240       if ( aHealer.GetParameter( aParam, aValue ) ) {
241         theParams.push_back( aParam.ToCString() );
242         theValues.push_back( aValue.ToCString() );
243       }
244       else
245         nbParamValueErrors++;
246     }
247   }
248   else
249     return false;
250
251   if ( nbParamValueErrors ) {
252     TCollection_AsciiString aMsg ("ERRORS retrieving ShapeProcess parameter values (GEOMImpl_IHealingOperations): nbParamValueErrors = ");
253     aMsg += TCollection_AsciiString( nbParamValueErrors );
254     MESSAGE(aMsg.ToCString());
255   }
256
257   return true;
258 }
259
260 //=============================================================================
261 /*!
262  *  GetParameters
263  */
264 //=============================================================================
265 bool GEOMImpl_IHealingOperations::GetParameters (const string theOperation,
266                                                  list<string>& theParams)
267 {
268   if ( theOperation == "SplitAngle" ) {
269     theParams.push_back( "SplitAngle.Angle" );
270     theParams.push_back( "SplitAngle.MaxTolerance" );
271
272   } else if ( theOperation == "SplitClosedFaces" ) {
273     theParams.push_back( "SplitClosedFaces.NbSplitPoints" );
274
275   } else if ( theOperation == "FixFaceSize" ) {
276     theParams.push_back( "FixFaceSize.Tolerance" );
277
278   } else if( theOperation == "DropSmallEdges" ) {
279     theParams.push_back( "DropSmallEdges.Tolerance3d" );
280
281   } else if( theOperation == "BSplineRestriction" ) {
282     theParams.push_back( "BSplineRestriction.SurfaceMode" );
283     theParams.push_back( "BSplineRestriction.Curve3dMode" );
284     theParams.push_back( "BSplineRestriction.Curve2dMode" );
285     theParams.push_back( "BSplineRestriction.Tolerance3d" );
286     theParams.push_back( "BSplineRestriction.Tolerance2d" );
287     theParams.push_back( "BSplineRestriction.RequiredDegree" );
288     theParams.push_back( "BSplineRestriction.RequiredNbSegments" );
289     theParams.push_back( "BSplineRestriction.Continuity3d" );
290     theParams.push_back( "BSplineRestriction.Continuity2d" );
291
292   } else if( theOperation == "SplitContinuity" ) {
293     theParams.push_back( "SplitContinuity.Tolerance3d" );
294     theParams.push_back( "SplitContinuity.SurfaceContinuity" );
295     theParams.push_back( "SplitContinuity.CurveContinuity" );
296
297   } else if( theOperation == "ToBezier" ) {
298     theParams.push_back( "ToBezier.SurfaceMode" );
299     theParams.push_back( "ToBezier.Curve3dMode" );
300     theParams.push_back( "ToBezier.Curve2dMode" );
301     theParams.push_back( "ToBezier.MaxTolerance" );
302
303   } else if( theOperation == "SameParameter" ) {
304     theParams.push_back( "SameParameter.Tolerance3d" );
305
306   } else if( theOperation == "FixShape" ) {
307     theParams.push_back( "FixShape.Tolerance3d" );
308     theParams.push_back( "FixShape.MaxTolerance3d" );
309
310   } else {
311     return false;
312   }
313
314   return true;
315 }
316
317 //=============================================================================
318 /*!
319  *  SuppressFaces
320  */
321 //=============================================================================
322 Handle(GEOM_Object) GEOMImpl_IHealingOperations::SuppressFaces
323        (Handle(GEOM_Object) theObject, const Handle(TColStd_HArray1OfInteger)& theFaces)
324 {
325   // set error code, check parameters
326   SetErrorCode(KO);
327
328   if ( theObject.IsNull() ) // if theFaces.IsNull() - it's OK, it means that ALL faces must be removed..
329     return NULL;
330
331   Handle(GEOM_Function) aFunction, aLastFunction = theObject->GetLastFunction();
332   if(aLastFunction.IsNull()) return NULL; //There is no function which creates an object to be processed
333
334   // Add a new object
335   Handle(GEOM_Object) aNewObject = GetEngine()->AddObject( GetDocID(), GEOM_COPY );
336
337   //Add the function
338   aFunction = aNewObject->AddFunction(GEOMImpl_HealingDriver::GetID(), SUPPRESS_FACES);
339
340   if(aFunction.IsNull()) return NULL;
341
342   //Check if the function is set correctly
343   if(aFunction->GetDriverGUID() != GEOMImpl_HealingDriver::GetID()) return NULL;
344
345   // prepare "data container" class IHealing
346   GEOMImpl_IHealing HI(aFunction);
347   HI.SetFaces( theFaces );
348   HI.SetOriginal( aLastFunction );
349
350   //Compute the translation
351   try {
352 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
353     OCC_CATCH_SIGNALS;
354 #endif
355     if (!GetSolver()->ComputeFunction(aFunction))
356     {
357       SetErrorCode("Healing driver failed");
358       return NULL;
359     }
360   }
361   catch (Standard_Failure)
362   {
363         Handle(Standard_Failure) aFail = Standard_Failure::Caught();
364     SetErrorCode(aFail->GetMessageString());
365     return NULL;
366   }
367
368   //Make a Python command
369   GEOM::TPythonDump pd (aFunction);
370   pd << aNewObject << " = geompy.SuppressFaces(" << theObject << ", [";
371
372   // list of face ids
373   int i = theFaces->Lower(), nb = theFaces->Upper();
374   for ( ; i <= nb; i++)
375     pd << theFaces->Value( i ) << (( i < nb ) ? ", " : "])");
376
377   SetErrorCode(OK);
378   return aNewObject;
379 }
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_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
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_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
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_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
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_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
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_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
692     OCC_CATCH_SIGNALS;
693 #endif
694     if (!GetSolver()->ComputeFunction(aFunction))
695     {
696       SetErrorCode("Healing driver failed");
697       return NULL;
698     }
699   }
700   catch (Standard_Failure)
701   {
702         Handle(Standard_Failure) aFail = Standard_Failure::Caught();
703     SetErrorCode(aFail->GetMessageString());
704     return NULL;
705   }
706
707   //Make a Python command
708   GEOM::TPythonDump(aFunction) << aNewObject << " = geompy.DivideEdge(" << theObject
709     << ", " << theIndex << ", " << theValue << ", " << (int)isByParameter << ")";
710
711   SetErrorCode(OK);
712   return aNewObject;
713 }
714
715 //=============================================================================
716 /*!
717  *  GetFreeBoundary
718  */
719 //=============================================================================
720 bool GEOMImpl_IHealingOperations::GetFreeBoundary (Handle(GEOM_Object) theObject,
721                                                    Handle(TColStd_HSequenceOfTransient)& theClosed,
722                                                    Handle(TColStd_HSequenceOfTransient)& theOpen )
723 {
724   // set error code, check parameters
725   SetErrorCode(KO);
726
727   if ( theObject.IsNull() || theClosed.IsNull() || theOpen.IsNull() )
728     return false;
729
730   TopoDS_Shape aShape = theObject->GetValue();
731   if ( aShape.IsNull() )
732     return false;
733
734   // get free boundary shapes
735   ShapeAnalysis_FreeBounds anAnalizer( aShape );
736   TopoDS_Compound aClosed = anAnalizer.GetClosedWires();
737   TopoDS_Compound anOpen = anAnalizer.GetOpenWires();
738
739   // iterate through shapes and append them to the return sequence
740   Handle(GEOM_Object) anObj;
741   Handle(GEOM_Function) aFunction;
742   TopExp_Explorer anExp;
743   for ( anExp.Init( aClosed, TopAbs_WIRE ); anExp.More(); anExp.Next() )
744   {
745     anObj = GetEngine()->AddObject( GetDocID(), GEOM_FREE_BOUNDS );
746     aFunction = anObj->AddFunction( GEOMImpl_CopyDriver::GetID(), COPY_WITHOUT_REF );
747     TopoDS_Shape aValueShape = anExp.Current();
748     aFunction->SetValue( aValueShape );
749     theClosed->Append(anObj);
750   }
751   for ( anExp.Init( anOpen, TopAbs_WIRE ); anExp.More(); anExp.Next() )
752   {
753     anObj = GetEngine()->AddObject( GetDocID(), GEOM_FREE_BOUNDS );
754     aFunction = anObj->AddFunction( GEOMImpl_CopyDriver::GetID(), COPY_WITHOUT_REF );
755     TopoDS_Shape aValueShape = anExp.Current();
756     aFunction->SetValue( aValueShape );
757     theOpen->Append(anObj);
758   }
759
760   if(!aFunction.IsNull()) {
761
762     //Make a Python command
763     GEOM::TPythonDump pd (aFunction);
764
765     Standard_Integer i, aLen = theClosed->Length();
766     if (aLen > 0) {
767       pd << "(isDone, [";
768       for (i = 1; i <= aLen; i++) {
769         Handle(GEOM_Object) anObj_i = Handle(GEOM_Object)::DownCast(theClosed->Value(i));
770         pd << anObj_i << ((i < aLen) ? ", " : "");
771       }
772       pd << "], ";
773     } else {
774       pd << "(isDone, empty_list, ";
775     }
776
777     aLen = theOpen->Length();
778     if (aLen > 0) {
779       pd << "[";
780       for (i = 1; i <= aLen; i++) {
781         Handle(GEOM_Object) anObj_i = Handle(GEOM_Object)::DownCast(theOpen->Value(i));
782         pd << anObj_i << ((i < aLen) ? ", " : "");
783       }
784       pd << "]";
785     } else {
786       pd << "empty_list";
787     }
788
789     pd << ") = geompy.GetFreeBoundary(" << theObject << ")";
790   }
791
792   SetErrorCode(OK);
793   return true;
794 }
795
796
797 //=============================================================================
798 /*!
799  *  ChangeOrientation
800  */
801 //=============================================================================
802 Handle(GEOM_Object) GEOMImpl_IHealingOperations::ChangeOrientation (Handle(GEOM_Object) theObject)
803 {
804   // set error code, check parameters
805   SetErrorCode(KO);
806
807   if (theObject.IsNull())
808     return NULL;
809
810   if (!theObject->IsMainShape()) {
811     SetErrorCode("Sub shape cannot be transformed - need to create a copy");
812     return NULL;
813   }
814
815   Handle(GEOM_Function) aFunction, aLastFunction = theObject->GetLastFunction();
816   if (aLastFunction.IsNull()) 
817     return NULL; //There is no function which creates an object to be processed
818
819   //Add the function
820   aFunction = theObject->AddFunction(GEOMImpl_HealingDriver::GetID(), CHANGE_ORIENTATION);
821
822   if (aFunction.IsNull())
823     return NULL;
824
825   //Check if the function is set correctly
826   if (aFunction->GetDriverGUID() != GEOMImpl_HealingDriver::GetID()) return NULL;
827
828   // prepare "data container" class IHealing
829   GEOMImpl_IHealing HI(aFunction);
830   HI.SetOriginal( aLastFunction );
831
832   //Compute the translation
833   try {
834 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
835     OCC_CATCH_SIGNALS;
836 #endif
837     if (!GetSolver()->ComputeFunction(aFunction)) {
838       SetErrorCode("Healing driver failed");
839       return NULL;
840     }
841   }
842   catch (Standard_Failure) {
843     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
844     SetErrorCode(aFail->GetMessageString());
845     return NULL;
846   }
847
848   //Make a Python command
849   GEOM::TPythonDump(aFunction) << "geompy.ChangeOrientationShell("
850                                << theObject << ")";
851
852   SetErrorCode(OK);
853   return theObject;
854 }
855
856
857 //=============================================================================
858 /*!
859  *  ChangeOrientationCopy
860  */
861 //=============================================================================
862 Handle(GEOM_Object) GEOMImpl_IHealingOperations::ChangeOrientationCopy (Handle(GEOM_Object) theObject)
863 {
864   // set error code, check parameters
865   SetErrorCode(KO);
866
867   if (theObject.IsNull())
868     return NULL;
869
870   Handle(GEOM_Function) aFunction, aLastFunction = theObject->GetLastFunction();
871   if (aLastFunction.IsNull())
872     return NULL; //There is no function which creates an object to be processed
873
874   // Add a new object
875   Handle(GEOM_Object) aNewObject = GetEngine()->AddObject( GetDocID(), GEOM_COPY );
876
877   //Add the function
878   aFunction = aNewObject->AddFunction(GEOMImpl_HealingDriver::GetID(), CHANGE_ORIENTATION);
879
880   if (aFunction.IsNull())
881     return NULL;
882
883   //Check if the function is set correctly
884   if (aFunction->GetDriverGUID() != GEOMImpl_HealingDriver::GetID()) return NULL;
885
886   // prepare "data container" class IHealing
887   GEOMImpl_IHealing HI(aFunction);
888   HI.SetOriginal( aLastFunction );
889
890   //Compute the translation
891   try {
892 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
893     OCC_CATCH_SIGNALS;
894 #endif
895     if (!GetSolver()->ComputeFunction(aFunction)) {
896       SetErrorCode("Healing driver failed");
897       return NULL;
898     }
899   }
900   catch (Standard_Failure) {
901     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
902     SetErrorCode(aFail->GetMessageString());
903     return NULL;
904   }
905
906   //Make a Python command
907   GEOM::TPythonDump(aFunction) << aNewObject << " = geompy.ChangeOrientationShellCopy("
908                                << theObject << ")";
909
910   SetErrorCode(OK);
911   return aNewObject;
912 }
913