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