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