Salome HOME
IMP 0021064: correct implementation
[modules/geom.git] / src / GEOMImpl / GEOMImpl_HealingDriver.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 #include <Standard_Stream.hxx>
23
24 #include <GEOMImpl_HealingDriver.hxx>
25 #include <GEOMImpl_Types.hxx>
26 #include <GEOMImpl_IHealing.hxx>
27 #include <GEOM_Function.hxx>
28
29 #include <GEOMImpl_GlueDriver.hxx>
30
31 #include <ShHealOper_ShapeProcess.hxx>
32 #include <ShHealOper_RemoveFace.hxx>
33 #include <ShHealOper_CloseContour.hxx>
34 #include <ShHealOper_RemoveInternalWires.hxx>
35 #include <ShHealOper_FillHoles.hxx>
36 #include <ShHealOper_Sewing.hxx>
37 #include <ShHealOper_EdgeDivide.hxx>
38 #include <ShHealOper_ChangeOrientation.hxx>
39
40 #include <BRep_Builder.hxx>
41
42 #include <TopExp.hxx>
43 #include <TopoDS.hxx>
44 #include <TopoDS_Iterator.hxx>
45 #include <TopTools_IndexedMapOfShape.hxx>
46
47 #include <TColStd_IndexedDataMapOfTransientTransient.hxx>
48 #include <TNaming_CopyShape.hxx>
49 #include <ShapeFix_ShapeTolerance.hxx>
50 #include <ShapeFix_Shape.hxx>
51 #include <BRepCheck_Analyzer.hxx>
52
53 #include <Precision.hxx>
54
55 #include <StdFail_NotDone.hxx>
56
57 //=======================================================================
58 //function :  raiseNotDoneExeption
59 //purpose  :  global function: forms error message and raises exeption
60 //=======================================================================
61 void raiseNotDoneExeption( const int theErrorStatus )
62 {
63   switch ( theErrorStatus )
64   {
65   case ShHealOper_NotError:           StdFail_NotDone::Raise( "ShHealOper_NotError_msg" );
66   case ShHealOper_InvalidParameters:  StdFail_NotDone::Raise( "ShHealOper_InvalidParameters_msg" );
67   case ShHealOper_ErrorExecution:
68   default:                            StdFail_NotDone::Raise( "ShHealOper_ErrorExecution_msg" );
69   }
70 }
71
72 //=======================================================================
73 //function : GetID
74 //purpose  :
75 //=======================================================================
76 const Standard_GUID& GEOMImpl_HealingDriver::GetID()
77 {
78   static Standard_GUID aHealingDriver("FF1BBB61-5D14-4df2-980B-3A668264EA16");
79   return aHealingDriver;
80 }
81
82 //=======================================================================
83 //function : GEOMImpl_HealingDriver
84 //purpose  :
85 //=======================================================================
86 GEOMImpl_HealingDriver::GEOMImpl_HealingDriver()
87 {
88 }
89
90 //=======================================================================
91 //function : Execute
92 //purpose  :
93 //=======================================================================
94 Standard_Integer GEOMImpl_HealingDriver::Execute(TFunction_Logbook& log) const
95 {
96   if (Label().IsNull()) return 0;
97   Handle(GEOM_Function) aFunction = GEOM_Function::GetFunction(Label());
98
99   if (aFunction.IsNull()) return 0;
100
101   GEOMImpl_IHealing HI (aFunction);
102   Standard_Integer aType = aFunction->GetType();
103   Handle(GEOM_Function) anOriginalFunction = HI.GetOriginal();
104   if (anOriginalFunction.IsNull()) return 0;
105   TopoDS_Shape aShape, anOriginalShape = anOriginalFunction->GetValue();
106   if (anOriginalShape.IsNull()) return 0;
107
108   switch (aType)
109   {
110   case SHAPE_PROCESS:
111     ShapeProcess(&HI, anOriginalShape, aShape);
112     break;
113   case SUPPRESS_FACES:
114     SuppressFaces(&HI, anOriginalShape, aShape);
115     break;
116   case CLOSE_CONTOUR:
117     CloseContour(&HI, anOriginalShape, aShape);
118     break;
119   case REMOVE_INT_WIRES:
120     RemoveIntWires(&HI, anOriginalShape, aShape);
121     break;
122   case FILL_HOLES:
123     RemoveHoles(&HI, anOriginalShape, aShape);
124     break;
125   case SEWING:
126     Sew(&HI, anOriginalShape, aShape);
127     break;
128   case DIVIDE_EDGE:
129     AddPointOnEdge(&HI, anOriginalShape, aShape);
130     break;
131   case CHANGE_ORIENTATION:
132     ChangeOrientation(&HI, anOriginalShape, aShape);
133     break;
134   case LIMIT_TOLERANCE:
135     LimitTolerance(&HI, anOriginalShape, aShape);
136     break;
137   default:
138     return 0;
139   }
140
141   if (aShape.IsNull())
142     raiseNotDoneExeption( ShHealOper_ErrorExecution );
143
144   aFunction->SetValue(aShape);
145
146   log.SetTouched(Label());
147   return 1;
148 }
149
150 //=======================================================================
151 //function :  ShapeProcess
152 //purpose  :
153 //=======================================================================
154 Standard_Boolean GEOMImpl_HealingDriver::ShapeProcess (GEOMImpl_IHealing* theHI,
155                                                        const TopoDS_Shape& theOriginalShape,
156                                                        TopoDS_Shape& theOutShape) const
157 {
158   Handle(TColStd_HArray1OfExtendedString) anOperators = theHI->GetOperators();
159   Handle(TColStd_HArray1OfExtendedString) aParams = theHI->GetParameters();
160   Handle(TColStd_HArray1OfExtendedString) aValues = theHI->GetValues();
161
162   if (anOperators.IsNull() || anOperators->Length() <= 0)
163     return Standard_False;
164
165   Standard_Integer nbParams = 0, nbValues = 0;
166   if (!aParams.IsNull()) {
167     nbParams = aParams->Length();
168   }
169   if (!aValues.IsNull()) {
170     nbValues = aValues->Length();
171   }
172   if (nbParams != nbValues)
173     return Standard_False;
174
175   ShHealOper_ShapeProcess aHealer;
176   TColStd_SequenceOfAsciiString anOperatorsAS, aParamsAS, aValuesAS;
177   int i;
178   for (i = 1; i <= anOperators->Length(); i++)
179     anOperatorsAS.Append(TCollection_AsciiString(anOperators->Value(i)));
180
181   aHealer.SetOperators(anOperatorsAS);
182
183   for (i = 1; i <= nbParams; i++) {
184     aHealer.SetParameter(TCollection_AsciiString(aParams->Value(i)),
185                          TCollection_AsciiString(aValues->Value(i)));
186   }
187
188   aHealer.Perform(theOriginalShape, theOutShape);
189
190   if (!aHealer.isDone())
191     raiseNotDoneExeption( ShHealOper_NotError );
192
193   return Standard_True;
194 }
195
196 //=======================================================================
197 //function :  SupressFaces
198 //purpose  :
199 //=======================================================================
200 void SuppressFacesRec (const TopTools_SequenceOfShape& theShapesFaces,
201                        const TopoDS_Shape&             theOriginalShape,
202                        TopoDS_Shape&                   theOutShape)
203 {
204   if ((theOriginalShape.ShapeType() != TopAbs_COMPOUND &&
205        theOriginalShape.ShapeType() != TopAbs_COMPSOLID))
206   {
207     ShHealOper_RemoveFace aHealer (theOriginalShape);
208     Standard_Boolean aResult = aHealer.Perform(theShapesFaces);
209
210     if (aResult)
211       theOutShape = aHealer.GetResultShape();
212     else
213       raiseNotDoneExeption(aHealer.GetErrorStatus());
214   }
215   else
216   {
217     BRep_Builder BB;
218     TopoDS_Compound CC;
219     BB.MakeCompound(CC);
220
221     TopTools_MapOfShape mapShape;
222     TopoDS_Iterator It (theOriginalShape, Standard_True, Standard_True);
223
224     for (; It.More(); It.Next()) {
225       TopoDS_Shape aShape_i = It.Value();
226       if (mapShape.Add(aShape_i)) {
227         // check, if current shape contains at least one of faces to be removed
228         bool isFound = false;
229         TopTools_IndexedMapOfShape aShapes_i;
230         TopExp::MapShapes(aShape_i, aShapes_i);
231         for (int i = 1; i <= theShapesFaces.Length() && !isFound; i++) {
232           const TopoDS_Shape& aFace_i = theShapesFaces.Value(i);
233           if (aShapes_i.Contains(aFace_i)) isFound = true;
234         }
235         if (isFound) {
236           TopoDS_Shape anOutSh_i;
237           SuppressFacesRec(theShapesFaces, aShape_i, anOutSh_i);
238           if ( !anOutSh_i.IsNull() )
239             BB.Add(CC, anOutSh_i);
240         }
241         else {
242           // nothing to do
243           BB.Add(CC, aShape_i);
244         }
245       }
246     }
247     theOutShape = CC;
248   }
249 }
250
251 Standard_Boolean GEOMImpl_HealingDriver::SuppressFaces (GEOMImpl_IHealing* theHI,
252                                                         const TopoDS_Shape& theOriginalShape,
253                                                         TopoDS_Shape& theOutShape) const
254 {
255   Handle(TColStd_HArray1OfInteger) aFaces = theHI->GetFaces();
256
257   Standard_Boolean aResult = Standard_False;
258
259   if (aFaces.IsNull()) {
260     ShHealOper_RemoveFace aHealer (theOriginalShape);
261     aResult = aHealer.Perform();
262
263     if (aResult)
264       theOutShape = aHealer.GetResultShape();
265     else
266       raiseNotDoneExeption(aHealer.GetErrorStatus());
267   }
268   else {
269     TopTools_SequenceOfShape aShapesFaces;
270     TopTools_IndexedMapOfShape aShapes;
271     TopExp::MapShapes(theOriginalShape, aShapes);
272     for (int i = 1; i <= aFaces->Length(); i++) {
273       int indexOfFace = aFaces->Value(i);
274       TopoDS_Shape aFace = aShapes.FindKey(indexOfFace);
275       aShapesFaces.Append(aFace);
276     }
277     SuppressFacesRec(aShapesFaces, theOriginalShape, theOutShape);
278     if ((theOriginalShape.ShapeType() == TopAbs_COMPOUND ||
279          theOriginalShape.ShapeType() == TopAbs_COMPSOLID)) {
280       TopoDS_Shape aSh = theOutShape;
281       theOutShape = GEOMImpl_GlueDriver::GlueFaces(aSh, Precision::Confusion(), Standard_True);
282     }
283   }
284
285   return Standard_True;
286 }
287
288 //=======================================================================
289 //function :  CloseContour
290 //purpose  :
291 //=======================================================================
292 Standard_Boolean GEOMImpl_HealingDriver::CloseContour (GEOMImpl_IHealing* theHI,
293                                                        const TopoDS_Shape& theOriginalShape,
294                                                        TopoDS_Shape& theOutShape) const
295 {
296   Standard_Boolean isByVertex = theHI->GetIsCommonVertex();
297   Handle(TColStd_HArray1OfInteger) aWires = theHI->GetWires();
298
299   ShHealOper_CloseContour aHealer (theOriginalShape);
300
301   Standard_Boolean aResult = Standard_False;
302   if ( aWires.IsNull() ) {
303     if ( theOriginalShape.ShapeType() == TopAbs_WIRE )
304       aResult = aHealer.Perform(TopoDS::Wire(theOriginalShape), isByVertex, !isByVertex);
305   }
306   else {
307     TopTools_SequenceOfShape aShapesWires;
308     TopTools_IndexedMapOfShape aShapes;
309     TopExp::MapShapes(theOriginalShape, aShapes);
310     for (int i = 1; i <= aWires->Length(); i++) {
311       int indexOfWire = aWires->Value(i);
312       TopoDS_Shape aWire = aShapes.FindKey(indexOfWire);
313       aShapesWires.Append(aWire);
314     }
315
316     aResult = aHealer.Perform( aShapesWires, isByVertex, !isByVertex );
317   }
318
319   if (aResult)
320     theOutShape = aHealer.GetResultShape();
321   else
322     raiseNotDoneExeption( aHealer.GetErrorStatus() );
323
324   return aResult;
325 }
326
327 //=======================================================================
328 //function :  RemoveIntWires
329 //purpose  :
330 //=======================================================================
331 Standard_Boolean GEOMImpl_HealingDriver::RemoveIntWires (GEOMImpl_IHealing* theHI,
332                                                          const TopoDS_Shape& theOriginalShape,
333                                                          TopoDS_Shape& theOutShape) const
334 {
335   Handle(TColStd_HArray1OfInteger) aWires = theHI->GetWires();
336
337   ShHealOper_RemoveInternalWires aHealer(theOriginalShape);
338
339   Standard_Boolean aResult = Standard_False;
340   if (aWires.IsNull()) { // remove all faces
341     aResult = aHealer.Remove();
342   } else {
343     TopTools_SequenceOfShape aShapesWires;
344     TopTools_IndexedMapOfShape aShapes;
345     TopExp::MapShapes(theOriginalShape, aShapes);
346     for (int i = 1; i <= aWires->Length(); i++) {
347       int indexOfWire = aWires->Value(i);
348       TopoDS_Shape aWire = aShapes.FindKey(indexOfWire);
349       aShapesWires.Append(aWire);
350     }
351
352     aResult = aHealer.Remove(aShapesWires);
353   }
354
355   if (aResult)
356     theOutShape = aHealer.GetResultShape();
357   else
358     raiseNotDoneExeption( aHealer.GetErrorStatus() );
359
360   return aResult;
361 }
362
363 //=======================================================================
364 //function :  RemoveHoles
365 //purpose  :
366 //=======================================================================
367 Standard_Boolean GEOMImpl_HealingDriver::RemoveHoles (GEOMImpl_IHealing* theHI,
368                                                       const TopoDS_Shape& theOriginalShape,
369                                                       TopoDS_Shape& theOutShape) const
370 {
371   Handle(TColStd_HArray1OfInteger) aWires = theHI->GetWires();
372
373   ShHealOper_FillHoles aHealer (theOriginalShape);
374
375   Standard_Boolean aResult = Standard_False;
376   if (aWires.IsNull()) { // remove all faces
377     aResult = aHealer.Fill();
378   } else {
379     TopTools_SequenceOfShape aShapesWires;
380     TopTools_IndexedMapOfShape aShapes;
381     TopExp::MapShapes(theOriginalShape, aShapes);
382     for (int i = 1; i <= aWires->Length(); i++) {
383       int indexOfWire = aWires->Value(i);
384       TopoDS_Shape aWire = aShapes.FindKey(indexOfWire);
385       aShapesWires.Append(aWire);
386     }
387
388     aResult = aHealer.Fill(aShapesWires);
389   }
390
391   if (aResult)
392     theOutShape = aHealer.GetResultShape();
393   else
394     raiseNotDoneExeption( aHealer.GetErrorStatus() );
395
396   return aResult;
397 }
398
399 //=======================================================================
400 //function :  Sew
401 //purpose  :
402 //=======================================================================
403 Standard_Boolean GEOMImpl_HealingDriver::Sew (GEOMImpl_IHealing* theHI,
404                                               const TopoDS_Shape& theOriginalShape,
405                                               TopoDS_Shape& theOutShape) const
406 {
407   Standard_Real aTol = theHI->GetTolerance();
408
409   ShHealOper_Sewing aHealer (theOriginalShape, aTol);
410
411   Standard_Boolean aResult = aHealer.Perform();
412
413   if (aResult)
414     theOutShape = aHealer.GetResultShape();
415   else
416     raiseNotDoneExeption( aHealer.GetErrorStatus() );
417
418   return aResult;
419 }
420
421 //=======================================================================
422 //function :  AddPointOnEdge
423 //purpose  :
424 //=======================================================================
425 Standard_Boolean GEOMImpl_HealingDriver::AddPointOnEdge (GEOMImpl_IHealing* theHI,
426                                                          const TopoDS_Shape& theOriginalShape,
427                                                          TopoDS_Shape& theOutShape) const
428 {
429   Standard_Boolean isByParameter = theHI->GetIsByParameter();
430   Standard_Integer anIndex = theHI->GetIndex();
431   Standard_Real aValue = theHI->GetDevideEdgeValue();
432
433   ShHealOper_EdgeDivide aHealer (theOriginalShape);
434
435   Standard_Boolean aResult = Standard_False;
436   if (anIndex == -1) { // apply algorythm for the whole shape which is EDGE
437     if (theOriginalShape.ShapeType() == TopAbs_EDGE)
438       aResult = aHealer.Perform(TopoDS::Edge(theOriginalShape), aValue, isByParameter);
439   } else {
440     TopTools_IndexedMapOfShape aShapes;
441     TopExp::MapShapes(theOriginalShape, aShapes);
442     TopoDS_Shape aEdgeShape = aShapes.FindKey(anIndex);
443     if (aEdgeShape.ShapeType() == TopAbs_EDGE)
444       aResult = aHealer.Perform(TopoDS::Edge(aEdgeShape), aValue, isByParameter);
445   }
446
447   if (aResult)
448     theOutShape = aHealer.GetResultShape();
449   else
450     raiseNotDoneExeption( aHealer.GetErrorStatus() );
451
452   return aResult;
453 }
454
455
456 //=======================================================================
457 //function :  ChangeOrientation
458 //purpose  :
459 //=======================================================================
460 Standard_Boolean GEOMImpl_HealingDriver::ChangeOrientation (GEOMImpl_IHealing* theHI,
461                                                             const TopoDS_Shape& theOriginalShape,
462                                                             TopoDS_Shape& theOutShape) const
463 {
464   ShHealOper_ChangeOrientation aHealer (theOriginalShape);
465
466   Standard_Boolean aResult = aHealer.Perform();
467
468   if (aResult)
469     theOutShape = aHealer.GetResultShape();
470   else
471     raiseNotDoneExeption( aHealer.GetErrorStatus() );
472
473   return aResult;
474 }
475
476 //=======================================================================
477 //function : LimitTolerance
478 //purpose  :
479 //=======================================================================
480 void GEOMImpl_HealingDriver::LimitTolerance (GEOMImpl_IHealing* theHI,
481                                              const TopoDS_Shape& theOriginalShape,
482                                              TopoDS_Shape& theOutShape) const
483 {
484   Standard_Real aTol = theHI->GetTolerance();
485   if (aTol < Precision::Confusion())
486     aTol = Precision::Confusion();
487
488   // 1. Make a copy to prevent the original shape changes.
489   TopoDS_Shape aShapeCopy;
490   TColStd_IndexedDataMapOfTransientTransient aMapTShapes;
491   TNaming_CopyShape::CopyTool(theOriginalShape, aMapTShapes, aShapeCopy);
492
493   // 2. Limit tolerance.
494   ShapeFix_ShapeTolerance aSFT;
495   aSFT.LimitTolerance(aShapeCopy, aTol, aTol, TopAbs_SHAPE);
496
497   // 3. Fix obtained shape.
498   Handle(ShapeFix_Shape) aSfs = new ShapeFix_Shape (aShapeCopy);
499   aSfs->Perform();
500   theOutShape = aSfs->Shape();
501
502   BRepCheck_Analyzer ana (theOutShape, Standard_True);
503   if (!ana.IsValid())
504     StdFail_NotDone::Raise("Non valid shape result");
505 }
506
507 //=======================================================================
508 //function :  GEOMImpl_HealingDriver_Type_
509 //purpose  :
510 //=======================================================================
511 Standard_EXPORT Handle_Standard_Type& GEOMImpl_HealingDriver_Type_()
512 {
513
514   static Handle_Standard_Type aType1 = STANDARD_TYPE(TFunction_Driver);
515   if ( aType1.IsNull()) aType1 = STANDARD_TYPE(TFunction_Driver);
516   static Handle_Standard_Type aType2 = STANDARD_TYPE(MMgt_TShared);
517   if ( aType2.IsNull()) aType2 = STANDARD_TYPE(MMgt_TShared);
518   static Handle_Standard_Type aType3 = STANDARD_TYPE(Standard_Transient);
519   if ( aType3.IsNull()) aType3 = STANDARD_TYPE(Standard_Transient);
520
521
522   static Handle_Standard_Transient _Ancestors[]= {aType1,aType2,aType3,NULL};
523   static Handle_Standard_Type _aType = new Standard_Type("GEOMImpl_HealingDriver",
524                                                          sizeof(GEOMImpl_HealingDriver),
525                                                          1,
526                                                          (Standard_Address)_Ancestors,
527                                                          (Standard_Address)NULL);
528
529   return _aType;
530 }
531
532 //=======================================================================
533 //function : DownCast
534 //purpose  :
535 //=======================================================================
536
537 const Handle(GEOMImpl_HealingDriver) Handle(GEOMImpl_HealingDriver)::DownCast(const Handle(Standard_Transient)& AnObject)
538 {
539   Handle(GEOMImpl_HealingDriver) _anOtherObject;
540
541   if (!AnObject.IsNull()) {
542      if (AnObject->IsKind(STANDARD_TYPE(GEOMImpl_HealingDriver))) {
543        _anOtherObject = Handle(GEOMImpl_HealingDriver)((Handle(GEOMImpl_HealingDriver)&)AnObject);
544      }
545   }
546
547   return _anOtherObject;
548 }