0029711: General Fuse operation produces invalid result
[occt.git] / src / BOPAlgo / BOPAlgo_PaveFiller_5.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
4e57c75e 18
4e57c75e 19#include <Bnd_Box.hxx>
42cf5bc1 20#include <BOPAlgo_PaveFiller.hxx>
33ba8565 21#include <BOPAlgo_Alerts.hxx>
42cf5bc1 22#include <BOPAlgo_Tools.hxx>
42cf5bc1 23#include <BOPDS_CommonBlock.hxx>
24#include <BOPDS_CoupleOfPaveBlocks.hxx>
25#include <BOPDS_Curve.hxx>
42cf5bc1 26#include <BOPDS_DS.hxx>
27#include <BOPDS_Interf.hxx>
28#include <BOPDS_Iterator.hxx>
29#include <BOPDS_MapOfPaveBlock.hxx>
30#include <BOPDS_Pave.hxx>
31#include <BOPDS_PaveBlock.hxx>
32#include <BOPTools_AlgoTools.hxx>
d3578357 33#include <BOPTools_AlgoTools2D.hxx>
34#include <BOPTools_BoxSelector.hxx>
1155d05a 35#include <BOPTools_Parallel.hxx>
42cf5bc1 36#include <BRep_Builder.hxx>
4e57c75e 37#include <BRep_Tool.hxx>
e30616a7 38#include <BRepAdaptor_Curve.hxx>
d3578357 39#include <GeomAPI_ProjectPointOnSurf.hxx>
42cf5bc1 40#include <gp_Pnt.hxx>
41#include <IntTools_CommonPrt.hxx>
42#include <IntTools_Context.hxx>
4e57c75e 43#include <IntTools_EdgeFace.hxx>
44#include <IntTools_Range.hxx>
45#include <IntTools_SequenceOfCommonPrts.hxx>
42cf5bc1 46#include <IntTools_Tools.hxx>
d3578357 47#include <NCollection_IncAllocator.hxx>
1155d05a 48#include <NCollection_Vector.hxx>
8ae442a8 49#include <Precision.hxx>
1155d05a 50#include <TColStd_MapOfInteger.hxx>
3510db62 51#include <TopoDS.hxx>
42cf5bc1 52#include <TopoDS_Edge.hxx>
53#include <TopoDS_Face.hxx>
54#include <TopoDS_Vertex.hxx>
55
e30616a7 56//=======================================================================
57//class : BOPAlgo_EdgeFace
58//purpose :
59//=======================================================================
36f4947b 60class BOPAlgo_EdgeFace :
61 public IntTools_EdgeFace,
62 public BOPAlgo_Algo {
63
e30616a7 64 public:
36f4947b 65 DEFINE_STANDARD_ALLOC
66
67 BOPAlgo_EdgeFace() :
68 IntTools_EdgeFace(),
69 BOPAlgo_Algo(),
70 myIE(-1), myIF(-1) {
e30616a7 71 };
72 //
36f4947b 73 virtual ~BOPAlgo_EdgeFace(){
e30616a7 74 };
75 //
76 void SetIndices(const Standard_Integer nE,
77 const Standard_Integer nF) {
78 myIE=nE;
79 myIF=nF;
80 }
81 //
82 void Indices(Standard_Integer& nE,
83 Standard_Integer& nF) {
84 nE=myIE;
85 nF=myIF;
86 }
87 //
88 void SetNewSR(const IntTools_Range& aR){
89 myNewSR=aR;
90 }
91 //
92 IntTools_Range& NewSR(){
93 return myNewSR;
94 }
95 //
96 void SetPaveBlock(const Handle(BOPDS_PaveBlock)& aPB) {
97 myPB=aPB;
98 }
99 //
100 Handle(BOPDS_PaveBlock)& PaveBlock() {
101 return myPB;
102 }
103 //
0d0481c7 104 void SetFuzzyValue(const Standard_Real theFuzz) {
105 IntTools_EdgeFace::SetFuzzyValue(theFuzz);
106 }
107 //
36f4947b 108 virtual void Perform() {
109 BOPAlgo_Algo::UserBreak();
ad8b073e 110 try
111 {
112 OCC_CATCH_SIGNALS
113
114 IntTools_EdgeFace::Perform();
115 }
116 catch (Standard_Failure)
117 {
118 AddError(new BOPAlgo_AlertIntersectionFailed);
119 }
36f4947b 120 }
121 //
e30616a7 122 protected:
123 Standard_Integer myIE;
124 Standard_Integer myIF;
125 IntTools_Range myNewSR;
126 Handle(BOPDS_PaveBlock) myPB;
127};
128//
129//=======================================================================
1155d05a 130typedef NCollection_Vector<BOPAlgo_EdgeFace> BOPAlgo_VectorOfEdgeFace;
e30616a7 131//
1155d05a 132typedef BOPTools_ContextFunctor
e30616a7 133 <BOPAlgo_EdgeFace,
134 BOPAlgo_VectorOfEdgeFace,
1e143abb 135 Handle(IntTools_Context),
136 IntTools_Context> BOPAlgo_EdgeFaceFunctor;
e30616a7 137//
1155d05a 138typedef BOPTools_ContextCnt
e30616a7 139 <BOPAlgo_EdgeFaceFunctor,
140 BOPAlgo_VectorOfEdgeFace,
1e143abb 141 Handle(IntTools_Context)> BOPAlgo_EdgeFaceCnt;
e30616a7 142//
4e57c75e 143//=======================================================================
144//function : PerformEF
145//purpose :
146//=======================================================================
e30616a7 147void BOPAlgo_PaveFiller::PerformEF()
4e57c75e 148{
e30616a7 149 FillShrunkData(TopAbs_EDGE, TopAbs_FACE);
150 //
4e57c75e 151 myIterator->Initialize(TopAbs_EDGE, TopAbs_FACE);
483ce1bd 152 Standard_Integer iSize = myIterator->ExpectedLength();
4e57c75e 153 if (!iSize) {
154 return;
155 }
e30616a7 156 //
483ce1bd 157 Standard_Integer nE, nF;
158 //
159 if (myGlue == BOPAlgo_GlueFull) {
160 // there is no need to intersect edges with faces in this mode
161 // just initialize FaceInfo for faces
162 for (; myIterator->More(); myIterator->Next()) {
25dfc507 163 myIterator->Value(nE, nF);
164 if (!myDS->ShapeInfo(nE).HasFlag()) {
483ce1bd 165 myDS->ChangeFaceInfo(nF);
166 }
167 }
168 return;
169 }
170 //
171 Standard_Boolean bV[2], bIsPBSplittable;
6dc83e21 172 Standard_Boolean bV1, bV2, bExpressCompute;
173 Standard_Integer nV1, nV2;
03cca6f7 174 Standard_Integer i, aNbCPrts, iX, nV[2];
e30616a7 175 Standard_Integer aNbEdgeFace, k;
03cca6f7 176 Standard_Real aTolE, aTolF, aTS1, aTS2, aT1, aT2;
488e5b9d 177 Handle(NCollection_BaseAllocator) aAllocator;
4e57c75e 178 TopAbs_ShapeEnum aType;
179 BOPDS_ListIteratorOfListOfPaveBlock aIt;
e30616a7 180 BOPAlgo_VectorOfEdgeFace aVEdgeFace;
e30616a7 181 //-----------------------------------------------------scope f
4e57c75e 182 //
488e5b9d 183 aAllocator=NCollection_BaseAllocator::CommonBaseAllocator();
184 //
1155d05a 185 TColStd_MapOfInteger aMIEFC(100, aAllocator);
4e57c75e 186 BOPDS_IndexedDataMapOfShapeCoupleOfPaveBlocks aMVCPB(100, aAllocator);
187 BOPDS_IndexedDataMapOfPaveBlockListOfInteger aMPBLI(100, aAllocator);
01b5b3df 188 BOPAlgo_DataMapOfPaveBlockBndBox aDMPBBox(100, aAllocator);
4e57c75e 189 //
4e57c75e 190 BOPDS_VectorOfInterfEF& aEFs=myDS->InterfEF();
4e57c75e 191 aEFs.SetIncrement(iSize);
4e57c75e 192 //
193 for (; myIterator->More(); myIterator->Next()) {
25dfc507 194 myIterator->Value(nE, nF);
4e57c75e 195 //
196 const BOPDS_ShapeInfo& aSIE=myDS->ShapeInfo(nE);
197 if (aSIE.HasFlag()){//degenerated
198 continue;
199 }
200 //
201 const TopoDS_Edge& aE=(*(TopoDS_Edge *)(&aSIE.Shape()));
202 const TopoDS_Face& aF=(*(TopoDS_Face *)(&myDS->Shape(nF)));
203 const Bnd_Box& aBBF=myDS->ShapeInfo(nF).Box();
204 //
205 BOPDS_FaceInfo& aFI=myDS->ChangeFaceInfo(nF);
206 const BOPDS_IndexedMapOfPaveBlock& aMPBF=aFI.PaveBlocksOn();
4e57c75e 207 //
1155d05a 208 const TColStd_MapOfInteger& aMVIn=aFI.VerticesIn();
209 const TColStd_MapOfInteger& aMVOn=aFI.VerticesOn();
6dc83e21 210 //
4e57c75e 211 aTolE=BRep_Tool::Tolerance(aE);
212 aTolF=BRep_Tool::Tolerance(aF);
213 //
214 BOPDS_ListOfPaveBlock& aLPB=myDS->ChangePaveBlocks(nE);
215 aIt.Initialize(aLPB);
216 for (; aIt.More(); aIt.Next()) {
217 Handle(BOPDS_PaveBlock)& aPB=aIt.ChangeValue();
218 //
5a77460e 219 const Handle(BOPDS_PaveBlock) aPBR=myDS->RealPaveBlock(aPB);
4e57c75e 220 if (aMPBF.Contains(aPBR)) {
221 continue;
222 }
223 //
01b5b3df 224 Bnd_Box aBBE;
225 if (!GetPBBox(aE, aPB, aDMPBBox, aT1, aT2, aTS1, aTS2, aBBE)) {
e30616a7 226 continue;
4e57c75e 227 }
228 //
4e57c75e 229 if (aBBF.IsOut (aBBE)) {
230 continue;
231 }
232 //
6dc83e21 233 aPBR->Indices(nV1, nV2);
234 bV1=aMVIn.Contains(nV1) || aMVOn.Contains(nV1);
235 bV2=aMVIn.Contains(nV2) || aMVOn.Contains(nV2);
236 bExpressCompute=bV1 && bV2;
237 //
1155d05a 238 BOPAlgo_EdgeFace& aEdgeFace=aVEdgeFace.Appended();
e30616a7 239 //
240 aEdgeFace.SetIndices(nE, nF);
241 aEdgeFace.SetPaveBlock(aPB);
4e57c75e 242 //
243 aEdgeFace.SetEdge (aE);
244 aEdgeFace.SetFace (aF);
0d0481c7 245 aEdgeFace.SetFuzzyValue(myFuzzyValue);
6dc83e21 246 aEdgeFace.UseQuickCoincidenceCheck(bExpressCompute);
4e57c75e 247 //
248 IntTools_Range aSR(aTS1, aTS2);
249 IntTools_Range anewSR=aSR;
4e57c75e 250 BOPTools_AlgoTools::CorrectRange(aE, aF, aSR, anewSR);
e30616a7 251 aEdgeFace.SetNewSR(anewSR);
b4109929 252 //
b4109929 253 IntTools_Range aPBRange(aT1, aT2);
254 aSR = aPBRange;
255 BOPTools_AlgoTools::CorrectRange(aE, aF, aSR, aPBRange);
b4109929 256 aEdgeFace.SetRange (aPBRange);
36f4947b 257 aEdgeFace.SetProgressIndicator(myProgressIndicator);
d3578357 258 // Save the pair to avoid their forced intersection
259 BOPDS_MapOfPaveBlock* pMPB = myFPBDone.ChangeSeek(nF);
260 if (!pMPB)
261 pMPB = myFPBDone.Bound(nF, BOPDS_MapOfPaveBlock());
262 pMPB->Add(aPB);
e30616a7 263 }//for (; aIt.More(); aIt.Next()) {
264 }//for (; myIterator->More(); myIterator->Next()) {
265 //
1155d05a 266 aNbEdgeFace=aVEdgeFace.Length();
e30616a7 267 //=================================================================
268 BOPAlgo_EdgeFaceCnt::Perform(myRunParallel, aVEdgeFace, myContext);
269 //=================================================================
270 //
271 for (k=0; k < aNbEdgeFace; ++k) {
272 BOPAlgo_EdgeFace& aEdgeFace=aVEdgeFace(k);
ad8b073e 273 if (!aEdgeFace.IsDone() || aEdgeFace.HasErrors()) {
274 // Warn about failed intersection of sub-shapes
275 AddIntersectionFailedWarning(aEdgeFace.Edge(), aEdgeFace.Face());
e30616a7 276 continue;
277 }
51db0179 278 //
279 const IntTools_SequenceOfCommonPrts& aCPrts=aEdgeFace.CommonParts();
280 aNbCPrts = aCPrts.Length();
281 if (!aNbCPrts) {
282 continue;
283 }
284 //
e30616a7 285 aEdgeFace.Indices(nE, nF);
286 //
287 const TopoDS_Edge& aE=aEdgeFace.Edge();
288 const TopoDS_Face& aF=aEdgeFace.Face();
289 //
0d0481c7 290 aTolE=BRep_Tool::Tolerance(aE);
291 aTolF=BRep_Tool::Tolerance(aF);
e30616a7 292 const IntTools_Range& anewSR=aEdgeFace.NewSR();
293 Handle(BOPDS_PaveBlock)& aPB=aEdgeFace.PaveBlock();
294 //
295 aPB->Range(aT1, aT2);
296 aPB->Indices(nV[0], nV[1]);
01b5b3df 297 bIsPBSplittable = aPB->IsSplittable();
298 //
01b5b3df 299 anewSR.Range(aTS1, aTS2);
300 //
51db0179 301 if (aCPrts(1).Type() == TopAbs_VERTEX) {
302 // for the intersection type VERTEX
303 // extend vertices ranges using Edge/Edge intersections
304 // between the edge aE and the edges of the face aF.
305 // thereby the edge's intersection range is reduced
306 ReduceIntersectionRange(nV[0], nV[1], nE, nF, aTS1, aTS2);
307 }
01b5b3df 308 //
309 IntTools_Range aR1(aT1, aTS1), aR2(aTS2, aT2);
e30616a7 310 //
311 BOPDS_FaceInfo& aFI=myDS->ChangeFaceInfo(nF);
1155d05a 312 const TColStd_MapOfInteger& aMIFOn=aFI.VerticesOn();
313 const TColStd_MapOfInteger& aMIFIn=aFI.VerticesIn();
3510db62 314 //
315 Standard_Boolean bLinePlane = Standard_False;
316 if (aNbCPrts) {
317 BRepAdaptor_Curve aBAC(aE);
3510db62 318 bLinePlane = (aBAC.GetType() == GeomAbs_Line &&
51db0179 319 myContext->SurfaceAdaptor(aF).GetType() == GeomAbs_Plane);
3510db62 320 }
51db0179 321 //
e30616a7 322 for (i=1; i<=aNbCPrts; ++i) {
323 const IntTools_CommonPrt& aCPart=aCPrts(i);
324 aType=aCPart.Type();
325 switch (aType) {
01b5b3df 326 case TopAbs_VERTEX: {
b4109929 327 Standard_Boolean bIsOnPave[2];
328 Standard_Integer j;
4e57c75e 329 Standard_Real aT, aTolToDecide;
330 TopoDS_Vertex aVnew;
e30616a7 331 //
1e143abb 332 IntTools_Tools::VertexParameter(aCPart, aT);
4e57c75e 333 BOPTools_AlgoTools::MakeNewVertex(aE, aT, aF, aVnew);
334 //
335 const IntTools_Range& aR=aCPart.Range1();
336 aTolToDecide=5.e-8;
4e57c75e 337 //
1e143abb 338 bIsOnPave[0]=IntTools_Tools::IsInRange(aR1, aR, aTolToDecide);
339 bIsOnPave[1]=IntTools_Tools::IsInRange(aR2, aR, aTolToDecide);
b4109929 340 //
3510db62 341 if ((bIsOnPave[0] && bIsOnPave[1]) ||
342 (bLinePlane && (bIsOnPave[0] || bIsOnPave[1]))) {
b4109929 343 bV[0]=CheckFacePaves(nV[0], aMIFOn, aMIFIn);
344 bV[1]=CheckFacePaves(nV[1], aMIFOn, aMIFIn);
345 if (bV[0] && bV[1]) {
4e57c75e 346 IntTools_CommonPrt aCP = aCPart;
347 aCP.SetType(TopAbs_EDGE);
1155d05a 348 BOPDS_InterfEF& aEF=aEFs.Appended();
349 iX=aEFs.Length()-1;
4e57c75e 350 aEF.SetIndices(nE, nF);
351 aEF.SetCommonPart(aCP);
352 myDS->AddInterf(nE, nF);
ceb31c61 353 //
354 aMIEFC.Add(nF);
355 //
4e57c75e 356 BOPAlgo_Tools::FillMap(aPB, nF, aMPBLI, aAllocator);
357 break;
358 }
359 }
01b5b3df 360 //
361 if (!bIsPBSplittable) {
362 continue;
363 }
364 //
d3578357 365 for (j = 0; j < 2; ++j)
366 {
367 if (bIsOnPave[j])
368 {
369 bV[j] = CheckFacePaves(nV[j], aMIFOn, aMIFIn);
370 if (!bV[j])
b4109929 371 bIsOnPave[j] = ForceInterfVF(nV[j], nF);
4e57c75e 372 }
4e57c75e 373 }
d3578357 374
375 if (bIsOnPave[0] || bIsOnPave[1])
376 {
377 // The found intersection point is located closely to one of the pave block's
378 // bounds. So, do not create the new vertex in this point.
379 // Check if this point is a real intersection, or just a touching point.
380 // If it is a touching point, do nothing.
381 // If it is an intersection point, update the existing vertex to cover the
382 // intersection point.
383 GeomAPI_ProjectPointOnSurf& aProjPS = myContext->ProjPS(aF);
384 const gp_Pnt aPnew = BRep_Tool::Pnt(aVnew);
385 aProjPS.Perform(aPnew);
386 Standard_Real aMinDistEF = (aProjPS.IsDone() && aProjPS.NbPoints()) ?
387 aProjPS.LowerDistance() : Precision::Infinite();
388 Standard_Boolean hasRealIntersection = aMinDistEF < Precision::Intersection();
389
390 if (!hasRealIntersection)
391 // no intersection point
4e57c75e 392 continue;
d3578357 393
394 // Real intersection is present.
395 // Update the existing vertex to cover the intersection point.
396 for (j = 0; j < 2; ++j)
397 {
398 if (bIsOnPave[j])
399 {
400 const TopoDS_Vertex& aV = TopoDS::Vertex(myDS->Shape(nV[j]));
401 const gp_Pnt aP = BRep_Tool::Pnt(aV);
402 Standard_Real aDistPP = aP.Distance(aPnew);
403 UpdateVertex(nV[j], aDistPP);
404 myVertsToAvoidExtension.Add(nV[j]);
405 }
4e57c75e 406 }
d3578357 407 continue;
408 }
409
410 if (CheckFacePaves(aVnew, aMIFOn)) {
411 continue;
412 }
413 //
414 Standard_Real aTolVnew = BRep_Tool::Tolerance(aVnew);
415 aTolVnew = Max(aTolVnew, Max(aTolE, aTolF));
416 BRep_Builder().UpdateVertex(aVnew, aTolVnew);
417 if (bLinePlane) {
418 // increase tolerance for Line/Plane intersection, but do not update
419 // the vertex till its intersection with some other shape
420 IntTools_Range aCR = aCPart.Range1();
421 aTolVnew = Max(aTolVnew, (aCR.Last() - aCR.First()) / 2.);
4e57c75e 422 }
d3578357 423 //
424 const gp_Pnt& aPnew = BRep_Tool::Pnt(aVnew);
425 //
426 if (!myContext->IsPointInFace(aPnew, aF, aTolVnew)) {
427 continue;
428 }
429 //
430 aMIEFC.Add(nF);
431 // 1
432 BOPDS_InterfEF& aEF = aEFs.Appended();
433 iX = aEFs.Length() - 1;
434 aEF.SetIndices(nE, nF);
435 aEF.SetCommonPart(aCPart);
436 // 2
437 myDS->AddInterf(nE, nF);
438 // 3
439 BOPDS_CoupleOfPaveBlocks aCPB;
440 //
441 aCPB.SetPaveBlocks(aPB, aPB);
442 aCPB.SetIndexInterf(iX);
443 aCPB.SetTolerance(aTolVnew);
444 aMVCPB.Add(aVnew, aCPB);
4e57c75e 445 }
446 break;
447 case TopAbs_EDGE: {
448 aMIEFC.Add(nF);
449 //
450 // 1
1155d05a 451 BOPDS_InterfEF& aEF=aEFs.Appended();
452 iX=aEFs.Length()-1;
4e57c75e 453 aEF.SetIndices(nE, nF);
454 //
b4109929 455 bV[0]=CheckFacePaves(nV[0], aMIFOn, aMIFIn);
456 bV[1]=CheckFacePaves(nV[1], aMIFOn, aMIFIn);
457 if (!bV[0] || !bV[1]) {
4e57c75e 458 myDS->AddInterf(nE, nF);
459 break;
460 }
4e57c75e 461 aEF.SetCommonPart(aCPart);
462 // 2
463 myDS->AddInterf(nE, nF);
464 // 3
465 BOPAlgo_Tools::FillMap(aPB, nF, aMPBLI, aAllocator);
466
467 }
468 break;
469 default:
470 break;
e30616a7 471 }//switch (aType) {
472 }//for (i=1; i<=aNbCPrts; ++i) {
473 }// for (k=0; k < aNbEdgeEdge; ++k) {
4e57c75e 474 //
475 //=========================================
476 // post treatment
477 //=========================================
d3578357 478 BOPAlgo_Tools::PerformCommonBlocks(aMPBLI, aAllocator, myDS, myContext);
479 UpdateVerticesOfCB();
8ae442a8 480 PerformNewVertices(aMVCPB, aAllocator, Standard_False);
4e57c75e 481 //
482 // Update FaceInfoIn for all faces having EF common parts
1155d05a 483 TColStd_MapIteratorOfMapOfInteger aItMI;
4e57c75e 484 aItMI.Initialize(aMIEFC);
485 for (; aItMI.More(); aItMI.Next()) {
486 nF=aItMI.Value();
487 myDS->UpdateFaceInfoIn(nF);
488 }
4e57c75e 489 //-----------------------------------------------------scope t
490 aMIEFC.Clear();
491 aMVCPB.Clear();
492 aMPBLI.Clear();
e30616a7 493 ////aAllocator.Nullify();
4e57c75e 494}
495//=======================================================================
4e57c75e 496// function: CheckFacePaves
497// purpose:
498//=======================================================================
e30616a7 499Standard_Boolean BOPAlgo_PaveFiller::CheckFacePaves
500 (const Standard_Integer nVx,
1155d05a 501 const TColStd_MapOfInteger& aMIFOn,
502 const TColStd_MapOfInteger& aMIFIn)
4e57c75e 503{
504 Standard_Boolean bRet;
505 Standard_Integer nV;
1155d05a 506 TColStd_MapIteratorOfMapOfInteger aIt;
4e57c75e 507 //
508 bRet=Standard_False;
509 //
510 aIt.Initialize(aMIFOn);
511 for (; aIt.More(); aIt.Next()) {
512 nV=aIt.Value();
513 if (nV==nVx) {
514 bRet=!bRet;
515 return bRet;
516 }
517 }
518 aIt.Initialize(aMIFIn);
519 for (; aIt.More(); aIt.Next()) {
520 nV=aIt.Value();
521 if (nV==nVx) {
522 bRet=!bRet;
523 return bRet;
524 }
525 }
526 //
527 return bRet;
528}
529//=======================================================================
530// function: CheckFacePaves
531// purpose:
532//=======================================================================
e30616a7 533Standard_Boolean BOPAlgo_PaveFiller::CheckFacePaves
534 (const TopoDS_Vertex& aVnew,
1155d05a 535 const TColStd_MapOfInteger& aMIF)
4e57c75e 536{
537 Standard_Boolean bRet;
538 Standard_Integer nV, iFlag;
1155d05a 539 TColStd_MapIteratorOfMapOfInteger aIt;
4e57c75e 540 //
541 bRet=Standard_True;
542 //
543 aIt.Initialize(aMIF);
544 for (; aIt.More(); aIt.Next()) {
545 nV=aIt.Value();
546 const TopoDS_Vertex& aV=(*(TopoDS_Vertex *)(&myDS->Shape(nV)));
547 iFlag=BOPTools_AlgoTools::ComputeVV(aVnew, aV);
548 if (!iFlag) {
549 return bRet;
550 }
551 }
552 //
553 return !bRet;
554}
b4109929 555//=======================================================================
556//function : ForceInterfVF
557//purpose :
558//=======================================================================
e30616a7 559Standard_Boolean BOPAlgo_PaveFiller::ForceInterfVF
560 (const Standard_Integer nV,
561 const Standard_Integer nF)
b4109929 562{
563 Standard_Boolean bRet;
3510db62 564 Standard_Integer iFlag, nVx;
565 Standard_Real U, V, aTolVNew;
b4109929 566 //
567 bRet = Standard_False;
568 const TopoDS_Vertex& aV = *(TopoDS_Vertex*)&myDS->Shape(nV);
569 const TopoDS_Face& aF = *(TopoDS_Face*) &myDS->Shape(nF);
570 //
0d0481c7 571 iFlag = myContext->ComputeVF(aV, aF, U, V, aTolVNew, myFuzzyValue);
3510db62 572 if (iFlag == 0 || iFlag == -2) {
573 bRet=!bRet;
b4109929 574 //
b4109929 575 BOPDS_VectorOfInterfVF& aVFs=myDS->InterfVF();
a3476a9f 576 aVFs.SetIncrement(10);
3510db62 577 // 1
1155d05a 578 BOPDS_InterfVF& aVF=aVFs.Appended();
3510db62 579 //
b4109929 580 aVF.SetIndices(nV, nF);
581 aVF.SetUV(U, V);
3510db62 582 // 2
b4109929 583 myDS->AddInterf(nV, nF);
584 //
3510db62 585 // 3 update vertex V/F if necessary
586 nVx=UpdateVertex(nV, aTolVNew);
587 // 4
588 if (myDS->IsNewShape(nVx)) {
589 aVF.SetIndexNew(nVx);
590 }
b4109929 591 //
592 BOPDS_FaceInfo& aFI=myDS->ChangeFaceInfo(nF);
1155d05a 593 TColStd_MapOfInteger& aMVIn=aFI.ChangeVerticesIn();
3510db62 594 aMVIn.Add(nVx);
33ba8565 595 //
596 // check for self-interference
597 Standard_Integer iRV = myDS->Rank(nV);
598 if (iRV >= 0 && iRV == myDS->Rank(nF)) {
599 // add warning status
600 TopoDS_Compound aWC;
601 BRep_Builder().MakeCompound(aWC);
602 BRep_Builder().Add(aWC, aV);
603 BRep_Builder().Add(aWC, aF);
604 AddWarning (new BOPAlgo_AlertSelfInterferingShape (aWC));
605 }
606
b4109929 607 }
b4109929 608 return bRet;
609}
01b5b3df 610//=======================================================================
611//function : ReduceIntersectionRange
612//purpose :
613//=======================================================================
614void BOPAlgo_PaveFiller::ReduceIntersectionRange(const Standard_Integer theV1,
615 const Standard_Integer theV2,
616 const Standard_Integer theE,
617 const Standard_Integer theF,
618 Standard_Real& theTS1,
619 Standard_Real& theTS2)
620{
621 if (!myDS->IsNewShape(theV1) &&
622 !myDS->IsNewShape(theV2)) {
623 return;
624 }
625 //
51db0179 626 if (!myDS->HasInterfShapeSubShapes(theE, theF)) {
627 return;
628 }
629 //
01b5b3df 630 BOPDS_VectorOfInterfEE& aEEs = myDS->InterfEE();
1155d05a 631 Standard_Integer aNbEEs = aEEs.Length();
01b5b3df 632 if (!aNbEEs) {
633 return;
634 }
635 //
636 Standard_Integer i, nV, nE1, nE2;
637 Standard_Real aTR1, aTR2;
638 //
639 // get face's edges to check that E/E contains the edge from the face
1155d05a 640 TColStd_MapOfInteger aMFE;
641 const TColStd_ListOfInteger& aLI = myDS->ShapeInfo(theF).SubShapes();
642 TColStd_ListIteratorOfListOfInteger aItLI(aLI);
01b5b3df 643 for (; aItLI.More(); aItLI.Next()) {
644 nE1 = aItLI.Value();
645 if (myDS->ShapeInfo(nE1).ShapeType() == TopAbs_EDGE) {
646 aMFE.Add(nE1);
647 }
648 }
649 //
650 for (i = 0; i < aNbEEs; ++i) {
651 BOPDS_InterfEE& aEE = aEEs(i);
652 if (!aEE.HasIndexNew()) {
653 continue;
654 }
655 //
656 // check the vertex
657 nV = aEE.IndexNew();
658 if (nV != theV1 && nV != theV2) {
659 continue;
660 }
661 //
662 // check that the intersection is between the edge
663 // and one of the face's edge
664 aEE.Indices(nE1, nE2);
665 if (((theE != nE1) && (theE != nE2)) ||
666 (!aMFE.Contains(nE1) && !aMFE.Contains(nE2))) {
667 continue;
668 }
669 //
670 // update the intersection range
671 const IntTools_CommonPrt& aCPart = aEE.CommonPart();
672 const IntTools_Range& aCRange =
673 (theE == nE1) ? aCPart.Range1() : aCPart.Ranges2().First();
674 aCRange.Range(aTR1, aTR2);
675 //
676 if (nV == theV1) {
677 if (theTS1 < aTR2) {
678 theTS1 = aTR2;
679 }
680 }
681 else {
682 if (theTS2 > aTR1) {
683 theTS2 = aTR1;
684 }
685 }
686 }
687}
d3578357 688
689//=======================================================================
690//function : ForceInterfEF
691//purpose :
692//=======================================================================
693void BOPAlgo_PaveFiller::ForceInterfEF()
694{
695 if (!myIsPrimary)
696 return;
697
698 // Now that we have vertices increased and unified, try to find additional
699 // edge/face common blocks among the pairs of edge/face.
700 // Here, we are interested in common blocks only, as all real intersections
701 // should have happened already. Thus, we need to check only those pairs
702 // of edge/face which have the same vertices.
703
704 // Collect all pave blocks
705 BOPDS_IndexedMapOfPaveBlock aMPB;
706 const Standard_Integer aNbS = myDS->NbSourceShapes();
707 for (Standard_Integer nE = 0; nE < aNbS; ++nE)
708 {
709 const BOPDS_ShapeInfo& aSI = myDS->ShapeInfo(nE);
710 if (aSI.ShapeType() != TopAbs_EDGE)
711 // Not an edge
712 continue;
713
714 if (!aSI.HasReference())
715 // Edge has no pave blocks
716 continue;
717
718 if (aSI.HasFlag())
719 // Degenerated edge
720 continue;
721
722 const BOPDS_ListOfPaveBlock& aLPB = myDS->PaveBlocks(nE);
723 BOPDS_ListIteratorOfListOfPaveBlock aItLPB(aLPB);
724 for (; aItLPB.More(); aItLPB.Next())
725 {
726 const Handle(BOPDS_PaveBlock)& aPB = aItLPB.Value();
727 const Handle(BOPDS_PaveBlock)& aPBR = myDS->RealPaveBlock(aPB);
728 aMPB.Add(aPBR);
729 }
730 }
731
732 // Perform intersection of collected pave blocks with faces
733 ForceInterfEF(aMPB, Standard_True);
734}
735
736//=======================================================================
737//function : ForceInterfEF
738//purpose :
739//=======================================================================
740void BOPAlgo_PaveFiller::ForceInterfEF(const BOPDS_IndexedMapOfPaveBlock& theMPB,
741 const Standard_Boolean theAddInterf)
742{
743 if (theMPB.IsEmpty())
744 return;
745
746 // Fill the tree with bounding boxes of the pave blocks
747 NCollection_UBTree<Standard_Integer, Bnd_Box> aBBTree;
748 NCollection_UBTreeFiller<Standard_Integer, Bnd_Box> aTreeFiller(aBBTree);
749
750 Handle(NCollection_IncAllocator) anAlloc = new NCollection_IncAllocator;
751 BOPDS_IndexedMapOfPaveBlock aPBMap(1, anAlloc);
752
753 Standard_Integer aNbPB = theMPB.Extent();
754 for (Standard_Integer iPB = 1; iPB <= aNbPB; ++iPB)
755 {
756 Handle(BOPDS_PaveBlock) aPB = theMPB(iPB);
757 if (!aPB->HasShrunkData() || !myDS->IsValidShrunkData(aPB))
758 {
759 FillShrunkData(aPB);
760 if (!aPB->HasShrunkData())
761 continue;
762 }
763
764 Standard_Real f, l;
765 Bnd_Box aPBBox;
766 Standard_Boolean isSplit;
767 aPB->ShrunkData(f, l, aPBBox, isSplit);
768
769 aTreeFiller.Add(aPBMap.Add(aPB), aPBBox);
770 }
771
772 // Shake the tree
773 aTreeFiller.Fill();
774
775 // Find pairs of Face/PaveBlock containing the same vertices
776 // and prepare those pairs for intersection.
777 BOPAlgo_VectorOfEdgeFace aVEdgeFace;
778
779 const Standard_Integer aNbS = myDS->NbSourceShapes();
780 for (Standard_Integer nF = 0; nF < aNbS; ++nF)
781 {
782 const BOPDS_ShapeInfo& aSI = myDS->ShapeInfo(nF);
783 if (aSI.ShapeType() != TopAbs_FACE)
784 // Not a face
785 continue;
786
787 if (!aSI.HasReference())
788 // Face has no face info
789 continue;
790
791 const Bnd_Box& aBoxF = aSI.Box();
792 BOPTools_BoxSelector<Bnd_Box> aSelector;
793 aSelector.SetBox(aBoxF);
794
795 if (!aBBTree.Select(aSelector))
796 continue;
797
798 const TopoDS_Face& aF = TopoDS::Face(aSI.Shape());
799 const BOPDS_FaceInfo& aFI = myDS->FaceInfo(nF);
800 // Vertices of the face
801 TColStd_MapOfInteger aMVF;
802 const TColStd_MapOfInteger* pMVF[] = { &aFI.VerticesOn(),
803 &aFI.VerticesIn(),
804 &aFI.VerticesSc() };
805 for (Standard_Integer iM = 0; iM < 3; ++iM)
806 {
807 TColStd_MapIteratorOfMapOfInteger itM(*pMVF[iM]);
808 for (; itM.More(); itM.Next())
809 aMVF.Add(itM.Value());
810 }
811
812 // Pave Blocks of the face
813 const BOPDS_IndexedMapOfPaveBlock* pMPBF[] = { &aFI.PaveBlocksOn(),
814 &aFI.PaveBlocksIn(),
815 &aFI.PaveBlocksSc() };
816 for (Standard_Integer iM = 0; iM < 3; ++iM)
817 {
818 const Standard_Integer aNb = pMPBF[iM]->Extent();
819 for (Standard_Integer iPB = 1; iPB <= aNb; ++iPB)
820 {
821 const Handle(BOPDS_PaveBlock)& aPB = pMPBF[iM]->FindKey(iPB);
822 aMVF.Add(aPB->Pave1().Index());
823 aMVF.Add(aPB->Pave2().Index());
824 }
825 }
826
827 // Projection tool
828 GeomAPI_ProjectPointOnSurf& aProjPS = myContext->ProjPS(aF);
829
830 // Iterate on pave blocks and combine pairs containing
831 // the same vertices
832 const TColStd_ListOfInteger& aLIPB = aSelector.Indices();
833 TColStd_ListOfInteger::Iterator itLIPB(aLIPB);
834 for (; itLIPB.More(); itLIPB.Next())
835 {
836 const Handle(BOPDS_PaveBlock)& aPB = aPBMap(itLIPB.Value());
837 if (pMPBF[0]->Contains(aPB) ||
838 pMPBF[1]->Contains(aPB) ||
839 pMPBF[2]->Contains(aPB))
840 continue;
841
842 // Check if the face contains both vertices of the pave block
843 Standard_Integer nV1, nV2;
844 aPB->Indices(nV1, nV2);
845 if (!aMVF.Contains(nV1) || !aMVF.Contains(nV2))
846 // Face does not contain the vertices
847 continue;
848
849 // Get the edge
850 Standard_Integer nE;
851 if (!aPB->HasEdge(nE))
852 {
853 nE = aPB->OriginalEdge();
854 if (nE < 0)
855 continue;
856
857 // Make sure that the edge and face came from different arguments
858 if (myDS->Rank(nF) == myDS->Rank(nE))
859 continue;
860 }
861
862 const TopoDS_Edge& aE = TopoDS::Edge(myDS->Shape(nE));
863 BRepAdaptor_Curve aBAC(aE);
864
865 // Check directions coincidence at middle point on the edge
866 // and projection of that point on the face.
867 // If the angle between tangent vector to the curve and normal
868 // of the face is not in the range of 80 - 100 degrees, do not use the additional
869 // tolerance, as it may lead to undesired unification of edge with the face.
870 Standard_Boolean bUseAddTol = Standard_True;
871
872 Standard_Real aTS[2];
873 Bnd_Box aPBBox;
874 Standard_Boolean isSplit;
875 aPB->ShrunkData(aTS[0], aTS[1], aPBBox, isSplit);
876
877 // Middle point
878 gp_Pnt aPOnE;
879 // Tangent vector in the middle point
880 gp_Vec aVETgt;
881 aBAC.D1(BOPTools_AlgoTools2D::IntermediatePoint(aTS[0], aTS[1]), aPOnE, aVETgt);
882 if (aVETgt.SquareMagnitude() < gp::Resolution())
883 continue;
884
885 aProjPS.Perform(aPOnE);
886 if (!aProjPS.NbPoints())
887 continue;
888
889 // Check the distance in the middle point, using the max vertices
890 // tolerance as the criteria.
891 const TopoDS_Vertex& aV1 = TopoDS::Vertex(myDS->Shape(nV1));
892 const TopoDS_Vertex& aV2 = TopoDS::Vertex(myDS->Shape(nV2));
893 Standard_Real aTolCheck = 2 * Max(BRep_Tool::Tolerance(aV1),
894 BRep_Tool::Tolerance(aV2));
895
896 if (aProjPS.LowerDistance() > aTolCheck + myFuzzyValue)
897 continue;
898
899 Standard_Real U, V;
900 aProjPS.LowerDistanceParameters(U, V);
901 if (!myContext->IsPointInFace(aF, gp_Pnt2d(U, V)))
902 continue;
903
904 gp_Pnt aPOnS = aProjPS.NearestPoint();
905 gp_Vec aVFNorm(aPOnS, aPOnE);
906 if (aVFNorm.SquareMagnitude() > gp::Resolution())
907 {
908 // Angle between vectors should be close to 90 degrees.
909 // We allow deviation of 10 degrees.
910 Standard_Real aCos = aVFNorm.Dot(aVETgt);
911 if (Abs(aCos) > 0.174)
912 bUseAddTol = Standard_False;
913 }
914
915 // Compute an addition to Fuzzy value
916 Standard_Real aTolAdd = 0.0;
917 if (bUseAddTol)
918 {
919 // Compute the distance from the bounding points of the edge
920 // to the face and use the maximal of these distances as a
921 // fuzzy tolerance for the intersection.
922 // Use the maximal tolerance of the pave block's vertices
923 // as a max criteria for the computed distance.
924
925 for (Standard_Integer iP = 0; iP < 2; ++iP)
926 {
927 gp_Pnt aP = aBAC.Value(aTS[iP]);
928 aProjPS.Perform(aP);
929 if (aProjPS.NbPoints())
930 {
931 Standard_Real aDistEF = aProjPS.LowerDistance();
932 if (aDistEF < aTolCheck && aDistEF > aTolAdd)
933 aTolAdd = aDistEF;
934 }
935 }
936 if (aTolAdd > 0.)
937 {
938 aTolAdd -= (BRep_Tool::Tolerance(aE) + BRep_Tool::Tolerance(aF));
939 if (aTolAdd < 0.)
940 aTolAdd = 0.;
941 }
942 }
943
944 Standard_Boolean bIntersect = aTolAdd > 0;
945 if (!bIntersect)
946 {
947 const BOPDS_MapOfPaveBlock* pMPB = myFPBDone.Seek(nF);
948 bIntersect = !pMPB || !(pMPB->Contains(aPB));
949 }
950
951 if (bIntersect)
952 {
953 // Prepare pair for intersection
954 BOPAlgo_EdgeFace& aEdgeFace = aVEdgeFace.Appended();
955 aEdgeFace.SetIndices(nE, nF);
956 aEdgeFace.SetPaveBlock(aPB);
957 aEdgeFace.SetEdge(aE);
958 aEdgeFace.SetFace(aF);
959 aEdgeFace.SetFuzzyValue(myFuzzyValue + aTolAdd);
960 aEdgeFace.UseQuickCoincidenceCheck(Standard_True);
961 aEdgeFace.SetRange(IntTools_Range(aPB->Pave1().Parameter(), aPB->Pave2().Parameter()));
962 aEdgeFace.SetProgressIndicator(myProgressIndicator);
963 }
964 }
965 }
966
967 Standard_Integer aNbEFs = aVEdgeFace.Length();
968 if (!aNbEFs)
969 return;
970
971 aPBMap.Clear();
972 anAlloc->Reset();
973
974 // Perform intersection of the found pairs
975 BOPAlgo_EdgeFaceCnt::Perform(myRunParallel, aVEdgeFace, myContext);
976
977 BOPDS_VectorOfInterfEF& aEFs = myDS->InterfEF();
978 if (theAddInterf && aEFs.IsEmpty())
979 aEFs.SetIncrement(10);
980
981 // Analyze the results of intersection looking for TopAbs_EDGE
982 // intersection type only.
983
984 // Collect all pairs for common block creation
985 BOPDS_IndexedDataMapOfPaveBlockListOfInteger aMPBLI(1, anAlloc);
986
987 for (Standard_Integer i = 0; i < aNbEFs; ++i)
988 {
989 BOPAlgo_EdgeFace& anEdgeFace = aVEdgeFace(i);
990 if (!anEdgeFace.IsDone() || anEdgeFace.HasErrors())
991 {
992 // Warn about failed intersection of sub-shapes
993 AddIntersectionFailedWarning(anEdgeFace.Edge(), anEdgeFace.Face());
994 continue;
995 }
996
997 const IntTools_SequenceOfCommonPrts& aCParts = anEdgeFace.CommonParts();
998 if (aCParts.Length() != 1)
999 continue;
1000
1001 const IntTools_CommonPrt& aCP = aCParts(1);
1002 if (aCP.Type() != TopAbs_EDGE)
1003 continue;
1004
1005 Standard_Integer nE, nF;
1006 anEdgeFace.Indices(nE, nF);
1007 if (theAddInterf)
1008 {
1009 // Add interference
1010 BOPDS_InterfEF& aEF = aEFs.Appended();
1011 aEF.SetIndices(nE, nF);
1012 aEF.SetCommonPart(aCP);
1013 myDS->AddInterf(nE, nF);
1014 }
1015
1016 const Handle(BOPDS_PaveBlock)& aPB = anEdgeFace.PaveBlock();
1017 // Update face information with new IN pave block
1018 myDS->ChangeFaceInfo(nF).ChangePaveBlocksIn().Add(aPB);
1019 if (theAddInterf)
1020 // Fill map for common blocks creation
1021 BOPAlgo_Tools::FillMap(aPB, nF, aMPBLI, anAlloc);
1022 }
1023
1024 if (aMPBLI.Extent())
1025 // Create new common blocks for coinciding pairs
1026 BOPAlgo_Tools::PerformCommonBlocks(aMPBLI, anAlloc, myDS);
1027}