0026738: Make Boolean operations safely treating arguments when running with fuzzy...
[occt.git] / src / BOPAlgo / BOPAlgo_PaveFiller_8.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_SectionAttribute.hxx>
20 #include <BOPCol_ListOfInteger.hxx>
21 #include <BOPDS_Curve.hxx>
22 #include <BOPDS_DS.hxx>
23 #include <BOPDS_FaceInfo.hxx>
24 #include <BOPDS_MapOfPaveBlock.hxx>
25 #include <BOPDS_Pave.hxx>
26 #include <BOPDS_PaveBlock.hxx>
27 #include <BOPDS_ShapeInfo.hxx>
28 #include <BRep_Builder.hxx>
29 #include <BRep_Tool.hxx>
30 #include <ElCLib.hxx>
31 #include <Geom2d_Curve.hxx>
32 #include <Geom2d_Line.hxx>
33 #include <Geom2d_TrimmedCurve.hxx>
34 #include <Geom2dAdaptor_Curve.hxx>
35 #include <Geom2dInt_GInter.hxx>
36 #include <gp_Lin2d.hxx>
37 #include <gp_Pnt.hxx>
38 #include <gp_Pnt2d.hxx>
39 #include <IntRes2d_IntersectionPoint.hxx>
40 #include <IntTools_Context.hxx>
41 #include <Precision.hxx>
42 #include <TopoDS_Edge.hxx>
43 #include <TopoDS_Face.hxx>
44 #include <TopoDS_Vertex.hxx>
45
46 static
47   void MakeSplitEdge1 (const TopoDS_Edge&   aE,
48                        const TopoDS_Face&   aF,
49                        const TopoDS_Vertex& aV1,
50                        const Standard_Real  aP1,
51                        const TopoDS_Vertex& aV2,
52                        const Standard_Real  aP2,
53                        TopoDS_Edge& aNewEdge);
54
55 //=======================================================================
56 //function : ProcessDE
57 //purpose  : 
58 //=======================================================================
59 void BOPAlgo_PaveFiller::ProcessDE()
60 {
61   Standard_Integer nF, aNb, nE, nV, nVSD, aNbPB;
62   Handle(NCollection_BaseAllocator) aAllocator;
63   Handle(BOPDS_PaveBlock) aPBD;
64   BOPCol_ListIteratorOfListOfInteger aItLI;
65   //
66   myErrorStatus=0;
67   //
68   // 1. Find degnerated edges
69   //-----------------------------------------------------scope f
70   //
71   aAllocator=
72     NCollection_BaseAllocator::CommonBaseAllocator();
73   BOPDS_ListOfPaveBlock aLPBOut(aAllocator);
74   //
75   aNb=myDS->NbSourceShapes();
76   for (nE=0; nE<aNb; ++nE) {
77     const BOPDS_ShapeInfo& aSIE=myDS->ShapeInfo(nE);
78     if (aSIE.ShapeType()==TopAbs_EDGE) {
79       if (aSIE.HasFlag(nF)) {
80         const BOPDS_ShapeInfo& aSIF=myDS->ShapeInfo(nF);
81         nV=aSIE.SubShapes().First();
82         if (myDS->HasShapeSD(nV, nVSD)) {
83           nV=nVSD;
84         }
85         //nV,nE,nF
86         //
87         if (aSIF.ShapeType() == TopAbs_FACE) {
88           // 1. Find PaveBlocks that are go through nV for nF
89           FindPaveBlocks(nV, nF, aLPBOut);
90           aNbPB=aLPBOut.Extent();
91           if (aNbPB) {
92             //
93             // 2.
94             BOPDS_ListOfPaveBlock& aLPBD = myDS->ChangePaveBlocks(nE);
95             Standard_ASSERT_VOID(!aLPBD.IsEmpty(), "ListOfPaveBlock is unexpectedly empty");
96             if (aLPBD.IsEmpty())
97               continue;
98             aPBD = aLPBD.First();
99             //
100             FillPaves(nV, nE, nF, aLPBOut, aPBD);
101             //
102             myDS->UpdatePaveBlock(aPBD);
103           }
104           //
105           MakeSplitEdge(nE, nF);
106           //
107           aLPBOut.Clear();
108         }
109         if (aSIF.ShapeType() == TopAbs_EDGE) {
110           Standard_Real aTol=1.e-7;
111           Standard_Integer nEn;
112           BRep_Builder BB;
113           const TopoDS_Edge& aDE=(*(TopoDS_Edge *)(&myDS->Shape(nE))); 
114           const TopoDS_Vertex& aVn = (*(TopoDS_Vertex *)(&myDS->Shape(nV)));
115           //
116           TopoDS_Edge aE=aDE;
117           aE.EmptyCopy();
118           BB.Add(aE, aVn);
119           BB.Degenerated(aE, Standard_True);
120           BB.UpdateEdge(aE, aTol);
121           BOPDS_ShapeInfo aSI;
122           aSI.SetShapeType(TopAbs_EDGE);
123           aSI.SetShape(aE);
124           nEn=myDS->Append(aSI);
125           BOPDS_ListOfPaveBlock& aLPBD=myDS->ChangePaveBlocks(nE);
126           aPBD=aLPBD.First();
127           aPBD->SetEdge(nEn);
128         }
129       }
130     }
131   }
132 }
133
134 //=======================================================================
135 //function : FindPaveBlocks
136 //purpose  : 
137 //=======================================================================
138   void BOPAlgo_PaveFiller::FindPaveBlocks(const Standard_Integer nV,
139                                           const Standard_Integer nF,
140                                           BOPDS_ListOfPaveBlock& aLPBOut)
141 {
142   Standard_Integer i, aNbPBOn, aNbPBIn, aNbPBSc, nV1, nV2;
143   //
144   const BOPDS_FaceInfo& aFI=myDS->ChangeFaceInfo(nF);
145   // In
146   const BOPDS_IndexedMapOfPaveBlock& aMPBIn=aFI.PaveBlocksIn();
147   aNbPBIn = aMPBIn.Extent();
148   for (i = 1; i <= aNbPBIn; ++i) {
149     const Handle(BOPDS_PaveBlock)& aPB = aMPBIn(i);
150     aPB->Indices(nV1, nV2);
151     if (nV==nV1 || nV==nV2) {
152       aLPBOut.Append(aPB);
153     }
154   }
155   // On
156   const BOPDS_IndexedMapOfPaveBlock& aMPBOn=aFI.PaveBlocksOn();
157   aNbPBOn = aMPBOn.Extent();
158   for (i = 1; i <= aNbPBOn; ++i) {
159     const Handle(BOPDS_PaveBlock)& aPB = aMPBOn(i);
160     aPB->Indices(nV1, nV2);
161     if (nV==nV1 || nV==nV2) {
162       aLPBOut.Append(aPB);
163     }
164   }
165   // Sections
166   const BOPDS_IndexedMapOfPaveBlock& aMPBSc=aFI.PaveBlocksSc();
167   aNbPBSc = aMPBSc.Extent();
168   for (i = 1; i <= aNbPBSc; ++i) {
169     const Handle(BOPDS_PaveBlock)& aPB = aMPBSc(i);
170     aPB->Indices(nV1, nV2);
171     if (nV==nV1 || nV==nV2) {
172       aLPBOut.Append(aPB);
173     }
174   }
175 }
176
177 //=======================================================================
178 //function : MakeSplitEdge
179 //purpose  : 
180 //=======================================================================
181   void BOPAlgo_PaveFiller::MakeSplitEdge (const Standard_Integer nDE,
182                                           const Standard_Integer nDF)
183
184   Standard_Integer nSp, nV1, nV2, aNbPB;
185   Standard_Real aT1, aT2;
186   TopoDS_Edge aDE, aSp;
187   TopoDS_Vertex aV1, aV2;
188   BOPDS_ListIteratorOfListOfPaveBlock aItLPB;
189   BOPDS_ShapeInfo aSI;
190   //
191   aSI.SetShapeType(TopAbs_EDGE);
192   //
193   aDE=(*(TopoDS_Edge *)(&myDS->Shape(nDE))); 
194   aDE.Orientation(TopAbs_FORWARD);
195   //
196   const TopoDS_Face& aDF=(*(TopoDS_Face *)(&myDS->Shape(nDF)));
197   //
198   BOPDS_ListOfPaveBlock& aLPB=myDS->ChangePaveBlocks(nDE);
199   aNbPB=aLPB.Extent();
200   //
201   aItLPB.Initialize(aLPB);
202   for (; aItLPB.More(); aItLPB.Next()) {
203     Handle(BOPDS_PaveBlock)& aPB=aItLPB.ChangeValue();
204     //
205     const BOPDS_Pave& aPave1=aPB->Pave1();
206     aPave1.Contents(nV1, aT1);
207     //
208     const BOPDS_Pave& aPave2=aPB->Pave2();
209     aPave2.Contents(nV2, aT2);
210     //
211     if (myDS->IsNewShape(nV1) || aNbPB>1) {
212       aV1=(*(TopoDS_Vertex *)(&myDS->Shape(nV1)));
213       aV1.Orientation(TopAbs_FORWARD); 
214       //
215       aV2=(*(TopoDS_Vertex *)(&myDS->Shape(nV2)));
216       aV2.Orientation(TopAbs_REVERSED); 
217       //
218       MakeSplitEdge1(aDE, aDF, aV1, aT1, aV2, aT2, aSp); 
219       //
220       aSI.SetShape(aSp);
221       nSp=myDS->Append(aSI);
222       aPB->SetEdge(nSp);
223     }
224     else {
225       //aPB->SetEdge(nDE);
226       aLPB.Clear();
227       break;
228     }
229   }
230 }
231
232 //=======================================================================
233 //function : FillPaves
234 //purpose  : 
235 //=======================================================================
236   void BOPAlgo_PaveFiller::FillPaves(const Standard_Integer nVD,
237                                      const Standard_Integer nED,
238                                      const Standard_Integer nFD,
239                                      const BOPDS_ListOfPaveBlock& aLPBOut,
240                                      const Handle(BOPDS_PaveBlock)& aPBD)
241 {
242   Standard_Boolean bXDir, bIsDone;
243   Standard_Integer nE, aNbPoints, j, anInd;
244   Standard_Real aTD1, aTD2, aT1, aT2, aTolInter, aX, aDT;
245   Standard_Real aTolCmp;
246   gp_Pnt2d aP2d1, aP2d2, aP2D;
247   gp_Lin2d aLDE;
248   Handle(Geom2d_Line) aCLDE;
249   Handle(Geom2d_Curve) aC2DDE1, aC2D;
250   Handle(Geom2d_TrimmedCurve)aC2DDE;
251   BOPDS_ListIteratorOfListOfPaveBlock aItLPB;
252   BOPDS_Pave aPave;
253   //
254   aDT=Precision::PConfusion();
255   //
256   aPave.SetIndex(nVD);
257   //
258   const TopoDS_Edge& aDE=(*(TopoDS_Edge *)(&myDS->Shape(nED)));
259   const TopoDS_Face& aDF=(*(TopoDS_Face *)(&myDS->Shape(nFD)));
260   //aC2DDE
261   aC2DDE1=BRep_Tool::CurveOnSurface(aDE, aDF, aTD1, aTD2);
262   aC2DDE=new Geom2d_TrimmedCurve(aC2DDE1, aTD1, aTD2);
263   //aCLDE
264   Handle(Geom2d_TrimmedCurve) aCLDET1=Handle(Geom2d_TrimmedCurve)::DownCast(aC2DDE1);
265   if (aCLDET1.IsNull()) {
266     aCLDE=Handle(Geom2d_Line)::DownCast(aC2DDE1);
267   }
268   else {
269     Handle(Geom2d_Curve) aBasisCurve=aCLDET1->BasisCurve();
270     aCLDE=Handle(Geom2d_Line)::DownCast(aBasisCurve);
271   }
272   //
273   // Choose direction for degenerated edge
274   aC2DDE->D0(aTD1, aP2d1);
275   aC2DDE->D0(aTD2, aP2d2);
276   //
277   bXDir=Standard_False;
278   if (fabs(aP2d1.Y()-aP2d2.Y()) < aDT){
279     bXDir=!bXDir;
280   }
281   //
282   aItLPB.Initialize(aLPBOut);
283   for (; aItLPB.More(); aItLPB.Next()) {
284     const Handle(BOPDS_PaveBlock)& aPB=aItLPB.Value();
285     nE=aPB->Edge();
286     if (nE < 0) {
287       continue;
288     }
289     const TopoDS_Edge& aE=(*(TopoDS_Edge *)(&myDS->Shape(nE)));
290     aC2D=BRep_Tool::CurveOnSurface(aE, aDF, aT1, aT2);
291     if (aC2D.IsNull()) {
292       continue;
293     }
294     //
295     // Intersection
296     Geom2dAdaptor_Curve aGAC1, aGAC2;
297     aGAC1.Load(aC2DDE, aTD1, aTD2);
298     //
299     Handle(Geom2d_Line) aL2D= Handle(Geom2d_Line)::DownCast(aC2D);
300     if (!aL2D.IsNull()) {
301       aGAC2.Load(aC2D);
302     }
303     else {
304       aGAC2.Load(aC2D, aT1, aT2);
305     }
306     //
307     aTolInter=0.001;
308     aTolCmp=1.414213562*aTolInter+aDT;
309     Geom2dInt_GInter aGInter(aGAC1, aGAC2, aTolInter, aTolInter);
310     bIsDone=aGInter.IsDone();
311     if(!bIsDone) {
312       continue;
313     }
314     //
315     aNbPoints=aGInter.NbPoints();
316     if (!aNbPoints){
317       continue;
318     }
319     //
320     for (j=1; j<=aNbPoints; ++j) {
321       aP2D=aGInter.Point(j).Value();
322       aX=aGInter.Point(j).ParamOnFirst();
323       //
324       if (fabs (aX-aTD1) < aTolCmp || fabs (aX-aTD2) < aTolCmp) {
325         continue; 
326       }
327       if (aX < aTD1 || aX > aTD2) {
328         continue; 
329       }
330       //
331       if (aPBD->ContainsParameter(aX, aDT, anInd)) {
332         continue;
333       }
334       aPave.SetParameter(aX);
335       aPBD->AppendExtPave1(aPave);
336     }
337   }//for (; aItLPB.More(); aItLPB.Next()) {
338 }
339 //=======================================================================
340 // function:  MakeSplitEdge1
341 // purpose: 
342 //=======================================================================
343   void MakeSplitEdge1 (const TopoDS_Edge&   aE,
344                        const TopoDS_Face&   aF,
345                        const TopoDS_Vertex& aV1,
346                        const Standard_Real  aP1,
347                        const TopoDS_Vertex& aV2,
348                        const Standard_Real  aP2,
349                        TopoDS_Edge& aNewEdge)
350 {
351   Standard_Real aTol=1.e-7;
352
353   TopoDS_Edge E=aE;
354
355   E.EmptyCopy();
356   BRep_Builder BB;
357   BB.Add  (E, aV1);
358   BB.Add  (E, aV2);
359
360   BB.Range(E, aF, aP1, aP2);
361
362   BB.Degenerated(E, Standard_True);
363
364   BB.UpdateEdge(E, aTol);
365   aNewEdge=E;
366 }