0030618: Modeling Algorithms, BOPTools_Parallel - avoid using map for thread-local...
[occt.git] / src / BOPAlgo / BOPAlgo_Builder_2.cxx
CommitLineData
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.
4e57c75e 17
42cf5bc1 18
19#include <BOPAlgo_Builder.hxx>
20#include <BOPAlgo_BuilderFace.hxx>
21#include <BOPAlgo_PaveFiller.hxx>
edfa30de 22#include <BOPAlgo_Tools.hxx>
4e57c75e 23#include <BOPDS_DS.hxx>
24#include <BOPDS_FaceInfo.hxx>
4e57c75e 25#include <BOPDS_Interf.hxx>
42cf5bc1 26#include <BOPDS_MapOfPaveBlock.hxx>
27#include <BOPDS_PaveBlock.hxx>
28#include <BOPDS_ShapeInfo.hxx>
4e57c75e 29#include <BOPDS_VectorOfCurve.hxx>
42cf5bc1 30#include <BOPDS_VectorOfInterfFF.hxx>
4e57c75e 31#include <BOPDS_VectorOfPoint.hxx>
4e57c75e 32#include <BOPTools_AlgoTools.hxx>
acccace3 33#include <BOPTools_AlgoTools2D.hxx>
4e57c75e 34#include <BOPTools_AlgoTools3D.hxx>
4e57c75e 35#include <BOPTools_CoupleOfShape.hxx>
36#include <BOPTools_ListOfCoupleOfShape.hxx>
37#include <BOPTools_MapOfSet.hxx>
1155d05a 38#include <BOPTools_Parallel.hxx>
42cf5bc1 39#include <BRep_Builder.hxx>
f16a6cc5 40#include <BRepLib.hxx>
42cf5bc1 41#include <BRep_Tool.hxx>
39067947 42#include <GeomAdaptor_Surface.hxx>
43#include <GeomLib.hxx>
86218548 44#include <NCollection_IncAllocator.hxx>
1155d05a 45#include <NCollection_Vector.hxx>
39067947 46#include <Precision.hxx>
42cf5bc1 47#include <IntTools_Context.hxx>
1155d05a 48#include <TColStd_ListOfInteger.hxx>
49#include <TColStd_MapOfInteger.hxx>
42cf5bc1 50#include <TopExp_Explorer.hxx>
98b37659 51#include <TopoDS.hxx>
42cf5bc1 52#include <TopoDS_Compound.hxx>
53#include <TopoDS_Edge.hxx>
54#include <TopoDS_Face.hxx>
55#include <TopoDS_Shape.hxx>
56#include <TopoDS_Vertex.hxx>
1155d05a 57#include <TopTools_ListOfShape.hxx>
4e57c75e 58
86218548 59#include <algorithm>
a0a3f6ac 60//
98b37659 61static
62 TopoDS_Face BuildDraftFace(const TopoDS_Face& theFace,
1155d05a 63 const TopTools_DataMapOfShapeListOfShape& theImages,
80d55adf 64 Handle(IntTools_Context)& theCtx,
65 const Handle(Message_Report)& theReport);
86218548 66
a0a3f6ac 67//=======================================================================
68//class : BOPAlgo_PairOfShapeBoolean
69//purpose :
70//=======================================================================
36f4947b 71class BOPAlgo_PairOfShapeBoolean : public BOPAlgo_Algo {
72
a0a3f6ac 73 public:
36f4947b 74 DEFINE_STANDARD_ALLOC
75
76 BOPAlgo_PairOfShapeBoolean() :
77 BOPAlgo_Algo(),
78 myFlag(Standard_False) {
79 }
80 //
81 virtual ~BOPAlgo_PairOfShapeBoolean() {
a0a3f6ac 82 }
83 //
84 TopoDS_Shape& Shape1() {
85 return myShape1;
86 }
87 //
88 TopoDS_Shape& Shape2() {
89 return myShape2;
90 }
91 //
92 Standard_Boolean& Flag() {
93 return myFlag;
94 }
95 //
36f4947b 96 void SetContext(const Handle(IntTools_Context)& aContext) {
97 myContext=aContext;
98 }
99 //
100 const Handle(IntTools_Context)& Context()const {
101 return myContext;
102 }
103 //
104 virtual void Perform() {
105 BOPAlgo_Algo::UserBreak();
106 //
107 const TopoDS_Face& aFj=*((TopoDS_Face*)&myShape1);
108 const TopoDS_Face& aFk=*((TopoDS_Face*)&myShape2);
0d0481c7 109 myFlag=BOPTools_AlgoTools::AreFacesSameDomain(aFj, aFk, myContext, myFuzzyValue);
36f4947b 110 }
111 //
a0a3f6ac 112 protected:
113 Standard_Boolean myFlag;
114 TopoDS_Shape myShape1;
115 TopoDS_Shape myShape2;
36f4947b 116 Handle(IntTools_Context) myContext;
a0a3f6ac 117};
118//
fc867b96 119typedef NCollection_Vector<BOPAlgo_PairOfShapeBoolean> BOPAlgo_VectorOfPairOfShapeBoolean;
120
a0a3f6ac 121//=======================================================================
122// BuilderFace
123//
1155d05a 124typedef NCollection_Vector<BOPAlgo_BuilderFace> BOPAlgo_VectorOfBuilderFace;
fc867b96 125
a0a3f6ac 126//=======================================================================
127//class : BOPAlgo_VFI
128//purpose :
129//=======================================================================
36f4947b 130class BOPAlgo_VFI : public BOPAlgo_Algo {
131
a0a3f6ac 132 public:
36f4947b 133 DEFINE_STANDARD_ALLOC
134
135 BOPAlgo_VFI() :
136 BOPAlgo_Algo(),
81a55a69 137 myIsInternal(Standard_False) {
a0a3f6ac 138 }
139 //
36f4947b 140 virtual ~BOPAlgo_VFI(){
a0a3f6ac 141 }
142 //
143 void SetVertex(const TopoDS_Vertex& aV) {
144 myV=aV;
145 }
146 //
147 TopoDS_Vertex& Vertex() {
148 return myV;
149 }
150 //
151 void SetFace(const TopoDS_Face& aF) {
152 myF=aF;
153 }
154 //
155 TopoDS_Face& Face() {
156 return myF;
157 }
158 //
81a55a69 159 Standard_Boolean IsInternal()const {
160 return myIsInternal;
a0a3f6ac 161 }
162 //
1e143abb 163 void SetContext(const Handle(IntTools_Context)& aContext) {
a0a3f6ac 164 myContext=aContext;
165 }
166 //
1e143abb 167 const Handle(IntTools_Context)& Context()const {
a0a3f6ac 168 return myContext;
169 }
170 //
36f4947b 171 virtual void Perform() {
3510db62 172 Standard_Real aT1, aT2, dummy;
a0a3f6ac 173 //
36f4947b 174 BOPAlgo_Algo::UserBreak();
81a55a69 175 Standard_Integer iFlag =
176 myContext->ComputeVF(myV, myF, aT1, aT2, dummy, myFuzzyValue);
177 myIsInternal = (iFlag == 0);
a0a3f6ac 178 }
179 //
180 protected:
81a55a69 181 Standard_Boolean myIsInternal;
a0a3f6ac 182 TopoDS_Vertex myV;
183 TopoDS_Face myF;
1e143abb 184 Handle(IntTools_Context) myContext;
a0a3f6ac 185};
186//
1155d05a 187typedef NCollection_Vector<BOPAlgo_VFI> BOPAlgo_VectorOfVFI;
fc867b96 188
4e57c75e 189//=======================================================================
190//function : FillImagesFaces
191//purpose :
192//=======================================================================
acccace3 193void BOPAlgo_Builder::FillImagesFaces()
4e57c75e 194{
4e57c75e 195 BuildSplitFaces();
196 FillSameDomainFaces();
81a55a69 197 FillInternalVertices();
4e57c75e 198}
199//=======================================================================
200//function : BuildSplitFaces
201//purpose :
202//=======================================================================
acccace3 203void BOPAlgo_Builder::BuildSplitFaces()
4e57c75e 204{
205 Standard_Boolean bHasFaceInfo, bIsClosed, bIsDegenerated, bToReverse;
37e640d5 206 Standard_Integer i, j, k, aNbS, aNbPBIn, aNbPBOn, aNbPBSc, aNbAV, nSp;
4e57c75e 207 TopoDS_Face aFF, aFSD;
208 TopoDS_Edge aSp, aEE;
209 TopAbs_Orientation anOriF, anOriE;
210 TopExp_Explorer aExp;
1155d05a 211 TopTools_ListIteratorOfListOfShape aIt;
212 TColStd_ListOfInteger aLIAV;
213 TopTools_MapOfShape aMFence;
acccace3 214 Handle(NCollection_BaseAllocator) aAllocator;
acccace3 215 BOPAlgo_VectorOfBuilderFace aVBF;
4e57c75e 216 //
4e57c75e 217 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~scope f
488e5b9d 218 aAllocator=
219 NCollection_BaseAllocator::CommonBaseAllocator();
4e57c75e 220 //
1155d05a 221 TopTools_ListOfShape aLE(aAllocator);
222 TopTools_MapOfShape aMDE(100, aAllocator);
4e57c75e 223 //
98b37659 224 // Build temporary map of faces images to avoid rebuilding
225 // of the faces without any IN or section edges
1155d05a 226 NCollection_IndexedDataMap<Standard_Integer, TopTools_ListOfShape> aFacesIm;
98b37659 227 //
4e57c75e 228 aNbS=myDS->NbSourceShapes();
acccace3 229 //
4e57c75e 230 for (i=0; i<aNbS; ++i) {
231 const BOPDS_ShapeInfo& aSI=myDS->ShapeInfo(i);
232 if (aSI.ShapeType()!=TopAbs_FACE) {
233 continue;
234 }
235 //
236 const TopoDS_Face& aF=(*(TopoDS_Face*)(&aSI.Shape()));
39067947 237 Standard_Boolean isUClosed = Standard_False,
238 isVClosed = Standard_False,
239 isChecked = Standard_False;
4e57c75e 240 //
241 bHasFaceInfo=myDS->HasFaceInfo(i);
242 if(!bHasFaceInfo) {
243 continue;
244 }
245 //
4e57c75e 246 const BOPDS_FaceInfo& aFI=myDS->FaceInfo(i);
247 //
248 const BOPDS_IndexedMapOfPaveBlock& aMPBIn=aFI.PaveBlocksIn();
249 const BOPDS_IndexedMapOfPaveBlock& aMPBOn=aFI.PaveBlocksOn();
250 const BOPDS_IndexedMapOfPaveBlock& aMPBSc=aFI.PaveBlocksSc();
251 aLIAV.Clear();
252 myDS->AloneVertices(i, aLIAV);
253
254 aNbPBIn=aMPBIn.Extent();
255 aNbPBOn=aMPBOn.Extent();
256 aNbPBSc=aMPBSc.Extent();
257 aNbAV=aLIAV.Extent();
258 if (!aNbPBIn && !aNbPBOn && !aNbPBSc && !aNbAV) { // not compete
259 continue;
260 }
98b37659 261
262 if (!aNbPBIn && !aNbPBSc)
263 {
80da8585 264 // If there are any alone vertices to be put in the face,
265 // the new face has to be created even if the wires of the
266 // face have not been modified.
267
268 // It is also necessary to check if the face contains any internal edges,
269 // as such edges may split the face on parts and it is better
270 // to send the face be treated by the BuilderFace algorithm.
271 // In case of alone vertices the check for internals will be performed
272 // in the BuildDraftFace method.
273 Standard_Boolean hasInternals = Standard_False;
81a55a69 274 if (!aNbAV)
275 {
276 // Check if any wires of the face have been modified.
80da8585 277 // If no modified and internal wires present in the face
278 // there is no need to create the new face.
279 Standard_Boolean hasModified = Standard_False;
280
81a55a69 281 TopoDS_Iterator aItW(aF);
282 for (; aItW.More(); aItW.Next())
283 {
80da8585 284 TopoDS_Iterator itE(aItW.Value());
285 hasInternals = (itE.More() && (itE.Value().Orientation() == TopAbs_INTERNAL));
286 if (hasInternals)
81a55a69 287 break;
80da8585 288
289 hasModified |= myImages.IsBound(aItW.Value());
81a55a69 290 }
80da8585 291
292 if (!hasInternals && !hasModified)
81a55a69 293 continue;
294 }
295
80da8585 296 if (!hasInternals)
98b37659 297 {
80da8585 298 // No internal parts for the face, so just build the draft face
299 // and keep it to pass directly into result.
300 // If the original face has any internal edges or multi-connected vertices,
301 // the draft face will be null, as such sub-shapes may split the face on parts
302 // (as in the case "bugs modalg_5 bug25245_1").
303 // The BuilderFace algorithm will be called in this case.
304 TopoDS_Face aFD = BuildDraftFace(aF, myImages, myContext, myReport);
305 if (!aFD.IsNull())
306 {
307 aFacesIm(aFacesIm.Add(i, TopTools_ListOfShape())).Append(aFD);
308 continue;
309 }
98b37659 310 }
311 }
312
4e57c75e 313 aMFence.Clear();
314 //
315 anOriF=aF.Orientation();
316 aFF=aF;
317 aFF.Orientation(TopAbs_FORWARD);
4e57c75e 318 //
98b37659 319 // 1. Fill the edges set for the face aFF -> LE
4e57c75e 320 aLE.Clear();
98b37659 321
4e57c75e 322 // 1.1 Bounding edges
323 aExp.Init(aFF, TopAbs_EDGE);
324 for (; aExp.More(); aExp.Next()) {
325 const TopoDS_Edge& aE=(*(TopoDS_Edge*)(&aExp.Current()));
326 anOriE=aE.Orientation();
4e57c75e 327 //
328 if (!myImages.IsBound(aE)) {
329 if (anOriE==TopAbs_INTERNAL) {
330 aEE=aE;
331 aEE.Orientation(TopAbs_FORWARD);
332 aLE.Append(aEE);
333 aEE.Orientation(TopAbs_REVERSED);
334 aLE.Append(aEE);
335 }
336 else {
337 aLE.Append(aE);
338 }
39067947 339
340 continue;
4e57c75e 341 }
39067947 342
343 if(!isChecked)
344 {
345 const Handle(Geom_Surface) aSurf = BRep_Tool::Surface(aF);
346 GeomLib::IsClosed(aSurf, BRep_Tool::Tolerance(aE),
347 isUClosed, isVClosed);
348
349 isChecked = Standard_True;
350 }
351
352 bIsClosed = Standard_False;
353
354 if((isUClosed || isVClosed) && BRep_Tool::IsClosed(aE, aF))
355 {
356
357 Standard_Boolean isUIso = Standard_False, isVIso = Standard_False;
358 BOPTools_AlgoTools2D::IsEdgeIsoline(aE, aF, isUIso, isVIso);
359
360 bIsClosed = ((isUClosed && isUIso) || (isVClosed && isVIso));
361 }
362
363 bIsDegenerated=BRep_Tool::Degenerated(aE);
364
1155d05a 365 const TopTools_ListOfShape& aLIE=myImages.Find(aE);
39067947 366 aIt.Initialize(aLIE);
367 for (; aIt.More(); aIt.Next()) {
368 aSp=(*(TopoDS_Edge*)(&aIt.Value()));
369 if (bIsDegenerated) {
370 aSp.Orientation(anOriE);
371 aLE.Append(aSp);
372 continue;
373 }
374 //
375 if (anOriE==TopAbs_INTERNAL) {
376 aSp.Orientation(TopAbs_FORWARD);
377 aLE.Append(aSp);
378 aSp.Orientation(TopAbs_REVERSED);
379 aLE.Append(aSp);
380 continue;
381 }
4e57c75e 382 //
39067947 383 if (bIsClosed) {
384 if (aMFence.Add(aSp)) {
385 if (!BRep_Tool::IsClosed(aSp, aF)){
386 BOPTools_AlgoTools3D::DoSplitSEAMOnFace(aSp, aF);
387 }
388 //
4e57c75e 389 aSp.Orientation(TopAbs_FORWARD);
390 aLE.Append(aSp);
391 aSp.Orientation(TopAbs_REVERSED);
392 aLE.Append(aSp);
39067947 393 }// if (aMFence.Add(aSp))
394 continue;
395 }// if (bIsClosed){
396 //
397 aSp.Orientation(anOriE);
80d55adf 398 bToReverse=BOPTools_AlgoTools::IsSplitToReverseWithWarn(aSp, aE, myContext, myReport);
39067947 399 if (bToReverse) {
400 aSp.Reverse();
401 }
402 aLE.Append(aSp);
403 }// for (; aIt.More(); aIt.Next()) {
4e57c75e 404 }// for (; aExp.More(); aExp.Next()) {
405 //
406 //
407 // 1.2 In edges
408 for (j=1; j<=aNbPBIn; ++j) {
409 const Handle(BOPDS_PaveBlock)& aPB=aMPBIn(j);
410 nSp=aPB->Edge();
411 aSp=(*(TopoDS_Edge*)(&myDS->Shape(nSp)));
412 //
413 aSp.Orientation(TopAbs_FORWARD);
414 aLE.Append(aSp);
415 aSp.Orientation(TopAbs_REVERSED);
416 aLE.Append(aSp);
417 }
418 //
419 //
420 // 1.3 Section edges
421 for (j=1; j<=aNbPBSc; ++j) {
422 const Handle(BOPDS_PaveBlock)& aPB=aMPBSc(j);
423 nSp=aPB->Edge();
424 aSp=(*(TopoDS_Edge*)(&myDS->Shape(nSp)));
425 //
426 aSp.Orientation(TopAbs_FORWARD);
427 aLE.Append(aSp);
428 aSp.Orientation(TopAbs_REVERSED);
429 aLE.Append(aSp);
430 }
431 //
3510db62 432 if (!myPaveFiller->NonDestructive()) {
433 // speed up for planar faces
f16a6cc5 434 BRepLib::BuildPCurveForEdgesOnPlane(aLE, aFF);
3510db62 435 }
acccace3 436 // 3 Build split faces
1155d05a 437 BOPAlgo_BuilderFace& aBF=aVBF.Appended();
acccace3 438 aBF.SetFace(aF);
4e57c75e 439 aBF.SetShapes(aLE);
db8e4b9a 440 aBF.SetRunParallel(myRunParallel);
36f4947b 441 aBF.SetProgressIndicator(myProgressIndicator);
4e57c75e 442 //
acccace3 443 }// for (i=0; i<aNbS; ++i) {
444 //
acccace3 445 //===================================================
fc867b96 446 BOPTools_Parallel::Perform (myRunParallel, aVBF);
acccace3 447 //===================================================
448 //
1155d05a 449 Standard_Integer aNbBF = aVBF.Length();
98b37659 450 for (k = 0; k < aNbBF; ++k)
451 {
452 BOPAlgo_BuilderFace& aBF = aVBF(k);
93964cc2 453 aFacesIm.Add(myDS->Index(aBF.Face()), aBF.Areas());
d3578357 454 myReport->Merge(aBF.GetReport());
98b37659 455 }
456
457 aNbBF = aFacesIm.Extent();
458 for (k = 1; k <= aNbBF; ++k)
459 {
93964cc2 460 const TopoDS_Face& aF = TopoDS::Face(myDS->Shape(aFacesIm.FindKey(k)));
98b37659 461 anOriF = aF.Orientation();
1155d05a 462 const TopTools_ListOfShape& aLFR = aFacesIm(k);
98b37659 463 //
81a55a69 464 TopTools_ListOfShape* pLFIm = myImages.Bound(aF, TopTools_ListOfShape());
4e57c75e 465 aIt.Initialize(aLFR);
466 for (; aIt.More(); aIt.Next()) {
467 TopoDS_Shape& aFR=aIt.ChangeValue();
98b37659 468 if (anOriF==TopAbs_REVERSED)
4e57c75e 469 aFR.Orientation(TopAbs_REVERSED);
98b37659 470 pLFIm->Append(aFR);
4e57c75e 471 }
98b37659 472 }
4e57c75e 473 //
4e57c75e 474 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~scope t
475}
86218548 476
477//=======================================================================
478//function : AddEdgeSet
479//purpose :
480//=======================================================================
481typedef
482 NCollection_IndexedDataMap<BOPTools_Set,
1155d05a 483 TopTools_ListOfShape,
86218548 484 BOPTools_SetMapHasher> BOPAlgo_IndexedDataMapOfSetListOfShape;
485
486static void AddEdgeSet(const TopoDS_Shape& theS,
487 BOPAlgo_IndexedDataMapOfSetListOfShape& theMap,
488 const Handle(NCollection_BaseAllocator)& theAllocator)
489{
490 // Make set
491 BOPTools_Set aSE;
492 aSE.Add(theS, TopAbs_EDGE);
493 // Add set to the map, keeping connection to the shape
1155d05a 494 TopTools_ListOfShape* pLF = theMap.ChangeSeek(aSE);
86218548 495 if (!pLF)
1155d05a 496 pLF = &theMap(theMap.Add(aSE, TopTools_ListOfShape(theAllocator)));
86218548 497 pLF->Append(theS);
498}
499
4e57c75e 500//=======================================================================
501//function : FillSameDomainFaces
502//purpose :
503//=======================================================================
acccace3 504void BOPAlgo_Builder::FillSameDomainFaces()
4e57c75e 505{
86218548 506 // It is necessary to analyze all Face/Face intersections
507 // and find all faces with equal sets of edges
508 const BOPDS_VectorOfInterfFF& aFFs = myDS->InterfFF();
1155d05a 509 Standard_Integer aNbFFs = aFFs.Length();
86218548 510 if (!aNbFFs)
4e57c75e 511 return;
86218548 512
513 Handle(NCollection_BaseAllocator) aAllocator = new NCollection_IncAllocator;
514
515 // Vector to store the indices of faces for future sorting
516 // for making the SD face for the group from the face with
517 // smallest index in Data structure
1155d05a 518 NCollection_Vector<Standard_Integer> aFIVec(256, aAllocator);
86218548 519 // Fence map to avoid repeated checks of the same face.
1155d05a 520 TColStd_MapOfInteger aMFence(1, aAllocator);
86218548 521
522 // Fill the vector with indices of faces
523 for (Standard_Integer i = 0; i < aNbFFs; ++i)
524 {
525 const BOPDS_InterfFF& aFF = aFFs(i);
526 // get indices
527 Standard_Integer nF[2];
528 aFF.Indices(nF[0], nF[1]);
529 // store indices to the vector
530 for (Standard_Integer j = 0; j < 2; ++j)
531 {
532 if (!myDS->HasFaceInfo(nF[j]))
533 continue;
534
535 if (!aMFence.Add(nF[j]))
536 continue;
537
1155d05a 538 aFIVec.Appended() = nF[j];
86218548 539 }
4e57c75e 540 }
86218548 541
542 // Sort the indices
543 std::sort(aFIVec.begin(), aFIVec.end());
544
545 // Data map of set of edges with all faces having this set
546 NCollection_IndexedDataMap<BOPTools_Set,
1155d05a 547 TopTools_ListOfShape,
86218548 548 BOPTools_SetMapHasher> anESetFaces(1, aAllocator);
549 // Map of planar bounded faces. If such faces have the same Edge set
550 // they are considered Same domain, without additional check.
1155d05a 551 TopTools_MapOfShape aMFPlanar(1, aAllocator);
86218548 552
1155d05a 553 Standard_Integer aNbF = aFIVec.Length();
86218548 554 for (Standard_Integer i = 0; i < aNbF; ++i)
555 {
556 const Standard_Integer nF = aFIVec(i);
557 const BOPDS_ShapeInfo& aSI = myDS->ShapeInfo(nF);
558 const TopoDS_Shape& aF = aSI.Shape();
559
560 Standard_Boolean bCheckPlanar = Standard_False;
561 {
562 // At this stage, context should contain adaptor for all intersected faces,
563 // so getting a type of the underlying surface should be done at no cost.
564 if (myContext->SurfaceAdaptor(TopoDS::Face(aF)).GetType() == GeomAbs_Plane)
565 {
566 // Check bounding box of the face - it should not be open in any side
567 const Bnd_Box& aBox = aSI.Box();
568 bCheckPlanar = !(aBox.IsOpenXmin() || aBox.IsOpenXmax() ||
569 aBox.IsOpenYmin() || aBox.IsOpenYmax() ||
570 aBox.IsOpenZmin() || aBox.IsOpenZmax());
571 }
4e57c75e 572 }
86218548 573
81a55a69 574 const TopTools_ListOfShape* pLFSp = myImages.Seek(aF);
86218548 575 if (pLFSp)
576 {
1155d05a 577 TopTools_ListIteratorOfListOfShape aItLF(*pLFSp);
86218548 578 for (; aItLF.More(); aItLF.Next())
579 {
580 AddEdgeSet(aItLF.Value(), anESetFaces, aAllocator);
581 if (bCheckPlanar)
582 aMFPlanar.Add(aItLF.Value());
c209782c 583 }
86218548 584 }
585 else
586 {
587 AddEdgeSet(aF, anESetFaces, aAllocator);
588 if (bCheckPlanar)
589 aMFPlanar.Add(aF);
590 }
591 }
592
593 // Store pairs of faces with equal set of edges to check if they are really Same Domain
19941687 594 BOPAlgo_VectorOfPairOfShapeBoolean aVPSB;
86218548 595
596 // Back and forth map of SD faces to make the blocks
1155d05a 597 TopTools_IndexedDataMapOfShapeListOfShape aDMSLS(1, aAllocator);
86218548 598
599 Standard_Integer aNbSets = anESetFaces.Extent();
600 for (Standard_Integer i = 1; i <= aNbSets; ++i)
601 {
1155d05a 602 const TopTools_ListOfShape& aLF = anESetFaces(i);
86218548 603 if (aLF.Extent() < 2)
4e57c75e 604 continue;
86218548 605
606 // All possible pairs from <aLF> should be checked
1155d05a 607 TopTools_ListIteratorOfListOfShape aIt1(aLF);
86218548 608 for (; aIt1.More(); aIt1.Next())
609 {
610 const TopoDS_Shape& aF1 = aIt1.Value();
611 Standard_Boolean bCheckPlanar = aMFPlanar.Contains(aF1);
612
1155d05a 613 TopTools_ListIteratorOfListOfShape aIt2 = aIt1;
86218548 614 for (aIt2.Next(); aIt2.More(); aIt2.Next())
615 {
616 const TopoDS_Shape& aF2 = aIt2.Value();
617 if (bCheckPlanar && aMFPlanar.Contains(aF2))
618 {
619 // Consider planar bounded faces as Same Domain without additional check
620 BOPAlgo_Tools::FillMap<TopoDS_Shape, TopTools_ShapeMapHasher>(aF1, aF2, aDMSLS, aAllocator);
621 continue;
622 }
623 // Add pair for analysis
1155d05a 624 BOPAlgo_PairOfShapeBoolean& aPSB = aVPSB.Appended();
86218548 625 aPSB.Shape1() = aF1;
626 aPSB.Shape2() = aF2;
0d0481c7 627 aPSB.SetFuzzyValue(myFuzzyValue);
36f4947b 628 aPSB.SetProgressIndicator(myProgressIndicator);
4e57c75e 629 }
19941687 630 }
631 }
86218548 632
36f4947b 633 //================================================================
86218548 634 // Perform analysis
fc867b96 635 BOPTools_Parallel::Perform (myRunParallel, aVPSB, myContext);
36f4947b 636 //================================================================
86218548 637
1155d05a 638 NCollection_List<TopTools_ListOfShape> aMBlocks(aAllocator);
86218548 639 // Fill map with SD faces to make the blocks
1155d05a 640 Standard_Integer aNbPairs = aVPSB.Length();
86218548 641 for (Standard_Integer i = 0; i < aNbPairs; ++i)
642 {
643 BOPAlgo_PairOfShapeBoolean& aPSB = aVPSB(i);
644 if (aPSB.Flag())
645 BOPAlgo_Tools::FillMap<TopoDS_Shape, TopTools_ShapeMapHasher>
646 (aPSB.Shape1(), aPSB.Shape2(), aDMSLS, aAllocator);
19941687 647 }
648 aVPSB.Clear();
86218548 649
650 // Make blocks of SD faces using the back and forth map
651 BOPAlgo_Tools::MakeBlocks<TopoDS_Shape, TopTools_ShapeMapHasher>
652 (aDMSLS, aMBlocks, aAllocator);
653
654 // Fill same domain faces map
1155d05a 655 NCollection_List<TopTools_ListOfShape>::Iterator aItB(aMBlocks);
86218548 656 for (; aItB.More(); aItB.Next())
657 {
1155d05a 658 const TopTools_ListOfShape& aLSD = aItB.Value();
81a55a69 659 // If the group contains some original faces, the one with minimal
660 // index in the DS will be chosen as the SD for the whole group.
661 // If there are no original faces in the group, the first face from
662 // the group will be used as the SD face.
663 // Such SD face will be representative of the whole group in the result.
664 TopoDS_Face* pFSD = NULL;
665 Standard_Integer nFMin = ::IntegerLast();
1155d05a 666 TopTools_ListIteratorOfListOfShape aItLF(aLSD);
86218548 667 for (; aItLF.More(); aItLF.Next())
668 {
81a55a69 669 const TopoDS_Shape& aF = aItLF.Value();
670 // Check the index of the face in DS
671 const Standard_Integer nF = myDS->Index(aF);
672 if (nF >= 0)
673 {
674 // The fact that the face is found in the DS, means that
675 // the face has not been change, and thus it is original one.
676 //
677 // Such face does not have any splits, but have an SD face.
678 // Consider it being split.
679 myImages.Bound(aF, TopTools_ListOfShape())->Append(aF);
680
681 // For the SD face chose the one with minimal index
682 if (nF < nFMin)
683 {
684 nFMin = nF;
685 pFSD = (TopoDS_Face*)&aF;
686 }
687 }
688 }
689
690 if (!pFSD)
691 {
692 // No original faces in the group, take the first one
693 pFSD = (TopoDS_Face*)&aLSD.First();
694 }
695
696 // Save all SD connections
697 aItLF.Initialize(aLSD);
698 for (; aItLF.More(); aItLF.Next())
699 {
700 const TopoDS_Shape& aF = aItLF.Value();
701 myShapesSD.Bind(aF, *pFSD);
19941687 702 }
c209782c 703 }
81a55a69 704
705 // Update the map of images with SD faces and
706 // fill the map of origins.
707 Standard_Integer aNbS = myDS->NbSourceShapes();
708 for (Standard_Integer i = 0; i < aNbS; ++i)
709 {
710 const BOPDS_ShapeInfo& aSI = myDS->ShapeInfo(i);
711 if (aSI.ShapeType() != TopAbs_FACE)
712 continue;
713
714 const TopoDS_Shape& aF = aSI.Shape();
715 TopTools_ListOfShape* pLFIm = myImages.ChangeSeek(aF);
716 if (!pLFIm)
717 continue;
718
719 TopTools_ListIteratorOfListOfShape aItLFIm(*pLFIm);
720 for (; aItLFIm.More(); aItLFIm.Next())
721 {
722 TopoDS_Shape& aFIm = aItLFIm.ChangeValue();
723 const TopoDS_Shape* pFSD = myShapesSD.Seek(aFIm);
724 if (pFSD)
725 // Update image with SD face
726 aFIm = *pFSD;
727
728 // Fill the map of origins
729 TopTools_ListOfShape* pLFOr = myOrigins.ChangeSeek(aFIm);
730 if (!pLFOr)
731 pLFOr = myOrigins.Bound(aFIm, TopTools_ListOfShape());
732 pLFOr->Append(aF);
733 }
734 }
735
4e57c75e 736 aMBlocks.Clear();
737 aDMSLS.Clear();
4e57c75e 738}
739//=======================================================================
740// function: FillImagesFaces1
741// purpose:
742//=======================================================================
81a55a69 743void BOPAlgo_Builder::FillInternalVertices()
4e57c75e 744{
81a55a69 745 // Vector of pairs of Vertex/Face for classification of the vertices
746 // relatively faces, and adding them as internal into the faces
a0a3f6ac 747 BOPAlgo_VectorOfVFI aVVFI;
81a55a69 748
749 Standard_Integer aNbS = myDS->NbSourceShapes();
750 for (Standard_Integer i = 0; i < aNbS; ++i)
751 {
752 const BOPDS_ShapeInfo& aSI = myDS->ShapeInfo(i);
753 if (aSI.ShapeType() != TopAbs_FACE)
4e57c75e 754 continue;
81a55a69 755
756 const TopoDS_Shape& aF = aSI.Shape();
757 const TopTools_ListOfShape* pLFIm = myImages.Seek(aF);
758 if (!pLFIm)
4e57c75e 759 continue;
81a55a69 760
761 // Find vertices to add as internal into the splits
762 TColStd_ListOfInteger aLIAV;
4e57c75e 763 myDS->AloneVertices(i, aLIAV);
81a55a69 764
765 // Add vertices and faces for classification
766 TColStd_ListIteratorOfListOfInteger aItLV(aLIAV);
767 for (; aItLV.More(); aItLV.Next())
768 {
769 TopoDS_Vertex aV = TopoDS::Vertex(myDS->Shape(aItLV.Value()));
770 aV.Orientation(TopAbs_INTERNAL);
771
772 TopTools_ListIteratorOfListOfShape aItLFIm(*pLFIm);
773 for (; aItLFIm.More(); aItLFIm.Next())
774 {
775 const TopoDS_Face& aFIm = TopoDS::Face(aItLFIm.Value());
776 // Make the pair
777 BOPAlgo_VFI& aVFI = aVVFI.Appended();
778 aVFI.SetVertex(aV);
779 aVFI.SetFace(aFIm);
0d0481c7 780 aVFI.SetFuzzyValue(myFuzzyValue);
36f4947b 781 aVFI.SetProgressIndicator(myProgressIndicator);
4e57c75e 782 }
783 }
81a55a69 784 }
785
786 // Perform classification
a0a3f6ac 787 //================================================================
fc867b96 788 BOPTools_Parallel::Perform (myRunParallel, aVVFI, myContext);
a0a3f6ac 789 //================================================================
81a55a69 790
791 Standard_Integer aNbVFI = aVVFI.Length();
792 for (Standard_Integer i = 0; i < aNbVFI; ++i)
793 {
794 BOPAlgo_VFI& aVFI = aVVFI(i);
795 if (aVFI.IsInternal())
796 {
797 TopoDS_Vertex& aV = aVFI.Vertex();
798 TopoDS_Face& aF = aVFI.Face();
799 BRep_Builder().Add(aF, aV);
a0a3f6ac 800 }
4e57c75e 801 }
802}
98b37659 803//=======================================================================
1ccef79a 804//function : HasMultiConnected
805//purpose : Checks if the edge has multi-connected vertices.
806//=======================================================================
807static Standard_Boolean HasMultiConnected(const TopoDS_Edge& theEdge,
80d55adf 808 TopTools_DataMapOfShapeListOfShape& theMap)
1ccef79a 809{
810 TopoDS_Iterator itV(theEdge);
811 for (; itV.More(); itV.Next())
812 {
813 const TopoDS_Shape& aV = itV.Value();
80d55adf 814 TopTools_ListOfShape *pList = theMap.ChangeSeek(aV);
815 if (!pList)
816 {
817 pList = theMap.Bound(aV, TopTools_ListOfShape());
818 pList->Append(theEdge);
819 }
1ccef79a 820 else
821 {
80d55adf 822 // The list is expected to be 1-2 elements long,
823 // thus using "Contains" is safe.
824 if (!pList->Contains(theEdge))
825 pList->Append(theEdge);
1ccef79a 826
80d55adf 827 if (pList->Extent() > 2)
828 return Standard_True;
1ccef79a 829 }
830 }
831 return Standard_False;
832}
833//=======================================================================
98b37659 834//function : BuildDraftFace
835//purpose : Build draft faces, updating the bounding edges,
836// according to the information stored into the <theImages> map
837//=======================================================================
838TopoDS_Face BuildDraftFace(const TopoDS_Face& theFace,
1155d05a 839 const TopTools_DataMapOfShapeListOfShape& theImages,
80d55adf 840 Handle(IntTools_Context)& theCtx,
841 const Handle(Message_Report)& theReport)
98b37659 842{
843 BRep_Builder aBB;
844 // Take the information from the original face
845 TopLoc_Location aLoc;
846 const Handle(Geom_Surface)& aS = BRep_Tool::Surface(theFace, aLoc);
847 const Standard_Real aTol = BRep_Tool::Tolerance(theFace);
848 // Make the new face, without any wires
849 TopoDS_Face aDraftFace;
850 aBB.MakeFace(aDraftFace, aS, aLoc, aTol);
851
1ccef79a 852 // Check if the thin face can be split by a vertex - in this case
853 // this vertex will be contained in more than two edges. Thus, count
854 // the vertices appearance, and if the multi-connexity is met return
855 // the null face to use the BuilderFace algorithm for checking the
856 // possibility of split.
80d55adf 857 TopTools_DataMapOfShapeListOfShape aVerticesCounter;
1ccef79a 858
4ccdb6f6 859 // Check that the edges of the initial face have not been unified during intersection.
860 // Otherwise, it will be necessary to check validity of the new wires.
861 TopTools_MapOfShape aMEdges;
862
98b37659 863 // Update wires of the original face and add them to draft face
864 TopoDS_Iterator aItW(theFace.Oriented(TopAbs_FORWARD));
865 for (; aItW.More(); aItW.Next())
866 {
867 const TopoDS_Shape& aW = aItW.Value();
868 if (aW.ShapeType() != TopAbs_WIRE)
869 continue;
870
871 // Rebuild wire using images of edges
872 TopoDS_Iterator aItE(aW.Oriented(TopAbs_FORWARD));
873 if (!aItE.More())
874 continue;
875
876 TopoDS_Wire aNewWire;
877 aBB.MakeWire(aNewWire);
878
879 for (; aItE.More(); aItE.Next())
880 {
881 const TopoDS_Edge& aE = TopoDS::Edge(aItE.Value());
882
883 TopAbs_Orientation anOriE = aE.Orientation();
884 if (anOriE == TopAbs_INTERNAL)
885 {
886 // The internal edges could split the original face on halves.
887 // Thus, use the BuilderFace algorithm to build the new face.
1ccef79a 888 return TopoDS_Face();
98b37659 889 }
890
80d55adf 891 // Check if the original edge is degenerated
892 Standard_Boolean bIsDegenerated = BRep_Tool::Degenerated(aE);
4ccdb6f6 893 // Check if the original edge is closed on the face
894 Standard_Boolean bIsClosed = BRep_Tool::IsClosed(aE, theFace);
80d55adf 895
1ccef79a 896 // Check for the splits of the edge
1155d05a 897 const TopTools_ListOfShape* pLEIm = theImages.Seek(aE);
98b37659 898 if (!pLEIm)
899 {
1ccef79a 900 // Check if the edge has multi-connected vertices
80d55adf 901 if (!bIsDegenerated && HasMultiConnected(aE, aVerticesCounter))
1ccef79a 902 return TopoDS_Face();
903
4ccdb6f6 904 // Check edges unification
905 if (!bIsClosed && !aMEdges.Add(aE))
906 return TopoDS_Face();
907
98b37659 908 aBB.Add(aNewWire, aE);
909 continue;
910 }
911
1155d05a 912 TopTools_ListIteratorOfListOfShape aItLEIm(*pLEIm);
98b37659 913 for (; aItLEIm.More(); aItLEIm.Next())
914 {
915 TopoDS_Edge& aSp = TopoDS::Edge(aItLEIm.Value());
916
1ccef79a 917 // Check if the split has multi-connected vertices
80d55adf 918 if (!bIsDegenerated && HasMultiConnected(aSp, aVerticesCounter))
1ccef79a 919 return TopoDS_Face();
920
4ccdb6f6 921 // Check edges unification
922 if (!bIsClosed && !aMEdges.Add(aSp))
923 return TopoDS_Face();
924
98b37659 925 aSp.Orientation(anOriE);
926 if (bIsDegenerated)
927 {
928 aBB.Add(aNewWire, aSp);
929 continue;
930 }
931
80d55adf 932 // If the original edge is closed on the face check closeness
933 // of the split edge and if it is not closed make the second PCurve
98b37659 934 if (bIsClosed && !BRep_Tool::IsClosed(aSp, theFace))
935 BOPTools_AlgoTools3D::DoSplitSEAMOnFace(aSp, theFace);
936
937 // Check if the split should be reversed
80d55adf 938 if (BOPTools_AlgoTools::IsSplitToReverseWithWarn(aSp, aE, theCtx, theReport))
98b37659 939 aSp.Reverse();
940
941 aBB.Add(aNewWire, aSp);
942 }
943 }
944
945 aNewWire.Orientation(aW.Orientation());
946 aNewWire.Closed(BRep_Tool::IsClosed(aNewWire));
947 aBB.Add(aDraftFace, aNewWire);
948 }
949
950 if (theFace.Orientation() == TopAbs_REVERSED)
951 aDraftFace.Reverse();
952
953 return aDraftFace;
954}