mirror of
https://git.dev.opencascade.org/repos/occt.git
synced 2025-06-05 11:24:17 +03:00
848 lines
25 KiB
C++
848 lines
25 KiB
C++
// 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 <Bnd_Box.hxx>
|
|
#include <BndLib_Add3dCurve.hxx>
|
|
#include <BndLib_AddSurface.hxx>
|
|
#include <BRep_Tool.hxx>
|
|
#include <BRepAdaptor_Curve.hxx>
|
|
#include <BRepAdaptor_Surface.hxx>
|
|
#include <BRepBndLib.hxx>
|
|
#include <Geom_Surface.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_Curve.hxx>
|
|
#include <Adaptor3d_Surface.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, Standard_Boolean useTriangulation)
|
|
{
|
|
TopExp_Explorer ex;
|
|
|
|
// Add the faces
|
|
BRepAdaptor_Surface BS;
|
|
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());
|
|
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() && T->MinMax(B, l))
|
|
{
|
|
// B.Enlarge(T->Deflection());
|
|
B.Enlarge(T->Deflection() + BRep_Tool::Tolerance(F));
|
|
}
|
|
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())
|
|
{
|
|
const TopoDS_Edge& anEdge = TopoDS::Edge(ex2.Current());
|
|
if (BRep_Tool::IsGeometric(anEdge))
|
|
{
|
|
BC.Initialize(anEdge);
|
|
BndLib_Add3dCurve::Add(BC, BRep_Tool::Tolerance(anEdge), B);
|
|
}
|
|
}
|
|
B.Enlarge(BRep_Tool::Tolerance(F));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Add the edges not in faces
|
|
Handle(TColStd_HArray1OfInteger) HIndices;
|
|
Handle(Poly_PolygonOnTriangulation) Poly;
|
|
Handle(Poly_Triangulation) T;
|
|
for (ex.Init(S, TopAbs_EDGE, TopAbs_FACE); ex.More(); ex.Next())
|
|
{
|
|
const TopoDS_Edge& E = TopoDS::Edge(ex.Current());
|
|
|
|
if (!useTriangulation && BRep_Tool::IsGeometric(E))
|
|
{
|
|
BC.Initialize(E);
|
|
BndLib_Add3dCurve::Add(BC, BRep_Tool::Tolerance(E), B);
|
|
continue;
|
|
}
|
|
|
|
Handle(Poly_Polygon3D) P3d = BRep_Tool::Polygon3D(E, l);
|
|
if (!P3d.IsNull() && P3d->NbNodes() > 0)
|
|
{
|
|
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));
|
|
}
|
|
// B.Enlarge(P3d->Deflection());
|
|
B.Enlarge(P3d->Deflection() + BRep_Tool::Tolerance(E));
|
|
}
|
|
else
|
|
{
|
|
BRep_Tool::PolygonOnTriangulation(E, Poly, T, l);
|
|
if (!Poly.IsNull() && !T.IsNull() && T->NbNodes() > 0)
|
|
{
|
|
const TColStd_Array1OfInteger& Indices = Poly->Nodes();
|
|
nbNodes = Indices.Length();
|
|
if (l.IsIdentity())
|
|
{
|
|
for (i = 1; i <= nbNodes; i++)
|
|
{
|
|
B.Add(T->Node(Indices[i]));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for (i = 1; i <= nbNodes; i++)
|
|
{
|
|
B.Add(T->Node(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);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Add the vertices not in edges
|
|
|
|
for (ex.Init(S, TopAbs_VERTEX, TopAbs_EDGE); ex.More(); ex.Next())
|
|
{
|
|
B.Add(BRep_Tool::Pnt(TopoDS::Vertex(ex.Current())));
|
|
B.Enlarge(BRep_Tool::Tolerance(TopoDS::Vertex(ex.Current())));
|
|
}
|
|
}
|
|
|
|
//=======================================================================
|
|
// function : AddClose
|
|
// purpose : Add a precise shape bounding to a box
|
|
//=======================================================================
|
|
|
|
void BRepBndLib::AddClose(const TopoDS_Shape& S, Bnd_Box& B)
|
|
{
|
|
TopExp_Explorer ex;
|
|
|
|
// No faces
|
|
|
|
// Add the edges
|
|
|
|
BRepAdaptor_Curve BC;
|
|
|
|
for (ex.Init(S, TopAbs_EDGE); ex.More(); ex.Next())
|
|
{
|
|
const TopoDS_Edge& anEdge = TopoDS::Edge(ex.Current());
|
|
if (BRep_Tool::IsGeometric(anEdge))
|
|
{
|
|
BC.Initialize(anEdge);
|
|
BndLib_Add3dCurve::Add(BC, 0., B);
|
|
}
|
|
}
|
|
|
|
// Add the vertices not in edges
|
|
|
|
for (ex.Init(S, TopAbs_VERTEX, TopAbs_EDGE); ex.More(); ex.Next())
|
|
{
|
|
B.Add(BRep_Tool::Pnt(TopoDS::Vertex(ex.Current())));
|
|
}
|
|
}
|
|
|
|
//=======================================================================
|
|
// 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() && T->MinMax(aLocBox, 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) || !BRep_Tool::IsGeometric(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) || !BRep_Tool::IsGeometric(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);
|
|
}
|
|
}
|
|
|
|
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 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() && P3d->NbNodes() > 0)
|
|
{
|
|
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() && !T.IsNull() && T->NbNodes() > 0)
|
|
{
|
|
const TColStd_Array1OfInteger& Indices = Poly->Nodes();
|
|
nbNodes = Indices.Length();
|
|
for (i = 1; i <= nbNodes; i++)
|
|
{
|
|
if (l.IsIdentity())
|
|
{
|
|
aLocBox.Add(T->Node(Indices[i]));
|
|
}
|
|
else
|
|
{
|
|
aLocBox.Add(T->Node(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_Curve)& aBC = BS.BasisCurve();
|
|
if (aBC->GetType() == GeomAbs_Line)
|
|
{
|
|
return Standard_True;
|
|
}
|
|
else
|
|
{
|
|
return Standard_False;
|
|
}
|
|
}
|
|
else if (aST == GeomAbs_OffsetSurface)
|
|
{
|
|
const Handle(Adaptor3d_Surface)& aS = BS.BasisSurface();
|
|
return CanUseEdges(*aS);
|
|
}
|
|
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;
|
|
}
|
|
|
|
//=================================================================================================
|
|
|
|
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);
|
|
//
|
|
}
|
|
|
|
// In some cases no edges are found
|
|
if (!aBox.IsVoid())
|
|
{
|
|
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;
|
|
}
|
|
}
|
|
}
|
|
|
|
//=================================================================================================
|
|
|
|
inline void Reorder(Standard_Real& a, Standard_Real& b)
|
|
{
|
|
if (a > b)
|
|
{
|
|
Standard_Real t = a;
|
|
a = b;
|
|
b = t;
|
|
}
|
|
}
|
|
|
|
//=================================================================================================
|
|
|
|
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_IN)
|
|
{
|
|
return Standard_True;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
return Standard_True; // extrema point seems to be out of face UV bounds
|
|
}
|
|
}
|
|
//
|
|
return Standard_False;
|
|
}
|
|
|
|
//
|
|
//=================================================================================================
|
|
|
|
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)
|
|
{
|
|
if (EdgeBox.IsVoid())
|
|
{
|
|
return;
|
|
}
|
|
if (FaceBox.IsVoid())
|
|
{
|
|
FaceBox = EdgeBox;
|
|
return;
|
|
}
|
|
|
|
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);
|
|
}
|
|
}
|