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