From 88f91d621b69cfea40bfc460836cb8e12935490e Mon Sep 17 00:00:00 2001 From: wmayer Date: Tue, 11 Jun 2019 13:25:52 +0200 Subject: [PATCH] determine edge parameters where curve point will be projected onto a mesh edge --- src/Mod/MeshPart/App/AppMeshPartPy.cpp | 34 ++++++++++ src/Mod/MeshPart/App/CurveProjector.cpp | 83 +++++++++++++++++++++++++ src/Mod/MeshPart/App/CurveProjector.h | 22 +++++-- src/Mod/MeshPart/App/PreCompiled.h | 2 + 4 files changed, 135 insertions(+), 6 deletions(-) diff --git a/src/Mod/MeshPart/App/AppMeshPartPy.cpp b/src/Mod/MeshPart/App/AppMeshPartPy.cpp index d481e58371..70cb47eaf4 100644 --- a/src/Mod/MeshPart/App/AppMeshPartPy.cpp +++ b/src/Mod/MeshPart/App/AppMeshPartPy.cpp @@ -24,6 +24,7 @@ #include "PreCompiled.h" #ifndef _PreComp_ # include +# include #endif #include @@ -61,6 +62,12 @@ public: " upVector ((x, y, z) tuple):\n" " MaxSize (float):\n" ); + add_varargs_method("findSectionParameters",&Module::findSectionParameters, + "Find the parameters of the edge where when projecting the corresponding point\n" + "will lie on an edge of the mesh\n" + "\n" + "findSectionParameters(Edge, Mesh, Vector) -> list\n" + ); add_keyword_method("projectShapeOnMesh",&Module::projectShapeOnMesh, "Projects a shape onto a mesh with a given maximum distance\n" "projectShapeOnMesh(Shape, Mesh, float) -> polygon\n" @@ -208,6 +215,33 @@ private: MeshPart::MeshAlgos::LoftOnCurve(M,aShape,poly,Base::Vector3f(x,y,z),size); return Py::asObject(new Mesh::MeshPy(new Mesh::MeshObject(M))); } + Py::Object findSectionParameters(const Py::Tuple& args) + { + PyObject *e, *m, *v; + if (!PyArg_ParseTuple(args.ptr(), "O!O!O!", &(Part::TopoShapeEdgePy::Type), &e, + &(Mesh::MeshPy::Type), &m, + &(Base::VectorPy::Type),&v)) + throw Py::Exception(); + + TopoDS_Shape shape = static_cast(e)->getTopoShapePtr()->getShape(); + const Mesh::MeshObject* mesh = static_cast(m)->getMeshObjectPtr(); + MeshCore::MeshKernel kernel(mesh->getKernel()); + kernel.Transform(mesh->getTransform()); + Base::Vector3d* vec = static_cast(v)->getVectorPtr(); + Base::Vector3f dir = Base::convertTo(*vec); + + MeshProjection proj(kernel); + std::set parameters; + proj.findSectionParameters(TopoDS::Edge(shape), dir, parameters); + + Py::List list; + for (auto it : parameters) { + Py::Float val(it); + list.append(val); + } + + return list; + } Py::Object projectShapeOnMesh(const Py::Tuple& args, const Py::Dict& kwds) { static char* kwds_maxdist[] = {"Shape", "Mesh", "MaxDistance", NULL}; diff --git a/src/Mod/MeshPart/App/CurveProjector.cpp b/src/Mod/MeshPart/App/CurveProjector.cpp index 2e58929965..9059d08c9a 100644 --- a/src/Mod/MeshPart/App/CurveProjector.cpp +++ b/src/Mod/MeshPart/App/CurveProjector.cpp @@ -29,6 +29,9 @@ # include # include # include +# include +# include +# include # include # include # include @@ -39,6 +42,7 @@ # include # include # include +# include #endif @@ -733,6 +737,85 @@ void MeshProjection::splitMeshByShape ( const TopoDS_Shape &aShape, float fMaxDi str.close(); } +bool MeshProjection::findIntersection(const Edge& edgeSegm, const Edge& meshEdge, + const Base::Vector3f& dir, Base::Vector3f& res) const +{ + Base::Vector3f planeNormal; + planeNormal = dir.Cross(edgeSegm.cPt2 - edgeSegm.cPt1); + float dist1 = planeNormal.Dot(meshEdge.cPt1 - edgeSegm.cPt1); + float dist2 = planeNormal.Dot(meshEdge.cPt2 - edgeSegm.cPt1); + if (dist1 * dist2 < 0) { + planeNormal = dir.Cross(meshEdge.cPt2 - meshEdge.cPt1); + dist1 = planeNormal.Dot(edgeSegm.cPt1 - meshEdge.cPt1); + dist2 = planeNormal.Dot(edgeSegm.cPt2 - meshEdge.cPt1); + if (dist1 * dist2 < 0) { + // intersection detected + float t = planeNormal.Dot(meshEdge.cPt1 - edgeSegm.cPt1) / + planeNormal.Dot(edgeSegm.cPt2 - edgeSegm.cPt1); + res = edgeSegm.cPt1 * (1-t) + edgeSegm.cPt2 * t; + return true; + } + } + return false; +} + +void MeshProjection::findSectionParameters(const TopoDS_Edge& edge, const Base::Vector3f& dir, std::set& parameters) const +{ + MeshAlgorithm clAlg( _rcMesh ); + float fAvgLen = clAlg.GetAverageEdgeLength(); + BRepAdaptor_Curve adapt(edge); + double edgeLen = GCPnts_AbscissaPoint::Length(adapt, Precision::Confusion()); + + std::vector polyline; + discretize(edge, polyline, std::max(10, static_cast(edgeLen/fAvgLen))); + if (polyline.empty()) + return; + + std::vector lines; + Base::Vector3f start = polyline.front(); + for (auto it = polyline.begin()+1; it != polyline.end(); ++it) { + Edge line; + line.cPt1 = start; + line.cPt2 = *it; + start = line.cPt2; + lines.push_back(line); + } + + const MeshCore::MeshFacetArray& facets = _rcMesh.GetFacets(); + const MeshCore::MeshPointArray& points = _rcMesh.GetPoints(); + + Base::Vector3f res; + for (auto it : facets) { + for (int i=0; i<3; i++) { + Base::Vector3f pt1 = points[it._aulPoints[i]]; + Base::Vector3f pt2 = points[it._aulPoints[(i+1)%3]]; + Edge line; + line.cPt1 = pt1; + line.cPt2 = pt2; + + for (auto jt : lines) { + if (findIntersection(jt, line, dir, res)) { + try { + BRepBuilderAPI_MakeVertex aBuilder(gp_Pnt(res.x,res.y,res.z)); + BRepExtrema_DistShapeShape extss(aBuilder.Vertex(), edge); + if (extss.NbSolution() == 1) { + Standard_Real par; + //gp_pnt pnt = extss.PointOnShape2(1); + //Standard_Real par = BRep_Tool::Parameter(aBuilder.Vertex(), edge); + extss.ParOnEdgeS2(1, par); + parameters.insert(par); + break; + } + } + catch (const Standard_Failure&) { + // ignore + } + } + } + } + } +} + void MeshProjection::projectToMesh (const TopoDS_Shape &aShape, float fMaxDist, std::vector& rPolyLines) const { // calculate the average edge length and create a grid diff --git a/src/Mod/MeshPart/App/CurveProjector.h b/src/Mod/MeshPart/App/CurveProjector.h index 36ccd8d9f1..e824ec04e6 100644 --- a/src/Mod/MeshPart/App/CurveProjector.h +++ b/src/Mod/MeshPart/App/CurveProjector.h @@ -29,14 +29,9 @@ #endif #include - -#include - - -class TopoDS_Edge; -class TopoDS_Shape; #include +#include #include namespace MeshCore @@ -170,6 +165,11 @@ public: unsigned long uE0, uE1; /**< start and endpoint of an edge */ Base::Vector3f cPt; /**< Point on edge (\a uE0, \a uE1) */ }; + struct Edge + { + Base::Vector3f cPt1; + Base::Vector3f cPt2; + }; struct PolyLine { std::vector points; @@ -180,6 +180,15 @@ public: /// Destruction ~MeshProjection(); + /** + * @brief findSectionParameters + * Find the parameters of the edge where when projecting the corresponding point will lie + * on an edge of the mesh. + * @param edge + * @param dir + * @param parameters + */ + void findSectionParameters(const TopoDS_Edge& edge, const Base::Vector3f& dir, std::set& parameters) const; void discretize(const TopoDS_Edge& aEdge, std::vector& polyline, std::size_t minPoints=2) const; /** * Searches all edges that intersect with the projected curve \a aShape. Therefore \a aShape must @@ -204,6 +213,7 @@ public: protected: void projectEdgeToEdge(const TopoDS_Edge &aCurve, float fMaxDist, const MeshCore::MeshFacetGrid& rGrid, std::vector& rSplitEdges) const; + bool findIntersection(const Edge&, const Edge&, const Base::Vector3f& dir, Base::Vector3f& res) const; private: const MeshKernel& _rcMesh; diff --git a/src/Mod/MeshPart/App/PreCompiled.h b/src/Mod/MeshPart/App/PreCompiled.h index deea45c934..07eac4d2e8 100644 --- a/src/Mod/MeshPart/App/PreCompiled.h +++ b/src/Mod/MeshPart/App/PreCompiled.h @@ -135,6 +135,8 @@ #include #include #include +#include +#include #include #include #include