0027352: Optimal axis-aligned bounding box for a shape

Add method for exact calculation of bounding boxes

Modifications made according to remarks.

Small correction of test case for issue CR27352

Small correction of test cases for issue CR27352

Avoid warning on VS2015
This commit is contained in:
ifv
2016-04-26 15:00:29 +03:00
committed by bugmaster
parent 745c138678
commit 3ba87fdb66
19 changed files with 2643 additions and 250 deletions
+532 -199
View File
@@ -37,6 +37,7 @@
#include <gp_XYZ.hxx>
#include <Precision.hxx>
#include <Standard_Failure.hxx>
#include <ElSLib.hxx>
static
Standard_Integer ComputeBox(const gp_Hypr& aHypr,
@@ -389,25 +390,165 @@ void BndLib::Add( const gp_Lin2d& L,const Standard_Real P1,
B.Enlarge(Tol);
}
void BndLib::Add( const gp_Circ& C,const Standard_Real Tol, Bnd_Box& B) {
void BndLib::Add( const gp_Circ& C, const Standard_Real Tol, Bnd_Box& B)
{
Standard_Real U1 = 0., U2 = 2.*M_PI;
Add(C, U1, U2, Tol, B);
}
void BndLib::Add(const gp_Circ& C,
const Standard_Real U1,
const Standard_Real U2,
const Standard_Real Tol,
Bnd_Box& B)
{
Standard_Real period = 2.*M_PI - Epsilon(2.*M_PI);
Standard_Real utrim1 = U1, utrim2 = U2;
if(U2 - U1 > period)
{
utrim1 = 0.;
utrim2 = 2.*M_PI;
}
else
{
Standard_Real tol = Epsilon(1.);
ElCLib::AdjustPeriodic(0., 2.*M_PI,
tol,
utrim1, utrim2);
}
Standard_Real R = C.Radius();
gp_XYZ O = C.Location().XYZ();
gp_XYZ Xd = C.XAxis().Direction().XYZ();
gp_XYZ Yd = C.YAxis().Direction().XYZ();
B.Add(gp_Pnt(O -R*Xd -R*Yd));
B.Add(gp_Pnt(O -R*Xd +R*Yd));
B.Add(gp_Pnt(O +R*Xd -R*Yd));
B.Add(gp_Pnt(O +R*Xd +R*Yd));
B.Enlarge(Tol);
}
void BndLib::Add( const gp_Circ& C,const Standard_Real P1,
const Standard_Real P2,
const Standard_Real Tol, Bnd_Box& B) {
Compute(P1,P2,C.Radius(),C.Radius(),gp_Pnt(C.XAxis().Direction().XYZ()),
gp_Pnt(C.YAxis().Direction().XYZ()),C.Location(),B);
const gp_Ax2& pos = C.Position();
//
Standard_Real tt;
Standard_Real xmin, xmax, txmin, txmax;
if(Abs(Xd.X()) > gp::Resolution())
{
txmin = ATan(Yd.X() / Xd.X());
txmin = ElCLib::InPeriod(txmin, 0., 2.*M_PI);
}
else
{
txmin = M_PI/ 2.;
}
txmax = txmin <= M_PI? txmin + M_PI : txmin - M_PI;
xmin = R * Cos(txmin) * Xd.X() + R * Sin(txmin) * Yd.X() + O.X();
xmax = R * Cos(txmax) * Xd.X() + R * Sin(txmax) * Yd.X() + O.X();
if(xmin > xmax)
{
tt = xmin;
xmin = xmax;
xmax = tt;
tt = txmin;
txmin = txmax;
txmax = tt;
}
//
Standard_Real ymin, ymax, tymin, tymax;
if(Abs(Xd.Y()) > gp::Resolution())
{
tymin = ATan(Yd.Y() / Xd.Y());
tymin = ElCLib::InPeriod(tymin, 0., 2.*M_PI);
}
else
{
tymin = M_PI/ 2.;
}
tymax = tymin <= M_PI? tymin + M_PI : tymin - M_PI;
ymin = R * Cos(tymin) * Xd.Y() + R * Sin(tymin) * Yd.Y() + O.Y();
ymax = R * Cos(tymax) * Xd.Y() + R * Sin(tymax) * Yd.Y() + O.Y();
if(ymin > ymax)
{
tt = ymin;
ymin = ymax;
ymax = tt;
tt = tymin;
tymin = tymax;
tymax = tt;
}
//
Standard_Real zmin, zmax, tzmin, tzmax;
if(Abs(Xd.Z()) > gp::Resolution())
{
tzmin = ATan(Yd.Z() / Xd.Z());
tzmin = ElCLib::InPeriod(tzmin, 0., 2.*M_PI);
}
else
{
tzmin = M_PI/ 2.;
}
tzmax = tzmin <= M_PI? tzmin + M_PI : tzmin - M_PI;
zmin = R * Cos(tzmin) * Xd.Z() + R * Sin(tzmin) * Yd.Z() + O.Z();
zmax = R * Cos(tzmax) * Xd.Z() + R * Sin(tzmax) * Yd.Z() + O.Z();
if(zmin > zmax)
{
tt = zmin;
zmin = zmax;
zmax = tt;
tt = tzmin;
tzmin = tzmax;
tzmax = tt;
}
//
if(utrim2 - utrim1 >= period)
{
B.Update(xmin, ymin, zmin, xmax, ymax, zmax);
}
else
{
gp_Pnt P = ElCLib::CircleValue(utrim1, pos, R);
B.Add(P);
P = ElCLib::CircleValue(utrim2, pos, R);
B.Add(P);
Standard_Real Xmin, Ymin, Zmin, Xmax, Ymax, Zmax;
B.Get(Xmin, Ymin, Zmin, Xmax, Ymax, Zmax);
Standard_Real gap = B.GetGap();
Xmin += gap;
Ymin += gap;
Zmin += gap;
Xmax -= gap;
Ymax -= gap;
Zmax -= gap;
//
txmin = ElCLib::InPeriod(txmin, utrim1, utrim1 + 2. * M_PI);
if(txmin >= utrim1 && txmin <= utrim2)
{
Xmin = Min(xmin, Xmin);
}
txmax = ElCLib::InPeriod(txmax, utrim1, utrim1 + 2. * M_PI);
if(txmax >= utrim1 && txmax <= utrim2)
{
Xmax = Max(xmax, Xmax);
}
//
tymin = ElCLib::InPeriod(tymin, utrim1, utrim1 + 2. * M_PI);
if(tymin >= utrim1 && tymin <= utrim2)
{
Ymin = Min(ymin, Ymin);
}
tymax = ElCLib::InPeriod(tymax, utrim1, utrim1 + 2. * M_PI);
if(tymax >= utrim1 && tymax <= utrim2)
{
Ymax = Max(ymax, Ymax);
}
//
tzmin = ElCLib::InPeriod(tzmin, utrim1, utrim1 + 2. * M_PI);
if(tzmin >= utrim1 && tzmin <= utrim2)
{
Zmin = Min(zmin, Zmin);
}
tzmax = ElCLib::InPeriod(tzmax, utrim1, utrim1 + 2. * M_PI);
if(tzmax >= utrim1 && tzmax <= utrim2)
{
Zmax = Max(zmax, Zmax);
}
//
B.Update(Xmin, Ymin, Zmin, Xmax, Ymax, Zmax);
}
//
B.Enlarge(Tol);
}
@@ -433,26 +574,166 @@ void BndLib::Add(const gp_Circ2d& C,const Standard_Real P1,
B.Enlarge(Tol);
}
void BndLib::Add( const gp_Elips& C,const Standard_Real Tol, Bnd_Box& B) {
Standard_Real Ra = C.MajorRadius();
Standard_Real Rb = C.MinorRadius();
gp_XYZ Xd = C.XAxis().Direction().XYZ();
gp_XYZ Yd = C.YAxis().Direction().XYZ();
gp_XYZ O = C.Location().XYZ();
B.Add(gp_Pnt(O +Ra*Xd +Rb*Yd));
B.Add(gp_Pnt(O -Ra*Xd +Rb*Yd));
B.Add(gp_Pnt(O -Ra*Xd -Rb*Yd));
B.Add(gp_Pnt(O +Ra*Xd -Rb*Yd));
B.Enlarge(Tol);
void BndLib::Add(const gp_Elips& C, const Standard_Real Tol, Bnd_Box& B)
{
Standard_Real U1 = 0., U2 = 2.*M_PI;
Add(C, U1, U2, Tol, B);
}
void BndLib::Add( const gp_Elips& C,const Standard_Real P1,
const Standard_Real P2,
const Standard_Real Tol, Bnd_Box& B) {
void BndLib::Add(const gp_Elips& C,
const Standard_Real U1,
const Standard_Real U2,
const Standard_Real Tol,
Bnd_Box& B)
{
Standard_Real period = 2.*M_PI - Epsilon(2.*M_PI);
Compute(P1,P2,C.MajorRadius(),C.MinorRadius(),gp_Pnt(C.XAxis().Direction().XYZ()),
gp_Pnt(C.YAxis().Direction().XYZ()),C.Location(),B);
Standard_Real utrim1 = U1, utrim2 = U2;
if(U2 - U1 > period)
{
utrim1 = 0.;
utrim2 = 2.*M_PI;
}
else
{
Standard_Real tol = Epsilon(1.);
ElCLib::AdjustPeriodic(0., 2.*M_PI,
tol,
utrim1, utrim2);
}
Standard_Real MajR = C.MajorRadius();
Standard_Real MinR = C.MinorRadius();
gp_XYZ O = C.Location().XYZ();
gp_XYZ Xd = C.XAxis().Direction().XYZ();
gp_XYZ Yd = C.YAxis().Direction().XYZ();
const gp_Ax2& pos = C.Position();
//
Standard_Real tt;
Standard_Real xmin, xmax, txmin, txmax;
if(Abs(Xd.X()) > gp::Resolution())
{
txmin = ATan((MinR*Yd.X()) / (MajR*Xd.X()));
txmin = ElCLib::InPeriod(txmin, 0., 2.*M_PI);
}
else
{
txmin = M_PI/ 2.;
}
txmax = txmin <= M_PI? txmin + M_PI : txmin - M_PI;
xmin = MajR * Cos(txmin) * Xd.X() + MinR * Sin(txmin) * Yd.X() + O.X();
xmax = MajR * Cos(txmax) * Xd.X() + MinR * Sin(txmax) * Yd.X() + O.X();
if(xmin > xmax)
{
tt = xmin;
xmin = xmax;
xmax = tt;
tt = txmin;
txmin = txmax;
txmax = tt;
}
//
Standard_Real ymin, ymax, tymin, tymax;
if(Abs(Xd.Y()) > gp::Resolution())
{
tymin = ATan((MinR*Yd.Y()) / (MajR*Xd.Y()));
tymin = ElCLib::InPeriod(tymin, 0., 2.*M_PI);
}
else
{
tymin = M_PI/ 2.;
}
tymax = tymin <= M_PI? tymin + M_PI : tymin - M_PI;
ymin = MajR * Cos(tymin) * Xd.Y() + MinR * Sin(tymin) * Yd.Y() + O.Y();
ymax = MajR * Cos(tymax) * Xd.Y() + MinR * Sin(tymax) * Yd.Y() + O.Y();
if(ymin > ymax)
{
tt = ymin;
ymin = ymax;
ymax = tt;
tt = tymin;
tymin = tymax;
tymax = tt;
}
//
Standard_Real zmin, zmax, tzmin, tzmax;
if(Abs(Xd.Z()) > gp::Resolution())
{
tzmin = ATan((MinR*Yd.Z()) / (MajR*Xd.Z()));
tzmin = ElCLib::InPeriod(tzmin, 0., 2.*M_PI);
}
else
{
tzmin = M_PI/ 2.;
}
tzmax = tzmin <= M_PI? tzmin + M_PI : tzmin - M_PI;
zmin = MajR * Cos(tzmin) * Xd.Z() + MinR * Sin(tzmin) * Yd.Z() + O.Z();
zmax = MajR * Cos(tzmax) * Xd.Z() + MinR * Sin(tzmax) * Yd.Z() + O.Z();
if(zmin > zmax)
{
tt = zmin;
zmin = zmax;
zmax = tt;
tt = tzmin;
tzmin = tzmax;
tzmax = tt;
}
//
if(utrim2 - utrim1 >= period)
{
B.Update(xmin, ymin, zmin, xmax, ymax, zmax);
}
else
{
gp_Pnt P = ElCLib::EllipseValue(utrim1, pos, MajR, MinR);
B.Add(P);
P = ElCLib::EllipseValue(utrim2, pos, MajR, MinR);
B.Add(P);
Standard_Real Xmin, Ymin, Zmin, Xmax, Ymax, Zmax;
B.Get(Xmin, Ymin, Zmin, Xmax, Ymax, Zmax);
Standard_Real gap = B.GetGap();
Xmin += gap;
Ymin += gap;
Zmin += gap;
Xmax -= gap;
Ymax -= gap;
Zmax -= gap;
//
txmin = ElCLib::InPeriod(txmin, utrim1, utrim1 + 2. * M_PI);
if(txmin >= utrim1 && txmin <= utrim2)
{
Xmin = Min(xmin, Xmin);
}
txmax = ElCLib::InPeriod(txmax, utrim1, utrim1 + 2. * M_PI);
if(txmax >= utrim1 && txmax <= utrim2)
{
Xmax = Max(xmax, Xmax);
}
//
tymin = ElCLib::InPeriod(tymin, utrim1, utrim1 + 2. * M_PI);
if(tymin >= utrim1 && tymin <= utrim2)
{
Ymin = Min(ymin, Ymin);
}
tymax = ElCLib::InPeriod(tymax, utrim1, utrim1 + 2. * M_PI);
if(tymax >= utrim1 && tymax <= utrim2)
{
Ymax = Max(ymax, Ymax);
}
//
tzmin = ElCLib::InPeriod(tzmin, utrim1, utrim1 + 2. * M_PI);
if(tzmin >= utrim1 && tzmin <= utrim2)
{
Zmin = Min(zmin, Zmin);
}
tzmax = ElCLib::InPeriod(tzmax, utrim1, utrim1 + 2. * M_PI);
if(tzmax >= utrim1 && tzmax <= utrim2)
{
Zmax = Max(zmax, Zmax);
}
//
B.Update(Xmin, Ymin, Zmin, Xmax, Ymax, Zmax);
}
//
B.Enlarge(Tol);
}
@@ -661,57 +942,70 @@ void BndLib::Add(const gp_Hypr2d& H,const Standard_Real P1,
B.Enlarge(Tol);
}
static void ComputeCyl(const gp_Cylinder& Cyl,
const Standard_Real UMin, const Standard_Real UMax,
const Standard_Real VMin, const Standard_Real VMax,
Bnd_Box& B)
{
gp_Circ aC = ElSLib::CylinderVIso(Cyl.Position(), Cyl.Radius(), VMin);
BndLib::Add(aC, UMin, UMax, 0., B);
//
gp_Vec aT = (VMax - VMin) * Cyl.Axis().Direction();
aC.Translate(aT);
BndLib::Add(aC, UMin, UMax, 0., B);
}
void BndLib::Add( const gp_Cylinder& S,const Standard_Real UMin,
const Standard_Real UMax,const Standard_Real VMin,
const Standard_Real VMax,const Standard_Real Tol, Bnd_Box& B) {
if (Precision::IsNegativeInfinite(VMin)) {
if (Precision::IsNegativeInfinite(VMax)) {
const Standard_Real VMax,const Standard_Real Tol, Bnd_Box& B)
{
if (Precision::IsNegativeInfinite(VMin))
{
if (Precision::IsNegativeInfinite(VMax))
{
Standard_Failure::Raise("BndLib::bad parameter");
}
else if (Precision::IsPositiveInfinite(VMax)) {
OpenMinMax(S.Axis().Direction(),B);
}
else {
Compute(UMin,UMax,S.Radius(),S.Radius(),
gp_Pnt(S.XAxis().Direction().XYZ()),
gp_Pnt(S.YAxis().Direction().XYZ()),
gp_Pnt(S.Location().XYZ() + VMax*S.Axis().Direction().XYZ()),B);
OpenMin(S.Axis().Direction(),B);
}
}
else if (Precision::IsPositiveInfinite(VMin)) {
if (Precision::IsNegativeInfinite(VMax)) {
else if (Precision::IsPositiveInfinite(VMax))
{
OpenMinMax(S.Axis().Direction(),B);
}
else if (Precision::IsPositiveInfinite(VMax)) {
Standard_Failure::Raise("BndLib::bad parameter");
}
else {
Compute(UMin,UMax,S.Radius(),S.Radius(),
gp_Pnt(S.XAxis().Direction().XYZ()),
gp_Pnt(S.YAxis().Direction().XYZ()),
gp_Pnt(S.Location().XYZ() + VMax*S.Axis().Direction().XYZ()),B);
OpenMax(S.Axis().Direction(),B);
}
}
else {
Compute(UMin,UMax,S.Radius(),S.Radius(),
gp_Pnt(S.XAxis().Direction().XYZ()),
gp_Pnt(S.YAxis().Direction().XYZ()),
gp_Pnt(S.Location().XYZ() + VMin*S.Axis().Direction().XYZ()),B);
if (Precision::IsNegativeInfinite(VMax)) {
else
{
ComputeCyl(S, UMin, UMax, 0., VMax,B);
OpenMin(S.Axis().Direction(),B);
}
else if (Precision::IsPositiveInfinite(VMax)) {
}
else if (Precision::IsPositiveInfinite(VMin))
{
if (Precision::IsNegativeInfinite(VMax))
{
OpenMinMax(S.Axis().Direction(),B);
}
else if (Precision::IsPositiveInfinite(VMax))
{
Standard_Failure::Raise("BndLib::bad parameter");
}
else
{
ComputeCyl(S, UMin, UMax, 0., VMax, B);
OpenMax(S.Axis().Direction(),B);
}
}
else
{
if (Precision::IsNegativeInfinite(VMax))
{
ComputeCyl(S, UMin, UMax, VMin, 0., B);
OpenMin(S.Axis().Direction(),B);
}
else if (Precision::IsPositiveInfinite(VMax))
{
ComputeCyl(S, UMin, UMax, VMin, 0., B);
OpenMax(S.Axis().Direction(),B);
}
else {
Compute(UMin,UMax,S.Radius(),S.Radius(),
gp_Pnt(S.XAxis().Direction().XYZ()),
gp_Pnt(S.YAxis().Direction().XYZ()),
gp_Pnt(S.Location().XYZ() + VMax*S.Axis().Direction().XYZ()),B);
else
{
ComputeCyl(S, UMin, UMax, VMin, VMax, B);
}
}
@@ -725,74 +1019,97 @@ void BndLib::Add( const gp_Cylinder& S,const Standard_Real VMin,
BndLib::Add(S,0.,2.*M_PI,VMin,VMax,Tol,B);
}
static void ComputeCone (const gp_Cone& Cone,
const Standard_Real UMin, const Standard_Real UMax,
const Standard_Real VMin, const Standard_Real VMax,
Bnd_Box& B)
{
const gp_Ax3& aPos = Cone.Position();
Standard_Real R = Cone.RefRadius();
Standard_Real sang = Cone.SemiAngle();
gp_Circ aC = ElSLib::ConeVIso(aPos, R, sang, VMin);
if(aC.Radius() > Precision::Confusion())
{
BndLib::Add(aC, UMin, UMax, 0., B);
}
else
{
B.Add(aC.Location());
}
//
aC = ElSLib::ConeVIso(aPos, R, sang, VMax);
if(aC.Radius() > Precision::Confusion())
{
BndLib::Add(aC, UMin, UMax, 0., B);
}
else
{
B.Add(aC.Location());
}
}
void BndLib::Add(const gp_Cone& S,const Standard_Real UMin,
const Standard_Real UMax,const Standard_Real VMin,
const Standard_Real VMax,const Standard_Real Tol, Bnd_Box& B) {
Standard_Real R = S.RefRadius();
Standard_Real A = S.SemiAngle();
if (Precision::IsNegativeInfinite(VMin)) {
if (Precision::IsNegativeInfinite(VMax)) {
if (Precision::IsNegativeInfinite(VMin))
{
if (Precision::IsNegativeInfinite(VMax))
{
Standard_Failure::Raise("BndLib::bad parameter");
}
else if (Precision::IsPositiveInfinite(VMax)) {
else if (Precision::IsPositiveInfinite(VMax))
{
gp_Dir D(Cos(A)*S.Axis().Direction());
OpenMinMax(D,B);
}
else {
Compute(UMin,UMax,R+VMax*Sin(A),R+VMax*Sin(A),
gp_Pnt(S.XAxis().Direction().XYZ()),
gp_Pnt(S.YAxis().Direction().XYZ()),
gp_Pnt(S.Location().XYZ() +
VMax*Cos(A)*S.Axis().Direction().XYZ()),B);
else
{
ComputeCone(S, UMin, UMax, 0., VMax, B);
gp_Dir D(Cos(A)*S.Axis().Direction());
OpenMin(D,B);
}
}
else if (Precision::IsPositiveInfinite(VMin)) {
if (Precision::IsNegativeInfinite(VMax)) {
else if (Precision::IsPositiveInfinite(VMin))
{
if (Precision::IsNegativeInfinite(VMax))
{
gp_Dir D(Cos(A)*S.Axis().Direction());
OpenMinMax(D,B);
}
else if (Precision::IsPositiveInfinite(VMax)) {
else if (Precision::IsPositiveInfinite(VMax))
{
Standard_Failure::Raise("BndLib::bad parameter");
}
else {
Compute(UMin,UMax,R+VMax*Sin(A),R+VMax*Sin(A),
gp_Pnt(S.XAxis().Direction().XYZ()),
gp_Pnt(S.YAxis().Direction().XYZ()),
gp_Pnt(S.Location().XYZ() +
VMax*Cos(A)*S.Axis().Direction().XYZ()),B);
else
{
ComputeCone(S, UMin, UMax, 0., VMax, B);
gp_Dir D(Cos(A)*S.Axis().Direction());
OpenMax(D,B);
}
}
else {
Compute(UMin,UMax,R+VMin*Sin(A),R+VMin*Sin(A),
gp_Pnt(S.XAxis().Direction().XYZ()),
gp_Pnt(S.YAxis().Direction().XYZ()),
gp_Pnt(S.Location().XYZ() +
VMin*Cos(A)*S.Axis().Direction().XYZ()),B);
if (Precision::IsNegativeInfinite(VMax)) {
else
{
if (Precision::IsNegativeInfinite(VMax))
{
ComputeCone(S, UMin, UMax, VMin, 0., B);
gp_Dir D(Cos(A)*S.Axis().Direction());
OpenMin(D,B);
}
else if (Precision::IsPositiveInfinite(VMax)) {
else if (Precision::IsPositiveInfinite(VMax))
{
ComputeCone(S, UMin, UMax, VMin, 0., B);
gp_Dir D(Cos(A)*S.Axis().Direction());
OpenMax(D,B);
}
else {
Compute(UMin,UMax,R+VMax*Sin(A),R+VMax*Sin(A),
gp_Pnt(S.XAxis().Direction().XYZ()),
gp_Pnt(S.YAxis().Direction().XYZ()),
gp_Pnt(S.Location().XYZ() +
VMax*Cos(A)*S.Axis().Direction().XYZ()),B);
else
{
ComputeCone(S, UMin, UMax, VMin, VMax, B);
}
}
B.Enlarge(Tol);
}
@@ -802,102 +1119,118 @@ void BndLib::Add( const gp_Cone& S,const Standard_Real VMin,
BndLib::Add(S,0.,2.*M_PI,VMin,VMax,Tol,B);
}
void BndLib::Add(const gp_Sphere& S,const Standard_Real UMin,
const Standard_Real UMax,const Standard_Real VMin,
const Standard_Real VMax,const Standard_Real Tol, Bnd_Box& B) {
#if 0
Standard_Real Fi1;
Standard_Real Fi2;
if (VMax<VMin) {
Fi1 = VMax;
Fi2 = VMin;
}
else {
Fi1 = VMin;
Fi2 = VMax;
}
if (-Fi1>Precision::Angular()) {
if (-Fi2>Precision::Angular()) {
Compute(UMin,UMax,S.Radius(),S.Radius(),
gp_Pnt(S.XAxis().Direction().XYZ()),gp_Pnt(S.YAxis().Direction().XYZ()),
S.Location(),B);
Compute(UMin,UMax,S.Radius(),S.Radius(),
gp_Pnt(S.XAxis().Direction().XYZ()),gp_Pnt(S.YAxis().Direction().XYZ()),
gp_Pnt(S.Location().XYZ()- S.Radius()*S.Position().Axis().Direction().XYZ()),B);
}
else {
Compute(UMin,UMax,S.Radius(),S.Radius(),
gp_Pnt(S.XAxis().Direction().XYZ()),gp_Pnt(S.YAxis().Direction().XYZ()),
gp_Pnt(S.Location().XYZ()+ S.Radius()*S.Position().Axis().Direction().XYZ()),B);
Compute(UMin,UMax,S.Radius(),S.Radius(),
gp_Pnt(S.XAxis().Direction().XYZ()),gp_Pnt(S.YAxis().Direction().XYZ()),
gp_Pnt(S.Location().XYZ()- S.Radius()*S.Position().Axis().Direction().XYZ()),B);
}
}
else {
Compute(UMin,UMax,S.Radius(),S.Radius(),
gp_Pnt(S.XAxis().Direction().XYZ()),gp_Pnt(S.YAxis().Direction().XYZ()),
S.Location(),B);
Compute(UMin,UMax,S.Radius(),S.Radius(),
gp_Pnt(S.XAxis().Direction().XYZ()),gp_Pnt(S.YAxis().Direction().XYZ()),
gp_Pnt(S.Location().XYZ() +S.Radius()*S.Position().Axis().Direction().XYZ()),B);
}
B.Enlarge(Tol);
#else
Standard_Real u,v,du,dv;
Standard_Integer iu,iv;
du = (UMax-UMin)/10;
dv = (VMax-VMin)/10;
Standard_Real COSV[11];
Standard_Real SINV[11];
for(iv=0,v=VMin;iv<=10;iv++) {
COSV[iv]=cos(v);
SINV[iv]=sin(v);
v+=dv;
}
for(u=UMin,iu=0; iu<=10 ; iu++) {
Standard_Real Radiuscosu=S.Radius()*cos(u);
Standard_Real Radiussinu=S.Radius()*sin(u);
for(v=VMin,iv=0; iv<=10 ; iv++) {
Standard_Real sinv=SINV[iv];
Standard_Real cosv=COSV[iv];
gp_XYZ M;
M.SetLinearForm (cosv*Radiuscosu, S.Position().XDirection().XYZ(),
cosv*Radiussinu, S.Position().YDirection().XYZ(),
S.Radius()*sinv, S.Position().Direction().XYZ() ,
S.Position().Location().XYZ() );
//-- static int t=0;
//-- cout<<"point p"<<++t<<" "<<M.X()<<" "<<M.Y()<<" "<<M.Z()<<endl;
B.Add(gp_Pnt(M));
v+=dv;
}
u+=du;
}
Standard_Real Maxduv = Max(du,dv)*0.5;
Standard_Real Fleche = S.Radius() * (1 - cos(Maxduv));
B.Enlarge(Fleche);
B.Enlarge(10*Tol);
#endif
static void ComputeSphere (const gp_Sphere& Sphere,
const Standard_Real UMin, const Standard_Real UMax,
const Standard_Real VMin, const Standard_Real VMax,
Bnd_Box& B)
{
gp_Pnt P = Sphere.Location();
Standard_Real R = Sphere.Radius();
Standard_Real xmin, ymin, zmin, xmax, ymax, zmax;
xmin = P.X() - R;
xmax = P.X() + R;
ymin = P.Y() - R;
ymax = P.Y() + R;
zmin = P.Z() - R;
zmax = P.Z() + R;
Standard_Real uper = 2. * M_PI - Precision::PConfusion();
Standard_Real vper = M_PI - Precision::PConfusion();
if (UMax - UMin >= uper && VMax - VMin >= vper)
{
// a whole sphere
B.Update(xmin, ymin, zmin, xmax, ymax, zmax);
}
else
{
Standard_Real u, v;
Standard_Real umax = UMin + 2. * M_PI;
const gp_Ax3& Pos = Sphere.Position();
gp_Pnt PExt = P;
PExt.SetX(xmin);
ElSLib::SphereParameters(Pos, R, PExt, u, v);
u = ElCLib::InPeriod(u, UMin, umax);
if(u >= UMin && u <= UMax && v >= VMin && v <= VMax)
{
B.Add(PExt);
}
//
PExt.SetX(xmax);
ElSLib::SphereParameters(Pos, R, PExt, u, v);
u = ElCLib::InPeriod(u, UMin, umax);
if(u >= UMin && u <= UMax && v >= VMin && v <= VMax)
{
B.Add(PExt);
}
PExt.SetX(P.X());
//
PExt.SetY(ymin);
ElSLib::SphereParameters(Pos, R, PExt, u, v);
u = ElCLib::InPeriod(u, UMin, umax);
if(u >= UMin && u <= UMax && v >= VMin && v <= VMax)
{
B.Add(PExt);
}
//
PExt.SetY(ymax);
ElSLib::SphereParameters(Pos, R, PExt, u, v);
u = ElCLib::InPeriod(u, UMin, umax);
if(u >= UMin && u <= UMax && v >= VMin && v <= VMax)
{
B.Add(PExt);
}
PExt.SetY(P.Y());
//
PExt.SetZ(zmin);
ElSLib::SphereParameters(Pos, R, PExt, u, v);
u = ElCLib::InPeriod(u, UMin, umax);
if(u >= UMin && u <= UMax && v >= VMin && v <= VMax)
{
B.Add(PExt);
}
//
PExt.SetZ(zmax);
ElSLib::SphereParameters(Pos, R, PExt, u, v);
u = ElCLib::InPeriod(u, UMin, umax);
if(u >= UMin && u <= UMax && v >= VMin && v <= VMax)
{
B.Add(PExt);
}
//
// Add boundaries of patch
// UMin, UMax
gp_Circ aC = ElSLib::SphereUIso(Pos, R, UMin);
BndLib::Add(aC, VMin, VMax, 0., B);
aC = ElSLib::SphereUIso(Pos, R, UMax);
BndLib::Add(aC, VMin, VMax, 0., B);
// VMin, VMax
aC = ElSLib::SphereVIso(Pos, R, VMin);
BndLib::Add(aC, UMin, UMax, 0., B);
aC = ElSLib::SphereVIso(Pos, R, VMax);
BndLib::Add(aC, UMin, UMax, 0., B);
}
}
void BndLib::Add( const gp_Sphere& S,const Standard_Real Tol, Bnd_Box& B) {
void BndLib::Add(const gp_Sphere& S,const Standard_Real UMin,
const Standard_Real UMax,const Standard_Real VMin,
const Standard_Real VMax,const Standard_Real Tol, Bnd_Box& B)
{
ComputeSphere(S, UMin, UMax, VMin, VMax, B);
B.Enlarge(Tol);
}
void BndLib::Add( const gp_Sphere& S,const Standard_Real Tol, Bnd_Box& B)
{
gp_Pnt P = S.Location();
Standard_Real R = S.Radius();
gp_XYZ O = S.Location().XYZ();
gp_XYZ Xd = S.XAxis().Direction().XYZ();
gp_XYZ Yd = S.YAxis().Direction().XYZ();
gp_XYZ Zd = S.Position().Axis().Direction().XYZ();
B.Add(gp_Pnt(O -R*Xd -R*Yd+ R*Zd));
B.Add(gp_Pnt(O -R*Xd +R*Yd+ R*Zd));
B.Add(gp_Pnt(O +R*Xd -R*Yd+ R*Zd));
B.Add(gp_Pnt(O +R*Xd +R*Yd+ R*Zd));
B.Add(gp_Pnt(O +R*Xd -R*Yd- R*Zd));
B.Add(gp_Pnt(O -R*Xd -R*Yd- R*Zd));
B.Add(gp_Pnt(O +R*Xd +R*Yd- R*Zd));
B.Add(gp_Pnt(O -R*Xd +R*Yd- R*Zd));
Standard_Real xmin, ymin, zmin, xmax, ymax, zmax;
xmin = P.X() - R;
xmax = P.X() + R;
ymin = P.Y() - R;
ymax = P.Y() + R;
zmin = P.Z() - R;
zmax = P.Z() + R;
B.Update(xmin, ymin, zmin, xmax, ymax, zmax);
B.Enlarge(Tol);
}
+378
View File
@@ -32,6 +32,10 @@
#include <gp.hxx>
#include <Precision.hxx>
#include <Standard_Type.hxx>
#include <math_MultipleVarFunction.hxx>
#include <math_Function.hxx>
#include <math_BrentMinimum.hxx>
#include <math_PSO.hxx>
//=======================================================================
//function : BndLib_Box2dCurve
@@ -57,6 +61,8 @@ class BndLib_Box2dCurve {
void Perform();
void PerformOptimal(const Standard_Real Tol);
void Clear();
Standard_Integer ErrorStatus() const;
@@ -89,6 +95,17 @@ class BndLib_Box2dCurve {
const Standard_Real );
//
void PerformOnePoint();
//
void PerformGenCurv(const Standard_Real Tol = Precision::PConfusion());
//
Standard_Integer NbSamples();
//
Standard_Real AdjustExtr(const Standard_Real UMin,
const Standard_Real UMax,
const Standard_Real Extr0,
const Standard_Integer CoordIndx,
const Standard_Real Tol,
const Standard_Boolean IsMin);
//-----------------------------
protected:
Handle(Geom2d_Curve) myCurve;
@@ -101,7 +118,109 @@ class BndLib_Box2dCurve {
Standard_Real myT2;
GeomAbs_CurveType myTypeBase;
};
//
class Curv2dMaxMinCoordMVar : public math_MultipleVarFunction
{
public:
Curv2dMaxMinCoordMVar(const Handle(Geom2d_Curve)& theCurve,
const Standard_Real UMin,
const Standard_Real UMax,
const Standard_Integer CoordIndx,
const Standard_Real Sign)
: myCurve(theCurve),
myUMin(UMin),
myUMax(UMax),
myCoordIndx(CoordIndx),
mySign(Sign)
{
}
Standard_Boolean Value (const math_Vector& X,
Standard_Real& F)
{
if (!CheckInputData(X(1)))
{
return Standard_False;
}
gp_Pnt2d aP = myCurve->Value(X(1));
F = mySign * aP.Coord(myCoordIndx);
return Standard_True;
}
Standard_Integer NbVariables() const
{
return 1;
}
private:
Curv2dMaxMinCoordMVar & operator = (const Curv2dMaxMinCoordMVar & theOther);
Standard_Boolean CheckInputData(Standard_Real theParam)
{
if (theParam < myUMin ||
theParam > myUMax)
return Standard_False;
return Standard_True;
}
const Handle(Geom2d_Curve)& myCurve;
Standard_Real myUMin;
Standard_Real myUMax;
Standard_Integer myCoordIndx;
Standard_Real mySign;
};
//
class Curv2dMaxMinCoord : public math_Function
{
public:
Curv2dMaxMinCoord(const Handle(Geom2d_Curve)& theCurve,
const Standard_Real UMin,
const Standard_Real UMax,
const Standard_Integer CoordIndx,
const Standard_Real Sign)
: myCurve(theCurve),
myUMin(UMin),
myUMax(UMax),
myCoordIndx(CoordIndx),
mySign(Sign)
{
}
Standard_Boolean Value (const Standard_Real X,
Standard_Real& F)
{
if (!CheckInputData(X))
{
return Standard_False;
}
gp_Pnt2d aP = myCurve->Value(X);
F = mySign * aP.Coord(myCoordIndx);
return Standard_True;
}
private:
Curv2dMaxMinCoord & operator = (const Curv2dMaxMinCoord & theOther);
Standard_Boolean CheckInputData(Standard_Real theParam)
{
if (theParam < myUMin ||
theParam > myUMax)
return Standard_False;
return Standard_True;
}
const Handle(Geom2d_Curve)& myCurve;
Standard_Real myUMin;
Standard_Real myUMax;
Standard_Integer myCoordIndx;
Standard_Real mySign;
};
//=======================================================================
//function :
@@ -244,6 +363,41 @@ void BndLib_Box2dCurve::Perform()
}
}
//=======================================================================
//function : PerformOptimal
//purpose :
//=======================================================================
void BndLib_Box2dCurve::PerformOptimal(const Standard_Real Tol)
{
Clear();
myErrorStatus=0;
CheckData();
if(myErrorStatus) {
return;
}
if (myT1==myT2) {
PerformOnePoint();
return;
}
GetInfoBase();
if(myErrorStatus) {
return;
}
if (myTypeBase==GeomAbs_Line ||
myTypeBase==GeomAbs_Circle ||
myTypeBase==GeomAbs_Ellipse ||
myTypeBase==GeomAbs_Parabola ||
myTypeBase==GeomAbs_Hyperbola) { // LineConic
PerformLineConic();
}
else {
PerformGenCurv(Tol);
}
}
//=======================================================================
//function : PerformOnePoint
//purpose :
//=======================================================================
@@ -379,6 +533,209 @@ void BndLib_Box2dCurve::PerformOther()
myBox.Add(aP2D);
}
//=======================================================================
//function : NbSamples
//purpose :
//=======================================================================
Standard_Integer BndLib_Box2dCurve::NbSamples()
{
Standard_Integer N;
switch (myTypeBase) {
case GeomAbs_BezierCurve:
{
Handle(Geom2d_BezierCurve) aCBz=Handle(Geom2d_BezierCurve)::DownCast(myCurveBase);
N = aCBz->NbPoles();
//By default parametric range of Bezier curv is [0, 1]
Standard_Real du = myT2 - myT1;
if(du < .9)
{
N = RealToInt(du*N) + 1;
N = Max(N, 5);
}
break;
}
case GeomAbs_BSplineCurve:
{
Handle(Geom2d_BSplineCurve) aCBS=Handle(Geom2d_BSplineCurve)::DownCast(myCurveBase);
N = (aCBS->Degree() + 1)*(aCBS->NbKnots() -1);
Standard_Real umin = aCBS->FirstParameter(),
umax = aCBS->LastParameter();
Standard_Real du = (myT2 - myT1) / (umax - umin);
if(du < .9)
{
N = RealToInt(du*N) + 1;
N = Max(N, 5);
}
break;
}
default:
N = 17;
}
return Min (23,N);
}
//=======================================================================
//function : AdjustExtr
//purpose :
//=======================================================================
Standard_Real BndLib_Box2dCurve::AdjustExtr(const Standard_Real UMin,
const Standard_Real UMax,
const Standard_Real Extr0,
const Standard_Integer CoordIndx,
const Standard_Real Tol,
const Standard_Boolean IsMin)
{
Standard_Real aSign = IsMin ? 1.:-1.;
Standard_Real extr = aSign * Extr0;
//
Standard_Real Du = (myCurve->LastParameter() - myCurve->FirstParameter());
//
Geom2dAdaptor_Curve aGAC(myCurve);
Standard_Real UTol = Max(aGAC.Resolution(Tol), Precision::PConfusion());
Standard_Real reltol = UTol / Max(Abs(UMin), Abs(UMax));
if(UMax - UMin < 0.01 * Du)
{
//It is suggested that function has one extremum on small interval
math_BrentMinimum anOptLoc(reltol, 100, UTol);
Curv2dMaxMinCoord aFunc(myCurve, UMin, UMax, CoordIndx, aSign);
anOptLoc.Perform(aFunc, UMin, (UMin+UMax)/2., UMax);
if(anOptLoc.IsDone())
{
extr = anOptLoc.Minimum();
return aSign * extr;
}
}
//
Standard_Integer aNbParticles = Max(8, RealToInt(32 * (UMax - UMin) / Du));
Standard_Real maxstep = (UMax - UMin) / (aNbParticles + 1);
math_Vector aT(1,1);
math_Vector aLowBorder(1,1);
math_Vector aUppBorder(1,1);
math_Vector aSteps(1,1);
aLowBorder(1) = UMin;
aUppBorder(1) = UMax;
aSteps(1) = Min(0.1 * Du, maxstep);
Curv2dMaxMinCoordMVar aFunc(myCurve, UMin, UMax, CoordIndx, aSign);
math_PSO aFinder(&aFunc, aLowBorder, aUppBorder, aSteps, aNbParticles);
aFinder.Perform(aSteps, extr, aT);
//
math_BrentMinimum anOptLoc(reltol, 100, UTol);
Curv2dMaxMinCoord aFunc1(myCurve, UMin, UMax, CoordIndx, aSign);
anOptLoc.Perform(aFunc1, Max(aT(1) - aSteps(1), UMin), aT(1), Min(aT(1) + aSteps(1), UMax));
if(anOptLoc.IsDone())
{
extr = anOptLoc.Minimum();
return aSign * extr;
}
return aSign * extr;
}
//=======================================================================
//function : PerformGenCurv
//purpose :
//=======================================================================
void BndLib_Box2dCurve::PerformGenCurv(const Standard_Real Tol)
{
//
Standard_Integer Nu = NbSamples();
//
Standard_Real CoordMin[2] = {RealLast(), RealLast()};
Standard_Real CoordMax[2] = {-RealLast(), -RealLast()};
Standard_Real DeflMax[2] = {-RealLast(), -RealLast()};
//
gp_Pnt2d P;
Standard_Integer i, k;
Standard_Real du = (myT2 - myT1)/(Nu-1), du2 = du / 2.;
NCollection_Array1<gp_XY> aPnts(1, Nu);
Standard_Real u;
for (i = 1, u = myT1; i <= Nu; i++, u += du)
{
D0(u,P);
aPnts(i) = P.XY();
//
for(k = 0; k < 2; ++k)
{
if(CoordMin[k] > P.Coord(k+1))
{
CoordMin[k] = P.Coord(k+1);
}
if(CoordMax[k] < P.Coord(k+1))
{
CoordMax[k] = P.Coord(k+1);
}
}
//
if(i > 1)
{
gp_XY aPm = 0.5 * (aPnts(i-1) + aPnts(i));
D0(u - du2, P);
gp_XY aD = (P.XY() - aPm);
for(k = 0; k < 2; ++k)
{
if(CoordMin[k] > P.Coord(k+1))
{
CoordMin[k] = P.Coord(k+1);
}
if(CoordMax[k] < P.Coord(k+1))
{
CoordMax[k] = P.Coord(k+1);
}
Standard_Real d = Abs(aD.Coord(k+1));
if(DeflMax[k] < d)
{
DeflMax[k] = d;
}
}
}
}
//
//Adjusting minmax
for(k = 0; k < 2; ++k)
{
Standard_Real d = DeflMax[k];
if(d <= Tol)
{
continue;
}
Standard_Real CMin = CoordMin[k];
Standard_Real CMax = CoordMax[k];
for(i = 1; i <= Nu; ++i)
{
if(aPnts(i).Coord(k+1) - CMin < d)
{
Standard_Real tmin, tmax;
tmin = myT1 + Max(0, i-2) * du;
tmax = myT1 + Min(Nu-1, i) * du;
Standard_Real cmin = AdjustExtr(tmin, tmax,
CMin, k + 1, Tol, Standard_True);
if(cmin < CMin)
{
CMin = cmin;
}
}
else if(CMax - aPnts(i).Coord(k+1) < d)
{
Standard_Real tmin, tmax;
tmin = myT1 + Max(0, i-2) * du;
tmax = myT1 + Min(Nu-1, i) * du;
Standard_Real cmax = AdjustExtr(tmin, tmax,
CMax, k + 1, Tol, Standard_False);
if(cmax > CMax)
{
CMax = cmax;
}
}
}
CoordMin[k] = CMin;
CoordMax[k] = CMax;
}
myBox.Add(gp_Pnt2d(CoordMin[0], CoordMin[1]));
myBox.Add(gp_Pnt2d(CoordMax[0], CoordMax[1]));
myBox.Enlarge(Tol);
}
//=======================================================================
//function : D0
//purpose :
//=======================================================================
@@ -895,3 +1252,24 @@ void BndLib_Add2dCurve::Add(const Handle(Geom2d_Curve)& aC2D,
aBox2D.Add(aBoxC);
aBox2D.Enlarge(aTol);
}
//=======================================================================
//function : AddOptimal
//purpose :
//=======================================================================
void BndLib_Add2dCurve::AddOptimal(const Handle(Geom2d_Curve)& aC2D,
const Standard_Real aT1,
const Standard_Real aT2,
const Standard_Real aTol,
Bnd_Box2d& aBox2D)
{
BndLib_Box2dCurve aBC;
//
aBC.SetCurve(aC2D);
aBC.SetRange(aT1, aT2);
//
aBC.PerformOptimal(aTol);
//
const Bnd_Box2d& aBoxC=aBC.Box();
aBox2D.Add(aBoxC);
aBox2D.Enlarge(aTol);
}
+13 -1
View File
@@ -115,7 +115,19 @@ public:
//! - if not, the points of an approximation of the curve C.
Standard_EXPORT static void Add (const Handle(Geom2d_Curve)& C, const Standard_Real U1, const Standard_Real U2, const Standard_Real Tol, Bnd_Box2d& B);
//! Adds to the bounding box B the part of curve C
//! B is then enlarged by the tolerance value Tol.
//! U1, U2 - the parametric range to comute the bounding box;
//! Note: depending on the type of curve, one of the following
//! algorithms is used to include it in the bounding box B:
//! - an exact analytical if C is built from a line, a circle or a conic curve,
//! - numerical calculation of bounding box sizes, based on minimization algorithm, for other types of curve
//! If Tol = < Precision::PConfusion(), Precision::PConfusion is used as tolerance for calculation
Standard_EXPORT static void AddOptimal(const Handle(Geom2d_Curve)& C,
const Standard_Real U1,
const Standard_Real U2,
const Standard_Real Tol,
Bnd_Box2d& B);
protected:
+393
View File
@@ -32,6 +32,23 @@
#include <TColgp_Array1OfPnt.hxx>
#include <TColStd_Array1OfInteger.hxx>
#include <TColStd_Array1OfReal.hxx>
#include <math_MultipleVarFunction.hxx>
#include <math_Function.hxx>
#include <math_PSO.hxx>
#include <math_BrentMinimum.hxx>
//
static Standard_Integer NbSamples(const Adaptor3d_Curve& C,
const Standard_Real Umin,
const Standard_Real Umax);
static Standard_Real AdjustExtr(const Adaptor3d_Curve& C,
const Standard_Real UMin,
const Standard_Real UMax,
const Standard_Real Extr0,
const Standard_Integer CoordIndx,
const Standard_Real Tol,
const Standard_Boolean IsMin);
//=======================================================================
//function : reduceSplineBox
@@ -247,3 +264,379 @@ void BndLib_Add3dCurve::Add( const Adaptor3d_Curve& C,
}
}
}
//=======================================================================
//function : AddOptimal
//purpose :
//=======================================================================
void BndLib_Add3dCurve::AddOptimal( const Adaptor3d_Curve& C,
const Standard_Real Tol,
Bnd_Box& B )
{
BndLib_Add3dCurve::AddOptimal(C,
C.FirstParameter(),
C.LastParameter (),
Tol,B);
}
//=======================================================================
//function : AddOptimal
//purpose :
//=======================================================================
void BndLib_Add3dCurve::AddOptimal( const Adaptor3d_Curve& C,
const Standard_Real U1,
const Standard_Real U2,
const Standard_Real Tol,
Bnd_Box& B)
{
switch (C.GetType()) {
case GeomAbs_Line:
{
BndLib::Add(C.Line(),U1,U2,Tol,B);
break;
}
case GeomAbs_Circle:
{
BndLib::Add(C.Circle(),U1,U2,Tol,B);
break;
}
case GeomAbs_Ellipse:
{
BndLib::Add(C.Ellipse(),U1,U2,Tol,B);
break;
}
case GeomAbs_Hyperbola:
{
BndLib::Add(C.Hyperbola(),U1,U2,Tol,B);
break;
}
case GeomAbs_Parabola:
{
BndLib::Add(C.Parabola(),U1,U2,Tol,B);
break;
}
default:
{
AddGenCurv(C, U1, U2, Tol, B);
}
}
}
//=======================================================================
//function : AddGenCurv
//purpose :
//=======================================================================
void BndLib_Add3dCurve::AddGenCurv(const Adaptor3d_Curve& C,
const Standard_Real UMin,
const Standard_Real UMax,
const Standard_Real Tol,
Bnd_Box& B)
{
Standard_Integer Nu = NbSamples(C, UMin, UMax);
//
Standard_Real CoordMin[3] = {RealLast(), RealLast(), RealLast()};
Standard_Real CoordMax[3] = {-RealLast(), -RealLast(), -RealLast()};
Standard_Real DeflMax[3] = {-RealLast(), -RealLast(), -RealLast()};
//
gp_Pnt P;
Standard_Integer i, k;
Standard_Real du = (UMax-UMin)/(Nu-1), du2 = du / 2.;
NCollection_Array1<gp_XYZ> aPnts(1, Nu);
Standard_Real u;
for (i = 1, u = UMin; i <= Nu; i++, u += du)
{
C.D0(u,P);
aPnts(i) = P.XYZ();
//
for(k = 0; k < 3; ++k)
{
if(CoordMin[k] > P.Coord(k+1))
{
CoordMin[k] = P.Coord(k+1);
}
if(CoordMax[k] < P.Coord(k+1))
{
CoordMax[k] = P.Coord(k+1);
}
}
//
if(i > 1)
{
gp_XYZ aPm = 0.5 * (aPnts(i-1) + aPnts(i));
C.D0(u - du2, P);
gp_XYZ aD = (P.XYZ() - aPm);
for(k = 0; k < 3; ++k)
{
if(CoordMin[k] > P.Coord(k+1))
{
CoordMin[k] = P.Coord(k+1);
}
if(CoordMax[k] < P.Coord(k+1))
{
CoordMax[k] = P.Coord(k+1);
}
Standard_Real d = Abs(aD.Coord(k+1));
if(DeflMax[k] < d)
{
DeflMax[k] = d;
}
}
}
}
//
//Adjusting minmax
Standard_Real eps = Max(Tol, Precision::Confusion());
for(k = 0; k < 3; ++k)
{
Standard_Real d = DeflMax[k];
if(d <= eps)
{
continue;
}
Standard_Real CMin = CoordMin[k];
Standard_Real CMax = CoordMax[k];
for(i = 1; i <= Nu; ++i)
{
if(aPnts(i).Coord(k+1) - CMin < d)
{
Standard_Real umin, umax;
umin = UMin + Max(0, i-2) * du;
umax = UMin + Min(Nu-1, i) * du;
Standard_Real cmin = AdjustExtr(C, umin, umax,
CMin, k + 1, eps, Standard_True);
if(cmin < CMin)
{
CMin = cmin;
}
}
else if(CMax - aPnts(i).Coord(k+1) < d)
{
Standard_Real umin, umax;
umin = UMin + Max(0, i-2) * du;
umax = UMin + Min(Nu-1, i) * du;
Standard_Real cmax = AdjustExtr(C, umin, umax,
CMax, k + 1, eps, Standard_False);
if(cmax > CMax)
{
CMax = cmax;
}
}
}
CoordMin[k] = CMin;
CoordMax[k] = CMax;
}
B.Add(gp_Pnt(CoordMin[0], CoordMin[1], CoordMin[2]));
B.Add(gp_Pnt(CoordMax[0], CoordMax[1], CoordMax[2]));
B.Enlarge(eps);
}
//
class CurvMaxMinCoordMVar : public math_MultipleVarFunction
{
public:
CurvMaxMinCoordMVar(const Adaptor3d_Curve& theCurve,
const Standard_Real UMin,
const Standard_Real UMax,
const Standard_Integer CoordIndx,
const Standard_Real Sign)
: myCurve(theCurve),
myUMin(UMin),
myUMax(UMax),
myCoordIndx(CoordIndx),
mySign(Sign)
{
}
Standard_Boolean Value (const math_Vector& X,
Standard_Real& F)
{
if (!CheckInputData(X(1)))
{
return Standard_False;
}
gp_Pnt aP = myCurve.Value(X(1));
F = mySign * aP.Coord(myCoordIndx);
return Standard_True;
}
Standard_Integer NbVariables() const
{
return 1;
}
private:
CurvMaxMinCoordMVar & operator = (const CurvMaxMinCoordMVar & theOther);
Standard_Boolean CheckInputData(Standard_Real theParam)
{
if (theParam < myUMin ||
theParam > myUMax)
return Standard_False;
return Standard_True;
}
const Adaptor3d_Curve& myCurve;
Standard_Real myUMin;
Standard_Real myUMax;
Standard_Integer myCoordIndx;
Standard_Real mySign;
};
//
class CurvMaxMinCoord : public math_Function
{
public:
CurvMaxMinCoord(const Adaptor3d_Curve& theCurve,
const Standard_Real UMin,
const Standard_Real UMax,
const Standard_Integer CoordIndx,
const Standard_Real Sign)
: myCurve(theCurve),
myUMin(UMin),
myUMax(UMax),
myCoordIndx(CoordIndx),
mySign(Sign)
{
}
Standard_Boolean Value (const Standard_Real X,
Standard_Real& F)
{
if (!CheckInputData(X))
{
return Standard_False;
}
gp_Pnt aP = myCurve.Value(X);
F = mySign * aP.Coord(myCoordIndx);
return Standard_True;
}
private:
CurvMaxMinCoord & operator = (const CurvMaxMinCoord & theOther);
Standard_Boolean CheckInputData(Standard_Real theParam)
{
if (theParam < myUMin ||
theParam > myUMax)
return Standard_False;
return Standard_True;
}
const Adaptor3d_Curve& myCurve;
Standard_Real myUMin;
Standard_Real myUMax;
Standard_Integer myCoordIndx;
Standard_Real mySign;
};
//=======================================================================
//function : AdjustExtr
//purpose :
//=======================================================================
Standard_Real AdjustExtr(const Adaptor3d_Curve& C,
const Standard_Real UMin,
const Standard_Real UMax,
const Standard_Real Extr0,
const Standard_Integer CoordIndx,
const Standard_Real Tol,
const Standard_Boolean IsMin)
{
Standard_Real aSign = IsMin ? 1.:-1.;
Standard_Real extr = aSign * Extr0;
//
Standard_Real uTol = Max(C.Resolution(Tol), Precision::PConfusion());
Standard_Real Du = (C.LastParameter() - C.FirstParameter());
//
Standard_Real reltol = uTol / Max(Abs(UMin), Abs(UMax));
if(UMax - UMin < 0.01 * Du)
{
math_BrentMinimum anOptLoc(reltol, 100, uTol);
CurvMaxMinCoord aFunc(C, UMin, UMax, CoordIndx, aSign);
anOptLoc.Perform(aFunc, UMin, (UMin+UMax)/2., UMax);
if(anOptLoc.IsDone())
{
extr = anOptLoc.Minimum();
return aSign * extr;
}
}
//
Standard_Integer aNbParticles = Max(8, RealToInt(32 * (UMax - UMin) / Du));
Standard_Real maxstep = (UMax - UMin) / (aNbParticles + 1);
math_Vector aT(1,1);
math_Vector aLowBorder(1,1);
math_Vector aUppBorder(1,1);
math_Vector aSteps(1,1);
aLowBorder(1) = UMin;
aUppBorder(1) = UMax;
aSteps(1) = Min(0.1 * Du, maxstep);
CurvMaxMinCoordMVar aFunc(C, UMin, UMax, CoordIndx, aSign);
math_PSO aFinder(&aFunc, aLowBorder, aUppBorder, aSteps, aNbParticles);
aFinder.Perform(aSteps, extr, aT);
//
math_BrentMinimum anOptLoc(reltol, 100, uTol);
CurvMaxMinCoord aFunc1(C, UMin, UMax, CoordIndx, aSign);
anOptLoc.Perform(aFunc1, Max(aT(1) - aSteps(1), UMin), aT(1), Min(aT(1) + aSteps(1), UMax));
if(anOptLoc.IsDone())
{
extr = anOptLoc.Minimum();
return aSign * extr;
}
return aSign * extr;
}
//=======================================================================
//function : NbSamples
//purpose :
//=======================================================================
Standard_Integer NbSamples(const Adaptor3d_Curve& C,
const Standard_Real Umin,
const Standard_Real Umax)
{
Standard_Integer N;
GeomAbs_CurveType Type = C.GetType();
switch (Type) {
case GeomAbs_BezierCurve:
{
N = 2 * C.NbPoles();
//By default parametric range of Bezier curv is [0, 1]
Standard_Real du = Umax - Umin;
if(du < .9)
{
N = RealToInt(du*N) + 1;
N = Max(N, 5);
}
break;
}
case GeomAbs_BSplineCurve:
{
const Handle(Geom_BSplineCurve)& BC = C.BSpline();
N = 2 * (BC->Degree() + 1)*(BC->NbKnots() -1);
Standard_Real umin = BC->FirstParameter(),
umax = BC->LastParameter();
Standard_Real du = (Umax - Umin) / (umax - umin);
if(du < .9)
{
N = RealToInt(du*N) + 1;
N = Max(N, 5);
}
break;
}
default:
N = 33;
}
return Min(500, N);
}
+19 -2
View File
@@ -22,8 +22,11 @@
#include <Standard_Handle.hxx>
#include <Standard_Real.hxx>
//
class Adaptor3d_Curve;
class Bnd_Box;
class gp_Circ;
class gp_Elips;
//! Computes the bounding box for a curve in 3d.
@@ -92,8 +95,22 @@ public:
//! numbers, or two positive infinite real numbers.
Standard_EXPORT static void Add (const Adaptor3d_Curve& C, const Standard_Real U1, const Standard_Real U2, const Standard_Real Tol, Bnd_Box& B);
//! Adds to the bounding box B the curve C
//! These methods use more precise algorithms for building bnd box
//! then methods Add(...)
Standard_EXPORT static void AddOptimal (const Adaptor3d_Curve& C, const Standard_Real Tol, Bnd_Box& B);
Standard_EXPORT static void AddOptimal (const Adaptor3d_Curve& C,
const Standard_Real U1, const Standard_Real U2,
const Standard_Real Tol, Bnd_Box& B);
//! Adds to the bounding box B the curve C
//! using numerical minimization algorithms
//! This method is used in AddOptimal for not analytical curves.
//! if Tol < Precision::Confusion(), Precision:;Confusion is used as computation tolerance
Standard_EXPORT static void AddGenCurv(const Adaptor3d_Curve& C,
const Standard_Real UMin,
const Standard_Real UMax,
const Standard_Real Tol,
Bnd_Box& B);
protected:
+526
View File
@@ -23,15 +23,42 @@
#include <BndLib_AddSurface.hxx>
#include <BSplCLib.hxx>
#include <ElSLib.hxx>
#include <ElCLib.hxx>
#include <Geom_BezierSurface.hxx>
#include <Geom_BSplineSurface.hxx>
#include <GeomAbs_SurfaceType.hxx>
#include <gp_Pln.hxx>
#include <gp_Pnt.hxx>
#include <gp_Cylinder.hxx>
#include <gp_Cone.hxx>
#include <gp_Lin.hxx>
#include <Precision.hxx>
#include <TColgp_Array2OfPnt.hxx>
#include <TColStd_Array1OfInteger.hxx>
#include <TColStd_Array1OfReal.hxx>
#include <BndLib_Add3dCurve.hxx>
#include <math_MultipleVarFunction.hxx>
#include <math_PSO.hxx>
#include <math_Matrix.hxx>
#include <math_Powell.hxx>
//
static Standard_Integer NbUSamples(const Adaptor3d_Surface& S,
const Standard_Real Umin,
const Standard_Real Umax);
//
static Standard_Integer NbVSamples(const Adaptor3d_Surface& S,
const Standard_Real Vmin,
const Standard_Real Vmax);
//
static Standard_Real AdjustExtr(const Adaptor3d_Surface& S,
const Standard_Real UMin,
const Standard_Real UMax,
const Standard_Real VMin,
const Standard_Real VMax,
const Standard_Real Extr0,
const Standard_Integer CoordIndx,
const Standard_Real Tol,
const Standard_Boolean IsMin);
//=======================================================================
//function : Add
@@ -450,3 +477,502 @@ void BndLib_AddSurface::Add(const Adaptor3d_Surface& S,
}
}
}
//----- Methods for AddOptimal ---------------------------------------
//=======================================================================
//function : AddOptimal
//purpose :
//=======================================================================
void BndLib_AddSurface::AddOptimal(const Adaptor3d_Surface& S,
const Standard_Real Tol,
Bnd_Box& B )
{
BndLib_AddSurface::AddOptimal(S,
S.FirstUParameter(),
S.LastUParameter (),
S.FirstVParameter(),
S.LastVParameter (),Tol,B);
}
//=======================================================================
//function : AddOptimal
//purpose :
//=======================================================================
void BndLib_AddSurface::AddOptimal(const Adaptor3d_Surface& S,
const Standard_Real UMin,
const Standard_Real UMax,
const Standard_Real VMin,
const Standard_Real VMax,
const Standard_Real Tol,
Bnd_Box& B )
{
GeomAbs_SurfaceType Type = S.GetType();
if (Precision::IsInfinite(VMin) ||
Precision::IsInfinite(VMax) ||
Precision::IsInfinite(UMin) ||
Precision::IsInfinite(UMax) ) {
switch (Type) {
case GeomAbs_Plane:
{
TreatInfinitePlane(S.Plane(), UMin, UMax, VMin, VMax, Tol, B);
return;
}
default:
{
B.SetWhole();
return;
}
}
}
switch (Type) {
case GeomAbs_Plane:
{
gp_Pln Plan = S.Plane();
B.Add(ElSLib::Value(UMin,VMin,Plan));
B.Add(ElSLib::Value(UMin,VMax,Plan));
B.Add(ElSLib::Value(UMax,VMin,Plan));
B.Add(ElSLib::Value(UMax,VMax,Plan));
B.Enlarge(Tol);
break;
}
case GeomAbs_Cylinder:
{
BndLib::Add(S.Cylinder(), UMin, UMax, VMin, VMax, Tol, B);
break;
}
case GeomAbs_Cone:
{
BndLib::Add(S.Cone(), UMin, UMax, VMin, VMax, Tol, B);
break;
}
case GeomAbs_Sphere:
{
BndLib::Add(S.Sphere(), UMin, UMax, VMin, VMax, Tol, B);
break;
}
default:
{
AddGenSurf(S, UMin, UMax, VMin, VMax, Tol, B);
}
}
}
//=======================================================================
//function : AddGenSurf
//purpose :
//=======================================================================
void BndLib_AddSurface::AddGenSurf(const Adaptor3d_Surface& S,
const Standard_Real UMin,
const Standard_Real UMax,
const Standard_Real VMin,
const Standard_Real VMax,
const Standard_Real Tol,
Bnd_Box& B)
{
Standard_Integer Nu = NbUSamples(S, UMin, UMax);
Standard_Integer Nv = NbVSamples(S, VMin, VMax);
//
Standard_Real CoordMin[3] = {RealLast(), RealLast(), RealLast()};
Standard_Real CoordMax[3] = {-RealLast(), -RealLast(), -RealLast()};
Standard_Real DeflMax[3] = {-RealLast(), -RealLast(), -RealLast()};
//
//
Standard_Real du = (UMax-UMin)/(Nu-1), du2 = du / 2.;
Standard_Real dv = (VMax-VMin)/(Nv-1), dv2 = dv / 2.;
NCollection_Array2<gp_XYZ> aPnts(1, Nu, 1, Nv);
Standard_Real u, v;
Standard_Integer i, j, k;
gp_Pnt P;
for (i = 1, u = UMin; i <= Nu; i++, u += du){
for (j = 1, v = VMin;j <= Nv; j++, v += dv){
S.D0(u,v,P);
aPnts(i, j) = P.XYZ();
//
for(k = 0; k < 3; ++k)
{
if(CoordMin[k] > P.Coord(k+1))
{
CoordMin[k] = P.Coord(k+1);
}
if(CoordMax[k] < P.Coord(k+1))
{
CoordMax[k] = P.Coord(k+1);
}
}
//
if(i > 1)
{
gp_XYZ aPm = 0.5 * (aPnts(i-1,j) + aPnts(i, j));
S.D0(u - du2, v, P);
gp_XYZ aD = (P.XYZ() - aPm);
for(k = 0; k < 3; ++k)
{
if(CoordMin[k] > P.Coord(k+1))
{
CoordMin[k] = P.Coord(k+1);
}
if(CoordMax[k] < P.Coord(k+1))
{
CoordMax[k] = P.Coord(k+1);
}
Standard_Real d = Abs(aD.Coord(k+1));
if(DeflMax[k] < d)
{
DeflMax[k] = d;
}
}
}
if(j > 1)
{
gp_XYZ aPm = 0.5 * (aPnts(i,j-1) + aPnts(i, j));
S.D0(u , v - dv2, P);
gp_XYZ aD = (P.XYZ() - aPm);
for(k = 0; k < 3; ++k)
{
if(CoordMin[k] > P.Coord(k+1))
{
CoordMin[k] = P.Coord(k+1);
}
if(CoordMax[k] < P.Coord(k+1))
{
CoordMax[k] = P.Coord(k+1);
}
Standard_Real d = Abs(aD.Coord(k+1));
if(DeflMax[k] < d)
{
DeflMax[k] = d;
}
}
}
}
}
//
//Adjusting minmax
Standard_Real eps = Max(Tol, Precision::Confusion());
for(k = 0; k < 3; ++k)
{
Standard_Real d = DeflMax[k];
if(d <= eps)
{
continue;
}
Standard_Real CMin = CoordMin[k];
Standard_Real CMax = CoordMax[k];
for(i = 1; i <= Nu; ++i)
{
for(j = 1; j <= Nv; ++j)
{
if(aPnts(i,j).Coord(k+1) - CMin < d)
{
Standard_Real umin, umax, vmin, vmax;
umin = UMin + Max(0, i-2) * du;
umax = UMin + Min(Nu-1, i) * du;
vmin = VMin + Max(0, j-2) * dv;
vmax = VMin + Min(Nv-1, j) * dv;
Standard_Real cmin = AdjustExtr(S, umin, umax, vmin, vmax,
CMin, k + 1, eps, Standard_True);
if(cmin < CMin)
{
CMin = cmin;
}
}
else if(CMax - aPnts(i,j).Coord(k+1) < d)
{
Standard_Real umin, umax, vmin, vmax;
umin = UMin + Max(0, i-2) * du;
umax = UMin + Min(Nu-1, i) * du;
vmin = VMin + Max(0, j-2) * dv;
vmax = VMin + Min(Nv-1, j) * dv;
Standard_Real cmax = AdjustExtr(S, umin, umax, vmin, vmax,
CMax, k + 1, eps, Standard_False);
if(cmax > CMax)
{
CMax = cmax;
}
}
}
}
CoordMin[k] = CMin;
CoordMax[k] = CMax;
}
B.Add(gp_Pnt(CoordMin[0], CoordMin[1], CoordMin[2]));
B.Add(gp_Pnt(CoordMax[0], CoordMax[1], CoordMax[2]));
B.Enlarge(eps);
}
//
//
class SurfMaxMinCoord : public math_MultipleVarFunction
{
public:
SurfMaxMinCoord(const Adaptor3d_Surface& theSurf,
const Standard_Real UMin,
const Standard_Real UMax,
const Standard_Real VMin,
const Standard_Real VMax,
const Standard_Integer CoordIndx,
const Standard_Real Sign)
: mySurf(theSurf),
myUMin(UMin),
myUMax(UMax),
myVMin(VMin),
myVMax(VMax),
myCoordIndx(CoordIndx),
mySign(Sign)
{
math_Vector X(1,2);
X(1) = UMin;
X(2) = (VMin + VMax) / 2.;
Standard_Real F1, F2;
Value(X, F1);
X(1) = UMax;
Value(X, F2);
Standard_Real DU = Abs((F2 - F1) / (UMax - UMin));
X(1) = (UMin + UMax) / 2.;
X(2) = VMin;
Value(X, F1);
X(2) = VMax;
Value(X, F2);
Standard_Real DV = Abs((F2 - F1) / (VMax - VMin));
myPenalty = 10. * Max(DU, DV);
myPenalty = Max(myPenalty, 1.);
}
Standard_Boolean Value (const math_Vector& X,
Standard_Real& F)
{
if (CheckInputData(X))
{
gp_Pnt aP = mySurf.Value(X(1), X(2));
F = mySign * aP.Coord(myCoordIndx);
}
else
{
Standard_Real UPen = 0., VPen = 0., u0, v0;
if(X(1) < myUMin)
{
UPen = myPenalty * (myUMin - X(1));
u0 = myUMin;
}
else if(X(1) > myUMax)
{
UPen = myPenalty * (X(1) - myUMax);
u0 = myUMax;
}
else
{
u0 = X(1);
}
//
if(X(2) < myVMin)
{
VPen = myPenalty * (myVMin - X(2));
v0 = myVMin;
}
else if(X(2) > myVMax)
{
VPen = myPenalty * (X(2) - myVMax);
v0 = myVMax;
}
else
{
v0 = X(2);
}
//
gp_Pnt aP = mySurf.Value(u0, v0);
F = mySign * aP.Coord(myCoordIndx) + UPen + VPen;
}
return Standard_True;
}
Standard_Integer NbVariables() const
{
return 2;
}
private:
SurfMaxMinCoord & operator = (const SurfMaxMinCoord & theOther);
Standard_Boolean CheckInputData(const math_Vector theParams)
{
if (theParams(1) < myUMin ||
theParams(1) > myUMax ||
theParams(2) < myVMin ||
theParams(2) > myVMax)
return Standard_False;
return Standard_True;
}
const Adaptor3d_Surface& mySurf;
Standard_Real myUMin;
Standard_Real myUMax;
Standard_Real myVMin;
Standard_Real myVMax;
Standard_Integer myCoordIndx;
Standard_Real mySign;
Standard_Real myPenalty;
};
//=======================================================================
//function : AdjustExtr
//purpose :
//=======================================================================
Standard_Real AdjustExtr(const Adaptor3d_Surface& S,
const Standard_Real UMin,
const Standard_Real UMax,
const Standard_Real VMin,
const Standard_Real VMax,
const Standard_Real Extr0,
const Standard_Integer CoordIndx,
const Standard_Real Tol,
const Standard_Boolean IsMin)
{
Standard_Real aSign = IsMin ? 1.:-1.;
Standard_Real extr = aSign * Extr0;
Standard_Real relTol = 2.*Tol;
if(Abs(extr) > Tol)
{
relTol /= Abs(extr);
}
Standard_Real Du = (S.LastUParameter() - S.FirstUParameter());
Standard_Real Dv = (S.LastVParameter() - S.FirstVParameter());
//
math_Vector aT(1,2);
math_Vector aLowBorder(1,2);
math_Vector aUppBorder(1,2);
math_Vector aSteps(1,2);
aLowBorder(1) = UMin;
aUppBorder(1) = UMax;
aLowBorder(2) = VMin;
aUppBorder(2) = VMax;
Standard_Integer aNbU = Max(8, RealToInt(32 * (UMax - UMin) / Du));
Standard_Integer aNbV = Max(8, RealToInt(32 * (VMax - VMin) / Dv));
Standard_Integer aNbParticles = aNbU * aNbV;
Standard_Real aMaxUStep = (UMax - UMin) / (aNbU + 1);
aSteps(1) = Min(0.1 * Du, aMaxUStep);
Standard_Real aMaxVStep = (VMax - VMin) / (aNbV + 1);
aSteps(2) = Min(0.1 * Dv, aMaxVStep);
SurfMaxMinCoord aFunc(S, UMin, UMax, VMin, VMax, CoordIndx, aSign);
math_PSO aFinder(&aFunc, aLowBorder, aUppBorder, aSteps, aNbParticles);
aFinder.Perform(aSteps, extr, aT);
//Refinement of extremal value
math_Matrix aDir(1, 2, 1, 2, 0.0);
aDir(1, 1) = 1.;
aDir(2, 1) = 0.;
aDir(1, 2) = 0.;
aDir(2, 2) = 1.;
Standard_Integer aNbIter = 200;
math_Powell powell(aFunc, relTol, aNbIter, Tol);
powell.Perform(aFunc, aT, aDir);
if (powell.IsDone())
{
powell.Location(aT);
extr = powell.Minimum();
}
return aSign * extr;
}
//=======================================================================
//function : NbUSamples
//purpose :
//=======================================================================
Standard_Integer NbUSamples(const Adaptor3d_Surface& S,
const Standard_Real Umin,
const Standard_Real Umax)
{
Standard_Integer N;
GeomAbs_SurfaceType Type = S.GetType();
switch (Type) {
case GeomAbs_BezierSurface:
{
N = 2*S.NbUPoles();
//By default parametric range of Bezier surf is [0, 1] [0, 1]
Standard_Real du = Umax - Umin;
if(du < .9)
{
N = RealToInt(du*N) + 1;
N = Max(N, 5);
}
break;
}
case GeomAbs_BSplineSurface:
{
const Handle(Geom_BSplineSurface)& BS = S.BSpline();
N = 2*(BS->UDegree() + 1)*(BS->NbUKnots() -1);
Standard_Real umin, umax, vmin, vmax;
BS->Bounds(umin, umax, vmin, vmax);
Standard_Real du = (Umax - Umin) / (umax - umin);
if(du < .9)
{
N = RealToInt(du*N) + 1;
N = Max(N, 5);
}
break;
}
default:
N = 33;
}
return Min (50,N);
}
//=======================================================================
//function : NbVSamples
//purpose :
//=======================================================================
Standard_Integer NbVSamples(const Adaptor3d_Surface& S,
const Standard_Real Vmin,
const Standard_Real Vmax)
{
Standard_Integer N;
GeomAbs_SurfaceType Type = S.GetType();
switch (Type) {
case GeomAbs_BezierSurface:
{
N = 2*S.NbVPoles();
//By default parametric range of Bezier surf is [0, 1] [0, 1]
Standard_Real dv = Vmax - Vmin;
if(dv < .9)
{
N = RealToInt(dv*N) + 1;
N = Max(N, 5);
}
break;
}
case GeomAbs_BSplineSurface:
{
const Handle(Geom_BSplineSurface)& BS = S.BSpline();
N = 2*(BS->VDegree() + 1)*(BS->NbVKnots() - 1) ;
Standard_Real umin, umax, vmin, vmax;
BS->Bounds(umin, umax, vmin, vmax);
Standard_Real dv = (Vmax - Vmin) / (vmax - vmin);
if(dv < .9)
{
N = RealToInt(dv*N) + 1;
N = Max(N, 5);
}
break;
}
default:
N = 33;
}
return Min(50,N);
}
+23 -3
View File
@@ -24,7 +24,9 @@
#include <Standard_Real.hxx>
class Adaptor3d_Surface;
class Bnd_Box;
class gp_Cylinder;
class gp_Cone;
class gp_Sphere;
//! computes the box from a surface
//! Functions to add a surface to a bounding box.
@@ -99,8 +101,28 @@ public:
//! AddSurface::Add ( S, Tol, B );
Standard_EXPORT static void Add (const Adaptor3d_Surface& S, const Standard_Real UMin, const Standard_Real UMax, const Standard_Real VMin, const Standard_Real VMax, const Standard_Real Tol, Bnd_Box& B);
//! Adds the surface S to the bounding box B.
//! This algorith builds precise bounding box
Standard_EXPORT static void AddOptimal (const Adaptor3d_Surface& S, const Standard_Real Tol, Bnd_Box& B);
Standard_EXPORT static void AddOptimal (const Adaptor3d_Surface& S,
const Standard_Real UMin, const Standard_Real UMax,
const Standard_Real VMin, const Standard_Real VMax,
const Standard_Real Tol, Bnd_Box& B);
//! Adds to the bounding box B the surface S
//! using numerical minimization algorithms
//! This method is used in AddOptimal for not analytical surfaces and torus.
//! if Tol < Precision::Confusion(), Precision::Confusion is used as computation tolerance
Standard_EXPORT static void AddGenSurf(const Adaptor3d_Surface& S,
const Standard_Real UMin,
const Standard_Real UMax,
const Standard_Real VMin,
const Standard_Real VMax,
const Standard_Real Tol,
Bnd_Box& B);
protected:
@@ -112,8 +134,6 @@ private:
};