mirror of https://github.com/CGAL/cgal
change the distance check between constraint segment and vertex
Now it is done up-front, and not during the execution of the process.
This commit is contained in:
parent
a7f97ca017
commit
fccbeaed59
|
|
@ -248,20 +248,9 @@ protected:
|
||||||
Visitor&) {
|
Visitor&) {
|
||||||
if(va != vb) {
|
if(va != vb) {
|
||||||
if(segment_vertex_epsilon != 0.) {
|
if(segment_vertex_epsilon != 0.) {
|
||||||
if(!max_bbox_edge_length) {
|
|
||||||
update_max_bbox_edge_length();
|
|
||||||
}
|
|
||||||
auto [min_dist, min_vertex] = min_distance_and_vertex_between_constraint_and_encroaching_vertex(va, vb);
|
auto [min_dist, min_vertex] = min_distance_and_vertex_between_constraint_and_encroaching_vertex(va, vb);
|
||||||
if(min_dist < segment_vertex_epsilon * *max_bbox_edge_length) {
|
check_segment_vertex_distance_or_throw(va, vb, min_vertex, CGAL::to_double(min_dist),
|
||||||
std::stringstream ss;
|
Check_distance::NON_SQUARED_DISTANCE);
|
||||||
ss.precision(std::cerr.precision());
|
|
||||||
ss << "A constrained segment is too close to a vertex.\n";
|
|
||||||
ss << " -> vertex " << display_vert(min_vertex) << '\n';
|
|
||||||
ss << " -> constrained segment " << display_vert(va) << " - " << display_vert(vb) << '\n';
|
|
||||||
ss << " -> distance = " << min_dist << '\n';
|
|
||||||
ss << " -> max_bbox_edge_length = " << *max_bbox_edge_length << '\n';
|
|
||||||
throw std::runtime_error(ss.str());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
const Constraint_id c_id = constraint_hierarchy.insert_constraint(va, vb);
|
const Constraint_id c_id = constraint_hierarchy.insert_constraint(va, vb);
|
||||||
pair_of_vertices_to_cid.emplace(make_sorted_pair(va, vb), c_id);
|
pair_of_vertices_to_cid.emplace(make_sorted_pair(va, vb), c_id);
|
||||||
|
|
@ -439,6 +428,32 @@ public:
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum class Check_distance { SQUARED_DISTANCE, NON_SQUARED_DISTANCE };
|
||||||
|
|
||||||
|
void check_segment_vertex_distance_or_throw(Vertex_handle va,
|
||||||
|
Vertex_handle vb,
|
||||||
|
Vertex_handle min_vertex,
|
||||||
|
double min_dist,
|
||||||
|
Check_distance option)
|
||||||
|
{
|
||||||
|
if(!max_bbox_edge_length) {
|
||||||
|
update_max_bbox_edge_length();
|
||||||
|
}
|
||||||
|
if((option == Check_distance::NON_SQUARED_DISTANCE && min_dist < segment_vertex_epsilon * *max_bbox_edge_length) ||
|
||||||
|
(option == Check_distance::SQUARED_DISTANCE &&
|
||||||
|
min_dist < CGAL::square(segment_vertex_epsilon * *max_bbox_edge_length)))
|
||||||
|
{
|
||||||
|
std::stringstream ss;
|
||||||
|
ss.precision(std::cerr.precision());
|
||||||
|
ss << "A constrained segment is too close to a vertex.\n";
|
||||||
|
ss << " -> vertex " << display_vert(min_vertex) << '\n';
|
||||||
|
ss << " -> constrained segment " << display_vert(va) << " - " << display_vert(vb) << '\n';
|
||||||
|
ss << " -> distance = " << min_dist << '\n';
|
||||||
|
ss << " -> max_bbox_edge_length = " << *max_bbox_edge_length << '\n';
|
||||||
|
throw std::runtime_error(ss.str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
auto ancestors_of_Steiner_vertex_on_edge(Vertex_handle v) const {
|
auto ancestors_of_Steiner_vertex_on_edge(Vertex_handle v) const {
|
||||||
std::pair<Vertex_handle, Vertex_handle> result;
|
std::pair<Vertex_handle, Vertex_handle> result;
|
||||||
CGAL_precondition(v->is_Steiner_vertex_on_edge());
|
CGAL_precondition(v->is_Steiner_vertex_on_edge());
|
||||||
|
|
@ -471,6 +486,21 @@ public:
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto min_distance_and_vertex_between_constraint_and_encroaching_vertex(Vertex_handle va, Vertex_handle vb) const {
|
||||||
|
struct Result {
|
||||||
|
typename T_3::Geom_traits::FT min_dist = std::numeric_limits<double>::max();
|
||||||
|
Vertex_handle v = {};
|
||||||
|
} result;
|
||||||
|
const auto vector_of_encroaching_vertices = encroaching_vertices(va, vb);
|
||||||
|
for(auto v: vector_of_encroaching_vertices) {
|
||||||
|
const auto dist = CGAL::approximate_sqrt(squared_distance(tr.point(v), Line{tr.point(va), tr.point(vb)}));
|
||||||
|
if(dist < result.min_dist) {
|
||||||
|
result = Result{dist, v};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
bool write_missing_segments_file(std::ostream &out) {
|
bool write_missing_segments_file(std::ostream &out) {
|
||||||
bool any_missing_segment = false;
|
bool any_missing_segment = false;
|
||||||
std::for_each(
|
std::for_each(
|
||||||
|
|
@ -753,21 +783,6 @@ protected:
|
||||||
return vector_of_encroaching_vertices;
|
return vector_of_encroaching_vertices;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto min_distance_and_vertex_between_constraint_and_encroaching_vertex(Vertex_handle va, Vertex_handle vb) const {
|
|
||||||
struct Result {
|
|
||||||
typename T_3::Geom_traits::FT min_dist = std::numeric_limits<double>::max();
|
|
||||||
Vertex_handle v = {};
|
|
||||||
} result;
|
|
||||||
const auto vector_of_encroaching_vertices = encroaching_vertices(va, vb);
|
|
||||||
for(auto v: vector_of_encroaching_vertices) {
|
|
||||||
const auto dist = CGAL::approximate_sqrt(squared_distance(tr.point(v), Line{tr.point(va), tr.point(vb)}));
|
|
||||||
if(dist < result.min_dist) {
|
|
||||||
result = Result{dist, v};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
Construct_Steiner_point_return_type
|
Construct_Steiner_point_return_type
|
||||||
construct_Steiner_point(Constraint_id constraint_id, Subconstraint subconstraint)
|
construct_Steiner_point(Constraint_id constraint_id, Subconstraint subconstraint)
|
||||||
{
|
{
|
||||||
|
|
@ -867,16 +882,8 @@ protected:
|
||||||
update_max_bbox_edge_length();
|
update_max_bbox_edge_length();
|
||||||
}
|
}
|
||||||
auto sq_dist = squared_distance(reference_point, Line{orig_pa, orig_pb});
|
auto sq_dist = squared_distance(reference_point, Line{orig_pa, orig_pb});
|
||||||
if(sq_dist < CGAL::square(segment_vertex_epsilon * *max_bbox_edge_length)) {
|
check_segment_vertex_distance_or_throw(orig_va, orig_vb, reference_vertex, CGAL::to_double(sq_dist),
|
||||||
std::stringstream ss;
|
Check_distance::SQUARED_DISTANCE);
|
||||||
ss.precision(std::cerr.precision());
|
|
||||||
ss << "A constrained segment is too close to a vertex.\n";
|
|
||||||
ss << " -> vertex " << display_vert(reference_vertex) << '\n';
|
|
||||||
ss << " -> constrained segment " << display_vert(orig_va) << " - " << display_vert(orig_vb) << '\n';
|
|
||||||
ss << " -> distance = " << CGAL::approximate_sqrt(sq_dist) << '\n';
|
|
||||||
ss << " -> max_bbox_edge_length = " << *max_bbox_edge_length << '\n';
|
|
||||||
throw std::runtime_error(ss.str());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// compute the projection of the reference point
|
// compute the projection of the reference point
|
||||||
|
|
|
||||||
|
|
@ -71,8 +71,8 @@ struct CDT_options
|
||||||
bool use_new_cavity_algorithm = true;
|
bool use_new_cavity_algorithm = true;
|
||||||
bool debug_validity = false;
|
bool debug_validity = false;
|
||||||
double ratio = 0.1;
|
double ratio = 0.1;
|
||||||
double vertex_vertex_epsilon = 1e-6;
|
double vertex_vertex_epsilon = 1e-14;
|
||||||
double segment_vertex_epsilon = 1e-8;
|
double segment_vertex_epsilon = 1e-14;
|
||||||
std::string failure_assertion_expression{};
|
std::string failure_assertion_expression{};
|
||||||
std::string input_filename = CGAL::data_file_path("meshes/mpi.off");
|
std::string input_filename = CGAL::data_file_path("meshes/mpi.off");
|
||||||
std::string output_filename{"dump.off"};
|
std::string output_filename{"dump.off"};
|
||||||
|
|
@ -357,10 +357,10 @@ int go(Mesh mesh, CDT_options options) {
|
||||||
|
|
||||||
auto pmap = get(CGAL::vertex_point, mesh);
|
auto pmap = get(CGAL::vertex_point, mesh);
|
||||||
|
|
||||||
auto [patch_id_map, ok] = mesh.add_property_map<face_descriptor, int>("f:patch_id", -2);
|
auto [patch_id_map, patch_id_map_ok] = mesh.add_property_map<face_descriptor, int>("f:patch_id", -2);
|
||||||
assert(ok); CGAL_USE(ok);
|
assert(patch_id_map_ok); CGAL_USE(patch_id_map_ok);
|
||||||
auto [v_selected_map, ok2] = mesh.add_property_map<vertex_descriptor, bool>("v:selected", false);
|
auto [v_selected_map, v_selected_map_ok] = mesh.add_property_map<vertex_descriptor, bool>("v:selected", false);
|
||||||
assert(ok2); CGAL_USE(ok2);
|
assert(v_selected_map_ok); CGAL_USE(v_selected_map_ok);
|
||||||
int nb_patches = 0;
|
int nb_patches = 0;
|
||||||
std::vector<std::vector<std::pair<vertex_descriptor, vertex_descriptor>>> patch_edges;
|
std::vector<std::vector<std::pair<vertex_descriptor, vertex_descriptor>>> patch_edges;
|
||||||
if(options.merge_facets) {
|
if(options.merge_facets) {
|
||||||
|
|
@ -490,10 +490,14 @@ int go(Mesh mesh, CDT_options options) {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
auto [tr_vertex_pmap, tr_vertex_pmap_ok] = mesh.add_property_map<vertex_descriptor, CDT::Vertex_handle>("tr_vertex");
|
||||||
|
assert(tr_vertex_pmap_ok); CGAL_USE(tr_vertex_pmap_ok);
|
||||||
|
|
||||||
auto start_time = std::chrono::high_resolution_clock::now();
|
auto start_time = std::chrono::high_resolution_clock::now();
|
||||||
for(auto v: vertices(mesh)) {
|
for(auto v: vertices(mesh)) {
|
||||||
if(options.merge_facets && false == get(v_selected_map, v)) continue;
|
if(options.merge_facets && false == get(v_selected_map, v)) continue;
|
||||||
cdt.insert(get(pmap, v));
|
auto vh = cdt.insert(get(pmap, v));
|
||||||
|
put(tr_vertex_pmap, v, vh);
|
||||||
}
|
}
|
||||||
if(!options.quiet) {
|
if(!options.quiet) {
|
||||||
std::cout << "[timings] inserted vertices in " << std::chrono::duration_cast<std::chrono::milliseconds>(
|
std::cout << "[timings] inserted vertices in " << std::chrono::duration_cast<std::chrono::milliseconds>(
|
||||||
|
|
@ -517,6 +521,7 @@ int go(Mesh mesh, CDT_options options) {
|
||||||
cdt.insert(Point(bbox.xmax() + d_x, bbox.ymin() - d_y, bbox.zmax() + d_z));
|
cdt.insert(Point(bbox.xmax() + d_x, bbox.ymin() - d_y, bbox.zmax() + d_z));
|
||||||
cdt.insert(Point(bbox.xmax() + d_x, bbox.ymax() + d_y, bbox.zmax() + d_z));
|
cdt.insert(Point(bbox.xmax() + d_x, bbox.ymax() + d_y, bbox.zmax() + d_z));
|
||||||
}
|
}
|
||||||
|
start_time = std::chrono::high_resolution_clock::now();
|
||||||
{
|
{
|
||||||
auto [min_sq_distance, min_edge] = std::ranges::min(
|
auto [min_sq_distance, min_edge] = std::ranges::min(
|
||||||
cdt.finite_edges() | std::views::transform([&](auto edge) { return std::make_pair(cdt.segment(edge).squared_length(), edge); }));
|
cdt.finite_edges() | std::views::transform([&](auto edge) { return std::make_pair(cdt.segment(edge).squared_length(), edge); }));
|
||||||
|
|
@ -533,6 +538,57 @@ int go(Mesh mesh, CDT_options options) {
|
||||||
return exit_code;
|
return exit_code;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
{
|
||||||
|
double min_distance = std::numeric_limits<double>::max();
|
||||||
|
CDT::Vertex_handle min_va, min_vb, min_vertex;
|
||||||
|
if(options.merge_facets) {
|
||||||
|
for(int i = 0; i < nb_patches; ++i) {
|
||||||
|
const auto& edges = patch_edges[i];
|
||||||
|
for(auto [vda, vdb]: edges) {
|
||||||
|
auto va = get(tr_vertex_pmap, vda);
|
||||||
|
auto vb = get(tr_vertex_pmap, vdb);
|
||||||
|
auto [min_dist, min_v] = cdt.min_distance_and_vertex_between_constraint_and_encroaching_vertex(va, vb);
|
||||||
|
if(min_dist < min_distance) {
|
||||||
|
min_distance = CGAL::to_double(min_dist);
|
||||||
|
min_va = va;
|
||||||
|
min_vb = vb;
|
||||||
|
min_vertex = min_v;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for(auto face_descriptor : faces(mesh)) {
|
||||||
|
auto he = halfedge(face_descriptor, mesh);
|
||||||
|
const auto end = he;
|
||||||
|
do {
|
||||||
|
auto va = get(tr_vertex_pmap, source(he, mesh));
|
||||||
|
auto vb = get(tr_vertex_pmap, target(he, mesh));
|
||||||
|
auto [min_dist, min_v] = cdt.min_distance_and_vertex_between_constraint_and_encroaching_vertex(va, vb);
|
||||||
|
if(min_dist < min_distance) {
|
||||||
|
min_distance = CGAL::to_double(min_dist);
|
||||||
|
min_va = va;
|
||||||
|
min_vb = vb;
|
||||||
|
min_vertex = min_v;
|
||||||
|
}
|
||||||
|
he = next(he, mesh);
|
||||||
|
} while((he = next(he, mesh)) != end);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(!options.quiet) {
|
||||||
|
std::cout << "Min distance between constraint segment and vertex: " << min_distance << '\n'
|
||||||
|
<< " between segment : "
|
||||||
|
<< CGAL::IO::oformat(min_va, CDT::Conforming_Dt::with_point) << " "
|
||||||
|
<< CGAL::IO::oformat(min_vb, CDT::Conforming_Dt::with_point) << '\n'
|
||||||
|
<< " and vertex: : "
|
||||||
|
<< CGAL::IO::oformat(min_vertex, CDT::Conforming_Dt::with_point) << "\n\n";
|
||||||
|
}
|
||||||
|
cdt.check_segment_vertex_distance_or_throw(min_va, min_vb, min_vertex, min_distance,
|
||||||
|
CDT::Check_distance::NON_SQUARED_DISTANCE);
|
||||||
|
}
|
||||||
|
if(!options.quiet) {
|
||||||
|
std::cout << "[timings] compute distances on " << std::chrono::duration_cast<std::chrono::milliseconds>(
|
||||||
|
std::chrono::high_resolution_clock::now() - start_time).count() << " ms\n";
|
||||||
|
}
|
||||||
int poly_id = 0;
|
int poly_id = 0;
|
||||||
CDT_3_try {
|
CDT_3_try {
|
||||||
start_time = std::chrono::high_resolution_clock::now();
|
start_time = std::chrono::high_resolution_clock::now();
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue