This commit is contained in:
Jane Tournois 2024-09-17 18:02:36 +02:00
parent c55477cda3
commit ce9cd9e596
5 changed files with 168 additions and 216 deletions

View File

@ -35,22 +35,23 @@ typedef CGAL::Mesh_criteria_3<Tr> Mesh_criteria;
namespace params = CGAL::parameters; namespace params = CGAL::parameters;
// Custom_Initial_points_generator will put points on the mesh for initialisation. // Custom_initial_points_generator will put points on the mesh for initialisation.
// Those points are objects of type std::tuple<Weighted_point_3, int, Index>. // Those points are objects of type std::tuple<Weighted_point_3, int, Index>.
// Weighted_point_3 is the point's position and weight, // Weighted_point_3 is the point's position and weight,
// int is the dimension of the minimal dimension subcomplex on which the point lies, // int is the dimension of the minimal dimension subcomplex on which the point lies,
// Index is the underlying subcomplex index. // Index is the underlying subcomplex index.
struct Custom_Initial_points_generator struct Custom_initial_points_generator
{ {
CGAL::Image_3& image_; const CGAL::Image_3& image_;
Custom_Initial_points_generator(CGAL::Image_3& image) : image_(image) { }
template <typename OutputIterator, typename MeshDomain, typename C3t3> template <typename OutputIterator>
OutputIterator operator()(OutputIterator pts, const MeshDomain& /* domain */, const C3t3& c3t3, int /* n */ = 1) const OutputIterator operator()(OutputIterator pts) const
{ {
typedef typename C3t3::Triangulation::Geom_traits::Point_3 Point_3; typedef Tr::Geom_traits Gt;
typedef typename C3t3::Triangulation::Geom_traits::Vector_3 Vector_3; typedef Gt::Point_3 Point_3;
typedef typename C3t3::Triangulation::Geom_traits::Segment_3 Segment_3; typedef Gt::Vector_3 Vector_3;
typedef Gt::Segment_3 Segment_3;
typedef Mesh_domain::Index Index;
typename C3t3::Triangulation::Geom_traits::Construct_weighted_point_3 cwp = typename C3t3::Triangulation::Geom_traits::Construct_weighted_point_3 cwp =
c3t3.triangulation().geom_traits().construct_weighted_point_3_object(); c3t3.triangulation().geom_traits().construct_weighted_point_3_object();
@ -64,10 +65,11 @@ struct Custom_Initial_points_generator
Vector_3 vector = segment.to_vector(); Vector_3 vector = segment.to_vector();
double edge_size = 5; double edge_size = 5;
std::size_t nb = static_cast<int>(CGAL::sqrt(segment.squared_length()) / edge_size); std::size_t nb = static_cast<int>(CGAL::sqrt(segment.squared_length()) / edge_size);
const double frac = 1. / (double)nb;
for (std::size_t i = 1; i < nb; i++) for (std::size_t i = 1; i < nb; i++)
{ {
*pts++ = std::make_tuple( *pts++ = {cwp(source + (i * frac) * vector), 1, Index(1));
cwp(source + (i/(double)nb)*vector, edge_size*edge_size), 1, 0);
} }
return pts; return pts;
} }
@ -95,7 +97,7 @@ int main()
/// [Meshing] /// [Meshing]
C3t3 c3t3 = CGAL::make_mesh_3<C3t3>(domain, criteria C3t3 c3t3 = CGAL::make_mesh_3<C3t3>(domain, criteria
, params::initial_points_generator(Custom_Initial_points_generator(image)) , params::initial_points_generator(Custom_initial_points_generator{ image })
); );
/// [Meshing] /// [Meshing]

View File

@ -62,8 +62,8 @@ int main()
// Creation of the initial_points vector // Creation of the initial_points vector
std::vector<Initial_point_t> initial_points = { std::vector<Initial_point_t> initial_points = {
std::make_tuple(Weighted_point_3(Point_3(30.0, 50.0, 83.33), 30.0), 1, 0), {Weighted_point_3(Point_3(30.0, 50.0, 83.33), 30.0), 1, Index(1)},
std::make_tuple(Weighted_point_3(Point_3(70.0, 50.0, 83.33), 50.0), 1, 0) {Weighted_point_3(Point_3(70.0, 50.0, 83.33), 50.0), 1, Index(1)}
}; };
/// [Meshing] /// [Meshing]

View File

@ -293,7 +293,7 @@ struct Construct_initial_points_labeled_image
if (pi_inside_protecting_sphere) if (pi_inside_protecting_sphere)
continue; continue;
*pts++ = std::make_tuple(cwp(intersect_point), 2, intersect_index); // dimension 2 by construction, points are on surface *pts++ = {cwp(intersect_point), 2, intersect_index}; // dimension 2 by construction, points are on surface
} }
} }
} }

View File

@ -38,38 +38,55 @@ namespace CGAL {
namespace Mesh_3 { namespace Mesh_3 {
namespace internal { namespace internal {
template < typename C3T3, typename MeshDomain, typename MeshCriteria > template < typename C3T3, typename MeshDomain, typename InitialPointsGenerator >
void void
add_points_from_generator(C3T3& c3t3, const MeshDomain& domain, add_points_from_generator(C3T3& c3t3,
const MeshDomain& domain,
const int nb_initial_points, const int nb_initial_points,
const parameters::internal::Initial_points_generator_options<MeshDomain, C3T3>& generator) const InitialPointsGenerator& generator)
{ {
typedef typename C3T3::Triangulation Tr; typedef typename C3T3::Triangulation Tr;
typedef typename Tr::Geom_traits::Weighted_point_3 Weighted_point_3;
typedef typename MeshDomain::Index Index;
typedef typename std::tuple<Weighted_point_3, int, Index> Initialization_point;
typedef std::vector< Initialization_point > Initial_points_vector;
typedef typename C3T3::Vertex_handle Vertex_handle; typedef typename C3T3::Vertex_handle Vertex_handle;
typedef CGAL::Mesh_3::Triangulation_helpers<Tr> Th; typedef CGAL::Mesh_3::Triangulation_helpers<Tr> Th;
// Mesh initialization : get some points and add them to the mesh using Point_3 = typename Tr::Geom_traits::Point_3;
Initial_points_vector initial_points; using Index = typename MeshDomain::Index;
if (nb_initial_points > -1) using PointIndexPair = std::pair<Point_3, Index>;
generator(std::back_inserter(initial_points), domain, c3t3, using PointDimIndex = parameters::internal::Initial_point_type<MeshDomain, C3t3>;
nb_initial_points);
else //use default number of points struct InitialPointPair2TupleConverter
generator(std::back_inserter(initial_points), domain, c3t3); {
PointDimIndex operator()(const PointDimIndex& wp_d_i) const
{
return wp_d_i;
}
PointDimIndex operator()(const PointIndexPair& p_i) const
{
auto cwp = Tr::Geom_traits().construct_weighted_point_3_object();
return PointDimIndex{ cwp(p_i.first), 2, p_i.second };
}
};
std::vector<PointDimIndex> initial_points;
InitialPointPair2TupleConverter pair2tuple;
auto push_initial_point = [&](const auto& initial_pt)->void
{
initial_points.push_back(pair2tuple(initial_pt));
};
if (nb_initial_points > 0)
generator(boost::make_function_output_iterator(push_initial_point), nb_initial_points);
else
generator(boost::make_function_output_iterator(push_initial_point));
Tr& triangulation = c3t3.triangulation();
// Insert points and set their index and dimension // Insert points and set their index and dimension
for (const auto& [weighted_point_3, dimension, index] : initial_points) { for (const auto& [wpoint, dimension, index] : initial_points)
if(Th().inside_protecting_balls(triangulation, Vertex_handle(), weighted_point_3.point())) {
if(Th().inside_protecting_balls(c3t3.triangulation(), Vertex_handle(), wpoint.point()))
continue; continue;
Vertex_handle v = c3t3.triangulation().insert(weighted_point_3); Vertex_handle v = c3t3.triangulation().insert(wpoint);
// v could be null if point is hidden // v could be null if point is hidden
if ( v != Vertex_handle() ) if ( v != Vertex_handle() )
@ -80,18 +97,19 @@ add_points_from_generator(C3T3& c3t3, const MeshDomain& domain,
} }
} }
template < typename C3T3, typename MeshDomain, typename MeshCriteria > template < typename C3T3, typename MeshDomain, typename MeshCriteria, typename InitializationOptions>
void void
init_c3t3(C3T3& c3t3, const MeshDomain& domain, const MeshCriteria&, init_c3t3(C3T3& c3t3, const MeshDomain& domain, const MeshCriteria&,
const int nb_initial_points, const int nb_initial_points,
const parameters::internal::Initial_points_generator_options<MeshDomain, C3T3>& generator = parameters::internal::Initial_points_generator_generator<MeshDomain, C3T3>()()) const InitializationOptions& init_generator)
{ {
add_points_from_generator<C3T3, MeshDomain, MeshCriteria>(c3t3, domain, nb_initial_points, generator); add_points_from_generator(c3t3, domain, nb_initial_points, init_generator);
// If c3t3 initialization is not sufficient (may happen if // If c3t3 initialization is not sufficient (may happen if
// the user has not specified enough points ), add some surface points // the user has not specified enough points ), add some surface points
bool need_more_init = c3t3.triangulation().dimension() != 3 || !generator.is_default(); bool need_more_init = c3t3.triangulation().dimension() != 3 || !init_generator.is_default();
if(!need_more_init) { if(!need_more_init)
{
CGAL::Mesh_3::C3T3_helpers<C3T3, MeshDomain> helper(c3t3, domain); CGAL::Mesh_3::C3T3_helpers<C3T3, MeshDomain> helper(c3t3, domain);
helper.update_restricted_facets(); helper.update_restricted_facets();
@ -106,10 +124,10 @@ init_c3t3(C3T3& c3t3, const MeshDomain& domain, const MeshCriteria&,
} }
} }
} }
if(need_more_init) { if(need_more_init)
parameters::internal::Initial_points_generator_options<MeshDomain, C3T3> domain_generator = {
parameters::internal::Initial_points_generator_generator<MeshDomain, C3T3>()(); InitializationOptions init_options(domain.construct_initial_points_object());
add_points_from_generator<C3T3, MeshDomain, MeshCriteria>(c3t3, domain, nb_initial_points, domain_generator); add_points_from_generator(c3t3, domain, nb_initial_points, init_options);
} }
} }
@ -196,23 +214,22 @@ template < typename C3T3,
typename MeshDomain, typename MeshDomain,
typename MeshCriteria, typename MeshCriteria,
bool MeshDomainHasHasFeatures, bool MeshDomainHasHasFeatures,
typename HasFeatures = int> typename HasFeatures,
typename InitOptions>
struct C3t3_initializer { }; struct C3t3_initializer { };
// Partial specialization of C3t3_initializer // Partial specialization of C3t3_initializer
// Handle cases where MeshDomain::Has_features is not a valid type // Handle cases where MeshDomain::Has_features is not a valid type
template < typename C3T3, typename MD, typename MC, typename HasFeatures> template < typename C3T3, typename MD, typename MC, typename HasFeatures, typename InitOptions>
struct C3t3_initializer < C3T3, MD, MC, false, HasFeatures > struct C3t3_initializer < C3T3, MD, MC, false, HasFeatures, InitOptions >
{ {
typedef parameters::internal::Mesh_3_options Mesh_3_options; typedef parameters::internal::Mesh_3_options Mesh_3_options;
typedef parameters::internal::Initial_points_generator_options<MD, C3T3> Initial_points_generator_options;
typedef parameters::internal::Initial_points_generator_generator<MD, C3T3> Initial_points_generator_generator;
void operator()(C3T3& c3t3, void operator()(C3T3& c3t3,
const MD& domain, const MD& domain,
const MC& criteria, const MC& criteria,
bool with_features, bool with_features,
Mesh_3_options mesh_options = Mesh_3_options(), Mesh_3_options mesh_options = Mesh_3_options(),
const Initial_points_generator_options& generator = Initial_points_generator_generator()()) const InitOptions& init_options = InitOptions())
{ {
if ( with_features ) if ( with_features )
{ {
@ -221,48 +238,47 @@ struct C3t3_initializer < C3T3, MD, MC, false, HasFeatures >
} }
init_c3t3(c3t3,domain,criteria, init_c3t3(c3t3,domain,criteria,
mesh_options.number_of_initial_points, generator); mesh_options.number_of_initial_points,
init_options);
} }
}; };
// Partial specialization of C3t3_initializer // Partial specialization of C3t3_initializer
// Handles cases where MeshDomain::Has_features is a valid type // Handles cases where MeshDomain::Has_features is a valid type
template < typename C3T3, typename MD, typename MC, typename HasFeatures > template < typename C3T3, typename MD, typename MC, typename HasFeatures, typename InitOptions>
struct C3t3_initializer < C3T3, MD, MC, true, HasFeatures > struct C3t3_initializer < C3T3, MD, MC, true, HasFeatures, InitOptions>
{ {
typedef parameters::internal::Mesh_3_options Mesh_3_options; typedef parameters::internal::Mesh_3_options Mesh_3_options;
typedef parameters::internal::Initial_points_generator_options<MD, C3T3> Initial_points_generator_options;
typedef parameters::internal::Initial_points_generator_generator<MD, C3T3> Initial_points_generator_generator;
void operator()(C3T3& c3t3, void operator()(C3T3& c3t3,
const MD& domain, const MD& domain,
const MC& criteria, const MC& criteria,
bool with_features, bool with_features,
Mesh_3_options mesh_options = Mesh_3_options(), Mesh_3_options mesh_options = Mesh_3_options(),
const Initial_points_generator_options& generator = Initial_points_generator_generator()()) const InitOptions& init_options = InitOptions())
{ {
C3t3_initializer < C3T3, MD, MC, true, typename MD::Has_features >() C3t3_initializer < C3T3, MD, MC, true, typename MD::Has_features, InitOptions >()
(c3t3,domain,criteria,with_features,mesh_options,generator); (c3t3,domain,criteria,with_features,mesh_options,init_options);
} }
}; };
// Partial specialization of C3t3_initializer // Partial specialization of C3t3_initializer
// Handles cases where MeshDomain::Has_features is a valid type and is defined // Handles cases where MeshDomain::Has_features is a valid type and is defined
// to CGAL::Tag_true // to CGAL::Tag_true
template < typename C3T3, typename MD, typename MC > template < typename C3T3, typename MD, typename MC, typename InitOptions >
struct C3t3_initializer < C3T3, MD, MC, true, CGAL::Tag_true > struct C3t3_initializer < C3T3, MD, MC, true, CGAL::Tag_true, InitOptions >
: public C3t3_initializer_base < C3T3, MD, MC > : public C3t3_initializer_base < C3T3, MD, MC >
{ {
virtual ~C3t3_initializer() { } virtual ~C3t3_initializer() { }
typedef parameters::internal::Mesh_3_options Mesh_3_options; typedef parameters::internal::Mesh_3_options Mesh_3_options;
typedef parameters::internal::Initial_points_generator_options<MD, C3T3> Initial_points_generator_options;
typedef parameters::internal::Initial_points_generator_generator<MD, C3T3> Initial_points_generator_generator;
void operator()(C3T3& c3t3, void operator()(C3T3& c3t3,
const MD& domain, const MD& domain,
const MC& criteria, const MC& criteria,
bool with_features, bool with_features,
Mesh_3_options mesh_options = Mesh_3_options(), Mesh_3_options mesh_options = Mesh_3_options(),
const Initial_points_generator_options& generator = Initial_points_generator_generator()()) const InitOptions& init_options = InitOptions())
{ {
if ( with_features ) { if ( with_features ) {
this->initialize_features(c3t3, domain, criteria,mesh_options); this->initialize_features(c3t3, domain, criteria,mesh_options);
@ -270,7 +286,7 @@ struct C3t3_initializer < C3T3, MD, MC, true, CGAL::Tag_true >
// If c3t3 initialization is not sufficient (may happen if there is only // If c3t3 initialization is not sufficient (may happen if there is only
// a planar curve as feature for example), add some surface points // a planar curve as feature for example), add some surface points
bool need_more_init = c3t3.triangulation().dimension() != 3 || !generator.is_default(); bool need_more_init = c3t3.triangulation().dimension() != 3 || !init_options.is_default();
if(!need_more_init) { if(!need_more_init) {
CGAL::Mesh_3::C3T3_helpers<C3T3, MD> helper(c3t3, domain); CGAL::Mesh_3::C3T3_helpers<C3T3, MD> helper(c3t3, domain);
helper.update_restricted_facets(); helper.update_restricted_facets();
@ -288,29 +304,28 @@ struct C3t3_initializer < C3T3, MD, MC, true, CGAL::Tag_true >
} }
if(need_more_init) { if(need_more_init) {
init_c3t3(c3t3, domain, criteria, init_c3t3(c3t3, domain, criteria,
mesh_options.number_of_initial_points, generator); mesh_options.number_of_initial_points, init_options);
} }
} }
else { init_c3t3(c3t3,domain,criteria, else { init_c3t3(c3t3,domain,criteria,
mesh_options.number_of_initial_points, generator); } mesh_options.number_of_initial_points, init_options); }
} }
}; };
// Partial specialization of C3t3_initializer // Partial specialization of C3t3_initializer
// Handles cases where MeshDomain::Has_features is a valid type and is defined // Handles cases where MeshDomain::Has_features is a valid type and is defined
// to CGAL::Tag_false // to CGAL::Tag_false
template < typename C3T3, typename MD, typename MC > template < typename C3T3, typename MD, typename MC, typename InitOptions >
struct C3t3_initializer < C3T3, MD, MC, true, CGAL::Tag_false > struct C3t3_initializer < C3T3, MD, MC, true, CGAL::Tag_false, InitOptions >
{ {
typedef parameters::internal::Mesh_3_options Mesh_3_options; typedef parameters::internal::Mesh_3_options Mesh_3_options;
typedef parameters::internal::Initial_points_generator_options<MD, C3T3> Initial_points_generator_options; typedef parameters::internal::Initialization_options<MD, C3T3> Initialization_options;
typedef parameters::internal::Initial_points_generator_generator<MD, C3T3> Initial_points_generator_generator;
void operator()(C3T3& c3t3, void operator()(C3T3& c3t3,
const MD& domain, const MD& domain,
const MC& criteria, const MC& criteria,
bool with_features, bool with_features,
Mesh_3_options mesh_options = Mesh_3_options(), Mesh_3_options mesh_options = Mesh_3_options(),
const Initial_points_generator_options& generator = Initial_points_generator_generator()()) const Initialization_options& init_options = Initialization_options())
{ {
if ( with_features ) if ( with_features )
{ {
@ -319,7 +334,7 @@ struct C3t3_initializer < C3T3, MD, MC, true, CGAL::Tag_false >
} }
init_c3t3(c3t3,domain,criteria, init_c3t3(c3t3,domain,criteria,
mesh_options.number_of_initial_points, generator); mesh_options.number_of_initial_points, init_options);
} }
}; };
@ -517,22 +532,28 @@ C3T3 make_mesh_3(const MeshDomain& domain, const MeshCriteria& criteria, const C
parameters::internal::Mesh_3_options mesh_options_param = choose_parameter(get_parameter(np, internal_np::mesh_param), parameters::internal::Mesh_3_options()); parameters::internal::Mesh_3_options mesh_options_param = choose_parameter(get_parameter(np, internal_np::mesh_param), parameters::internal::Mesh_3_options());
parameters::internal::Manifold_options manifold_options_param = choose_parameter(get_parameter(np, internal_np::manifold_param), parameters::internal::Manifold_options()); parameters::internal::Manifold_options manifold_options_param = choose_parameter(get_parameter(np, internal_np::manifold_param), parameters::internal::Manifold_options());
using Initial_points_generator_generator = parameters::internal::Initial_points_generator_generator<MeshDomain, C3T3>; // range of initial points
using Value_type = typename Initial_points_generator_generator::Value_type; using Initial_point = parameters::internal::Initial_point_type<MeshDomain, C3T3>;
std::vector<Value_type> empty_vec; using Initial_points_range_ref = typename internal_np::Lookup_named_param_def<internal_np::initial_points_param_t,
const auto& initial_points CGAL_NP_CLASS,
= choose_parameter(get_parameter_reference(np, internal_np::initial_points_param), empty_vec); std::vector<Initial_point>>::type;
parameters::internal::Initial_points_generator_options initial_points_generator_options_param = std::vector<Initial_point> empty_vec;
Initial_points_generator_generator() const Initial_points_range_ref initial_points = choose_parameter(get_parameter_reference(np, internal_np::initial_points_param), empty_vec);
(choose_parameter(get_parameter(np, internal_np::initial_points_generator_param),
CGAL::Null_functor()), // initial points generator
initial_points); using Initial_points_generator = typename internal_np::Lookup_named_param_def<internal_np::initial_points_generator_param_t,
CGAL_NP_CLASS,
typename MeshDomain::Construct_initial_points>::reference;
Initial_points_generator initial_points_generator = choose_parameter(get_parameter(np, internal_np::initial_points_generator_param),
domain.construct_initial_points_object());
const parameters::internal::Initialization_options<MeshDomain, C3T3, Initial_points_generator, Initial_points_range_ref>
initial_points_gen_param(initial_points_generator, initial_points);
make_mesh_3_impl(c3t3, domain, criteria, make_mesh_3_impl(c3t3, domain, criteria,
exude_param, perturb_param, odt_param, lloyd_param, exude_param, perturb_param, odt_param, lloyd_param,
features_param.features(), mesh_options_param, features_param.features(), mesh_options_param,
manifold_options_param, manifold_options_param,
initial_points_generator_options_param); initial_points_gen_param);
return c3t3; return c3t3;
} }
@ -561,7 +582,7 @@ C3T3 make_mesh_3(const MeshDomain& domain, const MeshCriteria& criteria,
* *
* @return The mesh as a C3T3 object * @return The mesh as a C3T3 object
*/ */
template<class C3T3, class MeshDomain, class MeshCriteria> template<class C3T3, class MeshDomain, class MeshCriteria, class InitPtsGenerator>
void make_mesh_3_impl(C3T3& c3t3, void make_mesh_3_impl(C3T3& c3t3,
const MeshDomain& domain, const MeshDomain& domain,
const MeshCriteria& criteria, const MeshCriteria& criteria,
@ -574,25 +595,28 @@ void make_mesh_3_impl(C3T3& c3t3,
mesh_options = parameters::internal::Mesh_3_options(), mesh_options = parameters::internal::Mesh_3_options(),
const parameters::internal::Manifold_options& const parameters::internal::Manifold_options&
manifold_options = parameters::internal::Manifold_options(), manifold_options = parameters::internal::Manifold_options(),
const parameters::internal::Initial_points_generator_options<MeshDomain, C3T3>& const parameters::internal::Initialization_options<MeshDomain, C3T3, InitPtsGenerator>&
initial_points_generator_options = parameters::internal::Initial_points_generator_generator<MeshDomain, C3T3>()()) initialization_options = parameters::internal::Initialization_options<MeshDomain, C3T3, InitPtsGenerator>())
{ {
// InitialPointsGenerator& generator = Null_functor_internal::default_null_functor
#ifdef CGAL_MESH_3_INITIAL_POINTS_NO_RANDOM_SHOOTING #ifdef CGAL_MESH_3_INITIAL_POINTS_NO_RANDOM_SHOOTING
CGAL::get_default_random() = CGAL::Random(0); CGAL::get_default_random() = CGAL::Random(0);
#endif #endif
using Init_options = parameters::internal::Initialization_options<MeshDomain, C3T3, InitPtsGenerator>;
// Initialize c3t3 // Initialize c3t3
Mesh_3::internal::C3t3_initializer< Mesh_3::internal::C3t3_initializer<
C3T3, C3T3,
MeshDomain, MeshDomain,
MeshCriteria, MeshCriteria,
::CGAL::internal::has_Has_features<MeshDomain>::value > () (c3t3, ::CGAL::internal::has_Has_features<MeshDomain>::value,
int,
Init_options>() (c3t3,
domain, domain,
criteria, criteria,
with_features, with_features,
mesh_options, mesh_options,
initial_points_generator_options); initialization_options);
CGAL_assertion( c3t3.triangulation().dimension() >= 2 ); CGAL_assertion( c3t3.triangulation().dimension() >= 2 );

View File

@ -15,6 +15,8 @@
#include <CGAL/STL_Extension/internal/Has_features.h> #include <CGAL/STL_Extension/internal/Has_features.h>
#include <boost/iterator/function_output_iterator.hpp> #include <boost/iterator/function_output_iterator.hpp>
#include <type_traits>
#include <iterator>
namespace CGAL { namespace CGAL {
@ -169,135 +171,59 @@ private:
}; };
// Mesh initialization // Mesh initialization
// This process has two parameters : `initial_points_generator` and `initial_points`.
// These two parameters are packed into a `Initial_points_generator_options`
// that do not know the parameters types.
// To remove the type of the `initial_points_generator` functor, two `std::function` are used.
// To remove the type of the `initial_points` container, two `Input_const_iterator_interface` are used.
// A common interface for an iterator to a const value. template<typename MeshDomain, typename C3t3>
template <typename Value> struct Initial_point_type
class Input_const_iterator_interface
{ {
public: typename C3t3::Triangulation::Point m_point;
virtual ~Input_const_iterator_interface() {} int m_dimension;
virtual const Value& operator*() = 0; typename MeshDomain::Index m_index;
virtual Input_const_iterator_interface<Value>* operator++() = 0;
virtual bool operator!=(const Input_const_iterator_interface<Value>* other) const = 0;
virtual Input_const_iterator_interface<Value>* clone() = 0;
};
// An iterator container that implements the `Input_const_iterator_interface` interface.
template <typename Value, typename Iterator>
struct Input_const_iterator_container
: Input_const_iterator_interface<Value>
{
typedef Input_const_iterator_container<Value, Iterator> Self;
public:
Input_const_iterator_container(const Iterator& it) : it_(it) {}
~Input_const_iterator_container() override {}
const Value& operator*() override
{
return *it_;
}
Input_const_iterator_interface<Value>* operator++() override
{
++it_;
return this;
}
bool operator!=(const Input_const_iterator_interface<Value>* other) const override
{
const Self* other_casted = dynamic_cast<const Self*>(other);
if (other_casted == nullptr)
return true;
return it_ != other_casted->it_;
}
Input_const_iterator_interface<Value>* clone() override
{
return new Input_const_iterator_container<Value, Iterator>(it_);
}
private:
Iterator it_;
}; };
// Holds the two parameters `initial_points_generator` and `initial_points`, // Holds the two parameters `initial_points_generator` and `initial_points`,
// without knowing their types, into a single generator. // without knowing their types, into a single generator.
template <typename MeshDomain, typename C3t3> template <typename MeshDomain,
struct Initial_points_generator_options typename C3t3,
typename InitialPointsGenerator = typename MeshDomain::Construct_initial_points,
typename InitialPointsRange = std::vector<Initial_point_type<MeshDomain, C3t3> > >
struct Initialization_options
{ {
typedef typename C3t3::Triangulation::Geom_traits::Weighted_point_3 Weighted_point_3; using DefaultGenerator = typename MeshDomain::Construct_initial_points;
typedef typename MeshDomain::Index Index; using Initial_points_const_iterator = typename InitialPointsRange::const_iterator;
typedef typename std::tuple<Weighted_point_3, int, Index> Value_type; using Initial_point = typename std::iterator_traits<Initial_points_const_iterator>::value_type;
typedef typename std::back_insert_iterator<std::vector<Value_type>> OutputIterator;
template <typename Initial_points_generator, typename Initial_points> Initialization_options()
Initial_points_generator_options(const Initial_points_generator& generator, const Initial_points& initial_points, bool is_default = false) : is_default_(true)
: initial_points_generator_no_number_of_points_(generator) {}
, initial_points_generator_(generator)
, is_default_(is_default && initial_points.size() == 0)
{
if (initial_points.size() == 0)
{
begin_it = nullptr;
end_it = nullptr;
}
else
{
using Iterator_type = typename Initial_points::const_iterator;
begin_it = new Input_const_iterator_container<Value_type, Iterator_type>(initial_points.cbegin());
end_it = new Input_const_iterator_container<Value_type, Iterator_type>(initial_points.cend());
}
}
~Initial_points_generator_options() Initialization_options(const InitialPointsGenerator& generator,
{ const InitialPointsRange& initial_points = InitialPointsRange())
if (begin_it != nullptr) : initial_points_generator_(generator)
delete begin_it; , begin_it(initial_points.begin())
if (end_it != nullptr) , end_it(initial_points.end())
delete end_it; , is_default_(boost::is_same<InitialPointsGenerator, DefaultGenerator>::value
} && std::empty(initial_points))
{}
// Firstly, the `initial_points` are inserted, then, the `initial_points_generator` is called. template<typename OutputIterator>
OutputIterator operator()(OutputIterator pts, const MeshDomain& domain, const C3t3& c3t3) const OutputIterator operator()(OutputIterator pts, int n = 0) const
{ {
add_initial_points(pts); // add initial_points
return initial_points_generator_no_number_of_points_(pts, domain, c3t3); for (typename InitialPointsRange::const_iterator it = begin_it; it != end_it; ++it)
} *pts++ = *it;
OutputIterator operator()(OutputIterator pts, const MeshDomain& domain, const C3t3& c3t3, int n) const return initial_points_generator_(pts, n);
{
add_initial_points(pts);
return initial_points_generator_(pts, domain, c3t3, n);
}
OutputIterator add_initial_points(OutputIterator pts) const
{
if (begin_it != nullptr && end_it != nullptr)
{
Input_const_iterator_interface<Value_type>* it_ptr = begin_it->clone();
Input_const_iterator_interface<Value_type>& it = *(it_ptr);
for (; it != end_it; ++it)
*pts++ = *it;
delete it_ptr;
}
return pts;
} }
bool is_default() const { return is_default_; } bool is_default() const { return is_default_; }
private: private:
// The two functions holds the `initial_points_generator` functor InitialPointsGenerator initial_points_generator_;
const std::function<OutputIterator(OutputIterator&,const MeshDomain&,const C3t3&)> initial_points_generator_no_number_of_points_;
const std::function<OutputIterator(OutputIterator&,const MeshDomain&,const C3t3&,int)> initial_points_generator_; // The two iterators point to the `initial_points` container
// The two iterators holds the `initial_points` container Initial_points_const_iterator begin_it;
Input_const_iterator_interface<Value_type>* begin_it; Initial_points_const_iterator end_it;
Input_const_iterator_interface<Value_type>* end_it;
// Is the option a default-constructed one ? // Is the option a default-constructed one ?
const bool is_default_; const bool is_default_;
}; };
@ -345,14 +271,14 @@ struct Domain_features_generator< MeshDomain, true >
}; };
// Evaluate the two parameters `initial_points_generator` and `initial_points` // Evaluate the two parameters `initial_points_generator` and `initial_points`
// and returns the appropriate `Initial_points_generator_options`. // and returns the appropriate `Initialization_options`.
// If no generator and no initial points, then use the domain's construct_initial_points_object. // If no generator and no initial points, then use the domain's construct_initial_points_object.
template <typename MeshDomain, typename C3t3> template <typename MeshDomain, typename C3t3>
struct Initial_points_generator_generator struct Initial_points_generator_generator
{ {
typedef typename CGAL::parameters::internal::Initial_points_generator_options<MeshDomain, C3t3> Initial_points_generator_options; typedef typename CGAL::parameters::internal::Initialization_options<MeshDomain, C3t3> Initialization_options;
typedef typename Initial_points_generator_options::Value_type Value_type; typedef typename Initialization_options::Value_type Value_type;
typedef typename Initial_points_generator_options::OutputIterator OutputIterator; typedef typename Initialization_options::OutputIterator OutputIterator;
struct Initial_points_generator_domain_traductor struct Initial_points_generator_domain_traductor
{ {
@ -392,31 +318,31 @@ struct Initial_points_generator_generator
// With a custom InitialPointsGenerator // With a custom InitialPointsGenerator
template <typename InitialPointsGenerator, typename InitalPointsRange> template <typename InitialPointsGenerator, typename InitalPointsRange>
Initial_points_generator_options operator()(const InitialPointsGenerator& initial_points_generator, const InitalPointsRange& input_features) Initialization_options operator()(const InitialPointsGenerator& initial_points_generator, const InitalPointsRange& input_points)
{ {
return Initial_points_generator_options(initial_points_generator, input_features, false); return Initialization_options(initial_points_generator, input_points, false);
} }
template <typename InitialPointsGenerator> template <typename InitialPointsGenerator>
Initial_points_generator_options operator()(const InitialPointsGenerator& initial_points_generator) Initialization_options operator()(const InitialPointsGenerator& initial_points_generator)
{ {
std::vector<Value_type> empty_input_features; std::vector<Value_type> empty_input_points;
return operator()(initial_points_generator, empty_input_features); return operator()(initial_points_generator, empty_input_points);
} }
// Without a custom InitialPointsGenerator // Without a custom InitialPointsGenerator
template <typename InitalPointsRange> template <typename InitalPointsRange>
Initial_points_generator_options operator()(const Null_functor&, const InitalPointsRange& input_features) Initialization_options operator()(const Null_functor&, const InitalPointsRange& input_points)
{ {
// The domain's construct_initial_points_object is called only if input_features is empty // The domain's construct_initial_points_object is called only if input_points is empty
if (input_features.size() == 0) { if (input_points.empty()) {
return Initial_points_generator_options(Initial_points_generator_domain_traductor(), input_features, true); return Initialization_options(Initial_points_generator_domain_traductor(), input_points, true);
} }
return Initial_points_generator_options(Initial_points_generator_empty(), input_features, true); return Initialization_options(Initial_points_generator_empty(), input_features, true);
} }
// Default construction // Default construction
Initial_points_generator_options operator()() Initialization_options operator()()
{ {
return operator()(Null_functor()); return operator()(Null_functor());
} }