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