mirror of
https://git.dev.opencascade.org/repos/occt.git
synced 2025-04-10 18:51:21 +03:00
Update empty method guards to new style with regex (see PR). Used clang-format 18.1.8. New actions to validate code formatting is added. Update .clang-format with disabling of include sorting. It is temporary changes, then include will be sorted. Apply formatting for /src and /tools folder. The files with .hxx,.cxx,.lxx,.h,.pxx,.hpp,*.cpp extensions.
1276 lines
31 KiB
C++
1276 lines
31 KiB
C++
// Copyright (c) 1996-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 <Adaptor2d_Curve2d.hxx>
|
|
#include <Bnd_Box2d.hxx>
|
|
#include <BndLib_Add2dCurve.hxx>
|
|
#include <Geom2d_BezierCurve.hxx>
|
|
#include <Geom2d_BSplineCurve.hxx>
|
|
#include <Geom2d_Circle.hxx>
|
|
#include <Geom2d_Conic.hxx>
|
|
#include <Geom2d_Curve.hxx>
|
|
#include <Geom2d_Ellipse.hxx>
|
|
#include <Geom2d_Geometry.hxx>
|
|
#include <Geom2d_Hyperbola.hxx>
|
|
#include <Geom2d_Line.hxx>
|
|
#include <Geom2d_OffsetCurve.hxx>
|
|
#include <Geom2d_Parabola.hxx>
|
|
#include <Geom2d_TrimmedCurve.hxx>
|
|
#include <Geom2dAdaptor_Curve.hxx>
|
|
#include <gp.hxx>
|
|
#include <Precision.hxx>
|
|
#include <Standard_Type.hxx>
|
|
#include <math_Function.hxx>
|
|
#include <math_BrentMinimum.hxx>
|
|
#include <math_PSO.hxx>
|
|
|
|
//=================================================================================================
|
|
|
|
class BndLib_Box2dCurve
|
|
{
|
|
public:
|
|
BndLib_Box2dCurve();
|
|
|
|
virtual ~BndLib_Box2dCurve();
|
|
|
|
void SetCurve(const Handle(Geom2d_Curve)& aC);
|
|
|
|
const Handle(Geom2d_Curve)& Curve() const;
|
|
|
|
void SetRange(const Standard_Real aT1, const Standard_Real aT2);
|
|
|
|
void Range(Standard_Real& aT1, Standard_Real& aT2) const;
|
|
|
|
const Bnd_Box2d& Box() const;
|
|
|
|
void Perform();
|
|
|
|
void PerformOptimal(const Standard_Real Tol);
|
|
|
|
// Keep myT1 and myT2 unchanged
|
|
void Clear();
|
|
|
|
Standard_Integer ErrorStatus() const;
|
|
//
|
|
//-----------------------------
|
|
protected:
|
|
void CheckData();
|
|
void GetInfoBase();
|
|
void PerformLineConic();
|
|
void PerformBezier();
|
|
void PerformBSpline();
|
|
void PerformOther();
|
|
void D0(const Standard_Real, gp_Pnt2d&);
|
|
//
|
|
void Compute(const Handle(Geom2d_Conic)&,
|
|
const GeomAbs_CurveType,
|
|
const Standard_Real,
|
|
const Standard_Real,
|
|
Bnd_Box2d& aBox2D);
|
|
//
|
|
static Standard_Integer Compute(const Handle(Geom2d_Conic)&,
|
|
const GeomAbs_CurveType,
|
|
Standard_Real*);
|
|
static Standard_Boolean IsTypeBase(const Handle(Geom2d_Curve)&, GeomAbs_CurveType&);
|
|
static Standard_Real AdjustToPeriod(const Standard_Real, 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;
|
|
Bnd_Box2d myBox;
|
|
Standard_Integer myErrorStatus;
|
|
Handle(Geom2d_Curve) myCurveBase;
|
|
Standard_Real myOffsetBase;
|
|
Standard_Boolean myOffsetFlag;
|
|
Standard_Real myT1;
|
|
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;
|
|
};
|
|
|
|
//=================================================================================================
|
|
|
|
BndLib_Box2dCurve::BndLib_Box2dCurve()
|
|
{
|
|
Clear();
|
|
}
|
|
|
|
//=================================================================================================
|
|
|
|
BndLib_Box2dCurve::~BndLib_Box2dCurve() {}
|
|
|
|
//=================================================================================================
|
|
|
|
void BndLib_Box2dCurve::Clear()
|
|
{
|
|
myBox.SetVoid();
|
|
//
|
|
myErrorStatus = -1;
|
|
myTypeBase = GeomAbs_OtherCurve;
|
|
myOffsetBase = 0.;
|
|
myOffsetFlag = Standard_False;
|
|
}
|
|
|
|
//=================================================================================================
|
|
|
|
void BndLib_Box2dCurve::SetCurve(const Handle(Geom2d_Curve)& aC2D)
|
|
{
|
|
myCurve = aC2D;
|
|
}
|
|
|
|
//=================================================================================================
|
|
|
|
const Handle(Geom2d_Curve)& BndLib_Box2dCurve::Curve() const
|
|
{
|
|
return myCurve;
|
|
}
|
|
|
|
//=================================================================================================
|
|
|
|
void BndLib_Box2dCurve::SetRange(const Standard_Real aT1, const Standard_Real aT2)
|
|
{
|
|
myT1 = aT1;
|
|
myT2 = aT2;
|
|
}
|
|
|
|
//=================================================================================================
|
|
|
|
void BndLib_Box2dCurve::Range(Standard_Real& aT1, Standard_Real& aT2) const
|
|
{
|
|
aT1 = myT1;
|
|
aT2 = myT2;
|
|
}
|
|
|
|
//=================================================================================================
|
|
|
|
Standard_Integer BndLib_Box2dCurve::ErrorStatus() const
|
|
{
|
|
return myErrorStatus;
|
|
}
|
|
|
|
//=================================================================================================
|
|
|
|
const Bnd_Box2d& BndLib_Box2dCurve::Box() const
|
|
{
|
|
return myBox;
|
|
}
|
|
|
|
//=================================================================================================
|
|
|
|
void BndLib_Box2dCurve::CheckData()
|
|
{
|
|
myErrorStatus = 0;
|
|
//
|
|
if (myCurve.IsNull())
|
|
{
|
|
myErrorStatus = 10;
|
|
return;
|
|
}
|
|
//
|
|
if (myT1 > myT2)
|
|
{
|
|
myErrorStatus = 12; // invalid range
|
|
return;
|
|
}
|
|
}
|
|
|
|
//=================================================================================================
|
|
|
|
void BndLib_Box2dCurve::Perform()
|
|
{
|
|
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 if (myTypeBase == GeomAbs_BezierCurve)
|
|
{ // Bezier
|
|
PerformBezier();
|
|
}
|
|
else if (myTypeBase == GeomAbs_BSplineCurve)
|
|
{ // B-Spline
|
|
PerformBSpline();
|
|
}
|
|
else
|
|
{
|
|
myErrorStatus = 11; // unknown type base
|
|
}
|
|
}
|
|
|
|
//=================================================================================================
|
|
|
|
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);
|
|
}
|
|
}
|
|
|
|
//=================================================================================================
|
|
|
|
void BndLib_Box2dCurve::PerformOnePoint()
|
|
{
|
|
gp_Pnt2d aP2D;
|
|
//
|
|
myCurve->D0(myT1, aP2D);
|
|
myBox.Add(aP2D);
|
|
}
|
|
|
|
//=================================================================================================
|
|
|
|
void BndLib_Box2dCurve::PerformBezier()
|
|
{
|
|
if (myOffsetFlag)
|
|
{
|
|
PerformOther();
|
|
return;
|
|
}
|
|
//
|
|
Standard_Integer i, aNbPoles;
|
|
Standard_Real aT1, aT2, aTb[2];
|
|
gp_Pnt2d aP2D;
|
|
Handle(Geom2d_Geometry) aG;
|
|
Handle(Geom2d_BezierCurve) aCBz, aCBzSeg;
|
|
//
|
|
myErrorStatus = 0;
|
|
Bnd_Box2d& aBox2D = myBox;
|
|
//
|
|
aCBz = Handle(Geom2d_BezierCurve)::DownCast(myCurveBase);
|
|
aT1 = aCBz->FirstParameter();
|
|
aT2 = aCBz->LastParameter();
|
|
//
|
|
aTb[0] = myT1;
|
|
if (aTb[0] < aT1)
|
|
{
|
|
aTb[0] = aT1;
|
|
}
|
|
//
|
|
aTb[1] = myT2;
|
|
if (aTb[1] > aT2)
|
|
{
|
|
aTb[1] = aT2;
|
|
}
|
|
//
|
|
if (!(aT1 == aTb[0] && aT2 == aTb[1]))
|
|
{
|
|
aG = aCBz->Copy();
|
|
//
|
|
aCBzSeg = Handle(Geom2d_BezierCurve)::DownCast(aG);
|
|
aCBzSeg->Segment(aTb[0], aTb[1]);
|
|
aCBz = aCBzSeg;
|
|
}
|
|
//
|
|
aNbPoles = aCBz->NbPoles();
|
|
for (i = 1; i <= aNbPoles; ++i)
|
|
{
|
|
aP2D = aCBz->Pole(i);
|
|
aBox2D.Add(aP2D);
|
|
}
|
|
}
|
|
|
|
//=================================================================================================
|
|
|
|
void BndLib_Box2dCurve::PerformBSpline()
|
|
{
|
|
if (myOffsetFlag)
|
|
{
|
|
PerformOther();
|
|
return;
|
|
}
|
|
//
|
|
Standard_Integer i, aNbPoles;
|
|
Standard_Real aT1, aT2, aTb[2];
|
|
gp_Pnt2d aP2D;
|
|
Handle(Geom2d_Geometry) aG;
|
|
Handle(Geom2d_BSplineCurve) aCBS, aCBSs;
|
|
//
|
|
myErrorStatus = 0;
|
|
Bnd_Box2d& aBox2D = myBox;
|
|
//
|
|
aCBS = Handle(Geom2d_BSplineCurve)::DownCast(myCurveBase);
|
|
aT1 = aCBS->FirstParameter();
|
|
aT2 = aCBS->LastParameter();
|
|
//
|
|
aTb[0] = myT1;
|
|
if (aTb[0] < aT1)
|
|
{
|
|
aTb[0] = aT1;
|
|
}
|
|
aTb[1] = myT2;
|
|
if (aTb[1] > aT2)
|
|
{
|
|
aTb[1] = aT2;
|
|
}
|
|
|
|
if (aTb[1] < aTb[0])
|
|
{
|
|
aTb[0] = aT1;
|
|
aTb[1] = aT2;
|
|
}
|
|
|
|
//
|
|
constexpr Standard_Real eps = Precision::PConfusion();
|
|
if (fabs(aT1 - aTb[0]) > eps || fabs(aT2 - aTb[1]) > eps)
|
|
{
|
|
aG = aCBS->Copy();
|
|
//
|
|
aCBSs = Handle(Geom2d_BSplineCurve)::DownCast(aG);
|
|
aCBSs->Segment(aTb[0], aTb[1]);
|
|
aCBS = aCBSs;
|
|
}
|
|
//
|
|
aNbPoles = aCBS->NbPoles();
|
|
for (i = 1; i <= aNbPoles; ++i)
|
|
{
|
|
aP2D = aCBS->Pole(i);
|
|
aBox2D.Add(aP2D);
|
|
}
|
|
}
|
|
|
|
//=================================================================================================
|
|
|
|
void BndLib_Box2dCurve::PerformOther()
|
|
{
|
|
Standard_Integer j, aNb;
|
|
Standard_Real aT, dT;
|
|
gp_Pnt2d aP2D;
|
|
//
|
|
aNb = 33;
|
|
dT = (myT2 - myT1) / (aNb - 1);
|
|
//
|
|
for (j = 0; j < aNb; ++j)
|
|
{
|
|
aT = myT1 + j * dT;
|
|
myCurve->D0(aT, aP2D);
|
|
myBox.Add(aP2D);
|
|
}
|
|
myCurve->D0(myT2, aP2D);
|
|
myBox.Add(aP2D);
|
|
}
|
|
|
|
//=================================================================================================
|
|
|
|
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);
|
|
}
|
|
|
|
//=================================================================================================
|
|
|
|
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;
|
|
}
|
|
|
|
//=================================================================================================
|
|
|
|
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);
|
|
}
|
|
|
|
//=================================================================================================
|
|
|
|
void BndLib_Box2dCurve::D0(const Standard_Real aU, gp_Pnt2d& aP2D)
|
|
{
|
|
gp_Vec2d aV1;
|
|
//
|
|
myCurveBase->D1(aU, aP2D, aV1);
|
|
//
|
|
if (myOffsetFlag)
|
|
{
|
|
Standard_Integer aIndex, aMaxDegree;
|
|
Standard_Real aA, aB, aR, aRes;
|
|
//
|
|
aMaxDegree = 9;
|
|
aIndex = 2;
|
|
aRes = gp::Resolution();
|
|
//
|
|
while (aV1.Magnitude() <= aRes && aIndex <= aMaxDegree)
|
|
{
|
|
aV1 = myCurveBase->DN(aU, aIndex);
|
|
++aIndex;
|
|
}
|
|
//
|
|
aA = aV1.Y();
|
|
aB = -aV1.X();
|
|
aR = sqrt(aA * aA + aB * aB);
|
|
if (aR <= aRes)
|
|
{
|
|
myErrorStatus = 13;
|
|
return;
|
|
}
|
|
//
|
|
aR = myOffsetBase / aR;
|
|
aA = aA * aR;
|
|
aB = aB * aR;
|
|
aP2D.SetCoord(aP2D.X() + aA, aP2D.Y() + aB);
|
|
}
|
|
//
|
|
}
|
|
|
|
//=================================================================================================
|
|
|
|
void BndLib_Box2dCurve::GetInfoBase()
|
|
{
|
|
Standard_Boolean bIsTypeBase;
|
|
Standard_Integer iTrimmed, iOffset;
|
|
GeomAbs_CurveType aTypeB;
|
|
Handle(Geom2d_Curve) aC2DB;
|
|
Handle(Geom2d_TrimmedCurve) aCT2D;
|
|
Handle(Geom2d_OffsetCurve) aCF2D;
|
|
//
|
|
myErrorStatus = 0;
|
|
myTypeBase = GeomAbs_OtherCurve;
|
|
myOffsetBase = 0;
|
|
//
|
|
aC2DB = myCurve;
|
|
bIsTypeBase = IsTypeBase(aC2DB, aTypeB);
|
|
if (bIsTypeBase)
|
|
{
|
|
myTypeBase = aTypeB;
|
|
myCurveBase = myCurve;
|
|
return;
|
|
}
|
|
//
|
|
while (!bIsTypeBase)
|
|
{
|
|
iTrimmed = 0;
|
|
iOffset = 0;
|
|
aCT2D = Handle(Geom2d_TrimmedCurve)::DownCast(aC2DB);
|
|
if (!aCT2D.IsNull())
|
|
{
|
|
aC2DB = aCT2D->BasisCurve();
|
|
++iTrimmed;
|
|
}
|
|
//
|
|
aCF2D = Handle(Geom2d_OffsetCurve)::DownCast(aC2DB);
|
|
if (!aCF2D.IsNull())
|
|
{
|
|
Standard_Real aOffset;
|
|
//
|
|
aOffset = aCF2D->Offset();
|
|
myOffsetBase = myOffsetBase + aOffset;
|
|
myOffsetFlag = Standard_True;
|
|
//
|
|
aC2DB = aCF2D->BasisCurve();
|
|
++iOffset;
|
|
}
|
|
//
|
|
if (!(iTrimmed || iOffset))
|
|
{
|
|
break;
|
|
}
|
|
//
|
|
bIsTypeBase = IsTypeBase(aC2DB, aTypeB);
|
|
if (bIsTypeBase)
|
|
{
|
|
myTypeBase = aTypeB;
|
|
myCurveBase = aC2DB;
|
|
return;
|
|
}
|
|
}
|
|
//
|
|
myErrorStatus = 11; // unknown type base
|
|
}
|
|
|
|
//=================================================================================================
|
|
|
|
Standard_Boolean BndLib_Box2dCurve::IsTypeBase(const Handle(Geom2d_Curve)& aC2D,
|
|
GeomAbs_CurveType& aTypeB)
|
|
{
|
|
Standard_Boolean bRet;
|
|
Handle(Standard_Type) aType;
|
|
//
|
|
bRet = Standard_True;
|
|
//
|
|
aType = aC2D->DynamicType();
|
|
if (aType == STANDARD_TYPE(Geom2d_Line))
|
|
{
|
|
aTypeB = GeomAbs_Line;
|
|
}
|
|
else if (aType == STANDARD_TYPE(Geom2d_Circle))
|
|
{
|
|
aTypeB = GeomAbs_Circle;
|
|
}
|
|
else if (aType == STANDARD_TYPE(Geom2d_Ellipse))
|
|
{
|
|
aTypeB = GeomAbs_Ellipse;
|
|
}
|
|
else if (aType == STANDARD_TYPE(Geom2d_Parabola))
|
|
{
|
|
aTypeB = GeomAbs_Parabola;
|
|
}
|
|
else if (aType == STANDARD_TYPE(Geom2d_Hyperbola))
|
|
{
|
|
aTypeB = GeomAbs_Hyperbola;
|
|
}
|
|
else if (aType == STANDARD_TYPE(Geom2d_BezierCurve))
|
|
{
|
|
aTypeB = GeomAbs_BezierCurve;
|
|
}
|
|
else if (aType == STANDARD_TYPE(Geom2d_BSplineCurve))
|
|
{
|
|
aTypeB = GeomAbs_BSplineCurve;
|
|
}
|
|
else
|
|
{
|
|
aTypeB = GeomAbs_OtherCurve;
|
|
bRet = !bRet;
|
|
}
|
|
return bRet;
|
|
}
|
|
|
|
//=================================================================================================
|
|
|
|
void BndLib_Box2dCurve::PerformLineConic()
|
|
{
|
|
Standard_Integer i, iInf[2];
|
|
Standard_Real aTb[2];
|
|
gp_Pnt2d aP2D;
|
|
//
|
|
myErrorStatus = 0;
|
|
//
|
|
Bnd_Box2d& aBox2D = myBox;
|
|
//
|
|
iInf[0] = 0;
|
|
iInf[1] = 0;
|
|
aTb[0] = myT1;
|
|
aTb[1] = myT2;
|
|
//
|
|
for (i = 0; i < 2; ++i)
|
|
{
|
|
if (Precision::IsNegativeInfinite(aTb[i]))
|
|
{
|
|
D0(aTb[i], aP2D);
|
|
aBox2D.Add(aP2D);
|
|
++iInf[0];
|
|
}
|
|
else if (Precision::IsPositiveInfinite(aTb[i]))
|
|
{
|
|
D0(aTb[i], aP2D);
|
|
aBox2D.Add(aP2D);
|
|
++iInf[1];
|
|
}
|
|
else
|
|
{
|
|
D0(aTb[i], aP2D);
|
|
aBox2D.Add(aP2D);
|
|
}
|
|
}
|
|
//
|
|
if (myTypeBase == GeomAbs_Line)
|
|
{
|
|
return;
|
|
}
|
|
//
|
|
if (iInf[0] && iInf[1])
|
|
{
|
|
return;
|
|
}
|
|
//-------------
|
|
Handle(Geom2d_Conic) aConic2D;
|
|
//
|
|
aConic2D = Handle(Geom2d_Conic)::DownCast(myCurveBase);
|
|
Compute(aConic2D, myTypeBase, aTb[0], aTb[1], aBox2D);
|
|
}
|
|
|
|
//=================================================================================================
|
|
|
|
void BndLib_Box2dCurve::Compute(const Handle(Geom2d_Conic)& aConic2D,
|
|
const GeomAbs_CurveType aType,
|
|
const Standard_Real aT1,
|
|
const Standard_Real aT2,
|
|
Bnd_Box2d& aBox2D)
|
|
{
|
|
Standard_Integer i, aNbT;
|
|
Standard_Real pT[10], aT, aTwoPI, dT, aEps;
|
|
gp_Pnt2d aP2D;
|
|
//
|
|
aNbT = Compute(aConic2D, aType, pT);
|
|
//
|
|
if (aType == GeomAbs_Parabola || aType == GeomAbs_Hyperbola)
|
|
{
|
|
for (i = 0; i < aNbT; ++i)
|
|
{
|
|
aT = pT[i];
|
|
if (aT > aT1 && aT < aT2)
|
|
{
|
|
D0(aT, aP2D);
|
|
aBox2D.Add(aP2D);
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
//
|
|
// aType==GeomAbs_Circle || aType==GeomAbs_Ellipse
|
|
aEps = 1.e-14;
|
|
aTwoPI = 2. * M_PI;
|
|
dT = aT2 - aT1;
|
|
//
|
|
Standard_Real aT1z = AdjustToPeriod(aT1, aTwoPI);
|
|
if (fabs(aT1z) < aEps)
|
|
{
|
|
aT1z = 0.;
|
|
}
|
|
//
|
|
Standard_Real aT2z = aT1z + dT;
|
|
if (fabs(aT2z - aTwoPI) < aEps)
|
|
{
|
|
aT2z = aTwoPI;
|
|
}
|
|
//
|
|
for (i = 0; i < aNbT; ++i)
|
|
{
|
|
aT = pT[i];
|
|
// adjust aT to range [aT1z, aT1z + 2*PI]; note that pT[i] and aT1z
|
|
// are adjusted to range [0, 2*PI], but aT2z can be greater than 2*PI
|
|
aT = (aT < aT1z ? aT + aTwoPI : aT);
|
|
if (aT <= aT2z)
|
|
{
|
|
D0(aT, aP2D);
|
|
aBox2D.Add(aP2D);
|
|
}
|
|
}
|
|
}
|
|
|
|
//=================================================================================================
|
|
|
|
Standard_Integer BndLib_Box2dCurve::Compute(const Handle(Geom2d_Conic)& aConic2D,
|
|
const GeomAbs_CurveType aType,
|
|
Standard_Real* pT)
|
|
{
|
|
Standard_Integer iRet, i, j;
|
|
Standard_Real aCosBt, aSinBt, aCosGm, aSinGm;
|
|
Standard_Real aLx, aLy;
|
|
//
|
|
iRet = 0;
|
|
//
|
|
const gp_Ax22d& aPos = aConic2D->Position();
|
|
const gp_XY& aXDir = aPos.XDirection().XY();
|
|
const gp_XY& aYDir = aPos.YDirection().XY();
|
|
//
|
|
aCosBt = aXDir.X();
|
|
aSinBt = aXDir.Y();
|
|
aCosGm = aYDir.X();
|
|
aSinGm = aYDir.Y();
|
|
//
|
|
if (aType == GeomAbs_Circle || aType == GeomAbs_Ellipse)
|
|
{
|
|
Standard_Real aR1 = 0.0, aR2 = 0.0, aTwoPI = M_PI + M_PI;
|
|
Standard_Real aA11 = 0.0, aA12 = 0.0, aA21 = 0.0, aA22 = 0.0;
|
|
Standard_Real aBx = 0.0, aBy = 0.0, aB = 0.0, aCosFi = 0.0, aSinFi = 0.0, aFi = 0.0;
|
|
//
|
|
if (aType == GeomAbs_Ellipse)
|
|
{
|
|
Handle(Geom2d_Ellipse) aEL2D;
|
|
//
|
|
aEL2D = Handle(Geom2d_Ellipse)::DownCast(aConic2D);
|
|
aR1 = aEL2D->MajorRadius();
|
|
aR2 = aEL2D->MinorRadius();
|
|
}
|
|
else if (aType == GeomAbs_Circle)
|
|
{
|
|
Handle(Geom2d_Circle) aCR2D;
|
|
//
|
|
aCR2D = Handle(Geom2d_Circle)::DownCast(aConic2D);
|
|
aR1 = aCR2D->Radius();
|
|
aR2 = aR1;
|
|
}
|
|
//
|
|
aA11 = -aR1 * aCosBt;
|
|
aA12 = aR2 * aCosGm;
|
|
aA21 = -aR1 * aSinBt;
|
|
aA22 = aR2 * aSinGm;
|
|
//
|
|
for (i = 0; i < 2; ++i)
|
|
{
|
|
aLx = (!i) ? 0. : 1.;
|
|
aLy = (!i) ? 1. : 0.;
|
|
aBx = aLx * aA21 - aLy * aA11;
|
|
aBy = aLx * aA22 - aLy * aA12;
|
|
aB = sqrt(aBx * aBx + aBy * aBy);
|
|
//
|
|
aCosFi = aBx / aB;
|
|
aSinFi = aBy / aB;
|
|
//
|
|
aFi = acos(aCosFi);
|
|
if (aSinFi < 0.)
|
|
{
|
|
aFi = aTwoPI - aFi;
|
|
}
|
|
//
|
|
j = 2 * i;
|
|
pT[j] = aTwoPI - aFi;
|
|
pT[j] = AdjustToPeriod(pT[j], aTwoPI);
|
|
//
|
|
pT[j + 1] = M_PI - aFi;
|
|
pT[j + 1] = AdjustToPeriod(pT[j + 1], aTwoPI);
|
|
}
|
|
iRet = 4;
|
|
} // if (aType==GeomAbs_Ellipse) {
|
|
//
|
|
else if (aType == GeomAbs_Parabola)
|
|
{
|
|
Standard_Real aFc, aEps;
|
|
Standard_Real aA1, aA2;
|
|
Handle(Geom2d_Parabola) aPR2D;
|
|
//
|
|
aEps = 1.e-12;
|
|
//
|
|
aPR2D = Handle(Geom2d_Parabola)::DownCast(aConic2D);
|
|
aFc = aPR2D->Focal();
|
|
//
|
|
j = 0;
|
|
for (i = 0; i < 2; i++)
|
|
{
|
|
aLx = (!i) ? 0. : 1.;
|
|
aLy = (!i) ? 1. : 0.;
|
|
//
|
|
aA2 = aLx * aSinBt - aLy * aCosBt;
|
|
if (fabs(aA2) < aEps)
|
|
{
|
|
continue;
|
|
}
|
|
//
|
|
aA1 = aLy * aCosGm - aLx * aSinGm;
|
|
//
|
|
pT[j] = 2. * aFc * aA1 / aA2;
|
|
++j;
|
|
}
|
|
iRet = j;
|
|
} // else if (aType==GeomAbs_Parabola) {
|
|
//
|
|
else if (aType == GeomAbs_Hyperbola)
|
|
{
|
|
Standard_Integer k;
|
|
Standard_Real aR1, aR2;
|
|
Standard_Real aEps, aB1, aB2, aB12, aB22, aZ, aD;
|
|
Handle(Geom2d_Hyperbola) aHP2D;
|
|
//
|
|
aEps = 1.e-12;
|
|
//
|
|
aHP2D = Handle(Geom2d_Hyperbola)::DownCast(aConic2D);
|
|
aR1 = aHP2D->MajorRadius();
|
|
aR2 = aHP2D->MinorRadius();
|
|
//
|
|
j = 0;
|
|
for (i = 0; i < 2; i++)
|
|
{
|
|
aLx = (!i) ? 0. : 1.;
|
|
aLy = (!i) ? 1. : 0.;
|
|
//
|
|
aB1 = aR1 * (aLx * aSinBt - aLy * aCosBt);
|
|
aB2 = aR2 * (aLx * aSinGm - aLy * aCosGm);
|
|
//
|
|
if (fabs(aB1) < aEps)
|
|
{
|
|
continue;
|
|
}
|
|
//
|
|
if (fabs(aB2) < aEps)
|
|
{
|
|
pT[j] = 0.;
|
|
++j;
|
|
}
|
|
else
|
|
{
|
|
aB12 = aB1 * aB1;
|
|
aB22 = aB2 * aB2;
|
|
if (!(aB12 > aB22))
|
|
{
|
|
continue;
|
|
}
|
|
//
|
|
aD = sqrt(aB12 - aB22);
|
|
//-------------
|
|
for (k = -1; k < 2; k += 2)
|
|
{
|
|
aZ = (aB1 + k * aD) / aB2;
|
|
if (fabs(aZ) < 1.)
|
|
{
|
|
pT[j] = -log((1. + aZ) / (1. - aZ));
|
|
++j;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
iRet = j;
|
|
} // else if (aType==GeomAbs_Hyperbola) {
|
|
//
|
|
return iRet;
|
|
}
|
|
|
|
//=================================================================================================
|
|
|
|
Standard_Real BndLib_Box2dCurve::AdjustToPeriod(const Standard_Real aT, const Standard_Real aPeriod)
|
|
{
|
|
Standard_Integer k;
|
|
Standard_Real aTRet;
|
|
//
|
|
aTRet = aT;
|
|
if (aT < 0.)
|
|
{
|
|
k = 1 + (Standard_Integer)(-aT / aPeriod);
|
|
aTRet = aT + k * aPeriod;
|
|
}
|
|
else if (aT > aPeriod)
|
|
{
|
|
k = (Standard_Integer)(aT / aPeriod);
|
|
aTRet = aT - k * aPeriod;
|
|
}
|
|
if (aTRet == aPeriod)
|
|
{
|
|
aTRet = 0.;
|
|
}
|
|
return aTRet;
|
|
}
|
|
|
|
//
|
|
// myErrorStatus:
|
|
//
|
|
// -1 - object is just initialized
|
|
// 10 - myCurve is Null
|
|
// 12 - invalid range myT1 > myT2l
|
|
// 11 - unknown type of base curve
|
|
// 13 - offset curve can not be computed
|
|
// NMTTest
|
|
|
|
//=================================================================================================
|
|
|
|
void BndLib_Add2dCurve::Add(const Adaptor2d_Curve2d& aC,
|
|
const Standard_Real aTol,
|
|
Bnd_Box2d& aBox2D)
|
|
{
|
|
BndLib_Add2dCurve::Add(aC, aC.FirstParameter(), aC.LastParameter(), aTol, aBox2D);
|
|
}
|
|
|
|
//=================================================================================================
|
|
|
|
void BndLib_Add2dCurve::Add(const Adaptor2d_Curve2d& aC,
|
|
const Standard_Real aU1,
|
|
const Standard_Real aU2,
|
|
const Standard_Real aTol,
|
|
Bnd_Box2d& aBox2D)
|
|
{
|
|
Adaptor2d_Curve2d* pC = (Adaptor2d_Curve2d*)&aC;
|
|
Geom2dAdaptor_Curve* pA = dynamic_cast<Geom2dAdaptor_Curve*>(pC);
|
|
if (!pA)
|
|
{
|
|
Standard_Real U, DU;
|
|
Standard_Integer N, j;
|
|
gp_Pnt2d P;
|
|
N = 33;
|
|
U = aU1;
|
|
DU = (aU2 - aU1) / (N - 1);
|
|
for (j = 1; j < N; j++)
|
|
{
|
|
aC.D0(U, P);
|
|
U += DU;
|
|
aBox2D.Add(P);
|
|
}
|
|
aC.D0(aU2, P);
|
|
aBox2D.Add(P);
|
|
aBox2D.Enlarge(aTol);
|
|
return;
|
|
}
|
|
//
|
|
const Handle(Geom2d_Curve)& aC2D = pA->Curve();
|
|
//
|
|
BndLib_Add2dCurve::Add(aC2D, aU1, aU2, aTol, aBox2D);
|
|
}
|
|
|
|
//=================================================================================================
|
|
|
|
void BndLib_Add2dCurve::Add(const Handle(Geom2d_Curve)& aC2D,
|
|
const Standard_Real aTol,
|
|
Bnd_Box2d& aBox2D)
|
|
{
|
|
Standard_Real aT1, aT2;
|
|
//
|
|
aT1 = aC2D->FirstParameter();
|
|
aT2 = aC2D->LastParameter();
|
|
//
|
|
BndLib_Add2dCurve::Add(aC2D, aT1, aT2, aTol, aBox2D);
|
|
}
|
|
|
|
//=================================================================================================
|
|
|
|
void BndLib_Add2dCurve::Add(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.Perform();
|
|
//
|
|
const Bnd_Box2d& aBoxC = aBC.Box();
|
|
aBox2D.Add(aBoxC);
|
|
aBox2D.Enlarge(aTol);
|
|
}
|
|
|
|
//=================================================================================================
|
|
|
|
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);
|
|
} |