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 }
|
||||
|
||||
|
||||
\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
|
||||
triangulation.
|
||||
|
||||
The following example demonstrates how to detect surface patches separated by sharp edges and use
|
||||
this segmentation during the tetrahedralization process.
|
||||
|
||||
When the named parameter `face_patch_map` is specified,
|
||||
the face constraint indices in the 3D triangulation (accessible
|
||||
via `CGAL::Conforming_constrained_Delaunay_triangulation_cell_data_3::face_constraint_index()`) are
|
||||
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.
|
||||
When the named parameter `plc_face_id` is specified, each constrained face in the 3D triangulation
|
||||
is assigned to the corresponding input PLC face, identified in the provided property map.
|
||||
If this parameter is not specified, each input polygon, or PLC face, is given a unique face index.
|
||||
|
||||
\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";
|
||||
|
||||
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: "
|
||||
<< ccdt.triangulation().number_of_vertices() << '\n'
|
||||
|
|
@ -47,7 +47,7 @@ int main(int argc, char* argv[])
|
|||
filename = argc > 3 ? argv[3] : "out.mesh";
|
||||
std::ofstream out(filename);
|
||||
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";
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
|
|
|
|||
|
|
@ -658,14 +658,14 @@ public:
|
|||
auto v_selected_map = get(CGAL::dynamic_vertex_property_t<bool>{}, mesh);
|
||||
|
||||
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) {
|
||||
auto mesh_face_patch_map = parameters::get_parameter(np, internal_np::face_patch);
|
||||
using Patch_id_type = CGAL::cpp20::remove_cvref_t<decltype(get(mesh_face_patch_map, *faces(mesh).first))>;
|
||||
if constexpr (has_plc_face_id) {
|
||||
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_plc_face_id, *faces(mesh).first))>;
|
||||
Patch_id_type max_patch_id{0};
|
||||
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);
|
||||
patch_edges.resize(number_of_patches);
|
||||
|
|
@ -673,9 +673,9 @@ public:
|
|||
if(is_border(h, mesh))
|
||||
continue;
|
||||
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);
|
||||
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 vb = target(h, mesh);
|
||||
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);
|
||||
Cell_handle hint_ch{};
|
||||
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;
|
||||
}
|
||||
auto p = get(mesh_vp_map, v);
|
||||
|
|
@ -709,7 +709,7 @@ public:
|
|||
auto operator()(vertex_descriptor v) const { return get(*vertex_map, v); }
|
||||
} 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) {
|
||||
auto& edges = patch_edges[i];
|
||||
if(edges.empty())
|
||||
|
|
@ -792,12 +792,12 @@ public:
|
|||
auto point_map = choose_parameter(get_parameter(np, internal_np::point_map),
|
||||
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::cend;
|
||||
|
||||
if constexpr (false == has_face_patch_map) {
|
||||
if constexpr (false == has_plc_face_id) {
|
||||
using Vertex_handle = typename Triangulation::Vertex_handle;
|
||||
using Cell_handle = typename Triangulation::Cell_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))>;
|
||||
constexpr auto invalid_patch_id = (std::numeric_limits<PID>::max)();
|
||||
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;
|
||||
|
||||
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);
|
||||
|
||||
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) {
|
||||
put(face_patch_pmap, pid_f.second, get(polygon_patch_map, pid_f.first));
|
||||
[plc_face_id_pmap, polygon_patch_map](std::pair<std::size_t, face_descriptor> pid_f) {
|
||||
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,
|
||||
np.polygon_to_face_output_iterator(polygon_to_face_output_iterator));
|
||||
|
||||
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)
|
||||
.geom_traits(cdt_impl.geom_traits())};
|
||||
*this = std::move(ccdt);
|
||||
|
|
|
|||
|
|
@ -12,6 +12,10 @@
|
|||
#include "CGAL/type_traits.h"
|
||||
#include "CGAL/unordered_flat_map.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 <ostream>
|
||||
|
||||
|
|
@ -27,12 +31,24 @@ namespace IO
|
|||
* file format.
|
||||
* @param os the output stream
|
||||
* @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
|
||||
*/
|
||||
template <typename Traits, typename Tr>
|
||||
template <typename Traits,
|
||||
typename Tr,
|
||||
typename NamedParameters = parameters::Default_named_parameters>
|
||||
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();
|
||||
|
||||
|
|
@ -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,
|
||||
tr,
|
||||
tr.finite_vertex_handles(),
|
||||
ccdt.constrained_facets(),
|
||||
tr.finite_cell_handles(),
|
||||
boost::make_function_property_map<Vertex_handle>([](Vertex_handle) { return 0; }),
|
||||
boost::make_function_property_map<Facet>([](const Facet& f) {
|
||||
return f.first->ccdt_3_data().face_constraint_index(f.second) + 1;
|
||||
}),
|
||||
plc_patch_map,
|
||||
boost::make_function_property_map<Cell_handle>([&](Cell_handle ch) {
|
||||
return cells_in_domain[ch] ? 1 : 0;
|
||||
}));
|
||||
|
|
|
|||
|
|
@ -20,6 +20,9 @@
|
|||
#include <CGAL/Triangulation_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 {
|
||||
|
||||
/*!
|
||||
|
|
@ -39,14 +42,14 @@ namespace CGAL {
|
|||
during the triangulation process.
|
||||
|
||||
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
|
||||
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
|
||||
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
|
||||
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.
|
||||
|
|
@ -108,11 +111,13 @@ namespace CGAL {
|
|||
* must be available in `PolygonMesh`.}
|
||||
* \cgalParamNEnd
|
||||
*
|
||||
* \cgalParamNBegin{face_patch_map}
|
||||
* \cgalParamDescription{a property map associating a patch identifier to each face of `mesh`}
|
||||
* \cgalParamNBegin{plc_face_id}
|
||||
* \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`
|
||||
* 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.}
|
||||
* \cgalParamNEnd
|
||||
*
|
||||
|
|
@ -182,8 +187,10 @@ auto make_conforming_constrained_Delaunay_triangulation_3(const PolygonMesh &mes
|
|||
* \cgalParamDefault{`CGAL::Identity_property_map`}
|
||||
* \cgalParamNEnd
|
||||
*
|
||||
* \cgalParamNBegin{face_patch_map}
|
||||
* \cgalParamDescription{a property map associating a patch identifier to each face of `soup`}
|
||||
* \cgalParamNBegin{plc_face_id}
|
||||
* \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`
|
||||
* 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.}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
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)
|
||||
|
||||
// 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