ReverseEngineering: improve workflow of fitting of B-spline surface
This commit is contained in:
@@ -81,9 +81,9 @@ public:
|
||||
Module() : Py::ExtensionModule<Module>("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<Mesh::MeshPy*>(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());
|
||||
|
||||
@@ -78,11 +78,12 @@ CmdApproxSurface::CmdApproxSurface()
|
||||
void CmdApproxSurface::activated(int)
|
||||
{
|
||||
App::DocumentObjectT objT;
|
||||
std::vector<App::DocumentObject*> obj = Gui::Selection().getObjectsOfType(Points::Feature::getClassTypeId());
|
||||
if (obj.size() != 1) {
|
||||
std::vector<App::DocumentObject*> 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;
|
||||
}
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#include "PreCompiled.h"
|
||||
|
||||
#ifndef _PreComp_
|
||||
# include <algorithm>
|
||||
# include <QMessageBox>
|
||||
# include <QTextStream>
|
||||
#endif
|
||||
@@ -40,9 +41,12 @@
|
||||
#include <Gui/WaitCursor.h>
|
||||
|
||||
#include <Base/Interpreter.h>
|
||||
#include <Base/Converter.h>
|
||||
#include <Base/CoordinateSystem.h>
|
||||
#include <App/Application.h>
|
||||
#include <App/Document.h>
|
||||
#include <App/Placement.h>
|
||||
#include <Mod/Mesh/App/Core/Approximation.h>
|
||||
|
||||
|
||||
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<App::GeoFeature>();
|
||||
if (geo) {
|
||||
const App::PropertyComplexGeoData* geom = geo->getPropertyOfGeometry();
|
||||
if (geom) {
|
||||
std::vector<Base::Vector3d> points, normals;
|
||||
geom->getComplexData()->getPoints(points, normals, 0.001);
|
||||
|
||||
std::vector<Base::Vector3f> data;
|
||||
std::transform(points.begin(), points.end(), std::back_inserter(data), [](const Base::Vector3d& v) {
|
||||
return Base::convertTo<Base::Vector3f>(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::Vector3d>(base));
|
||||
cs.setAxes(Base::convertTo<Base::Vector3d>(norm),
|
||||
Base::convertTo<Base::Vector3d>(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, "
|
||||
|
||||
@@ -45,6 +45,9 @@ private:
|
||||
void saveSettings();
|
||||
void changeEvent(QEvent *e);
|
||||
|
||||
private Q_SLOTS:
|
||||
void on_makePlacement_clicked();
|
||||
|
||||
private:
|
||||
class Private;
|
||||
Private* d;
|
||||
|
||||
@@ -340,7 +340,7 @@
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<item row="2" column="0">
|
||||
<widget class="Gui::PrefCheckBox" name="uvdir">
|
||||
<property name="text">
|
||||
<string>User-defined u/v directions</string>
|
||||
@@ -353,6 +353,13 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QPushButton" name="makePlacement">
|
||||
<property name="text">
|
||||
<string>Create placement</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
|
||||
@@ -178,7 +178,7 @@ void Segmentation::accept()
|
||||
for (auto bt = bounds.begin(); bt != bounds.end(); ++bt) {
|
||||
// project the points onto the surface
|
||||
std::vector<gp_Pnt> 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();
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user