0028556: Invalid result of Fuse operation in the test case bugs moddata_2 bug469
[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  : Find all pave blocks passing through the vertex <nVD> and
235 //           intersecting the 2D curve of the degenerated edge
236 //           somewhere in the middle. Save intersection points into
237 //           Extra paves of the pave block of degenerated edge for future
238 //           splitting.
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   // Prepare pave to put to pave block as an Extra pave
247   BOPDS_Pave aPave;
248   aPave.SetIndex(nVD);
249   //
250   const TopoDS_Vertex& aDV = (*(TopoDS_Vertex *)(&myDS->Shape(nVD)));
251   const TopoDS_Edge& aDE = (*(TopoDS_Edge *)(&myDS->Shape(nED)));
252   const TopoDS_Face& aDF = (*(TopoDS_Face *)(&myDS->Shape(nFD)));
253   //
254   Standard_Real aTolV = BRep_Tool::Tolerance(aDV);
255   const BRepAdaptor_Surface& aBAS = myContext->SurfaceAdaptor(aDF);
256   //
257   // 2D intersection tolerance should be computed as a resolution
258   // from the tolerance of vertex to resolve the touching cases
259   Standard_Real aTolInt = Precision::PConfusion();
260   // UResolution from the tolerance of the vertex
261   Standard_Real aURes = aBAS.UResolution(aTolV);
262   // VResolution from the tolerance of the vertex
263   Standard_Real aVRes = aBAS.VResolution(aTolV);
264   //
265   aTolInt = Max(aTolInt, Max(aURes, aVRes));
266   //
267   // Parametric tolerance to compare intersection point with boundaries
268   // should be computed as a resolution from the tolerance of vertex
269   // in the direction of the 2D curve of degenerated edge
270   Standard_Real aTolCmp = Precision::PConfusion();
271   // Get 2D curve
272   Standard_Real aTD1, aTD2;
273   Handle(Geom2d_Curve) aC2DDE = BRep_Tool::CurveOnSurface(aDE, aDF, aTD1, aTD2);
274   // Get direction of the curve
275   Standard_Boolean bUDir = Abs(aC2DDE->Value(aTD1).Y() - aC2DDE->Value(aTD2).Y()) < Precision::PConfusion();
276   //
277   aTolCmp = Max(aTolCmp, (bUDir ? aURes : aVRes));
278   //
279   // Prepare adaptor for the degenerated edge for intersection
280   Geom2dAdaptor_Curve aGAC1;
281   aGAC1.Load(aC2DDE, aTD1, aTD2);
282   //
283   BOPDS_ListIteratorOfListOfPaveBlock aItLPB(aLPBOut);
284   for (; aItLPB.More(); aItLPB.Next()) {
285     const Handle(BOPDS_PaveBlock)& aPB = aItLPB.Value();
286     Standard_Integer nE = aPB->Edge();
287     if (nE < 0) {
288       continue;
289     }
290     const TopoDS_Edge& aE = (*(TopoDS_Edge *)(&myDS->Shape(nE)));
291     Standard_Real aT1, aT2;
292     Handle(Geom2d_Curve) aC2D = BRep_Tool::CurveOnSurface(aE, aDF, aT1, aT2);
293     if (aC2D.IsNull()) {
294       continue;
295     }
296     //
297     // Prepare adaptor for the passing edge for intersection
298     Geom2dAdaptor_Curve aGAC2;
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     // Intersection
308     Geom2dInt_GInter aGInter(aGAC1, aGAC2, aTolInt, aTolInt);
309     if (!aGInter.IsDone()) {
310       continue;
311     }
312     //
313     // Analyze intersection points
314     Standard_Integer i, aNbPoints = aGInter.NbPoints();
315     for (i = 1; i <= aNbPoints; ++i) {
316       Standard_Real aX = aGInter.Point(i).ParamOnFirst();
317       if (aX - aTD1 < aTolCmp || aTD2 - aX < aTolCmp) {
318         continue;
319       }
320       //
321       Standard_Integer anInd;
322       if (aPBD->ContainsParameter(aX, aTolCmp, anInd)) {
323         continue;
324       }
325       //
326       aPave.SetParameter(aX);
327       aPBD->AppendExtPave1(aPave);
328     }
329   }
330 }
331 //=======================================================================
332 // function:  MakeSplitEdge1
333 // purpose: 
334 //=======================================================================
335   void MakeSplitEdge1 (const TopoDS_Edge&   aE,
336                        const TopoDS_Face&   aF,
337                        const TopoDS_Vertex& aV1,
338                        const Standard_Real  aP1,
339                        const TopoDS_Vertex& aV2,
340                        const Standard_Real  aP2,
341                        TopoDS_Edge& aNewEdge)
342 {
343   Standard_Real aTol=1.e-7;
344
345   TopoDS_Edge E=aE;
346
347   E.EmptyCopy();
348   BRep_Builder BB;
349   BB.Add  (E, aV1);
350   BB.Add  (E, aV2);
351
352   BB.Range(E, aF, aP1, aP2);
353
354   BB.Degenerated(E, Standard_True);
355
356   BB.UpdateEdge(E, aTol);
357   aNewEdge=E;
358 }