+// Copyright (c) 1995-1999 Matra Datavision
+// Copyright (c) 1999-2014 OPEN CASCADE SAS
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
-#include <BRepBndLib.ixx>
-#include <TopExp_Explorer.hxx>
-#include <BRepAdaptor_Surface.hxx>
-#include <BRepAdaptor_Curve.hxx>
-#include <BRep_Tool.hxx>
-#include <TopoDS.hxx>
+
+#include <Bnd_Box.hxx>
#include <BndLib_Add3dCurve.hxx>
#include <BndLib_AddSurface.hxx>
-#include <Geom_Surface.hxx>
-#include <TopLoc_Location.hxx>
-#include <Poly_Triangulation.hxx>
-#include <Poly_PolygonOnTriangulation.hxx>
-#include <Poly_Polygon3D.hxx>
#include <BRep_Polygon3D.hxx>
-#include <TColStd_HArray1OfInteger.hxx>
-#include <TColStd_Array1OfInteger.hxx>
-#include <TColgp_Array1OfPnt.hxx>
+#include <BRep_Tool.hxx>
+#include <BRepAdaptor_Curve.hxx>
+#include <BRepAdaptor_Surface.hxx>
+#include <BRepBndLib.hxx>
#include <Geom_Curve.hxx>
+#include <Geom_Surface.hxx>
#include <GeomAdaptor_Curve.hxx>
-#include <BndLib_Add3dCurve.hxx>
-
+#include <Poly_Polygon3D.hxx>
+#include <Poly_PolygonOnTriangulation.hxx>
+#include <Poly_Triangulation.hxx>
+#include <TColgp_Array1OfPnt.hxx>
+#include <TColStd_Array1OfInteger.hxx>
+#include <TColStd_HArray1OfInteger.hxx>
+#include <TopExp_Explorer.hxx>
+#include <TopLoc_Location.hxx>
+#include <TopoDS.hxx>
+#include <TopoDS_Shape.hxx>
+#include <Adaptor3d_HCurve.hxx>
+#include <Adaptor3d_HSurface.hxx>
+#include <BRepTools.hxx>
+#include <Geom_BSplineSurface.hxx>
+#include <Geom_BezierSurface.hxx>
+#include <Bnd_Box2d.hxx>
+#include <BndLib_Add2dCurve.hxx>
+#include <BRepTopAdaptor_FClass2d.hxx>
+#include <ElSLib.hxx>
+#include <ElCLib.hxx>
+#include <Geom_Plane.hxx>
+#include <Extrema_ExtSS.hxx>
+#include <GeomAdaptor_Surface.hxx>
+//
+static Standard_Boolean CanUseEdges(const Adaptor3d_Surface& BS);
+//
+static void FindExactUVBounds(const TopoDS_Face F,
+ Standard_Real& umin, Standard_Real& umax,
+ Standard_Real& vmin, Standard_Real& vmax,
+ const Standard_Real Tol,
+ Standard_Boolean& isNaturalRestriction);
+//
+static void AdjustFaceBox(const BRepAdaptor_Surface& BS,
+ const Standard_Real umin, const Standard_Real umax,
+ const Standard_Real vmin, const Standard_Real vmax,
+ Bnd_Box& FaceBox,
+ const Bnd_Box& EdgeBox, const Standard_Real Tol);
+//
+static Standard_Boolean IsModifySize(const BRepAdaptor_Surface& theBS,
+ const gp_Pln& thePln, const gp_Pnt& theP,
+ const Standard_Real umin, const Standard_Real umax,
+ const Standard_Real vmin, const Standard_Real vmax,
+ const BRepTopAdaptor_FClass2d& theFClass,
+ const Standard_Real theTolU, const Standard_Real theTolV);
+//
//=======================================================================
//function : Add
//purpose : Add a shape bounding to a box
//=======================================================================
-
-void BRepBndLib::Add(const TopoDS_Shape& S, Bnd_Box& B)
+void BRepBndLib::Add(const TopoDS_Shape& S, Bnd_Box& B, Standard_Boolean useTriangulation)
{
TopExp_Explorer ex;
// Add the faces
-
BRepAdaptor_Surface BS;
- Handle(Geom_Surface) GS;
- Handle(Poly_Triangulation) T;
- TopLoc_Location l;
+ TopLoc_Location l, aDummyLoc;
Standard_Integer i, nbNodes;
BRepAdaptor_Curve BC;
for (ex.Init(S,TopAbs_FACE); ex.More(); ex.Next()) {
const TopoDS_Face& F = TopoDS::Face(ex.Current());
- T = BRep_Tool::Triangulation(F, l);
- if (!T.IsNull()) {
+ const Handle(Poly_Triangulation)& T = BRep_Tool::Triangulation(F, l);
+ const Handle(Geom_Surface)& GS = BRep_Tool::Surface (F, aDummyLoc);
+ if ((useTriangulation || GS.IsNull()) && !T.IsNull())
+ {
nbNodes = T->NbNodes();
const TColgp_Array1OfPnt& Nodes = T->Nodes();
for (i = 1; i <= nbNodes; i++) {
- if (l.IsIdentity()) B.Add(Nodes(i));
- else B.Add(Nodes(i).Transformed(l));
+ if (l.IsIdentity()) B.Add(Nodes(i));
+ else B.Add(Nodes(i).Transformed(l));
}
// B.Enlarge(T->Deflection());
B.Enlarge(T->Deflection() + BRep_Tool::Tolerance(F));
- }
- else {
- GS = BRep_Tool::Surface(F, l);
+ } else
+ {
if (!GS.IsNull()) {
- BS.Initialize(F, Standard_False);
- if (BS.GetType() != GeomAbs_Plane) {
- BS.Initialize(F);
- BndLib_AddSurface::Add(BS, BRep_Tool::Tolerance(F), B);
- }
- else {
- // on travaille directement sur les courbes 3d.
- TopExp_Explorer ex2(F, TopAbs_EDGE);
- if (!ex2.More()) {
- BS.Initialize(F);
- BndLib_AddSurface::Add(BS, BRep_Tool::Tolerance(F), B);
- }
- else {
- for (;ex2.More();ex2.Next()) {
- BC.Initialize(TopoDS::Edge(ex2.Current()));
- BndLib_Add3dCurve::Add(BC, BRep_Tool::Tolerance(F), B);
- }
- B.Enlarge(BRep_Tool::Tolerance(F));
- }
- }
+ BS.Initialize(F, Standard_False);
+ if (BS.GetType() != GeomAbs_Plane) {
+ BS.Initialize(F);
+ BndLib_AddSurface::Add(BS, BRep_Tool::Tolerance(F), B);
+ }
+ else {
+ // on travaille directement sur les courbes 3d.
+ TopExp_Explorer ex2(F, TopAbs_EDGE);
+ if (!ex2.More()) {
+ BS.Initialize(F);
+ BndLib_AddSurface::Add(BS, BRep_Tool::Tolerance(F), B);
+ }
+ else {
+ for (;ex2.More();ex2.Next()) {
+ BC.Initialize(TopoDS::Edge(ex2.Current()));
+ BndLib_Add3dCurve::Add(BC, BRep_Tool::Tolerance(F), B);
+ }
+ B.Enlarge(BRep_Tool::Tolerance(F));
+ }
+ }
}
}
}
// Add the edges not in faces
-
-
Handle(TColStd_HArray1OfInteger) HIndices;
Handle(Poly_PolygonOnTriangulation) Poly;
-
- for (ex.Init(S,TopAbs_EDGE,TopAbs_FACE); ex.More(); ex.Next()) {
+ Handle(Poly_Triangulation) T;
+ for (ex.Init(S,TopAbs_EDGE,TopAbs_FACE); ex.More(); ex.Next())
+ {
const TopoDS_Edge& E = TopoDS::Edge(ex.Current());
Handle(Poly_Polygon3D) P3d = BRep_Tool::Polygon3D(E, l);
- if (!P3d.IsNull()) {
+ if (!P3d.IsNull())
+ {
const TColgp_Array1OfPnt& Nodes = P3d->Nodes();
nbNodes = P3d->NbNodes();
- for (i = 1; i <= nbNodes; i++) {
- if (l.IsIdentity()) B.Add(Nodes(i));
- else B.Add(Nodes(i).Transformed(l));
+ for (i = 1; i <= nbNodes; i++)
+ {
+ if (l.IsIdentity()) B.Add(Nodes(i));
+ else B.Add(Nodes(i).Transformed(l));
}
// B.Enlarge(P3d->Deflection());
B.Enlarge(P3d->Deflection() + BRep_Tool::Tolerance(E));
}
- else {
+ else
+ {
BRep_Tool::PolygonOnTriangulation(E, Poly, T, l);
- if (!Poly.IsNull()) {
- const TColStd_Array1OfInteger& Indices = Poly->Nodes();
- const TColgp_Array1OfPnt& Nodes = T->Nodes();
- nbNodes = Indices.Length();
- for (i = 1; i <= nbNodes; i++) {
- if (l.IsIdentity()) B.Add(Nodes(Indices(i)));
- else B.Add(Nodes(Indices(i)).Transformed(l));
- }
- // B.Enlarge(T->Deflection());
- B.Enlarge(Poly->Deflection() + BRep_Tool::Tolerance(E));
+ if (useTriangulation && !Poly.IsNull())
+ {
+ const TColStd_Array1OfInteger& Indices = Poly->Nodes();
+ const TColgp_Array1OfPnt& Nodes = T->Nodes();
+ nbNodes = Indices.Length();
+ for (i = 1; i <= nbNodes; i++)
+ {
+ if (l.IsIdentity()) B.Add(Nodes(Indices(i)));
+ else B.Add(Nodes(Indices(i)).Transformed(l));
+ }
+ // B.Enlarge(T->Deflection());
+ B.Enlarge(Poly->Deflection() + BRep_Tool::Tolerance(E));
}
else {
- if (BRep_Tool::IsGeometric(E)) {
- BC.Initialize(E);
- BndLib_Add3dCurve::Add(BC, BRep_Tool::Tolerance(E), B);
- }
+ if (BRep_Tool::IsGeometric(E))
+ {
+ BC.Initialize(E);
+ BndLib_Add3dCurve::Add(BC, BRep_Tool::Tolerance(E), B);
+ }
}
}
}
}
}
+//=======================================================================
+//function : AddOptimal
+//purpose : Add a shape bounding to a box
+//=======================================================================
+void BRepBndLib::AddOptimal(const TopoDS_Shape& S, Bnd_Box& B,
+ const Standard_Boolean useTriangulation,
+ const Standard_Boolean useShapeTolerance)
+{
+ TopExp_Explorer ex;
+
+ // Add the faces
+ BRepAdaptor_Surface BS;
+ Handle(Poly_Triangulation) T;
+ TopLoc_Location l;
+ Standard_Integer i, nbNodes;
+ BRepAdaptor_Curve BC;
+
+ for (ex.Init(S,TopAbs_FACE); ex.More(); ex.Next()) {
+ const TopoDS_Face& F = TopoDS::Face(ex.Current());
+ T = BRep_Tool::Triangulation(F, l);
+ Bnd_Box aLocBox;
+ if (useTriangulation && !T.IsNull())
+ {
+ nbNodes = T->NbNodes();
+ const TColgp_Array1OfPnt& Nodes = T->Nodes();
+ for (i = 1; i <= nbNodes; i++) {
+ if (l.IsIdentity()) aLocBox.Add(Nodes(i));
+ else aLocBox.Add(Nodes(i).Transformed(l));
+ }
+ // B.Enlarge(T->Deflection());
+ aLocBox.Enlarge(T->Deflection() + BRep_Tool::Tolerance(F));
+ Standard_Real xmin, ymin, zmin, xmax, ymax, zmax;
+ aLocBox.Get(xmin, ymin, zmin, xmax, ymax, zmax);
+ B.Update(xmin, ymin, zmin, xmax, ymax, zmax);
+ }
+ else
+ {
+ const Handle(Geom_Surface)& GS = BRep_Tool::Surface(F, l);
+ if (!GS.IsNull()) {
+ BS.Initialize(F, Standard_False);
+ if (CanUseEdges(BS)) {
+ TopExp_Explorer ex2(F, TopAbs_EDGE);
+ if (!ex2.More()) {
+ BS.Initialize(F);
+ Standard_Real Tol = useShapeTolerance? BRep_Tool::Tolerance(F) : 0.;
+ BndLib_AddSurface::AddOptimal(BS, Tol, aLocBox);
+ }
+ else
+ {
+ Standard_Real Tol;
+ for (;ex2.More();ex2.Next()) {
+ Bnd_Box anEBox;
+ const TopoDS_Edge& anE = TopoDS::Edge(ex2.Current());
+ if(BRep_Tool::Degenerated(anE))
+ {
+ continue;
+ }
+ BC.Initialize(anE);
+ Tol = useShapeTolerance? BRep_Tool::Tolerance(anE) : 0.;
+ BndLib_Add3dCurve::AddOptimal(BC, Tol, anEBox);
+ aLocBox.Add(anEBox);
+ }
+ }
+ }
+ else
+ {
+ Standard_Real umin, umax, vmin, vmax;
+ Standard_Boolean isNaturalRestriction = Standard_False;
+ Standard_Real Tol = useShapeTolerance? BRep_Tool::Tolerance(F) : 0.;
+ FindExactUVBounds(F, umin, umax, vmin, vmax, Tol, isNaturalRestriction);
+ BndLib_AddSurface::AddOptimal(BS, umin, umax, vmin, vmax,
+ Tol, aLocBox);
+ //
+ if(!isNaturalRestriction)
+ {
+ TopExp_Explorer ex2(F, TopAbs_EDGE);
+ Bnd_Box EBox;
+ for (;ex2.More();ex2.Next()) {
+ Bnd_Box anEBox;
+ const TopoDS_Edge& anE = TopoDS::Edge(ex2.Current());
+ if(BRep_Tool::Degenerated(anE))
+ {
+ continue;
+ }
+ BC.Initialize(anE);
+ Tol = useShapeTolerance? BRep_Tool::Tolerance(anE) : 0.;
+ BndLib_Add3dCurve::AddOptimal(BC, Tol, anEBox);
+ EBox.Add(anEBox);
+ }
+ Tol = useShapeTolerance? BRep_Tool::Tolerance(F) : 0.;
+ AdjustFaceBox(BS, umin, umax, vmin, vmax, aLocBox, EBox,
+ Tol);
+ }
+ }
+ Standard_Real xmin, ymin, zmin, xmax, ymax, zmax;
+ aLocBox.Get(xmin, ymin, zmin, xmax, ymax, zmax);
+ B.Update(xmin, ymin, zmin, xmax, ymax, zmax);
+ }
+ }
+ }
+
+ // Add the edges not in faces
+ Handle(TColStd_HArray1OfInteger) HIndices;
+ Handle(Poly_PolygonOnTriangulation) Poly;
+
+ for (ex.Init(S,TopAbs_EDGE,TopAbs_FACE); ex.More(); ex.Next())
+ {
+ const TopoDS_Edge& E = TopoDS::Edge(ex.Current());
+ Bnd_Box aLocBox;
+ Handle(Poly_Polygon3D) P3d = BRep_Tool::Polygon3D(E, l);
+ if (useTriangulation && (!P3d.IsNull()))
+ {
+ const TColgp_Array1OfPnt& Nodes = P3d->Nodes();
+ nbNodes = P3d->NbNodes();
+ for (i = 1; i <= nbNodes; i++)
+ {
+ if (l.IsIdentity()) aLocBox.Add(Nodes(i));
+ else aLocBox.Add(Nodes(i).Transformed(l));
+ }
+ Standard_Real Tol = useShapeTolerance? BRep_Tool::Tolerance(E) : 0.;
+ aLocBox.Enlarge(P3d->Deflection() + Tol);
+ }
+ else
+ {
+ BRep_Tool::PolygonOnTriangulation(E, Poly, T, l);
+ if (useTriangulation && !Poly.IsNull())
+ {
+ const TColStd_Array1OfInteger& Indices = Poly->Nodes();
+ const TColgp_Array1OfPnt& Nodes = T->Nodes();
+ nbNodes = Indices.Length();
+ for (i = 1; i <= nbNodes; i++)
+ {
+ if (l.IsIdentity()) aLocBox.Add(Nodes(Indices(i)));
+ else aLocBox.Add(Nodes(Indices(i)).Transformed(l));
+ }
+ Standard_Real Tol = useShapeTolerance? BRep_Tool::Tolerance(E) : 0.;
+ aLocBox.Enlarge(Poly->Deflection() + Tol);
+ }
+ else {
+ if (BRep_Tool::IsGeometric(E))
+ {
+ BC.Initialize(E);
+ Standard_Real Tol = useShapeTolerance? BRep_Tool::Tolerance(E) : 0.;
+ BndLib_Add3dCurve::AddOptimal(BC, Tol, aLocBox);
+ }
+ }
+ }
+ if (!aLocBox.IsVoid())
+ {
+ Standard_Real xmin, ymin, zmin, xmax, ymax, zmax;
+ aLocBox.Get(xmin, ymin, zmin, xmax, ymax, zmax);
+ B.Update(xmin, ymin, zmin, xmax, ymax, zmax);
+ }
+ }
+
+ // Add the vertices not in edges
+
+ for (ex.Init(S,TopAbs_VERTEX,TopAbs_EDGE); ex.More(); ex.Next()) {
+ Bnd_Box aLocBox;
+ const TopoDS_Vertex& aV = TopoDS::Vertex(ex.Current());
+ aLocBox.Add(BRep_Tool::Pnt(aV));
+ Standard_Real Tol = useShapeTolerance? BRep_Tool::Tolerance(aV) : 0.;
+ aLocBox.Enlarge(Tol);
+ Standard_Real xmin, ymin, zmin, xmax, ymax, zmax;
+ aLocBox.Get(xmin, ymin, zmin, xmax, ymax, zmax);
+ B.Update(xmin, ymin, zmin, xmax, ymax, zmax);
+ }
+}
+
+//=======================================================================
+//function : CanUseEdges
+//purpose : Define is it possible using only edges bnd boxes
+// to get face bnd box
+//=======================================================================
+Standard_Boolean CanUseEdges(const Adaptor3d_Surface& BS)
+{
+ GeomAbs_SurfaceType aST = BS.GetType();
+ if(aST == GeomAbs_Plane ||
+ aST == GeomAbs_Cylinder ||
+ aST == GeomAbs_Cone ||
+ aST == GeomAbs_SurfaceOfExtrusion)
+ {
+ return Standard_True;
+ }
+ else if(aST == GeomAbs_SurfaceOfRevolution)
+ {
+ const Handle(Adaptor3d_HCurve)& aBC = BS.BasisCurve();
+ if(aBC->GetType() == GeomAbs_Line)
+ {
+ return Standard_True;
+ }
+ else
+ {
+ return Standard_False;
+ }
+ }
+ else if(aST == GeomAbs_OffsetSurface)
+ {
+ const Handle(Adaptor3d_HSurface)& aS = BS.BasisSurface();
+ return CanUseEdges(aS->Surface());
+ }
+ else if(aST == GeomAbs_BSplineSurface)
+ {
+ Handle(Geom_BSplineSurface) aBSpl = BS.BSpline();
+ if((aBSpl->UDegree() == 1 && aBSpl->NbUKnots() == 2) ||
+ (aBSpl->VDegree() == 1 && aBSpl->NbVKnots() == 2))
+ {
+ return Standard_True;
+ }
+ else
+ {
+ return Standard_False;
+ }
+ }
+ else if(aST == GeomAbs_BezierSurface)
+ {
+ Handle(Geom_BezierSurface) aBz = BS.Bezier();
+ if((aBz->UDegree() == 1 ) ||
+ (aBz->VDegree() == 1 ))
+ {
+ return Standard_True;
+ }
+ else
+ {
+ return Standard_False;
+ }
+ }
+ return Standard_False;
+}
+
+//=======================================================================
+//function : FindExactUVBounds
+//purpose :
+//=======================================================================
+void FindExactUVBounds(const TopoDS_Face FF,
+ Standard_Real& umin, Standard_Real& umax,
+ Standard_Real& vmin, Standard_Real& vmax,
+ const Standard_Real Tol,
+ Standard_Boolean& isNaturalRestriction)
+{
+ TopoDS_Face F = FF;
+ F.Orientation(TopAbs_FORWARD);
+ TopExp_Explorer ex(F,TopAbs_EDGE);
+ //
+ //Check Natural restriction
+ isNaturalRestriction = BRep_Tool::NaturalRestriction(F); //Can we trust this flag?
+ BRepAdaptor_Surface aBAS(F, Standard_False);
+ if(!isNaturalRestriction)
+ {
+ //Check by comparing pcurves and surface boundaries
+ umin = aBAS.FirstUParameter();
+ umax = aBAS.LastUParameter();
+ vmin = aBAS.FirstVParameter();
+ vmax = aBAS.LastVParameter();
+ Standard_Boolean isUperiodic = aBAS.IsUPeriodic(), isVperiodic = aBAS.IsVPeriodic();
+ Standard_Real aT1, aT2;
+ Standard_Real TolU = Max(aBAS.UResolution(Tol), Precision::PConfusion());
+ Standard_Real TolV = Max(aBAS.VResolution(Tol), Precision::PConfusion());
+ Standard_Integer Nu = 0, Nv = 0, NbEdges = 0;
+ gp_Vec2d Du(1, 0), Dv(0, 1);
+ gp_Pnt2d aP;
+ gp_Vec2d aV;
+ for (;ex.More();ex.Next()) {
+ NbEdges++;
+ if(NbEdges > 4)
+ {
+ break;
+ }
+ const TopoDS_Edge& aE = TopoDS::Edge(ex.Current());
+ const Handle(Geom2d_Curve) aC2D = BRep_Tool::CurveOnSurface(aE, F, aT1, aT2);
+ if (aC2D.IsNull())
+ {
+ break;
+ }
+ //
+ aC2D->D1((aT1 + aT2)/2., aP, aV);
+ Standard_Real magn = aV.SquareMagnitude();
+ if(magn < gp::Resolution())
+ {
+ break;
+ }
+ else
+ {
+ aV /= Sqrt(magn);
+ }
+ Standard_Real u = aP.X(), v = aP.Y();
+ if(isUperiodic)
+ {
+ ElCLib::InPeriod(u, umin, umax);
+ }
+ if(isVperiodic)
+ {
+ ElCLib::InPeriod(v, vmin, vmax);
+ }
+ //
+ if(Abs(u - umin) <= TolU || Abs(u - umax) <= TolU)
+ {
+ Standard_Real d = Dv * aV;
+ if(1. - Abs(d) <= Precision::PConfusion())
+ {
+ Nu++;
+ if(Nu > 2)
+ {
+ break;
+ }
+ }
+ else
+ {
+ break;
+ }
+ }
+ else if(Abs(v - vmin) <= TolV || Abs(v - vmax) <= TolV)
+ {
+ Standard_Real d = Du * aV;
+ if(1. - Abs(d) <= Precision::PConfusion())
+ {
+ Nv++;
+ if(Nv > 2)
+ {
+ break;
+ }
+ }
+ else
+ {
+ break;
+ }
+ }
+ else
+ {
+ break;
+ }
+ }
+ if(Nu == 2 && Nv == 2)
+ {
+ isNaturalRestriction = Standard_True;
+ }
+ }
+ //
+ if(isNaturalRestriction)
+ {
+ umin = aBAS.FirstUParameter();
+ umax = aBAS.LastUParameter();
+ vmin = aBAS.FirstVParameter();
+ vmax = aBAS.LastVParameter();
+ return;
+ }
+
+ // fill box for the given face
+ Standard_Real aT1, aT2;
+ Standard_Real TolU = Max(aBAS.UResolution(Tol), Precision::PConfusion());
+ Standard_Real TolV = Max(aBAS.VResolution(Tol), Precision::PConfusion());
+ Standard_Real TolUV = Max(TolU, TolV);
+ Bnd_Box2d aBox;
+ ex.Init(F,TopAbs_EDGE);
+ for (;ex.More();ex.Next()) {
+ const TopoDS_Edge& aE = TopoDS::Edge(ex.Current());
+ const Handle(Geom2d_Curve) aC2D = BRep_Tool::CurveOnSurface(aE, F, aT1, aT2);
+ if (aC2D.IsNull())
+ {
+ continue;
+ }
+ //
+ BndLib_Add2dCurve::AddOptimal(aC2D, aT1, aT2, TolUV, aBox);
+ //
+ }
+ //
+ aBox.Get(umin, vmin, umax, vmax);
+ //
+ TopLoc_Location aLoc;
+ Handle(Geom_Surface) aS = BRep_Tool::Surface(FF, aLoc);
+ Standard_Real aUmin, aUmax, aVmin, aVmax;
+ aS->Bounds(aUmin, aUmax, aVmin, aVmax);
+ if(!aS->IsUPeriodic())
+ {
+ umin = Max(aUmin, umin);
+ umax = Min(aUmax, umax);
+ }
+ else
+ {
+ if(umax - umin > aS->UPeriod())
+ {
+ Standard_Real delta = umax - umin - aS->UPeriod();
+ umin += delta/2.;
+ umax -= delta/2;
+ }
+ }
+ //
+ if(!aS->IsVPeriodic())
+ {
+ vmin = Max(aVmin, vmin);
+ vmax = Min(aVmax, vmax);
+ }
+ else
+ {
+ if(vmax - vmin > aS->VPeriod())
+ {
+ Standard_Real delta = vmax - vmin - aS->VPeriod();
+ vmin += delta/2.;
+ vmax -= delta/2;
+ }
+ }
+}
+//=======================================================================
+//function : Reorder
+//purpose :
+//=======================================================================
+inline void Reorder(Standard_Real& a, Standard_Real& b)
+{
+ if(a > b)
+ {
+ Standard_Real t = a;
+ a = b;
+ b = t;
+ }
+}
+//=======================================================================
+//function : IsModifySize
+//purpose :
+//=======================================================================
+Standard_Boolean IsModifySize(const BRepAdaptor_Surface& theBS,
+ const gp_Pln& thePln, const gp_Pnt& theP,
+ const Standard_Real umin, const Standard_Real umax,
+ const Standard_Real vmin, const Standard_Real vmax,
+ const BRepTopAdaptor_FClass2d& theFClass,
+ const Standard_Real theTolU, const Standard_Real theTolV)
+{
+ Standard_Real pu1 = 0, pu2, pv1 = 0, pv2;
+ ElSLib::PlaneParameters(thePln.Position(), theP, pu2, pv2);
+ Reorder(pu1, pu2);
+ Reorder(pv1, pv2);
+ Handle(Geom_Plane) aPlane = new Geom_Plane(thePln);
+ GeomAdaptor_Surface aGAPln(aPlane, pu1, pu2, pv1, pv2);
+ Extrema_ExtSS anExtr(aGAPln, theBS, pu1, pu2, pv1, pv2, umin, umax, vmin, vmax, theTolU, theTolV);
+ if(anExtr.IsDone())
+ {
+ if(anExtr.NbExt() > 0)
+ {
+ Standard_Integer i, imin = 0;;
+ Standard_Real dmin = RealLast();
+ Standard_Real uextr = 0., vextr = 0.;
+ Extrema_POnSurf P1, P2;
+ for(i = 1; i <= anExtr.NbExt(); ++i)
+ {
+ Standard_Real d = anExtr.SquareDistance(i);
+ if(d < dmin)
+ {
+ imin = i;
+ dmin = d;
+ }
+ }
+ if(imin > 0)
+ {
+ anExtr.Points(imin, P1, P2);
+ P2.Parameter(uextr, vextr);
+ }
+ else
+ {
+ return Standard_False;
+ }
+ //
+ gp_Pnt2d aP2d(uextr, vextr);
+ TopAbs_State aSt = theFClass.Perform(aP2d);
+ if(aSt == TopAbs_OUT)
+ {
+ return Standard_True;
+ }
+ }
+ else
+ {
+ return Standard_True; //extrema point seems to be out of face UV bounds
+ }
+ }
+ //
+ return Standard_False;
+}
+//
+//=======================================================================
+//function : AdjustFaceBox
+//purpose :
+//=======================================================================
+void AdjustFaceBox(const BRepAdaptor_Surface& BS,
+ const Standard_Real umin, const Standard_Real umax,
+ const Standard_Real vmin, const Standard_Real vmax,
+ Bnd_Box& FaceBox,
+ const Bnd_Box& EdgeBox, const Standard_Real Tol)
+{
+ Standard_Real fxmin, fymin, fzmin, fxmax, fymax, fzmax;
+ Standard_Real exmin, eymin, ezmin, exmax, eymax, ezmax;
+ //
+ FaceBox.Get(fxmin, fymin, fzmin, fxmax, fymax, fzmax);
+ EdgeBox.Get(exmin, eymin, ezmin, exmax, eymax, ezmax);
+ //
+ Standard_Real TolU = Max(BS.UResolution(Tol), Precision::PConfusion());
+ Standard_Real TolV = Max(BS.VResolution(Tol), Precision::PConfusion());
+ BRepTopAdaptor_FClass2d FClass(BS.Face(), Max(TolU, TolV));
+ //
+ Standard_Boolean isModified = Standard_False;
+ if(exmin > fxmin)
+ {
+ //
+ gp_Pln pl(gp_Ax3(gp_Pnt(fxmin, fymin, fzmin), gp::DX()));
+ gp_Pnt aP(fxmin, fymax, fzmax);
+ if(IsModifySize(BS, pl, aP,
+ umin, umax, vmin, vmax, FClass, TolU, TolV))
+ {
+ fxmin = exmin;
+ isModified = Standard_True;
+ }
+ }
+ if(exmax < fxmax)
+ {
+ //
+ gp_Pln pl(gp_Ax3(gp_Pnt(fxmax, fymax, fzmax), gp::DX()));
+ gp_Pnt aP(fxmax, fymin, fzmin);
+ if(IsModifySize(BS, pl, aP,
+ umin, umax, vmin, vmax, FClass, TolU, TolV))
+ {
+ fxmax = exmax;
+ isModified = Standard_True;
+ }
+ }
+ //
+ if(eymin > fymin)
+ {
+ //
+ gp_Pln pl(gp_Ax3(gp_Pnt(fxmin, fymin, fzmin), gp::DY()));
+ gp_Pnt aP(fxmax, fymin, fzmax);
+ if(IsModifySize(BS, pl, aP,
+ umin, umax, vmin, vmax, FClass, TolU, TolV))
+ {
+ fymin = eymin;
+ isModified = Standard_True;
+ }
+ }
+ if(eymax < fymax)
+ {
+ //
+ gp_Pln pl(gp_Ax3(gp_Pnt(fxmax, fymax, fzmax), gp::DY()));
+ gp_Pnt aP(fxmin, fymax, fzmin);
+ if(IsModifySize(BS, pl, aP,
+ umin, umax, vmin, vmax, FClass, TolU, TolV))
+ {
+ fymax = eymax;
+ isModified = Standard_True;
+ }
+ }
+ //
+ if(ezmin > fzmin)
+ {
+ //
+ gp_Pln pl(gp_Ax3(gp_Pnt(fxmin, fymin, fzmin), gp::DZ()));
+ gp_Pnt aP(fxmax, fymax, fzmin);
+ if(IsModifySize(BS, pl, aP,
+ umin, umax, vmin, vmax, FClass, TolU, TolV))
+ {
+ fzmin = ezmin;
+ isModified = Standard_True;
+ }
+ }
+ if(ezmax < fzmax)
+ {
+ //
+ gp_Pln pl(gp_Ax3(gp_Pnt(fxmax, fymax, fzmax), gp::DZ()));
+ gp_Pnt aP(fxmin, fymin, fzmax);
+ if(IsModifySize(BS, pl, aP,
+ umin, umax, vmin, vmax, FClass, TolU, TolV))
+ {
+ fzmax = ezmax;
+ isModified = Standard_True;
+ }
+ }
+ //
+ if(isModified)
+ {
+ FaceBox.SetVoid();
+ FaceBox.Update(fxmin, fymin, fzmin, fxmax, fymax, fzmax);
+ }
+}
+