0031682: Visualization - Prs3d_ShadingAspect::SetTransparency() has no effect with...
[occt.git] / src / BOPAlgo / BOPAlgo_BuilderFace.cxx
CommitLineData
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
42cf5bc1 19#include <Bnd_Box.hxx>
1155d05a 20#include <Bnd_Box2d.hxx>
42cf5bc1 21#include <BOPAlgo_BuilderFace.hxx>
22#include <BOPAlgo_WireEdgeSet.hxx>
23#include <BOPAlgo_WireSplitter.hxx>
33ba8565 24#include <BOPAlgo_Alerts.hxx>
42cf5bc1 25#include <BOPTools_AlgoTools.hxx>
26#include <BOPTools_AlgoTools2D.hxx>
9324aa2d 27#include <BOPTools_BoxTree.hxx>
28#include <Bnd_Tools.hxx>
42cf5bc1 29#include <BRep_Builder.hxx>
30#include <BRep_Tool.hxx>
31#include <BRepBndLib.hxx>
32#include <BRepTools.hxx>
33#include <Geom_Surface.hxx>
4e57c75e 34#include <gp_Dir.hxx>
42cf5bc1 35#include <gp_Pln.hxx>
4e57c75e 36#include <gp_Pnt.hxx>
42cf5bc1 37#include <gp_Pnt2d.hxx>
38#include <gp_Vec.hxx>
39#include <IntTools_Context.hxx>
40#include <IntTools_FClass2d.hxx>
41#include <NCollection_DataMap.hxx>
d3578357 42#include <TColStd_MapOfInteger.hxx>
4e57c75e 43#include <TopAbs.hxx>
42cf5bc1 44#include <TopExp.hxx>
45#include <TopExp_Explorer.hxx>
4e57c75e 46#include <TopLoc_Location.hxx>
98b37659 47#include <TopoDS.hxx>
42cf5bc1 48#include <TopoDS_Edge.hxx>
4e57c75e 49#include <TopoDS_Face.hxx>
42cf5bc1 50#include <TopoDS_Iterator.hxx>
4e57c75e 51#include <TopoDS_Shape.hxx>
4e57c75e 52#include <TopoDS_Vertex.hxx>
42cf5bc1 53#include <TopoDS_Wire.hxx>
1155d05a 54#include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
55#include <TopTools_IndexedDataMapOfShapeShape.hxx>
56#include <TopTools_ListOfShape.hxx>
57#include <TopTools_MapOfShape.hxx>
58#include <TopTools_MapOfOrientedShape.hxx>
36f4947b 59//
4e57c75e 60static
61 Standard_Boolean IsGrowthWire(const TopoDS_Shape& ,
1155d05a 62 const TopTools_IndexedMapOfShape& );
4e57c75e 63
64static
65 Standard_Boolean IsInside(const TopoDS_Shape& ,
66 const TopoDS_Shape& ,
1e143abb 67 Handle(IntTools_Context)& );
4e57c75e 68static
1155d05a 69 void MakeInternalWires(const TopTools_IndexedMapOfShape& ,
70 TopTools_ListOfShape& );
b858a698 71
4e57c75e 72//=======================================================================
73//function :
74//purpose :
75//=======================================================================
db8e4b9a 76BOPAlgo_BuilderFace::BOPAlgo_BuilderFace()
4e57c75e 77:
78 BOPAlgo_BuilderArea()
79{
acccace3 80 myOrientation=TopAbs_EXTERNAL;
4e57c75e 81}
82//=======================================================================
83//function :
84//purpose :
85//=======================================================================
db8e4b9a 86BOPAlgo_BuilderFace::BOPAlgo_BuilderFace
87 (const Handle(NCollection_BaseAllocator)& theAllocator)
4e57c75e 88:
89 BOPAlgo_BuilderArea(theAllocator)
acccace3 90{
91 myOrientation=TopAbs_EXTERNAL;
4e57c75e 92}
93//=======================================================================
94//function : ~
95//purpose :
96//=======================================================================
97 BOPAlgo_BuilderFace::~BOPAlgo_BuilderFace()
98{
99}
100//=======================================================================
101//function : SetFace
102//purpose :
103//=======================================================================
db8e4b9a 104void BOPAlgo_BuilderFace::SetFace(const TopoDS_Face& theFace)
4e57c75e 105{
acccace3 106 myOrientation=theFace.Orientation();
4e57c75e 107 myFace=theFace;
acccace3 108 myFace.Orientation(TopAbs_FORWARD);
109}
110//=======================================================================
111//function : Orientation
112//purpose :
113//=======================================================================
114TopAbs_Orientation BOPAlgo_BuilderFace::Orientation()const
115{
116 return myOrientation;
4e57c75e 117}
118//=======================================================================
119//function : Face
120//purpose :
121//=======================================================================
db8e4b9a 122const TopoDS_Face& BOPAlgo_BuilderFace::Face()const
4e57c75e 123{
124 return myFace;
125}
126//=======================================================================
127//function : CheckData
128//purpose :
129//=======================================================================
db8e4b9a 130void BOPAlgo_BuilderFace::CheckData()
4e57c75e 131{
4e57c75e 132 if (myFace.IsNull()) {
33ba8565 133 AddError (new BOPAlgo_AlertNullInputShapes);
4e57c75e 134 return;
135 }
db8e4b9a 136 if (myContext.IsNull()) {
1e143abb 137 myContext = new IntTools_Context;
db8e4b9a 138 }
4e57c75e 139}
140//=======================================================================
141//function : Perform
142//purpose :
143//=======================================================================
db8e4b9a 144void BOPAlgo_BuilderFace::Perform()
4e57c75e 145{
33ba8565 146 GetReport()->Clear();
4e57c75e 147 //
148 CheckData();
33ba8565 149 if (HasErrors()) {
4e57c75e 150 return;
151 }
152 //
36f4947b 153 UserBreak();
154 //
4e57c75e 155 PerformShapesToAvoid();
33ba8565 156 if (HasErrors()) {
4e57c75e 157 return;
158 }
159 //
36f4947b 160 UserBreak();
161 //
4e57c75e 162 PerformLoops();
33ba8565 163 if (HasErrors()) {
4e57c75e 164 return;
165 }
166 //
36f4947b 167 UserBreak();
168 //
4e57c75e 169 PerformAreas();
33ba8565 170 if (HasErrors()) {
4e57c75e 171 return;
172 }
173 //
36f4947b 174 UserBreak();
175 //
4e57c75e 176 PerformInternalShapes();
33ba8565 177 if (HasErrors()) {
4e57c75e 178 return;
179 }
180}
181//=======================================================================
182//function :PerformShapesToAvoid
183//purpose :
184//=======================================================================
db8e4b9a 185void BOPAlgo_BuilderFace::PerformShapesToAvoid()
4e57c75e 186{
187 Standard_Boolean bFound;
188 Standard_Integer i, iCnt, aNbV, aNbE;
1155d05a 189 TopTools_IndexedDataMapOfShapeListOfShape aMVE;
190 TopTools_ListIteratorOfListOfShape aIt;
4e57c75e 191 //
192 myShapesToAvoid.Clear();
193 //
194 iCnt=0;
302f96fb 195 for(;;) {
4e57c75e 196 ++iCnt;
197 bFound=Standard_False;
198 //
199 // 1. MEF
200 aMVE.Clear();
201 aIt.Initialize (myShapes);
202 for (; aIt.More(); aIt.Next()) {
203 const TopoDS_Shape& aE=aIt.Value();
204 if (!myShapesToAvoid.Contains(aE)) {
1155d05a 205 TopExp::MapShapesAndAncestors(aE, TopAbs_VERTEX, TopAbs_EDGE, aMVE);
4e57c75e 206 }
4e57c75e 207 }
208 aNbV=aMVE.Extent();
209 //
210 // 2. myEdgesToAvoid
211 for (i=1; i<=aNbV; ++i) {
212 const TopoDS_Vertex& aV=(*(TopoDS_Vertex *)(&aMVE.FindKey(i)));
213 //
1155d05a 214 TopTools_ListOfShape& aLE=aMVE.ChangeFromKey(aV);
4e57c75e 215 aNbE=aLE.Extent();
216 if (!aNbE) {
217 continue;
218 }
219 //
220 const TopoDS_Edge& aE1=(*(TopoDS_Edge *)(&aLE.First()));
221 if (aNbE==1) {
222 if (BRep_Tool::Degenerated(aE1)) {
223 continue;
224 }
225 if (aV.Orientation()==TopAbs_INTERNAL) {
226 continue;
227 }
228 bFound=Standard_True;
229 myShapesToAvoid.Add(aE1);
230 }
231 else if (aNbE==2) {
232 const TopoDS_Edge& aE2=(*(TopoDS_Edge *)(&aLE.Last()));
233 if (aE2.IsSame(aE1)) {
234 TopoDS_Vertex aV1x, aV2x;
235 //
236 TopExp::Vertices(aE1, aV1x, aV2x);
237 if (aV1x.IsSame(aV2x)) {
238 continue;
239 }
240 bFound=Standard_True;
241 myShapesToAvoid.Add(aE1);
242 myShapesToAvoid.Add(aE2);
243 }
244 }
245 }// for (i=1; i<=aNbE; ++i) {
246 //
247 if (!bFound) {
248 break;
249 }
250 //
251 }//while (1)
252 //printf(" EdgesToAvoid=%d, iCnt=%d\n", EdgesToAvoid.Extent(), iCnt);
253}
254//=======================================================================
255//function : PerformLoops
256//purpose :
257//=======================================================================
db8e4b9a 258void BOPAlgo_BuilderFace::PerformLoops()
4e57c75e 259{
4e57c75e 260 Standard_Boolean bFlag;
33ba8565 261 Standard_Integer i, aNbEA;
1155d05a 262 TopTools_ListIteratorOfListOfShape aIt;
263 TopTools_IndexedDataMapOfShapeListOfShape aVEMap;
264 TopTools_MapOfOrientedShape aMAdded;
4e57c75e 265 TopoDS_Iterator aItW;
266 BRep_Builder aBB;
267 BOPAlgo_WireEdgeSet aWES(myAllocator);
268 BOPAlgo_WireSplitter aWSp(myAllocator);
269 //
270 // 1.
271 myLoops.Clear();
272 aWES.SetFace(myFace);
273 //
274 aIt.Initialize(myShapes);
275 for (; aIt.More(); aIt.Next()) {
276 const TopoDS_Shape& aE=aIt.Value();
277 if (!myShapesToAvoid.Contains(aE)) {
278 aWES.AddStartElement(aE);
279 }
280 }
281 //
282 aWSp.SetWES(aWES);
db8e4b9a 283 aWSp.SetRunParallel(myRunParallel);
51db0179 284 aWSp.SetContext(myContext);
4e57c75e 285 aWSp.Perform();
33ba8565 286 if (aWSp.HasErrors()) {
4e57c75e 287 return;
288 }
289 //
1155d05a 290 const TopTools_ListOfShape& aLW=aWES.Shapes();
4e57c75e 291 aIt.Initialize (aLW);
292 for (; aIt.More(); aIt.Next()) {
293 const TopoDS_Shape& aW=aIt.Value();
294 myLoops.Append(aW);
295 }
296 // Post Treatment
1155d05a 297 TopTools_MapOfOrientedShape aMEP;
4e57c75e 298 //
299 // a. collect all edges that are in loops
300 aIt.Initialize (myLoops);
301 for (; aIt.More(); aIt.Next()) {
302 const TopoDS_Shape& aW=aIt.Value();
303 aItW.Initialize(aW);
304 for (; aItW.More(); aItW.Next()) {
305 const TopoDS_Shape& aE=aItW.Value();
306 aMEP.Add(aE);
307 }
308 }
309 //
310 // b. collect all edges that are to avoid
319da2e4 311 aNbEA = myShapesToAvoid.Extent();
312 for (i = 1; i <= aNbEA; ++i) {
313 const TopoDS_Shape& aE = myShapesToAvoid(i);
4e57c75e 314 aMEP.Add(aE);
315 }
316 //
317 // c. add all edges that are not processed to myShapesToAvoid
318 aIt.Initialize (myShapes);
319 for (; aIt.More(); aIt.Next()) {
320 const TopoDS_Shape& aE=aIt.Value();
321 if (!aMEP.Contains(aE)) {
322 myShapesToAvoid.Add(aE);
323 }
324 }
325 //
326 // 2. Internal Wires
327 myLoopsInternal.Clear();
328 //
319da2e4 329 aNbEA = myShapesToAvoid.Extent();
330 for (i = 1; i <= aNbEA; ++i) {
331 const TopoDS_Shape& aEE = myShapesToAvoid(i);
1155d05a 332 TopExp::MapShapesAndAncestors(aEE,
1e143abb 333 TopAbs_VERTEX,
334 TopAbs_EDGE,
335 aVEMap);
4e57c75e 336 }
337 //
338 bFlag=Standard_True;
319da2e4 339 for (i = 1; (i <= aNbEA) && bFlag; ++i) {
340 const TopoDS_Shape& aEE = myShapesToAvoid(i);
4e57c75e 341 if (!aMAdded.Add(aEE)) {
342 continue;
343 }
344 //
345 // make new wire
346 TopoDS_Wire aW;
347 aBB.MakeWire(aW);
348 aBB.Add(aW, aEE);
349 //
350 aItW.Initialize(aW);
351 for (; aItW.More()&&bFlag; aItW.Next()) {
352 const TopoDS_Edge& aE=(*(TopoDS_Edge *)(&aItW.Value()));
353 //
354 TopoDS_Iterator aItE(aE);
355 for (; aItE.More()&&bFlag; aItE.Next()) {
356 const TopoDS_Vertex& aV = (*(TopoDS_Vertex *)(&aItE.Value()));
1155d05a 357 const TopTools_ListOfShape& aLE=aVEMap.FindFromKey(aV);
4e57c75e 358 aIt.Initialize(aLE);
359 for (; aIt.More()&&bFlag; aIt.Next()) {
360 const TopoDS_Shape& aEx=aIt.Value();
361 if (aMAdded.Add(aEx)) {
362 aBB.Add(aW, aEx);
363 if(aMAdded.Extent()==aNbEA) {
364 bFlag=!bFlag;
365 }
366 }
367 }//for (; aIt.More(); aIt.Next()) {
368 }//for (; aItE.More(); aItE.Next()) {
369 }//for (; aItW.More(); aItW.Next()) {
c5d8782c 370 aW.Closed(BRep_Tool::IsClosed(aW));
4e57c75e 371 myLoopsInternal.Append(aW);
319da2e4 372 }//for (i = 1; (i <= aNbEA) && bFlag; ++i) {
4e57c75e 373}
374//=======================================================================
375//function : PerformAreas
376//purpose :
377//=======================================================================
db8e4b9a 378void BOPAlgo_BuilderFace::PerformAreas()
4e57c75e 379{
4e57c75e 380 myAreas.Clear();
98b37659 381 BRep_Builder aBB;
382 // Location of the myFace
383 TopLoc_Location aLoc;
384 // Get surface from myFace
385 const Handle(Geom_Surface)& aS = BRep_Tool::Surface(myFace, aLoc);
386 // Get tolerance of myFace
387 Standard_Real aTol = BRep_Tool::Tolerance(myFace);
388
389 // Check if there are no loops at all
390 if (myLoops.IsEmpty())
391 {
392 if (myContext->IsInfiniteFace(myFace))
393 {
394 TopoDS_Face aFace;
f47b8d2b 395 aBB.MakeFace(aFace, aS, aLoc, aTol);
98b37659 396 if (BRep_Tool::NaturalRestriction(myFace))
f47b8d2b 397 aBB.NaturalRestriction(aFace, Standard_True);
98b37659 398 myAreas.Append(aFace);
f47b8d2b 399 }
400 return;
401 }
98b37659 402
403 // The new faces
1155d05a 404 TopTools_ListOfShape aNewFaces;
98b37659 405 // The hole faces which has to be classified relatively new faces
1155d05a 406 TopTools_IndexedMapOfShape aHoleFaces;
98b37659 407 // Map of the edges of the hole faces for quick check of the growths.
408 // If the analyzed wire contains any of the edges from the hole faces
409 // it is considered as growth.
1155d05a 410 TopTools_IndexedMapOfShape aMHE;
98b37659 411
412 // Analyze the new wires - classify them to be the holes and growths
1155d05a 413 TopTools_ListIteratorOfListOfShape aItLL(myLoops);
98b37659 414 for (; aItLL.More(); aItLL.Next())
415 {
416 const TopoDS_Shape& aWire = aItLL.Value();
417
418 TopoDS_Face aFace;
db8e4b9a 419 aBB.MakeFace(aFace, aS, aLoc, aTol);
98b37659 420 aBB.Add(aFace, aWire);
421
422 Standard_Boolean bIsGrowth = IsGrowthWire(aWire, aMHE);
423 if (!bIsGrowth)
424 {
425 // Fast check did not give the result, run classification
426 IntTools_FClass2d& aClsf = myContext->FClass2d(aFace);
427 bIsGrowth = !aClsf.IsHole();
4e57c75e 428 }
98b37659 429
430 // Save the face
431 if (bIsGrowth)
432 {
433 aNewFaces.Append(aFace);
4e57c75e 434 }
98b37659 435 else
436 {
437 aHoleFaces.Add(aFace);
1155d05a 438 TopExp::MapShapes(aWire, TopAbs_EDGE, aMHE);
db8e4b9a 439 }
4e57c75e 440 }
98b37659 441
442 if (aHoleFaces.IsEmpty())
443 {
444 // No holes, stop the analysis
445 myAreas.Append(aNewFaces);
d3578357 446 return;
98b37659 447 }
448
449 // Classify holes relatively faces
450
9324aa2d 451 // Prepare tree with the boxes of the hole faces
452 BOPTools_Box2dTree aBoxTree;
98b37659 453 Standard_Integer i, aNbH = aHoleFaces.Extent();
9324aa2d 454 aBoxTree.SetSize (aNbH);
98b37659 455 for (i = 1; i <= aNbH; ++i)
456 {
457 const TopoDS_Face& aHFace = TopoDS::Face(aHoleFaces(i));
db8e4b9a 458 //
98b37659 459 Bnd_Box2d aBox;
460 BRepTools::AddUVBounds(aHFace, aBox);
9324aa2d 461 aBoxTree.Add(i, Bnd_Tools::Bnd2BVH (aBox));
98b37659 462 }
463
9324aa2d 464 // Build BVH
465 aBoxTree.Build();
98b37659 466
467 // Find outer growth face that is most close to each hole face
1155d05a 468 TopTools_IndexedDataMapOfShapeShape aHoleFaceMap;
469
470 // Selector
9324aa2d 471 BOPTools_Box2dTreeSelector aSelector;
472 aSelector.SetBVHSet (&aBoxTree);
98b37659 473
1155d05a 474 TopTools_ListIteratorOfListOfShape aItLS(aNewFaces);
98b37659 475 for (; aItLS.More(); aItLS.Next())
476 {
477 const TopoDS_Face& aFace = TopoDS::Face(aItLS.Value());
478
479 // Build box
480 Bnd_Box2d aBox;
481 BRepTools::AddUVBounds(aFace, aBox);
482
1155d05a 483 aSelector.Clear();
9324aa2d 484 aSelector.SetBox(Bnd_Tools::Bnd2BVH (aBox));
485 aSelector.Select();
98b37659 486
1155d05a 487 const TColStd_ListOfInteger& aLI = aSelector.Indices();
488 TColStd_ListIteratorOfListOfInteger aItLI(aLI);
98b37659 489 for (; aItLI.More(); aItLI.Next())
490 {
491 Standard_Integer k = aItLI.Value();
492 const TopoDS_Shape& aHole = aHoleFaces(k);
493 // Check if it is inside
494 if (!IsInside(aHole, aFace, myContext))
4e57c75e 495 continue;
98b37659 496
497 // Save the relation
498 TopoDS_Shape* pFaceWas = aHoleFaceMap.ChangeSeek(aHole);
499 if (pFaceWas)
500 {
501 if (IsInside(aFace, *pFaceWas, myContext))
502 {
503 *pFaceWas = aFace;
4e57c75e 504 }
505 }
98b37659 506 else
507 {
508 aHoleFaceMap.Add(aHole, aFace);
4e57c75e 509 }
510 }
98b37659 511 }
512
513 // Make the back map from faces to holes
1155d05a 514 TopTools_IndexedDataMapOfShapeListOfShape aFaceHolesMap;
98b37659 515
516 aNbH = aHoleFaceMap.Extent();
517 for (i = 1; i <= aNbH; ++i)
518 {
519 const TopoDS_Shape& aHole = aHoleFaceMap.FindKey(i);
520 const TopoDS_Shape& aFace = aHoleFaceMap(i);
4e57c75e 521 //
1155d05a 522 TopTools_ListOfShape* pLHoles = aFaceHolesMap.ChangeSeek(aFace);
98b37659 523 if (!pLHoles)
1155d05a 524 pLHoles = &aFaceHolesMap(aFaceHolesMap.Add(aFace, TopTools_ListOfShape()));
98b37659 525 pLHoles->Append(aHole);
db8e4b9a 526 }
98b37659 527
528 // Add unused holes to the original face
529 if (aHoleFaces.Extent() != aHoleFaceMap.Extent())
530 {
d2d9e8dc 531 Bnd_Box aBoxF;
532 BRepBndLib::Add(myFace, aBoxF);
533 if (aBoxF.IsOpenXmin() || aBoxF.IsOpenXmax() ||
534 aBoxF.IsOpenYmin() || aBoxF.IsOpenYmax() ||
98b37659 535 aBoxF.IsOpenZmin() || aBoxF.IsOpenZmax())
536 {
537 TopoDS_Face aFace;
538 aBB.MakeFace(aFace, aS, aLoc, aTol);
1155d05a 539 TopTools_ListOfShape& anUnUsedHoles = aFaceHolesMap(aFaceHolesMap.Add(aFace, TopTools_ListOfShape()));
98b37659 540 aNbH = aHoleFaces.Extent();
541 for (i = 1; i <= aNbH; ++i)
542 {
543 const TopoDS_Shape& aHole = aHoleFaces(i);
544 if (!aHoleFaceMap.Contains(aHole))
545 anUnUsedHoles.Append(aHole);
d2d9e8dc 546 }
98b37659 547 // Save it
548 aNewFaces.Append(aFace);
d2d9e8dc 549 }
550 }
98b37659 551
552 // Add Holes to Faces and add them to myAreas
553 aItLS.Initialize(aNewFaces);
554 for ( ; aItLS.More(); aItLS.Next())
555 {
556 TopoDS_Face& aFace = *(TopoDS_Face*)&aItLS.Value();
1155d05a 557 const TopTools_ListOfShape* pLHoles = aFaceHolesMap.Seek(aFace);
98b37659 558 if (pLHoles)
559 {
560 // update faces with the holes
1155d05a 561 TopTools_ListIteratorOfListOfShape aItLH(*pLHoles);
98b37659 562 for (; aItLH.More(); aItLH.Next())
563 {
564 const TopoDS_Shape& aFHole = aItLH.Value();
565 // The hole face contains only one wire
566 TopoDS_Iterator aItW(aFHole);
567 aBB.Add(aFace, aItW.Value());
568 }
569
570 // update classifier
571 myContext->FClass2d(aFace).Init(aFace, aTol);
db8e4b9a 572 }
98b37659 573
574 // The face is just a draft that does not contain any internal shapes
575 myAreas.Append(aFace);
4e57c75e 576 }
577}
578//=======================================================================
579//function : PerformInternalShapes
580//purpose :
581//=======================================================================
db8e4b9a 582void BOPAlgo_BuilderFace::PerformInternalShapes()
4e57c75e 583{
d3578357 584 if (myAvoidInternalShapes)
585 // User-defined option to avoid internal edges
586 // in the result is in force.
291fced1 587 return;
d3578357 588
589 if (myLoopsInternal.IsEmpty())
590 // No edges left for classification
4e57c75e 591 return;
d3578357 592
9324aa2d 593 // Prepare tree with the boxes of the edges to classify
594 BOPTools_Box2dTree aBoxTree;
d3578357 595
596 // Map of edges to classify
597 TopTools_IndexedMapOfShape anEdgesMap;
598
599 // Fill the tree and the map
600 TopTools_ListIteratorOfListOfShape itLE(myLoopsInternal);
601 for (; itLE.More(); itLE.Next())
602 {
603 TopoDS_Iterator itE(itLE.Value());
604 for (; itE.More(); itE.Next())
605 {
606 const TopoDS_Edge& aE = TopoDS::Edge(itE.Value());
607 if (!anEdgesMap.Contains(aE))
608 {
609 Bnd_Box2d aBoxE;
610 BRepTools::AddUVBounds(myFace, aE, aBoxE);
611 // Make sure the index of edge in the map and
612 // of the box in the tree is the same
9324aa2d 613 aBoxTree.Add(anEdgesMap.Add(aE), Bnd_Tools::Bnd2BVH (aBoxE));
d3578357 614 }
4e57c75e 615 }
616 }
d3578357 617
9324aa2d 618 // Build BVH
619 aBoxTree.Build();
d3578357 620
621 // Fence map
622 TColStd_MapOfInteger aMEDone;
623
624 // Classify edges relatively faces
625 TopTools_ListIteratorOfListOfShape itLF(myAreas);
626 for (; itLF.More(); itLF.Next())
627 {
628 TopoDS_Face& aF = *(TopoDS_Face*)&itLF.Value();
629
630 // Build box
631 Bnd_Box2d aBoxF;
632 BRepTools::AddUVBounds(aF, aBoxF);
633
634 // Select edges for the classification
9324aa2d 635 BOPTools_Box2dTreeSelector aSelector;
636 aSelector.SetBVHSet (&aBoxTree);
637 aSelector.SetBox(Bnd_Tools::Bnd2BVH (aBoxF));
638 if (!aSelector.Select())
d3578357 639 continue;
640
641 // Collect edges inside the face
642 TopTools_IndexedMapOfShape anEdgesInside;
643
644 const TColStd_ListOfInteger& aLI = aSelector.Indices();
645 TColStd_ListIteratorOfListOfInteger itLI(aLI);
646 for (; itLI.More(); itLI.Next())
647 {
648 const Standard_Integer nE = itLI.Value();
649 if (aMEDone.Contains(nE))
650 continue;
651
652 const TopoDS_Edge& aE = TopoDS::Edge(anEdgesMap(nE));
653 if (IsInside(aE, aF, myContext))
654 {
655 anEdgesInside.Add(aE);
656 aMEDone.Add(nE);
319da2e4 657 }
4e57c75e 658 }
d3578357 659
660 if (anEdgesInside.IsEmpty())
661 continue;
662
663 // Make internal wires
664 TopTools_ListOfShape aLSI;
665 MakeInternalWires(anEdgesInside, aLSI);
666
667 // Add wires to a face
668 TopTools_ListIteratorOfListOfShape itLSI(aLSI);
669 for (; itLSI.More(); itLSI.Next())
670 {
671 const TopoDS_Shape& aWI = itLSI.Value();
672 BRep_Builder().Add(aF, aWI);
4e57c75e 673 }
d3578357 674
675 // Condition of early exit
676 if (aMEDone.Extent() == anEdgesMap.Extent())
677 // All edges are classified and added into the faces
678 return;
679 }
680
681 // Some edges are left unclassified - warn user about them
682 TopTools_IndexedMapOfShape anEdgesUnUsed;
683 for (Standard_Integer i = 1; i <= anEdgesMap.Extent(); ++i)
684 {
685 if (!aMEDone.Contains(i))
686 anEdgesUnUsed.Add(anEdgesMap(i));
687 }
688
689 // Make internal wires
690 TopTools_ListOfShape aLSI;
691 MakeInternalWires(anEdgesUnUsed, aLSI);
692
693 // Make compound
694 TopoDS_Compound aWShape;
695 BRep_Builder().MakeCompound(aWShape);
696 BRep_Builder().Add(aWShape, myFace);
697 if (aLSI.Extent() == 1)
698 BRep_Builder().Add(aWShape, aLSI.First());
699 else
700 {
701 TopoDS_Compound aCE;
702 BRep_Builder().MakeCompound(aCE);
703 for (TopTools_ListIteratorOfListOfShape it(aLSI); it.More(); it.Next())
704 BRep_Builder().Add(aCE, it.Value());
705 BRep_Builder().Add(aWShape, aCE);
706 }
707
708 // Add warning
709 AddWarning(new BOPAlgo_AlertFaceBuilderUnusedEdges(aWShape));
4e57c75e 710}
711//=======================================================================
712//function : MakeInternalWires
713//purpose :
714//=======================================================================
1155d05a 715void MakeInternalWires(const TopTools_IndexedMapOfShape& theME,
716 TopTools_ListOfShape& theWires)
4e57c75e 717{
319da2e4 718 Standard_Integer i, aNbE;
1155d05a 719 TopTools_MapOfShape aAddedMap;
720 TopTools_ListIteratorOfListOfShape aItE;
721 TopTools_IndexedDataMapOfShapeListOfShape aMVE;
4e57c75e 722 BRep_Builder aBB;
723 //
319da2e4 724 aNbE = theME.Extent();
725 for (i = 1; i <= aNbE; ++i) {
726 const TopoDS_Shape& aE = theME(i);
1155d05a 727 TopExp::MapShapesAndAncestors(aE, TopAbs_VERTEX, TopAbs_EDGE, aMVE);
4e57c75e 728 }
729 //
319da2e4 730 for (i = 1; i <= aNbE; ++i) {
731 TopoDS_Shape aEE = theME(i);
4e57c75e 732 if (!aAddedMap.Add(aEE)) {
733 continue;
734 }
735 //
736 // make a new shell
737 TopoDS_Wire aW;
738 aBB.MakeWire(aW);
739 aEE.Orientation(TopAbs_INTERNAL);
740 aBB.Add(aW, aEE);
741 //
742 TopoDS_Iterator aItAdded (aW);
743 for (; aItAdded.More(); aItAdded.Next()) {
744 const TopoDS_Shape& aE =aItAdded.Value();
745 //
746 TopExp_Explorer aExp(aE, TopAbs_VERTEX);
747 for (; aExp.More(); aExp.Next()) {
748 const TopoDS_Shape& aV =aExp.Current();
1155d05a 749 const TopTools_ListOfShape& aLE=aMVE.FindFromKey(aV);
4e57c75e 750 aItE.Initialize(aLE);
751 for (; aItE.More(); aItE.Next()) {
752 TopoDS_Shape aEL=aItE.Value();
753 if (aAddedMap.Add(aEL)){
754 aEL.Orientation(TopAbs_INTERNAL);
755 aBB.Add(aW, aEL);
756 }
757 }
758 }
759 }
c5d8782c 760 aW.Closed(BRep_Tool::IsClosed(aW));
4e57c75e 761 theWires.Append(aW);
762 }
763}
764//=======================================================================
765//function : IsInside
766//purpose :
767//=======================================================================
f8163956 768Standard_Boolean IsInside(const TopoDS_Shape& theWire,
769 const TopoDS_Shape& theF,
1e143abb 770 Handle(IntTools_Context)& theContext)
4e57c75e 771{
f8163956 772 // Check if the wire is located inside the face:
773 // take unique point from the wire and classify it relatively the face
774
775 // Avoid edges of the face
776 TopTools_IndexedMapOfShape aFaceEdgesMap;
777 TopExp::MapShapes(theF, TopAbs_EDGE, aFaceEdgesMap);
778
779 // Get classification tool from the context
780 const TopoDS_Face& aF = TopoDS::Face(theF);
781 IntTools_FClass2d& aClassifier = theContext->FClass2d(aF);
782
783 Standard_Boolean isInside = Standard_False;
784
785 // Iterate on wire edges until first classification is performed
786 TopExp_Explorer anExp(theWire, TopAbs_EDGE);
787 for (; anExp.More(); anExp.Next())
788 {
789 const TopoDS_Edge& aE = TopoDS::Edge(anExp.Current());
790 if (BRep_Tool::Degenerated(aE))
791 // Avoid checking degenerated edges.
792 continue;
793
794 if (aFaceEdgesMap.Contains(aE))
795 // Face contains the edge from the wire, thus the wire cannot be
796 // inside that face.
797 return isInside;
798
799 // Get 2d curve of the edge on the face
800 Standard_Real aT1, aT2;
801 const Handle(Geom2d_Curve)& aC2D = BRep_Tool::CurveOnSurface(aE, aF, aT1, aT2);
802 if (aC2D.IsNull())
803 continue;
804
805 // Get middle point on the curve
806 gp_Pnt2d aP2D = aC2D->Value((aT1 + aT2) / 2.);
807
808 // Classify the point
809 TopAbs_State aState = aClassifier.Perform(aP2D);
810 isInside = (aState == TopAbs_IN);
811 break;
4e57c75e 812 }
f8163956 813 return isInside;
4e57c75e 814}
4e57c75e 815//=======================================================================
816//function : IsGrowthWire
817//purpose :
818//=======================================================================
819Standard_Boolean IsGrowthWire(const TopoDS_Shape& theWire,
1155d05a 820 const TopTools_IndexedMapOfShape& theMHE)
4e57c75e 821{
98b37659 822 if (theMHE.Extent())
823 {
824 TopoDS_Iterator aIt(theWire);
825 for(; aIt.More(); aIt.Next())
826 {
827 if (theMHE.Contains(aIt.Value()))
828 return Standard_True;
4e57c75e 829 }
830 }
98b37659 831 return Standard_False;
4e57c75e 832}