Merge pull request #5621 from sloriot/Demo-polylines_in_offset_meshing

Add support for protecting features in offset meshing
This commit is contained in:
Sebastien Loriot 2021-04-21 15:31:36 +02:00 committed by GitHub
commit 4f3c2b7ee4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 204 additions and 115 deletions

View File

@ -36,7 +36,8 @@ if(NOT CGAL_DISABLE_GMP)
polyhedron_demo_plugin(offset_meshing_plugin Offset_meshing_plugin polyhedron_demo_plugin(offset_meshing_plugin Offset_meshing_plugin
${remeshingUI_FILES}) ${remeshingUI_FILES})
target_link_libraries(offset_meshing_plugin PUBLIC scene_surface_mesh_item target_link_libraries(offset_meshing_plugin PUBLIC scene_surface_mesh_item
scene_polygon_soup_item) scene_polygon_soup_item
scene_polylines_item)
if(TARGET CGAL::Eigen3_support) if(TARGET CGAL::Eigen3_support)
target_link_libraries(offset_meshing_plugin PUBLIC CGAL::Eigen3_support) target_link_libraries(offset_meshing_plugin PUBLIC CGAL::Eigen3_support)
endif() endif()

View File

@ -12,6 +12,7 @@
#include <QThread> #include <QThread>
#include "Scene_surface_mesh_item.h" #include "Scene_surface_mesh_item.h"
#include "Scene_polygon_soup_item.h" #include "Scene_polygon_soup_item.h"
#include "Scene_polylines_item.h"
#include <QInputDialog> #include <QInputDialog>
#include <QStringList> #include <QStringList>
#include <QMessageBox> #include <QMessageBox>
@ -30,6 +31,7 @@
#include <CGAL/Timer.h> #include <CGAL/Timer.h>
#include <CGAL/make_mesh_3.h> #include <CGAL/make_mesh_3.h>
#include <CGAL/Labeled_mesh_domain_3.h> #include <CGAL/Labeled_mesh_domain_3.h>
#include <CGAL/Mesh_domain_with_polyline_features_3.h>
#include <CGAL/Mesh_criteria_3.h> #include <CGAL/Mesh_criteria_3.h>
#include <CGAL/Three/Three.h> #include <CGAL/Three/Three.h>
@ -250,15 +252,18 @@ public:
// declare the CGAL function // declare the CGAL function
template<class Mesh> template<class Mesh>
SMesh* cgal_off_meshing(QWidget*, SMesh* cgal_off_meshing(QWidget*,
Mesh* tm_ptr, Mesh* tm_ptr,
const double offset_value, Scene_polylines_item* polylines_item,
const double angle, const double offset_value,
const double sizing, const double angle,
const double approx, const double sizing,
int tag) const double approx,
const double edge_size,
int tag)
{ {
typedef EPICK GT; typedef EPICK GT;
typedef CGAL::Labeled_mesh_domain_3<GT, int, int> Mesh_domain; typedef CGAL::Labeled_mesh_domain_3<GT, int, int> Mesh_domain_base;
typedef CGAL::Mesh_domain_with_polyline_features_3<Mesh_domain_base> Mesh_domain;
typedef C3t3::Triangulation Tr; typedef C3t3::Triangulation Tr;
typedef CGAL::Mesh_criteria_3<Tr> Mesh_criteria; typedef CGAL::Mesh_criteria_3<Tr> Mesh_criteria;
typedef GT::Sphere_3 Sphere_3; typedef GT::Sphere_3 Sphere_3;
@ -292,7 +297,20 @@ SMesh* cgal_off_meshing(QWidget*,
Mesh_criteria criteria(p::facet_angle = angle, Mesh_criteria criteria(p::facet_angle = angle,
p::facet_size = sizing, p::facet_size = sizing,
p::facet_distance = approx, p::facet_distance = approx,
p::facet_topology = topology); p::facet_topology = topology,
p::edge_size = edge_size);
if (polylines_item!=nullptr)
{
typedef std::vector<Mesh_domain::Surface_patch_index> Surface_patch_ids;
std::vector<Mesh_domain::Surface_patch_index> surface_patch_ids;
domain.add_features_and_incidences(polylines_item->polylines.begin(),
polylines_item->polylines.end(),
CGAL::Identity_property_map<Scene_polylines_item::Polyline>(),
CGAL::Constant_property_map<Scene_polylines_item::Polyline, Surface_patch_ids>(
surface_patch_ids));
}
C3t3 c3t3 = CGAL::make_mesh_3<C3t3>(domain, criteria, C3t3 c3t3 = CGAL::make_mesh_3<C3t3>(domain, criteria,
p::no_perturb(), p::no_perturb(),
@ -330,40 +348,48 @@ struct Mesher_thread:public QThread{
private: private:
SMesh* sMesh; SMesh* sMesh;
Scene_polygon_soup_item* soup_item; Scene_polygon_soup_item* soup_item;
Scene_polylines_item* polylines_item;
const double offset_value; const double offset_value;
const double angle; const double angle;
const double sizing; const double sizing;
const double approx; const double approx;
const double edge_size;
int tag_index; int tag_index;
public: public:
Mesher_thread( SMesh* tm_ptr, Mesher_thread( SMesh* tm_ptr,
Scene_polygon_soup_item* soup_item, Scene_polygon_soup_item* soup_item,
Scene_polylines_item* polylines_item,
const double offset_value, const double offset_value,
const double angle, const double angle,
const double sizing, const double sizing,
const double approx, const double approx,
const double edge_size,
int tag) int tag)
:sMesh(tm_ptr), soup_item(soup_item), :sMesh(tm_ptr), soup_item(soup_item), polylines_item(polylines_item),
offset_value(offset_value), angle(angle), offset_value(offset_value), angle(angle),
sizing(sizing), approx(approx), tag_index(tag){ sizing(sizing), approx(approx), edge_size(edge_size), tag_index(tag){
} }
void run() override { void run() override {
SMesh* new_mesh= nullptr; SMesh* new_mesh= nullptr;
if(soup_item) if(soup_item)
new_mesh = cgal_off_meshing(CGAL::Three::Three::mainWindow(), new_mesh = cgal_off_meshing(CGAL::Three::Three::mainWindow(),
soup_item, soup_item,
polylines_item,
offset_value, offset_value,
angle, angle,
sizing, sizing,
approx, approx,
edge_size,
tag_index); tag_index);
else else
new_mesh = cgal_off_meshing(CGAL::Three::Three::mainWindow(), new_mesh = cgal_off_meshing(CGAL::Three::Three::mainWindow(),
sMesh, sMesh,
polylines_item,
offset_value, offset_value,
angle, angle,
sizing, sizing,
approx, approx,
edge_size,
tag_index); tag_index);
Q_EMIT resultReady(new_mesh); Q_EMIT resultReady(new_mesh);
} }
@ -399,12 +425,20 @@ public:
} }
} }
bool applicable(QAction* a) const { bool applicable(QAction*) const {
Scene_item* item = scene->item(scene->mainSelectionIndex()); if ( scene->selectionIndices().size() != 1 &&
scene->selectionIndices().size() != 2 )
{
return false;
}
return Q_FOREACH(CGAL::Three::Scene_interface::Item_id index, scene->selectionIndices())
qobject_cast<Scene_surface_mesh_item*>(item) || {
(a == actionOffsetMeshing && qobject_cast<Scene_polygon_soup_item*>(item)); if ( qobject_cast<Scene_surface_mesh_item*>(scene->item(index)) ||
qobject_cast<Scene_polygon_soup_item*>(scene->item(index)) )
return true;
}
return false;
} }
QList<QAction*> actions() const { QList<QAction*> actions() const {
@ -456,12 +490,37 @@ void Polyhedron_demo_offset_meshing_plugin::inflate_mesh()
void Polyhedron_demo_offset_meshing_plugin::offset_meshing() void Polyhedron_demo_offset_meshing_plugin::offset_meshing()
{ {
const CGAL::Three::Scene_interface::Item_id index = scene->mainSelectionIndex(); Scene_surface_mesh_item* sm_item = nullptr;
Scene_item* item = scene->item(index); Scene_polygon_soup_item* soup_item = nullptr;
Scene_surface_mesh_item* sm_item = Scene_polylines_item* polylines_item = nullptr;
qobject_cast<Scene_surface_mesh_item*>(item); Scene_item* item = nullptr;
Scene_polygon_soup_item* soup_item =
qobject_cast<Scene_polygon_soup_item*>(item); bool mesh_or_soup_item_found = false;
Q_FOREACH(CGAL::Three::Scene_interface::Item_id index, scene->selectionIndices())
{
if (!mesh_or_soup_item_found)
{
sm_item = qobject_cast<Scene_surface_mesh_item*>(scene->item(index));
if (sm_item == nullptr)
{
soup_item = qobject_cast<Scene_polygon_soup_item*>(item);
if (soup_item != nullptr)
{
item=scene->item(index);
mesh_or_soup_item_found = true;
continue;
}
}
else
{
item=scene->item(index);
mesh_or_soup_item_found = true;
continue;
}
}
polylines_item = qobject_cast<Scene_polylines_item*>(scene->item(index));
}
SMesh* sMesh = NULL; SMesh* sMesh = NULL;
double diag = 0; double diag = 0;
@ -507,6 +566,14 @@ void Polyhedron_demo_offset_meshing_plugin::offset_meshing()
diag); // max diag); // max
ui.approx->setValue(diag * 0.005); ui.approx->setValue(diag * 0.005);
if (polylines_item!=nullptr)
{
ui.edge_sizing->setRange(diag * 10e-6, // min
diag); // max
ui.edge_sizing->setValue(diag * 0.05); // default value
}
else
ui.edge_sizing->setEnabled(false);
int i = dialog.exec(); int i = dialog.exec();
if(i == QDialog::Rejected) if(i == QDialog::Rejected)
@ -515,6 +582,7 @@ void Polyhedron_demo_offset_meshing_plugin::offset_meshing()
const double angle = ui.angle->value(); const double angle = ui.angle->value();
const double approx = ui.approx->value(); const double approx = ui.approx->value();
const double sizing = ui.sizing->value(); const double sizing = ui.sizing->value();
const double edge_size=polylines_item!=nullptr?ui.edge_sizing->value():0;
const int tag_index = ui.tags->currentIndex(); const int tag_index = ui.tags->currentIndex();
if(tag_index < 0) return; if(tag_index < 0) return;
@ -532,22 +600,26 @@ void Polyhedron_demo_offset_meshing_plugin::offset_meshing()
if(soup_item) if(soup_item)
worker = new Mesher_thread(nullptr, worker = new Mesher_thread(nullptr,
soup_item, soup_item,
polylines_item,
offset_value, offset_value,
angle, angle,
sizing, sizing,
approx, approx,
edge_size,
tag_index); tag_index);
else else
worker = new Mesher_thread(sMesh, worker = new Mesher_thread(sMesh,
nullptr, nullptr,
polylines_item,
offset_value, offset_value,
angle, angle,
sizing, sizing,
approx, approx,
edge_size,
tag_index); tag_index);
connect(worker, &QThread::finished, worker, &QObject::deleteLater); connect(worker, &QThread::finished, worker, &QObject::deleteLater);
connect(worker, &Mesher_thread::resultReady, this, connect(worker, &Mesher_thread::resultReady, this,
[item, angle, sizing, approx, offset_value, index] [item, angle, sizing, approx, offset_value/* , index */]
(SMesh *new_mesh){ (SMesh *new_mesh){
QApplication::restoreOverrideCursor(); QApplication::restoreOverrideCursor();
if(!new_mesh){ if(!new_mesh){
@ -563,7 +635,7 @@ void Polyhedron_demo_offset_meshing_plugin::offset_meshing()
new_item->setColor(Qt::magenta); new_item->setColor(Qt::magenta);
new_item->setWireframeMode(); new_item->setWireframeMode();
CGAL::Three::Three::scene()->addItem(new_item); CGAL::Three::Three::scene()->addItem(new_item);
CGAL::Three::Three::scene()->itemChanged(index); // CGAL::Three::Three::scene()->itemChanged(index);
QApplication::restoreOverrideCursor(); QApplication::restoreOverrideCursor();
}); });

View File

@ -6,102 +6,78 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>344</width> <width>376</width>
<height>169</height> <height>216</height>
</rect> </rect>
</property> </property>
<property name="windowTitle"> <property name="windowTitle">
<string>Meshing criteria</string> <string>Meshing criteria</string>
</property> </property>
<layout class="QVBoxLayout" name="verticalLayout"> <layout class="QGridLayout" name="gridLayout">
<item> <item row="0" column="2" colspan="2">
<layout class="QGridLayout" name="gridLayout" columnstretch="0,0"> <widget class="DoubleEdit" name="angle">
<item row="1" column="1"> <property name="text">
<widget class="DoubleEdit" name="sizing"> <string>25.0</string>
<property name="text"> </property>
<string>0.00</string> </widget>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QComboBox" name="tags">
<item>
<property name="text">
<string>Non manifold</string>
</property>
</item>
<item>
<property name="text">
<string>Manifold</string>
</property>
</item>
<item>
<property name="text">
<string>Manifold with boundaries</string>
</property>
</item>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="angleLabel">
<property name="text">
<string>&amp;Angle:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="sizingLabel">
<property name="text">
<string>&amp;Size:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="approxLabel">
<property name="text">
<string>Approximation &amp;error:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>&amp;Topological criterion:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<property name="buddy">
<cstring>tags</cstring>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="DoubleEdit" name="approx">
<property name="text">
<string>0.00</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="DoubleEdit" name="angle">
<property name="text">
<string>25.0</string>
</property>
</widget>
</item>
</layout>
</item> </item>
<item> <item row="1" column="2" colspan="2">
<widget class="DoubleEdit" name="sizing">
<property name="text">
<string>0.00</string>
</property>
</widget>
</item>
<item row="2" column="0" colspan="2">
<widget class="QLabel" name="approxLabel">
<property name="text">
<string>Approximation &amp;error:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="2" column="2" colspan="2">
<widget class="DoubleEdit" name="approx">
<property name="text">
<string>0.00</string>
</property>
</widget>
</item>
<item row="4" column="0" colspan="2">
<widget class="QLabel" name="label">
<property name="text">
<string>&amp;Topological criterion:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<property name="buddy">
<cstring>tags</cstring>
</property>
</widget>
</item>
<item row="4" column="2" colspan="2">
<widget class="QComboBox" name="tags">
<item>
<property name="text">
<string>Non manifold</string>
</property>
</item>
<item>
<property name="text">
<string>Manifold</string>
</property>
</item>
<item>
<property name="text">
<string>Manifold with boundaries</string>
</property>
</item>
</widget>
</item>
<item row="5" column="2">
<spacer name="verticalSpacer"> <spacer name="verticalSpacer">
<property name="orientation"> <property name="orientation">
<enum>Qt::Vertical</enum> <enum>Qt::Vertical</enum>
@ -114,7 +90,7 @@
</property> </property>
</spacer> </spacer>
</item> </item>
<item> <item row="6" column="3">
<widget class="QDialogButtonBox" name="buttonBox"> <widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation"> <property name="orientation">
<enum>Qt::Horizontal</enum> <enum>Qt::Horizontal</enum>
@ -124,6 +100,46 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="3" column="2" colspan="2">
<widget class="DoubleEdit" name="edge_sizing">
<property name="enabled">
<bool>true</bool>
</property>
<property name="text">
<string>0.00</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QLabel" name="sizingLabel_2">
<property name="text">
<string>&amp;Edge size:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLabel" name="sizingLabel">
<property name="text">
<string>&amp;Size:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLabel" name="angleLabel">
<property name="text">
<string>&amp;Angle:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
</layout> </layout>
</widget> </widget>
<customwidgets> <customwidgets>