0024157: Parallelization of assembly part of BO
[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.ixx>
19
20 #include <NCollection_IncAllocator.hxx>
21
22 #include <Geom_RectangularTrimmedSurface.hxx>
23 #include <Geom_Plane.hxx>
24 #include <Geom_Surface.hxx>
25 #include <Geom_RectangularTrimmedSurface.hxx>
26
27 #include <TopoDS_Vertex.hxx>
28 #include <TopoDS_Edge.hxx>
29 #include <TopoDS_Face.hxx>
30
31 #include <BRepBndLib.hxx>
32
33 #include <BRep_Tool.hxx>
34 #include <BRep_Builder.hxx>
35
36 #include <TopExp.hxx>
37 #include <TopExp_Explorer.hxx>
38
39 #include <Geom_Curve.hxx>
40 #include <Geom_Surface.hxx>
41 #include <Geom2d_Curve.hxx>
42
43 #include <BOPCol_NCVector.hxx>
44 #include <BOPCol_TBB.hxx>
45 #include <BOPCol_MapOfShape.hxx>
46
47 #include <BOPDS_VectorOfListOfPaveBlock.hxx>
48 #include <BOPDS_ListOfPaveBlock.hxx>
49 #include <BOPDS_PaveBlock.hxx>
50 #include <BOPDS_CommonBlock.hxx>
51 #include <BOPDS_Pave.hxx>
52 #include <BOPDS_ShapeInfo.hxx>
53 #include <BOPDS_MapOfPaveBlock.hxx>
54 #include <BOPDS_VectorOfInterfFF.hxx>
55 #include <BOPDS_Interf.hxx>
56 #include <BOPDS_VectorOfCurve.hxx>
57 #include <BOPDS_VectorOfFaceInfo.hxx>
58 #include <BOPDS_FaceInfo.hxx>
59 #include <BOPDS_MapOfPaveBlock.hxx>
60 #include <BOPDS_Curve.hxx>
61 #include <BOPDS_Iterator.hxx>
62
63 #include <BOPTools_AlgoTools.hxx>
64 #include <BOPTools_AlgoTools2D.hxx>
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 {
78  public:
79   BOPAlgo_SplitEdge() {
80     myT1=0.;
81     myT2=0.;
82   }
83   //
84   ~BOPAlgo_SplitEdge() {
85   }
86   //
87   void SetData(const TopoDS_Edge& aE,
88                const TopoDS_Vertex& aV1,
89                const Standard_Real aT1,
90                const TopoDS_Vertex& aV2,
91                const Standard_Real aT2) {
92     myE=aE;
93     myV1=aV1;
94     myT1=aT1;
95     myV2=aV2;
96     myT2=aT2;
97     myESp=aE;
98   }
99   //
100   void SetPaveBlock(const Handle(BOPDS_PaveBlock)& aPB) {
101     myPB=aPB;
102   }
103   //
104   Handle(BOPDS_PaveBlock)& PaveBlock() {
105     return myPB;
106   }
107   //
108   void SetCommonBlock(const Handle(BOPDS_CommonBlock)& aCB) {
109     myCB=aCB;
110   }
111   //
112   Handle(BOPDS_CommonBlock)& CommonBlock() {
113     return myCB;
114   }
115   //
116   const TopoDS_Edge& SplitEdge() const {
117     return myESp;
118   }
119   //
120   const Bnd_Box Box() {
121     return myBox;
122   }
123   //
124   void Perform () {
125     BOPTools_AlgoTools::MakeSplitEdge(myE, 
126                                       myV1, myT1, 
127                                       myV2, myT2, 
128                                       myESp);
129     BRepBndLib::Add(myESp, myBox);  
130   }
131   //
132  protected:
133   // ->
134   TopoDS_Edge myE;
135   TopoDS_Vertex myV1;
136   Standard_Real myT1;
137   TopoDS_Vertex myV2;
138   Standard_Real myT2;
139   // <->
140   Handle(BOPDS_PaveBlock) myPB;
141   Handle(BOPDS_CommonBlock) myCB;
142   // <-
143   TopoDS_Edge myESp;
144   Bnd_Box myBox;
145 };
146 //
147 //=======================================================================
148 typedef BOPCol_NCVector
149   <BOPAlgo_SplitEdge> BOPAlgo_VectorOfSplitEdge; 
150 //
151 typedef BOPCol_TBBFunctor 
152   <BOPAlgo_SplitEdge,
153   BOPAlgo_VectorOfSplitEdge> BOPAlgo_SplitEdgeFunctor;
154 //
155 typedef BOPCol_TBBCnt 
156   <BOPAlgo_SplitEdgeFunctor,
157   BOPAlgo_VectorOfSplitEdge> BOPAlgo_SplitEdgeCnt;
158 //
159 //=======================================================================
160 //class    : BOPAlgo_MPC
161 //purpose  : 
162 //=======================================================================
163 class BOPAlgo_MPC {
164  public:
165   BOPAlgo_MPC() 
166     : myFlag(Standard_False) {
167   };
168   //
169   ~BOPAlgo_MPC(){
170   };
171   //
172   void SetEdge(const TopoDS_Edge& aE) {
173     myE=aE;
174   }
175   //
176   const TopoDS_Edge& Edge() const {
177     return myE;
178   }
179   //
180   void SetFace(const TopoDS_Face& aF) {
181     myF=aF;
182   }
183   //
184   const TopoDS_Face& Face() const {
185     return myF;
186   }
187   //
188   void SetFlag(const Standard_Boolean bFlag) {
189     myFlag=bFlag;
190   }
191   //
192   Standard_Boolean Flag() const {
193     return myFlag;
194   }
195   //
196   void Perform() {
197     BOPTools_AlgoTools2D::BuildPCurveForEdgeOnFace(myE, myF);
198     if (myFlag) {
199       UpdateVertices(myE, myF);
200     }
201   }
202   //
203  protected:
204   Standard_Boolean myFlag;
205   TopoDS_Edge myE;
206   TopoDS_Face myF;
207 };
208 //
209 //=======================================================================
210 typedef BOPCol_NCVector
211   <BOPAlgo_MPC> BOPAlgo_VectorOfMPC; 
212 //
213 typedef BOPCol_TBBFunctor 
214   <BOPAlgo_MPC,
215   BOPAlgo_VectorOfMPC> BOPAlgo_MPCFunctor;
216 //
217 typedef BOPCol_TBBCnt 
218   <BOPAlgo_MPCFunctor,
219   BOPAlgo_VectorOfMPC> BOPAlgo_MPCCnt;
220 //
221 //=======================================================================
222 //class    : BOPAlgo_BPC
223 //purpose  : 
224 //=======================================================================
225 class BOPAlgo_BPC {
226  public:
227   BOPAlgo_BPC(){
228   };
229   //
230   ~BOPAlgo_BPC(){
231   };
232   //
233   void SetFace(const TopoDS_Face& aF) {
234     myF=aF;
235   }
236   //
237   void SetEdge(const TopoDS_Edge& aE) {
238     myE=aE;
239   }
240   //
241   void Perform() {
242     BOPTools_AlgoTools2D::BuildPCurveForEdgeOnPlane (myE, myF);
243   };
244   //
245  protected:
246   TopoDS_Edge myE;
247   TopoDS_Face myF;
248 };
249 //=======================================================================
250 typedef BOPCol_NCVector
251   <BOPAlgo_BPC> BOPAlgo_VectorOfBPC; 
252 //
253 typedef BOPCol_TBBFunctor 
254   <BOPAlgo_BPC,
255   BOPAlgo_VectorOfBPC> BOPAlgo_BPCFunctor;
256 //
257 typedef BOPCol_TBBCnt 
258   <BOPAlgo_BPCFunctor,
259   BOPAlgo_VectorOfBPC> BOPAlgo_BPCCnt;
260 //
261 //
262 //=======================================================================
263 // function: MakeSplitEdges
264 // purpose: 
265 //=======================================================================
266 void BOPAlgo_PaveFiller::MakeSplitEdges()
267 {
268   Standard_Integer aNbPBP;
269   //
270   myErrorStatus=0;
271   //
272   BOPDS_VectorOfListOfPaveBlock& aPBP=myDS->ChangePaveBlocksPool();
273   aNbPBP=aPBP.Extent();
274   if(!aNbPBP) {
275     return;
276   }
277   //
278   Standard_Boolean bCB, bV1, bV2;
279   Standard_Integer i, nE, nV1, nV2, nSp, aNbPB, aNbVBSE, k;
280   Standard_Real aT1, aT2;
281   BOPDS_ListIteratorOfListOfPaveBlock aItPB, aItPBCB;
282   Handle(BOPDS_PaveBlock) aPB;
283   BOPDS_MapOfPaveBlock aMPB(100);
284   TopoDS_Vertex aV1, aV2;
285   TopoDS_Edge aE;
286   BOPAlgo_VectorOfSplitEdge aVBSE;
287   
288   //
289   for (i=0; i<aNbPBP; ++i) {
290     BOPDS_ListOfPaveBlock& aLPB=aPBP(i);
291     //
292     aNbPB=aLPB.Extent();
293     if (aNbPB==1) {
294       aPB=aLPB.First();
295       aPB->Indices(nV1, nV2);
296       bV1=myDS->IsNewShape(nV1);
297       bV2=myDS->IsNewShape(nV2);
298       //
299       if (!(bV1 || bV2)) {
300         nE=aPB->OriginalEdge();
301         aPB->SetEdge(nE);
302         continue;
303       }
304     }
305     //
306     aItPB.Initialize(aLPB);
307     for (; aItPB.More(); aItPB.Next()) {
308       aPB=aItPB.Value();
309       const Handle(BOPDS_CommonBlock)& aCB=myDS->CommonBlock(aPB);
310       bCB=!aCB.IsNull();
311       if (bCB) {
312         myDS->SortPaveBlocks(aCB);
313         aPB=aCB->PaveBlock1();
314       }
315       //
316       if (aMPB.Add(aPB)) {
317         nE=aPB->OriginalEdge();
318         aPB->Indices(nV1, nV2);
319         aPB->Range(aT1, aT2);
320         //
321         aE=(*(TopoDS_Edge *)(&myDS->Shape(nE))); 
322         aE.Orientation(TopAbs_FORWARD);
323         //
324         aV1=(*(TopoDS_Vertex *)(&myDS->Shape(nV1)));
325         aV1.Orientation(TopAbs_FORWARD); 
326         //
327         aV2=(*(TopoDS_Vertex *)(&myDS->Shape(nV2)));
328         aV2.Orientation(TopAbs_REVERSED); 
329         //
330         BOPAlgo_SplitEdge& aBSE=aVBSE.Append1();
331         //
332         aBSE.SetData(aE, aV1, aT1, aV2, aT2);
333         aBSE.SetPaveBlock(aPB);
334         if (bCB) {
335           aBSE.SetCommonBlock(aCB);
336         }
337       }
338     } // for (; aItPB.More(); aItPB.Next()) {
339   }  // for (i=0; i<aNbPBP; ++i) {      
340   //
341   aNbVBSE=aVBSE.Extent();
342   //======================================================
343   BOPAlgo_SplitEdgeCnt::Perform(myRunParallel, aVBSE);
344   //======================================================
345   //
346   BOPDS_ShapeInfo aSI;
347   //
348   aSI.SetShapeType(TopAbs_EDGE);
349   //
350   for (k=0; k < aNbVBSE; ++k) {
351     BOPAlgo_SplitEdge& aBSE=aVBSE(k);
352     //
353     const TopoDS_Edge& aSp=aBSE.SplitEdge();
354     const Bnd_Box& aBox=aBSE.Box();
355     //
356     Handle(BOPDS_PaveBlock) aPBk=aBSE.PaveBlock();
357     Handle(BOPDS_CommonBlock)& aCBk=aBSE.CommonBlock();
358     //
359     aSI.SetShape(aSp);
360     aSI.ChangeBox()=aBox;
361     //
362     nSp=myDS->Append(aSI);
363     //
364     if (!aCBk.IsNull()) {
365       aCBk->SetEdge(nSp);
366     }
367     else {
368       aPBk->SetEdge(nSp);
369     }
370   }
371 }
372 //=======================================================================
373 // function: SplitEdge
374 // purpose: 
375 //=======================================================================
376 Standard_Integer BOPAlgo_PaveFiller::SplitEdge(const Standard_Integer nE, 
377                                                const Standard_Integer nV1,
378                                                const Standard_Real aT1, 
379                                                const Standard_Integer nV2, 
380                                                const Standard_Real aT2)
381 {
382   Standard_Integer nSp;
383   TopoDS_Vertex aV1, aV2;
384   TopoDS_Edge aE, aSp;
385   BOPDS_ShapeInfo aSI;
386   //
387   aSI.SetShapeType(TopAbs_EDGE);
388   //
389   aE=(*(TopoDS_Edge *)(&myDS->Shape(nE))); 
390   aE.Orientation(TopAbs_FORWARD);
391   //
392   aV1=(*(TopoDS_Vertex *)(&myDS->Shape(nV1)));
393   aV1.Orientation(TopAbs_FORWARD); 
394   //
395   aV2=(*(TopoDS_Vertex *)(&myDS->Shape(nV2)));
396   aV2.Orientation(TopAbs_REVERSED); 
397   //
398   BOPTools_AlgoTools::MakeSplitEdge(aE, aV1, aT1, aV2, aT2, aSp);  
399   //
400   aSI.SetShape(aSp);
401   //
402   Bnd_Box& aBox=aSI.ChangeBox();
403   BRepBndLib::Add(aSp, aBox);
404   //
405   nSp=myDS->Append(aSI);
406   return nSp;
407 }
408 //=======================================================================
409 // function: MakePCurves
410 // purpose: 
411 //=======================================================================
412 void BOPAlgo_PaveFiller::MakePCurves()
413 {
414   
415   Standard_Integer i, nF1, nF2, aNbC, k, nE, aNbFF, aNbFI;
416   BOPDS_ListIteratorOfListOfPaveBlock aItLPB;
417   BOPDS_MapIteratorOfMapOfPaveBlock aItMPB;
418   TopoDS_Face aF1F, aF2F;
419   BOPAlgo_VectorOfMPC aVMPC;
420   //
421   myErrorStatus=0;
422   //
423   // 1. Process Common Blocks 
424   const BOPDS_VectorOfFaceInfo& aFIP=myDS->FaceInfoPool();
425   //
426   aNbFI=aFIP.Extent();
427   for (i=0; i<aNbFI; ++i) {
428     const BOPDS_FaceInfo& aFI=aFIP(i);
429     nF1=aFI.Index();
430     //
431     aF1F=(*(TopoDS_Face *)(&myDS->Shape(nF1)));
432     aF1F.Orientation(TopAbs_FORWARD);
433     // In
434     const BOPDS_IndexedMapOfPaveBlock& aMPBIn=aFI.PaveBlocksIn();
435     aItMPB.Initialize(aMPBIn);
436     for(; aItMPB.More(); aItMPB.Next()) {
437       const Handle(BOPDS_PaveBlock)& aPB=aItMPB.Value();
438       nE=aPB->Edge();
439       const TopoDS_Edge& aE=(*(TopoDS_Edge *)(&myDS->Shape(nE)));
440       //
441       BOPAlgo_MPC& aMPC=aVMPC.Append1();
442       aMPC.SetEdge(aE);
443       aMPC.SetFace(aF1F);
444     }
445     //
446     // On
447     const BOPDS_IndexedMapOfPaveBlock& aMPBOn=aFI.PaveBlocksOn();
448     aItMPB.Initialize(aMPBOn);
449     for(; aItMPB.More(); aItMPB.Next()) {
450       const Handle(BOPDS_PaveBlock)& aPB=aItMPB.Value();
451       if (myDS->IsCommonBlockOnEdge(aPB)) {
452         nE=aPB->Edge();
453         const TopoDS_Edge& aE=(*(TopoDS_Edge *)(&myDS->Shape(nE)));
454         //
455         BOPAlgo_MPC& aMPC=aVMPC.Append1();
456         aMPC.SetEdge(aE);
457         aMPC.SetFace(aF1F);
458       }
459     }
460   }// for (i=0; i<aNbFI; ++i) {
461   //
462   // 2. Process section edges
463   Standard_Boolean bPCurveOnS[2];
464   Standard_Integer m;
465   TopoDS_Face aFf[2];
466   //
467   bPCurveOnS[0]=mySectionAttribute.PCurveOnS1();
468   bPCurveOnS[1]=mySectionAttribute.PCurveOnS2();
469   //
470   if (bPCurveOnS[0] || bPCurveOnS[1]) {
471     BOPDS_VectorOfInterfFF& aFFs=myDS->InterfFF();
472     aNbFF=aFFs.Extent();
473     for (i=0; i<aNbFF; ++i) {
474       const BOPDS_InterfFF& aFF=aFFs(i);
475       aFF.Indices(nF1, nF2);
476       //
477       aFf[0]=(*(TopoDS_Face *)(&myDS->Shape(nF1)));
478       aFf[0].Orientation(TopAbs_FORWARD);
479       //
480       aFf[1]=(*(TopoDS_Face *)(&myDS->Shape(nF2)));
481       aFf[1].Orientation(TopAbs_FORWARD);
482       //
483       const BOPDS_VectorOfCurve& aVNC=aFF.Curves();
484       aNbC=aVNC.Extent();
485       for (k=0; k<aNbC; ++k) {
486         const BOPDS_Curve& aNC=aVNC(k);
487         const BOPDS_ListOfPaveBlock& aLPB=aNC.PaveBlocks();
488         aItLPB.Initialize(aLPB);
489         for(; aItLPB.More(); aItLPB.Next()) {
490           const Handle(BOPDS_PaveBlock)& aPB=aItLPB.Value();
491           nE=aPB->Edge();
492           const TopoDS_Edge& aE=(*(TopoDS_Edge *)(&myDS->Shape(nE))); 
493           //
494           for (m=0; m<2; ++m) {
495             if (bPCurveOnS[m]) {
496               BOPAlgo_MPC& aMPC=aVMPC.Append1();
497               aMPC.SetEdge(aE);
498               aMPC.SetFace(aFf[m]);
499               aMPC.SetFlag(bPCurveOnS[m]);
500             }
501           }
502         }
503       }
504     }// for (i=0; i<aNbFF; ++i) {
505   }//if (bPCurveOnS1 || bPCurveOnS2 ) {
506   //
507   //======================================================
508   BOPAlgo_MPCCnt::Perform(myRunParallel, aVMPC);
509   //======================================================
510 }
511 //=======================================================================
512 // function: RefineFaceInfoOn
513 // purpose: 
514 //=======================================================================
515 void BOPAlgo_PaveFiller::RefineFaceInfoOn() 
516 {
517   Standard_Integer aNbPBP;
518   //
519   myErrorStatus=0;
520   //
521   BOPDS_VectorOfListOfPaveBlock& aPBP=myDS->ChangePaveBlocksPool();
522   aNbPBP=aPBP.Extent();
523   if(!aNbPBP) {
524     return;
525   }
526   //
527   Standard_Boolean bV1, bV2;
528   Standard_Integer i, nV1, nV2, aNbPB;
529   Handle(BOPDS_PaveBlock) aPB;
530   //
531   for (i=0; i<aNbPBP; ++i) {
532     BOPDS_ListOfPaveBlock& aLPB=aPBP(i);
533     //
534     aNbPB=aLPB.Extent();
535     if (aNbPB==1) {
536       aPB=aLPB.First();
537       aPB->Indices(nV1, nV2);
538       bV1=myDS->IsNewShape(nV1);
539       bV2=myDS->IsNewShape(nV2);
540       //
541       if (!(bV1 || bV2)) {
542         if (!myDS->IsCommonBlock(aPB)) {
543           // the PB seems to be untouced
544           aLPB.Clear();
545           continue;
546         }
547       }//if (!(bV1 || bV2)) {
548     }//if (aNbPB==1) {
549   }//for (i=0; i<aNbPBP; ++i) {
550   myDS->RefineFaceInfoOn();
551 }
552 //=======================================================================
553 //function : UpdateVertices
554 //purpose  : update tolerances of vertices comparing extremities of
555 //           3d and 2d curves
556 //=======================================================================
557 void UpdateVertices(const TopoDS_Edge& aE, 
558                     const TopoDS_Face& aF)
559 {
560   Standard_Integer j;
561   Standard_Real aT[2], aUx, aVx, aTolV2, aD2, aD;
562   gp_Pnt aP3D, aP3Dx;
563   gp_Pnt2d aP2Dx;
564   Handle(Geom_Surface) aS;
565   Handle(Geom_Curve) aC3D;
566   Handle(Geom2d_Curve) aC2D;
567   TopoDS_Edge aEf;
568   TopoDS_Vertex aV[2];
569   BRep_Builder aBB;
570   //
571   aEf=aE;
572   aEf.Orientation(TopAbs_FORWARD);
573   //
574   TopExp::Vertices(aEf, aV[0], aV[1]);
575   //
576   aS=BRep_Tool::Surface(aF);
577   aC3D=BRep_Tool::Curve(aEf, aT[0], aT[1]);
578   aC2D=BRep_Tool::CurveOnSurface(aEf, aF, aT[0], aT[1]);
579   //
580   for (j=0; j<2; ++j) {
581     aTolV2=BRep_Tool::Tolerance(aV[j]);
582     aTolV2=aTolV2*aTolV2;
583     //
584     aC3D->D0(aT[j], aP3D);
585     aC2D->D0(aT[j], aP2Dx);
586     aP2Dx.Coord(aUx, aVx);
587     aS->D0(aUx, aVx, aP3Dx);
588     aD2=aP3D.SquareDistance(aP3Dx);
589     if (aD2>aTolV2) {
590       aD=sqrt(aD2);
591       aBB.UpdateVertex(aV[j], aD);
592     }
593   }
594 }
595 //=======================================================================
596 // function: Prepare
597 // purpose: 
598 //=======================================================================
599 void BOPAlgo_PaveFiller::Prepare()
600 {
601   TopAbs_ShapeEnum aType[] = {
602     TopAbs_VERTEX,
603     TopAbs_EDGE,
604     TopAbs_FACE
605   };
606   Standard_Boolean bJustAdd, bIsBasedOnPlane;
607   Standard_Integer i, aNb, n1, nF;
608   TopExp_Explorer aExp;
609   BOPCol_MapOfShape aMF;
610   BOPCol_MapIteratorOfMapOfShape aItMF;
611   //
612   myErrorStatus=0;
613   //
614   aNb=3;
615   for(i=0; i<aNb; ++i) {
616     myIterator->Initialize(aType[i], aType[2]);
617     for (; myIterator->More(); myIterator->Next()) {
618       myIterator->Value(n1, nF, bJustAdd);
619       const TopoDS_Face& aF=(*(TopoDS_Face *)(&myDS->Shape(nF))); 
620       //
621       bIsBasedOnPlane=IsBasedOnPlane(aF);
622       if (bIsBasedOnPlane) {
623         aMF.Add(aF);
624       }
625     }
626   }
627   //
628   if (aMF.IsEmpty()) {
629     return;
630   }
631   //
632   BOPAlgo_VectorOfBPC aVBPC;
633   //
634   aItMF.Initialize(aMF);
635   for (; aItMF.More(); aItMF.Next()) {
636     const TopoDS_Face& aF=*((TopoDS_Face *)&aItMF.Key());
637     aExp.Init(aF, aType[1]);
638     for (; aExp.More(); aExp.Next()) {
639       const TopoDS_Edge& aE=*((TopoDS_Edge *)&aExp.Current());
640       BOPAlgo_BPC& aBPC=aVBPC.Append1();
641       aBPC.SetEdge(aE);
642       aBPC.SetFace(aF);
643     }
644   }
645   //
646   //======================================================
647   BOPAlgo_BPCCnt::Perform(myRunParallel, aVBPC);
648   //======================================================
649 }
650 //=======================================================================
651 //function : IsBasedOnPlane
652 //purpose  : 
653 //=======================================================================
654 Standard_Boolean IsBasedOnPlane(const TopoDS_Face& aF)
655 {
656   TopLoc_Location aLoc; 
657   Handle(Geom_RectangularTrimmedSurface) aGRTS;
658   Handle(Geom_Plane) aGP;
659   
660   const Handle(Geom_Surface)& aS = BRep_Tool::Surface(aF, aLoc);
661   aGRTS = Handle(Geom_RectangularTrimmedSurface)::DownCast(aS);
662   if(!aGRTS.IsNull()) {
663     aGP = Handle(Geom_Plane)::DownCast(aGRTS->BasisSurface());
664   }
665   else {
666     aGP = Handle(Geom_Plane)::DownCast(aS);
667   }
668   //
669   return (!aGP.IsNull()); 
670 }