Part: Add overloaded methods of GeomBSplineCurve::approximate

This commit is contained in:
wmayer
2024-04-03 10:43:06 +02:00
committed by wwmayer
parent e64af14325
commit 7a7c0081c3
4 changed files with 114 additions and 20 deletions

View File

@@ -828,8 +828,8 @@ PyObject* BSplineCurvePy::approximate(PyObject *args, PyObject *kwds)
else
c = GeomAbs_C2;
bool ok = this->getGeomBSplineCurvePtr()->approximate(tol3d, segMax, degMax, c);
return Py_BuildValue("O", (ok ? Py_True : Py_False));
this->getGeomBSplineCurvePtr()->approximate(tol3d, segMax, degMax, c);
Py_Return;
}
// Approximate a list of points

View File

@@ -65,6 +65,7 @@
# include <Geom_TrimmedCurve.hxx>
# include <GeomAPI_ExtremaCurveCurve.hxx>
# include <GeomAPI_Interpolate.hxx>
# include <GeomAPI_PointsToBSpline.hxx>
# include <GeomAPI_ProjectPointOnCurve.hxx>
# include <GeomConvert.hxx>
# include <GeomConvert_CompCurveToBSplineCurve.hxx>
@@ -1713,28 +1714,115 @@ void GeomBSplineCurve::increaseDegree(int degree)
* \param maxSegments
* \param maxDegree
* \param continuity
* \return true if the approximation succeeded, false otherwise
*/
bool GeomBSplineCurve::approximate(double tol3d, int maxSegments, int maxDegree, int continuity)
void GeomBSplineCurve::approximate(double tol3d, int maxSegments, int maxDegree,
GeomAbs_Shape continuity)
{
try {
GeomAbs_Shape cont = GeomAbs_C0;
if (continuity >= 0 && continuity <= 6)
cont = static_cast<GeomAbs_Shape>(continuity);
GeomAdaptor_Curve adapt(myCurve);
Handle(GeomAdaptor_HCurve) hCurve = new GeomAdaptor_HCurve(adapt);
Approx_Curve3d approx(hCurve, tol3d, cont, maxSegments, maxDegree);
if (approx.IsDone() && approx.HasResult()) {
Approx_Curve3d approx(hCurve, tol3d, continuity, maxSegments, maxDegree);
if (approx.IsDone()) {
this->setHandle(approx.Curve());
return true;
}
else if (approx.HasResult()) {
throw Standard_Failure("Approximation of B-Spline succeeded but is outside of tolerance");
}
else {
throw Standard_Failure("Approximation of B-Spline failed");
}
}
catch (Standard_Failure& e) {
THROWM(Base::CADKernelError,e.GetMessageString())
THROWM(Base::CADKernelError, e.GetMessageString())
}
}
return false;
void GeomBSplineCurve::approximate(const std::vector<Base::Vector3d>& pnts,
int minDegree, int maxDegree,
GeomAbs_Shape continuity, double tol3d)
{
try {
TColgp_Array1OfPnt coords(1, static_cast<int>(pnts.size()));
Standard_Integer index = 1;
for (const auto& it : pnts) {
coords(index++) = gp_Pnt(it.x, it.y, it.z);
}
GeomAPI_PointsToBSpline fit(coords, minDegree, maxDegree, continuity, tol3d);
const Handle(Geom_BSplineCurve)& spline = fit.Curve();
if (!spline.IsNull()) {
setHandle(spline);
}
else {
throw Standard_Failure("Failed to approximate B-Spline");
}
}
catch (Standard_Failure& e) {
THROWM(Base::CADKernelError, e.GetMessageString())
}
}
void GeomBSplineCurve::approximate(const std::vector<Base::Vector3d>& pnts,
Approx_ParametrizationType parType,
int minDegree, int maxDegree,
GeomAbs_Shape continuity, double tol3d)
{
try {
TColgp_Array1OfPnt coords(1, static_cast<int>(pnts.size()));
Standard_Integer index = 1;
for (const auto& it : pnts) {
coords(index++) = gp_Pnt(it.x, it.y, it.z);
}
GeomAPI_PointsToBSpline fit(coords, parType, minDegree, maxDegree, continuity, tol3d);
const Handle(Geom_BSplineCurve)& spline = fit.Curve();
if (!spline.IsNull()) {
setHandle(spline);
}
else {
throw Standard_Failure("Failed to approximate B-Spline");
}
}
catch (Standard_Failure& e) {
THROWM(Base::CADKernelError, e.GetMessageString())
}
}
/*!
* \brief GeomBSplineCurve::approximate
* \param pnts Points to fit
* \param weight1 Weight of curve length as smoothing criterion
* \param weight2 Weight of curvature as smoothing criterion
* \param weight3 Weight of torsion as smoothing criterion
* \param minDegree Minimum degree
* \param maxDegree Maximum degree
* \param continuity Continuity of the spline
* \param tol3d Tolerance to the data points
*/
void GeomBSplineCurve::approximate(const std::vector<Base::Vector3d>& pnts,
double weight1, double weight2, double weight3,
int maxDegree, GeomAbs_Shape continuity, double tol3d)
{
try {
TColgp_Array1OfPnt coords(1, static_cast<int>(pnts.size()));
Standard_Integer index = 1;
for (const auto& it : pnts) {
coords(index++) = gp_Pnt(it.x, it.y, it.z);
}
GeomAPI_PointsToBSpline fit(coords, weight1, weight2, weight3,
maxDegree, continuity, tol3d);
const Handle(Geom_BSplineCurve)& spline = fit.Curve();
if (!spline.IsNull()) {
setHandle(spline);
}
else {
throw Standard_Failure("Failed to approximate B-Spline");
}
}
catch (Standard_Failure& e) {
THROWM(Base::CADKernelError, e.GetMessageString())
}
}
void GeomBSplineCurve::increaseMultiplicity(int index, int multiplicity)
@@ -1742,11 +1830,10 @@ void GeomBSplineCurve::increaseMultiplicity(int index, int multiplicity)
try {
Handle(Geom_BSplineCurve) curve = Handle(Geom_BSplineCurve)::DownCast(this->handle());
curve->IncreaseMultiplicity(index, multiplicity);
return;
}
catch (Standard_Failure& e) {
THROWM(Base::CADKernelError,e.GetMessageString())
}
}
}
void GeomBSplineCurve::insertKnot(double param, int multiplicity)

View File

@@ -24,6 +24,7 @@
#define PART_GEOMETRY_H
#include <Adaptor3d_Curve.hxx>
#include <Approx_ParametrizationType.hxx>
#include <Geom_BezierCurve.hxx>
#include <Geom_BezierSurface.hxx>
#include <Geom_BSplineCurve.hxx>
@@ -339,7 +340,15 @@ public:
std::list<Geometry*> toBiArcs(double tolerance) const;
void increaseDegree(int degree);
bool approximate(double tol3d, int maxSegments, int maxDegree, int continuity);
void approximate(double tol3d, int maxSegments, int maxDegree, GeomAbs_Shape continuity);
void approximate(const std::vector<Base::Vector3d>& pnts, int minDegree = 3, int maxDegree = 8,
GeomAbs_Shape continuity = GeomAbs_C2, double tol3d = 1.0e-3);
void approximate(const std::vector<Base::Vector3d>& pnts, Approx_ParametrizationType parType,
int minDegree = 3, int maxDegree = 8,
GeomAbs_Shape continuity = GeomAbs_C2, double tol3d = 1.0e-3);
void approximate(const std::vector<Base::Vector3d>& pnts,
double weight1, double weight2, double weight3, int maxDegree = 8,
GeomAbs_Shape continuity = GeomAbs_C2, double tol3d = 1.0e-3);
void increaseMultiplicity(int index, int multiplicity);
void insertKnot(double param, int multiplicity);
@@ -353,7 +362,7 @@ public:
void Save(Base::Writer &/*writer*/) const override;
void Restore(Base::XMLReader &/*reader*/) override;
// Base implementer ----------------------------
PyObject *getPyObject(void) override;
PyObject *getPyObject() override;
bool isSame(const Geometry &other, double tol, double atol) const override;

View File

@@ -6508,9 +6508,7 @@ bool SketchObject::decreaseBSplineDegree(int GeoId, int degreedecrement /*= 1*/)
int maxdegree = cdegree - degreedecrement;
if (maxdegree == 0)
return false;
bool ok = bspline->approximate(Precision::Confusion(), 20, maxdegree, 0);
if (!ok)
return false;
bspline->approximate(Precision::Confusion(), 20, maxdegree, GeomAbs_C0);
}
catch (const Base::Exception& e) {
Base::Console().Error("%s\n", e.what());