From ec03fb541f9b13f9d45c54ff5d93d6b8132d53de Mon Sep 17 00:00:00 2001 From: Abdullah Tahiri Date: Thu, 27 Nov 2014 16:15:14 +0100 Subject: [PATCH] Part: Extension of Geometry::Curve Part: Extension of Geometry::Curve to wrap more functions of OCC Apart from: bool tangent(double u, gp_Dir&) const; that was already implemented, now it also implements: Base::Vector3d pointAtParameter(double u) const; Base::Vector3d firstDerivativeAtParameter(double u) const; Base::Vector3d secondDerivativeAtParameter(double u) const; bool normal(double u, gp_Dir& dir) const; bool closestParameter(Base::Vector3d point, double &u); i.e. apart from giving the tangent vector for a given curve at parameter value u, it also gives: - The point cartesian coordinates of the curve point at parameter value u - The vector of the first derivative at parameter value u - The vector of the second derivative at parameter value u - The normal vector to the curve at parameter value u - The parameter value of a curve closest ot a given point Code cleanup: Changing Trim functionality of Ellipse to use OCC calculations Part Curve functions extension: closestParameterToBasicCurve It provides the parameter of the curve closest to a given point. If the curve is a Trimmed curve, the parameter of the basic underlaying curve closest to the point is provided. --- src/Mod/Part/App/Geometry.cpp | 92 +++++++++++++++++++++++++++ src/Mod/Part/App/Geometry.h | 6 ++ src/Mod/Sketcher/App/SketchObject.cpp | 21 +++--- 3 files changed, 107 insertions(+), 12 deletions(-) diff --git a/src/Mod/Part/App/Geometry.cpp b/src/Mod/Part/App/Geometry.cpp index b2344175c..6c76829f1 100644 --- a/src/Mod/Part/App/Geometry.cpp +++ b/src/Mod/Part/App/Geometry.cpp @@ -87,6 +87,7 @@ # include # include # include +# include #endif @@ -320,6 +321,97 @@ bool GeomCurve::tangent(double u, gp_Dir& dir) const return false; } +Base::Vector3d GeomCurve::pointAtParameter(double u) const +{ + Handle_Geom_Curve c = Handle_Geom_Curve::DownCast(handle()); + GeomLProp_CLProps prop(c,u,0,Precision::Confusion()); + + const gp_Pnt &point=prop.Value(); + + return Base::Vector3d(point.X(),point.Y(),point.Z()); +} + +Base::Vector3d GeomCurve::firstDerivativeAtParameter(double u) const +{ + Handle_Geom_Curve c = Handle_Geom_Curve::DownCast(handle()); + GeomLProp_CLProps prop(c,u,1,Precision::Confusion()); + + const gp_Vec &vec=prop.D1(); + + return Base::Vector3d(vec.X(),vec.Y(),vec.Z()); +} + +Base::Vector3d GeomCurve::secondDerivativeAtParameter(double u) const +{ + Handle_Geom_Curve c = Handle_Geom_Curve::DownCast(handle()); + GeomLProp_CLProps prop(c,u,2,Precision::Confusion()); + + const gp_Vec &vec=prop.D2(); + + return Base::Vector3d(vec.X(),vec.Y(),vec.Z()); +} + +bool GeomCurve::normal(double u, gp_Dir& dir) const +{ + Handle_Geom_Curve c = Handle_Geom_Curve::DownCast(handle()); + GeomLProp_CLProps prop(c,u,1,Precision::Confusion()); + if (prop.IsTangentDefined()) { + prop.Normal(dir); + return true; + } + + return false; +} + +bool GeomCurve::closestParameter(Base::Vector3d point, double &u) const +{ + Handle_Geom_Curve c = Handle_Geom_Curve::DownCast(handle()); + try { + if (!c.IsNull()) { + gp_Pnt pnt(point.x,point.y,point.z); + GeomAPI_ProjectPointOnCurve ppc(pnt, c); + u = ppc.LowerDistanceParameter(); + return true; + } + } + catch (Standard_Failure) { + Handle_Standard_Failure e = Standard_Failure::Caught(); + std::cout << e->GetMessageString() << std::endl; + return false; + } + + return false; +} + +bool GeomCurve::closestParameterToBasicCurve(Base::Vector3d point, double &u) const +{ + Handle_Geom_Curve c = Handle_Geom_Curve::DownCast(handle()); + + if (c->IsKind(STANDARD_TYPE(Geom_TrimmedCurve))){ + Handle_Geom_TrimmedCurve tc = Handle_Geom_TrimmedCurve::DownCast(handle()); + Handle_Geom_Curve bc = Handle_Geom_Curve::DownCast(tc->BasisCurve()); + try { + if (!bc.IsNull()) { + gp_Pnt pnt(point.x,point.y,point.z); + GeomAPI_ProjectPointOnCurve ppc(pnt, bc); + u = ppc.LowerDistanceParameter(); + return true; + } + } + catch (Standard_Failure) { + Handle_Standard_Failure e = Standard_Failure::Caught(); + std::cout << e->GetMessageString() << std::endl; + return false; + } + + return false; + + } + else { + return this->closestParameter(point, u); + } +} + // ------------------------------------------------- diff --git a/src/Mod/Part/App/Geometry.h b/src/Mod/Part/App/Geometry.h index 0924b9953..3470f09af 100644 --- a/src/Mod/Part/App/Geometry.h +++ b/src/Mod/Part/App/Geometry.h @@ -115,6 +115,12 @@ public: TopoDS_Shape toShape() const; bool tangent(double u, gp_Dir&) const; + Base::Vector3d pointAtParameter(double u) const; + Base::Vector3d firstDerivativeAtParameter(double u) const; + Base::Vector3d secondDerivativeAtParameter(double u) const; + bool normal(double u, gp_Dir& dir) const; + bool closestParameter(Base::Vector3d point, double &u) const; + bool closestParameterToBasicCurve(Base::Vector3d point, double &u) const; }; class PartExport GeomBezierCurve : public GeomCurve diff --git a/src/Mod/Sketcher/App/SketchObject.cpp b/src/Mod/Sketcher/App/SketchObject.cpp index 529e33bdc..4632f97bf 100644 --- a/src/Mod/Sketcher/App/SketchObject.cpp +++ b/src/Mod/Sketcher/App/SketchObject.cpp @@ -969,19 +969,16 @@ int SketchObject::trim(int GeoId, const Base::Vector3d& point) } else if (geo->getTypeId() == Part::GeomEllipse::getClassTypeId()) { const Part::GeomEllipse *ellipse = dynamic_cast(geo); Base::Vector3d center = ellipse->getCenter(); - double theta0 = Base::fmod( - atan2(-ellipse->getMajorRadius()*((point.x-center.x)*sin(ellipse->getAngleXU())-(point.y-center.y)*cos(ellipse->getAngleXU())), - ellipse->getMinorRadius()*((point.x-center.x)*cos(ellipse->getAngleXU())+(point.y-center.y)*sin(ellipse->getAngleXU())) - ), 2.f*M_PI); + double theta0; + ellipse->closestParameter(point,theta0); + theta0 = Base::fmod(theta0, 2.f*M_PI); if (GeoId1 >= 0 && GeoId2 >= 0) { - double theta1 = Base::fmod( - atan2(-ellipse->getMajorRadius()*((point1.x-center.x)*sin(ellipse->getAngleXU())-(point1.y-center.y)*cos(ellipse->getAngleXU())), - ellipse->getMinorRadius()*((point1.x-center.x)*cos(ellipse->getAngleXU())+(point1.y-center.y)*sin(ellipse->getAngleXU())) - ), 2.f*M_PI); - double theta2 = Base::fmod( - atan2(-ellipse->getMajorRadius()*((point2.x-center.x)*sin(ellipse->getAngleXU())-(point2.y-center.y)*cos(ellipse->getAngleXU())), - ellipse->getMinorRadius()*((point2.x-center.x)*cos(ellipse->getAngleXU())+(point2.y-center.y)*sin(ellipse->getAngleXU())) - ), 2.f*M_PI); + double theta1; + ellipse->closestParameter(point1,theta1); + theta1 = Base::fmod(theta1, 2.f*M_PI); + double theta2; + ellipse->closestParameter(point2,theta2); + theta2 = Base::fmod(theta2, 2.f*M_PI); if (Base::fmod(theta1 - theta0, 2.f*M_PI) > Base::fmod(theta2 - theta0, 2.f*M_PI)) { std::swap(GeoId1,GeoId2); std::swap(point1,point2);