0030428: Modeling Algorithms - BRepBndLib::AddOBB() throws exception on empty Compound
[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());
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
193void 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//=======================================================================
223void 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//=======================================================================
393Standard_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//=======================================================================
453void 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//=======================================================================
625inline 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//=======================================================================
638Standard_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//=======================================================================
699void 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