Merge branch 'gsoc2023' into master

This commit is contained in:
Sébastien Loriot 2024-10-18 14:33:31 +02:00
commit 619875392c
16 changed files with 2251 additions and 2 deletions

View File

@ -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},

View File

@ -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

View File

@ -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

View File

@ -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>

View File

@ -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"

View File

@ -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)

View File

@ -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)
{

View File

@ -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`

View File

@ -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 */

View File

@ -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

View File

@ -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")

View File

@ -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

View File

@ -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)

View File

@ -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

View File

@ -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