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