4e57c75e |
1 | // Created by: Peter KURNEV |
db8e4b9a |
2 | // Copyright (c) 2010-2012 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 | // |
4e57c75e |
7 | // |
d5f74e42 |
8 | // This file is part of Open CASCADE Technology software library. |
4e57c75e |
9 | // |
d5f74e42 |
10 | // This library is free software; you can redistribute it and/or modify it under |
11 | // the terms of the GNU Lesser General Public License version 2.1 as published |
12 | // by the Free Software Foundation, with special exception defined in the file |
13 | // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT |
14 | // distribution for complete text of the license and disclaimer of any warranty. |
15 | // |
16 | // Alternatively, this file may be used under the terms of Open CASCADE |
17 | // commercial license or contractual agreement. |
4e57c75e |
18 | |
19 | #include <BOPAlgo_BuilderFace.ixx> |
36f4947b |
20 | // |
21 | #include <NCollection_UBTreeFiller.hxx> |
22 | #include <NCollection_DataMap.hxx> |
23 | // |
24 | #include <TColStd_MapIntegerHasher.hxx> |
25 | // |
4e57c75e |
26 | #include <gp_Pnt2d.hxx> |
27 | #include <gp_Pln.hxx> |
28 | #include <gp_Vec.hxx> |
29 | #include <gp_Dir.hxx> |
30 | #include <gp_Pnt.hxx> |
36f4947b |
31 | // |
4e57c75e |
32 | #include <Geom_Surface.hxx> |
36f4947b |
33 | // |
4e57c75e |
34 | #include <TopAbs.hxx> |
35 | #include <TopLoc_Location.hxx> |
36f4947b |
36 | // |
4e57c75e |
37 | #include <TopoDS_Iterator.hxx> |
38 | #include <TopoDS_Face.hxx> |
39 | #include <TopoDS_Shape.hxx> |
40 | #include <TopoDS_Wire.hxx> |
41 | #include <TopoDS_Edge.hxx> |
42 | #include <TopoDS_Vertex.hxx> |
36f4947b |
43 | // |
4e57c75e |
44 | #include <BRep_Builder.hxx> |
45 | #include <BRep_Tool.hxx> |
46 | #include <BRepTools.hxx> |
36f4947b |
47 | // |
d2d9e8dc |
48 | #include <Bnd_Box.hxx> |
49 | // |
50 | #include <BRepBndLib.hxx> |
51 | // |
4e57c75e |
52 | #include <TopExp.hxx> |
53 | #include <TopExp_Explorer.hxx> |
54 | |
55 | #include <IntTools_FClass2d.hxx> |
1e143abb |
56 | #include <IntTools_Context.hxx> |
4e57c75e |
57 | // |
58 | #include <BOPTools_AlgoTools.hxx> |
59 | #include <BOPTools_AlgoTools2D.hxx> |
60 | #include <BOPAlgo_WireEdgeSet.hxx> |
61 | // |
62 | #include <BOPCol_IndexedDataMapOfShapeListOfShape.hxx> |
63 | #include <BOPTools.hxx> |
64 | #include <BOPCol_ListOfShape.hxx> |
36f4947b |
65 | // |
4e57c75e |
66 | #include <BOPCol_DataMapOfShapeShape.hxx> |
67 | #include <BOPCol_DataMapOfShapeListOfShape.hxx> |
68 | #include <BOPCol_MapOfShape.hxx> |
36f4947b |
69 | #include <BOPCol_Box2DBndTree.hxx> |
70 | // |
71 | #include <BOPAlgo_WireSplitter.hxx> |
4e57c75e |
72 | |
73 | static |
74 | Standard_Boolean IsGrowthWire(const TopoDS_Shape& , |
75 | const BOPCol_IndexedMapOfShape& ); |
76 | |
77 | static |
78 | Standard_Boolean IsInside(const TopoDS_Shape& , |
79 | const TopoDS_Shape& , |
1e143abb |
80 | Handle(IntTools_Context)& ); |
4e57c75e |
81 | static |
82 | void MakeInternalWires(const BOPCol_MapOfShape& , |
83 | BOPCol_ListOfShape& ); |
db8e4b9a |
84 | static |
85 | void GetWire(const TopoDS_Shape& , |
1e143abb |
86 | TopoDS_Shape& ); |
db8e4b9a |
87 | // |
36f4947b |
88 | |
db8e4b9a |
89 | // |
90 | //======================================================================= |
91 | //class : BOPAlgo_ShapeBox2D |
92 | //purpose : Auxiliary class |
93 | //======================================================================= |
94 | class BOPAlgo_ShapeBox2D { |
95 | public: |
96 | BOPAlgo_ShapeBox2D() { |
97 | myIsHole=Standard_False; |
98 | }; |
99 | // |
100 | ~BOPAlgo_ShapeBox2D() { |
101 | }; |
102 | // |
103 | void SetShape(const TopoDS_Shape& aS) { |
104 | myShape=aS; |
105 | }; |
106 | // |
107 | const TopoDS_Shape& Shape()const { |
108 | return myShape; |
109 | }; |
110 | // |
111 | void SetBox2D(const Bnd_Box2d& aBox2D) { |
112 | myBox2D=aBox2D; |
113 | }; |
114 | // |
115 | const Bnd_Box2d& Box2D()const { |
116 | return myBox2D; |
117 | }; |
118 | // |
119 | void SetIsHole(const Standard_Boolean bFlag) { |
120 | myIsHole=bFlag; |
121 | }; |
122 | // |
123 | Standard_Boolean IsHole()const { |
124 | return myIsHole; |
125 | }; |
126 | // |
127 | protected: |
128 | Standard_Boolean myIsHole; |
129 | TopoDS_Shape myShape; |
130 | Bnd_Box2d myBox2D; |
131 | }; |
132 | // |
b858a698 |
133 | typedef NCollection_IndexedDataMap |
134 | <Standard_Integer, |
135 | BOPAlgo_ShapeBox2D, |
136 | TColStd_MapIntegerHasher> BOPAlgo_IndexedDataMapOfIntegerShapeBox2D; |
137 | |
138 | typedef NCollection_IndexedDataMap |
139 | <TopoDS_Shape, |
140 | TopoDS_Shape, |
141 | TopTools_ShapeMapHasher> BOPCol_IndexedDataMapOfShapeShape; |
db8e4b9a |
142 | // |
4e57c75e |
143 | //======================================================================= |
144 | //function : |
145 | //purpose : |
146 | //======================================================================= |
db8e4b9a |
147 | BOPAlgo_BuilderFace::BOPAlgo_BuilderFace() |
4e57c75e |
148 | : |
149 | BOPAlgo_BuilderArea() |
150 | { |
acccace3 |
151 | myOrientation=TopAbs_EXTERNAL; |
4e57c75e |
152 | } |
153 | //======================================================================= |
154 | //function : |
155 | //purpose : |
156 | //======================================================================= |
db8e4b9a |
157 | BOPAlgo_BuilderFace::BOPAlgo_BuilderFace |
158 | (const Handle(NCollection_BaseAllocator)& theAllocator) |
4e57c75e |
159 | : |
160 | BOPAlgo_BuilderArea(theAllocator) |
acccace3 |
161 | { |
162 | myOrientation=TopAbs_EXTERNAL; |
4e57c75e |
163 | } |
164 | //======================================================================= |
165 | //function : ~ |
166 | //purpose : |
167 | //======================================================================= |
168 | BOPAlgo_BuilderFace::~BOPAlgo_BuilderFace() |
169 | { |
170 | } |
171 | //======================================================================= |
172 | //function : SetFace |
173 | //purpose : |
174 | //======================================================================= |
db8e4b9a |
175 | void BOPAlgo_BuilderFace::SetFace(const TopoDS_Face& theFace) |
4e57c75e |
176 | { |
acccace3 |
177 | myOrientation=theFace.Orientation(); |
4e57c75e |
178 | myFace=theFace; |
acccace3 |
179 | myFace.Orientation(TopAbs_FORWARD); |
180 | } |
181 | //======================================================================= |
182 | //function : Orientation |
183 | //purpose : |
184 | //======================================================================= |
185 | TopAbs_Orientation BOPAlgo_BuilderFace::Orientation()const |
186 | { |
187 | return myOrientation; |
4e57c75e |
188 | } |
189 | //======================================================================= |
190 | //function : Face |
191 | //purpose : |
192 | //======================================================================= |
db8e4b9a |
193 | const TopoDS_Face& BOPAlgo_BuilderFace::Face()const |
4e57c75e |
194 | { |
195 | return myFace; |
196 | } |
197 | //======================================================================= |
198 | //function : CheckData |
199 | //purpose : |
200 | //======================================================================= |
db8e4b9a |
201 | void BOPAlgo_BuilderFace::CheckData() |
4e57c75e |
202 | { |
203 | myErrorStatus=0; |
204 | // |
4e57c75e |
205 | if (myFace.IsNull()) { |
206 | myErrorStatus=12;// Null face generix |
207 | return; |
208 | } |
db8e4b9a |
209 | if (myContext.IsNull()) { |
1e143abb |
210 | myContext = new IntTools_Context; |
db8e4b9a |
211 | } |
4e57c75e |
212 | } |
213 | //======================================================================= |
214 | //function : Perform |
215 | //purpose : |
216 | //======================================================================= |
db8e4b9a |
217 | void BOPAlgo_BuilderFace::Perform() |
4e57c75e |
218 | { |
219 | myErrorStatus=0; |
220 | // |
221 | CheckData(); |
222 | if (myErrorStatus) { |
223 | return; |
224 | } |
225 | // |
36f4947b |
226 | UserBreak(); |
227 | // |
4e57c75e |
228 | PerformShapesToAvoid(); |
229 | if (myErrorStatus) { |
230 | return; |
231 | } |
232 | // |
36f4947b |
233 | UserBreak(); |
234 | // |
4e57c75e |
235 | PerformLoops(); |
236 | if (myErrorStatus) { |
237 | return; |
238 | } |
239 | // |
36f4947b |
240 | UserBreak(); |
241 | // |
4e57c75e |
242 | PerformAreas(); |
243 | if (myErrorStatus) { |
244 | return; |
245 | } |
246 | // |
36f4947b |
247 | UserBreak(); |
248 | // |
4e57c75e |
249 | PerformInternalShapes(); |
250 | if (myErrorStatus) { |
251 | return; |
252 | } |
253 | } |
254 | //======================================================================= |
255 | //function :PerformShapesToAvoid |
256 | //purpose : |
257 | //======================================================================= |
db8e4b9a |
258 | void BOPAlgo_BuilderFace::PerformShapesToAvoid() |
4e57c75e |
259 | { |
260 | Standard_Boolean bFound; |
261 | Standard_Integer i, iCnt, aNbV, aNbE; |
262 | BOPCol_IndexedDataMapOfShapeListOfShape aMVE; |
263 | BOPCol_ListIteratorOfListOfShape aIt; |
264 | // |
265 | myShapesToAvoid.Clear(); |
266 | // |
267 | iCnt=0; |
302f96fb |
268 | for(;;) { |
4e57c75e |
269 | ++iCnt; |
270 | bFound=Standard_False; |
271 | // |
272 | // 1. MEF |
273 | aMVE.Clear(); |
274 | aIt.Initialize (myShapes); |
275 | for (; aIt.More(); aIt.Next()) { |
276 | const TopoDS_Shape& aE=aIt.Value(); |
277 | if (!myShapesToAvoid.Contains(aE)) { |
278 | BOPTools::MapShapesAndAncestors(aE, TopAbs_VERTEX, TopAbs_EDGE, aMVE); |
279 | } |
4e57c75e |
280 | } |
281 | aNbV=aMVE.Extent(); |
282 | // |
283 | // 2. myEdgesToAvoid |
284 | for (i=1; i<=aNbV; ++i) { |
285 | const TopoDS_Vertex& aV=(*(TopoDS_Vertex *)(&aMVE.FindKey(i))); |
286 | // |
287 | BOPCol_ListOfShape& aLE=aMVE.ChangeFromKey(aV); |
288 | aNbE=aLE.Extent(); |
289 | if (!aNbE) { |
290 | continue; |
291 | } |
292 | // |
293 | const TopoDS_Edge& aE1=(*(TopoDS_Edge *)(&aLE.First())); |
294 | if (aNbE==1) { |
295 | if (BRep_Tool::Degenerated(aE1)) { |
296 | continue; |
297 | } |
298 | if (aV.Orientation()==TopAbs_INTERNAL) { |
299 | continue; |
300 | } |
301 | bFound=Standard_True; |
302 | myShapesToAvoid.Add(aE1); |
303 | } |
304 | else if (aNbE==2) { |
305 | const TopoDS_Edge& aE2=(*(TopoDS_Edge *)(&aLE.Last())); |
306 | if (aE2.IsSame(aE1)) { |
307 | TopoDS_Vertex aV1x, aV2x; |
308 | // |
309 | TopExp::Vertices(aE1, aV1x, aV2x); |
310 | if (aV1x.IsSame(aV2x)) { |
311 | continue; |
312 | } |
313 | bFound=Standard_True; |
314 | myShapesToAvoid.Add(aE1); |
315 | myShapesToAvoid.Add(aE2); |
316 | } |
317 | } |
318 | }// for (i=1; i<=aNbE; ++i) { |
319 | // |
320 | if (!bFound) { |
321 | break; |
322 | } |
323 | // |
324 | }//while (1) |
325 | //printf(" EdgesToAvoid=%d, iCnt=%d\n", EdgesToAvoid.Extent(), iCnt); |
326 | } |
327 | //======================================================================= |
328 | //function : PerformLoops |
329 | //purpose : |
330 | //======================================================================= |
db8e4b9a |
331 | void BOPAlgo_BuilderFace::PerformLoops() |
4e57c75e |
332 | { |
333 | myErrorStatus=0; |
334 | // |
335 | Standard_Boolean bFlag; |
336 | Standard_Integer iErr, aNbEA; |
337 | BOPCol_ListIteratorOfListOfShape aIt; |
338 | BOPCol_MapIteratorOfMapOfOrientedShape aItM; |
339 | BOPCol_IndexedDataMapOfShapeListOfShape aVEMap; |
340 | BOPCol_MapOfOrientedShape aMAdded; |
341 | TopoDS_Iterator aItW; |
342 | BRep_Builder aBB; |
343 | BOPAlgo_WireEdgeSet aWES(myAllocator); |
344 | BOPAlgo_WireSplitter aWSp(myAllocator); |
345 | // |
346 | // 1. |
347 | myLoops.Clear(); |
348 | aWES.SetFace(myFace); |
349 | // |
350 | aIt.Initialize(myShapes); |
351 | for (; aIt.More(); aIt.Next()) { |
352 | const TopoDS_Shape& aE=aIt.Value(); |
353 | if (!myShapesToAvoid.Contains(aE)) { |
354 | aWES.AddStartElement(aE); |
355 | } |
356 | } |
357 | // |
358 | aWSp.SetWES(aWES); |
db8e4b9a |
359 | aWSp.SetRunParallel(myRunParallel); |
4e57c75e |
360 | aWSp.Perform(); |
361 | iErr=aWSp.ErrorStatus(); |
362 | if (iErr) { |
363 | return; |
364 | } |
365 | // |
366 | const BOPCol_ListOfShape& aLW=aWES.Shapes(); |
367 | aIt.Initialize (aLW); |
368 | for (; aIt.More(); aIt.Next()) { |
369 | const TopoDS_Shape& aW=aIt.Value(); |
370 | myLoops.Append(aW); |
371 | } |
372 | // Post Treatment |
373 | BOPCol_MapOfOrientedShape aMEP; |
374 | // |
375 | // a. collect all edges that are in loops |
376 | aIt.Initialize (myLoops); |
377 | for (; aIt.More(); aIt.Next()) { |
378 | const TopoDS_Shape& aW=aIt.Value(); |
379 | aItW.Initialize(aW); |
380 | for (; aItW.More(); aItW.Next()) { |
381 | const TopoDS_Shape& aE=aItW.Value(); |
382 | aMEP.Add(aE); |
383 | } |
384 | } |
385 | // |
386 | // b. collect all edges that are to avoid |
387 | aItM.Initialize(myShapesToAvoid); |
388 | for (; aItM.More(); aItM.Next()) { |
389 | const TopoDS_Shape& aE=aItM.Key(); |
390 | aMEP.Add(aE); |
391 | } |
392 | // |
393 | // c. add all edges that are not processed to myShapesToAvoid |
394 | aIt.Initialize (myShapes); |
395 | for (; aIt.More(); aIt.Next()) { |
396 | const TopoDS_Shape& aE=aIt.Value(); |
397 | if (!aMEP.Contains(aE)) { |
398 | myShapesToAvoid.Add(aE); |
399 | } |
400 | } |
401 | // |
402 | // 2. Internal Wires |
403 | myLoopsInternal.Clear(); |
404 | // |
405 | aNbEA=myShapesToAvoid.Extent(); |
406 | aItM.Initialize(myShapesToAvoid); |
407 | for (; aItM.More(); aItM.Next()) { |
408 | const TopoDS_Shape& aEE=aItM.Key(); |
1e143abb |
409 | BOPTools::MapShapesAndAncestors(aEE, |
410 | TopAbs_VERTEX, |
411 | TopAbs_EDGE, |
412 | aVEMap); |
4e57c75e |
413 | } |
414 | // |
415 | bFlag=Standard_True; |
416 | aItM.Initialize(myShapesToAvoid); |
417 | for (; aItM.More()&&bFlag; aItM.Next()) { |
418 | const TopoDS_Shape& aEE=aItM.Key(); |
419 | if (!aMAdded.Add(aEE)) { |
420 | continue; |
421 | } |
422 | // |
423 | // make new wire |
424 | TopoDS_Wire aW; |
425 | aBB.MakeWire(aW); |
426 | aBB.Add(aW, aEE); |
427 | // |
428 | aItW.Initialize(aW); |
429 | for (; aItW.More()&&bFlag; aItW.Next()) { |
430 | const TopoDS_Edge& aE=(*(TopoDS_Edge *)(&aItW.Value())); |
431 | // |
432 | TopoDS_Iterator aItE(aE); |
433 | for (; aItE.More()&&bFlag; aItE.Next()) { |
434 | const TopoDS_Vertex& aV = (*(TopoDS_Vertex *)(&aItE.Value())); |
435 | const BOPCol_ListOfShape& aLE=aVEMap.FindFromKey(aV); |
436 | aIt.Initialize(aLE); |
437 | for (; aIt.More()&&bFlag; aIt.Next()) { |
438 | const TopoDS_Shape& aEx=aIt.Value(); |
439 | if (aMAdded.Add(aEx)) { |
440 | aBB.Add(aW, aEx); |
441 | if(aMAdded.Extent()==aNbEA) { |
442 | bFlag=!bFlag; |
443 | } |
444 | } |
445 | }//for (; aIt.More(); aIt.Next()) { |
446 | }//for (; aItE.More(); aItE.Next()) { |
447 | }//for (; aItW.More(); aItW.Next()) { |
448 | myLoopsInternal.Append(aW); |
449 | }//for (; aItM.More(); aItM.Next()) { |
450 | } |
451 | //======================================================================= |
452 | //function : PerformAreas |
453 | //purpose : |
454 | //======================================================================= |
db8e4b9a |
455 | void BOPAlgo_BuilderFace::PerformAreas() |
4e57c75e |
456 | { |
4e57c75e |
457 | Standard_Boolean bIsGrowth, bIsHole; |
d2d9e8dc |
458 | Standard_Integer k, aNbS, aNbHoles, aNbDMISB, m, aNbMSH, aNbInOutMap; |
4e57c75e |
459 | Standard_Real aTol; |
db8e4b9a |
460 | TopLoc_Location aLoc; |
461 | Handle(Geom_Surface) aS; |
462 | BRep_Builder aBB; |
463 | TopoDS_Face aFace; |
db8e4b9a |
464 | BOPCol_ListIteratorOfListOfInteger aItLI; |
465 | BOPCol_IndexedMapOfShape aMHE; |
db8e4b9a |
466 | BOPCol_ListIteratorOfListOfShape aIt1; |
b858a698 |
467 | BOPCol_IndexedDataMapOfShapeListOfShape aMSH; |
468 | BOPCol_IndexedDataMapOfShapeShape aInOutMap; |
469 | BOPAlgo_IndexedDataMapOfIntegerShapeBox2D aDMISB(100); |
db8e4b9a |
470 | // |
471 | BOPCol_Box2DBndTreeSelector aSelector; |
472 | BOPCol_Box2DBndTree aBBTree; |
473 | NCollection_UBTreeFiller <Standard_Integer, Bnd_Box2d> aTreeFiller(aBBTree); |
474 | // |
475 | myErrorStatus=0; |
d2d9e8dc |
476 | aNbHoles=0; |
4e57c75e |
477 | // |
478 | aTol=BRep_Tool::Tolerance(myFace); |
479 | aS=BRep_Tool::Surface(myFace, aLoc); |
480 | // |
481 | myAreas.Clear(); |
482 | // |
f47b8d2b |
483 | if (myLoops.IsEmpty()) { |
484 | if (myContext->IsInfiniteFace(myFace)) { |
485 | aBB.MakeFace(aFace, aS, aLoc, aTol); |
486 | if (BRep_Tool::NaturalRestriction(myFace)) { |
487 | aBB.NaturalRestriction(aFace, Standard_True); |
488 | } |
489 | myAreas.Append(aFace); |
490 | } |
491 | return; |
492 | } |
493 | // |
db8e4b9a |
494 | // 1. Growthes and Holes -> aDMISB: [Index/ShapeBox2D] |
4e57c75e |
495 | aIt1.Initialize(myLoops); |
db8e4b9a |
496 | for (k=0 ; aIt1.More(); aIt1.Next(), ++k) { |
497 | Bnd_Box2d aBox2D; |
498 | // |
4e57c75e |
499 | const TopoDS_Shape& aWire=aIt1.Value(); |
500 | // |
db8e4b9a |
501 | aBB.MakeFace(aFace, aS, aLoc, aTol); |
502 | aBB.Add (aFace, aWire); |
503 | BRepTools::AddUVBounds(aFace, aBox2D); |
504 | // |
4e57c75e |
505 | bIsGrowth=IsGrowthWire(aWire, aMHE); |
506 | if (bIsGrowth) { |
db8e4b9a |
507 | bIsHole=Standard_False; |
4e57c75e |
508 | } |
509 | else{ |
510 | // check if a wire is a hole |
4e57c75e |
511 | IntTools_FClass2d& aClsf=myContext->FClass2d(aFace); |
512 | aClsf.Init(aFace, aTol); |
513 | // |
514 | bIsHole=aClsf.IsHole(); |
4e57c75e |
515 | if (bIsHole) { |
4e57c75e |
516 | BOPTools::MapShapes(aWire, TopAbs_EDGE, aMHE); |
d2d9e8dc |
517 | // |
518 | bIsHole=Standard_True; |
4e57c75e |
519 | } |
520 | else { |
1e143abb |
521 | bIsHole=Standard_False; |
4e57c75e |
522 | } |
523 | } |
db8e4b9a |
524 | // |
525 | BOPAlgo_ShapeBox2D aSB2D; |
526 | // |
527 | aSB2D.SetShape(aFace); |
528 | aSB2D.SetBox2D(aBox2D); |
529 | aSB2D.SetIsHole(bIsHole); |
530 | // |
b858a698 |
531 | aDMISB.Add(k, aSB2D); |
532 | }// for (k=0 ; aIt1.More(); aIt1.Next(), ++k) { |
db8e4b9a |
533 | // |
534 | // 2. Prepare TreeFiller |
b858a698 |
535 | aNbDMISB=aDMISB.Extent(); |
536 | for (m=1; m<=aNbDMISB; ++m) { |
537 | k=aDMISB.FindKey(m); |
538 | const BOPAlgo_ShapeBox2D& aSB2D=aDMISB.FindFromIndex(m); |
db8e4b9a |
539 | // |
540 | bIsHole=aSB2D.IsHole(); |
541 | if (bIsHole) { |
542 | const Bnd_Box2d& aBox2D=aSB2D.Box2D(); |
543 | aTreeFiller.Add(k, aBox2D); |
d2d9e8dc |
544 | ++aNbHoles; |
db8e4b9a |
545 | } |
4e57c75e |
546 | } |
547 | // |
db8e4b9a |
548 | // 3. Shake TreeFiller |
549 | aTreeFiller.Fill(); |
550 | // |
551 | // 4. Find outer growth shell that is most close |
552 | // to each hole shell |
b858a698 |
553 | for (m=1; m<=aNbDMISB; ++m) { |
554 | const BOPAlgo_ShapeBox2D& aSB2D=aDMISB.FindFromIndex(m); |
db8e4b9a |
555 | bIsHole=aSB2D.IsHole(); |
556 | if (bIsHole) { |
557 | continue; |
558 | } |
559 | // |
560 | const Bnd_Box2d& aBox2DF=aSB2D.Box2D(); |
561 | const TopoDS_Shape aF=aSB2D.Shape(); |
4e57c75e |
562 | // |
db8e4b9a |
563 | aSelector.Clear(); |
564 | aSelector.SetBox(aBox2DF); |
565 | // |
d2d9e8dc |
566 | aNbS = aBBTree.Select(aSelector); |
567 | if (!aNbS) { |
568 | continue; |
569 | } |
db8e4b9a |
570 | // |
571 | const BOPCol_ListOfInteger& aLI=aSelector.Indices(); |
572 | // |
573 | aItLI.Initialize(aLI); |
574 | for (; aItLI.More(); aItLI.Next()) { |
575 | k=aItLI.Value(); |
b858a698 |
576 | const BOPAlgo_ShapeBox2D& aSB2Dk=aDMISB.FindFromKey(k); |
db8e4b9a |
577 | const TopoDS_Shape& aHole=aSB2Dk.Shape(); |
4e57c75e |
578 | // |
579 | if (!IsInside(aHole, aF, myContext)){ |
580 | continue; |
581 | } |
582 | // |
b858a698 |
583 | if (aInOutMap.Contains(aHole)){ |
584 | TopoDS_Shape& aF2=aInOutMap.ChangeFromKey(aHole); |
1e143abb |
585 | if (IsInside(aF, aF2, myContext)) { |
b858a698 |
586 | aF2=aF; |
4e57c75e |
587 | } |
588 | } |
589 | else{ |
b858a698 |
590 | aInOutMap.Add(aHole, aF); |
4e57c75e |
591 | } |
592 | } |
b858a698 |
593 | }// for (m=1; m<=aNbDMISB; ++m) |
db8e4b9a |
594 | // |
d2d9e8dc |
595 | // 5.1 Map [Face/Holes] -> aMSH |
b858a698 |
596 | aNbInOutMap=aInOutMap.Extent(); |
597 | for (m=1; m<=aNbInOutMap; ++m) { |
598 | const TopoDS_Shape& aHole=aInOutMap.FindKey(m); |
599 | const TopoDS_Shape& aF=aInOutMap.FindFromIndex(m); |
4e57c75e |
600 | // |
b858a698 |
601 | if (aMSH.Contains(aF)) { |
602 | BOPCol_ListOfShape& aLH=aMSH.ChangeFromKey(aF); |
db8e4b9a |
603 | aLH.Append(aHole); |
4e57c75e |
604 | } |
db8e4b9a |
605 | else { |
606 | BOPCol_ListOfShape aLH; |
607 | aLH.Append(aHole); |
b858a698 |
608 | aMSH.Add(aF, aLH); |
db8e4b9a |
609 | } |
610 | } |
4e57c75e |
611 | // |
d2d9e8dc |
612 | // 5.2. Add unused holes to the original face |
613 | if (aNbHoles != aNbInOutMap) { |
614 | Bnd_Box aBoxF; |
615 | BRepBndLib::Add(myFace, aBoxF); |
616 | if (aBoxF.IsOpenXmin() || aBoxF.IsOpenXmax() || |
617 | aBoxF.IsOpenYmin() || aBoxF.IsOpenYmax() || |
618 | aBoxF.IsOpenZmin() || aBoxF.IsOpenZmax()) { |
619 | // |
620 | BOPCol_ListOfShape anUnUsedHoles; |
621 | for (m = 1; m <= aNbDMISB; ++m) { |
622 | const BOPAlgo_ShapeBox2D& aSB2D=aDMISB.FindFromIndex(m); |
623 | if (aSB2D.IsHole()) { |
624 | const TopoDS_Shape& aHole = aSB2D.Shape(); |
625 | if (!aInOutMap.Contains(aHole)) { |
626 | anUnUsedHoles.Append(aHole); |
627 | } |
628 | } |
629 | } |
630 | // |
631 | if (anUnUsedHoles.Extent()) { |
632 | TopoDS_Face aFace; |
633 | aBB.MakeFace(aFace, aS, aLoc, aTol); |
634 | aMSH.Add(aFace, anUnUsedHoles); |
635 | // |
636 | BOPAlgo_ShapeBox2D aSB2D; |
637 | // |
638 | aSB2D.SetShape(aFace); |
639 | aSB2D.SetIsHole(Standard_False); |
640 | // |
641 | aDMISB.Add(aNbDMISB, aSB2D); |
642 | ++aNbDMISB; |
643 | } |
644 | } |
645 | } |
646 | // |
b858a698 |
647 | // 6. Add aHoles to Faces |
648 | aNbMSH=aMSH.Extent(); |
649 | for (m=1; m<=aNbMSH; ++m) { |
650 | TopoDS_Face aF=(*(TopoDS_Face *)(&aMSH.FindKey(m))); |
651 | const BOPCol_ListOfShape& aLH=aMSH.FindFromIndex(m); |
4e57c75e |
652 | // |
db8e4b9a |
653 | aIt1.Initialize(aLH); |
654 | for (; aIt1.More(); aIt1.Next()) { |
655 | TopoDS_Shape aWHole; |
656 | // |
657 | const TopoDS_Shape& aFHole=aIt1.Value(); |
658 | GetWire(aFHole, aWHole); |
659 | aBB.Add (aF, aWHole); |
4e57c75e |
660 | } |
661 | // |
662 | // update classifier |
663 | aTol=BRep_Tool::Tolerance(aF); |
664 | IntTools_FClass2d& aClsf=myContext->FClass2d(aF); |
665 | aClsf.Init(aF, aTol); |
666 | } |
667 | // |
db8e4b9a |
668 | // 7. Fill myAreas |
669 | // NB:These aNewFaces are draft faces that |
670 | // do not contain any internal shapes |
b858a698 |
671 | for (m=1; m<=aNbDMISB; ++m) { |
672 | const BOPAlgo_ShapeBox2D& aSB2D=aDMISB.FindFromIndex(m); |
db8e4b9a |
673 | bIsHole=aSB2D.IsHole(); |
674 | if (!bIsHole) { |
675 | const TopoDS_Shape aF=aSB2D.Shape(); |
676 | myAreas.Append(aF); |
677 | } |
678 | } |
679 | } |
680 | //======================================================================= |
681 | //function : GetWire |
682 | //purpose : |
683 | //======================================================================= |
684 | void GetWire(const TopoDS_Shape& aF, TopoDS_Shape& aW) |
685 | { |
686 | TopoDS_Shape aWx; |
687 | TopoDS_Iterator aIt; |
4e57c75e |
688 | // |
db8e4b9a |
689 | aIt.Initialize(aF); |
690 | for (; aIt.More(); aIt.Next()) { |
691 | aW=aIt.Value(); |
4e57c75e |
692 | } |
693 | } |
694 | //======================================================================= |
695 | //function : PerformInternalShapes |
696 | //purpose : |
697 | //======================================================================= |
db8e4b9a |
698 | void BOPAlgo_BuilderFace::PerformInternalShapes() |
4e57c75e |
699 | { |
700 | myErrorStatus=0; |
701 | // |
702 | Standard_Integer aNbWI=myLoopsInternal.Extent(); |
703 | if (!aNbWI) {// nothing to do |
704 | return; |
705 | } |
706 | // |
707 | //Standard_Real aTol; |
708 | BRep_Builder aBB; |
709 | BOPCol_ListIteratorOfListOfShape aIt1, aIt2; |
710 | TopoDS_Iterator aIt; |
711 | BOPCol_MapOfShape aME, aMEP; |
712 | BOPCol_MapIteratorOfMapOfShape aItME; |
713 | BOPCol_IndexedDataMapOfShapeListOfShape aMVE; |
714 | BOPCol_ListOfShape aLSI; |
715 | // |
716 | // 1. All internal edges |
717 | aIt1.Initialize(myLoopsInternal); |
718 | for (; aIt1.More(); aIt1.Next()) { |
719 | const TopoDS_Shape& aWire=aIt1.Value(); |
720 | aIt.Initialize(aWire); |
721 | for (; aIt.More(); aIt.Next()) { |
722 | const TopoDS_Shape& aE=aIt.Value(); |
723 | aME.Add(aE); |
724 | } |
725 | } |
726 | aNbWI=aME.Extent(); |
727 | // |
728 | // 2 Process faces |
729 | aIt2.Initialize(myAreas); |
730 | for ( ; aIt2.More(); aIt2.Next()) { |
731 | TopoDS_Face& aF=(*(TopoDS_Face *)(&aIt2.Value())); |
732 | // |
733 | aMVE.Clear(); |
734 | BOPTools::MapShapesAndAncestors(aF, TopAbs_VERTEX, TopAbs_EDGE, aMVE); |
735 | // |
736 | // 2.1 Separate faces to process aMEP |
737 | aMEP.Clear(); |
738 | aItME.Initialize(aME); |
739 | for (; aItME.More(); aItME.Next()) { |
740 | const TopoDS_Edge& aE=(*(TopoDS_Edge *)(&aItME.Key())); |
741 | if (IsInside(aE, aF, myContext)) { |
742 | aMEP.Add(aE); |
743 | } |
744 | } |
745 | // |
746 | // 2.2 Make Internal Wires |
747 | aLSI.Clear(); |
748 | MakeInternalWires(aMEP, aLSI); |
749 | // |
750 | // 2.3 Add them to aF |
751 | aIt1.Initialize(aLSI); |
752 | for (; aIt1.More(); aIt1.Next()) { |
753 | const TopoDS_Shape& aSI=aIt1.Value(); |
754 | aBB.Add (aF, aSI); |
755 | } |
756 | // |
757 | // 2.4 Remove faces aMFP from aMF |
758 | aItME.Initialize(aMEP); |
759 | for (; aItME.More(); aItME.Next()) { |
760 | const TopoDS_Shape& aE=aItME.Key(); |
761 | aME.Remove(aE); |
762 | } |
763 | // |
764 | aNbWI=aME.Extent(); |
765 | if (!aNbWI) { |
766 | break; |
767 | } |
768 | } //for ( ; aIt2.More(); aIt2.Next()) { |
769 | } |
770 | //======================================================================= |
771 | //function : MakeInternalWires |
772 | //purpose : |
773 | //======================================================================= |
774 | void MakeInternalWires(const BOPCol_MapOfShape& theME, |
775 | BOPCol_ListOfShape& theWires) |
776 | { |
777 | BOPCol_MapIteratorOfMapOfShape aItM; |
778 | BOPCol_MapOfShape aAddedMap; |
779 | BOPCol_ListIteratorOfListOfShape aItE; |
780 | BOPCol_IndexedDataMapOfShapeListOfShape aMVE; |
781 | BRep_Builder aBB; |
782 | // |
783 | aItM.Initialize(theME); |
784 | for (; aItM.More(); aItM.Next()) { |
785 | const TopoDS_Shape& aE=aItM.Key(); |
786 | BOPTools::MapShapesAndAncestors(aE, TopAbs_VERTEX, TopAbs_EDGE, aMVE); |
787 | } |
788 | // |
789 | aItM.Initialize(theME); |
790 | for (; aItM.More(); aItM.Next()) { |
791 | TopoDS_Shape aEE=aItM.Key(); |
792 | if (!aAddedMap.Add(aEE)) { |
793 | continue; |
794 | } |
795 | // |
796 | // make a new shell |
797 | TopoDS_Wire aW; |
798 | aBB.MakeWire(aW); |
799 | aEE.Orientation(TopAbs_INTERNAL); |
800 | aBB.Add(aW, aEE); |
801 | // |
802 | TopoDS_Iterator aItAdded (aW); |
803 | for (; aItAdded.More(); aItAdded.Next()) { |
804 | const TopoDS_Shape& aE =aItAdded.Value(); |
805 | // |
806 | TopExp_Explorer aExp(aE, TopAbs_VERTEX); |
807 | for (; aExp.More(); aExp.Next()) { |
808 | const TopoDS_Shape& aV =aExp.Current(); |
809 | const BOPCol_ListOfShape& aLE=aMVE.FindFromKey(aV); |
810 | aItE.Initialize(aLE); |
811 | for (; aItE.More(); aItE.Next()) { |
812 | TopoDS_Shape aEL=aItE.Value(); |
813 | if (aAddedMap.Add(aEL)){ |
814 | aEL.Orientation(TopAbs_INTERNAL); |
815 | aBB.Add(aW, aEL); |
816 | } |
817 | } |
818 | } |
819 | } |
820 | theWires.Append(aW); |
821 | } |
822 | } |
823 | //======================================================================= |
824 | //function : IsInside |
825 | //purpose : |
826 | //======================================================================= |
827 | Standard_Boolean IsInside(const TopoDS_Shape& theHole, |
828 | const TopoDS_Shape& theF2, |
1e143abb |
829 | Handle(IntTools_Context)& theContext) |
4e57c75e |
830 | { |
831 | Standard_Boolean bRet; |
832 | Standard_Real aT, aU, aV; |
833 | |
834 | TopAbs_State aState; |
835 | TopExp_Explorer aExp; |
836 | BOPCol_IndexedMapOfShape aME2; |
837 | gp_Pnt2d aP2D; |
838 | // |
839 | bRet=Standard_False; |
840 | aState=TopAbs_UNKNOWN; |
841 | const TopoDS_Face& aF2=(*(TopoDS_Face *)(&theF2)); |
842 | // |
843 | BOPTools::MapShapes(aF2, TopAbs_EDGE, aME2);//AA |
844 | // |
845 | aExp.Init(theHole, TopAbs_EDGE); |
846 | if (aExp.More()) { |
847 | const TopoDS_Edge& aE =(*(TopoDS_Edge *)(&aExp.Current())); |
848 | if (aME2.Contains(aE)) { |
849 | return bRet; |
850 | } |
851 | if (!BRep_Tool::Degenerated(aE)) { |
852 | // |
853 | aT=BOPTools_AlgoTools2D::IntermediatePoint(aE); |
854 | BOPTools_AlgoTools2D::PointOnSurface(aE, aF2, aT, aU, aV); |
855 | aP2D.SetCoord(aU, aV); |
856 | // |
857 | IntTools_FClass2d& aClsf=theContext->FClass2d(aF2); |
858 | aState=aClsf.Perform(aP2D); |
859 | bRet=(aState==TopAbs_IN); |
860 | } |
861 | } |
862 | // |
863 | return bRet; |
864 | } |
865 | |
866 | //======================================================================= |
867 | //function : IsGrowthWire |
868 | //purpose : |
869 | //======================================================================= |
870 | Standard_Boolean IsGrowthWire(const TopoDS_Shape& theWire, |
871 | const BOPCol_IndexedMapOfShape& theMHE) |
872 | { |
873 | Standard_Boolean bRet; |
874 | TopoDS_Iterator aIt; |
875 | // |
876 | bRet=Standard_False; |
877 | if (theMHE.Extent()) { |
878 | aIt.Initialize(theWire); |
879 | for(; aIt.More(); aIt.Next()) { |
880 | const TopoDS_Shape& aE=aIt.Value(); |
881 | if (theMHE.Contains(aE)) { |
882 | return !bRet; |
883 | } |
884 | } |
885 | } |
886 | return bRet; |
887 | } |
888 | |
889 | //BRepTools::Write(aFF, "ff"); |
890 | // |
891 | // ErrorStatus : |
892 | // 11 - Null Context |
893 | // 12 - Null face generix |