#include <TopoDS_Vertex.hxx>
#include <TopoDS_Wire.hxx>
#include <TopTools_ShapeMapHasher.hxx>
+#include <Geom2dLProp_CLProps2d.hxx>
typedef NCollection_DataMap \
<TopoDS_Shape, Standard_Boolean, TopTools_ShapeMapHasher> \
BOPCol_DataMapOfShapeBoolean;
for (i=1; i<=aNb; i++) {
const TopoDS_Vertex& aV = (*(TopoDS_Vertex *)(&mySmartMap.FindKey(i)));
const BOPAlgo_ListOfEdgeInfo& aLEI= mySmartMap(i);
-
aItLEI.Initialize(aLEI);
for (; aItLEI.More(); aItLEI.Next()) {
BOPAlgo_EdgeInfo& aEI=aItLEI.ChangeValue();
TopoDS_Vertex aVa, aVb;
TopoDS_Edge aEOuta;
BOPAlgo_ListIteratorOfListOfEdgeInfo anIt;
+ Standard_Real eps = Epsilon(1.);
//
aVa = aVFirst;
aEOuta = aEFirst;
anAngleOut=anEI.Angle();
anAngle=ClockWiseAngle(anAngleIn, anAngleOut);
}
- if (anAngle < aMinAngle) {
+ if (anAngle < aMinAngle - eps) {
aMinAngle=anAngle;
pEdgeInfo=&anEI;
anIsFound=Standard_True;
//
BOPTools_AlgoTools2D::CurveOnSurface (anEdge, myFace, aC2D,
aFirst, aLast, aToler);
- dt=2.*Tolerance2D(aV, aGAS);
+ Standard_Real tol2d =2.*Tolerance2D(aV, aGAS);
+ //
+ GeomAbs_CurveType aType;
+ Geom2dAdaptor_Curve aGAC2D(aC2D);
+ //
+ dt = Max(aGAC2D.Resolution(tol2d), Precision::PConfusion());
//
+ aType=aGAC2D.GetType();
+ if (aType != GeomAbs_Line )
+ {
+ Geom2dLProp_CLProps2d LProp(aC2D, aTV, 2, Precision::PConfusion());
+ if(LProp.IsTangentDefined())
+ {
+ Standard_Real R = LProp.Curvature();
+ if(R > Precision::PConfusion())
+ {
+ R = 1./R;
+ Standard_Real cosphi = R / (R + tol2d);
+ dt = Max(dt, ACos(cosphi)); //to avoid small dt for big R.
+ }
+ }
+ }
//for case chl/927/r9
- aTX=0.05*(aLast - aFirst);//aTX=0.25*(aLast - aFirst);
+ aTX=0.05*(aLast - aFirst);//aTX=0.25*(aLast - aFirst);
if (aTX < 5.e-5) {
aTX = 5.e-5;
}
// in the case of big tolerances
dt = aTX;
}
- //
- GeomAbs_CurveType aType;
- Geom2dAdaptor_Curve aGAC2D(aC2D);
- aType=aGAC2D.GetType();
- if (aType==GeomAbs_BSplineCurve ||
- aType==GeomAbs_BezierCurve) {
- dt=1.1*dt;
- }
+
if (fabs (aTV-aFirst) < fabs(aTV - aLast)) {
aTV1=aTV + dt;
}
aTV1=aTV - dt;
}
//
- if (aType==GeomAbs_Circle) {
- Standard_Real aTM;
- TopAbs_Orientation aOrE;
- gp_Pnt2d aPM;
- //
- aTM=0.5*(aTV1+aTV);
- //
- aGAC2D.D1(aTM, aPM, aV2D);
- aOrE=anEdge.Orientation();
- if (aOrE==TopAbs_REVERSED) {
- aV2D.Reverse();
- }
- }
- else {
- aGAC2D.D0 (aTV1, aPV1);
- aGAC2D.D0 (aTV, aPV);
- //
- aV2D = bIsIN ? gp_Vec2d(aPV1, aPV) : gp_Vec2d(aPV, aPV1);
- }
+ aGAC2D.D0 (aTV1, aPV1);
+ aGAC2D.D0 (aTV, aPV);
+ //
+ aV2D = bIsIN ? gp_Vec2d(aPV1, aPV) : gp_Vec2d(aPV, aPV1);
//
gp_Dir2d aDir2D(aV2D);
anAngle=Angle(aDir2D);
#include <TopLoc_Location.hxx>
#include <TopoDS.hxx>
#include <TopoDS_Shape.hxx>
+#include <Adaptor3d_HCurve.hxx>
+#include <Adaptor3d_HSurface.hxx>
+#include <BRepTools.hxx>
+#include <Geom_BSplineSurface.hxx>
+#include <Geom_BezierSurface.hxx>
+#include <Bnd_Box2d.hxx>
+#include <BndLib_Add2dCurve.hxx>
+#include <BRepTopAdaptor_FClass2d.hxx>
+#include <ElSLib.hxx>
+#include <ElCLib.hxx>
+#include <Geom_Plane.hxx>
+#include <Extrema_ExtSS.hxx>
+#include <GeomAdaptor_Surface.hxx>
+//
+static Standard_Boolean CanUseEdges(const Adaptor3d_Surface& BS);
+//
+static void FindExactUVBounds(const TopoDS_Face F,
+ Standard_Real& umin, Standard_Real& umax,
+ Standard_Real& vmin, Standard_Real& vmax,
+ const Standard_Real Tol,
+ Standard_Boolean& isNaturalRestriction);
+//
+static void AdjustFaceBox(const BRepAdaptor_Surface& BS,
+ const Standard_Real umin, const Standard_Real umax,
+ const Standard_Real vmin, const Standard_Real vmax,
+ Bnd_Box& FaceBox,
+ const Bnd_Box& EdgeBox, const Standard_Real Tol);
+//
+static Standard_Boolean IsModifySize(const BRepAdaptor_Surface& theBS,
+ const gp_Pln& thePln, const gp_Pnt& theP,
+ const Standard_Real umin, const Standard_Real umax,
+ const Standard_Real vmin, const Standard_Real vmax,
+ const BRepTopAdaptor_FClass2d& theFClass,
+ const Standard_Real theTolU, const Standard_Real theTolV);
+//
//=======================================================================
//function : Add
//purpose : Add a shape bounding to a box
}
}
+//=======================================================================
+//function : AddOptimal
+//purpose : Add a shape bounding to a box
+//=======================================================================
+void BRepBndLib::AddOptimal(const TopoDS_Shape& S, Bnd_Box& B,
+ const Standard_Boolean useTriangulation,
+ const Standard_Boolean useShapeTolerance)
+{
+ TopExp_Explorer ex;
+
+ // Add the faces
+ BRepAdaptor_Surface BS;
+ Handle(Poly_Triangulation) T;
+ TopLoc_Location l;
+ Standard_Integer i, nbNodes;
+ BRepAdaptor_Curve BC;
+
+ for (ex.Init(S,TopAbs_FACE); ex.More(); ex.Next()) {
+ const TopoDS_Face& F = TopoDS::Face(ex.Current());
+ T = BRep_Tool::Triangulation(F, l);
+ Bnd_Box aLocBox;
+ if (useTriangulation && !T.IsNull())
+ {
+ nbNodes = T->NbNodes();
+ const TColgp_Array1OfPnt& Nodes = T->Nodes();
+ for (i = 1; i <= nbNodes; i++) {
+ if (l.IsIdentity()) aLocBox.Add(Nodes(i));
+ else aLocBox.Add(Nodes(i).Transformed(l));
+ }
+ // B.Enlarge(T->Deflection());
+ aLocBox.Enlarge(T->Deflection() + BRep_Tool::Tolerance(F));
+ Standard_Real xmin, ymin, zmin, xmax, ymax, zmax;
+ aLocBox.Get(xmin, ymin, zmin, xmax, ymax, zmax);
+ B.Update(xmin, ymin, zmin, xmax, ymax, zmax);
+ }
+ else
+ {
+ const Handle(Geom_Surface)& GS = BRep_Tool::Surface(F, l);
+ if (!GS.IsNull()) {
+ BS.Initialize(F, Standard_False);
+ if (CanUseEdges(BS)) {
+ TopExp_Explorer ex2(F, TopAbs_EDGE);
+ if (!ex2.More()) {
+ BS.Initialize(F);
+ Standard_Real Tol = useShapeTolerance? BRep_Tool::Tolerance(F) : 0.;
+ BndLib_AddSurface::AddOptimal(BS, Tol, aLocBox);
+ }
+ else
+ {
+ Standard_Real Tol;
+ for (;ex2.More();ex2.Next()) {
+ Bnd_Box anEBox;
+ const TopoDS_Edge& anE = TopoDS::Edge(ex2.Current());
+ if(BRep_Tool::Degenerated(anE))
+ {
+ continue;
+ }
+ BC.Initialize(anE);
+ Tol = useShapeTolerance? BRep_Tool::Tolerance(anE) : 0.;
+ BndLib_Add3dCurve::AddOptimal(BC, Tol, anEBox);
+ aLocBox.Add(anEBox);
+ }
+ }
+ }
+ else
+ {
+ Standard_Real umin, umax, vmin, vmax;
+ Standard_Boolean isNaturalRestriction = Standard_False;
+ Standard_Real Tol = useShapeTolerance? BRep_Tool::Tolerance(F) : 0.;
+ FindExactUVBounds(F, umin, umax, vmin, vmax, Tol, isNaturalRestriction);
+ BndLib_AddSurface::AddOptimal(BS, umin, umax, vmin, vmax,
+ Tol, aLocBox);
+ //
+ if(!isNaturalRestriction)
+ {
+ TopExp_Explorer ex2(F, TopAbs_EDGE);
+ Bnd_Box EBox;
+ for (;ex2.More();ex2.Next()) {
+ Bnd_Box anEBox;
+ const TopoDS_Edge& anE = TopoDS::Edge(ex2.Current());
+ if(BRep_Tool::Degenerated(anE))
+ {
+ continue;
+ }
+ BC.Initialize(anE);
+ Tol = useShapeTolerance? BRep_Tool::Tolerance(anE) : 0.;
+ BndLib_Add3dCurve::AddOptimal(BC, Tol, anEBox);
+ EBox.Add(anEBox);
+ }
+ Tol = useShapeTolerance? BRep_Tool::Tolerance(F) : 0.;
+ AdjustFaceBox(BS, umin, umax, vmin, vmax, aLocBox, EBox,
+ Tol);
+ }
+ }
+ Standard_Real xmin, ymin, zmin, xmax, ymax, zmax;
+ aLocBox.Get(xmin, ymin, zmin, xmax, ymax, zmax);
+ B.Update(xmin, ymin, zmin, xmax, ymax, zmax);
+ }
+ }
+ }
+
+ // Add the edges not in faces
+ Handle(TColStd_HArray1OfInteger) HIndices;
+ Handle(Poly_PolygonOnTriangulation) Poly;
+
+ for (ex.Init(S,TopAbs_EDGE,TopAbs_FACE); ex.More(); ex.Next())
+ {
+ const TopoDS_Edge& E = TopoDS::Edge(ex.Current());
+ Bnd_Box aLocBox;
+ Handle(Poly_Polygon3D) P3d = BRep_Tool::Polygon3D(E, l);
+ if (useTriangulation && (!P3d.IsNull()))
+ {
+ const TColgp_Array1OfPnt& Nodes = P3d->Nodes();
+ nbNodes = P3d->NbNodes();
+ for (i = 1; i <= nbNodes; i++)
+ {
+ if (l.IsIdentity()) aLocBox.Add(Nodes(i));
+ else aLocBox.Add(Nodes(i).Transformed(l));
+ }
+ Standard_Real Tol = useShapeTolerance? BRep_Tool::Tolerance(E) : 0.;
+ aLocBox.Enlarge(P3d->Deflection() + Tol);
+ }
+ else
+ {
+ BRep_Tool::PolygonOnTriangulation(E, Poly, T, l);
+ if (useTriangulation && !Poly.IsNull())
+ {
+ const TColStd_Array1OfInteger& Indices = Poly->Nodes();
+ const TColgp_Array1OfPnt& Nodes = T->Nodes();
+ nbNodes = Indices.Length();
+ for (i = 1; i <= nbNodes; i++)
+ {
+ if (l.IsIdentity()) aLocBox.Add(Nodes(Indices(i)));
+ else aLocBox.Add(Nodes(Indices(i)).Transformed(l));
+ }
+ Standard_Real Tol = useShapeTolerance? BRep_Tool::Tolerance(E) : 0.;
+ aLocBox.Enlarge(Poly->Deflection() + Tol);
+ }
+ else {
+ if (BRep_Tool::IsGeometric(E))
+ {
+ BC.Initialize(E);
+ Standard_Real Tol = useShapeTolerance? BRep_Tool::Tolerance(E) : 0.;
+ BndLib_Add3dCurve::AddOptimal(BC, Tol, aLocBox);
+ }
+ }
+ }
+ if (!aLocBox.IsVoid())
+ {
+ Standard_Real xmin, ymin, zmin, xmax, ymax, zmax;
+ aLocBox.Get(xmin, ymin, zmin, xmax, ymax, zmax);
+ B.Update(xmin, ymin, zmin, xmax, ymax, zmax);
+ }
+ }
+
+ // Add the vertices not in edges
+
+ for (ex.Init(S,TopAbs_VERTEX,TopAbs_EDGE); ex.More(); ex.Next()) {
+ Bnd_Box aLocBox;
+ const TopoDS_Vertex& aV = TopoDS::Vertex(ex.Current());
+ aLocBox.Add(BRep_Tool::Pnt(aV));
+ Standard_Real Tol = useShapeTolerance? BRep_Tool::Tolerance(aV) : 0.;
+ aLocBox.Enlarge(Tol);
+ Standard_Real xmin, ymin, zmin, xmax, ymax, zmax;
+ aLocBox.Get(xmin, ymin, zmin, xmax, ymax, zmax);
+ B.Update(xmin, ymin, zmin, xmax, ymax, zmax);
+ }
+}
+
+//=======================================================================
+//function : CanUseEdges
+//purpose : Define is it possible using only edges bnd boxes
+// to get face bnd box
+//=======================================================================
+Standard_Boolean CanUseEdges(const Adaptor3d_Surface& BS)
+{
+ GeomAbs_SurfaceType aST = BS.GetType();
+ if(aST == GeomAbs_Plane ||
+ aST == GeomAbs_Cylinder ||
+ aST == GeomAbs_Cone ||
+ aST == GeomAbs_SurfaceOfExtrusion)
+ {
+ return Standard_True;
+ }
+ else if(aST == GeomAbs_SurfaceOfRevolution)
+ {
+ const Handle(Adaptor3d_HCurve)& aBC = BS.BasisCurve();
+ if(aBC->GetType() == GeomAbs_Line)
+ {
+ return Standard_True;
+ }
+ else
+ {
+ return Standard_False;
+ }
+ }
+ else if(aST == GeomAbs_OffsetSurface)
+ {
+ const Handle(Adaptor3d_HSurface)& aS = BS.BasisSurface();
+ return CanUseEdges(aS->Surface());
+ }
+ else if(aST == GeomAbs_BSplineSurface)
+ {
+ Handle(Geom_BSplineSurface) aBSpl = BS.BSpline();
+ if((aBSpl->UDegree() == 1 && aBSpl->NbUKnots() == 2) ||
+ (aBSpl->VDegree() == 1 && aBSpl->NbVKnots() == 2))
+ {
+ return Standard_True;
+ }
+ else
+ {
+ return Standard_False;
+ }
+ }
+ else if(aST == GeomAbs_BezierSurface)
+ {
+ Handle(Geom_BezierSurface) aBz = BS.Bezier();
+ if((aBz->UDegree() == 1 ) ||
+ (aBz->VDegree() == 1 ))
+ {
+ return Standard_True;
+ }
+ else
+ {
+ return Standard_False;
+ }
+ }
+ return Standard_False;
+}
+
+//=======================================================================
+//function : FindExactUVBounds
+//purpose :
+//=======================================================================
+void FindExactUVBounds(const TopoDS_Face FF,
+ Standard_Real& umin, Standard_Real& umax,
+ Standard_Real& vmin, Standard_Real& vmax,
+ const Standard_Real Tol,
+ Standard_Boolean& isNaturalRestriction)
+{
+ TopoDS_Face F = FF;
+ F.Orientation(TopAbs_FORWARD);
+ TopExp_Explorer ex(F,TopAbs_EDGE);
+ //
+ //Check Natural restriction
+ isNaturalRestriction = BRep_Tool::NaturalRestriction(F); //Can we trust this flag?
+ BRepAdaptor_Surface aBAS(F, Standard_False);
+ if(!isNaturalRestriction)
+ {
+ //Check by comparing pcurves and surface boundaries
+ umin = aBAS.FirstUParameter();
+ umax = aBAS.LastUParameter();
+ vmin = aBAS.FirstVParameter();
+ vmax = aBAS.LastVParameter();
+ Standard_Boolean isUperiodic = aBAS.IsUPeriodic(), isVperiodic = aBAS.IsVPeriodic();
+ Standard_Real aT1, aT2;
+ Standard_Real TolU = Max(aBAS.UResolution(Tol), Precision::PConfusion());
+ Standard_Real TolV = Max(aBAS.VResolution(Tol), Precision::PConfusion());
+ Standard_Integer Nu = 0, Nv = 0, NbEdges = 0;
+ gp_Vec2d Du(1, 0), Dv(0, 1);
+ gp_Pnt2d aP;
+ gp_Vec2d aV;
+ for (;ex.More();ex.Next()) {
+ NbEdges++;
+ if(NbEdges > 4)
+ {
+ break;
+ }
+ const TopoDS_Edge& aE = TopoDS::Edge(ex.Current());
+ const Handle(Geom2d_Curve) aC2D = BRep_Tool::CurveOnSurface(aE, F, aT1, aT2);
+ if (aC2D.IsNull())
+ {
+ break;
+ }
+ //
+ aC2D->D1((aT1 + aT2)/2., aP, aV);
+ Standard_Real magn = aV.SquareMagnitude();
+ if(magn < gp::Resolution())
+ {
+ break;
+ }
+ else
+ {
+ aV /= Sqrt(magn);
+ }
+ Standard_Real u = aP.X(), v = aP.Y();
+ if(isUperiodic)
+ {
+ ElCLib::InPeriod(u, umin, umax);
+ }
+ if(isVperiodic)
+ {
+ ElCLib::InPeriod(v, vmin, vmax);
+ }
+ //
+ if(Abs(u - umin) <= TolU || Abs(u - umax) <= TolU)
+ {
+ Standard_Real d = Dv * aV;
+ if(1. - Abs(d) <= Precision::PConfusion())
+ {
+ Nu++;
+ if(Nu > 2)
+ {
+ break;
+ }
+ }
+ else
+ {
+ break;
+ }
+ }
+ else if(Abs(v - vmin) <= TolV || Abs(v - vmax) <= TolV)
+ {
+ Standard_Real d = Du * aV;
+ if(1. - Abs(d) <= Precision::PConfusion())
+ {
+ Nv++;
+ if(Nv > 2)
+ {
+ break;
+ }
+ }
+ else
+ {
+ break;
+ }
+ }
+ else
+ {
+ break;
+ }
+ }
+ if(Nu == 2 && Nv == 2)
+ {
+ isNaturalRestriction = Standard_True;
+ }
+ }
+ //
+ if(isNaturalRestriction)
+ {
+ umin = aBAS.FirstUParameter();
+ umax = aBAS.LastUParameter();
+ vmin = aBAS.FirstVParameter();
+ vmax = aBAS.LastVParameter();
+ return;
+ }
+
+ // fill box for the given face
+ Standard_Real aT1, aT2;
+ Standard_Real TolU = Max(aBAS.UResolution(Tol), Precision::PConfusion());
+ Standard_Real TolV = Max(aBAS.VResolution(Tol), Precision::PConfusion());
+ Standard_Real TolUV = Max(TolU, TolV);
+ Bnd_Box2d aBox;
+ ex.Init(F,TopAbs_EDGE);
+ for (;ex.More();ex.Next()) {
+ const TopoDS_Edge& aE = TopoDS::Edge(ex.Current());
+ const Handle(Geom2d_Curve) aC2D = BRep_Tool::CurveOnSurface(aE, F, aT1, aT2);
+ if (aC2D.IsNull())
+ {
+ continue;
+ }
+ //
+ BndLib_Add2dCurve::AddOptimal(aC2D, aT1, aT2, TolUV, aBox);
+ //
+ }
+ //
+ aBox.Get(umin, vmin, umax, vmax);
+ //
+ TopLoc_Location aLoc;
+ Handle(Geom_Surface) aS = BRep_Tool::Surface(FF, aLoc);
+ Standard_Real aUmin, aUmax, aVmin, aVmax;
+ aS->Bounds(aUmin, aUmax, aVmin, aVmax);
+ if(!aS->IsUPeriodic())
+ {
+ umin = Max(aUmin, umin);
+ umax = Min(aUmax, umax);
+ }
+ else
+ {
+ if(umax - umin > aS->UPeriod())
+ {
+ Standard_Real delta = umax - umin - aS->UPeriod();
+ umin += delta/2.;
+ umax -= delta/2;
+ }
+ }
+ //
+ if(!aS->IsVPeriodic())
+ {
+ vmin = Max(aVmin, vmin);
+ vmax = Min(aVmax, vmax);
+ }
+ else
+ {
+ if(vmax - vmin > aS->VPeriod())
+ {
+ Standard_Real delta = vmax - vmin - aS->VPeriod();
+ vmin += delta/2.;
+ vmax -= delta/2;
+ }
+ }
+}
+//=======================================================================
+//function : Reorder
+//purpose :
+//=======================================================================
+inline void Reorder(Standard_Real& a, Standard_Real& b)
+{
+ if(a > b)
+ {
+ Standard_Real t = a;
+ a = b;
+ b = t;
+ }
+}
+//=======================================================================
+//function : IsModifySize
+//purpose :
+//=======================================================================
+Standard_Boolean IsModifySize(const BRepAdaptor_Surface& theBS,
+ const gp_Pln& thePln, const gp_Pnt& theP,
+ const Standard_Real umin, const Standard_Real umax,
+ const Standard_Real vmin, const Standard_Real vmax,
+ const BRepTopAdaptor_FClass2d& theFClass,
+ const Standard_Real theTolU, const Standard_Real theTolV)
+{
+ Standard_Real pu1 = 0, pu2, pv1 = 0, pv2;
+ ElSLib::PlaneParameters(thePln.Position(), theP, pu2, pv2);
+ Reorder(pu1, pu2);
+ Reorder(pv1, pv2);
+ Handle(Geom_Plane) aPlane = new Geom_Plane(thePln);
+ GeomAdaptor_Surface aGAPln(aPlane, pu1, pu2, pv1, pv2);
+ Extrema_ExtSS anExtr(aGAPln, theBS, pu1, pu2, pv1, pv2, umin, umax, vmin, vmax, theTolU, theTolV);
+ if(anExtr.IsDone())
+ {
+ if(anExtr.NbExt() > 0)
+ {
+ Standard_Integer i, imin = 0;;
+ Standard_Real dmin = RealLast();
+ Standard_Real uextr = 0., vextr = 0.;
+ Extrema_POnSurf P1, P2;
+ for(i = 1; i <= anExtr.NbExt(); ++i)
+ {
+ Standard_Real d = anExtr.SquareDistance(i);
+ if(d < dmin)
+ {
+ imin = i;
+ dmin = d;
+ }
+ }
+ if(imin > 0)
+ {
+ anExtr.Points(imin, P1, P2);
+ P2.Parameter(uextr, vextr);
+ }
+ else
+ {
+ return Standard_False;
+ }
+ //
+ gp_Pnt2d aP2d(uextr, vextr);
+ TopAbs_State aSt = theFClass.Perform(aP2d);
+ if(aSt == TopAbs_OUT)
+ {
+ return Standard_True;
+ }
+ }
+ else
+ {
+ return Standard_True; //extrema point seems to be out of face UV bounds
+ }
+ }
+ //
+ return Standard_False;
+}
+//
+//=======================================================================
+//function : AdjustFaceBox
+//purpose :
+//=======================================================================
+void AdjustFaceBox(const BRepAdaptor_Surface& BS,
+ const Standard_Real umin, const Standard_Real umax,
+ const Standard_Real vmin, const Standard_Real vmax,
+ Bnd_Box& FaceBox,
+ const Bnd_Box& EdgeBox, const Standard_Real Tol)
+{
+ Standard_Real fxmin, fymin, fzmin, fxmax, fymax, fzmax;
+ Standard_Real exmin, eymin, ezmin, exmax, eymax, ezmax;
+ //
+ FaceBox.Get(fxmin, fymin, fzmin, fxmax, fymax, fzmax);
+ EdgeBox.Get(exmin, eymin, ezmin, exmax, eymax, ezmax);
+ //
+ Standard_Real TolU = Max(BS.UResolution(Tol), Precision::PConfusion());
+ Standard_Real TolV = Max(BS.VResolution(Tol), Precision::PConfusion());
+ BRepTopAdaptor_FClass2d FClass(BS.Face(), Max(TolU, TolV));
+ //
+ Standard_Boolean isModified = Standard_False;
+ if(exmin > fxmin)
+ {
+ //
+ gp_Pln pl(gp_Ax3(gp_Pnt(fxmin, fymin, fzmin), gp::DX()));
+ gp_Pnt aP(fxmin, fymax, fzmax);
+ if(IsModifySize(BS, pl, aP,
+ umin, umax, vmin, vmax, FClass, TolU, TolV))
+ {
+ fxmin = exmin;
+ isModified = Standard_True;
+ }
+ }
+ if(exmax < fxmax)
+ {
+ //
+ gp_Pln pl(gp_Ax3(gp_Pnt(fxmax, fymax, fzmax), gp::DX()));
+ gp_Pnt aP(fxmax, fymin, fzmin);
+ if(IsModifySize(BS, pl, aP,
+ umin, umax, vmin, vmax, FClass, TolU, TolV))
+ {
+ fxmax = exmax;
+ isModified = Standard_True;
+ }
+ }
+ //
+ if(eymin > fymin)
+ {
+ //
+ gp_Pln pl(gp_Ax3(gp_Pnt(fxmin, fymin, fzmin), gp::DY()));
+ gp_Pnt aP(fxmax, fymin, fzmax);
+ if(IsModifySize(BS, pl, aP,
+ umin, umax, vmin, vmax, FClass, TolU, TolV))
+ {
+ fymin = eymin;
+ isModified = Standard_True;
+ }
+ }
+ if(eymax < fymax)
+ {
+ //
+ gp_Pln pl(gp_Ax3(gp_Pnt(fxmax, fymax, fzmax), gp::DY()));
+ gp_Pnt aP(fxmin, fymax, fzmin);
+ if(IsModifySize(BS, pl, aP,
+ umin, umax, vmin, vmax, FClass, TolU, TolV))
+ {
+ fymax = eymax;
+ isModified = Standard_True;
+ }
+ }
+ //
+ if(ezmin > fzmin)
+ {
+ //
+ gp_Pln pl(gp_Ax3(gp_Pnt(fxmin, fymin, fzmin), gp::DZ()));
+ gp_Pnt aP(fxmax, fymax, fzmin);
+ if(IsModifySize(BS, pl, aP,
+ umin, umax, vmin, vmax, FClass, TolU, TolV))
+ {
+ fzmin = ezmin;
+ isModified = Standard_True;
+ }
+ }
+ if(ezmax < fzmax)
+ {
+ //
+ gp_Pln pl(gp_Ax3(gp_Pnt(fxmax, fymax, fzmax), gp::DZ()));
+ gp_Pnt aP(fxmin, fymin, fzmax);
+ if(IsModifySize(BS, pl, aP,
+ umin, umax, vmin, vmax, FClass, TolU, TolV))
+ {
+ fzmax = ezmax;
+ isModified = Standard_True;
+ }
+ }
+ //
+ if(isModified)
+ {
+ FaceBox.SetVoid();
+ FaceBox.Update(fxmin, fymin, fzmin, fxmax, fymax, fzmax);
+ }
+}
+
//! box is closer to the shape S.
Standard_EXPORT static void AddClose (const TopoDS_Shape& S, Bnd_Box& B);
+ //! Adds the shape S to the bounding box B.
+ //! This algorith builds precise bounding box,
+ //! which differs from exact geometry boundaries of shape only on shape entities tolerances
+ //! Algorithm is the same as for method Add(..), but uses more precise methods for building boxes
+ //! for geometry objects.
+ //! If useShapeTolerance = True, bounding box is enlardged by shape tolerances and
+ //! these tolerances are used for numerical methods of bounding box size calculations,
+ //! otherwise bounding box is built according to sizes of uderlined geometrical entities,
+ //! numerical calculation use tolerance Precision::Confusion().
+ Standard_EXPORT static void AddOptimal (const TopoDS_Shape& S, Bnd_Box& B,
+ const Standard_Boolean useTriangulation = Standard_True,
+ const Standard_Boolean useShapeTolerance = Standard_False);
return 0;
}
//=======================================================================
+//function : optbounding
+//purpose :
+//=======================================================================
+static Standard_Integer optbounding(Draw_Interpretor& di,Standard_Integer n,const char** a)
+{
+ if (n < 2)
+ {
+ di << "Usage: optbounding shape [usetri [usetol]]\n";
+ di << "usetri and usetol can be 0 or 1, by default usetri = 1, usetol = 0\n";
+ return 1;
+ }
+ Standard_Real axmin,aymin,azmin,axmax,aymax,azmax;
+ Bnd_Box B; Handle(Draw_Box) DB;
+
+ TopoDS_Shape S = DBRep::Get(a[1]);
+ if (S.IsNull())
+ {
+ di << "Null shape\n";
+ return 1;
+ }
+ Standard_Boolean useTri = Standard_True;
+ Standard_Boolean useTol = Standard_False;
+ if(n > 2 )
+ {
+ Standard_Integer ii = atoi(a[2]);
+ useTri = ii > 0;
+ }
+ if(n > 3 )
+ {
+ Standard_Integer ii = atoi(a[3]);
+ useTol = ii > 0;
+ }
+ BRepBndLib::AddOptimal(S, B, useTri, useTol);
+ B.Get(axmin, aymin, azmin, axmax, aymax, azmax);
+ DB = new Draw_Box(gp_Pnt(axmin,aymin,azmin),gp_Pnt(axmax,aymax,azmax),Draw_vert);
+ dout<<DB;
+ di << axmin<<" "<< aymin<<" "<< azmin<<" "<< axmax<<" "<< aymax<<" "<< azmax;
+ return 0;
+}
+//=======================================================================
+//function : gbounding
+//purpose :
+//=======================================================================
+#include <GeomAdaptor_Surface.hxx>
+#include <BndLib_AddSurface.hxx>
+#include <BndLib_Add3dCurve.hxx>
+static Standard_Integer gbounding(Draw_Interpretor& di,Standard_Integer n,const char** a)
+{
+ if (n < 2)
+ {
+ di << "Usage: gbounding surf/curve \n";
+ return 1;
+ }
+ Standard_Real axmin,aymin,azmin,axmax,aymax,azmax;
+ Bnd_Box B; Handle(Draw_Box) DB;
+
+ if (n == 2) {
+ Handle(Geom_Curve) C;
+ Handle(Geom_Surface) S;
+ S = DrawTrSurf::GetSurface(a[1]);
+ if (S.IsNull())
+ {
+ C = DrawTrSurf::GetCurve(a[1]);
+ }
+ if(!S.IsNull())
+ {
+ GeomAdaptor_Surface aGAS(S);
+ BndLib_AddSurface::AddOptimal(aGAS, Precision::Confusion(), B);
+ }
+ else if(!C.IsNull())
+ {
+ GeomAdaptor_Curve aGAC(C);
+ BndLib_Add3dCurve::AddOptimal(aGAC, Precision::Confusion(), B);
+ }
+ else
+ {
+ di << "Wrong argument \n";
+ return 1;
+ }
+ B.Get(axmin,aymin,azmin,axmax,aymax,azmax);
+ DB = new Draw_Box(gp_Pnt(axmin,aymin,azmin),gp_Pnt(axmax,aymax,azmax),Draw_vert);
+ dout<<DB;
+ di << axmin<<" "<< aymin<<" "<< azmin<<" "<< axmax<<" "<< aymax<<" "<< azmax;
+ }
+ return 0;
+}//=======================================================================
//function : findplane
//purpose :
//=======================================================================
__FILE__,
bounding,g);
+ theCommands.Add("optbounding",
+ "optbounding shape [usetri (0/1) [usetol (0/1)]] ; ",
+ __FILE__,
+ optbounding,g);
+ //
+ theCommands.Add("gbounding",
+ "gbounding curve/surf ",
+ __FILE__,
+ gbounding,g);
+
theCommands.Add("boundingstr",
"boundingstr shape [ xmin ymin zmin xmax ymax zmax] ; print bounding box",
__FILE__,
#include <gp_XYZ.hxx>
#include <Precision.hxx>
#include <Standard_Failure.hxx>
+#include <ElSLib.hxx>
static
Standard_Integer ComputeBox(const gp_Hypr& aHypr,
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);
}
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);
}
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 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);
+ else
+ {
+ ComputeCyl(S, UMin, UMax, 0., VMax,B);
OpenMin(S.Axis().Direction(),B);
}
}
- else if (Precision::IsPositiveInfinite(VMin)) {
- if (Precision::IsNegativeInfinite(VMax)) {
+ else if (Precision::IsPositiveInfinite(VMin))
+ {
+ if (Precision::IsNegativeInfinite(VMax))
+ {
OpenMinMax(S.Axis().Direction(),B);
}
- else if (Precision::IsPositiveInfinite(VMax)) {
+ 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);
+ else
+ {
+ ComputeCyl(S, UMin, UMax, 0., VMax, 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
+ {
+ if (Precision::IsNegativeInfinite(VMax))
+ {
+ ComputeCyl(S, UMin, UMax, VMin, 0., B);
OpenMin(S.Axis().Direction(),B);
}
- else if (Precision::IsPositiveInfinite(VMax)) {
+ 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);
}
}
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);
}
BndLib::Add(S,0.,2.*M_PI,VMin,VMax,Tol,B);
}
+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 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
+ 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) {
-
+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);
}
#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
void Perform();
+ void PerformOptimal(const Standard_Real Tol);
+
void Clear();
Standard_Integer ErrorStatus() const;
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;
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 :
}
}
//=======================================================================
+//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 :
//=======================================================================
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 :
//=======================================================================
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);
+}
\ No newline at end of file
//! - 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:
#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
}
}
}
+
+//=======================================================================
+//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);
+}
#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.
//! 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:
#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
}
}
}
+//----- 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);
+}
+
#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.
//! 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);
-protected:
+ //! 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:
-private:
+private:
# test script on make volume operation
# plane sphere
-puts "TODO OCC26020 ALL: Faulty shapes in variables faulty_1 to faulty_"
+puts "TODO OCC26020 Windows: Faulty shapes in variables faulty_1 to faulty_"
puts "TODO OCC26020 ALL: Error: bopcheck failed"
puts "TODO OCC26020 ALL: Error : The area of result shape is"
# make volume operation
mkvolume result f1 f2 f3 f4 f5 f6 f7
-checkprops result -s 3.7173e+06
+checkprops result -s 3.76654e+06
# test script on make volume operation
# cone plane killed by cpulimit 300
-puts "TODO OCC26020 ALL: Error: bopcheck failed"
-puts "TODO OCC26020 ALL: Error : The area of result shape is"
-puts "TODO OCC26020 ALL: Faulty shapes in variables faulty_1 to"
-
# planar face
plane pln_f1 -460.8377555733228 -1160 -121.8751945104883 0.17364817766693036 -5.955424826592936e-017 -0.98480775301220813
erase pln_f1
# make volume operation
mkvolume result f1 f2 f3 f4 f5 f6 f7
-checkprops result -s 0
+checkprops result -s 6.47464e+006
-puts "TODO OCC26020 Linux: Error : The area of result shape is"
-puts "TODO OCC26020 Linux: Error: bopcheck failed"
-
# test script on make volume operation
# cylinder plane
isos result 0
triangles result
-checktrinfo result -tri 98 -nod 100
+checktrinfo result -tri 101 -nod 103
checkprops result -s 150.283
checkview -display result -3d -path ${imagedir}/${test_image}.png
isos result 0
triangles result
-checktrinfo result -tri 1145 -nod 831
+checktrinfo result -tri 1111 -nod 814
checkprops result -s 376.873
checkview -screenshot -3d -path ${imagedir}/${test_image}.png
}
set mlog [bounding a_1_3]
-if (![regexp {(-7.26623440743389) (-8.0984932752388978) (-150.09849327523889) (7.2662344074338865) (8.0984932752388978) (-141.90150672476111)} $mlog]) {
+if (![regexp {(-7.1677412321949925) (-8.0000000999999994) (-150.00000009999999) (7.1677412321949898) (8.0000000999999994) (-141.99999990000001)} $mlog]) {
set status 0
}
set x1 210
set y1 184
-set x2 205
+set x2 207
set y2 180
stepread [locate_data_file OCC23012-Sample_3.stp] a *