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