mirror of https://github.com/CGAL/cgal
replace face_patch_map with plc_face_id
the patches actually correspond to PLC faces, which must be planar, and do not match the "face patches" of PMP::isotropic_remeshing for example + add a np to CGAL::IO::write_MEDIT(ccdt) to save the corresponding PLC ids, or just "1" everywhere as patch id
This commit is contained in:
parent
bbc534f0b3
commit
1f3e98abac
|
|
@ -181,20 +181,18 @@ following example demonstrates how to build such a triangulation.
|
||||||
\cgalExample{Constrained_triangulation_3/conforming_constrained_Delaunay_triangulation_3_from_soup.cpp }
|
\cgalExample{Constrained_triangulation_3/conforming_constrained_Delaunay_triangulation_3_from_soup.cpp }
|
||||||
|
|
||||||
|
|
||||||
\subsection CT_3_example_ccdt_fpmap Build a Conforming Constrained Delaunay Triangulation with Known Face Patches
|
\subsection CT_3_example_ccdt_fpmap Build a Conforming Constrained Delaunay Triangulation with Known Polygon Identifiers
|
||||||
|
|
||||||
If the user already knows the set of patch identifiers to associate with each face, this information can be
|
If the user already knows the set of polygon identifiers to associate with each face, this information can be
|
||||||
provided and preserved throughout the construction of the conforming constrained Delaunay
|
provided and preserved throughout the construction of the conforming constrained Delaunay
|
||||||
triangulation.
|
triangulation.
|
||||||
|
|
||||||
The following example demonstrates how to detect surface patches separated by sharp edges and use
|
The following example demonstrates how to detect surface patches separated by sharp edges and use
|
||||||
this segmentation during the tetrahedralization process.
|
this segmentation during the tetrahedralization process.
|
||||||
|
|
||||||
When the named parameter `face_patch_map` is specified,
|
When the named parameter `plc_face_id` is specified, each constrained face in the 3D triangulation
|
||||||
the face constraint indices in the 3D triangulation (accessible
|
is assigned to the corresponding input PLC face, identified in the provided property map.
|
||||||
via `CGAL::Conforming_constrained_Delaunay_triangulation_cell_data_3::face_constraint_index()`) are
|
If this parameter is not specified, each input polygon, or PLC face, is given a unique face index.
|
||||||
set to the corresponding patch identifiers from the given property map. If this parameter is not provided, each
|
|
||||||
input polygon is assigned a unique face index.
|
|
||||||
|
|
||||||
\cgalExample{Constrained_triangulation_3/conforming_constrained_Delaunay_triangulation_3_fpmap.cpp}
|
\cgalExample{Constrained_triangulation_3/conforming_constrained_Delaunay_triangulation_3_fpmap.cpp}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -37,7 +37,7 @@ int main(int argc, char* argv[])
|
||||||
std::cout << "Wrote segmented mesh to " << filename << "\n";
|
std::cout << "Wrote segmented mesh to " << filename << "\n";
|
||||||
|
|
||||||
auto ccdt = CGAL::make_conforming_constrained_Delaunay_triangulation_3(mesh,
|
auto ccdt = CGAL::make_conforming_constrained_Delaunay_triangulation_3(mesh,
|
||||||
CGAL::parameters::face_patch_map(face_patch_map));
|
CGAL::parameters::plc_face_id(face_patch_map));
|
||||||
|
|
||||||
std::cout << "Number of vertices in the CDT: "
|
std::cout << "Number of vertices in the CDT: "
|
||||||
<< ccdt.triangulation().number_of_vertices() << '\n'
|
<< ccdt.triangulation().number_of_vertices() << '\n'
|
||||||
|
|
@ -47,7 +47,7 @@ int main(int argc, char* argv[])
|
||||||
filename = argc > 3 ? argv[3] : "out.mesh";
|
filename = argc > 3 ? argv[3] : "out.mesh";
|
||||||
std::ofstream out(filename);
|
std::ofstream out(filename);
|
||||||
out.precision(17);
|
out.precision(17);
|
||||||
CGAL::IO::write_MEDIT(out, ccdt);
|
CGAL::IO::write_MEDIT(out, ccdt, CGAL::parameters::with_plc_face_id(true));
|
||||||
std::cout << "Wrote CDT to " << filename << "\n";
|
std::cout << "Wrote CDT to " << filename << "\n";
|
||||||
|
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
|
|
|
||||||
|
|
@ -658,14 +658,14 @@ public:
|
||||||
auto v_selected_map = get(CGAL::dynamic_vertex_property_t<bool>{}, mesh);
|
auto v_selected_map = get(CGAL::dynamic_vertex_property_t<bool>{}, mesh);
|
||||||
|
|
||||||
int number_of_patches = 0;
|
int number_of_patches = 0;
|
||||||
constexpr bool has_face_patch_map = !parameters::is_default_parameter<CGAL_NP_CLASS, internal_np::face_patch_t>::value;
|
constexpr bool has_plc_face_id = !parameters::is_default_parameter<CGAL_NP_CLASS, internal_np::plc_face_id_t>::value;
|
||||||
|
|
||||||
if constexpr (has_face_patch_map) {
|
if constexpr (has_plc_face_id) {
|
||||||
auto mesh_face_patch_map = parameters::get_parameter(np, internal_np::face_patch);
|
auto mesh_plc_face_id = parameters::get_parameter(np, internal_np::plc_face_id);
|
||||||
using Patch_id_type = CGAL::cpp20::remove_cvref_t<decltype(get(mesh_face_patch_map, *faces(mesh).first))>;
|
using Patch_id_type = CGAL::cpp20::remove_cvref_t<decltype(get(mesh_plc_face_id, *faces(mesh).first))>;
|
||||||
Patch_id_type max_patch_id{0};
|
Patch_id_type max_patch_id{0};
|
||||||
for(auto f : faces(mesh)) {
|
for(auto f : faces(mesh)) {
|
||||||
max_patch_id = (std::max)(max_patch_id, get(mesh_face_patch_map, f));
|
max_patch_id = (std::max)(max_patch_id, get(mesh_plc_face_id, f));
|
||||||
}
|
}
|
||||||
number_of_patches = static_cast<int>(max_patch_id + 1);
|
number_of_patches = static_cast<int>(max_patch_id + 1);
|
||||||
patch_edges.resize(number_of_patches);
|
patch_edges.resize(number_of_patches);
|
||||||
|
|
@ -673,9 +673,9 @@ public:
|
||||||
if(is_border(h, mesh))
|
if(is_border(h, mesh))
|
||||||
continue;
|
continue;
|
||||||
auto f = face(h, mesh);
|
auto f = face(h, mesh);
|
||||||
auto patch_id = get(mesh_face_patch_map, f);
|
auto patch_id = get(mesh_plc_face_id, f);
|
||||||
auto opp = opposite(h, mesh);
|
auto opp = opposite(h, mesh);
|
||||||
if(is_border(opp, mesh) || patch_id != get(mesh_face_patch_map, face(opp, mesh))) {
|
if(is_border(opp, mesh) || patch_id != get(mesh_plc_face_id, face(opp, mesh))) {
|
||||||
auto va = source(h, mesh);
|
auto va = source(h, mesh);
|
||||||
auto vb = target(h, mesh);
|
auto vb = target(h, mesh);
|
||||||
patch_edges[patch_id].emplace_back(va, vb);
|
patch_edges[patch_id].emplace_back(va, vb);
|
||||||
|
|
@ -692,7 +692,7 @@ public:
|
||||||
auto tr_vertex_map = get(CGAL::dynamic_vertex_property_t<Vertex_handle>(), mesh);
|
auto tr_vertex_map = get(CGAL::dynamic_vertex_property_t<Vertex_handle>(), mesh);
|
||||||
Cell_handle hint_ch{};
|
Cell_handle hint_ch{};
|
||||||
for(auto v : vertices(mesh)) {
|
for(auto v : vertices(mesh)) {
|
||||||
if constexpr(has_face_patch_map) {
|
if constexpr(has_plc_face_id) {
|
||||||
if(false == get(v_selected_map, v)) continue;
|
if(false == get(v_selected_map, v)) continue;
|
||||||
}
|
}
|
||||||
auto p = get(mesh_vp_map, v);
|
auto p = get(mesh_vp_map, v);
|
||||||
|
|
@ -709,7 +709,7 @@ public:
|
||||||
auto operator()(vertex_descriptor v) const { return get(*vertex_map, v); }
|
auto operator()(vertex_descriptor v) const { return get(*vertex_map, v); }
|
||||||
} tr_vertex_fct{&tr_vertex_map};
|
} tr_vertex_fct{&tr_vertex_map};
|
||||||
|
|
||||||
if constexpr(has_face_patch_map) {
|
if constexpr(has_plc_face_id) {
|
||||||
for(int i = 0; i < number_of_patches; ++i) {
|
for(int i = 0; i < number_of_patches; ++i) {
|
||||||
auto& edges = patch_edges[i];
|
auto& edges = patch_edges[i];
|
||||||
if(edges.empty())
|
if(edges.empty())
|
||||||
|
|
@ -792,12 +792,12 @@ public:
|
||||||
auto point_map = choose_parameter(get_parameter(np, internal_np::point_map),
|
auto point_map = choose_parameter(get_parameter(np, internal_np::point_map),
|
||||||
CGAL::Identity_property_map<PointRange_value_type>{});
|
CGAL::Identity_property_map<PointRange_value_type>{});
|
||||||
|
|
||||||
constexpr bool has_face_patch_map = !parameters::is_default_parameter<NamedParams, internal_np::face_patch_t>::value;
|
constexpr bool has_plc_face_id = !parameters::is_default_parameter<NamedParams, internal_np::plc_face_id_t>::value;
|
||||||
|
|
||||||
using std::cbegin;
|
using std::cbegin;
|
||||||
using std::cend;
|
using std::cend;
|
||||||
|
|
||||||
if constexpr (false == has_face_patch_map) {
|
if constexpr (false == has_plc_face_id) {
|
||||||
using Vertex_handle = typename Triangulation::Vertex_handle;
|
using Vertex_handle = typename Triangulation::Vertex_handle;
|
||||||
using Cell_handle = typename Triangulation::Cell_handle;
|
using Cell_handle = typename Triangulation::Cell_handle;
|
||||||
using Vec_vertex_handle = std::vector<Vertex_handle>;
|
using Vec_vertex_handle = std::vector<Vertex_handle>;
|
||||||
|
|
@ -836,7 +836,7 @@ public:
|
||||||
using PID = CGAL::cpp20::remove_cvref_t<decltype(get(polygon_patch_map, 0u))>;
|
using PID = CGAL::cpp20::remove_cvref_t<decltype(get(polygon_patch_map, 0u))>;
|
||||||
constexpr auto invalid_patch_id = (std::numeric_limits<PID>::max)();
|
constexpr auto invalid_patch_id = (std::numeric_limits<PID>::max)();
|
||||||
Surface_mesh surface_mesh;
|
Surface_mesh surface_mesh;
|
||||||
auto face_patch_pmap =
|
auto plc_face_id_pmap =
|
||||||
surface_mesh.template add_property_map<face_descriptor, PID>("fpm", invalid_patch_id).first;
|
surface_mesh.template add_property_map<face_descriptor, PID>("fpm", invalid_patch_id).first;
|
||||||
|
|
||||||
auto to_point = [point_map](const PointRange_value_type& v) { return get(point_map, v); };
|
auto to_point = [point_map](const PointRange_value_type& v) { return get(point_map, v); };
|
||||||
|
|
@ -849,14 +849,14 @@ public:
|
||||||
PMP::orient_polygon_soup(rw_points, rw_polygons);
|
PMP::orient_polygon_soup(rw_points, rw_polygons);
|
||||||
|
|
||||||
auto polygon_to_face_output_iterator = boost::make_function_output_iterator(
|
auto polygon_to_face_output_iterator = boost::make_function_output_iterator(
|
||||||
[face_patch_pmap, polygon_patch_map](std::pair<std::size_t, face_descriptor> pid_f) {
|
[plc_face_id_pmap, polygon_patch_map](std::pair<std::size_t, face_descriptor> pid_f) {
|
||||||
put(face_patch_pmap, pid_f.second, get(polygon_patch_map, pid_f.first));
|
put(plc_face_id_pmap, pid_f.second, get(polygon_patch_map, pid_f.first));
|
||||||
});
|
});
|
||||||
PMP::polygon_soup_to_polygon_mesh(std::move(rw_points), std::move(rw_polygons), surface_mesh,
|
PMP::polygon_soup_to_polygon_mesh(std::move(rw_points), std::move(rw_polygons), surface_mesh,
|
||||||
np.polygon_to_face_output_iterator(polygon_to_face_output_iterator));
|
np.polygon_to_face_output_iterator(polygon_to_face_output_iterator));
|
||||||
|
|
||||||
Conforming_constrained_Delaunay_triangulation_3 ccdt{std::move(surface_mesh),
|
Conforming_constrained_Delaunay_triangulation_3 ccdt{std::move(surface_mesh),
|
||||||
CGAL::parameters::face_patch_map(face_patch_pmap)
|
CGAL::parameters::plc_face_id(plc_face_id_pmap)
|
||||||
.do_self_intersection_tests(false)
|
.do_self_intersection_tests(false)
|
||||||
.geom_traits(cdt_impl.geom_traits())};
|
.geom_traits(cdt_impl.geom_traits())};
|
||||||
*this = std::move(ccdt);
|
*this = std::move(ccdt);
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,10 @@
|
||||||
#include "CGAL/type_traits.h"
|
#include "CGAL/type_traits.h"
|
||||||
#include "CGAL/unordered_flat_map.h"
|
#include "CGAL/unordered_flat_map.h"
|
||||||
#include <CGAL/Conforming_constrained_Delaunay_triangulation_3.h>
|
#include <CGAL/Conforming_constrained_Delaunay_triangulation_3.h>
|
||||||
|
|
||||||
|
#include <CGAL/Named_function_parameters.h>
|
||||||
|
#include <CGAL/boost/graph/named_params_helper.h>
|
||||||
|
|
||||||
#include <CGAL/IO/File_medit.h>
|
#include <CGAL/IO/File_medit.h>
|
||||||
#include <ostream>
|
#include <ostream>
|
||||||
|
|
||||||
|
|
@ -27,12 +31,24 @@ namespace IO
|
||||||
* file format.
|
* file format.
|
||||||
* @param os the output stream
|
* @param os the output stream
|
||||||
* @param ccdt the conforming constrained Delaunay triangulation to be written
|
* @param ccdt the conforming constrained Delaunay triangulation to be written
|
||||||
|
* \param np an optional sequence of \ref bgl_namedparameters "Named Parameters" among the ones listed below
|
||||||
*
|
*
|
||||||
|
* \cgalNamedParamsBegin
|
||||||
|
* \cgalParamNBegin{with_plc_face_id}
|
||||||
|
* \cgalParamDescription{a Boolean activating the numbering of PLC face identifiers in the output}
|
||||||
|
* \cgalParamType{Boolean}
|
||||||
|
* \cgalParamDefault{`false`}
|
||||||
|
* \cgalParamNEnd
|
||||||
|
* \cgalNamedParamsEnd
|
||||||
|
|
||||||
* \see \ref IOStreamMedit
|
* \see \ref IOStreamMedit
|
||||||
*/
|
*/
|
||||||
template <typename Traits, typename Tr>
|
template <typename Traits,
|
||||||
|
typename Tr,
|
||||||
|
typename NamedParameters = parameters::Default_named_parameters>
|
||||||
void write_MEDIT(std::ostream& os,
|
void write_MEDIT(std::ostream& os,
|
||||||
const Conforming_constrained_Delaunay_triangulation_3<Traits, Tr>& ccdt)
|
const Conforming_constrained_Delaunay_triangulation_3<Traits, Tr>& ccdt,
|
||||||
|
const NamedParameters& np = parameters::default_values())
|
||||||
{
|
{
|
||||||
const auto& tr = ccdt.triangulation();
|
const auto& tr = ccdt.triangulation();
|
||||||
|
|
||||||
|
|
@ -62,15 +78,21 @@ void write_MEDIT(std::ostream& os,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
using parameters::choose_parameter;
|
||||||
|
using parameters::get_parameter;
|
||||||
|
const bool has_plc_face_id
|
||||||
|
= choose_parameter(get_parameter(np, internal_np::with_plc_face_id), false);
|
||||||
|
|
||||||
|
auto plc_patch_map = boost::make_function_property_map<Facet>([&](const Facet& f)
|
||||||
|
{ return has_plc_face_id ? f.first->ccdt_3_data().face_constraint_index(f.second) + 1 : 1; });
|
||||||
|
|
||||||
return SMDS_3::output_to_medit(os,
|
return SMDS_3::output_to_medit(os,
|
||||||
tr,
|
tr,
|
||||||
tr.finite_vertex_handles(),
|
tr.finite_vertex_handles(),
|
||||||
ccdt.constrained_facets(),
|
ccdt.constrained_facets(),
|
||||||
tr.finite_cell_handles(),
|
tr.finite_cell_handles(),
|
||||||
boost::make_function_property_map<Vertex_handle>([](Vertex_handle) { return 0; }),
|
boost::make_function_property_map<Vertex_handle>([](Vertex_handle) { return 0; }),
|
||||||
boost::make_function_property_map<Facet>([](const Facet& f) {
|
plc_patch_map,
|
||||||
return f.first->ccdt_3_data().face_constraint_index(f.second) + 1;
|
|
||||||
}),
|
|
||||||
boost::make_function_property_map<Cell_handle>([&](Cell_handle ch) {
|
boost::make_function_property_map<Cell_handle>([&](Cell_handle ch) {
|
||||||
return cells_in_domain[ch] ? 1 : 0;
|
return cells_in_domain[ch] ? 1 : 0;
|
||||||
}));
|
}));
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,9 @@
|
||||||
#include <CGAL/Triangulation_3.h>
|
#include <CGAL/Triangulation_3.h>
|
||||||
#include <CGAL/Triangulation_data_structure_3.h>
|
#include <CGAL/Triangulation_data_structure_3.h>
|
||||||
|
|
||||||
|
#include <CGAL/Named_function_parameters.h>
|
||||||
|
#include <CGAL/boost/graph/named_params_helper.h>
|
||||||
|
|
||||||
namespace CGAL {
|
namespace CGAL {
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
|
@ -39,14 +42,14 @@ namespace CGAL {
|
||||||
during the triangulation process.
|
during the triangulation process.
|
||||||
|
|
||||||
By default, each face of the input is considered a polygonal constraint for the triangulation. The
|
By default, each face of the input is considered a polygonal constraint for the triangulation. The
|
||||||
named parameter `face_patch_map` can be used to describe larger polygonal constraints, possibly with holes. If
|
named parameter `plc_face_id` can be used to describe larger polygonal constraints, possibly with holes. If
|
||||||
used, this parameter must be a property map that associates each face of the input with a patch
|
used, this parameter must be a property map that associates each face of the input with a patch
|
||||||
identifier. Faces with the same patch identifier are considered part of the same surface patch. Each of these
|
identifier. Faces with the same patch identifier are considered part of the same surface patch. Each of these
|
||||||
surface patches (defined as the union of the input faces with a given patch identifier) is expected to be a polygon or
|
surface patches (defined as the union of the input faces with a given patch identifier) is expected to be a polygon or
|
||||||
a polygon with holes, with coplanar vertices (or nearly coplanar up to the precision of the number type used).
|
a polygon with holes, with coplanar vertices (or nearly coplanar up to the precision of the number type used).
|
||||||
|
|
||||||
The generated triangulation will conform to the faces of the input, or to the surface patches
|
The generated triangulation will conform to the faces of the input, or to the surface patches
|
||||||
described by the `face_patch_map` property map if provided.
|
described by the `plc_face_id` property map if provided.
|
||||||
|
|
||||||
|
|
||||||
\pre The input data must not be coplanar.
|
\pre The input data must not be coplanar.
|
||||||
|
|
@ -108,11 +111,13 @@ namespace CGAL {
|
||||||
* must be available in `PolygonMesh`.}
|
* must be available in `PolygonMesh`.}
|
||||||
* \cgalParamNEnd
|
* \cgalParamNEnd
|
||||||
*
|
*
|
||||||
* \cgalParamNBegin{face_patch_map}
|
* \cgalParamNBegin{plc_face_id}
|
||||||
* \cgalParamDescription{a property map associating a patch identifier to each face of `mesh`}
|
* \cgalParamDescription{a property map associating a patch identifier to each face of `mesh`.
|
||||||
|
* Each identifier corresponds to a planar surface patch. Each surface
|
||||||
|
* patch can be composed of several faces of `mesh`, forming a planar polygon.}
|
||||||
* \cgalParamType{a class model of `ReadWritePropertyMap` with `boost::graph_traits<PolygonMesh>::%face_descriptor`
|
* \cgalParamType{a class model of `ReadWritePropertyMap` with `boost::graph_traits<PolygonMesh>::%face_descriptor`
|
||||||
* as key type and with any value type that is a *regular* type (model of `Regular`)}
|
* as key type and with any value type that is a *regular* type (model of `Regular`)}
|
||||||
* \cgalParamExtra{If this parameter is omitted, each face of the mesh is considered a separate patch.
|
* \cgalParamExtra{If this parameter is omitted, each face of `mesh` is considered a separate patch.
|
||||||
* Faces with the same patch identifier are considered part of the same surface patch.}
|
* Faces with the same patch identifier are considered part of the same surface patch.}
|
||||||
* \cgalParamNEnd
|
* \cgalParamNEnd
|
||||||
*
|
*
|
||||||
|
|
@ -182,8 +187,10 @@ auto make_conforming_constrained_Delaunay_triangulation_3(const PolygonMesh &mes
|
||||||
* \cgalParamDefault{`CGAL::Identity_property_map`}
|
* \cgalParamDefault{`CGAL::Identity_property_map`}
|
||||||
* \cgalParamNEnd
|
* \cgalParamNEnd
|
||||||
*
|
*
|
||||||
* \cgalParamNBegin{face_patch_map}
|
* \cgalParamNBegin{plc_face_id}
|
||||||
* \cgalParamDescription{a property map associating a patch identifier to each face of `soup`}
|
* \cgalParamDescription{a property map associating a patch identifier to each face of `soup`.
|
||||||
|
* Each identifier corresponds to a planar surface patch. Each surface
|
||||||
|
* patch can be composed of several faces of `soup`, forming a planar polygon.}
|
||||||
* \cgalParamType{a class model of `ReadWritePropertyMap` with `std::size_t`
|
* \cgalParamType{a class model of `ReadWritePropertyMap` with `std::size_t`
|
||||||
* as key type and with any value type that is a *regular* type (model of `Regular`)}
|
* as key type and with any value type that is a *regular* type (model of `Regular`)}
|
||||||
* \cgalParamExtra{If this parameter is omitted, each face of the polygon soup is considered a separate patch.}
|
* \cgalParamExtra{If this parameter is omitted, each face of the polygon soup is considered a separate patch.}
|
||||||
|
|
|
||||||
|
|
@ -404,3 +404,7 @@ CGAL_add_named_parameter(do_not_modify_geometry_t, do_not_modify_geometry, do_no
|
||||||
//List of named parameters used in Straight_skeleton_2
|
//List of named parameters used in Straight_skeleton_2
|
||||||
CGAL_add_named_parameter_with_compatibility_ref_only(angles_param_t, angles_param, angles)
|
CGAL_add_named_parameter_with_compatibility_ref_only(angles_param_t, angles_param, angles)
|
||||||
CGAL_add_named_parameter(maximum_height_t, maximum_height, maximum_height)
|
CGAL_add_named_parameter(maximum_height_t, maximum_height, maximum_height)
|
||||||
|
|
||||||
|
// List of named parameters used in the package 'Constrained_triangulation_3'
|
||||||
|
CGAL_add_named_parameter(plc_face_id_t, plc_face_id, plc_face_id)
|
||||||
|
CGAL_add_named_parameter(with_plc_face_id_t, with_plc_face_id, with_plc_face_id)
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue