]> SALOME platform Git repositories - modules/geom.git/blob - src/GEOMImpl/GEOMImpl_ShapeDriver.cxx
Salome HOME
Join modifications from branch BR_DEBUG_3_2_0b1
[modules/geom.git] / src / GEOMImpl / GEOMImpl_ShapeDriver.cxx
1 // Copyright (C) 2005  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
2 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
3 // 
4 // This library is free software; you can redistribute it and/or
5 // modify it under the terms of the GNU Lesser General Public
6 // License as published by the Free Software Foundation; either 
7 // version 2.1 of the License.
8 // 
9 // This library is distributed in the hope that it will be useful 
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
12 // Lesser General Public License for more details.
13 //
14 // You should have received a copy of the GNU Lesser General Public  
15 // License along with this library; if not, write to the Free Software 
16 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
17 //
18 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
19 //
20
21 #include <Standard_Stream.hxx>
22
23 #include <GEOMImpl_ShapeDriver.hxx>
24 #include <GEOMImpl_IShapes.hxx>
25 #include <GEOMImpl_IShapesOperations.hxx>
26 #include <GEOMImpl_Types.hxx>
27 #include <GEOMImpl_Block6Explorer.hxx>
28
29 #include <GEOM_Function.hxx>
30
31 // OCCT Includes
32 #include <ShapeFix_Wire.hxx>
33
34 #include <BRep_Tool.hxx>
35 #include <BRep_Builder.hxx>
36 #include <BRepAlgo_FaceRestrictor.hxx>
37 #include <BRepBuilderAPI_Sewing.hxx>
38 #include <BRepBuilderAPI_Copy.hxx>
39 #include <BRepTools_Quilt.hxx>
40 #include <BRepCheck.hxx>
41 #include <BRepCheck_Analyzer.hxx>
42 #include <BRepCheck_Shell.hxx>
43 #include <BRepClass3d_SolidClassifier.hxx>
44 #include <BRepBuilderAPI_MakeWire.hxx>
45
46 #include <TopAbs.hxx>
47 #include <TopoDS.hxx>
48 #include <TopoDS_Shape.hxx>
49 #include <TopoDS_Edge.hxx>
50 #include <TopoDS_Wire.hxx>
51 #include <TopoDS_Solid.hxx>
52 #include <TopoDS_Compound.hxx>
53 #include <TopoDS_Iterator.hxx>
54 #include <TopExp_Explorer.hxx>
55 #include <TopTools_MapOfShape.hxx>
56 #include <TopTools_SequenceOfShape.hxx>
57 #include <TopTools_ListIteratorOfListOfShape.hxx>
58
59 #include <Precision.hxx>
60 #include <Standard_NullObject.hxx>
61 #include <Standard_TypeMismatch.hxx>
62 #include <Standard_ConstructionError.hxx>
63
64 //=======================================================================
65 //function : GetID
66 //purpose  :
67 //=======================================================================
68 const Standard_GUID& GEOMImpl_ShapeDriver::GetID()
69 {
70   static Standard_GUID aShapeDriver("FF1BBB54-5D14-4df2-980B-3A668264EA16");
71   return aShapeDriver;
72 }
73
74
75 //=======================================================================
76 //function : GEOMImpl_ShapeDriver
77 //purpose  :
78 //=======================================================================
79 GEOMImpl_ShapeDriver::GEOMImpl_ShapeDriver()
80 {
81 }
82
83 //=======================================================================
84 //function : Execute
85 //purpose  :
86 //=======================================================================
87 Standard_Integer GEOMImpl_ShapeDriver::Execute(TFunction_Logbook& log) const
88 {
89   if (Label().IsNull()) return 0;
90   Handle(GEOM_Function) aFunction = GEOM_Function::GetFunction(Label());
91
92   GEOMImpl_IShapes aCI (aFunction);
93   Standard_Integer aType = aFunction->GetType();
94
95   TopoDS_Shape aShape;
96   BRep_Builder B;
97
98   if (aType == WIRE_EDGES) {
99     Handle(TColStd_HSequenceOfTransient) aShapes = aCI.GetShapes();
100     unsigned int ind, nbshapes = aShapes->Length();
101
102     TopoDS_Wire aWire;
103     B.MakeWire(aWire);
104     BRepBuilderAPI_MakeWire MW;
105     bool isMWDone = true;
106
107     // add edges
108     for (ind = 1; ind <= nbshapes; ind++) {
109       Handle(GEOM_Function) aRefShape = Handle(GEOM_Function)::DownCast(aShapes->Value(ind));
110       TopoDS_Shape aShape_i = aRefShape->GetValue();
111       if (aShape_i.IsNull()) {
112         Standard_NullObject::Raise("Shape for wire construction is null");
113       }
114       if (aShape_i.ShapeType() == TopAbs_EDGE) {
115         B.Add(aWire, TopoDS::Edge(aShape_i));
116         MW.Add(TopoDS::Edge(aShape_i));
117       } else if (aShape_i.ShapeType() == TopAbs_WIRE) {
118         B.Add(aWire, TopoDS::Wire(aShape_i));
119         MW.Add(TopoDS::Wire(aShape_i));
120       } else {
121         Standard_TypeMismatch::Raise
122           ("Shape for wire construction is neither an edge nor a wire");
123       }
124       if (!MW.IsDone()) {
125         // check status after each edge/wire addition, because the final status
126         // can be OK even in case, when some edges/wires was not accepted.
127         isMWDone = false;
128       }
129     }
130
131     if (isMWDone) {
132       aShape = MW;
133     } else {
134       // fix edges order
135       Handle(ShapeFix_Wire) aFW = new ShapeFix_Wire;
136       aFW->Load(aWire);
137       aFW->FixReorder();
138
139       if (aFW->StatusReorder(ShapeExtend_FAIL1)) {
140         Standard_ConstructionError::Raise("Wire construction failed: several loops detected");
141       } else if (aFW->StatusReorder(ShapeExtend_FAIL)) {
142         Standard_ConstructionError::Raise("Wire construction failed");
143       } else if (aFW->StatusReorder(ShapeExtend_DONE2)) {
144         Standard_ConstructionError::Raise("Wire construction failed: some gaps detected");
145       } else {
146       }
147       aShape = aFW->WireAPIMake();
148     }
149
150   } else if (aType == FACE_WIRE) {
151     Handle(GEOM_Function) aRefBase = aCI.GetBase();
152     TopoDS_Shape aShapeBase = aRefBase->GetValue();
153     if (aShapeBase.IsNull() || aShapeBase.ShapeType() != TopAbs_WIRE) {
154       Standard_NullObject::Raise
155         ("Shape for face construction is null or not a wire");
156     }
157     TopoDS_Wire W = TopoDS::Wire(aShapeBase);
158     //BRepBuilderAPI_MakeFace MF (W, aCI.GetIsPlanar());
159     //if (!MF.IsDone()) {
160     //  Standard_ConstructionError::Raise("Face construction failed");
161     //}
162     //aShape = MF.Shape();
163     GEOMImpl_Block6Explorer::MakeFace(W, aCI.GetIsPlanar(), aShape);
164     if (aShape.IsNull()) {
165       Standard_ConstructionError::Raise("Face construction failed");
166     }
167
168   } else if (aType == FACE_WIRES) {
169     Handle(TColStd_HSequenceOfTransient) aShapes = aCI.GetShapes();
170     int nbshapes = aShapes->Length();
171     if (nbshapes < 1) {
172       Standard_ConstructionError::Raise("No wires given");
173     }
174
175     // first wire
176     Handle(GEOM_Function) aRefWire = Handle(GEOM_Function)::DownCast(aShapes->Value(1));
177     TopoDS_Shape aWire = aRefWire->GetValue();
178     if (aWire.IsNull() || aWire.ShapeType() != TopAbs_WIRE) {
179       Standard_NullObject::Raise("Shape for face construction is null or not a wire");
180     }
181     TopoDS_Wire W = TopoDS::Wire(aWire);
182
183     // basic face
184     //BRepBuilderAPI_MakeFace MF (W, aCI.GetIsPlanar());
185     //if (!MF.IsDone()) {
186     //  Standard_ConstructionError::Raise("Face construction failed");
187     //}
188     //TopoDS_Shape FFace = MF.Shape();
189     TopoDS_Shape FFace;
190     GEOMImpl_Block6Explorer::MakeFace(W, aCI.GetIsPlanar(), FFace);
191     if (FFace.IsNull()) {
192       Standard_ConstructionError::Raise("Face construction failed");
193     }
194
195     if (nbshapes == 1) {
196       aShape = FFace;
197
198     } else {
199       TopoDS_Compound C;
200       BRep_Builder aBuilder;
201       aBuilder.MakeCompound(C);
202       BRepAlgo_FaceRestrictor FR;
203
204       TopAbs_Orientation OriF = FFace.Orientation();
205       TopoDS_Shape aLocalS = FFace.Oriented(TopAbs_FORWARD);
206       FR.Init(TopoDS::Face(aLocalS), Standard_False, Standard_True);
207
208       for (int ind = 1; ind <= nbshapes; ind++) {
209         Handle(GEOM_Function) aRefWire_i =
210           Handle(GEOM_Function)::DownCast(aShapes->Value(ind));
211         TopoDS_Shape aWire_i = aRefWire_i->GetValue();
212         if (aWire_i.IsNull() || aWire_i.ShapeType() != TopAbs_WIRE) {
213           Standard_NullObject::Raise("Shape for face construction is null or not a wire");
214         }
215
216         FR.Add(TopoDS::Wire(aWire_i));
217       }
218
219       FR.Perform();
220
221       if (FR.IsDone()) {
222         int k = 0;
223         TopoDS_Shape aFace;
224         for (; FR.More(); FR.Next()) {
225           aFace = FR.Current().Oriented(OriF);
226           aBuilder.Add(C, aFace);
227           k++;
228         }
229         if (k == 1) {
230           aShape = aFace;
231         } else {
232           aShape = C;
233         }
234       }
235     }
236   } else if (aType == SHELL_FACES) {
237     Handle(TColStd_HSequenceOfTransient) aShapes = aCI.GetShapes();
238     unsigned int ind, nbshapes = aShapes->Length();
239
240     // add faces
241     BRepBuilderAPI_Sewing aSewing(Precision::Confusion()*10.0);
242     for (ind = 1; ind <= nbshapes; ind++) {
243       Handle(GEOM_Function) aRefShape = Handle(GEOM_Function)::DownCast(aShapes->Value(ind));
244       TopoDS_Shape aShape_i = aRefShape->GetValue();
245       if (aShape_i.IsNull()) {
246         Standard_NullObject::Raise("Face for shell construction is null");
247       }
248       aSewing.Add(aShape_i);
249     }
250
251     aSewing.Perform();
252
253     TopExp_Explorer exp (aSewing.SewedShape(), TopAbs_SHELL);
254     Standard_Integer ish = 0;
255     for (; exp.More(); exp.Next()) {
256       aShape = exp.Current();
257       ish++;
258     }
259
260     if (ish != 1)
261       aShape = aSewing.SewedShape();
262
263   } else if (aType == SOLID_SHELL) {
264     Handle(GEOM_Function) aRefShell = aCI.GetBase();
265     TopoDS_Shape aShapeShell = aRefShell->GetValue();
266     if (aShapeShell.IsNull() || aShapeShell.ShapeType() != TopAbs_SHELL) {
267       Standard_NullObject::Raise("Shape for solid construction is null or not a shell");
268     }
269
270     BRepCheck_Shell chkShell(TopoDS::Shell(aShapeShell));
271     if(chkShell.Closed() == BRepCheck_NotClosed) return 0;
272
273     TopoDS_Solid Sol;
274     B.MakeSolid(Sol);
275     B.Add(Sol, aShapeShell);
276     BRepClass3d_SolidClassifier SC (Sol);
277     SC.PerformInfinitePoint(Precision::Confusion());
278     if (SC.State() == TopAbs_IN) {
279       B.MakeSolid(Sol);
280       B.Add(Sol, aShapeShell.Reversed());
281     }
282
283     aShape = Sol;
284
285   } else if (aType == SOLID_SHELLS) {
286     Handle(TColStd_HSequenceOfTransient) aShapes = aCI.GetShapes();
287     unsigned int ind, nbshapes = aShapes->Length();
288     Standard_Integer ish = 0;
289     TopoDS_Solid Sol;
290     B.MakeSolid(Sol);
291
292     // add shapes
293     for (ind = 1; ind <= nbshapes; ind++) {
294       Handle(GEOM_Function) aRefShape = Handle(GEOM_Function)::DownCast(aShapes->Value(ind));
295       TopoDS_Shape aShapeShell = aRefShape->GetValue();
296       if (aShapeShell.IsNull()) {
297         Standard_NullObject::Raise("Shell for solid construction is null");
298       }
299       if (aShapeShell.ShapeType() == TopAbs_SHELL) {
300         B.Add(Sol, aShapeShell);
301         ish++;
302       }
303     }
304     if ( ish == 0 ) return 0;
305     BRepClass3d_SolidClassifier SC (Sol);
306     SC.PerformInfinitePoint(Precision::Confusion());
307     switch (SC.State()) {
308     case TopAbs_IN:
309       aShape = Sol.Reversed(); break;
310     case TopAbs_OUT:
311       aShape = Sol; break;
312     default: // not closed shell?
313       return 0;
314     }
315
316   } else if (aType == COMPOUND_SHAPES) {
317     Handle(TColStd_HSequenceOfTransient) aShapes = aCI.GetShapes();
318     unsigned int ind, nbshapes = aShapes->Length();
319
320     // add shapes
321     TopoDS_Compound C;
322     B.MakeCompound(C);
323     for (ind = 1; ind <= nbshapes; ind++) {
324       Handle(GEOM_Function) aRefShape = Handle(GEOM_Function)::DownCast(aShapes->Value(ind));
325       TopoDS_Shape aShape_i = aRefShape->GetValue();
326       if (aShape_i.IsNull()) {
327         Standard_NullObject::Raise("Shape for compound construction is null");
328       }
329       B.Add(C, aShape_i);
330     }
331
332     aShape = C;
333
334   } else if (aType == REVERSE_ORIENTATION) {
335     Handle(GEOM_Function) aRefShape = aCI.GetBase();
336     TopoDS_Shape aShape_i = aRefShape->GetValue();
337     if (aShape_i.IsNull()) {
338        Standard_NullObject::Raise("Shape for reverse is null");
339     }
340
341     BRepBuilderAPI_Copy Copy(aShape_i);
342     if( Copy.IsDone() ) {
343       TopoDS_Shape tds = Copy.Shape();
344       if( tds.IsNull() ) {
345         Standard_ConstructionError::Raise("Orientation aborted : Can not reverse the shape");
346       }
347
348       if( tds.Orientation() == TopAbs_FORWARD)
349         tds.Orientation(TopAbs_REVERSED) ;
350       else
351         tds.Orientation(TopAbs_FORWARD) ;
352
353       aShape = tds;
354     }
355   }
356
357   if (aShape.IsNull()) return 0;
358
359   // Check shape validity
360   BRepCheck_Analyzer ana (aShape, false);
361   if (!ana.IsValid()) {
362     Standard_ConstructionError::Raise("Algorithm have produced an invalid shape result");
363   }
364
365   aFunction->SetValue(aShape);
366
367   log.SetTouched(Label());
368
369   return 1;
370 }
371
372
373 //=======================================================================
374 //function :  GEOMImpl_ShapeDriver_Type_
375 //purpose  :
376 //=======================================================================
377 Standard_EXPORT Handle_Standard_Type& GEOMImpl_ShapeDriver_Type_()
378 {
379
380   static Handle_Standard_Type aType1 = STANDARD_TYPE(TFunction_Driver);
381   if ( aType1.IsNull()) aType1 = STANDARD_TYPE(TFunction_Driver);
382   static Handle_Standard_Type aType2 = STANDARD_TYPE(MMgt_TShared);
383   if ( aType2.IsNull()) aType2 = STANDARD_TYPE(MMgt_TShared);
384   static Handle_Standard_Type aType3 = STANDARD_TYPE(Standard_Transient);
385   if ( aType3.IsNull()) aType3 = STANDARD_TYPE(Standard_Transient);
386
387
388   static Handle_Standard_Transient _Ancestors[]= {aType1,aType2,aType3,NULL};
389   static Handle_Standard_Type _aType = new Standard_Type("GEOMImpl_ShapeDriver",
390                                                          sizeof(GEOMImpl_ShapeDriver),
391                                                          1,
392                                                          (Standard_Address)_Ancestors,
393                                                          (Standard_Address)NULL);
394
395   return _aType;
396 }
397
398 //=======================================================================
399 //function : DownCast
400 //purpose  :
401 //=======================================================================
402 const Handle(GEOMImpl_ShapeDriver) Handle(GEOMImpl_ShapeDriver)::DownCast(const Handle(Standard_Transient)& AnObject)
403 {
404   Handle(GEOMImpl_ShapeDriver) _anOtherObject;
405
406   if (!AnObject.IsNull()) {
407      if (AnObject->IsKind(STANDARD_TYPE(GEOMImpl_ShapeDriver))) {
408        _anOtherObject = Handle(GEOMImpl_ShapeDriver)((Handle(GEOMImpl_ShapeDriver)&)AnObject);
409      }
410   }
411
412   return _anOtherObject ;
413 }