diff --git a/Mesh_3/include/CGAL/Mesh_3/Protect_edges_sizing_field.h b/Mesh_3/include/CGAL/Mesh_3/Protect_edges_sizing_field.h index 409ebf16f34..096044cdea9 100644 --- a/Mesh_3/include/CGAL/Mesh_3/Protect_edges_sizing_field.h +++ b/Mesh_3/include/CGAL/Mesh_3/Protect_edges_sizing_field.h @@ -106,7 +106,7 @@ void debug_dump_c3t3(const std::string filename, const C3t3& c3t3) out << c3t3; } -template +template class Protect_edges_sizing_field : public CGAL::SMDS_3::internal::Debug_messages_tools { @@ -140,7 +140,7 @@ public: const MeshDomain& domain, SizingFunction size=SizingFunction(), const FT minimal_size = FT(), - const FT edge_distance = FT(), + DistanceFunction edge_distance = DistanceFunction(), std::size_t maximal_number_of_vertices = 0, Mesh_error_code* error_code = 0 #ifndef CGAL_NO_ATOMIC @@ -461,13 +461,36 @@ private: return s; } + /// Query the sizing field for edge distance and return its value squared at the point `p` + FT query_distance(const Bare_point& p, int dim, const Index& index) const + { + const FT d = edge_distance_(p, dim, index); + if(d <= FT(0)) { + std::stringstream msg; + msg.precision(17); + msg << "Error: the sizing field is null at "; + if(dim == 0) msg << "corner ("; + else msg << "point ("; + msg << p << ")"; +#if CGAL_MESH_3_PROTECTION_DEBUG & 4 + CGAL_error_msg(([this, str = msg.str()](){ + dump_c3t3(this->c3t3_, "dump-bug"); + return str.c_str(); + }())); +#else // not CGAL_MESH_3_PROTECTION_DEBUG & 4 + CGAL_error_msg(msg.str().c_str()); +#endif + } + return d; + } + private: C3T3& c3t3_; const MeshDomain& domain_; SizingFunction size_; FT minimal_size_; Weight minimal_weight_; - FT edge_distance_; + DistanceFunction edge_distance_; std::set treated_edges_; Vertex_set unchecked_vertices_; int refine_balls_iteration_nb; @@ -481,11 +504,11 @@ private: }; -template -Protect_edges_sizing_field:: +template +Protect_edges_sizing_field:: Protect_edges_sizing_field(C3T3& c3t3, const MD& domain, Sf size, const FT minimal_size, - const FT edge_distance, + Df edge_distance, std::size_t maximal_number_of_vertices, Mesh_error_code* error_code #ifndef CGAL_NO_ATOMIC @@ -512,9 +535,9 @@ Protect_edges_sizing_field(C3T3& c3t3, const MD& domain, } -template +template void -Protect_edges_sizing_field:: +Protect_edges_sizing_field:: operator()(const bool refine) { // This class is only meant to be used with non-periodic triangulations @@ -560,9 +583,9 @@ operator()(const bool refine) } -template +template void -Protect_edges_sizing_field:: +Protect_edges_sizing_field:: insert_corners() { // Iterate on domain corners @@ -640,9 +663,9 @@ insert_corners() } //end insert_corners() -template -typename Protect_edges_sizing_field::Vertex_handle -Protect_edges_sizing_field:: +template +typename Protect_edges_sizing_field::Vertex_handle +Protect_edges_sizing_field:: insert_point(const Bare_point& p, const Weight& w, int dim, const Index& index, const bool special_ball /* = false */) { @@ -711,11 +734,11 @@ insert_point(const Bare_point& p, const Weight& w, int dim, const Index& index, } -template +template template -std::pair::Vertex_handle, +std::pair::Vertex_handle, ErasedVeOutIt> -Protect_edges_sizing_field:: +Protect_edges_sizing_field:: smart_insert_point(const Bare_point& p, Weight w, int dim, const Index& index, ErasedVeOutIt out) { @@ -948,9 +971,9 @@ smart_insert_point(const Bare_point& p, Weight w, int dim, const Index& index, } -template +template void -Protect_edges_sizing_field:: +Protect_edges_sizing_field:: insert_balls_on_edges() { // Get features @@ -1036,9 +1059,9 @@ insert_balls_on_edges() } //end insert_balls_on_edges() -template -typename Protect_edges_sizing_field::Vertex_handle -Protect_edges_sizing_field:: +template +typename Protect_edges_sizing_field::Vertex_handle +Protect_edges_sizing_field:: get_vertex_corner_from_point(const Bare_point& p, const Index&) const { typename Gt::Construct_weighted_point_3 cwp = @@ -1057,10 +1080,10 @@ get_vertex_corner_from_point(const Bare_point& p, const Index&) const } -template +template template ErasedVeOutIt -Protect_edges_sizing_field:: +Protect_edges_sizing_field:: insert_balls(const Vertex_handle& vp, const Vertex_handle& vq, const Curve_index& curve_index, @@ -1093,10 +1116,10 @@ insert_balls(const Vertex_handle& vp, } -template +template template ErasedVeOutIt -Protect_edges_sizing_field:: +Protect_edges_sizing_field:: insert_balls(const Vertex_handle& vp, const Vertex_handle& vq, const FT sp, @@ -1329,9 +1352,9 @@ insert_balls(const Vertex_handle& vp, } -template +template void -Protect_edges_sizing_field:: +Protect_edges_sizing_field:: refine_balls() { #if CGAL_MESH_3_PROTECTION_DEBUG & 8 @@ -1467,9 +1490,9 @@ refine_balls() } // end refine_balls() -template +template bool -Protect_edges_sizing_field:: +Protect_edges_sizing_field:: non_adjacent_but_intersect(const Vertex_handle& va, const Vertex_handle& vb) const { if ( ! c3t3_.is_in_complex(va,vb) ) @@ -1480,9 +1503,9 @@ non_adjacent_but_intersect(const Vertex_handle& va, const Vertex_handle& vb) con return false; } -template +template bool -Protect_edges_sizing_field:: +Protect_edges_sizing_field:: do_balls_intersect(const Vertex_handle& va, const Vertex_handle& vb) const { typename Gt::Construct_sphere_3 sphere = @@ -1499,12 +1522,12 @@ do_balls_intersect(const Vertex_handle& va, const Vertex_handle& vb) const return do_intersect(sphere(cp(wa), cw(wa)), sphere(cp(wb), cw(wb))); } -template +template bool - Protect_edges_sizing_field:: + Protect_edges_sizing_field:: approx_is_too_large(const Vertex_handle& va, const Vertex_handle& vb) const { - if ( ! c3t3_.is_in_complex(va, vb) || edge_distance_ == 0) + if ( ! c3t3_.is_in_complex(va, vb) ) { return false; } @@ -1513,8 +1536,11 @@ bool Curve_index curve_index = c3t3_.curve_index(va, vb); Point_3 pa = va->point().point(); Point_3 pb = vb->point().point(); + Point_3 segment_middle = CGAL::midpoint(pa, pb); + // Obtain the geodesic distance between a and b and the orientation to follow CGAL::Sign orientation = domain_.distance_sign(pa, pb, curve_index); FT geodesic_distance = domain_.curve_segment_length(pa, pb, curve_index, orientation); + // Obtain the geodesic middle point Point_3 geodesic_middle; if (orientation >= 0) { @@ -1524,15 +1550,15 @@ bool { geodesic_middle = domain_.construct_point_on_curve(pb, curve_index, geodesic_distance / 2); } - Point_3 segment_middle = CGAL::midpoint(pa, pb); + // Compare distance to the parameter's distance FT squared_evaluated_distance = CGAL::squared_distance(segment_middle, geodesic_middle); - - return squared_evaluated_distance > edge_distance_ * edge_distance_; + FT segment_middle_edge_distance = query_distance(segment_middle, 1, curve_index); + return squared_evaluated_distance > CGAL::square(segment_middle_edge_distance); } -template -typename Protect_edges_sizing_field::Vertex_handle -Protect_edges_sizing_field:: +template +typename Protect_edges_sizing_field::Vertex_handle +Protect_edges_sizing_field:: change_ball_size(const Vertex_handle& v, const FT squared_size, const bool special_ball) { Weight w(squared_size); @@ -1643,9 +1669,9 @@ namespace details { } // end namespace details -template +template void -Protect_edges_sizing_field:: +Protect_edges_sizing_field:: check_and_repopulate_edges() { #if CGAL_MESH_3_PROTECTION_DEBUG & 1 @@ -1672,10 +1698,10 @@ check_and_repopulate_edges() } -template +template template ErasedVeOutIt -Protect_edges_sizing_field:: +Protect_edges_sizing_field:: check_and_fix_vertex_along_edge(const Vertex_handle& v, ErasedVeOutIt out) { #if CGAL_MESH_3_PROTECTION_DEBUG & 1 @@ -1760,9 +1786,9 @@ check_and_fix_vertex_along_edge(const Vertex_handle& v, ErasedVeOutIt out) } -template +template bool -Protect_edges_sizing_field:: +Protect_edges_sizing_field:: is_sampling_dense_enough(const Vertex_handle& v1, const Vertex_handle& v2, const Curve_index& curve_index, const CGAL::Orientation orientation) const @@ -1834,9 +1860,9 @@ is_sampling_dense_enough(const Vertex_handle& v1, const Vertex_handle& v2, } -template +template CGAL::Orientation -Protect_edges_sizing_field:: +Protect_edges_sizing_field:: orientation_of_walk(const Vertex_handle& start, const Vertex_handle& next, Curve_index curve_index) const @@ -1861,10 +1887,10 @@ orientation_of_walk(const Vertex_handle& start, } } -template +template template ErasedVeOutIt -Protect_edges_sizing_field:: +Protect_edges_sizing_field:: walk_along_edge(const Vertex_handle& start, const Vertex_handle& next, Curve_index curve_index, const CGAL::Orientation orientation, @@ -1906,9 +1932,9 @@ walk_along_edge(const Vertex_handle& start, const Vertex_handle& next, } -template -typename Protect_edges_sizing_field::Vertex_handle -Protect_edges_sizing_field:: +template +typename Protect_edges_sizing_field::Vertex_handle +Protect_edges_sizing_field:: next_vertex_along_curve(const Vertex_handle& start, const Vertex_handle& previous, const Curve_index& curve_index) const @@ -1939,10 +1965,10 @@ next_vertex_along_curve(const Vertex_handle& start, } -template +template template ErasedVeOutIt -Protect_edges_sizing_field:: +Protect_edges_sizing_field:: repopulate(InputIterator begin, InputIterator last, const Curve_index& index, const CGAL::Orientation orientation, @@ -2004,10 +2030,10 @@ repopulate(InputIterator begin, InputIterator last, } -template +template template ErasedVeOutIt -Protect_edges_sizing_field:: +Protect_edges_sizing_field:: analyze_and_repopulate(InputIterator begin, InputIterator last, const Curve_index& index, const CGAL::Orientation orientation, @@ -2079,9 +2105,9 @@ analyze_and_repopulate(InputIterator begin, InputIterator last, return out; } -template +template bool -Protect_edges_sizing_field:: +Protect_edges_sizing_field:: is_sizing_field_correct(const Vertex_handle& v1, const Vertex_handle& v2, const Vertex_handle& v3, @@ -2107,10 +2133,10 @@ is_sizing_field_correct(const Vertex_handle& v1, } -template +template template ErasedVeOutIt -Protect_edges_sizing_field:: +Protect_edges_sizing_field:: repopulate_edges_around_corner(const Vertex_handle& v, ErasedVeOutIt out) { CGAL_precondition(c3t3_.is_in_complex(v)); diff --git a/Mesh_3/include/CGAL/Mesh_criteria_3.h b/Mesh_3/include/CGAL/Mesh_criteria_3.h index f54ca2f7ae5..60ae4636e7d 100644 --- a/Mesh_3/include/CGAL/Mesh_criteria_3.h +++ b/Mesh_3/include/CGAL/Mesh_criteria_3.h @@ -74,7 +74,9 @@ public: 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::edge_min_size_param), FT(0)), - parameters::choose_parameter(parameters::get_parameter(np, internal_np::edge_distance_param), FT(0))), + parameters::choose_parameter(parameters::get_parameter(np, internal_np::edge_distance_param), + parameters::choose_parameter(parameters::get_parameter_reference(np, internal_np::edge_distance_sizing_field_param), + parameters::choose_parameter(parameters::get_parameter(np, internal_np::sizing_field_param), FT(DBL_MAX))))), 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), @@ -270,7 +272,8 @@ typedef Mesh_cell_criteria_3 Cell_criteria; * to keep the feature graph valid.} * \cgalParamNEnd * \cgalParamNBegin{edge_distance} - * \cgalParamDescription{a constant describing a upper bound for the distances between the + * \cgalParamDescription{a scalar field (resp. a constant) describing a space varying + * (resp. a uniform) upper bound for the distances between the * edge and it's coresponding input feature.} * \cgalParamNEnd * \cgalParamNBegin{facet_angle} diff --git a/Mesh_3/include/CGAL/Mesh_edge_criteria_3.h b/Mesh_3/include/CGAL/Mesh_edge_criteria_3.h index fbc56a7965d..fac9ca650e0 100644 --- a/Mesh_3/include/CGAL/Mesh_edge_criteria_3.h +++ b/Mesh_3/include/CGAL/Mesh_edge_criteria_3.h @@ -144,7 +144,11 @@ public: Point_3, Index>(length_bound)) , min_length_bound_(min_length_bound) - , distance_bound_(distance_bound) + , distance_bound_(new Mesh_3::internal::Sizing_field_container< + Mesh_constant_domain_field_3 , + FT, + Point_3, + Index>(distance_bound)) {} // Nb: SFINAE to avoid wrong matches with built-in numerical types @@ -168,7 +172,11 @@ public: #endif ) : min_length_bound_(min_length_bound) - , distance_bound_(distance_bound) + , distance_bound_(new Mesh_3::internal::Sizing_field_container< + Mesh_constant_domain_field_3 , + FT, + Point_3, + Index>(distance_bound)) { p_size_ = new Mesh_3::internal::Sizing_field_container(length_bound); } + /*! + * @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 `distance_bound` + * parameter is a functional instead of a constant. + */ + template < typename DistanceField > + Mesh_edge_criteria_3(const FT& length_bound, + const FT& min_length_bound = 0, + const DistanceField& distance_bound = 0 +#ifndef DOXYGEN_RUNNING + , std::enable_if_t::value>* = 0 +#endif + ) + : p_size_(new Mesh_3::internal::Sizing_field_container< + Mesh_constant_domain_field_3 , + FT, + Point_3, + Index>(length_bound)) + , min_length_bound_(min_length_bound) + { + distance_bound_ = new Mesh_3::internal::Sizing_field_container(distance_bound); + } + + /*! + * @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 `distance_bound` and `length_bound` + * parameters are functional instead of a constant. + */ + template < typename SizingField, typename DistanceField> + Mesh_edge_criteria_3(const SizingField& length_bound, + const FT& min_length_bound = 0, + const DistanceField& distance_bound = 0 +#ifndef DOXYGEN_RUNNING + , std::enable_if_t::value>* = 0 + , std::enable_if_t::value>* = 0 +#endif + ) + : min_length_bound_(min_length_bound) + { + p_size_ = new Mesh_3::internal::Sizing_field_container(length_bound); + distance_bound_ = new Mesh_3::internal::Sizing_field_container(distance_bound); + } + /// @} #ifndef DOXYGEN_RUNNING @@ -195,16 +261,15 @@ public: FT sizing_field(const Point_3& p, const int dim, const Index& index) const { return (*p_size_)(p,dim,index); } + FT distance_bound_field(const Point_3& p, const int dim, const Index& index) const + { return (*distance_bound_)(p,dim,index); } + public: const FT& min_length_bound() const { return min_length_bound_; } - - const FT& distance_bound() const - { - return distance_bound_; - } + #endif private: @@ -215,7 +280,7 @@ private: // real Sizing_field type Sizing_field_interface* p_size_; const FT min_length_bound_; - const FT distance_bound_; + Sizing_field_interface* distance_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 313787b2471..31f2de9b669 100644 --- a/Mesh_3/include/CGAL/make_mesh_3.h +++ b/Mesh_3/include/CGAL/make_mesh_3.h @@ -92,6 +92,22 @@ private: const EdgeCriteria& ec_; }; +template < typename EdgeCriteria > +struct Edge_criteria_distance_field_wrapper +{ + typedef typename EdgeCriteria::Index Index; + typedef typename EdgeCriteria::FT FT; + typedef typename EdgeCriteria::Point_3 Point_3; + + Edge_criteria_distance_field_wrapper(const EdgeCriteria& ec) : ec_(ec) {} + FT operator()(const Point_3& p, const int dim, const Index& index) const + { return ec_.distance_bound_field(p,dim,index); } + + private: + // No need to copy EdgeCriteria here + const EdgeCriteria& ec_; +}; + template < typename C3T3, typename MeshDomain, typename MeshCriteria> void init_c3t3_with_features(C3T3& c3t3, const MeshDomain& domain, @@ -106,13 +122,16 @@ void init_c3t3_with_features(C3T3& c3t3, { typedef typename MeshCriteria::Edge_criteria Edge_criteria; typedef Edge_criteria_sizing_field_wrapper Sizing_field; + typedef Edge_criteria_distance_field_wrapper Distance_field; +// typedef Sizing_field_container +// Sizing_field_container; - CGAL::Mesh_3::Protect_edges_sizing_field + CGAL::Mesh_3::Protect_edges_sizing_field protect_edges(c3t3, domain, Sizing_field(criteria.edge_criteria_object()), criteria.edge_criteria_object().min_length_bound(), - criteria.edge_criteria_object().distance_bound(), + Distance_field(criteria.edge_criteria_object()), maximal_number_of_vertices, pointer_to_error_code #ifndef CGAL_NO_ATOMIC 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 2940f20cdd0..892f1e137fc 100644 --- a/STL_Extension/include/CGAL/STL_Extension/internal/parameters_interface.h +++ b/STL_Extension/include/CGAL/STL_Extension/internal/parameters_interface.h @@ -339,6 +339,7 @@ CGAL_add_named_parameter_with_compatibility(input_features_param_t, input_featur CGAL_add_named_parameter_with_compatibility(edge_size_param_t, edge_size_param, edge_size) CGAL_add_named_parameter_with_compatibility_cref_only(edge_sizing_field_param_t, edge_sizing_field_param, edge_sizing_field) CGAL_add_named_parameter_with_compatibility(edge_min_size_param_t, edge_min_size_param, edge_min_size) +CGAL_add_named_parameter_with_compatibility_cref_only(edge_distance_sizing_field_param_t, edge_distance_sizing_field_param, edge_distance_sizing_field) CGAL_add_named_parameter_with_compatibility_cref_only(edge_distance_param_t, edge_distance_param, edge_distance) 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)