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