0029311: Implementation of the Oriented Bounding Boxes (OBB) functionality
[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()) {
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
189void 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//=======================================================================
215void 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//=======================================================================
385Standard_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//=======================================================================
445void 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//=======================================================================
617inline 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//=======================================================================
630Standard_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//=======================================================================
691void 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