ReverseEngineering: improve manual segmentation
This commit is contained in:
@@ -41,6 +41,7 @@
|
||||
#include <Mod/Mesh/App/Core/Smoothing.h>
|
||||
#include <Mod/Mesh/App/Mesh.h>
|
||||
#include <Mod/Mesh/App/MeshFeature.h>
|
||||
#include <Mod/Mesh/Gui/ViewProvider.h>
|
||||
|
||||
using namespace ReverseEngineeringGui;
|
||||
|
||||
@@ -110,6 +111,119 @@ void SegmentationManual::on_cbSelectComp_toggled(bool on)
|
||||
meshSel.setAddComponentOnClick(on);
|
||||
}
|
||||
|
||||
class SegmentationManual::Private {
|
||||
public:
|
||||
static void findGeometry(int minFaces, double tolerance,
|
||||
std::function<MeshCore::AbstractSurfaceFit*(const std::vector<Base::Vector3f>&,
|
||||
const std::vector<Base::Vector3f>&)> fitFunc)
|
||||
{
|
||||
Gui::Document* gdoc = Gui::Application::Instance->activeDocument();
|
||||
if (!gdoc)
|
||||
return;
|
||||
|
||||
App::Document* adoc = gdoc->getDocument();
|
||||
std::vector<Mesh::Feature*> meshes = adoc->getObjectsOfType<Mesh::Feature>();
|
||||
for (auto it : meshes) {
|
||||
MeshGui::ViewProviderMesh* vpm = static_cast<MeshGui::ViewProviderMesh*>(gdoc->getViewProvider(it));
|
||||
const Mesh::MeshObject& mesh = it->Mesh.getValue();
|
||||
|
||||
if (mesh.hasSelectedFacets()) {
|
||||
const MeshCore::MeshKernel& kernel = mesh.getKernel();
|
||||
|
||||
std::vector<unsigned long> facets, vertexes;
|
||||
mesh.getFacetsFromSelection(facets);
|
||||
vertexes = mesh.getPointsFromFacets(facets);
|
||||
MeshCore::MeshPointArray coords = kernel.GetPoints(vertexes);
|
||||
|
||||
std::vector<Base::Vector3f> points, normals;
|
||||
normals = kernel.GetFacetNormals(facets);
|
||||
points.insert(points.end(), coords.begin(), coords.end());
|
||||
coords.clear();
|
||||
|
||||
MeshCore::AbstractSurfaceFit* surfFit = fitFunc(points, normals);
|
||||
if (surfFit) {
|
||||
MeshCore::MeshSegmentAlgorithm finder(kernel);
|
||||
|
||||
std::vector<MeshCore::MeshSurfaceSegmentPtr> segm;
|
||||
segm.emplace_back(new MeshCore::MeshDistanceGenericSurfaceFitSegment
|
||||
(surfFit, kernel, minFaces, tolerance));
|
||||
finder.FindSegments(segm);
|
||||
|
||||
for (auto segmIt : segm) {
|
||||
const std::vector<MeshCore::MeshSegment>& data = segmIt->GetSegments();
|
||||
for (const auto dataIt : data) {
|
||||
vpm->addSelection(dataIt);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
void SegmentationManual::on_planeDetect_clicked()
|
||||
{
|
||||
auto func = [=](const std::vector<Base::Vector3f>& points,
|
||||
const std::vector<Base::Vector3f>& normal) -> MeshCore::AbstractSurfaceFit* {
|
||||
Q_UNUSED(normal)
|
||||
|
||||
MeshCore::PlaneFit fit;
|
||||
fit.AddPoints(points);
|
||||
if (fit.Fit() < FLOAT_MAX) {
|
||||
Base::Vector3f base = fit.GetBase();
|
||||
Base::Vector3f axis = fit.GetNormal();
|
||||
return new MeshCore::PlaneSurfaceFit(base, axis);
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
};
|
||||
Private::findGeometry(ui->numPln->value(), ui->tolPln->value(), func);
|
||||
}
|
||||
|
||||
void SegmentationManual::on_cylinderDetect_clicked()
|
||||
{
|
||||
auto func = [=](const std::vector<Base::Vector3f>& points,
|
||||
const std::vector<Base::Vector3f>& normal) -> MeshCore::AbstractSurfaceFit* {
|
||||
Q_UNUSED(normal)
|
||||
|
||||
MeshCore::CylinderFit fit;
|
||||
fit.AddPoints(points);
|
||||
if (!normal.empty()) {
|
||||
Base::Vector3f base = fit.GetGravity();
|
||||
Base::Vector3f axis = fit.GetInitialAxisFromNormals(normal);
|
||||
fit.SetInitialValues(base, axis);
|
||||
}
|
||||
if (fit.Fit() < FLOAT_MAX) {
|
||||
Base::Vector3f base = fit.GetBase();
|
||||
Base::Vector3f axis = fit.GetAxis();
|
||||
float radius = fit.GetRadius();
|
||||
return new MeshCore::CylinderSurfaceFit(base, axis, radius);
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
};
|
||||
Private::findGeometry(ui->numCyl->value(), ui->tolCyl->value(), func);
|
||||
}
|
||||
|
||||
void SegmentationManual::on_sphereDetect_clicked()
|
||||
{
|
||||
auto func = [=](const std::vector<Base::Vector3f>& points,
|
||||
const std::vector<Base::Vector3f>& normal) -> MeshCore::AbstractSurfaceFit* {
|
||||
Q_UNUSED(normal)
|
||||
|
||||
MeshCore::SphereFit fit;
|
||||
fit.AddPoints(points);
|
||||
if (fit.Fit() < FLOAT_MAX) {
|
||||
Base::Vector3f base = fit.GetCenter();
|
||||
float radius = fit.GetRadius();
|
||||
return new MeshCore::SphereSurfaceFit(base, radius);
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
};
|
||||
Private::findGeometry(ui->numSph->value(), ui->tolSph->value(), func);
|
||||
}
|
||||
|
||||
void SegmentationManual::createSegment()
|
||||
{
|
||||
Gui::Document* gdoc = Gui::Application::Instance->activeDocument();
|
||||
@@ -138,6 +252,12 @@ void SegmentationManual::createSegment()
|
||||
Mesh::MeshObject* feaMesh = feaSegm->Mesh.startEditing();
|
||||
feaMesh->swap(*segment);
|
||||
feaSegm->Mesh.finishEditing();
|
||||
|
||||
if (ui->checkBoxCutSegm->isChecked()) {
|
||||
Mesh::MeshObject* editmesh = it->Mesh.startEditing();
|
||||
editmesh->deleteFacets(facets);
|
||||
it->Mesh.finishEditing();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -57,10 +57,16 @@ public Q_SLOTS:
|
||||
void on_visibleTriangles_toggled(bool);
|
||||
void on_screenTriangles_toggled(bool);
|
||||
void on_cbSelectComp_toggled(bool);
|
||||
void on_planeDetect_clicked();
|
||||
void on_cylinderDetect_clicked();
|
||||
void on_sphereDetect_clicked();
|
||||
|
||||
protected:
|
||||
void changeEvent(QEvent *e);
|
||||
|
||||
private:
|
||||
class Private;
|
||||
|
||||
private:
|
||||
std::unique_ptr<Ui_SegmentationManual> ui;
|
||||
MeshGui::MeshSelection meshSel;
|
||||
|
||||
@@ -7,13 +7,13 @@
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>346</width>
|
||||
<height>314</height>
|
||||
<height>804</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Manual segmentation</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_2">
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="0" column="0">
|
||||
<widget class="QGroupBox" name="groupBox">
|
||||
<property name="title">
|
||||
@@ -117,11 +117,170 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QGroupBox" name="groupBoxPln">
|
||||
<property name="title">
|
||||
<string>Plane</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayoutPln">
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>Tolerance</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QDoubleSpinBox" name="tolPln">
|
||||
<property name="decimals">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<double>0.010000000000000</double>
|
||||
</property>
|
||||
<property name="value">
|
||||
<double>0.010000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="text">
|
||||
<string>Minimum number of faces</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QSpinBox" name="numPln">
|
||||
<property name="maximum">
|
||||
<number>100000</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>100</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QPushButton" name="planeDetect">
|
||||
<property name="text">
|
||||
<string>Detect</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QGroupBox" name="groupBoxCyl">
|
||||
<property name="title">
|
||||
<string>Cylinder</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayoutCyl">
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="text">
|
||||
<string>Tolerance</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QDoubleSpinBox" name="tolCyl">
|
||||
<property name="decimals">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<double>0.010000000000000</double>
|
||||
</property>
|
||||
<property name="value">
|
||||
<double>0.010000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_5">
|
||||
<property name="text">
|
||||
<string>Minimum number of faces</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QSpinBox" name="numCyl">
|
||||
<property name="maximum">
|
||||
<number>100000</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>100</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QPushButton" name="cylinderDetect">
|
||||
<property name="text">
|
||||
<string>Detect</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QGroupBox" name="groupBoxSph">
|
||||
<property name="title">
|
||||
<string>Sphere</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayoutSph">
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_7">
|
||||
<property name="text">
|
||||
<string>Tolerance</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QDoubleSpinBox" name="tolSph">
|
||||
<property name="decimals">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<double>0.010000000000000</double>
|
||||
</property>
|
||||
<property name="value">
|
||||
<double>0.010000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_8">
|
||||
<property name="text">
|
||||
<string>Minimum number of faces</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QSpinBox" name="numSph">
|
||||
<property name="maximum">
|
||||
<number>100000</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>100</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QPushButton" name="sphereDetect">
|
||||
<property name="text">
|
||||
<string>Detect</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QGroupBox" name="groupBox_3">
|
||||
<property name="title">
|
||||
<string>Region options</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_3">
|
||||
<layout class="QGridLayout" name="gridLayoutReg">
|
||||
<item row="0" column="0">
|
||||
<widget class="QCheckBox" name="visibleTriangles">
|
||||
<property name="text">
|
||||
@@ -145,6 +304,22 @@
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0">
|
||||
<widget class="QGroupBox" name="groupBoxSegm">
|
||||
<property name="title">
|
||||
<string>Segmentation</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayoutSegm">
|
||||
<item row="0" column="0">
|
||||
<widget class="QCheckBox" name="checkBoxCutSegm">
|
||||
<property name="text">
|
||||
<string>Cut segment from mesh</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<tabstops>
|
||||
|
||||
Reference in New Issue
Block a user