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