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