]> SALOME platform Git repositories - modules/geom.git/blob - src/GEOMImpl/GEOMImpl_ShapeDriver.cxx
Salome HOME
784052cf25ebce9fdbfbe39dd644b668c9da0119
[modules/geom.git] / src / GEOMImpl / GEOMImpl_ShapeDriver.cxx
1
2 using namespace std;
3 #include "GEOMImpl_ShapeDriver.hxx"
4 #include "GEOMImpl_IShapes.hxx"
5 #include "GEOMImpl_IShapesOperations.hxx"
6 #include "GEOMImpl_Types.hxx"
7 #include "GEOM_Function.hxx"
8
9 #include <BRep_Tool.hxx>
10 #include <BRep_Builder.hxx>
11 #include <BRepAlgo_FaceRestrictor.hxx>
12
13 #include <Standard_Version.hxx>
14 #ifdef OCC_VERSION_MAINTENANCE 
15 #if (OCC_VERSION_MAJOR >= 5 && OCC_VERSION_MINOR >= 2 && OCC_VERSION_MAINTENANCE >= 4)
16 #include <BRepBuilderAPI_Sewing.hxx>
17 #define BRepAlgo_Sewing BRepBuilderAPI_Sewing
18 #else 
19 #include <BRepAlgo_Sewing.hxx>
20 #endif 
21 #else 
22 #include <BRepAlgo_Sewing.hxx>
23 #endif 
24
25 #include <BRepBuilderAPI_Copy.hxx>
26 #include <BRepTools_Quilt.hxx>
27 #include <BRepCheck.hxx>
28 #include <BRepCheck_Analyzer.hxx>
29 #include <BRepCheck_Shell.hxx>
30 #include <BRepClass3d_SolidClassifier.hxx>
31 #include <BRepBuilderAPI_MakeWire.hxx>
32 #include <BRepBuilderAPI_MakeFace.hxx>
33
34 #include <TopAbs.hxx>
35 #include <TopoDS.hxx>
36 #include <TopoDS_Shape.hxx>
37 #include <TopoDS_Edge.hxx>
38 #include <TopoDS_Wire.hxx>
39 #include <TopoDS_Solid.hxx>
40 #include <TopoDS_Compound.hxx>
41 #include <TopoDS_Iterator.hxx>
42 #include <TopExp_Explorer.hxx>
43 #include <TopTools_MapOfShape.hxx>
44 #include <TopTools_SequenceOfShape.hxx>
45 #include <TopTools_ListIteratorOfListOfShape.hxx>
46
47 #include <Precision.hxx>
48 #include <Standard_NullObject.hxx>
49 #include <Standard_TypeMismatch.hxx>
50 #include <Standard_ConstructionError.hxx>
51
52 //=======================================================================
53 //function : GetID
54 //purpose  :
55 //=======================================================================
56 const Standard_GUID& GEOMImpl_ShapeDriver::GetID()
57 {
58   static Standard_GUID aShapeDriver("FF1BBB54-5D14-4df2-980B-3A668264EA16");
59   return aShapeDriver;
60 }
61
62
63 //=======================================================================
64 //function : GEOMImpl_ShapeDriver
65 //purpose  :
66 //=======================================================================
67 GEOMImpl_ShapeDriver::GEOMImpl_ShapeDriver()
68 {
69 }
70
71 //=======================================================================
72 //function : Execute
73 //purpose  :
74 //=======================================================================
75 Standard_Integer GEOMImpl_ShapeDriver::Execute(TFunction_Logbook& log) const
76 {
77   if (Label().IsNull()) return 0;
78   Handle(GEOM_Function) aFunction = GEOM_Function::GetFunction(Label());
79
80   GEOMImpl_IShapes aCI (aFunction);
81   Standard_Integer aType = aFunction->GetType();
82
83   TopoDS_Shape aShape;
84   BRep_Builder B;
85
86   if (aType == WIRE_EDGES) {
87     Handle(TColStd_HSequenceOfTransient) aShapes = aCI.GetShapes();
88     unsigned int ind, nbshapes = aShapes->Length();
89
90     // add edges
91     BRepBuilderAPI_MakeWire MW;
92     for (ind = 1; ind <= nbshapes; ind++) {
93       Handle(GEOM_Function) aRefShape = Handle(GEOM_Function)::DownCast(aShapes->Value(ind));
94       TopoDS_Shape aShape_i = aRefShape->GetValue();
95       if (aShape_i.IsNull()) {
96         Standard_NullObject::Raise("Shape for wire construction is null");
97       }
98       if (aShape_i.ShapeType() == TopAbs_EDGE)
99         MW.Add(TopoDS::Edge(aShape_i));
100       else if (aShape_i.ShapeType() == TopAbs_WIRE)
101         MW.Add(TopoDS::Wire(aShape_i));
102       else
103         Standard_TypeMismatch::Raise
104           ("Shape for wire construction is neither an edge nor a wire");
105     }
106
107     if (!MW.IsDone()) {
108       Standard_ConstructionError::Raise("Wire construction failed");
109     }
110     aShape = MW;
111
112   } else if (aType == FACE_WIRE) {
113     Handle(GEOM_Function) aRefBase = aCI.GetBase();
114     TopoDS_Shape aShapeBase = aRefBase->GetValue();
115     if (aShapeBase.IsNull() || aShapeBase.ShapeType() != TopAbs_WIRE) {
116       Standard_NullObject::Raise
117         ("Shape for face construction is null or not a wire");
118     }
119     TopoDS_Wire W = TopoDS::Wire(aShapeBase);
120     BRepBuilderAPI_MakeFace MF (W, aCI.GetIsPlanar());
121     if (!MF.IsDone()) {
122       Standard_ConstructionError::Raise("Face construction failed");
123     }
124     aShape = MF.Shape();
125
126   } else if (aType == FACE_WIRES) {
127     Handle(TColStd_HSequenceOfTransient) aShapes = aCI.GetShapes();
128
129     // first wire
130     Handle(GEOM_Function) aRefWire = Handle(GEOM_Function)::DownCast(aShapes->Value(1));
131     TopoDS_Shape aWire = aRefWire->GetValue();
132     if (aWire.IsNull() || aWire.ShapeType() != TopAbs_WIRE) {
133       Standard_NullObject::Raise("Shape for face construction is null or not a wire");
134     }
135     TopoDS_Wire W = TopoDS::Wire(aWire);
136
137     // basic face
138     BRepBuilderAPI_MakeFace MF (W, aCI.GetIsPlanar());
139     if (!MF.IsDone()) {
140       Standard_ConstructionError::Raise("Face construction failed");
141     }
142     TopoDS_Shape FFace = MF.Shape();
143     if (!FFace.IsNull()) {
144       unsigned int ind, nbshapes = aShapes->Length();
145       if (nbshapes == 1) {
146         aShape = FFace;
147
148       } else if (nbshapes >= 2) {
149         TopoDS_Compound C;
150         BRep_Builder aBuilder;
151         aBuilder.MakeCompound(C);
152         BRepAlgo_FaceRestrictor FR;
153
154         TopAbs_Orientation OriF = FFace.Orientation();
155         TopoDS_Shape aLocalS = FFace.Oriented(TopAbs_FORWARD);
156         FR.Init(TopoDS::Face(aLocalS), Standard_False, Standard_True);
157
158         for (ind = 1; ind <= nbshapes; ind++) {
159           Handle(GEOM_Function) aRefWire_i =
160             Handle(GEOM_Function)::DownCast(aShapes->Value(ind));
161           TopoDS_Shape aWire_i = aRefWire_i->GetValue();
162           if (aWire_i.IsNull() || aWire_i.ShapeType() != TopAbs_WIRE) {
163             Standard_NullObject::Raise("Shape for face construction is null or not a wire");
164           }
165
166           FR.Add(TopoDS::Wire(aWire_i));
167         }
168
169         FR.Perform();
170
171         if (FR.IsDone()) {
172           int k = 0;
173           TopoDS_Shape aFace;
174           for (; FR.More(); FR.Next()) {
175             aFace = FR.Current().Oriented(OriF);
176             aBuilder.Add(C, aFace);
177             k++;
178           }
179           if (k == 1) {
180             aShape = aFace;
181           } else {
182             aShape = C;
183           }
184         }
185       }
186     }
187   } else if (aType == SHELL_FACES) {
188     Handle(TColStd_HSequenceOfTransient) aShapes = aCI.GetShapes();
189     unsigned int ind, nbshapes = aShapes->Length();
190
191     // add faces
192     BRepAlgo_Sewing aSewing(Precision::Confusion()*10.0);
193     for (ind = 1; ind <= nbshapes; ind++) {
194       Handle(GEOM_Function) aRefShape = Handle(GEOM_Function)::DownCast(aShapes->Value(ind));
195       TopoDS_Shape aShape_i = aRefShape->GetValue();
196       if (aShape_i.IsNull()) {
197         Standard_NullObject::Raise("Face for shell construction is null");
198       }
199       aSewing.Add(aShape_i);
200     }
201
202     aSewing.Perform();
203
204     TopExp_Explorer exp (aSewing.SewedShape(), TopAbs_SHELL);
205     Standard_Integer ish = 0;
206     for (; exp.More(); exp.Next()) {
207       aShape = exp.Current();
208       ish++;
209     }
210
211     if (ish != 1)
212       aShape = aSewing.SewedShape();
213
214   } else if (aType == SOLID_SHELL) {
215     Handle(GEOM_Function) aRefShell = aCI.GetBase();
216     TopoDS_Shape aShapeShell = aRefShell->GetValue();
217     if (aShapeShell.IsNull() || aShapeShell.ShapeType() != TopAbs_SHELL) {
218       Standard_NullObject::Raise("Shape for solid construction is null or not a shell");
219     }
220
221     BRepCheck_Shell chkShell(TopoDS::Shell(aShapeShell));
222     if(chkShell.Closed() == BRepCheck_NotClosed) return 0;
223
224     TopoDS_Solid Sol;
225     B.MakeSolid(Sol);
226     B.Add(Sol, aShapeShell);
227     BRepClass3d_SolidClassifier SC (Sol);
228     SC.PerformInfinitePoint(Precision::Confusion());
229     if (SC.State() == TopAbs_IN) {
230       B.MakeSolid(Sol);
231       B.Add(Sol, aShapeShell.Reversed());
232     }
233
234     aShape = Sol;
235
236   } else if (aType == SOLID_SHELLS) {
237     Handle(TColStd_HSequenceOfTransient) aShapes = aCI.GetShapes();
238     unsigned int ind, nbshapes = aShapes->Length();
239     Standard_Integer ish = 0;
240     TopoDS_Solid Sol;
241     B.MakeSolid(Sol);
242
243     // add shapes
244     for (ind = 1; ind <= nbshapes; ind++) {
245       Handle(GEOM_Function) aRefShape = Handle(GEOM_Function)::DownCast(aShapes->Value(ind));
246       TopoDS_Shape aShapeShell = aRefShape->GetValue();
247       if (aShapeShell.IsNull()) {
248         Standard_NullObject::Raise("Shell for solid construction is null");
249       }
250       if (aShapeShell.ShapeType() == TopAbs_SHELL) {
251         B.Add(Sol, aShapeShell);
252         ish++;
253       }
254     }
255     if ( ish == 0 ) return 0;
256     BRepClass3d_SolidClassifier SC (Sol);
257     SC.PerformInfinitePoint(Precision::Confusion());
258     switch (SC.State()) {
259     case TopAbs_IN:
260       aShape = Sol.Reversed(); break;
261     case TopAbs_OUT:
262       aShape = Sol; break;
263     default: // not closed shell?
264       return 0;
265     }
266
267   } else if (aType == COMPOUND_SHAPES) {
268     Handle(TColStd_HSequenceOfTransient) aShapes = aCI.GetShapes();
269     unsigned int ind, nbshapes = aShapes->Length();
270
271     // add shapes
272     TopoDS_Compound C;
273     B.MakeCompound(C);
274     for (ind = 1; ind <= nbshapes; ind++) {
275       Handle(GEOM_Function) aRefShape = Handle(GEOM_Function)::DownCast(aShapes->Value(ind));
276       TopoDS_Shape aShape_i = aRefShape->GetValue();
277       if (aShape_i.IsNull()) {
278         Standard_NullObject::Raise("Shape for compound construction is null");
279       }
280       B.Add(C, aShape_i);
281     }
282
283     aShape = C;
284
285   } else if (aType == REVERSE_ORIENTATION) {
286     Handle(GEOM_Function) aRefShape = aCI.GetBase();
287     TopoDS_Shape aShape_i = aRefShape->GetValue();
288     if (aShape_i.IsNull()) {
289        Standard_NullObject::Raise("Shape for reverse is null");
290     }
291   
292     BRepBuilderAPI_Copy Copy(aShape_i);
293     if( Copy.IsDone() ) {
294       TopoDS_Shape tds = Copy.Shape();
295       if( tds.IsNull() ) {
296         Standard_ConstructionError::Raise("Orientation aborted : Can not reverse the shape");
297       }
298
299       if( tds.Orientation() == TopAbs_FORWARD)
300         tds.Orientation(TopAbs_REVERSED) ;
301       else
302         tds.Orientation(TopAbs_FORWARD) ;
303
304       aShape = tds;
305     } 
306   }
307
308   if (aShape.IsNull()) return 0;
309
310   // Check shape validity
311   BRepCheck_Analyzer ana (aShape, false);
312   if (!ana.IsValid()) {
313     Standard_ConstructionError::Raise("Algorithm have produced an invalid shape result");
314   }
315
316   aFunction->SetValue(aShape);
317
318   log.SetTouched(Label());
319
320   return 1;
321 }
322
323
324 //=======================================================================
325 //function :  GEOMImpl_ShapeDriver_Type_
326 //purpose  :
327 //=======================================================================
328 Standard_EXPORT Handle_Standard_Type& GEOMImpl_ShapeDriver_Type_()
329 {
330
331   static Handle_Standard_Type aType1 = STANDARD_TYPE(TFunction_Driver);
332   if ( aType1.IsNull()) aType1 = STANDARD_TYPE(TFunction_Driver);
333   static Handle_Standard_Type aType2 = STANDARD_TYPE(MMgt_TShared);
334   if ( aType2.IsNull()) aType2 = STANDARD_TYPE(MMgt_TShared);
335   static Handle_Standard_Type aType3 = STANDARD_TYPE(Standard_Transient);
336   if ( aType3.IsNull()) aType3 = STANDARD_TYPE(Standard_Transient);
337
338
339   static Handle_Standard_Transient _Ancestors[]= {aType1,aType2,aType3,NULL};
340   static Handle_Standard_Type _aType = new Standard_Type("GEOMImpl_ShapeDriver",
341                                                          sizeof(GEOMImpl_ShapeDriver),
342                                                          1,
343                                                          (Standard_Address)_Ancestors,
344                                                          (Standard_Address)NULL);
345
346   return _aType;
347 }
348
349 //=======================================================================
350 //function : DownCast
351 //purpose  :
352 //=======================================================================
353 const Handle(GEOMImpl_ShapeDriver) Handle(GEOMImpl_ShapeDriver)::DownCast(const Handle(Standard_Transient)& AnObject)
354 {
355   Handle(GEOMImpl_ShapeDriver) _anOtherObject;
356
357   if (!AnObject.IsNull()) {
358      if (AnObject->IsKind(STANDARD_TYPE(GEOMImpl_ShapeDriver))) {
359        _anOtherObject = Handle(GEOMImpl_ShapeDriver)((Handle(GEOMImpl_ShapeDriver)&)AnObject);
360      }
361   }
362
363   return _anOtherObject ;
364 }