0029368: Incorrect intersection state of the intersection point of two 2d curves
[occt.git] / src / BOPAlgo / BOPAlgo_PaveFiller_3.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
19#include <Bnd_Box.hxx>
42cf5bc1 20#include <BOPAlgo_PaveFiller.hxx>
42cf5bc1 21#include <BOPAlgo_Tools.hxx>
33ba8565 22#include <BOPAlgo_Alerts.hxx>
4e57c75e 23#include <BOPDS_CommonBlock.hxx>
24#include <BOPDS_CoupleOfPaveBlocks.hxx>
42cf5bc1 25#include <BOPDS_DS.hxx>
4e57c75e 26#include <BOPDS_Interf.hxx>
42cf5bc1 27#include <BOPDS_Iterator.hxx>
28#include <BOPDS_MapOfPaveBlock.hxx>
4e57c75e 29#include <BOPDS_Pave.hxx>
42cf5bc1 30#include <BOPDS_PaveBlock.hxx>
31#include <BOPDS_VectorOfInterfEE.hxx>
32#include <BOPTools_AlgoTools.hxx>
1155d05a 33#include <BOPTools_Parallel.hxx>
01b5b3df 34#include <BndLib_Add3dCurve.hxx>
42cf5bc1 35#include <BRep_Tool.hxx>
33ba8565 36#include <BRep_Builder.hxx>
3510db62 37#include <BRepAdaptor_Curve.hxx>
42cf5bc1 38#include <gp_Pnt.hxx>
39#include <IntTools_CommonPrt.hxx>
40#include <IntTools_Context.hxx>
41#include <IntTools_EdgeEdge.hxx>
42#include <IntTools_Range.hxx>
43#include <IntTools_SequenceOfCommonPrts.hxx>
44#include <IntTools_SequenceOfRanges.hxx>
45#include <IntTools_ShrunkRange.hxx>
46#include <IntTools_Tools.hxx>
b7cd7c2b 47#include <NCollection_IncAllocator.hxx>
1155d05a 48#include <NCollection_Vector.hxx>
42cf5bc1 49#include <Precision.hxx>
8ae442a8 50#include <TopoDS.hxx>
42cf5bc1 51#include <TopoDS_Edge.hxx>
42cf5bc1 52#include <TopoDS_Vertex.hxx>
db8e4b9a 53
a2098360 54/////////////////////////////////////////////////////////////////////////
a942f2da 55//=======================================================================
56//class : BOPAlgo_EdgeEdge
57//purpose :
58//=======================================================================
36f4947b 59class BOPAlgo_EdgeEdge :
60 public IntTools_EdgeEdge,
61 public BOPAlgo_Algo {
62
a942f2da 63 public:
36f4947b 64
65 DEFINE_STANDARD_ALLOC
66 //
67 BOPAlgo_EdgeEdge():
68 IntTools_EdgeEdge(),
69 BOPAlgo_Algo() {
a942f2da 70 };
71 //
36f4947b 72 virtual ~BOPAlgo_EdgeEdge(){
a942f2da 73 };
74 //
75 void SetPaveBlock1(const Handle(BOPDS_PaveBlock)& aPB) {
76 myPB1=aPB;
77 }
78 //
79 Handle(BOPDS_PaveBlock)& PaveBlock1() {
80 return myPB1;
81 }
82 //
83 void SetPaveBlock2(const Handle(BOPDS_PaveBlock)& aPB) {
84 myPB2=aPB;
85 }
86 //
87 Handle(BOPDS_PaveBlock)& PaveBlock2() {
88 return myPB2;
89 }
36f4947b 90 //
0d0481c7 91 void SetFuzzyValue(const Standard_Real theFuzz) {
92 IntTools_EdgeEdge::SetFuzzyValue(theFuzz);
93 }
94 //
36f4947b 95 virtual void Perform() {
96 BOPAlgo_Algo::UserBreak();
ad8b073e 97 try
98 {
99 OCC_CATCH_SIGNALS
100
101 IntTools_EdgeEdge::Perform();
102 }
103 catch (Standard_Failure)
104 {
105 AddError(new BOPAlgo_AlertIntersectionFailed);
106 }
36f4947b 107 }
a942f2da 108 //
109 protected:
110 Handle(BOPDS_PaveBlock) myPB1;
111 Handle(BOPDS_PaveBlock) myPB2;
112};
113//
505abfb8 114//=======================================================================
1155d05a 115typedef NCollection_Vector
505abfb8 116 <BOPAlgo_EdgeEdge> BOPAlgo_VectorOfEdgeEdge;
a942f2da 117//
1155d05a 118typedef BOPTools_Functor
505abfb8 119 <BOPAlgo_EdgeEdge,
120 BOPAlgo_VectorOfEdgeEdge> BOPAlgo_EdgeEdgeFunctor;
121//
1155d05a 122typedef BOPTools_Cnt
505abfb8 123 <BOPAlgo_EdgeEdgeFunctor,
124 BOPAlgo_VectorOfEdgeEdge> BOPAlgo_EdgeEdgeCnt;
a942f2da 125//
a2098360 126/////////////////////////////////////////////////////////////////////////
127//=======================================================================
4e57c75e 128// function: PerformEE
129// purpose:
130//=======================================================================
db8e4b9a 131void BOPAlgo_PaveFiller::PerformEE()
4e57c75e 132{
505abfb8 133 FillShrunkData(TopAbs_EDGE, TopAbs_EDGE);
134 //
4e57c75e 135 myIterator->Initialize(TopAbs_EDGE, TopAbs_EDGE);
33ba8565 136 Standard_Integer iSize = myIterator->ExpectedLength();
4e57c75e 137 if (!iSize) {
138 return;
139 }
140 //
25dfc507 141 Standard_Boolean bExpressCompute, bIsPBSplittable1, bIsPBSplittable2;
01b5b3df 142 Standard_Integer i, iX, nE1, nE2, aNbCPrts, k, aNbEdgeEdge;
6dc83e21 143 Standard_Integer nV11, nV12, nV21, nV22;
a942f2da 144 Standard_Real aTS11, aTS12, aTS21, aTS22, aT11, aT12, aT21, aT22;
145 TopAbs_ShapeEnum aType;
146 BOPDS_ListIteratorOfListOfPaveBlock aIt1, aIt2;
488e5b9d 147 Handle(NCollection_BaseAllocator) aAllocator;
a942f2da 148 BOPAlgo_VectorOfEdgeEdge aVEdgeEdge;
149 BOPDS_MapIteratorOfMapOfPaveBlock aItPB;
8ae442a8 150 // keep modified edges for further update
1155d05a 151 TColStd_MapOfInteger aMEdges;
a942f2da 152 //
488e5b9d 153 aAllocator=NCollection_BaseAllocator::CommonBaseAllocator();
4e57c75e 154 //-----------------------------------------------------scope f
4e57c75e 155 BOPDS_IndexedDataMapOfPaveBlockListOfPaveBlock aMPBLPB(100, aAllocator);
156 BOPDS_IndexedDataMapOfShapeCoupleOfPaveBlocks aMVCPB(100, aAllocator);
01b5b3df 157 BOPAlgo_DataMapOfPaveBlockBndBox aDMPBBox(100, aAllocator);
4e57c75e 158 //
4e57c75e 159 BOPDS_VectorOfInterfEE& aEEs=myDS->InterfEE();
4e57c75e 160 aEEs.SetIncrement(iSize);
4e57c75e 161 //
162 for (; myIterator->More(); myIterator->Next()) {
25dfc507 163 myIterator->Value(nE1, nE2);
4e57c75e 164 //
165 const BOPDS_ShapeInfo& aSIE1=myDS->ShapeInfo(nE1);
166 if (aSIE1.HasFlag()){
167 continue;
168 }
169 const BOPDS_ShapeInfo& aSIE2=myDS->ShapeInfo(nE2);
170 if (aSIE2.HasFlag()){
171 continue;
172 }
173 //
752f9d72 174 BOPDS_ListOfPaveBlock& aLPB1 = myDS->ChangePaveBlocks(nE1);
175 if (aLPB1.IsEmpty()) {
176 continue;
177 }
178 //
179 BOPDS_ListOfPaveBlock& aLPB2 = myDS->ChangePaveBlocks(nE2);
180 if (aLPB2.IsEmpty()) {
181 continue;
182 }
183 //
4e57c75e 184 const TopoDS_Edge& aE1=(*(TopoDS_Edge *)(&aSIE1.Shape()));
01b5b3df 185 const TopoDS_Edge& aE2=(*(TopoDS_Edge *)(&aSIE2.Shape()));
4e57c75e 186 //
4e57c75e 187 aIt1.Initialize(aLPB1);
188 for (; aIt1.More(); aIt1.Next()) {
189 Bnd_Box aBB1;
190 //
191 Handle(BOPDS_PaveBlock)& aPB1=aIt1.ChangeValue();
01b5b3df 192 //
193 if (!GetPBBox(aE1, aPB1, aDMPBBox, aT11, aT12, aTS11, aTS12, aBB1)) {
505abfb8 194 continue;
4e57c75e 195 }
4e57c75e 196 //
6dc83e21 197 aPB1->Indices(nV11, nV12);
198 //
4e57c75e 199 aIt2.Initialize(aLPB2);
200 for (; aIt2.More(); aIt2.Next()) {
201 Bnd_Box aBB2;
202 //
203 Handle(BOPDS_PaveBlock)& aPB2=aIt2.ChangeValue();
01b5b3df 204 //
205 if (!GetPBBox(aE2, aPB2, aDMPBBox, aT21, aT22, aTS21, aTS22, aBB2)) {
505abfb8 206 continue;
4e57c75e 207 }
4e57c75e 208 //
209 if (aBB1.IsOut(aBB2)) {
210 continue;
211 }
212 //
6dc83e21 213 aPB2->Indices(nV21, nV22);
214 //
215 bExpressCompute=((nV11==nV21 && nV12==nV22) ||
216 (nV12==nV21 && nV11==nV22));
217 //
1155d05a 218 BOPAlgo_EdgeEdge& anEdgeEdge=aVEdgeEdge.Appended();
6dc83e21 219 //
220 anEdgeEdge.UseQuickCoincidenceCheck(bExpressCompute);
221 //
a942f2da 222 anEdgeEdge.SetPaveBlock1(aPB1);
223 anEdgeEdge.SetPaveBlock2(aPB2);
224 //
ec0cdc0e 225 anEdgeEdge.SetEdge1(aE1, aT11, aT12);
226 anEdgeEdge.SetEdge2(aE2, aT21, aT22);
0d0481c7 227 anEdgeEdge.SetFuzzyValue(myFuzzyValue);
36f4947b 228 anEdgeEdge.SetProgressIndicator(myProgressIndicator);
a942f2da 229 }//for (; aIt2.More(); aIt2.Next()) {
230 }//for (; aIt1.More(); aIt1.Next()) {
231 }//for (; myIterator->More(); myIterator->Next()) {
232 //
1155d05a 233 aNbEdgeEdge=aVEdgeEdge.Length();
a942f2da 234 //======================================================
235 BOPAlgo_EdgeEdgeCnt::Perform(myRunParallel, aVEdgeEdge);
236 //======================================================
237 //
01b5b3df 238 for (k = 0; k < aNbEdgeEdge; ++k) {
a942f2da 239 Bnd_Box aBB1, aBB2;
240 //
241 BOPAlgo_EdgeEdge& anEdgeEdge=aVEdgeEdge(k);
ad8b073e 242 if (!anEdgeEdge.IsDone() || anEdgeEdge.HasErrors()) {
243 // Warn about failed intersection of sub-shapes
244 const TopoDS_Shape& aE1 = myDS->Shape(anEdgeEdge.PaveBlock1()->OriginalEdge());
245 const TopoDS_Shape& aE2 = myDS->Shape(anEdgeEdge.PaveBlock2()->OriginalEdge());
246 AddIntersectionFailedWarning(aE1, aE2);
a942f2da 247 continue;
248 }
249 //
51db0179 250 const IntTools_SequenceOfCommonPrts& aCPrts = anEdgeEdge.CommonParts();
251 aNbCPrts = aCPrts.Length();
252 if (!aNbCPrts) {
253 continue;
254 }
a942f2da 255 //--------------------------------------------
256 Handle(BOPDS_PaveBlock)& aPB1=anEdgeEdge.PaveBlock1();
257 nE1=aPB1->OriginalEdge();
258 aPB1->Range(aT11, aT12);
01b5b3df 259 if (!aPB1->HasShrunkData()) {
260 aTS11 = aT11;
261 aTS12 = aT12;
262 bIsPBSplittable1 = Standard_False;
263 }
264 else {
265 aPB1->ShrunkData(aTS11, aTS12, aBB1, bIsPBSplittable1);
266 }
a942f2da 267 //
268 Handle(BOPDS_PaveBlock)& aPB2=anEdgeEdge.PaveBlock2();
269 nE2=aPB2->OriginalEdge();
270 aPB2->Range(aT21, aT22);
01b5b3df 271 if (!aPB2->HasShrunkData()) {
272 aTS21 = aT21;
273 aTS22 = aT22;
274 bIsPBSplittable2 = Standard_False;
275 }
276 else {
277 aPB2->ShrunkData(aTS21, aTS22, aBB2, bIsPBSplittable2);
278 }
a942f2da 279 //
280 //--------------------------------------------
281 IntTools_Range aR11(aT11, aTS11), aR12(aTS12, aT12),
282 aR21(aT21, aTS21), aR22(aTS22, aT22);
283 //
3065019c 284 Standard_Boolean bAnalytical = Standard_False;
51db0179 285 {
3510db62 286 const TopoDS_Edge& aOE1 = *(TopoDS_Edge*)&myDS->Shape(nE1);
287 const TopoDS_Edge& aOE2 = *(TopoDS_Edge*)&myDS->Shape(nE2);
288 //
289 BRepAdaptor_Curve aBAC1(aOE1), aBAC2(aOE2);
290 //
3065019c 291 GeomAbs_CurveType aType1 = aBAC1.GetType();
292 GeomAbs_CurveType aType2 = aBAC2.GetType();
293 //
294 bAnalytical = (((aType1 == GeomAbs_Line) &&
295 (aType2 == GeomAbs_Line ||
296 aType2 == GeomAbs_Circle)) ||
297 ((aType2 == GeomAbs_Line) &&
298 (aType1 == GeomAbs_Line ||
299 aType1 == GeomAbs_Circle)));
3510db62 300 }
301 //
a942f2da 302 for (i=1; i<=aNbCPrts; ++i) {
303 const IntTools_CommonPrt& aCPart=aCPrts(i);
304 //
305 const TopoDS_Edge& aE1=aCPart.Edge1();
306 const TopoDS_Edge& aE2=aCPart.Edge2();
307 //
308 aType=aCPart.Type();
309 switch (aType) {
310 case TopAbs_VERTEX: {
01b5b3df 311 if (!bIsPBSplittable1 || !bIsPBSplittable2) {
312 continue;
313 }
314 //
a942f2da 315 Standard_Boolean bIsOnPave[4], bFlag;
316 Standard_Integer nV[4], j;
317 Standard_Real aT1, aT2, aTol;
318 TopoDS_Vertex aVnew;
319 IntTools_Range aCR1, aCR2;
320 //
1e143abb 321 IntTools_Tools::VertexParameters(aCPart, aT1, aT2);
a942f2da 322 aTol = Precision::Confusion();
323 aCR1 = aCPart.Range1();
324 aCR2 = aCPart.Ranges2()(1);
325 //
326 //decide to keep the pave or not
1e143abb 327 bIsOnPave[0] = IntTools_Tools::IsOnPave1(aT1, aR11, aTol) ||
328 IntTools_Tools::IsOnPave1(aR11.First(), aCR1, aTol);
329 bIsOnPave[1] = IntTools_Tools::IsOnPave1(aT1, aR12, aTol) ||
330 IntTools_Tools::IsOnPave1(aR12.Last(), aCR1, aTol);
331 bIsOnPave[2] = IntTools_Tools::IsOnPave1(aT2, aR21, aTol) ||
332 IntTools_Tools::IsOnPave1(aR21.First(), aCR2, aTol);
333 bIsOnPave[3] = IntTools_Tools::IsOnPave1(aT2, aR22, aTol) ||
334 IntTools_Tools::IsOnPave1(aR22.Last(), aCR2, aTol);
a942f2da 335 //
336 aPB1->Indices(nV[0], nV[1]);
337 aPB2->Indices(nV[2], nV[3]);
338 //
339 if((bIsOnPave[0] && bIsOnPave[2]) ||
340 (bIsOnPave[0] && bIsOnPave[3]) ||
341 (bIsOnPave[1] && bIsOnPave[2]) ||
342 (bIsOnPave[1] && bIsOnPave[3])) {
343 continue;
344 }
345 //
346 bFlag = Standard_False;
347 for (j = 0; j < 4; ++j) {
348 if (bIsOnPave[j]) {
349 //add interf VE(nV[j], nE)
350 Handle(BOPDS_PaveBlock)& aPB = (j < 2) ? aPB2 : aPB1;
b7cd7c2b 351 bFlag = ForceInterfVE(nV[j], aPB, aMEdges);
a942f2da 352 break;
353 }
354 }
355 if (bFlag) {
1155d05a 356 BOPDS_InterfEE& aEE = aEEs.Appended();
24542bc0 357 aEE.SetIndices(nE1, nE2);
358 aEE.SetCommonPart(aCPart);
a942f2da 359 continue;
360 }
361 //
362 BOPTools_AlgoTools::MakeNewVertex(aE1, aT1, aE2, aT2, aVnew);
3510db62 363 Standard_Real aTolVnew = BRep_Tool::Tolerance(aVnew);
3065019c 364 if (bAnalytical) {
3510db62 365 // increase tolerance for Line/Line intersection, but do not update
366 // the vertex till its intersection with some other shape
3065019c 367 Standard_Real aTolMin = (BRepAdaptor_Curve(aE1).GetType() == GeomAbs_Line) ?
368 (aCR1.Last() - aCR1.First()) / 2. : (aCR2.Last() - aCR2.First()) / 2.;
8bb8064e 369 if (aTolMin > aTolVnew) {
370 aTolVnew = aTolMin;
3510db62 371 }
372 }
a942f2da 373 // <-LXBR
374 {
51740958 375 Standard_Integer nVS[2], iFound;
3510db62 376 Standard_Real aTolVx, aD2, aDT2;
1155d05a 377 TColStd_MapOfInteger aMV;
a942f2da 378 gp_Pnt aPnew, aPx;
4e57c75e 379 //
a942f2da 380 iFound=0;
381 j=-1;
382 aMV.Add(nV[0]);
383 aMV.Add(nV[1]);
384 //
385 if (aMV.Contains(nV[2])) {
386 ++j;
387 nVS[j]=nV[2];
388 }
389 if (aMV.Contains(nV[3])) {
390 ++j;
391 nVS[j]=nV[3];
392 }
393 //
a942f2da 394 aPnew=BRep_Tool::Pnt(aVnew);
395 //
51740958 396 for (Standard_Integer k1=0; k1<=j; ++k1) {
397 const TopoDS_Vertex& aVx= *(TopoDS_Vertex*)&(myDS->Shape(nVS[k1]));
a942f2da 398 aTolVx=BRep_Tool::Tolerance(aVx);
399 aPx=BRep_Tool::Pnt(aVx);
400 aD2=aPnew.SquareDistance(aPx);
401 //
402 aDT2=100.*(aTolVnew+aTolVx)*(aTolVnew+aTolVx);
7eed5d29 403 //
a942f2da 404 if (aD2<aDT2) {
405 iFound=1;
4e57c75e 406 break;
407 }
a942f2da 408 }
409 //
410 if (iFound) {
411 continue;
412 }
413 }
402bfe81 414 //
a942f2da 415 // 1
1155d05a 416 BOPDS_InterfEE& aEE=aEEs.Appended();
417 iX=aEEs.Length()-1;
a942f2da 418 aEE.SetIndices(nE1, nE2);
419 aEE.SetCommonPart(aCPart);
420 // 2
421 myDS->AddInterf(nE1, nE2);
422 //
423 BOPDS_CoupleOfPaveBlocks aCPB;
424 //
425 aCPB.SetPaveBlocks(aPB1, aPB2);
426 aCPB.SetIndexInterf(iX);
3510db62 427 aCPB.SetTolerance(aTolVnew);
a942f2da 428 aMVCPB.Add(aVnew, aCPB);
429 }//case TopAbs_VERTEX:
430 break;
431 //
432 case TopAbs_EDGE: {
433 if (aNbCPrts > 1) {
4e57c75e 434 break;
a942f2da 435 }
436 //
437 Standard_Boolean bHasSameBounds;
438 bHasSameBounds=aPB1->HasSameBounds(aPB2);
439 if (!bHasSameBounds) {
440 break;
441 }
442 // 1
1155d05a 443 BOPDS_InterfEE& aEE=aEEs.Appended();
444 iX=aEEs.Length()-1;
a942f2da 445 aEE.SetIndices(nE1, nE2);
446 aEE.SetCommonPart(aCPart);
447 // 2
448 myDS->AddInterf(nE1, nE2);
449 //
edfa30de 450 BOPAlgo_Tools::FillMap<Handle(BOPDS_PaveBlock), TColStd_MapTransientHasher>(aPB1, aPB2, aMPBLPB, aAllocator);
a942f2da 451 }//case TopAbs_EDGE
452 break;
453 default:
454 break;
455 }//switch (aType) {
456 }//for (i=1; i<=aNbCPrts; i++) {
457 }//for (k=0; k < aNbFdgeEdge; ++k) {
4e57c75e 458 //
459 //=========================================
460 // post treatment
461 //=========================================
8ae442a8 462 BOPAlgo_Tools::PerformCommonBlocks(aMPBLPB, aAllocator, myDS);
463 PerformNewVertices(aMVCPB, aAllocator);
464 //
465 if (aMEdges.Extent()) {
466 Standard_Integer aNbV = aMVCPB.Extent();
467 for (i = 1; i <= aNbV; ++i) {
468 Handle(BOPDS_PaveBlock) aPB1, aPB2;
469 const BOPDS_CoupleOfPaveBlocks& aCPB = aMVCPB.FindFromIndex(i);
470 aCPB.PaveBlocks(aPB1, aPB2);
a3476a9f 471 //
8ae442a8 472 aMEdges.Remove(aPB1->OriginalEdge());
473 aMEdges.Remove(aPB2->OriginalEdge());
b4109929 474 }
8ae442a8 475 //
476 SplitPaveBlocks(aMEdges, Standard_False);
b4109929 477 }
478 //
4e57c75e 479 //-----------------------------------------------------scope t
480 aMPBLPB.Clear();
481 aMVCPB.Clear();
4e57c75e 482}
483//=======================================================================
3510db62 484//function : PerformVerticesEE
4e57c75e 485//purpose :
486//=======================================================================
8ae442a8 487void BOPAlgo_PaveFiller::PerformNewVertices
db8e4b9a 488 (BOPDS_IndexedDataMapOfShapeCoupleOfPaveBlocks& theMVCPB,
8ae442a8 489 const Handle(NCollection_BaseAllocator)& theAllocator,
490 const Standard_Boolean bIsEEIntersection)
4e57c75e 491{
8ae442a8 492 Standard_Integer aNbV = theMVCPB.Extent();
4e57c75e 493 if (!aNbV) {
8ae442a8 494 return;
4e57c75e 495 }
496 //
8ae442a8 497 Standard_Real aTolAdd = myFuzzyValue / 2.;
4e57c75e 498 //
8ae442a8 499 // 1. Fuse the new vertices
1155d05a 500 TopTools_IndexedDataMapOfShapeListOfShape aImages;
3510db62 501 TreatNewVertices(theMVCPB, aImages);
4e57c75e 502 //
8ae442a8 503 // 2. Add new vertices to myDS and connect indices to CPB structure
504 BOPDS_VectorOfInterfEE& aEEs = myDS->InterfEE();
505 BOPDS_VectorOfInterfEF& aEFs = myDS->InterfEF();
506 //
507 Standard_Integer i, aNb = aImages.Extent();
508 for (i = 1; i <= aNb; ++i) {
509 const TopoDS_Vertex& aV = TopoDS::Vertex(aImages.FindKey(i));
1155d05a 510 const TopTools_ListOfShape& aLVSD = aImages.FindFromIndex(i);
4e57c75e 511 //
8ae442a8 512 BOPDS_ShapeInfo aSI;
513 aSI.SetShapeType(TopAbs_VERTEX);
4e57c75e 514 aSI.SetShape(aV);
8ae442a8 515 Standard_Integer iV = myDS->Append(aSI);
4e57c75e 516 //
8ae442a8 517 BOPDS_ShapeInfo& aSIDS = myDS->ChangeShapeInfo(iV);
518 Bnd_Box& aBox = aSIDS.ChangeBox();
519 aBox.Add(BRep_Tool::Pnt(aV));
520 aBox.SetGap(BRep_Tool::Tolerance(aV) + aTolAdd);
4e57c75e 521 //
1155d05a 522 TopTools_ListIteratorOfListOfShape aItLS(aLVSD);
4e57c75e 523 for (; aItLS.More(); aItLS.Next()) {
524 const TopoDS_Shape& aVx = aItLS.Value();
8ae442a8 525 BOPDS_CoupleOfPaveBlocks &aCPB = theMVCPB.ChangeFromKey(aVx);
4e57c75e 526 aCPB.SetIndex(iV);
8ae442a8 527 // update interference
528 Standard_Integer iX = aCPB.IndexInterf();
529 BOPDS_Interf *aInt = bIsEEIntersection ? (BOPDS_Interf*)(&aEEs(iX)) : (BOPDS_Interf*) (&aEFs(iX));
530 aInt->SetIndexNew(iV);
4e57c75e 531 }
532 }
533 //
8ae442a8 534 // 3. Map PaveBlock/ListOfVertices to add to this PaveBlock ->aMPBLI
535 BOPDS_IndexedDataMapOfPaveBlockListOfInteger aMPBLI(100, theAllocator);
536 for (i = 1; i <= aNbV; ++i) {
537 const BOPDS_CoupleOfPaveBlocks& aCPB = theMVCPB.FindFromIndex(i);
538 Standard_Integer iV = aCPB.Index();
4e57c75e 539 //
8ae442a8 540 Handle(BOPDS_PaveBlock) aPB[2];
541 aCPB.PaveBlocks(aPB[0], aPB[1]);
542 for (Standard_Integer j = 0; j < 2; ++j) {
1155d05a 543 TColStd_ListOfInteger *pLI = aMPBLI.ChangeSeek(aPB[j]);
8ae442a8 544 if (!pLI) {
1155d05a 545 pLI = &aMPBLI(aMPBLI.Add(aPB[j], TColStd_ListOfInteger(theAllocator)));
4e57c75e 546 }
8ae442a8 547 pLI->Append(iV);
4e57c75e 548 //
8ae442a8 549 if (aPB[0] == aPB[1]) {
550 break;
551 }
4e57c75e 552 }
553 }
4e57c75e 554 //
8ae442a8 555 // 4. Compute Extra Paves and split Pave blocks by the Extra paves
556 IntersectVE(aMPBLI, Standard_False);
4e57c75e 557}
4e57c75e 558//=======================================================================
559//function : TreatNewVertices
560//purpose :
561//=======================================================================
db8e4b9a 562void BOPAlgo_PaveFiller::TreatNewVertices
8ae442a8 563 (const BOPDS_IndexedDataMapOfShapeCoupleOfPaveBlocks& theMVCPB,
1155d05a 564 TopTools_IndexedDataMapOfShapeListOfShape& myImages)
4e57c75e 565{
4e57c75e 566 //
8ae442a8 567 // Prepare for intersection
1155d05a 568 TopTools_IndexedDataMapOfShapeReal aVerts;
8ae442a8 569 Standard_Integer i, aNbV = theMVCPB.Extent();
570 for (i = 1; i <= aNbV; ++i) {
571 const TopoDS_Shape& aV = theMVCPB.FindKey(i);
572 Standard_Real aTol = theMVCPB.FindFromIndex(i).Tolerance();
573 aVerts.Add(aV, aTol);
4e57c75e 574 }
575 //
8ae442a8 576 // Perform intersection
1155d05a 577 TopTools_ListOfListOfShape aChains;
8ae442a8 578 BOPAlgo_Tools::IntersectVertices(aVerts, myRunParallel, myFuzzyValue, aChains);
a2098360 579 //
8ae442a8 580 // Treat the results - make new vertices for each chain
1155d05a 581 TopTools_ListOfListOfShape::Iterator aItC(aChains);
8ae442a8 582 for (; aItC.More(); aItC.Next()) {
1155d05a 583 const TopTools_ListOfShape& aLVSD = aItC.Value();
4e57c75e 584 //
8ae442a8 585 TopoDS_Vertex aVNew;
586 BOPTools_AlgoTools::MakeVertex(aLVSD, aVNew);
587 myImages.Add(aVNew, aLVSD);
4e57c75e 588 }
589}
4e57c75e 590//=======================================================================
591//function : FillShrunkData
592//purpose :
593//=======================================================================
db8e4b9a 594void BOPAlgo_PaveFiller::FillShrunkData(Handle(BOPDS_PaveBlock)& thePB)
4e57c75e 595{
33ba8565 596 // Vertices
597 Standard_Integer nV1, nV2;
598 thePB->Indices(nV1, nV2);
4e57c75e 599 const TopoDS_Vertex& aV1=(*(TopoDS_Vertex *)(&myDS->Shape(nV1)));
4e57c75e 600 const TopoDS_Vertex& aV2=(*(TopoDS_Vertex *)(&myDS->Shape(nV2)));
33ba8565 601 // Original edge
602 Standard_Integer nE = thePB->OriginalEdge();
4e57c75e 603 const TopoDS_Edge& aE=(*(TopoDS_Edge *)(&myDS->Shape(nE)));
33ba8565 604 // Range
605 Standard_Real aT1, aT2;
606 thePB->Range(aT1, aT2);
4e57c75e 607 //
33ba8565 608 IntTools_ShrunkRange aSR;
505abfb8 609 aSR.SetContext(myContext);
610 aSR.SetData(aE, aT1, aT2, aV1, aV2);
4e57c75e 611 aSR.Perform();
33ba8565 612 // Analyze the results of computations
613 AnalyzeShrunkData(thePB, aSR);
614}
615//=======================================================================
616// function: AnalyzeShrunkData
617// purpose:
618//=======================================================================
619void BOPAlgo_PaveFiller::AnalyzeShrunkData(const Handle(BOPDS_PaveBlock)& thePB,
620 const IntTools_ShrunkRange& theSR)
621{
622 // in case of error treat the warning status
623 Standard_Boolean bWholeEdge = Standard_False;
624 TopoDS_Shape aWarnShape;
625 //
626 if (!theSR.IsDone() || !theSR.IsSplittable()) {
627 Standard_Real aEFirst, aELast, aPBFirst, aPBLast;
628 BRep_Tool::Range(theSR.Edge(), aEFirst, aELast);
629 thePB->Range(aPBFirst, aPBLast);
630 bWholeEdge = !(aPBFirst > aEFirst || aPBLast < aELast);
631 if (bWholeEdge) {
632 aWarnShape = theSR.Edge();
633 }
634 else {
635 const TopoDS_Shape& aV1 = myDS->Shape(thePB->Pave1().Index());
636 const TopoDS_Shape& aV2 = myDS->Shape(thePB->Pave2().Index());
637 BRep_Builder().MakeCompound(TopoDS::Compound(aWarnShape));
638 BRep_Builder().Add(aWarnShape, theSR.Edge());
639 BRep_Builder().Add(aWarnShape, aV1);
640 BRep_Builder().Add(aWarnShape, aV2);
641 }
642 //
643 if (!theSR.IsDone()) {
644 if (bWholeEdge)
645 AddWarning (new BOPAlgo_AlertTooSmallEdge (aWarnShape));
646 else
647 AddWarning (new BOPAlgo_AlertBadPositioning (aWarnShape));
4bc805bf 648 Standard_Real aTS1, aTS2;
649 theSR.ShrunkRange(aTS1, aTS2);
650 thePB->SetShrunkData(aTS1, aTS2, Bnd_Box(), Standard_False);
33ba8565 651 return;
652 }
653 //
654 if (bWholeEdge)
655 AddWarning (new BOPAlgo_AlertNotSplittableEdge (aWarnShape));
656 else
657 AddWarning (new BOPAlgo_AlertBadPositioning (aWarnShape));
4e57c75e 658 }
659 //
33ba8565 660 Standard_Real aTS1, aTS2;
661 theSR.ShrunkRange(aTS1, aTS2);
662 Bnd_Box aBox = theSR.BndBox();
663 aBox.SetGap(aBox.GetGap() + myFuzzyValue / 2.);
664 thePB->SetShrunkData(aTS1, aTS2, aBox, theSR.IsSplittable());
4e57c75e 665}
b4109929 666//=======================================================================
667//function : ForceInterfVE
668//purpose :
669//=======================================================================
b7cd7c2b 670Standard_Boolean BOPAlgo_PaveFiller::ForceInterfVE(const Standard_Integer nV,
671 Handle(BOPDS_PaveBlock)& aPB,
1155d05a 672 TColStd_MapOfInteger& theMEdges)
b4109929 673{
3510db62 674 Standard_Integer nE, nVx, nVSD, iFlag;
675 Standard_Real aT, aTolVNew;
b4109929 676 //
677 nE = aPB->OriginalEdge();
678 //
679 const BOPDS_ShapeInfo& aSIE=myDS->ShapeInfo(nE);
680 if (aSIE.HasSubShape(nV)) {
b7cd7c2b 681 return Standard_False;
b4109929 682 }
683 //
684 if (myDS->HasInterf(nV, nE)) {
b7cd7c2b 685 return Standard_False;
33ba8565 686 }
b4109929 687 //
688 if (myDS->HasInterfShapeSubShapes(nV, nE)) {
b7cd7c2b 689 return Standard_False;
b4109929 690 }
691 //
3510db62 692 if (aPB->Pave1().Index() == nV ||
693 aPB->Pave2().Index() == nV) {
b7cd7c2b 694 return Standard_False;
b4109929 695 }
696 //
3510db62 697 nVx = nV;
698 if (myDS->HasShapeSD(nV, nVSD)) {
699 nVx = nVSD;
700 }
b4109929 701 //
3510db62 702 const TopoDS_Vertex& aV = *(TopoDS_Vertex*)&myDS->Shape(nVx);
703 const TopoDS_Edge& aE = *(TopoDS_Edge*) &myDS->Shape(nE);
b4109929 704 //
0d0481c7 705 iFlag = myContext->ComputeVE(aV, aE, aT, aTolVNew, myFuzzyValue);
3510db62 706 if (iFlag == 0 || iFlag == -4) {
b4109929 707 BOPDS_Pave aPave;
708 //
b4109929 709 //
710 BOPDS_VectorOfInterfVE& aVEs=myDS->InterfVE();
a3476a9f 711 aVEs.SetIncrement(10);
3510db62 712 // 1
1155d05a 713 BOPDS_InterfVE& aVE=aVEs.Appended();
b4109929 714 aVE.SetIndices(nV, nE);
715 aVE.SetParameter(aT);
3510db62 716 // 2
b4109929 717 myDS->AddInterf(nV, nE);
718 //
3510db62 719 // 3 update vertex V/E if necessary
720 nVx=UpdateVertex(nV, aTolVNew);
721 // 4
722 if (myDS->IsNewShape(nVx)) {
723 aVE.SetIndexNew(nVx);
724 }
725 // 5 append ext pave to pave block
726 aPave.SetIndex(nVx);
b4109929 727 aPave.SetParameter(aT);
728 aPB->AppendExtPave(aPave);
729 //
8ae442a8 730 theMEdges.Add(nE);
33ba8565 731 //
732 // check for self-interference
733 Standard_Integer iRV = myDS->Rank(nV);
734 if (iRV >= 0 && iRV == myDS->Rank(nE)) {
735 // add warning status
736 TopoDS_Compound aWC;
737 BRep_Builder().MakeCompound(aWC);
738 BRep_Builder().Add(aWC, aV);
739 BRep_Builder().Add(aWC, aE);
740 AddWarning (new BOPAlgo_AlertSelfInterferingShape (aWC));
741 }
b7cd7c2b 742 return Standard_True;
b4109929 743 }
b7cd7c2b 744 return Standard_False;
b4109929 745}
01b5b3df 746
747//=======================================================================
748//function : GetPBBox
749//purpose :
750//=======================================================================
751Standard_Boolean BOPAlgo_PaveFiller::GetPBBox(const TopoDS_Edge& theE,
752 const Handle(BOPDS_PaveBlock)& thePB,
753 BOPAlgo_DataMapOfPaveBlockBndBox& thePBBox,
754 Standard_Real& theFirst,
755 Standard_Real& theLast,
756 Standard_Real& theSFirst,
757 Standard_Real& theSLast,
758 Bnd_Box& theBox)
759{
760 thePB->Range(theFirst, theLast);
761 // check the validity of PB's range
762 Standard_Boolean bValid = theLast - theFirst > Precision::PConfusion();
763 if (!bValid) {
764 return bValid;
765 }
766 //
767 // check shrunk data
768 if (thePB->HasShrunkData()) {
769 Standard_Boolean bIsSplittable;
770 thePB->ShrunkData(theSFirst, theSLast, theBox, bIsSplittable);
771 return bValid;
772 }
773 //
774 theSFirst = theFirst;
775 theSLast = theLast;
776 // check the map
777 if (thePBBox.IsBound(thePB)) {
778 theBox = thePBBox.Find(thePB);
779 }
780 else {
781 // build bounding box
782 BRepAdaptor_Curve aBAC(theE);
783 Standard_Real aTol = BRep_Tool::Tolerance(theE) + Precision::Confusion();
784 BndLib_Add3dCurve::Add(aBAC, theSFirst, theSLast, aTol, theBox);
785 thePBBox.Bind(thePB, theBox);
786 }
787 return bValid;
788}
b7cd7c2b 789
790//=======================================================================
791//function : ForceInterfEE
792//purpose :
793//=======================================================================
794void BOPAlgo_PaveFiller::ForceInterfEE()
795{
796 // Now that we have vertices increased and unified, try to find additional
797 // common blocks among the pairs of edges that did not participate in
798 // intersection (PerformEE() method) due to being rejected by bounding boxes.
799 // Here, we are interested in common blocks only, as all real intersections
800 // should have happened already. Thus, we need to look only for the same
801 // vertices in the pairs of pave blocks and check the coincidence of such pave blocks.
802
803 Handle(NCollection_IncAllocator) anAlloc = new NCollection_IncAllocator;
804
805 // Initialize pave blocks for all SD vertices
806 Standard_Integer i, aNbS = myDS->NbSourceShapes();
807 for (i = 0; i < aNbS; ++i)
808 {
809 const BOPDS_ShapeInfo& aSI = myDS->ShapeInfo(i);
810 if (aSI.ShapeType() == TopAbs_VERTEX)
811 {
812 Standard_Integer nVSD;
813 if (myDS->HasShapeSD(i, nVSD))
814 myDS->InitPaveBlocksForVertex(i);
815 }
816 }
817
818 // Find all Pave Blocks with both paves being SD vertices.
819 NCollection_IndexedDataMap<BOPDS_Pair,
820 BOPDS_ListOfPaveBlock,
821 BOPDS_PairMapHasher> aPBMap(1, anAlloc);
822 // Fence map of pave blocks
823 BOPDS_MapOfPaveBlock aMPBFence(1, anAlloc);
824
825 BOPDS_VectorOfListOfPaveBlock& aPBP = myDS->ChangePaveBlocksPool();
1155d05a 826 Standard_Integer aNbPBP = aPBP.Length();
b7cd7c2b 827 for (i = 0; i < aNbPBP; ++i)
828 {
829 BOPDS_ListOfPaveBlock& aLPB = aPBP(i);
830 BOPDS_ListIteratorOfListOfPaveBlock aItLPB(aLPB);
831 for (; aItLPB.More(); aItLPB.Next())
832 {
833 const Handle(BOPDS_PaveBlock)& aPB = aItLPB.Value();
834 const Handle(BOPDS_PaveBlock)& aPBR = myDS->RealPaveBlock(aPB);
835 if (!aMPBFence.Add(aPBR))
836 continue;
837
838 // Get indices
839 Standard_Integer nV1, nV2;
840 aPBR->Indices(nV1, nV2);
841
842 // Add pave block to a map
843 BOPDS_Pair aPair(nV1, nV2);
844 BOPDS_ListOfPaveBlock *pList = aPBMap.ChangeSeek(aPair);
845 if (!pList)
846 pList = &aPBMap(aPBMap.Add(aPair, BOPDS_ListOfPaveBlock(anAlloc)));
847 pList->Append(aPBR);
848 }
849 }
850
851 Standard_Integer aNbPB = aPBMap.Extent();
852 if (!aNbPB)
853 return;
854
855 // Find pairs of Pave Blocks having the same SD vertices,
856 // rejecting the pairs of edges that have already been intersected
857
858 // Prepare map of pairs of intersected edges
859 BOPDS_MapOfPair aMEEDone(1, anAlloc);
860 myIterator->Initialize(TopAbs_EDGE, TopAbs_EDGE);
861 for (; myIterator->More(); myIterator->Next())
862 {
863 Standard_Integer nE1, nE2;
864 myIterator->Value(nE1, nE2);
865 aMEEDone.Add(BOPDS_Pair(nE1, nE2));
866 }
867
868 // Vector of pairs for intersection
869 BOPAlgo_VectorOfEdgeEdge aVEdgeEdge;
870
871 for (i = 1; i <= aNbPB; ++i)
872 {
873 const BOPDS_ListOfPaveBlock& aLPB = aPBMap(i);
874 if (aLPB.Extent() < 2)
875 continue;
876
877 const BOPDS_Pair& aPair = aPBMap.FindKey(i);
878 Standard_Integer nV1, nV2;
879 aPair.Indices(nV1, nV2);
880
881 const TopoDS_Vertex& aV1 = TopoDS::Vertex(myDS->Shape(nV1));
882 const TopoDS_Vertex& aV2 = TopoDS::Vertex(myDS->Shape(nV2));
883
884 // Use the max tolerance of vertices as Fuzzy value for intersection
885 // of edges
886 Standard_Real aTolAdd = 2 * Max(BRep_Tool::Tolerance(aV1),
887 BRep_Tool::Tolerance(aV2));
888
889 // All possible pairs combined from the list <aLPB> should be checked
890 BOPDS_ListIteratorOfListOfPaveBlock aItLPB1(aLPB);
891 for (; aItLPB1.More(); aItLPB1.Next())
892 {
893 const Handle(BOPDS_PaveBlock)& aPB1 = aItLPB1.Value();
894 const Standard_Integer nE1 = aPB1->OriginalEdge();
895 const TopoDS_Edge& aE1 = TopoDS::Edge(myDS->Shape(nE1));
896 Standard_Real aT11, aT12;
897 aPB1->Range(aT11, aT12);
898
899 BOPDS_ListIteratorOfListOfPaveBlock aItLPB2 = aItLPB1;
900 for (aItLPB2.Next(); aItLPB2.More(); aItLPB2.Next())
901 {
902 const Handle(BOPDS_PaveBlock)& aPB2 = aItLPB2.Value();
903 const Standard_Integer nE2 = aPB2->OriginalEdge();
904
905 if (aMEEDone.Contains(BOPDS_Pair(nE1, nE2)))
906 continue;
907
908 // Make sure that the edges came from different arguments
909 if (myDS->Rank(nE1) == myDS->Rank(nE2))
910 continue;
911
912 const TopoDS_Edge& aE2 = TopoDS::Edge(myDS->Shape(nE2));
913 Standard_Real aT21, aT22;
914 aPB2->Range(aT21, aT22);
915
916 // Add pair for intersection
1155d05a 917 BOPAlgo_EdgeEdge& anEdgeEdge = aVEdgeEdge.Appended();
b7cd7c2b 918 anEdgeEdge.UseQuickCoincidenceCheck(Standard_True);
919 anEdgeEdge.SetPaveBlock1(aPB1);
920 anEdgeEdge.SetPaveBlock2(aPB2);
921 anEdgeEdge.SetEdge1(aE1, aT11, aT12);
922 anEdgeEdge.SetEdge2(aE2, aT21, aT22);
923 anEdgeEdge.SetFuzzyValue(myFuzzyValue + aTolAdd);
924 anEdgeEdge.SetProgressIndicator(myProgressIndicator);
925 }
926 }
927 }
928
1155d05a 929 Standard_Integer aNbPairs = aVEdgeEdge.Length();
b7cd7c2b 930 if (!aNbPairs)
931 return;
932
933 aPBMap.Clear();
934 aMPBFence.Clear();
935 aMEEDone.Clear();
936 anAlloc->Reset();
937
938 // Perform intersection of the found pairs
939 BOPAlgo_EdgeEdgeCnt::Perform(myRunParallel, aVEdgeEdge);
940
941 BOPDS_VectorOfInterfEE& aEEs = myDS->InterfEE();
942 if (aEEs.IsEmpty())
943 aEEs.SetIncrement(10);
944
945 // Analyze the results of intersection looking for TopAbs_EDGE
946 // intersection type only.
947
948 BOPDS_IndexedDataMapOfPaveBlockListOfPaveBlock aMPBLPB(1, anAlloc);
949
950 for (i = 0; i < aNbPairs; ++i)
951 {
952 BOPAlgo_EdgeEdge& anEdgeEdge = aVEdgeEdge(i);
953 if (!anEdgeEdge.IsDone() || anEdgeEdge.HasErrors())
954 {
955 // Warn about failed intersection of sub-shapes
956 const TopoDS_Shape& aE1 = myDS->Shape(anEdgeEdge.PaveBlock1()->OriginalEdge());
957 const TopoDS_Shape& aE2 = myDS->Shape(anEdgeEdge.PaveBlock2()->OriginalEdge());
958 AddIntersectionFailedWarning(aE1, aE2);
959 continue;
960 }
961
962 const IntTools_SequenceOfCommonPrts& aCParts = anEdgeEdge.CommonParts();
963 if (aCParts.Length() != 1)
964 continue;
965
966 const IntTools_CommonPrt& aCP = aCParts(1);
967 if (aCP.Type() != TopAbs_EDGE)
968 continue;
969
970 Handle(BOPDS_PaveBlock) aPB[] = {anEdgeEdge.PaveBlock1(), anEdgeEdge.PaveBlock2()};
971 const Standard_Integer nE1 = aPB[0]->OriginalEdge();
972 const Standard_Integer nE2 = aPB[1]->OriginalEdge();
973
1155d05a 974 BOPDS_InterfEE& aEE = aEEs.Appended();
b7cd7c2b 975 aEE.SetIndices(nE1, nE2);
976 aEE.SetCommonPart(aCP);
977 myDS->AddInterf(nE1, nE2);
978
979 // Fill map for common blocks creation
980 for (Standard_Integer j = 0; j < 2; ++j)
981 {
982 if (myDS->IsCommonBlock(aPB[j]))
983 {
984 const BOPDS_ListOfPaveBlock& aLPBCB = myDS->CommonBlock(aPB[j])->PaveBlocks();
985 BOPDS_ListIteratorOfListOfPaveBlock aItLPB(aLPBCB);
986 for (; aItLPB.More(); aItLPB.Next())
987 BOPAlgo_Tools::FillMap<Handle(BOPDS_PaveBlock),
988 TColStd_MapTransientHasher>(aPB[j], aItLPB.Value(), aMPBLPB, anAlloc);
989 }
990 }
991 BOPAlgo_Tools::FillMap<Handle(BOPDS_PaveBlock),
992 TColStd_MapTransientHasher>(aPB[0], aPB[1], aMPBLPB, anAlloc);
993 }
994
995 // Create new common blocks of coinciding pairs.
996 BOPAlgo_Tools::PerformCommonBlocks(aMPBLPB, anAlloc, myDS);
997}