727fc8be403a5bc25df5be4cf474dc056a2fe444
[occt.git] / src / BOPAlgo / BOPAlgo_PaveFiller_7.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 #include <BOPAlgo_PaveFiller.hxx>
19 #include <BOPAlgo_Alerts.hxx>
20 #include <BOPAlgo_SectionAttribute.hxx>
21 #include <BOPAlgo_Tools.hxx>
22 #include <BOPDS_CommonBlock.hxx>
23 #include <BOPDS_Curve.hxx>
24 #include <BOPDS_DS.hxx>
25 #include <BOPDS_FaceInfo.hxx>
26 #include <BOPDS_Interf.hxx>
27 #include <BOPDS_Iterator.hxx>
28 #include <BOPDS_ListOfPaveBlock.hxx>
29 #include <BOPDS_MapOfCommonBlock.hxx>
30 #include <BOPDS_MapOfPair.hxx>
31 #include <BOPDS_MapOfPaveBlock.hxx>
32 #include <BOPDS_Pave.hxx>
33 #include <BOPDS_PaveBlock.hxx>
34 #include <BOPDS_ShapeInfo.hxx>
35 #include <BOPDS_VectorOfCurve.hxx>
36 #include <BOPDS_VectorOfFaceInfo.hxx>
37 #include <BOPDS_VectorOfInterfFF.hxx>
38 #include <BOPDS_VectorOfListOfPaveBlock.hxx>
39 #include <BOPTools_AlgoTools.hxx>
40 #include <BOPTools_AlgoTools2D.hxx>
41 #include <BOPTools_Parallel.hxx>
42 #include <BRepLib.hxx>
43 #include <BRep_Builder.hxx>
44 #include <BRep_Tool.hxx>
45 #include <BRepBndLib.hxx>
46 #include <Geom2d_Curve.hxx>
47 #include <Geom_Curve.hxx>
48 #include <Geom_Plane.hxx>
49 #include <Geom_RectangularTrimmedSurface.hxx>
50 #include <Geom_Surface.hxx>
51 #include <GeomAPI_ProjectPointOnCurve.hxx>
52 #include <GeomAPI_ProjectPointOnSurf.hxx>
53 #include <gp_Pnt.hxx>
54 #include <IntTools_Context.hxx>
55 #include <IntTools_Tools.hxx>
56 #include <NCollection_Vector.hxx>
57 #include <TopExp.hxx>
58 #include <TopExp_Explorer.hxx>
59 #include <TopoDS.hxx>
60 #include <TopoDS_Edge.hxx>
61 #include <TopoDS_Face.hxx>
62 #include <TopoDS_Vertex.hxx>
63 #include <TopTools_IndexedMapOfShape.hxx>
64
65
66 static
67   Standard_Boolean IsBasedOnPlane(const TopoDS_Face& aF);
68
69
70 static void UpdateVertices(const TopoDS_Edge& aE, 
71                            const TopoDS_Face& aF);
72
73 //=======================================================================
74 //class    : BOPAlgo_SplitEdge
75 //purpose  : 
76 //=======================================================================
77 class BOPAlgo_SplitEdge : public BOPAlgo_Algo  {
78  
79  public:
80   DEFINE_STANDARD_ALLOC
81
82   BOPAlgo_SplitEdge() :
83     BOPAlgo_Algo() {
84     myT1=0.;
85     myT2=0.;
86     myTol = 0.;
87   }
88   //
89   virtual ~BOPAlgo_SplitEdge() {
90   }
91   //
92   void SetData(const TopoDS_Edge& aE,
93                const TopoDS_Vertex& aV1,
94                const Standard_Real aT1,
95                const TopoDS_Vertex& aV2,
96                const Standard_Real aT2) {
97     myE=aE;
98     myV1=aV1;
99     myT1=aT1;
100     myV2=aV2;
101     myT2=aT2;
102     myESp=aE;
103   }
104   //
105   void SetPaveBlock(const Handle(BOPDS_PaveBlock)& aPB) {
106     myPB=aPB;
107   }
108   //
109   Handle(BOPDS_PaveBlock)& PaveBlock() {
110     return myPB;
111   }
112   //
113   void SetCommonBlock(const Handle(BOPDS_CommonBlock)& aCB) {
114     myCB=aCB;
115   }
116   //
117   Handle(BOPDS_CommonBlock)& CommonBlock() {
118     return myCB;
119   }
120   //
121   const TopoDS_Edge& SplitEdge() const {
122     return myESp;
123   }
124   //
125   const Bnd_Box Box() {
126     return myBox;
127   }
128   //
129   Standard_Real Tolerance() const {
130     return myTol;
131   }
132   //
133   void SetDS(const BOPDS_PDS theDS) {
134     myDS = theDS;
135   }
136   //
137   void SetContext(const Handle(IntTools_Context)& aContext) {
138     myContext = aContext;
139   }
140   //
141   virtual void Perform () {
142     BOPAlgo_Algo::UserBreak();
143     myTol = BOPAlgo_Tools::ComputeToleranceOfCB(myCB, myDS, myContext);
144     BOPTools_AlgoTools::MakeSplitEdge(myE, 
145                                       myV1, myT1, 
146                                       myV2, myT2, 
147                                       myESp);
148     BRepBndLib::Add(myESp, myBox);
149     myBox.SetGap(myBox.GetGap() + Precision::Confusion());
150   }
151   //
152  protected:
153   // ->
154   TopoDS_Edge myE;
155   TopoDS_Vertex myV1;
156   Standard_Real myT1;
157   TopoDS_Vertex myV2;
158   Standard_Real myT2;
159   // <->
160   Handle(BOPDS_PaveBlock) myPB;
161   Handle(BOPDS_CommonBlock) myCB;
162   // <-
163   TopoDS_Edge myESp;
164   Bnd_Box myBox;
165   Standard_Real myTol;
166   //
167   BOPDS_PDS   myDS;
168   Handle(IntTools_Context) myContext;
169 };
170 //
171 //=======================================================================
172 typedef NCollection_Vector
173   <BOPAlgo_SplitEdge> BOPAlgo_VectorOfSplitEdge; 
174 //
175 typedef BOPTools_ContextFunctor
176   <BOPAlgo_SplitEdge,
177   BOPAlgo_VectorOfSplitEdge,
178   Handle(IntTools_Context),
179   IntTools_Context> BOPAlgo_SplitEdgeFunctor;
180 //
181 typedef BOPTools_ContextCnt
182   <BOPAlgo_SplitEdgeFunctor,
183   BOPAlgo_VectorOfSplitEdge,
184   Handle(IntTools_Context)> BOPAlgo_SplitEdgeCnt;
185 //
186 //=======================================================================
187 //class    : BOPAlgo_MPC
188 //purpose  : 
189 //=======================================================================
190 class BOPAlgo_MPC : public BOPAlgo_Algo  {
191  
192  public:
193   DEFINE_STANDARD_ALLOC
194
195   BOPAlgo_MPC() : 
196     BOPAlgo_Algo(),
197     myFlag(Standard_False) {
198   };
199   //
200   virtual ~BOPAlgo_MPC(){
201   };
202   //
203   void SetEdge(const TopoDS_Edge& aE) {
204     myE=aE;
205   }
206   //
207   const TopoDS_Edge& Edge() const {
208     return myE;
209   }
210   //
211   void SetFace(const TopoDS_Face& aF) {
212     myF=aF;
213   }
214   //
215   const TopoDS_Face& Face() const {
216     return myF;
217   }
218   //
219   void SetFlag(const Standard_Boolean bFlag) {
220     myFlag=bFlag;
221   }
222   //
223   Standard_Boolean Flag() const {
224     return myFlag;
225   }
226   //
227   void SetData(const TopoDS_Edge& aEz,
228                const TopoDS_Vertex& aV1,
229                const Standard_Real aT1,
230                const TopoDS_Vertex& aV2,
231                const Standard_Real aT2) {
232     myEz=aEz;
233     myV1=aV1;
234     myT1=aT1;
235     myV2=aV2;
236     myT2=aT2;
237   }
238   //
239   void SetContext(const Handle(IntTools_Context)& aContext) {
240     myContext=aContext;
241   }
242   //
243   const Handle(IntTools_Context)& Context()const {
244     return myContext;
245   }
246   //
247   virtual void Perform() {
248     try
249     {
250       OCC_CATCH_SIGNALS
251
252       // Check if edge has pcurve. If no then make its copy to avoid data races,
253       // and use it to build pcurve.
254       TopoDS_Edge aCopyE = myE;
255       Standard_Real f, l;
256       Handle(Geom2d_Curve) aC2d = BRep_Tool::CurveOnSurface(aCopyE, myF, f, l);
257       if (aC2d.IsNull())
258       {
259         aCopyE = BOPTools_AlgoTools::CopyEdge(aCopyE);
260
261         Standard_Integer iErr = 1;
262         if (!myEz.IsNull())
263         {
264           // Attach pcurve from the original edge
265           TopoDS_Edge aSpz;
266           BOPTools_AlgoTools::MakeSplitEdge(myEz, myV1, myT1,
267                                             myV2, myT2, aSpz);
268           iErr = BOPTools_AlgoTools2D::AttachExistingPCurve(aSpz,
269                                                             aCopyE, 
270                                                             myF,
271                                                             myContext);
272         }
273         if (iErr)
274           BOPTools_AlgoTools2D::BuildPCurveForEdgeOnFace(aCopyE, myF, myContext);
275
276         myNewC2d = BRep_Tool::CurveOnSurface(aCopyE, myF, f, l);
277         if (myNewC2d.IsNull())
278         {
279           AddError(new BOPAlgo_AlertBuildingPCurveFailed(TopoDS_Shape()));
280           return;
281         }
282         else
283           myNewTol = BRep_Tool::Tolerance(aCopyE);
284       }
285       else
286       {
287         const BRepAdaptor_Surface& aBAS = myContext->SurfaceAdaptor(myF);
288         if (aBAS.IsUPeriodic() || aBAS.IsVPeriodic())
289         {
290           // The curve already exists. Adjust it for periodic cases.
291           BOPTools_AlgoTools2D::AdjustPCurveOnSurf
292             (myContext->SurfaceAdaptor(myF), f, l, aC2d, myNewC2d);
293           if (myNewC2d != aC2d)
294             myNewTol = BRep_Tool::Tolerance(aCopyE);
295           else
296             myNewC2d.Nullify();
297         }
298       }
299
300       if (myFlag) {
301         UpdateVertices(aCopyE, myF);
302       }
303     }
304     catch (Standard_Failure const&)
305     {
306       AddError(new BOPAlgo_AlertBuildingPCurveFailed(TopoDS_Shape()));
307     }
308   }
309
310   const Handle(Geom2d_Curve)& GetNewPCurve() const
311   {
312     return myNewC2d;
313   }
314
315   Standard_Real GetNewTolerance() const
316   {
317     return myNewTol;
318   }
319
320  protected:
321   Standard_Boolean myFlag;
322   TopoDS_Edge myE;
323   TopoDS_Face myF;
324   TopoDS_Edge myEz;
325   TopoDS_Vertex myV1;
326   Standard_Real myT1;
327   TopoDS_Vertex myV2;
328   Standard_Real myT2;
329   Handle(Geom2d_Curve) myNewC2d;
330   Standard_Real myNewTol;
331   //
332   Handle(IntTools_Context) myContext;
333 };
334 //
335 //=======================================================================
336 typedef NCollection_Vector
337   <BOPAlgo_MPC> BOPAlgo_VectorOfMPC; 
338 //
339 typedef BOPTools_ContextFunctor 
340   <BOPAlgo_MPC,
341   BOPAlgo_VectorOfMPC,
342   Handle(IntTools_Context), 
343   IntTools_Context> BOPAlgo_MPCFunctor;
344 //
345 typedef BOPTools_ContextCnt 
346   <BOPAlgo_MPCFunctor,
347   BOPAlgo_VectorOfMPC,
348   Handle(IntTools_Context)> BOPAlgo_MPCCnt;
349 //
350 //=======================================================================
351 //class    : BOPAlgo_BPC
352 //purpose  : 
353 //=======================================================================
354 class BOPAlgo_BPC {
355  public:
356   BOPAlgo_BPC(){
357   };
358   //
359   ~BOPAlgo_BPC(){
360   };
361   //
362   void SetFace(const TopoDS_Face& aF) {
363     myF=aF;
364   }
365   //
366   void SetEdge(const TopoDS_Edge& aE) {
367     myE=aE;
368   }
369   //
370   const TopoDS_Edge& GetEdge() const {
371     return myE;
372   }
373   const TopoDS_Face& GetFace() const {
374     return myF;
375   }
376   const Handle(Geom2d_Curve)& GetCurve2d() const {
377     return myCurve;
378   }
379   Standard_Boolean IsToUpdate() const {
380     return myToUpdate;
381   }
382   //
383   void Perform() {
384     BRepLib::BuildPCurveForEdgeOnPlane(myE, myF, myCurve, myToUpdate);
385   };
386   //
387  protected:
388   TopoDS_Edge myE;
389   TopoDS_Face myF;
390   Handle(Geom2d_Curve) myCurve;
391   Standard_Boolean myToUpdate;
392 };
393 //=======================================================================
394 typedef NCollection_Vector
395   <BOPAlgo_BPC> BOPAlgo_VectorOfBPC; 
396 //
397 typedef BOPTools_Functor 
398   <BOPAlgo_BPC,
399   BOPAlgo_VectorOfBPC> BOPAlgo_BPCFunctor;
400 //
401 typedef BOPTools_Cnt 
402   <BOPAlgo_BPCFunctor,
403   BOPAlgo_VectorOfBPC> BOPAlgo_BPCCnt;
404 //
405 //
406 //=======================================================================
407 // function: MakeSplitEdges
408 // purpose: 
409 //=======================================================================
410 void BOPAlgo_PaveFiller::MakeSplitEdges()
411 {
412   BOPDS_VectorOfListOfPaveBlock& aPBP=myDS->ChangePaveBlocksPool();
413   Standard_Integer aNbPBP = aPBP.Length();
414   if(!aNbPBP) {
415     return;
416   }
417   //
418   Standard_Integer i, nE, nV1, nV2, nSp, aNbVBSE, k;
419   Standard_Real aT1, aT2;
420   BOPDS_ListIteratorOfListOfPaveBlock aItPB;
421   Handle(BOPDS_PaveBlock) aPB;
422   BOPDS_MapOfCommonBlock aMCB(100);
423   TopoDS_Vertex aV1, aV2;
424   TopoDS_Edge aE;
425   BOPAlgo_VectorOfSplitEdge aVBSE;
426   
427   //
428   UpdateCommonBlocksWithSDVertices();
429   //
430   aNbPBP=aPBP.Length();
431   //
432   for (i = 0; i < aNbPBP; ++i)
433   {
434     BOPDS_ListOfPaveBlock& aLPB = aPBP(i);
435     //
436     aItPB.Initialize(aLPB);
437     for (; aItPB.More(); aItPB.Next()) {
438       aPB = aItPB.Value();
439       nE = aPB->OriginalEdge();
440       const BOPDS_ShapeInfo& aSIE = myDS->ShapeInfo(nE);
441       if (aSIE.HasFlag())
442       {
443         // Skip degenerated edges
444         continue;
445       }
446
447       const Handle(BOPDS_CommonBlock)& aCB = myDS->CommonBlock(aPB);
448       Standard_Boolean bCB = !aCB.IsNull();
449       if (bCB && !aMCB.Add(aCB))
450         continue;
451
452       aPB->Indices(nV1, nV2);
453       // Check if it is necessary to make the split of the edge
454       {
455         Standard_Boolean bV1 = myDS->IsNewShape(nV1);
456         Standard_Boolean bV2 = myDS->IsNewShape(nV2);
457
458         Standard_Boolean bToSplit = Standard_True;
459         if (!bV1 && !bV2) // no new vertices here
460         {
461           if (!myNonDestructive || !bCB)
462           {
463             if (bCB)
464             {
465               // Find the edge with these vertices
466               BOPDS_ListIteratorOfListOfPaveBlock it(aCB->PaveBlocks());
467               for (; it.More(); it.Next())
468               {
469                 nE = it.Value()->OriginalEdge();
470                 if (myDS->PaveBlocks(nE).Extent() == 1)
471                   break;
472               }
473               if (it.More())
474               {
475                 // The pave block is found
476                 bToSplit = Standard_False;
477                 aCB->SetRealPaveBlock(it.Value());
478                 aCB->SetEdge(nE);
479                 // Compute tolerance of the common block and update the edge
480                 Standard_Real aTol = BOPAlgo_Tools::ComputeToleranceOfCB(aCB, myDS, myContext);
481                 UpdateEdgeTolerance(nE, aTol);
482               }
483             }
484             else if (aLPB.Extent() == 1)
485             {
486               bToSplit = Standard_False;
487               aPB->SetEdge(nE);
488             }
489             if (!bToSplit)
490               continue;
491           }
492         }
493       }
494
495       // Split the edge
496       if (bCB)
497       {
498         aPB = aCB->PaveBlock1();
499         nE = aPB->OriginalEdge();
500         aPB->Indices(nV1, nV2);
501       }
502       aPB->Range(aT1, aT2);
503       //
504       aE = (*(TopoDS_Edge *)(&myDS->Shape(nE)));
505       aE.Orientation(TopAbs_FORWARD);
506       //
507       aV1 = (*(TopoDS_Vertex *)(&myDS->Shape(nV1)));
508       aV1.Orientation(TopAbs_FORWARD);
509       //
510       aV2 = (*(TopoDS_Vertex *)(&myDS->Shape(nV2)));
511       aV2.Orientation(TopAbs_REVERSED);
512       //
513       BOPAlgo_SplitEdge& aBSE = aVBSE.Appended();
514       //
515       aBSE.SetData(aE, aV1, aT1, aV2, aT2);
516       aBSE.SetPaveBlock(aPB);
517       if (bCB) {
518         aBSE.SetCommonBlock(aCB);
519       }
520       aBSE.SetDS(myDS);
521       aBSE.SetProgressIndicator(myProgressIndicator);
522     } // for (; aItPB.More(); aItPB.Next()) {
523   }  // for (i=0; i<aNbPBP; ++i) {      
524   //
525   aNbVBSE=aVBSE.Length();
526   //======================================================
527   BOPAlgo_SplitEdgeCnt::Perform(myRunParallel, aVBSE, myContext);
528   //======================================================
529   //
530   for (k=0; k < aNbVBSE; ++k) {
531     BOPAlgo_SplitEdge& aBSE=aVBSE(k);
532     //
533     const TopoDS_Edge& aSp=aBSE.SplitEdge();
534     const Bnd_Box& aBox=aBSE.Box();
535     //
536     Handle(BOPDS_PaveBlock) aPBk=aBSE.PaveBlock();
537     Handle(BOPDS_CommonBlock)& aCBk=aBSE.CommonBlock();
538     //
539     BOPDS_ShapeInfo aSI;
540     aSI.SetShapeType(TopAbs_EDGE);
541     aSI.SetShape(aSp);
542     aSI.ChangeBox()=aBox;
543     TColStd_ListOfInteger& aSubShapes = aSI.ChangeSubShapes();
544     aSubShapes.Append(aPBk->Pave1().Index());
545     aSubShapes.Append(aPBk->Pave2().Index());
546     //
547     nSp=myDS->Append(aSI);
548     //
549     if (!aCBk.IsNull()) {
550       UpdateEdgeTolerance(nSp, aBSE.Tolerance());
551       aCBk->SetEdge(nSp);
552     }
553     else {
554       aPBk->SetEdge(nSp);
555     }
556   }
557 }
558
559 //=======================================================================
560 // function: SplitEdge
561 // purpose: 
562 //=======================================================================
563 Standard_Integer BOPAlgo_PaveFiller::SplitEdge(const Standard_Integer nE, 
564                                                const Standard_Integer nV1,
565                                                const Standard_Real aT1, 
566                                                const Standard_Integer nV2, 
567                                                const Standard_Real aT2)
568 {
569   Standard_Integer nSp;
570   TopoDS_Vertex aV1, aV2;
571   TopoDS_Edge aE, aSp;
572   BOPDS_ShapeInfo aSI;
573   //
574   aSI.SetShapeType(TopAbs_EDGE);
575   //
576   aE=(*(TopoDS_Edge *)(&myDS->Shape(nE))); 
577   aE.Orientation(TopAbs_FORWARD);
578   //
579   aV1=(*(TopoDS_Vertex *)(&myDS->Shape(nV1)));
580   aV1.Orientation(TopAbs_FORWARD); 
581   //
582   aV2=(*(TopoDS_Vertex *)(&myDS->Shape(nV2)));
583   aV2.Orientation(TopAbs_REVERSED); 
584   //
585   BOPTools_AlgoTools::MakeSplitEdge(aE, aV1, aT1, aV2, aT2, aSp);  
586   //
587   aSI.SetShape(aSp);
588   //
589   Bnd_Box& aBox=aSI.ChangeBox();
590   BRepBndLib::Add(aSp, aBox);
591   aBox.SetGap(aBox.GetGap() + Precision::Confusion());
592   //
593   nSp=myDS->Append(aSI);
594   return nSp;
595 }
596 //=======================================================================
597 // function: MakePCurves
598 // purpose: 
599 //=======================================================================
600 void BOPAlgo_PaveFiller::MakePCurves()
601 {
602   if (myAvoidBuildPCurve ||
603       (!mySectionAttribute.PCurveOnS1() && !mySectionAttribute.PCurveOnS2()))
604     return;
605   Standard_Boolean bHasPC;
606   Standard_Integer i, nF1, aNbC, k, nE, aNbFF, aNbFI, nEx;
607   Standard_Integer j, aNbPBIn, aNbPBOn;
608   BOPDS_ListIteratorOfListOfPaveBlock aItLPB;
609   TopoDS_Face aF1F, aF2F;
610   BOPAlgo_VectorOfMPC aVMPC;
611   //
612   // 1. Process Common Blocks 
613   const BOPDS_VectorOfFaceInfo& aFIP=myDS->FaceInfoPool();
614   //
615   aNbFI=aFIP.Length();
616   for (i=0; i<aNbFI; ++i) {
617     const BOPDS_FaceInfo& aFI=aFIP(i);
618     nF1=aFI.Index();
619     //
620     aF1F=(*(TopoDS_Face *)(&myDS->Shape(nF1)));
621     aF1F.Orientation(TopAbs_FORWARD);
622     // In
623     const BOPDS_IndexedMapOfPaveBlock& aMPBIn=aFI.PaveBlocksIn();
624     aNbPBIn = aMPBIn.Extent();
625     for (j = 1; j <= aNbPBIn; ++j) {
626       const Handle(BOPDS_PaveBlock)& aPB = aMPBIn(j);
627       nE=aPB->Edge();
628       const TopoDS_Edge& aE=(*(TopoDS_Edge *)(&myDS->Shape(nE)));
629       //
630       BOPAlgo_MPC& aMPC=aVMPC.Appended();
631       aMPC.SetEdge(aE);
632       aMPC.SetFace(aF1F);
633       aMPC.SetProgressIndicator(myProgressIndicator);
634     }
635     //
636     // On
637     const BOPDS_IndexedMapOfPaveBlock& aMPBOn=aFI.PaveBlocksOn();
638     aNbPBOn = aMPBOn.Extent();
639     for (j = 1; j <= aNbPBOn; ++j) {
640       const Handle(BOPDS_PaveBlock)& aPB = aMPBOn(j);
641       nE=aPB->Edge();
642       const TopoDS_Edge& aE=(*(TopoDS_Edge *)(&myDS->Shape(nE)));
643       bHasPC=BOPTools_AlgoTools2D::HasCurveOnSurface (aE, aF1F);
644       if (bHasPC) {
645         continue;
646       }
647       //
648       BOPAlgo_MPC& aMPC = aVMPC.Appended();
649
650       Handle(BOPDS_CommonBlock) aCB = myDS->CommonBlock(aPB);
651
652       if (!aCB.IsNull())
653       {
654         const BOPDS_ListOfPaveBlock& aLPB = aCB->PaveBlocks();
655         if (aLPB.Extent() >= 2)
656         {
657           aItLPB.Initialize(aLPB);
658           for(; aItLPB.More(); aItLPB.Next()) {
659             const Handle(BOPDS_PaveBlock)& aPBx=aItLPB.Value();
660             if (aPBx==aPB) {
661               continue;
662             }
663             //
664             nEx=aPBx->OriginalEdge();
665             const TopoDS_Edge& aEx=(*(TopoDS_Edge *)(&myDS->Shape(nEx))); 
666             bHasPC=BOPTools_AlgoTools2D::HasCurveOnSurface (aEx, aF1F);
667             if (!bHasPC) {
668               continue;
669             }
670             //
671             Standard_Integer nV1x, nV2x;
672             Standard_Real aT1x, aT2x;
673             TopoDS_Vertex aV1x, aV2x;
674             TopoDS_Edge aEz;
675             //
676             aEz=aEx;
677             aEz.Orientation(TopAbs_FORWARD);
678             //
679             aPBx->Indices(nV1x, nV2x);
680             aPBx->Range(aT1x, aT2x);
681             //
682             aV1x=(*(TopoDS_Vertex *)(&myDS->Shape(nV1x)));
683             aV1x.Orientation(TopAbs_FORWARD); 
684             //
685             aV2x=(*(TopoDS_Vertex *)(&myDS->Shape(nV2x)));
686             aV2x.Orientation(TopAbs_REVERSED); 
687             //
688             aMPC.SetData(aEz, aV1x, aT1x, aV2x, aT2x);
689             //
690             break;
691           }
692         }
693       }
694
695       aMPC.SetEdge(aE);
696       aMPC.SetFace(aF1F);
697       aMPC.SetProgressIndicator(myProgressIndicator);
698     }
699   }// for (i=0; i<aNbFI; ++i) {
700   //
701   // 2. Process section edges. P-curves on them must already be computed.
702   // However, we must provide the call to UpdateVertices.
703   Standard_Boolean bPCurveOnS[2];
704   bPCurveOnS[0]=mySectionAttribute.PCurveOnS1();
705   bPCurveOnS[1]=mySectionAttribute.PCurveOnS2();
706   //
707   if (bPCurveOnS[0] || bPCurveOnS[1]) {
708     // container to remember already added edge-face pairs
709     BOPDS_MapOfPair anEFPairs;
710     BOPDS_VectorOfInterfFF& aFFs=myDS->InterfFF();
711     aNbFF=aFFs.Length();
712     for (i=0; i<aNbFF; ++i) {
713       const BOPDS_InterfFF& aFF=aFFs(i);
714       const BOPDS_VectorOfCurve& aVNC = aFF.Curves();
715       aNbC = aVNC.Length();
716       if (aNbC == 0)
717         continue;
718       Standard_Integer nF[2];
719       aFF.Indices(nF[0], nF[1]);
720       //
721       TopoDS_Face aFf[2];
722       aFf[0] = (*(TopoDS_Face *)(&myDS->Shape(nF[0])));
723       aFf[0].Orientation(TopAbs_FORWARD);
724       //
725       aFf[1]=(*(TopoDS_Face *)(&myDS->Shape(nF[1])));
726       aFf[1].Orientation(TopAbs_FORWARD);
727       //
728       for (k=0; k<aNbC; ++k)
729       {
730         const BOPDS_Curve& aNC=aVNC(k);
731         const BOPDS_ListOfPaveBlock& aLPB=aNC.PaveBlocks();
732         aItLPB.Initialize(aLPB);
733         for(; aItLPB.More(); aItLPB.Next())
734         {
735           const Handle(BOPDS_PaveBlock)& aPB=aItLPB.Value();
736           nE=aPB->Edge();
737           const TopoDS_Edge& aE=(*(TopoDS_Edge *)(&myDS->Shape(nE))); 
738           //
739           for (Standard_Integer m = 0; m<2; ++m)
740           {
741             if (bPCurveOnS[m] && anEFPairs.Add(BOPDS_Pair(nE, nF[m])))
742             {
743               BOPAlgo_MPC& aMPC = aVMPC.Appended();
744               aMPC.SetEdge(aE);
745               aMPC.SetFace(aFf[m]);
746               aMPC.SetFlag(Standard_True);
747               aMPC.SetProgressIndicator(myProgressIndicator);
748             }
749           }
750         }
751       }
752     }// for (i=0; i<aNbFF; ++i) {
753   }//if (bPCurveOnS1 || bPCurveOnS2 ) {
754   //
755   //======================================================
756   BOPAlgo_MPCCnt::Perform(myRunParallel, aVMPC, myContext);
757   //======================================================
758
759   // Add warnings of the failed projections and update edges with new pcurves
760   Standard_Integer aNb = aVMPC.Length();
761   for (i = 0; i < aNb; ++i)
762   {
763     const BOPAlgo_MPC& aMPC = aVMPC(i);
764     if (aMPC.HasErrors())
765     {
766       TopoDS_Compound aWC;
767       BRep_Builder().MakeCompound(aWC);
768       BRep_Builder().Add(aWC, aMPC.Edge());
769       BRep_Builder().Add(aWC, aMPC.Face());
770       AddWarning(new BOPAlgo_AlertBuildingPCurveFailed(aWC));
771     }
772     else
773     {
774       const Handle(Geom2d_Curve)& aNewPC = aMPC.GetNewPCurve();
775       // if aNewPC is null we do not need to update the edge because it already contains
776       // valid p-curve, and only vertices have been updated.
777       if (!aNewPC.IsNull())
778         BRep_Builder().UpdateEdge(aMPC.Edge(), aNewPC, aMPC.Face(), aMPC.GetNewTolerance());
779     }
780   }
781 }
782 //=======================================================================
783 //function : UpdateVertices
784 //purpose  : update tolerances of vertices comparing extremities of
785 //           3d and 2d curves
786 //=======================================================================
787 void UpdateVertices(const TopoDS_Edge& aE, 
788                     const TopoDS_Face& aF)
789 {
790   Standard_Integer j;
791   Standard_Real aT[2], aUx, aVx, aTolV2, aD2, aD;
792   gp_Pnt aP3D, aP3Dx;
793   gp_Pnt2d aP2Dx;
794   Handle(Geom_Surface) aS;
795   Handle(Geom_Curve) aC3D;
796   Handle(Geom2d_Curve) aC2D;
797   TopoDS_Edge aEf;
798   TopoDS_Vertex aV[2];
799   BRep_Builder aBB;
800   //
801   aEf=aE;
802   aEf.Orientation(TopAbs_FORWARD);
803   //
804   TopExp::Vertices(aEf, aV[0], aV[1]);
805   //
806   aS=BRep_Tool::Surface(aF);
807   aC3D=BRep_Tool::Curve(aEf, aT[0], aT[1]);
808   aC2D=BRep_Tool::CurveOnSurface(aEf, aF, aT[0], aT[1]);
809   //
810   for (j=0; j<2; ++j) {
811     aTolV2=BRep_Tool::Tolerance(aV[j]);
812     aTolV2=aTolV2*aTolV2;
813     //
814     aC3D->D0(aT[j], aP3D);
815     aC2D->D0(aT[j], aP2Dx);
816     aP2Dx.Coord(aUx, aVx);
817     aS->D0(aUx, aVx, aP3Dx);
818     aD2=aP3D.SquareDistance(aP3Dx);
819     if (aD2>aTolV2) {
820       aD=sqrt(aD2);
821       aBB.UpdateVertex(aV[j], aD);
822     }
823   }
824 }
825 //=======================================================================
826 // function: Prepare
827 // purpose: 
828 //=======================================================================
829 void BOPAlgo_PaveFiller::Prepare()
830 {
831   if (myNonDestructive) {
832     // do not allow storing pcurves in original edges if non-destructive mode is on
833     return;
834   }
835   TopAbs_ShapeEnum aType[] = {
836     TopAbs_VERTEX,
837     TopAbs_EDGE,
838     TopAbs_FACE
839   };
840   Standard_Boolean bIsBasedOnPlane;
841   Standard_Integer i, aNb, n1, nF, aNbF;
842   TopExp_Explorer aExp;
843   TopTools_IndexedMapOfShape aMF;
844   //
845   aNb=3;
846   for(i=0; i<aNb; ++i) {
847     myIterator->Initialize(aType[i], aType[2]);
848     for (; myIterator->More(); myIterator->Next()) {
849       myIterator->Value(n1, nF);
850       const TopoDS_Face& aF=(*(TopoDS_Face *)(&myDS->Shape(nF))); 
851       //
852       bIsBasedOnPlane=IsBasedOnPlane(aF);
853       if (bIsBasedOnPlane) {
854         aMF.Add(aF);
855       }
856     }
857   }
858   //
859   aNbF = aMF.Extent();
860   if (!aNbF) {
861     return;
862   }
863   //
864   // Build pcurves of edges on planes; first collect pairs edge-face.
865   BOPAlgo_VectorOfBPC aVBPC;
866   //
867   for (i = 1; i <= aNbF; ++i) {
868     const TopoDS_Face& aF = *(TopoDS_Face*)&aMF(i);
869     aExp.Init(aF, aType[1]);
870     for (; aExp.More(); aExp.Next()) {
871       const TopoDS_Edge& aE=*((TopoDS_Edge *)&aExp.Current());
872       BOPAlgo_BPC& aBPC=aVBPC.Appended();
873       aBPC.SetEdge(aE);
874       aBPC.SetFace(aF);
875     }
876   }
877   //
878   //======================================================
879   BOPAlgo_BPCCnt::Perform(myRunParallel, aVBPC);
880   //======================================================
881
882   // pcurves are built, and now update edges
883   BRep_Builder aBB;
884   TopoDS_Edge E;
885   for (i = 0; i < aVBPC.Length(); i++) {
886     const BOPAlgo_BPC& aBPC=aVBPC(i);
887     if (aBPC.IsToUpdate()) {
888       Standard_Real aTolE = BRep_Tool::Tolerance(aBPC.GetEdge());
889       aBB.UpdateEdge(aBPC.GetEdge(), aBPC.GetCurve2d(), aBPC.GetFace(), aTolE);
890     }
891   }
892 }
893 //=======================================================================
894 //function : IsBasedOnPlane
895 //purpose  : 
896 //=======================================================================
897 Standard_Boolean IsBasedOnPlane(const TopoDS_Face& aF)
898 {
899   TopLoc_Location aLoc; 
900   Handle(Geom_RectangularTrimmedSurface) aGRTS;
901   Handle(Geom_Plane) aGP;
902   
903   const Handle(Geom_Surface)& aS = BRep_Tool::Surface(aF, aLoc);
904   aGRTS = Handle(Geom_RectangularTrimmedSurface)::DownCast(aS);
905   if(!aGRTS.IsNull()) {
906     aGP = Handle(Geom_Plane)::DownCast(aGRTS->BasisSurface());
907   }
908   else {
909     aGP = Handle(Geom_Plane)::DownCast(aS);
910   }
911   //
912   return (!aGP.IsNull()); 
913 }