0031836: Modeling Algorithms - Boolean cut failed between a Cone and a Torus
[occt.git] / src / BOPAlgo / BOPAlgo_PaveFiller_3.cxx
1 // Created by: Peter KURNEV
2 // Copyright (c) 2010-2014 OPEN CASCADE SAS
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 //
7 // This file is part of Open CASCADE Technology software library.
8 //
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
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.
14 //
15 // Alternatively, this file may be used under the terms of Open CASCADE
16 // commercial license or contractual agreement.
17
18
19 #include <Bnd_Box.hxx>
20 #include <BOPAlgo_PaveFiller.hxx>
21 #include <BOPAlgo_Tools.hxx>
22 #include <BOPAlgo_Alerts.hxx>
23 #include <BOPDS_CommonBlock.hxx>
24 #include <BOPDS_CoupleOfPaveBlocks.hxx>
25 #include <BOPDS_DS.hxx>
26 #include <BOPDS_Interf.hxx>
27 #include <BOPDS_Iterator.hxx>
28 #include <BOPDS_MapOfPaveBlock.hxx>
29 #include <BOPDS_Pave.hxx>
30 #include <BOPDS_PaveBlock.hxx>
31 #include <BOPDS_VectorOfInterfEE.hxx>
32 #include <BOPTools_AlgoTools.hxx>
33 #include <BOPTools_AlgoTools2D.hxx>
34 #include <BOPTools_Parallel.hxx>
35 #include <BndLib_Add3dCurve.hxx>
36 #include <BRep_Tool.hxx>
37 #include <BRep_Builder.hxx>
38 #include <BRepAdaptor_Curve.hxx>
39 #include <GeomAPI_ProjectPointOnCurve.hxx>
40 #include <gp_Pnt.hxx>
41 #include <IntTools_CommonPrt.hxx>
42 #include <IntTools_Context.hxx>
43 #include <IntTools_EdgeEdge.hxx>
44 #include <IntTools_Range.hxx>
45 #include <IntTools_SequenceOfCommonPrts.hxx>
46 #include <IntTools_SequenceOfRanges.hxx>
47 #include <IntTools_ShrunkRange.hxx>
48 #include <IntTools_Tools.hxx>
49 #include <NCollection_IncAllocator.hxx>
50 #include <NCollection_Vector.hxx>
51 #include <Precision.hxx>
52 #include <TopoDS.hxx>
53 #include <TopoDS_Edge.hxx>
54 #include <TopoDS_Vertex.hxx>
55
56 /////////////////////////////////////////////////////////////////////////
57 //=======================================================================
58 //class    : BOPAlgo_EdgeEdge
59 //purpose  : 
60 //=======================================================================
61 class BOPAlgo_EdgeEdge : 
62   public IntTools_EdgeEdge,
63   public BOPAlgo_Algo {
64  
65  public:
66
67   DEFINE_STANDARD_ALLOC
68   //
69   BOPAlgo_EdgeEdge(): 
70     IntTools_EdgeEdge(),
71     BOPAlgo_Algo() {
72   };
73   //
74   virtual ~BOPAlgo_EdgeEdge(){
75   };
76   //
77   void SetPaveBlock1(const Handle(BOPDS_PaveBlock)& aPB) {
78     myPB1=aPB;
79   }
80   //
81   Handle(BOPDS_PaveBlock)& PaveBlock1() {
82     return myPB1;
83   }
84   //
85   void SetPaveBlock2(const Handle(BOPDS_PaveBlock)& aPB) {
86     myPB2=aPB;
87   }
88   //
89   Handle(BOPDS_PaveBlock)& PaveBlock2() {
90     return myPB2;
91   }
92   //
93   void SetBoxes (const Bnd_Box& theBox1,
94                  const Bnd_Box& theBox2)
95   {
96     myBox1 = theBox1;
97     myBox2 = theBox2;
98   }
99   //
100   void SetFuzzyValue(const Standard_Real theFuzz) {
101     IntTools_EdgeEdge::SetFuzzyValue(theFuzz);
102   }
103   //
104   virtual void Perform() {
105     BOPAlgo_Algo::UserBreak();
106     TopoDS_Edge anE1 = myEdge1, anE2 = myEdge2;
107     Standard_Boolean hasTrsf = false;
108     try
109     {
110       OCC_CATCH_SIGNALS
111
112       gp_Trsf aTrsf;
113       if (BOPAlgo_Tools::TrsfToPoint (myBox1, myBox2, aTrsf))
114       {
115         // Shapes are located far from origin, move the shapes to the origin,
116         // to increase the accuracy of intersection.
117         TopLoc_Location aLoc (aTrsf);
118         myEdge1.Move (aLoc);
119         myEdge2.Move (aLoc);
120         hasTrsf = Standard_True;
121       }
122
123       IntTools_EdgeEdge::Perform();
124     }
125     catch (Standard_Failure const&)
126     {
127       AddError(new BOPAlgo_AlertIntersectionFailed);
128     }
129
130     myEdge1 = anE1;
131     myEdge2 = anE2;
132     if (hasTrsf)
133     {
134       for (Standard_Integer i = 1; i <= myCommonParts.Length(); ++i)
135       {
136         IntTools_CommonPrt& aCPart = myCommonParts (i);
137         aCPart.SetEdge1 (myEdge1);
138         aCPart.SetEdge2 (myEdge2);
139       }
140     }
141
142   }
143   //
144  protected:
145   Handle(BOPDS_PaveBlock) myPB1;
146   Handle(BOPDS_PaveBlock) myPB2;
147   Bnd_Box myBox1;
148   Bnd_Box myBox2;
149 };
150 //
151 //=======================================================================
152 typedef NCollection_Vector<BOPAlgo_EdgeEdge> BOPAlgo_VectorOfEdgeEdge;
153
154 //=======================================================================
155 // function: PerformEE
156 // purpose: 
157 //=======================================================================
158 void BOPAlgo_PaveFiller::PerformEE()
159 {
160   FillShrunkData(TopAbs_EDGE, TopAbs_EDGE);
161   //
162   myIterator->Initialize(TopAbs_EDGE, TopAbs_EDGE);
163   Standard_Integer iSize = myIterator->ExpectedLength();
164   if (!iSize) {
165     return; 
166   }
167   //
168   Standard_Boolean bExpressCompute, bIsPBSplittable1, bIsPBSplittable2;
169   Standard_Integer i, iX, nE1, nE2, aNbCPrts, k, aNbEdgeEdge;
170   Standard_Integer nV11, nV12, nV21, nV22;
171   Standard_Real aTS11, aTS12, aTS21, aTS22, aT11, aT12, aT21, aT22;
172   TopAbs_ShapeEnum aType;
173   BOPDS_ListIteratorOfListOfPaveBlock aIt1, aIt2;
174   Handle(NCollection_BaseAllocator) aAllocator;
175   BOPAlgo_VectorOfEdgeEdge aVEdgeEdge;
176   BOPDS_MapIteratorOfMapOfPaveBlock aItPB; 
177   // keep modified edges for further update
178   TColStd_MapOfInteger aMEdges;
179   //
180   aAllocator=NCollection_BaseAllocator::CommonBaseAllocator();
181   //-----------------------------------------------------scope f
182   BOPDS_IndexedDataMapOfPaveBlockListOfPaveBlock aMPBLPB(100, aAllocator);
183   BOPDS_IndexedDataMapOfShapeCoupleOfPaveBlocks aMVCPB(100, aAllocator);
184   BOPAlgo_DataMapOfPaveBlockBndBox aDMPBBox(100, aAllocator);
185   //
186   BOPDS_VectorOfInterfEE& aEEs=myDS->InterfEE();
187   aEEs.SetIncrement(iSize);
188   //
189   for (; myIterator->More(); myIterator->Next()) {
190     myIterator->Value(nE1, nE2);
191     //
192     const BOPDS_ShapeInfo& aSIE1=myDS->ShapeInfo(nE1);
193     if (aSIE1.HasFlag()){
194       continue;
195     }
196     const BOPDS_ShapeInfo& aSIE2=myDS->ShapeInfo(nE2);
197     if (aSIE2.HasFlag()){
198       continue;
199     }
200     //
201     BOPDS_ListOfPaveBlock& aLPB1 = myDS->ChangePaveBlocks(nE1);
202     if (aLPB1.IsEmpty()) {
203       continue;
204     }
205     //
206     BOPDS_ListOfPaveBlock& aLPB2 = myDS->ChangePaveBlocks(nE2);
207     if (aLPB2.IsEmpty()) {
208       continue;
209     }
210     //
211     const TopoDS_Edge& aE1=(*(TopoDS_Edge *)(&aSIE1.Shape()));
212     const TopoDS_Edge& aE2=(*(TopoDS_Edge *)(&aSIE2.Shape()));
213     //
214     aIt1.Initialize(aLPB1);
215     for (; aIt1.More(); aIt1.Next()) {
216       Bnd_Box aBB1;
217       //
218       Handle(BOPDS_PaveBlock)& aPB1=aIt1.ChangeValue();
219       //
220       if (!GetPBBox(aE1, aPB1, aDMPBBox, aT11, aT12, aTS11, aTS12, aBB1)) {
221         continue;
222       }
223       //
224       aPB1->Indices(nV11, nV12);
225       //
226       aIt2.Initialize(aLPB2);
227       for (; aIt2.More(); aIt2.Next()) {
228         Bnd_Box aBB2;
229         //
230         Handle(BOPDS_PaveBlock)& aPB2=aIt2.ChangeValue();
231         //
232         if (!GetPBBox(aE2, aPB2, aDMPBBox, aT21, aT22, aTS21, aTS22, aBB2)) {
233           continue;
234         }
235         //
236         if (aBB1.IsOut(aBB2)) {
237           continue;
238         }
239         //
240         aPB2->Indices(nV21, nV22);
241         //
242         bExpressCompute=((nV11==nV21 && nV12==nV22) ||
243                          (nV12==nV21 && nV11==nV22));
244         //
245         BOPAlgo_EdgeEdge& anEdgeEdge=aVEdgeEdge.Appended();
246         //
247         anEdgeEdge.UseQuickCoincidenceCheck(bExpressCompute);
248         //
249         anEdgeEdge.SetPaveBlock1(aPB1);
250         anEdgeEdge.SetPaveBlock2(aPB2);
251         //
252         anEdgeEdge.SetEdge1(aE1, aT11, aT12);
253         anEdgeEdge.SetEdge2(aE2, aT21, aT22);
254         anEdgeEdge.SetBoxes (aBB1, aBB2);
255         anEdgeEdge.SetFuzzyValue(myFuzzyValue);
256         if (myProgressScope != NULL)
257         {
258           anEdgeEdge.SetProgressIndicator(*myProgressScope);
259         }
260       }//for (; aIt2.More(); aIt2.Next()) {
261     }//for (; aIt1.More(); aIt1.Next()) {
262   }//for (; myIterator->More(); myIterator->Next()) {
263   //
264   aNbEdgeEdge=aVEdgeEdge.Length();
265   //======================================================
266   BOPTools_Parallel::Perform (myRunParallel, aVEdgeEdge);
267   //======================================================
268   //
269   for (k = 0; k < aNbEdgeEdge; ++k) {
270     Bnd_Box aBB1, aBB2;
271     //
272     BOPAlgo_EdgeEdge& anEdgeEdge=aVEdgeEdge(k);
273     if (!anEdgeEdge.IsDone() || anEdgeEdge.HasErrors()) {
274       // Warn about failed intersection of sub-shapes
275       const TopoDS_Shape& aE1 = myDS->Shape(anEdgeEdge.PaveBlock1()->OriginalEdge());
276       const TopoDS_Shape& aE2 = myDS->Shape(anEdgeEdge.PaveBlock2()->OriginalEdge());
277       AddIntersectionFailedWarning(aE1, aE2);
278       continue;
279     }
280     //
281     const IntTools_SequenceOfCommonPrts& aCPrts = anEdgeEdge.CommonParts();
282     aNbCPrts = aCPrts.Length();
283     if (!aNbCPrts) {
284       continue;
285     }
286     //--------------------------------------------
287     Handle(BOPDS_PaveBlock)& aPB1=anEdgeEdge.PaveBlock1();
288     nE1=aPB1->OriginalEdge();
289     aPB1->Range(aT11, aT12);
290     if (!aPB1->HasShrunkData()) {
291       aTS11 = aT11;
292       aTS12 = aT12;
293       bIsPBSplittable1 = Standard_False;
294     }
295     else {
296       aPB1->ShrunkData(aTS11, aTS12, aBB1, bIsPBSplittable1);
297     }
298     //
299     Handle(BOPDS_PaveBlock)& aPB2=anEdgeEdge.PaveBlock2();
300     nE2=aPB2->OriginalEdge();
301     aPB2->Range(aT21, aT22);
302     if (!aPB2->HasShrunkData()) {
303       aTS21 = aT21;
304       aTS22 = aT22;
305       bIsPBSplittable2 = Standard_False;
306     }
307     else {
308       aPB2->ShrunkData(aTS21, aTS22, aBB2, bIsPBSplittable2);
309     }
310     //
311     //--------------------------------------------
312     IntTools_Range aR11(aT11, aTS11), aR12(aTS12, aT12),
313                    aR21(aT21, aTS21), aR22(aTS22, aT22);
314     //
315     Standard_Boolean bAnalytical = Standard_False;
316     {
317       const TopoDS_Edge& aOE1 = *(TopoDS_Edge*)&myDS->Shape(nE1);
318       const TopoDS_Edge& aOE2 = *(TopoDS_Edge*)&myDS->Shape(nE2);
319       //
320       BRepAdaptor_Curve aBAC1(aOE1), aBAC2(aOE2);
321       //
322       GeomAbs_CurveType aType1 = aBAC1.GetType();
323       GeomAbs_CurveType aType2 = aBAC2.GetType();
324       //
325       bAnalytical = (((aType1 == GeomAbs_Line) &&
326                       (aType2 == GeomAbs_Line ||
327                        aType2 == GeomAbs_Circle)) ||
328                      ((aType2 == GeomAbs_Line) &&
329                       (aType1 == GeomAbs_Line ||
330                        aType1 == GeomAbs_Circle)));
331     }
332     //
333     for (i=1; i<=aNbCPrts; ++i) {
334       const IntTools_CommonPrt& aCPart=aCPrts(i);
335       //
336       const TopoDS_Edge& aE1=aCPart.Edge1();
337       const TopoDS_Edge& aE2=aCPart.Edge2();
338       //
339       aType=aCPart.Type();
340       switch (aType) {
341         case TopAbs_VERTEX:  { 
342           if (!bIsPBSplittable1 || !bIsPBSplittable2) {
343             continue;
344           }
345           //
346           Standard_Boolean bIsOnPave[4];
347           Standard_Integer nV[4], j;
348           Standard_Real aT1, aT2, aTol;
349           TopoDS_Vertex aVnew;
350           IntTools_Range aCR1, aCR2;
351           //
352           IntTools_Tools::VertexParameters(aCPart, aT1, aT2);
353           aTol = Precision::Confusion();
354           aCR1 = aCPart.Range1();
355           aCR2 = aCPart.Ranges2()(1);
356           // 
357           //decide to keep the pave or not
358           bIsOnPave[0] = IntTools_Tools::IsOnPave1(aT1, aR11, aTol) ||
359             IntTools_Tools::IsOnPave1(aR11.First(), aCR1, aTol);
360           bIsOnPave[1] = IntTools_Tools::IsOnPave1(aT1, aR12, aTol) || 
361             IntTools_Tools::IsOnPave1(aR12.Last(), aCR1, aTol);
362           bIsOnPave[2] = IntTools_Tools::IsOnPave1(aT2, aR21, aTol) ||
363             IntTools_Tools::IsOnPave1(aR21.First(), aCR2, aTol);
364           bIsOnPave[3] = IntTools_Tools::IsOnPave1(aT2, aR22, aTol) ||
365             IntTools_Tools::IsOnPave1(aR22.Last(), aCR2, aTol);
366           //
367           aPB1->Indices(nV[0], nV[1]);
368           aPB2->Indices(nV[2], nV[3]);
369           //
370           if((bIsOnPave[0] && bIsOnPave[2]) || 
371              (bIsOnPave[0] && bIsOnPave[3]) ||
372              (bIsOnPave[1] && bIsOnPave[2]) || 
373              (bIsOnPave[1] && bIsOnPave[3])) {
374             continue;
375           }
376           //
377           Standard_Boolean isVExists = Standard_False;
378           for (j = 0; j < 4; ++j)
379           {
380             if (bIsOnPave[j])
381             {
382               Handle(BOPDS_PaveBlock)& aPB = (j < 2) ? aPB2 : aPB1;
383               bIsOnPave[j] = ForceInterfVE(nV[j], aPB, aMEdges);
384               if (bIsOnPave[j]) isVExists = Standard_True;
385             }
386           }
387
388           BOPTools_AlgoTools::MakeNewVertex(aE1, aT1, aE2, aT2, aVnew);
389           const gp_Pnt aPnew = BRep_Tool::Pnt(aVnew);
390
391           if (isVExists)
392           {
393             // The found intersection point is located closely to one of the
394             // pave blocks bounds. So, do not create the new vertex in this point.
395             // Check if this point is a real intersection point or just a touching point.
396             // If it is a touching point, do nothing.
397             // If it is an intersection point, update the existing vertex to cover the
398             // intersection point.
399             const gp_Pnt aPOnE1 = BRepAdaptor_Curve(aE1).Value(aT1);
400             const gp_Pnt aPOnE2 = BRepAdaptor_Curve(aE2).Value(aT2);
401             if (aPOnE1.Distance(aPOnE2) > Precision::Intersection())
402               // No intersection point
403               continue;
404
405             // Real intersection is present.
406             // Update the existing vertex to cover the intersection point.
407             for (j = 0; j < 4; ++j)
408             {
409               if (bIsOnPave[j])
410               {
411                 const TopoDS_Vertex& aV = TopoDS::Vertex(myDS->Shape(nV[j]));
412                 const gp_Pnt aP = BRep_Tool::Pnt(aV);
413                 Standard_Real aDistPP = aP.Distance(aPnew);
414                 // Just update the vertex
415                 UpdateVertex(nV[j], aDistPP);
416                 myVertsToAvoidExtension.Add(nV[j]);
417               }
418             }
419           }
420
421           Standard_Real aTolVnew = BRep_Tool::Tolerance(aVnew);
422           if (bAnalytical) {
423             // increase tolerance for Line/Line intersection, but do not update 
424             // the vertex till its intersection with some other shape
425             Standard_Real aTolMin = (BRepAdaptor_Curve(aE1).GetType() == GeomAbs_Line) ?
426               (aCR1.Last() - aCR1.First()) / 2. : (aCR2.Last() - aCR2.First()) / 2.;
427             if (aTolMin > aTolVnew) {
428               aTolVnew = aTolMin;
429             }
430           }
431           // <-LXBR
432           {
433             Standard_Integer nVS[2], iFound;
434             Standard_Real aTolVx, aD2, aDT2;
435             TColStd_MapOfInteger aMV;
436             gp_Pnt aPx;
437             //
438             iFound=0;
439             j=-1;
440             aMV.Add(nV[0]);
441             aMV.Add(nV[1]);
442             //
443             if (aMV.Contains(nV[2])) {
444               ++j;
445               nVS[j]=nV[2];
446             }
447             if (aMV.Contains(nV[3])) {
448               ++j;
449               nVS[j]=nV[3];
450             }
451             //
452             for (Standard_Integer k1=0; k1<=j; ++k1) {
453               const TopoDS_Vertex& aVx= *(TopoDS_Vertex*)&(myDS->Shape(nVS[k1]));
454               aTolVx=BRep_Tool::Tolerance(aVx);
455               aPx=BRep_Tool::Pnt(aVx);
456               aD2=aPnew.SquareDistance(aPx);
457               //
458               aDT2=100.*(aTolVnew+aTolVx)*(aTolVnew+aTolVx);
459               //
460               if (aD2<aDT2) {
461                 iFound=1;
462                 break;
463               }
464             }
465             //
466             if (iFound) {
467               continue;
468             }
469           }
470           //
471           // 1
472           BOPDS_InterfEE& aEE=aEEs.Appended();
473           iX=aEEs.Length()-1;
474           aEE.SetIndices(nE1, nE2);
475           aEE.SetCommonPart(aCPart);
476           // 2
477           myDS->AddInterf(nE1, nE2);
478           //
479           BOPDS_CoupleOfPaveBlocks aCPB;
480           //
481           aCPB.SetPaveBlocks(aPB1, aPB2);
482           aCPB.SetIndexInterf(iX);
483           aCPB.SetTolerance(aTolVnew);
484           aMVCPB.Add(aVnew, aCPB);
485         }//case TopAbs_VERTEX: 
486           break;
487             //
488         case TopAbs_EDGE: {
489           if (aNbCPrts > 1) {
490             break;
491           }
492           //
493           Standard_Boolean bHasSameBounds;
494           bHasSameBounds=aPB1->HasSameBounds(aPB2);
495           if (!bHasSameBounds) {
496             break;
497           }
498           // 1
499           BOPDS_InterfEE& aEE=aEEs.Appended();
500           iX=aEEs.Length()-1;
501           aEE.SetIndices(nE1, nE2);
502           aEE.SetCommonPart(aCPart);
503           // 2
504           myDS->AddInterf(nE1, nE2);
505           //
506           BOPAlgo_Tools::FillMap<Handle(BOPDS_PaveBlock), TColStd_MapTransientHasher>(aPB1, aPB2, aMPBLPB, aAllocator);
507         }//case TopAbs_EDGE
508           break;
509         default:
510           break;
511       }//switch (aType) {
512     }//for (i=1; i<=aNbCPrts; i++) {
513   }//for (k=0; k < aNbFdgeEdge; ++k) {
514   // 
515   //=========================================
516   // post treatment
517   //=========================================
518   BOPAlgo_Tools::PerformCommonBlocks(aMPBLPB, aAllocator, myDS, myContext);
519   // Update vertices of common blocks with real CB tolerances
520   UpdateVerticesOfCB();
521
522   PerformNewVertices(aMVCPB, aAllocator);
523   //
524   if (aMEdges.Extent()) {
525     Standard_Integer aNbV = aMVCPB.Extent();
526     for (i = 1; i <= aNbV; ++i) {
527       Handle(BOPDS_PaveBlock) aPB1, aPB2;
528       const BOPDS_CoupleOfPaveBlocks& aCPB = aMVCPB.FindFromIndex(i);
529       aCPB.PaveBlocks(aPB1, aPB2);
530       //
531       aMEdges.Remove(aPB1->OriginalEdge());
532       aMEdges.Remove(aPB2->OriginalEdge());
533     }
534     //
535     SplitPaveBlocks(aMEdges, Standard_False);
536   }
537   //
538   //-----------------------------------------------------scope t
539   aMPBLPB.Clear();
540   aMVCPB.Clear();
541 }
542 //=======================================================================
543 //function : PerformVerticesEE
544 //purpose  : 
545 //=======================================================================
546 void BOPAlgo_PaveFiller::PerformNewVertices
547   (BOPDS_IndexedDataMapOfShapeCoupleOfPaveBlocks& theMVCPB,
548    const Handle(NCollection_BaseAllocator)& theAllocator,
549    const Standard_Boolean bIsEEIntersection)
550 {
551   Standard_Integer aNbV = theMVCPB.Extent();
552   if (!aNbV) {
553     return;
554   }
555   //
556   Standard_Real aTolAdd = myFuzzyValue / 2.;
557   //
558   // 1. Fuse the new vertices
559   TopTools_IndexedDataMapOfShapeListOfShape aImages;
560   TreatNewVertices(theMVCPB, aImages);
561   //
562   // 2. Add new vertices to myDS and connect indices to CPB structure
563   BOPDS_VectorOfInterfEE& aEEs = myDS->InterfEE();
564   BOPDS_VectorOfInterfEF& aEFs = myDS->InterfEF();
565   //
566   Standard_Integer i, aNb = aImages.Extent();
567   for (i = 1; i <= aNb; ++i) {
568     const TopoDS_Vertex& aV = TopoDS::Vertex(aImages.FindKey(i));
569     const TopTools_ListOfShape& aLVSD = aImages.FindFromIndex(i);
570     //
571     BOPDS_ShapeInfo aSI;
572     aSI.SetShapeType(TopAbs_VERTEX);
573     aSI.SetShape(aV);
574     Standard_Integer iV = myDS->Append(aSI);
575     //
576     BOPDS_ShapeInfo& aSIDS = myDS->ChangeShapeInfo(iV);
577     Bnd_Box& aBox = aSIDS.ChangeBox();
578     aBox.Add(BRep_Tool::Pnt(aV));
579     aBox.SetGap(BRep_Tool::Tolerance(aV) + aTolAdd);
580     //
581     TopTools_ListIteratorOfListOfShape aItLS(aLVSD);
582     for (; aItLS.More(); aItLS.Next()) {
583       const TopoDS_Shape& aVx = aItLS.Value();
584       BOPDS_CoupleOfPaveBlocks &aCPB = theMVCPB.ChangeFromKey(aVx);
585       aCPB.SetIndex(iV);
586       // update interference
587       Standard_Integer iX = aCPB.IndexInterf();
588       BOPDS_Interf *aInt = bIsEEIntersection ? (BOPDS_Interf*)(&aEEs(iX)) : (BOPDS_Interf*) (&aEFs(iX));
589       aInt->SetIndexNew(iV);
590     }
591   }
592   //
593   // 3. Map PaveBlock/ListOfVertices to add to this PaveBlock ->aMPBLI
594   BOPDS_IndexedDataMapOfPaveBlockListOfInteger aMPBLI(100, theAllocator);
595   for (i = 1; i <= aNbV; ++i) {
596     const BOPDS_CoupleOfPaveBlocks& aCPB = theMVCPB.FindFromIndex(i);
597     Standard_Integer iV = aCPB.Index();
598     //
599     Handle(BOPDS_PaveBlock) aPB[2];
600     aCPB.PaveBlocks(aPB[0], aPB[1]);
601     for (Standard_Integer j = 0; j < 2; ++j) {
602       TColStd_ListOfInteger *pLI = aMPBLI.ChangeSeek(aPB[j]);
603       if (!pLI) {
604         pLI = &aMPBLI(aMPBLI.Add(aPB[j], TColStd_ListOfInteger(theAllocator)));
605       }
606       pLI->Append(iV);
607       //
608       if (aPB[0] == aPB[1]) {
609         break;
610       }
611     }
612   }
613   //
614   // 4. Compute Extra Paves and split Pave blocks by the Extra paves
615   IntersectVE(aMPBLI, Standard_False);
616 }
617 //=======================================================================
618 //function : TreatNewVertices
619 //purpose  : 
620 //=======================================================================
621 void BOPAlgo_PaveFiller::TreatNewVertices
622   (const BOPDS_IndexedDataMapOfShapeCoupleOfPaveBlocks& theMVCPB,
623    TopTools_IndexedDataMapOfShapeListOfShape& myImages)
624 {
625   //
626   // Prepare for intersection
627   TopTools_IndexedDataMapOfShapeReal aVerts;
628   Standard_Integer i, aNbV = theMVCPB.Extent();
629   for (i = 1; i <= aNbV; ++i) {
630     const TopoDS_Shape& aV = theMVCPB.FindKey(i);
631     Standard_Real aTol = theMVCPB.FindFromIndex(i).Tolerance();
632     aVerts.Add(aV, aTol);
633   }
634   //
635   // Perform intersection
636   TopTools_ListOfListOfShape aChains;
637   BOPAlgo_Tools::IntersectVertices(aVerts, myFuzzyValue, aChains);
638   //
639   // Treat the results - make new vertices for each chain
640   TopTools_ListOfListOfShape::Iterator aItC(aChains);
641   for (; aItC.More(); aItC.Next()) {
642     const TopTools_ListOfShape& aLVSD = aItC.Value();
643     //
644     TopoDS_Vertex aVNew;
645     BOPTools_AlgoTools::MakeVertex(aLVSD, aVNew);
646     myImages.Add(aVNew, aLVSD);
647   }
648 }
649 //=======================================================================
650 //function : FillShrunkData
651 //purpose  : 
652 //=======================================================================
653 void BOPAlgo_PaveFiller::FillShrunkData(Handle(BOPDS_PaveBlock)& thePB)
654 {
655   // Vertices
656   Standard_Integer nV1, nV2;
657   thePB->Indices(nV1, nV2);
658   const TopoDS_Vertex& aV1=(*(TopoDS_Vertex *)(&myDS->Shape(nV1))); 
659   const TopoDS_Vertex& aV2=(*(TopoDS_Vertex *)(&myDS->Shape(nV2))); 
660   // Get the edge
661   Standard_Integer nE = -1;
662   if (!thePB->HasEdge(nE))
663   {
664     nE = thePB->OriginalEdge();
665     if (nE < 0)
666       return;
667   }
668
669   const TopoDS_Edge& aE=(*(TopoDS_Edge *)(&myDS->Shape(nE))); 
670   // Range
671   Standard_Real aT1, aT2;
672   thePB->Range(aT1, aT2);
673   //
674   IntTools_ShrunkRange aSR;
675   aSR.SetContext(myContext);
676   aSR.SetData(aE, aT1, aT2, aV1, aV2);
677   aSR.Perform();
678   // Analyze the results of computations
679   AnalyzeShrunkData(thePB, aSR);
680 }
681 //=======================================================================
682 // function: AnalyzeShrunkData
683 // purpose: 
684 //=======================================================================
685 void BOPAlgo_PaveFiller::AnalyzeShrunkData(const Handle(BOPDS_PaveBlock)& thePB,
686                                            const IntTools_ShrunkRange& theSR)
687 {
688   // in case of error treat the warning status
689   Standard_Boolean bWholeEdge = Standard_False;
690   TopoDS_Shape aWarnShape;
691   //
692   if (!theSR.IsDone() || !theSR.IsSplittable()) {
693     Standard_Real aEFirst, aELast, aPBFirst, aPBLast;
694     BRep_Tool::Range(theSR.Edge(), aEFirst, aELast);
695     thePB->Range(aPBFirst, aPBLast);
696     bWholeEdge = !(aPBFirst > aEFirst || aPBLast < aELast);
697     if (bWholeEdge && thePB->OriginalEdge() >= 0) {
698       aWarnShape = theSR.Edge();
699     }
700     else {
701       const TopoDS_Shape& aV1 = myDS->Shape(thePB->Pave1().Index());
702       const TopoDS_Shape& aV2 = myDS->Shape(thePB->Pave2().Index());
703       BRep_Builder().MakeCompound(TopoDS::Compound(aWarnShape));
704       BRep_Builder().Add(aWarnShape, theSR.Edge());
705       BRep_Builder().Add(aWarnShape, aV1);
706       BRep_Builder().Add(aWarnShape, aV2);
707     }
708     //
709     if (!theSR.IsDone()) {
710       if (bWholeEdge)
711         AddWarning (new BOPAlgo_AlertTooSmallEdge (aWarnShape));
712       else
713         AddWarning (new BOPAlgo_AlertBadPositioning (aWarnShape));
714       Standard_Real aTS1, aTS2;
715       theSR.ShrunkRange(aTS1, aTS2);
716       thePB->SetShrunkData(aTS1, aTS2, Bnd_Box(), Standard_False);
717       return;
718     }
719     //
720     if (bWholeEdge)
721       AddWarning (new BOPAlgo_AlertNotSplittableEdge (aWarnShape));
722     else
723       AddWarning (new BOPAlgo_AlertBadPositioning (aWarnShape));
724   }
725   //
726   Standard_Real aTS1, aTS2;
727   theSR.ShrunkRange(aTS1, aTS2);
728   Bnd_Box aBox = theSR.BndBox();
729   aBox.SetGap(aBox.GetGap() + myFuzzyValue / 2.);
730   thePB->SetShrunkData(aTS1, aTS2, aBox, theSR.IsSplittable());
731 }
732 //=======================================================================
733 //function : ForceInterfVE
734 //purpose  : 
735 //=======================================================================
736 Standard_Boolean BOPAlgo_PaveFiller::ForceInterfVE(const Standard_Integer nV,
737                                                    Handle(BOPDS_PaveBlock)& aPB,
738                                                    TColStd_MapOfInteger& theMEdges)
739 {
740   Standard_Integer nE, nVx, nVSD, iFlag;
741   Standard_Real aT, aTolVNew;
742   //
743   nE = aPB->OriginalEdge();
744   //
745   const BOPDS_ShapeInfo& aSIE=myDS->ShapeInfo(nE);
746   if (aSIE.HasSubShape(nV)) {
747     return Standard_True;
748   }
749   //
750   if (myDS->HasInterf(nV, nE)) {
751     return Standard_True;
752   }
753   //
754   if (myDS->HasInterfShapeSubShapes(nV, nE)) {
755     return Standard_True;
756   }
757   //
758   if (aPB->Pave1().Index() == nV || 
759       aPB->Pave2().Index() == nV) {
760     return Standard_True;
761   }
762   //
763   nVx = nV;
764   if (myDS->HasShapeSD(nV, nVSD)) {
765     nVx = nVSD;
766   }
767   //
768   const TopoDS_Vertex& aV = *(TopoDS_Vertex*)&myDS->Shape(nVx);
769   const TopoDS_Edge&   aE = *(TopoDS_Edge*)  &myDS->Shape(nE);
770   //
771   iFlag = myContext->ComputeVE(aV, aE, aT, aTolVNew, myFuzzyValue);
772   if (iFlag == 0 || iFlag == -4) {
773     BOPDS_Pave aPave;
774     //
775     //
776     BOPDS_VectorOfInterfVE& aVEs=myDS->InterfVE();
777     aVEs.SetIncrement(10);
778     // 1
779     BOPDS_InterfVE& aVE=aVEs.Appended();
780     aVE.SetIndices(nV, nE);
781     aVE.SetParameter(aT);
782     // 2
783     myDS->AddInterf(nV, nE);
784     //
785     // 3 update vertex V/E if necessary
786     nVx=UpdateVertex(nV, aTolVNew);
787     // 4
788     if (myDS->IsNewShape(nVx)) {
789       aVE.SetIndexNew(nVx);
790     }
791     // 5 append ext pave to pave block
792     aPave.SetIndex(nVx);
793     aPave.SetParameter(aT);
794     aPB->AppendExtPave(aPave);
795     //
796     theMEdges.Add(nE);
797     //
798     // check for self-interference
799     Standard_Integer iRV = myDS->Rank(nV);
800     if (iRV >= 0 && iRV == myDS->Rank(nE)) {
801       // add warning status
802       TopoDS_Compound aWC;
803       BRep_Builder().MakeCompound(aWC);
804       BRep_Builder().Add(aWC, aV);
805       BRep_Builder().Add(aWC, aE);
806       AddWarning (new BOPAlgo_AlertSelfInterferingShape (aWC));
807     }
808     return Standard_True;
809   }
810   return Standard_False;
811 }
812
813 //=======================================================================
814 //function : GetPBBox
815 //purpose  : 
816 //=======================================================================
817 Standard_Boolean BOPAlgo_PaveFiller::GetPBBox(const TopoDS_Edge& theE,
818                                               const Handle(BOPDS_PaveBlock)& thePB,
819                                               BOPAlgo_DataMapOfPaveBlockBndBox& thePBBox,
820                                               Standard_Real& theFirst,
821                                               Standard_Real& theLast,
822                                               Standard_Real& theSFirst,
823                                               Standard_Real& theSLast,
824                                               Bnd_Box& theBox)
825 {
826   thePB->Range(theFirst, theLast);
827   // check the validity of PB's range
828   Standard_Boolean bValid = theLast - theFirst > Precision::PConfusion();
829   if (!bValid) {
830     return bValid;
831   }
832   //
833   // check shrunk data
834   if (thePB->HasShrunkData()) {
835     Standard_Boolean bIsSplittable;
836     thePB->ShrunkData(theSFirst, theSLast, theBox, bIsSplittable);
837     return bValid;
838   }
839   //
840   theSFirst = theFirst;
841   theSLast = theLast;
842   // check the map
843   if (thePBBox.IsBound(thePB)) {
844     theBox = thePBBox.Find(thePB);
845   }
846   else {
847     // build bounding box
848     BRepAdaptor_Curve aBAC(theE);
849     Standard_Real aTol = BRep_Tool::Tolerance(theE) + Precision::Confusion();
850     BndLib_Add3dCurve::Add(aBAC, theSFirst, theSLast, aTol, theBox);
851     thePBBox.Bind(thePB, theBox);
852   }
853   return bValid;
854 }
855
856 //=======================================================================
857 //function : UpdateVerticesOfCB
858 //purpose  : 
859 //=======================================================================
860 void BOPAlgo_PaveFiller::UpdateVerticesOfCB()
861 {
862   // Fence map to avoid checking same Common block twice
863   BOPDS_MapOfPaveBlock aMPBFence;
864
865   BOPDS_VectorOfListOfPaveBlock& aPBP = myDS->ChangePaveBlocksPool();
866   const Standard_Integer aNbPBP = aPBP.Length();
867   for (Standard_Integer i = 0; i < aNbPBP; ++i)
868   {
869     const BOPDS_ListOfPaveBlock& aLPB = aPBP(i);
870     BOPDS_ListIteratorOfListOfPaveBlock itPB(aLPB);
871     for (; itPB.More(); itPB.Next())
872     {
873       const Handle(BOPDS_CommonBlock)& aCB = myDS->CommonBlock(itPB.Value());
874       if (aCB.IsNull())
875         continue;
876
877       const Handle(BOPDS_PaveBlock)& aPBR = aCB->PaveBlock1();
878       if (!aMPBFence.Add(aPBR))
879         continue;
880
881       Standard_Real aTolCB = aCB->Tolerance();
882       if (aTolCB > 0.)
883       {
884         UpdateVertex(aPBR->Pave1().Index(), aTolCB);
885         UpdateVertex(aPBR->Pave2().Index(), aTolCB);
886       }
887     }
888   }
889 }
890
891 //=======================================================================
892 //function : ForceInterfEE
893 //purpose  : 
894 //=======================================================================
895 void BOPAlgo_PaveFiller::ForceInterfEE()
896 {
897   // Now that we have vertices increased and unified, try to find additional
898   // common blocks among the pairs of edges.
899   // Since all real intersections should have already happened, here we
900   // are interested in common blocks only, thus we need to check only
901   // those pairs of pave blocks with the same bounding vertices.
902
903   Handle(NCollection_IncAllocator) anAlloc = new NCollection_IncAllocator;
904
905   // Initialize pave blocks for all vertices which participated in intersections
906   const Standard_Integer aNbS = myDS->NbSourceShapes();
907   for (Standard_Integer i = 0; i < aNbS; ++i)
908   {
909     const BOPDS_ShapeInfo& aSI = myDS->ShapeInfo(i);
910     if (aSI.ShapeType() == TopAbs_VERTEX)
911     {
912       if (myDS->HasInterf(i))
913         myDS->InitPaveBlocksForVertex(i);
914     }
915   }
916
917   // Fill the connection map from bounding vertices to pave blocks
918   // having those bounding vertices
919   NCollection_IndexedDataMap<BOPDS_Pair,
920                              BOPDS_ListOfPaveBlock,
921                              BOPDS_PairMapHasher> aPBMap(1, anAlloc);
922   // Fence map of pave blocks
923   BOPDS_MapOfPaveBlock aMPBFence(1, anAlloc);
924
925   for (Standard_Integer i = 0; i < aNbS; ++i)
926   {
927     const BOPDS_ShapeInfo& aSI = myDS->ShapeInfo(i);
928     if (aSI.ShapeType() != TopAbs_EDGE)
929       // Not an edge
930       continue;
931
932     if (!aSI.HasReference())
933       // Edge has no pave blocks
934       continue;
935
936     if (aSI.HasFlag())
937       // Degenerated edge
938       continue;
939
940     const BOPDS_ListOfPaveBlock& aLPB = myDS->PaveBlocks(i);
941     BOPDS_ListIteratorOfListOfPaveBlock aItLPB(aLPB);
942     for (; aItLPB.More(); aItLPB.Next())
943     {
944       const Handle(BOPDS_PaveBlock)& aPB = aItLPB.Value();
945       const Handle(BOPDS_PaveBlock)& aPBR = myDS->RealPaveBlock(aPB);
946       if (!aMPBFence.Add(aPBR))
947         continue;
948
949       // Get indices
950       Standard_Integer nV1, nV2;
951       aPBR->Indices(nV1, nV2);
952
953       // Add pave block to a map
954       BOPDS_Pair aPair(nV1, nV2);
955       BOPDS_ListOfPaveBlock *pList = aPBMap.ChangeSeek(aPair);
956       if (!pList)
957         pList = &aPBMap(aPBMap.Add(aPair, BOPDS_ListOfPaveBlock(anAlloc)));
958       pList->Append(aPBR);
959     }
960   }
961
962   Standard_Integer aNbPB = aPBMap.Extent();
963   if (!aNbPB)
964     return;
965
966   const Standard_Boolean bSICheckMode = (myArguments.Extent() == 1);
967
968   // Prepare pave blocks with the same vertices for intersection.
969   BOPAlgo_VectorOfEdgeEdge aVEdgeEdge;
970
971   for (Standard_Integer i = 1; i <= aNbPB; ++i)
972   {
973     const BOPDS_ListOfPaveBlock& aLPB = aPBMap(i);
974     if (aLPB.Extent() < 2)
975       continue;
976
977     const BOPDS_Pair& aPair = aPBMap.FindKey(i);
978     Standard_Integer nV1, nV2;
979     aPair.Indices(nV1, nV2);
980
981     const TopoDS_Vertex& aV1 = TopoDS::Vertex(myDS->Shape(nV1));
982     const TopoDS_Vertex& aV2 = TopoDS::Vertex(myDS->Shape(nV2));
983
984     // Use the max tolerance of vertices as Fuzzy value for intersection of edges.
985     // In the Self-Interference check mode we are interested in real
986     // intersections only, so use only the real tolerance of edges,
987     // no need to use the extended tolerance.
988     Standard_Real aTolAdd = (bSICheckMode ? myFuzzyValue :
989       2 * Max(BRep_Tool::Tolerance(aV1), BRep_Tool::Tolerance(aV2)));
990
991     // All possible pairs combined from the list <aLPB> should be checked
992     BOPDS_ListIteratorOfListOfPaveBlock aItLPB1(aLPB);
993     for (; aItLPB1.More(); aItLPB1.Next())
994     {
995       const Handle(BOPDS_PaveBlock)& aPB1 = aItLPB1.Value();
996       const Handle(BOPDS_CommonBlock)& aCB1 = myDS->CommonBlock(aPB1);
997       const Standard_Integer nE1 = aPB1->OriginalEdge();
998       const Standard_Integer iR1 = myDS->Rank(nE1);
999       const TopoDS_Edge& aE1 = TopoDS::Edge(myDS->Shape(nE1));
1000       Standard_Real aT11, aT12;
1001       aPB1->Range(aT11, aT12);
1002       BRepAdaptor_Curve aBAC1(aE1);
1003       gp_Pnt aPm;
1004       gp_Vec aVTgt1;
1005       aBAC1.D1((aT11 + aT12) * 0.5, aPm, aVTgt1);
1006       if (aVTgt1.SquareMagnitude() < gp::Resolution())
1007         continue;
1008       aVTgt1.Normalize();
1009
1010       BOPDS_ListIteratorOfListOfPaveBlock aItLPB2 = aItLPB1;
1011       for (aItLPB2.Next(); aItLPB2.More(); aItLPB2.Next())
1012       {
1013         const Handle(BOPDS_PaveBlock)& aPB2 = aItLPB2.Value();
1014         const Handle(BOPDS_CommonBlock)& aCB2 = myDS->CommonBlock(aPB2);
1015         const Standard_Integer nE2 = aPB2->OriginalEdge();
1016         const Standard_Integer iR2 = myDS->Rank(nE2);
1017
1018         // Check that the edges came from different arguments
1019         if (iR1 == iR2)
1020         {
1021           // If the sharing of the vertices is not original, but has been acquired
1022           // during the operation, check the coincidence of the edges even if
1023           // they came from the same argument
1024           if ((!myDS->IsNewShape(nV1) && (myDS->Rank(nV1) == iR1)) ||
1025               (!myDS->IsNewShape(nV2) && (myDS->Rank(nV2) == iR2)))
1026             continue;
1027         }
1028
1029         // Check that the Pave blocks do not form the Common block already
1030         if (!aCB1.IsNull() && !aCB2.IsNull())
1031         {
1032           if (aCB1 == aCB2)
1033             continue;
1034         }
1035
1036         const TopoDS_Edge& aE2 = TopoDS::Edge(myDS->Shape(nE2));
1037         Standard_Real aT21, aT22;
1038         aPB2->Range(aT21, aT22);
1039
1040         // Check the angle between edges in the middle point.
1041         // If the angle is more than 25 degrees, do not use the additional
1042         // tolerance, as it may lead to undesired unification of edges
1043         Standard_Boolean bUseAddTol = Standard_True;
1044         {
1045           BRepAdaptor_Curve aBAC2(aE2);
1046           if (aBAC1.GetType() != GeomAbs_Line ||
1047               aBAC2.GetType() != GeomAbs_Line)
1048           {
1049             GeomAPI_ProjectPointOnCurve& aProjPC = myContext->ProjPC(aE2);
1050             aProjPC.Perform(aPm);
1051             if (!aProjPC.NbPoints())
1052               continue;
1053
1054             gp_Pnt aPm2;
1055             gp_Vec aVTgt2;
1056             aBAC2.D1(aProjPC.LowerDistanceParameter(), aPm2, aVTgt2);
1057             if (aVTgt2.SquareMagnitude() < gp::Resolution())
1058               continue;
1059
1060             // The angle should be close to zero
1061             Standard_Real aCos = aVTgt1.Dot (aVTgt2.Normalized());
1062             if (Abs(aCos) < 0.9063)
1063               bUseAddTol = Standard_False;
1064           }
1065         }
1066
1067         // Add pair for intersection
1068         BOPAlgo_EdgeEdge& anEdgeEdge = aVEdgeEdge.Appended();
1069         anEdgeEdge.UseQuickCoincidenceCheck(Standard_True);
1070         anEdgeEdge.SetPaveBlock1(aPB1);
1071         anEdgeEdge.SetPaveBlock2(aPB2);
1072         anEdgeEdge.SetEdge1(aE1, aT11, aT12);
1073         anEdgeEdge.SetEdge2(aE2, aT21, aT22);
1074         anEdgeEdge.SetBoxes (myDS->ShapeInfo(nE1).Box(), myDS->ShapeInfo (nE2).Box());
1075         if (bUseAddTol)
1076         {
1077           anEdgeEdge.SetFuzzyValue(myFuzzyValue + aTolAdd);
1078         }
1079         else
1080         {
1081           anEdgeEdge.SetFuzzyValue(myFuzzyValue);
1082         }
1083         if (myProgressScope != NULL)
1084         {
1085           anEdgeEdge.SetProgressIndicator(*myProgressScope);
1086         }
1087       }
1088     }
1089   }
1090
1091   Standard_Integer aNbPairs = aVEdgeEdge.Length();
1092   if (!aNbPairs)
1093     return;
1094
1095   aPBMap.Clear();
1096   aMPBFence.Clear();
1097   anAlloc->Reset();
1098
1099   // Perform intersection of the found pairs
1100   BOPTools_Parallel::Perform (myRunParallel, aVEdgeEdge);
1101
1102   BOPDS_VectorOfInterfEE& aEEs = myDS->InterfEE();
1103   if (aEEs.IsEmpty())
1104     aEEs.SetIncrement(10);
1105
1106   // Analyze the results of intersection looking for TopAbs_EDGE
1107   // intersection type only.
1108
1109   BOPDS_IndexedDataMapOfPaveBlockListOfPaveBlock aMPBLPB(1, anAlloc);
1110
1111   for (Standard_Integer i = 0; i < aNbPairs; ++i)
1112   {
1113     BOPAlgo_EdgeEdge& anEdgeEdge = aVEdgeEdge(i);
1114     if (!anEdgeEdge.IsDone() || anEdgeEdge.HasErrors())
1115     {
1116       // Warn about failed intersection of sub-shapes
1117       const TopoDS_Shape& aE1 = myDS->Shape(anEdgeEdge.PaveBlock1()->OriginalEdge());
1118       const TopoDS_Shape& aE2 = myDS->Shape(anEdgeEdge.PaveBlock2()->OriginalEdge());
1119       AddIntersectionFailedWarning(aE1, aE2);
1120       continue;
1121     }
1122
1123     const IntTools_SequenceOfCommonPrts& aCParts = anEdgeEdge.CommonParts();
1124     if (aCParts.Length() != 1)
1125       continue;
1126
1127     const IntTools_CommonPrt& aCP = aCParts(1);
1128     if (aCP.Type() != TopAbs_EDGE)
1129       continue;
1130
1131     Handle(BOPDS_PaveBlock) aPB[] = {anEdgeEdge.PaveBlock1(), anEdgeEdge.PaveBlock2()};
1132     const Standard_Integer nE1 = aPB[0]->OriginalEdge();
1133     const Standard_Integer nE2 = aPB[1]->OriginalEdge();
1134
1135     if (myDS->Rank(nE1) == myDS->Rank(nE2))
1136     {
1137       // Add acquired self-interference warning
1138       TopoDS_Compound aWC;
1139       BRep_Builder().MakeCompound(aWC);
1140       BRep_Builder().Add(aWC, myDS->Shape(nE1));
1141       BRep_Builder().Add(aWC, myDS->Shape(nE2));
1142       AddWarning(new BOPAlgo_AlertAcquiredSelfIntersection(aWC));
1143     }
1144
1145     BOPDS_InterfEE& aEE = aEEs.Appended();
1146     aEE.SetIndices(nE1, nE2);
1147     aEE.SetCommonPart(aCP);
1148     myDS->AddInterf(nE1, nE2);
1149
1150     // Fill map for common blocks creation
1151     for (Standard_Integer j = 0; j < 2; ++j)
1152     {
1153       if (myDS->IsCommonBlock(aPB[j]))
1154       {
1155         const BOPDS_ListOfPaveBlock& aLPBCB = myDS->CommonBlock(aPB[j])->PaveBlocks();
1156         BOPDS_ListIteratorOfListOfPaveBlock aItLPB(aLPBCB);
1157         for (; aItLPB.More(); aItLPB.Next())
1158           BOPAlgo_Tools::FillMap<Handle(BOPDS_PaveBlock),
1159                            TColStd_MapTransientHasher>(aPB[j], aItLPB.Value(), aMPBLPB, anAlloc);
1160       }
1161     }
1162     BOPAlgo_Tools::FillMap<Handle(BOPDS_PaveBlock),
1163                            TColStd_MapTransientHasher>(aPB[0], aPB[1], aMPBLPB, anAlloc);
1164   }
1165
1166   // Create new common blocks of coinciding pairs.
1167   BOPAlgo_Tools::PerformCommonBlocks(aMPBLPB, anAlloc, myDS);
1168 }