0024059: Eliminate compiler warning C4701 in MSVC++ with warning level 4
[occt.git] / src / LocOpe / LocOpe_BuildShape.cxx
1 // Created on: 1996-09-16
2 // Created by: Jacques GOUSSARD
3 // Copyright (c) 1996-1999 Matra Datavision
4 // Copyright (c) 1999-2012 OPEN CASCADE SAS
5 //
6 // The content of this file is subject to the Open CASCADE Technology Public
7 // License Version 6.5 (the "License"). You may not use the content of this file
8 // except in compliance with the License. Please obtain a copy of the License
9 // at http://www.opencascade.org and read it completely before using this file.
10 //
11 // The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
12 // main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
13 //
14 // The Original Code and all software distributed under the License is
15 // distributed on an "AS IS" basis, without warranty of any kind, and the
16 // Initial Developer hereby disclaims all such warranties, including without
17 // limitation, any warranties of merchantability, fitness for a particular
18 // purpose or non-infringement. Please see the License for the specific terms
19 // and conditions governing the rights and limitations under the License.
20
21
22
23 #include <LocOpe_BuildShape.ixx>
24
25
26 #include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
27 #include <TopTools_DataMapOfShapeListOfShape.hxx>
28 #include <TopTools_IndexedMapOfShape.hxx>
29 #include <TColStd_MapOfInteger.hxx>
30
31 #include <TopTools_DataMapIteratorOfDataMapOfShapeListOfShape.hxx>
32 #include <TopTools_ListIteratorOfListOfShape.hxx>
33 #include <TColStd_MapIteratorOfMapOfInteger.hxx>
34
35 #include <TopoDS_Compound.hxx>
36 #include <TopoDS_Solid.hxx>
37 #include <TopoDS_Shell.hxx>
38 #include <TopoDS_Edge.hxx>
39
40 #include <BRep_Tool.hxx>
41 #include <BRep_Builder.hxx>
42 #include <gp_Pnt.hxx>
43
44 #include <BRepClass3d_SolidClassifier.hxx>
45
46 #include <Standard_ConstructionError.hxx>
47
48
49 #include <TopExp.hxx>
50 #include <TopAbs.hxx>
51 #include <TopoDS.hxx>
52 #include <Precision.hxx>
53
54
55 static void Add(const Standard_Integer,
56                 TColStd_MapOfInteger&,
57                 TopTools_IndexedMapOfShape&,
58                 const TopTools_IndexedDataMapOfShapeListOfShape&);
59
60 static void Propagate(const TopoDS_Shape&, // face
61                       TopoDS_Shape&, // shell
62                       const TopTools_IndexedMapOfShape&,
63                       TColStd_MapOfInteger&);
64                       
65 static Standard_Boolean IsInside(const TopoDS_Shape&,
66                                  const TopoDS_Shape&);
67
68
69 //=======================================================================
70 //function : Perform
71 //purpose  : 
72 //=======================================================================
73
74 void LocOpe_BuildShape::Perform(const TopTools_ListOfShape& L)
75 {
76   Standard_Integer i ;
77   Standard_Integer j ;
78   Standard_Integer k ;
79   myRes.Nullify();
80
81   TopoDS_Compound C;
82   BRep_Builder B;
83   B.MakeCompound(C);
84
85   TopTools_IndexedMapOfShape mapF;
86   TopTools_ListIteratorOfListOfShape itl;
87
88   for (itl.Initialize(L); itl.More(); itl.Next()) {
89     if (itl.Value().ShapeType() == TopAbs_FACE &&
90         !mapF.Contains(itl.Value())) {
91       mapF.Add(itl.Value());
92       B.Add(C,itl.Value());
93     }
94   }
95
96   if (mapF.Extent() == 0) {
97     return; // no face
98   }
99
100   TopTools_IndexedDataMapOfShapeListOfShape theMapEF;
101   TopExp::MapShapesAndAncestors(C,TopAbs_EDGE,TopAbs_FACE,theMapEF);
102
103   TopTools_DataMapOfShapeListOfShape mapSh;
104   TColStd_MapOfInteger mapI,mapIf;
105   Standard_Integer Nbedges = theMapEF.Extent();
106
107   TopTools_ListOfShape lshell;
108   TopTools_ListOfShape lresult;
109
110   do {
111     // Recherche du premier edge non traite
112     for ( i = 1; i <= Nbedges; i++) {
113       if (!mapI.Contains(i)) {
114         break;
115       }
116     }
117     if (i <= Nbedges) {
118       mapF.Clear();
119       mapIf.Clear();
120       Add(i,mapI,mapF,theMapEF);
121       Standard_Boolean Manifold = Standard_True;
122       TopoDS_Shape FaceRef;
123       TopAbs_Orientation orient;
124
125       for ( j = 1; j<= mapF.Extent(); j++) {
126         orient = mapF(j).Orientation();
127         if (orient == TopAbs_INTERNAL || orient == TopAbs_EXTERNAL) {
128           Manifold = Standard_False;
129         }
130         else if (FaceRef.IsNull()) {
131           FaceRef = mapF(j);
132         }
133         mapIf.Add(j);
134       }
135
136       TopoDS_Shell newSh;
137       B.MakeShell(newSh);
138       if (!Manifold && FaceRef.IsNull()) {
139         // on a un paquet de faces. pas d'orientation possible ?
140         for (j = 1; j <= mapF.Extent(); j++) {
141           B.Add(newSh,mapF(j));
142         }
143       }
144       else {
145         // orienter ce qu`on peut
146         if (!Manifold) {
147           for (j = 1; j <= mapF.Extent(); j++) {
148             if (mapF(j).Orientation() == TopAbs_INTERNAL ||
149                 mapF(j).Orientation() == TopAbs_EXTERNAL) {
150               B.Add(newSh,mapF(j));
151               mapIf.Remove(j);
152             }
153           }
154         }
155         
156         B.Add(newSh,FaceRef);
157         Propagate(FaceRef,newSh,mapF,mapIf);
158       }
159       if (!Manifold) {
160         lshell.Append(newSh.Oriented(TopAbs_INTERNAL));
161       }
162       else {
163         TopTools_IndexedDataMapOfShapeListOfShape theMapEFbis;
164         TopExp::MapShapesAndAncestors(newSh,TopAbs_EDGE,TopAbs_FACE,theMapEFbis);
165         for ( k = 1; k<=theMapEFbis.Extent(); k++) {
166           const TopoDS_Edge& Ed = TopoDS::Edge(theMapEFbis.FindKey(k));
167           TopAbs_Orientation OriEd = Ed.Orientation();
168           if (OriEd != TopAbs_INTERNAL && OriEd != TopAbs_EXTERNAL) {  
169             Standard_Integer Nbfac = theMapEFbis(k).Extent();
170             if (Nbfac > 2) { // peu probable
171               break;
172             }
173             else if (Nbfac == 1) {
174               if (!BRep_Tool::Degenerated(Ed)) {
175                 break;
176               }
177             }
178           }
179         }
180         if (k > theMapEFbis.Extent()) {
181           TopoDS_Solid newSo;
182           B.MakeSolid(newSo);
183           B.Add(newSo,newSh); // newSh est FORWARD
184           BRepClass3d_SolidClassifier Class(newSo);
185           Class.PerformInfinitePoint(Precision::Confusion());
186           if (Class.State() == TopAbs_IN) {
187             lresult.Append(newSh.Oriented(TopAbs_REVERSED));
188           }
189           else {
190             lresult.Append(newSh);
191           }
192         }
193         else {
194           lshell.Append(newSh.Oriented(TopAbs_INTERNAL));
195         }
196       }
197     }
198   } while (mapI.Extent() < Nbedges);
199
200
201   // on a une list de shells dans lresult. on suppose qu`ils ne s`intersectent pas.
202   // il faut classifier les shells orientes pour en faire des solides...
203   // on n`accepte qu`1 niveau d'imbrication
204
205   TopTools_DataMapOfShapeListOfShape imbSh;
206   TopTools_ListOfShape LIntern;
207
208   for (itl.Initialize(lresult); itl.More(); itl.Next()) {
209     const TopoDS_Shape& sh = itl.Value();
210     TopoDS_Solid tempo;
211     B.MakeSolid(tempo);
212     B.Add(tempo,sh);
213
214     TopTools_ListOfShape thelist;    
215     imbSh.Bind(sh, thelist);
216     TopTools_ListIteratorOfListOfShape itl2;
217     for (itl2.Initialize(lresult);
218 //    for (TopTools_ListIteratorOfListOfShape itl2(lresult);
219          itl2.More(); itl2.Next()) {
220       const TopoDS_Shape& sh2 = itl2.Value();  
221       if (!sh2.IsSame(sh)) {
222         if (IsInside(sh2, tempo)) {
223           LIntern.Append(sh2);
224           imbSh(sh).Append(sh2);
225         }
226       }
227     }
228   }
229   
230
231   // LPA 07/10/98: on vire les shells imbriques comme
232   // etant aussi des solides a part entiere.
233   for (itl.Initialize(LIntern); itl.More(); itl.Next()) {
234     const TopoDS_Shape& sh = itl.Value();
235     if (imbSh.IsBound(sh)) {
236       imbSh.UnBind(sh);
237     }
238   }
239
240
241
242   TopTools_ListOfShape lsolid;
243   do {
244 //    for (TopTools_DataMapIteratorOfDataMapOfShapeListOfShape itdm(imbSh);
245     TopTools_DataMapIteratorOfDataMapOfShapeListOfShape itdm(imbSh);
246     for ( ; itdm.More(); itdm.Next()) {
247       if (itdm.Value().Extent() != 0) {
248         break;
249       }
250     }
251     if (itdm.More()) {
252       TopoDS_Solid newSo;
253       B.MakeSolid(newSo);
254       B.Add(newSo,itdm.Key());
255       for (itl.Initialize(itdm.Value()); itl.More(); itl.Next()) {
256         B.Add(newSo,itl.Value().Reversed());
257       }
258       lsolid.Append(newSo);
259       imbSh.UnBind(itdm.Key());
260     }
261     else {
262       for (itdm.Reset(); itdm.More(); itdm.Next()) {
263         TopoDS_Solid newSo;
264         B.MakeSolid(newSo);
265         B.Add(newSo,itdm.Key());
266         lsolid.Append(newSo);
267       }
268       imbSh.Clear();
269     }
270   } while (!imbSh.Extent() == 0);
271
272   Standard_Integer nbsol = lsolid.Extent();
273   Standard_Integer nbshl = lshell.Extent();
274
275   if (nbsol == 1 && nbshl == 0) {
276     myRes = lsolid.First();
277   }
278   else if (nbsol == 0 && nbshl == 1) {
279     myRes = lshell.First();
280   }
281   else {
282     B.MakeCompound(TopoDS::Compound(myRes));
283     for (itl.Initialize(lsolid); itl.More(); itl.Next()) {
284       B.Add(myRes,itl.Value());
285     }
286     for (itl.Initialize(lshell); itl.More(); itl.Next()) {
287       B.Add(myRes,itl.Value());
288     }
289   }
290 }
291
292
293
294
295
296 //=======================================================================
297 //function : Add
298 //purpose  : static function
299 //=======================================================================
300
301 static void Add(const Standard_Integer ind,
302                 TColStd_MapOfInteger& mapI,
303                 TopTools_IndexedMapOfShape& mapF,
304                 const TopTools_IndexedDataMapOfShapeListOfShape& mapEF)
305
306 {
307   if (!mapI.Add(ind)) {
308     Standard_ConstructionError::Raise();
309   }
310
311   TopTools_ListIteratorOfListOfShape itl(mapEF(ind));
312   for (; itl.More(); itl.Next()) {
313     if (!mapF.Contains(itl.Value())) {
314       mapF.Add(itl.Value());
315       TopExp_Explorer exp;
316       for (exp.Init(itl.Value(),TopAbs_EDGE);
317 //      for (TopExp_Explorer exp(itl.Value(),TopAbs_EDGE);
318            exp.More(); exp.Next()) {
319         const TopoDS_Shape& edg = exp.Current();
320         Standard_Integer indedg = mapEF.FindIndex(edg);
321         if (indedg == 0) {
322           Standard_ConstructionError::Raise();
323         }
324         if (!mapI.Contains(indedg)) {
325           Add(indedg,mapI,mapF,mapEF);
326         }
327       }
328     }
329   }
330 }
331
332
333 //=======================================================================
334 //function : Propagate
335 //purpose  : static function
336 //=======================================================================
337
338 static void Propagate(const TopoDS_Shape& F,
339                       TopoDS_Shape& Sh,
340                       const TopTools_IndexedMapOfShape& mapF,
341                       TColStd_MapOfInteger& mapIf)
342 {
343   BRep_Builder B;
344   Standard_Integer indf = mapF.FindIndex(F);
345   if (!mapIf.Contains(indf)) {
346     return;
347   }
348   mapIf.Remove(indf);
349   if (mapIf.Extent() == 0) {
350     return;
351   }
352   
353   TopExp_Explorer exp;
354   for (exp.Init(F,TopAbs_EDGE); exp.More(); exp.Next()) {
355 //  for (TopExp_Explorer exp(F,TopAbs_EDGE); exp.More(); exp.Next()) {
356     const TopoDS_Shape& edg = exp.Current();
357
358     TopAbs_Orientation ored1 = edg.Orientation(),ored2 = TopAbs_FORWARD;
359
360     if (ored1 == TopAbs_INTERNAL || ored1 == TopAbs_EXTERNAL) {
361       continue;
362     }
363 //    for (TColStd_MapIteratorOfMapOfInteger itm(mapIf);
364     TColStd_MapIteratorOfMapOfInteger itm(mapIf);
365     for ( ; itm.More(); itm.Next()) {
366       const TopoDS_Shape& newF = mapF(itm.Key());
367 //      for (TopExp_Explorer exp2(newF,TopAbs_EDGE);exp2.More(); exp2.Next()) {
368       TopExp_Explorer exp2(newF,TopAbs_EDGE) ;
369       for ( ;exp2.More(); exp2.Next()) {
370         if (exp2.Current().IsSame(edg)) {
371           break;
372         }
373       }
374       if (exp2.More()) {
375         ored2 = exp2.Current().Orientation();
376         break;
377       }
378     }
379     if (itm.More()) {
380       TopoDS_Shape FtoAdd = mapF(itm.Key());
381       Standard_Boolean added = Standard_False;
382       if (ored2 == ored1) {
383         FtoAdd.Reverse();
384         B.Add(Sh,FtoAdd);
385         added = Standard_True;
386       }
387       else if (ored2 == TopAbs::Reverse(ored1)) {
388         B.Add(Sh,FtoAdd);
389         added = Standard_True;
390       }
391       if (added) {
392         Propagate(FtoAdd,Sh,mapF,mapIf);
393       }
394     }
395   }
396 }
397
398 //=======================================================================
399 //function : IsInside
400 //purpose  : static function
401 //=======================================================================
402
403 static Standard_Boolean IsInside(const TopoDS_Shape& S1,
404                                  const TopoDS_Shape& S2)
405 {
406   BRepClass3d_SolidClassifier Class(S2);
407   TopExp_Explorer exp;
408   for (exp.Init(S1,TopAbs_VERTEX);exp.More(); exp.Next()) {
409 //  for (TopExp_Explorer exp(S1,TopAbs_VERTEX);exp.More(); exp.Next()) {
410     const TopoDS_Vertex& vtx = TopoDS::Vertex(exp.Current());
411     gp_Pnt Pttest = BRep_Tool::Pnt(vtx);
412     Standard_Real Tol = BRep_Tool::Tolerance(vtx);
413     Class.Perform(Pttest,Tol);
414     if (Class.State() == TopAbs_IN) {
415       return Standard_True;
416     }
417     else if (Class.State() == TopAbs_OUT) {
418       return Standard_False;
419     }
420   }
421 #ifdef DEB
422   cout << "Classification impossible sur vertex " << endl;
423 #endif
424   
425   return Standard_True;
426   
427 }
428