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