diff --git a/src/Mod/Mesh/App/Mesh.cpp b/src/Mod/Mesh/App/Mesh.cpp index 21e54a386..924db294a 100644 --- a/src/Mod/Mesh/App/Mesh.cpp +++ b/src/Mod/Mesh/App/Mesh.cpp @@ -256,10 +256,28 @@ void MeshObject::getPoints(std::vector &Points, std::vector &Normals, float Accuracy, uint16_t flags) const { + Base::Matrix4D mat = _Mtrx; + unsigned long ctpoints = _kernel.CountPoints(); Points.reserve(ctpoints); for (unsigned long i=0; igetPoint(i)); + Base::Vector3f vertf = _kernel.GetPoint(i); + Base::Vector3d vertd(vertf.x, vertf.y, vertf.z); + vertd = mat * vertd; + Points.push_back(vertd); + } + + // nullify translation part + mat[0][3] = 0.0; + mat[1][3] = 0.0; + mat[2][3] = 0.0; + Normals.reserve(ctpoints); + MeshCore::MeshRefNormalToPoints ptNormals(_kernel); + for (unsigned long i=0; i &Points,std::vector &Topo, - float Accuracy, uint16_t flags) const +void PointKernel::getPoints(std::vector &Points, + std::vector &Normals, + float Accuracy, uint16_t flags) const { unsigned long ctpoints = _Points.size(); Points.reserve(ctpoints); diff --git a/src/Mod/Points/App/Points.h b/src/Mod/Points/App/Points.h index d0541c24c..8b058feed 100644 --- a/src/Mod/Points/App/Points.h +++ b/src/Mod/Points/App/Points.h @@ -85,9 +85,10 @@ public: { this->_Points = pts; } void swap(std::vector& pts) { this->_Points.swap(pts); } - void getFaces(std::vector &Points,std::vector &Topo, - float Accuracy, uint16_t flags=0) const; + virtual void getPoints(std::vector &Points, + std::vector &Normals, + float Accuracy, uint16_t flags=0) const; virtual void transformGeometry(const Base::Matrix4D &rclMat); virtual Base::BoundBox3d getBoundBox(void)const; diff --git a/src/Mod/ReverseEngineering/Gui/Command.cpp b/src/Mod/ReverseEngineering/Gui/Command.cpp index 6b0a04d30..9cb2e6911 100644 --- a/src/Mod/ReverseEngineering/Gui/Command.cpp +++ b/src/Mod/ReverseEngineering/Gui/Command.cpp @@ -101,79 +101,80 @@ void CmdApproxPlane::activated(int iMsg) { std::vector obj = Gui::Selection().getObjectsOfType(); for (std::vector::iterator it = obj.begin(); it != obj.end(); ++it) { - std::map Map; - (*it)->getPropertyMap(Map); - for (std::map::iterator jt = Map.begin(); jt != Map.end(); ++jt) { - if (jt->second->getTypeId().isDerivedFrom(App::PropertyComplexGeoData::getClassTypeId())) { - std::vector aPoints; - std::vector aTopo; - const Data::ComplexGeoData* data = static_cast(jt->second)->getComplexData(); - if (!data) - continue; + std::vector aPoints; + std::vector aNormals; - data->getFaces(aPoints, aTopo,0.01f); - - // get a reference normal for the plane fit - Base::Vector3f refNormal(0,0,0); - if (!aTopo.empty()) { - Data::ComplexGeoData::Facet f = aTopo.front(); - Base::Vector3d v1 = aPoints[f.I2] - aPoints[f.I1]; - Base::Vector3d v2 = aPoints[f.I3] - aPoints[f.I1]; - refNormal = Base::convertTo(v1 % v2); + std::vector List; + (*it)->getPropertyList(List); + for (std::vector::iterator jt = List.begin(); jt != List.end(); ++jt) { + if ((*jt)->getTypeId().isDerivedFrom(App::PropertyComplexGeoData::getClassTypeId())) { + const Data::ComplexGeoData* data = static_cast(*jt)->getComplexData(); + if (data) { + data->getPoints(aPoints, aNormals, 0.01f); + if (!aPoints.empty()) + break; } - - std::vector aData; - aData.reserve(aPoints.size()); - for (std::vector::iterator jt = aPoints.begin(); jt != aPoints.end(); ++jt) - aData.push_back(Base::toVector(*jt)); - MeshCore::PlaneFit fit; - fit.AddPoints(aData); - float sigma = fit.Fit(); - Base::Vector3f base = fit.GetBase(); - Base::Vector3f dirU = fit.GetDirU(); - Base::Vector3f dirV = fit.GetDirV(); - Base::Vector3f norm = fit.GetNormal(); - - // if the dot product of the reference with the plane normal is negative - // a flip must be done - if (refNormal * norm < 0) { - norm = -norm; - dirU = -dirU; - } - - float width, length; - fit.Dimension(width, length); - - // move to the corner point - base = base - (0.5f * length * dirU + 0.5f * width * dirV); - - Base::CoordinateSystem cs; - cs.setPosition(Base::convertTo(base)); - cs.setAxes(Base::convertTo(norm), - Base::convertTo(dirU)); - Base::Placement pm = Base::CoordinateSystem().displacement(cs); - double q0, q1, q2, q3; - pm.getRotation().getValue(q0, q1, q2, q3); - - Base::Console().Log("RMS value for plane fit with %lu points: %.4f\n", aData.size(), sigma); - Base::Console().Log(" Plane base(%.4f, %.4f, %.4f)\n", base.x, base.y, base.z); - Base::Console().Log(" Plane normal(%.4f, %.4f, %.4f)\n", norm.x, norm.y, norm.z); - - std::stringstream str; - str << "from FreeCAD import Base" << std::endl; - str << "App.ActiveDocument.addObject('Part::Plane','Plane_fit')" << std::endl; - str << "App.ActiveDocument.ActiveObject.Length = " << length << std::endl; - str << "App.ActiveDocument.ActiveObject.Width = " << width << std::endl; - str << "App.ActiveDocument.ActiveObject.Placement = Base.Placement(" - << "Base.Vector(" << base.x << "," << base.y << "," << base.z << ")," - << "Base.Rotation(" << q0 << "," << q1 << "," << q2 << "," << q3 << "))" << std::endl; - - openCommand("Fit plane"); - doCommand(Gui::Command::Doc, str.str().c_str()); - commitCommand(); - updateActive(); } } + + if (!aPoints.empty()) { + // get a reference normal for the plane fit + Base::Vector3f refNormal(0,0,0); + if (!aNormals.empty()) { + refNormal = Base::convertTo(aNormals.front()); + } + + std::vector aData; + aData.reserve(aPoints.size()); + for (std::vector::iterator jt = aPoints.begin(); jt != aPoints.end(); ++jt) + aData.push_back(Base::toVector(*jt)); + MeshCore::PlaneFit fit; + fit.AddPoints(aData); + float sigma = fit.Fit(); + Base::Vector3f base = fit.GetBase(); + Base::Vector3f dirU = fit.GetDirU(); + Base::Vector3f dirV = fit.GetDirV(); + Base::Vector3f norm = fit.GetNormal(); + + // if the dot product of the reference with the plane normal is negative + // a flip must be done + if (refNormal * norm < 0) { + norm = -norm; + dirU = -dirU; + } + + float width, length; + fit.Dimension(width, length); + + // move to the corner point + base = base - (0.5f * length * dirU + 0.5f * width * dirV); + + Base::CoordinateSystem cs; + cs.setPosition(Base::convertTo(base)); + cs.setAxes(Base::convertTo(norm), + Base::convertTo(dirU)); + Base::Placement pm = Base::CoordinateSystem().displacement(cs); + double q0, q1, q2, q3; + pm.getRotation().getValue(q0, q1, q2, q3); + + Base::Console().Log("RMS value for plane fit with %lu points: %.4f\n", aData.size(), sigma); + Base::Console().Log(" Plane base(%.4f, %.4f, %.4f)\n", base.x, base.y, base.z); + Base::Console().Log(" Plane normal(%.4f, %.4f, %.4f)\n", norm.x, norm.y, norm.z); + + std::stringstream str; + str << "from FreeCAD import Base" << std::endl; + str << "App.ActiveDocument.addObject('Part::Plane','Plane_fit')" << std::endl; + str << "App.ActiveDocument.ActiveObject.Length = " << length << std::endl; + str << "App.ActiveDocument.ActiveObject.Width = " << width << std::endl; + str << "App.ActiveDocument.ActiveObject.Placement = Base.Placement(" + << "Base.Vector(" << base.x << "," << base.y << "," << base.z << ")," + << "Base.Rotation(" << q0 << "," << q1 << "," << q2 << "," << q3 << "))" << std::endl; + + openCommand("Fit plane"); + doCommand(Gui::Command::Doc, str.str().c_str()); + commitCommand(); + updateActive(); + } } }