diff --git a/src/Mod/Mesh/App/Mesh.cpp b/src/Mod/Mesh/App/Mesh.cpp index 49c8aa6829..79fd28f70b 100644 --- a/src/Mod/Mesh/App/Mesh.cpp +++ b/src/Mod/Mesh/App/Mesh.cpp @@ -841,6 +841,37 @@ bool MeshObject::nearestFacetOnRay(const MeshObject::TRay& ray, double maxAngle, return false; } +std::vector MeshObject::foraminate(const TRay& ray, double maxAngle) const +{ + Base::Vector3f pnt = Base::toVector(ray.first); + Base::Vector3f dir = Base::toVector(ray.second); + + Base::Placement plm = getPlacement(); + Base::Placement inv = plm.inverse(); + + // transform the ray relative to the mesh kernel + inv.multVec(pnt, pnt); + inv.getRotation().multVec(dir, dir); + + Base::Vector3f res; + MeshCore::MeshFacetIterator f_it(getKernel()); + int index = 0; + + std::vector output; + for (f_it.Begin(); f_it.More(); f_it.Next(), index++) { + if (f_it->Foraminate(pnt, dir, res, static_cast(maxAngle))) { + plm.multVec(res, res); + + MeshObject::TFaceSection section; + section.first = index; + section.second = Base::toVector(res); + output.push_back(section); + } + } + + return output; +} + void MeshObject::updateMesh(const std::vector& facets) const { std::vector points; diff --git a/src/Mod/Mesh/App/Mesh.h b/src/Mod/Mesh/App/Mesh.h index 87f8ada1d9..f875760f07 100644 --- a/src/Mod/Mesh/App/Mesh.h +++ b/src/Mod/Mesh/App/Mesh.h @@ -155,6 +155,7 @@ public: float Accuracy, uint16_t flags=0) const; std::vector getPointsFromFacets(const std::vector& facets) const; bool nearestFacetOnRay(const TRay& ray, double maxAngle, TFaceSection& output) const; + std::vector foraminate(const TRay& ray, double maxAngle) const; //@} void setKernel(const MeshCore::MeshKernel& m); diff --git a/src/Mod/Mesh/App/MeshPyImp.cpp b/src/Mod/Mesh/App/MeshPyImp.cpp index 7f5503fd13..85dff1f3a3 100644 --- a/src/Mod/Mesh/App/MeshPyImp.cpp +++ b/src/Mod/Mesh/App/MeshPyImp.cpp @@ -1635,7 +1635,7 @@ PyObject* MeshPy::collapseFacets(PyObject *args) Py_Return; } -PyObject* MeshPy::foraminate(PyObject *args) +PyObject* MeshPy::foraminate(PyObject *args) { PyObject* pnt_p; PyObject* dir_p; @@ -1644,28 +1644,20 @@ PyObject* MeshPy::foraminate(PyObject *args) return nullptr; try { - Py::Tuple pnt_t(pnt_p); - Py::Tuple dir_t(dir_p); - Base::Vector3f pnt((float)Py::Float(pnt_t.getItem(0)), - (float)Py::Float(pnt_t.getItem(1)), - (float)Py::Float(pnt_t.getItem(2))); - Base::Vector3f dir((float)Py::Float(dir_t.getItem(0)), - (float)Py::Float(dir_t.getItem(1)), - (float)Py::Float(dir_t.getItem(2))); + Py::Vector pnt_t(pnt_p, false); + Py::Vector dir_t(dir_p, false); - Base::Vector3f res; - MeshCore::MeshFacetIterator f_it(getMeshObjectPtr()->getKernel()); - int index = 0; + MeshObject::TRay ray = std::make_pair(pnt_t.toVector(), + dir_t.toVector()); + auto output = getMeshObjectPtr()->foraminate(ray, maxAngle); Py::Dict dict; - for (f_it.Begin(); f_it.More(); f_it.Next(), index++) { - if (f_it->Foraminate(pnt, dir, res, static_cast(maxAngle))) { - Py::Tuple tuple(3); - tuple.setItem(0, Py::Float(res.x)); - tuple.setItem(1, Py::Float(res.y)); - tuple.setItem(2, Py::Float(res.z)); - dict.setItem(Py::Long(index), tuple); - } + for (const auto& it : output) { + Py::Tuple tuple(3); + tuple.setItem(0, Py::Float(it.second.x)); + tuple.setItem(1, Py::Float(it.second.y)); + tuple.setItem(2, Py::Float(it.second.z)); + dict.setItem(Py::Long(it.first), tuple); } return Py::new_reference_to(dict); diff --git a/src/Mod/Mesh/App/MeshTestsApp.py b/src/Mod/Mesh/App/MeshTestsApp.py index 1775f587ef..23e286a993 100644 --- a/src/Mod/Mesh/App/MeshTestsApp.py +++ b/src/Mod/Mesh/App/MeshTestsApp.py @@ -229,6 +229,24 @@ class MeshSplitTestCases(unittest.TestCase): self.assertEqual(filtered_result, list(self.mesh.foraminate((0.0, 0.0, 0.0), (0,1,1), math.pi/2).keys())) + def testForaminatePlacement(self): + pnt = Base.Vector(0.0, 0.0, 0.0) + vec = Base.Vector(0.0, 1.0, 1.0) + results = self.mesh.foraminate(pnt, vec) + self.assertEqual(len(results), 4) + + # Apply placement to mesh + plm = Base.Placement(Base.Vector(1,2,3), Base.Rotation(1,1,1,1)) + self.mesh.Placement = plm + self.assertEqual(len(self.mesh.foraminate(pnt, vec)), 0) + + # Apply the placement on the ray as well + pnt = plm.multVec(pnt) + vec = plm.Rotation.multVec(vec) + results2 = self.mesh.foraminate(pnt, vec) + self.assertEqual(len(results2), 4) + self.assertEqual(list(results.keys()), list(results2.keys())) + class MeshGeoTestCases(unittest.TestCase): def setUp(self): # set up a planar face with 2 triangles