diff --git a/src/Mod/ReverseEngineering/App/AppReverseEngineering.cpp b/src/Mod/ReverseEngineering/App/AppReverseEngineering.cpp index 2eb291c43f..92bfe076e1 100644 --- a/src/Mod/ReverseEngineering/App/AppReverseEngineering.cpp +++ b/src/Mod/ReverseEngineering/App/AppReverseEngineering.cpp @@ -81,9 +81,9 @@ public: Module() : Py::ExtensionModule("ReverseEngineering") { add_keyword_method("approxSurface",&Module::approxSurface, - "approxSurface(Points=,UDegree=3,VDegree=3,NbUPoles=6,NbVPoles=6,Smooth=True)\n" + "approxSurface(Points=,UDegree=3,VDegree=3,NbUPoles=6,NbVPoles=6,Smooth=True,\n" "Weight=0.1,Grad=1.0,Bend=0.0,\n" - "Iterations=5,Correction=True,PatchFactor=1.0" + "Iterations=5,Correction=True,PatchFactor=1.0)" ); #if defined(HAVE_PCL_SURFACE) add_keyword_method("triangulate",&Module::triangulate, @@ -213,6 +213,11 @@ private: Points::PointKernel* points = pPoints->getPointKernelPtr(); pts = points->getBasicPoints(); } + else if (PyObject_TypeCheck(o, &(Mesh::MeshPy::Type))) { + const Mesh::MeshObject* mesh = static_cast(o)->getMeshObjectPtr(); + const MeshCore::MeshPointArray& points = mesh->getKernel().GetPoints(); + pts.insert(pts.begin(), points.begin(), points.end()); + } else { Py::Sequence l(o); pts.reserve(l.size()); diff --git a/src/Mod/ReverseEngineering/Gui/Command.cpp b/src/Mod/ReverseEngineering/Gui/Command.cpp index 06bb71ed87..b6c8bc7295 100644 --- a/src/Mod/ReverseEngineering/Gui/Command.cpp +++ b/src/Mod/ReverseEngineering/Gui/Command.cpp @@ -78,11 +78,12 @@ CmdApproxSurface::CmdApproxSurface() void CmdApproxSurface::activated(int) { App::DocumentObjectT objT; - std::vector obj = Gui::Selection().getObjectsOfType(Points::Feature::getClassTypeId()); - if (obj.size() != 1) { + std::vector obj = Gui::Selection().getObjectsOfType(App::GeoFeature::getClassTypeId()); + if (obj.size() != 1 || !(obj.at(0)->isDerivedFrom(Points::Feature::getClassTypeId()) || + obj.at(0)->isDerivedFrom(Mesh::Feature::getClassTypeId()))) { QMessageBox::warning(Gui::getMainWindow(), qApp->translate("Reen_ApproxSurface", "Wrong selection"), - qApp->translate("Reen_ApproxSurface", "Please select a single point cloud.") + qApp->translate("Reen_ApproxSurface", "Please select a point cloud or mesh.") ); return; } diff --git a/src/Mod/ReverseEngineering/Gui/FitBSplineSurface.cpp b/src/Mod/ReverseEngineering/Gui/FitBSplineSurface.cpp index 7a9ea62171..8dd9738164 100644 --- a/src/Mod/ReverseEngineering/Gui/FitBSplineSurface.cpp +++ b/src/Mod/ReverseEngineering/Gui/FitBSplineSurface.cpp @@ -24,6 +24,7 @@ #include "PreCompiled.h" #ifndef _PreComp_ +# include # include # include #endif @@ -40,9 +41,12 @@ #include #include +#include +#include #include #include #include +#include using namespace ReenGui; @@ -107,6 +111,63 @@ void FitBSplineSurfaceWidget::saveSettings() d->ui.uvdir->onSave(); } +void FitBSplineSurfaceWidget::on_makePlacement_clicked() +{ + try { + App::GeoFeature* geo = d->obj.getObjectAs(); + if (geo) { + const App::PropertyComplexGeoData* geom = geo->getPropertyOfGeometry(); + if (geom) { + std::vector points, normals; + geom->getComplexData()->getPoints(points, normals, 0.001); + + std::vector data; + std::transform(points.begin(), points.end(), std::back_inserter(data), [](const Base::Vector3d& v) { + return Base::convertTo(v); + }); + MeshCore::PlaneFit fit; + fit.AddPoints(data); + if (fit.Fit() < FLOAT_MAX) { + Base::Vector3f base = fit.GetBase(); + Base::Vector3f dirU = fit.GetDirU(); + Base::Vector3f norm = fit.GetNormal(); + + 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); + + QString argument = QString::fromLatin1("Base.Placement(Base.Vector(%1, %2, %3), Base.Rotation(%4, %5, %6, %7))") + .arg(base.x) + .arg(base.y) + .arg(base.z) + .arg(q0) + .arg(q1) + .arg(q2) + .arg(q3); + + QString document = QString::fromStdString(d->obj.getDocumentPython()); + QString command = QString::fromLatin1("%1.addObject(\"App::Placement\", \"Placement\").Placement = %2") + .arg(document, argument); + + Gui::Command::openCommand("Placement"); + Gui::Command::runCommand(Gui::Command::Doc, "from FreeCAD import Base"); + Gui::Command::runCommand(Gui::Command::Doc, command.toLatin1()); + Gui::Command::commitCommand(); + Gui::Command::updateActive(); + } + } + } + } + catch (const Base::Exception& e) { + Gui::Command::abortCommand(); + QMessageBox::warning(this, tr("Input error"), QString::fromLatin1(e.what())); + } +} + bool FitBSplineSurfaceWidget::accept() { try { @@ -114,7 +175,7 @@ bool FitBSplineSurfaceWidget::accept() QString object = QString::fromStdString(d->obj.getObjectPython()); QString argument = QString::fromLatin1( - "Points=%1.Points, " + "Points=getattr(%1, %1.getPropertyNameOfGeometry()), " "UDegree=%2, VDegree=%3, " "NbUPoles=%4, NbVPoles=%5, " "Smooth=%6, " diff --git a/src/Mod/ReverseEngineering/Gui/FitBSplineSurface.h b/src/Mod/ReverseEngineering/Gui/FitBSplineSurface.h index b331af52d2..96a02bd15f 100644 --- a/src/Mod/ReverseEngineering/Gui/FitBSplineSurface.h +++ b/src/Mod/ReverseEngineering/Gui/FitBSplineSurface.h @@ -45,6 +45,9 @@ private: void saveSettings(); void changeEvent(QEvent *e); +private Q_SLOTS: + void on_makePlacement_clicked(); + private: class Private; Private* d; diff --git a/src/Mod/ReverseEngineering/Gui/FitBSplineSurface.ui b/src/Mod/ReverseEngineering/Gui/FitBSplineSurface.ui index ee2c7d7fb6..23734d367f 100644 --- a/src/Mod/ReverseEngineering/Gui/FitBSplineSurface.ui +++ b/src/Mod/ReverseEngineering/Gui/FitBSplineSurface.ui @@ -340,7 +340,7 @@ - + User-defined u/v directions @@ -353,6 +353,13 @@ + + + + Create placement + + + diff --git a/src/Mod/ReverseEngineering/Gui/Segmentation.cpp b/src/Mod/ReverseEngineering/Gui/Segmentation.cpp index 56d9f3c1b4..5a544fb141 100644 --- a/src/Mod/ReverseEngineering/Gui/Segmentation.cpp +++ b/src/Mod/ReverseEngineering/Gui/Segmentation.cpp @@ -178,7 +178,7 @@ void Segmentation::accept() for (auto bt = bounds.begin(); bt != bounds.end(); ++bt) { // project the points onto the surface std::vector polygon; - std::transform(bt->begin(), bt->end(), std::back_inserter(polygon), [&hPlane](const Base::Vector3f v) { + std::transform(bt->begin(), bt->end(), std::back_inserter(polygon), [&hPlane](const Base::Vector3f& v) { gp_Pnt p(v.x, v.y, v.z); return GeomAPI_ProjectPointOnSurf(p, hPlane).NearestPoint(); });