Commit | Line | Data |
---|---|---|
b311480e | 1 | // Copyright (c) 1995-1999 Matra Datavision |
973c2be1 | 2 | // Copyright (c) 1999-2014 OPEN CASCADE SAS |
b311480e | 3 | // |
973c2be1 | 4 | // This file is part of Open CASCADE Technology software library. |
b311480e | 5 | // |
d5f74e42 | 6 | // This library is free software; you can redistribute it and/or modify it under |
7 | // the terms of the GNU Lesser General Public License version 2.1 as published | |
973c2be1 | 8 | // by the Free Software Foundation, with special exception defined in the file |
9 | // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT | |
10 | // distribution for complete text of the license and disclaimer of any warranty. | |
b311480e | 11 | // |
973c2be1 | 12 | // Alternatively, this file may be used under the terms of Open CASCADE |
13 | // commercial license or contractual agreement. | |
7fd59977 | 14 | |
42cf5bc1 | 15 | |
16 | #include <Bnd_Box.hxx> | |
7fd59977 | 17 | #include <BndLib_Add3dCurve.hxx> |
18 | #include <BndLib_AddSurface.hxx> | |
7fd59977 | 19 | #include <BRep_Polygon3D.hxx> |
42cf5bc1 | 20 | #include <BRep_Tool.hxx> |
21 | #include <BRepAdaptor_Curve.hxx> | |
22 | #include <BRepAdaptor_Surface.hxx> | |
23 | #include <BRepBndLib.hxx> | |
7fd59977 | 24 | #include <Geom_Curve.hxx> |
42cf5bc1 | 25 | #include <Geom_Surface.hxx> |
7fd59977 | 26 | #include <GeomAdaptor_Curve.hxx> |
42cf5bc1 | 27 | #include <Poly_Polygon3D.hxx> |
28 | #include <Poly_PolygonOnTriangulation.hxx> | |
29 | #include <Poly_Triangulation.hxx> | |
30 | #include <TColgp_Array1OfPnt.hxx> | |
31 | #include <TColStd_Array1OfInteger.hxx> | |
32 | #include <TColStd_HArray1OfInteger.hxx> | |
33 | #include <TopExp_Explorer.hxx> | |
34 | #include <TopLoc_Location.hxx> | |
35 | #include <TopoDS.hxx> | |
36 | #include <TopoDS_Shape.hxx> | |
3ba87fdb | 37 | #include <Adaptor3d_HCurve.hxx> |
38 | #include <Adaptor3d_HSurface.hxx> | |
39 | #include <BRepTools.hxx> | |
40 | #include <Geom_BSplineSurface.hxx> | |
41 | #include <Geom_BezierSurface.hxx> | |
42 | #include <Bnd_Box2d.hxx> | |
43 | #include <BndLib_Add2dCurve.hxx> | |
44 | #include <BRepTopAdaptor_FClass2d.hxx> | |
45 | #include <ElSLib.hxx> | |
46 | #include <ElCLib.hxx> | |
47 | #include <Geom_Plane.hxx> | |
48 | #include <Extrema_ExtSS.hxx> | |
49 | #include <GeomAdaptor_Surface.hxx> | |
50 | // | |
51 | static Standard_Boolean CanUseEdges(const Adaptor3d_Surface& BS); | |
52 | // | |
53 | static void FindExactUVBounds(const TopoDS_Face F, | |
54 | Standard_Real& umin, Standard_Real& umax, | |
55 | Standard_Real& vmin, Standard_Real& vmax, | |
56 | const Standard_Real Tol, | |
57 | Standard_Boolean& isNaturalRestriction); | |
58 | // | |
59 | static void AdjustFaceBox(const BRepAdaptor_Surface& BS, | |
60 | const Standard_Real umin, const Standard_Real umax, | |
61 | const Standard_Real vmin, const Standard_Real vmax, | |
62 | Bnd_Box& FaceBox, | |
63 | const Bnd_Box& EdgeBox, const Standard_Real Tol); | |
64 | // | |
65 | static Standard_Boolean IsModifySize(const BRepAdaptor_Surface& theBS, | |
66 | const gp_Pln& thePln, const gp_Pnt& theP, | |
67 | const Standard_Real umin, const Standard_Real umax, | |
68 | const Standard_Real vmin, const Standard_Real vmax, | |
69 | const BRepTopAdaptor_FClass2d& theFClass, | |
70 | const Standard_Real theTolU, const Standard_Real theTolV); | |
7fd59977 | 71 | |
3ba87fdb | 72 | // |
7fd59977 | 73 | //======================================================================= |
74 | //function : Add | |
75 | //purpose : Add a shape bounding to a box | |
76 | //======================================================================= | |
3c34883c | 77 | void BRepBndLib::Add(const TopoDS_Shape& S, Bnd_Box& B, Standard_Boolean useTriangulation) |
7fd59977 | 78 | { |
79 | TopExp_Explorer ex; | |
80 | ||
81 | // Add the faces | |
7fd59977 | 82 | BRepAdaptor_Surface BS; |
4d19a2c5 | 83 | TopLoc_Location l, aDummyLoc; |
7fd59977 | 84 | Standard_Integer i, nbNodes; |
85 | BRepAdaptor_Curve BC; | |
86 | ||
87 | for (ex.Init(S,TopAbs_FACE); ex.More(); ex.Next()) { | |
88 | const TopoDS_Face& F = TopoDS::Face(ex.Current()); | |
4d19a2c5 | 89 | const Handle(Poly_Triangulation)& T = BRep_Tool::Triangulation(F, l); |
90 | const Handle(Geom_Surface)& GS = BRep_Tool::Surface (F, aDummyLoc); | |
91 | if ((useTriangulation || GS.IsNull()) && !T.IsNull()) | |
3c34883c | 92 | { |
7fd59977 | 93 | nbNodes = T->NbNodes(); |
94 | const TColgp_Array1OfPnt& Nodes = T->Nodes(); | |
95 | for (i = 1; i <= nbNodes; i++) { | |
3c34883c O |
96 | if (l.IsIdentity()) B.Add(Nodes(i)); |
97 | else B.Add(Nodes(i).Transformed(l)); | |
7fd59977 | 98 | } |
99 | // B.Enlarge(T->Deflection()); | |
100 | B.Enlarge(T->Deflection() + BRep_Tool::Tolerance(F)); | |
3c34883c O |
101 | } else |
102 | { | |
7fd59977 | 103 | if (!GS.IsNull()) { |
3c34883c O |
104 | BS.Initialize(F, Standard_False); |
105 | if (BS.GetType() != GeomAbs_Plane) { | |
106 | BS.Initialize(F); | |
107 | BndLib_AddSurface::Add(BS, BRep_Tool::Tolerance(F), B); | |
108 | } | |
109 | else { | |
110 | // on travaille directement sur les courbes 3d. | |
111 | TopExp_Explorer ex2(F, TopAbs_EDGE); | |
112 | if (!ex2.More()) { | |
113 | BS.Initialize(F); | |
114 | BndLib_AddSurface::Add(BS, BRep_Tool::Tolerance(F), B); | |
115 | } | |
116 | else { | |
117 | for (;ex2.More();ex2.Next()) { | |
118 | BC.Initialize(TopoDS::Edge(ex2.Current())); | |
119 | BndLib_Add3dCurve::Add(BC, BRep_Tool::Tolerance(F), B); | |
120 | } | |
121 | B.Enlarge(BRep_Tool::Tolerance(F)); | |
122 | } | |
123 | } | |
7fd59977 | 124 | } |
125 | } | |
126 | } | |
127 | ||
128 | // Add the edges not in faces | |
7fd59977 | 129 | Handle(TColStd_HArray1OfInteger) HIndices; |
130 | Handle(Poly_PolygonOnTriangulation) Poly; | |
4d19a2c5 | 131 | Handle(Poly_Triangulation) T; |
3c34883c O |
132 | for (ex.Init(S,TopAbs_EDGE,TopAbs_FACE); ex.More(); ex.Next()) |
133 | { | |
7fd59977 | 134 | const TopoDS_Edge& E = TopoDS::Edge(ex.Current()); |
135 | Handle(Poly_Polygon3D) P3d = BRep_Tool::Polygon3D(E, l); | |
3c34883c O |
136 | if (!P3d.IsNull()) |
137 | { | |
7fd59977 | 138 | const TColgp_Array1OfPnt& Nodes = P3d->Nodes(); |
139 | nbNodes = P3d->NbNodes(); | |
3c34883c O |
140 | for (i = 1; i <= nbNodes; i++) |
141 | { | |
142 | if (l.IsIdentity()) B.Add(Nodes(i)); | |
143 | else B.Add(Nodes(i).Transformed(l)); | |
7fd59977 | 144 | } |
145 | // B.Enlarge(P3d->Deflection()); | |
146 | B.Enlarge(P3d->Deflection() + BRep_Tool::Tolerance(E)); | |
147 | } | |
3c34883c O |
148 | else |
149 | { | |
7fd59977 | 150 | BRep_Tool::PolygonOnTriangulation(E, Poly, T, l); |
3c34883c O |
151 | if (useTriangulation && !Poly.IsNull()) |
152 | { | |
153 | const TColStd_Array1OfInteger& Indices = Poly->Nodes(); | |
154 | const TColgp_Array1OfPnt& Nodes = T->Nodes(); | |
155 | nbNodes = Indices.Length(); | |
156 | for (i = 1; i <= nbNodes; i++) | |
157 | { | |
158 | if (l.IsIdentity()) B.Add(Nodes(Indices(i))); | |
159 | else B.Add(Nodes(Indices(i)).Transformed(l)); | |
160 | } | |
161 | // B.Enlarge(T->Deflection()); | |
162 | B.Enlarge(Poly->Deflection() + BRep_Tool::Tolerance(E)); | |
7fd59977 | 163 | } |
164 | else { | |
3c34883c O |
165 | if (BRep_Tool::IsGeometric(E)) |
166 | { | |
167 | BC.Initialize(E); | |
168 | BndLib_Add3dCurve::Add(BC, BRep_Tool::Tolerance(E), B); | |
169 | } | |
7fd59977 | 170 | } |
171 | } | |
172 | } | |
173 | ||
174 | // Add the vertices not in edges | |
175 | ||
176 | for (ex.Init(S,TopAbs_VERTEX,TopAbs_EDGE); ex.More(); ex.Next()) { | |
177 | B.Add(BRep_Tool::Pnt(TopoDS::Vertex(ex.Current()))); | |
178 | B.Enlarge(BRep_Tool::Tolerance(TopoDS::Vertex(ex.Current()))); | |
179 | } | |
180 | } | |
181 | ||
182 | ||
183 | ||
184 | //======================================================================= | |
185 | //function : AddClose | |
186 | //purpose : Add a precise shape bounding to a box | |
187 | //======================================================================= | |
188 | ||
189 | void BRepBndLib::AddClose(const TopoDS_Shape& S, Bnd_Box& B) | |
190 | { | |
191 | TopExp_Explorer ex; | |
192 | ||
193 | // No faces | |
194 | ||
195 | // Add the edges | |
196 | ||
197 | BRepAdaptor_Curve BC; | |
198 | ||
199 | for (ex.Init(S,TopAbs_EDGE); ex.More(); ex.Next()) { | |
200 | BC.Initialize(TopoDS::Edge(ex.Current())); | |
201 | BndLib_Add3dCurve::Add(BC,0.,B); | |
202 | } | |
203 | ||
204 | // Add the vertices not in edges | |
205 | ||
206 | for (ex.Init(S,TopAbs_VERTEX,TopAbs_EDGE); ex.More(); ex.Next()) { | |
207 | B.Add(BRep_Tool::Pnt(TopoDS::Vertex(ex.Current()))); | |
208 | } | |
209 | } | |
210 | ||
3ba87fdb | 211 | //======================================================================= |
212 | //function : AddOptimal | |
213 | //purpose : Add a shape bounding to a box | |
214 | //======================================================================= | |
215 | void BRepBndLib::AddOptimal(const TopoDS_Shape& S, Bnd_Box& B, | |
216 | const Standard_Boolean useTriangulation, | |
217 | const Standard_Boolean useShapeTolerance) | |
218 | { | |
219 | TopExp_Explorer ex; | |
220 | ||
221 | // Add the faces | |
222 | BRepAdaptor_Surface BS; | |
223 | Handle(Poly_Triangulation) T; | |
224 | TopLoc_Location l; | |
225 | Standard_Integer i, nbNodes; | |
226 | BRepAdaptor_Curve BC; | |
227 | ||
228 | for (ex.Init(S,TopAbs_FACE); ex.More(); ex.Next()) { | |
229 | const TopoDS_Face& F = TopoDS::Face(ex.Current()); | |
230 | T = BRep_Tool::Triangulation(F, l); | |
231 | Bnd_Box aLocBox; | |
232 | if (useTriangulation && !T.IsNull()) | |
233 | { | |
234 | nbNodes = T->NbNodes(); | |
235 | const TColgp_Array1OfPnt& Nodes = T->Nodes(); | |
236 | for (i = 1; i <= nbNodes; i++) { | |
237 | if (l.IsIdentity()) aLocBox.Add(Nodes(i)); | |
238 | else aLocBox.Add(Nodes(i).Transformed(l)); | |
239 | } | |
240 | // B.Enlarge(T->Deflection()); | |
241 | aLocBox.Enlarge(T->Deflection() + BRep_Tool::Tolerance(F)); | |
242 | Standard_Real xmin, ymin, zmin, xmax, ymax, zmax; | |
243 | aLocBox.Get(xmin, ymin, zmin, xmax, ymax, zmax); | |
244 | B.Update(xmin, ymin, zmin, xmax, ymax, zmax); | |
245 | } | |
246 | else | |
247 | { | |
248 | const Handle(Geom_Surface)& GS = BRep_Tool::Surface(F, l); | |
249 | if (!GS.IsNull()) { | |
250 | BS.Initialize(F, Standard_False); | |
251 | if (CanUseEdges(BS)) { | |
252 | TopExp_Explorer ex2(F, TopAbs_EDGE); | |
253 | if (!ex2.More()) { | |
254 | BS.Initialize(F); | |
255 | Standard_Real Tol = useShapeTolerance? BRep_Tool::Tolerance(F) : 0.; | |
256 | BndLib_AddSurface::AddOptimal(BS, Tol, aLocBox); | |
257 | } | |
258 | else | |
259 | { | |
260 | Standard_Real Tol; | |
261 | for (;ex2.More();ex2.Next()) { | |
262 | Bnd_Box anEBox; | |
263 | const TopoDS_Edge& anE = TopoDS::Edge(ex2.Current()); | |
264 | if(BRep_Tool::Degenerated(anE)) | |
265 | { | |
266 | continue; | |
267 | } | |
268 | BC.Initialize(anE); | |
269 | Tol = useShapeTolerance? BRep_Tool::Tolerance(anE) : 0.; | |
270 | BndLib_Add3dCurve::AddOptimal(BC, Tol, anEBox); | |
271 | aLocBox.Add(anEBox); | |
272 | } | |
273 | } | |
274 | } | |
275 | else | |
276 | { | |
277 | Standard_Real umin, umax, vmin, vmax; | |
278 | Standard_Boolean isNaturalRestriction = Standard_False; | |
279 | Standard_Real Tol = useShapeTolerance? BRep_Tool::Tolerance(F) : 0.; | |
280 | FindExactUVBounds(F, umin, umax, vmin, vmax, Tol, isNaturalRestriction); | |
281 | BndLib_AddSurface::AddOptimal(BS, umin, umax, vmin, vmax, | |
282 | Tol, aLocBox); | |
283 | // | |
284 | if(!isNaturalRestriction) | |
285 | { | |
286 | TopExp_Explorer ex2(F, TopAbs_EDGE); | |
287 | Bnd_Box EBox; | |
288 | for (;ex2.More();ex2.Next()) { | |
289 | Bnd_Box anEBox; | |
290 | const TopoDS_Edge& anE = TopoDS::Edge(ex2.Current()); | |
291 | if(BRep_Tool::Degenerated(anE)) | |
292 | { | |
293 | continue; | |
294 | } | |
295 | BC.Initialize(anE); | |
296 | Tol = useShapeTolerance? BRep_Tool::Tolerance(anE) : 0.; | |
297 | BndLib_Add3dCurve::AddOptimal(BC, Tol, anEBox); | |
298 | EBox.Add(anEBox); | |
299 | } | |
300 | Tol = useShapeTolerance? BRep_Tool::Tolerance(F) : 0.; | |
301 | AdjustFaceBox(BS, umin, umax, vmin, vmax, aLocBox, EBox, | |
302 | Tol); | |
303 | } | |
304 | } | |
305 | Standard_Real xmin, ymin, zmin, xmax, ymax, zmax; | |
306 | aLocBox.Get(xmin, ymin, zmin, xmax, ymax, zmax); | |
307 | B.Update(xmin, ymin, zmin, xmax, ymax, zmax); | |
308 | } | |
309 | } | |
310 | } | |
311 | ||
312 | // Add the edges not in faces | |
313 | Handle(TColStd_HArray1OfInteger) HIndices; | |
314 | Handle(Poly_PolygonOnTriangulation) Poly; | |
315 | ||
316 | for (ex.Init(S,TopAbs_EDGE,TopAbs_FACE); ex.More(); ex.Next()) | |
317 | { | |
318 | const TopoDS_Edge& E = TopoDS::Edge(ex.Current()); | |
319 | Bnd_Box aLocBox; | |
320 | Handle(Poly_Polygon3D) P3d = BRep_Tool::Polygon3D(E, l); | |
321 | if (useTriangulation && (!P3d.IsNull())) | |
322 | { | |
323 | const TColgp_Array1OfPnt& Nodes = P3d->Nodes(); | |
324 | nbNodes = P3d->NbNodes(); | |
325 | for (i = 1; i <= nbNodes; i++) | |
326 | { | |
327 | if (l.IsIdentity()) aLocBox.Add(Nodes(i)); | |
328 | else aLocBox.Add(Nodes(i).Transformed(l)); | |
329 | } | |
330 | Standard_Real Tol = useShapeTolerance? BRep_Tool::Tolerance(E) : 0.; | |
331 | aLocBox.Enlarge(P3d->Deflection() + Tol); | |
332 | } | |
333 | else | |
334 | { | |
335 | BRep_Tool::PolygonOnTriangulation(E, Poly, T, l); | |
336 | if (useTriangulation && !Poly.IsNull()) | |
337 | { | |
338 | const TColStd_Array1OfInteger& Indices = Poly->Nodes(); | |
339 | const TColgp_Array1OfPnt& Nodes = T->Nodes(); | |
340 | nbNodes = Indices.Length(); | |
341 | for (i = 1; i <= nbNodes; i++) | |
342 | { | |
343 | if (l.IsIdentity()) aLocBox.Add(Nodes(Indices(i))); | |
344 | else aLocBox.Add(Nodes(Indices(i)).Transformed(l)); | |
345 | } | |
346 | Standard_Real Tol = useShapeTolerance? BRep_Tool::Tolerance(E) : 0.; | |
347 | aLocBox.Enlarge(Poly->Deflection() + Tol); | |
348 | } | |
349 | else { | |
350 | if (BRep_Tool::IsGeometric(E)) | |
351 | { | |
352 | BC.Initialize(E); | |
353 | Standard_Real Tol = useShapeTolerance? BRep_Tool::Tolerance(E) : 0.; | |
354 | BndLib_Add3dCurve::AddOptimal(BC, Tol, aLocBox); | |
355 | } | |
356 | } | |
357 | } | |
358 | if (!aLocBox.IsVoid()) | |
359 | { | |
360 | Standard_Real xmin, ymin, zmin, xmax, ymax, zmax; | |
361 | aLocBox.Get(xmin, ymin, zmin, xmax, ymax, zmax); | |
362 | B.Update(xmin, ymin, zmin, xmax, ymax, zmax); | |
363 | } | |
364 | } | |
365 | ||
366 | // Add the vertices not in edges | |
367 | ||
368 | for (ex.Init(S,TopAbs_VERTEX,TopAbs_EDGE); ex.More(); ex.Next()) { | |
369 | Bnd_Box aLocBox; | |
370 | const TopoDS_Vertex& aV = TopoDS::Vertex(ex.Current()); | |
371 | aLocBox.Add(BRep_Tool::Pnt(aV)); | |
372 | Standard_Real Tol = useShapeTolerance? BRep_Tool::Tolerance(aV) : 0.; | |
373 | aLocBox.Enlarge(Tol); | |
374 | Standard_Real xmin, ymin, zmin, xmax, ymax, zmax; | |
375 | aLocBox.Get(xmin, ymin, zmin, xmax, ymax, zmax); | |
376 | B.Update(xmin, ymin, zmin, xmax, ymax, zmax); | |
377 | } | |
378 | } | |
379 | ||
380 | //======================================================================= | |
381 | //function : CanUseEdges | |
382 | //purpose : Define is it possible using only edges bnd boxes | |
383 | // to get face bnd box | |
384 | //======================================================================= | |
385 | Standard_Boolean CanUseEdges(const Adaptor3d_Surface& BS) | |
386 | { | |
387 | GeomAbs_SurfaceType aST = BS.GetType(); | |
388 | if(aST == GeomAbs_Plane || | |
389 | aST == GeomAbs_Cylinder || | |
390 | aST == GeomAbs_Cone || | |
391 | aST == GeomAbs_SurfaceOfExtrusion) | |
392 | { | |
393 | return Standard_True; | |
394 | } | |
395 | else if(aST == GeomAbs_SurfaceOfRevolution) | |
396 | { | |
397 | const Handle(Adaptor3d_HCurve)& aBC = BS.BasisCurve(); | |
398 | if(aBC->GetType() == GeomAbs_Line) | |
399 | { | |
400 | return Standard_True; | |
401 | } | |
402 | else | |
403 | { | |
404 | return Standard_False; | |
405 | } | |
406 | } | |
407 | else if(aST == GeomAbs_OffsetSurface) | |
408 | { | |
409 | const Handle(Adaptor3d_HSurface)& aS = BS.BasisSurface(); | |
410 | return CanUseEdges(aS->Surface()); | |
411 | } | |
412 | else if(aST == GeomAbs_BSplineSurface) | |
413 | { | |
414 | Handle(Geom_BSplineSurface) aBSpl = BS.BSpline(); | |
415 | if((aBSpl->UDegree() == 1 && aBSpl->NbUKnots() == 2) || | |
416 | (aBSpl->VDegree() == 1 && aBSpl->NbVKnots() == 2)) | |
417 | { | |
418 | return Standard_True; | |
419 | } | |
420 | else | |
421 | { | |
422 | return Standard_False; | |
423 | } | |
424 | } | |
425 | else if(aST == GeomAbs_BezierSurface) | |
426 | { | |
427 | Handle(Geom_BezierSurface) aBz = BS.Bezier(); | |
428 | if((aBz->UDegree() == 1 ) || | |
429 | (aBz->VDegree() == 1 )) | |
430 | { | |
431 | return Standard_True; | |
432 | } | |
433 | else | |
434 | { | |
435 | return Standard_False; | |
436 | } | |
437 | } | |
438 | return Standard_False; | |
439 | } | |
440 | ||
441 | //======================================================================= | |
442 | //function : FindExactUVBounds | |
443 | //purpose : | |
444 | //======================================================================= | |
445 | void FindExactUVBounds(const TopoDS_Face FF, | |
446 | Standard_Real& umin, Standard_Real& umax, | |
447 | Standard_Real& vmin, Standard_Real& vmax, | |
448 | const Standard_Real Tol, | |
449 | Standard_Boolean& isNaturalRestriction) | |
450 | { | |
451 | TopoDS_Face F = FF; | |
452 | F.Orientation(TopAbs_FORWARD); | |
453 | TopExp_Explorer ex(F,TopAbs_EDGE); | |
454 | // | |
455 | //Check Natural restriction | |
456 | isNaturalRestriction = BRep_Tool::NaturalRestriction(F); //Can we trust this flag? | |
457 | BRepAdaptor_Surface aBAS(F, Standard_False); | |
458 | if(!isNaturalRestriction) | |
459 | { | |
460 | //Check by comparing pcurves and surface boundaries | |
461 | umin = aBAS.FirstUParameter(); | |
462 | umax = aBAS.LastUParameter(); | |
463 | vmin = aBAS.FirstVParameter(); | |
464 | vmax = aBAS.LastVParameter(); | |
465 | Standard_Boolean isUperiodic = aBAS.IsUPeriodic(), isVperiodic = aBAS.IsVPeriodic(); | |
466 | Standard_Real aT1, aT2; | |
467 | Standard_Real TolU = Max(aBAS.UResolution(Tol), Precision::PConfusion()); | |
468 | Standard_Real TolV = Max(aBAS.VResolution(Tol), Precision::PConfusion()); | |
469 | Standard_Integer Nu = 0, Nv = 0, NbEdges = 0; | |
470 | gp_Vec2d Du(1, 0), Dv(0, 1); | |
471 | gp_Pnt2d aP; | |
472 | gp_Vec2d aV; | |
473 | for (;ex.More();ex.Next()) { | |
474 | NbEdges++; | |
475 | if(NbEdges > 4) | |
476 | { | |
477 | break; | |
478 | } | |
479 | const TopoDS_Edge& aE = TopoDS::Edge(ex.Current()); | |
480 | const Handle(Geom2d_Curve) aC2D = BRep_Tool::CurveOnSurface(aE, F, aT1, aT2); | |
481 | if (aC2D.IsNull()) | |
482 | { | |
483 | break; | |
484 | } | |
485 | // | |
486 | aC2D->D1((aT1 + aT2)/2., aP, aV); | |
487 | Standard_Real magn = aV.SquareMagnitude(); | |
488 | if(magn < gp::Resolution()) | |
489 | { | |
490 | break; | |
491 | } | |
492 | else | |
493 | { | |
494 | aV /= Sqrt(magn); | |
495 | } | |
496 | Standard_Real u = aP.X(), v = aP.Y(); | |
497 | if(isUperiodic) | |
498 | { | |
499 | ElCLib::InPeriod(u, umin, umax); | |
500 | } | |
501 | if(isVperiodic) | |
502 | { | |
503 | ElCLib::InPeriod(v, vmin, vmax); | |
504 | } | |
505 | // | |
506 | if(Abs(u - umin) <= TolU || Abs(u - umax) <= TolU) | |
507 | { | |
508 | Standard_Real d = Dv * aV; | |
509 | if(1. - Abs(d) <= Precision::PConfusion()) | |
510 | { | |
511 | Nu++; | |
512 | if(Nu > 2) | |
513 | { | |
514 | break; | |
515 | } | |
516 | } | |
517 | else | |
518 | { | |
519 | break; | |
520 | } | |
521 | } | |
522 | else if(Abs(v - vmin) <= TolV || Abs(v - vmax) <= TolV) | |
523 | { | |
524 | Standard_Real d = Du * aV; | |
525 | if(1. - Abs(d) <= Precision::PConfusion()) | |
526 | { | |
527 | Nv++; | |
528 | if(Nv > 2) | |
529 | { | |
530 | break; | |
531 | } | |
532 | } | |
533 | else | |
534 | { | |
535 | break; | |
536 | } | |
537 | } | |
538 | else | |
539 | { | |
540 | break; | |
541 | } | |
542 | } | |
543 | if(Nu == 2 && Nv == 2) | |
544 | { | |
545 | isNaturalRestriction = Standard_True; | |
546 | } | |
547 | } | |
548 | // | |
549 | if(isNaturalRestriction) | |
550 | { | |
551 | umin = aBAS.FirstUParameter(); | |
552 | umax = aBAS.LastUParameter(); | |
553 | vmin = aBAS.FirstVParameter(); | |
554 | vmax = aBAS.LastVParameter(); | |
555 | return; | |
556 | } | |
557 | ||
558 | // fill box for the given face | |
559 | Standard_Real aT1, aT2; | |
560 | Standard_Real TolU = Max(aBAS.UResolution(Tol), Precision::PConfusion()); | |
561 | Standard_Real TolV = Max(aBAS.VResolution(Tol), Precision::PConfusion()); | |
562 | Standard_Real TolUV = Max(TolU, TolV); | |
563 | Bnd_Box2d aBox; | |
564 | ex.Init(F,TopAbs_EDGE); | |
565 | for (;ex.More();ex.Next()) { | |
566 | const TopoDS_Edge& aE = TopoDS::Edge(ex.Current()); | |
567 | const Handle(Geom2d_Curve) aC2D = BRep_Tool::CurveOnSurface(aE, F, aT1, aT2); | |
568 | if (aC2D.IsNull()) | |
569 | { | |
570 | continue; | |
571 | } | |
572 | // | |
573 | BndLib_Add2dCurve::AddOptimal(aC2D, aT1, aT2, TolUV, aBox); | |
574 | // | |
575 | } | |
576 | // | |
577 | aBox.Get(umin, vmin, umax, vmax); | |
578 | // | |
579 | TopLoc_Location aLoc; | |
580 | Handle(Geom_Surface) aS = BRep_Tool::Surface(FF, aLoc); | |
581 | Standard_Real aUmin, aUmax, aVmin, aVmax; | |
582 | aS->Bounds(aUmin, aUmax, aVmin, aVmax); | |
583 | if(!aS->IsUPeriodic()) | |
584 | { | |
585 | umin = Max(aUmin, umin); | |
586 | umax = Min(aUmax, umax); | |
587 | } | |
588 | else | |
589 | { | |
590 | if(umax - umin > aS->UPeriod()) | |
591 | { | |
592 | Standard_Real delta = umax - umin - aS->UPeriod(); | |
593 | umin += delta/2.; | |
594 | umax -= delta/2; | |
595 | } | |
596 | } | |
597 | // | |
598 | if(!aS->IsVPeriodic()) | |
599 | { | |
600 | vmin = Max(aVmin, vmin); | |
601 | vmax = Min(aVmax, vmax); | |
602 | } | |
603 | else | |
604 | { | |
605 | if(vmax - vmin > aS->VPeriod()) | |
606 | { | |
607 | Standard_Real delta = vmax - vmin - aS->VPeriod(); | |
608 | vmin += delta/2.; | |
609 | vmax -= delta/2; | |
610 | } | |
611 | } | |
612 | } | |
613 | //======================================================================= | |
614 | //function : Reorder | |
615 | //purpose : | |
616 | //======================================================================= | |
617 | inline void Reorder(Standard_Real& a, Standard_Real& b) | |
618 | { | |
619 | if(a > b) | |
620 | { | |
621 | Standard_Real t = a; | |
622 | a = b; | |
623 | b = t; | |
624 | } | |
625 | } | |
626 | //======================================================================= | |
627 | //function : IsModifySize | |
628 | //purpose : | |
629 | //======================================================================= | |
630 | Standard_Boolean IsModifySize(const BRepAdaptor_Surface& theBS, | |
631 | const gp_Pln& thePln, const gp_Pnt& theP, | |
632 | const Standard_Real umin, const Standard_Real umax, | |
633 | const Standard_Real vmin, const Standard_Real vmax, | |
634 | const BRepTopAdaptor_FClass2d& theFClass, | |
635 | const Standard_Real theTolU, const Standard_Real theTolV) | |
636 | { | |
637 | Standard_Real pu1 = 0, pu2, pv1 = 0, pv2; | |
638 | ElSLib::PlaneParameters(thePln.Position(), theP, pu2, pv2); | |
639 | Reorder(pu1, pu2); | |
640 | Reorder(pv1, pv2); | |
641 | Handle(Geom_Plane) aPlane = new Geom_Plane(thePln); | |
642 | GeomAdaptor_Surface aGAPln(aPlane, pu1, pu2, pv1, pv2); | |
643 | Extrema_ExtSS anExtr(aGAPln, theBS, pu1, pu2, pv1, pv2, umin, umax, vmin, vmax, theTolU, theTolV); | |
644 | if(anExtr.IsDone()) | |
645 | { | |
646 | if(anExtr.NbExt() > 0) | |
647 | { | |
648 | Standard_Integer i, imin = 0;; | |
649 | Standard_Real dmin = RealLast(); | |
650 | Standard_Real uextr = 0., vextr = 0.; | |
651 | Extrema_POnSurf P1, P2; | |
652 | for(i = 1; i <= anExtr.NbExt(); ++i) | |
653 | { | |
654 | Standard_Real d = anExtr.SquareDistance(i); | |
655 | if(d < dmin) | |
656 | { | |
657 | imin = i; | |
658 | dmin = d; | |
659 | } | |
660 | } | |
661 | if(imin > 0) | |
662 | { | |
663 | anExtr.Points(imin, P1, P2); | |
664 | P2.Parameter(uextr, vextr); | |
665 | } | |
666 | else | |
667 | { | |
668 | return Standard_False; | |
669 | } | |
670 | // | |
671 | gp_Pnt2d aP2d(uextr, vextr); | |
672 | TopAbs_State aSt = theFClass.Perform(aP2d); | |
673 | if(aSt == TopAbs_OUT) | |
674 | { | |
675 | return Standard_True; | |
676 | } | |
677 | } | |
678 | else | |
679 | { | |
680 | return Standard_True; //extrema point seems to be out of face UV bounds | |
681 | } | |
682 | } | |
683 | // | |
684 | return Standard_False; | |
685 | } | |
686 | // | |
687 | //======================================================================= | |
688 | //function : AdjustFaceBox | |
689 | //purpose : | |
690 | //======================================================================= | |
691 | void AdjustFaceBox(const BRepAdaptor_Surface& BS, | |
692 | const Standard_Real umin, const Standard_Real umax, | |
693 | const Standard_Real vmin, const Standard_Real vmax, | |
694 | Bnd_Box& FaceBox, | |
695 | const Bnd_Box& EdgeBox, const Standard_Real Tol) | |
696 | { | |
697 | Standard_Real fxmin, fymin, fzmin, fxmax, fymax, fzmax; | |
698 | Standard_Real exmin, eymin, ezmin, exmax, eymax, ezmax; | |
699 | // | |
700 | FaceBox.Get(fxmin, fymin, fzmin, fxmax, fymax, fzmax); | |
701 | EdgeBox.Get(exmin, eymin, ezmin, exmax, eymax, ezmax); | |
702 | // | |
703 | Standard_Real TolU = Max(BS.UResolution(Tol), Precision::PConfusion()); | |
704 | Standard_Real TolV = Max(BS.VResolution(Tol), Precision::PConfusion()); | |
705 | BRepTopAdaptor_FClass2d FClass(BS.Face(), Max(TolU, TolV)); | |
706 | // | |
707 | Standard_Boolean isModified = Standard_False; | |
708 | if(exmin > fxmin) | |
709 | { | |
710 | // | |
711 | gp_Pln pl(gp_Ax3(gp_Pnt(fxmin, fymin, fzmin), gp::DX())); | |
712 | gp_Pnt aP(fxmin, fymax, fzmax); | |
713 | if(IsModifySize(BS, pl, aP, | |
714 | umin, umax, vmin, vmax, FClass, TolU, TolV)) | |
715 | { | |
716 | fxmin = exmin; | |
717 | isModified = Standard_True; | |
718 | } | |
719 | } | |
720 | if(exmax < fxmax) | |
721 | { | |
722 | // | |
723 | gp_Pln pl(gp_Ax3(gp_Pnt(fxmax, fymax, fzmax), gp::DX())); | |
724 | gp_Pnt aP(fxmax, fymin, fzmin); | |
725 | if(IsModifySize(BS, pl, aP, | |
726 | umin, umax, vmin, vmax, FClass, TolU, TolV)) | |
727 | { | |
728 | fxmax = exmax; | |
729 | isModified = Standard_True; | |
730 | } | |
731 | } | |
732 | // | |
733 | if(eymin > fymin) | |
734 | { | |
735 | // | |
736 | gp_Pln pl(gp_Ax3(gp_Pnt(fxmin, fymin, fzmin), gp::DY())); | |
737 | gp_Pnt aP(fxmax, fymin, fzmax); | |
738 | if(IsModifySize(BS, pl, aP, | |
739 | umin, umax, vmin, vmax, FClass, TolU, TolV)) | |
740 | { | |
741 | fymin = eymin; | |
742 | isModified = Standard_True; | |
743 | } | |
744 | } | |
745 | if(eymax < fymax) | |
746 | { | |
747 | // | |
748 | gp_Pln pl(gp_Ax3(gp_Pnt(fxmax, fymax, fzmax), gp::DY())); | |
749 | gp_Pnt aP(fxmin, fymax, fzmin); | |
750 | if(IsModifySize(BS, pl, aP, | |
751 | umin, umax, vmin, vmax, FClass, TolU, TolV)) | |
752 | { | |
753 | fymax = eymax; | |
754 | isModified = Standard_True; | |
755 | } | |
756 | } | |
757 | // | |
758 | if(ezmin > fzmin) | |
759 | { | |
760 | // | |
761 | gp_Pln pl(gp_Ax3(gp_Pnt(fxmin, fymin, fzmin), gp::DZ())); | |
762 | gp_Pnt aP(fxmax, fymax, fzmin); | |
763 | if(IsModifySize(BS, pl, aP, | |
764 | umin, umax, vmin, vmax, FClass, TolU, TolV)) | |
765 | { | |
766 | fzmin = ezmin; | |
767 | isModified = Standard_True; | |
768 | } | |
769 | } | |
770 | if(ezmax < fzmax) | |
771 | { | |
772 | // | |
773 | gp_Pln pl(gp_Ax3(gp_Pnt(fxmax, fymax, fzmax), gp::DZ())); | |
774 | gp_Pnt aP(fxmin, fymin, fzmax); | |
775 | if(IsModifySize(BS, pl, aP, | |
776 | umin, umax, vmin, vmax, FClass, TolU, TolV)) | |
777 | { | |
778 | fzmax = ezmax; | |
779 | isModified = Standard_True; | |
780 | } | |
781 | } | |
782 | // | |
783 | if(isModified) | |
784 | { | |
785 | FaceBox.SetVoid(); | |
786 | FaceBox.Update(fxmin, fymin, fzmin, fxmax, fymax, fzmax); | |
787 | } | |
788 | } | |
789 |