0029646: Boolean Operations algorithm produces a face with self-intersecting wire
[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>
1155d05a 27#include <BOPTools_BoxSelector.hxx>
42cf5bc1 28#include <BRep_Builder.hxx>
29#include <BRep_Tool.hxx>
30#include <BRepBndLib.hxx>
31#include <BRepTools.hxx>
32#include <Geom_Surface.hxx>
4e57c75e 33#include <gp_Dir.hxx>
42cf5bc1 34#include <gp_Pln.hxx>
4e57c75e 35#include <gp_Pnt.hxx>
42cf5bc1 36#include <gp_Pnt2d.hxx>
37#include <gp_Vec.hxx>
38#include <IntTools_Context.hxx>
39#include <IntTools_FClass2d.hxx>
40#include <NCollection_DataMap.hxx>
41#include <NCollection_UBTreeFiller.hxx>
42#include <TColStd_MapIntegerHasher.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);
446 }
447
448 // Classify holes relatively faces
449
450 // Prepare tree filler with the boxes of the hole faces
1155d05a 451 NCollection_UBTree<Standard_Integer, Bnd_Box2d> aBBTree;
98b37659 452 NCollection_UBTreeFiller <Standard_Integer, Bnd_Box2d> aTreeFiller(aBBTree);
453
454 Standard_Integer i, aNbH = aHoleFaces.Extent();
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);
461 aTreeFiller.Add(i, aBox);
462 }
463
464 // Shake TreeFiller
465 aTreeFiller.Fill();
466
467 // Find outer growth face that is most close to each hole face
1155d05a 468 TopTools_IndexedDataMapOfShapeShape aHoleFaceMap;
469
470 // Selector
471 BOPTools_BoxSelector<Bnd_Box2d> aSelector;
98b37659 472
1155d05a 473 TopTools_ListIteratorOfListOfShape aItLS(aNewFaces);
98b37659 474 for (; aItLS.More(); aItLS.Next())
475 {
476 const TopoDS_Face& aFace = TopoDS::Face(aItLS.Value());
477
478 // Build box
479 Bnd_Box2d aBox;
480 BRepTools::AddUVBounds(aFace, aBox);
481
1155d05a 482 aSelector.Clear();
98b37659 483 aSelector.SetBox(aBox);
484 aBBTree.Select(aSelector);
485
1155d05a 486 const TColStd_ListOfInteger& aLI = aSelector.Indices();
487 TColStd_ListIteratorOfListOfInteger aItLI(aLI);
98b37659 488 for (; aItLI.More(); aItLI.Next())
489 {
490 Standard_Integer k = aItLI.Value();
491 const TopoDS_Shape& aHole = aHoleFaces(k);
492 // Check if it is inside
493 if (!IsInside(aHole, aFace, myContext))
4e57c75e 494 continue;
98b37659 495
496 // Save the relation
497 TopoDS_Shape* pFaceWas = aHoleFaceMap.ChangeSeek(aHole);
498 if (pFaceWas)
499 {
500 if (IsInside(aFace, *pFaceWas, myContext))
501 {
502 *pFaceWas = aFace;
4e57c75e 503 }
504 }
98b37659 505 else
506 {
507 aHoleFaceMap.Add(aHole, aFace);
4e57c75e 508 }
509 }
98b37659 510 }
511
512 // Make the back map from faces to holes
1155d05a 513 TopTools_IndexedDataMapOfShapeListOfShape aFaceHolesMap;
98b37659 514
515 aNbH = aHoleFaceMap.Extent();
516 for (i = 1; i <= aNbH; ++i)
517 {
518 const TopoDS_Shape& aHole = aHoleFaceMap.FindKey(i);
519 const TopoDS_Shape& aFace = aHoleFaceMap(i);
4e57c75e 520 //
1155d05a 521 TopTools_ListOfShape* pLHoles = aFaceHolesMap.ChangeSeek(aFace);
98b37659 522 if (!pLHoles)
1155d05a 523 pLHoles = &aFaceHolesMap(aFaceHolesMap.Add(aFace, TopTools_ListOfShape()));
98b37659 524 pLHoles->Append(aHole);
db8e4b9a 525 }
98b37659 526
527 // Add unused holes to the original face
528 if (aHoleFaces.Extent() != aHoleFaceMap.Extent())
529 {
d2d9e8dc 530 Bnd_Box aBoxF;
531 BRepBndLib::Add(myFace, aBoxF);
532 if (aBoxF.IsOpenXmin() || aBoxF.IsOpenXmax() ||
533 aBoxF.IsOpenYmin() || aBoxF.IsOpenYmax() ||
98b37659 534 aBoxF.IsOpenZmin() || aBoxF.IsOpenZmax())
535 {
536 TopoDS_Face aFace;
537 aBB.MakeFace(aFace, aS, aLoc, aTol);
1155d05a 538 TopTools_ListOfShape& anUnUsedHoles = aFaceHolesMap(aFaceHolesMap.Add(aFace, TopTools_ListOfShape()));
98b37659 539 aNbH = aHoleFaces.Extent();
540 for (i = 1; i <= aNbH; ++i)
541 {
542 const TopoDS_Shape& aHole = aHoleFaces(i);
543 if (!aHoleFaceMap.Contains(aHole))
544 anUnUsedHoles.Append(aHole);
d2d9e8dc 545 }
98b37659 546 // Save it
547 aNewFaces.Append(aFace);
d2d9e8dc 548 }
549 }
98b37659 550
551 // Add Holes to Faces and add them to myAreas
552 aItLS.Initialize(aNewFaces);
553 for ( ; aItLS.More(); aItLS.Next())
554 {
555 TopoDS_Face& aFace = *(TopoDS_Face*)&aItLS.Value();
1155d05a 556 const TopTools_ListOfShape* pLHoles = aFaceHolesMap.Seek(aFace);
98b37659 557 if (pLHoles)
558 {
559 // update faces with the holes
1155d05a 560 TopTools_ListIteratorOfListOfShape aItLH(*pLHoles);
98b37659 561 for (; aItLH.More(); aItLH.Next())
562 {
563 const TopoDS_Shape& aFHole = aItLH.Value();
564 // The hole face contains only one wire
565 TopoDS_Iterator aItW(aFHole);
566 aBB.Add(aFace, aItW.Value());
567 }
568
569 // update classifier
570 myContext->FClass2d(aFace).Init(aFace, aTol);
db8e4b9a 571 }
98b37659 572
573 // The face is just a draft that does not contain any internal shapes
574 myAreas.Append(aFace);
4e57c75e 575 }
576}
577//=======================================================================
578//function : PerformInternalShapes
579//purpose :
580//=======================================================================
db8e4b9a 581void BOPAlgo_BuilderFace::PerformInternalShapes()
4e57c75e 582{
291fced1 583 if (myAvoidInternalShapes) {
584 return;
585 }
4e57c75e 586 //
587 Standard_Integer aNbWI=myLoopsInternal.Extent();
588 if (!aNbWI) {// nothing to do
589 return;
590 }
591 //
592 //Standard_Real aTol;
319da2e4 593 Standard_Integer i;
4e57c75e 594 BRep_Builder aBB;
1155d05a 595 TopTools_ListIteratorOfListOfShape aIt1, aIt2;
4e57c75e 596 TopoDS_Iterator aIt;
1155d05a 597 TopTools_IndexedMapOfShape aME1, aME2, aMEP;
598 TopTools_IndexedDataMapOfShapeListOfShape aMVE;
599 TopTools_ListOfShape aLSI;
4e57c75e 600 //
601 // 1. All internal edges
602 aIt1.Initialize(myLoopsInternal);
603 for (; aIt1.More(); aIt1.Next()) {
604 const TopoDS_Shape& aWire=aIt1.Value();
605 aIt.Initialize(aWire);
606 for (; aIt.More(); aIt.Next()) {
607 const TopoDS_Shape& aE=aIt.Value();
319da2e4 608 aME1.Add(aE);
4e57c75e 609 }
610 }
4e57c75e 611 //
612 // 2 Process faces
613 aIt2.Initialize(myAreas);
614 for ( ; aIt2.More(); aIt2.Next()) {
615 TopoDS_Face& aF=(*(TopoDS_Face *)(&aIt2.Value()));
616 //
617 aMVE.Clear();
1155d05a 618 TopExp::MapShapesAndAncestors(aF, TopAbs_VERTEX, TopAbs_EDGE, aMVE);
4e57c75e 619 //
620 // 2.1 Separate faces to process aMEP
319da2e4 621 aME2.Clear();
4e57c75e 622 aMEP.Clear();
319da2e4 623 aNbWI = aME1.Extent();
624 for (i = 1; i <= aNbWI; ++i) {
625 const TopoDS_Edge& aE=(*(TopoDS_Edge *)(&aME1(i)));
4e57c75e 626 if (IsInside(aE, aF, myContext)) {
627 aMEP.Add(aE);
628 }
319da2e4 629 else {
630 aME2.Add(aE);
631 }
4e57c75e 632 }
633 //
634 // 2.2 Make Internal Wires
635 aLSI.Clear();
636 MakeInternalWires(aMEP, aLSI);
637 //
638 // 2.3 Add them to aF
639 aIt1.Initialize(aLSI);
640 for (; aIt1.More(); aIt1.Next()) {
641 const TopoDS_Shape& aSI=aIt1.Value();
642 aBB.Add (aF, aSI);
643 }
644 //
645 // 2.4 Remove faces aMFP from aMF
319da2e4 646 aME1 = aME2;
4e57c75e 647 //
319da2e4 648 aNbWI = aME1.Extent();
4e57c75e 649 if (!aNbWI) {
650 break;
651 }
652 } //for ( ; aIt2.More(); aIt2.Next()) {
653}
654//=======================================================================
655//function : MakeInternalWires
656//purpose :
657//=======================================================================
1155d05a 658void MakeInternalWires(const TopTools_IndexedMapOfShape& theME,
659 TopTools_ListOfShape& theWires)
4e57c75e 660{
319da2e4 661 Standard_Integer i, aNbE;
1155d05a 662 TopTools_MapOfShape aAddedMap;
663 TopTools_ListIteratorOfListOfShape aItE;
664 TopTools_IndexedDataMapOfShapeListOfShape aMVE;
4e57c75e 665 BRep_Builder aBB;
666 //
319da2e4 667 aNbE = theME.Extent();
668 for (i = 1; i <= aNbE; ++i) {
669 const TopoDS_Shape& aE = theME(i);
1155d05a 670 TopExp::MapShapesAndAncestors(aE, TopAbs_VERTEX, TopAbs_EDGE, aMVE);
4e57c75e 671 }
672 //
319da2e4 673 for (i = 1; i <= aNbE; ++i) {
674 TopoDS_Shape aEE = theME(i);
4e57c75e 675 if (!aAddedMap.Add(aEE)) {
676 continue;
677 }
678 //
679 // make a new shell
680 TopoDS_Wire aW;
681 aBB.MakeWire(aW);
682 aEE.Orientation(TopAbs_INTERNAL);
683 aBB.Add(aW, aEE);
684 //
685 TopoDS_Iterator aItAdded (aW);
686 for (; aItAdded.More(); aItAdded.Next()) {
687 const TopoDS_Shape& aE =aItAdded.Value();
688 //
689 TopExp_Explorer aExp(aE, TopAbs_VERTEX);
690 for (; aExp.More(); aExp.Next()) {
691 const TopoDS_Shape& aV =aExp.Current();
1155d05a 692 const TopTools_ListOfShape& aLE=aMVE.FindFromKey(aV);
4e57c75e 693 aItE.Initialize(aLE);
694 for (; aItE.More(); aItE.Next()) {
695 TopoDS_Shape aEL=aItE.Value();
696 if (aAddedMap.Add(aEL)){
697 aEL.Orientation(TopAbs_INTERNAL);
698 aBB.Add(aW, aEL);
699 }
700 }
701 }
702 }
c5d8782c 703 aW.Closed(BRep_Tool::IsClosed(aW));
4e57c75e 704 theWires.Append(aW);
705 }
706}
707//=======================================================================
708//function : IsInside
709//purpose :
710//=======================================================================
f8163956 711Standard_Boolean IsInside(const TopoDS_Shape& theWire,
712 const TopoDS_Shape& theF,
1e143abb 713 Handle(IntTools_Context)& theContext)
4e57c75e 714{
f8163956 715 // Check if the wire is located inside the face:
716 // take unique point from the wire and classify it relatively the face
717
718 // Avoid edges of the face
719 TopTools_IndexedMapOfShape aFaceEdgesMap;
720 TopExp::MapShapes(theF, TopAbs_EDGE, aFaceEdgesMap);
721
722 // Get classification tool from the context
723 const TopoDS_Face& aF = TopoDS::Face(theF);
724 IntTools_FClass2d& aClassifier = theContext->FClass2d(aF);
725
726 Standard_Boolean isInside = Standard_False;
727
728 // Iterate on wire edges until first classification is performed
729 TopExp_Explorer anExp(theWire, TopAbs_EDGE);
730 for (; anExp.More(); anExp.Next())
731 {
732 const TopoDS_Edge& aE = TopoDS::Edge(anExp.Current());
733 if (BRep_Tool::Degenerated(aE))
734 // Avoid checking degenerated edges.
735 continue;
736
737 if (aFaceEdgesMap.Contains(aE))
738 // Face contains the edge from the wire, thus the wire cannot be
739 // inside that face.
740 return isInside;
741
742 // Get 2d curve of the edge on the face
743 Standard_Real aT1, aT2;
744 const Handle(Geom2d_Curve)& aC2D = BRep_Tool::CurveOnSurface(aE, aF, aT1, aT2);
745 if (aC2D.IsNull())
746 continue;
747
748 // Get middle point on the curve
749 gp_Pnt2d aP2D = aC2D->Value((aT1 + aT2) / 2.);
750
751 // Classify the point
752 TopAbs_State aState = aClassifier.Perform(aP2D);
753 isInside = (aState == TopAbs_IN);
754 break;
4e57c75e 755 }
f8163956 756 return isInside;
4e57c75e 757}
4e57c75e 758//=======================================================================
759//function : IsGrowthWire
760//purpose :
761//=======================================================================
762Standard_Boolean IsGrowthWire(const TopoDS_Shape& theWire,
1155d05a 763 const TopTools_IndexedMapOfShape& theMHE)
4e57c75e 764{
98b37659 765 if (theMHE.Extent())
766 {
767 TopoDS_Iterator aIt(theWire);
768 for(; aIt.More(); aIt.Next())
769 {
770 if (theMHE.Contains(aIt.Value()))
771 return Standard_True;
4e57c75e 772 }
773 }
98b37659 774 return Standard_False;
4e57c75e 775}