mirror of https://github.com/CGAL/cgal
Merge branch 'gsoc2023' into master
This commit is contained in:
commit
619875392c
|
|
@ -2370,6 +2370,48 @@ location = {Salt Lake City, Utah, USA}
|
|||
,update = "98.01 kettner"
|
||||
}
|
||||
|
||||
@article{cgal:vc-acvdupmc-04,
|
||||
author = {Valette, Sébastien and Chassery, Jean-Marc},
|
||||
doi = {10.1111/j.1467-8659.2004.00769.x},
|
||||
hal_id = {hal-00534535},
|
||||
hal_version = {v1},
|
||||
journal = {Computer Graphics Forum},
|
||||
note = {Eurographics 2004 proceedings},
|
||||
number = {3},
|
||||
pages = {381-389},
|
||||
pdf = {https://hal.archives-ouvertes.fr/hal-00534535/file/valette.pdf},
|
||||
publisher = {Wiley},
|
||||
title = {Approximated Centroidal Voronoi Diagrams for Uniform Polygonal Mesh Coarsening},
|
||||
url = {https://hal.archives-ouvertes.fr/hal-00534535},
|
||||
volume = {23},
|
||||
year = {2004}
|
||||
}
|
||||
|
||||
@inproceedings{cgal:vkc-apmsdcvd-05,
|
||||
address = {Tozeur, Tunisia},
|
||||
author = {Valette, Sébastien and Kompatsiaris, I. and Chassery, J.M.},
|
||||
booktitle = {Proceedings of 2nd International Conference on Machine Intelligence ICMI 2005},
|
||||
month = {November},
|
||||
pages = {655-662},
|
||||
title = {Adaptive Polygonal Mesh Simplification With Discrete Centroidal Voronoi Diagrams},
|
||||
year = {2005}
|
||||
}
|
||||
|
||||
@article{cgal:vcp-grtmmdvd-08,
|
||||
author = {Valette, Sébastien and Chassery, Jean-Marc and Prost, Rémy},
|
||||
doi = {10.1109/TVCG.2007.70430},
|
||||
hal_id = {hal-00537025},
|
||||
hal_version = {v1},
|
||||
journal = {IEEE Transactions on Visualization and Computer Graphics},
|
||||
number = {2},
|
||||
pages = {369--381},
|
||||
pdf = {https://hal.archives-ouvertes.fr/hal-00537025/file/VCP08TVCG.pdf},
|
||||
publisher = {Institute of Electrical and Electronics Engineers},
|
||||
title = {Generic remeshing of 3D triangular meshes with metric-dependent discrete Voronoi Diagrams},
|
||||
url = {https://hal.archives-ouvertes.fr/hal-00537025},
|
||||
volume = {14},
|
||||
year = {2008}
|
||||
}
|
||||
|
||||
@techreport{cgal:vla-lod-15,
|
||||
title={LOD Generation for Urban Scenes},
|
||||
|
|
|
|||
|
|
@ -0,0 +1,54 @@
|
|||
// Copyright (c) 2016 GeometryFactory SARL (France).
|
||||
// All rights reserved.
|
||||
//
|
||||
// This file is part of CGAL (www.cgal.org)
|
||||
//
|
||||
// $URL$
|
||||
// $Id$
|
||||
// SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial
|
||||
//
|
||||
// Author(s) : Andreas Fabri
|
||||
//
|
||||
// Warning: this file is generated, see include/CGAL/license/README.md
|
||||
|
||||
#ifndef CGAL_LICENSE_POLYGON_MESH_PROCESSING_ACVD_H
|
||||
#define CGAL_LICENSE_POLYGON_MESH_PROCESSING_ACVD_H
|
||||
|
||||
#include <CGAL/config.h>
|
||||
#include <CGAL/license.h>
|
||||
|
||||
#ifdef CGAL_POLYGON_MESH_PROCESSING_ACVD_COMMERCIAL_LICENSE
|
||||
|
||||
# if CGAL_POLYGON_MESH_PROCESSING_ACVD_COMMERCIAL_LICENSE < CGAL_RELEASE_DATE
|
||||
|
||||
# if defined(CGAL_LICENSE_WARNING)
|
||||
|
||||
CGAL_pragma_warning("Your commercial license for CGAL does not cover "
|
||||
"this release of the Polygon Mesh Processing - ACVD remeshing package.")
|
||||
# endif
|
||||
|
||||
# ifdef CGAL_LICENSE_ERROR
|
||||
# error "Your commercial license for CGAL does not cover this release \
|
||||
of the Polygon Mesh Processing - ACVD remeshing package. \
|
||||
You get this error, as you defined CGAL_LICENSE_ERROR."
|
||||
# endif // CGAL_LICENSE_ERROR
|
||||
|
||||
# endif // CGAL_POLYGON_MESH_PROCESSING_ACVD_COMMERCIAL_LICENSE < CGAL_RELEASE_DATE
|
||||
|
||||
#else // no CGAL_POLYGON_MESH_PROCESSING_ACVD_COMMERCIAL_LICENSE
|
||||
|
||||
# if defined(CGAL_LICENSE_WARNING)
|
||||
CGAL_pragma_warning("\nThe macro CGAL_POLYGON_MESH_PROCESSING_ACVD_COMMERCIAL_LICENSE is not defined."
|
||||
"\nYou use the CGAL Polygon Mesh Processing - ACVD remeshing package under "
|
||||
"the terms of the GPLv3+.")
|
||||
# endif // CGAL_LICENSE_WARNING
|
||||
|
||||
# ifdef CGAL_LICENSE_ERROR
|
||||
# error "The macro CGAL_POLYGON_MESH_PROCESSING_ACVD_COMMERCIAL_LICENSE is not defined.\
|
||||
You use the CGAL Polygon Mesh Processing - ACVD remeshing package under the terms of \
|
||||
the GPLv3+. You get this error, as you defined CGAL_LICENSE_ERROR."
|
||||
# endif // CGAL_LICENSE_ERROR
|
||||
|
||||
#endif // no CGAL_POLYGON_MESH_PROCESSING_ACVD_COMMERCIAL_LICENSE
|
||||
|
||||
#endif // CGAL_LICENSE_POLYGON_MESH_PROCESSING_ACVD_H
|
||||
|
|
@ -67,6 +67,7 @@ Polygon_mesh_processing/miscellaneous Polygon Mesh Processing - Miscellaneous
|
|||
Polygon_mesh_processing/detect_features Polygon Mesh Processing - Feature Detection
|
||||
Polygon_mesh_processing/collision_detection Polygon Mesh Processing - Collision Detection
|
||||
Polygon_mesh_processing/autorefinement Polygon Mesh Processing - Autorefinement
|
||||
Polygon_mesh_processing/acvd Polygon Mesh Processing - ACVD remeshing
|
||||
Polyhedron 3D Polyhedral Surface
|
||||
Polyline_simplification_2 2D Polyline Simplification
|
||||
Polytope_distance_d Optimal Distances
|
||||
|
|
|
|||
|
|
@ -0,0 +1,128 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>ACVDDialog</class>
|
||||
<widget class="QDialog" name="ACVDDialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>400</width>
|
||||
<height>241</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>ACVD Remeshing</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="text">
|
||||
<string>Target number of Vertices (Clusters):</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="DoubleEdit" name="nb_clusters_spin_box">
|
||||
<property name="value" stdset="0">
|
||||
<number>100</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>Cluster Metric:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QRadioButton" name="IsotropicClustering">
|
||||
<property name="text">
|
||||
<string>Isotropic Clustering</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<attribute name="buttonGroup">
|
||||
<string notr="true">buttonGroup</string>
|
||||
</attribute>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QRadioButton" name="QEMClustering">
|
||||
<property name="text">
|
||||
<string>QEM Clustering</string>
|
||||
</property>
|
||||
<attribute name="buttonGroup">
|
||||
<string notr="true">buttonGroup</string>
|
||||
</attribute>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QRadioButton" name="AnisotropicClustering">
|
||||
<property name="text">
|
||||
<string>Anisotropic Clustering</string>
|
||||
</property>
|
||||
<attribute name="buttonGroup">
|
||||
<string notr="true">buttonGroup</string>
|
||||
</attribute>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>DoubleEdit</class>
|
||||
<extends>QLineEdit</extends>
|
||||
<header>CGAL_double_edit.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>accepted()</signal>
|
||||
<receiver>ACVDDialog</receiver>
|
||||
<slot>accept()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>248</x>
|
||||
<y>254</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>157</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>rejected()</signal>
|
||||
<receiver>ACVDDialog</receiver>
|
||||
<slot>reject()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>316</x>
|
||||
<y>260</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>286</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
<buttongroups>
|
||||
<buttongroup name="buttonGroup"/>
|
||||
</buttongroups>
|
||||
</ui>
|
||||
|
|
@ -0,0 +1,125 @@
|
|||
#include <QtCore/qglobal.h>
|
||||
|
||||
#include "Messages_interface.h"
|
||||
#include <CGAL/Three/CGAL_Lab_plugin_helper.h>
|
||||
#include <CGAL/Three/Three.h>
|
||||
#include "Scene_polyhedron_selection_item.h"
|
||||
#include "ui_ACVD_remeshing_dialog.h"
|
||||
|
||||
#include "SMesh_type.h"
|
||||
typedef Scene_surface_mesh_item Scene_facegraph_item;
|
||||
|
||||
#include <CGAL/iterator.h>
|
||||
#include <CGAL/Polygon_mesh_processing/acvd/acvd.h>
|
||||
|
||||
#include <QElapsedTimer>
|
||||
#include <QRadioButton>
|
||||
#include <QCheckBox>
|
||||
#include <QAction>
|
||||
#include <QMainWindow>
|
||||
#include <QApplication>
|
||||
#include <QDockWidget>
|
||||
#include <QEvent>
|
||||
#include <QKeyEvent>
|
||||
#include <QMouseEvent>
|
||||
#include <QFileDialog>
|
||||
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
#include <queue>
|
||||
|
||||
typedef Scene_facegraph_item::Face_graph FaceGraph;
|
||||
|
||||
using namespace CGAL::Three;
|
||||
namespace PMP = CGAL::Polygon_mesh_processing;
|
||||
|
||||
class CGAL_Lab_acvd_remeshing_plugin :
|
||||
public QObject,
|
||||
public CGAL_Lab_plugin_helper
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_INTERFACES(CGAL::Three::CGAL_Lab_plugin_interface)
|
||||
Q_PLUGIN_METADATA(IID "com.geometryfactory.PolyhedronDemo.PluginInterface/1.0" FILE "acvd_remeshing_plugin.json")
|
||||
public:
|
||||
bool applicable(QAction*) const {
|
||||
return qobject_cast<Scene_facegraph_item*>(scene->item(scene->mainSelectionIndex()));
|
||||
}
|
||||
void print_message(QString message) { CGAL::Three::Three::information(message);}
|
||||
QList<QAction*> actions() const { return QList<QAction*>() << actionACVD; }
|
||||
|
||||
|
||||
void init(QMainWindow* mainWindow, CGAL::Three::Scene_interface* scene_interface, Messages_interface*) {
|
||||
mw = mainWindow;
|
||||
scene = scene_interface;
|
||||
actionACVD = new QAction(tr(
|
||||
"ACVD Remeshing"
|
||||
), mw);
|
||||
//actionACVD->setProperty("subMenuName", "");
|
||||
if (actionACVD)
|
||||
connect(actionACVD, SIGNAL(triggered()), this, SLOT(acvd_action()));
|
||||
}
|
||||
|
||||
public Q_SLOTS:
|
||||
void acvd_action() {
|
||||
|
||||
// Create dialog box
|
||||
QDialog dialog(mw);
|
||||
ui.setupUi(&dialog);
|
||||
|
||||
ui.nb_clusters_spin_box->setMinimum(10);
|
||||
ui.nb_clusters_spin_box->setMaximum(1000000);
|
||||
// get number of vertices of the mesh
|
||||
Scene_facegraph_item* item = getSelectedItem<Scene_facegraph_item>();
|
||||
if(!item) { return; }
|
||||
// set default number of clusters to 5% of the number of vertices
|
||||
ui.nb_clusters_spin_box->setValue(max(item->face_graph()->number_of_faces() / 20, (unsigned int)10));
|
||||
|
||||
int i = dialog.exec();
|
||||
if (i == QDialog::Rejected)
|
||||
{
|
||||
std::cout << "Remeshing aborted" << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
Face_graph* graph = item->face_graph();
|
||||
if(!graph) return;
|
||||
QElapsedTimer time;
|
||||
time.start();
|
||||
CGAL::Three::Three::information("ACVD Remeshing...");
|
||||
|
||||
|
||||
QApplication::setOverrideCursor(Qt::WaitCursor);
|
||||
FaceGraph remeshed;
|
||||
|
||||
// TODO add post-processing
|
||||
|
||||
if (ui.IsotropicClustering->isChecked())
|
||||
remeshed = PMP::acvd_isotropic_remeshing(*graph, ui.nb_clusters_spin_box->value());
|
||||
else if (ui.QEMClustering->isChecked())
|
||||
remeshed = PMP::acvd_isotropic_remeshing(*graph, ui.nb_clusters_spin_box->value(), CGAL::parameters::post_processing_qem(true)); // make it its own option once acvd_qem_remeshing works
|
||||
// remeshed = PMP::acvd_qem_remeshing(*graph, ui.nb_clusters_spin_box->value());
|
||||
else
|
||||
remeshed = PMP::acvd_isotropic_remeshing(*graph, ui.nb_clusters_spin_box->value(), CGAL::parameters::gradation_factor(0.8));
|
||||
|
||||
// update the scene
|
||||
CGAL::Three::Three::information(QString("ok (%1 ms)").arg(time.elapsed()));
|
||||
QApplication::restoreOverrideCursor();
|
||||
item->invalidateOpenGLBuffers();
|
||||
|
||||
// add the simplified mesh to the scene
|
||||
Scene_facegraph_item* remeshed_item = new Scene_facegraph_item(remeshed);
|
||||
remeshed_item->setName(QString(item->name() + "_simplified"));
|
||||
scene->addItem(remeshed_item);
|
||||
remeshed_item->invalidateOpenGLBuffers();
|
||||
scene->itemChanged(remeshed_item);
|
||||
item->setVisible(false);
|
||||
}
|
||||
|
||||
private:
|
||||
QAction* actionACVD;
|
||||
Ui::ACVDDialog ui;
|
||||
}; // end CGAL_Lab_acvd_remeshing_plugin
|
||||
|
||||
|
||||
#include "ACVD_remeshing_plugin.moc"
|
||||
|
|
@ -29,6 +29,11 @@ target_link_libraries(extrude_plugin PUBLIC scene_surface_mesh_item
|
|||
|
||||
if(TARGET CGAL::Eigen3_support)
|
||||
if("${EIGEN3_VERSION}" VERSION_GREATER "3.1.90")
|
||||
|
||||
qt6_wrap_ui( acvd_remeshingUI_FILES ACVD_remeshing_dialog.ui)
|
||||
cgal_lab_plugin(acvd_remeshing_plugin ACVD_remeshing_plugin ${acvd_remeshingUI_FILES} KEYWORDS PMP)
|
||||
target_link_libraries(acvd_remeshing_plugin PUBLIC scene_surface_mesh_item scene_points_with_normal_item scene_polygon_soup_item CGAL::Eigen3_support)
|
||||
|
||||
qt6_wrap_ui( hole_fillingUI_FILES Hole_filling_widget.ui)
|
||||
cgal_lab_plugin(hole_filling_plugin Hole_filling_plugin ${hole_fillingUI_FILES} KEYWORDS PMP)
|
||||
target_link_libraries(hole_filling_plugin PUBLIC scene_surface_mesh_item scene_polylines_item scene_selection_item CGAL::Eigen3_support)
|
||||
|
|
|
|||
|
|
@ -37,14 +37,17 @@ public:
|
|||
messages = m;
|
||||
scene = scene_interface;
|
||||
QAction *actionLoop = new QAction("Loop", mw);
|
||||
QAction *actionUpsample = new QAction("Upsample", mw);
|
||||
QAction *actionCatmullClark = new QAction("Catmull Clark", mw);
|
||||
QAction *actionSqrt3 = new QAction("Sqrt3", mw);
|
||||
QAction *actionDooSabin = new QAction("Doo Sabin", mw);
|
||||
actionLoop->setObjectName("actionLoop");
|
||||
actionUpsample->setObjectName("actionUpsample");
|
||||
actionCatmullClark->setObjectName("actionCatmullClark");
|
||||
actionSqrt3->setObjectName("actionSqrt3");
|
||||
actionDooSabin->setObjectName("actionDooSabin");
|
||||
_actions << actionLoop
|
||||
<< actionUpsample
|
||||
<< actionCatmullClark
|
||||
<< actionSqrt3
|
||||
<< actionDooSabin;
|
||||
|
|
@ -60,6 +63,7 @@ public:
|
|||
|
||||
public Q_SLOTS:
|
||||
void on_actionLoop_triggered();
|
||||
void on_actionUpsample_triggered();
|
||||
void on_actionCatmullClark_triggered();
|
||||
void on_actionSqrt3_triggered();
|
||||
void on_actionDooSabin_triggered();
|
||||
|
|
@ -69,6 +73,8 @@ private :
|
|||
template<class FaceGraphItem>
|
||||
void apply_loop(FaceGraphItem* item, int nb_steps);
|
||||
template<class FaceGraphItem>
|
||||
void apply_upsample(FaceGraphItem* item, int nb_steps);
|
||||
template<class FaceGraphItem>
|
||||
void apply_catmullclark(FaceGraphItem* item, int nb_steps);
|
||||
template<class FaceGraphItem>
|
||||
void apply_sqrt3(FaceGraphItem* item, int nb_steps);
|
||||
|
|
@ -92,6 +98,22 @@ void CGAL_Lab_subdivision_methods_plugin::apply_loop(FaceGraphItem* item, int nb
|
|||
scene->itemChanged(item);
|
||||
}
|
||||
|
||||
template<class FaceGraphItem>
|
||||
void CGAL_Lab_subdivision_methods_plugin::apply_upsample(FaceGraphItem* item, int nb_steps)
|
||||
{
|
||||
typename FaceGraphItem::Face_graph* graph = item->face_graph();
|
||||
if(!graph) return;
|
||||
QElapsedTimer time;
|
||||
time.start();
|
||||
CGAL::Three::Three::information("Upsample subdivision...");
|
||||
QApplication::setOverrideCursor(Qt::WaitCursor);
|
||||
CGAL::Subdivision_method_3::Upsample_subdivision(*graph, params::number_of_iterations(nb_steps));
|
||||
CGAL::Three::Three::information(QString("ok (%1 ms)").arg(time.elapsed()));
|
||||
QApplication::restoreOverrideCursor();
|
||||
item->invalidateOpenGLBuffers();
|
||||
scene->itemChanged(item);
|
||||
}
|
||||
|
||||
void CGAL_Lab_subdivision_methods_plugin::on_actionLoop_triggered()
|
||||
{
|
||||
CGAL::Three::Scene_interface::Item_id index = scene->mainSelectionIndex();
|
||||
|
|
@ -111,6 +133,25 @@ void CGAL_Lab_subdivision_methods_plugin::on_actionLoop_triggered()
|
|||
apply_loop(sm_item, nb_steps);
|
||||
}
|
||||
|
||||
void CGAL_Lab_subdivision_methods_plugin::on_actionUpsample_triggered()
|
||||
{
|
||||
CGAL::Three::Scene_interface::Item_id index = scene->mainSelectionIndex();
|
||||
Scene_surface_mesh_item* sm_item = qobject_cast<Scene_surface_mesh_item*>(scene->item(index));
|
||||
if(!sm_item)
|
||||
return;
|
||||
|
||||
bool ok = true;
|
||||
int nb_steps = QInputDialog::getInt(mw,
|
||||
QString("Number of Iterations"),
|
||||
QString("Choose number of iterations"),
|
||||
1 /* value */, 1 /* min */, (std::numeric_limits<int>::max)() /* max */, 1 /*step*/,
|
||||
&ok);
|
||||
if(!ok)
|
||||
return;
|
||||
|
||||
apply_upsample(sm_item, nb_steps);
|
||||
}
|
||||
|
||||
template<class FaceGraphItem>
|
||||
void CGAL_Lab_subdivision_methods_plugin::apply_catmullclark(FaceGraphItem* item, int nb_steps)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -12,6 +12,10 @@
|
|||
/// Functions to fill holes given as a range of halfedges or as range of points.
|
||||
/// \ingroup PkgPolygonMeshProcessingRef
|
||||
|
||||
/// \defgroup PMP_acvd_grp ACVD Simplification
|
||||
/// Functions to simplify and remesh triangle meshes based on Approximated Centroidal Voronoi Diagrams (ACVD) with a variety of metrics.
|
||||
/// \ingroup PkgPolygonMeshProcessingRef
|
||||
|
||||
/// \defgroup PMP_meshing_grp Meshing
|
||||
/// Functions to triangulate faces, and to refine and fair regions of a polygon mesh.
|
||||
/// \ingroup PkgPolygonMeshProcessingRef
|
||||
|
|
@ -79,7 +83,7 @@
|
|||
\cgalPkgPicture{hole_filling_ico.png}
|
||||
|
||||
\cgalPkgSummaryBegin
|
||||
\cgalPkgAuthors{David Coeurjolly, Jaques-Olivier Lachaud, Konstantinos Katrioplas, Sébastien Loriot, Ivan Pađen, Mael Rouxel-Labbé, Hossam Saeed, Jane Tournois, and Ilker %O. Yaz}
|
||||
\cgalPkgAuthors{David Coeurjolly, Jaques-Olivier Lachaud, Konstantinos Katrioplas, Sébastien Loriot, Ivan Pađen, Mael Rouxel-Labbé, Hossam Saeed, Jane Tournois, Sébastien Valette, and Ilker %O. Yaz}
|
||||
\cgalPkgDesc{This package provides a collection of methods and classes for polygon mesh processing,
|
||||
ranging from basic operations on simplices, to complex geometry processing algorithms such as
|
||||
Boolean operations, remeshing, repairing, collision and intersection detection, and more.}
|
||||
|
|
@ -134,6 +138,9 @@ The page \ref bgl_namedparameters "Named Parameters" describes their usage.
|
|||
- `CGAL::Polygon_mesh_processing::smooth_shape()`
|
||||
- `CGAL::Polygon_mesh_processing::random_perturbation()`
|
||||
|
||||
\cgalCRPSection{ACVD Simplification Functions}
|
||||
- \link PMP_acvd_grp `CGAL::Polygon_mesh_processing::acvd_isotropic_remeshing()` \endlink
|
||||
|
||||
\cgalCRPSection{Sizing Fields}
|
||||
- `CGAL::Polygon_mesh_processing::Uniform_sizing_field`
|
||||
- `CGAL::Polygon_mesh_processing::Adaptive_sizing_field`
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ namespace CGAL {
|
|||
\anchor Chapter_PolygonMeshProcessing
|
||||
|
||||
\cgalAutoToc
|
||||
\authors David Coeurjolly, Jaques-Olivier Lachaud, Konstantinos Katrioplas, Sébastien Loriot, Ivan Pađen, Mael Rouxel-Labbé, Hossam Saeed, Jane Tournois, and Ilker %O. Yaz
|
||||
\authors David Coeurjolly, Jaques-Olivier Lachaud, Konstantinos Katrioplas, Sébastien Loriot, Ivan Pađen, Mael Rouxel-Labbé, Hossam Saeed, Jane Tournois, Sébastien Valette, and Ilker %O. Yaz
|
||||
|
||||
\image html neptun_head.jpg
|
||||
\image latex neptun_head.jpg
|
||||
|
|
@ -53,6 +53,8 @@ mesh, which includes point location and self intersection tests.
|
|||
- \ref PMPSlicer : functor able to compute the intersections of a polygon mesh with arbitrary planes (slicer).
|
||||
- \ref PMPConnectedComponents : methods to deal with connected
|
||||
components of a polygon mesh (extraction, marks, removal, ...).
|
||||
- \ref PMPACVD : methods to remesh a polygon mesh using approximated centroidal Voronoi diagrams
|
||||
as described in \cgalCite{cgal:vcp-grtmmdvd-08} and preceeding work.
|
||||
|
||||
\subsection PMPIO Reading and Writing Polygon Meshes
|
||||
|
||||
|
|
@ -1311,6 +1313,46 @@ which enables to treat one or several connected components as a face graph.
|
|||
|
||||
\cgalExample{Polygon_mesh_processing/face_filtered_graph_example.cpp}
|
||||
|
||||
\section PMPACVD ACVD Remeshing
|
||||
|
||||
The Approximated Centroidal Voronoi Diagram (ACVD) package is a set of vertex-clustering-based tools to
|
||||
remesh a triangle mesh. It is based on the method introduced in \cgalCite{cgal:vc-acvdupmc-04} and extended
|
||||
in \cgalCite{cgal:vkc-apmsdcvd-05} and \cgalCite{cgal:vcp-grtmmdvd-08}.
|
||||
|
||||
\subsection ACVDBackground Brief Background
|
||||
|
||||
WIP
|
||||
|
||||
\subsection ACVDAPI API
|
||||
|
||||
The implementation is generic in terms of mesh data structure. It can be used on `Surface_mesh`, `Polyhedron_3` and
|
||||
other triangle mesh structures based on the concept `FaceGraph`.
|
||||
|
||||
The main function is `CGAL::Polygon_mesh_processing::acvd_isotropic_remeshing()`. It takes as input a triangle mesh and
|
||||
a lower bound on the target number of vertices and returns a remeshed version. The number of vertices in the output mesh
|
||||
might be larger than the input parameters if the input is not closed or if the budget of points provided is too low
|
||||
to generate a manifold output mesh. Note that providing a initial low number of vertices will affect the uniformity
|
||||
of the output triangles in case some extra points are added to make the output manifold.
|
||||
|
||||
To enable Adaptive Remeshing, the named parameter `gradation_factor` can be used. It controls the sensitivity of the
|
||||
clustering algorithm to curvature. Moreover, the named parameter
|
||||
`vertex_principal_curvatures_and_directions_map` can be used to provide a user-defined principal curvature map.
|
||||
|
||||
For Clustering based on QEM, the function `CGAL::Polygon_mesh_processing::acvd_qem_simplification()` and
|
||||
`CGAL::Polygon_mesh_processing::acvd_qem_simplification_polygon_soup()` can be used. THIS IS NOT 100% WORKING YET.
|
||||
|
||||
|
||||
\subsection ACVDResults Results
|
||||
|
||||
WIP
|
||||
|
||||
\subsection ACVDExample Usage Example
|
||||
|
||||
The example below shows the usage of the `CGAL::Polygon_mesh_processing::acvd_isotropic_remeshing()` function
|
||||
and how the extra named parameters can be passed.
|
||||
|
||||
\cgalExample{Polygon_mesh_processing/acvd_example.cpp}
|
||||
|
||||
\section PMPDistance Hausdorff Distance
|
||||
|
||||
This package provides methods to compute (approximate) distances between meshes and point sets.
|
||||
|
|
@ -1441,5 +1483,10 @@ used as a reference during the project.
|
|||
|
||||
The curvature-based sizing field version of isotropic remeshing was added by Ivan Pađen during GSoC 2023, under the supervision of Sébastien Loriot and Jane Tournois.
|
||||
|
||||
The ACVD Simplification and Remeshing methods were implemented during GSoC 2023. This was implemented by Hossam Saeed and under
|
||||
supervision of Sébastien Valette and Sébastien Loriot. The implementation is based on \cgalCite{cgal:vcp-grtmmdvd-08}. and
|
||||
preceeding work. <a href="https://www.creatis.insa-lyon.fr/~valette/public/project/acvd/">ACVD's implementation</a> was also
|
||||
used as a reference during the project.
|
||||
|
||||
*/
|
||||
} /* namespace CGAL */
|
||||
|
|
|
|||
|
|
@ -46,6 +46,7 @@
|
|||
\example Polygon_mesh_processing/cc_compatible_orientations.cpp
|
||||
\example Polygon_mesh_processing/remesh_planar_patches.cpp
|
||||
\example Polygon_mesh_processing/remesh_almost_planar_patches.cpp
|
||||
\example Polygon_mesh_processing/acvd_example.cpp
|
||||
\example Polygon_mesh_processing/sample_example.cpp
|
||||
\example Polygon_mesh_processing/soup_autorefinement.cpp
|
||||
\example Polygon_mesh_processing/isotropic_remeshing_with_allow_move.cpp
|
||||
|
|
|
|||
|
|
@ -59,9 +59,12 @@ create_single_source_cgal_program("isotropic_remeshing_with_allow_move.cpp")
|
|||
create_single_source_cgal_program("triangle_mesh_autorefinement.cpp")
|
||||
create_single_source_cgal_program("soup_autorefinement.cpp")
|
||||
|
||||
|
||||
find_package(Eigen3 3.2.0 QUIET) #(requires 3.2.0 or greater)
|
||||
include(CGAL_Eigen3_support)
|
||||
if(TARGET CGAL::Eigen3_support)
|
||||
create_single_source_cgal_program("acvd_example.cpp")
|
||||
target_link_libraries(acvd_example PUBLIC CGAL::Eigen3_support)
|
||||
create_single_source_cgal_program("hole_filling_example.cpp")
|
||||
target_link_libraries(hole_filling_example PUBLIC CGAL::Eigen3_support)
|
||||
create_single_source_cgal_program("hole_filling_example_SM.cpp")
|
||||
|
|
|
|||
|
|
@ -0,0 +1,94 @@
|
|||
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
|
||||
#include <CGAL/Polygon_mesh_processing/acvd/acvd.h>
|
||||
#include <CGAL/Polygon_mesh_processing/IO/polygon_mesh_io.h>
|
||||
#include <CGAL/Surface_mesh.h>
|
||||
#include <CGAL/property_map.h>
|
||||
#include <CGAL/Polygon_mesh_processing/interpolated_corrected_curvatures.h>
|
||||
|
||||
#include <boost/graph/graph_traits.hpp>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
namespace PMP = CGAL::Polygon_mesh_processing;
|
||||
|
||||
typedef CGAL::Exact_predicates_inexact_constructions_kernel Epic_kernel;
|
||||
typedef CGAL::Surface_mesh<Epic_kernel::Point_3> Surface_Mesh;
|
||||
typedef boost::graph_traits<Surface_Mesh>::vertex_descriptor vertex_descriptor;
|
||||
typedef boost::property_map<Surface_Mesh, CGAL::dynamic_vertex_property_t<CGAL::IO::Color> >::type VertexColorMap;
|
||||
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
Surface_Mesh smesh;
|
||||
const std::string filename = (argc > 1) ?
|
||||
CGAL::data_file_path(argv[1]) :
|
||||
CGAL::data_file_path("meshes/fandisk.off");
|
||||
|
||||
const int nb_clusters = (argc > 2) ? atoi(argv[2]) : 3000;
|
||||
|
||||
if (!CGAL::IO::read_polygon_mesh(filename, smesh))
|
||||
{
|
||||
std::cerr << "Invalid input file." << std::endl;
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
///// Uniform Isotropic ACVD
|
||||
|
||||
//std::cout << "Uniform Isotropic ACVD ...." << std::endl;
|
||||
//auto acvd_mesh = PMP::acvd_isotropic_remeshing(smesh, nb_clusters);
|
||||
//CGAL::IO::write_OFF("fandisk_acvd_3000.off", acvd_mesh);
|
||||
|
||||
//std::cout << "Completed" << std::endl;
|
||||
|
||||
//// With Post-Processing QEM Optimization
|
||||
|
||||
//std::cout << "Uniform Isotropic ACVD with QEM optimization ...." << std::endl;
|
||||
|
||||
//auto acvd_mesh_qem_pp = PMP::acvd_isotropic_remeshing(smesh, nb_clusters, CGAL::parameters::post_processing_qem(true));
|
||||
//CGAL::IO::write_OFF("fandisk_acvd_qem-pp_3000.off", acvd_mesh_qem_pp);
|
||||
|
||||
//std::cout << "Completed" << std::endl;
|
||||
|
||||
// With QEM Energy Minimization
|
||||
|
||||
std::cout << "Uniform QEM ACVD ...." << std::endl;
|
||||
|
||||
auto acvd_mesh_qem = PMP::acvd_qem_remeshing(smesh, nb_clusters);
|
||||
CGAL::IO::write_OFF("fandisk_acvd_qem_3000.off", acvd_mesh_qem);
|
||||
|
||||
std::cout << "Completed" << std::endl;
|
||||
|
||||
/// Adaptive Isotropic ACVD
|
||||
|
||||
/*std::cout << "Adaptive Isotropic ACVD ...." << std::endl;
|
||||
|
||||
const double gradation_factor = (argc > 3) ? atof(argv[3]) : 2;
|
||||
|
||||
bool created = false;
|
||||
Surface_Mesh::Property_map<vertex_descriptor, PMP::Principal_curvatures_and_directions<Epic_kernel>>
|
||||
principal_curvatures_and_directions_map;
|
||||
|
||||
boost::tie(principal_curvatures_and_directions_map, created) =
|
||||
smesh.add_property_map<vertex_descriptor, PMP::Principal_curvatures_and_directions<Epic_kernel>>
|
||||
("v:principal_curvatures_and_directions_map", { 0, 0,
|
||||
Epic_kernel::Vector_3(0,0,0),
|
||||
Epic_kernel::Vector_3(0,0,0) });
|
||||
assert(created);
|
||||
|
||||
PMP::interpolated_corrected_curvatures(smesh, CGAL::parameters::vertex_principal_curvatures_and_directions_map(principal_curvatures_and_directions_map));
|
||||
|
||||
auto adaptive_acvd_mesh =
|
||||
PMP::acvd_isotropic_remeshing(
|
||||
smesh,
|
||||
nb_clusters,
|
||||
CGAL::parameters::vertex_principal_curvatures_and_directions_map(principal_curvatures_and_directions_map)
|
||||
.gradation_factor(gradation_factor)
|
||||
);
|
||||
|
||||
CGAL::IO::write_OFF("fandisk_acvd_adaptive_3000.off", adaptive_acvd_mesh);
|
||||
|
||||
std::cout << "Completed" << std::endl;*/
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -101,6 +101,8 @@ CGAL_add_named_parameter(vertex_mean_curvature_t, vertex_mean_curvature, vertex_
|
|||
CGAL_add_named_parameter(vertex_Gaussian_curvature_t, vertex_Gaussian_curvature, vertex_Gaussian_curvature)
|
||||
CGAL_add_named_parameter(vertex_principal_curvatures_and_directions_t, vertex_principal_curvatures_and_directions, vertex_principal_curvatures_and_directions)
|
||||
CGAL_add_named_parameter(ball_radius_t, ball_radius, ball_radius)
|
||||
CGAL_add_named_parameter(gradation_factor_t, gradation_factor, gradation_factor)
|
||||
CGAL_add_named_parameter(post_processing_qem_t, post_processing_qem, post_processing_qem)
|
||||
CGAL_add_named_parameter(outward_orientation_t, outward_orientation, outward_orientation)
|
||||
CGAL_add_named_parameter(overlap_test_t, overlap_test, do_overlap_test_of_bounded_sides)
|
||||
CGAL_add_named_parameter(preserve_genus_t, preserve_genus, preserve_genus)
|
||||
|
|
@ -165,6 +167,7 @@ CGAL_add_named_parameter(postprocess_regions_t, postprocess_regions, postprocess
|
|||
CGAL_add_named_parameter(sizing_function_t, sizing_function, sizing_function)
|
||||
CGAL_add_named_parameter(bbox_scaling_t, bbox_scaling, bbox_scaling)
|
||||
|
||||
|
||||
// List of named parameters that we use in the package 'Surface Mesh Simplification'
|
||||
CGAL_add_named_parameter(get_cost_policy_t, get_cost_policy, get_cost)
|
||||
CGAL_add_named_parameter(get_placement_policy_t, get_placement_policy, get_placement)
|
||||
|
|
|
|||
|
|
@ -373,6 +373,99 @@ public:
|
|||
/// @}
|
||||
};
|
||||
|
||||
// ======================================================================
|
||||
/*!
|
||||
\ingroup PkgSurfaceSubdivisionMethod3Ref
|
||||
|
||||
TODO: need to find the correct name for this scheme, if it exists. And also complete the documentation.
|
||||
|
||||
The geometry mask of Upsample subdivision. This does not change the geometry of the mesh.
|
||||
In other words, the original vertices are not moved, and the new vertices are
|
||||
the average of the incident vertices. This is useful for increasing the resolution
|
||||
of a mesh without changing its geometry.
|
||||
|
||||
A stencil determines a source neighborhood
|
||||
whose points contribute to the position of a refined point.
|
||||
The geometry mask of a stencil specifies
|
||||
the computation on the nodes of the stencil.
|
||||
`Upsample_mask_3` implements the geometry masks of
|
||||
Upsample subdivision on a triangulated model of `MutableFaceGraph`,
|
||||
such as `Polyhedron_3` and `Surface_mesh`.
|
||||
|
||||
\tparam PolygonMesh must be a model of the concept `MutableFaceGraph`. Additionally all faces must be triangles.
|
||||
\tparam VertexPointMap must be a model of `WritablePropertyMap` with value type `Point_3`
|
||||
|
||||
\cgalModels `PTQMask_3`
|
||||
|
||||
\sa `CGAL::Subdivision_method_3`
|
||||
|
||||
*/
|
||||
template <class PolygonMesh,
|
||||
class VertexPointMap = typename boost::property_map<PolygonMesh,
|
||||
vertex_point_t>::type >
|
||||
class Upsample_mask_3 : public PQQ_stencil_3<PolygonMesh, VertexPointMap> {
|
||||
typedef PQQ_stencil_3<PolygonMesh, VertexPointMap> Base;
|
||||
public:
|
||||
typedef PolygonMesh Mesh;
|
||||
|
||||
#ifndef DOXYGEN_RUNNING
|
||||
typedef typename Base::vertex_descriptor vertex_descriptor;
|
||||
typedef typename Base::halfedge_descriptor halfedge_descriptor;
|
||||
|
||||
typedef typename Base::Kernel Kernel;
|
||||
|
||||
typedef typename Base::FT FT;
|
||||
typedef typename Base::Point Point;
|
||||
typedef typename boost::property_traits<VertexPointMap>::reference Point_ref;
|
||||
#endif
|
||||
|
||||
typedef Halfedge_around_target_circulator<Mesh> Halfedge_around_vertex_circulator;
|
||||
|
||||
public:
|
||||
/// \name Creation
|
||||
/// @{
|
||||
|
||||
/// Constructor.
|
||||
/// The default vertex point property map, `get(vertex_point, pmesh)`, is used.
|
||||
Upsample_mask_3(Mesh* pmesh)
|
||||
: Base(pmesh, get(vertex_point, pmesh))
|
||||
{ }
|
||||
|
||||
/// Constructor with a custom vertex point property map.
|
||||
Upsample_mask_3(Mesh* pmesh, VertexPointMap vpmap)
|
||||
: Base(pmesh, vpmap)
|
||||
{ }
|
||||
|
||||
/// @}
|
||||
|
||||
/// \name Stencil functions
|
||||
/// @{
|
||||
|
||||
/// computes the Upsample edge-point `pt` of the edge `edge`, simply the midpoint of the edge.
|
||||
void edge_node(halfedge_descriptor edge, Point& pt) {
|
||||
Point_ref p1 = get(this->vpmap,target(edge, *(this->pmesh)));
|
||||
Point_ref p2 = get(this->vpmap,target(opposite(edge, *(this->pmesh)), *(this->pmesh)));
|
||||
|
||||
pt = Point(0.5 * (p1[0]+p2[0]),
|
||||
0.5 * (p1[1]+p2[1]),
|
||||
0.5 * (p1[2]+p2[2]) );
|
||||
}
|
||||
|
||||
/// returns Upsample vertex-point `pt` of the vertex `vertex`, simply the original vertex.
|
||||
void vertex_node(vertex_descriptor vertex, Point& pt) {
|
||||
pt = get(this->vpmap,vertex);
|
||||
}
|
||||
|
||||
/// computes the Upsample edge-point `ept` and the Upsample vertex-point `vpt` of the border edge `edge`.
|
||||
void border_node(halfedge_descriptor edge, Point& ept, Point& vpt) {
|
||||
edge_node(edge, ept);
|
||||
|
||||
Halfedge_around_vertex_circulator vcir(edge, *(this->pmesh));
|
||||
vpt = get(this->vpmap,target(*vcir, *(this->pmesh)));
|
||||
}
|
||||
|
||||
/// @}
|
||||
};
|
||||
|
||||
//==========================================================================
|
||||
/// The stencil of the Dual-Quadrilateral-Quadrisection
|
||||
|
|
|
|||
|
|
@ -199,6 +199,56 @@ void Loop_subdivision(PolygonMesh& pmesh, const NamedParameters& np = parameters
|
|||
}
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
/*!
|
||||
*
|
||||
* applies Upsample subdivision several times on the control mesh `pmesh`.
|
||||
* The geometry of the refined mesh is computed by the geometry policy mask `Upsample_mask_3`.
|
||||
* Which is similar to Loop subdivision but does not change the shape of the mesh (only the connectivity).
|
||||
* The new vertices are trivially computed as the average of the incident vertices (midpoint of edge).
|
||||
* This function overwrites the control mesh `pmesh` with the subdivided mesh.
|
||||
|
||||
* @tparam PolygonMesh a model of `MutableFaceGraph`
|
||||
* @tparam NamedParameters a sequence of \ref bgl_namedparameters "Named Parameters"
|
||||
*
|
||||
* @param pmesh a polygon mesh
|
||||
* @param np an optional sequence of \ref bgl_namedparameters "Named Parameters" among the ones listed below
|
||||
*
|
||||
* \cgalNamedParamsBegin
|
||||
* \cgalParamNBegin{vertex_point_map}
|
||||
* \cgalParamDescription{a property map associating points to the vertices of `pmesh`}
|
||||
* \cgalParamType{a class model of `ReadWritePropertyMap` with `boost::graph_traits<PolygonMesh>::%vertex_descriptor`
|
||||
* as key type and `%Point_3` as value type}
|
||||
* \cgalParamDefault{`boost::get(CGAL::vertex_point, pmesh)`}
|
||||
* \cgalParamExtra{If this parameter is omitted, an internal property map for `CGAL::vertex_point_t`
|
||||
* should be available for the vertices of `pmesh`.}
|
||||
* \cgalParamNEnd
|
||||
*
|
||||
* \cgalParamNBegin{number_of_iterations}
|
||||
* \cgalParamDescription{the number of subdivision steps}
|
||||
* \cgalParamType{unsigned int}
|
||||
* \cgalParamDefault{`1`}
|
||||
* \cgalParamNEnd
|
||||
* \cgalNamedParamsEnd
|
||||
*
|
||||
* \pre `pmesh` must be a triangle mesh.
|
||||
**/
|
||||
template <class PolygonMesh, class NamedParameters = parameters::Default_named_parameters>
|
||||
void Upsample_subdivision(PolygonMesh& pmesh, const NamedParameters& np = parameters::default_values()) {
|
||||
using parameters::choose_parameter;
|
||||
using parameters::get_parameter;
|
||||
|
||||
typedef typename CGAL::GetVertexPointMap<PolygonMesh, NamedParameters>::type Vpm;
|
||||
Vpm vpm = choose_parameter(get_parameter(np, internal_np::vertex_point),
|
||||
get_property_map(CGAL::vertex_point, pmesh));
|
||||
|
||||
unsigned int step = choose_parameter(get_parameter(np, internal_np::number_of_iterations), 1);
|
||||
Upsample_mask_3<PolygonMesh,Vpm> mask(&pmesh, vpm);
|
||||
|
||||
for(unsigned int i = 0; i < step; i++)
|
||||
internal::PTQ_1step(pmesh, vpm, mask);
|
||||
}
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
#ifndef DOXYGEN_RUNNING
|
||||
// backward compatibility
|
||||
#ifndef CGAL_NO_DEPRECATED_CODE
|
||||
|
|
|
|||
Loading…
Reference in New Issue