diff --git a/Installation/CHANGES.md b/Installation/CHANGES.md
index cc7e537c714..962edbe37f7 100644
--- a/Installation/CHANGES.md
+++ b/Installation/CHANGES.md
@@ -60,6 +60,8 @@ for automatic detection and protection
of 1D-curves that lie at the intersection of three or more subdomains,
extracted from labeled images.
+- Added new meshing criterion `edge_min_size` to avoid subdividing sharp edges that are shorter than the prescribed size bound.
+
### [Shape Detection](https://doc.cgal.org/5.6/Manual/packages.html#PkgShapeDetection) (breaking change, major changes)
- **Breaking change**: The region growing part of the package have been reworked to fix design issues introduced with the handling `FaceGraph` models.
diff --git a/Mesh_3/doc/Mesh_3/CGAL/Mesh_edge_criteria_3.h b/Mesh_3/doc/Mesh_3/CGAL/Mesh_edge_criteria_3.h
deleted file mode 100644
index 3acbda1bd27..00000000000
--- a/Mesh_3/doc/Mesh_3/CGAL/Mesh_edge_criteria_3.h
+++ /dev/null
@@ -1,53 +0,0 @@
-namespace CGAL {
-
-/*!
-\ingroup PkgMesh3MeshClasses
-
-The function object class `Mesh_edge_criteria_3` is a model of `MeshEdgeCriteria_3`. It
-provides a bound for the size criterion.
-
-\cgalModels `MeshEdgeCriteria_3`
-
-\sa `MeshCriteria_3`
-\sa `CGAL::Mesh_criteria_3
`
-\sa `MeshDomainField_3`
-
-*/
-template< typename Tr >
-class Mesh_edge_criteria_3 {
-public:
-
-/// \name Types
-/// @{
-
-/*!
-Numerical type.
-*/
-typedef Tr::Geom_traits::FT FT;
-
-/// @}
-
-/// \name Creation
-/// @{
-
-/*!
-Returns an object to serve as criteria for edges.
-The argument `length_bound` is an upper bound
-for the length of the edges which are used to discretize the curves.
-Note that if one parameter is set to 0, then its corresponding criteria is ignored.
-*/
-Mesh_edge_criteria_3(const FT& length_bound);
-
-/*!
-Returns an object to serve as criteria for edges. The type `SizingField`
-must be a model of concept `MeshDomainField_3`. The behavior and semantic of the argument are the same
-as above, except that the length
-parameter is a functional instead of a constant.
-*/
-template
-Mesh_edge_criteria_3(const SizingField& length_bound);
-
-/// @}
-
-}; /* end Mesh_edge_criteria_3 */
-} /* end namespace CGAL */
diff --git a/Mesh_3/doc/Mesh_3/Concepts/MeshEdgeCriteria_3.h b/Mesh_3/doc/Mesh_3/Concepts/MeshEdgeCriteria_3.h
index 29ad69bc395..4c044751069 100644
--- a/Mesh_3/doc/Mesh_3/Concepts/MeshEdgeCriteria_3.h
+++ b/Mesh_3/doc/Mesh_3/Concepts/MeshEdgeCriteria_3.h
@@ -50,6 +50,12 @@ Returns the value of the sizing field (i.e.\ the maximum edge length) at point `
*/
FT sizing_field(const Point_3& p);
+/*!
+Returns the lower bound on edge length, set by the user.
+The lower bound is ignored when its value is 0.
+*/
+const FT& min_length_bound() const;
+
/// @}
}; /* end MeshEdgeCriteria_3 */
diff --git a/Mesh_3/doc/Mesh_3/Doxyfile.in b/Mesh_3/doc/Mesh_3/Doxyfile.in
index d3608c7b5a0..3c630018edc 100644
--- a/Mesh_3/doc/Mesh_3/Doxyfile.in
+++ b/Mesh_3/doc/Mesh_3/Doxyfile.in
@@ -20,7 +20,8 @@ INPUT += \
${CGAL_PACKAGE_INCLUDE_DIR}/CGAL/Mesh_cell_base_3.h \
${CGAL_PACKAGE_INCLUDE_DIR}/CGAL/Compact_mesh_cell_base_3.h \
${CGAL_PACKAGE_INCLUDE_DIR}/CGAL/Mesh_3/Detect_features_in_image.h \
- ${CGAL_PACKAGE_INCLUDE_DIR}/CGAL/Mesh_3/Detect_features_on_image_bbox.h
+ ${CGAL_PACKAGE_INCLUDE_DIR}/CGAL/Mesh_3/Detect_features_on_image_bbox.h \
+ ${CGAL_PACKAGE_INCLUDE_DIR}/CGAL/Mesh_edge_criteria_3.h
PROJECT_NAME = "CGAL ${CGAL_DOC_VERSION} - 3D Mesh Generation"
HTML_EXTRA_FILES = ${CGAL_PACKAGE_DOC_DIR}/fig/implicit_domain_3.jpg \
diff --git a/Mesh_3/include/CGAL/Mesh_criteria_3.h b/Mesh_3/include/CGAL/Mesh_criteria_3.h
index 334e7c6e290..5358e813742 100644
--- a/Mesh_3/include/CGAL/Mesh_criteria_3.h
+++ b/Mesh_3/include/CGAL/Mesh_criteria_3.h
@@ -72,7 +72,8 @@ public:
Mesh_criteria_3_impl(const CGAL_NP_CLASS& np)
:edge_criteria_(parameters::choose_parameter(parameters::get_parameter(np, internal_np::edge_size_param),
parameters::choose_parameter(parameters::get_parameter_reference(np, internal_np::edge_sizing_field_param),
- parameters::choose_parameter(parameters::get_parameter(np, internal_np::sizing_field_param), FT(DBL_MAX))))),
+ parameters::choose_parameter(parameters::get_parameter(np, internal_np::sizing_field_param), FT(DBL_MAX)))),
+ parameters::choose_parameter(parameters::get_parameter(np, internal_np::edge_min_size_param), FT(0))),
facet_criteria_(parameters::choose_parameter(parameters::get_parameter(np, internal_np::facet_angle_param), FT(0)),
parameters::choose_parameter(parameters::get_parameter(np, internal_np::facet_size_param),
parameters::choose_parameter(parameters::get_parameter_reference(np, internal_np::facet_sizing_field_param),
@@ -255,6 +256,18 @@ typedef Mesh_cell_criteria_3 Cell_criteria;
* upper bound for the lengths of curve edges. This parameter has to be set to a positive
* value when 1-dimensional features protection is used.}
* \cgalParamNEnd
+ * \cgalParamNBegin{edge_min_size}
+ * \cgalParamDescription{a desired uniform lower-bound for the lengths of curve edges.
+ * Only feature edges with a length larger than this bound will be refined.
+ * If a feature edge is too small with respect to this criterion,
+ * it will not be refined whether the other criteria are met or not.}
+ * \cgalParamExtra{If this criterion is applied during the meshing process,
+ * the feature protection algorithm correctness is not guaranteed anymore,
+ * and the output mesh may contain incorrect polyline features,
+ * or have missing polyline features.}
+ * \cgalParamExtra{Note this lower-bound may not be respected everywhere in the output mesh,
+ * to keep the feature graph valid.}
+ * \cgalParamNEnd
* \cgalParamNBegin{facet_angle}
* \cgalParamDescription{a lower bound for the angles (in degrees) of the
* surface mesh facets.}
diff --git a/Mesh_3/include/CGAL/Mesh_edge_criteria_3.h b/Mesh_3/include/CGAL/Mesh_edge_criteria_3.h
index d45ff426f9f..8846555dc6b 100644
--- a/Mesh_3/include/CGAL/Mesh_edge_criteria_3.h
+++ b/Mesh_3/include/CGAL/Mesh_edge_criteria_3.h
@@ -85,43 +85,98 @@ namespace internal {
} // end namespace internal
} // end namespace Mesh_3
+/*!
+\ingroup PkgMesh3MeshClasses
+
+The function object class `Mesh_edge_criteria_3` is a model of `MeshEdgeCriteria_3`. It
+provides a bound for the size criterion.
+
+\cgalModels `MeshEdgeCriteria_3`
+
+\sa `MeshCriteria_3`
+\sa `CGAL::Mesh_criteria_3
`
+\sa `MeshDomainField_3`
+
+*/
template < typename Tr >
class Mesh_edge_criteria_3
{
+private:
typedef Mesh_edge_criteria_3 Self;
+ typedef typename Tr::Geom_traits Gt;
public:
- typedef typename Tr::Vertex::Index Index;
- typedef typename Tr::Geom_traits Gt;
- typedef typename Gt::FT FT;
- typedef typename Tr::Bare_point Point_3;
+ /// \name Types
+ /// @{
+ /*!
+ Numerical type.
+ */
+ typedef typename Tr::Geom_traits::FT FT;
+ typedef typename Tr::Vertex::Index Index;
+ typedef typename Tr::Bare_point Point_3;
- /// Constructors
- Mesh_edge_criteria_3(const FT& value)
+ /// @}
+
+
+ /// \name Creation
+ /// @{
+ /*!
+ * Returns an object to serve as criteria for edges.
+ * \param length_bound is an upper bound
+ * for the length of the edges which are used to discretize the curves.
+ * \param min_length_bound is a desired lower bound
+ * for the length of the edges which are used to discretize the curves.
+ * Only edges that are longer than this bound will be refined. Using
+ * this lower bound can be handy on some domains, but using it may
+ * break all the surface topology guarantees of the meshing algorithm.
+ * It is not guaranteed to be exactly respected in the output mesh.
+ *
+ * Note that if one parameter is set to 0, then its corresponding criterion is ignored.
+ */
+ Mesh_edge_criteria_3(const FT& length_bound,
+ const FT& min_length_bound = 0)
: p_size_(new Mesh_3::internal::Sizing_field_container<
Mesh_constant_domain_field_3 ,
FT,
Point_3,
- Index>(value))
+ Index>(length_bound))
+ , min_length_bound_(min_length_bound)
{}
// Nb: SFINAE to avoid wrong matches with built-in numerical types
// as int.
- template < typename Sizing_field >
+ /*!
+ * @tparam SizingField a model of `MeshDomainField_3`
+ *
+ * Returns an object to serve as criteria for edges.
+ * The behavior and semantic of the argument are the same
+ * as above, except that the `length_bound`
+ * parameter is a functional instead of a constant.
+ */
+ template < typename SizingField >
Mesh_edge_criteria_3
(
- const Sizing_field& size,
- std::enable_if_t::value>* = 0
+ const SizingField& length_bound,
+ const FT& min_length_bound = 0
+#ifndef DOXYGEN_RUNNING
+ , std::enable_if_t::value>* = 0
+#endif
)
+ : min_length_bound_(min_length_bound)
{
- p_size_ = new Mesh_3::internal::Sizing_field_container(size);
+ Index>(length_bound);
}
+ /// @}
+
+#ifndef DOXYGEN_RUNNING
Mesh_edge_criteria_3(const Self& rhs)
- : p_size_(rhs.p_size_->clone()) {}
+ : p_size_(rhs.p_size_->clone())
+ , min_length_bound_(rhs.min_length_bound_)
+ {}
/// Destructor
~Mesh_edge_criteria_3()
@@ -133,6 +188,13 @@ public:
FT sizing_field(const Point_3& p, const int dim, const Index& index) const
{ return (*p_size_)(p,dim,index); }
+public:
+ const FT& min_length_bound() const
+ {
+ return min_length_bound_;
+ }
+#endif
+
private:
typedef Mesh_3::internal::Sizing_field_interface
Sizing_field_interface;
@@ -140,6 +202,7 @@ private:
// A pointer to Sizing_field_interface to handle dynamic wrapping of
// real Sizing_field type
Sizing_field_interface* p_size_;
+ const FT min_length_bound_;
};
} // end namespace CGAL
diff --git a/Mesh_3/include/CGAL/make_mesh_3.h b/Mesh_3/include/CGAL/make_mesh_3.h
index db1c8448811..79277f1643f 100644
--- a/Mesh_3/include/CGAL/make_mesh_3.h
+++ b/Mesh_3/include/CGAL/make_mesh_3.h
@@ -111,7 +111,7 @@ void init_c3t3_with_features(C3T3& c3t3,
protect_edges(c3t3,
domain,
Sizing_field(criteria.edge_criteria_object()),
- typename Edge_criteria::FT(),
+ criteria.edge_criteria_object().min_length_bound(),
maximal_number_of_vertices,
pointer_to_error_code
#ifndef CGAL_NO_ATOMIC
diff --git a/Mesh_3/test/Mesh_3/CMakeLists.txt b/Mesh_3/test/Mesh_3/CMakeLists.txt
index 6914a7cc846..9d5103e9405 100644
--- a/Mesh_3/test/Mesh_3/CMakeLists.txt
+++ b/Mesh_3/test/Mesh_3/CMakeLists.txt
@@ -54,6 +54,7 @@ create_single_source_cgal_program( "test_mesh_3_issue_1554.cpp" )
create_single_source_cgal_program( "test_mesh_polyhedral_domain_with_features_deprecated.cpp" )
create_single_source_cgal_program( "test_meshing_with_one_step.cpp" )
create_single_source_cgal_program( "test_mesh_cell_base_3.cpp")
+create_single_source_cgal_program( "test_min_edge_length.cpp")
foreach(target
test_boost_has_xxx
@@ -84,6 +85,7 @@ foreach(target
test_mesh_polyhedral_domain_with_features_deprecated
test_mesh_cell_base_3
test_meshing_with_one_step
+ test_min_edge_length
test_min_size_criteria
)
if(TARGET ${target})
@@ -108,6 +110,7 @@ if(TARGET CGAL::TBB_support)
test_mesh_3_issue_1554
test_mesh_polyhedral_domain_with_features_deprecated
test_mesh_cell_base_3
+ test_min_edge_length
test_min_size_criteria
)
if(TARGET ${target})
diff --git a/Mesh_3/test/Mesh_3/test_min_edge_length.cpp b/Mesh_3/test/Mesh_3/test_min_edge_length.cpp
new file mode 100644
index 00000000000..5f65c365218
--- /dev/null
+++ b/Mesh_3/test/Mesh_3/test_min_edge_length.cpp
@@ -0,0 +1,85 @@
+#include
+
+#include
+#include
+#include
+#include
+
+#include
+#include
+
+#include
+
+
+template
+struct Tester
+{
+ // Domain
+ typedef CGAL::Polyhedral_mesh_domain_with_features_3 Mesh_domain;
+
+ // Triangulation
+ typedef typename CGAL::Mesh_triangulation_3::type Tr;
+
+ typedef CGAL::Mesh_complex_3_in_triangulation_3 C3t3;
+
+ // Criteria
+ typedef CGAL::Mesh_criteria_3
Mesh_criteria;
+
+ void operator()(const std::string fname, const std::string out_fname)
+ {
+ std::ifstream input(fname);
+ using namespace CGAL::parameters;
+
+ Polyhedron polyhedron;
+ input >> polyhedron;
+ if (input.fail()) {
+ std::cerr << "Error: Cannot read file " << fname << std::endl;
+ return;
+ }
+
+ if (!CGAL::is_triangle_mesh(polyhedron)) {
+ std::cerr << "Input geometry is not triangulated." << std::endl;
+ return;
+ }
+
+ // Create domain
+ Mesh_domain domain(polyhedron);
+
+ domain.detect_features(40);
+
+ Sizing_field_with_aabb_tree sf(0.074, domain.aabb_tree(), domain);
+
+ // Mesh criteria
+ Mesh_criteria criteria(edge_size = sf,
+ edge_min_size = 0.1,
+ facet_distance = 0.0074,
+ facet_angle = 25,
+ facet_size = 0.074,
+ cell_radius_edge_ratio = 3,
+ cell_size = 0.074);
+
+ // Mesh generation
+ C3t3 c3t3 = CGAL::make_mesh_3(domain, criteria, no_perturb(), no_exude());
+
+ // Output
+ CGAL::dump_c3t3(c3t3, out_fname);
+ }
+};
+
+int main(int argc, char* argv[])
+{
+ const std::string fname = (argc > 1) ? argv[1] : CGAL::data_file_path("meshes/dragknob.off");
+
+ typedef CGAL::Exact_predicates_inexact_constructions_kernel K;
+ typedef CGAL::Surface_mesh Surface_mesh;
+
+ std::cout << "Sequential test" << std::endl;
+ Tester()(fname, "out-dragknob-sequential");
+
+ std::cout << "Parallel test" << std::endl;
+ Tester()(fname, "out-dragknob-parallel");
+
+ return EXIT_SUCCESS;
+}
diff --git a/Polyhedron/demo/Polyhedron/Plugins/Mesh_3/Mesh_3_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/Mesh_3/Mesh_3_plugin.cpp
index 3f5ff1d1f45..11e52ca9587 100644
--- a/Polyhedron/demo/Polyhedron/Plugins/Mesh_3/Mesh_3_plugin.cpp
+++ b/Polyhedron/demo/Polyhedron/Plugins/Mesh_3/Mesh_3_plugin.cpp
@@ -70,6 +70,7 @@ class Mesh_3_plugin :
READ get_sharp_edges_angle_bound
WRITE set_sharp_edges_angle_bound)
Q_PROPERTY(double edges_sizing READ get_edges_sizing WRITE set_edges_sizing)
+ Q_PROPERTY(double edges_min_sizing READ get_edges_min_sizing WRITE set_edges_min_sizing)
Q_PROPERTY(double facets_sizing READ get_facets_sizing WRITE set_facets_sizing)
Q_PROPERTY(double approx READ get_approx WRITE set_approx)
Q_PROPERTY(double tets_sizing READ get_tets_sizing WRITE set_tets_sizing)
@@ -155,6 +156,7 @@ public Q_SLOTS:
sharp_edges_angle_bound = v;
}
void set_edges_sizing(const double v) { edges_sizing = v; };
+ void set_edges_min_sizing(const double v) { edges_min_sizing = v; };
void set_facets_sizing(const double v) { facets_sizing = v; };
void set_approx(const double v) { approx = v; };
void set_tets_sizing(const double v) { tets_sizing = v; };
@@ -167,6 +169,7 @@ public Q_SLOTS:
double get_angle() { return angle; };
double get_sharp_edges_angle_bound() { return sharp_edges_angle_bound; }
double get_edges_sizing() { return edges_sizing; };
+ double get_edges_min_sizing() { return edges_min_sizing; };
double get_facets_sizing() { return facets_sizing; };
double get_approx() { return approx; };
double get_tets_sizing() { return tets_sizing; };
@@ -202,6 +205,7 @@ private:
double approx;
int approx_decimals;
double edges_sizing;
+ double edges_min_sizing;
double facets_sizing;
double facets_min_sizing;
double tets_sizing;
@@ -422,6 +426,7 @@ void Mesh_3_plugin::set_defaults() {
double diag = CGAL::sqrt((bbox.xmax()-bbox.xmin())*(bbox.xmax()-bbox.xmin()) + (bbox.ymax()-bbox.ymin())*(bbox.ymax()-bbox.ymin()) + (bbox.zmax()-bbox.zmin())*(bbox.zmax()-bbox.zmin()));
facets_sizing = get_approximate(diag * 0.05, 2, sizing_decimals);
edges_sizing = facets_sizing;
+ edges_min_sizing = 0.1 * facets_sizing;
tets_sizing = facets_sizing;
facets_min_sizing = 0.1 * facets_sizing;
tets_min_sizing = 0.1 * tets_sizing;
@@ -518,6 +523,7 @@ void Mesh_3_plugin::mesh_3(const Mesh_type mesh_type,
ui.tetShape,
SLOT(setEnabled(bool)));
+ //edge sizing
connect(ui.protect,
SIGNAL(toggled(bool)),
ui.noEdgeSizing,
@@ -538,6 +544,28 @@ void Mesh_3_plugin::mesh_3(const Mesh_type mesh_type,
ui.edgeSizing,
SLOT(setEnabled(bool)));
+ //edge min sizing
+ connect(ui.protect,
+ SIGNAL(toggled(bool)),
+ ui.noEdgeMinSizing,
+ SLOT(setEnabled(bool)));
+
+ connect(ui.protect,
+ SIGNAL(toggled(bool)),
+ ui.noEdgeMinSizing,
+ SLOT(setChecked(bool)));
+
+ connect(ui.noEdgeMinSizing,
+ SIGNAL(toggled(bool)),
+ ui.edgeMinSizingLabel,
+ SLOT(setEnabled(bool)));
+
+ connect(ui.noEdgeMinSizing,
+ SIGNAL(toggled(bool)),
+ ui.edgeMinSizing,
+ SLOT(setEnabled(bool)));
+
+ //sharp edges
connect(ui.protect,
SIGNAL(toggled(bool)),
ui.sharpEdgesAngle,
@@ -572,6 +600,7 @@ void Mesh_3_plugin::mesh_3(const Mesh_type mesh_type,
ui.facetSizing->setValue(facets_sizing);
ui.facetMinSizing->setValue(facets_min_sizing);
ui.edgeSizing->setValue(edges_sizing);
+ ui.edgeMinSizing->setValue(edges_min_sizing);
ui.tetSizing->setRange(diag * 10e-6, // min
diag); // max
@@ -610,8 +639,11 @@ void Mesh_3_plugin::mesh_3(const Mesh_type mesh_type,
" automatically"));
}
ui.noEdgeSizing->setChecked(ui.protect->isChecked());
+ ui.noEdgeMinSizing->setChecked(false);
ui.edgeLabel->setEnabled(ui.noEdgeSizing->isChecked());
ui.edgeSizing->setEnabled(ui.noEdgeSizing->isChecked());
+ ui.edgeMinSizingLabel->setEnabled(ui.noEdgeMinSizing->isChecked());
+ ui.edgeMinSizing->setEnabled(ui.noEdgeMinSizing->isChecked());
const QString sharp_and_boundary("Sharp and Boundary edges");
const QString boundary_only("Boundary edges only");
@@ -677,6 +709,8 @@ void Mesh_3_plugin::mesh_3(const Mesh_type mesh_type,
std::cerr << "sharp_edges_angle_bound: " << sharp_edges_angle_bound << '\n';
edges_sizing =
!ui.noEdgeSizing->isChecked() ? DBL_MAX : ui.edgeSizing->value();
+ edges_min_sizing =
+ !ui.noEdgeMinSizing->isChecked() ? 0. : ui.edgeMinSizing->value();
facets_sizing = !ui.noFacetSizing->isChecked() ? 0 : ui.facetSizing->value();
facets_min_sizing = !ui.noFacetMinSizing->isChecked() ? 0 : ui.facetMinSizing->value();
approx = !ui.noApprox->isChecked() ? 0 : ui.approx->value();
@@ -685,12 +719,23 @@ void Mesh_3_plugin::mesh_3(const Mesh_type mesh_type,
tets_min_sizing = !ui.noTetMinSizing->isChecked() ? 0 : ui.tetMinSizing->value();
const int pe_ci = ui.protectEdges->currentIndex();
- protect_borders = ui.protect->isChecked()
- && ( pe_ci == ui.protectEdges->findText(on_cube, Qt::MatchContains)
- || pe_ci == ui.protectEdges->findText(boundary_only, Qt::MatchContains));
- protect_features = ui.protect->isChecked()
- && ( pe_ci == ui.protectEdges->findText(triple_lines, Qt::MatchContains)
- || pe_ci == ui.protectEdges->findText(sharp_and_boundary, Qt::MatchContains));
+ if (items->which() == IMAGE_MESH_ITEMS)
+ {
+ protect_borders = ui.protect->isChecked()
+ && ( pe_ci == ui.protectEdges->findText(on_cube, Qt::MatchContains)
+ || pe_ci == ui.protectEdges->findText(boundary_only, Qt::MatchContains));
+ protect_features = ui.protect->isChecked()
+ && ( pe_ci == ui.protectEdges->findText(triple_lines, Qt::MatchContains)
+ || pe_ci == ui.protectEdges->findText(sharp_and_boundary, Qt::MatchContains));
+ }
+ else if (items->which() == POLYHEDRAL_MESH_ITEMS)
+ {
+ protect_borders = ui.protect->isChecked()
+ && ( pe_ci == ui.protectEdges->findText(sharp_and_boundary, Qt::MatchContains)
+ || pe_ci == ui.protectEdges->findText(boundary_only, Qt::MatchContains));
+ protect_features = ui.protect->isChecked()
+ && ( pe_ci == ui.protectEdges->findText(sharp_edges, Qt::MatchContains));
+ }
const bool detect_connected_components = ui.detectComponents->isChecked();
const int manifold = (ui.manifoldCheckBox->isChecked() ? 1 : 0) +
@@ -762,6 +807,7 @@ void Mesh_3_plugin::mesh_3(const Mesh_type mesh_type,
tets_sizing,
tets_min_sizing,
edges_sizing,
+ edges_min_sizing,
tets_shape,
protect_features,
protect_borders,
@@ -782,6 +828,7 @@ void Mesh_3_plugin::mesh_3(const Mesh_type mesh_type,
tets_sizing,
tets_min_sizing,
edges_sizing,
+ edges_min_sizing,
tets_shape,
protect_features,
protect_borders,
@@ -808,6 +855,7 @@ void Mesh_3_plugin::mesh_3(const Mesh_type mesh_type,
tets_sizing,
tets_min_sizing,
edges_sizing,
+ edges_min_sizing,
tets_shape,
manifold,
mesh_type == Mesh_type::SURFACE_ONLY);
@@ -850,6 +898,7 @@ void Mesh_3_plugin::mesh_3(const Mesh_type mesh_type,
tets_sizing,
tets_min_sizing,
edges_sizing,
+ edges_min_sizing,
tets_shape,
protect_features,
protect_borders,
diff --git a/Polyhedron/demo/Polyhedron/Plugins/Mesh_3/Mesh_3_plugin_cgal_code.cpp b/Polyhedron/demo/Polyhedron/Plugins/Mesh_3/Mesh_3_plugin_cgal_code.cpp
index 707313d3aa3..bfd480bceba 100644
--- a/Polyhedron/demo/Polyhedron/Plugins/Mesh_3/Mesh_3_plugin_cgal_code.cpp
+++ b/Polyhedron/demo/Polyhedron/Plugins/Mesh_3/Mesh_3_plugin_cgal_code.cpp
@@ -44,6 +44,7 @@ Meshing_thread* cgal_code_mesh_3(QList pMeshes,
const double tet_sizing,
const double tet_min_sizing,
const double edge_size,
+ const double edge_min_size,
const double tet_shape,
bool protect_features,
bool protect_borders,
@@ -56,6 +57,7 @@ Meshing_thread* cgal_code_mesh_3(QList pMeshes,
std::cerr << "Meshing file \"" << qPrintable(filename) << "\"\n";
std::cerr << " angle: " << facet_angle << std::endl
<< " edge size bound: " << edge_size << std::endl
+ << " edge min size bound: " << edge_min_size << std::endl
<< " facets size bound: " << facet_sizing << std::endl
<< " approximation bound: " << facet_approx << std::endl;
if (!surface_only)
@@ -105,10 +107,12 @@ Meshing_thread* cgal_code_mesh_3(QList pMeshes,
""
"- Angle: %1
"
"- Edge size bound: %2
"
- "- Facets size bound: %3
"
- "- Approximation bound: %4
")
+ "- Edge min size bound: %3
"
+ "- Facets size bound: %4
"
+ "- Approximation bound: %5
")
.arg(facet_angle)
.arg(edge_size)
+ .arg(edge_min_size)
.arg(facet_sizing)
.arg(facet_approx);
if (!surface_only)
@@ -126,6 +130,7 @@ Meshing_thread* cgal_code_mesh_3(QList pMeshes,
param.tet_min_sizing = tet_min_sizing;
param.tet_shape = tet_shape;
param.edge_sizing = edge_size;
+ param.edge_min_sizing = edge_min_size;
param.manifold = manifold;
param.protect_features = protect_features || protect_borders;
param.use_sizing_field_with_aabb_tree = polylines.empty() && protect_features;
@@ -147,6 +152,7 @@ Meshing_thread* cgal_code_mesh_3(const QList pMeshes,
const double tet_sizing,
const double tet_min_sizing,
const double edge_size,
+ const double edge_min_size,
const double tet_shape,
bool protect_features,
bool protect_borders,
@@ -159,6 +165,7 @@ Meshing_thread* cgal_code_mesh_3(const QList pMeshes,
std::cerr << "Meshing file \"" << qPrintable(filename) << "\"\n";
std::cerr << " angle: " << facet_angle << std::endl
<< " edge size bound: " << edge_size << std::endl
+ << " edge min size bound: " << edge_min_size << std::endl
<< " facets size bound: " << facet_sizing << std::endl
<< " approximation bound: " << facet_approx << std::endl;
if (!surface_only)
@@ -203,10 +210,12 @@ Meshing_thread* cgal_code_mesh_3(const QList pMeshes,
""
"- Angle: %1
"
"- Edge size bound: %2
"
- "- Facets size bound: %3
"
- "- Approximation bound: %4
")
+ "- Edge min size bound :%3
"
+ "- Facets size bound: %4
"
+ "- Approximation bound: %5
")
.arg(facet_angle)
.arg(edge_size)
+ .arg(edge_min_size)
.arg(facet_sizing)
.arg(facet_approx);
if (!surface_only)
@@ -224,6 +233,7 @@ Meshing_thread* cgal_code_mesh_3(const QList pMeshes,
param.tet_min_sizing = tet_min_sizing;
param.tet_shape = tet_shape;
param.edge_sizing = edge_size;
+ param.edge_min_sizing = edge_min_size;
param.manifold = manifold;
param.protect_features = protect_features || protect_borders;
param.use_sizing_field_with_aabb_tree = protect_features;
@@ -246,6 +256,7 @@ Meshing_thread* cgal_code_mesh_3(const Implicit_function_interface* pfunction,
const double tet_sizing,
const double tet_min_sizing,
const double edge_size,
+ const double edge_min_size,
const double tet_shape,
const int manifold,
const bool surface_only)
@@ -277,6 +288,7 @@ Meshing_thread* cgal_code_mesh_3(const Implicit_function_interface* pfunction,
param.tet_min_sizing = tet_min_sizing;
param.tet_shape = tet_shape;
param.edge_sizing = edge_size;
+ param.edge_min_sizing = edge_min_size;
param.manifold = manifold;
param.detect_connected_components = false; // to avoid random values
// in the debug displays
@@ -306,6 +318,7 @@ Meshing_thread* cgal_code_mesh_3(const Image* pImage,
const double tet_sizing,
const double tet_min_sizing,
const double edge_size,
+ const double edge_min_size,
const double tet_shape,
bool protect_features, //detect_polylines
const bool protect_borders,//polylines on bbox
@@ -333,6 +346,7 @@ Meshing_thread* cgal_code_mesh_3(const Image* pImage,
param.facet_min_sizing = facet_min_sizing;
param.tet_min_sizing = tet_min_sizing;
param.edge_sizing = edge_size;
+ param.edge_min_sizing = edge_min_size;
param.tet_shape = tet_shape;
param.manifold = manifold;
param.image_3_ptr = pImage;
@@ -343,10 +357,12 @@ Meshing_thread* cgal_code_mesh_3(const Image* pImage,
""
"- Angle: %1
"
"- Edge size bound: %2
"
- "- Facets size bound: %3
"
- "- Approximation bound: %4
")
+ "- Edge min size bound: %3
"
+ "- Facets size bound: %4
"
+ "- Approximation bound: %5
")
.arg(facet_angle)
.arg(edge_size)
+ .arg(edge_min_size)
.arg(facet_sizing)
.arg(facet_approx);
if (!surface_only)
diff --git a/Polyhedron/demo/Polyhedron/Plugins/Mesh_3/Mesh_3_plugin_cgal_code.h b/Polyhedron/demo/Polyhedron/Plugins/Mesh_3/Mesh_3_plugin_cgal_code.h
index 4bf500ea510..4a705ccd4eb 100644
--- a/Polyhedron/demo/Polyhedron/Plugins/Mesh_3/Mesh_3_plugin_cgal_code.h
+++ b/Polyhedron/demo/Polyhedron/Plugins/Mesh_3/Mesh_3_plugin_cgal_code.h
@@ -31,6 +31,7 @@ Meshing_thread* cgal_code_mesh_3(QList pMeshes,
const double tet_sizing,
const double tet_min_sizing,
const double edge_size,
+ const double edge_min_size,
const double tet_shape,
bool protect_features,
bool protect_border,
@@ -48,6 +49,7 @@ Meshing_thread* cgal_code_mesh_3(const QList pMeshes,
const double tet_sizing,
const double tet_min_sizing,
const double edge_size,
+ const double edge_min_size,
const double tet_shape,
bool protect_features,
bool protect_border,
@@ -64,6 +66,7 @@ Meshing_thread* cgal_code_mesh_3(const Implicit_function_interface* pfunction,
const double tet_sizing,
const double tet_min_sizing,
const double edge_size,
+ const double edge_min_size,
const double tet_shape,
const int manifold,
const bool surface_only);
@@ -79,6 +82,7 @@ Meshing_thread* cgal_code_mesh_3(const CGAL::Image_3* pImage,
const double tet_sizing,
const double tet_min_sizing,
const double edge_size,
+ const double edge_min_size,
const double tet_shape,
bool protect_features,
const bool protect_borders,
diff --git a/Polyhedron/demo/Polyhedron/Plugins/Mesh_3/Mesh_function.h b/Polyhedron/demo/Polyhedron/Plugins/Mesh_3/Mesh_function.h
index 366b452f17b..65392c0366e 100644
--- a/Polyhedron/demo/Polyhedron/Plugins/Mesh_3/Mesh_function.h
+++ b/Polyhedron/demo/Polyhedron/Plugins/Mesh_3/Mesh_function.h
@@ -51,6 +51,7 @@ struct Mesh_parameters
double tet_sizing;
double tet_min_sizing;
double edge_sizing;
+ double edge_min_sizing;
bool protect_features;
bool detect_connected_components;
int manifold;
@@ -110,8 +111,8 @@ private:
void initialize(const Mesh_criteria& criteria, Mesh_fnt::Domain_tag);
void initialize(const Mesh_criteria& criteria, Mesh_fnt::Labeled_image_domain_tag);
- Edge_criteria edge_criteria(double b, Mesh_fnt::Domain_tag);
- Edge_criteria edge_criteria(double b, Mesh_fnt::Polyhedral_domain_tag);
+ Edge_criteria edge_criteria(double b, double minb, Mesh_fnt::Domain_tag);
+ Edge_criteria edge_criteria(double b, double minb, Mesh_fnt::Polyhedral_domain_tag);
void tweak_criteria(Mesh_criteria&, Mesh_fnt::Domain_tag) {}
void tweak_criteria(Mesh_criteria&, Mesh_fnt::Polyhedral_domain_tag);
@@ -139,6 +140,7 @@ log() const
{
return QStringList()
<< QString("edge max size: %1").arg(edge_sizing)
+ << QString("edge min size: %1").arg(edge_min_sizing)
<< QString("facet min angle: %1").arg(facet_angle)
<< QString("facet max size: %1").arg(facet_sizing)
<< QString("facet min size: %1").arg(facet_min_sizing)
@@ -242,9 +244,9 @@ initialize(const Mesh_criteria& criteria, Mesh_fnt::Domain_tag)
template < typename D_, typename Tag >
typename Mesh_function::Edge_criteria
Mesh_function::
-edge_criteria(double b, Mesh_fnt::Domain_tag)
+edge_criteria(double b, double minb, Mesh_fnt::Domain_tag)
{
- return Edge_criteria(b);
+ return Edge_criteria(b, minb);
}
#include
@@ -253,7 +255,7 @@ edge_criteria(double b, Mesh_fnt::Domain_tag)
template < typename D_, typename Tag >
typename Mesh_function::Edge_criteria
Mesh_function::
-edge_criteria(double edge_size, Mesh_fnt::Polyhedral_domain_tag)
+edge_criteria(double edge_size, double minb, Mesh_fnt::Polyhedral_domain_tag)
{
if(p_.use_sizing_field_with_aabb_tree) {
typedef typename Domain::Surface_patch_index_set Set_of_patch_ids;
@@ -281,9 +283,9 @@ edge_criteria(double edge_size, Mesh_fnt::Polyhedral_domain_tag)
QSharedPointer(patches_ids_vector_p));
std::cerr << "Note: Mesh_3 is using a sizing field based on AABB tree.\n";
- return Edge_criteria(*sizing_field_ptr);
+ return Edge_criteria(*sizing_field_ptr, minb);
} else {
- return Edge_criteria(edge_size);
+ return Edge_criteria(edge_size, minb);
}
}
@@ -297,7 +299,9 @@ launch()
#endif
// Create mesh criteria
- Mesh_criteria criteria(edge_criteria(p_.edge_sizing, Tag()),
+ Mesh_criteria criteria(edge_criteria(p_.edge_sizing,
+ p_.edge_min_sizing,
+ Tag()),
Facet_criteria(p_.facet_angle,
p_.facet_sizing,
p_.facet_approx,
@@ -349,8 +353,9 @@ tweak_criteria(Mesh_criteria& c, Mesh_fnt::Polyhedral_domain_tag) {
typedef CGAL::Mesh_3::Facet_topological_criterion_with_adjacency New_topo_adj_crit;
- if((int(c.facet_criteria_object().topology()) &
+ if(((int(c.facet_criteria_object().topology()) &
CGAL::FACET_VERTICES_ON_SAME_SURFACE_PATCH_WITH_ADJACENCY_CHECK) != 0)
+ && c.edge_criteria_object().min_length_bound() == 0)
{
c.add_facet_criterion(new New_topo_adj_crit(this->domain_));
}
diff --git a/Polyhedron/demo/Polyhedron/Plugins/Mesh_3/Meshing_dialog.ui b/Polyhedron/demo/Polyhedron/Plugins/Mesh_3/Meshing_dialog.ui
index e95fd891898..88ee87fc1be 100644
--- a/Polyhedron/demo/Polyhedron/Plugins/Mesh_3/Meshing_dialog.ui
+++ b/Polyhedron/demo/Polyhedron/Plugins/Mesh_3/Meshing_dialog.ui
@@ -10,7 +10,7 @@
0
0
799
- 1231
+ 1295
@@ -101,22 +101,15 @@
Sharp features
- -
-
+
-
+
- 60.00
+ 0.0
- -
-
-
-
-
-
- true
-
-
+
-
+
-
@@ -134,15 +127,22 @@
- -
-
+
-
+
-
+ 60.00
- -
-
+
-
+
+
+
+
+
+ true
+
+
-
@@ -157,13 +157,6 @@
- -
-
-
- 0.0
-
-
-
-
@@ -177,6 +170,33 @@
+ -
+
+
+
+
+
+
+ -
+
+
+ Edge min size
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+
+ -
+
+
+ -
+
+
+
+
+
+
diff --git a/STL_Extension/include/CGAL/STL_Extension/internal/parameters_interface.h b/STL_Extension/include/CGAL/STL_Extension/internal/parameters_interface.h
index 49ed237c50c..6f6b2ef5178 100644
--- a/STL_Extension/include/CGAL/STL_Extension/internal/parameters_interface.h
+++ b/STL_Extension/include/CGAL/STL_Extension/internal/parameters_interface.h
@@ -337,6 +337,7 @@ CGAL_add_named_parameter_with_compatibility(features_detector_param_t, features_
CGAL_add_named_parameter_with_compatibility(input_features_param_t, input_features_param, input_features)
CGAL_add_named_parameter_with_compatibility(edge_size_param_t, edge_size_param, edge_size)
+CGAL_add_named_parameter_with_compatibility(edge_min_size_param_t, edge_min_size_param, edge_min_size)
CGAL_add_named_parameter_with_compatibility_ref_only(edge_sizing_field_param_t, edge_sizing_field_param, edge_sizing_field)
CGAL_add_named_parameter_with_compatibility(facet_angle_param_t, facet_angle_param, facet_angle)
CGAL_add_named_parameter_with_compatibility(facet_size_param_t, facet_size_param, facet_size)