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