Skip to content

Commit

Permalink
ReverseEngineering: improve manual segmentation
Browse files Browse the repository at this point in the history
  • Loading branch information
wwmayer committed May 8, 2020
1 parent 916a423 commit 00ba1c4
Show file tree
Hide file tree
Showing 3 changed files with 304 additions and 3 deletions.
120 changes: 120 additions & 0 deletions src/Mod/ReverseEngineering/Gui/SegmentationManual.cpp
Expand Up @@ -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;

Expand Down Expand Up @@ -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();
Expand Down Expand Up @@ -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();
}
}
}

Expand Down
6 changes: 6 additions & 0 deletions src/Mod/ReverseEngineering/Gui/SegmentationManual.h
Expand Up @@ -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;
Expand Down
181 changes: 178 additions & 3 deletions src/Mod/ReverseEngineering/Gui/SegmentationManual.ui
Expand Up @@ -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">
Expand Down Expand Up @@ -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">
Expand All @@ -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>
Expand Down

0 comments on commit 00ba1c4

Please sign in to comment.