4e57c75e |
1 | // Created by: Peter KURNEV |
973c2be1 |
2 | // Copyright (c) 2010-2014 OPEN CASCADE SAS |
4e57c75e |
3 | // Copyright (c) 2007-2010 CEA/DEN, EDF R&D, OPEN CASCADE |
4 | // Copyright (c) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, CEDRAT, |
5 | // EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS |
6 | // |
973c2be1 |
7 | // This file is part of Open CASCADE Technology software library. |
4e57c75e |
8 | // |
d5f74e42 |
9 | // This library is free software; you can redistribute it and/or modify it under |
10 | // the terms of the GNU Lesser General Public License version 2.1 as published |
973c2be1 |
11 | // by the Free Software Foundation, with special exception defined in the file |
12 | // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT |
13 | // distribution for complete text of the license and disclaimer of any warranty. |
4e57c75e |
14 | // |
973c2be1 |
15 | // Alternatively, this file may be used under the terms of Open CASCADE |
16 | // commercial license or contractual agreement. |
465d1fba |
17 | // |
42cf5bc1 |
18 | #include <BOPAlgo_BuilderSolid.hxx> |
19 | #include <BOPAlgo_ShellSplitter.hxx> |
33ba8565 |
20 | #include <BOPAlgo_Alerts.hxx> |
b7cd7c2b |
21 | #include <BOPAlgo_Tools.hxx> |
42cf5bc1 |
22 | #include <BOPCol_BoxBndTree.hxx> |
23 | #include <BOPCol_DataMapOfShapeListOfShape.hxx> |
24 | #include <BOPCol_DataMapOfShapeShape.hxx> |
25 | #include <BOPCol_IndexedDataMapOfShapeListOfShape.hxx> |
319da2e4 |
26 | #include <BOPCol_IndexedDataMapOfShapeShape.hxx> |
42cf5bc1 |
27 | #include <BOPCol_ListOfInteger.hxx> |
28 | #include <BOPCol_ListOfShape.hxx> |
29 | #include <BOPCol_MapOfOrientedShape.hxx> |
30 | #include <BOPCol_MapOfShape.hxx> |
31 | #include <BOPCol_NCVector.hxx> |
32 | #include <BOPCol_Parallel.hxx> |
33 | #include <BOPTools.hxx> |
34 | #include <BOPTools_AlgoTools.hxx> |
35 | #include <BOPTools_AlgoTools3D.hxx> |
36 | #include <BOPTools_CoupleOfShape.hxx> |
37 | #include <BRep_Builder.hxx> |
38 | #include <BRep_Tool.hxx> |
39 | #include <BRepBndLib.hxx> |
40 | #include <BRepClass3d_SolidClassifier.hxx> |
41 | #include <Geom2d_Curve.hxx> |
42 | #include <Geom_Curve.hxx> |
43 | #include <Geom_Surface.hxx> |
4e57c75e |
44 | #include <gp_Dir.hxx> |
42cf5bc1 |
45 | #include <gp_Pln.hxx> |
4e57c75e |
46 | #include <gp_Pnt.hxx> |
42cf5bc1 |
47 | #include <gp_Pnt2d.hxx> |
48 | #include <gp_Vec.hxx> |
49 | #include <IntTools_Context.hxx> |
50 | #include <NCollection_DataMap.hxx> |
42cf5bc1 |
51 | #include <NCollection_List.hxx> |
52 | #include <NCollection_UBTreeFiller.hxx> |
682c9d06 |
53 | #include <TColStd_MapIntegerHasher.hxx> |
4e57c75e |
54 | #include <TopAbs.hxx> |
42cf5bc1 |
55 | #include <TopExp.hxx> |
56 | #include <TopExp_Explorer.hxx> |
b7cd7c2b |
57 | #include <TopoDS.hxx> |
42cf5bc1 |
58 | #include <TopoDS_Compound.hxx> |
59 | #include <TopoDS_Edge.hxx> |
4e57c75e |
60 | #include <TopoDS_Face.hxx> |
42cf5bc1 |
61 | #include <TopoDS_Iterator.hxx> |
4e57c75e |
62 | #include <TopoDS_Shape.hxx> |
63 | #include <TopoDS_Shell.hxx> |
4e57c75e |
64 | #include <TopoDS_Solid.hxx> |
65 | #include <TopoDS_Vertex.hxx> |
4e57c75e |
66 | |
42cf5bc1 |
67 | // |
4e57c75e |
68 | static |
69 | Standard_Boolean IsGrowthShell(const TopoDS_Shape& , |
70 | const BOPCol_IndexedMapOfShape& ); |
71 | static |
72 | Standard_Boolean IsHole(const TopoDS_Shape& , |
1e143abb |
73 | Handle(IntTools_Context)& ); |
4e57c75e |
74 | static |
75 | Standard_Boolean IsInside(const TopoDS_Shape& , |
76 | const TopoDS_Shape& , |
1e143abb |
77 | Handle(IntTools_Context)& ); |
4e57c75e |
78 | static |
319da2e4 |
79 | void MakeInternalShells(const BOPCol_IndexedMapOfShape& , |
4e57c75e |
80 | BOPCol_ListOfShape& ); |
81 | |
465d1fba |
82 | //======================================================================= |
4e57c75e |
83 | //function : |
84 | //purpose : |
85 | //======================================================================= |
682c9d06 |
86 | BOPAlgo_BuilderSolid::BOPAlgo_BuilderSolid() |
4e57c75e |
87 | : |
88 | BOPAlgo_BuilderArea() |
89 | { |
90 | } |
91 | //======================================================================= |
92 | //function : |
93 | //purpose : |
94 | //======================================================================= |
682c9d06 |
95 | BOPAlgo_BuilderSolid::BOPAlgo_BuilderSolid |
96 | (const Handle(NCollection_BaseAllocator)& theAllocator) |
4e57c75e |
97 | : |
98 | BOPAlgo_BuilderArea(theAllocator) |
99 | { |
100 | } |
101 | //======================================================================= |
102 | //function : ~ |
103 | //purpose : |
104 | //======================================================================= |
30ecd5f8 |
105 | BOPAlgo_BuilderSolid::~BOPAlgo_BuilderSolid() |
4e57c75e |
106 | { |
107 | } |
108 | //======================================================================= |
30ecd5f8 |
109 | //function : SetSolid |
110 | //purpose : |
111 | //======================================================================= |
112 | void BOPAlgo_BuilderSolid::SetSolid(const TopoDS_Solid& aS) |
113 | { |
114 | mySolid=aS; |
115 | } |
116 | //======================================================================= |
117 | //function : Solid |
118 | //purpose : |
119 | //======================================================================= |
120 | const TopoDS_Solid& BOPAlgo_BuilderSolid::Solid()const |
121 | { |
122 | return mySolid; |
123 | } |
124 | //======================================================================= |
4e57c75e |
125 | //function : Perform |
126 | //purpose : |
127 | //======================================================================= |
30ecd5f8 |
128 | void BOPAlgo_BuilderSolid::Perform() |
4e57c75e |
129 | { |
33ba8565 |
130 | GetReport()->Clear(); |
4e57c75e |
131 | // |
98b37659 |
132 | if (myShapes.IsEmpty()) |
133 | return; |
134 | |
4e57c75e |
135 | if (myContext.IsNull()) { |
1e143abb |
136 | myContext=new IntTools_Context; |
4e57c75e |
137 | } |
b7cd7c2b |
138 | |
139 | myBoxes.Clear(); |
140 | |
4e57c75e |
141 | TopoDS_Compound aC; |
142 | BRep_Builder aBB; |
143 | BOPCol_ListIteratorOfListOfShape aIt; |
144 | // |
145 | aBB.MakeCompound(aC); |
146 | aIt.Initialize(myShapes); |
147 | for(; aIt.More(); aIt.Next()) { |
148 | const TopoDS_Shape& aF=aIt.Value(); |
149 | aBB.Add(aC, aF); |
150 | } |
151 | // |
36f4947b |
152 | UserBreak(); |
4e57c75e |
153 | // |
154 | PerformShapesToAvoid(); |
33ba8565 |
155 | if (HasErrors()) { |
4e57c75e |
156 | return; |
157 | } |
158 | // |
36f4947b |
159 | UserBreak(); |
160 | // |
4e57c75e |
161 | PerformLoops(); |
33ba8565 |
162 | if (HasErrors()) { |
4e57c75e |
163 | return; |
164 | } |
36f4947b |
165 | // |
166 | UserBreak(); |
167 | // |
4e57c75e |
168 | PerformAreas(); |
33ba8565 |
169 | if (HasErrors()) { |
4e57c75e |
170 | return; |
171 | } |
36f4947b |
172 | // |
173 | UserBreak(); |
174 | // |
4e57c75e |
175 | PerformInternalShapes(); |
33ba8565 |
176 | if (HasErrors()) { |
4e57c75e |
177 | return; |
178 | } |
179 | } |
180 | //======================================================================= |
181 | //function :PerformShapesToAvoid |
182 | //purpose : |
183 | //======================================================================= |
30ecd5f8 |
184 | void BOPAlgo_BuilderSolid::PerformShapesToAvoid() |
4e57c75e |
185 | { |
186 | Standard_Boolean bFound; |
187 | Standard_Integer i, iCnt, aNbE, aNbF; |
188 | TopAbs_Orientation aOrE; |
189 | BOPCol_IndexedDataMapOfShapeListOfShape aMEF; |
190 | BOPCol_ListIteratorOfListOfShape aIt; |
191 | // |
192 | myShapesToAvoid.Clear(); |
193 | // |
194 | iCnt=0; |
302f96fb |
195 | for(;;) { |
4e57c75e |
196 | ++iCnt; |
197 | bFound=Standard_False; |
198 | // |
199 | // 1. MEF |
200 | aMEF.Clear(); |
201 | aIt.Initialize (myShapes); |
202 | for (; aIt.More(); aIt.Next()) { |
203 | const TopoDS_Shape& aF=aIt.Value(); |
204 | if (!myShapesToAvoid.Contains(aF)) { |
465d1fba |
205 | BOPTools::MapShapesAndAncestors(aF, |
206 | TopAbs_EDGE, |
207 | TopAbs_FACE, |
208 | aMEF); |
4e57c75e |
209 | } |
4e57c75e |
210 | } |
211 | aNbE=aMEF.Extent(); |
212 | // |
213 | // 2. myFacesToAvoid |
214 | for (i=1; i<=aNbE; ++i) { |
215 | const TopoDS_Edge& aE=(*(TopoDS_Edge*)(&aMEF.FindKey(i))); |
216 | if (BRep_Tool::Degenerated(aE)) { |
217 | continue; |
218 | } |
219 | // |
220 | BOPCol_ListOfShape& aLF=aMEF.ChangeFromKey(aE); |
221 | aNbF=aLF.Extent(); |
222 | if (!aNbF) { |
223 | continue; |
224 | } |
225 | // |
226 | aOrE=aE.Orientation(); |
227 | // |
228 | const TopoDS_Face& aF1=(*(TopoDS_Face*)(&aLF.First())); |
229 | if (aNbF==1) { |
230 | if (aOrE==TopAbs_INTERNAL) { |
231 | continue; |
232 | } |
233 | bFound=Standard_True; |
234 | myShapesToAvoid.Add(aF1); |
235 | } |
236 | else if (aNbF==2) { |
237 | const TopoDS_Face& aF2=(*(TopoDS_Face*)(&aLF.Last())); |
238 | if (aF2.IsSame(aF1)) { |
239 | if (BRep_Tool::IsClosed(aE, aF1)) { |
240 | continue; |
241 | } |
242 | // |
243 | if (aOrE==TopAbs_INTERNAL) { |
244 | continue; |
245 | } |
246 | // |
247 | bFound=Standard_True; |
248 | myShapesToAvoid.Add(aF1); |
249 | myShapesToAvoid.Add(aF2); |
250 | } |
251 | } |
252 | }// for (i=1; i<=aNbE; ++i) { |
253 | // |
254 | if (!bFound) { |
255 | break; |
256 | } |
257 | // |
682c9d06 |
258 | }//for(;;) { |
4e57c75e |
259 | } |
260 | //======================================================================= |
261 | //function : PerformLoops |
262 | //purpose : |
263 | //======================================================================= |
30ecd5f8 |
264 | void BOPAlgo_BuilderSolid::PerformLoops() |
4e57c75e |
265 | { |
33ba8565 |
266 | Standard_Integer i, aNbSh; |
682c9d06 |
267 | BOPCol_ListIteratorOfListOfShape aIt; |
4e57c75e |
268 | TopoDS_Iterator aItS; |
0090ae85 |
269 | Handle(NCollection_BaseAllocator) aAlr; |
682c9d06 |
270 | // |
682c9d06 |
271 | myLoops.Clear(); |
4e57c75e |
272 | // |
488e5b9d |
273 | aAlr= |
274 | NCollection_BaseAllocator::CommonBaseAllocator(); |
0090ae85 |
275 | BOPAlgo_ShellSplitter aSSp(aAlr); |
276 | // |
4e57c75e |
277 | // 1. Shells Usual |
682c9d06 |
278 | aIt.Initialize (myShapes); |
279 | for (; aIt.More(); aIt.Next()) { |
f47b8d2b |
280 | const TopoDS_Face& aF=*((TopoDS_Face*)&aIt.Value()); |
281 | if (myContext->IsInfiniteFace(aF)) { |
282 | TopoDS_Shell aSh; |
283 | BRep_Builder aBB; |
284 | // |
285 | aBB.MakeShell(aSh); |
286 | aBB.Add(aSh, aF); |
287 | myLoops.Append(aSh); |
288 | continue; |
289 | } |
290 | // |
682c9d06 |
291 | if (!myShapesToAvoid.Contains(aF)) { |
292 | aSSp.AddStartElement(aF); |
293 | } |
294 | } |
4e57c75e |
295 | // |
682c9d06 |
296 | aSSp.SetRunParallel(myRunParallel); |
297 | aSSp.Perform(); |
33ba8565 |
298 | if (aSSp.HasErrors()) { |
299 | // add warning status |
300 | { |
301 | TopoDS_Compound aFacesSp; |
302 | BRep_Builder().MakeCompound(aFacesSp); |
303 | BOPCol_ListIteratorOfListOfShape aItLF(aSSp.StartElements()); |
304 | for (; aItLF.More(); aItLF.Next()) { |
305 | BRep_Builder().Add(aFacesSp, aItLF.Value()); |
306 | } |
307 | AddWarning (new BOPAlgo_AlertShellSplitterFailed (aFacesSp)); |
308 | } |
682c9d06 |
309 | return; |
4e57c75e |
310 | } |
311 | // |
682c9d06 |
312 | const BOPCol_ListOfShape& aLSh=aSSp.Shells(); |
313 | aIt.Initialize (aLSh); |
314 | for (; aIt.More(); aIt.Next()) { |
315 | const TopoDS_Shape& aSh=aIt.Value(); |
316 | myLoops.Append(aSh); |
317 | } |
318 | //================================================= |
4e57c75e |
319 | // |
682c9d06 |
320 | // 2. Post Treatment |
682c9d06 |
321 | BRep_Builder aBB; |
322 | BOPCol_MapOfOrientedShape AddedFacesMap; |
323 | BOPCol_IndexedDataMapOfShapeListOfShape aEFMap; |
4e57c75e |
324 | BOPCol_MapOfOrientedShape aMP; |
682c9d06 |
325 | // |
4e57c75e |
326 | // a. collect all edges that are in loops |
327 | aIt.Initialize (myLoops); |
328 | for (; aIt.More(); aIt.Next()) { |
329 | const TopoDS_Shape& aS=aIt.Value(); |
330 | aItS.Initialize(aS); |
331 | for (; aItS.More(); aItS.Next()) { |
332 | const TopoDS_Shape& aF=aItS.Value(); |
333 | aMP.Add(aF); |
334 | } |
335 | } |
336 | // |
337 | // b. collect all edges that are to avoid |
319da2e4 |
338 | aNbSh = myShapesToAvoid.Extent(); |
339 | for (i = 1; i <= aNbSh; ++i) { |
340 | const TopoDS_Shape& aF = myShapesToAvoid(i); |
4e57c75e |
341 | aMP.Add(aF); |
342 | } |
343 | // |
344 | // c. add all edges that are not processed to myShapesToAvoid |
345 | aIt.Initialize (myShapes); |
346 | for (; aIt.More(); aIt.Next()) { |
f47b8d2b |
347 | const TopoDS_Face& aF=*((TopoDS_Face*)&aIt.Value()); |
348 | if (!myContext->IsInfiniteFace(aF)) { |
349 | if (!aMP.Contains(aF)) { |
350 | myShapesToAvoid.Add(aF); |
351 | } |
4e57c75e |
352 | } |
353 | } |
354 | //================================================= |
355 | // |
682c9d06 |
356 | // 3.Internal Shells |
4e57c75e |
357 | myLoopsInternal.Clear(); |
358 | // |
359 | aEFMap.Clear(); |
360 | AddedFacesMap.Clear(); |
361 | // |
319da2e4 |
362 | aNbSh = myShapesToAvoid.Extent(); |
363 | for (i = 1; i <= aNbSh; ++i) { |
364 | const TopoDS_Shape& aFF = myShapesToAvoid(i); |
682c9d06 |
365 | BOPTools::MapShapesAndAncestors(aFF, |
1e143abb |
366 | TopAbs_EDGE, TopAbs_FACE, |
367 | aEFMap); |
4e57c75e |
368 | } |
369 | // |
319da2e4 |
370 | for (i = 1; i <= aNbSh; ++i) { |
371 | const TopoDS_Shape& aFF = myShapesToAvoid(i); |
4e57c75e |
372 | if (!AddedFacesMap.Add(aFF)) { |
373 | continue; |
374 | } |
375 | // |
376 | // make a new shell |
0090ae85 |
377 | TopExp_Explorer aExp; |
4e57c75e |
378 | TopoDS_Shell aShell; |
379 | aBB.MakeShell(aShell); |
380 | aBB.Add(aShell, aFF); |
381 | // |
0090ae85 |
382 | aItS.Initialize(aShell); |
383 | for (; aItS.More(); aItS.Next()) { |
384 | const TopoDS_Face& aF = (*(TopoDS_Face*)(&aItS.Value())); |
4e57c75e |
385 | // |
0090ae85 |
386 | aExp.Init(aF, TopAbs_EDGE); |
387 | for (; aExp.More(); aExp.Next()) { |
388 | const TopoDS_Edge& aE = (*(TopoDS_Edge*)(&aExp.Current())); |
4e57c75e |
389 | const BOPCol_ListOfShape& aLF=aEFMap.FindFromKey(aE); |
682c9d06 |
390 | aIt.Initialize(aLF); |
391 | for (; aIt.More(); aIt.Next()) { |
392 | const TopoDS_Face& aFL=(*(TopoDS_Face*)(&aIt.Value())); |
4e57c75e |
393 | if (AddedFacesMap.Add(aFL)){ |
394 | aBB.Add(aShell, aFL); |
395 | } |
396 | } |
397 | } |
398 | } |
ab860031 |
399 | aShell.Closed (BRep_Tool::IsClosed (aShell)); |
4e57c75e |
400 | myLoopsInternal.Append(aShell); |
401 | } |
402 | } |
403 | //======================================================================= |
404 | //function : PerformAreas |
405 | //purpose : |
406 | //======================================================================= |
30ecd5f8 |
407 | void BOPAlgo_BuilderSolid::PerformAreas() |
4e57c75e |
408 | { |
4e57c75e |
409 | myAreas.Clear(); |
98b37659 |
410 | BRep_Builder aBB; |
411 | // The new solids |
412 | BOPCol_ListOfShape aNewSolids; |
413 | // The hole shells which has to be classified relatively new solids |
414 | BOPCol_IndexedMapOfShape aHoleShells; |
415 | // Map of the faces of the hole shells for quick check of the growths. |
416 | // If the analyzed shell contains any of the hole faces, it is considered as growth. |
417 | BOPCol_IndexedMapOfShape aMHF; |
418 | |
419 | // Analyze the shells |
420 | BOPCol_ListIteratorOfListOfShape aItLL(myLoops); |
421 | for (; aItLL.More(); aItLL.Next()) |
422 | { |
423 | const TopoDS_Shape& aShell = aItLL.Value(); |
424 | |
425 | Standard_Boolean bIsGrowth = IsGrowthShell(aShell, aMHF); |
426 | if (!bIsGrowth) |
427 | { |
428 | // Fast check did not give the result, run classification |
429 | bIsGrowth = !IsHole(aShell, myContext); |
430 | } |
431 | |
432 | // Save the solid |
433 | if (bIsGrowth) |
434 | { |
435 | TopoDS_Solid aSolid; |
682c9d06 |
436 | aBB.MakeSolid(aSolid); |
437 | aBB.Add (aSolid, aShell); |
682c9d06 |
438 | aNewSolids.Append (aSolid); |
4e57c75e |
439 | } |
98b37659 |
440 | else |
441 | { |
442 | aHoleShells.Add(aShell); |
443 | BOPTools::MapShapes(aShell, TopAbs_FACE, aMHF); |
4e57c75e |
444 | } |
98b37659 |
445 | } |
446 | |
447 | if (aHoleShells.IsEmpty()) |
448 | { |
449 | // No holes, stop the analysis |
b7cd7c2b |
450 | BOPCol_ListIteratorOfListOfShape aItLS(aNewSolids); |
451 | for (; aItLS.More(); aItLS.Next()) |
452 | { |
453 | const TopoDS_Shape& aSol = aItLS.Value(); |
454 | myAreas.Append(aSol); |
455 | // Build box |
456 | Bnd_Box aBox; |
457 | BRepBndLib::Add(aSol, aBox); |
458 | myBoxes.Bind(aSol, aBox); |
459 | } |
98b37659 |
460 | return; |
461 | } |
462 | |
463 | // Classify holes relatively solids |
464 | |
465 | // Prepare tree filler with the boxes of the hole shells |
466 | BOPCol_BoxBndTree aBBTree; |
467 | NCollection_UBTreeFiller <Standard_Integer, Bnd_Box> aTreeFiller(aBBTree); |
468 | |
469 | Standard_Integer i, aNbH = aHoleShells.Extent(); |
470 | for (i = 1; i <= aNbH; ++i) |
471 | { |
472 | const TopoDS_Shape& aHShell = aHoleShells(i); |
682c9d06 |
473 | // |
98b37659 |
474 | Bnd_Box aBox; |
475 | BRepBndLib::Add(aHShell, aBox); |
476 | aTreeFiller.Add(i, aBox); |
b7cd7c2b |
477 | |
478 | myBoxes.Bind(aHShell, aBox); |
4e57c75e |
479 | } |
98b37659 |
480 | |
481 | // Shake TreeFiller |
682c9d06 |
482 | aTreeFiller.Fill(); |
98b37659 |
483 | |
484 | // Find outer growth shell that is most close to each hole shell |
485 | BOPCol_IndexedDataMapOfShapeShape aHoleSolidMap; |
486 | |
487 | BOPCol_ListIteratorOfListOfShape aItLS(aNewSolids); |
488 | for (; aItLS.More(); aItLS.Next()) |
489 | { |
490 | const TopoDS_Shape& aSolid = aItLS.Value(); |
491 | |
492 | // Build box |
493 | Bnd_Box aBox; |
494 | BRepBndLib::Add(aSolid, aBox); |
495 | |
b7cd7c2b |
496 | myBoxes.Bind(aSolid, aBox); |
497 | |
98b37659 |
498 | BOPCol_BoxBndTreeSelector aSelector; |
499 | aSelector.SetBox(aBox); |
bcf50875 |
500 | aBBTree.Select(aSelector); |
98b37659 |
501 | |
502 | const BOPCol_ListOfInteger& aLI = aSelector.Indices(); |
503 | BOPCol_ListIteratorOfListOfInteger aItLI(aLI); |
504 | for (; aItLI.More(); aItLI.Next()) |
505 | { |
506 | Standard_Integer k = aItLI.Value(); |
507 | const TopoDS_Shape& aHole = aHoleShells(k); |
508 | // Check if it is inside |
509 | if (!IsInside(aHole, aSolid, myContext)) |
4e57c75e |
510 | continue; |
98b37659 |
511 | |
512 | // Save the relation |
513 | TopoDS_Shape* pSolidWas = aHoleSolidMap.ChangeSeek(aHole); |
514 | if (pSolidWas) |
515 | { |
516 | if (IsInside(aSolid, *pSolidWas, myContext)) |
517 | { |
518 | *pSolidWas = aSolid; |
4e57c75e |
519 | } |
520 | } |
98b37659 |
521 | else |
522 | { |
523 | aHoleSolidMap.Add(aHole, aSolid); |
4e57c75e |
524 | } |
525 | } |
682c9d06 |
526 | } |
98b37659 |
527 | |
528 | // Make the back map from solids to holes |
529 | BOPCol_IndexedDataMapOfShapeListOfShape aSolidHolesMap; |
530 | |
531 | aNbH = aHoleSolidMap.Extent(); |
532 | for (i = 1; i <= aNbH; ++i) |
533 | { |
534 | const TopoDS_Shape& aHole = aHoleSolidMap.FindKey(i); |
535 | const TopoDS_Shape& aSolid = aHoleSolidMap(i); |
4e57c75e |
536 | // |
98b37659 |
537 | BOPCol_ListOfShape* pLHoles = aSolidHolesMap.ChangeSeek(aSolid); |
538 | if (!pLHoles) |
539 | pLHoles = &aSolidHolesMap(aSolidHolesMap.Add(aSolid, BOPCol_ListOfShape())); |
540 | pLHoles->Append(aHole); |
4e57c75e |
541 | } |
98b37659 |
542 | |
543 | // Add Holes to Solids and add them to myAreas |
682c9d06 |
544 | aItLS.Initialize(aNewSolids); |
98b37659 |
545 | for ( ; aItLS.More(); aItLS.Next()) |
546 | { |
547 | TopoDS_Solid& aSolid = *(TopoDS_Solid*)&aItLS.Value(); |
548 | const BOPCol_ListOfShape* pLHoles = aSolidHolesMap.Seek(aSolid); |
549 | if (pLHoles) |
550 | { |
551 | // update solid |
552 | BOPCol_ListIteratorOfListOfShape aItLH(*pLHoles); |
553 | for (; aItLH.More(); aItLH.Next()) |
554 | { |
555 | const TopoDS_Shape& aHole = aItLH.Value(); |
556 | aBB.Add(aSolid, aHole); |
557 | } |
558 | |
559 | // update classifier |
560 | myContext->SolidClassifier(aSolid).Load(aSolid); |
561 | } |
562 | |
563 | myAreas.Append(aSolid); |
4e57c75e |
564 | } |
98b37659 |
565 | |
4e57c75e |
566 | // Add holes that outside the solids to myAreas |
98b37659 |
567 | aNbH = aHoleShells.Extent(); |
568 | for (i = 1; i <= aNbH; ++i) |
569 | { |
570 | const TopoDS_Shape& aHole = aHoleShells(i); |
571 | if (!aHoleSolidMap.Contains(aHole)) |
572 | { |
4e57c75e |
573 | TopoDS_Solid aSolid; |
574 | aBB.MakeSolid(aSolid); |
575 | aBB.Add (aSolid, aHole); |
576 | // |
577 | myAreas.Append(aSolid); |
b7cd7c2b |
578 | // Make an infinite box for the hole |
579 | Bnd_Box aBox; |
580 | aBox.SetWhole(); |
581 | myBoxes.Bind(aSolid, aBox); |
4e57c75e |
582 | } |
b7cd7c2b |
583 | |
584 | myBoxes.UnBind(aHole); |
4e57c75e |
585 | } |
586 | } |
587 | //======================================================================= |
588 | //function : PerformInternalShapes |
589 | //purpose : |
590 | //======================================================================= |
30ecd5f8 |
591 | void BOPAlgo_BuilderSolid::PerformInternalShapes() |
4e57c75e |
592 | { |
b7cd7c2b |
593 | if (myAvoidInternalShapes) |
594 | // user-defined option to avoid internal parts is in force |
291fced1 |
595 | return; |
b7cd7c2b |
596 | |
597 | if (myLoopsInternal.IsEmpty()) |
598 | // no internal parts |
4e57c75e |
599 | return; |
b7cd7c2b |
600 | |
601 | // Get all faces to classify |
319da2e4 |
602 | BOPCol_IndexedMapOfShape aMFs; |
b7cd7c2b |
603 | BOPCol_ListIteratorOfListOfShape aItLS(myLoopsInternal); |
604 | for (; aItLS.More(); aItLS.Next()) |
605 | { |
606 | const TopoDS_Shape& aShell = aItLS.Value(); |
607 | TopoDS_Iterator aIt(aShell); |
608 | for (; aIt.More(); aIt.Next()) |
609 | aMFs.Add(aIt.Value()); |
4e57c75e |
610 | } |
b7cd7c2b |
611 | |
612 | BRep_Builder aBB; |
613 | // Check existence of the growths solids |
614 | if (myAreas.IsEmpty()) |
615 | { |
616 | // No areas. |
617 | // Just make solid of the faces |
465d1fba |
618 | TopoDS_Solid aSolid; |
619 | aBB.MakeSolid(aSolid); |
4e57c75e |
620 | // |
b7cd7c2b |
621 | BOPCol_ListOfShape aLSI; |
465d1fba |
622 | MakeInternalShells(aMFs, aLSI); |
623 | // |
624 | aItLS.Initialize(aLSI); |
b7cd7c2b |
625 | for (; aItLS.More(); aItLS.Next()) |
626 | aBB.Add(aSolid, aItLS.Value()); |
627 | |
465d1fba |
628 | myAreas.Append(aSolid); |
465d1fba |
629 | return; |
630 | } |
b7cd7c2b |
631 | |
632 | // Classify faces relatively solids |
633 | |
634 | // Prepare list of faces to classify |
635 | BOPCol_ListOfShape aLFaces; |
636 | Standard_Integer i, aNbF = aMFs.Extent(); |
637 | for (i = 1; i <= aNbF; ++i) |
638 | aLFaces.Append(aMFs(i)); |
639 | |
640 | // Map of solids with IN faces |
465d1fba |
641 | BOPCol_IndexedDataMapOfShapeListOfShape aMSLF; |
b7cd7c2b |
642 | |
643 | // Perform classification |
644 | BOPAlgo_Tools::ClassifyFaces(aLFaces, myAreas, myRunParallel, myContext, aMSLF, myBoxes); |
645 | |
646 | // Update Solids by internal Faces |
647 | |
648 | BOPCol_MapOfShape aMFDone; |
649 | |
650 | Standard_Integer aNbS = aMSLF.Extent(); |
651 | for (i = 1; i <= aNbS; ++i) |
652 | { |
653 | const TopoDS_Shape& aSolid = aMSLF.FindKey(i); |
654 | TopoDS_Shape *pSolid = (TopoDS_Shape*)&aSolid; |
655 | |
656 | const BOPCol_ListOfShape& aLF = aMSLF(i); |
657 | if (aLF.IsEmpty()) |
465d1fba |
658 | continue; |
b7cd7c2b |
659 | |
660 | BOPCol_IndexedMapOfShape aMF; |
465d1fba |
661 | aItLS.Initialize(aLF); |
b7cd7c2b |
662 | for (; aItLS.More(); aItLS.Next()) |
663 | { |
664 | const TopoDS_Shape& aF = aItLS.Value(); |
665 | aMF.Add(aF); |
666 | aMFDone.Add(aF); |
4e57c75e |
667 | } |
465d1fba |
668 | // |
b7cd7c2b |
669 | BOPCol_ListOfShape aLSI; |
670 | MakeInternalShells(aMF, aLSI); |
465d1fba |
671 | // |
672 | aItLS.Initialize(aLSI); |
b7cd7c2b |
673 | for (; aItLS.More(); aItLS.Next()) |
674 | { |
675 | const TopoDS_Shape& aSI = aItLS.Value(); |
465d1fba |
676 | aBB.Add (*pSolid, aSI); |
677 | } |
678 | } |
b7cd7c2b |
679 | |
680 | // Make solid from the unused faces (if any) |
681 | BOPCol_IndexedMapOfShape aMFUnUsed; |
682 | for (i = 1; i <= aNbF; ++i) |
683 | { |
684 | const TopoDS_Shape& aF = aMFs(i); |
685 | if (!aMFDone.Contains(aF)) |
686 | aMFUnUsed.Add(aF); |
465d1fba |
687 | } |
b7cd7c2b |
688 | |
689 | if (aMFUnUsed.Extent()) |
690 | { |
4e57c75e |
691 | TopoDS_Solid aSolid; |
692 | aBB.MakeSolid(aSolid); |
693 | // |
b7cd7c2b |
694 | BOPCol_ListOfShape aLSI; |
695 | MakeInternalShells(aMFUnUsed, aLSI); |
465d1fba |
696 | // |
697 | aItLS.Initialize(aLSI); |
b7cd7c2b |
698 | for (; aItLS.More(); aItLS.Next()) |
699 | { |
700 | const TopoDS_Shape& aSI = aItLS.Value(); |
4e57c75e |
701 | aBB.Add (aSolid, aSI); |
b7cd7c2b |
702 | |
703 | Bnd_Box aBox; |
704 | BRepBndLib::Add(aSolid, aBox); |
705 | myBoxes.Bind(aSolid, aBox); |
4e57c75e |
706 | } |
707 | myAreas.Append(aSolid); |
708 | } |
709 | } |
4e57c75e |
710 | //======================================================================= |
711 | //function : MakeInternalShells |
712 | //purpose : |
713 | //======================================================================= |
319da2e4 |
714 | void MakeInternalShells(const BOPCol_IndexedMapOfShape& theMF, |
4e57c75e |
715 | BOPCol_ListOfShape& theShells) |
716 | { |
319da2e4 |
717 | Standard_Integer i, aNbF; |
4e57c75e |
718 | BRep_Builder aBB; |
319da2e4 |
719 | BOPCol_ListIteratorOfListOfShape aItF; |
4e57c75e |
720 | BOPCol_IndexedDataMapOfShapeListOfShape aMEF; |
4e57c75e |
721 | BOPCol_MapOfShape aAddedFacesMap; |
722 | // |
319da2e4 |
723 | aNbF = theMF.Extent(); |
724 | for (i = 1; i <= aNbF; ++i) { |
725 | TopoDS_Shape aF = theMF(i); |
682c9d06 |
726 | BOPTools::MapShapesAndAncestors(aF, |
1e143abb |
727 | TopAbs_EDGE, TopAbs_FACE, |
728 | aMEF); |
4e57c75e |
729 | } |
730 | // |
319da2e4 |
731 | for (i = 1; i <= aNbF; ++i) { |
732 | TopoDS_Shape aFF = theMF(i); |
4e57c75e |
733 | if (!aAddedFacesMap.Add(aFF)) { |
734 | continue; |
735 | } |
736 | // |
737 | // make a new shell |
738 | TopoDS_Shell aShell; |
739 | aBB.MakeShell(aShell); |
740 | aFF.Orientation(TopAbs_INTERNAL); |
741 | aBB.Add(aShell, aFF); |
742 | // |
743 | TopoDS_Iterator aItAddedF (aShell); |
744 | for (; aItAddedF.More(); aItAddedF.Next()) { |
745 | const TopoDS_Shape& aF =aItAddedF.Value(); |
746 | // |
747 | TopExp_Explorer aEdgeExp(aF, TopAbs_EDGE); |
748 | for (; aEdgeExp.More(); aEdgeExp.Next()) { |
749 | const TopoDS_Shape& aE =aEdgeExp.Current(); |
750 | const BOPCol_ListOfShape& aLF=aMEF.FindFromKey(aE); |
751 | aItF.Initialize(aLF); |
752 | for (; aItF.More(); aItF.Next()) { |
753 | TopoDS_Shape aFL=aItF.Value(); |
754 | if (aAddedFacesMap.Add(aFL)){ |
755 | aFL.Orientation(TopAbs_INTERNAL); |
756 | aBB.Add(aShell, aFL); |
757 | } |
758 | } |
759 | } |
760 | } |
ab860031 |
761 | aShell.Closed (BRep_Tool::IsClosed (aShell)); |
4e57c75e |
762 | theShells.Append(aShell); |
763 | } |
764 | } |
765 | //======================================================================= |
766 | //function : IsHole |
767 | //purpose : |
768 | //======================================================================= |
769 | Standard_Boolean IsHole(const TopoDS_Shape& theS2, |
1e143abb |
770 | Handle(IntTools_Context)& theContext) |
4e57c75e |
771 | { |
772 | TopoDS_Solid *pS2=(TopoDS_Solid *)&theS2; |
773 | BRepClass3d_SolidClassifier& aClsf=theContext->SolidClassifier(*pS2); |
774 | // |
775 | aClsf.PerformInfinitePoint(::RealSmall()); |
776 | // |
777 | return (aClsf.State()==TopAbs_IN); |
778 | } |
779 | //======================================================================= |
780 | //function : IsInside |
781 | //purpose : |
782 | //======================================================================= |
783 | Standard_Boolean IsInside(const TopoDS_Shape& theS1, |
784 | const TopoDS_Shape& theS2, |
1e143abb |
785 | Handle(IntTools_Context)& theContext) |
4e57c75e |
786 | { |
787 | TopExp_Explorer aExp; |
788 | TopAbs_State aState; |
789 | // |
790 | TopoDS_Solid *pS2=(TopoDS_Solid *)&theS2; |
791 | // |
792 | aExp.Init(theS1, TopAbs_FACE); |
793 | if (!aExp.More()){ |
794 | BRepClass3d_SolidClassifier& aClsf=theContext->SolidClassifier(*pS2); |
795 | aClsf.PerformInfinitePoint(::RealSmall()); |
796 | aState=aClsf.State(); |
797 | } |
798 | else { |
799 | BOPCol_IndexedMapOfShape aBounds; |
800 | BOPTools::MapShapes(*pS2, TopAbs_EDGE, aBounds); |
801 | const TopoDS_Face& aF = (*(TopoDS_Face*)(&aExp.Current())); |
92ae0f2f |
802 | aState=BOPTools_AlgoTools::ComputeState(aF, *pS2, |
803 | Precision::Confusion(), |
1e143abb |
804 | aBounds, theContext); |
4e57c75e |
805 | } |
806 | return (aState==TopAbs_IN); |
807 | } |
808 | //======================================================================= |
809 | //function : IsGrowthShell |
810 | //purpose : |
811 | //======================================================================= |
812 | Standard_Boolean IsGrowthShell(const TopoDS_Shape& theShell, |
813 | const BOPCol_IndexedMapOfShape& theMHF) |
814 | { |
98b37659 |
815 | if (theMHF.Extent()) |
816 | { |
817 | TopoDS_Iterator aIt(theShell); |
818 | for(; aIt.More(); aIt.Next()) |
819 | { |
820 | if (theMHF.Contains(aIt.Value())) |
821 | return Standard_True; |
4e57c75e |
822 | } |
823 | } |
98b37659 |
824 | return Standard_False; |
4e57c75e |
825 | } |