0028556: Invalid result of Fuse operation in the test case bugs moddata_2 bug469
[occt.git] / src / BOPAlgo / BOPAlgo_PaveFiller_8.cxx
CommitLineData
4e57c75e 1// Created by: Peter KURNEV
973c2be1 2// Copyright (c) 2010-2014 OPEN CASCADE SAS
4e57c75e 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//
973c2be1 7// This file is part of Open CASCADE Technology software library.
4e57c75e 8//
d5f74e42 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
973c2be1 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.
4e57c75e 14//
973c2be1 15// Alternatively, this file may be used under the terms of Open CASCADE
16// commercial license or contractual agreement.
4e57c75e 17
42cf5bc1 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>
4e57c75e 30#include <ElCLib.hxx>
4e57c75e 31#include <Geom2d_Curve.hxx>
4e57c75e 32#include <Geom2d_Line.hxx>
42cf5bc1 33#include <Geom2d_TrimmedCurve.hxx>
4e57c75e 34#include <Geom2dAdaptor_Curve.hxx>
35#include <Geom2dInt_GInter.hxx>
42cf5bc1 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>
42cf5bc1 41#include <Precision.hxx>
4e57c75e 42#include <TopoDS_Edge.hxx>
43#include <TopoDS_Face.hxx>
44#include <TopoDS_Vertex.hxx>
45
4e57c75e 46static
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//=======================================================================
488e5b9d 59void BOPAlgo_PaveFiller::ProcessDE()
4e57c75e 60{
61 Standard_Integer nF, aNb, nE, nV, nVSD, aNbPB;
488e5b9d 62 Handle(NCollection_BaseAllocator) aAllocator;
4e57c75e 63 Handle(BOPDS_PaveBlock) aPBD;
64 BOPCol_ListIteratorOfListOfInteger aItLI;
65 //
66 myErrorStatus=0;
67 //
68 // 1. Find degnerated edges
69 //-----------------------------------------------------scope f
70 //
488e5b9d 71 aAllocator=
72 NCollection_BaseAllocator::CommonBaseAllocator();
4e57c75e 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();
3510db62 91 if (aNbPB) {
92 //
93 // 2.
94 BOPDS_ListOfPaveBlock& aLPBD = myDS->ChangePaveBlocks(nE);
0d0481c7 95 Standard_ASSERT_VOID(!aLPBD.IsEmpty(), "ListOfPaveBlock is unexpectedly empty");
96 if (aLPBD.IsEmpty())
97 continue;
3510db62 98 aPBD = aLPBD.First();
99 //
100 FillPaves(nV, nE, nF, aLPBOut, aPBD);
101 //
102 myDS->UpdatePaveBlock(aPBD);
4e57c75e 103 }
104 //
4e57c75e 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{
319da2e4 142 Standard_Integer i, aNbPBOn, aNbPBIn, aNbPBSc, nV1, nV2;
4e57c75e 143 //
144 const BOPDS_FaceInfo& aFI=myDS->ChangeFaceInfo(nF);
145 // In
146 const BOPDS_IndexedMapOfPaveBlock& aMPBIn=aFI.PaveBlocksIn();
319da2e4 147 aNbPBIn = aMPBIn.Extent();
148 for (i = 1; i <= aNbPBIn; ++i) {
149 const Handle(BOPDS_PaveBlock)& aPB = aMPBIn(i);
4e57c75e 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();
319da2e4 157 aNbPBOn = aMPBOn.Extent();
158 for (i = 1; i <= aNbPBOn; ++i) {
159 const Handle(BOPDS_PaveBlock)& aPB = aMPBOn(i);
4e57c75e 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();
319da2e4 167 aNbPBSc = aMPBSc.Extent();
168 for (i = 1; i <= aNbPBSc; ++i) {
169 const Handle(BOPDS_PaveBlock)& aPB = aMPBSc(i);
4e57c75e 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
f80842e3 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.
4e57c75e 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{
f80842e3 246 // Prepare pave to put to pave block as an Extra pave
4e57c75e 247 BOPDS_Pave aPave;
f80842e3 248 aPave.SetIndex(nVD);
4e57c75e 249 //
f80842e3 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)));
4e57c75e 253 //
f80842e3 254 Standard_Real aTolV = BRep_Tool::Tolerance(aDV);
255 const BRepAdaptor_Surface& aBAS = myContext->SurfaceAdaptor(aDF);
4e57c75e 256 //
f80842e3 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);
4e57c75e 264 //
f80842e3 265 aTolInt = Max(aTolInt, Max(aURes, aVRes));
4e57c75e 266 //
f80842e3 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));
4e57c75e 278 //
f80842e3 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);
4e57c75e 284 for (; aItLPB.More(); aItLPB.Next()) {
f80842e3 285 const Handle(BOPDS_PaveBlock)& aPB = aItLPB.Value();
286 Standard_Integer nE = aPB->Edge();
01b5b3df 287 if (nE < 0) {
288 continue;
289 }
f80842e3 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);
4e57c75e 293 if (aC2D.IsNull()) {
294 continue;
295 }
296 //
f80842e3 297 // Prepare adaptor for the passing edge for intersection
298 Geom2dAdaptor_Curve aGAC2;
4e57c75e 299 //
f80842e3 300 Handle(Geom2d_Line) aL2D = Handle(Geom2d_Line)::DownCast(aC2D);
4e57c75e 301 if (!aL2D.IsNull()) {
302 aGAC2.Load(aC2D);
303 }
304 else {
305 aGAC2.Load(aC2D, aT1, aT2);
306 }
f80842e3 307 // Intersection
308 Geom2dInt_GInter aGInter(aGAC1, aGAC2, aTolInt, aTolInt);
309 if (!aGInter.IsDone()) {
4e57c75e 310 continue;
311 }
312 //
f80842e3 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;
4e57c75e 319 }
320 //
f80842e3 321 Standard_Integer anInd;
322 if (aPBD->ContainsParameter(aX, aTolCmp, anInd)) {
4e57c75e 323 continue;
324 }
f80842e3 325 //
4e57c75e 326 aPave.SetParameter(aX);
327 aPBD->AppendExtPave1(aPave);
328 }
f80842e3 329 }
4e57c75e 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}