diff --git a/.gitignore b/.gitignore index 74e4fdc1f4a0..e6ecde661dcd 100644 --- a/.gitignore +++ b/.gitignore @@ -1077,6 +1077,12 @@ Makefile *.sln *.depends +# Output files of tetgen +*.edge +*.cell +*.node +*.smesh + # The rest: "various" things that I do not know how to classify # -- Laurent Rineau, 2013/01/11 *.ncb @@ -1163,10 +1169,11 @@ Data/data/meshes/*.*.vtk Data/data/meshes/*.log Data/data/meshes/*.off-cdt-output.off dump_*.off +dump_*.ply dump_*.txt -dump-*.binary.cgal -dump-*.polylines.txt -dump-*.xyz +dump*.binary.cgal +dump*.polylines.txt +dump*.xyz dump.off.mesh log.txt patches_after_merge.ply diff --git a/Constrained_triangulation_3/include/CGAL/Conforming_Delaunay_triangulation_3.h b/Constrained_triangulation_3/include/CGAL/Conforming_Delaunay_triangulation_3.h index 06f383e0ff1d..6d44949161b5 100644 --- a/Constrained_triangulation_3/include/CGAL/Conforming_Delaunay_triangulation_3.h +++ b/Constrained_triangulation_3/include/CGAL/Conforming_Delaunay_triangulation_3.h @@ -14,7 +14,7 @@ #include -#include +#include // IWYU pragma: export #include #include @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -33,6 +34,7 @@ #include #include #include +#include #include #include @@ -45,6 +47,7 @@ #include #include #include +#include #include #include #include @@ -72,12 +75,17 @@ namespace CGAL { namespace CDT_3 { struct Debug_options { - enum class Flags { + enum class Flag; + bool get(Flag f) const { return flags[static_cast(f)]; } + auto get(Flag f) { return flags[static_cast(f)]; } + enum class Flag { Steiner_points = 0, Steiner_points_construction, conforming, input_faces, missing_region, + debug_missing_triangles, + flips, regions, copy_triangulation_into_hole, validity, @@ -91,71 +99,102 @@ struct Debug_options { debug_geometric_errors, debug_polygon_insertion, debug_restore_faces, + debug_move_Steiner_vertices_bit1, + debug_move_Steiner_vertices_bit2, display_statistics, use_epeck_for_normals, use_epeck_for_Steiner_points, + move_Steiner_vertices_allow_negative_tets, + use_flips_to_recover_segments, nb_of_flags }; - bool Steiner_points_construction() const { return flags[static_cast(Flags::Steiner_points_construction)]; } - void Steiner_points_construction(bool b) { flags.set(static_cast(Flags::Steiner_points_construction), b); } - bool Steiner_points() const { return flags[static_cast(Flags::Steiner_points)]; } - void Steiner_points(bool b) { flags.set(static_cast(Flags::Steiner_points), b); } + using Flags = std::bitset(Flag::nb_of_flags)>; - bool input_faces() const { return flags[static_cast(Flags::input_faces)]; } - void input_faces(bool b) { flags.set(static_cast(Flags::input_faces), b); } + bool Steiner_points_construction() const { return get(Flag::Steiner_points_construction); } + void Steiner_points_construction(bool b) { get(Flag::Steiner_points_construction) = b; } - bool missing_region() const { return flags[static_cast(Flags::missing_region)]; } - void missing_region(bool b) { flags.set(static_cast(Flags::missing_region), b); } + bool Steiner_points() const { return get(Flag::Steiner_points); } + void Steiner_points(bool b) { get(Flag::Steiner_points) = b; } - bool regions() const { return flags[static_cast(Flags::regions)]; } - void regions(bool b) { flags.set(static_cast(Flags::regions), b); } + bool input_faces() const { return get(Flag::input_faces); } + void input_faces(bool b) { get(Flag::input_faces) = b; } - bool copy_triangulation_into_hole() const { return flags[static_cast(Flags::copy_triangulation_into_hole)]; } - void copy_triangulation_into_hole(bool b) { flags.set(static_cast(Flags::copy_triangulation_into_hole), b); } + bool missing_region() const { return get(Flag::missing_region); } + void missing_region(bool b) { get(Flag::missing_region) = b; } - bool validity() const { return flags[static_cast(Flags::validity)]; } - void validity(bool b) { flags.set(static_cast(Flags::validity), b); } + bool missing_triangles() const { return get(Flag::debug_missing_triangles); } + void missing_triangles(bool b) { get(Flag::debug_missing_triangles) = b; } + bool flips() const { return get(Flag::flips); } + void flips(bool b) { get(Flag::flips) = b; } - bool finite_edges_map() const { return flags[static_cast(Flags::debug_finite_edges_map)]; } - void finite_edges_map(bool b) { flags.set(static_cast(Flags::debug_finite_edges_map), b); } + bool regions() const { return get(Flag::regions); } + void regions(bool b) { get(Flag::regions) = b; } - bool subconstraints_to_conform() const { return flags[static_cast(Flags::debug_subconstraints_to_conform)]; } - void subconstraints_to_conform(bool b) { flags.set(static_cast(Flags::debug_subconstraints_to_conform), b); } + bool copy_triangulation_into_hole() const { return get(Flag::copy_triangulation_into_hole); } + void copy_triangulation_into_hole(bool b) { get(Flag::copy_triangulation_into_hole) = b; } - bool use_finite_edges_map_flag() const { return flags[static_cast(Flags::use_finite_edges_map)]; } - void use_finite_edges_map(bool b) { flags.set(static_cast(Flags::use_finite_edges_map), b); } + bool validity() const { return get(Flag::validity); } + void validity(bool b) { get(Flag::validity) = b; } - bool verbose_special_cases() const { return flags[static_cast(Flags::verbose_special_cases)]; } - void verbose_special_cases(bool b) { flags.set(static_cast(Flags::verbose_special_cases), b); } + bool finite_edges_map() const { return get(Flag::debug_finite_edges_map); } + void finite_edges_map(bool b) { get(Flag::debug_finite_edges_map) = b; } - bool encroaching_vertices() const { return flags[static_cast(Flags::debug_encroaching_vertices)]; } - void encroaching_vertices(bool b) { flags.set(static_cast(Flags::debug_encroaching_vertices), b); } + bool subconstraints_to_conform() const { return get(Flag::debug_subconstraints_to_conform); } + void subconstraints_to_conform(bool b) { get(Flag::debug_subconstraints_to_conform) = b; } - bool conforming_validation() const { return flags[static_cast(Flags::debug_conforming_validation)]; } - void conforming_validation(bool b) { flags.set(static_cast(Flags::debug_conforming_validation), b); } + bool use_finite_edges_map_flag() const { return get(Flag::use_finite_edges_map); } + void use_finite_edges_map(bool b) { get(Flag::use_finite_edges_map) = b; } - bool constraint_hierarchy() const { return flags[static_cast(Flags::debug_constraint_hierarchy)]; } - void constraint_hierarchy(bool b) { flags.set(static_cast(Flags::debug_constraint_hierarchy), b); } + bool verbose_special_cases() const { return get(Flag::verbose_special_cases); } + void verbose_special_cases(bool b) { get(Flag::verbose_special_cases) = b; } - bool geometric_errors() const { return flags[static_cast(Flags::debug_geometric_errors)]; } - void geometric_errors(bool b) { flags.set(static_cast(Flags::debug_geometric_errors), b); } + bool encroaching_vertices() const { return get(Flag::debug_encroaching_vertices); } + void encroaching_vertices(bool b) { get(Flag::debug_encroaching_vertices) = b; } - bool polygon_insertion() const { return flags[static_cast(Flags::debug_polygon_insertion)]; } - void polygon_insertion(bool b) { flags.set(static_cast(Flags::debug_polygon_insertion), b); } + bool conforming_validation() const { return get(Flag::debug_conforming_validation); } + void conforming_validation(bool b) { get(Flag::debug_conforming_validation) = b; } - bool restore_faces() const { return flags[static_cast(Flags::debug_restore_faces)]; } - void restore_faces(bool b) { flags.set(static_cast(Flags::debug_restore_faces), b); } + bool constraint_hierarchy() const { return get(Flag::debug_constraint_hierarchy); } + void constraint_hierarchy(bool b) { get(Flag::debug_constraint_hierarchy) = b; } - bool display_statistics() const { return flags[static_cast(Flags::display_statistics)]; } - void display_statistics(bool b) { flags.set(static_cast(Flags::display_statistics), b); } + bool geometric_errors() const { return get(Flag::debug_geometric_errors); } + void geometric_errors(bool b) { get(Flag::debug_geometric_errors) = b; } - bool use_epeck_for_normals() const { return flags[static_cast(Flags::use_epeck_for_normals)]; } - void use_epeck_for_normals(bool b) { flags.set(static_cast(Flags::use_epeck_for_normals), b); } + bool polygon_insertion() const { return get(Flag::debug_polygon_insertion); } + void polygon_insertion(bool b) { get(Flag::debug_polygon_insertion) = b; } - bool use_epeck_for_Steiner_points() const { return flags[static_cast(Flags::use_epeck_for_Steiner_points)]; } - void use_epeck_for_Steiner_points(bool b) { flags.set(static_cast(Flags::use_epeck_for_Steiner_points), b); } + bool restore_faces() const { return get(Flag::debug_restore_faces); } + void restore_faces(bool b) { get(Flag::debug_restore_faces) = b; } + + bool move_Steiner_vertices() const { + return get(Flag::debug_move_Steiner_vertices_bit1) || get(Flag::debug_move_Steiner_vertices_bit2); + } + + unsigned int move_Steiner_vertices_level() const { + return get(Flag::debug_move_Steiner_vertices_bit1) + 2 * get(Flag::debug_move_Steiner_vertices_bit2); + } + void move_Steiner_vertices(unsigned int level) { + CGAL_assertion(level <= 3); + get(Flag::debug_move_Steiner_vertices_bit1) = level & 1; + get(Flag::debug_move_Steiner_vertices_bit2) = (level >> 1) & 1; + } + + bool move_Steiner_vertices_allow_negative_tets() const { return get(Flag::move_Steiner_vertices_allow_negative_tets); } + void move_Steiner_vertices_allow_negative_tets(bool b) { get(Flag::move_Steiner_vertices_allow_negative_tets) = b; } + + bool display_statistics() const { return get(Flag::display_statistics); } + void display_statistics(bool b) { get(Flag::display_statistics) = b; } + + bool use_epeck_for_normals() const { return get(Flag::use_epeck_for_normals); } + void use_epeck_for_normals(bool b) { get(Flag::use_epeck_for_normals) = b; } + + bool use_epeck_for_Steiner_points() const { return get(Flag::use_epeck_for_Steiner_points); } + void use_epeck_for_Steiner_points(bool b) { get(Flag::use_epeck_for_Steiner_points) = b; } + + bool use_flips_to_recover_segments() const { return get(Flag::use_flips_to_recover_segments); } + void use_flips_to_recover_segments(bool b) { get(Flag::use_flips_to_recover_segments) = b; } double segment_vertex_epsilon() const { return segment_vertex_epsilon_; } void set_segment_vertex_epsilon(double eps) { segment_vertex_epsilon_ = eps; } @@ -164,7 +203,7 @@ struct Debug_options { void set_vertex_vertex_epsilon(double eps) { vertex_vertex_epsilon_ = eps; } private: - std::bitset(Flags::nb_of_flags)> flags{}; + Flags flags{}; double segment_vertex_epsilon_ = 0.0; double vertex_vertex_epsilon_ = 0.0; }; // end struct Debug_options @@ -173,13 +212,14 @@ namespace internal { inline auto& tasks_manager() { struct Tasks_manager { - enum { + enum class Tm { READ_INPUT = 0, MERGE_FACETS, INSERT_VERTICES, COMPUTE_DISTANCES, CONFORMING, CDT, + MOVE_STEINER_VERTICES, OUTPUT, VALIDATION, NB_TASKS @@ -187,18 +227,19 @@ inline auto& tasks_manager() { #if CGAL_USE_ITT __itt_domain* cdt_3_domain = __itt_domain_create("org.cgal.CDT_3"); - const std::array<__itt_string_handle*, NB_TASKS> task_handles = { + const std::array<__itt_string_handle*, static_cast(Tm::NB_TASKS)> task_handles = { __itt_string_handle_create("CDT_3: read input file"), __itt_string_handle_create("CDT_3: merge facets"), __itt_string_handle_create("CDT_3: insert vertices"), __itt_string_handle_create("CDT_3: compute distances"), __itt_string_handle_create("CDT_3: conforming"), __itt_string_handle_create("CDT_3: cdt"), + __itt_string_handle_create("CDT_3: move Steiner vertices"), __itt_string_handle_create("CDT_3: outputs"), __itt_string_handle_create("CDT_3: validation") }; #endif - std::array timers{}; + std::array(Tm::NB_TASKS)> timers{}; struct Scope_guard { Tasks_manager *instance = nullptr; int task_id; @@ -222,18 +263,19 @@ inline auto& tasks_manager() { } }; - Scope_guard make_task_scope_guard(int task_id) { - return Scope_guard(this, task_id); + Scope_guard make_task_scope_guard(Tm task_id) { + return Scope_guard(this, static_cast(task_id)); } - Scope_guard READ_INPUT_TASK_guard() { return make_task_scope_guard(READ_INPUT); } - Scope_guard MERGE_FACETS_TASK_guard() { return make_task_scope_guard(MERGE_FACETS); } - Scope_guard INSERT_VERTICES_TASK_guard() { return make_task_scope_guard(INSERT_VERTICES); } - Scope_guard COMPUTE_DISTANCES_TASK_guard() { return make_task_scope_guard(COMPUTE_DISTANCES); } - Scope_guard CONFORMING_TASK_guard() { return make_task_scope_guard(CONFORMING); } - Scope_guard CDT_TASK_guard() { return make_task_scope_guard(CDT); } - Scope_guard OUTPUT_TASK_guard() { return make_task_scope_guard(OUTPUT); } - Scope_guard VALIDATION_TASK_guard() { return make_task_scope_guard(VALIDATION); } + Scope_guard READ_INPUT_TASK_guard() { return make_task_scope_guard(Tm::READ_INPUT); } + Scope_guard MERGE_FACETS_TASK_guard() { return make_task_scope_guard(Tm::MERGE_FACETS); } + Scope_guard INSERT_VERTICES_TASK_guard() { return make_task_scope_guard(Tm::INSERT_VERTICES); } + Scope_guard COMPUTE_DISTANCES_TASK_guard() { return make_task_scope_guard(Tm::COMPUTE_DISTANCES); } + Scope_guard CONFORMING_TASK_guard() { return make_task_scope_guard(Tm::CONFORMING); } + Scope_guard CDT_TASK_guard() { return make_task_scope_guard(Tm::CDT); } + Scope_guard MOVE_STEINER_VERTICES_TASK_guard() { return make_task_scope_guard(Tm::MOVE_STEINER_VERTICES); } + Scope_guard OUTPUT_TASK_guard() { return make_task_scope_guard(Tm::OUTPUT); } + Scope_guard VALIDATION_TASK_guard() { return make_task_scope_guard(Tm::VALIDATION); } }; // end struct Intel_OneAPI_ITT_API @@ -273,6 +315,10 @@ inline auto CDT_3_OUTPUT_TASK_guard() { return CDT_3::internal::tasks_manager().OUTPUT_TASK_guard(); } +inline auto CDT_3_MOVE_STEINER_VERTICES_TASK_guard() { + return CDT_3::internal::tasks_manager().MOVE_STEINER_VERTICES_TASK_guard(); +} + inline auto CDT_3_VALIDATION_TASK_guard() { return CDT_3::internal::tasks_manager().VALIDATION_TASK_guard(); } @@ -291,9 +337,17 @@ class Conforming_Delaunay_triangulation_3 : public T_3 { using Line = typename T_3::Geom_traits::Line_3; using Locate_type = typename T_3::Locate_type; - inline static With_offset_tag with_offset{ -1 }; - inline static With_point_tag with_point{ {-1} }; - inline static With_point_and_info_tag with_point_and_info{ { {-1} } }; + inline static With_offset_tag with_offset_tag{ -1 }; + With_point_tag with_point_tag{ {-1}, this }; + With_point_and_info_tag with_point_and_info_tag{ { {-1}, this } }; + + auto with_point(Vertex_handle v) const { + return IO::oformat(v, with_point_tag); + } + + auto with_point_and_info(Vertex_handle v) const { + return IO::oformat(v, with_point_and_info_tag); + } Conforming_Delaunay_triangulation_3(const Geom_traits& gt = Geom_traits()) : T_3(gt) @@ -318,16 +372,34 @@ class Conforming_Delaunay_triangulation_3 : public T_3 { using Subconstraint = typename Constraint_hierarchy::Subconstraint; auto display_vert(Vertex_handle v) const{ - std::stringstream os; - os.precision(17); - os << IO::oformat(v, with_point); - return os.str(); + return IO::oformat(v, with_point_tag); + } + + auto display_facet(Vertex_handle v0, Vertex_handle v1, Vertex_handle v2) const { + return IO::oformat( + [v0, v1, v2, this](std::ostream& os) -> auto& { + os << "(" << this->display_vert(v0) << ", " << this->display_vert(v1) << ", " << this->display_vert(v2) + << ")"; + return os; + }, + IO_manip_tag{}); + } + + auto display_facet(Facet f) const { + return IO::oformat( + [f, this](std::ostream& os) -> auto& { + auto [v0, v1, v2] = T_3::vertices(f); + os << "(" << this->display_vert(v0) << ", " << this->display_vert(v1) << ", " << this->display_vert(v2) + << ")"; + return os; + }, + IO_manip_tag{}); } auto display_subcstr(Subconstraint subconstraint) const { auto [va, vb] = subconstraint; std::stringstream os; - os << "(" << IO::oformat(va, with_offset) << ", " << IO::oformat(vb, with_offset) << ")" + os << "(" << with_offset(va) << ", " << with_offset(vb) << ")" << ": [ " << display_vert(va) << " - " << display_vert(vb) << " ]"; return os.str(); } @@ -339,24 +411,29 @@ class Conforming_Delaunay_triangulation_3 : public T_3 { Insert_in_conflict_visitor(Conforming_Delaunay_triangulation_3* self) : self(self) {} template - void process_cells_in_conflict(InputIterator cell_it, InputIterator end) { + void process_cells_in_conflict(InputIterator cell_it, InputIterator end) + { const CGAL::unordered_flat_set cells_set(cell_it, end); - std::set> edges_in_conflict; - auto d = self->tr().dimension(); - for( ; cell_it != end; ++cell_it ) { - for( int i = 0; i < d; ++i ) { - const auto n = (*cell_it)->neighbor(i); - if(cells_set.find(n) == cells_set.end()) continue; - // here: (c, i) is a facet internal to the conflict region - for(int j = 0; j < 3; ++j ) { - auto v1 = (*cell_it)->vertex(self->tr().vertex_triple_index(i, j)); - auto v2 = (*cell_it)->vertex(self->tr().vertex_triple_index(i, self->tr().cw(j))); - if(self->tr().is_infinite(v1) || self->tr().is_infinite(v2)) continue; - edges_in_conflict.insert(CGAL::make_sorted_pair(v1, v2)); + std::set border_facets; + std::set> cavity_edges; + for(auto c : cells_set) { + for(int i = 0; i < 4; ++i) { + if(!cells_set.count(c->neighbor(i))) { + border_facets.emplace(c, i); + } + for(int j = i + 1; j < 4; ++j) { + cavity_edges.emplace(make_sorted_pair(c->vertex(i), c->vertex(j))); } } } - for(auto [v1, v2]: edges_in_conflict) { + for(auto f : border_facets) { + const auto f_vertices = T_3::vertices(f); + for(int i = 0; i < 3; ++i) { + cavity_edges.erase(make_sorted_pair(f_vertices[i], f_vertices[T_3::ccw(i)])); + } + } + + for(auto [v1, v2]: cavity_edges) { if(self->use_finite_edges_map()) { auto v1_index = v1->time_stamp(); [[maybe_unused]] auto nb_erased = self->all_finite_edges[v1_index].erase(v2); @@ -407,6 +484,10 @@ class Conforming_Delaunay_triangulation_3 : public T_3 { { } + bool is_facet_protected(Facet ) const { return false; } + + void after_flip23(Vertex_handle, Vertex_handle, Facet) const {} + Vertex_handle insert_in_triangulation(const Point& p, Locate_type lt, Cell_handle c, int li, int lj) { return self->insert_impl_do_not_split(p, lt, c, li, lj, *this); } @@ -440,7 +521,7 @@ class Conforming_Delaunay_triangulation_3 : public T_3 { // vertices as sub-constraints. std::for_each(tr().segment_traverser_simplices_begin(va, vb), tr().segment_traverser_simplices_end(), [&, prev = Vertex_handle{}](auto simplex) mutable { - // std::cerr << "- " << oformat(simplex, With_point_tag{}) << '\n'; + // std::cerr << "- " << oformat(simplex, with_point_tag) << '\n'; if(simplex.dimension() == 0) { const auto v = static_cast(simplex); v->ccdt_3_data().set_on_constraint(c_id); @@ -564,6 +645,8 @@ class Conforming_Delaunay_triangulation_3 : public T_3 { public: CDT_3::Debug_options& debug() { return debug_options_; } const CDT_3::Debug_options& debug() const { return debug_options_; } + CDT_3::Debug_options& options() { return debug_options_; } + const CDT_3::Debug_options& options() const { return debug_options_; } // Backward compatibility wrappers (deprecated, use debug().method() instead) bool use_finite_edges_map() const { return update_all_finite_edges_ && debug_options_.use_finite_edges_map_flag(); } @@ -624,14 +707,18 @@ class Conforming_Delaunay_triangulation_3 : public T_3 { const auto is_edge = this->is_edge(va, vb); if constexpr (cdt_3_can_use_cxx20_format()) if(debug().conforming_validation()) { std::cerr << cdt_3_format("is_conforming>> Edge is 3D: {} ({} , {})\n", - is_edge, - CGAL::IO::oformat(va, with_point_and_info), - CGAL::IO::oformat(vb, with_point_and_info)); + is_edge, + with_point_and_info(va), + with_point_and_info(vb)); } return is_edge; }); } + auto all_constrained_edges () const { + return constraint_hierarchy.subconstraints(); + } + enum class Check_distance { SQUARED_DISTANCE, NON_SQUARED_DISTANCE }; void check_segment_vertex_distance_or_throw(Vertex_handle va, @@ -752,7 +839,6 @@ class Conforming_Delaunay_triangulation_3 : public T_3 { /// @{ /// remove functions cannot be called - void remove(Vertex_handle) = delete; void remove_cluster() = delete; /// @} @@ -774,6 +860,15 @@ class Conforming_Delaunay_triangulation_3 : public T_3 { } } + bool has_constrained_edges_to_restore() const { + return !subconstraints_to_conform.empty(); + } + + template + void restore_constrained_edges(Visitor& visitor) { + return restore_Delaunay(visitor); + } + template void restore_Delaunay(Visitor& visitor) { update_all_finite_edges(); @@ -810,7 +905,7 @@ class Conforming_Delaunay_triangulation_3 : public T_3 { ss << "insert_Steiner_point_on_subconstraint: Steiner point coincides with an existing vertex\n"; ss << " -> Steiner point: " << steiner_pt << '\n'; ss << " on constraint: " << display_vert(c_va) << " - " << display_vert(c_vb) << '\n'; - ss << " -> existing vertex: " << IO::oformat(other_v, with_point_and_info) << '\n'; + ss << " -> existing vertex: " << display_vert(other_v) << '\n'; if(other_v->ccdt_3_data().number_of_incident_constraints() > 0) { const auto c_id = other_v->ccdt_3_data().constrained_polyline_id(*this); const auto [c_va, c_vb] = constraint_extremities(c_id); @@ -835,6 +930,139 @@ class Conforming_Delaunay_triangulation_3 : public T_3 { return v; } + template + std::optional + find_in_incident_cells(Vertex_handle v, Pred pred) const + { + boost::container::flat_set, + boost::container::small_vector> found_cells; + boost::container::small_vector cells; + cells.push_back(v->cell()); + found_cells.insert(cells[0]); + std::size_t head=0; + do { + Cell_handle c = cells[head]; + if(pred(c)) return c; + for (int i=0; i<4; ++i) { + if (c->vertex(i) == v) continue; + Cell_handle next = c->neighbor(i); + if (! found_cells.insert(next).second ) continue; + cells.push_back(next); + } + ++head; + } while(head != cells.size()); + return std::nullopt; + } + + template + bool remove_edge_by_flips(Edge edge_preventing_flip, Visitor& visitor) + { + const auto [va, vb] = tr().vertices(edge_preventing_flip); + if(is_a_constrained_edge(va, vb)) { + if(debug().flips()) { + std::cerr << "-- edge (" << display_vert(va) << ", " << display_vert(vb) + << ") is a constrained edge, cannot remove it\n"; + } + return false; + } + if(debug().flips()) { + std::cerr << "-- edge (" << display_vert(va) << ", " << display_vert(vb) + << ") is NOT a constrained edge\n"; + } + CGAL_USE(edge_preventing_flip); + CGAL_USE(visitor); + return false; + } + + // try to flip facet crossed by [va, vb] to make it an edge of the triangulation + template + bool recover_subconstraint_by_flips(Subconstraint subconstraint, + [[maybe_unused]] Constrained_polyline_id constraint, + Visitor& visitor) + { + const Vertex_handle va = subconstraint.first; + const Vertex_handle vb = subconstraint.second; + CGAL_assertion(va != vb); + auto simplex_it = tr().segment_traverser_simplices_begin(va, vb); + while(true) { + switch(simplex_it->dimension()) { + case 0: { + const auto v = static_cast(*simplex_it); + if(v == vb) { + return true; + } + CGAL_assertion(v == va); + ++simplex_it; + break; + } + case 1: { + const auto [v0, v1] = tr().vertices(static_cast(*simplex_it)); + if( ( v0 == va && v1 == vb) || (v0 == vb && v1 == va) ) { + if(debug().flips()) { + std::cerr << "-- flip restored edge (" << display_vert(va) << ", " << display_vert(vb) << ")\n"; + } + return true; + } else { + return false; + } + } + case 2: { + auto facet = static_cast(*simplex_it); + if(facet.first->vertex(facet.second) != va) { + facet = tr().mirror_facet(facet); + } + const auto [c, facet_index] = facet; + if(c->vertex(facet_index) != va && c->has_vertex(va)) { + // the segment is coplanar with the facet + return false; + } + CGAL_assertion(c->vertex(facet_index) == va); + if(visitor.is_facet_protected(facet)) { + if(debug().flips()) { + std::cerr << "-- facet " << display_facet(facet) + << " is protected, cannot flip to make edge (" << display_vert(va) << ", " << display_vert(vb) + << ") an edge in the triangulation\n"; + } + return false; + } + const auto [v0, v1, v2] = tr().vertices(facet); + const auto opt_edge_preventing_flip = tr().edge_preventing_the_flip(c, facet_index); + if(!opt_edge_preventing_flip.has_value()) + { + const auto [other_cell, other_index] = tr().mirror_facet(facet); + const auto next_v = other_cell->vertex(other_index); + tr().flip_flippable(facet); + visitor.after_flip23(va, next_v, facet); + if(debug().flips()) { + std::cerr << "flipped facet " << display_facet(v0, v1, v2) << " to make edge (" + << display_vert(va) << ", " << display_vert(vb) + << ") an edge in the triangulation\n"; + } + this->is_Delaunay = false; + simplex_it = tr().segment_traverser_simplices_begin(va, vb); + break; + } + else + { + int edge_index = opt_edge_preventing_flip.value(); + Edge edge_preventing_flip{c, + tr().vertex_triple_index(facet_index, tr().ccw(edge_index)), + tr().vertex_triple_index(facet_index, tr(). cw(edge_index))}; + if(debug().flips()) { + std::cerr << "-- flip failed to make edge (" << display_vert(va) << ", " << display_vert(vb) + << ") an edge in the triangulation: edge ( " + << display_vert(c->vertex(edge_preventing_flip.second)) << ", " + << display_vert(c->vertex(edge_preventing_flip.third)) << " ) is in the way\n"; + } + return remove_edge_by_flips(edge_preventing_flip, visitor); + } + } + case 3: ++simplex_it; break; + } + } // end while(true) + return false; + } + /// Return `true` if a Steiner point was inserted template bool conform_subconstraint(Subconstraint subconstraint, @@ -844,23 +1072,37 @@ class Conforming_Delaunay_triangulation_3 : public T_3 { const Vertex_handle va = subconstraint.first; const Vertex_handle vb = subconstraint.second; CGAL_assertion(va != vb); - if(!this->is_edge(va, vb)) { - const auto& [steiner_pt, hint, ref_vertex] = construct_Steiner_point(constraint, subconstraint); - [[maybe_unused]] const auto v = - insert_Steiner_point_on_subconstraint(steiner_pt, hint, subconstraint, constraint, visitor); - if(debug().Steiner_points()) { - const auto [c_start, c_end] = constraint_extremities(constraint); - std::cerr << "(" << IO::oformat(va, with_offset) << ", " << IO::oformat(vb, with_offset) << ")"; - std::cerr << ": [ " << display_vert(c_start) << " - " << display_vert(c_end) << " ] "; - std::cerr << " new vertex " << display_vert(v) << '\n'; + if(this->is_edge(va, vb)) { + if(debug().subconstraints_to_conform()) { + std::cerr << "conform_subconstraint>> subconstraint " << display_subcstr(subconstraint) + << " is already an edge in the triangulation.\n"; + } + return false; + } + if(options().use_flips_to_recover_segments() && recover_subconstraint_by_flips(subconstraint, constraint, visitor)) + { + if(debug().subconstraints_to_conform()) { + std::cerr << "conform_subconstraint>> subconstraint " << display_subcstr(subconstraint) + << " was recovered by flips.\n"; } return true; - } else if(debug().subconstraints_to_conform()) { - std::cerr << "conform_subconstraint>> subconstraint " << display_subcstr(subconstraint) - << " is already an edge in the triangulation.\n"; } + const auto& [steiner_pt, hint, ref_vertex] = construct_Steiner_point(constraint, subconstraint); + [[maybe_unused]] const auto v = + insert_Steiner_point_on_subconstraint(steiner_pt, hint, subconstraint, constraint, visitor); + if(debug().Steiner_points()) { + const auto [c_start, c_end] = constraint_extremities(constraint); + std::cerr << "(" << with_offset(va) << ", " << with_offset(vb) << ")"; + std::cerr << ": [ " << display_vert(c_start) << " - " << display_vert(c_end) << " ] "; + std::cerr << " new vertex " << display_vert(v) << '\n'; + } + return true; + } - return false; +public: + bool is_a_constrained_edge(Vertex_handle va, Vertex_handle vb) const { + auto [contexts_begin, contexts_end] = this->constraint_hierarchy.contexts(va, vb); + return (contexts_begin != contexts_end); } Constrained_polyline_id constraint_from_extremities(Vertex_handle va, Vertex_handle vb) const { @@ -882,15 +1124,16 @@ class Conforming_Delaunay_triangulation_3 : public T_3 { return c_id; } +protected: auto constraint_extremities(Constrained_polyline_id c_id) const { - CGAL_assertion(this->constraint_hierarchy.vertices_in_constraint_begin(c_id) != - this->constraint_hierarchy.vertices_in_constraint_end(c_id)); + CGAL_assertion(this->constraint_hierarchy.is_valid_constraint(c_id)); if(debug().constraint_hierarchy()) { std::cerr << "constraint " << static_cast(c_id.vl_ptr()) << " has " << c_id.vl_ptr()->skip_size() << " vertices\n"; } const auto begin = this->constraint_hierarchy.vertices_in_constraint_begin(c_id); const auto end = this->constraint_hierarchy.vertices_in_constraint_end(c_id); + CGAL_assertion(begin != end); const auto c_va = *begin; const auto c_vb = *std::prev(end); return std::make_pair(c_va, c_vb); @@ -947,7 +1190,7 @@ class Conforming_Delaunay_triangulation_3 : public T_3 { }; auto fill_encroaching_vertices = [&](const auto simplex) { if(debug().encroaching_vertices()) { - std::cerr << " - " << IO::oformat(simplex, With_point_tag{}) << '\n'; + std::cerr << " - " << IO::oformat(simplex, with_point_tag) << '\n'; } auto visit_cell = [&](Cell_handle cell) { for(int i = 0, end = this->tr().dimension() + 1; i < end; ++i) { @@ -1169,6 +1412,12 @@ class Conforming_Delaunay_triangulation_3 : public T_3 { } const auto vector_of_encroaching_vertices = encroaching_vertices(va, vb); + if(vector_of_encroaching_vertices.empty()) { + if(debug().Steiner_points_construction()) { + std::cerr << " -> no encroaching vertices, using midpoint\n"; + } + return {exact(midpoint_functor(pa, pb)), va->cell(), va}; + } CGAL_assertion(vector_of_encroaching_vertices.size() > 0); const auto reference_vertex_it = std::max_element( diff --git a/Constrained_triangulation_3/include/CGAL/Conforming_constrained_Delaunay_triangulation_3.h b/Constrained_triangulation_3/include/CGAL/Conforming_constrained_Delaunay_triangulation_3.h index 75286ad367c4..12c7a08e840b 100644 --- a/Constrained_triangulation_3/include/CGAL/Conforming_constrained_Delaunay_triangulation_3.h +++ b/Constrained_triangulation_3/include/CGAL/Conforming_constrained_Delaunay_triangulation_3.h @@ -12,12 +12,11 @@ #ifndef CGAL_CONFORMING_CONSTRAINED_DELAUNAY_TRIANGULATION_3_H #define CGAL_CONFORMING_CONSTRAINED_DELAUNAY_TRIANGULATION_3_H -#include #include #include -#include +#include // IWYU pragma: export #include #include @@ -44,8 +43,10 @@ #include #include #include +#include #include #include +#include #include #include #include @@ -53,8 +54,10 @@ #include #include #include +#include #include #include +#include #include #include #include @@ -125,7 +128,10 @@ #include #include #include +#include #include +#include +#include #include #include #include @@ -133,7 +139,9 @@ #include #include #include +#include #include +#include #include #include #if __has_include() @@ -179,16 +187,14 @@ auto segment_soup_to_polylines(const Range_of_segments& segment_soup) { boost::add_edge(va, vb, graph); } - struct Polylines_visitor - { + struct { Graph& graph; std::vector>& polylines; void start_new_polyline() { polylines.emplace_back(); } void add_node(typename Graph::vertex_descriptor vd) { polylines.back().push_back(graph[vd]); } void end_polyline() {} - }; - Polylines_visitor visitor{graph, polylines}; + } visitor{graph, polylines}; CGAL::split_graph_into_polylines(graph, visitor); return polylines; @@ -565,11 +571,12 @@ concept Range_of_polygon_3 = std::ranges::common_range && Polygon_3, Kernel>; #endif // concepts -template -struct Output_rep, With_point_and_info_tag> +template +struct Output_rep, With_point_and_info_tag> : public Output_rep> { int offset = 0; + With_point_and_info_tag tag; using Base = Output_rep>; using CC_iterator = CGAL::internal::CC_iterator; using Compact_container = typename CC_iterator::CC; @@ -577,26 +584,30 @@ struct Output_rep, With_point_and_info_t using Base::Base; - Output_rep(const CC_iterator& it, With_point_and_info_tag tag) - : Base(it), offset(tag.offset) + Output_rep(const CC_iterator& it, With_point_and_info_tag tag) + : Base(it), offset(tag.offset), tag(tag) { } std::ostream& operator()(std::ostream& out) const { - out << Time_stamper::display_id(this->it.operator->(), offset); - if(this->it.operator->() != nullptr) { - out << (this->it->ccdt_3_data().is_Steiner_vertex_on_edge() ? "(Steiner)" : "") - << (this->it->ccdt_3_data().is_Steiner_vertex_in_face() ? "(Steiner in face)" : "") - << "= " << this->it->point(); - if(this->it->ccdt_3_data().is_marked(CDT_3_vertex_marker::REGION_BORDER)) out << " (region border)"; - if(this->it->ccdt_3_data().is_marked(CDT_3_vertex_marker::REGION_INSIDE)) out << " (inside region)"; - if(this->it->ccdt_3_data().is_marked(CDT_3_vertex_marker::CAVITY)) out << " (cavity vertex)"; - if(this->it->ccdt_3_data().is_marked(CDT_3_vertex_marker::CAVITY_ABOVE)) out << " (vertex above)"; - if(this->it->ccdt_3_data().is_marked(CDT_3_vertex_marker::CAVITY_BELOW)) out << " (vertex below)"; - return out; - } - else - return out; + auto v_ptr = this->it.operator->(); + if(v_ptr == nullptr) + return out << "nullptr"; + if(Time_stamper::time_stamp(v_ptr) == 0) + return out << "# = infinite_vertex()"; + + out << Time_stamper::display_id(v_ptr, offset); + + out << (v_ptr->ccdt_3_data().is_Steiner_vertex_on_edge() ? "(Steiner)" : "") + << (v_ptr->ccdt_3_data().is_Steiner_vertex_in_face() ? "(Steiner in face)" : "") + << (v_ptr->ccdt_3_data().is_Steiner_vertex_in_volume() ? "(Steiner in volume)" : "") + << "= " << tag.tr->point(this->it); + if(v_ptr->ccdt_3_data().is_marked(CDT_3_vertex_marker::REGION_BORDER)) out << " (region border)"; + if(v_ptr->ccdt_3_data().is_marked(CDT_3_vertex_marker::REGION_INSIDE)) out << " (inside region)"; + if(v_ptr->ccdt_3_data().is_marked(CDT_3_vertex_marker::CAVITY)) out << " (cavity vertex)"; + if(v_ptr->ccdt_3_data().is_marked(CDT_3_vertex_marker::CAVITY_ABOVE)) out << " (vertex above)"; + if(v_ptr->ccdt_3_data().is_marked(CDT_3_vertex_marker::CAVITY_BELOW)) out << " (vertex below)"; + return out; } }; @@ -646,14 +657,209 @@ class Conforming_constrained_Delaunay_triangulation_3 public: using Vertex_handle = typename Triangulation::Vertex_handle; + using Edge = typename Triangulation::Edge; + using Facet = typename Triangulation::Facet; + using Cell_handle = typename Triangulation::Cell_handle; + + using Concurrency_tag = typename Triangulation::Concurrency_tag; #ifndef DOXYGEN_RUNNING using Constrained_polyline_id = typename CDT_3_impl::Constrained_polyline_id; #endif // not DOXYGEN_RUNNING using size_type = typename Triangulation::size_type; + using Subdomain_index = int; + using Surface_patch_index = CDT_3_signed_index; + using Curve_index = std::size_t;//Constrained_polyline_id::size_type; + using Corner_index = int;//check that + using Index = typename Triangulation::Triangulation_data_structure::Vertex::Index; + + void rescan_after_load_of_triangulation() { /*todo*/ } + + bool is_in_complex(const Cell_handle& c) const + { + Subdomain_index default_index{}; + return c->subdomain_index() != default_index; + } + bool is_in_complex(const Facet& f) const + { + return is_in_complex(f.first, f.second); + } + bool is_in_complex(const Cell_handle c, const int i) const + { + return is_facet_constrained({c, i}); + } + bool is_in_complex(const Vertex_handle u, const Vertex_handle v) const + { + Constrained_polyline_id c_id = impl().constraint_from_extremities(u, v); + return (c_id != Constrained_polyline_id{}); + } + bool is_in_complex(const Edge& e) const + { + return is_in_complex(e.first->vertex(e.second), e.first->vertex(e.third)); + } + bool is_in_complex(const Vertex_handle& v) const + { + return impl().vertex_type(v) == CDT_3_vertex_type::INPUT_VERTEX; + } + Subdomain_index subdomain_index(const Cell_handle& c) const + { + return is_in_complex(c) ? Subdomain_index{1} : Subdomain_index(); + } + Surface_patch_index surface_patch_index(const Cell_handle c, const int i) const + { + return surface_patch_index({c, i}); + } + Surface_patch_index surface_patch_index(const Facet& f) const + { + Surface_patch_index index = face_constraint_index(f.first, f.second) + 1; + // valid face_constraint_index() starts at 0 + // Surface_patch_index 0 is for "not a surface" + return index; + } + void set_surface_patch_index(const Facet& f, const Surface_patch_index& index) + { + const Facet& mf = impl().mirror_facet(f); + + // warning : cdt2_index may be outdated + f.first->ccdt_3_data().set_face_constraint_index(f.second, index); + mf.first->ccdt_3_data().set_face_constraint_index(mf.second, index); + } + Curve_index curve_index(const Vertex_handle v1, const Vertex_handle v2) const + { + return impl().constraint_from_extremities(v1, v2).index(); + } + Curve_index curve_index(const Edge& e) const + { + return curve_index(e.first->vertex(e.second), e.first->vertex(e.third)); + } + Index index(const Vertex_handle&) const + { + return 1;//not used in tetrahedral remeshing outside of sizing field + } + int in_dimension(const Vertex_handle& v) const + { + auto type = impl().vertex_type(v); + switch(type) + { + case CDT_3_vertex_type::INPUT_VERTEX : + return 0; + case CDT_3_vertex_type::STEINER_ON_EDGE: + return 1; + case CDT_3_vertex_type::STEINER_IN_FACE: + return 2; + case CDT_3_vertex_type::STEINER_IN_VOLUME: + case CDT_3_vertex_type::FREE: + case CDT_3_vertex_type::BBOX: + return 3; + } + CGAL_unreachable(); + } + + void add_to_complex(const Cell_handle c, const Subdomain_index& index) + { + CGAL_precondition(!triangulation().is_infinite(c)); + CGAL_precondition(index == Subdomain_index{1}); + CGAL_USE(c); CGAL_USE(index); + } + void set_subdomain_index(const Cell_handle, const Subdomain_index&) + { + ; + } + void add_to_complex(const Facet& f, const Surface_patch_index& index) + { + //todo : use index and cdt2_index too + impl().set_facet_constrained(f, index, {}); + set_surface_patch_index(f, index); + } + void add_to_complex(const Edge& e, const Curve_index& index) + { + add_to_complex(e.first->vertex(e.second), e.first->vertex(e.third), index); + } + void add_to_complex(const Vertex_handle& v, const Corner_index&) + { + v->ccdt_3_data().set_vertex_type(CDT_3_vertex_type::INPUT_VERTEX); + } + void add_to_complex(const Vertex_handle, const Vertex_handle, const Curve_index&) + { +// impl().insert_constrained_edge(v1, v2, false/*restore Delaunay*/); + } + void remove_from_complex(const Cell_handle c) + { + CGAL_precondition(!triangulation().is_infinite(c)); + CGAL_USE(c); + } + void remove_from_complex(const Facet& f) + { + CGAL_precondition(is_in_complex(f.first, f.second)); + const Facet mf = impl().mirror_facet(f); + impl().set_facet_as_not_constrained(f); + impl().set_facet_as_not_constrained(mf); + } + void remove_from_complex(const Cell_handle c, const int i) + { + remove_from_complex({c, i}); + } + void remove_from_complex(const Edge&) + { +// remove_from_complex(e.first->vertex(e.second), e.first->vertex(e.third)); + } + void remove_from_complex(const Vertex_handle, const Vertex_handle) + { + //should not happen during tetrahedral remeshing since we keep constrained edges + CGAL_error_msg("removing a constrained edge is not supported"); + } + + void set_index(Vertex_handle, const Index&) const + { + // nothing to do since index is not used in tetrahedral remeshing outside of sizing field + } + void set_dimension(Vertex_handle v, const int dim) const + { + switch (dim) + { + case 0: + v->ccdt_3_data().set_vertex_type(CDT_3_vertex_type::INPUT_VERTEX); + break; + case 1: + v->ccdt_3_data().set_vertex_type(CDT_3_vertex_type::STEINER_ON_EDGE); + break; + case 2: + v->ccdt_3_data().set_vertex_type(CDT_3_vertex_type::STEINER_IN_FACE); + break; + case 3: + v->ccdt_3_data().set_vertex_type(CDT_3_vertex_type::STEINER_IN_VOLUME); + break; + }; + } + + using Edges_in_complex_iterator = typename CDT_3_impl::Complex_edges_iterator; + auto edges_in_complex() const + { + return impl().edges_in_complex(); + } + auto edges_in_complex_begin() const { using std::begin; return begin(impl().edges_in_complex()); } + auto edges_in_complex_end() const { using std::end; return end(impl().edges_in_complex()); } + using Facets_in_complex_iterator = typename CDT_3_impl::Constrained_facets_iterator; + auto facets_in_complex() const + { + return impl().constrained_facets(); + } + auto facets_in_complex_begin() const { using std::begin; return begin(impl().constrained_facets()); } + auto facets_in_complex_end() const { using std::end; return end(impl().constrained_facets()); } + auto cells_in_complex() const + { + return impl().finite_cell_handles(); + } + std::size_t number_of_edges() const + { + const auto& [ebegin, eend] = edges_in_complex(); + return std::distance(ebegin, eend); + } + /// \cond SKIP_IN_MANUAL - CDT_3_impl& impl() { return cdt_impl; } + CDT_3_impl& impl() { return cdt_impl; } + const CDT_3_impl& impl() const { return cdt_impl; } /// \endcond public: /** \name Constructors @@ -913,9 +1119,6 @@ class Conforming_constrained_Delaunay_triangulation_3 std::cout << "Number of vertices after CDT: " << cdt_impl.number_of_vertices() << "\n\n"; } } - - // std::cerr << cdt_3_format("cdt_impl: {} vertices, {} cells\n", cdt_impl.number_of_vertices(), - // cdt_impl.number_of_cells()); } /*! @@ -1018,6 +1221,15 @@ class Conforming_constrained_Delaunay_triangulation_3 /// @} // end constructors section + /** + * swaps `this` and `rhs` + */ + void swap(Conforming_constrained_Delaunay_triangulation_3& rhs) + { + std::swap(cdt_impl, rhs.cdt_impl); + } + + // ----------------------- // Accessors // ----------------------- @@ -1038,6 +1250,8 @@ class Conforming_constrained_Delaunay_triangulation_3 return cdt_impl; } + Triangulation& triangulation() & { return cdt_impl; } + /*! * \brief moves and returns the underlying triangulation, then clears the object. * @@ -1084,24 +1298,24 @@ class Conforming_constrained_Delaunay_triangulation_3 * \link TriangulationDataStructure_3::Facet `Triangulation::Facet`\endlink, * as defined by its triangulation data structure. */ - bool is_facet_constrained(const typename Triangulation::Facet& f) const { + bool is_facet_constrained(const Facet& f) const { return cdt_impl.is_facet_constrained(f); } /*! * \brief same as `is_facet_constrained(f)` with `f` being `Triangulation::Facet(ch, index)`. */ - bool is_facet_constrained(typename Triangulation::Cell_handle ch, int index) const { - return cdt_impl.is_facet_constrained(typename Triangulation::Facet(ch, index)); + bool is_facet_constrained(Cell_handle ch, int index) const { + return cdt_impl.is_facet_constrained(Facet(ch, index)); } /*! * @brief same as `face_constraint_index(f)` with `f` being `Triangulation::Facet(ch, index)`. * @pre \link Conforming_constrained_Delaunay_triangulation_3::is_facet_constrained `is_facet_constrained`\endlink(`f`) */ - CDT_3_signed_index face_constraint_index(typename Triangulation::Cell_handle ch, int i) const + CDT_3_signed_index face_constraint_index(Cell_handle ch, int i) const { - return ch->ccdt_3_data().face_constraint_index(i); + return cdt_impl.face_constraint_index(ch, i); } /*! @@ -1109,9 +1323,9 @@ class Conforming_constrained_Delaunay_triangulation_3 * facet \p f * @pre \link Conforming_constrained_Delaunay_triangulation_3::is_facet_constrained `is_facet_constrained`\endlink(`f`) */ - CDT_3_signed_index face_constraint_index(const typename Triangulation::Facet& f) const + CDT_3_signed_index face_constraint_index(const Facet& f) const { - return face_constraint_index(f.first, f.second); + return cdt_impl.face_constraint_index(f.first, f.second); } /*! @@ -1154,6 +1368,13 @@ class Conforming_constrained_Delaunay_triangulation_3 /// \name Checking /// These methods are mainly a debugging help for the users of advanced features. /// @{ + /*! + \brief returns whether the triangulation is valid. + When `verbose` is set to `true`, messages describing the first invalidity encountered are + printed. + */ + bool is_valid(bool verbose = false) const { return cdt_impl.is_valid(verbose); } + /// @} // ----------------------- @@ -1180,11 +1401,27 @@ class Conforming_constrained_Delaunay_triangulation_3 // Validation helpers bool is_conforming() const { return cdt_impl.is_conforming(); } - bool is_valid(bool verbose = false) const { return cdt_impl.is_valid(verbose); } // IO helpers for debugging bool write_missing_segments_file(std::ostream& out) { return cdt_impl.write_missing_segments_file(out); } void write_all_segments_file(std::ostream& out) { cdt_impl.write_all_segments_file(out); } + void dump_constrained_facets_to_off(std::string filename) const { cdt_impl.dump_constrained_facets_to_off(filename); } + void save_binary_file(std::string filename = "dump.binary.cgal") const { + cdt_impl.dump_triangulation(filename); + } + + // Post-processing helpers + /// \brief Moves Steiner vertices on the boundary to the volume. + /// + /// This function moves Steiner vertices that lie on edges or faces + /// of the constrained surface to inside the volume. + void move_Steiner_vertices_to_the_volume() { + cdt_impl.move_Steiner_vertices_to_the_volume(); + } + + void remove_bbox_points() { + cdt_impl.remove_bbox_points(); + } // Lightweight accessors used by tests/tools size_type number_of_vertices() const { return static_cast(cdt_impl.number_of_vertices()); } @@ -1205,6 +1442,50 @@ class Conforming_constrained_Delaunay_triangulation_3 void write_facets(std::ostream& out, const CDT& cdt, FacetRange&& facets) const { cdt_impl.write_facets(out, cdt, std::forward(facets)); } + + auto statistics(std::string prefix = "") const { + using Stats_array = std::array(CDT_3_vertex_type::last) + 1>; + return IO::oformat([this, prefix=std::move(prefix)](std::ostream& out) -> auto& { + out << prefix << "Number of vertices: " << triangulation().number_of_vertices() << "\n"; + out << prefix << "Number of cells: " << triangulation().number_of_cells() << "\n"; + + auto nb = [nb_vertices_by_type = Stats_array{}](CDT_3_vertex_type type) mutable -> auto& { + return nb_vertices_by_type[static_cast(type)]; + }; + + for(auto v: triangulation().finite_vertex_handles()) { + ++nb(v->ccdt_3_data().vertex_type()); + } + out << prefix << "Number of vertices by type:\n"; + out << prefix << " - " << nb(CDT_3_vertex_type::INPUT_VERTEX) << " input vertices\n"; + out << prefix << " - " << nb(CDT_3_vertex_type::STEINER_ON_EDGE) << " Steiner vertices on edges\n"; + out << prefix << " - " << nb(CDT_3_vertex_type::STEINER_IN_FACE) << " Steiner vertices in faces\n"; + out << prefix << " - " << nb(CDT_3_vertex_type::STEINER_IN_VOLUME) << " Steiner vertices in volume\n"; + out << prefix << " - " << nb(CDT_3_vertex_type::FREE) << " free vertices\n"; + if(impl().options().move_Steiner_vertices_allow_negative_tets()) { + std::size_t nb_of_negative_tets = 0; + auto point = [this](typename Triangulation::Vertex_handle vh) { + return triangulation().point(vh); + }; + CGAL::unordered_flat_set vertices_with_negative_tets; + for(auto c: triangulation().finite_cell_handles()) { + const auto verts + = triangulation().vertices(c); + if(triangulation().orientation(point(verts[0]), point(verts[1]), point(verts[2]), point(verts[3])) < 0) { + ++nb_of_negative_tets; + for(auto v : verts) { + if(v->ccdt_3_data().vertex_type() == CDT_3_vertex_type::STEINER_IN_VOLUME) { + vertices_with_negative_tets.insert(v); + } + } + } + } + out << prefix << " - " << nb_of_negative_tets << " negative tetrahedra\n"; + out << prefix << " - " << vertices_with_negative_tets.size() << " Steiner vertices with negative tetrahedra around\n"; + } + return out; + }, IO_manip_tag{}); + } }; #ifndef DOXYGEN_RUNNING @@ -1213,9 +1494,10 @@ class Conforming_constrained_Delaunay_triangulation_3 // ---------------------------------------------------------- template class Conforming_constrained_Delaunay_triangulation_3_impl : public Conforming_Delaunay_triangulation_3 { + Conforming_constrained_Delaunay_triangulation_3_impl& tr() { return *this; }; + const Conforming_constrained_Delaunay_triangulation_3_impl& tr() const { return *this; }; public: using Conforming_Dt = Conforming_Delaunay_triangulation_3; - using Conforming_Dt::tr; static_assert(Conforming_Dt::t_3_is_not_movable || CGAL::is_nothrow_movable_v); using Vertex_handle = typename T_3::Vertex_handle; @@ -1223,9 +1505,13 @@ class Conforming_constrained_Delaunay_triangulation_3_impl : public Conforming_D using Facet = typename T_3::Facet; using Cell_handle = typename T_3::Cell_handle; + using Facet_pair = std::array; + static Facet_pair null_facet_pair() { return{Facet{}, Facet{}}; }; + using Geom_traits = typename T_3::Geom_traits; using Point_3 = typename T_3::Point; using Segment_3 = typename Geom_traits::Segment_3; + using Triangle_3 = typename Geom_traits::Triangle_3; using Vector_3 = typename Geom_traits::Vector_3; using Locate_type = typename T_3::Locate_type; using size_type = typename T_3::size_type; @@ -1234,8 +1520,11 @@ class Conforming_constrained_Delaunay_triangulation_3_impl : public Conforming_D using Cell_marker = CDT_3_cell_marker; using Face_index = CDT_3_signed_index; + static inline constexpr Face_index INVALID_FACE_INDEX = -1; using Conforming_Dt::Conforming_Dt; + using Conforming_Dt::with_point; + using Conforming_Dt::with_point_and_info; using Tds = typename T_3::Triangulation_data_structure; using Concurrency_tag = typename Tds::Concurrency_tag; @@ -1250,6 +1539,11 @@ class Conforming_constrained_Delaunay_triangulation_3_impl : public Conforming_D bool operator()(Facet f) const { return cdt.is_facet_constrained(f); } + bool operator()(Edge e) const { + return Constrained_polyline_id{} + != cdt.constraint_from_extremities(e.first->vertex(e.second), + e.first->vertex(e.third)); + } }; using Constrained_facets_iterator = boost::filter_iterator; @@ -1264,6 +1558,21 @@ class Conforming_constrained_Delaunay_triangulation_3_impl : public Conforming_D Constrained_facets_range constrained_facets() const { return {constrained_facets_begin(), constrained_facets_end()}; } + + + using Complex_edges_iterator = boost::filter_iterator; + using Complex_edges_range = CGAL::Iterator_range; + + Complex_edges_iterator edges_in_complex_begin() const { + return {Is_constrained{*this}, this->finite_edges_begin(), this->finite_edges_end()}; + } + Complex_edges_iterator edges_in_complex_end() const { + return {Is_constrained{*this}, this->finite_edges_end(), this->finite_edges_end()}; + } + Complex_edges_range edges_in_complex() const { + return { edges_in_complex_begin(), edges_in_complex_end()}; + } + private: struct CDT_2_types { @@ -1273,62 +1582,1338 @@ class Conforming_constrained_Delaunay_triangulation_3_impl : public Conforming_D }; static_assert(CGAL::is_nothrow_movable_v); - struct Vertex_info - { - Vertex_handle vertex_handle_3d = {}; - }; + struct Vertex_info + { + Vertex_handle vertex_handle_3d = {}; + }; + + using Color_value_type = std::int8_t; + enum class Face_is_outside_the_face : Color_value_type { UNKNOWN = -1, INSIDE = 0, OUTSIDE = 1 }; + struct Face_info + { + Face_is_outside_the_face is_outside_the_face = Face_is_outside_the_face::UNKNOWN; + Color_value_type is_in_region = 0; + std::bitset<3> is_edge_also_in_3d_triangulation = 0; + bool missing_subface = true; + Facet facet_3d = {}; + }; + using Vb1 = Triangulation_vertex_base_with_info_2; + using Vb = Triangulation_simplex_base_with_time_stamp; + using Fb1 = Triangulation_face_base_with_info_2; + using Fb = Constrained_triangulation_face_base_2; + using TDS = Triangulation_data_structure_2; + using Itag = No_constraint_intersection_requiring_constructions_tag; + using CDT_base = Constrained_Delaunay_triangulation_2; + using CDT = Constrained_triangulation_plus_2; + using CT = typename CDT::Ctr; + + template struct CDT_2_dual_color_map + { + using category = boost::read_write_property_map_tag; + using reference = Color_value_type&; + using value_type = Color_value_type; + using key_type = typename CDT::Face_handle; + + friend reference get(CDT_2_dual_color_map, key_type fh) { return fh->info().*member_ptr; } + friend void put(CDT_2_dual_color_map, key_type fh, value_type value) { fh->info().*member_ptr = value; } + }; + using Color_map_is_in_region = CDT_2_dual_color_map<&Face_info::is_in_region>; + }; // CDT_2_types + using CDT_2 = typename CDT_2_types::CDT; + using CT_2 = typename CDT_2_types::CT; + using CDT_2_traits = typename CDT_2_types::Projection_traits; + using CDT_2_face_handle = typename CDT_2::Face_handle; + using CDT_2_edge = typename CDT_2::Edge; + using CDT_2_vertex_handle = typename CDT_2::Vertex_handle; + using Face_is_outside_the_face = typename CDT_2_types::Face_is_outside_the_face; + static inline constexpr Face_is_outside_the_face OUTSIDE = Face_is_outside_the_face::OUTSIDE; + static inline constexpr Face_is_outside_the_face INSIDE = Face_is_outside_the_face::INSIDE; + static_assert(CGAL::cdt_3_msvc_2019_or_older() || CGAL::is_nothrow_movable_v); + + static Vertex_handle& vertex_3d(CDT_2_vertex_handle v) { + return v->info().vertex_handle_3d; + } + +protected: + struct Null_normal_error : Error_exception { + Null_normal_error(std::string msg, std::string file, int line) + : Error_exception("CGAL CDT_3", msg, file, line) + { + } + }; + + using Constraint_hierarchy = typename Conforming_Dt::Constraint_hierarchy; + using Subconstraint = typename Constraint_hierarchy::Subconstraint; + +public: + using Constrained_polyline_id = typename Constraint_hierarchy::Constraint_id; + +protected: + auto display_vert(Vertex_handle v) const { + return with_point_and_info(v); + } + + template > + auto display_facet(std::string_view prefix, Facet f, Tag tag = {}) const { + std::array vertices = { Vertex_handle{} , Vertex_handle{} , Vertex_handle{} }; + Vertex_handle v4 = {}; + if(f.first != Cell_handle{}) { + vertices = tr().vertices(f); + v4 = f.first->vertex((f.second)); + } + return IO::oformat( + [prefix, tag, vertices, v4](auto& out) -> auto& { + if(v4 == Vertex_handle{}) { + return out << "null facet"; + } + return out << cdt_3_format("\n{}{}" + "\n{}{}" + "\n{}{}" + "\n{}(fourth vertex of its cell: {})", + prefix, IO::oformat(vertices[0], tag), prefix, IO::oformat(vertices[1], tag), + prefix, IO::oformat(vertices[2], tag), prefix, IO::oformat(v4, tag)); + }, + IO_manip_tag{}); + } + + const auto& dbg() const { return this->debug(); } + + bool same_triple(const std::array f1_vertices, + std::array f2_vertices, + Orientation o = EQUAL) const + { + auto f2_it_equal_to_f_first_vertex = std::find(f2_vertices.begin(), f2_vertices.end(), f1_vertices[0]); + if(f2_it_equal_to_f_first_vertex == f2_vertices.end()) return false; + std::rotate(f2_vertices.begin(), f2_it_equal_to_f_first_vertex, f2_vertices.end()); + CGAL_assertion(f1_vertices[0] == f2_vertices[0]); + if(o == NEGATIVE) { + return (f1_vertices[1] == f2_vertices[2] && f1_vertices[2] == f2_vertices[1]); + } else { + return (f1_vertices[1] == f2_vertices[1] && f1_vertices[2] == f2_vertices[2]); + } + } + + bool same_triple(Facet f, Facet f2, Orientation o = EQUAL) const { + return same_triple(tr().vertices(f), tr().vertices(f2), o); + } + + bool same_triple(Facet f, CDT_2_face_handle fh, Orientation o = EQUAL) const { + auto f_vertices = tr().vertices(f); + std::array fh_vertices{vertex_3d(fh->vertex(0)), + vertex_3d(fh->vertex(1)), + vertex_3d(fh->vertex(2))}; + return same_triple(f_vertices, fh_vertices, o); + } + + bool opposite_triple(Facet f, Facet f2) const { + return same_triple(f, f2, NEGATIVE); + } + +public: + void set_facet_constrained(Facet f, CDT_3_signed_index polygon_constraint_id, + CDT_2_face_handle fh, [[maybe_unused]] Orientation o = EQUAL) + { + CGAL_assertion(fh == CDT_2_face_handle{} || same_triple(f, fh, o)); + CGAL_assertion(o == EQUAL); + CGAL_assertion(fh == CDT_2_face_handle{} || fh->info().is_outside_the_face != OUTSIDE); + + const auto [c, facet_index] = f; + c->ccdt_3_data().set_facet_constraint(facet_index, polygon_constraint_id, fh); + if(tr().dimension() > 2) { + const auto [n, n_index] = tr().mirror_facet(f); + n->ccdt_3_data().set_facet_constraint(n_index, polygon_constraint_id, fh); + } + if(fh != CDT_2_face_handle{}) { + fh->info().facet_3d = f; + fh->info().missing_subface = false; + } + } + + auto set_facet_as_not_constrained(Facet f) { + return set_facet_constrained(f, INVALID_FACE_INDEX, CDT_2_face_handle{}); + } + +protected: + void set_adjacency_between_3d_facets(Facet f1, Facet f2) const { + // } + tr().tds().set_adjacency(f1.first, f1.second, f2.first, f2.second); + if(dbg().move_Steiner_vertices_level() > 1) { + std::cerr << cdt_3_format("-> set adjacency between facets ({})=[{}]+{} and ({})=[{}]+{}\n", + IO::oformat(f1), with_offset(tr().vertices(f1)), + with_offset(f1.first->vertex(f1.second)), + IO::oformat(f2), with_offset(tr().vertices(f2)), + with_offset(f2.first->vertex(f2.second))); + CGAL_assertion(opposite_triple(f1, f2)); + } + CGAL_assertion(std::all_of(boost::counting_iterator(1), boost::counting_iterator(4), + [f1, f2](int i) { + return f1.first->neighbor((f1.second + i) % 4) != f2.first && + f2.first->neighbor((f2.second + i) % 4) != f1.first; + } + )); + } + + template + std::optional + find_in_incident_facets(Vertex_handle v, Pred pred) const + { + boost::container::flat_set, + boost::container::small_vector> found_cells; + boost::container::small_vector cells; + cells.push_back(v->cell()); + found_cells.insert(cells[0]); + int head=0; + int tail=1; + do { + Cell_handle c = cells[head]; + for (int i=0; i<4; ++i) { + if (c->vertex(i) == v) continue; + Cell_handle next = c->neighbor(i); + if(c < next && pred(Facet(c, i))) { + return Facet(c, i); + } + if (! found_cells.insert(next).second ) + continue; + cells.push_back(next); + ++tail; + } + ++head; + } while(head != tail); + return std::nullopt; + } + + template + CGAL::Surface_mesh + construct_star_component_mesh(std::size_t component_index, + const Components& components, + const Map& map_from_incident_constraint_face_id_to_new_triangles) const + { + CGAL::Surface_mesh component_mesh; + using face_descriptor = typename CGAL::Surface_mesh::Face_index; + auto [patch_id_map, _] = component_mesh.template add_property_map("f:patch_id", 0); + + std::vector points; + std::vector> triangles; + std::vector triangle_face_indices; + std::size_t vertex_index = 0; + for(std::size_t facet_id = components.component_offsets[component_index - 1], + end = components.component_offsets[component_index]; + facet_id < end; ++facet_id) + { + const auto& [cell, facet_index, type] = components.facets[facet_id]; + if(!this->debug().move_Steiner_vertices_allow_negative_tets() && + type == Star_components_facets::Type_of_facet::INCIDENT_TO_V) + { + continue; + } + Facet facet(cell, facet_index); + if(tr().is_infinite(facet)) { + continue; + } + for(auto v: this->vertices(facet)) { + points.push_back(tr().point(v)); + } // end for each vertex of the facet + // swap the orientation: our facets are oriented toward the center of the star component + // but we want them to be oriented outward + triangles.push_back({vertex_index, vertex_index + 2, vertex_index + 1}); + Face_index face_index = -1; + if(type == Star_components_facets::Type_of_facet::INCIDENT_TO_V) { + face_index = face_constraint_index(facet); + } + triangle_face_indices.push_back(face_index); + vertex_index += 3; + } // end for each facet in the component + if(!this->debug().move_Steiner_vertices_allow_negative_tets()) { + const auto& incident_face_ids = components.component_incident_constraint_face_ids[component_index - 1]; + for(auto face_id : incident_face_ids) { + if(face_id == INVALID_FACE_INDEX) { + continue; + } + const auto& new_triangles = map_from_incident_constraint_face_id_to_new_triangles.at(face_id); + for(const auto& triangle : new_triangles) { + points.push_back(triangle[0]); + points.push_back(triangle[1]); + points.push_back(triangle[2]); + triangles.push_back({vertex_index, vertex_index + 1, vertex_index + 2}); + triangle_face_indices.push_back(face_id); + vertex_index += 3; + } + } + } + CGAL::Polygon_mesh_processing::merge_duplicate_points_in_polygon_soup(points, triangles); + CGAL::Polygon_mesh_processing::orient_polygon_soup(points, triangles); + CGAL::Polygon_mesh_processing::polygon_soup_to_polygon_mesh(points, triangles, component_mesh, + CGAL::parameters::polygon_to_face_output_iterator(boost::make_function_output_iterator( + [&](const auto& polygon_to_face) { + auto [poly_idx, fd] = polygon_to_face; + put(patch_id_map, fd, triangle_face_indices[poly_idx]); + }))); + return component_mesh; + } + + std::optional compute_center_point_if_possible(const CGAL::Surface_mesh& component_mesh) const { + return CGAL::Polygon_mesh_processing::kernel_point(component_mesh); + } + + template + CGAL::Surface_mesh + construct_link_mesh_for_debug(const Components& components, + const Map& map_from_incident_constraint_face_id_to_new_triangles) const + { + using Mesh = CGAL::Surface_mesh; + using face_descriptor = typename Mesh::Face_index; + Mesh link_mesh; + auto [patch_id_map, _] = link_mesh.template add_property_map("f:patch_id", 0); + + for(std::size_t component_index = 1; component_index < components.component_offsets.size(); ++component_index) { + Mesh component_mesh = construct_star_component_mesh(component_index, components, + map_from_incident_constraint_face_id_to_new_triangles); + + std::vector new_faces; + auto out_it = boost::make_function_output_iterator( + [&new_faces](std::pair fd_pair) { new_faces.push_back(fd_pair.second); }); + CGAL::copy_face_graph(component_mesh, link_mesh, CGAL::parameters::face_to_face_output_iterator(out_it)); + for(auto fd : new_faces) { + put(patch_id_map, fd, static_cast(component_index)); + } + } + return link_mesh; + } + + template + void dump_link_mesh_of_vertex_to_ply(Vertex_handle v, + const Components& components, + const Map& map_from_incident_constraint_face_id_to_new_triangles) const { + const auto link_mesh = + construct_link_mesh_for_debug(components, map_from_incident_constraint_face_id_to_new_triangles); + + std::stringstream filename; + filename << "dump_link_mesh_vertex" << IO::oformat(v, With_offset_tag{}) << ".ply"; + std::ofstream out(filename.str()); + CGAL::IO::write_PLY(out, link_mesh); + out.close(); + } + + struct Star_components_facets { // output type of `collect_star_components_facets()` + enum class Type_of_facet { + INCIDENT_TO_V, + OPPOSITE_TO_V + }; + + struct Facet_of_star_component { + Cell_handle cell; + int index_of_opposite_vertex; + Type_of_facet type; + + bool operator<(const Facet_of_star_component& other) const { + if(cell != other.cell) + return cell < other.cell; + return index_of_opposite_vertex < other.index_of_opposite_vertex; + } + }; + + template + using small_vector = boost::container::small_vector; + + small_vector facets; + small_vector component_offsets = {0}; + small_vector nb_of_incident_facets_for_each_component; + small_vector> face_ids_between_consecutive_components; + small_vector> component_incident_constraint_face_ids; + + auto component_facets_range(std::size_t component_index) const { + return CGAL::make_range(facets.begin() + component_offsets[component_index - 1], + facets.begin() + component_offsets[component_index]); + } + }; + + Orientation constrained_facet_orientation(const Facet& f) const { + const auto& cdt_2 = this->face_cdt_2(face_constraint_index(f)); + const auto fh_2d = f.first->ccdt_3_data().face_2(cdt_2, f.second); + if(fh_2d->info().facet_3d == f) { + return CGAL::EQUAL; + } + CGAL_assertion(fh_2d->info().facet_3d == T_3::mirror_facet(f)); + return CGAL::NEGATIVE; + } + + Star_components_facets collect_star_components_facets(Vertex_handle v, Facet incident_constrained_facet) const { + const auto [first_cell, first_facet_index] = incident_constrained_facet; + const auto first_facet_face_id = face_constraint_index(incident_constrained_facet); + + const Orientation first_facet_orientation = constrained_facet_orientation(incident_constrained_facet); + + const auto vertex_Steiner_type = vertex_type(v); + CGAL_assertion(vertex_Steiner_type == CDT_3_vertex_type::STEINER_IN_FACE || + vertex_Steiner_type == CDT_3_vertex_type::STEINER_ON_EDGE); + + Star_components_facets out; // the returned object, yet to be filled + + auto register_cell_and_check_if_new = + [seen_cells = CGAL::unordered_flat_set{}](Cell_handle c) mutable + { + auto [_, inserted] = seen_cells.insert(c); + return inserted; + }; + + // `cells_in_other_components` is used to keep track of cells that belong to other components: + // when we finish processing a component, we take one of these cells (if not yet processed) to + // start processing the next component. + // -> Start with one of the facets incident to `v` that is constrained, and explore the star + // of `v` through unconstrained facets as long as possible; + boost::container::small_vector, 128> cells_in_other_components = { + { first_cell, first_facet_face_id, first_facet_orientation } + }; + + while(!cells_in_other_components.empty()) { + auto [other_cell, component_first_incident_face_id, component_first_facet_orientation] = + cells_in_other_components.back(); + cells_in_other_components.pop_back(); + auto other_cell_is_a_new_cell = register_cell_and_check_if_new(other_cell); + if(!other_cell_is_a_new_cell) continue; + + // start a new component from this cell + out.facets.emplace_back(other_cell, other_cell->index(v), Star_components_facets::Type_of_facet::OPPOSITE_TO_V); + + out.face_ids_between_consecutive_components.push_back( + {component_first_incident_face_id, component_first_facet_orientation}); + out.component_incident_constraint_face_ids.push_back( + {component_first_incident_face_id, INVALID_FACE_INDEX}); // placeholder for the next component + auto& current_component_incident_constraint_face_ids = out.component_incident_constraint_face_ids.back(); + cells_in_other_components.clear(); // clear it here, and fill it again with the cells opposite to a constrained + // facet during the exploration of the current component + + if(dbg().move_Steiner_vertices_level() > 1) { + std::cerr << " (starting a new component through face with id " << component_first_incident_face_id << ")\n"; + } + // - `out.facets` is part of the result, and a queue as well, with `queue_head` as the index of + // the head of the queue: popping is done by incrementing `queue_head`, and pushing is done by + // adding new facets at the end of the vector. + for(auto queue_head = out.facets.size() - 1; queue_head != out.facets.size(); ++queue_head) { + const auto [c, facet_index, facet_type] = out.facets[queue_head]; + if(facet_type == Star_components_facets::Type_of_facet::INCIDENT_TO_V) continue; + + for(int i = 0; i < 4; ++i) + { + // follow only cells in the star of `v` + if(c->vertex(i) == v) continue; + const Cell_handle next_cell = c->neighbor(i); + + const auto facet_c_to_next_is_constrained = is_facet_constrained(Facet(c, i)); + if(facet_c_to_next_is_constrained) { + out.facets.emplace_back(c, i, Star_components_facets::Type_of_facet::INCIDENT_TO_V); + const auto constrained_facet_face_id = face_constraint_index(c, i); + if(INVALID_FACE_INDEX == current_component_incident_constraint_face_ids[1] && + constrained_facet_face_id != current_component_incident_constraint_face_ids[0]) + { + current_component_incident_constraint_face_ids[1] = constrained_facet_face_id; + } + CGAL_assertion(constrained_facet_face_id == current_component_incident_constraint_face_ids[0] || + constrained_facet_face_id == current_component_incident_constraint_face_ids[1]); + + // unless the Steiner vertex is in a face, the component will always be incident to + // two different constraint faces, and therefore we can prefer to push only cells that + // are on the other side a constraint with a different face id. + if(constrained_facet_face_id != component_first_incident_face_id || + vertex_Steiner_type == CDT_3_vertex_type::STEINER_IN_FACE ) + { + const auto orientation = constrained_facet_orientation(Facet(c, i)); + cells_in_other_components.push_back({next_cell, constrained_facet_face_id, orientation}); + } + } else { // Facet(c, i), between `c` and `next_cell` is not constrained + auto next_is_a_new_cell = register_cell_and_check_if_new(next_cell); + if(next_is_a_new_cell) { + out.facets.emplace_back(next_cell, next_cell->index(v), Star_components_facets::Type_of_facet::OPPOSITE_TO_V); + } + } + } // end for each facet of `c` + } // end while there is still a facet in the current component to process + + // end of the current component reached, start a new one if there is any cell in + // another component that we haven't processed yet + + // reorder the component to that incident facets are first + const auto component_offset = out.component_offsets.back(); + const auto begin_it = out.facets.begin() + component_offset; + const auto incident_facets_end = std::partition(begin_it, out.facets.end(), [](const auto& facet_info) { + return facet_info.type == Star_components_facets::Type_of_facet::INCIDENT_TO_V; + }); + + out.nb_of_incident_facets_for_each_component.push_back(std::distance(begin_it, incident_facets_end)); + out.component_offsets.push_back(out.facets.size()); + + if(dbg().move_Steiner_vertices_level() > 1) { + std::cerr << "- Star component #" << out.nb_of_incident_facets_for_each_component.size() + << " has:\n - " + << (out.facets.size() - component_offset) << " total facets,\n - " + << out.nb_of_incident_facets_for_each_component.back() << " facets incident to the vertex.\n" + << " It is incident to constraint faces with ids: {" + << IO::oformat(current_component_incident_constraint_face_ids) << "}\n"; + } + } // end while there is still a component to process + + CGAL_assertion_code(const auto nb_of_components = out.component_incident_constraint_face_ids.size()); + + CGAL_assertion(false == out.facets.empty()); + CGAL_assertion(nb_of_components >= 1); + CGAL_assertion(out.component_offsets.size() == nb_of_components + 1); + + CGAL_assertion(out.component_offsets.front() == 0); + CGAL_assertion(out.component_offsets.back() == out.facets.size()); + CGAL_assertion(out.face_ids_between_consecutive_components.size() == nb_of_components); + + if(vertex_Steiner_type == CDT_3_vertex_type::STEINER_IN_FACE) { + CGAL_assertion(nb_of_components == 2); + CGAL_assertion(std::all_of(out.component_incident_constraint_face_ids.begin(), out.component_incident_constraint_face_ids.end(), + [first_facet_face_id](const std::array& face_ids) + { + return face_ids[0] == first_facet_face_id && face_ids[1] == INVALID_FACE_INDEX; + })); + CGAL_assertion(std::all_of(out.face_ids_between_consecutive_components.begin(), out.face_ids_between_consecutive_components.end(), + [first_facet_face_id](const std::pair& face_id_orientation) + { + return face_id_orientation.first == first_facet_face_id; + })); + } else { + CGAL_assertion(vertex_Steiner_type == CDT_3_vertex_type::STEINER_ON_EDGE); + CGAL_assertion(std::adjacent_find(out.face_ids_between_consecutive_components.begin(), + out.face_ids_between_consecutive_components.end()) == + out.face_ids_between_consecutive_components.end()); + CGAL_assertion(nb_of_components == 1 || + std::all_of(out.component_incident_constraint_face_ids.begin(), out.component_incident_constraint_face_ids.end(), + [](const std::array& face_ids) + { + return face_ids[1] != INVALID_FACE_INDEX; + })); + } + + return out; + } // end collect_star_components_facets(..) + + enum Run_mode { NORMAL_RUN, DRY_RUN }; + + template + std::pair + fill_cdt_2_hole_with_delaunay(CDT_2& cdt_2, + Face_index face_index, + CDT_3_vertex_type vertex_type, + std::list& hole_boundary, + const Map_from_hole_edge_to_facet_3d& map_from_hole_edge_to_facet_3d, + Face_is_outside_the_face is_outside_the_face, + New_CDT_2_face_handles_output_iterator new_face_handles_out, + Run_mode run_mode = NORMAL_RUN) + { + const bool debug = dbg().move_Steiner_vertices_level() > 1 && run_mode == NORMAL_RUN; + const bool is_a_half_hole = vertex_type == CDT_3_vertex_type::STEINER_ON_EDGE; + if(debug) { + std::cerr << cdt_3_format("Filling {}hole in CDT_2 with {} edges, is_outside_the_face = {}\n", + is_a_half_hole ? "half " : "", hole_boundary.size(), + enum_cast(is_outside_the_face)); + } + auto indent_guard = IO::make_indenting_guards(debug ? "# " : "", std::cerr); + const auto at_scope_exit_guard = + make_scope_exit([&cdt_2, hole_edges = std::vector(hole_boundary.begin(), hole_boundary.end())]() { + if(std::uncaught_exceptions() > 0) { + std::cerr << "WARNING: an exception is being thrown while filling the hole, the triangulation may be left " + "in an invalid state.\n"; + return; + } + // restore the constrained/unconstrained status of edges, from a copy of `hole_boundary`. + std::for_each(hole_edges.begin(), hole_edges.end(), [&cdt_2](CDT_2_edge e) { + auto [f, i] = cdt_2.mirror_edge(e); + f->set_constraint(i, cdt_2.is_constrained(e)); + }); + }); + + if(is_outside_the_face == OUTSIDE) { + if(hole_boundary.size() <= 2) { // degenerated hole + CGAL_assertion(hole_boundary.size() == 2); // size == 1 is not possible + auto [f0, i0] = hole_boundary.front(); + auto [f1, i1] = hole_boundary.back(); + + cdt_2.tds().set_adjacency(f1, i1, f0, i0); + } else { + CGAL::fill_hole_delaunay(cdt_2, hole_boundary, boost::make_function_output_iterator([&](CDT_2_face_handle fh) { + auto& info = fh->info(); + info.is_outside_the_face = OUTSIDE; + info.missing_subface = false; + info.is_in_region = 0; + info.facet_3d = {}; + })); + } + return {new_face_handles_out, null_facet_pair()}; + } + + const CDT_2_face_handle half_hole_neighbor_face = is_a_half_hole ? hole_boundary.back().first : CDT_2_face_handle{}; + const auto [outside_2d_face, outside_2d_index] = hole_boundary.front(); + const auto first_2d_face = outside_2d_face->neighbor(outside_2d_index); + const auto v0 = vertex_3d(outside_2d_face->vertex(cdt_2.cw(outside_2d_index))); + const auto v1 = vertex_3d(outside_2d_face->vertex(cdt_2.ccw(outside_2d_index))); + const auto front_facet = first_2d_face->info().facet_3d; + const auto [front_cell, front_index] = front_facet; + CGAL_assertion(front_cell != Cell_handle{}); + const auto back_facet = tr().mirror_facet(front_facet); + const auto [back_cell, back_index] = back_facet; + + const auto index_v_front = 6 - front_index - front_cell->index(v0) - front_cell->index(v1); + const Vertex_handle v_front = front_cell->vertex(index_v_front); + const Vertex_handle v_back = back_cell->vertex(6 - back_index - back_cell->index(v0) - back_cell->index(v1)); + + if(hole_boundary.size() <= 2) { // degenerated hole + CGAL_assertion(hole_boundary.size() == 2); // size == 1 is not possible + auto [f0, i0] = hole_boundary.front(); + auto [f1, i1] = hole_boundary.back(); + + cdt_2.tds().set_adjacency(f1, i1, f0, i0); + + if(debug) { + std::cerr << "Degenerated hole with edges: (f0, " << i0 << ") and (f1, " << i1 << ")\n"; + std::cerr << "f0 is: " + << display_vert(vertex_3d(f0->vertex(0))) << "\n " + << display_vert(vertex_3d(f0->vertex(1))) << "\n " + << display_vert(vertex_3d(f0->vertex(2))) << "\n"; + std::cerr << "f1 is: " + << display_vert(vertex_3d(f1->vertex(0))) << "\n " + << display_vert(vertex_3d(f1->vertex(1))) << "\n " + << display_vert(vertex_3d(f1->vertex(2))) << "\n"; + std::cerr << "front_facet is " << IO::oformat(front_facet) << display_facet(" - ", front_facet) << "\n"; + std::cerr << "back_facet is " << IO::oformat(back_facet) << display_facet(" - ", back_facet) << "\n"; + } + + return {new_face_handles_out, Facet_pair{front_facet, back_facet}}; + } + + Facet_pair half_hole_facet_pair = null_facet_pair(); + + std::for_each(hole_boundary.begin(), hole_boundary.end(), + [](const CDT_2_edge& e) { e.first->info().is_in_region = 0; }); + + if(debug) { + std::cerr << cdt_3_format("- first_2d_face has vertices ( {} ,\n" + " {} ,\n" + " {} )\n", + display_vert(vertex_3d(first_2d_face->vertex(0))), + display_vert(vertex_3d(first_2d_face->vertex(1))), + display_vert(vertex_3d(first_2d_face->vertex(2)))); + std::cerr << cdt_3_format("- front_cell is ({}) with vertices:{}\n", + IO::oformat(front_cell), + display_facet(" - ", Facet{front_cell, front_index})) + << "\n- back vertex is "<< display_vert(v_back) << '\n'; + } + + auto action_for_each_new_2d_face = [&](CDT_2_face_handle fh_2d) { + auto& info = fh_2d->info(); + info.is_outside_the_face = INSIDE; + info.missing_subface = false; + info.is_in_region = 1; + + const auto v1 = vertex_3d(fh_2d->vertex(0)); + const auto v2 = vertex_3d(fh_2d->vertex(1)); + const auto v3 = vertex_3d(fh_2d->vertex(2)); + + if(debug) { + std::cerr << cdt_3_format("New CDT_2 face with 3D vertices ( {} ,\n" + " {} ,\n" + " {} )\n", + display_vert(v1), + display_vert(v2), + display_vert(v3)); + } + auto indent_guard = IO::make_indenting_guards(debug ? " " : "", std::cerr); + + auto new_cell = [&](Vertex_handle v_a, Vertex_handle v_b, Vertex_handle v_c, Vertex_handle v_d) { + auto cell = tr().tds().create_cell(v_a, v_b, v_c, v_d); + CGAL_assertion(!debug || this->debug().move_Steiner_vertices_allow_negative_tets() || + tr().orientation(v_a->point(), v_b->point(), v_c->point(), v_d->point()) > 0); + return cell; + }; + + const auto new_front_cell = new_cell(v1, v2, v3, v_front); + const auto new_back_cell = new_cell(v1, v3, v2, v_back); + set_adjacency_between_3d_facets({new_front_cell, 3}, {new_back_cell, 3}); + set_facet_constrained({new_front_cell, 3}, face_index, fh_2d); + + for(int i = 0; i < 3; ++i) { + const int back_cell_i = (3 - i) % 3; // the index of the neighbor in `new_back_cell` is deduced from the + // fact that `new_back_cell` was created with vertices in reversed + // order compared to `new_front_cell` + const CDT_2_face_handle neighbor_2d = fh_2d->neighbor(i); + if(debug) { + std::cerr << "-- explore neighbor(" << i << ") --\n"; + } + + if(neighbor_2d == CDT_2_face_handle{}) { + if(debug) { + std::cerr << "(neighbor not yet connected, continue)\n"; + } + // this edge of `fh_2d` is not yet connected + continue; + } else if(neighbor_2d == half_hole_neighbor_face) { + // this edge of `fh_2d` is dandling to be connected to the other part of the half hole + CGAL_assertion(half_hole_facet_pair[0].first == Cell_handle{}); // only one edge of the hole can be a half hole + half_hole_facet_pair = Facet_pair{Facet{new_front_cell, i}, Facet{new_back_cell, back_cell_i}}; + if(debug) { + std::cerr << cdt_3_format("- the 3D facet (new_front_cell={}, i={}) is ON THE BORDER of the half hole:{}\n" + , IO::oformat(new_front_cell), i + , display_facet(" ", Facet{new_front_cell, i})); + std::cerr << cdt_3_format("- its back facet (new_back_cell={}, i={}) is ON THE BORDER of the half hole:{}\n" + , IO::oformat(new_back_cell), back_cell_i + , display_facet(" ", Facet{new_back_cell, back_cell_i})); + } + continue; + } + // else + CGAL_assertion(new_front_cell->neighbor(i) == Cell_handle{}); // facet (new_front_cell, i) is no yet connected + const bool neighbor_2d_is_in_the_star = neighbor_2d->info().is_in_region; + const auto mirror_index = cdt_2.cw(neighbor_2d->index(fh_2d->vertex(cdt_2.cw(i)))); + const auto [neighbor_front_cell_3d, neighbor_front_index_3d] = + neighbor_2d_is_in_the_star ? neighbor_2d->info().facet_3d + : map_from_hole_edge_to_facet_3d.at({neighbor_2d, mirror_index}); + CGAL_assertion(neighbor_front_cell_3d != Cell_handle{}); + + const auto neighbor_back_cell_3d = neighbor_front_cell_3d->neighbor(neighbor_front_index_3d); + + const auto fh_index_in_neighbor_2d = + neighbor_2d_is_in_the_star ? neighbor_2d->index(fh_2d) : neighbor_front_index_3d; + + if(debug) { + std::cerr << cdt_3_format("- the 2D face fh_2d->neighbor(i={}) IS{} in region. Its 3D vertices are:\n" + " {}\n" + " {}\n" + " {}\n" + , i, (neighbor_2d_is_in_the_star ? "" : " NOT") + , display_vert(vertex_3d(neighbor_2d->vertex(0))) + , display_vert(vertex_3d(neighbor_2d->vertex(1))) + , display_vert(vertex_3d(neighbor_2d->vertex(2)))); + std::cerr << cdt_3_format(" * the 3D facet (new_front_cell={}, i={}) is{}\n" + , IO::oformat(new_front_cell), i + , display_facet(" ", Facet{new_front_cell, i})); + std::cerr << cdt_3_format(" * the 3D facet (neighbor_front_cell_3d={}, fh_index_in_neighbor_2d={}) is{}\n" + , IO::oformat(neighbor_front_cell_3d), fh_index_in_neighbor_2d + , display_facet(" ", Facet{neighbor_front_cell_3d, fh_index_in_neighbor_2d})); + } // end of debug output + + set_adjacency_between_3d_facets({new_front_cell, i}, {neighbor_front_cell_3d, fh_index_in_neighbor_2d}); + + const int back_cell_fh_index_in_neighbor_2d = neighbor_2d_is_in_the_star + ? (3 - fh_index_in_neighbor_2d) % 3 + : neighbor_back_cell_3d->index(neighbor_front_cell_3d); + + if(debug) { + std::cerr << cdt_3_format(" * the 3D facet (new_back_cell={}, back_cell_i={}) is{}\n" + , IO::oformat(new_back_cell), back_cell_i + , display_facet(" ", Facet{new_back_cell, back_cell_i})); + std::cerr << cdt_3_format(" * the 3D facet (neighbor_back_cell_3d={}, back_cell_fh_index_in_neighbor_2d={}) is{}\n" + , IO::oformat(neighbor_back_cell_3d), back_cell_fh_index_in_neighbor_2d + , display_facet(" ", Facet{neighbor_back_cell_3d, back_cell_fh_index_in_neighbor_2d})); + } // end of debug output + + set_adjacency_between_3d_facets({new_back_cell, back_cell_i}, + {neighbor_back_cell_3d, back_cell_fh_index_in_neighbor_2d}); + } + + + *new_face_handles_out++ = fh_2d; + }; // end of `action_for_each_new_2d_face` + switch(run_mode) { + case NORMAL_RUN: + CGAL::fill_hole_delaunay(cdt_2, hole_boundary, boost::make_function_output_iterator(action_for_each_new_2d_face)); + break; + case DRY_RUN: + CGAL::fill_hole_delaunay(cdt_2, hole_boundary, new_face_handles_out); + break; + default: + CGAL_unreachable(); + } + return {new_face_handles_out, half_hole_facet_pair}; + } + + bool maybe_flip_an_incident_edge_in_cdt_2_to_avoid_degeneracy(Vertex_handle v, Face_index face_id) { + auto& mutable_cdt_2 = non_const_face_cdt_2(face_id); + const auto vh_2d = vertex_of_cdt_2_functor(mutable_cdt_2)(v); + CGAL_assertion(vertex_3d(vh_2d) == v); + auto face_circ = mutable_cdt_2.incident_faces(vh_2d); + const auto done = face_circ; + do { + CDT_2_face_handle current = face_circ; + CDT_2_face_handle next = ++face_circ; + CDT_2_edge current_edge = {current, CDT_2::ccw(current->index(vh_2d))}; + CGAL_assertion(current_edge.first->neighbor(current_edge.second) == next); + if(current->info().is_outside_the_face == OUTSIDE || next->info().is_outside_the_face == OUTSIDE) { + continue; + } + auto current_facet_3d = current->info().facet_3d; + auto current_back_facet_3d = tr().mirror_facet(current_facet_3d); + auto next_facet_3d = next->info().facet_3d; + auto next_back_facet_3d = tr().mirror_facet(next_facet_3d); + + std::optional>> + common_cell_incident_to_current_and_next{}; + + if(current_facet_3d.first == next_facet_3d.first) { + common_cell_incident_to_current_and_next.emplace( + current_facet_3d.first, NEGATIVE, + std::array{next_facet_3d.second, current_facet_3d.second}); + } + if(current_back_facet_3d.first == next_back_facet_3d.first) { + common_cell_incident_to_current_and_next.emplace( + current_back_facet_3d.first, EQUAL, + std::array{current_back_facet_3d.second, next_back_facet_3d.second}); + } + if(common_cell_incident_to_current_and_next) { + auto [common_cell, orientation, common_cell_opposite_vertices] = *common_cell_incident_to_current_and_next; + auto [index_va, index_vb] = common_cell_opposite_vertices; + auto index_vc = tr().next_around_edge(index_va, index_vb); + auto index_vd = tr().next_around_edge(index_vb, index_va); + CGAL_assertion(common_cell->vertex(index_vd) == v); + if(dbg().move_Steiner_vertices_level() > 0) { + const auto v = tr().vertices(common_cell); + std::cerr << cdt_3_format( + "The edge (from \n" + " {} to\n" + " {})\n" + "in the CDT_2 of face F#{} must be flipped, because its incident facets \n" + "are incident to the same cell {}, with the two other vertices\n" + " {},\n" + " {})\n", + display_vert(v[index_vc]), display_vert(v[index_vd]), + face_id, + IO::oformat(common_cell), + display_vert(v[index_va]), display_vert(v[index_vb])); + } + mutable_cdt_2.flip(current_edge.first, current_edge.second); + set_facet_as_not_constrained(current_facet_3d); + set_facet_as_not_constrained(next_facet_3d); + Facet facet_c{common_cell, index_vc}; + Facet facet_d{common_cell, index_vd}; + if(orientation == NEGATIVE) { + facet_c = tr().mirror_facet(facet_c); + facet_d = tr().mirror_facet(facet_d); + } + set_facet_constrained(facet_c, face_id, next); + set_facet_constrained(facet_d, face_id, current); + CGAL_assertion(dbg().move_Steiner_vertices_level() < 2 || mutable_cdt_2.tds().is_valid(true)); + return true; + } + } while(face_circ != done); + return false; + } + + template + std::tuple + remove_Steiner_vertex_from_cdt_2(Vertex_handle v, + CDT_3_vertex_type vertex_type, + Face_index face_id, + CDT_2_vertex_handle vh_2d, + New_CDT_2_face_handles_output_iterator new_face_handles_out, + Run_mode run_mode = NORMAL_RUN) + { + const bool debug = dbg().move_Steiner_vertices_level() > 1 && run_mode == NORMAL_RUN; + std::tuple result{ + new_face_handles_out, null_facet_pair(), null_facet_pair()}; + auto& [new_face_handles_out_it, half_hole_facet_pair, second_half_hole_facet_pair] = result; + + using CDT_2_base = typename CDT_2::Triangulation; + auto& original_mutable_cdt_2 = static_cast(non_const_face_cdt_2(face_id)); + std::unique_ptr cdt_2_copy_ptr{}; + if(run_mode == DRY_RUN) { + cdt_2_copy_ptr.reset(new CDT_2_base(original_mutable_cdt_2)); + auto vh_2d_index = std::distance(original_mutable_cdt_2.all_vertices_begin(), vh_2d); + vh_2d = std::next(cdt_2_copy_ptr->all_vertices_begin(), vh_2d_index); + } + auto& mutable_cdt_2 = (run_mode == DRY_RUN) ? *cdt_2_copy_ptr : original_mutable_cdt_2; + const auto & cdt_2 = mutable_cdt_2; + + CGAL_assertion(vertex_3d(vh_2d) == v); + + if(debug) { + using std::begin; using std::end; + std::for_each(begin(cdt_2.all_face_handles()), end(cdt_2.all_face_handles()), + [](CDT_2_face_handle fh) { + fh->info().is_in_region = 0; + }); + auto face_circ = cdt_2.incident_faces(vh_2d); + const auto done = face_circ; + auto nb_of_incident_faces = 0u; + do { + face_circ->info().is_in_region = 1; + ++nb_of_incident_faces; + } while(++face_circ != done); + dump_face(face_id); + std::cerr << " -> remove Steiner vertex " << display_vert(v) << " from CDT_2 of face F#" << face_id + << " (nb of incident faces: " << nb_of_incident_faces << ")\n"; + if(!cdt_2.tds().is_valid(true, 3)) { + std::cerr << "ERROR: CDT_2 is not valid BEFORE removing Steiner vertex " << display_vert(v) + << " from face F#" << face_id << '\n'; + CGAL_error_msg("Aborting due to invalid CDT_2"); + } + } + auto indent_guard = IO::make_indenting_guards(debug ? " |" : "", std::cerr); + + auto map_from_hole_edges_to_incident_3d_facets = [&](const auto& hole_boundary_begin, const auto& hole_boundary_end, + Face_is_outside_the_face is_outside_the_face) { + CGAL::unordered_flat_map> map; + if(is_outside_the_face == OUTSIDE) + return map; + + for(auto it = hole_boundary_begin; it != hole_boundary_end; ++it) { + auto [fh_2d, index] = *it; + CGAL_assertion(!debug || cdt_2.tds().is_face(fh_2d)); + const auto neighbor_2d_inside_star = fh_2d->neighbor(index); + CGAL_assertion(!debug || cdt_2.tds().is_face(neighbor_2d_inside_star)); + const auto facet_3d = neighbor_2d_inside_star->info().facet_3d; + CGAL_assertion(facet_3d.first != Cell_handle{}); + [[maybe_unused]] auto [_, inserted] = map.insert({{fh_2d, index}, facet_3d}); + CGAL_assertion(inserted); + if(debug) { + auto back_facet_3d = tr().mirror_facet(facet_3d); + std::cerr << cdt_3_format("for the hole edge ({}, {}), the 3D facet is ({}){}\n" + " the opposite facet is ({})\n" + " opposite vertex: {}\n", + display_vert(vertex_3d(fh_2d->vertex(cdt_2.cw(index)))), + display_vert(vertex_3d(fh_2d->vertex(cdt_2.ccw(index)))), + IO::oformat(facet_3d), + display_facet(" ", facet_3d), + IO::oformat(back_facet_3d), + display_vert(back_facet_3d.first->vertex(back_facet_3d.second))); + } + } + return map; + }; + + auto carve_hole_and_fill_with_delaunay = [&](CDT_3_vertex_type vertex_type, auto& hole_boundary, + const auto& faces_to_delete, + Face_is_outside_the_face is_outside_the_face) + { + if(debug) { + std::cerr << "The star of " << display_vert(v) << " in the CDT_2 of face F#" << face_id << " has a component " + << (is_outside_the_face == OUTSIDE ? "OUTSIDE the face " : "") << "with " + << hole_boundary.size() << " edges, and " << faces_to_delete.size() << " faces:\n"; + } + auto indent_guard = IO::make_indenting_guards(debug ? " >" : "", std::cerr); + if(debug) { + for(const auto& fh_2d : faces_to_delete) { + std::cerr << cdt_3_format("- CDT_2 face with 3D vertices ( {} ,\n" + " {} ,\n" + " {} )\n", + display_vert(vertex_3d(fh_2d->vertex(0))), + display_vert(vertex_3d(fh_2d->vertex(1))), + display_vert(vertex_3d(fh_2d->vertex(2)))); + } + } // end of debug output + + // if the vertex is a Steiner point on an edge, the hole is a half-hole, and the last boundary + // edge is not part of the original hole boundary. + const auto hole_boundary_end = + vertex_type == CDT_3_vertex_type::STEINER_ON_EDGE ? std::prev(hole_boundary.end()) : hole_boundary.end(); + + const auto hole_boundary_map = + map_from_hole_edges_to_incident_3d_facets(hole_boundary.begin(), hole_boundary_end, is_outside_the_face); + + auto result = + fill_cdt_2_hole_with_delaunay(mutable_cdt_2, face_id, vertex_type, hole_boundary, hole_boundary_map, + is_outside_the_face, new_face_handles_out, run_mode); + + std::for_each(faces_to_delete.begin(), faces_to_delete.end(), + [&mutable_cdt_2](CDT_2_face_handle f) { mutable_cdt_2.delete_face(f); }); + + return result; + }; + + auto set_constrained = [&](CDT_2_edge e, bool is_constrained) { + auto [f, i] = e; + f->set_constraint(i, is_constrained); + auto [n, ni] = cdt_2.mirror_edge(e); + n->set_constraint(ni, is_constrained); + }; + + if(vertex_type == CDT_3_vertex_type::STEINER_ON_EDGE) { + + auto first_constrained_edge_circulator_before_face = [&](CDT_2_face_handle incident_fh) { + auto edge_circulator = cdt_2.incident_edges(vh_2d, incident_fh); + --edge_circulator; // take the edge before `incident_fh` + CGAL_assertion_code(const auto done = edge_circulator); + while(!cdt_2.is_constrained(*edge_circulator)) { + --edge_circulator; + CGAL_assertion(edge_circulator != done); + } + return edge_circulator; + }; + + auto advance_circulator_until_next_constrained_edge = [&](auto& edge_circulator, auto func) { + CGAL_assertion_code(const auto done = edge_circulator); + do { + ++edge_circulator; + func(*edge_circulator); + CGAL_assertion(edge_circulator != done); + } while(!cdt_2.is_constrained(*edge_circulator)); + return edge_circulator; + }; + + auto half_hole = [&](CDT_2_face_handle incident_fh) { + struct Result + { + std::list hole_side; + boost::container::small_vector to_delete; + CDT_2_edge last_incident_edge; + } result; + auto edge_circulator = first_constrained_edge_circulator_before_face(incident_fh); + result.last_incident_edge = + *advance_circulator_until_next_constrained_edge(edge_circulator, [&](CDT_2_edge current_edge) { + const auto [f, i] = current_edge; + result.to_delete.push_back(f); + const auto edge_opposite_to_v = cdt_2.mirror_edge(CDT_2_edge{f, cdt_2.cw(i)}); + result.hole_side.push_back(edge_opposite_to_v); + const auto [n, ni] = edge_opposite_to_v; + n->vertex(cdt_2.cw(ni))->set_face(n); + n->vertex(cdt_2.ccw(ni))->set_face(n); + }); + return result; + }; + + auto [hole_side_1, hole_side_1_faces_to_delete, side_1_last_incident_edge] = half_hole(vh_2d->face()); + const auto [side_1_last_face, side_1_last_edge_index] = side_1_last_incident_edge; + const auto side_1_hole_is_outside_the_face = side_1_last_face->info().is_outside_the_face; + + const auto side_2_first_face = side_1_last_face->neighbor(side_1_last_edge_index); + + auto [hole_side_2, hole_side_2_faces_to_delete, side_2_last_incident_edge] = half_hole(side_2_first_face); + const auto [side_2_last_face, side_2_last_edge_index] = side_2_last_incident_edge; + const auto side_2_hole_is_outside_the_face = side_2_last_face->info().is_outside_the_face; + + CGAL_assertion(side_1_last_incident_edge.first != side_2_last_incident_edge.first); + + // unmark the two constrained edges + set_constrained(side_1_last_incident_edge, false); + set_constrained(side_2_last_incident_edge, false); + + // start boring and sewing the two half-holes: + // - we start from side 1, + // - `side_2_last_face` will temporarily be modified to close `hole_side_1` + const auto v1 = side_1_last_face->vertex(cdt_2.ccw(side_1_last_edge_index)); + side_2_last_face->set_vertex(cdt_2.cw(side_2_last_edge_index), v1); + hole_side_1.push_back(side_2_last_incident_edge); + + // - bore the hole on side 1, and fill it with CDT triangles + auto [out_it, facet_pair_side_1] = carve_hole_and_fill_with_delaunay( + vertex_type, hole_side_1, hole_side_1_faces_to_delete, side_1_hole_is_outside_the_face); + new_face_handles_out = out_it; + CGAL_assertion(run_mode == DRY_RUN || + side_1_hole_is_outside_the_face == OUTSIDE || facet_pair_side_1[0].first != Cell_handle{}); + + // - now the edge opposite to `(side_2_last_face, side_2_last_edge_index)` is on the border of the hole + // `hole_side_2`, so we can start sewing from there + const auto side_1_border_edge = cdt_2.mirror_edge(CDT_2_edge{side_2_last_face, side_2_last_edge_index}); + hole_side_2.push_back(side_1_border_edge); + auto [out_it_2, facet_pair_side_2] = carve_hole_and_fill_with_delaunay( + vertex_type, hole_side_2, hole_side_2_faces_to_delete, side_2_hole_is_outside_the_face); + new_face_handles_out = out_it_2; + CGAL_assertion(run_mode == DRY_RUN || + side_2_hole_is_outside_the_face == OUTSIDE || facet_pair_side_2[0].first != Cell_handle{}); + + half_hole_facet_pair = facet_pair_side_1; + second_half_hole_facet_pair = facet_pair_side_2; + + // - then re-mark the edge between the two holes as a constrained edge + set_constrained(side_1_border_edge, true); + } else { // if vertex_type != CDT_3_vertex_type::STEINER_ON_EDGE + CGAL_assertion(vertex_type == CDT_3_vertex_type::STEINER_IN_FACE); + + auto [hole_boundary, faces_to_delete] = std::invoke([&]() { + struct Result + { + std::list hole_boundary; + boost::container::small_vector to_delete; + } result; + auto face_circulator = cdt_2.incident_faces(vh_2d); + const auto done = face_circulator; + do { + const CDT_2_face_handle fh_2d = face_circulator; + auto v_index = fh_2d->index(vh_2d); + CDT_2_edge opposite_edge = cdt_2.mirror_edge(CDT_2_edge{fh_2d, v_index}); + auto adjacent_vertex = fh_2d->vertex(cdt_2.cw(v_index)); + adjacent_vertex->set_face(opposite_edge.first); + result.hole_boundary.push_back(opposite_edge); + result.to_delete.push_back(fh_2d); + } while(++face_circulator != done); + return result; + }); + + auto [out_it, facet_pair] = + carve_hole_and_fill_with_delaunay(vertex_type, hole_boundary, faces_to_delete, INSIDE); + new_face_handles_out = out_it; + CGAL_assertion(facet_pair[0].first == Cell_handle{}); + } + mutable_cdt_2.delete_vertex(vh_2d); + if(debug) { + dump_face(face_id, std::string("dump_face_") + std::to_string(face_id) + "_after_removing_Steiner_vertex_" + + std::to_string(vh_2d->time_stamp()) + ".off"); + + if(!cdt_2.tds().is_valid(true, 3)) { + std::cerr << "ERROR: CDT_2 is not valid after removing Steiner vertex " << with_point_and_info(v) + << " from face F#" << face_id << '\n'; + CGAL_error_msg("Aborting due to invalid CDT_2"); + } + } + new_face_handles_out_it = new_face_handles_out; + return result; + } // end of `remove_Steiner_vertex_from_cdt_2` + + bool move_one_Steiner_vertex_to_the_volume(Vertex_handle v) { + if(dbg().move_Steiner_vertices()) { + auto _ = IO::make_color_guards(std::cerr); + std::cerr << "Moving Steiner vertex " << display_vert(v) << " to the volume\n"; + } + auto indent_guards = CGAL::IO::make_indenting_guards(dbg().move_Steiner_vertices_level() > 1 ? "| " : "", std::cerr); + + CGAL::unordered_flat_map face_to_cdt_2_vertex_for_v; + const auto v_type = vertex_type(v); + if(v_type == CDT_3_vertex_type::STEINER_IN_FACE) { + const auto incident_face_id = v->ccdt_3_data().face_index(); + face_to_cdt_2_vertex_for_v.emplace(incident_face_id, + vertex_of_cdt_2_functor(non_const_face_cdt_2(incident_face_id))(v)); + while(maybe_flip_an_incident_edge_in_cdt_2_to_avoid_degeneracy(v, incident_face_id)) {} + } else { + CGAL_assertion(v_type == CDT_3_vertex_type::STEINER_ON_EDGE); + const auto incident_polyline_constraint_id = v->ccdt_3_data().constrained_polyline_id(*this); + for(const auto& [_, incident_face_id] : + CGAL::make_range(this->incident_faces_to_polyline.equal_range(incident_polyline_constraint_id))) + { + face_to_cdt_2_vertex_for_v.emplace(incident_face_id, + vertex_of_cdt_2_functor(non_const_face_cdt_2(incident_face_id))(v)); + while(maybe_flip_an_incident_edge_in_cdt_2_to_avoid_degeneracy(v, incident_face_id)) {} + } + } + + const auto incident_constrained_facet_opt = + find_in_incident_facets(v, [this](Facet f) { return is_facet_constrained(f); }); + CGAL_assertion(incident_constrained_facet_opt.has_value()); + + const auto incident_constrained_facet = *incident_constrained_facet_opt; + + if(dbg().move_Steiner_vertices_level() > 1) { + const auto nb_of_incident_cells = std::invoke([&]() { + std::size_t nb_of_incident_cells{0}; + tr().incident_cells(v, CGAL::Counting_output_iterator(&nb_of_incident_cells)); + return nb_of_incident_cells; + }); + + std::cerr << "- Number of incident cells: " << nb_of_incident_cells << '\n'; + } + + const auto star_components = collect_star_components_facets(v, incident_constrained_facet); + const auto nb_of_star_components = star_components.component_incident_constraint_face_ids.size(); + + if(dbg().move_Steiner_vertices_level() > 1) { + std::cerr << "- Nb of components of the star: " << nb_of_star_components << '\n'; + } + if(nb_of_star_components == 1) { + if(dbg().move_Steiner_vertices_level() > 1) { + auto _ = IO::make_color_guards(std::cerr); + std::cerr << "- Only one component in the star, cannot move the vertex to the volume, aborting\n"; + } + return false; + } + std::map> map_from_incident_constraint_face_id_to_new_triangles; + + auto dry_run_output_iterator = [&](Face_index face_id) { + auto* triangles_for_this_face_ptr = &map_from_incident_constraint_face_id_to_new_triangles[face_id]; + std::function func = [&,triangles_for_this_face_ptr](CDT_2_face_handle fh_2d) { + const auto v1 = vertex_3d(fh_2d->vertex(0)); + const auto v2 = vertex_3d(fh_2d->vertex(1)); + const auto v3 = vertex_3d(fh_2d->vertex(2)); + triangles_for_this_face_ptr->emplace_back(v1->point(), v2->point(), v3->point()); + }; + return boost::make_function_output_iterator(func); + }; + + if(v_type == CDT_3_vertex_type::STEINER_IN_FACE) { + CGAL_assertion(star_components.component_incident_constraint_face_ids.size() == 2); + [[maybe_unused]] const auto& [face_id, _] = star_components.face_ids_between_consecutive_components.front(); + remove_Steiner_vertex_from_cdt_2(v, v_type, face_id, face_to_cdt_2_vertex_for_v[face_id], + dry_run_output_iterator(face_id), DRY_RUN); + } else { + CGAL_assertion(v_type == CDT_3_vertex_type::STEINER_ON_EDGE); + for(std::size_t component_index = 0, end = star_components.face_ids_between_consecutive_components.size(); + component_index < end; ++component_index) + { + const auto& [face_id, _] = star_components.face_ids_between_consecutive_components[component_index]; + + remove_Steiner_vertex_from_cdt_2(v, v_type, face_id, face_to_cdt_2_vertex_for_v[face_id], + dry_run_output_iterator(face_id), DRY_RUN); + } + } + + const auto components_central_points = std::invoke([&]() { + std::optional> central_points{std::in_place}; + central_points->reserve(nb_of_star_components); + for(std::size_t component_index = 1; component_index <= nb_of_star_components; ++component_index) { + auto component_mesh = construct_star_component_mesh(component_index, star_components, + map_from_incident_constraint_face_id_to_new_triangles); + if(dbg().move_Steiner_vertices_level() > 1) { + std::ostringstream ss; + ss << "dump_vertex_" << with_offset(v) << "_component_" << component_index << ".ply"; + CGAL::IO::write_PLY(ss.str(), component_mesh, CGAL::parameters::stream_precision(17)); + } + std::chrono::steady_clock::time_point start_time = std::chrono::steady_clock::now(); + auto opt_kernel_center_point = compute_center_point_if_possible(component_mesh); + std::chrono::duration elapsed_time = std::chrono::steady_clock::now() - start_time; + if(dbg().move_Steiner_vertices_level() > 1) { + std::cerr << " - incident constraint faces ids of component #" << component_index << ": {" + << IO::oformat(star_components.component_incident_constraint_face_ids[component_index - 1]) + << "}\n"; + std::cerr << " kernel center point of component #" << component_index << ": "; + } + if(dbg().move_Steiner_vertices_level() > 0) { + std::cerr << " computation time for kernel_point of component #" << component_index << ": " << elapsed_time.count() << " s\n"; + } + if(opt_kernel_center_point.has_value()) { + auto kernel_center_point = this->exact(*opt_kernel_center_point); + central_points->push_back(kernel_center_point); + if(dbg().move_Steiner_vertices_level() > 1) { + std::cerr << *opt_kernel_center_point << " (distance to vertex: " + << CGAL::approximate_sqrt(CGAL::squared_distance(kernel_center_point, v->point())) << ")" + << "\n"; + } + } else { + if(dbg().move_Steiner_vertices_level() > 1) { + auto _ = IO::make_color_guards(std::cerr); + std::cerr << "none (the component is either degenerate or open) ABORT\n"; + } + if(!this->debug().move_Steiner_vertices_allow_negative_tets()) { + central_points.reset(); + return central_points; + } else { + central_points->push_back(tr().point(v)); // push the current position of the vertex as a fallback + } + } + } + return central_points; + }); // end compute central points for each component + + if(dbg().move_Steiner_vertices_level() > 1) { + dump_link_mesh_of_vertex_to_ply(v, star_components, map_from_incident_constraint_face_id_to_new_triangles); + } + + if(!components_central_points.has_value()) { + if(dbg().move_Steiner_vertices_level() > 0) { + auto _ = IO::make_color_guards(std::cerr); + std::cerr << "- No central point could be computed for at least one of the components, aborting moving the " + "vertex to the volume\n"; + // CGAL_error(); + } + return false; + } + CGAL_assertion(components_central_points->size() == nb_of_star_components); + boost::container::small_vector new_center_vertices; + new_center_vertices.reserve(nb_of_star_components); + + for(std::size_t component_index = 1; component_index <= nb_of_star_components; ++component_index) + { + const auto star_component_new_center_vertex = tr().tds().create_vertex(); + star_component_new_center_vertex->ccdt_3_data().set_vertex_type(CDT_3_vertex_type::STEINER_IN_VOLUME); + star_component_new_center_vertex->set_point((*components_central_points)[component_index - 1]); + new_center_vertices.push_back(star_component_new_center_vertex); + + const auto& component_facets = star_components.component_facets_range(component_index); + for(const auto& [cell, facet_index, facet_type] : component_facets) { + if(facet_type == Star_components_facets::Type_of_facet::INCIDENT_TO_V) { + continue; + } + cell->set_vertex(facet_index, star_component_new_center_vertex); + + // now unconstrain the facets of `cell` that were incident to `v`, because they are now + // incident to `star_component_new_center_vertex` instead of `v`. + for(int i = 0; i < 3; ++i) { + const auto incident_facet_index = Tds::vertex_triple_index(facet_index, i); + set_facet_as_not_constrained(Facet{cell, incident_facet_index}); + } + } // end for each facet of the current component, which are now all incident to `star_component_new_center_vertex` + using std::begin; + star_component_new_center_vertex->set_cell(begin(component_facets)->cell); // cell of the first facet + } // loop on each component of the star of `v` + - using Color_value_type = std::int8_t; - struct Face_info - { - Color_value_type is_outside_the_face = -1; - Color_value_type is_in_region = 0; - std::bitset<3> is_edge_also_in_3d_triangulation = 0; - bool missing_subface = true; - Facet facet_3d = {}; - }; - using Vb1 = Triangulation_vertex_base_with_info_2; - using Vb = Triangulation_simplex_base_with_time_stamp; - using Fb1 = Triangulation_face_base_with_info_2; - using Fb = Constrained_triangulation_face_base_2; - using TDS = Triangulation_data_structure_2; - using Itag = No_constraint_intersection_requiring_constructions_tag; - using CDT_base = Constrained_Delaunay_triangulation_2; - using CDT = Constrained_triangulation_plus_2; + std::size_t nb_of_new_2d_faces = 0; + CGAL::Counting_output_iterator output_iterator{&nb_of_new_2d_faces}; - template struct CDT_2_dual_color_map - { - using category = boost::read_write_property_map_tag; - using reference = Color_value_type&; - using value_type = Color_value_type; - using key_type = typename CDT::Face_handle; + if(v_type == CDT_3_vertex_type::STEINER_IN_FACE) { + CGAL_assertion(star_components.component_incident_constraint_face_ids.size() == 2); + const auto& [face_id, orientation] = star_components.face_ids_between_consecutive_components.front(); + auto [new_output_iterator, half_hole_front_facet, second_half_hole_front_facet] = + remove_Steiner_vertex_from_cdt_2(v, v_type, face_id, face_to_cdt_2_vertex_for_v[face_id], output_iterator); + output_iterator = new_output_iterator; + } else { + CGAL_assertion(v_type == CDT_3_vertex_type::STEINER_ON_EDGE); + std::optional previous_facet_to_reconnect_opt; + std::optional last_facet_to_reconnect_to_opt; + for(std::size_t component_index = 0, end = star_components.face_ids_between_consecutive_components.size(); + component_index < end; ++component_index) + { + const auto& [face_id, orientation] = star_components.face_ids_between_consecutive_components[component_index]; + if(dbg().move_Steiner_vertices_level() > 1) { + std::cerr << "Component " << (component_index+1) << " with center " + << display_vert(new_center_vertices[component_index]) << "\n"; + if(this->debug().move_Steiner_vertices_level() > 2) { + const auto& component_facets = star_components.component_facets_range(component_index+1); + for(const auto& [cell, facet_index, facet_type] : component_facets) { + std::cerr << cdt_3_format(" - facet ({}) of with vertices:{}\n", + IO::oformat(Facet{cell, facet_index}), + display_facet(" ", Facet{cell, facet_index})); + } + } + std::cerr << "Now remove the Steiner vertex from the CDT_2 of face with id " << face_id << " (orientation: " + << (orientation == CGAL::NEGATIVE ? "negative" : "positive") << ")\n"; + } + auto [new_output_iterator, half_hole_facet_pair, second_half_hole_facet_pair] = + remove_Steiner_vertex_from_cdt_2(v, v_type, face_id, face_to_cdt_2_vertex_for_v[face_id], output_iterator); + output_iterator = new_output_iterator; - friend reference get(CDT_2_dual_color_map, key_type fh) { return fh->info().*member_ptr; } - friend void put(CDT_2_dual_color_map, key_type fh, value_type value) { fh->info().*member_ptr = value; } - }; - using Color_map_is_outside_the_face = CDT_2_dual_color_map<&Face_info::is_outside_the_face>; - using Color_map_is_in_region = CDT_2_dual_color_map<&Face_info::is_in_region>; - }; // CDT_2_types - using CDT_2 = typename CDT_2_types::CDT; - using CDT_2_traits = typename CDT_2_types::Projection_traits; - using CDT_2_face_handle = typename CDT_2::Face_handle; - using CDT_2_edge = typename CDT_2::Edge; - static_assert(CGAL::cdt_3_msvc_2019_or_older() || CGAL::is_nothrow_movable_v); + auto facet_pair_to_reconnect = half_hole_facet_pair; + if(facet_pair_to_reconnect[0].first == Cell_handle{}) { + facet_pair_to_reconnect = second_half_hole_facet_pair; + } + CGAL_assertion(facet_pair_to_reconnect[0].first != Cell_handle{}); + if(true == facet_pair_to_reconnect[0].first->has_vertex(new_center_vertices[component_index]) && + false == facet_pair_to_reconnect[1].first->has_vertex(new_center_vertices[component_index])) + { + if(dbg().move_Steiner_vertices_level() > 1) { std::cerr << "SWAPPING facet pair to reconnect\n"; } + std::swap(facet_pair_to_reconnect[0], facet_pair_to_reconnect[1]); + } + if(dbg().move_Steiner_vertices_level() > 1) { + std::cerr << cdt_3_format("The facet ({}) to reconnect in the 3D triangulation is:{}\n", + IO::oformat(facet_pair_to_reconnect[0]), + display_facet(" - ", facet_pair_to_reconnect[0])); + std::cerr << cdt_3_format("The facet ({}) on the other side of the CDT_2 is:{}\n", + IO::oformat(facet_pair_to_reconnect[1]), + display_facet(" - ", facet_pair_to_reconnect[1])); + } -protected: - struct Null_normal_error : Error_exception { - Null_normal_error(std::string msg, std::string file, int line) - : Error_exception("CGAL CDT_3", msg, file, line) - { + if(!last_facet_to_reconnect_to_opt.has_value()) { + last_facet_to_reconnect_to_opt = facet_pair_to_reconnect[0]; + CGAL_assertion(previous_facet_to_reconnect_opt.has_value() == false); + } + else if(previous_facet_to_reconnect_opt.has_value()) { + set_adjacency_between_3d_facets(previous_facet_to_reconnect_opt.value(), facet_pair_to_reconnect[0]); + } + previous_facet_to_reconnect_opt = facet_pair_to_reconnect[1]; + } + CGAL_assertion(previous_facet_to_reconnect_opt.has_value()); + CGAL_assertion(last_facet_to_reconnect_to_opt.has_value()); + set_adjacency_between_3d_facets(previous_facet_to_reconnect_opt.value(), + last_facet_to_reconnect_to_opt.value()); } - }; - using Constraint_hierarchy = typename Conforming_Dt::Constraint_hierarchy; - using Subconstraint = typename Constraint_hierarchy::Subconstraint; -public: - using Constrained_polyline_id = typename Constraint_hierarchy::Constraint_id; + if(dbg().move_Steiner_vertices_level() > 1) { + std::cerr << "- number of new 2D faces created in the CDT: " << nb_of_new_2d_faces << '\n'; + } -protected: + tr().tds().delete_vertex(v); + + CGAL_assertion(dbg().move_Steiner_vertices_level() < 2 || tr().tds().is_valid(true)); + + return true; + } // end move_one_Steiner_vertex_to_the_volume(..) void register_facet_to_be_constrained(Cell_handle cell, int facet_index) { const auto face_id = static_cast(cell->ccdt_3_data().face_constraint_index(facet_index)); @@ -1336,7 +2921,7 @@ class Conforming_constrained_Delaunay_triangulation_3_impl : public Conforming_D auto fh_2 = cell->ccdt_3_data().face_2(this->face_cdt_2(face_id), facet_index); fh_2->info().facet_3d = Facet{}; fh_2->info().missing_subface = true; - this->set_facet_constrained({cell, facet_index}, -1, {}); + this->set_facet_as_not_constrained({cell, facet_index}); } void register_facet_to_be_constrained(Facet f) { @@ -1361,12 +2946,12 @@ class Conforming_constrained_Delaunay_triangulation_3_impl : public Conforming_D auto c = *cell_it; for(int li = first_li; li < 4; ++li) { if(c->ccdt_3_data().is_facet_constrained(li)) { - #if CGAL_CDT_3_DEBUG_MISSING_TRIANGLES - auto face_id = static_cast(c->ccdt_3_data().face_constraint_index(li)); - auto fh_2 = c->ccdt_3_data().face_2(self->face_cdt_2(face_id), li); - std::cerr << "Add missing triangle (from visitor), face F#" << face_id << ": \n"; - self->write_2d_triangle(std::cerr, fh_2); - #endif // CGAL_CDT_3_DEBUG_MISSING_TRIANGLES + if(self->debug().missing_triangles()) { + auto face_id = static_cast(c->ccdt_3_data().face_constraint_index(li)); + auto fh_2 = c->ccdt_3_data().face_2(self->face_cdt_2(face_id), li); + std::cerr << "Add missing triangle (from visitor), face F#" << face_id << ": \n"; + self->write_2d_triangle(std::cerr, fh_2); + } self->register_facet_to_be_constrained(c, li); } } @@ -1389,6 +2974,39 @@ class Conforming_constrained_Delaunay_triangulation_3_impl : public Conforming_D void hide_point(Cell_handle, const Point_3 &) const {} + bool is_facet_protected(Facet f) const { + return self->is_facet_constrained(f); + } + + void after_flip23(Vertex_handle va, Vertex_handle vb, Facet facet) const { + const auto [cell, _] = facet; + const auto ia = cell->index(va); + const auto ib = cell->index(vb); + const auto ic = Tds::next_around_edge(ia, ib); + const auto id = Tds::next_around_edge(ib, ia); + + for(const auto cell : make_array(cell, cell->neighbor(ic), cell->neighbor(id))) { + const auto ia = cell->index(va); + const auto ib = cell->index(vb); + for(auto index : make_array(ia, ib)) { + const Facet f{cell, index}; + const Facet mirror_facet = self->mirror_facet(f); + const auto [mirror_cell, mirror_index] = mirror_facet; + if(mirror_cell->ccdt_3_data().is_facet_constrained(mirror_index)) { + auto face_id = self->face_constraint_index(mirror_cell, mirror_index); + const CDT_2& cdt_2 = self->face_cdt_2(face_id); + const auto f2d = mirror_cell->ccdt_3_data().face_2(cdt_2, mirror_index); + Facet oriented_facet = self->same_triple(f, f2d) ? f : mirror_facet; + self->set_facet_constrained(oriented_facet, face_id, f2d); + } else { + self->set_facet_as_not_constrained(f); + } + } + const auto ic = Tds::next_around_edge(ia, ib); + self->set_facet_as_not_constrained({cell, ic}); + } + } + void insert_Steiner_point_on_constraint(Constrained_polyline_id constraint, Vertex_handle va, Vertex_handle vb, @@ -1417,8 +3035,18 @@ class Conforming_constrained_Delaunay_triangulation_3_impl : public Conforming_D fh_2d->set_constraint(edge_index, false); mirror_fh_2d->set_constraint(mirror_edge_index, false); + std::vector faces_in_conflict; + non_const_cdt_2.get_conflicts(point, std::back_inserter(faces_in_conflict), fh_2d); + for(auto fh : faces_in_conflict) { + if(fh->info().is_outside_the_face != OUTSIDE) { + auto facet_3d = fh->info().facet_3d; + if(facet_3d.first != Cell_handle{}) { + self->set_facet_as_not_constrained(facet_3d); + } + } + } const auto v_Steiner_2d = non_const_cdt_2.insert(point, fh_2d); - v_Steiner_2d->info().vertex_handle_3d = v_Steiner; + vertex_3d(v_Steiner_2d) = v_Steiner; non_const_cdt_2.insert_constraint(va_2d, v_Steiner_2d); non_const_cdt_2.insert_constraint(vb_2d, v_Steiner_2d); @@ -1438,10 +3066,18 @@ class Conforming_constrained_Delaunay_triangulation_3_impl : public Conforming_D fc->info().is_outside_the_face = outside_on_left; fc->info().is_in_region = in_region_on_left; } while(++fc != fc_begin); - fc = cdt_2.incident_faces(v_Steiner_2d, fh_2d); - fc_begin = fc; + fc = fc_begin; do { - fc->info().missing_subface = true; + auto is_facet = self->is_2d_face_also_a_3d_facet(fc); + if(!is_facet) { + fc->info().missing_subface = (fc->info().is_outside_the_face != OUTSIDE); + } else { + if((fc->info().is_outside_the_face != OUTSIDE)) { + const auto [facet, orient] = *is_facet; + fc->info().missing_subface = false; + self->set_facet_constrained(facet, polygon_id, fc, orient); + } + } const auto v_Steiner_index = fc->index(v_Steiner_2d); const auto other_edge = cdt_2.mirror_edge({fc, v_Steiner_index}); fc->info().is_edge_also_in_3d_triangulation.set(other_edge.first->info().is_edge_also_in_3d_triangulation.test(other_edge.second)); @@ -1491,12 +3127,12 @@ class Conforming_constrained_Delaunay_triangulation_3_impl : public Conforming_D switch(tr().dimension()) { case 3: { typename T_3::Conflict_tester_3 tester(p, this); - this->find_conflicts(ch, tester, triple_of_output_iterators); + tr().find_conflicts(ch, tester, triple_of_output_iterators); break; } // dim 3 case 2: { typename T_3::Conflict_tester_2 tester(p, this); - this->find_conflicts(ch, tester, triple_of_output_iterators); + tr().find_conflicts(ch, tester, triple_of_output_iterators); break; } // dim 2 default: CGAL_error(); @@ -1528,8 +3164,7 @@ class Conforming_constrained_Delaunay_triangulation_3_impl : public Conforming_D // vertices of the border of the cavity should point to cells outside of it for(auto [c, index]: exterior_border_facets_of_original_cavity) { - for(int i = 0; i < 3; ++i) { - auto v = c->vertex(tr().vertex_triple_index(index, i)); + for(auto v : tr().vertices(Facet{c, index})) { v->set_cell(c); } } @@ -1547,22 +3182,21 @@ class Conforming_constrained_Delaunay_triangulation_3_impl : public Conforming_D typename T_3::Vertex_triple_Facet_map outer_map; for(auto f: facets_of_cavity) { - typename T_3::Vertex_triple vt = this->make_vertex_triple(f); - this->make_canonical_oriented_triple(vt); + auto vt = T_3::make_canonical_oriented_triple(f); outer_map[vt] = f; } const auto inner_map = tr().create_triangulation_inner_map( cavity_triangulation, map_cavity_vertices_to_ambient_vertices, the_infinite_vertex_is_in_the_cavity); - this->copy_triangulation_into_hole(map_cavity_vertices_to_ambient_vertices, - std::move(outer_map), - inner_map, - this->new_cells_output_iterator()); + tr().copy_triangulation_into_hole(map_cavity_vertices_to_ambient_vertices, + std::move(outer_map), + inner_map, + this->new_cells_output_iterator()); for(auto outside_facet : facets_of_cavity) { const auto [outside_cell, outside_face_index] = outside_facet; - const auto mirror_facet = this->mirror_facet(outside_facet); + const auto mirror_facet = tr().mirror_facet(outside_facet); if(outside_cell->ccdt_3_data().is_facet_constrained(outside_face_index)) { const auto polygon_id = outside_cell->ccdt_3_data().face_constraint_index(outside_face_index); const CDT_2& cdt_2 = face_cdt_2(polygon_id); @@ -1577,7 +3211,7 @@ class Conforming_constrained_Delaunay_triangulation_3_impl : public Conforming_D this->new_vertex(p_vh); - CGAL_assume(!this->debug().validity() || this->is_valid(true)); + CGAL_assertion(!this->debug().validity() || tr().tds().is_valid(true)); return p_vh; } @@ -1645,12 +3279,12 @@ class Conforming_constrained_Delaunay_triangulation_3_impl : public Conforming_D if(false == get(v_filter_map, v)) continue; } auto vh = this->insert(get(vertex_point_map, v), hint_ch, false); - vh->ccdt_3_data().set_vertex_type(CDT_3_vertex_type::CORNER); + vh->ccdt_3_data().set_vertex_type(CDT_3_vertex_type::INPUT_VERTEX); hint_ch = vh->cell(); put(tr_vertex_pmap, v, vh); } - add_bbox_points_if_not_dimension_3(); + add_bbox_points(); if(this->debug().display_statistics()) { @@ -1755,43 +3389,20 @@ class Conforming_constrained_Delaunay_triangulation_3_impl : public Conforming_D return f.first->ccdt_3_data().is_facet_constrained(f.second); } - auto number_of_constrained_facets() const + CDT_3_signed_index face_constraint_index(Cell_handle ch, int i) const { - return std::count_if(tr().all_facets_begin(), tr().all_facets_end(), - [this](auto f) { return is_facet_constrained(f); }); + return ch->ccdt_3_data().face_constraint_index(i); } - bool same_triangle(Facet f, CDT_2_face_handle fh) const { - return true; - const auto [c, facet_index] = f; - std::array f_vertices{c->vertex(tr().vertex_triple_index(facet_index,0)), - c->vertex(tr().vertex_triple_index(facet_index,1)), - c->vertex(tr().vertex_triple_index(facet_index,2))}; - std::sort(f_vertices.begin(), f_vertices.end()); - std::array fh_vertices{fh->vertex(0)->info().vertex_handle_3d, - fh->vertex(1)->info().vertex_handle_3d, - fh->vertex(2)->info().vertex_handle_3d}; - std::sort(fh_vertices.begin(), fh_vertices.end()); - return (f_vertices == fh_vertices); + CDT_3_signed_index face_constraint_index(const Facet& f) const + { + return face_constraint_index(f.first, f.second); } - void set_facet_constrained(Facet f, CDT_3_signed_index polygon_constraint_id, - CDT_2_face_handle fh) + auto number_of_constrained_facets() const { - CGAL_assertion(fh == CDT_2_face_handle{} || same_triangle(f, fh)); - - const auto [c, facet_index] = f; - c->ccdt_3_data().set_facet_constraint(facet_index, polygon_constraint_id, fh); - if(tr().dimension() > 2) { - const auto [n, n_index] = tr().mirror_facet({c, facet_index}); - n->ccdt_3_data().set_facet_constraint(n_index, polygon_constraint_id, fh); - } - if(fh == CDT_2_face_handle{}) return; - - if(fh != CDT_2_face_handle{}) { - fh->info().facet_3d = f; - fh->info().missing_subface = false; - } + return std::count_if(tr().all_facets_begin(), tr().all_facets_end(), + [this](auto f) { return is_facet_constrained(f); }); } template ) Polygon> @@ -1983,11 +3594,11 @@ class Conforming_constrained_Delaunay_triangulation_3_impl : public Conforming_D return {min_distance, vertices_of_min_edge}; } - static void print_minimum_distance_info(const Min_distance_result& min_dist) { + void print_minimum_distance_info(const Min_distance_result& min_dist) const { std::cout << "Min distance between vertices: " << min_dist.min_distance << '\n' << " between vertices: : " - << CGAL::IO::oformat(min_dist.vertices_of_min_edge[0], CGAL::With_point_tag{}) << " " - << CGAL::IO::oformat(min_dist.vertices_of_min_edge[1], CGAL::With_point_tag{}) << "\n\n"; + << display_vert(min_dist.vertices_of_min_edge[0]) << " " + << display_vert(min_dist.vertices_of_min_edge[1]) << "\n\n"; } struct Constraint_distance_result { @@ -2079,10 +3690,10 @@ class Conforming_constrained_Delaunay_triangulation_3_impl : public Conforming_D if(this->debug().display_statistics()) { std::cout << "Min distance between constraint segment and vertex: " << min_distance << '\n' << " between segment : " - << CGAL::IO::oformat(min_va, CGAL::With_point_tag{}) << " " - << CGAL::IO::oformat(min_vb, CGAL::With_point_tag{}) << '\n' + << with_point(min_va) << " " + << with_point(min_vb) << '\n' << " and vertex : " - << CGAL::IO::oformat(min_vertex, CGAL::With_point_tag{}) << "\n\n"; + << with_point(min_vertex) << "\n\n"; } this->check_segment_vertex_distance_or_throw(min_va, min_vb, min_vertex, min_distance); } @@ -2098,8 +3709,8 @@ class Conforming_constrained_Delaunay_triangulation_3_impl : public Conforming_D if(this->debug().display_statistics()) { std::cout << "Min distance between vertices: " << result.min_distance << '\n' << " between vertices : " - << CGAL::IO::oformat(result.vertices_of_min_edge[0], CGAL::With_point_tag{}) << " " - << CGAL::IO::oformat(result.vertices_of_min_edge[1], CGAL::With_point_tag{}) << "\n\n"; + << with_point(result.vertices_of_min_edge[0]) << " " + << with_point(result.vertices_of_min_edge[1]) << "\n\n"; } this->check_vertex_vertex_distance_or_throw(result.vertices_of_min_edge[0], result.vertices_of_min_edge[1], @@ -2125,6 +3736,38 @@ class Conforming_constrained_Delaunay_triangulation_3_impl : public Conforming_D } } + auto vertex_type(Vertex_handle v) const { + return v->ccdt_3_data().vertex_type(); + } + + bool is_Steiner_vertex_on_surface(Vertex_handle v) const { + switch(vertex_type(v)) { + case CDT_3_vertex_type::INPUT_VERTEX: + case CDT_3_vertex_type::FREE: + case CDT_3_vertex_type::STEINER_IN_VOLUME: + case CDT_3_vertex_type::BBOX: + return false; + case CDT_3_vertex_type::STEINER_IN_FACE: + case CDT_3_vertex_type::STEINER_ON_EDGE: + return true; + } + CGAL_unreachable(); + } + + auto move_Steiner_vertices_to_the_volume() { + if(dbg().move_Steiner_vertices_level() > 1) { + std::cerr << "move_Steiner_vertices_to_the_volume()\n"; + dump_constrained_facets_to_off("dump_before_moving_steiner_vertices.off"); + } + std::vector steiner_vertices; + for(auto v : this->finite_vertex_handles()) { + if(is_Steiner_vertex_on_surface(v)) steiner_vertices.push_back(v); + } + for(auto v : steiner_vertices) { + move_one_Steiner_vertex_to_the_volume(v); + } + CGAL_assertion(tr().tds().is_valid(true)); + } private: @@ -2138,7 +3781,6 @@ class Conforming_constrained_Delaunay_triangulation_3_impl : public Conforming_D case Vertex_marker::CAVITY: std::cerr << "CAVITY"; break; case Vertex_marker::CAVITY_ABOVE: std::cerr << "CAVITY_ABOVE"; break; case Vertex_marker::CAVITY_BELOW: std::cerr << "CAVITY_BELOW"; break; - case Vertex_marker::nb_of_markers: CGAL_unreachable(); break; } std::cerr << ")\n"; } @@ -2199,9 +3841,7 @@ class Conforming_constrained_Delaunay_triangulation_3_impl : public Conforming_D auto insert_constraint_in_cdt_2 = [&](const auto& va, const auto& vb) { if(this->debug().input_faces()) { std::cerr << "cdt_2.insert_constraint (" - << IO::oformat(va->info().vertex_handle_3d, with_point_and_info) - << " , " - << IO::oformat(vb->info().vertex_handle_3d, with_point_and_info) + << display_vert(vertex_3d(va)) << " , " << display_vert(vertex_3d(vb)) << ")\n"; } auto cstr_id = cdt_2.insert_constraint(va, vb); @@ -2209,10 +3849,12 @@ class Conforming_constrained_Delaunay_triangulation_3_impl : public Conforming_D }; auto insert_vertex_in_cdt_2 = [&](const auto& v) { auto vh_2d = cdt_2.insert(tr().point(v)); - vh_2d->info().vertex_handle_3d = v; + vertex_3d(vh_2d) = v; return vh_2d; }; + vertex_3d(cdt_2.infinite_vertex()) = this->infinite_vertex(); + for(const auto& handles : vec_of_handles) { const auto first_2d = insert_vertex_in_cdt_2(handles.front()); @@ -2221,7 +3863,7 @@ class Conforming_constrained_Delaunay_triangulation_3_impl : public Conforming_D it != end; /* incremented in the loop */) { const auto va = *it; - CGAL_assertion(previous_2d->info().vertex_handle_3d == va); + CGAL_assertion(vertex_3d(previous_2d) == va); ++it; const auto vb = *it; const auto c_id = this->constraint_from_extremities(va, vb); @@ -2286,25 +3928,28 @@ class Conforming_constrained_Delaunay_triangulation_3_impl : public Conforming_D for(auto fh: cdt_2.all_face_handles()) { - fh->info().is_outside_the_face = -1; + fh->info().is_outside_the_face = Face_is_outside_the_face::UNKNOWN; } struct Face_handle_and_outside { CDT_2_face_handle fh; - bool outside; + Face_is_outside_the_face outside; }; const auto d = cdt_2.dimension(); std::stack stack; - stack.push({cdt_2.infinite_face(), true}); + stack.push({cdt_2.infinite_face(), OUTSIDE}); while(!stack.empty()) { const auto [fh, outside] = stack.top(); stack.pop(); - if(fh->info().is_outside_the_face == -1) { + if(fh->info().is_outside_the_face == Face_is_outside_the_face::UNKNOWN) { fh->info().is_outside_the_face = outside; - CGAL_assertion(!cdt_2.is_infinite(fh) || outside == true); + CGAL_assertion(!cdt_2.is_infinite(fh) || outside == OUTSIDE); for(int i = 0; i <= d; ++i) { const auto neighbor = fh->neighbor(i); - const auto new_outside = is_constrained_with_odd_nb_of_constraints(cdt_2, fh, i) ? !outside : outside; - if(neighbor->info().is_outside_the_face == -1) { + const auto new_outside = + is_constrained_with_odd_nb_of_constraints(cdt_2, fh, i) + ? (outside == OUTSIDE ? INSIDE : OUTSIDE) + : outside; + if(neighbor->info().is_outside_the_face == Face_is_outside_the_face::UNKNOWN) { stack.push({neighbor, new_outside}); } } @@ -2314,7 +3959,7 @@ class Conforming_constrained_Delaunay_triangulation_3_impl : public Conforming_D if(this->debug().input_faces()) { int counter = 0; for(const auto fh: cdt_2.finite_face_handles()) { - if(!fh->info().is_outside_the_face) ++counter; + if(fh->info().is_outside_the_face == INSIDE) ++counter; } std::cerr << counter << " triangles(s) in the face\n"; } @@ -2341,8 +3986,8 @@ class Conforming_constrained_Delaunay_triangulation_3_impl : public Conforming_D const auto [ch2, index2] = cdt_2.mirror_edge({ch, index}); const auto vd = ch2->vertex(index2); CGAL_assertion(!cdt_2.is_edge(vb, vd)); - const auto vb_3d = vb->info().vertex_handle_3d; - const auto vd_3d = vd->info().vertex_handle_3d; + const auto vb_3d = vertex_3d(vb); + const auto vd_3d = vertex_3d(vd); if(this->is_edge(vb_3d, vd_3d)) { // let's insert the diagonal [bd] in the CDT_2 cdt_2.insert_constraint(vb, vd); @@ -2366,30 +4011,32 @@ class Conforming_constrained_Delaunay_triangulation_3_impl : public Conforming_D search_for_missing_subfaces(CDT_3_signed_index polygon_constraint_id, Search_for_missing_subfaces_option option = Search_for_missing_subfaces_option::DEFAULT) { bool something_has_changed = false; - const CDT_2& cdt_2 = face_cdt_2(polygon_constraint_id); + const CDT_2& cdt_2 = this->face_cdt_2(polygon_constraint_id); - face_constraint_misses_subfaces_reset(static_cast(polygon_constraint_id)); + this->face_constraint_misses_subfaces_reset(static_cast(polygon_constraint_id)); for(const auto fh: cdt_2.all_face_handles()) { - if(fh->info().is_outside_the_face) continue; - const auto v0 = fh->vertex(0)->info().vertex_handle_3d; - const auto v1 = fh->vertex(1)->info().vertex_handle_3d; - const auto v2 = fh->vertex(2)->info().vertex_handle_3d; - Cell_handle c; - int i, j, k; - if(!tr().is_facet(v0, v1, v2, c, i, j, k)) { + if(fh->info().is_outside_the_face == OUTSIDE) { + fh->info().missing_subface = false; + continue; + } + const auto v0 = vertex_3d(fh->vertex(0)); + const auto v1 = vertex_3d(fh->vertex(1)); + const auto v2 = vertex_3d(fh->vertex(2)); + auto is_facet = this->is_2d_face_also_a_3d_facet(fh); + if(!is_facet) { fh->info().missing_subface = true; - face_constraint_misses_subfaces_set(static_cast(polygon_constraint_id)); + this->face_constraint_misses_subfaces_set(static_cast(polygon_constraint_id)); something_has_changed = true; -#if CGAL_CDT_3_DEBUG_MISSING_TRIANGLES - std::cerr << cdt_3_format("Missing triangle in polygon #{}:\n", polygon_constraint_id); - write_triangle(std::cerr, v0, v1, v2); -#endif // CGAL_CDT_3_DEBUG_MISSING_TRIANGLES + if(this->debug().missing_triangles()) { + std::cerr << cdt_3_format("Missing triangle in polygon #{}:\n", polygon_constraint_id); + write_triangle(std::cerr, v0, v1, v2); + } } else { + const auto [facet, orient] = *is_facet; fh->info().missing_subface = false; - const int facet_index = 6 - i - j - k; if(option == Search_for_missing_subfaces_option::SEARCH_FOR_UNCONSTRAINED_FACETS && - !is_facet_constrained({c, facet_index})) + !is_facet_constrained(facet)) { something_has_changed = true; if(this->debug().restore_faces()) { @@ -2398,7 +4045,7 @@ class Conforming_constrained_Delaunay_triangulation_3_impl : public Conforming_D << this->display_vert(v2) << '\n'; } } - set_facet_constrained({c, facet_index}, polygon_constraint_id, fh); + set_facet_constrained(facet, polygon_constraint_id, fh, orient); } } if(option == Search_for_missing_subfaces_option::SEARCH_FOR_UNCONSTRAINED_FACETS && something_has_changed) { @@ -2408,10 +4055,8 @@ class Conforming_constrained_Delaunay_triangulation_3_impl : public Conforming_D std::cerr << "Some missing subfaces were found in polygon #" << polygon_constraint_id << ".\n"; for(const auto fh: cdt_2.all_face_handles()) { - if(fh->info().is_outside_the_face || !fh->info().missing_subface) continue; - const auto v0 = fh->vertex(0)->info().vertex_handle_3d; - const auto v1 = fh->vertex(1)->info().vertex_handle_3d; - const auto v2 = fh->vertex(2)->info().vertex_handle_3d; + if(fh->info().is_outside_the_face == OUTSIDE || !fh->info().missing_subface) continue; + const auto [v0, v1, v2] = this->apply_functor(vertex_3d, cdt_2.vertices(fh)); std::cerr << " - missing triangle with vertices " << this->display_vert(v0) << ", " << this->display_vert(v1) << ", " << this->display_vert(v2) << '\n'; } @@ -2430,7 +4075,9 @@ class Conforming_constrained_Delaunay_triangulation_3_impl : public Conforming_D const auto i = unsigned(edge.second); return false == face->info().is_edge_also_in_3d_triangulation.test(i); }, - +[](CDT_2_face_handle face_handle) { return false == face_handle->info().is_outside_the_face; }); + +[](CDT_2_face_handle face_handle) { + return INSIDE == face_handle->info().is_outside_the_face; + }); boost::breadth_first_search(dual, fh, boost::color_map(typename CDT_2_types::Color_map_is_in_region()) .visitor(boost::make_bfs_visitor(boost::write_property( @@ -2452,8 +4099,8 @@ class Conforming_constrained_Delaunay_triangulation_3_impl : public Conforming_D for(int index = 0; index < 3; ++index) { if(fh_region_set.count(fh->neighbor(index)) > 0) continue; // otherwise we have a border edge: fh->neighbor(i) is not in the region - const auto va = fh->vertex(CDT_2::ccw(index))->info().vertex_handle_3d; - const auto vb = fh->vertex(CDT_2:: cw(index))->info().vertex_handle_3d; + const auto va = vertex_3d(fh->vertex(CDT_2::ccw(index))); + const auto vb = vertex_3d(fh->vertex(CDT_2:: cw(index))); Cell_handle c; int i, j; CGAL_assume_code(bool b =) @@ -2491,9 +4138,9 @@ class Conforming_constrained_Delaunay_triangulation_3_impl : public Conforming_D const auto pc = this->point(vc); const auto pd = this->point(vd); for(const auto fh_2d : fh_region) { - const auto v0 = fh_2d->vertex(0)->info().vertex_handle_3d; - const auto v1 = fh_2d->vertex(1)->info().vertex_handle_3d; - const auto v2 = fh_2d->vertex(2)->info().vertex_handle_3d; + const auto v0 = vertex_3d(fh_2d->vertex(0)); + const auto v1 = vertex_3d(fh_2d->vertex(1)); + const auto v2 = vertex_3d(fh_2d->vertex(2)); if(vc == v0 || vc == v1 || vc == v2 || vd == v0 || vd == v1 || vd == v2) { continue; } @@ -2600,14 +4247,12 @@ class Conforming_constrained_Delaunay_triangulation_3_impl : public Conforming_D if(this->debug().regions()) { std::cerr << "Edge interior intersects region in face with vertices:\n " - << IO::oformat(fh->vertex(0)->info().vertex_handle_3d, with_point_and_info) << "\n " - << IO::oformat(fh->vertex(1)->info().vertex_handle_3d, with_point_and_info) << "\n " - << IO::oformat(fh->vertex(2)->info().vertex_handle_3d, with_point_and_info) << "\n"; + << display_vert(vertex_3d(fh->vertex(0))) << "\n " + << display_vert(vertex_3d(fh->vertex(1))) << "\n " + << display_vert(vertex_3d(fh->vertex(2))) << "\n"; } - return {1, - {fh->vertex(0)->info().vertex_handle_3d, fh->vertex(1)->info().vertex_handle_3d, - fh->vertex(2)->info().vertex_handle_3d}}; + return {1, {vertex_3d(fh->vertex(0)), vertex_3d(fh->vertex(1)), vertex_3d(fh->vertex(2))}}; } while(false == line_face_circulator->has_vertex(vq_2d) && ++line_face_circulator != start); } // End of if(region_vertices.count(vc) > 0 && region_vertices.count(vd) > 0 && // border_edges_set.count(CGAL::make_sorted_pair(vc, vd)) == 0) @@ -2896,7 +4541,7 @@ class Conforming_constrained_Delaunay_triangulation_3_impl : public Conforming_D }); CGAL_assume(vertex_above != Vertex_handle{}); if(this->debug().regions()) { - std::cerr << "The vertex above the region is " << IO::oformat(vertex_above, with_point_and_info) << "\n"; + std::cerr << "The vertex above the region is " << display_vert(vertex_above) << "\n"; } CGAL::unordered_flat_set> remaining_facets_of_border(facets_of_border.begin(), @@ -2913,9 +4558,9 @@ class Conforming_constrained_Delaunay_triangulation_3_impl : public Conforming_D auto [c, i] = facet; if(this->debug().regions()) { std::cerr << " stack facet " << (above_below == 1 ? "above" : "below") << ": " - << IO::oformat(c->vertex(tr().vertex_triple_index(i, 0)), with_point_and_info) << " " - << IO::oformat(c->vertex(tr().vertex_triple_index(i, 1)), with_point_and_info) << " " - << IO::oformat(c->vertex(tr().vertex_triple_index(i, 2)), with_point_and_info) << "\n"; + << display_vert(c->vertex(tr().vertex_triple_index(i, 0))) << " " + << display_vert(c->vertex(tr().vertex_triple_index(i, 1))) << " " + << display_vert(c->vertex(tr().vertex_triple_index(i, 2))) << "\n"; } if(above_below == 1) { @@ -2972,14 +4617,11 @@ class Conforming_constrained_Delaunay_triangulation_3_impl : public Conforming_D if(remaining_facets_of_border.erase(neighbor_facet) > 0) { if(this->debug().regions()) { std::cerr << " -> stack push new facet " << (next_facet_is_above_below == 1 ? "above" : "below") << ": " - << IO::oformat(neighbor_facet.first->vertex(tr().vertex_triple_index(neighbor_facet.second, 0)), - with_point_and_info) + << display_vert(neighbor_facet.first->vertex(tr().vertex_triple_index(neighbor_facet.second, 0))) << " " - << IO::oformat(neighbor_facet.first->vertex(tr().vertex_triple_index(neighbor_facet.second, 1)), - with_point_and_info) + << display_vert(neighbor_facet.first->vertex(tr().vertex_triple_index(neighbor_facet.second, 1))) << " " - << IO::oformat(neighbor_facet.first->vertex(tr().vertex_triple_index(neighbor_facet.second, 2)), - with_point_and_info) + << display_vert(neighbor_facet.first->vertex(tr().vertex_triple_index(neighbor_facet.second, 2))) << "\n"; } stack.push({neighbor_facet, next_facet_is_above_below}); @@ -3025,7 +4667,7 @@ class Conforming_constrained_Delaunay_triangulation_3_impl : public Conforming_D if(is_marked(v, Vertex_marker::CAVITY)) { clear_mark(v, Vertex_marker::CAVITY); if(this->debug().regions()) { - std::cerr << " " << IO::oformat(v, with_point_and_info) << "\n"; + std::cerr << " " << display_vert(v) << "\n"; } } } @@ -3054,23 +4696,19 @@ class Conforming_constrained_Delaunay_triangulation_3_impl : public Conforming_D })); } - using Conforming_Dt::with_offset; - using Conforming_Dt::with_point; - using Conforming_Dt::with_point_and_info; - // ------------------------- // restore_subface_region // ------------------------- template - void restore_subface_region(CDT_3_signed_index face_index, int region_index, + bool restore_subface_region(CDT_3_signed_index face_index, int region_index, CDT_2& non_const_cdt_2, Fh_region& non_const_fh_region) { if(this->debug().regions()) { auto guard_color = CGAL::IO::make_color_guards(std::cerr); std::cerr << "restore_subface_region face index: " << face_index << ", region #" << region_index << "\n"; } - auto guard_indenting = CGAL::IO::make_indenting_guards("| ", std::cerr, std::cout); + auto guard_indenting = CGAL::IO::make_indenting_guards("| ", std::cerr); const auto& cdt_2 = non_const_cdt_2; const auto& fh_region = non_const_fh_region; @@ -3079,7 +4717,7 @@ class Conforming_constrained_Delaunay_triangulation_3_impl : public Conforming_D std::set vertices; for(const auto fh_2d: fh_region) { for(int i = 0; i < 3; ++i) { - vertices.insert(fh_2d->vertex(i)->info().vertex_handle_3d); + vertices.insert(vertex_3d(fh_2d->vertex(i))); } } return vertices; @@ -3095,7 +4733,7 @@ class Conforming_constrained_Delaunay_triangulation_3_impl : public Conforming_D if constexpr (cdt_3_can_use_cxx20_format()) if(this->debug().regions()) { std::cerr << "region_border_vertices.size() = " << region_border_vertices.size() << "\n"; for(auto v : region_border_vertices) { - std::cerr << cdt_3_format(" {}\n", IO::oformat(v, with_point)); + std::cerr << cdt_3_format(" {}\n", with_point(v)); } std::ofstream out(cdt_3_format("dump_border_edges_region_{}_{}.polylines.txt", face_index, region_index)); out.precision(17); @@ -3113,7 +4751,7 @@ class Conforming_constrained_Delaunay_triangulation_3_impl : public Conforming_D std::set diagonal; for(auto fh : fh_region) { for(int i = 0; i < 3; ++i) { - auto [it, new_vertex] = vertices.insert(fh->vertex(i)->info().vertex_handle_3d); + auto [it, new_vertex] = vertices.insert(vertex_3d(fh->vertex(i))); if(!new_vertex) { diagonal.insert(*it); } @@ -3128,10 +4766,10 @@ class Conforming_constrained_Delaunay_triangulation_3_impl : public Conforming_D const auto diagonal_index = fh_region[0]->index(fh_region[1]); CGAL_assertion(diagonal_index >= 0 && diagonal_index < 3); - const auto v0 = fh_region[0]->vertex(diagonal_index)->info().vertex_handle_3d; - const auto v1 = fh_region[0]->vertex(cdt_2.ccw(diagonal_index))->info().vertex_handle_3d; - const auto v2 = fh_region[0]->vertex(cdt_2.cw(diagonal_index))->info().vertex_handle_3d; - const auto v3 = fh_region[1]->vertex(fh_region[1]->index(fh_region[0]))->info().vertex_handle_3d; + const auto v0 = vertex_3d(fh_region[0]->vertex(diagonal_index)); + const auto v1 = vertex_3d(fh_region[0]->vertex(cdt_2.ccw(diagonal_index))); + const auto v2 = vertex_3d(fh_region[0]->vertex(cdt_2.cw(diagonal_index))); + const auto v3 = vertex_3d(fh_region[1]->vertex(fh_region[1]->index(fh_region[0]))) ; if(tr().is_facet(v0, v1, v3) && tr().is_facet(v0, v3, v2)) { if(cdt_2.orientation(v0->point(), v1->point(), v3->point()) == CGAL::POSITIVE && @@ -3146,14 +4784,10 @@ class Conforming_constrained_Delaunay_triangulation_3_impl : public Conforming_D const auto mirror_edge = cdt_2.mirror_edge({fh, i}); fh->set_constraint(i, mirror_edge.first->is_constrained(mirror_edge.second)); } - int i, j, k; - Cell_handle c; - [[maybe_unused]] bool fh_is_3d_facet = tr().is_facet(fh->vertex(0)->info().vertex_handle_3d, - fh->vertex(1)->info().vertex_handle_3d, - fh->vertex(2)->info().vertex_handle_3d, - c, i, j, k); - CGAL_assertion(fh_is_3d_facet); - set_facet_constrained({c, 6-i-j-k}, face_index, fh); + const auto fh_is_3d_facet = is_2d_face_also_a_3d_facet(fh); + CGAL_assertion(fh_is_3d_facet.has_value()); + const auto [facet, orient] = *fh_is_3d_facet; + set_facet_constrained(facet, face_index, fh, orient); fh->info().missing_subface = false; } return true; @@ -3170,13 +4804,13 @@ class Conforming_constrained_Delaunay_triangulation_3_impl : public Conforming_D if constexpr (cdt_3_can_use_cxx20_format()) if(this->debug().regions()) { std::cerr << cdt_3_format ("NOTE: diagonal: {:.6} {:.6} {} in tr\n", - IO::oformat(*diagonal.begin(), with_point), - IO::oformat(*std::next(diagonal.begin()), with_point), + with_point(*diagonal.begin()), + with_point(*std::next(diagonal.begin())), this->is_edge(*diagonal.begin(), *std::next(diagonal.begin())) ? "IS" : "is NOT"); std::cerr << cdt_3_format( "NOTE: the other diagonal: {:.6} {:.6} {} in tr\n", - IO::oformat(*other_diagonal.begin(), with_point), - IO::oformat(*std::next(other_diagonal.begin()), with_point), + with_point(*other_diagonal.begin()), + with_point(*std::next(other_diagonal.begin())), this->is_edge(*other_diagonal.begin(), *std::next(other_diagonal.begin())) ? "IS" : "is NOT"); if(cdt_2.geom_traits().side_of_oriented_circle_2_object()( (*region_border_vertices.begin())->point(), (*std::next(region_border_vertices.begin()))->point(), @@ -3212,7 +4846,7 @@ class Conforming_constrained_Delaunay_triangulation_3_impl : public Conforming_D }; if(!found_edge_opt) { if(try_flip_region_size_4()) { - return; + return true; } // { // Conforming_constrained_Delaunay_triangulation_3_impl new_tr; @@ -3305,13 +4939,13 @@ class Conforming_constrained_Delaunay_triangulation_3_impl : public Conforming_D std::cerr << " "; auto vertices = tr().vertices(f); for(int i = 0; i < 3; ++i) { - std::cerr << IO::oformat(vertices[i], with_point_and_info) << " "; + std::cerr << display_vert(vertices[i]) << " "; } std::cerr << "\n"; } std::cerr << " Vertices:\n"; for(const auto& v : std::set(original_vertices_of_lower_cavity.begin(), original_vertices_of_lower_cavity.end())) { - std::cerr << " " << IO::oformat(v, with_point_and_info) << "\n"; + std::cerr << " " << display_vert(v) << "\n"; } std::cerr << "Upper cavity:\n"; std::cerr << " Facets:\n"; @@ -3319,21 +4953,21 @@ class Conforming_constrained_Delaunay_triangulation_3_impl : public Conforming_D std::cerr << " "; auto vertices = tr().vertices(f); for(int i = 0; i < 3; ++i) { - std::cerr << IO::oformat(vertices[i], with_point_and_info) << " "; + std::cerr << display_vert(vertices[i]) << " "; } std::cerr << "\n"; } std::cerr << " Vertices:\n"; for(const auto& v : std::set(original_vertices_of_upper_cavity.begin(), original_vertices_of_upper_cavity.end())) { - std::cerr << " " << IO::oformat(v, with_point_and_info) << "\n"; + std::cerr << " " << display_vert(v) << "\n"; } } auto register_internal_constrained_facet = [this](Facet f) { this->register_facet_to_be_constrained(f); }; - std::optional indent_guards; + std::optional indent_guards; if(this->debug().copy_triangulation_into_hole() || this->debug().regions()) { std::cerr << "# upper cavity\n"; - indent_guards.emplace(IO::make_indenting_guards(" ", std::cerr, std::cout, std::clog)); + indent_guards.emplace(IO::make_indenting_guards(" ", std::cerr)); } [[maybe_unused]] const auto [upper_cavity_triangulation, vertices_of_upper_cavity, map_upper_cavity_vertices_to_ambient_vertices, facets_of_upper_cavity, @@ -3346,7 +4980,7 @@ class Conforming_constrained_Delaunay_triangulation_3_impl : public Conforming_D if(this->debug().copy_triangulation_into_hole() || this->debug().regions()) { indent_guards.reset(); std::cerr << "# lower cavity\n"; - indent_guards.emplace(IO::make_indenting_guards(" ", std::cerr, std::cout, std::clog)); + indent_guards.emplace(IO::make_indenting_guards(" ", std::cerr)); } [[maybe_unused]] const auto [lower_cavity_triangulation, vertices_of_lower_cavity, map_lower_cavity_vertices_to_ambient_vertices, facets_of_lower_cavity, @@ -3362,9 +4996,9 @@ class Conforming_constrained_Delaunay_triangulation_3_impl : public Conforming_D // the following transform_reduce is like `std::any_of` but without the fast-exit if(std::transform_reduce(fh_region.begin(), fh_region.end(), false, std::logical_or{}, [&](auto fh) { - const auto v0 = fh->vertex(0)->info().vertex_handle_3d; - const auto v1 = fh->vertex(1)->info().vertex_handle_3d; - const auto v2 = fh->vertex(2)->info().vertex_handle_3d; + const auto v0 = vertex_3d(fh->vertex(0)); + const auto v1 = vertex_3d(fh->vertex(1)); + const auto v2 = vertex_3d(fh->vertex(2)); auto is_fh_facet_of = [&](const auto& tr) -> std::optional { return this->vertex_triple_is_facet_of_other_triangulation(*this, v0, v1, v2, tr); }; @@ -3376,8 +5010,7 @@ class Conforming_constrained_Delaunay_triangulation_3_impl : public Conforming_D auto display_face = [&]() { std::stringstream s; s.precision(std::cerr.precision()); - s << "(" << IO::oformat(v0, this->with_offset) << ", " << IO::oformat(v1, this->with_offset) - << ", " << IO::oformat(v2, this->with_offset) << ") = ( " + s << "(" << with_offset(v0) << ", " << with_offset(v1) << ", " << with_offset(v2) << ") = ( " << tr().point(v0) << " " << tr().point(v1) << " " << tr().point(v2) << " )"; return s.str(); @@ -3428,12 +5061,9 @@ class Conforming_constrained_Delaunay_triangulation_3_impl : public Conforming_D throw Next_region{"missing facet in polygon", fh_region[0]}; } - { - std::vector all_cells_in_conflict(cells_of_upper_cavity.size() + cells_of_lower_cavity.size()); - auto it = std::copy(cells_of_upper_cavity.begin(), cells_of_upper_cavity.end(), all_cells_in_conflict.begin()); - std::copy(cells_of_lower_cavity.begin(), cells_of_lower_cavity.end(), it); - insert_in_conflict_visitor.process_cells_in_conflict(all_cells_in_conflict.begin(), all_cells_in_conflict.end()); - } + std::set cells_to_remove{cells_of_lower_cavity.begin(), cells_of_lower_cavity.end()}; + cells_to_remove.insert(cells_of_upper_cavity.begin(), cells_of_upper_cavity.end()); + insert_in_conflict_visitor.process_cells_in_conflict(cells_to_remove.begin(), cells_to_remove.end()); if(this->debug().copy_triangulation_into_hole()) { std::cerr << "# glu the upper triangulation of the cavity\n"; @@ -3441,18 +5071,20 @@ class Conforming_constrained_Delaunay_triangulation_3_impl : public Conforming_D cells_of_upper_cavity.size() > original_intersecting_cells.size()) { std::cerr << cdt_3_format("!! Cavity has grown and has now " - "{} vertices in upper cavity and {} in lower, " - "{} facets in upper cavity and {} in lower\n", - vertices_of_upper_cavity.size(), - vertices_of_lower_cavity.size(), - facets_of_upper_cavity.size(), - facets_of_lower_cavity.size()); + "{} vertices in upper cavity and {} in lower, " + "{} facets in upper cavity and {} in lower\n", + vertices_of_upper_cavity.size(), + vertices_of_lower_cavity.size(), + facets_of_upper_cavity.size(), + facets_of_lower_cavity.size()); } } typename T_3::Vertex_triple_Facet_map outer_map; auto add_to_outer_map = [&](typename T_3::Vertex_triple vt, Facet f, - [[maybe_unused]] std::string_view extra = {}) { + [[maybe_unused]] std::string_view extra = {}) + { + if(cells_to_remove.count(f.first) != 0) return false; // the cell of the facet cannot be in the cavity outer_map[vt] = f; CGAL_USE(this); #if CGAL_CDT_3_CAN_USE_CXX20_FORMAT @@ -3461,27 +5093,40 @@ class Conforming_constrained_Delaunay_triangulation_3_impl : public Conforming_D CGAL_assertion(vt[0] != vt[2]); CGAL_assertion(vt[1] != vt[2]); std::cerr << cdt_3_format("outer map: Adding {}triple ({:.6}, {:.6}, {:.6})\n", extra, - IO::oformat(vt[0], with_point), - IO::oformat(vt[1], with_point), - IO::oformat(vt[2], with_point)); - std::stringstream filename; - filename << "dump_upper_outer_map_region_" << face_index << "_" << region_index << ".off"; - std::ofstream out(filename.str()); - out.precision(17); - write_facets(out, *this, std::ranges::views::values(outer_map)); - out.close(); + with_point(vt[0]), + with_point(vt[1]), + with_point(vt[2])); } #endif // CGAL_CDT_3_CAN_USE_CXX20_FORMAT + return true; }; auto fill_outer_map_of_cavity = [&](const auto&, const auto& facets) { + std::vector facets_to_add_to_pseudo_cells; for(auto f : facets) { - typename T_3::Vertex_triple vt = this->make_vertex_triple(f); - this->make_canonical_oriented_triple(vt); - add_to_outer_map(vt, f); + auto vt = T_3::make_canonical_oriented_triple(f); + if(!add_to_outer_map(vt, f)) { + facets_to_add_to_pseudo_cells.push_back(f); + } } + return facets_to_add_to_pseudo_cells; }; - fill_outer_map_of_cavity(upper_cavity_triangulation, facets_of_upper_cavity); + auto extra_pseudo_facets = fill_outer_map_of_cavity(upper_cavity_triangulation, facets_of_upper_cavity); +#if CGAL_CDT_3_CAN_USE_CXX20_FORMAT + if(this->debug().copy_triangulation_into_hole()) { + std::cerr << "outer_map:\n"; + for(auto [vt, _] : outer_map) { + std::cerr << cdt_3_format(" {:.6}, {:.6}, {:.6})\n", + with_point(vt[0]), with_point(vt[1]), with_point(vt[2])); + } + std::stringstream filename; + filename << "dump_upper_outer_map_region_" << face_index << "_" << region_index << ".off"; + std::ofstream out(filename.str()); + out.precision(17); + write_facets(out, *this, std::ranges::views::values(outer_map)); + out.close(); + } +#endif // CGAL_CDT_3_CAN_USE_CXX20_FORMAT auto add_pseudo_cells_to_outer_map = [&](const auto& tr, const auto& map_cavity_vertices_to_ambient_vertices, bool is_upper_cavity) { // @TODO: comment this piece of code @@ -3496,19 +5141,17 @@ class Conforming_constrained_Delaunay_triangulation_3_impl : public Conforming_D continue; // we might be in a sliver in the plane of the polygon const auto [fh_2d, reverse_orientation] = *is_facet; if(this->debug().regions()) facets_of_polygon.push_back(f); - const auto vt_aux = this->make_vertex_triple(f); - typename T_3::Vertex_triple vt{map_cavity_vertices_to_ambient_vertices[vt_aux[0]], - map_cavity_vertices_to_ambient_vertices[vt_aux[1]], - map_cavity_vertices_to_ambient_vertices[vt_aux[2]]}; - this->make_canonical_oriented_triple(vt); + auto vt = T_3::make_canonical_oriented_mapped_triple(map_cavity_vertices_to_ambient_vertices, f); if(reverse_orientation == is_upper_cavity) { std::swap(vt[1], vt[2]); } - auto new_cell = this->tds().create_cell(); + auto new_cell = this->tds().create_cell(vt[0], vt[1], vt[2], this->infinite_vertex()); pseudo_cells.emplace_back(new_cell, fh_2d); - new_cell->set_vertices(vt[0], vt[1], vt[2], this->infinite_vertex()); - CGAL_assertion(static_cast(facet_is_facet_of_cdt_2(*this, {new_cell, 3}, cdt_2))); - add_to_outer_map(vt, {new_cell, 3}, "pseudo "); + Facet new_facet{new_cell, 3}; + CGAL_assertion_code(const auto new_facet_is_2d = facet_is_facet_of_cdt_2(*this, new_facet, cdt_2)); + CGAL_assertion(new_facet_is_2d.has_value() && + new_facet_is_2d->fh == fh_2d && new_facet_is_2d->reversed_orientation != is_upper_cavity); + add_to_outer_map(vt, new_facet, "pseudo "); } if(this->debug().regions()) { std::ofstream out(cdt_3_format("dump_{}_pseudo_cells_region_{}_{}.off", is_upper_cavity ? "upper" : "lower", @@ -3521,6 +5164,14 @@ class Conforming_constrained_Delaunay_triangulation_3_impl : public Conforming_D const auto pseudo_cells = add_pseudo_cells_to_outer_map(upper_cavity_triangulation, map_upper_cavity_vertices_to_ambient_vertices, true); + for(auto& facet: extra_pseudo_facets) { + auto verts = tr().vertices(facet); + auto new_cell = this->tds().create_cell(verts[0], verts[1], verts[2], this->infinite_vertex()); + facet = Facet{new_cell, 3}; + T_3::make_canonical_oriented_triple(verts); + add_to_outer_map(verts, facet, "extra"); + } + { const auto upper_inner_map = tr().create_triangulation_inner_map( upper_cavity_triangulation, map_upper_cavity_vertices_to_ambient_vertices, false); @@ -3529,15 +5180,13 @@ class Conforming_constrained_Delaunay_triangulation_3_impl : public Conforming_D std::cerr << "upper_inner_map:\n"; for(auto [vt, _] : upper_inner_map) { std::cerr << cdt_3_format(" {:.6}, {:.6}, {:.6})\n", - IO::oformat(vt[0], with_point), - IO::oformat(vt[1], with_point), - IO::oformat(vt[2], with_point)); + with_point(vt[0]), with_point(vt[1]), with_point(vt[2])); } } - this->copy_triangulation_into_hole(map_upper_cavity_vertices_to_ambient_vertices, - std::move(outer_map), - upper_inner_map, - this->new_cells_output_iterator()); + tr().copy_triangulation_into_hole(map_upper_cavity_vertices_to_ambient_vertices, + std::move(outer_map), + upper_inner_map, + this->new_cells_output_iterator()); } if(this->debug().copy_triangulation_into_hole()) { std::cerr << "# glu the lower triangulation of the cavity\n"; @@ -3547,14 +5196,20 @@ class Conforming_constrained_Delaunay_triangulation_3_impl : public Conforming_D std::vector> new_constrained_facets; new_constrained_facets.reserve(pseudo_cells.size()); for(const auto& [c, fh_2d] : pseudo_cells) { - const Facet f = this->mirror_facet({c, 3}); - new_constrained_facets.emplace_back(f, fh_2d); - CGAL_assertion(static_cast(facet_is_facet_of_cdt_2(*this, f, cdt_2))); - auto vt = this->make_vertex_triple(f); - this->make_canonical_oriented_triple(vt); - add_to_outer_map(vt, f, "pseudo "); + const Facet f{c, 3}; + const Facet opposite_f = tr().mirror_facet(f); + new_constrained_facets.emplace_back(opposite_f, fh_2d); + CGAL_assertion(static_cast(facet_is_facet_of_cdt_2(*this, opposite_f, cdt_2))); + auto vt = T_3::make_canonical_oriented_triple(opposite_f); + add_to_outer_map(vt, opposite_f, "pseudo "); this->tds().delete_cell(c); } + for(const auto& facet: extra_pseudo_facets) { + auto opposite_f = tr().mirror_facet(facet); + auto vt = T_3::make_canonical_oriented_triple(opposite_f); + add_to_outer_map(vt, opposite_f, "pseudo "); + this->tds().delete_cell(facet.first); + } fill_outer_map_of_cavity(lower_cavity_triangulation, facets_of_lower_cavity); { const auto lower_inner_map = tr().create_triangulation_inner_map( @@ -3564,9 +5219,12 @@ class Conforming_constrained_Delaunay_triangulation_3_impl : public Conforming_D std::cerr << "outer_map:\n"; for(auto [vt, _] : outer_map) { std::cerr << cdt_3_format(" {:.6}, {:.6}, {:.6})\n", - IO::oformat(vt[0], with_point), - IO::oformat(vt[1], with_point), - IO::oformat(vt[2], with_point)); + with_point(vt[0]), with_point(vt[1]), with_point(vt[2])); + } + std::cerr << "lower_inner_map:\n"; + for(auto [vt, _] : lower_inner_map) { + std::cerr << cdt_3_format(" {:.6}, {:.6}, {:.6})\n", + with_point(vt[0]), with_point(vt[1]), with_point(vt[2])); } std::stringstream filename; filename << "dump_lower_outer_map_region_" << face_index << "_" << region_index << ".off"; @@ -3576,11 +5234,9 @@ class Conforming_constrained_Delaunay_triangulation_3_impl : public Conforming_D out.close(); } #endif // CGAL_CDT_3_CAN_USE_CXX20_FORMAT - this->copy_triangulation_into_hole(map_lower_cavity_vertices_to_ambient_vertices, std::move(outer_map), + tr().copy_triangulation_into_hole(map_lower_cavity_vertices_to_ambient_vertices, std::move(outer_map), lower_inner_map, this->new_cells_output_iterator()); } - std::set cells_to_remove{cells_of_lower_cavity.begin(), cells_of_lower_cavity.end()}; - cells_to_remove.insert(cells_of_upper_cavity.begin(), cells_of_upper_cavity.end()); for(auto c : cells_to_remove) { if(this->debug().copy_triangulation_into_hole()) { std::cerr << "delete cell " << IO::oformat(c) << "\n"; @@ -3590,7 +5246,10 @@ class Conforming_constrained_Delaunay_triangulation_3_impl : public Conforming_D auto restore_markers = [&](Facet outside_facet) { const auto [outside_cell, outside_face_index] = outside_facet; - const auto mirror_facet = this->mirror_facet(outside_facet); + if(cells_to_remove.count(outside_cell) > 0) { + return; + } + const auto mirror_facet = tr().mirror_facet(outside_facet); if(outside_cell->ccdt_3_data().is_facet_constrained(outside_face_index)) { const auto polygon_id = outside_cell->ccdt_3_data().face_constraint_index(outside_face_index); const CDT_2& cdt_2 = face_cdt_2(polygon_id); @@ -3603,11 +5262,19 @@ class Conforming_constrained_Delaunay_triangulation_3_impl : public Conforming_D std::for_each(facets_of_upper_cavity.begin(), facets_of_upper_cavity.end(), restore_markers); for(const auto& [f, f2d] : new_constrained_facets) { - set_facet_constrained(f, face_index, f2d); + set_facet_constrained(T_3::mirror_facet(f), face_index, f2d); f2d->info().missing_subface = false; } - CGAL_assume(!this->debug().validity() || this->is_valid(true)); - }; + bool result = true; + if(this->has_constrained_edges_to_restore()) { + this->restore_constrained_edges(insert_in_conflict_visitor); + result = false; + } + + // CGAL_assertion(has_all_constrained_edges()); + CGAL_assertion(!this->debug().validity() || tr().tds().is_valid(true)); + return result; + } // ------------------------- // end of restore_subface_region @@ -3618,44 +5285,121 @@ class Conforming_constrained_Delaunay_triangulation_3_impl : public Conforming_D bool reversed_orientation = false; }; - static auto vertex_of_cdt_2_functor(const CDT_2& cdt_2) { - return [&, hint = CDT_2_face_handle{}](const auto& p) mutable { + auto vertex_of_cdt_2_functor(const CDT_2& cdt_2) const { + return [&, hint = CDT_2_face_handle{}](const auto vh_3d) mutable { + const auto& p = tr().point(vh_3d); int i; typename CDT_2::Locate_type lt; const auto fh = cdt_2.locate(p, lt, i, hint); - if(lt != CDT_2::VERTEX) { - exception_ostream() << cdt_3_format("vertex_of_cdt_2_functor: point {} lt = {}\n", IO::oformat(p), int(lt)); - } - CGAL_assume(lt == CDT_2::VERTEX); hint = fh; - return fh->vertex(i); + if(lt == CDT_2::VERTEX) { + return fh->vertex(i); + } + else { + // the CDT_2 might have been invalidated by flips (valid TDS_2 but invalid CDT_2) + auto it = std::find_if(cdt_2.finite_vertex_handles().begin(), + cdt_2.finite_vertex_handles().end(), + [&](const auto& vh) { return vertex_3d(vh) == vh_3d; }); + CGAL_assertion(it != cdt_2.finite_vertex_handles().end()); + return *it; + } }; } template - static auto facet_is_facet_of_cdt_2(const Tr& tr, typename Tr::Facet f, const CDT_2& cdt_2) + auto facet_is_facet_of_cdt_2(const Tr& tr, typename Tr::Facet f, const CDT_2& cdt_2) const -> std::optional { - const auto [c, facet_index] = f; - const auto v0 = c->vertex(Tr::vertex_triple_index(facet_index, 0)); - const auto v1 = c->vertex(Tr::vertex_triple_index(facet_index, 1)); - const auto v2 = c->vertex(Tr::vertex_triple_index(facet_index, 2)); - + const auto [v0, v1, v2] = tr.vertices(f); auto v = vertex_of_cdt_2_functor(cdt_2); - const auto cdt_2_v0 = v(tr.point(v0)); - const auto cdt_2_v1 = v(tr.point(v1)); - const auto cdt_2_v2 = v(tr.point(v2)); + try { + const auto cdt_2_v0 = v(v0); + const auto cdt_2_v1 = v(v1); + const auto cdt_2_v2 = v(v2); - CDT_2_face_handle fh; - const bool is_face = cdt_2.is_face(cdt_2_v0, cdt_2_v1, cdt_2_v2, fh); - if(is_face && fh->info().is_in_region != 0) { - const int index_v0 = fh->index(cdt_2_v0); - const bool reverse_orientation = (cdt_2_v2 == fh->vertex(T_3::ccw(index_v0))); - return Oriented_face_of_cdt_2{fh, reverse_orientation}; + CDT_2_face_handle fh; + const bool is_face = cdt_2.is_face(cdt_2_v0, cdt_2_v1, cdt_2_v2, fh); + if(is_face && fh->info().is_outside_the_face != OUTSIDE) { + const int index_v0 = fh->index(cdt_2_v0); + const bool reverse_orientation = (cdt_2_v2 == fh->vertex(T_3::ccw(index_v0))); + return Oriented_face_of_cdt_2{fh, reverse_orientation}; + } + } catch(CGAL::Failure_exception&) { } - else + return std::nullopt; + } + + std::optional> + is_2d_face_also_a_3d_facet(CDT_2_face_handle fh_2d) const + { + const auto v0 = vertex_3d(fh_2d->vertex(0)); + const auto v1 = vertex_3d(fh_2d->vertex(1)); + const auto v2 = vertex_3d(fh_2d->vertex(2)); + typename T_3::Cell_handle c; + std::array indices; + const bool is_facet = tr().is_facet(v0, v1, v2, c, indices[0], indices[1], indices[2]); + if(is_facet) { + const int facet_index = 6 - indices[0] - indices[1] - indices[2]; + auto it = std::min_element(indices.begin(), indices.end()); + std::rotate(indices.begin(), it, indices.end()); + const std::array vertex_triple_index = { tr().vertex_triple_index(facet_index, 0), + tr().vertex_triple_index(facet_index, 1), + tr().vertex_triple_index(facet_index, 2) }; + CGAL_assertion(indices[0] == vertex_triple_index[0]); + CGAL_assertion((indices[1] == vertex_triple_index[1] && indices[2] == vertex_triple_index[2]) || + (indices[1] == vertex_triple_index[2] && indices[2] == vertex_triple_index[1])); + Orientation orient = indices[1] == vertex_triple_index[1] ? CGAL::EQUAL : CGAL::NEGATIVE; + + Facet facet{c, facet_index}; + if(orient == CGAL::NEGATIVE) { + facet = tr().mirror_facet(facet); + } + CGAL_assertion(same_triple(facet, fh_2d)); + return std::make_pair(facet, CGAL::EQUAL); + } else { return std::nullopt; + } + } + + bool constrained_facet_has_2d_triangle(Facet facet) const + { + const auto face_index = face_constraint_index(facet); + if(face_index < 0 || static_cast(face_index) >= face_data.size() || + face_data[face_index].skip_face) + { + return false; + } + + const auto& cdt_2 = face_cdt_2(face_index); + auto opt = facet_is_facet_of_cdt_2(*this, facet, cdt_2); + return opt.has_value(); + } + + bool has_extra_constrained_facets() const + { + bool result = true; + const bool debug = this->debug().flips() || this->debug().restore_faces() || this->debug().conforming_validation(); + std::vector extra_facets; + for(const auto facet : constrained_facets()) { + if(constrained_facet_has_2d_triangle(facet)) { + continue; + } + result = false; + if(debug) { + extra_facets.push_back(facet); + std::cerr << "ERROR: constrained 3D facet" + << display_facet(" ", facet, this->with_point_and_info_tag) + << "\n has no corresponding 2D triangle in face #" + << face_constraint_index(facet) << '\n'; + } + } + if(debug && !extra_facets.empty()) { + std::ofstream dump("dump_extra_constrained_facets.off"); + dump.precision(17); + write_facets(dump, *this, extra_facets); + } + return result; } auto edge_of_cdt_2(const CDT_2& cdt_2, const Vertex_handle va, const Vertex_handle vb) const @@ -3663,8 +5407,8 @@ class Conforming_constrained_Delaunay_triangulation_3_impl : public Conforming_D { auto v = vertex_of_cdt_2_functor(cdt_2); - const auto cdt_2_v0 = v(this->point(va)); - const auto cdt_2_v1 = v(this->point(vb)); + const auto cdt_2_v0 = v(va); + const auto cdt_2_v1 = v(vb); CDT_2_face_handle fh; int edge_index; const bool is_edge = cdt_2.is_edge(cdt_2_v0, cdt_2_v1, fh, edge_index); @@ -3744,9 +5488,9 @@ class Conforming_constrained_Delaunay_triangulation_3_impl : public Conforming_D map_cavity_vertices_to_ambient_vertices[cavity_v] = v; if constexpr (cdt_3_can_use_cxx20_format()) if(this->debug().regions()) { std::cerr << cdt_3_format("inserted {}cavity vertex {:.6} -> {:.6}\n", - extra, - IO::oformat(cavity_v, with_point_and_info), - IO::oformat(v, with_point_and_info)); + extra, + display_vert(cavity_v), + display_vert(v)); } return cavity_v; }; @@ -3793,7 +5537,7 @@ class Conforming_constrained_Delaunay_triangulation_3_impl : public Conforming_D } for(int i = 0; i < 3; ++i) { Facet other_f{cell, this->vertex_triple_index(facet_index, i)}; - Facet mirror_f = this->mirror_facet(other_f); + Facet mirror_f = tr().mirror_facet(other_f); if(cells_of_cavity.count(mirror_f.first) == 0) { facets_of_cavity_border.insert(mirror_f); } @@ -3827,8 +5571,8 @@ class Conforming_constrained_Delaunay_triangulation_3_impl : public Conforming_D // IO::oformat(a), IO::oformat(b), IO::oformat(CGAL::angle(a, steiner_pt, b))) // << '\n'; if(CGAL::angle(a, steiner_pt, b) != CGAL::ACUTE) { - const auto va_3d = va->info().vertex_handle_3d; - const auto vb_3d = vb->info().vertex_handle_3d; + const auto va_3d = vertex_3d(va); + const auto vb_3d = vertex_3d(vb); return std::make_pair(va_3d, vb_3d); } } @@ -3918,25 +5662,21 @@ class Conforming_constrained_Delaunay_triangulation_3_impl : public Conforming_D } cleanup(); - // assert(is_valid(true)); - // this->study_bug = true; const auto v = this->insert_in_cdt_3(steiner_pt, lt, ch, li, lj, insert_in_conflict_visitor);// TODO: use "insert in hole" - // this->study_bug = false; - // assert(is_valid(true)); if constexpr (cdt_3_can_use_cxx20_format()) if(this->debug().Steiner_points()) { - std::cerr << " -> " << IO::oformat(v, with_offset) << '\n'; + std::cerr << " -> " << with_offset(v) << '\n'; } v->ccdt_3_data().set_Steiner_vertex_in_face(face_index); [[maybe_unused]] typename CDT_2::Locate_type lt_2; int i; auto fh = cdt_2.locate(steiner_pt, lt_2, i, fh_2d); - CGAL_assertion(!fh->info().is_outside_the_face); CGAL_USE(fh); + CGAL_assertion(fh->info().is_outside_the_face == INSIDE); CGAL_USE(fh); const auto v_2d = non_const_cdt_2.insert(steiner_pt, fh_2d); - v_2d->info().vertex_handle_3d = v; + vertex_3d(v_2d) = v; auto f_circ = cdt_2.incident_faces(v_2d); const auto end = f_circ; do { - f_circ->info().is_outside_the_face = false; + f_circ->info().is_outside_the_face = INSIDE; } while(++f_circ != end); search_for_missing_subfaces(face_index); return std::nullopt; @@ -3949,8 +5689,7 @@ class Conforming_constrained_Delaunay_triangulation_3_impl : public Conforming_D const auto mid = construct_midpoint(a, b); if constexpr (cdt_3_can_use_cxx20_format()) if(this->debug().Steiner_points()) { std::cerr << cdt_3_format("Inserting Steiner (midpoint) point {} of constrained edge ({:.6} , {:.6})\n", - IO::oformat(mid), IO::oformat(va_3d, with_point_and_info), - IO::oformat(vb_3d, with_point_and_info)); + IO::oformat(mid), display_vert(va_3d), display_vert(vb_3d)); } auto&& contexts = this->constraint_hierarchy.contexts(va_3d, vb_3d); if constexpr (cdt_3_can_use_cxx20_format()) if(this->debug().verbose_special_cases()) { @@ -3963,8 +5702,8 @@ class Conforming_constrained_Delaunay_triangulation_3_impl : public Conforming_D vh_it != end; ++vh_it) { std::cerr << cdt_3_format(" {} {}\n", - (vh_it == current) ? '>' : '-', - IO::oformat(*vh_it, with_point_and_info)); + (vh_it == current) ? '>' : '-', + display_vert(*vh_it)); } } } @@ -3973,7 +5712,6 @@ class Conforming_constrained_Delaunay_triangulation_3_impl : public Conforming_D const auto& context = *contexts.begin(); const auto constrained_polyline_id = context.id(); CGAL_assertion(constrained_polyline_id != Constrained_polyline_id{}); - // this->study_bug = true; Locate_type mid_lt; int mid_li, min_lj; Cell_handle mid_c = tr().locate(mid, mid_lt, mid_li, min_lj, va_3d->cell()); @@ -3982,13 +5720,26 @@ class Conforming_constrained_Delaunay_triangulation_3_impl : public Conforming_D this->insert_Steiner_point_on_subconstraint(mid, mid_c, {va_3d, vb_3d}, constrained_polyline_id, insert_in_conflict_visitor); if constexpr (cdt_3_can_use_cxx20_format()) if(this->debug().Steiner_points()) { - std::cerr << " -> " << IO::oformat(v, with_offset) << '\n'; + std::cerr << " -> " << with_offset(v) << '\n'; + } + } + + bool has_all_constrained_edges() const { + bool result = true; + for(const auto& [va, vb] : this->all_constrained_edges()) { + const bool is_3d = this->is_edge(va, vb); + if(!is_3d) { + std::cerr << cdt_3_format("Edge is not 3D: ({} , {})\n", display_vert(va), display_vert(vb)); + result = false; + } } - // this->study_bug = false; - // assert(is_valid(true)); + return result; } bool restore_face(CDT_3_signed_index face_index) { + // CGAL_assertion(has_all_constrained_edges()); + // auto _ = CGAL::make_scope_exit([&]() { CGAL_assertion(has_all_constrained_edges()); }); + CDT_2& non_const_cdt_2 = this->non_const_face_cdt_2(face_index); const CDT_2& cdt_2 = non_const_cdt_2; if constexpr (cdt_3_can_use_cxx20_format()) @@ -4001,13 +5752,13 @@ class Conforming_constrained_Delaunay_triangulation_3_impl : public Conforming_D for(const auto& edge : cdt_2.finite_edges()) { const auto fh = edge.first; const auto i = edge.second; - const auto va_3d = fh->vertex(cdt_2.cw(i))->info().vertex_handle_3d; - const auto vb_3d = fh->vertex(cdt_2.ccw(i))->info().vertex_handle_3d; + const auto va_3d = vertex_3d(fh->vertex(cdt_2.cw(i))); + const auto vb_3d = vertex_3d(fh->vertex(cdt_2.ccw(i))); const bool is_3d = this->is_edge(va_3d, vb_3d); if constexpr(cdt_3_can_use_cxx20_format()) { if(this->debug().copy_triangulation_into_hole() || this->debug().conforming_validation()) { - std::cerr << cdt_3_format("Edge is 3D: {:6} ({} , {})\n", is_3d, IO::oformat(va_3d, with_point_and_info), - IO::oformat(vb_3d, with_point_and_info)); + std::cerr << cdt_3_format("Edge is 3D: {:6} ({} , {})\n", is_3d, display_vert(va_3d), + display_vert(vb_3d)); } } CGAL_assertion(is_3d || !cdt_2.is_constrained(edge)); @@ -4018,18 +5769,15 @@ class Conforming_constrained_Delaunay_triangulation_3_impl : public Conforming_D std::set processed_faces; auto& region_index = face_region_number(face_index); for(const CDT_2_face_handle fh : cdt_2.finite_face_handles()) { - if(fh->info().is_outside_the_face) continue; + if(fh->info().is_outside_the_face == OUTSIDE) continue; if(false == fh->info().missing_subface) { continue; } - Cell_handle c; - int i, j, k; - if(tr().is_facet(fh->vertex(0)->info().vertex_handle_3d, - fh->vertex(1)->info().vertex_handle_3d, - fh->vertex(2)->info().vertex_handle_3d, c, i, j, k)) + const auto is_facet_opt = is_2d_face_also_a_3d_facet(fh); + if(is_facet_opt) { - const int facet_index = 6 - i - j - k; - set_facet_constrained({c, facet_index}, face_index, fh); + const auto [facet, orientation] = *is_facet_opt; + set_facet_constrained(facet, face_index, fh, orientation); fh->info().missing_subface = false; continue; } @@ -4050,11 +5798,9 @@ class Conforming_constrained_Delaunay_triangulation_3_impl : public Conforming_D for(auto [c, index]: cdt_2.constrained_edges()) { const auto va = c->vertex(cdt_2.cw(index)); const auto vb = c->vertex(cdt_2.ccw(index)); - const auto va_3d = va->info().vertex_handle_3d; - const auto vb_3d = vb->info().vertex_handle_3d; - std::cerr << cdt_3_format(" ({:.6} , {:.6})\n", - IO::oformat(va_3d, with_point_and_info), - IO::oformat(vb_3d, with_point_and_info)); + const auto va_3d = vertex_3d(va); + const auto vb_3d = vertex_3d(vb); + std::cerr << cdt_3_format(" ({:.6} , {:.6})\n", display_vert(va_3d), display_vert(vb_3d)); } } const auto encroach_edge_opt = @@ -4064,13 +5810,15 @@ class Conforming_constrained_Delaunay_triangulation_3_impl : public Conforming_D insert_mid_point_in_constrained_edge(va_3d, vb_3d); } }; + bool result = false; try { - restore_subface_region(face_index, region_index++, non_const_cdt_2, fh_region); + result = restore_subface_region(face_index, region_index++, non_const_cdt_2, fh_region); } catch(Next_region& e) { handle_error_with_region(e.what(), e.fh_2d); return false; } + if(!result) return false; } return true; } @@ -4111,11 +5859,11 @@ class Conforming_constrained_Delaunay_triangulation_3_impl : public Conforming_D const auto v = tr().vertices(it); std::cerr << "non-empty sphere at non-constrained facet (" << IO::oformat(Cell_handle(it)) << ", " << i << ") the cell is:\n " - << IO::oformat(v[0], with_point) << "\n " - << IO::oformat(v[1], with_point) << "\n " - << IO::oformat(v[2], with_point) << "\n " - << IO::oformat(v[3], with_point) << "\ncontains:\n " - << IO::oformat(n->vertex(n_index), with_point_and_info) << '\n'; + << with_point(v[0]) << "\n " + << with_point(v[1]) << "\n " + << with_point(v[2]) << "\n " + << with_point(v[3]) << "\ncontains:\n " + << display_vert(n->vertex(n_index)) << '\n'; using EK = CGAL::Exact_predicates_exact_constructions_kernel; const auto to_exact = CGAL::Cartesian_converter(); const auto from_exact = CGAL::Cartesian_converter(); @@ -4180,8 +5928,7 @@ class Conforming_constrained_Delaunay_triangulation_3_impl : public Conforming_D test = this->is_edge(v1, v2); result = result && test; if(!test && verbose) { - std::cerr << "edge (" << IO::oformat(v1, with_point_and_info) << ", " - << IO::oformat(v2, with_point_and_info) << ") is not an edge" << std::endl; + std::cerr << "edge (" << display_vert(v1) << ", " << display_vert(v2) << ") is not an edge" << std::endl; } } } @@ -4191,9 +5938,8 @@ class Conforming_constrained_Delaunay_triangulation_3_impl : public Conforming_D test = this->all_finite_edges[v1_index].find(v2)!= this->all_finite_edges[v1_index].end(); result = result && test; if(!test && verbose) { - std::cerr << "finite edge (" << IO::oformat(v1, with_point_and_info) << ", " - << IO::oformat(v2, with_point_and_info) << ") is not in the set all_finite_edges" - << std::endl; + std::cerr << "finite edge (" << display_vert(v1) << ", " << display_vert(v2) + << ") is not in the set all_finite_edges" << std::endl; } } } @@ -4205,8 +5951,12 @@ class Conforming_constrained_Delaunay_triangulation_3_impl : public Conforming_D } bool recheck_for_missing_subfaces() { + CGAL::Real_timer timer; + if(this->debug().display_statistics()) { + timer.start(); + } bool nothing_has_changed = true; - for(CDT_3_signed_index i = 0, end = static_cast(face_constraint_misses_subfaces.size()); i < end; ++i) { + for(CDT_3_signed_index i = 0, end = signed_number_of_faces(); i < end; ++i) { if(this->face_data[i].skip_face == false) { nothing_has_changed = nothing_has_changed && @@ -4220,15 +5970,15 @@ class Conforming_constrained_Delaunay_triangulation_3_impl : public Conforming_D void restore_constrained_Delaunay(Args&&... args) { this->is_Delaunay = false; - for(CDT_3_signed_index i = 0, end = static_cast (face_constraint_misses_subfaces.size()); i < end; - ++i) + for(CDT_3_signed_index i = 0, end = signed_number_of_faces(); i < end; ++i) { CDT_2& cdt_2 = non_const_face_cdt_2(i); try { fill_cdt_2(cdt_2, i); search_for_missing_subfaces(i); - } catch (typename CDT_2::Intersection_of_constraints_exception&) { - std::cerr << "ERROR: Intersection of constraints in face F#" << i << "\n"; + } catch (typename CDT_2::Intersection_of_constraints_exception& e) { + std::cerr << "ERROR: Intersection of constraints in face F#" << i << ": " + << e.what() << "\n"; this->face_data[i].skip_face = true; dump_face_polygons(build_face_border_handles(face_borders(i)), i); } catch (Null_normal_error& e) { @@ -4239,7 +5989,7 @@ class Conforming_constrained_Delaunay_triangulation_3_impl : public Conforming_D } } if(this->debug().input_faces()) { - for(CDT_3_signed_index i = 0, end = static_cast (face_constraint_misses_subfaces.size()); i < end; ++i) { + for(CDT_3_signed_index i = 0, end = signed_number_of_faces(); i < end; ++i) { dump_face(i); } } @@ -4253,7 +6003,9 @@ class Conforming_constrained_Delaunay_triangulation_3_impl : public Conforming_D // same face const CDT_2& cdt_2 = face_cdt_2(i); if(std::any_of(begin(cdt_2.finite_face_handles()), end(cdt_2.finite_face_handles()), - [](const auto& fh) { return !fh->info().is_outside_the_face && fh->info().missing_subface; })) + [](const auto& fh) { + return fh->info().is_outside_the_face == INSIDE && fh->info().missing_subface; + })) { face_constraint_misses_subfaces_set(i); } else { @@ -4269,7 +6021,7 @@ class Conforming_constrained_Delaunay_triangulation_3_impl : public Conforming_D std::cerr << "restore_face(" << i << ") incomplete, back to conforming...\n"; } Conforming_Dt::restore_Delaunay(insert_in_conflict_visitor); - // restart from the beginning, as the state of the triangulation has changed + // and then restart the loop at the beginning, to be sure that all faces are treated i = face_constraint_misses_subfaces_find_first(); } } @@ -4277,7 +6029,7 @@ class Conforming_constrained_Delaunay_triangulation_3_impl : public Conforming_D [](const auto& fd) { return fd.skip_face; })) { std::vector failed_faces; - for(CDT_3_signed_index i = 0, end = static_cast(face_data.size()); i < end; ++i) { + for(CDT_3_signed_index i = 0, end = signed_number_of_faces(); i < end; ++i) { if(face_data[i].skip_face) { failed_faces.push_back(i); } @@ -4300,38 +6052,106 @@ class Conforming_constrained_Delaunay_triangulation_3_impl : public Conforming_D } CGAL_assertion_msg( recheck_for_missing_subfaces() && - face_constraint_misses_subfaces_find_first() == face_constraint_misses_subfaces_npos, + are_there_any_face_constraint_misses_subfaces() == false, "All faces have been restored, but the triangulation is still not a CDT. This should not happen."); + CGAL_assertion_msg( + has_extra_constrained_facets(), + "All faces have been restored, but the triangulation has extra constrained facets. This should not happen."); + } + + void add_bbox_points() { + const auto bbox = CGAL::bbox_3(this->points_begin(), this->points_end(), this->geom_traits()); + double d_x = bbox.xmax() - bbox.xmin(); + double d_y = bbox.ymax() - bbox.ymin(); + double d_z = bbox.zmax() - bbox.zmin(); + + const double d = (std::max)({d_x, d_y, d_z}); + + using Point = typename T_3::Point_3; + + std::vector bbox_points + = { Point(bbox.xmin() - d, bbox.ymin() - d, bbox.zmin() - d), + Point(bbox.xmin() - d, bbox.ymax() + d, bbox.zmin() - d), + Point(bbox.xmin() - d, bbox.ymin() - d, bbox.zmax() + d), + Point(bbox.xmin() - d, bbox.ymax() + d, bbox.zmax() + d), + Point(bbox.xmax() + d, bbox.ymin() - d, bbox.zmin() - d), + Point(bbox.xmax() + d, bbox.ymax() + d, bbox.zmin() - d), + Point(bbox.xmax() + d, bbox.ymin() - d, bbox.zmax() + d), + Point(bbox.xmax() + d, bbox.ymax() + d, bbox.zmax() + d)}; + for(const auto& p : bbox_points) + { + Vertex_handle v = this->insert(p); + v->ccdt_3_data().set_vertex_type(CDT_3_vertex_type::BBOX); + } } void add_bbox_points_if_not_dimension_3() { if(this->dimension() != 3) { - const auto bbox = CGAL::bbox_3(this->points_begin(), this->points_end(), this->geom_traits()); - double d_x = bbox.xmax() - bbox.xmin(); - double d_y = bbox.ymax() - bbox.ymin(); - double d_z = bbox.zmax() - bbox.zmin(); + add_bbox_points(); + CGAL_assertion(this->dimension() == 3); + } + } + + void remove_bbox_points() + { + std::vector bbox_vertices; + this->adjacent_vertices(this->infinite_vertex(), std::back_inserter(bbox_vertices)); + if(bbox_vertices.size() != 8) + return; - const double d = (std::max)({d_x, d_y, d_z}); + auto remove_bbox_vertex = [this](Vertex_handle v) + { + // collect facets that will be on the outer hull after removing v + // seen from the other side, so that they remain valid + std::vector cells_incident_to_v; + this->finite_incident_cells(v, std::back_inserter(cells_incident_to_v)); - using Point = typename T_3::Point_3; + std::unordered_set> cavity_outer_hull; + for(Cell_handle c : cells_incident_to_v) + cavity_outer_hull.insert(this->mirror_facet({c, c->index(v)})); - this->insert(Point(bbox.xmin() - d, bbox.ymin() - d, bbox.zmin() - d)); - this->insert(Point(bbox.xmin() - d, bbox.ymax() + d, bbox.zmin() - d)); - this->insert(Point(bbox.xmin() - d, bbox.ymin() - d, bbox.zmax() + d)); - this->insert(Point(bbox.xmin() - d, bbox.ymax() + d, bbox.zmax() + d)); - this->insert(Point(bbox.xmax() + d, bbox.ymin() - d, bbox.zmin() - d)); - this->insert(Point(bbox.xmax() + d, bbox.ymax() + d, bbox.zmin() - d)); - this->insert(Point(bbox.xmax() + d, bbox.ymin() - d, bbox.zmax() + d)); - this->insert(Point(bbox.xmax() + d, bbox.ymax() + d, bbox.zmax() + d)); + // remove v + this->remove(v); - CGAL_assertion(this->dimension() == 3); + // mark the facets that are on the outer hull after removal + for(const auto& f : cavity_outer_hull) // f is seen from the "inside" + { + const auto& outer_facet = f; + const auto& outer_data = outer_facet.first->ccdt_3_data(); + const auto& cavity_facet = this->mirror_facet(outer_facet); + + const Cell_handle outer_cell = outer_facet.first; + const int outer_index = outer_facet.second; + if(outer_cell->ccdt_3_data().is_facet_constrained(outer_index)) + { + const CDT_3_signed_index face_id = face_constraint_index(outer_facet); + const auto& cdt_2d = this->face_cdt_2(face_id); + auto f_2d = outer_data.face_2(cdt_2d, outer_index);//CDT_2_face_handle + Facet oriented_facet = same_triple(outer_facet, f_2d) + ? outer_facet + : cavity_facet; + set_facet_constrained(oriented_facet, face_id, f_2d); + } + else + set_facet_as_not_constrained(cavity_facet); + } + }; + + for(auto v : bbox_vertices) + { + if (v->ccdt_3_data().vertex_type() != CDT_3_vertex_type::BBOX) + { + std::cout << "Bbox invalid. Cannot be removed" << std::endl; + return; + } + remove_bbox_vertex(v); } } static void write_region_to_OFF(std::ostream& out, const CDT_2& cdt_2) { out.precision(17); auto color_fn = [](CDT_2_face_handle fh_2d) -> CGAL::IO::Color { - if(fh_2d->info().is_outside_the_face) return CGAL::IO::gray(); + if(fh_2d->info().is_outside_the_face == OUTSIDE) return CGAL::IO::gray(); if(fh_2d->info().is_in_region) { if(fh_2d->info().is_in_region == 1) return CGAL::IO::violet(); else return CGAL::IO::red(); @@ -4395,14 +6215,14 @@ class Conforming_constrained_Delaunay_triangulation_3_impl : public Conforming_D { if constexpr (cdt_3_can_use_cxx20_format()) if(this->debug().regions()) { std::cerr << cdt_3_format("test_edge {} {} return {} {}\n", - IO::oformat(v0, with_point_and_info), - IO::oformat(v1, with_point_and_info), + with_point_and_info(v0), + with_point_and_info(v1), b, not_visited ? "(new)" : "(cached)"); if(not_visited && b) { - std::cerr << " triangle " << IO::oformat(triangle_vertices[0], with_point_and_info) << "\n" - << " " << IO::oformat(triangle_vertices[1], with_point_and_info) << "\n" - << " " << IO::oformat(triangle_vertices[2], with_point_and_info) << "\n"; + std::cerr << " triangle " << with_point_and_info(triangle_vertices[0]) << "\n" + << " " << with_point_and_info(triangle_vertices[1]) << "\n" + << " " << with_point_and_info(triangle_vertices[2]) << "\n"; } } CGAL_USE(this, v0, v1, b, not_visited); @@ -4422,6 +6242,7 @@ class Conforming_constrained_Delaunay_triangulation_3_impl : public Conforming_D std::swap(v0, v1); } if constexpr(cdt_3_can_use_cxx20_format()) if(this->debug().regions()) { + auto indent_guard = CGAL::IO::make_indenting_guards("| ", std::cerr); debug_dump_edge_region_intersection(face_index, region_index, fh_region, region_vertices, border_edges, intersecting_edges.size(), v0, v1, {cell, index_v0, index_v1}, triangle_vertices); } @@ -4430,8 +6251,7 @@ class Conforming_constrained_Delaunay_triangulation_3_impl : public Conforming_D std::stringstream ss; ss.precision(std::cerr.precision()); ss << "Error: detected a self-intersection.\n" - " The constrained edge (" << IO::oformat(v0, with_point_and_info) - << ", " << IO::oformat(v1, with_point_and_info) + " The constrained edge (" << with_point_and_info(v0) << ", " << with_point_and_info(v1) << ") intersects the interior of the polygonal constraint #" << face_index << " (sub-region #" << region_index << ").\n" << " The input data is either self-intersecting or the input" @@ -4450,16 +6270,15 @@ class Conforming_constrained_Delaunay_triangulation_3_impl : public Conforming_D }; auto test_cell = [&](Cell_handle cell) { - std::optional indent_guards; if constexpr(cdt_3_can_use_cxx20_format()) if(this->debug().regions()) { std::cerr << cdt_3_format("test_cell #{}\n {}\n {}\n {}\n {}\n", cell->time_stamp(), - IO::oformat(cell->vertex(0), with_point_and_info), - IO::oformat(cell->vertex(1), with_point_and_info), - IO::oformat(cell->vertex(2), with_point_and_info), - IO::oformat(cell->vertex(3), with_point_and_info)); - indent_guards.emplace(CGAL::IO::make_indenting_guards("| ", std::cerr, std::cout, std::clog)); + with_point_and_info(cell->vertex(0)), + with_point_and_info(cell->vertex(1)), + with_point_and_info(cell->vertex(2)), + with_point_and_info(cell->vertex(3))); } + auto indent_guards = CGAL::IO::make_indenting_guards(this->debug().regions() ? "| " : "", std::cerr); bool does_intersect = false; for(int i = 0; i < 4; ++i) { const auto v0 = cell->vertex(i); @@ -4509,8 +6328,7 @@ class Conforming_constrained_Delaunay_triangulation_3_impl : public Conforming_D // Dump intersecting edges information for(auto edge : intersecting_edges) { auto [v1, v2] = tr().vertices(edge); - std::cerr << cdt_3_format(" edge: {} {}\n", IO::oformat(v1, with_point_and_info), - IO::oformat(v2, with_point_and_info)); + std::cerr << cdt_3_format(" edge: {} {}\n", with_point_and_info(v1), with_point_and_info(v2)); } // Dump upper and lower cavity facets @@ -4533,7 +6351,7 @@ class Conforming_constrained_Delaunay_triangulation_3_impl : public Conforming_D std::cerr << " facet: "; const auto facet_vertices = tr().vertices(facet); for(auto v: facet_vertices) { - std::cerr << IO::oformat(v, with_point_and_info) << " "; + std::cerr << with_point_and_info(v) << " "; } // This assertion is wrong, because there might be only one half-cavity and not a full cavity. // CGAL_assertion(!std::all_of(facet_vertices.begin(), facet_vertices.end(), @@ -4557,19 +6375,15 @@ class Conforming_constrained_Delaunay_triangulation_3_impl : public Conforming_D const auto to_exact = CGAL::Cartesian_converter(); const auto& cdt_2 = this->face_cdt_2(face_index); - auto of = [](auto&&... args) { - return IO::oformat(std::forward(args)..., with_point_and_info); - }; - auto indent_guard = CGAL::IO::make_indenting_guards("| ", std::cerr, std::cout, std::clog); std::cerr << cdt_3_format("intersecting edge #{}: ( {} {} )\n" "intersected triangle vertices: {}\n" " {}\n" " {}\n", - edge_index, of(v_above), of(v_below), - of(first_intersected_triangle_vertices[0]), - of(first_intersected_triangle_vertices[1]), - of(first_intersected_triangle_vertices[2])); + edge_index, with_point_and_info(v_above), with_point_and_info(v_below), + with_point_and_info(first_intersected_triangle_vertices[0]), + with_point_and_info(first_intersected_triangle_vertices[1]), + with_point_and_info(first_intersected_triangle_vertices[2])); dump_region(face_index, region_index, cdt_2); const auto p_above = this->point(v_above); @@ -4583,9 +6397,9 @@ class Conforming_constrained_Delaunay_triangulation_3_impl : public Conforming_D std::ofstream intersect_out(ss_filename.str()); intersect_out.precision(17); for(auto fh: fh_region) { - auto v0 = fh->vertex(0)->info().vertex_handle_3d; - auto v1 = fh->vertex(1)->info().vertex_handle_3d; - auto v2 = fh->vertex(2)->info().vertex_handle_3d; + auto v0 = vertex_3d(fh->vertex(0)); + auto v1 = vertex_3d(fh->vertex(1)); + auto v2 = vertex_3d(fh->vertex(2)); auto triangle = typename Geom_traits::Triangle_3{tr().point(v0), tr().point(v1), tr().point(v2)}; auto exact_triangle = to_exact(triangle); if(auto edge_intersection_opt = CGAL::intersection(exact_edge_segment, exact_triangle)) { @@ -4604,7 +6418,10 @@ class Conforming_constrained_Delaunay_triangulation_3_impl : public Conforming_D continue; } std::cerr << cdt_3_format("Test tetrahedron (#{}):\n {}\n {}\n {}\n {}\n", ch->time_stamp(), - of(ch->vertex(0)), of(ch->vertex(1)), of(ch->vertex(2)), of(ch->vertex(3))); + with_point_and_info(ch->vertex(0)), + with_point_and_info(ch->vertex(1)), + with_point_and_info(ch->vertex(2)), + with_point_and_info(ch->vertex(3))); bool does_intersect_region = std::invoke([&]() { for(int i = 0; i < 4; ++i) { for(int j = i + 1; j < 4; ++j) { @@ -4624,7 +6441,11 @@ class Conforming_constrained_Delaunay_triangulation_3_impl : public Conforming_D exception_ostream() << cdt_3_format( "ERROR: The following tetrahedron (#{}) does not intersect the region:\n {}\n {}\n {}\n {}", - ch->time_stamp(), of(ch->vertex(0)), of(ch->vertex(1)), of(ch->vertex(2)), of(ch->vertex(3))) + ch->time_stamp(), + with_point_and_info(ch->vertex(0)), + with_point_and_info(ch->vertex(1)), + with_point_and_info(ch->vertex(2)), + with_point_and_info(ch->vertex(3))) << std::endl; } } @@ -4694,9 +6515,9 @@ class Conforming_constrained_Delaunay_triangulation_3_impl : public Conforming_D auto tetrahedron = tr().tetrahedron(ch); auto exact_tetrahedron = to_exact(tetrahedron); for(auto fh : fh_region) { - auto v0 = fh->vertex(0)->info().vertex_handle_3d; - auto v1 = fh->vertex(1)->info().vertex_handle_3d; - auto v2 = fh->vertex(2)->info().vertex_handle_3d; + auto v0 = vertex_3d(fh->vertex(0)); + auto v1 = vertex_3d(fh->vertex(1)); + auto v2 = vertex_3d(fh->vertex(2)); auto triangle = typename Geom_traits::Triangle_3{tr().point(v0), tr().point(v1), tr().point(v2)}; auto exact_triangle = to_exact(triangle); @@ -4742,8 +6563,8 @@ class Conforming_constrained_Delaunay_triangulation_3_impl : public Conforming_D write_3d_triangulation_to_OFF(dump, tr); } - void dump_triangulation() const { - std::ofstream dump("dump.binary.cgal", std::ios::binary); + void dump_triangulation(std::string filename = "dump.binary.cgal") const { + std::ofstream dump(filename, std::ios::binary); CGAL::IO::save_binary_file(dump, *this); } @@ -4754,6 +6575,12 @@ class Conforming_constrained_Delaunay_triangulation_3_impl : public Conforming_D write_3d_triangulation_to_OFF(dump, *this); } + void dump_constrained_facets_to_off(std::string filename) const { + std::ofstream dump(filename); + dump.precision(17); + write_facets(dump, *this, this->constrained_facets()); + } + void dump_face_polygons( const std::vector>& vec_of_handles, CDT_3_signed_index polygon_constraint_id, @@ -4779,9 +6606,10 @@ class Conforming_constrained_Delaunay_triangulation_3_impl : public Conforming_D write_region_to_OFF(dump_region, cdt_2); } - void dump_face(CDT_3_signed_index face_index) { + void dump_face(CDT_3_signed_index face_index, std::string filename = {}) const { const auto& cdt_2 = face_cdt_2(face_index); - std::ofstream dump_region(std::string("dump_face_") + std::to_string(face_index) + ".off"); + if(filename.empty()) filename = std::string("dump_face_") + std::to_string(face_index) + ".off"; + std::ofstream dump_region(filename); dump_region.precision(17); write_region_to_OFF(dump_region, cdt_2); } @@ -4869,17 +6697,15 @@ class Conforming_constrained_Delaunay_triangulation_3_impl : public Conforming_D void write_2d_triangle(std::ostream &out, const CDT_2_face_handle fh) { - const auto v0 = fh->vertex(0)->info().vertex_handle_3d; - const auto v1 = fh->vertex(1)->info().vertex_handle_3d; - const auto v2 = fh->vertex(2)->info().vertex_handle_3d; + const auto v0 = vertex_3d(fh->vertex(0)); + const auto v1 = vertex_3d(fh->vertex(1)); + const auto v2 = vertex_3d(fh->vertex(2)); write_triangle(out, v0, v1, v2); } bool write_missing_subfaces_file(std::ostream& out) { - const auto npos = face_constraint_misses_subfaces_npos; - auto i = face_constraint_misses_subfaces_find_first(); - bool has_missing_subfaces = i != npos; - while(i != npos) { + const bool has_missing_subfaces = are_there_any_face_constraint_misses_subfaces(); + loop_on_face_constraint_misses_subfaces([&](auto i) { const CDT_2& cdt = face_cdt_2(i); for(const auto fh: cdt.finite_face_handles()) { if (false == fh->info().is_outside_the_face && @@ -4888,14 +6714,12 @@ class Conforming_constrained_Delaunay_triangulation_3_impl : public Conforming_D write_2d_triangle(out, fh); } } - i = face_constraint_misses_subfaces_find_next(i); - } + }); return has_missing_subfaces; } /// @{ /// remove functions cannot be called - void remove(Vertex_handle) = delete; void remove_cluster() = delete; /// @} @@ -4919,6 +6743,10 @@ class Conforming_constrained_Delaunay_triangulation_3_impl : public Conforming_D }; protected: + CDT_3_signed_index signed_number_of_faces() const { + return static_cast(face_data.size()); + } + // Accessor functions for Face_data members CDT_2& non_const_face_cdt_2(std::size_t face_id) { return face_data[face_id].cdt_2; @@ -5008,7 +6836,22 @@ class Conforming_constrained_Delaunay_triangulation_3_impl : public Conforming_D void face_constraint_misses_subfaces_reset(std::size_t pos) { face_constraint_misses_subfaces[pos] = false; } -}; + + template + auto loop_on_face_constraint_misses_subfaces(F f) const { + auto i = face_constraint_misses_subfaces_find_first(); + bool has_any = i != face_constraint_misses_subfaces_npos; + while(i != face_constraint_misses_subfaces_npos) { + f(i); + i = face_constraint_misses_subfaces_find_next(i); + } + return has_any; + } + + auto are_there_any_face_constraint_misses_subfaces() const { + return face_constraint_misses_subfaces_find_first() != face_constraint_misses_subfaces_npos; + } +}; // end of Conforming_constrained_Delaunay_triangulation_3_impl #endif // DOXYGEN_RUNNING @@ -5066,7 +6909,7 @@ auto get_remeshing_triangulation(Conforming_constrained_Delaunay_triangulation_3 { for(auto v : ccdt.triangulation().all_vertex_handles()) { switch(v->ccdt_3_data().vertex_type()) { - case CDT_3_vertex_type::CORNER: + case CDT_3_vertex_type::INPUT_VERTEX: v->set_dimension(0); v->set_index(0); break; @@ -5079,12 +6922,11 @@ auto get_remeshing_triangulation(Conforming_constrained_Delaunay_triangulation_3 v->set_index(v->ccdt_3_data().face_index()); break; case CDT_3_vertex_type::FREE: + case CDT_3_vertex_type::BBOX: + case CDT_3_vertex_type::STEINER_IN_VOLUME: v->set_dimension(3); v->set_index(1); break; - default: - CGAL_error(); - break; } } @@ -5123,6 +6965,8 @@ auto get_remeshing_triangulation(Conforming_constrained_Delaunay_triangulation_3 using TDS = typename CDT_3::Triangulation::Triangulation_data_structure; static_assert(std::is_same_v>); + static constexpr int INVALID_SUBDOMAIN_INDEX = -1; + if(tr.dimension() < 3) { for(auto ch : tr.all_cell_handles()) { ch->set_subdomain_index(0); @@ -5135,7 +6979,7 @@ auto get_remeshing_triangulation(Conforming_constrained_Delaunay_triangulation_3 } } else { for(auto ch : tr.all_cell_handles()) { - ch->set_subdomain_index(-1); + ch->set_subdomain_index(INVALID_SUBDOMAIN_INDEX); } // Use a flood algorithm to mark constrained connected components. @@ -5149,7 +6993,7 @@ auto get_remeshing_triangulation(Conforming_constrained_Delaunay_triangulation_3 // Function to flood-fill a connected component with a given subdomain index auto flood_component = [&border](typename Tr::Cell_handle start, int subdomain_index) { - if(start->subdomain_index() != -1) + if(start->subdomain_index() != INVALID_SUBDOMAIN_INDEX) return; std::stack queue; @@ -5158,12 +7002,12 @@ auto get_remeshing_triangulation(Conforming_constrained_Delaunay_triangulation_3 while(!queue.empty()) { auto ch = queue.top(); queue.pop(); - if(ch->subdomain_index() == -1) { + if(ch->subdomain_index() == INVALID_SUBDOMAIN_INDEX) { ch->set_subdomain_index(subdomain_index); for(int i = 0; i < 4; i++) { typename Tr::Facet f(ch, i); auto n = ch->neighbor(i); - if(n->subdomain_index() == -1) { + if(n->subdomain_index() == INVALID_SUBDOMAIN_INDEX) { if(ch->ccdt_3_data().is_facet_constrained(i)) border.push(f); else @@ -5183,7 +7027,7 @@ auto get_remeshing_triangulation(Conforming_constrained_Delaunay_triangulation_3 auto f = border.top(); border.pop(); auto n = f.first->neighbor(f.second); - if(n->subdomain_index() == -1) { + if(n->subdomain_index() == INVALID_SUBDOMAIN_INDEX) { // If we are coming from an even subdomain, use next odd, and vice versa bool from_even = (f.first->subdomain_index() % 2 == 0); int next_index = from_even ? next_odd_subdomain : next_even_subdomain; @@ -5197,7 +7041,7 @@ auto get_remeshing_triangulation(Conforming_constrained_Delaunay_triangulation_3 bool found_unvisited = false; for(auto ch : tr.finite_cell_handles()) { - if(ch->subdomain_index() == -1) { + if(ch->subdomain_index() == INVALID_SUBDOMAIN_INDEX) { flood_component(ch, next_even_subdomain); next_even_subdomain += 2; found_unvisited = true; diff --git a/Constrained_triangulation_3/include/CGAL/Conforming_constrained_Delaunay_triangulation_cell_base_3.h b/Constrained_triangulation_3/include/CGAL/Conforming_constrained_Delaunay_triangulation_cell_base_3.h index f109feaed163..d9e42f9e0b79 100644 --- a/Constrained_triangulation_3/include/CGAL/Conforming_constrained_Delaunay_triangulation_cell_base_3.h +++ b/Constrained_triangulation_3/include/CGAL/Conforming_constrained_Delaunay_triangulation_cell_base_3.h @@ -69,6 +69,41 @@ class Conforming_constrained_Delaunay_triangulation_cell_base_3 return ccdt_3_data_; } + ///////// for C3T3 : dummy implementation for compilation purposes + using Subdomain_index = int; + Subdomain_index subdomain_{}; + Subdomain_index subdomain_index() const { return subdomain_; } + // dummy value, not used in the implementation of CCDT + // todo : remove this function and the corresponding typedef, as they are not used in the implementation of CCDT, and + // are only here to satisfy the requirements of the concept `SimplicialMeshCellBase_3` + // for tetrahedral remeshing + // PLUS value 1 does not make any sense in the general case + void set_subdomain_index(Subdomain_index) {} + void reset_cache_validity() {} + bool is_cache_valid() const { return false;} + void set_sliver_value(double) {} + double sliver_value() const { return 0.; } + + ///////// valid implementation + template + void set_surface_patch_index(const int i, const Surface_patch_index& patch) + { + if(patch > 0) + this->ccdt_3_data().set_face_constraint_index(i, patch - 1); + else + this->ccdt_3_data().set_face_constraint_index(i, patch); + } + + auto surface_patch_index(const int i) const { + return this->ccdt_3_data().face_constraint_index(i) + 1; + } + + bool is_facet_on_surface(const int i) const { + return this->ccdt_3_data().face_constraint_index(i) >= 0; + } + + ///////// end of for C3T3 + static std::string io_signature() { static_assert( std::is_same_v< @@ -105,7 +140,7 @@ class Conforming_constrained_Delaunay_triangulation_cell_base_3 CGAL::read(is, i); } if(!is) return is; - c->ccdt_3_data().set_face_constraint_index(li, i); + c.ccdt_3_data().set_face_constraint_index(li, i); } return is; } diff --git a/Constrained_triangulation_3/include/CGAL/Conforming_constrained_Delaunay_triangulation_cell_data_3.h b/Constrained_triangulation_3/include/CGAL/Conforming_constrained_Delaunay_triangulation_cell_data_3.h index 91d9b73044ae..dc1eff2b045c 100644 --- a/Constrained_triangulation_3/include/CGAL/Conforming_constrained_Delaunay_triangulation_cell_data_3.h +++ b/Constrained_triangulation_3/include/CGAL/Conforming_constrained_Delaunay_triangulation_cell_data_3.h @@ -15,6 +15,7 @@ #include #include +#include #include #include @@ -25,7 +26,7 @@ enum class CDT_3_cell_marker { IN_REGION = 1, VISITED = 1, ON_REGION_BOUNDARY = 2, - nb_of_markers + last = ON_REGION_BOUNDARY, }; /*! @@ -44,7 +45,7 @@ class Conforming_constrained_Delaunay_triangulation_cell_data_3 { std::array face_id = { -1, -1, -1, -1 }; std::array facet_2d = {nullptr, nullptr, nullptr, nullptr}; - std::bitset(CDT_3_cell_marker::nb_of_markers)> markers; + std::bitset(CDT_3_cell_marker::last) + 1> markers{}; bool is_marked() const { return markers.any(); } bool is_marked(CDT_3_cell_marker m) const { return markers.test(static_cast(m)); } diff --git a/Constrained_triangulation_3/include/CGAL/Conforming_constrained_Delaunay_triangulation_vertex_base_3.h b/Constrained_triangulation_3/include/CGAL/Conforming_constrained_Delaunay_triangulation_vertex_base_3.h index 30b1c1c54f12..305c3e9456dc 100644 --- a/Constrained_triangulation_3/include/CGAL/Conforming_constrained_Delaunay_triangulation_vertex_base_3.h +++ b/Constrained_triangulation_3/include/CGAL/Conforming_constrained_Delaunay_triangulation_vertex_base_3.h @@ -55,6 +55,11 @@ class Conforming_constrained_Delaunay_triangulation_vertex_base_3 using Base = Triangulation_simplex_base_with_time_stamp; using Base::Base; + ///////// for C3T3 : dummy implementation for compilation purposes + using Index = int; + void set_dimension(int) {} + ///////// end of for C3T3 + // model of ConformingConstrainedDelaunayTriangulationVertexBase_3 Conforming_constrained_Delaunay_triangulation_vertex_data_3& ccdt_3_data() { return ccdt_3_data_; } const Conforming_constrained_Delaunay_triangulation_vertex_data_3& ccdt_3_data() const { return ccdt_3_data_; } diff --git a/Constrained_triangulation_3/include/CGAL/Conforming_constrained_Delaunay_triangulation_vertex_data_3.h b/Constrained_triangulation_3/include/CGAL/Conforming_constrained_Delaunay_triangulation_vertex_data_3.h index 790eb11bdce9..7033e4e48c07 100644 --- a/Constrained_triangulation_3/include/CGAL/Conforming_constrained_Delaunay_triangulation_vertex_data_3.h +++ b/Constrained_triangulation_3/include/CGAL/Conforming_constrained_Delaunay_triangulation_vertex_data_3.h @@ -35,7 +35,15 @@ namespace CGAL { struct Conforming_constrained_Delaunay_triangulation_vertex_data_3 {}; #else // DOXYGEN_RUNNING -enum class CDT_3_vertex_type { FREE, CORNER, INPUT_VERTEX = CORNER, STEINER_ON_EDGE, STEINER_IN_FACE }; +enum class CDT_3_vertex_type : unsigned char { + FREE, + INPUT_VERTEX, + STEINER_ON_EDGE, + STEINER_IN_FACE, + STEINER_IN_VOLUME, + BBOX, + last = BBOX, +}; enum class CDT_3_vertex_marker { CLEAR = 0, @@ -44,14 +52,14 @@ enum class CDT_3_vertex_marker { CAVITY, CAVITY_ABOVE, CAVITY_BELOW, - nb_of_markers + last = CAVITY_BELOW }; class Conforming_constrained_Delaunay_triangulation_vertex_data_3 { protected: // TODO: check and improve the compactness of this class CDT_3_vertex_type m_vertex_type = CDT_3_vertex_type::FREE; - std::bitset(CDT_3_vertex_marker::nb_of_markers)> mark{}; + std::bitset(CDT_3_vertex_marker::last) + 1> mark{}; struct C_id { void* ptr = nullptr; std::size_t id = 0; @@ -143,7 +151,8 @@ class Conforming_constrained_Delaunay_triangulation_vertex_data_3 { void set_vertex_type(CDT_3_vertex_type type) { m_vertex_type = type; } bool is_Steiner_vertex_on_edge() const { return m_vertex_type == CDT_3_vertex_type::STEINER_ON_EDGE; } bool is_Steiner_vertex_in_face() const { return m_vertex_type == CDT_3_vertex_type::STEINER_IN_FACE; } - bool is_corner() const { return m_vertex_type == CDT_3_vertex_type::CORNER; } + bool is_Steiner_vertex_in_volume() const { return m_vertex_type == CDT_3_vertex_type::STEINER_IN_VOLUME; } + bool is_corner() const { return m_vertex_type == CDT_3_vertex_type::INPUT_VERTEX; } }; #endif // DOXYGEN_RUNNING diff --git a/Constrained_triangulation_3/include/CGAL/Constrained_triangulation_3/internal/cdt_debug_io.h b/Constrained_triangulation_3/include/CGAL/Constrained_triangulation_3/internal/cdt_debug_io.h index 752aaacfec32..e3d3ed247db1 100644 --- a/Constrained_triangulation_3/include/CGAL/Constrained_triangulation_3/internal/cdt_debug_io.h +++ b/Constrained_triangulation_3/include/CGAL/Constrained_triangulation_3/internal/cdt_debug_io.h @@ -35,9 +35,7 @@ namespace CGAL { std::size_t i = 0; for(const auto& [cell, facet_index] : facets_range) { - const auto v0 = cell->vertex(Tr::vertex_triple_index(facet_index, 0)); - const auto v1 = cell->vertex(Tr::vertex_triple_index(facet_index, 1)); - const auto v2 = cell->vertex(Tr::vertex_triple_index(facet_index, 2)); + const auto [v0, v1, v2] = tr.vertices({cell, facet_index}); points.push_back(tr.point(v0)); points.push_back(tr.point(v1)); points.push_back(tr.point(v2)); diff --git a/Constrained_triangulation_3/include/CGAL/Constrained_triangulation_3/internal/smooth_Steiner_vertices.h b/Constrained_triangulation_3/include/CGAL/Constrained_triangulation_3/internal/smooth_Steiner_vertices.h new file mode 100644 index 000000000000..db84878bbc01 --- /dev/null +++ b/Constrained_triangulation_3/include/CGAL/Constrained_triangulation_3/internal/smooth_Steiner_vertices.h @@ -0,0 +1,186 @@ +// Copyright (c) 2019-2026 GeometryFactory Sarl (France). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org). +// +// $URL$ +// $Id$ +// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial +// +// Author(s) : Jane Tournois + +#ifndef CGAL_INTERNAL_CDT_3_SMOOTH_STEINER_VERTICES_H +#define CGAL_INTERNAL_CDT_3_SMOOTH_STEINER_VERTICES_H + +#include + +#include + +#include +#include + +#include + +#include +#include +#include +#include + +namespace CGAL +{ +namespace internal +{ + +template +struct Is_input_vertex_map +{ + using category = boost::readable_property_map_tag; + using reference = bool; + using value_type = bool; + using key_type = Vertex_handle; + friend reference get(const Is_input_vertex_map&, key_type v) + { + auto type = v->ccdt_3_data().vertex_type(); + return type == CDT_3_vertex_type::INPUT_VERTEX || type == CDT_3_vertex_type::BBOX; + } +}; + +template +struct Is_finite_cell_pmap +{ + using category = boost::read_write_property_map_tag; + using reference = bool; + using value_type = bool; + using key_type = typename CDT::Cell_handle; + + const typename CDT::Vertex_handle infinite_vertex_; + + friend reference get(const Is_finite_cell_pmap& m, key_type cell) + { + for(int i = 0; i < 4; ++i) + { + if(cell->vertex(i) == m.infinite_vertex_) + return false; + } + return true; + } + friend void put(Is_finite_cell_pmap&, const key_type, const value_type) {} +}; + +template +std::size_t count_negative_tetrahedra(const CDT_3& cdt) +{ + const auto& tr = cdt.triangulation(); + return std::count_if( + tr.finite_cells_begin(), + tr.finite_cells_end(), + [&](const auto& c) + { + return CGAL::POSITIVE != CGAL::orientation(tr.point(c.vertex(0)), + tr.point(c.vertex(1)), + tr.point(c.vertex(2)), + tr.point(c.vertex(3))); + }); +} + +template +void dump_negative_tetrahedra(const char* filename, const CDT_3& cdt) +{ + std::ofstream ofs(filename); + ofs.precision(17); + for(auto c : cdt.finite_cell_handles()) + { + if(CGAL::volume(c->vertex(0)->point(), c->vertex(1)->point(), + c->vertex(2)->point(), c->vertex(3)->point()) < 0.) + { + ofs << "2 " << c->vertex(0)->point() << " " << c->vertex(1)->point() << std::endl; + ofs << "2 " << c->vertex(0)->point() << " " << c->vertex(2)->point() << std::endl; + ofs << "2 " << c->vertex(0)->point() << " " << c->vertex(3)->point() << std::endl; + ofs << "2 " << c->vertex(1)->point() << " " << c->vertex(2)->point() << std::endl; + ofs << "2 " << c->vertex(1)->point() << " " << c->vertex(3)->point() << std::endl; + ofs << "2 " << c->vertex(2)->point() << " " << c->vertex(3)->point() << std::endl; + } + } + ofs.close(); +} + +template +void smooth_Steiner_vertices_in_volume(CDT_3& cdt, + const double bbox_max_span, + const bool remesh) +{ + using Vertex_handle = typename CDT_3::Vertex_handle; + + std::cout << "#Negative tetrahedra before Steiner smoothing: " << count_negative_tetrahedra(cdt) << std::endl; + + std::ofstream ofs00("out_before_steiner_smoothing.mesh"); + ofs00.precision(17); + CGAL::IO::write_MEDIT(ofs00, cdt, CGAL::parameters::all_cells(true).with_plc_face_id(true)); + ofs00.close(); + + if(count_negative_tetrahedra(cdt) == 0) { + std::cout << "Good :-) No negative tetrahedra left!" << std::endl; + return; + } + + cdt.triangulation().may_have_badly_oriented_cells(true); + + if(remesh) + { + internal::Is_input_vertex_map is_input_vertex_pmap; + internal::Is_finite_cell_pmap is_finite_cell{cdt.triangulation().infinite_vertex()}; + + // collapse and smooth only + CGAL::tetrahedral_isotropic_remeshing(cdt, bbox_max_span, + CGAL::parameters::number_of_iterations(5) + .nb_smoothing_iterations(3) + .nb_flip_smooth_iterations(0) + .do_split(false) + .do_collapse(true) + .do_flip(true) + .remesh_boundaries(false) + .cell_is_selected_map(is_finite_cell) + .vertex_is_constrained_map(is_input_vertex_pmap)); + + std::cout << std::endl; + std::cout << "AFTER COLLAPSE" << std::endl; + std::cout << cdt.statistics() << std::endl; + + std::ofstream ofs("out_after_collapse.mesh"); + ofs.precision(17); + CGAL::IO::write_MEDIT(ofs, cdt); + ofs.close(); + if(count_negative_tetrahedra(cdt) == 0) { + std::cout << "Good :-) No negative tetrahedra left after collapse!" << std::endl; + return; + } + + // split long internal edges + const double target_edge_length = 0.0005 * bbox_max_span; + CGAL::tetrahedral_isotropic_remeshing(cdt, target_edge_length, + CGAL::parameters::number_of_iterations(5) + .nb_smoothing_iterations(5) + .nb_flip_smooth_iterations(10) + .do_split(true) + .do_collapse(true) + .do_flip(true) + .remesh_boundaries(false) + .vertex_is_constrained_map(is_input_vertex_pmap)); + + std::cout << std::endl; + std::cout << "AFTER SPLIT AND BEFORE SMOOTH" << std::endl; + std::cout << cdt.statistics() << std::endl; + + if(count_negative_tetrahedra(cdt) == 0) + { + std::cout << "Good :-) No negative tetrahedra left after remeshing!" << std::endl; + return; + } + } + std::cout << cdt.statistics() << std::endl; +} + +} // namespace internal +} // namespace CGAL + +#endif // CGAL_INTERNAL_CDT_3_SMOOTH_STEINER_VERTICES_H diff --git a/Constrained_triangulation_3/package_info/Constrained_triangulation_3/dependencies b/Constrained_triangulation_3/package_info/Constrained_triangulation_3/dependencies index 854e686ee58b..722c7f611507 100644 --- a/Constrained_triangulation_3/package_info/Constrained_triangulation_3/dependencies +++ b/Constrained_triangulation_3/package_info/Constrained_triangulation_3/dependencies @@ -1,3 +1,4 @@ +AABB_tree Algebraic_foundations Arithmetic_kernel BGL @@ -10,6 +11,7 @@ Constrained_triangulation_3 Distance_2 Distance_3 Filtered_kernel +Generator Hash_map Homogeneous_kernel Installation @@ -21,6 +23,7 @@ Kernel_d Mesh_3 Modular_arithmetic Number_types +PMP_Boolean_operations PMP_Mesh_repair PMP_Remeshing Polygon @@ -32,6 +35,7 @@ Random_numbers SMDS_3 STL_Extension Solver_interface +Spatial_searching Spatial_sorting Stream_support Surface_mesh diff --git a/Constrained_triangulation_3/test/Constrained_triangulation_3/CMakeLists.txt b/Constrained_triangulation_3/test/Constrained_triangulation_3/CMakeLists.txt index 83e6440f3f41..e30151e36d16 100644 --- a/Constrained_triangulation_3/test/Constrained_triangulation_3/CMakeLists.txt +++ b/Constrained_triangulation_3/test/Constrained_triangulation_3/CMakeLists.txt @@ -10,28 +10,37 @@ create_single_source_cgal_program(test_ccdt_remeshing.cpp) find_package(Eigen3 QUIET) include(CGAL_Eigen3_support) +set(CMAKE_CXX_SCAN_FOR_MODULES FALSE) + # CDT_3: C++20 for structured bindings -add_library(CDT_3_dependencies INTERFACE) -target_compile_features(CDT_3_dependencies INTERFACE cxx_std_20) -target_link_libraries(CDT_3_dependencies INTERFACE CGAL::CGAL CGAL::Data CGAL::Eigen3_support) +add_library(CGAL_CDT_3_dependencies INTERFACE) +target_compile_features(CGAL_CDT_3_dependencies INTERFACE cxx_std_20) +target_link_libraries(CGAL_CDT_3_dependencies INTERFACE CGAL::CGAL CGAL::Data CGAL::Eigen3_support) + +find_package(CLI11 QUIET) +add_library(CGAL_CDT_3_CLI11 INTERFACE) +if(TARGET CLI11::CLI11) + target_link_libraries(CGAL_CDT_3_CLI11 INTERFACE CLI11::CLI11) + target_compile_definitions(CGAL_CDT_3_CLI11 INTERFACE CGAL_USE_CLI11) +endif() create_single_source_cgal_program( "cdt_test_insert_constrained_edge_from_EDG_file.cpp") -target_link_libraries(cdt_test_insert_constrained_edge_from_EDG_file PRIVATE CDT_3_dependencies) +target_link_libraries(cdt_test_insert_constrained_edge_from_EDG_file PRIVATE CGAL_CDT_3_dependencies) create_single_source_cgal_program( "cdt_test_insert_constrained_edge_from_OFF_file.cpp") -target_link_libraries(cdt_test_insert_constrained_edge_from_OFF_file PRIVATE CDT_3_dependencies) +target_link_libraries(cdt_test_insert_constrained_edge_from_OFF_file PRIVATE CGAL_CDT_3_dependencies) create_single_source_cgal_program( "cdt_3_from_off.cpp") -target_link_libraries(cdt_3_from_off PRIVATE CDT_3_dependencies) +target_link_libraries(cdt_3_from_off PRIVATE CGAL_CDT_3_dependencies CGAL_CDT_3_CLI11) create_single_source_cgal_program( "cdt_3_from_off_with_Epeck.cpp") -target_link_libraries(cdt_3_from_off_with_Epeck PRIVATE CDT_3_dependencies) +target_link_libraries(cdt_3_from_off_with_Epeck PRIVATE CGAL_CDT_3_dependencies CGAL_CDT_3_CLI11) create_single_source_cgal_program( "snap_and_cdt3.cpp") add_executable(test_CDT_3_insert_constrained_edge_from_EDG_file cdt_test_insert_constrained_edge_from_EDG_file.cpp) -target_link_libraries(test_CDT_3_insert_constrained_edge_from_EDG_file PRIVATE CDT_3_dependencies) +target_link_libraries(test_CDT_3_insert_constrained_edge_from_EDG_file PRIVATE CGAL_CDT_3_dependencies) target_compile_definitions(test_CDT_3_insert_constrained_edge_from_EDG_file PUBLIC CGAL_TEST_CDT_3_USE_CDT) cgal_add_test(test_CDT_3_insert_constrained_edge_from_EDG_file) add_executable(test_CDT_3_insert_constrained_edge_from_OFF_file cdt_test_insert_constrained_edge_from_OFF_file.cpp) -target_link_libraries(test_CDT_3_insert_constrained_edge_from_OFF_file PRIVATE CDT_3_dependencies) +target_link_libraries(test_CDT_3_insert_constrained_edge_from_OFF_file PRIVATE CGAL_CDT_3_dependencies) target_compile_definitions(test_CDT_3_insert_constrained_edge_from_OFF_file PUBLIC CGAL_TEST_CDT_3_USE_CDT) cgal_add_test(test_CDT_3_insert_constrained_edge_from_OFF_file) @@ -93,6 +102,29 @@ function(CGAL_add_cdt3_from_local_off_test data_name) CGAL_add_cdt3_from_off_test_aux(${data_name} ${CMAKE_CURRENT_SOURCE_DIR}/data ${ARGN}) endfunction() +CGAL_add_cdt3_from_local_off_test(bug2 OPTIONS --read-mesh-with-operator) +CGAL_add_cdt3_from_local_off_test(bug5 OPTIONS --read-mesh-with-operator) +CGAL_add_cdt3_from_local_off_test(bug6 OPTIONS --read-mesh-with-operator) +CGAL_add_cdt3_from_local_off_test(bug-move-vertex-1 OPTIONS --read-mesh-with-operator) +CGAL_add_cdt3_from_local_off_test(bug-move-vertex-2 OPTIONS --read-mesh-with-operator) +CGAL_add_cdt3_from_local_off_test(bug-move-vertex-3 OPTIONS --read-mesh-with-operator) +CGAL_add_cdt3_from_local_off_test(bug-move-vertex-4 OPTIONS --read-mesh-with-operator) +CGAL_add_cdt3_from_local_off_test(bug-move-vertex-5 OPTIONS --read-mesh-with-operator) +CGAL_add_cdt3_from_local_off_test(bug-move-vertex-6 OPTIONS --read-mesh-with-operator) +CGAL_add_cdt3_from_local_off_test(bug-move-vertex-7 OPTIONS --read-mesh-with-operator) +CGAL_add_cdt3_from_local_off_test(bug-split-1 OPTIONS --read-mesh-with-operator) +CGAL_add_cdt3_from_local_off_test(bug-flip-1 OPTIONS --read-mesh-with-operator) +CGAL_add_cdt3_from_local_off_test(bug-flip-2 OPTIONS --read-mesh-with-operator) +CGAL_add_cdt3_from_local_off_test(bug-flip-3 OPTIONS --read-mesh-with-operator) +CGAL_add_cdt3_from_local_off_test(bug-flip-4 OPTIONS --read-mesh-with-operator) +CGAL_add_cdt3_from_local_off_test(bug7 OPTIONS --read-mesh-with-operator) +CGAL_add_cdt3_from_local_off_test(bug-segfault OPTIONS --read-mesh-with-operator) +CGAL_add_cdt3_from_local_off_test(bug8 OPTIONS --read-mesh-with-operator) +CGAL_add_cdt3_from_local_off_test(bug9 OPTIONS --read-mesh-with-operator) +CGAL_add_cdt3_from_local_off_test(bug12 OPTIONS --read-mesh-with-operator) +CGAL_add_cdt3_from_local_off_test(bug-fixed --move-Steiner-vertices-to-the-volume) +CGAL_add_cdt3_from_local_off_test(bug3-fixed --move-Steiner-vertices-to-the-volume) +CGAL_add_cdt3_from_local_off_test(bug4-fixed --move-Steiner-vertices-to-the-volume) CGAL_add_cdt3_from_local_off_test(cheese18) CGAL_add_cdt3_from_local_off_test(cheese23) CGAL_add_cdt3_from_local_off_test(cheese28) diff --git a/Constrained_triangulation_3/test/Constrained_triangulation_3/cdt_3_from_off.cpp b/Constrained_triangulation_3/test/Constrained_triangulation_3/cdt_3_from_off.cpp index 635890f6b54a..5ebb65c83273 100644 --- a/Constrained_triangulation_3/test/Constrained_triangulation_3/cdt_3_from_off.cpp +++ b/Constrained_triangulation_3/test/Constrained_triangulation_3/cdt_3_from_off.cpp @@ -1,5 +1,6 @@ #include +//#define CGAL_TETRAHEDRAL_REMESHING_VERBOSE 1 // #define CGAL_CDT_2_DEBUG_INTERSECTIONS 1 #include #include @@ -13,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -20,6 +22,7 @@ #include #include #include +#include #include #include @@ -32,6 +35,7 @@ #include #include +#include #include #include @@ -39,6 +43,7 @@ #include #include #include +#include #include #include #include @@ -48,8 +53,9 @@ #include #include #include -#include #include +#include +#include #include #include #include @@ -57,21 +63,19 @@ # include #endif -#if CGAL_CXX20 && __cpp_lib_concepts >= 201806L && __cpp_lib_ranges >= 201911L -# include +#if CGAL_USE_CLI11 +# include #endif -#if CGAL_CDT_3_USE_EPECK - -#include - -using K = CGAL::Exact_predicates_exact_constructions_kernel; - -#else // use Epick +#ifndef CGAL_CDT_3_USE_EPECK +# define CGAL_CDT_3_USE_EPECK 0 +#endif -using K = CGAL::Exact_predicates_inexact_constructions_kernel; +namespace CGAL::CDT_3::test::cdt_3_from_off { -#endif // use Epick +using K = std::conditional_t; using CDT = CGAL::Conforming_constrained_Delaunay_triangulation_3; using Point = K::Point_3; @@ -82,68 +86,21 @@ using vertex_descriptor = boost::graph_traits::vertex_descriptor; using edge_descriptor = boost::graph_traits::edge_descriptor; using face_descriptor = boost::graph_traits::face_descriptor; -void help(std::ostream& out) { - out << R"!!!!!( -Usage: cdt_3_from_off [options] input.off output.off - - input.off: input mesh - output.off: output mesh - - --merge-facets/--no-merge-facets: merge facets into patches (set by default) - --merge-facets-old: merge facets using the old method - --bisect: bisect failures - --vertex-vertex-epsilon : epsilon for vertex-vertex min distance (default: 1e-6) - --segment-vertex-epsilon : epsilon for segment-vertex min distance (default: 0) - --coplanar-polygon-max-angle : max angle for coplanar polygons (default: 1) - --coplanar-polygon-max-distance : max distance for coplanar polygons (default: 1e-6) - - --dump-patches-after-merge : dump patches after merging facets in PLY - --dump-surface-mesh-after-merge : dump surface mesh after merging facets in OFF - --dump-patches-borders-prefix : dump patches borders - --dump-after-conforming : dump mesh after conforming in OFF - - --no-repair: do not repair the mesh - --read-mesh-with-operator: read the mesh with operator>> - --reject-self-intersections: reject self-intersecting polygon soups - --no-is-valid: do not call is_valid checks - - --debug-Steiner-points: debug Steiner point insertion - --debug-Steiner-points-construction: debug Steiner point construction - --debug-input-faces: debug input faces - --debug-missing-regions: debug missing regions - --debug-regions: debug regions - --debug_copy_triangulation_into_hole: debug copy_triangulation_into_hole - --debug-validity: add is_valid checks after modifications to the TDS - --debug-finite-edges-map: debug the use of a hash map for finite edges - --debug-subconstraints-to-conform: debug subconstraints to conform - --debug-verbose-special-cases: debug verbose output for special cases - --debug-encroaching-vertices: debug encroaching vertices computation - --debug-conforming-validation: debug edge conforming validation - --debug-constraint-hierarchy: debug constraint hierarchy operations - --debug-geometric-errors: debug geometric error handling - --debug-polygon-insertion: debug polygon insertion process - --debug-restore-faces: debug face restoration process - - --use-finite-edges-map: use a hash map for finite edges (default: false) - --use-epeck-for-normals/--no-use-epeck-for-normals: use exact kernel for normal computations (default: false) - --use-epeck-for-Steiner-points/--no-use-epeck-for-Steiner-points: use exact kernel for Steiner point computations (default: false) - - --verbose/-V: verbose (can be used several times) - --quiet: do not print anything - --help/-h: print this help -)!!!!!"; -} +template +auto milliseconds(std::chrono::duration duration) { + return std::chrono::duration_cast(duration).count(); +}; -[[noreturn]] void error(std::string_view message, std::string_view extra = "") { - std::cerr << "Error: " << message << extra << '\n'; - help(std::cerr); - std::exit(EXIT_FAILURE); -} +template +auto milliseconds_since(std::chrono::time_point start_time) { + return milliseconds(Clock::now() - start_time); +}; + +using clock = std::chrono::high_resolution_clock; struct CDT_options { int verbose_level = 0; - bool need_help = false; bool quiet = false; bool merge_facets = true; bool merge_facets_old_method = false; @@ -152,8 +109,11 @@ struct CDT_options bool read_mesh_with_operator = false; bool debug_Steiner_points = false; bool debug_Steiner_points_construction = false; + unsigned debug_move_Steiner_vertices = 0; bool debug_input_faces = false; bool debug_missing_regions = false; + bool debug_missing_triangles = false; + bool debug_flips = false; bool debug_regions = false; bool debug_copy_triangulation_into_hole = false; bool debug_validity = false; @@ -167,6 +127,14 @@ struct CDT_options bool debug_polygon_insertion = false; bool debug_restore_faces = false; bool use_finite_edges_map = false; + bool use_flips_to_recover_segments = +#ifdef CGAL_CT3_FLIP_BEFORE_INSERTING_STEINER_POINTS + true; +#else + false; +#endif + bool move_Steiner_vertices_to_the_volume = false; + bool allow_moving_Steiner_vertices_to_create_negative_tets = true; bool use_epeck_for_normals = false; bool use_epeck_for_Steiner_points = false; bool call_is_valid = true; @@ -186,116 +154,197 @@ struct CDT_options }; CDT_options::CDT_options(int argc, char* argv[]) { - const std::vector args(argv + 1, argv + argc); - int positional = 0; - - using namespace std::literals::string_view_literals; - for (auto it = args.begin(); it != args.end(); ++it) { - auto get_next_arg_or_error_out = [&it, &args]() -> std::string { - if(it + 1 == args.end()) { - error("extra argument required after "sv, *it); +#if CGAL_USE_CLI11 + CLI::App app{"Build and process a constrained Delaunay triangulation from an OFF mesh"}; + app.set_help_flag("-h,--help", "print this help"); + app.allow_extras(false); + + app.add_flag("-V,--verbose", verbose_level, + "verbose (can be used several times)") + ->multi_option_policy(CLI::MultiOptionPolicy::Sum); + + app.add_flag("--quiet", quiet, "do not print anything"); + + app.add_flag("--merge-facets,!--no-merge-facets", merge_facets, + "merge facets into patches"); + app.add_flag("--merge-facets-old", merge_facets_old_method, + "merge facets using the old method"); + app.add_flag("--bisect", bisect_failures, "bisect failures"); + app.add_flag("--reject-self-intersections", reject_self_intersections, + "reject self-intersecting polygon soups"); + app.add_flag("--read-mesh-with-operator", read_mesh_with_operator, + "read the mesh with operator>>"); + app.add_flag("--repair,!--no-repair", repair_mesh, + "repair the mesh while reading polygon soup"); + app.add_flag("--call-is-valid,!--no-is-valid", call_is_valid, + "call is_valid checks"); + + app.add_option("--vertex-vertex-epsilon", vertex_vertex_epsilon, + "epsilon for vertex-vertex min distance"); + app.add_option("--segment-vertex-epsilon", segment_vertex_epsilon, + "epsilon for segment-vertex min distance"); + app.add_option("--coplanar-polygon-max-angle", coplanar_polygon_max_angle, + "max angle for coplanar polygons"); + app.add_option("--coplanar-polygon-max-distance", coplanar_polygon_max_distance, + "max distance for coplanar polygons"); + + app.add_option("--dump-patches-after-merge", dump_patches_after_merge_filename, + "dump patches after merging facets in PLY")->option_text("FILENAME"); + app.add_option("--dump-surface-mesh-after-merge", dump_surface_mesh_after_merge_filename, + "dump surface mesh after merging facets in OFF")->option_text("FILENAME"); + app.add_option("--dump-patches-borders-prefix", dump_patches_borders_prefix, + "dump patches borders")->option_text("PREFIX"); + app.add_option("--dump-after-conforming", dump_after_conforming_filename, + "dump mesh after conforming in OFF")->option_text("FILENAME"); + + app.add_flag("--debug-Steiner-points", debug_Steiner_points, + "debug Steiner point insertion"); + app.add_flag("--debug-Steiner-points-construction", debug_Steiner_points_construction, + "debug Steiner point construction"); + auto debug_move_Steiner_vertices_option = + app.add_option("--debug-move-Steiner-vertices-to-the-volume", debug_move_Steiner_vertices, + "debug moving Steiner vertices to the volume (level 0..3)") + ->check(CLI::Range(0, 3)) + ->expected(0, 1); + app.add_flag("--debug-input-faces", debug_input_faces, "debug input faces"); + app.add_flag("--debug-missing-regions", debug_missing_regions, "debug missing regions"); + app.add_flag("--debug-missing-triangles", debug_missing_triangles, "debug missing triangles"); + app.add_flag("--debug-flips", debug_flips, "debug flips"); + app.add_flag("--debug-regions", debug_regions, "debug regions"); + app.add_flag("--debug_copy_triangulation_into_hole", debug_copy_triangulation_into_hole, + "debug copy_triangulation_into_hole"); + app.add_flag("--debug-validity", debug_validity, + "add is_valid checks after modifications to the TDS"); + app.add_flag("--debug-finite-edges-map", debug_finite_edges_map, + "debug the use of a hash map for finite edges"); + app.add_flag("--debug-subconstraints-to-conform", debug_subconstraints_to_conform, + "debug subconstraints to conform"); + app.add_flag("--debug-verbose-special-cases", debug_verbose_special_cases, + "debug verbose output for special cases"); + app.add_flag("--debug-encroaching-vertices", debug_encroaching_vertices, + "debug encroaching vertices computation"); + app.add_flag("--debug-conforming-validation", debug_conforming_validation, + "debug edge conforming validation"); + app.add_flag("--debug-constraint-hierarchy", debug_constraint_hierarchy, + "debug constraint hierarchy operations"); + app.add_flag("--debug-geometric-errors", debug_geometric_errors, + "debug geometric error handling"); + app.add_flag("--debug-polygon-insertion", debug_polygon_insertion, + "debug polygon insertion process"); + app.add_flag("--debug-restore-faces", debug_restore_faces, + "debug face restoration process"); + + app.add_flag("--use-finite-edges-map", use_finite_edges_map, + "use a hash map for finite edges"); + app.add_flag("--use-flips-to-recover-segments", use_flips_to_recover_segments, + "use flips to recover constrained segments"); + app.add_flag("--move-Steiner-vertices-to-the-volume,!--no-move-Steiner-vertices-to-the-volume", + move_Steiner_vertices_to_the_volume, + "move Steiner vertices to the volume"); + app.add_flag("--allow-moving-Steiner-vertices-to-create-negative-tets", + allow_moving_Steiner_vertices_to_create_negative_tets, + "allow moving Steiner vertices to create negative volume tetrahedra"); + app.add_flag("--use-epeck-for-normals,!--no-use-epeck-for-normals", use_epeck_for_normals, + "use exact kernel for normal computations"); + app.add_flag("--use-epeck-for-Steiner-points,!--no-use-epeck-for-Steiner-points", + use_epeck_for_Steiner_points, + "use exact kernel for Steiner point computations"); + + app.add_option("--input,input_mesh", input_filename, "input mesh")->option_text("INPUT_FILENAME"); + app.add_option("--output,output_mesh", output_filename, "output mesh")->option_text("FILENAME"); + + auto quote_colon = [](std::string_view s) { + auto nb_colons = std::count(s.begin(), s.end(), ':'); + std::string result; + result.reserve(s.size() + nb_colons); // reserve space for the extra backslashes + for(char c : s) { + if(c == ':') { + result.push_back('\\'); + result.push_back(':'); + } else { + result.push_back(c); } - return std::string(*++it); - }; - std::string_view arg = *it; - if(arg == "--merge-facets"sv) { - merge_facets = true; - } else if(arg == "--no-merge-facets"sv) { - merge_facets = false; - } else if(arg == "--reject-self-intersections"sv) { - reject_self_intersections = true; - } else if(arg == "--no-repair"sv) { - repair_mesh = false; - } else if(arg == "--read-mesh-with-operator"sv) { - read_mesh_with_operator = true; - } else if(arg == "--merge-facets-old"sv) { - merge_facets = true; - merge_facets_old_method = true; - } else if(arg == "--bisect"sv) { - bisect_failures = true; - } else if(arg == "--dump-patches-after-merge"sv) { - dump_patches_after_merge_filename = get_next_arg_or_error_out(); - } else if(arg == "--dump-patches-borders-prefix"sv) { - dump_patches_borders_prefix = get_next_arg_or_error_out(); - } else if(arg == "--dump-surface-mesh-after-merge"sv) { - dump_surface_mesh_after_merge_filename = get_next_arg_or_error_out(); - } else if(arg == "--dump-after-conforming"sv) { - dump_after_conforming_filename = get_next_arg_or_error_out(); - } else if(arg == "--vertex-vertex-epsilon"sv) { - vertex_vertex_epsilon = std::stod(get_next_arg_or_error_out()); - } else if(arg == "--segment-vertex-epsilon"sv) { - segment_vertex_epsilon = std::stod(get_next_arg_or_error_out()); - } else if(arg == "--coplanar-polygon-max-angle"sv) { - coplanar_polygon_max_angle = std::stod(get_next_arg_or_error_out()); - } else if(arg == "--coplanar-polygon-max-distance"sv) { - coplanar_polygon_max_distance = std::stod(get_next_arg_or_error_out()); - } else if(arg == "--quiet"sv) { - quiet = true; - } else if(arg == "--no-is-valid"sv) { - call_is_valid = false; - } else if(arg == "--debug-Steiner-points"sv) { - debug_Steiner_points = true; - } else if(arg == "--debug-Steiner-points-construction"sv) { - debug_Steiner_points_construction = true; - } else if(arg == "--debug-input-faces"sv) { - debug_input_faces = true; - } else if(arg == "--debug-missing-regions"sv) { - debug_missing_regions = true; - } else if(arg == "--debug-regions"sv) { - debug_regions = true; - } else if(arg == "--debug_copy_triangulation_into_hole"sv) { - debug_copy_triangulation_into_hole = true; - } else if(arg == "--debug-validity"sv) { - debug_validity = true; - } else if(arg == "--debug-finite-edges-map"sv) { - debug_finite_edges_map = true; - } else if(arg == "--debug-subconstraints-to-conform"sv) { - debug_subconstraints_to_conform = true; - } else if(arg == "--debug-verbose-special-cases"sv) { - debug_verbose_special_cases = true; - } else if(arg == "--debug-encroaching-vertices"sv) { - debug_encroaching_vertices = true; - } else if(arg == "--debug-conforming-validation"sv) { - debug_conforming_validation = true; - } else if(arg == "--debug-constraint-hierarchy"sv) { - debug_constraint_hierarchy = true; - } else if(arg == "--debug-geometric-errors"sv) { - debug_geometric_errors = true; - } else if(arg == "--debug-polygon-insertion"sv) { - debug_polygon_insertion = true; - } else if(arg == "--debug-restore-faces"sv) { - debug_restore_faces = true; - } else if(arg == "--use-finite-edges-map"sv) { - use_finite_edges_map = true; - } else if(arg == "--no-use-epeck-for-normals"sv) { - use_epeck_for_normals = false; - } else if(arg == "--no-use-epeck-for-Steiner-points"sv) { - use_epeck_for_Steiner_points = false; - } else if(arg == "--use-epeck-for-normals"sv) { - use_epeck_for_normals = true; - } else if(arg == "--use-epeck-for-Steiner-points"sv) { - use_epeck_for_Steiner_points = true; - } else if(arg == "--verbose"sv || arg == "-V"sv) { - ++verbose_level; - } else if(arg == "--help"sv || arg == "-h"sv) { - need_help = true; - } else if(arg[0] == '-') { - error("unknown option "sv, arg); + } + return result; + }; + + auto optspec = [&,positional=0](const CLI::Option* opt, std::string_view name = "") mutable { + std::ostringstream oss; + oss << " '"; + if(name.empty()) { + oss << opt->get_name(opt->get_positional()); } else { - switch(positional) { - case 0: - input_filename = arg; - ++positional; - break; - case 1: - output_filename = arg; - ++positional; - break; - default: - error("too many arguments"sv); + if(name[0] == '-') { + oss << name; + } + else { + oss << ++positional; + } + if(name[0] == '-' && opt->get_expected() > 0) { + oss << "=-"; + } + if(!opt->get_option_text().empty()) { + oss << "::" << quote_colon(opt->get_description()) << ":_files"; + } else { + if(opt->has_description()) { + oss << "[" << quote_colon(opt->get_description()) << "]"; + } + } + } + oss << "'"; + return oss.str(); + }; + + app.add_flag_callback("--completion",[&]() { + std::cout << +R"(#compdef _cdt_3_from_off cdt_3_from_off + +_cdt_3_from_off() { + _arguments \ +)"; + for(const auto* opt : app.get_options()) { + if(opt->get_group().empty()) continue; + if(opt->get_positional()) { + std::cout << " " << optspec(opt, opt->get_name(true)); + } + std::string all_names = opt->get_name(false, true, true); + for(std::string::size_type prev = 0, pos = all_names.find(',');;) + { + const auto name = std::string_view(all_names.data() + prev, + (std::min)(pos, all_names.size()) - prev); + if(!name.empty() && name.front() == '-') { + std::cout << " " << optspec(opt, name); + } + if(pos == std::string::npos) break; + prev = pos + 1; + pos = all_names.find(',', prev); } + std::cout << "\\\n"; } + std::cout << "\n}\n"; + std::exit(0); + })->group(""); + + for(auto* option : app.get_options()) { + option->always_capture_default(true); + } + + app.get_formatter()->enable_default_flag_values(true); + + try { + app.parse(argc, argv); + } catch(const CLI::ParseError& e) { + std::exit(app.exit(e)); + } + + if(*debug_move_Steiner_vertices_option && debug_move_Steiner_vertices == 0) { + debug_move_Steiner_vertices = 1; + } + + if(merge_facets_old_method) { + merge_facets = true; } +#endif // CGAL_USE_CLI11 } CGAL::CDT_3::Debug_options cdt_debug_options(const CDT_options& options) { @@ -304,6 +353,8 @@ CGAL::CDT_3::Debug_options cdt_debug_options(const CDT_options& options) { cdt_debug.Steiner_points_construction(options.debug_Steiner_points_construction); cdt_debug.input_faces(options.debug_input_faces); cdt_debug.missing_region(options.verbose_level > 1 || options.debug_missing_regions); + cdt_debug.missing_triangles(options.debug_missing_triangles); + cdt_debug.flips(options.debug_flips); cdt_debug.regions(options.debug_regions); cdt_debug.validity(options.debug_validity); cdt_debug.finite_edges_map(options.debug_finite_edges_map); @@ -311,12 +362,15 @@ CGAL::CDT_3::Debug_options cdt_debug_options(const CDT_options& options) { cdt_debug.verbose_special_cases(options.debug_verbose_special_cases); cdt_debug.encroaching_vertices(options.debug_encroaching_vertices); cdt_debug.conforming_validation(options.debug_conforming_validation); + cdt_debug.move_Steiner_vertices(options.debug_move_Steiner_vertices); + cdt_debug.move_Steiner_vertices_allow_negative_tets(options.allow_moving_Steiner_vertices_to_create_negative_tets); cdt_debug.constraint_hierarchy(options.debug_constraint_hierarchy); cdt_debug.geometric_errors(options.debug_geometric_errors); cdt_debug.polygon_insertion(options.debug_polygon_insertion); cdt_debug.restore_faces(options.debug_restore_faces); cdt_debug.copy_triangulation_into_hole(options.debug_copy_triangulation_into_hole); cdt_debug.use_finite_edges_map(options.use_finite_edges_map); + cdt_debug.use_flips_to_recover_segments(options.use_flips_to_recover_segments); cdt_debug.display_statistics(!options.quiet); cdt_debug.use_epeck_for_normals(options.use_epeck_for_normals); cdt_debug.use_epeck_for_Steiner_points(options.use_epeck_for_Steiner_points); @@ -348,8 +402,14 @@ std::function create_output_finalizer(const CDT& cdt, const CDT_options& return [&cdt, &options]() { auto _ = CGAL::CDT_3_OUTPUT_TASK_guard(); { - auto dump_tets_to_medit = [](std::string fname, + if(std::uncaught_exceptions() > 0) { + std::cerr << "create_output_finalizer: an exception is being thrown, the triangulation may be left in an " + "invalid state.\n"; + return; + } + auto dump_to_medit = [](std::string fname, const std::vector &points, + const std::vector> &indexed_triangles, const std::vector> &indexed_tetra, const std::vector &cell_ids) { @@ -359,19 +419,23 @@ std::function create_output_finalizer(const CDT& cdt, const CDT_options& out << points.size() << "\n"; for (const K::Point_3& p : points) out << p << " 0\n"; - out << "Triangles\n0\nTetrahedra\n"; + out << "Triangles\n" << indexed_triangles.size() << "\n"; + for (const auto& tri : indexed_triangles) + out << tri[0]+1 << " " << tri[1]+1 << " " << tri[2]+1 << " " << tri[3] << "\n"; + out << "Tetrahedra\n"; out << indexed_tetra.size() << "\n"; for (std::size_t k=0;k cells_map; + std::unordered_map cells_map; for(auto ch : tr.all_cell_handles()) { cells_map[ch] = 1; @@ -396,39 +460,62 @@ std::function create_output_finalizer(const CDT& cdt, const CDT_options& } } + const bool export_all_the_bbox = + std::all_of(cells_map.begin(), cells_map.end(), [](const auto& kv) { return kv.second == 0; }); + if (export_all_the_bbox) { + for(auto ch : tr.finite_cell_handles()) + { + cells_map[ch] = 1; + } + } + std::vector points(cdt.number_of_vertices()); + std::size_t idx = 0; for(auto v: cdt.finite_vertex_handles()) { - points.at(v->time_stamp() -1) = v->point(); + // renumber the vertices: there might be holes in the numbering due to removed vertices + v->set_time_stamp(++idx); + points.at(idx - 1) = v->point(); + } + std::vector> indexed_triangles; + std::size_t max_polygon_id = 0; + for(auto f : cdt.constrained_facets()) { + const auto verts = tr.vertices(f); + const auto polygon_id = static_cast(cdt.face_constraint_index(f)); + indexed_triangles.push_back({verts[0]->time_stamp() - 1, + verts[1]->time_stamp() - 1, + verts[2]->time_stamp() - 1, + polygon_id}); + if (polygon_id > max_polygon_id) { + max_polygon_id = polygon_id; + } + } + if(export_all_the_bbox) { + auto inf_v = tr.infinite_vertex(); + tr.incident_cells(inf_v, boost::make_function_output_iterator([&](Tr::Cell_handle ch) { + auto facet_index = ch->index(inf_v); + const auto verts = tr.vertices(Tr::Facet{ch, facet_index}); + indexed_triangles.push_back({verts[0]->time_stamp() - 1, + verts[1]->time_stamp() - 1, + verts[2]->time_stamp() - 1, + max_polygon_id + 1 /*a new polygon id for the bbox*/}); + })); } std::vector> indexed_tetra; indexed_tetra.reserve(cdt.number_of_cells()); for(auto ch: cdt.finite_cell_handles()) { if(cells_map[ch] > 0) { - indexed_tetra.push_back({ch->vertex(0)->time_stamp() -1, - ch->vertex(1)->time_stamp() -1, - ch->vertex(2)->time_stamp() -1, - ch->vertex(3)->time_stamp() -1}); + indexed_tetra.push_back({ch->vertex(0)->time_stamp() - 1, + ch->vertex(1)->time_stamp() - 1, + ch->vertex(2)->time_stamp() - 1, + ch->vertex(3)->time_stamp() - 1}); } } - std::vector cell_idsl(indexed_tetra.size(), 1); - dump_tets_to_medit(options.output_filename + ".mesh", points, indexed_tetra, cell_idsl); + std::vector cell_ids(indexed_tetra.size(), 1); + dump_to_medit(options.output_filename + ".mesh", points, indexed_triangles, indexed_tetra, cell_ids); + cdt.dump_constrained_facets_to_off(options.output_filename); } { - std::ofstream dump(options.output_filename); - dump.precision(17); -#if CGAL_CXX20 && __cpp_lib_concepts >= 201806L && __cpp_lib_ranges >= 201911L - cdt.write_facets(dump, cdt.triangulation(), std::views::filter(cdt.finite_facets(), [&](auto f) { - return cdt.is_facet_constrained(f); - })); -#else - auto is_facet_constrained = [&](auto f) { return cdt.is_facet_constrained(f); }; - const auto& tr = cdt.triangulation(); - auto it_begin = tr.finite_facets_begin(); - auto it_end = tr.finite_facets_end(); - auto filtered_it_begin = boost::make_filter_iterator(is_facet_constrained,it_begin, it_end); - auto filtered_it_end = boost::make_filter_iterator(is_facet_constrained,it_end, it_end); - cdt.write_facets(dump, tr, CGAL::make_range(filtered_it_begin, filtered_it_end)); -#endif + cdt.save_binary_file(options.output_filename + ".binary.cgal"); } }; } @@ -581,7 +668,7 @@ Borders_of_patches maybe_merge_facets( { auto _ = CGAL::CDT_3_MERGE_FACETS_TASK_guard(); - auto start_time = std::chrono::high_resolution_clock::now(); + auto start_time = clock::now(); if(options.merge_facets_old_method) { number_of_patches = merge_facets_old_method(mesh, pmaps, number_of_patches); @@ -592,9 +679,8 @@ Borders_of_patches maybe_merge_facets( } patch_edges = extract_patch_edges(mesh, pmaps, number_of_patches); if (!options.quiet) { - auto timing = std::chrono::high_resolution_clock::now() - start_time; std::cout << "[timings] found " << number_of_patches << " patches in " - << std::chrono::duration_cast(timing).count() << " ms\n"; + << milliseconds_since(start_time) << " ms\n"; } } @@ -701,16 +787,15 @@ int go(Mesh mesh, CDT_options options) { // Build CDT directly from the polygon mesh using the official API CDT cdt; auto output_on_exit_scope_guard = CGAL::make_scope_exit(create_output_finalizer(cdt, options)); - auto build_start = std::chrono::high_resolution_clock::now(); + auto build_start = clock::now(); cdt = CDT{std::invoke([&]() { auto np = CGAL::parameters::debug(cdt_debug).visitor(std::ref(dump_mesh_with_steiner_points)); return options.merge_facets ? CDT(mesh, np.plc_face_id(pmaps.patch_id_map)) : CDT(mesh, np); })}; if(!options.quiet) { - auto timing = std::chrono::high_resolution_clock::now() - build_start; std::cout << "[timings] built CDT from mesh in " - << std::chrono::duration_cast(timing).count() << " ms\n"; - std::cout << "Number of vertices: " << cdt.number_of_vertices() << "\n\n"; + << milliseconds_since(build_start) << " ms\n"; + std::cout << cdt.statistics() << "\n"; } // Validation: check conforming status and validity @@ -720,6 +805,21 @@ int go(Mesh mesh, CDT_options options) { CGAL_assertion(!options.call_is_valid || cdt.is_conforming()); } + // Move Steiner vertices to the volume if requested + if(options.move_Steiner_vertices_to_the_volume) + { +// cdt.remove_bbox_points(); + + auto move_vertices_guard = CGAL::CDT_3_MOVE_STEINER_VERTICES_TASK_guard(); + cdt.move_Steiner_vertices_to_the_volume(); + if(!options.quiet) { + std::cout << "[timings] moved Steiner vertices to the volume in " + << move_vertices_guard.time_ms() << " ms\n"; + std::cout << cdt.statistics() << "\n"; + } + CGAL::internal::smooth_Steiner_vertices_in_volume(cdt, bbox_max_span, true); + } + return EXIT_SUCCESS; } @@ -778,19 +878,18 @@ int bisect_errors(Mesh mesh, CDT_options options) { return CGAL::bisect_failures(mesh, get_size, simplify, run_test, save_mesh); } +} // end of namespaces CGAL::CDT_3::test::cdt_3_from_off + int main(int argc, char* argv[]) { + using namespace CGAL::CDT_3::test::cdt_3_from_off; std::cerr.precision(17); std::cout.precision(17); CGAL::get_default_random() = CGAL::Random(42); CDT_options options(argc, argv); - if(options.need_help) { - help(std::cout); - return 0; - } CGAL::CDT_3_read_polygon_mesh_output read_mesh_result; - auto start_time = std::chrono::high_resolution_clock::now(); + auto start_time = clock::now(); { auto _ = CGAL::CDT_3_READ_INPUT_TASK_guard(); @@ -817,8 +916,9 @@ int main(int argc, char* argv[]) { return EXIT_FAILURE; } if(!options.quiet) { - std::cout << "[timings] read mesh in " << std::chrono::duration_cast( - std::chrono::high_resolution_clock::now() - start_time).count() << " ms\n"; + std::cout << "[timings] read mesh \"" << options.input_filename << "\" in " + << milliseconds_since(start_time) + << " ms\n"; std::cout << "Number of vertices: " << read_mesh_result.polygon_mesh->number_of_vertices() << '\n'; std::cout << "Number of edges: " << read_mesh_result.polygon_mesh->number_of_edges() << '\n'; std::cout << "Number of faces: " << read_mesh_result.polygon_mesh->number_of_faces() << "\n\n"; @@ -849,8 +949,7 @@ int main(int argc, char* argv[]) { auto exit_code = go(std::move(*read_mesh_result.polygon_mesh), options); if(!options.quiet) { - std::cout << "[timings] total time: " << std::chrono::duration_cast( - std::chrono::high_resolution_clock::now() - start_time).count() << " ms\n"; + std::cout << "[timings] total time: " << milliseconds_since(start_time) << " ms\n"; if(exit_code != 0) std::cout << "ERROR with exit code " << exit_code << '\n'; } return exit_code; diff --git a/Constrained_triangulation_3/test/Constrained_triangulation_3/data/bug-fixed.off b/Constrained_triangulation_3/test/Constrained_triangulation_3/data/bug-fixed.off new file mode 100644 index 000000000000..12ce52dd9a52 --- /dev/null +++ b/Constrained_triangulation_3/test/Constrained_triangulation_3/data/bug-fixed.off @@ -0,0 +1,32 @@ +OFF +23 5 0 + +10 10 10 +-6.0240600000000004 -10.012 4.0160400000000003 +6.0144299999999999 -2.0024000000000002 4.00962 +-6.0072000000000001 -2.0024000000000002 4.00962 +-6.0240900000000002 -10.0321 -10.0321 +-6.0192600000000001 -6.0192600000000001 10.0321 +-6.0240900000000002 -6.0240900000000002 -10.0321 +-6.0192600000000001 -6.0192600000000001 -6.0192600000000001 +-6.0240900000000002 -6.0192699999999997 -10.0321 +10.019399999999999 -2.00387 0.33785900000000002 +10.0219 -0.92307300000000003 -0.92307300000000003 +-6.0240499999999999 -9.9999400000000005 10.0321 +6.0130600000000003 -0.86255199999999999 4.0087099999999998 +6.0144299999999999 -2.0018699999999998 5.3379099999999999 +-6.0130499999999998 -0.85634999999999994 4.0087000000000002 +-6.01823 -5.1587800000000001 4.0121500000000001 +-6.0072000000000001 -5.1587699999999996 4.0121500000000001 +-6.0192600000000001 -6.0192600000000001 4.0128399999999997 +-6.0116300000000003 -2.0038800000000001 0.33143699999999998 +10.0093 -2.0018699999999998 5.3355100000000002 +10 6 10 +10.013999999999999 0 2.9999899999999999 +-6.0192600000000001 -6.0192600000000001 5.0160499999999999 +7 1 17 22 15 14 5 11 +4 4 6 8 7 +6 15 16 3 2 12 14 +6 18 9 19 13 2 3 +6 20 21 19 9 10 0 + diff --git a/Constrained_triangulation_3/test/Constrained_triangulation_3/data/bug-flip-1.off b/Constrained_triangulation_3/test/Constrained_triangulation_3/data/bug-flip-1.off new file mode 100644 index 000000000000..3b4f674dbe51 --- /dev/null +++ b/Constrained_triangulation_3/test/Constrained_triangulation_3/data/bug-flip-1.off @@ -0,0 +1,53 @@ +OFF +35 14 0 + +0.0323030017 0.040972001899999999 -0.0323030017 +0.031844001300000001 0.040160000299999998 -0.018155999499999999 +0.031725998999999998 0.0398919992 -0.031725998999999998 +0.031470999100000001 0.039147999099999997 -0.018528999800000001 +0.031369999099999997 0.038718998400000003 -0.031369999099999997 +0.0312799998 0.038113001700000003 -0.0312799998 +0.031277999299999998 0.038086000799999999 -0.018721999600000001 +0.031268000599999998 0.037978000900000003 -0.026802999899999999 +0.031263001300000003 0.037099000100000001 -0.029234999800000001 +0.031252000500000002 0.037645999300000003 -0.028056999700000002 +0.03125 0.037500001499999998 -0.03125 +0.018750000700000002 0.037500001499999998 -0.03125 +0.018747 0.037686999899999997 -0.0279399995 +0.018742000700000001 0.037188000999999998 -0.029075000399999999 +0.0187309999 0.037987999600000003 -0.026743000400000001 +0.018721999600000001 0.038086000799999999 -0.018721999600000001 +0.018721999600000001 0.038086000799999999 -0.025546999599999998 +0.018719999099999999 0.038113001700000003 -0.0312799998 +0.018719999099999999 0.036887001199999998 -0.0312799998 +0.0186730009 0.036520998899999997 -0.030092999299999999 +0.018629999800000002 0.038718998400000003 -0.031369999099999997 +0.018629999800000002 0.036281000799999998 -0.031369999099999997 +-0.050000000699999998 0.032086998200000001 -0.040624998500000002 +-0.050000000699999998 0.033080998799999997 -0.041919000400000003 +-0.050000000699999998 0.034375000699999998 -0.042913000999999999 +-0.050000000699999998 0.035881999900000003 -0.043536998299999997 +-0.050000000699999998 0.037500001499999998 -0.043749999300000002 +-0.042697001200000001 0.0323030017 -0.040972001899999999 +-0.042697001200000001 0.034028001099999997 -0.042697001200000001 +-0.041919000400000003 0.033080998799999997 -0.041919000400000003 +-0.043749999300000002 0.037500001499999998 -0.043749999300000002 +-0.043719999500000002 0.036887001199999998 -0.043719999500000002 +-0.043719999500000002 0.038113001700000003 -0.043719999500000002 +-0.043630000199999998 0.036281000799999998 -0.043630000199999998 +-0.043274000299999997 0.035108 -0.043274000299999997 +3 7 9 5 +3 9 8 10 +3 4 3 6 +3 0 1 2 +3 18 21 19 +3 11 18 13 +3 11 12 17 +3 14 16 17 +3 15 20 16 +3 30 32 26 +3 25 33 31 +3 34 24 28 +3 27 29 23 +3 27 23 22 + diff --git a/Constrained_triangulation_3/test/Constrained_triangulation_3/data/bug-flip-2.off b/Constrained_triangulation_3/test/Constrained_triangulation_3/data/bug-flip-2.off new file mode 100644 index 000000000000..5a281d99df15 --- /dev/null +++ b/Constrained_triangulation_3/test/Constrained_triangulation_3/data/bug-flip-2.off @@ -0,0 +1,11 @@ +OFF +5 2 0 + +0.018719999099999999 0.0312799998 -0.038113001700000003 +0.018719999099999999 0.018719999099999999 -0.038113001700000003 +0.018629999800000002 0.031369999099999997 -0.038718998400000003 +0.018629999800000002 0.018629999800000002 -0.038718998400000003 +0.018273999900000001 0.018273999900000001 -0.0398919992 +3 3 2 4 +3 1 0 3 + diff --git a/Constrained_triangulation_3/test/Constrained_triangulation_3/data/bug-flip-3.off b/Constrained_triangulation_3/test/Constrained_triangulation_3/data/bug-flip-3.off new file mode 100644 index 000000000000..481cbcaf4d7c --- /dev/null +++ b/Constrained_triangulation_3/test/Constrained_triangulation_3/data/bug-flip-3.off @@ -0,0 +1,172 @@ +OFF +116 52 0 + +0.031335677999999999 0.018755000099999999 0.038650944800000003 +0.050000000699999998 -0.037500001499999998 0.0050889999000000002 +0.050000000699999998 -0.043749000900000001 -0.0125890002 +0.050000000699999998 -0.050000000699999998 0.0050889999000000002 +0.050000000699999998 -0.050000000699999998 -0.0125890002 +0.048792999199999999 -0.043614000100000001 -0.0137949996 +0.0476359986 -0.043248001500000001 -0.0149529995 +0.046569999299999998 -0.042665999400000001 -0.016017999500000001 +0.045637998700000001 -0.041887998599999997 -0.016951000300000001 +0.044874001300000001 -0.0409450009 -0.0177149996 +0.044305998800000003 -0.039870999800000001 -0.0182830002 +0.043749999300000002 -0.037500001499999998 -0.0011609999999999999 +0.0436550006 -0.038587000199999999 -0.001256 +0.0433720015 -0.0396410003 -0.001539 +0.042909998400000003 -0.0406300016 -0.0020020000999999999 +0.042773000899999997 -0.040855001699999997 -0.019816 +0.042282000200000003 -0.041524000499999998 -0.0026289999999999998 +0.0420489982 -0.041786000099999998 -0.020540000900000001 +0.041510000800000002 -0.042293999300000003 -0.0034020001000000001 +0.041163999600000001 -0.042564000900000003 -0.0214249995 +0.040614001499999997 -0.042918998700000002 -0.0042969999 +0.040148001199999998 -0.043161999399999998 -0.022440999699999999 +0.039037000400000001 -0.043558001499999999 -0.0235510003 +0.037872999900000003 -0.043738998500000001 -0.0247159991 +0.032664000999999998 -0.041459001600000003 -0.029924999899999999 +0.032005999200000003 -0.040479999000000003 -0.0305819996 +0.031642001099999997 0.0189449992 0.039680000399999998 +0.031504001500000003 0.0184959993 0.039262998799999997 +0.031341999799999999 -0.050000000699999998 -0.0135690002 +0.031295001500000003 0.018704999199999999 0.0382449999 +0.031060000899999999 0.018609000399999999 0.038819000100000001 +0.0308020003 0.018459999899999999 0.039381999500000001 +0.0305819996 -0.040479999000000003 -0.032005999200000003 +0.029296999800000001 -0.042918998700000002 -0.015614000100000001 +0.028402000699999999 -0.042293999300000003 -0.0165100005 +0.027628999200000001 -0.041524000499999998 -0.0172819998 +0.027499999899999999 0.0062500000999999999 0.037500001499999998 +0.027499999899999999 -0.018750000700000002 0.037500001499999998 +0.027499999899999999 -0.03125 0.037500001499999998 +0.027499999899999999 -0.043749999300000002 0.037500001499999998 +0.027499999899999999 -0.050000000699999998 0.037500001499999998 +0.027001999299999999 -0.0406300016 -0.017909999900000001 +0.026538999800000001 -0.0396410003 -0.018371999300000001 +0.026256000599999999 -0.038587000199999999 -0.018655000299999999 +0.026161000100000002 -0.037500001499999998 -0.018750000700000002 +0.018750000700000002 0.0062500000999999999 0.037500001499999998 +0.018750000700000002 -0.0062500000999999999 0.037500001499999998 +0.018750000700000002 -0.018750000700000002 0.037500001499999998 +0.018750000700000002 -0.03125 0.037500001499999998 +0.018750000700000002 -0.037500001499999998 -0.026161000100000002 +0.018750000700000002 -0.043749999300000002 0.037500001499999998 +0.018750000700000002 -0.050000000699999998 0.037500001499999998 +0.018655000299999999 -0.038587000199999999 -0.026256000599999999 +0.018371999300000001 -0.0396410003 -0.026538999800000001 +0.017909999900000001 -0.0406300016 -0.027001999299999999 +0.0172819998 -0.041524000499999998 -0.027628999200000001 +0.0165100005 -0.042293999300000003 -0.028402000699999999 +0.015614000100000001 -0.042918998700000002 -0.029296999800000001 +0.0146239996 -0.043377999200000003 -0.0302869994 +0.0135690002 -0.043657999500000003 -0.031341999799999999 +0.0135690002 -0.050000000699999998 -0.031341999799999999 +0.0063419998999999999 -0.043657999500000003 -0.038568999600000001 +0.0062500000999999999 0.050000000699999998 0.037500001499999998 +0.0062500000999999999 0.043749999300000002 0.037500001499999998 +0.0062500000999999999 0.0042849997999999997 0.037500001499999998 +0.0062500000999999999 -0.0062500000999999999 0.037500001499999998 +0.0062500000999999999 -0.018750000700000002 0.037500001499999998 +0.0062500000999999999 -0.03125 0.037500001499999998 +0.0062500000999999999 -0.043749999300000002 0.037500001499999998 +0.0062500000999999999 -0.050000000699999998 0.037500001499999998 +0.0060800002000000004 0.03125 0.037500001499999998 +0.005287 -0.043377999200000003 -0.039624001800000003 +0.0042969999 -0.042918998700000002 -0.040614001499999997 +0.0034020001000000001 -0.042293999300000003 -0.041510000800000002 +0.0026289999999999998 -0.041524000499999998 -0.042282000200000003 +0.0024999999 0.050000000699999998 0.050000000699999998 +0.0024999999 0.050000000699999998 0.037500001499999998 +0.0024999999 0.043749999300000002 0.037500001499999998 +0.0024999999 0.043536998299999997 0.039117999399999999 +0.0024999999 0.042913000999999999 0.040624998500000002 +0.0024999999 0.041919000400000003 0.041919000400000003 +0.0024999999 0.040624998500000002 0.042913000999999999 +0.0024999999 0.032086998200000001 0.040624998500000002 +0.0024999999 0.031463000900000003 0.039117999399999999 +0.0024999999 0.03125 0.037500001499999998 +0.0024999999 0.029183000300000001 0.037500001499999998 +0.0024999999 0.0021200001 0.050000000699999998 +0.0024999999 0.0021200001 0.037500001499999998 +0.0024999999 -0.0062500000999999999 0.037500001499999998 +0.0024999999 -0.010882000399999999 0.043536998299999997 +0.0024999999 -0.0125000002 0.043749999300000002 +0.0024999999 -0.014117999900000001 0.043536998299999997 +0.0024999999 -0.015625 0.042913000999999999 +0.0024999999 -0.016919000100000001 0.041919000400000003 +0.0024999999 -0.017913000700000001 0.040624998500000002 +0.0024999999 -0.018536999799999999 0.039117999399999999 +0.0024999999 -0.018750000700000002 0.037500001499999998 +0.0024999999 -0.03125 0.037500001499999998 +0.0024999999 -0.031463000900000003 0.039117999399999999 +0.0024999999 -0.032086998200000001 0.040624998500000002 +0.0024999999 -0.033080998799999997 0.041919000400000003 +0.0024999999 -0.034375000699999998 0.042913000999999999 +0.0024999999 -0.035881999900000003 0.043536998299999997 +0.0024999999 -0.037500001499999998 0.043749999300000002 +0.0024999999 -0.039117999399999999 0.043536998299999997 +0.0024999999 -0.040624998500000002 0.042913000999999999 +0.0024999999 -0.041919000400000003 0.041919000400000003 +0.0024999999 -0.042913000999999999 0.040624998500000002 +0.0024999999 -0.043536998299999997 0.039117999399999999 +0.0024999999 -0.043749999300000002 0.037500001499999998 +0.0024999999 -0.050000000699999998 0.050000000699999998 +0.0024999999 -0.050000000699999998 0.037500001499999998 +-0.0050889999000000002 -0.037500001499999998 -0.050000000699999998 +-0.0050889999000000002 -0.050000000699999998 -0.050000000699999998 +0.031468503199999998 0.0188249983 0.038962498300000002 +0.031351000099999998 0.018776999799999999 0.0392495021 +3 10 15 9 +3 9 17 8 +3 19 7 8 +3 24 25 32 +3 23 4 22 +3 5 4 2 +3 21 22 6 +3 19 21 7 +3 113 71 61 +3 72 113 73 +3 112 74 113 +3 11 1 12 +3 14 13 1 +3 20 18 3 +3 16 1 3 +3 59 58 60 +3 33 28 57 +3 34 33 56 +3 55 54 35 +3 54 41 35 +3 42 53 43 +3 44 52 49 +3 85 83 82 +3 79 78 76 +3 75 81 80 +3 36 45 46 +3 37 48 38 +3 47 48 37 +3 40 39 50 +3 40 50 51 +3 68 111 69 +3 96 67 66 +3 65 64 87 +3 65 87 88 +3 70 84 85 +3 76 77 63 +3 76 63 62 +3 100 93 101 +3 106 111 107 +3 109 108 111 +3 86 90 89 +3 110 105 104 +3 90 110 103 +3 102 101 91 +3 101 92 91 +3 94 99 98 +3 96 98 97 +3 95 98 96 +3 0 27 29 +3 26 115 31 +3 0 30 115 +3 0 115 114 + diff --git a/Constrained_triangulation_3/test/Constrained_triangulation_3/data/bug-flip-4.off b/Constrained_triangulation_3/test/Constrained_triangulation_3/data/bug-flip-4.off new file mode 100644 index 000000000000..10b3673abd1f --- /dev/null +++ b/Constrained_triangulation_3/test/Constrained_triangulation_3/data/bug-flip-4.off @@ -0,0 +1,54 @@ +OFF +35 15 0 + +0.050000000699999998 0.039585001799999998 0.018392000299999999 +0.050000000699999998 0.038086000799999999 0.031277999299999998 +0.050000000699999998 0.038086000799999999 0.018721999600000001 +0.050000000699999998 0.0113570001 0.018644999700000001 +0.050000000699999998 0.0109219998 0.031452000100000002 +0.050000000699999998 0.0098919999000000002 0.018179999700000001 +0.050000000699999998 -0.010882000399999999 0.031463000900000003 +0.050000000699999998 -0.010882000399999999 0.018536999799999999 +0.050000000699999998 -0.0125000002 0.018750000700000002 +0.043731998699999997 0.037978000900000003 -0.026802999899999999 +0.043721999999999997 0.038086000799999999 -0.025546999599999998 +0.043719999500000002 0.038113001700000003 -0.0312799998 +0.033236999099999998 0.0307030007 -0.032930001600000001 +0.033236999099999998 0.0170699991 -0.032930001600000001 +0.033080998799999997 0.033080998799999997 -0.033080998799999997 +0.033080998799999997 0.016919000100000001 -0.033080998799999997 +0.0323030017 0.017697000899999999 -0.034028001099999997 +0.018629999800000002 0.031369999099999997 -0.038718998400000003 +0.018629999800000002 0.018629999800000002 -0.038718998400000003 +0.018273999900000001 0.031725998999999998 -0.035108 +0.018273999900000001 0.031725998999999998 -0.0398919992 +0.018273999900000001 0.018273999900000001 -0.035108 +0.018273999900000001 0.018273999900000001 -0.0398919992 +0.017697000899999999 0.0323030017 -0.034028001099999997 +0.017697000899999999 0.0323030017 -0.040972001899999999 +0.017697000899999999 0.017697000899999999 -0.034028001099999997 +0.017697000899999999 0.017697000899999999 -0.040972001899999999 +0.016919000100000001 0.033080998799999997 -0.033080998799999997 +0.016919000100000001 0.016919000100000001 -0.033080998799999997 +0.016919000100000001 0.016919000100000001 -0.041919000400000003 +0.015971999600000002 0.0323030017 -0.0323030017 +0.015971999600000002 0.017697000899999999 -0.0323030017 +0.013718999900000001 0.018629999800000002 -0.043630000199999998 +0.0131130004 0.0312799998 -0.043719999500000002 +0.0131130004 0.018719999099999999 -0.043719999500000002 +3 30 27 31 +3 27 23 28 +3 5 3 4 +3 16 14 15 +3 12 13 15 +3 23 21 25 +3 28 23 25 +3 19 21 23 +3 9 10 11 +3 0 1 2 +3 8 7 6 +3 32 33 34 +3 26 24 29 +3 20 26 22 +3 18 17 22 + diff --git a/Constrained_triangulation_3/test/Constrained_triangulation_3/data/bug-move-vertex-1.off b/Constrained_triangulation_3/test/Constrained_triangulation_3/data/bug-move-vertex-1.off new file mode 100644 index 000000000000..99f68ff91709 --- /dev/null +++ b/Constrained_triangulation_3/test/Constrained_triangulation_3/data/bug-move-vertex-1.off @@ -0,0 +1,19 @@ +OFF +12 3 0 + +6.0047800000000002 6.0240600000000004 -10.007999999999999 +6.0072099999999997 4.00481 4.00481 +6.0240600000000004 6.0240600000000004 -10.007999999999999 +6.0072099999999997 2.0024000000000002 4.0064099999999998 +6.0048000000000004 6.0048000000000004 6.0048000000000004 +10 10 -10 +5.9999900000000004 10.007999999999999 -9.9999800000000008 +6.0116199999999997 2.00387 0.336254 +6.0060099999999998 6.0048000000000004 5.0039999999999996 +10.007999999999999 5.9999900000000004 4.9999900000000004 +6.0240600000000004 6.0047800000000002 -10.007999999999999 +10.007999999999999 5.9999900000000004 -9.9999800000000008 +4 6 5 2 0 +4 8 10 11 9 +7 4 2 10 8 7 3 1 + diff --git a/Constrained_triangulation_3/test/Constrained_triangulation_3/data/bug-move-vertex-2.off b/Constrained_triangulation_3/test/Constrained_triangulation_3/data/bug-move-vertex-2.off new file mode 100644 index 000000000000..831612722189 --- /dev/null +++ b/Constrained_triangulation_3/test/Constrained_triangulation_3/data/bug-move-vertex-2.off @@ -0,0 +1,16 @@ +OFF +8 4 0 + +0.22012599999999999 3.9465400000000001e-10 -0.17452799999999999 +0.22254199999999999 -0.024537199999999999 -0.17452799999999999 +0.22969899999999999 -0.048132000000000001 -0.17452799999999999 +0.24132200000000001 -0.069877800000000004 -0.17452799999999999 +0.22012599999999999 1.99686e-10 0.18239 +0.22253899999999999 -0.0245212 0.18239 +0.24129200000000001 -0.069834099999999996 0.18239 +0.229686 -0.048100400000000001 0.18239 +3 1 0 4 +3 5 2 1 +3 7 2 5 +3 6 3 7 + diff --git a/Constrained_triangulation_3/test/Constrained_triangulation_3/data/bug-move-vertex-3.off b/Constrained_triangulation_3/test/Constrained_triangulation_3/data/bug-move-vertex-3.off new file mode 100644 index 000000000000..1b241375090d --- /dev/null +++ b/Constrained_triangulation_3/test/Constrained_triangulation_3/data/bug-move-vertex-3.off @@ -0,0 +1,16 @@ +OFF +8 4 0 + +0.050000000699999998 -0.037500001499999998 0.0050889999000000002 +0.050000000699999998 -0.050000000699999998 0.0050889999000000002 +0.042909998400000003 -0.0406300016 -0.0020020000999999999 +0.042282000200000003 -0.041524000499999998 -0.0026289999999999998 +0.041510000800000002 -0.042293999300000003 -0.0034020001000000001 +0.040614001499999997 -0.042918998700000002 -0.0042969999 +0.039624001800000003 -0.043377999200000003 -0.005287 +0.038568999600000001 -0.050000000699999998 -0.0063419998999999999 +3 2 0 3 +3 7 6 1 +3 6 5 1 +3 5 4 1 + diff --git a/Constrained_triangulation_3/test/Constrained_triangulation_3/data/bug-move-vertex-4.off b/Constrained_triangulation_3/test/Constrained_triangulation_3/data/bug-move-vertex-4.off new file mode 100644 index 000000000000..6044eda4d312 --- /dev/null +++ b/Constrained_triangulation_3/test/Constrained_triangulation_3/data/bug-move-vertex-4.off @@ -0,0 +1,161 @@ +OFF +117 40 0 + +-23.07103157043457 -7.6288971900939941 2.1894557476043701 +-23.033435821533203 -7.7408347129821777 3.2313618659973145 +-23.299070358276367 -6.8942909240722656 3.0988237857818604 +17.360824312482563 -15.377271730072644 -136 +8.432548990055011 -18.353391063456634 -88 +13.392701946959207 -19.345430841251297 -84 +16.864809016792144 -10.913092729996661 -131 +18.352854903863403 -8.4329932855100047 -174 +7.4405183986741683 -19.345430841251297 -72 +14.880747834030466 -13.889212063380651 -117 +2.9763807374603921 -19.841450730148626 -79 +3.4723960331508117 -20.337470619045959 -110 +2.9763807374603921 -19.841450730148626 -109 +5.45645721591249 -19.345430841251297 -104 +22.320977269386759 -7.4409535077153421 -112 +7.4405183986741683 -22.321550174635284 -104 +12.896686651268787 -15.873291618969978 -87 +5.9524725116029096 -22.817570063532614 -105 +6.9445031029837487 -18.849410952353963 -105 +5.45645721591249 -19.345430841251297 -112 +6.9445031029837487 -18.849410952353963 -127 +1.4883348503891298 -23.313589952429947 -78 +3.4723960331508117 -23.313589952429947 -100 +3.9684113288412313 -22.817570063532614 -101 +2.9763807374603921 -19.841450730148626 -83 +10.416610172816689 -17.361351285661968 -96 +9.9205948771262698 -17.857371174559301 -95 +3.9684113288412313 -19.841450730148626 -85 +-22.320399342751017 -7.4409535077153421 2 +-21.824384047060597 -8.929013174407336 3 +-22.320399342751017 -7.4409535077153421 4 +-21.824384047060597 -7.9369733966126734 3 +-22.320399342751017 -6.4489137299206796 2 +-22.816414638441437 -5.9528938410233483 1 +-22.816414638441437 -4.9608540632286857 3 +-22.320399342751017 -5.456873952126017 2 +-22.816414638441437 -5.9528938410233483 3 +22.816992565077179 -5.9528938410233483 -113 +10.416610172816689 -17.361351285661968 -110 +17.360824312482563 -10.41707284109933 -132 +14.384732538340046 -18.353391063456634 -78 +7.9365336943645879 -18.849410952353963 -77 +5.45645721591249 -19.345430841251297 -90 +6.9445031029837487 -18.849410952353963 -89 +1.4883348503891298 -23.313589952429947 -58 +1.4883348503891298 -22.321550174635284 -58 +3.4723960331508117 -21.329510396840622 -74 +5.9524725116029096 -22.817570063532614 -95 +5.9524725116029096 -22.817570063532614 -83 +5.45645721591249 -19.345430841251297 -88 +8.432548990055011 -18.353391063456634 -86 +13.392701946959207 -15.377271730072644 -88 +13.888717242649626 -18.849410952353963 -77 +13.888717242649626 -14.881251841175313 -87 +12.400671355578368 -19.345430841251297 -84 +14.384732538340046 -14.385231952277982 -102 +1.4883348503891298 -20.337470619045959 -82 +8.432548990055011 -18.353391063456634 -128 +7.9365336943645879 -18.849410952353963 -127 +17.856839608172983 -9.9210529522019986 -131 +18.352854903863403 -8.4329932855100047 -176 +17.856839608172983 -9.9210529522019986 -175 +18.352854903863403 -14.385231952277982 -136 +22.320977269386759 -7.4409535077153421 -114 +14.384732538340046 -14.385231952277982 -116 +15.376763129720885 -13.393192174483319 -116 +17.856839608172983 -14.881251841175313 -135 +13.392701946959207 -15.377271730072644 -102 +5.45645721591249 -19.345430841251297 -84 +13.888717242649626 -14.881251841175313 -101 +8.9285642857454306 -18.849410952353963 -77 +7.4405183986741683 -19.345430841251297 -76 +6.9445031029837487 -18.849410952353963 -113 +2.9763807374603921 -19.841450730148626 -111 +9.9205948771262698 -17.857371174559301 -109 +9.4245795814358502 -18.353391063456634 -96 +7.4405183986741683 -22.321550174635284 -84 +10.416610172816689 -17.361351285661968 -106 +9.4245795814358502 -18.353391063456634 -106 +9.9205948771262698 -17.857371174559301 -107 +10.912625468507109 -20.833490507943289 -99 +11.904656059887948 -19.841450730148626 -99 +7.9365336943645879 -18.849410952353963 -87 +11.904656059887948 -19.841450730148626 -105 +11.408640764197528 -20.337470619045959 -104 +1.4883348503891298 -20.337470619045959 -84 +5.45645721591249 -19.345430841251297 -114 +11.408640764197528 -20.337470619045959 -110 +11.904656059887948 -19.841450730148626 -109 +6.4484878072933292 -22.321550174635284 -94 +7.4405183986741683 -22.321550174635284 -82 +11.904656059887948 -19.841450730148626 -83 +8.432548990055011 -19.345430841251297 -72 +8.432548990055011 -20.337470619045959 -72 +14.880747834030466 -17.857371174559301 -77 +0.49630425900829067 -22.321550174635284 -58 +11.904656059887948 -19.841450730148626 -119 +11.408640764197528 -20.337470619045959 -120 +12.400671355578368 -19.345430841251297 -120 +0.99231955469871047 -22.817570063532614 -77 +0.49630425900829067 -23.313589952429947 -78 +4.4644266245316508 -21.329510396840622 -74 +4.4644266245316508 -22.321550174635284 -74 +3.9684113288412313 -19.841450730148626 -79 +3.4723960331508117 -20.337470619045959 -78 +6.4484878072933292 -19.345430841251297 -104 +10.912625468507109 -20.833490507943289 -109 +11.408640764197528 -20.337470619045959 -100 +4.9604419202220704 -19.841450730148626 -85 +8.9285642857454306 -21.825530285737951 -103 +8.9285642857454306 -21.825530285737951 -105 +9.4245795814358502 -18.353391063456634 -110 +5.9524725116029096 -22.817570063532614 -93 +4.9604419202220704 -22.817570063532614 -101 +10.912625468507109 -20.833490507943289 -105 +5.45645721591249 -22.321550174635284 -106 +5.9524725116029096 -22.817570063532614 -107 +3 2 0 1 +3 31 30 29 +3 36 35 34 +3 33 36 32 +3 36 28 32 +3 58 20 57 +3 7 61 60 +3 37 63 14 +3 9 65 64 +3 6 39 59 +3 66 62 3 +3 5 54 91 +3 82 4 50 +3 8 93 92 +3 52 94 40 +3 16 51 53 +3 43 49 42 +3 70 71 41 +3 45 95 44 +3 98 97 96 +3 100 99 21 +3 90 76 48 +3 85 24 56 +3 102 46 101 +3 104 10 103 +3 55 69 67 +3 11 12 73 +3 18 105 13 +3 87 106 88 +3 80 81 107 +3 68 27 108 +3 110 15 109 +3 78 79 77 +3 111 38 74 +3 25 26 75 +3 47 112 89 +3 72 19 86 +3 22 113 23 +3 84 83 114 +3 116 115 17 + diff --git a/Constrained_triangulation_3/test/Constrained_triangulation_3/data/bug-move-vertex-5.off b/Constrained_triangulation_3/test/Constrained_triangulation_3/data/bug-move-vertex-5.off new file mode 100644 index 000000000000..1227221be945 --- /dev/null +++ b/Constrained_triangulation_3/test/Constrained_triangulation_3/data/bug-move-vertex-5.off @@ -0,0 +1,29 @@ +OFF +22 3 0 + +6 10 10 +-6.0072099999999997 4.00481 4.00481 +6.0048000000000004 6.0072099999999997 4.0031999999999996 +6.0072099999999997 4.00481 4.00481 +-6.0072099999999997 2.0024000000000002 4.0064099999999998 +6.0072099999999997 2.0024000000000002 4.0064099999999998 +6.0048000000000004 6.0048000000000004 6.0048000000000004 +6.0048000000000004 6.0048000000000004 10.007999999999999 +5.9999900000000004 10.007999999999999 5.9999900000000004 +5.9999900000000004 10.007999999999999 3.9999899999999999 +-6.0048000000000004 6.0060099999999998 5.0006000000000004 +-6.0110000000000001 0.85517500000000002 4.0073299999999996 +6.0109899999999996 0.86136599999999997 4.0073299999999996 +-6.0116300000000003 2.0038800000000001 0.33143699999999998 +-6.0060099999999998 6.0060099999999998 5.0006000000000004 +6.0116199999999997 2.00387 0.336254 +-10.02 0 -2.0080200000000001 +10.02 0 -1.9999899999999999 +-10.007999999999999 6.0240600000000004 5.0200500000000003 +6.0060099999999998 6.0048000000000004 5.0039999999999996 +10.007999999999999 5.9999900000000004 4.9999900000000004 +-6.0047899999999998 6.0192399999999999 5.0160400000000003 +10 16 18 21 10 14 13 15 19 20 17 +6 11 12 3 5 4 1 +8 9 2 6 3 12 7 0 8 + diff --git a/Constrained_triangulation_3/test/Constrained_triangulation_3/data/bug-move-vertex-6.off b/Constrained_triangulation_3/test/Constrained_triangulation_3/data/bug-move-vertex-6.off new file mode 100644 index 000000000000..99f68ff91709 --- /dev/null +++ b/Constrained_triangulation_3/test/Constrained_triangulation_3/data/bug-move-vertex-6.off @@ -0,0 +1,19 @@ +OFF +12 3 0 + +6.0047800000000002 6.0240600000000004 -10.007999999999999 +6.0072099999999997 4.00481 4.00481 +6.0240600000000004 6.0240600000000004 -10.007999999999999 +6.0072099999999997 2.0024000000000002 4.0064099999999998 +6.0048000000000004 6.0048000000000004 6.0048000000000004 +10 10 -10 +5.9999900000000004 10.007999999999999 -9.9999800000000008 +6.0116199999999997 2.00387 0.336254 +6.0060099999999998 6.0048000000000004 5.0039999999999996 +10.007999999999999 5.9999900000000004 4.9999900000000004 +6.0240600000000004 6.0047800000000002 -10.007999999999999 +10.007999999999999 5.9999900000000004 -9.9999800000000008 +4 6 5 2 0 +4 8 10 11 9 +7 4 2 10 8 7 3 1 + diff --git a/Constrained_triangulation_3/test/Constrained_triangulation_3/data/bug-move-vertex-7.off b/Constrained_triangulation_3/test/Constrained_triangulation_3/data/bug-move-vertex-7.off new file mode 100644 index 000000000000..c2b09c3542c3 --- /dev/null +++ b/Constrained_triangulation_3/test/Constrained_triangulation_3/data/bug-move-vertex-7.off @@ -0,0 +1,24 @@ +OFF +16 4 0 + +6.0047800000000002 6.0240600000000004 -10.007999999999999 +6.0047899999999998 6.0168400000000002 -4.00319 +6.0048000000000004 6.0072099999999997 4.0031999999999996 +6.0072099999999997 4.00481 4.00481 +6.0240600000000004 6.0240600000000004 -10.007999999999999 +6.0072099999999997 2.0024000000000002 4.0064099999999998 +6.0048000000000004 6.0048000000000004 6.0048000000000004 +4.0031999999999996 6.0072099999999997 4.0031999999999996 +-4.00319 6.0168400000000002 -4.00319 +5.9999900000000004 10.007999999999999 -9.9999800000000008 +5.9999900000000004 10.007999999999999 -3.9999899999999999 +6.0116199999999997 2.00387 0.336254 +6.0060099999999998 6.0048000000000004 5.0039999999999996 +10.007999999999999 5.9999900000000004 4.9999900000000004 +6.0240600000000004 6.0047800000000002 -10.007999999999999 +10.007999999999999 5.9999900000000004 -9.9999800000000008 +4 12 14 15 13 +7 6 4 14 12 11 5 3 +7 8 1 0 4 6 2 7 +4 9 0 1 10 + diff --git a/Constrained_triangulation_3/test/Constrained_triangulation_3/data/bug-segfault.off b/Constrained_triangulation_3/test/Constrained_triangulation_3/data/bug-segfault.off new file mode 100644 index 000000000000..08f3a6a0e6b1 --- /dev/null +++ b/Constrained_triangulation_3/test/Constrained_triangulation_3/data/bug-segfault.off @@ -0,0 +1,3714 @@ +OFF +1398 2312 0 + +26.597300000000001 36.607999999999997 97.103999999999999 +26.567900000000002 36.567549999999997 96.959999999999994 +36.567549999999997 26.567900000000002 96.959999999999994 +-50 0 96.239999999999995 +-47.552849999999999 15.450850000000001 96.239999999999995 +36.877704999999999 25.524087000000002 86.799999999999997 +41.277892999999999 27.766093999999999 86.799999999999997 +38.239677999999998 22.851068000000001 91.996151999999995 +43.429470999999999 9.9159480000000002 23.853847999999999 +44.368076000000002 3.9898180000000001 17.746151999999999 +44.368076000000002 3.9898180000000001 23.853847999999999 +-27.740373000000002 41.290998000000002 95 +-29.389250000000001 40.450850000000003 96.239999999999995 +-15.450850000000001 47.552849999999999 96.239999999999995 +36.607999999999997 26.597300000000001 97.103999999999999 +-49.715021999999998 1.7992950000000001 20.800000000000001 +38.239677999999998 22.851068000000001 81.603847999999999 +29.359850000000002 40.410400000000003 96.384 +29.359850000000002 40.410400000000003 96.480000000000004 +40.410400000000003 29.359850000000002 96.384 +-25.093077000000001 42.639868999999997 34.246152000000002 +-25.093077000000001 42.639868999999997 40.353847999999999 +-19.747043000000001 45.363821000000002 34.246152000000002 +13.983000000000001 43.035299999999999 97.103999999999999 +-48.307125999999997 10.688492 25.996151999999999 +-48.307125999999997 10.688492 32.103847999999999 +-47.837826999999997 13.651558 20.800000000000001 +40.410400000000003 29.359850000000002 96.480000000000004 +-29.389250000000001 40.450850000000003 0 +-27.766093999999999 41.277892999999999 12.550000000000001 +-49.245724000000003 4.7623610000000003 15.603847999999999 +42.639868999999997 25.093077000000001 91.996151999999995 +15.4354 47.505249999999997 96.384 +15.4354 47.505249999999997 96.480000000000004 +-17.074024999999999 46.725797 12.550000000000001 +-15.450850000000001 47.552849999999999 0 +-19.747043000000001 45.363821000000002 7.3538480000000002 +-47.552849999999999 15.450850000000001 0 +-25.093077000000001 42.639868999999997 7.3538480000000002 +-49.245724000000003 4.7623610000000003 32.103847999999999 +-49.245724000000003 4.7623610000000003 25.996151999999999 +-49.715021999999998 1.7992950000000001 37.299999999999997 +36.877704999999999 25.524087000000002 20.800000000000001 +36.405749999999998 26.45035 95.760000000000005 +36.405749999999998 26.45035 4.7999999999999998 +-48.307125999999997 10.688492 15.603847999999999 +36.877704999999999 25.524087000000002 37.299999999999997 +-19.747043000000001 45.363821000000002 17.746151999999999 +-19.747043000000001 45.363821000000002 23.853847999999999 +38.239677999999998 22.851068000000001 15.603847999999999 +36.877704999999999 25.524087000000002 70.299999999999997 +-25.093077000000001 42.639868999999997 56.853847999999999 +-25.093077000000001 42.639868999999997 50.746152000000002 +-27.766093999999999 41.277892999999999 62.049999999999997 +49.450000000000003 0 97.488 +47.02975 -15.280900000000001 97.488 +40.963622999999998 17.505030000000001 32.103847999999999 +42.325595999999997 14.832011 20.800000000000001 +42.325595999999997 14.832011 37.299999999999997 +-19.747043000000001 45.363821000000002 50.746152000000002 +49.25 0 97.680000000000007 +42.797550000000001 13.905749999999999 95.760000000000005 +42.797550000000001 13.905749999999999 4.7999999999999998 +-27.766093999999999 41.277892999999999 78.549999999999997 +-25.093077000000001 42.639868999999997 67.246151999999995 +47.02975 15.280900000000001 97.488 +40.963622999999998 17.505030000000001 9.4961520000000004 +42.639868999999997 25.093077000000001 9.4961520000000004 +40.963622999999998 17.505030000000001 15.603847999999999 +-27.766093999999999 41.277892999999999 29.050000000000001 +40.005899999999997 29.065999999999999 97.488 +46.839550000000003 15.219099999999999 97.680000000000007 +-47.837826999999997 13.651558 37.299999999999997 +41.461371 27.405999000000001 5 +38.239677999999998 22.851068000000001 9.4961520000000004 +38.239677999999998 22.851068000000001 25.996151999999999 +38.239677999999998 22.851068000000001 32.103847999999999 +-25.093077000000001 42.639868999999997 23.853847999999999 +29.065999999999999 40.005899999999997 97.488 +39.844099999999997 28.948399999999999 97.680000000000007 +-49.245724000000003 4.7623610000000003 58.996152000000002 +42.142118000000004 15.192107 5 +36.877704999999999 25.524087000000002 53.799999999999997 +46.75 0 98.304000000000002 +44.319249999999997 -14.4002 98.256 +44.4619 -14.44655 98.304000000000002 +-25.093077000000001 42.639868999999997 73.353847999999999 +-19.747043000000001 45.363821000000002 67.246151999999995 +-49.245724000000003 4.7623610000000003 42.496152000000002 +-49.245724000000003 4.7623610000000003 48.603847999999999 +44.4619 14.44655 98.304000000000002 +44.319249999999997 14.4002 98.256 +46.600000000000001 0 98.256 +-27.766093999999999 41.277892999999999 45.549999999999997 +15.280900000000001 47.02975 97.488 +-49.715021999999998 1.7992950000000001 53.799999999999997 +40.963622999999998 17.505030000000001 25.996151999999999 +-17.074024999999999 46.725797 29.050000000000001 +37.061183 25.163990999999999 5 +42.325595999999997 14.832011 53.799999999999997 +40.963622999999998 17.505030000000001 42.496152000000002 +37.821550000000002 27.478950000000001 98.304000000000002 +37.700200000000002 27.390799999999999 98.256 +0 49.450000000000003 97.488 +29.389250000000001 40.450850000000003 96.239999999999995 +15.450850000000001 47.552849999999999 96.239999999999995 +0 49.25 97.680000000000007 +-48.307125999999997 10.688492 42.496152000000002 +37.041370000000001 32.798729999999999 17.746151999999999 +33.549370000000003 29.306730000000002 17.746151999999999 +32.798729999999999 37.041370000000001 17.746151999999999 +27.478950000000001 37.821550000000002 98.304000000000002 +27.390799999999999 37.700200000000002 98.256 +-25.093077000000001 42.639868999999997 17.746151999999999 +-15.280900000000001 47.02975 97.488 +29.306730000000002 33.549370000000003 17.746151999999999 +38.239677999999998 22.851068000000001 42.496152000000002 +38.239677999999998 22.851068000000001 48.603847999999999 +-19.747043000000001 45.363821000000002 40.353847999999999 +-15.219099999999999 46.839550000000003 97.680000000000007 +30.677409000000001 39.162691000000002 12.550000000000001 +14.44655 44.4619 98.304000000000002 +14.4002 44.319249999999997 98.256 +-17.074024999999999 46.725797 78.549999999999997 +-17.074024999999999 46.725797 62.049999999999997 +-29.065999999999999 40.005899999999997 97.488 +27.185409 35.670690999999998 12.550000000000001 +38.239677999999998 22.851068000000001 58.996152000000002 +-28.948399999999999 39.844099999999997 97.680000000000007 +39.162691000000002 30.677409000000001 12.550000000000001 +35.670690999999998 27.185409 12.550000000000001 +38.239677999999998 22.851068000000001 75.496151999999995 +0 46.75 98.304000000000002 +0 46.600000000000001 98.256 +-17.074024999999999 46.725797 45.549999999999997 +-39.844099999999997 28.948399999999999 97.680000000000007 +37.041370000000001 32.798729999999999 7.3538480000000002 +-14.44655 44.4619 98.304000000000002 +-40.005899999999997 29.065999999999999 97.488 +-47.02975 15.280900000000001 97.488 +33.549370000000003 29.306730000000002 7.3538480000000002 +40.963622999999998 17.505030000000001 65.103847999999999 +40.963622999999998 17.505030000000001 58.996152000000002 +42.325595999999997 14.832011 70.299999999999997 +-14.4002 44.319249999999997 98.256 +32.798729999999999 37.041370000000001 7.3538480000000002 +-27.478950000000001 37.821550000000002 98.304000000000002 +-27.390799999999999 37.700200000000002 98.256 +-19.747043000000001 45.363821000000002 56.853847999999999 +-49.450000000000003 0 97.488 +29.306730000000002 33.549370000000003 7.3538480000000002 +38.239677999999998 22.851068000000001 65.103847999999999 +-49.25 0 97.680000000000007 +-37.700200000000002 27.390799999999999 98.256 +-44.4619 14.44655 98.304000000000002 +-44.319249999999997 14.4002 98.256 +-25.093077000000001 42.639868999999997 83.746151999999995 +33.549370000000003 29.306730000000002 23.853847999999999 +29.306730000000002 33.549370000000003 23.853847999999999 +-30.677409000000001 39.162691000000002 37.299999999999997 +-30.677409000000001 39.162691000000002 20.800000000000001 +-32.798729999999999 37.041370000000001 32.103847999999999 +19.747043000000001 45.363821000000002 25.996151999999999 +22.851068000000001 38.239677999999998 25.996151999999999 +17.505030000000001 40.963622999999998 25.996151999999999 +46.744450000000001 -15.1882 97.775999999999996 +-46.75 0 98.304000000000002 +-40.450850000000003 29.389250000000001 96.239999999999995 +-40.410400000000003 29.359850000000002 96.384 +27.766093999999999 41.277892999999999 20.800000000000001 +25.524087000000002 36.877704999999999 20.800000000000001 +25.093077000000001 42.639868999999997 25.996151999999999 +49.149999999999999 0 97.775999999999996 +-40.450850000000003 29.389250000000001 0 +37.041370000000001 32.798729999999999 34.246152000000002 +33.549370000000003 29.306730000000002 34.246152000000002 +32.798729999999999 37.041370000000001 34.246152000000002 +-37.821550000000002 27.478950000000001 98.304000000000002 +-19.747043000000001 45.363821000000002 83.746151999999995 +33.549370000000003 29.306730000000002 56.853847999999999 +29.306730000000002 33.549370000000003 56.853847999999999 +33.549370000000003 29.306730000000002 50.746152000000002 +-40.963622999999998 17.505030000000001 17.746151999999999 +-42.325595999999997 14.832011 12.550000000000001 +-45.363821000000002 19.747043000000001 17.746151999999999 +25.093077000000001 42.639868999999997 15.603847999999999 +46.744450000000001 15.1882 97.775999999999996 +30.677409000000001 39.162691000000002 29.050000000000001 +29.306730000000002 33.549370000000003 34.246152000000002 +-19.747043000000001 45.363821000000002 73.353847999999999 +35.670690999999998 27.185409 45.549999999999997 +35.670690999999998 27.185409 62.049999999999997 +14.477449999999999 44.557000000000002 98.304000000000002 +-46.725797 17.074024999999999 12.550000000000001 +22.851068000000001 38.239677999999998 15.603847999999999 +0 50 0 +27.185409 35.670690999999998 29.050000000000001 +29.306730000000002 33.549370000000003 40.353847999999999 +-40.963622999999998 17.505030000000001 7.3538480000000002 +-45.363821000000002 19.747043000000001 7.3538480000000002 +19.747043000000001 45.363821000000002 15.603847999999999 +39.763199999999998 28.88965 97.775999999999996 +15.450850000000001 47.552849999999999 0 +39.162691000000002 30.677409000000001 29.050000000000001 +35.670690999999998 27.185409 29.050000000000001 +-17.099747000000001 46.712691999999997 95 +0 49.950000000000003 96.384 +0 49.950000000000003 96.480000000000004 +27.537749999999999 37.902450000000002 98.304000000000002 +17.505030000000001 40.963622999999998 15.603847999999999 +28.88965 39.763199999999998 97.775999999999996 +29.389250000000001 40.450850000000003 0 +-38.239677999999998 22.851068000000001 17.746151999999999 +-42.639868999999997 25.093077000000001 17.746151999999999 +17.074024999999999 46.725797 37.299999999999997 +19.747043000000001 45.363821000000002 42.496152000000002 +17.505030000000001 40.963622999999998 42.496152000000002 +40.450850000000003 29.389250000000001 0 +-43.130400000000002 14.0139 97.200000000000003 +-45.399999999999999 0 97.296000000000006 +-45.350000000000001 0 97.200000000000003 +37.041370000000001 32.798729999999999 23.853847999999999 +-19.747043000000001 45.363821000000002 89.853847999999999 +-25.093077000000001 42.639868999999997 89.853847999999999 +17.505030000000001 40.963622999999998 91.996151999999995 +26.45035 36.405749999999998 95.760000000000005 +13.905749999999999 42.797550000000001 95.760000000000005 +37.902450000000002 27.537749999999999 98.304000000000002 +14.832011 42.325595999999997 37.299999999999997 +40.963622999999998 17.505030000000001 75.496151999999995 +22.851068000000001 38.239677999999998 9.4961520000000004 +26.45035 36.405749999999998 4.7999999999999998 +-41.277892999999999 27.766093999999999 12.550000000000001 +-36.877704999999999 25.524087000000002 12.550000000000001 +17.505030000000001 40.963622999999998 32.103847999999999 +19.747043000000001 45.363821000000002 32.103847999999999 +15.1882 46.744450000000001 97.775999999999996 +50 0 0 +32.798729999999999 37.041370000000001 23.853847999999999 +13.905749999999999 42.797550000000001 4.7999999999999998 +14.832011 42.325595999999997 20.800000000000001 +44.557000000000002 14.477449999999999 98.304000000000002 +47.552849999999999 -15.450850000000001 0 +17.505030000000001 40.963622999999998 75.496151999999995 +22.851068000000001 38.239677999999998 75.496151999999995 +17.505030000000001 40.963622999999998 81.603847999999999 +-38.239677999999998 22.851068000000001 7.3538480000000002 +25.093077000000001 42.639868999999997 42.496152000000002 +22.851068000000001 38.239677999999998 42.496152000000002 +0 49.149999999999999 97.775999999999996 +40.450850000000003 -29.389250000000001 0 +37.041370000000001 32.798729999999999 50.746152000000002 +32.798729999999999 37.041370000000001 50.746152000000002 +29.306730000000002 33.549370000000003 50.746152000000002 +30.677409000000001 39.162691000000002 45.549999999999997 +-42.325595999999997 14.832011 29.050000000000001 +-45.363821000000002 19.747043000000001 23.853847999999999 +-46.725797 17.074024999999999 29.050000000000001 +22.851068000000001 38.239677999999998 32.103847999999999 +-39.763199999999998 28.88965 97.775999999999996 +-46.725797 17.074024999999999 78.549999999999997 +-45.363821000000002 19.747043000000001 83.746151999999995 +-36.688899999999997 26.65605 97.200000000000003 +-43.177950000000003 14.029350000000001 97.296000000000006 +-30.677409000000001 39.162691000000002 53.799999999999997 +-32.798729999999999 37.041370000000001 48.603847999999999 +14.832011 42.325595999999997 86.799999999999997 +-44.557000000000002 14.477449999999999 98.304000000000002 +-38.239677999999998 22.851068000000001 34.246152000000002 +-40.963622999999998 17.505030000000001 34.246152000000002 +-42.639868999999997 25.093077000000001 34.246152000000002 +17.074024999999999 46.725797 53.799999999999997 +19.747043000000001 45.363821000000002 58.996152000000002 +17.505030000000001 40.963622999999998 58.996152000000002 +-46.744450000000001 15.1882 97.775999999999996 +-46.712691999999997 17.099747000000001 95 +39.162691000000002 30.677409000000001 45.549999999999997 +37.041370000000001 32.798729999999999 40.353847999999999 +-39.162691000000002 30.677409000000001 20.800000000000001 +-26.685449999999999 36.729349999999997 97.296000000000006 +-36.729349999999997 26.685449999999999 97.296000000000006 +37.041370000000001 32.798729999999999 67.246151999999995 +33.549370000000003 29.306730000000002 67.246151999999995 +32.798729999999999 37.041370000000001 67.246151999999995 +45.555599999999998 14.8019 98.352000000000004 +45.412950000000002 14.755549999999999 98.400000000000006 +47.75 0 98.400000000000006 +-26.65605 36.688899999999997 97.200000000000003 +29.306730000000002 33.549370000000003 67.246151999999995 +38.751899999999999 28.154900000000001 98.352000000000004 +-37.041370000000001 32.798729999999999 42.496152000000002 +-37.041370000000001 32.798729999999999 48.603847999999999 +-32.798729999999999 37.041370000000001 42.496152000000002 +30.677409000000001 39.162691000000002 62.049999999999997 +38.630549999999999 28.066749999999999 98.400000000000006 +-39.162691000000002 30.677409000000001 53.799999999999997 +-39.162691000000002 30.677409000000001 70.299999999999997 +-37.041370000000001 32.798729999999999 58.996152000000002 +27.185409 35.670690999999998 62.049999999999997 +27.185409 35.670690999999998 78.549999999999997 +28.154900000000001 38.751899999999999 98.352000000000004 +28.066749999999999 38.630549999999999 98.400000000000006 +-39.162691000000002 30.677409000000001 37.299999999999997 +27.185409 35.670690999999998 45.549999999999997 +0 46.850000000000001 98.304000000000002 +-29.359850000000002 40.410400000000003 96.384 +25.524087000000002 36.877704999999999 53.799999999999997 +22.851068000000001 38.239677999999998 48.603847999999999 +-45.363821000000002 19.747043000000001 34.246152000000002 +14.832011 42.325595999999997 53.799999999999997 +-41.277892999999999 27.766093999999999 29.050000000000001 +-36.877704999999999 25.524087000000002 29.050000000000001 +17.505030000000001 40.963622999999998 48.603847999999999 +19.747043000000001 45.363821000000002 48.603847999999999 +-49.149999999999999 0 97.775999999999996 +25.524087000000002 36.877704999999999 37.299999999999997 +38.226050000000001 27.772849999999998 98.400000000000006 +44.937399999999997 14.601050000000001 98.400000000000006 +27.772849999999998 38.226050000000001 98.400000000000006 +-38.239677999999998 22.851068000000001 23.853847999999999 +25.093077000000001 42.639868999999997 58.996152000000002 +22.851068000000001 38.239677999999998 58.996152000000002 +-42.639868999999997 25.093077000000001 7.3538480000000002 +14.601050000000001 44.937399999999997 98.400000000000006 +-42.639868999999997 25.093077000000001 23.853847999999999 +0 47.25 98.400000000000006 +14.755549999999999 45.412950000000002 98.400000000000006 +-40.963622999999998 17.505030000000001 23.853847999999999 +27.766093999999999 41.277892999999999 53.799999999999997 +-45.363821000000002 19.747043000000001 40.353847999999999 +-46.725797 17.074024999999999 45.549999999999997 +17.505030000000001 40.963622999999998 65.103847999999999 +14.832011 42.325595999999997 70.299999999999997 +-38.226050000000001 27.772849999999998 98.400000000000006 +-27.772849999999998 38.226050000000001 98.400000000000006 +-28.066749999999999 38.630549999999999 98.400000000000006 +-46.725797 17.074024999999999 62.049999999999997 +-45.363821000000002 19.747043000000001 50.746152000000002 +47.25 0 98.400000000000006 +-40.963622999999998 17.505030000000001 50.746152000000002 +-42.325595999999997 14.832011 45.549999999999997 +25.093077000000001 42.639868999999997 48.603847999999999 +-45.412950000000002 14.755549999999999 98.400000000000006 +-47.75 0 98.400000000000006 +-47.25 0 98.400000000000006 +-40.963622999999998 17.505030000000001 40.353847999999999 +-45.5 0 97.391999999999996 +-42.639868999999997 25.093077000000001 56.853847999999999 +-41.277892999999999 27.766093999999999 45.549999999999997 +-42.639868999999997 25.093077000000001 50.746152000000002 +-42.639868999999997 25.093077000000001 40.353847999999999 +-38.630549999999999 28.066749999999999 98.400000000000006 +-38.239677999999998 22.851068000000001 50.746152000000002 +17.074024999999999 46.725797 70.299999999999997 +19.747043000000001 45.363821000000002 75.496151999999995 +-45.363821000000002 19.747043000000001 56.853847999999999 +43.891249999999999 14.261150000000001 98.016000000000005 +43.796149999999997 14.23025 97.920000000000002 +46.049999999999997 0 97.920000000000002 +42.639868999999997 -25.093077000000001 7.3538480000000002 +-14.755549999999999 45.412950000000002 98.400000000000006 +-36.877704999999999 25.524087000000002 45.549999999999997 +19.747043000000001 45.363821000000002 65.103847999999999 +-14.601050000000001 44.937399999999997 98.400000000000006 +37.336150000000004 27.126300000000001 98.016000000000005 +37.255249999999997 27.067499999999999 97.920000000000002 +45.363821000000002 -19.747043000000001 7.3538480000000002 +22.851068000000001 38.239677999999998 91.996151999999995 +25.524087000000002 36.877704999999999 86.799999999999997 +0 47.75 98.400000000000006 +-38.239677999999998 22.851068000000001 40.353847999999999 +25.093077000000001 42.639868999999997 75.496151999999995 +-45.363821000000002 19.747043000000001 89.853847999999999 +-42.639868999999997 25.093077000000001 83.746151999999995 +25.524087000000002 36.877704999999999 70.299999999999997 +-37.255249999999997 27.067499999999999 97.920000000000002 +-43.891249999999999 14.261150000000001 98.016000000000005 +-43.796149999999997 14.23025 97.920000000000002 +46.725797 -17.074024999999999 12.550000000000001 +22.851068000000001 38.239677999999998 65.103847999999999 +27.766093999999999 41.277892999999999 70.299999999999997 +-46.149999999999999 0 98.016000000000005 +42.639868999999997 -25.093077000000001 23.853847999999999 +42.639868999999997 -25.093077000000001 17.746151999999999 +45.363821000000002 -19.747043000000001 17.746151999999999 +27.126300000000001 37.336150000000004 98.016000000000005 +27.067499999999999 37.255249999999997 97.920000000000002 +47.552849999999999 -15.450850000000001 96.239999999999995 +-40.963622999999998 17.505030000000001 67.246151999999995 +-42.325595999999997 14.832011 62.049999999999997 +-45.363821000000002 19.747043000000001 67.246151999999995 +25.093077000000001 42.639868999999997 65.103847999999999 +46.725797 -17.074024999999999 29.050000000000001 +45.363821000000002 -19.747043000000001 23.853847999999999 +22.851068000000001 38.239677999999998 81.603847999999999 +45.412950000000002 -14.755549999999999 98.400000000000006 +-40.963622999999998 17.505030000000001 56.853847999999999 +-43.273049999999998 14.06025 97.391999999999996 +-14.23025 43.796149999999997 97.920000000000002 +-27.126300000000001 37.336150000000004 98.016000000000005 +-27.067499999999999 37.255249999999997 97.920000000000002 +-38.239677999999998 22.851068000000001 67.246151999999995 +-42.639868999999997 25.093077000000001 67.246151999999995 +17.074024999999999 46.725797 86.799999999999997 +19.747043000000001 45.363821000000002 91.996151999999995 +-37.336150000000004 27.126300000000001 98.016000000000005 +46.725797 -17.074024999999999 45.549999999999997 +45.363821000000002 -19.747043000000001 34.246152000000002 +-41.277892999999999 27.766093999999999 78.549999999999997 +-41.277892999999999 27.766093999999999 62.049999999999997 +-36.877704999999999 25.524087000000002 62.049999999999997 +19.747043000000001 45.363821000000002 81.603847999999999 +17.505030000000001 40.963622999999998 9.4961520000000004 +-38.239677999999998 22.851068000000001 56.853847999999999 +25.093077000000001 42.639868999999997 91.996151999999995 +-14.029350000000001 43.177950000000003 97.296000000000006 +-26.744250000000001 36.810250000000003 97.391999999999996 +27.766093999999999 41.277892999999999 86.799999999999997 +-36.810250000000003 26.744250000000001 97.391999999999996 +25.163990999999999 37.061183 5 +15.192107 42.142118000000004 5 +44.937399999999997 -14.601050000000001 98.400000000000006 +-40.963622999999998 17.505030000000001 83.746151999999995 +-42.325595999999997 14.832011 78.549999999999997 +25.093077000000001 42.639868999999997 81.603847999999999 +-45.363821000000002 19.747043000000001 73.353847999999999 +-44.937399999999997 14.601050000000001 98.400000000000006 +-40.963622999999998 17.505030000000001 73.353847999999999 +45.399999999999999 0 97.296000000000006 +43.177950000000003 -14.029350000000001 97.296000000000006 +45.5 0 97.391999999999996 +-38.239677999999998 22.851068000000001 83.746151999999995 +25.093077000000001 42.639868999999997 9.4961520000000004 +19.747043000000001 45.363821000000002 9.4961520000000004 +43.273049999999998 -14.06025 97.391999999999996 +-42.639868999999997 25.093077000000001 73.353847999999999 +-15.4354 47.505249999999997 96.384 +-15.4354 47.505249999999997 96.480000000000004 +0 45.399999999999999 97.296000000000006 +-14.06025 43.273049999999998 97.391999999999996 +-36.877704999999999 25.524087000000002 78.549999999999997 +17.434121000000001 46.542318999999999 5 +1.055264 44.832863000000003 95 +0 45 95.760000000000005 +43.273049999999998 14.06025 97.391999999999996 +43.177950000000003 14.029350000000001 97.296000000000006 +-42.639868999999997 25.093077000000001 89.853847999999999 +3.9898180000000001 44.368076000000002 23.853847999999999 +1.0267520000000001 44.837378999999999 29.050000000000001 +3.9898180000000001 44.368076000000002 17.746151999999999 +-38.239677999999998 22.851068000000001 73.353847999999999 +27.405999000000001 41.461371 5 +3.9898180000000001 44.368076000000002 50.746152000000002 +9.9159480000000002 43.429470999999999 50.746152000000002 +3.9898180000000001 44.368076000000002 56.853847999999999 +-37.902450000000002 27.537749999999999 98.304000000000002 +-44.699649999999998 14.5238 98.352000000000004 +14.029350000000001 43.177950000000003 97.296000000000006 +14.0139 43.130400000000002 97.200000000000003 +26.65605 36.688899999999997 97.200000000000003 +3.9898180000000001 44.368076000000002 7.3538480000000002 +1.0267520000000001 44.837378999999999 12.550000000000001 +0 45 4.7999999999999998 +-47 0 98.352000000000004 +-46.850000000000001 0 98.304000000000002 +-41.290998000000002 27.740373000000002 95 +12.879013 42.960169 12.550000000000001 +0 45.5 97.391999999999996 +9.9159480000000002 43.429470999999999 7.3538480000000002 +-27.625900000000001 38.023800000000001 98.352000000000004 +-38.023800000000001 27.625900000000001 98.352000000000004 +-40.963622999999998 17.505030000000001 89.853847999999999 +-42.312489999999997 14.857732 95 +0 50 96.239999999999995 +1.0267520000000001 44.837378999999999 62.049999999999997 +1.0267520000000001 44.837378999999999 78.549999999999997 +-27.537749999999999 37.902450000000002 98.304000000000002 +-36.890810999999999 25.498366000000001 95 +10.688492 48.307125999999997 17.746151999999999 +9.9159480000000002 43.429470999999999 17.746151999999999 +4.7623610000000003 49.245724000000003 17.746151999999999 +-14.477449999999999 44.557000000000002 98.304000000000002 +3.9898180000000001 44.368076000000002 83.746151999999995 +9.9159480000000002 43.429470999999999 83.746151999999995 +3.9898180000000001 44.368076000000002 89.853847999999999 +-14.5238 44.699649999999998 98.352000000000004 +-38.239677999999998 22.851068000000001 89.853847999999999 +1.7992950000000001 49.715021999999998 12.550000000000001 +-47.505249999999997 15.4354 96.384 +12.879013 42.960169 29.050000000000001 +36.729349999999997 26.685449999999999 97.296000000000006 +36.688899999999997 26.65605 97.200000000000003 +43.130400000000002 14.0139 97.200000000000003 +9.9159480000000002 43.429470999999999 67.246151999999995 +12.879013 42.960169 62.049999999999997 +12.879013 42.960169 78.549999999999997 +0 47 98.352000000000004 +13.651558 47.837826999999997 12.550000000000001 +-49.950000000000003 0 96.384 +14.5238 44.699649999999998 98.352000000000004 +-40.410400000000003 29.359850000000002 96.480000000000004 +10.688492 48.307125999999997 7.3538480000000002 +36.810250000000003 26.744250000000001 97.391999999999996 +-44.368076000000002 3.9898180000000001 25.996151999999999 +-44.837378999999999 1.0267520000000001 20.800000000000001 +-29.359850000000002 40.410400000000003 96.480000000000004 +26.685449999999999 36.729349999999997 97.296000000000006 +27.625900000000001 38.023800000000001 98.352000000000004 +-47.505249999999997 15.4354 96.480000000000004 +4.7623610000000003 49.245724000000003 7.3538480000000002 +-44.368076000000002 3.9898180000000001 15.603847999999999 +3.9898180000000001 44.368076000000002 67.246151999999995 +3.9898180000000001 44.368076000000002 73.353847999999999 +38.023800000000001 27.625900000000001 98.352000000000004 +12.879013 42.960169 45.549999999999997 +9.9159480000000002 43.429470999999999 34.246152000000002 +-49.950000000000003 0 96.480000000000004 +-43.429470999999999 9.9159480000000002 25.996151999999999 +46.126249999999999 14.987299999999999 98.207999999999998 +39.237299999999998 28.5076 98.207999999999998 +46.031149999999997 14.9564 98.256 +39.156399999999998 28.448799999999999 98.256 +10.688492 48.307125999999997 34.246152000000002 +4.7623610000000003 49.245724000000003 34.246152000000002 +-42.960169 12.879013 20.800000000000001 +3.9898180000000001 44.368076000000002 34.246152000000002 +46.850000000000001 0 98.304000000000002 +44.557000000000002 -14.477449999999999 98.304000000000002 +47 0 98.352000000000004 +-44.368076000000002 3.9898180000000001 91.996151999999995 +-42.797550000000001 13.905749999999999 95.760000000000005 +-45 0 95.760000000000005 +1.7992950000000001 49.715021999999998 29.050000000000001 +-43.429470999999999 9.9159480000000002 15.603847999999999 +1.0267520000000001 44.837378999999999 45.549999999999997 +44.699649999999998 14.5238 98.352000000000004 +-43.429470999999999 9.9159480000000002 9.4961520000000004 +-42.797550000000001 13.905749999999999 4.7999999999999998 +14.987299999999999 46.126249999999999 98.207999999999998 +14.9564 46.031149999999997 98.256 +28.448799999999999 39.156399999999998 98.256 +47.901049 -13.252389000000001 5 +-45 0 4.7999999999999998 +13.651558 47.837826999999997 29.050000000000001 +0 48.5 98.207999999999998 +49.715021999999998 -1.7992950000000001 20.800000000000001 +49.245724000000003 -4.7623610000000003 15.603847999999999 +44.699649999999998 -14.5238 98.352000000000004 +-44.368076000000002 3.9898180000000001 75.496151999999995 +-43.429470999999999 9.9159480000000002 75.496151999999995 +-44.368076000000002 3.9898180000000001 81.603847999999999 +0 48.399999999999999 98.256 +47.837826999999997 -13.651558 20.800000000000001 +48.307125999999997 -10.688492 15.603847999999999 +-42.960169 12.879013 37.299999999999997 +-43.429470999999999 9.9159480000000002 32.103847999999999 +10.688492 48.307125999999997 23.853847999999999 +-44.368076000000002 3.9898180000000001 42.496152000000002 +-44.837378999999999 1.0267520000000001 37.299999999999997 +-14.987299999999999 46.126249999999999 98.207999999999998 +49.245724000000003 -4.7623610000000003 25.996151999999999 +49.245724000000003 -4.7623610000000003 32.103847999999999 +9.9159480000000002 43.429470999999999 23.853847999999999 +-14.9564 46.031149999999997 98.256 +-44.368076000000002 3.9898180000000001 32.103847999999999 +4.7623610000000003 49.245724000000003 23.853847999999999 +-28.5076 39.237299999999998 98.207999999999998 +48.307125999999997 -10.688492 25.996151999999999 +47.837826999999997 -13.651558 37.299999999999997 +46.649299999999997 -15.157299999999999 97.872 +-43.023390999999997 12.479844 5 +49.049999999999997 0 97.872 +-43.429470999999999 9.9159480000000002 42.496152000000002 +-39.237299999999998 28.5076 98.207999999999998 +-39.156399999999998 28.448799999999999 98.256 +49.245724000000003 -4.7623610000000003 48.603847999999999 +48.307125999999997 -10.688492 48.603847999999999 +48.307125999999997 -10.688492 42.496152000000002 +9.9159480000000002 43.429470999999999 56.853847999999999 +-28.448799999999999 39.156399999999998 98.256 +48.307125999999997 -10.688492 32.103847999999999 +9.9159480000000002 43.429470999999999 89.853847999999999 +10.688492 48.307125999999997 50.746152000000002 +4.7623610000000003 49.245724000000003 50.746152000000002 +46.649299999999997 15.157299999999999 97.872 +-46.126249999999999 14.987299999999999 98.207999999999998 +50 0 96.239999999999995 +-46.031149999999997 14.9564 98.256 +49.715021999999998 -1.7992950000000001 37.299999999999997 +9.9159480000000002 43.429470999999999 40.353847999999999 +3.9898180000000001 44.368076000000002 40.353847999999999 +-42.960169 12.879013 53.799999999999997 +-43.429470999999999 9.9159480000000002 48.603847999999999 +1.7992950000000001 49.715021999999998 45.549999999999997 +39.682299999999998 28.830850000000002 97.872 +-46.25 0 98.063999999999993 +47.837826999999997 -13.651558 53.799999999999997 +47.837826999999997 -13.651558 70.299999999999997 +28.830850000000002 39.682299999999998 97.872 +13.651558 47.837826999999997 45.549999999999997 +12.850501 42.964685000000003 95 +49.245724000000003 -4.7623610000000003 91.996151999999995 +49.715021999999998 -1.7992950000000001 86.799999999999997 +-44.837378999999999 1.0267520000000001 53.799999999999997 +10.688492 48.307125999999997 40.353847999999999 +15.157299999999999 46.649299999999997 97.872 +-44.368076000000002 3.9898180000000001 58.996152000000002 +49.245724000000003 -4.7623610000000003 58.996152000000002 +49.715021999999998 -1.7992950000000001 53.799999999999997 +49.715021999999998 -1.7992950000000001 70.299999999999997 +49.245724000000003 -4.7623610000000003 65.103847999999999 +48.307125999999997 -10.688492 58.996152000000002 +9.9159480000000002 43.429470999999999 73.353847999999999 +-44.368076000000002 3.9898180000000001 65.103847999999999 +-44.837378999999999 1.0267520000000001 70.299999999999997 +4.7623610000000003 49.245724000000003 40.353847999999999 +0 49.049999999999997 97.872 +-44.368076000000002 3.9898180000000001 48.603847999999999 +-15.1882 46.744450000000001 97.775999999999996 +49.245724000000003 -4.7623610000000003 42.496152000000002 +-15.157299999999999 46.649299999999997 97.872 +-43.429470999999999 9.9159480000000002 58.996152000000002 +48.307125999999997 -10.688492 65.103847999999999 +-28.88965 39.763199999999998 97.775999999999996 +48.307125999999997 -10.688492 75.496151999999995 +49.245724000000003 -4.7623610000000003 75.496151999999995 +48.307125999999997 -10.688492 81.603847999999999 +10.688492 48.307125999999997 67.246151999999995 +4.7623610000000003 49.245724000000003 67.246151999999995 +-28.830850000000002 39.682299999999998 97.872 +-39.682299999999998 28.830850000000002 97.872 +1.7992950000000001 49.715021999999998 62.049999999999997 +49.651800999999999 -2.1984650000000001 5 +13.651558 47.837826999999997 62.049999999999997 +-46.649299999999997 15.157299999999999 97.872 +-9.9159480000000002 43.429470999999999 91.996151999999995 +-13.905749999999999 42.797550000000001 95.760000000000005 +-9.9159480000000002 43.429470999999999 75.496151999999995 +-3.9898180000000001 44.368076000000002 75.496151999999995 +-9.9159480000000002 43.429470999999999 81.603847999999999 +-42.960169 12.879013 70.299999999999997 +10.688492 48.307125999999997 56.853847999999999 +4.7623610000000003 49.245724000000003 56.853847999999999 +-1.0267520000000001 44.837378999999999 37.299999999999997 +-3.9898180000000001 44.368076000000002 32.103847999999999 +-1.0267520000000001 44.837378999999999 20.800000000000001 +46.25 0 98.063999999999993 +43.891249999999999 -14.261150000000001 98.016000000000005 +49.245724000000003 -4.7623610000000003 81.603847999999999 +-9.9159480000000002 43.429470999999999 32.103847999999999 +-12.879013 42.960169 37.299999999999997 +-9.9159480000000002 43.429470999999999 25.996151999999999 +-13.905749999999999 42.797550000000001 4.7999999999999998 +-9.9159480000000002 43.429470999999999 15.603847999999999 +-12.879013 42.960169 20.800000000000001 +10.688492 48.307125999999997 83.746151999999995 +4.7623610000000003 49.245724000000003 83.746151999999995 +43.986350000000002 14.29205 98.063999999999993 +46.149999999999999 0 98.016000000000005 +-3.9898180000000001 44.368076000000002 9.4961520000000004 +-1.4259219999999999 44.774157000000002 5 +-43.429470999999999 9.9159480000000002 65.103847999999999 +1.7992950000000001 49.715021999999998 78.549999999999997 +-12.879013 42.960169 86.799999999999997 +-44.368076000000002 3.9898180000000001 9.4961520000000004 +13.651558 47.837826999999997 78.549999999999997 +48.307125999999997 -10.688492 91.996151999999995 +-1.0267520000000001 44.837378999999999 53.799999999999997 +-3.9898180000000001 44.368076000000002 48.603847999999999 +-3.9898180000000001 44.368076000000002 42.496152000000002 +44.794750000000001 -14.5547 98.352000000000004 +0 46.149999999999999 98.016000000000005 +14.261150000000001 43.891249999999999 98.016000000000005 +-12.879013 42.960169 53.799999999999997 +38.104700000000001 27.684699999999999 98.352000000000004 +44.794750000000001 14.5547 98.352000000000004 +-44.774157000000002 1.4259219999999999 5 +4.7623610000000003 49.245724000000003 73.353847999999999 +48.307125999999997 -10.688492 9.4961520000000004 +-9.9159480000000002 43.429470999999999 65.103847999999999 +-12.879013 42.960169 70.299999999999997 +-9.9159480000000002 43.429470999999999 58.996152000000002 +27.684699999999999 38.104700000000001 98.352000000000004 +-14.261150000000001 43.891249999999999 98.016000000000005 +4.7623610000000003 49.245724000000003 89.853847999999999 +1.827807 49.710507 95 +49.245724000000003 -4.7623610000000003 9.4961520000000004 +-9.9159480000000002 43.429470999999999 42.496152000000002 +13.623046 47.842343 95 +47.837826999999997 13.651558 12.550000000000001 +47.552849999999999 15.450850000000001 96.239999999999995 +10.688492 48.307125999999997 89.853847999999999 +49.715021999999998 1.7992950000000001 62.049999999999997 +49.245724000000003 4.7623610000000003 67.246151999999995 +49.715021999999998 1.7992950000000001 78.549999999999997 +-43.320599999999999 14.075699999999999 97.488 +47.837826999999997 13.651558 29.050000000000001 +49.715021999999998 1.7992950000000001 12.550000000000001 +49.245724000000003 4.7623610000000003 17.746151999999999 +49.245724000000003 4.7623610000000003 23.853847999999999 +48.307125999999997 10.688492 7.3538480000000002 +47.837826999999997 13.651558 78.549999999999997 +47.837826999999997 13.651558 62.049999999999997 +49.245724000000003 4.7623610000000003 7.3538480000000002 +-10.688492 48.307125999999997 25.996151999999999 +49.245724000000003 4.7623610000000003 50.746152000000002 +48.307125999999997 10.688492 50.746152000000002 +48.307125999999997 10.688492 56.853847999999999 +-13.651558 47.837826999999997 20.800000000000001 +-26.773599999999998 36.850700000000003 97.488 +-10.688492 48.307125999999997 15.603847999999999 +-36.850700000000003 26.773599999999998 97.488 +42.325595999999997 -14.832011 45.549999999999997 +45.363821000000002 19.747043000000001 48.603847999999999 +46.725797 17.074024999999999 53.799999999999997 +46.725797 17.074024999999999 37.299999999999997 +-1.0267520000000001 44.837378999999999 86.799999999999997 +-3.9898180000000001 44.368076000000002 91.996151999999995 +-1.7992950000000001 49.715021999999998 86.799999999999997 +-39.601399999999998 28.772099999999998 97.920000000000002 +-44.368076000000002 -3.9898180000000001 7.3538480000000002 +-44.837378999999999 -1.0267520000000001 12.550000000000001 +40.963622999999998 -17.505030000000001 50.746152000000002 +46.725797 17.074024999999999 20.800000000000001 +-4.7623610000000003 49.245724000000003 91.996151999999995 +-46.554200000000002 15.1264 97.920000000000002 +46.350000000000001 0 98.159999999999997 +41.277892999999999 27.766093999999999 70.299999999999997 +42.639868999999997 25.093077000000001 65.103847999999999 +42.639868999999997 25.093077000000001 58.996152000000002 +-3.9898180000000001 44.368076000000002 81.603847999999999 +-49.049999999999997 0 97.872 +-44.368076000000002 -3.9898180000000001 17.746151999999999 +44.081449999999997 -14.322950000000001 98.159999999999997 +45.363821000000002 19.747043000000001 75.496151999999995 +-4.7623610000000003 49.245724000000003 81.603847999999999 +-48.950000000000003 0 97.920000000000002 +44.081449999999997 14.322950000000001 98.159999999999997 +42.639868999999997 25.093077000000001 75.496151999999995 +-43.429470999999999 -9.9159480000000002 7.3538480000000002 +-10.688492 48.307125999999997 81.603847999999999 +14.322950000000001 44.081449999999997 98.159999999999997 +40.450850000000003 29.389250000000001 96.239999999999995 +-2.1984650000000001 49.651800999999999 5 +-43.429470999999999 -9.9159480000000002 17.746151999999999 +27.243849999999998 37.497950000000003 98.159999999999997 +41.277892999999999 27.766093999999999 53.799999999999997 +-4.7623610000000003 49.245724000000003 9.4961520000000004 +-45.75 0 97.680000000000007 +-44.081449999999997 14.322950000000001 98.159999999999997 +42.639868999999997 25.093077000000001 48.603847999999999 +42.639868999999997 25.093077000000001 42.496152000000002 +-12.479844 43.023390999999997 5 +-44.368076000000002 -3.9898180000000001 23.853847999999999 +-44.837378999999999 -1.0267520000000001 29.050000000000001 +-46.350000000000001 0 98.159999999999997 +45.363821000000002 19.747043000000001 32.103847999999999 +-13.252389000000001 47.901049 5 +0 46.350000000000001 98.159999999999997 +45.363821000000002 19.747043000000001 58.996152000000002 +-29.306730000000002 33.549370000000003 15.603847999999999 +-33.549370000000003 29.306730000000002 15.603847999999999 +-29.306730000000002 33.549370000000003 9.4961520000000004 +-44.368076000000002 -3.9898180000000001 34.246152000000002 +46.725797 17.074024999999999 70.299999999999997 +45.363821000000002 19.747043000000001 65.103847999999999 +-35.670690999999998 27.185409 53.799999999999997 +-33.549370000000003 29.306730000000002 58.996152000000002 +-35.670690999999998 27.185409 70.299999999999997 +-42.797550000000001 -13.905749999999999 4.7999999999999998 +-17.505030000000001 40.963622999999998 17.746151999999999 +-22.851068000000001 38.239677999999998 17.746151999999999 +48.307125999999997 10.688492 83.746151999999995 +47.837826999999997 13.651558 45.549999999999997 +48.307125999999997 10.688492 17.746151999999999 +49.715021999999998 1.7992950000000001 29.050000000000001 +48.307125999999997 10.688492 23.853847999999999 +49.245724000000003 4.7623610000000003 56.853847999999999 +48.307125999999997 10.688492 40.353847999999999 +48.307125999999997 10.688492 34.246152000000002 +-48.399999999999999 0 98.256 +-45.888500000000001 14.91005 98.304000000000002 +48.307125999999997 10.688492 67.246151999999995 +48.307125999999997 10.688492 73.353847999999999 +49.245724000000003 4.7623610000000003 34.246152000000002 +49.245724000000003 4.7623610000000003 40.353847999999999 +49.715021999999998 1.7992950000000001 45.549999999999997 +48.399999999999999 0 98.256 +45.888500000000001 -14.91005 98.304000000000002 +46.031149999999997 -14.9564 98.256 +48.25 0 98.304000000000002 +47.505249999999997 -15.4354 96.384 +45.888500000000001 14.91005 98.304000000000002 +49.245724000000003 4.7623610000000003 73.353847999999999 +39.035049999999998 28.36065 98.304000000000002 +28.36065 39.035049999999998 98.304000000000002 +47.842343 13.623046 95 +40.963622999999998 -17.505030000000001 7.3538480000000002 +49.710507 1.827807 95 +38.239677999999998 -22.851068000000001 7.3538480000000002 +42.325595999999997 -14.832011 12.550000000000001 +14.91005 45.888500000000001 98.304000000000002 +49.245724000000003 4.7623610000000003 83.746151999999995 +0 48.25 98.304000000000002 +48.307125999999997 10.688492 89.853847999999999 +49.245724000000003 4.7623610000000003 89.853847999999999 +40.963622999999998 -17.505030000000001 17.746151999999999 +38.239677999999998 -22.851068000000001 17.746151999999999 +40.963622999999998 -17.505030000000001 23.853847999999999 +38.239677999999998 -22.851068000000001 23.853847999999999 +42.325595999999997 -14.832011 29.050000000000001 +41.277892999999999 27.766093999999999 20.800000000000001 +40.963622999999998 -17.505030000000001 34.246152000000002 +41.277892999999999 27.766093999999999 37.299999999999997 +42.639868999999997 25.093077000000001 15.603847999999999 +45.363821000000002 19.747043000000001 42.496152000000002 +42.639868999999997 25.093077000000001 25.996151999999999 +42.639868999999997 25.093077000000001 32.103847999999999 +45.363821000000002 19.747043000000001 25.996151999999999 +40.963622999999998 -17.505030000000001 40.353847999999999 +37.497950000000003 27.243849999999998 98.159999999999997 +-14.322950000000001 44.081449999999997 98.159999999999997 +-27.243849999999998 37.497950000000003 98.159999999999997 +-37.497950000000003 27.243849999999998 98.159999999999997 +38.954149999999998 28.301850000000002 98.304000000000002 +45.793349999999997 14.879149999999999 98.304000000000002 +28.301850000000002 38.954149999999998 98.304000000000002 +14.879149999999999 45.793349999999997 98.304000000000002 +45.363821000000002 19.747043000000001 15.603847999999999 +0 48.149999999999999 98.304000000000002 +-38.954149999999998 28.301850000000002 98.304000000000002 +-28.301850000000002 38.954149999999998 98.304000000000002 +48.149999999999999 0 98.304000000000002 +-48.149999999999999 0 98.304000000000002 +49.950000000000003 0 96.384 +30.697821999999999 39.142277999999997 95 +-14.879149999999999 45.793349999999997 98.304000000000002 +32.798729999999999 37.041370000000001 40.353847999999999 +43.429470999999999 -9.9159480000000002 15.603847999999999 +42.960169 -12.879013 20.800000000000001 +44.368076000000002 -3.9898180000000001 15.603847999999999 +44.837378999999999 -1.0267520000000001 20.800000000000001 +32.798729999999999 37.041370000000001 56.853847999999999 +44.368076000000002 -3.9898180000000001 25.996151999999999 +30.677409000000001 39.162691000000002 78.549999999999997 +43.429470999999999 -9.9159480000000002 25.996151999999999 +43.429470999999999 -9.9159480000000002 32.103847999999999 +42.960169 -12.879013 37.299999999999997 +32.798729999999999 37.041370000000001 73.353847999999999 +44.368076000000002 -3.9898180000000001 32.103847999999999 +44.837378999999999 -1.0267520000000001 37.299999999999997 +45.793349999999997 -14.879149999999999 98.304000000000002 +-45.793349999999997 14.879149999999999 98.304000000000002 +44.368076000000002 -3.9898180000000001 42.496152000000002 +39.162691000000002 30.677409000000001 78.549999999999997 +39.162691000000002 30.677409000000001 62.049999999999997 +43.429470999999999 -9.9159480000000002 42.496152000000002 +37.041370000000001 32.798729999999999 56.853847999999999 +43.429470999999999 -9.9159480000000002 48.603847999999999 +42.960169 -12.879013 53.799999999999997 +-46.5 0 98.207999999999998 +44.368076000000002 -3.9898180000000001 48.603847999999999 +44.837378999999999 -1.0267520000000001 53.799999999999997 +32.798729999999999 37.041370000000001 83.746151999999995 +37.041370000000001 32.798729999999999 83.746151999999995 +44.368076000000002 -3.9898180000000001 58.996152000000002 +37.041370000000001 32.798729999999999 73.353847999999999 +43.429470999999999 -9.9159480000000002 58.996152000000002 +39.142277999999997 30.697821999999999 95 +43.429470999999999 -9.9159480000000002 65.103847999999999 +37.041370000000001 32.798729999999999 89.853847999999999 +32.798729999999999 37.041370000000001 89.853847999999999 +42.960169 -12.879013 70.299999999999997 +44.368076000000002 -3.9898180000000001 65.103847999999999 +44.837378999999999 -1.0267520000000001 70.299999999999997 +47.505249999999997 -15.4354 96.480000000000004 +49.950000000000003 0 96.480000000000004 +44.368076000000002 -3.9898180000000001 75.496151999999995 +42.797550000000001 -13.905749999999999 4.7999999999999998 +36.405749999999998 -26.45035 4.7999999999999998 +46.5 0 98.207999999999998 +43.429470999999999 -9.9159480000000002 75.496151999999995 +44.224150000000002 -14.369300000000001 98.207999999999998 +44.224150000000002 14.369300000000001 98.207999999999998 +42.797550000000001 -13.905749999999999 95.760000000000005 +37.619300000000003 27.332000000000001 98.207999999999998 +17.074024999999999 46.725797 20.800000000000001 +25.093077000000001 42.639868999999997 32.103847999999999 +44.368076000000002 -3.9898180000000001 81.603847999999999 +27.332000000000001 37.619300000000003 98.207999999999998 +43.429470999999999 -9.9159480000000002 81.603847999999999 +44.837378999999999 -1.0267520000000001 86.799999999999997 +14.369300000000001 44.224150000000002 98.207999999999998 +0 46.5 98.207999999999998 +44.368076000000002 -3.9898180000000001 91.996151999999995 +-44.224150000000002 14.369300000000001 98.207999999999998 +43.429470999999999 -9.9159480000000002 91.996151999999995 +-14.369300000000001 44.224150000000002 98.207999999999998 +44.774157000000002 -1.4259219999999999 5 +-27.332000000000001 37.619300000000003 98.207999999999998 +27.766093999999999 41.277892999999999 37.299999999999997 +43.023390999999997 -12.479844 5 +43.429470999999999 -9.9159480000000002 9.4961520000000004 +-37.619300000000003 27.332000000000001 98.207999999999998 +42.325595999999997 -14.832011 62.049999999999997 +40.963622999999998 -17.505030000000001 56.853847999999999 +44.368076000000002 -3.9898180000000001 9.4961520000000004 +47.505249999999997 15.4354 96.384 +43.429470999999999 9.9159480000000002 17.746151999999999 +42.960169 12.879013 12.550000000000001 +44.837378999999999 1.0267520000000001 12.550000000000001 +44.368076000000002 3.9898180000000001 7.3538480000000002 +43.429470999999999 9.9159480000000002 7.3538480000000002 +43.429470999999999 9.9159480000000002 34.246152000000002 +42.960169 12.879013 29.050000000000001 +45.650700000000001 -14.832800000000001 98.352000000000004 +44.368076000000002 3.9898180000000001 34.246152000000002 +48 0 98.352000000000004 +44.837378999999999 1.0267520000000001 29.050000000000001 +45.650700000000001 14.832800000000001 98.352000000000004 +38.832799999999999 28.213699999999999 98.352000000000004 +28.213699999999999 38.832799999999999 98.352000000000004 +47.505249999999997 15.4354 96.480000000000004 +14.832800000000001 45.650700000000001 98.352000000000004 +45 0 4.7999999999999998 +43.429470999999999 9.9159480000000002 50.746152000000002 +0 48 98.352000000000004 +42.960169 12.879013 45.549999999999997 +44.368076000000002 3.9898180000000001 50.746152000000002 +-14.832800000000001 45.650700000000001 98.352000000000004 +45 0 95.760000000000005 +44.837378999999999 1.0267520000000001 45.549999999999997 +-28.213699999999999 38.832799999999999 98.352000000000004 +-38.832799999999999 28.213699999999999 98.352000000000004 +44.368076000000002 3.9898180000000001 40.353847999999999 +-45.650700000000001 14.832800000000001 98.352000000000004 +43.429470999999999 9.9159480000000002 40.353847999999999 +-48 0 98.352000000000004 +-46.600000000000001 0 98.256 +43.429470999999999 9.9159480000000002 67.246151999999995 +42.960169 12.879013 62.049999999999997 +44.368076000000002 3.9898180000000001 67.246151999999995 +44.837378999999999 1.0267520000000001 62.049999999999997 +44.368076000000002 3.9898180000000001 56.853847999999999 +43.429470999999999 9.9159480000000002 56.853847999999999 +43.429470999999999 9.9159480000000002 83.746151999999995 +42.960169 12.879013 78.549999999999997 +44.368076000000002 3.9898180000000001 83.746151999999995 +44.837378999999999 1.0267520000000001 78.549999999999997 +44.368076000000002 3.9898180000000001 73.353847999999999 +43.429470999999999 9.9159480000000002 73.353847999999999 +10.688492 48.307125999999997 73.353847999999999 +44.832863000000003 1.055264 95 +42.964685000000003 12.850501 95 +43.429470999999999 9.9159480000000002 89.853847999999999 +44.368076000000002 3.9898180000000001 89.853847999999999 +-13.651558 47.837826999999997 70.299999999999997 +-13.651558 47.837826999999997 86.799999999999997 +-4.7623610000000003 49.245724000000003 25.996151999999999 +-4.7623610000000003 49.245724000000003 32.103847999999999 +-1.7992950000000001 49.715021999999998 20.800000000000001 +-38.751899999999999 28.154900000000001 98.352000000000004 +-28.154900000000001 38.751899999999999 98.352000000000004 +-10.688492 48.307125999999997 32.103847999999999 +-13.651558 47.837826999999997 37.299999999999997 +-4.7623610000000003 49.245724000000003 15.603847999999999 +-47.899999999999999 0 98.352000000000004 +-4.7623610000000003 49.245724000000003 65.103847999999999 +-1.7992950000000001 49.715021999999998 53.799999999999997 +-4.7623610000000003 49.245724000000003 58.996152000000002 +-13.651558 47.837826999999997 53.799999999999997 +-14.8019 45.555599999999998 98.352000000000004 +-1.7992950000000001 49.715021999999998 37.299999999999997 +-10.688492 48.307125999999997 75.496151999999995 +0 47.899999999999999 98.352000000000004 +-10.688492 48.307125999999997 58.996152000000002 +-10.688492 48.307125999999997 65.103847999999999 +14.8019 45.555599999999998 98.352000000000004 +-4.7623610000000003 49.245724000000003 48.603847999999999 +-10.688492 48.307125999999997 42.496152000000002 +-10.688492 48.307125999999997 48.603847999999999 +47.899999999999999 0 98.352000000000004 +-4.7623610000000003 49.245724000000003 42.496152000000002 +45.555599999999998 -14.8019 98.352000000000004 +-4.7623610000000003 49.245724000000003 75.496151999999995 +-1.7992950000000001 49.715021999999998 70.299999999999997 +40.963622999999998 17.505030000000001 48.603847999999999 +-10.688492 48.307125999999997 91.996151999999995 +-10.688492 48.307125999999997 9.4961520000000004 +-45.555599999999998 14.8019 98.352000000000004 +-37.041370000000001 32.798729999999999 91.996151999999995 +33.549370000000003 29.306730000000002 40.353847999999999 +-32.798729999999999 37.041370000000001 15.603847999999999 +-30.963183000000001 38.876916999999999 5 +-32.798729999999999 37.041370000000001 9.4961520000000004 +27.205822000000001 35.650278 95 +-37.041370000000001 32.798729999999999 65.103847999999999 +-37.041370000000001 32.798729999999999 25.996151999999999 +-32.798729999999999 37.041370000000001 25.996151999999999 +-37.041370000000001 32.798729999999999 32.103847999999999 +29.306730000000002 33.549370000000003 83.746151999999995 +33.549370000000003 29.306730000000002 83.746151999999995 +29.306730000000002 33.549370000000003 89.853847999999999 +-37.041370000000001 32.798729999999999 15.603847999999999 +35.670690999999998 27.185409 78.549999999999997 +29.306730000000002 33.549370000000003 73.353847999999999 +-32.798729999999999 37.041370000000001 65.103847999999999 +-32.798729999999999 37.041370000000001 58.996152000000002 +-37.041370000000001 32.798729999999999 81.603847999999999 +-37.041370000000001 32.798729999999999 75.496151999999995 +-39.162691000000002 30.677409000000001 86.799999999999997 +-32.798729999999999 37.041370000000001 75.496151999999995 +-30.677409000000001 39.162691000000002 86.799999999999997 +-30.677409000000001 39.162691000000002 70.299999999999997 +-32.798729999999999 37.041370000000001 81.603847999999999 +-32.798729999999999 37.041370000000001 91.996151999999995 +33.549370000000003 29.306730000000002 89.853847999999999 +33.549370000000003 29.306730000000002 73.353847999999999 +-37.041370000000001 32.798729999999999 9.4961520000000004 +-38.876916999999999 30.963183000000001 5 +35.650278 27.205822000000001 95 +-3.9898180000000001 44.368076000000002 15.603847999999999 +-3.9898180000000001 44.368076000000002 25.996151999999999 +47.100000000000001 0 98.352000000000004 +-35.670690999999998 27.185409 20.800000000000001 +-36.405749999999998 26.45035 4.7999999999999998 +-26.45035 36.405749999999998 4.7999999999999998 +-26.45035 36.405749999999998 95.760000000000005 +-27.185409 35.670690999999998 20.800000000000001 +-44.837378999999999 -1.0267520000000001 45.549999999999997 +-27.471183 35.384917000000002 5 +-36.405749999999998 26.45035 95.760000000000005 +-33.549370000000003 29.306730000000002 9.4961520000000004 +-33.549370000000003 29.306730000000002 25.996151999999999 +-35.670690999999998 27.185409 37.299999999999997 +-35.384917000000002 27.471183 5 +-33.549370000000003 29.306730000000002 42.496152000000002 +-9.9159480000000002 43.429470999999999 48.603847999999999 +-3.9898180000000001 44.368076000000002 58.996152000000002 +-1.0267520000000001 44.837378999999999 70.299999999999997 +-3.9898180000000001 44.368076000000002 65.103847999999999 +-9.9159480000000002 43.429470999999999 9.4961520000000004 +-25.524087000000002 36.877704999999999 12.550000000000001 +-14.832011 42.325595999999997 12.550000000000001 +-17.505030000000001 40.963622999999998 7.3538480000000002 +-22.851068000000001 38.239677999999998 7.3538480000000002 +-17.505030000000001 40.963622999999998 34.246152000000002 +-22.851068000000001 38.239677999999998 34.246152000000002 +-25.524087000000002 36.877704999999999 29.050000000000001 +-14.832011 42.325595999999997 29.050000000000001 +-17.505030000000001 40.963622999999998 23.853847999999999 +-22.851068000000001 38.239677999999998 23.853847999999999 +-17.505030000000001 40.963622999999998 50.746152000000002 +-22.851068000000001 38.239677999999998 50.746152000000002 +-25.524087000000002 36.877704999999999 45.549999999999997 +-14.832011 42.325595999999997 45.549999999999997 +-17.505030000000001 40.963622999999998 40.353847999999999 +-22.851068000000001 38.239677999999998 40.353847999999999 +-17.505030000000001 40.963622999999998 67.246151999999995 +-22.851068000000001 38.239677999999998 67.246151999999995 +-25.524087000000002 36.877704999999999 62.049999999999997 +-14.832011 42.325595999999997 62.049999999999997 +-17.505030000000001 40.963622999999998 56.853847999999999 +-22.851068000000001 38.239677999999998 56.853847999999999 +-17.505030000000001 40.963622999999998 83.746151999999995 +-22.851068000000001 38.239677999999998 83.746151999999995 +-25.524087000000002 36.877704999999999 78.549999999999997 +-14.832011 42.325595999999997 78.549999999999997 +-17.505030000000001 40.963622999999998 73.353847999999999 +-22.851068000000001 38.239677999999998 73.353847999999999 +-25.498366000000001 36.890810999999999 95 +-22.851068000000001 38.239677999999998 89.853847999999999 +-14.857732 42.312489999999997 95 +-17.505030000000001 40.963622999999998 89.853847999999999 +-29.306730000000002 33.549370000000003 25.996151999999999 +-29.306730000000002 33.549370000000003 42.496152000000002 +-27.185409 35.670690999999998 37.299999999999997 +-29.306730000000002 33.549370000000003 32.103847999999999 +-33.549370000000003 29.306730000000002 32.103847999999999 +-29.306730000000002 33.549370000000003 58.996152000000002 +-27.185409 35.670690999999998 53.799999999999997 +-29.306730000000002 33.549370000000003 48.603847999999999 +-33.549370000000003 29.306730000000002 48.603847999999999 +-29.306730000000002 33.549370000000003 75.496151999999995 +-33.549370000000003 29.306730000000002 75.496151999999995 +-27.185409 35.670690999999998 70.299999999999997 +-29.306730000000002 33.549370000000003 65.103847999999999 +-33.549370000000003 29.306730000000002 65.103847999999999 +-29.306730000000002 33.549370000000003 91.996151999999995 +-33.549370000000003 29.306730000000002 91.996151999999995 +-35.670690999999998 27.185409 86.799999999999997 +-27.185409 35.670690999999998 86.799999999999997 +-29.306730000000002 33.549370000000003 81.603847999999999 +-33.549370000000003 29.306730000000002 81.603847999999999 +-15.41995 47.457700000000003 96.623999999999995 +-29.330500000000001 40.369950000000003 96.623999999999995 +-40.369950000000003 29.330500000000001 96.623999999999995 +-47.457700000000003 15.41995 96.623999999999995 +-49.899999999999999 0 96.623999999999995 +-26.45035 -36.405749999999998 4.7999999999999998 +-36.405749999999998 -26.45035 4.7999999999999998 +-13.905749999999999 -42.797550000000001 4.7999999999999998 +0 -45 4.7999999999999998 +13.905749999999999 -42.797550000000001 4.7999999999999998 +26.45035 -36.405749999999998 4.7999999999999998 +-42.797550000000001 13.905749999999999 96.239999999999995 +-45 0 96.239999999999995 +-36.405749999999998 26.45035 96.239999999999995 +0 49.899999999999999 96.623999999999995 +-26.45035 36.405749999999998 96.239999999999995 +-15.41995 47.457700000000003 96.719999999999999 +0 49.899999999999999 96.719999999999999 +-29.330500000000001 40.369950000000003 96.719999999999999 +-40.369950000000003 29.330500000000001 96.719999999999999 +-47.457700000000003 15.41995 96.719999999999999 +-49.899999999999999 0 96.719999999999999 +-45.049999999999997 0 96.384 +-42.845100000000002 13.921200000000001 96.384 +-26.479749999999999 36.446199999999997 96.384 +-36.446199999999997 26.479749999999999 96.384 +47.457700000000003 -15.41995 96.623999999999995 +49.899999999999999 0 96.623999999999995 +45 0 96.239999999999995 +42.797550000000001 -13.905749999999999 96.239999999999995 +47.457700000000003 15.41995 96.623999999999995 +42.797550000000001 13.905749999999999 96.239999999999995 +40.369950000000003 29.330500000000001 96.623999999999995 +29.330500000000001 40.369950000000003 96.623999999999995 +36.405749999999998 26.45035 96.239999999999995 +15.41995 47.457700000000003 96.623999999999995 +26.45035 36.405749999999998 96.239999999999995 +13.905749999999999 42.797550000000001 96.239999999999995 +0 45 96.239999999999995 +-13.905749999999999 42.797550000000001 96.239999999999995 +15.41995 47.457700000000003 96.719999999999999 +15.404500000000001 47.410150000000002 96.864000000000004 +0 49.850000000000001 96.864000000000004 +-15.404500000000001 47.410150000000002 96.864000000000004 +-29.301100000000002 40.329500000000003 96.864000000000004 +-40.329500000000003 29.301100000000002 96.864000000000004 +-47.410150000000002 15.404500000000001 96.864000000000004 +-49.850000000000001 0 96.864000000000004 +-45.049999999999997 0 96.480000000000004 +-42.845100000000002 13.921200000000001 96.480000000000004 +-36.446199999999997 26.479749999999999 96.480000000000004 +-26.479749999999999 36.446199999999997 96.480000000000004 +-13.921200000000001 42.845100000000002 96.384 +-13.921200000000001 42.845100000000002 96.480000000000004 +47.457700000000003 -15.41995 96.719999999999999 +49.899999999999999 0 96.719999999999999 +45.049999999999997 0 96.384 +42.845100000000002 -13.921200000000001 96.384 +47.457700000000003 15.41995 96.719999999999999 +42.845100000000002 13.921200000000001 96.384 +40.369950000000003 29.330500000000001 96.719999999999999 +36.446199999999997 26.479749999999999 96.384 +29.330500000000001 40.369950000000003 96.719999999999999 +26.479749999999999 36.446199999999997 96.384 +13.921200000000001 42.845100000000002 96.384 +0 45.049999999999997 96.384 +29.301100000000002 40.329500000000003 96.864000000000004 +29.271699999999999 40.289050000000003 96.959999999999994 +15.389049999999999 47.3626 96.959999999999994 +0 49.799999999999997 96.959999999999994 +-15.389049999999999 47.3626 96.959999999999994 +-29.271699999999999 40.289050000000003 96.959999999999994 +-40.289050000000003 29.271699999999999 96.959999999999994 +-47.3626 15.389049999999999 96.959999999999994 +-49.799999999999997 0 96.959999999999994 +-45.100000000000001 0 96.623999999999995 +-42.892650000000003 13.93665 96.623999999999995 +-26.5091 36.486649999999997 96.623999999999995 +-36.486649999999997 26.5091 96.623999999999995 +0 45.049999999999997 96.480000000000004 +-13.93665 42.892650000000003 96.623999999999995 +47.410150000000002 -15.404500000000001 96.864000000000004 +49.850000000000001 0 96.864000000000004 +42.845100000000002 -13.921200000000001 96.480000000000004 +45.049999999999997 0 96.480000000000004 +42.845100000000002 13.921200000000001 96.480000000000004 +47.410150000000002 15.404500000000001 96.864000000000004 +36.446199999999997 26.479749999999999 96.480000000000004 +40.329500000000003 29.301100000000002 96.864000000000004 +26.479749999999999 36.446199999999997 96.480000000000004 +13.921200000000001 42.845100000000002 96.480000000000004 +40.289050000000003 29.271699999999999 96.959999999999994 +29.2423 40.248600000000003 97.103999999999999 +40.248600000000003 29.2423 97.103999999999999 +15.3736 47.315049999999999 97.103999999999999 +0 49.75 97.103999999999999 +-15.3736 47.315049999999999 97.103999999999999 +-29.2423 40.248600000000003 97.103999999999999 +-40.248600000000003 29.2423 97.103999999999999 +-47.315049999999999 15.3736 97.103999999999999 +-49.75 0 97.103999999999999 +-45.100000000000001 0 96.719999999999999 +-42.892650000000003 13.93665 96.719999999999999 +-36.486649999999997 26.5091 96.719999999999999 +-26.5091 36.486649999999997 96.719999999999999 +-13.93665 42.892650000000003 96.719999999999999 +0 45.100000000000001 96.623999999999995 +0 45.100000000000001 96.719999999999999 +47.3626 -15.389049999999999 96.959999999999994 +45.100000000000001 0 96.623999999999995 +42.892650000000003 -13.93665 96.623999999999995 +49.799999999999997 0 96.959999999999994 +42.892650000000003 13.93665 96.623999999999995 +36.486649999999997 26.5091 96.623999999999995 +47.3626 15.389049999999999 96.959999999999994 +26.5091 36.486649999999997 96.623999999999995 +13.93665 42.892650000000003 96.623999999999995 +47.315049999999999 15.3736 97.103999999999999 +47.219949999999997 15.342700000000001 97.200000000000003 +40.167700000000004 29.18355 97.200000000000003 +29.18355 40.167700000000004 97.200000000000003 +15.342700000000001 47.219949999999997 97.200000000000003 +0 49.649999999999999 97.200000000000003 +-15.342700000000001 47.219949999999997 97.200000000000003 +-29.18355 40.167700000000004 97.200000000000003 +-40.167700000000004 29.18355 97.200000000000003 +-47.219949999999997 15.342700000000001 97.200000000000003 +-49.649999999999999 0 97.200000000000003 +-45.149999999999999 0 96.864000000000004 +-42.940199999999997 13.9521 96.864000000000004 +-26.538499999999999 36.527099999999997 96.864000000000004 +-36.527099999999997 26.538499999999999 96.864000000000004 +-13.9521 42.940199999999997 96.864000000000004 +13.93665 42.892650000000003 96.719999999999999 +0 45.149999999999999 96.864000000000004 +42.892650000000003 -13.93665 96.719999999999999 +45.100000000000001 0 96.719999999999999 +47.315049999999999 -15.3736 97.103999999999999 +42.892650000000003 13.93665 96.719999999999999 +49.75 0 97.103999999999999 +36.486649999999997 26.5091 96.719999999999999 +26.5091 36.486649999999997 96.719999999999999 +49.649999999999999 0 97.200000000000003 +49.600000000000001 0 97.296000000000006 +47.172400000000003 15.327249999999999 97.296000000000006 +40.127249999999997 29.154150000000001 97.296000000000006 +29.154150000000001 40.127249999999997 97.296000000000006 +15.327249999999999 47.172400000000003 97.296000000000006 +0 49.600000000000001 97.296000000000006 +-15.327249999999999 47.172400000000003 97.296000000000006 +-29.154150000000001 40.127249999999997 97.296000000000006 +-40.127249999999997 29.154150000000001 97.296000000000006 +-47.172400000000003 15.327249999999999 97.296000000000006 +-49.600000000000001 0 97.296000000000006 +-45.200000000000003 0 96.959999999999994 +-42.987749999999998 13.967549999999999 96.959999999999994 +-26.567900000000002 36.567549999999997 96.959999999999994 +-36.567549999999997 26.567900000000002 96.959999999999994 +-13.967549999999999 42.987749999999998 96.959999999999994 +13.9521 42.940199999999997 96.864000000000004 +0 45.200000000000003 96.959999999999994 +45.149999999999999 0 96.864000000000004 +42.940199999999997 -13.9521 96.864000000000004 +42.940199999999997 13.9521 96.864000000000004 +47.219949999999997 -15.342700000000001 97.200000000000003 +36.527099999999997 26.538499999999999 96.864000000000004 +26.538499999999999 36.527099999999997 96.864000000000004 +47.172400000000003 -15.327249999999999 97.296000000000006 +47.077300000000001 -15.29635 97.391999999999996 +49.5 0 97.391999999999996 +47.077300000000001 15.29635 97.391999999999996 +40.046349999999997 29.09535 97.391999999999996 +29.09535 40.046349999999997 97.391999999999996 +15.29635 47.077300000000001 97.391999999999996 +0 49.5 97.391999999999996 +-15.29635 47.077300000000001 97.391999999999996 +-29.09535 40.046349999999997 97.391999999999996 +-40.046349999999997 29.09535 97.391999999999996 +-47.077300000000001 15.29635 97.391999999999996 +-49.5 0 97.391999999999996 +-45.25 0 97.103999999999999 +-43.035299999999999 13.983000000000001 97.103999999999999 +-26.597300000000001 36.607999999999997 97.103999999999999 +-36.607999999999997 26.597300000000001 97.103999999999999 +-13.983000000000001 43.035299999999999 97.103999999999999 +13.967549999999999 42.987749999999998 96.959999999999994 +0 45.25 97.103999999999999 +45.200000000000003 0 96.959999999999994 +42.987749999999998 -13.967549999999999 96.959999999999994 +42.987749999999998 13.967549999999999 96.959999999999994 +-14.0139 43.130400000000002 97.200000000000003 +0 45.350000000000001 97.200000000000003 +45.25 0 97.103999999999999 +43.035299999999999 -13.983000000000001 97.103999999999999 +45.350000000000001 0 97.200000000000003 +43.130400000000002 -14.0139 97.200000000000003 +43.035299999999999 13.983000000000001 97.103999999999999 +45.549999999999997 0 97.488 +43.320599999999999 -14.075699999999999 97.488 +43.320599999999999 14.075699999999999 97.488 +-14.075699999999999 43.320599999999999 97.488 +36.850700000000003 26.773599999999998 97.488 +14.06025 43.273049999999998 97.391999999999996 +0 45.549999999999997 97.488 +26.744250000000001 36.810250000000003 97.391999999999996 +26.773599999999998 36.850700000000003 97.488 +46.554200000000002 -15.1264 97.920000000000002 +48.950000000000003 0 97.920000000000002 +46.554200000000002 15.1264 97.920000000000002 +39.601399999999998 28.772099999999998 97.920000000000002 +28.772099999999998 39.601399999999998 97.920000000000002 +15.1264 46.554200000000002 97.920000000000002 +0 48.950000000000003 97.920000000000002 +-15.1264 46.554200000000002 97.920000000000002 +-28.772099999999998 39.601399999999998 97.920000000000002 +-43.510849999999998 14.137549999999999 97.680000000000007 +45.75 0 97.680000000000007 +43.510849999999998 -14.137549999999999 97.680000000000007 +-26.891200000000001 37.012549999999997 97.680000000000007 +-37.012549999999997 26.891200000000001 97.680000000000007 +43.510849999999998 14.137549999999999 97.680000000000007 +37.012549999999997 26.891200000000001 97.680000000000007 +-14.137549999999999 43.510849999999998 97.680000000000007 +26.891200000000001 37.012549999999997 97.680000000000007 +14.075699999999999 43.320599999999999 97.488 +0 45.75 97.680000000000007 +14.137549999999999 43.510849999999998 97.680000000000007 +46.459099999999999 -15.095499999999999 98.016000000000005 +48.850000000000001 0 98.016000000000005 +46.459099999999999 15.095499999999999 98.016000000000005 +39.520499999999998 28.7133 98.016000000000005 +28.7133 39.520499999999998 98.016000000000005 +15.095499999999999 46.459099999999999 98.016000000000005 +0 48.850000000000001 98.016000000000005 +-15.095499999999999 46.459099999999999 98.016000000000005 +-28.7133 39.520499999999998 98.016000000000005 +-39.520499999999998 28.7133 98.016000000000005 +-46.459099999999999 15.095499999999999 98.016000000000005 +-48.850000000000001 0 98.016000000000005 +-45.850000000000001 0 97.775999999999996 +-43.60595 14.16845 97.775999999999996 +45.850000000000001 0 97.775999999999996 +43.60595 -14.16845 97.775999999999996 +43.60595 14.16845 97.775999999999996 +-26.949950000000001 37.093449999999997 97.775999999999996 +-37.093449999999997 26.949950000000001 97.775999999999996 +37.093449999999997 26.949950000000001 97.775999999999996 +26.949950000000001 37.093449999999997 97.775999999999996 +-14.16845 43.60595 97.775999999999996 +14.16845 43.60595 97.775999999999996 +0 45.850000000000001 97.775999999999996 +46.363999999999997 -15.0646 98.063999999999993 +48.75 0 98.063999999999993 +46.363999999999997 15.0646 98.063999999999993 +39.439599999999999 28.65455 98.063999999999993 +28.65455 39.439599999999999 98.063999999999993 +15.0646 46.363999999999997 98.063999999999993 +0 48.75 98.063999999999993 +-15.0646 46.363999999999997 98.063999999999993 +-28.65455 39.439599999999999 98.063999999999993 +-39.439599999999999 28.65455 98.063999999999993 +-46.363999999999997 15.0646 98.063999999999993 +-48.75 0 98.063999999999993 +-45.950000000000003 0 97.872 +45.950000000000003 0 97.872 +43.701050000000002 -14.199350000000001 97.872 +-43.701050000000002 14.199350000000001 97.872 +43.701050000000002 14.199350000000001 97.872 +37.174349999999997 27.008749999999999 97.872 +-27.008749999999999 37.174349999999997 97.872 +-37.174349999999997 27.008749999999999 97.872 +27.008749999999999 37.174349999999997 97.872 +14.199350000000001 43.701050000000002 97.872 +-14.199350000000001 43.701050000000002 97.872 +0 45.950000000000003 97.872 +46.268900000000002 -15.0337 98.159999999999997 +48.649999999999999 0 98.159999999999997 +46.268900000000002 15.0337 98.159999999999997 +39.358699999999999 28.595749999999999 98.159999999999997 +28.595749999999999 39.358699999999999 98.159999999999997 +15.0337 46.268900000000002 98.159999999999997 +0 48.649999999999999 98.159999999999997 +-15.0337 46.268900000000002 98.159999999999997 +-28.595749999999999 39.358699999999999 98.159999999999997 +-39.358699999999999 28.595749999999999 98.159999999999997 +-46.268900000000002 15.0337 98.159999999999997 +-48.649999999999999 0 98.159999999999997 +-46.049999999999997 0 97.920000000000002 +43.796149999999997 -14.23025 97.920000000000002 +14.23025 43.796149999999997 97.920000000000002 +0 46.049999999999997 97.920000000000002 +46.126249999999999 -14.987299999999999 98.207999999999998 +48.5 0 98.207999999999998 +28.5076 39.237299999999998 98.207999999999998 +-48.5 0 98.207999999999998 +14.5547 44.794750000000001 98.352000000000004 +0 47.100000000000001 98.352000000000004 +-14.5547 44.794750000000001 98.352000000000004 +-27.684699999999999 38.104700000000001 98.352000000000004 +-38.104700000000001 27.684699999999999 98.352000000000004 +-44.794750000000001 14.5547 98.352000000000004 +-47.100000000000001 0 98.352000000000004 +-45 0 95.760000000000005 +42.797550000000001 -13.905749999999999 95.760000000000005 +3 274 152 314 +3 37 193 199 +3 170 225 315 +3 316 317 285 +3 270 310 268 +3 309 312 271 +3 37 199 173 +3 170 194 231 +3 318 316 294 +3 319 311 310 +3 320 321 272 +3 232 173 322 +3 228 216 309 +3 323 318 301 +3 324 319 310 +3 272 321 273 +3 173 232 167 +3 228 309 226 +3 325 323 326 +3 327 319 324 +3 328 306 320 +3 329 308 330 +3 331 332 273 +3 333 334 335 +3 256 327 324 +3 320 306 321 +3 330 336 337 +3 245 266 243 +3 317 338 286 +3 339 340 337 +3 328 341 306 +3 193 4 257 +3 307 216 248 +3 337 340 330 +3 306 341 307 +3 193 257 184 +3 307 312 216 +3 342 343 344 +3 345 329 340 +3 307 341 313 +3 263 346 219 +3 347 348 349 +3 315 306 248 +3 340 329 330 +3 312 307 313 +3 350 308 329 +3 315 225 306 +3 351 333 335 +3 352 339 349 +3 353 354 243 +3 310 232 324 +3 309 273 332 +3 351 342 333 +3 349 339 337 +3 332 353 243 +3 347 337 355 +3 356 357 358 +3 359 250 242 +3 332 266 226 +3 335 334 360 +3 348 361 352 +3 331 362 353 +3 232 310 167 +3 309 332 226 +3 334 363 360 +3 349 348 352 +3 332 331 353 +3 355 337 336 +3 364 365 357 +3 366 359 242 +3 367 368 225 +3 360 363 369 +3 370 361 348 +3 371 244 354 +3 261 372 373 +3 321 306 374 +3 369 325 326 +3 350 370 348 +3 354 244 243 +3 336 4 260 +3 375 376 377 +3 378 366 242 +3 379 273 321 +3 326 323 301 +3 345 370 350 +3 380 374 371 +3 350 270 308 +3 376 381 377 +3 382 383 384 +3 306 225 374 +3 301 318 294 +3 329 345 350 +3 371 374 244 +3 257 4 330 +3 385 386 365 +3 387 378 242 +3 368 374 225 +3 294 316 285 +3 388 389 390 +3 380 391 374 +3 324 213 184 +3 364 385 365 +3 392 393 378 +3 332 243 266 +3 285 317 286 +3 390 389 336 +3 374 391 379 +3 336 260 390 +3 394 245 244 +3 286 338 395 +3 396 355 389 +3 379 391 362 +3 257 330 308 +3 367 225 224 +3 389 355 336 +3 331 379 362 +3 280 397 263 +3 348 310 350 +3 398 399 400 +3 387 392 378 +3 368 394 244 +3 363 325 369 +3 401 388 402 +3 403 404 224 +3 397 346 263 +3 270 350 310 +3 399 405 375 +3 406 407 392 +3 379 331 273 +3 402 388 390 +3 266 403 224 +3 402 408 409 +3 374 379 321 +3 409 410 401 +3 245 411 403 +3 310 348 167 +3 412 230 209 +3 402 409 401 +3 266 245 403 +3 347 349 337 +3 244 374 368 +3 413 410 409 +3 414 367 404 +3 256 184 257 +3 239 412 209 +3 347 413 409 +3 404 367 224 +3 415 416 279 +3 330 4 336 +3 312 309 216 +3 396 413 347 +3 417 368 414 +3 416 418 280 +3 324 184 256 +3 239 231 419 +3 355 396 347 +3 414 368 367 +3 279 416 280 +3 373 167 408 +3 239 420 412 +3 338 421 395 +3 422 423 261 +3 417 424 368 +3 418 397 280 +3 390 425 402 +3 387 406 392 +3 239 419 420 +3 426 333 342 +3 261 423 260 +3 368 424 394 +3 348 347 409 +3 258 234 164 +3 427 425 423 +3 394 424 411 +3 348 409 167 +3 163 170 258 +3 423 425 260 +3 245 394 411 +3 428 429 430 +3 425 390 260 +3 194 209 230 +3 431 422 373 +3 432 230 433 +3 430 429 434 +3 435 402 425 +3 436 437 206 +3 373 422 261 +3 433 230 412 +3 438 439 415 +3 372 4 275 +3 206 437 207 +3 408 440 431 +3 441 433 412 +3 439 416 415 +3 409 408 167 +3 442 226 443 +3 373 408 431 +3 420 441 412 +3 444 445 428 +3 446 373 372 +3 447 448 449 +3 344 426 342 +3 450 440 408 +3 451 419 432 +3 430 444 428 +3 261 4 372 +3 452 453 454 +3 455 456 267 +3 435 450 408 +3 432 419 230 +3 457 458 459 +3 408 402 435 +3 460 461 462 +3 267 463 464 +3 427 450 435 +3 419 451 441 +3 457 438 458 +3 465 275 167 +3 239 226 466 +3 456 463 267 +3 425 427 435 +3 420 419 441 +3 467 439 438 +3 373 446 167 +3 462 239 468 +3 469 470 455 +3 471 372 472 +3 473 13 206 +3 467 438 457 +3 446 465 167 +3 474 475 443 +3 476 469 455 +3 472 372 275 +3 473 206 32 +3 322 173 199 +3 462 468 460 +3 470 456 455 +3 477 472 465 +3 478 479 480 +3 213 324 232 +3 462 461 443 +3 481 469 476 +3 465 472 275 +3 480 479 449 +3 167 4 168 +3 482 483 484 +3 304 485 481 +3 486 477 465 +3 487 480 449 +3 168 4 488 +3 466 226 489 +3 485 469 481 +3 446 486 465 +3 461 487 449 +3 490 491 492 +3 4 3 488 +3 493 494 495 +3 496 485 304 +3 471 486 446 +3 497 466 478 +3 445 490 492 +3 488 3 498 +3 449 479 447 +3 499 192 208 +3 168 500 305 +3 497 501 466 +3 444 502 445 +3 503 504 40 +3 461 448 443 +3 499 496 192 +3 305 500 505 +3 466 501 468 +3 506 459 491 +3 40 504 15 +3 461 449 448 +3 507 208 227 +3 488 508 168 +3 468 501 509 +3 490 506 491 +3 510 30 504 +3 511 493 512 +3 513 507 227 +3 168 508 500 +3 460 468 509 +3 504 30 15 +3 489 514 515 +3 507 499 208 +3 498 516 488 +3 460 509 487 +3 506 457 459 +3 517 503 24 +3 518 519 520 +3 393 382 384 +3 489 226 514 +3 513 227 241 +3 488 516 508 +3 461 460 487 +3 24 503 40 +3 519 521 520 +3 384 378 393 +3 522 515 523 +3 26 524 517 +3 523 515 525 +3 24 26 517 +3 484 442 443 +3 526 527 528 +3 529 530 531 +3 532 523 525 +3 533 524 26 +3 448 534 443 +3 528 535 526 +3 533 536 537 +3 448 532 525 +3 45 533 26 +3 538 539 540 +3 541 242 237 +3 534 452 474 +3 542 504 1396 +3 543 489 522 +3 510 533 45 +3 538 544 539 +3 545 546 237 +3 466 468 239 +3 528 527 547 +3 548 549 550 +3 522 489 515 +3 30 510 45 +3 544 551 539 +3 552 242 553 +3 483 495 226 +3 554 555 524 +3 543 556 489 +3 557 558 88 +3 544 559 551 +3 560 545 561 +3 514 226 494 +3 537 530 524 +3 489 556 562 +3 88 558 41 +3 551 559 563 +3 387 242 552 +3 454 474 452 +3 564 558 503 +3 562 556 565 +3 564 39 558 +3 559 566 563 +3 552 567 568 +3 475 482 443 +3 542 510 504 +3 447 562 565 +3 172 569 165 +3 558 39 41 +3 534 474 443 +3 536 570 537 +3 447 565 532 +3 571 569 172 +3 572 557 107 +3 566 573 574 +3 575 576 577 +3 494 578 453 +3 504 558 1396 +3 448 447 532 +3 172 186 571 +3 107 557 88 +3 579 566 574 +3 580 567 560 +3 581 484 483 +3 504 503 558 +3 582 453 583 +3 186 584 571 +3 72 554 572 +3 573 585 574 +3 586 545 237 +3 583 453 452 +3 186 201 584 +3 107 72 572 +3 574 585 587 +3 588 561 545 +3 589 590 515 +3 591 592 572 +3 593 583 452 +3 201 594 584 +3 555 554 72 +3 376 595 381 +3 596 597 387 +3 494 226 495 +3 555 503 517 +3 534 593 452 +3 210 598 594 +3 25 555 72 +3 568 577 596 +3 514 589 515 +3 524 530 554 +3 599 514 582 +3 201 210 594 +3 564 555 25 +3 387 552 568 +3 600 226 442 +3 524 533 537 +3 582 514 453 +3 210 236 598 +3 39 564 25 +3 601 602 586 +3 483 226 600 +3 558 557 603 +3 599 604 514 +3 236 605 598 +3 606 603 80 +3 607 608 609 +3 483 600 581 +3 558 603 1396 +3 514 604 589 +3 236 249 605 +3 80 603 95 +3 610 611 607 +3 495 612 493 +3 613 614 606 +3 589 604 615 +3 249 616 605 +3 617 89 603 +3 586 588 545 +3 590 589 615 +3 249 618 616 +3 603 89 95 +3 608 619 588 +3 489 562 466 +3 211 104 120 +3 552 838 839 +3 803 829 801 +3 129 217 136 +3 553 546 840 +3 801 827 795 +3 211 145 217 +3 838 553 840 +3 795 826 794 +3 145 136 217 +3 546 545 841 +3 794 824 792 +3 108 221 129 +3 840 546 841 +3 792 825 790 +3 217 129 742 +3 841 545 560 +3 790 832 788 +3 842 252 293 +3 843 841 560 +3 252 842 251 +3 560 567 843 +3 836 829 803 +3 293 844 283 +3 843 567 845 +3 120 104 187 +3 567 552 845 +3 120 187 110 +3 845 552 839 +3 221 108 238 +3 580 846 568 +3 110 238 108 +3 568 846 847 +3 283 848 281 +3 580 561 849 +3 254 293 252 +3 846 580 849 +3 129 203 742 +3 561 588 850 +3 832 851 788 +3 837 176 254 +3 849 561 850 +3 852 830 781 +3 187 104 254 +3 850 588 619 +3 238 110 187 +3 853 850 619 +3 277 174 837 +3 619 577 853 +3 281 854 855 +3 853 577 856 +3 174 277 203 +3 577 568 856 +3 203 276 742 +3 856 568 847 +3 857 251 842 +3 576 858 596 +3 833 852 781 +3 254 104 293 +3 596 858 859 +3 749 860 755 +3 187 254 176 +3 576 575 861 +3 276 857 855 +3 858 576 861 +3 276 855 742 +3 575 608 862 +3 844 104 863 +3 861 575 862 +3 857 276 251 +3 862 608 607 +3 864 742 854 +3 865 862 607 +3 854 281 866 +3 607 611 865 +3 866 281 848 +3 865 611 867 +3 855 854 742 +3 611 596 867 +3 835 742 868 +3 867 596 859 +3 863 104 835 +3 622 869 597 +3 870 863 871 +3 597 869 872 +3 863 835 871 +3 622 610 873 +3 868 742 870 +3 869 622 873 +3 864 863 870 +3 610 609 874 +3 864 870 742 +3 873 610 874 +3 875 791 834 +3 145 211 120 +3 874 609 625 +3 876 875 834 +3 293 104 844 +3 877 874 625 +3 806 808 800 +3 276 203 277 +3 625 624 877 +3 799 878 879 +3 726 733 880 +3 848 283 844 +3 877 624 881 +3 800 878 797 +3 880 733 882 +3 203 129 221 +3 883 737 726 +3 353 105 403 +3 880 883 726 +3 414 105 104 +3 884 878 800 +3 885 820 737 +3 202 105 886 +3 883 885 737 +3 171 887 169 +3 626 648 888 +3 889 745 820 +3 202 886 200 +3 890 626 888 +3 885 889 820 +3 451 211 202 +3 648 602 891 +3 892 741 745 +3 235 162 214 +3 888 648 891 +3 889 892 745 +3 451 185 211 +3 891 602 601 +3 810 800 808 +3 893 758 741 +3 211 169 104 +3 894 891 601 +3 884 800 810 +3 892 893 741 +3 887 162 235 +3 601 666 894 +3 823 895 749 +3 886 105 214 +3 894 666 896 +3 895 860 749 +3 886 214 162 +3 893 897 758 +3 391 328 320 +3 758 897 821 +3 271 105 353 +3 541 632 898 +3 810 812 819 +3 821 899 822 +3 169 900 104 +3 901 541 898 +3 897 899 821 +3 411 354 403 +3 678 541 902 +3 884 810 712 +3 899 903 823 +3 391 272 362 +3 902 541 901 +3 822 899 823 +3 341 215 313 +3 898 632 686 +3 904 712 905 +3 903 895 823 +3 214 105 271 +3 906 898 686 +3 808 806 809 +3 887 171 162 +3 686 678 906 +3 362 272 353 +3 906 678 902 +3 341 247 215 +3 690 907 834 +3 328 900 341 +3 690 742 907 +3 247 341 900 +3 689 774 908 +3 900 328 104 +3 909 689 908 +3 712 722 905 +3 424 371 411 +3 698 9 774 +3 884 712 904 +3 353 403 354 +3 774 9 908 +3 214 271 215 +3 697 910 698 +3 391 320 272 +3 698 910 9 +3 271 353 272 +3 697 703 910 +3 712 810 819 +3 417 371 424 +3 910 703 911 +3 328 391 380 +3 911 703 700 +3 328 380 104 +3 912 911 700 +3 414 104 417 +3 912 700 689 +3 403 105 404 +3 909 912 689 +3 371 417 380 +3 696 779 913 +3 417 104 380 +3 914 696 913 +3 832 915 851 +3 354 411 371 +3 784 916 779 +3 917 915 832 +3 404 105 414 +3 779 916 913 +3 832 825 917 +3 433 200 432 +3 775 918 784 +3 825 919 917 +3 441 200 433 +3 784 918 916 +3 797 878 799 +3 825 824 919 +3 202 200 441 +3 775 699 918 +3 824 920 919 +3 432 185 451 +3 918 699 10 +3 826 921 920 +3 900 169 887 +3 10 699 776 +3 807 809 806 +3 824 826 920 +3 169 211 185 +3 8 10 776 +3 834 907 922 +3 826 827 921 +3 313 215 271 +3 8 776 696 +3 876 834 922 +3 827 923 921 +3 451 202 441 +3 914 8 696 +3 901 924 878 +3 827 829 923 +3 185 432 200 +3 773 706 925 +3 902 838 906 +3 829 926 923 +3 685 473 105 +3 927 773 925 +3 839 838 878 +3 829 836 926 +3 523 615 522 +3 705 928 706 +3 873 862 865 +3 926 836 929 +3 195 473 487 +3 706 928 925 +3 930 924 841 +3 836 831 929 +3 497 202 501 +3 786 931 705 +3 888 877 890 +3 929 831 932 +3 195 509 202 +3 705 931 928 +3 906 924 898 +3 831 830 933 +3 509 501 202 +3 786 785 931 +3 849 845 846 +3 932 831 933 +3 478 556 497 +3 931 785 934 +3 861 856 858 +3 830 852 933 +3 202 497 105 +3 934 785 778 +3 846 845 847 +3 933 852 935 +3 642 583 631 +3 936 934 778 +3 884 839 878 +3 852 833 935 +3 583 642 582 +3 936 778 773 +3 847 859 856 +3 935 833 937 +3 631 662 628 +3 927 936 773 +3 849 843 845 +3 895 938 860 +3 487 473 532 +3 702 782 939 +3 487 532 480 +3 940 702 939 +3 930 841 850 +3 556 478 565 +3 693 941 782 +3 869 867 872 +3 480 565 478 +3 782 941 939 +3 884 847 839 +3 628 677 627 +3 692 942 693 +3 839 847 845 +3 593 631 583 +3 693 942 941 +3 861 853 856 +3 497 543 105 +3 692 777 942 +3 850 853 861 +3 615 523 593 +3 942 777 943 +3 930 850 862 +3 532 473 593 +3 943 777 707 +3 894 930 891 +3 565 480 532 +3 944 943 707 +3 604 522 615 +3 944 707 702 +3 627 665 633 +3 940 944 702 +3 884 859 847 +3 522 604 543 +3 701 772 945 +3 874 862 873 +3 543 599 105 +3 946 701 945 +3 930 862 874 +3 641 582 642 +3 802 947 772 +3 891 877 888 +3 593 473 631 +3 772 947 945 +3 862 850 861 +3 532 593 523 +3 694 948 802 +3 859 872 867 +3 599 641 633 +3 802 948 947 +3 858 856 859 +3 599 633 105 +3 694 793 948 +3 884 872 859 +3 880 882 92 +3 662 473 656 +3 948 793 949 +3 877 891 874 +3 92 882 84 +3 641 599 582 +3 949 793 783 +3 930 874 891 +3 91 883 880 +3 655 105 665 +3 950 949 783 +3 881 890 877 +3 92 91 880 +3 665 627 951 +3 950 783 701 +3 102 885 883 +3 951 627 677 +3 946 950 701 +3 930 894 1397 +3 91 102 883 +3 633 665 105 +3 798 952 796 +3 894 896 1397 +3 112 889 885 +3 685 105 688 +3 796 952 953 +3 873 865 867 +3 102 112 885 +3 656 473 685 +3 954 804 796 +3 898 924 901 +3 122 892 889 +3 691 656 684 +3 953 954 796 +3 838 901 878 +3 112 122 889 +3 656 685 684 +3 798 805 952 +3 840 924 906 +3 133 893 892 +3 688 105 691 +3 952 805 955 +3 840 906 838 +3 122 133 892 +3 655 656 691 +3 955 805 804 +3 838 902 901 +3 133 144 893 +3 655 691 105 +3 954 955 804 +3 841 924 840 +3 893 144 897 +3 509 195 487 +3 742 19 907 +3 850 841 849 +3 903 155 895 +3 631 473 662 +3 17 19 104 +3 843 849 841 +3 155 938 895 +3 599 543 604 +3 104 19 742 +3 873 867 869 +3 897 147 899 +3 677 628 662 +3 811 816 75 +3 907 19 27 +3 144 147 897 +3 543 497 556 +3 42 811 75 +3 922 907 27 +3 147 153 903 +3 956 13 957 +3 49 814 811 +3 911 924 910 +3 899 147 903 +3 724 13 473 +3 42 49 811 +3 909 61 62 +3 153 155 903 +3 35 13 708 +3 818 96 816 +3 954 61 945 +3 958 959 960 +3 816 96 75 +3 945 61 946 +3 35 708 710 +3 723 57 818 +3 10 910 918 +3 743 195 35 +3 818 57 96 +3 930 910 924 +3 961 962 932 +3 963 704 964 +3 723 828 57 +3 909 62 912 +3 743 965 195 +3 57 828 68 +3 924 911 62 +3 195 960 473 +3 68 828 814 +3 911 912 62 +3 935 937 966 +3 959 704 963 +3 49 68 814 +3 914 61 909 +3 708 13 964 +3 813 751 116 +3 946 61 940 +3 933 961 932 +3 708 964 704 +3 46 813 116 +3 947 954 945 +3 933 935 961 +3 967 968 969 +3 76 817 813 +3 946 939 950 +3 932 962 929 +3 970 13 956 +3 46 76 813 +3 944 928 943 +3 962 971 929 +3 960 972 473 +3 815 100 751 +3 931 916 918 +3 929 971 926 +3 740 973 957 +3 751 100 116 +3 930 918 910 +3 926 974 923 +3 967 975 976 +3 715 58 815 +3 913 927 914 +3 923 977 921 +3 978 979 980 +3 815 58 100 +3 914 908 8 +3 921 300 920 +3 964 13 970 +3 715 756 58 +3 9 8 908 +3 920 289 919 +3 959 958 704 +3 58 756 56 +3 927 61 914 +3 919 284 917 +3 976 975 956 +3 56 756 817 +3 908 914 909 +3 917 981 915 +3 978 982 979 +3 76 56 817 +3 953 61 954 +3 981 983 915 +3 968 972 978 +3 746 729 127 +3 939 946 940 +3 982 978 972 +3 82 746 127 +3 942 948 941 +3 972 968 473 +3 117 750 746 +3 940 925 944 +3 971 974 926 +3 735 984 740 +3 82 117 746 +3 936 916 934 +3 956 957 973 +3 759 142 729 +3 930 931 918 +3 974 977 923 +3 964 970 979 +3 729 142 127 +3 940 61 927 +3 967 969 975 +3 714 99 759 +3 927 913 936 +3 977 300 921 +3 970 956 975 +3 759 99 142 +3 949 941 948 +3 718 984 735 +3 714 713 99 +3 930 942 931 +3 300 289 920 +3 968 967 985 +3 99 713 986 +3 934 916 931 +3 968 985 473 +3 986 713 750 +3 950 941 949 +3 289 284 919 +3 724 473 718 +3 117 986 750 +3 954 947 955 +3 957 13 987 +3 727 738 131 +3 930 948 942 +3 284 981 917 +3 984 718 985 +3 50 727 131 +3 943 928 942 +3 718 473 985 +3 151 728 727 +3 931 942 928 +3 973 740 984 +3 50 151 727 +3 930 61 953 +3 987 13 724 +3 734 229 738 +3 930 953 952 +3 988 710 747 +3 738 229 131 +3 930 952 947 +3 966 989 935 +3 757 710 988 +3 764 143 734 +3 952 955 947 +3 35 710 757 +3 734 143 229 +3 948 930 947 +3 989 961 935 +3 747 965 743 +3 764 765 143 +3 925 940 927 +3 155 166 938 +3 972 960 959 +3 143 765 141 +3 910 10 9 +3 960 195 965 +3 141 765 728 +3 928 944 925 +3 980 979 970 +3 151 141 728 +3 941 950 939 +3 743 35 757 +3 6 31 7 +3 916 936 913 +3 965 747 710 +3 67 66 74 +3 5 131 16 +3 29 69 113 +3 98 73 74 +3 74 49 44 +3 92 84 83 +3 113 77 47 +3 108 130 109 +3 986 100 99 +3 121 132 122 +3 148 59 51 +3 176 175 188 +3 117 100 986 +3 147 146 153 +3 123 87 189 +3 303 254 253 +3 81 62 66 +3 97 34 48 +3 276 190 251 +3 62 81 44 +3 990 167 12 +3 190 277 991 +3 49 66 68 +3 992 993 994 +3 991 277 837 +3 76 75 96 +3 992 28 993 +3 197 991 837 +3 995 43 225 +3 981 395 983 +3 993 28 173 +3 197 837 254 +3 158 196 115 +3 286 395 981 +3 996 297 296 +3 303 197 254 +3 253 181 180 +3 981 284 286 +3 160 28 992 +3 855 191 281 +3 231 140 150 +3 289 300 294 +3 278 302 997 +3 281 191 282 +3 231 126 225 +3 300 977 301 +3 161 998 999 +3 855 857 191 +3 1000 1001 1002 +3 977 326 301 +3 1003 173 278 +3 191 857 179 +3 130 43 204 +3 977 974 326 +3 998 161 160 +3 282 191 1004 +3 974 369 326 +3 160 159 12 +3 1005 299 288 +3 974 971 369 +3 1006 264 1007 +3 115 109 158 +3 369 971 360 +3 1008 1009 1010 +3 126 196 225 +3 971 962 360 +3 1009 1008 1011 +3 126 115 196 +3 360 962 335 +3 302 167 295 +3 288 282 1005 +3 962 961 351 +3 999 997 302 +3 204 190 175 +3 335 962 351 +3 265 292 291 +3 204 43 190 +3 961 989 351 +3 992 994 1003 +3 197 303 188 +3 351 989 342 +3 1012 12 1013 +3 298 288 299 +3 989 966 342 +3 292 265 159 +3 1002 995 225 +3 342 966 343 +3 296 1010 1009 +3 196 303 225 +3 159 264 12 +3 303 253 298 +3 1011 1012 1013 +3 130 140 44 +3 296 167 1010 +3 1001 1004 43 +3 177 146 476 +3 297 996 1007 +3 190 43 191 +3 1014 1011 1008 +3 180 298 253 +3 264 1006 1013 +3 299 1000 225 +3 267 464 166 +3 264 1013 12 +3 303 298 225 +3 1015 12 1012 +3 191 179 181 +3 455 177 476 +3 1015 990 12 +3 1016 1002 1001 +3 455 267 177 +3 1006 1007 996 +3 1017 1005 282 +3 476 146 481 +3 1012 1011 1014 +3 991 197 175 +3 146 137 481 +3 1010 167 990 +3 191 43 1004 +3 481 137 304 +3 1018 1003 994 +3 190 991 175 +3 304 132 192 +3 1019 1003 1018 +3 1020 43 995 +3 192 121 208 +3 173 1003 1019 +3 1001 43 1020 +3 208 111 227 +3 993 173 1019 +3 1001 1020 1016 +3 227 101 241 +3 295 167 296 +3 1004 1017 282 +3 241 90 526 +3 302 295 290 +3 1000 1002 225 +3 526 83 527 +3 291 290 295 +3 204 157 130 +3 83 85 527 +3 997 999 998 +3 315 258 170 +3 90 83 526 +3 322 246 232 +3 231 225 170 +3 198 246 322 +3 234 228 164 +3 199 198 322 +3 239 209 240 +3 269 255 308 +3 230 419 231 +3 308 255 257 +3 240 228 226 +3 166 154 267 +3 327 256 255 +3 512 475 511 +3 496 304 192 +3 372 471 446 +3 1021 659 462 +3 621 591 640 +3 652 654 636 +3 661 606 621 +3 644 651 1022 +3 1023 670 338 +3 542 664 510 +3 645 443 643 +3 338 317 1023 +3 617 603 557 +3 645 1021 462 +3 317 675 1023 +3 542 537 570 +3 650 687 673 +3 317 316 675 +3 542 676 664 +3 761 1024 1025 +3 542 721 720 +3 1026 1027 1028 +3 763 754 1029 +3 762 1030 1026 +3 721 754 732 +3 1025 1024 1031 +3 721 1396 754 +3 1032 762 761 +3 754 753 732 +3 1024 1033 1034 +3 754 1396 1029 +3 1025 1030 1035 +3 720 739 769 +3 1034 1036 766 +3 744 732 753 +3 179 857 842 +3 180 179 842 +3 180 842 293 +3 298 180 293 +3 864 1001 863 +3 863 1001 1000 +3 844 863 1000 +3 299 844 1000 +3 854 1004 864 +3 864 1004 1001 +3 854 866 1004 +3 1004 866 1017 +3 1017 866 848 +3 1005 1017 848 +3 1005 848 844 +3 299 1005 844 +3 868 1020 835 +3 835 1020 995 +3 1002 871 835 +3 995 1002 835 +3 868 870 1020 +3 1020 870 1016 +3 1016 870 871 +3 1002 1016 871 +3 105 32 17 +3 105 473 32 +3 886 162 164 +3 240 886 164 +3 209 200 886 +3 240 209 886 +3 171 163 162 +3 215 248 216 +3 900 315 247 +3 247 315 248 +3 900 887 315 +3 315 887 258 +3 258 887 235 +3 478 466 479 +3 633 641 494 +3 494 641 578 +3 665 951 495 +3 495 951 612 +3 612 951 677 +3 512 612 677 +3 1022 651 958 +3 958 651 704 +3 645 1022 960 +3 960 1022 958 +3 645 960 1021 +3 1021 960 965 +3 653 1021 965 +3 710 653 965 +3 979 687 650 +3 964 979 650 +3 650 649 963 +3 964 650 963 +3 669 687 982 +3 982 687 979 +3 643 669 972 +3 972 669 982 +3 643 972 644 +3 644 972 959 +3 649 644 959 +3 963 649 959 +3 975 681 673 +3 970 975 673 +3 673 1037 980 +3 970 673 980 +3 1038 681 969 +3 969 681 975 +3 667 1038 968 +3 968 1038 969 +3 667 968 668 +3 668 968 978 +3 1037 668 978 +3 980 1037 978 +3 973 637 680 +3 956 973 680 +3 680 679 976 +3 956 680 976 +3 638 637 984 +3 984 637 973 +3 1039 638 985 +3 985 638 984 +3 1039 985 1040 +3 1040 985 967 +3 679 1040 967 +3 976 679 967 +3 987 635 663 +3 957 987 663 +3 663 639 740 +3 957 663 740 +3 717 635 724 +3 724 635 987 +3 659 1041 747 +3 747 1041 988 +3 988 1041 752 +3 757 988 752 +3 47 771 113 +3 113 771 1042 +3 29 113 1042 +3 1043 770 34 +3 34 770 47 +3 1043 34 1044 +3 1044 34 36 +3 1045 1044 36 +3 38 1045 36 +3 1042 1045 38 +3 29 1042 38 +3 1046 1047 22 +3 22 1047 20 +3 20 1047 1048 +3 69 20 1048 +3 1049 1046 97 +3 97 1046 22 +3 1049 97 1050 +3 1050 97 48 +3 1051 1050 48 +3 77 1051 48 +3 1048 1051 77 +3 69 1048 77 +3 1052 1053 59 +3 59 1053 52 +3 52 1053 1054 +3 93 52 1054 +3 1055 1052 134 +3 134 1052 59 +3 1055 134 1056 +3 1056 134 118 +3 1057 1056 118 +3 21 1057 118 +3 1054 1057 21 +3 93 1054 21 +3 1058 1059 87 +3 87 1059 64 +3 64 1059 1060 +3 53 64 1060 +3 1061 1058 124 +3 124 1058 87 +3 1061 124 1062 +3 1062 124 148 +3 1063 1062 148 +3 51 1063 148 +3 1060 1063 51 +3 53 1060 51 +3 1064 1065 178 +3 178 1065 156 +3 156 1065 1066 +3 63 156 1066 +3 1067 1064 123 +3 123 1064 178 +3 1067 123 1068 +3 1068 123 189 +3 1069 1068 189 +3 86 1069 189 +3 1066 1069 86 +3 63 1066 86 +3 1070 1071 223 +3 11 1070 223 +3 1072 1070 205 +3 205 1070 11 +3 1072 205 1073 +3 1073 205 222 +3 1071 1073 222 +3 223 1071 222 +3 1074 1033 998 +3 998 1033 997 +3 997 1033 1024 +3 278 997 1024 +3 1028 1074 160 +3 160 1074 998 +3 1028 160 760 +3 760 160 992 +3 761 760 992 +3 1003 761 992 +3 1024 761 1003 +3 278 1024 1003 +3 1075 1036 292 +3 292 1036 290 +3 290 1036 1034 +3 302 290 1034 +3 1076 1075 159 +3 159 1075 292 +3 1076 159 1077 +3 1077 159 161 +3 1078 1077 161 +3 999 1078 161 +3 1034 1078 999 +3 302 1034 999 +3 1079 767 1007 +3 1007 767 297 +3 297 767 766 +3 295 297 766 +3 1080 1079 264 +3 264 1079 1007 +3 1080 264 1081 +3 1081 264 265 +3 1082 1081 265 +3 291 1082 265 +3 766 1082 291 +3 295 766 291 +3 1083 1084 1011 +3 1011 1084 1009 +3 1009 1084 768 +3 296 1009 768 +3 1085 1083 1013 +3 1013 1083 1011 +3 1085 1013 1086 +3 1086 1013 1006 +3 1087 1086 1006 +3 996 1087 1006 +3 768 1087 996 +3 296 768 996 +3 1088 1089 1015 +3 1015 1089 990 +3 990 1089 1090 +3 1010 990 1090 +3 1091 1088 1012 +3 1012 1088 1015 +3 1091 1012 1092 +3 1092 1012 1014 +3 1093 1092 1014 +3 1008 1093 1014 +3 1090 1093 1008 +3 1010 1090 1008 +3 762 1032 994 +3 994 1032 1018 +3 1018 1032 1035 +3 1019 1018 1035 +3 1030 762 993 +3 993 762 994 +3 1035 1030 993 +3 1019 1035 993 +3 305 505 436 +3 436 505 437 +3 472 1031 530 +3 537 183 530 +3 427 423 388 +3 246 198 1025 +3 1025 1031 233 +3 422 471 530 +3 537 198 183 +3 537 1025 198 +3 183 255 530 +3 183 182 255 +3 423 422 530 +3 370 345 269 +3 319 182 212 +3 233 1031 311 +3 327 255 182 +3 255 340 530 +3 396 389 339 +3 370 269 268 +3 311 361 268 +3 311 1031 361 +3 410 413 352 +3 340 339 389 +3 340 389 530 +3 389 423 530 +3 345 340 269 +3 233 246 1025 +3 413 396 339 +3 361 1031 410 +3 401 410 440 +3 389 388 423 +3 422 431 471 +3 413 339 352 +3 486 471 431 +3 440 450 401 +3 361 370 268 +3 410 1031 440 +3 450 427 388 +3 352 361 410 +3 477 1031 472 +3 431 1031 477 +3 431 477 486 +3 431 440 1031 +3 450 388 401 +3 311 319 233 +3 319 327 182 +3 212 233 319 +3 255 269 340 +3 471 472 530 +3 437 505 1094 +3 1094 505 1095 +3 500 1096 505 +3 505 1096 1095 +3 500 508 1096 +3 1096 508 1097 +3 508 516 1097 +3 1097 516 1098 +3 537 542 769 +3 1099 537 1100 +3 1100 537 769 +3 1101 537 1099 +3 1102 537 1101 +3 1103 537 1102 +3 1104 537 1103 +3 879 537 1104 +3 878 537 879 +3 924 537 878 +3 62 537 924 +3 44 537 62 +3 231 537 44 +3 239 537 231 +3 462 537 239 +3 652 537 462 +3 1026 537 652 +3 1025 537 1026 +3 530 1105 1106 +3 531 530 1106 +3 1031 1107 1105 +3 530 1031 1105 +3 590 534 525 +3 474 511 475 +3 612 512 493 +3 482 484 443 +3 453 514 494 +3 525 515 590 +3 462 443 645 +3 668 1037 687 +3 643 667 669 +3 643 443 667 +3 673 681 680 +3 680 663 636 +3 673 680 636 +3 717 716 443 +3 1038 667 1039 +3 1040 681 1038 +3 667 443 1039 +3 716 1039 443 +3 680 637 663 +3 730 639 638 +3 717 443 635 +3 716 730 638 +3 1040 679 681 +3 1039 1040 1038 +3 1041 659 653 +3 638 1039 716 +3 652 1041 653 +3 1037 673 687 +3 652 462 660 +3 652 752 1041 +3 652 660 752 +3 644 649 651 +3 1022 645 644 +3 1021 653 659 +3 1070 636 1027 +3 1051 1048 771 +3 1053 1052 1063 +3 1045 1042 1026 +3 652 636 1043 +3 1026 652 1044 +3 1060 1066 1027 +3 1026 1044 1045 +3 1026 1042 1027 +3 1065 1064 1071 +3 1043 636 1049 +3 1058 1061 1067 +3 1069 1066 1059 +3 771 770 1051 +3 1042 1048 1027 +3 1042 771 1048 +3 1059 1058 1069 +3 1049 1055 1046 +3 1049 636 1055 +3 1057 1054 1047 +3 1060 1059 1066 +3 1071 1070 1027 +3 1048 1054 1027 +3 1054 1053 1060 +3 1043 1044 652 +3 1064 1067 636 +3 1055 636 1061 +3 1063 1060 1053 +3 1066 1065 1027 +3 1054 1060 1027 +3 1061 1062 1052 +3 1073 1071 1064 +3 1068 1069 1058 +3 1056 1057 1046 +3 1061 636 1067 +3 1055 1056 1046 +3 1072 636 1070 +3 1064 636 1072 +3 1064 1072 1073 +3 1067 1068 1058 +3 1065 1071 1027 +3 1049 1050 1043 +3 1050 1051 770 +3 770 1043 1050 +3 1048 1047 1054 +3 1062 1063 1052 +3 1052 1055 1061 +3 1047 1046 1057 +3 1089 1027 1031 +3 1076 1077 1028 +3 1087 768 767 +3 1081 1082 1075 +3 1028 1027 1076 +3 1028 760 1026 +3 1083 1085 1091 +3 1033 1074 1078 +3 1024 1034 1031 +3 1076 1080 1075 +3 1076 1027 1080 +3 1082 766 1036 +3 768 1090 1031 +3 1034 766 1031 +3 768 1084 1090 +3 1080 1081 1075 +3 1080 1027 1085 +3 1090 1089 1031 +3 1088 1091 1027 +3 767 1079 1087 +3 766 768 1031 +3 1078 1034 1033 +3 1091 1092 1083 +3 1088 1027 1089 +3 1093 1090 1084 +3 1092 1093 1083 +3 1086 1087 1079 +3 1085 1086 1079 +3 1091 1085 1027 +3 1084 1083 1093 +3 1025 1032 761 +3 1025 1026 1030 +3 1025 1035 1032 +3 760 762 1026 +3 1077 1078 1074 +3 1074 1028 1077 +3 1079 1080 1085 +3 1036 1075 1082 +3 207 437 1108 +3 1108 437 1094 +3 1027 1109 1107 +3 1031 1027 1107 +3 1094 1110 1108 +3 1108 1110 1111 +3 1095 1112 1094 +3 1094 1112 1110 +3 1096 1113 1095 +3 1095 1113 1112 +3 1097 1114 1096 +3 1096 1114 1113 +3 1098 1115 1097 +3 1097 1115 1114 +3 1105 1116 1106 +3 1107 1117 1105 +3 1117 1116 1105 +3 1118 1119 1107 +3 1109 1118 1107 +3 1119 1117 1107 +3 876 1120 875 +3 1121 1120 876 +3 876 922 1121 +3 1122 930 1123 +3 1123 930 1397 +3 922 1124 1121 +3 922 27 1124 +3 1122 1125 930 +3 930 1125 61 +3 27 1126 1124 +3 1127 1126 18 +3 18 1126 27 +3 1125 1128 61 +3 61 1128 43 +3 18 33 1127 +3 33 1129 1127 +3 33 207 1129 +3 43 1128 1130 +3 225 43 1130 +3 225 1130 1131 +3 226 225 1131 +3 207 1108 1129 +3 226 1131 1132 +3 443 226 1132 +3 443 1132 1133 +3 636 443 1133 +3 636 1133 1109 +3 1027 636 1109 +3 1108 1111 1129 +3 1129 1111 1134 +3 1133 1118 1109 +3 1134 1111 1135 +3 1111 1136 1135 +3 1111 1110 1136 +3 1136 1110 1137 +3 1110 1112 1137 +3 1137 1112 1138 +3 1113 1139 1112 +3 1112 1139 1138 +3 1113 1114 1139 +3 1139 1114 1140 +3 1114 1115 1140 +3 1140 1115 1141 +3 1142 1116 1117 +3 1143 1142 1117 +3 1143 1117 1119 +3 1144 1143 1119 +3 1145 1118 1146 +3 1147 1145 1146 +3 1146 1118 1133 +3 1144 1119 1118 +3 1145 1144 1118 +3 1148 1120 1121 +3 1149 1148 1121 +3 1122 1123 1150 +3 1150 1123 1151 +3 1121 1124 1152 +3 1149 1121 1152 +3 1153 1125 1122 +3 1150 1153 1122 +3 1124 1126 1154 +3 1152 1124 1154 +3 1155 1128 1125 +3 1153 1155 1125 +3 1127 1156 1126 +3 1126 1156 1154 +3 1129 1134 1127 +3 1127 1134 1156 +3 1157 1130 1128 +3 1155 1157 1128 +3 1158 1131 1130 +3 1157 1158 1130 +3 1159 1132 1131 +3 1158 1159 1131 +3 1159 1146 1132 +3 1132 1146 1133 +3 1156 1134 1160 +3 1134 1135 1160 +3 1160 1135 1161 +3 1135 1162 1161 +3 1135 1136 1162 +3 1136 1163 1162 +3 1136 1137 1163 +3 1163 1137 1164 +3 1137 1138 1164 +3 1164 1138 1165 +3 1139 1166 1138 +3 1138 1166 1165 +3 1139 1140 1166 +3 1166 1140 1167 +3 1140 1141 1167 +3 1167 1141 1168 +3 1143 1169 1142 +3 1144 1170 1143 +3 1170 1169 1143 +3 1171 1172 1144 +3 1145 1171 1144 +3 1172 1170 1144 +3 1147 1171 1145 +3 1173 1174 1147 +3 1147 1146 1159 +3 1173 1147 1159 +3 1174 1171 1147 +3 1149 1175 1148 +3 1176 1175 1149 +3 1149 1152 1176 +3 1151 1177 1150 +3 1150 1177 1178 +3 1153 1150 1179 +3 1179 1150 1178 +3 1152 1180 1176 +3 1152 1154 1180 +3 1155 1153 1181 +3 1181 1153 1179 +3 1154 1182 1180 +3 1160 1182 1156 +3 1156 1182 1154 +3 1183 1157 1155 +3 1181 1183 1155 +3 1184 1158 1157 +3 1183 1184 1157 +3 1173 1159 1158 +3 1184 1173 1158 +3 1161 1185 1160 +3 1160 1185 1182 +3 1186 1187 1161 +3 1161 1187 1185 +3 1161 1162 1186 +3 1162 1188 1186 +3 1162 1163 1188 +3 1163 1189 1188 +3 1163 1164 1189 +3 1189 1164 1190 +3 1164 1165 1190 +3 1190 1165 1191 +3 1166 1192 1165 +3 1165 1192 1191 +3 1166 1167 1192 +3 1192 1167 1193 +3 1167 1168 1193 +3 1193 1168 1194 +3 1195 1169 1170 +3 1196 1195 1170 +3 1196 1170 1172 +3 1197 1196 1172 +3 1198 1171 1174 +3 1199 1198 1174 +3 1197 1172 1171 +3 1198 1197 1171 +3 1200 1174 1173 +3 1200 1173 1184 +3 1199 1174 1200 +3 1201 1199 1200 +3 1176 1202 1175 +3 1178 1177 1203 +3 1203 1177 1204 +3 1205 1202 1176 +3 1176 1180 1205 +3 1206 1179 1178 +3 1203 1206 1178 +3 1207 1181 1179 +3 1206 1207 1179 +3 1180 1208 1205 +3 1180 1182 1208 +3 1209 1183 1181 +3 1207 1209 1181 +3 1182 1185 1208 +3 1210 1184 1183 +3 1209 1210 1183 +3 1210 1200 1184 +3 1208 1185 1211 +3 1185 1187 1211 +3 1211 1187 1212 +3 1187 1213 1212 +3 1186 1214 1213 +3 1187 1186 1213 +3 1186 1188 1214 +3 1188 1215 1214 +3 1188 1189 1215 +3 1189 1216 1215 +3 1189 1190 1216 +3 1216 1190 1217 +3 1190 1191 1217 +3 1217 1191 1218 +3 1191 1192 1219 +3 1218 1191 1219 +3 1192 1193 1219 +3 1219 1193 1220 +3 1193 1194 1220 +3 1220 1194 1221 +3 1196 1222 1195 +3 1197 1223 1196 +3 1223 1222 1196 +3 1224 1225 1197 +3 1198 1224 1197 +3 1225 1223 1197 +3 1199 1224 1198 +3 1201 1226 1199 +3 1226 1224 1199 +3 1201 1200 1210 +3 1227 1201 1210 +3 1228 1226 1201 +3 1228 1201 1227 +3 1204 1229 1203 +3 1203 1229 1230 +3 1205 1231 1202 +3 1206 1203 1232 +3 1232 1203 1230 +3 1233 1231 1205 +3 1205 1208 1233 +3 1207 1206 1234 +3 1234 1206 1232 +3 1235 1209 1207 +3 1234 1235 1207 +3 1208 1211 1233 +3 1227 1210 1209 +3 1235 1227 1209 +3 1233 1211 1236 +3 1211 1212 1236 +3 1236 1212 1237 +3 1212 1238 1237 +3 1212 1213 1238 +3 1213 1239 1238 +3 1240 1239 1214 +3 1214 1239 1213 +3 1214 1215 1240 +3 1215 1241 1240 +3 1215 1216 1241 +3 1216 1242 1241 +3 1216 1217 1242 +3 1242 1217 1243 +3 1217 1218 1243 +3 1243 1218 1244 +3 1219 1245 1218 +3 1218 1245 1244 +3 1219 1220 1245 +3 1245 1220 1246 +3 1220 1221 1246 +3 1246 1221 1247 +3 1223 1248 1222 +3 1225 1249 1223 +3 1249 1248 1223 +3 1226 1250 1224 +3 1250 1251 1225 +3 1224 1250 1225 +3 1251 1249 1225 +3 1228 1252 1226 +3 1252 1250 1226 +3 1253 1227 1235 +3 1253 1228 1227 +3 1254 1252 1228 +3 1254 1228 1253 +3 1230 1229 1255 +3 1255 1229 1256 +3 1257 1232 1230 +3 1255 1257 1230 +3 1233 1258 1231 +3 1259 1234 1232 +3 1257 1259 1232 +3 1236 1258 1233 +3 1260 1235 1234 +3 1259 1260 1234 +3 1260 1253 1235 +3 1236 1261 1258 +3 1237 1261 1236 +3 1237 1262 1261 +3 1263 1262 1237 +3 1237 1238 1263 +3 1238 1264 1263 +3 1238 1239 1264 +3 1239 1265 1264 +3 1240 1266 1265 +3 1239 1240 1265 +3 1240 1241 1266 +3 1241 1267 1266 +3 1241 1242 1267 +3 1242 1268 1267 +3 1242 1243 1268 +3 1268 1243 1269 +3 1243 1244 1269 +3 1269 1244 1270 +3 1244 1245 1271 +3 1270 1244 1271 +3 1245 1246 1271 +3 1271 1246 1272 +3 1246 1247 1272 +3 1272 1247 1273 +3 1249 1274 1248 +3 1251 1275 1249 +3 1275 1274 1249 +3 1252 1276 1250 +3 1276 1277 1251 +3 1250 1276 1251 +3 1277 1275 1251 +3 1254 1278 1252 +3 1278 1276 1252 +3 1279 1253 1260 +3 1279 1254 1253 +3 1280 1278 1254 +3 1280 1254 1279 +3 1255 1256 1281 +3 1281 1256 1282 +3 1283 1257 1255 +3 1281 1283 1255 +3 2 1259 1257 +3 1283 2 1257 +3 1 1260 1259 +3 2 1 1259 +3 1 1279 1260 +3 1263 55 1262 +3 54 55 1263 +3 1263 1264 54 +3 1264 65 54 +3 1264 1265 65 +3 1265 70 65 +3 78 70 1266 +3 1266 70 1265 +3 1266 1267 78 +3 1267 94 78 +3 1267 1268 94 +3 1268 103 94 +3 1268 1269 103 +3 103 1269 114 +3 1269 1270 114 +3 114 1270 125 +3 1271 138 1270 +3 1270 138 125 +3 1271 1272 138 +3 138 1272 139 +3 1272 1273 139 +3 139 1273 149 +3 1275 220 1274 +3 1277 218 1275 +3 218 220 1275 +3 1278 287 1276 +3 287 262 1277 +3 1276 287 1277 +3 262 218 1277 +3 1280 1284 1278 +3 1284 287 1278 +3 23 1279 1 +3 23 1280 1279 +3 1285 1284 1280 +3 1285 1280 23 +3 1281 1282 1286 +3 1286 1282 1287 +3 1286 1287 1288 +3 1288 1287 1289 +3 1290 1283 1281 +3 1286 1290 1281 +3 14 2 1283 +3 1290 14 1283 +3 65 71 60 +3 70 79 71 +3 125 138 135 +3 1284 279 287 +3 1285 415 1284 +3 415 279 1284 +3 1288 1289 428 +3 428 1289 429 +3 458 23 0 +3 458 1285 23 +3 438 415 1285 +3 438 1285 458 +3 492 1290 1286 +3 1288 492 1286 +3 445 492 1288 +3 428 445 1288 +3 491 14 1290 +3 492 491 1290 +3 459 0 14 +3 491 459 14 +3 459 458 0 +3 106 119 249 +3 249 119 618 +3 119 128 618 +3 618 128 623 +3 128 135 259 +3 623 128 259 +3 502 490 445 +3 634 314 731 +3 711 695 418 +3 430 434 1291 +3 1291 434 1292 +3 1293 444 430 +3 1291 1293 430 +3 467 1294 439 +3 1294 709 439 +3 1295 502 444 +3 1293 1295 444 +3 1296 457 506 +3 1296 467 457 +3 1297 1294 467 +3 1297 467 1296 +3 1298 506 490 +3 502 1298 490 +3 1299 1298 502 +3 1295 1299 502 +3 1298 1296 506 +3 571 1300 569 +3 1301 1300 571 +3 571 584 1301 +3 584 1302 1301 +3 584 594 1302 +3 594 1303 1302 +3 598 1304 1303 +3 594 598 1303 +3 598 605 1304 +3 605 1305 1304 +3 605 616 1305 +3 616 1306 1305 +3 616 620 1306 +3 1306 620 1307 +3 620 629 1307 +3 1307 629 1308 +3 629 630 719 +3 1308 629 719 +3 711 1309 695 +3 1309 748 695 +3 1291 1292 1310 +3 1310 1292 1311 +3 1294 1312 709 +3 1312 1313 711 +3 709 1312 711 +3 1313 1309 711 +3 1314 1293 1291 +3 1310 1314 1291 +3 1315 1295 1293 +3 1314 1315 1293 +3 1297 1316 1294 +3 1316 1312 1294 +3 1317 1299 1295 +3 1315 1317 1295 +3 1318 1296 1298 +3 1318 1297 1296 +3 1319 1316 1297 +3 1319 1297 1318 +3 1299 1318 1298 +3 1320 1318 1299 +3 1317 1320 1299 +3 1301 1321 1300 +3 1322 1321 1301 +3 1301 1302 1322 +3 1302 1323 1322 +3 1302 1303 1323 +3 1303 1324 1323 +3 1304 1325 1324 +3 1303 1304 1324 +3 1304 1305 1325 +3 1305 1326 1325 +3 1305 1306 1326 +3 1306 1327 1326 +3 1306 1307 1327 +3 1327 1307 1328 +3 1307 1308 1328 +3 1328 1308 1329 +3 1308 719 1330 +3 1329 1308 1330 +3 719 725 1330 +3 1330 725 1331 +3 725 736 1331 +3 1331 736 1332 +3 1309 1333 748 +3 1313 1334 1309 +3 1334 1333 1309 +3 1310 1311 1335 +3 1335 1311 1336 +3 1337 1314 1310 +3 1335 1337 1310 +3 1316 1338 1312 +3 1338 1339 1313 +3 1312 1338 1313 +3 1339 1334 1313 +3 1340 1315 1314 +3 1337 1340 1314 +3 1341 1317 1315 +3 1340 1341 1315 +3 1319 1342 1316 +3 1342 1338 1316 +3 1343 1320 1317 +3 1341 1343 1317 +3 1320 1319 1318 +3 1344 1342 1319 +3 1344 1319 1320 +3 1343 1344 1320 +3 1322 1345 1321 +3 1346 1345 1322 +3 1322 1323 1346 +3 1323 1347 1346 +3 1323 1324 1347 +3 1324 1348 1347 +3 1325 1349 1348 +3 1324 1325 1348 +3 1325 1326 1349 +3 1326 1350 1349 +3 1326 1327 1350 +3 1327 1351 1350 +3 1327 1328 1351 +3 1351 1328 1352 +3 1328 1329 1352 +3 1352 1329 1353 +3 1329 1330 1354 +3 1353 1329 1354 +3 1330 1331 1354 +3 1354 1331 1355 +3 1331 1332 1355 +3 1355 1332 1356 +3 1334 1357 1333 +3 1335 1336 1358 +3 1358 1336 1359 +3 1339 1360 1334 +3 1360 1357 1334 +3 1361 1337 1335 +3 1358 1361 1335 +3 1362 1340 1337 +3 1361 1362 1337 +3 1342 1363 1338 +3 1363 1364 1339 +3 1338 1363 1339 +3 1364 1360 1339 +3 1365 1341 1340 +3 1362 1365 1340 +3 1366 1343 1341 +3 1365 1366 1341 +3 1344 1367 1342 +3 1367 1363 1342 +3 1368 1344 1343 +3 1366 1368 1343 +3 1368 1367 1344 +3 1346 1369 1345 +3 1370 1369 1346 +3 1346 1347 1370 +3 1347 1371 1370 +3 1347 1348 1371 +3 1348 1372 1371 +3 1349 1373 1372 +3 1348 1349 1372 +3 1349 1350 1373 +3 1350 1374 1373 +3 1350 1351 1374 +3 1351 1375 1374 +3 1351 1352 1375 +3 1375 1352 1376 +3 1352 1353 1376 +3 1376 1353 1377 +3 1353 1354 1378 +3 1377 1353 1378 +3 1354 1355 1378 +3 1378 1355 1379 +3 1355 1356 1379 +3 1379 1356 1380 +3 1360 1381 1357 +3 1358 1359 358 +3 358 1359 1382 +3 357 1361 1358 +3 358 357 1358 +3 1364 377 1360 +3 377 1381 1360 +3 365 1362 1361 +3 357 365 1361 +3 386 1365 1362 +3 365 386 1362 +3 1367 400 1363 +3 400 375 1364 +3 1363 400 1364 +3 375 377 1364 +3 1383 1366 1365 +3 386 1383 1365 +3 1384 1368 1366 +3 1383 1384 1366 +3 1368 398 1367 +3 398 400 1367 +3 1384 398 1368 +3 1370 1385 1369 +3 1386 1385 1370 +3 1370 1371 1386 +3 1371 518 1386 +3 1371 1372 518 +3 1372 519 518 +3 1373 1387 519 +3 1372 1373 519 +3 1373 1374 1387 +3 1374 538 1387 +3 1374 1375 538 +3 1375 544 538 +3 1375 1376 544 +3 544 1376 559 +3 1376 1377 559 +3 559 1377 566 +3 1377 1378 573 +3 566 1377 573 +3 1378 1379 573 +3 573 1379 585 +3 1379 1380 585 +3 585 1380 1388 +3 377 381 1381 +3 358 1382 658 +3 658 1382 647 +3 658 356 358 +3 356 364 357 +3 672 1383 386 +3 385 672 386 +3 400 399 375 +3 405 376 375 +3 671 1384 1383 +3 672 671 1383 +3 671 683 1384 +3 1384 683 398 +3 683 399 398 +3 585 1388 587 +3 587 1388 780 +3 1386 789 1385 +3 787 789 1386 +3 1386 518 787 +3 518 520 787 +3 1387 540 521 +3 519 1387 521 +3 1387 538 540 +3 563 566 579 +3 658 647 646 +3 657 356 658 +3 535 241 526 +3 535 513 241 +3 323 1389 682 +3 323 325 1389 +3 325 1390 1389 +3 325 363 1390 +3 1390 363 1391 +3 363 334 1391 +3 1391 334 1392 +3 334 333 1393 +3 1392 334 1393 +3 333 426 1393 +3 1393 426 1394 +3 426 344 1394 +3 1394 344 1395 +3 470 469 1392 +3 1394 1395 463 +3 1393 470 1392 +3 1393 1394 470 +3 1392 469 1391 +3 469 485 1391 +3 1391 485 1390 +3 1390 496 1389 +3 1389 499 682 +3 682 507 674 +3 674 513 675 +3 675 535 1023 +3 1023 528 670 +3 528 547 670 +3 485 496 1390 +3 496 499 1389 +3 499 507 682 +3 507 513 674 +3 513 535 675 +3 535 528 1023 +3 463 456 1394 +3 456 470 1394 + diff --git a/Constrained_triangulation_3/test/Constrained_triangulation_3/data/bug-split-1.off b/Constrained_triangulation_3/test/Constrained_triangulation_3/data/bug-split-1.off new file mode 100644 index 000000000000..b032321ed281 --- /dev/null +++ b/Constrained_triangulation_3/test/Constrained_triangulation_3/data/bug-split-1.off @@ -0,0 +1,78 @@ +OFF +60 14 0 + +10 10 10 +-9.9999199999999995 10.040100000000001 -9.9999199999999995 +-6.0047800000000002 6.0240600000000004 -10.007999999999999 +6.0047800000000002 6.0240600000000004 -10.007999999999999 +6.0047899999999998 6.0168400000000002 -4.00319 +-5.9999900000000004 10.012 3.9999899999999999 +-6 10 10 +6 10 10 +-6.0072099999999997 4.00481 4.00481 +6.0144299999999999 -2.0024000000000002 4.00962 +6.0048000000000004 6.0072099999999997 4.0031999999999996 +6.0072099999999997 4.00481 4.00481 +-6.0240600000000004 6.0240600000000004 -10.007999999999999 +6.0240600000000004 6.0240600000000004 -10.007999999999999 +-6.0072000000000001 -2.0024000000000002 4.00962 +-6.0072099999999997 2.0024000000000002 4.0064099999999998 +-6.0048000000000004 6.0048000000000004 6.0048000000000004 +6.0072099999999997 2.0024000000000002 4.0064099999999998 +6.0048000000000004 6.0048000000000004 6.0048000000000004 +-6.0240900000000002 -10.0321 -10.0321 +10 10 -10 +6.0048000000000004 6.0048000000000004 10.007999999999999 +-10.007999999999999 6.0240600000000004 -10.007999999999999 +-6.0240600000000004 6.0192699999999997 -10.007999999999999 +-6.0240900000000002 -6.0240900000000002 -10.0321 +-6.0192600000000001 -6.0192600000000001 -6.0192600000000001 +-6.0240900000000002 -6.0192699999999997 -10.0321 +-6.0192600000000001 6.0192600000000001 -6.0192600000000001 +-6.0047899999999998 6.0192399999999999 4.00319 +4.0031999999999996 6.0072099999999997 4.0031999999999996 +-6.0047899999999998 6.0192399999999999 -4.00319 +-6.0047899999999998 6.0192399999999999 -6.0047899999999998 +-4.00319 6.0168400000000002 -4.00319 +-5.9999599999999997 10.0321 -9.9999400000000005 +-5.9999599999999997 10.0321 -5.9999599999999997 +5.9999900000000004 10.007999999999999 -9.9999800000000008 +5.9999900000000004 10.007999999999999 -3.9999899999999999 +5.9999900000000004 10.007999999999999 5.9999900000000004 +5.9999900000000004 10.007999999999999 3.9999899999999999 +-6.0048000000000004 6.0060099999999998 5.0006000000000004 +10.019399999999999 -2.00387 0.33785900000000002 +10.0219 -0.92307300000000003 -0.92307300000000003 +6.0144299999999999 -2.0018699999999998 5.3379099999999999 +-6.0110000000000001 0.85517500000000002 4.0073299999999996 +6.0109899999999996 0.86136599999999997 4.0073299999999996 +-6.00481 5.9986300000000004 10.007999999999999 +-6.0116300000000003 2.0038800000000001 0.33143699999999998 +-6.0060099999999998 6.0060099999999998 5.0006000000000004 +6.0116199999999997 2.00387 0.336254 +-6.0116300000000003 -2.0038800000000001 0.33143699999999998 +10.0093 -2.0018699999999998 5.3355100000000002 +-10.02 0 -2.0080200000000001 +10.02 0 -1.9999899999999999 +10 6 10 +-10.007999999999999 6.0240600000000004 5.0200500000000003 +6.0060099999999998 6.0048000000000004 5.0039999999999996 +10.007999999999999 5.9999900000000004 4.9999900000000004 +6.0240600000000004 6.0047800000000002 -10.007999999999999 +10.007999999999999 5.9999900000000004 -9.9999800000000008 +-6.0047899999999998 6.0192399999999999 5.0160400000000003 +4 19 24 26 25 +6 49 40 50 42 9 14 +6 20 0 41 52 56 58 +10 51 54 59 39 47 46 48 55 56 52 +10 22 23 27 31 30 32 29 28 59 54 +3 1 34 33 +9 43 8 16 39 59 28 5 6 45 +6 43 44 11 17 15 8 +8 38 10 18 11 44 21 7 37 +3 21 53 0 +4 55 57 58 56 +7 32 4 3 13 18 10 29 +4 12 2 31 27 +4 35 3 4 36 + diff --git a/Constrained_triangulation_3/test/Constrained_triangulation_3/data/bug12.off b/Constrained_triangulation_3/test/Constrained_triangulation_3/data/bug12.off new file mode 100644 index 000000000000..46cfa956f364 --- /dev/null +++ b/Constrained_triangulation_3/test/Constrained_triangulation_3/data/bug12.off @@ -0,0 +1,1443 @@ +OFF +1009 430 0 + +26.567900000000002 36.567549999999997 96.959999999999994 +-48.307125999999997 10.688492 91.996151999999995 +-50 0 96.239999999999995 +-47.552849999999999 15.450850000000001 96.239999999999995 +36.877704999999999 25.524087000000002 86.799999999999997 +43.429470999999999 9.9159480000000002 23.853847999999999 +44.368076000000002 3.9898180000000001 17.746151999999999 +44.368076000000002 3.9898180000000001 23.853847999999999 +-27.740373000000002 41.290998000000002 95 +-29.389250000000001 40.450850000000003 96.239999999999995 +-15.450850000000001 47.552849999999999 96.239999999999995 +-50 0 0 +-49.715021999999998 1.7992950000000001 20.800000000000001 +38.239677999999998 22.851068000000001 81.603847999999999 +29.359850000000002 40.410400000000003 96.384 +29.359850000000002 40.410400000000003 96.480000000000004 +40.410400000000003 29.359850000000002 96.384 +-25.093077000000001 42.639868999999997 40.353847999999999 +-19.747043000000001 45.363821000000002 34.246152000000002 +13.983000000000001 43.035299999999999 97.103999999999999 +-48.307125999999997 10.688492 25.996151999999999 +-47.837826999999997 13.651558 20.800000000000001 +40.410400000000003 29.359850000000002 96.480000000000004 +-29.389250000000001 40.450850000000003 0 +-27.766093999999999 41.277892999999999 12.550000000000001 +-49.245724000000003 4.7623610000000003 15.603847999999999 +45.363821000000002 19.747043000000001 91.996151999999995 +15.4354 47.505249999999997 96.384 +15.4354 47.505249999999997 96.480000000000004 +-15.450850000000001 47.552849999999999 0 +-19.747043000000001 45.363821000000002 7.3538480000000002 +-47.901049 13.252389000000001 5 +-47.552849999999999 15.450850000000001 0 +-25.093077000000001 42.639868999999997 7.3538480000000002 +-49.245724000000003 4.7623610000000003 32.103847999999999 +-49.245724000000003 4.7623610000000003 25.996151999999999 +-49.715021999999998 1.7992950000000001 37.299999999999997 +46.725797 17.074024999999999 86.799999999999997 +42.325595999999997 14.832011 86.799999999999997 +36.877704999999999 25.524087000000002 20.800000000000001 +36.405749999999998 26.45035 95.760000000000005 +36.405749999999998 26.45035 4.7999999999999998 +-48.307125999999997 10.688492 15.603847999999999 +36.877704999999999 25.524087000000002 37.299999999999997 +-19.747043000000001 45.363821000000002 17.746151999999999 +38.239677999999998 22.851068000000001 15.603847999999999 +36.877704999999999 25.524087000000002 70.299999999999997 +49.450000000000003 0 97.488 +40.963622999999998 17.505030000000001 32.103847999999999 +42.325595999999997 14.832011 20.800000000000001 +42.325595999999997 14.832011 37.299999999999997 +49.25 0 97.680000000000007 +42.797550000000001 13.905749999999999 95.760000000000005 +-27.766093999999999 41.277892999999999 78.549999999999997 +-25.093077000000001 42.639868999999997 67.246151999999995 +47.02975 15.280900000000001 97.488 +-47.837826999999997 13.651558 53.799999999999997 +45.363821000000002 19.747043000000001 9.4961520000000004 +40.963622999999998 17.505030000000001 9.4961520000000004 +40.963622999999998 17.505030000000001 15.603847999999999 +-27.766093999999999 41.277892999999999 29.050000000000001 +40.005899999999997 29.065999999999999 97.488 +46.839550000000003 15.219099999999999 97.680000000000007 +-47.837826999999997 13.651558 37.299999999999997 +41.461371 27.405999000000001 5 +38.239677999999998 22.851068000000001 9.4961520000000004 +38.239677999999998 22.851068000000001 25.996151999999999 +38.239677999999998 22.851068000000001 32.103847999999999 +-25.093077000000001 42.639868999999997 23.853847999999999 +29.065999999999999 40.005899999999997 97.488 +39.844099999999997 28.948399999999999 97.680000000000007 +-49.245724000000003 4.7623610000000003 58.996152000000002 +46.542318999999999 17.434121000000001 5 +42.142118000000004 15.192107 5 +36.877704999999999 25.524087000000002 53.799999999999997 +46.75 0 98.304000000000002 +44.319249999999997 -14.4002 98.256 +44.4619 -14.44655 98.304000000000002 +-25.093077000000001 42.639868999999997 73.353847999999999 +-19.747043000000001 45.363821000000002 67.246151999999995 +-48.307125999999997 10.688492 48.603847999999999 +-49.245724000000003 4.7623610000000003 42.496152000000002 +44.4619 14.44655 98.304000000000002 +44.319249999999997 14.4002 98.256 +46.600000000000001 0 98.256 +-49.715021999999998 1.7992950000000001 53.799999999999997 +40.963622999999998 17.505030000000001 25.996151999999999 +15.219099999999999 46.839550000000003 97.680000000000007 +37.061183 25.163990999999999 5 +42.325595999999997 14.832011 53.799999999999997 +40.963622999999998 17.505030000000001 42.496152000000002 +37.821550000000002 27.478950000000001 98.304000000000002 +37.700200000000002 27.390799999999999 98.256 +-49.715021999999998 1.7992950000000001 70.299999999999997 +29.389250000000001 40.450850000000003 96.239999999999995 +15.450850000000001 47.552849999999999 96.239999999999995 +0 49.25 97.680000000000007 +-48.307125999999997 10.688492 42.496152000000002 +33.549370000000003 29.306730000000002 17.746151999999999 +32.798729999999999 37.041370000000001 17.746151999999999 +27.478950000000001 37.821550000000002 98.304000000000002 +27.390799999999999 37.700200000000002 98.256 +-25.093077000000001 42.639868999999997 17.746151999999999 +-15.280900000000001 47.02975 97.488 +29.306730000000002 33.549370000000003 17.746151999999999 +38.239677999999998 22.851068000000001 42.496152000000002 +38.239677999999998 22.851068000000001 48.603847999999999 +-19.747043000000001 45.363821000000002 40.353847999999999 +-15.219099999999999 46.839550000000003 97.680000000000007 +30.677409000000001 39.162691000000002 12.550000000000001 +14.44655 44.4619 98.304000000000002 +14.4002 44.319249999999997 98.256 +-17.074024999999999 46.725797 78.549999999999997 +-17.074024999999999 46.725797 62.049999999999997 +-29.065999999999999 40.005899999999997 97.488 +27.185409 35.670690999999998 12.550000000000001 +-28.948399999999999 39.844099999999997 97.680000000000007 +39.162691000000002 30.677409000000001 12.550000000000001 +35.670690999999998 27.185409 12.550000000000001 +38.239677999999998 22.851068000000001 75.496151999999995 +0 46.75 98.304000000000002 +0 46.600000000000001 98.256 +-39.844099999999997 28.948399999999999 97.680000000000007 +37.041370000000001 32.798729999999999 7.3538480000000002 +-14.44655 44.4619 98.304000000000002 +-40.005899999999997 29.065999999999999 97.488 +-47.02975 15.280900000000001 97.488 +33.549370000000003 29.306730000000002 7.3538480000000002 +40.963622999999998 17.505030000000001 65.103847999999999 +-14.4002 44.319249999999997 98.256 +-46.839550000000003 15.219099999999999 97.680000000000007 +32.798729999999999 37.041370000000001 7.3538480000000002 +-27.478950000000001 37.821550000000002 98.304000000000002 +-27.390799999999999 37.700200000000002 98.256 +-49.450000000000003 0 97.488 +38.239677999999998 22.851068000000001 65.103847999999999 +-49.25 0 97.680000000000007 +-37.700200000000002 27.390799999999999 98.256 +-25.093077000000001 42.639868999999997 83.746151999999995 +33.549370000000003 29.306730000000002 23.853847999999999 +29.306730000000002 33.549370000000003 23.853847999999999 +-30.677409000000001 39.162691000000002 37.299999999999997 +-30.677409000000001 39.162691000000002 20.800000000000001 +-32.798729999999999 37.041370000000001 32.103847999999999 +19.747043000000001 45.363821000000002 25.996151999999999 +22.851068000000001 38.239677999999998 25.996151999999999 +17.505030000000001 40.963622999999998 25.996151999999999 +-47.552849999999999 -15.450850000000001 0 +-40.450850000000003 29.389250000000001 96.239999999999995 +-40.410400000000003 29.359850000000002 96.384 +27.766093999999999 41.277892999999999 20.800000000000001 +25.524087000000002 36.877704999999999 20.800000000000001 +25.093077000000001 42.639868999999997 25.996151999999999 +49.149999999999999 0 97.775999999999996 +-40.450850000000003 29.389250000000001 0 +32.798729999999999 37.041370000000001 34.246152000000002 +29.306730000000002 33.549370000000003 56.853847999999999 +33.549370000000003 29.306730000000002 50.746152000000002 +-40.963622999999998 17.505030000000001 17.746151999999999 +-42.325595999999997 14.832011 12.550000000000001 +25.093077000000001 42.639868999999997 15.603847999999999 +46.744450000000001 15.1882 97.775999999999996 +30.677409000000001 39.162691000000002 29.050000000000001 +35.670690999999998 27.185409 45.549999999999997 +22.851068000000001 38.239677999999998 15.603847999999999 +0 50 0 +27.185409 35.670690999999998 29.050000000000001 +29.306730000000002 33.549370000000003 40.353847999999999 +-40.963622999999998 17.505030000000001 7.3538480000000002 +19.747043000000001 45.363821000000002 15.603847999999999 +15.450850000000001 47.552849999999999 0 +39.162691000000002 30.677409000000001 29.050000000000001 +35.670690999999998 27.185409 29.050000000000001 +-17.099747000000001 46.712691999999997 95 +0 49.950000000000003 96.480000000000004 +27.537749999999999 37.902450000000002 98.304000000000002 +17.505030000000001 40.963622999999998 15.603847999999999 +28.88965 39.763199999999998 97.775999999999996 +29.389250000000001 40.450850000000003 0 +-49.245724000000003 4.7623610000000003 91.996151999999995 +-38.239677999999998 22.851068000000001 17.746151999999999 +-42.639868999999997 25.093077000000001 17.746151999999999 +17.074024999999999 46.725797 37.299999999999997 +19.747043000000001 45.363821000000002 42.496152000000002 +40.450850000000003 29.389250000000001 0 +-43.130400000000002 14.0139 97.200000000000003 +-45.399999999999999 0 97.296000000000006 +-45.350000000000001 0 97.200000000000003 +-49.245724000000003 4.7623610000000003 9.4961520000000004 +37.041370000000001 32.798729999999999 23.853847999999999 +-19.747043000000001 45.363821000000002 89.853847999999999 +-25.093077000000001 42.639868999999997 89.853847999999999 +26.45035 36.405749999999998 95.760000000000005 +13.905749999999999 42.797550000000001 95.760000000000005 +37.902450000000002 27.537749999999999 98.304000000000002 +14.832011 42.325595999999997 37.299999999999997 +47.552849999999999 15.450850000000001 0 +-49.651800999999999 2.1984650000000001 5 +40.963622999999998 17.505030000000001 75.496151999999995 +22.851068000000001 38.239677999999998 9.4961520000000004 +26.45035 36.405749999999998 4.7999999999999998 +-41.277892999999999 27.766093999999999 12.550000000000001 +-36.877704999999999 25.524087000000002 12.550000000000001 +17.505030000000001 40.963622999999998 32.103847999999999 +19.747043000000001 45.363821000000002 32.103847999999999 +15.1882 46.744450000000001 97.775999999999996 +50 0 0 +32.798729999999999 37.041370000000001 23.853847999999999 +13.905749999999999 42.797550000000001 4.7999999999999998 +14.832011 42.325595999999997 20.800000000000001 +44.557000000000002 14.477449999999999 98.304000000000002 +47.552849999999999 -15.450850000000001 0 +-38.239677999999998 22.851068000000001 7.3538480000000002 +25.093077000000001 42.639868999999997 42.496152000000002 +22.851068000000001 38.239677999999998 42.496152000000002 +0 49.149999999999999 97.775999999999996 +37.041370000000001 32.798729999999999 50.746152000000002 +32.798729999999999 37.041370000000001 50.746152000000002 +29.306730000000002 33.549370000000003 50.746152000000002 +30.677409000000001 39.162691000000002 45.549999999999997 +-42.325595999999997 14.832011 29.050000000000001 +-45.363821000000002 19.747043000000001 23.853847999999999 +-46.725797 17.074024999999999 29.050000000000001 +22.851068000000001 38.239677999999998 32.103847999999999 +-39.763199999999998 28.88965 97.775999999999996 +-46.725797 17.074024999999999 78.549999999999997 +-45.363821000000002 19.747043000000001 83.746151999999995 +-36.688899999999997 26.65605 97.200000000000003 +-43.177950000000003 14.029350000000001 97.296000000000006 +-49.715021999999998 -1.7992950000000001 12.550000000000001 +-30.677409000000001 39.162691000000002 53.799999999999997 +-38.239677999999998 22.851068000000001 34.246152000000002 +-40.963622999999998 17.505030000000001 34.246152000000002 +-42.639868999999997 25.093077000000001 34.246152000000002 +17.074024999999999 46.725797 53.799999999999997 +19.747043000000001 45.363821000000002 58.996152000000002 +17.505030000000001 40.963622999999998 58.996152000000002 +-46.744450000000001 15.1882 97.775999999999996 +-49.245724000000003 -4.7623610000000003 7.3538480000000002 +-48.307125999999997 -10.688492 7.3538480000000002 +39.162691000000002 30.677409000000001 45.549999999999997 +37.041370000000001 32.798729999999999 40.353847999999999 +-39.162691000000002 30.677409000000001 20.800000000000001 +32.798729999999999 37.041370000000001 67.246151999999995 +45.555599999999998 14.8019 98.352000000000004 +47.75 0 98.400000000000006 +-26.65605 36.688899999999997 97.200000000000003 +29.306730000000002 33.549370000000003 67.246151999999995 +-39.162691000000002 30.677409000000001 70.299999999999997 +-37.041370000000001 32.798729999999999 58.996152000000002 +27.185409 35.670690999999998 78.549999999999997 +28.066749999999999 38.630549999999999 98.400000000000006 +27.185409 35.670690999999998 45.549999999999997 +0 46.850000000000001 98.304000000000002 +-29.359850000000002 40.410400000000003 96.384 +25.524087000000002 36.877704999999999 53.799999999999997 +22.851068000000001 38.239677999999998 48.603847999999999 +-45.363821000000002 19.747043000000001 34.246152000000002 +14.832011 42.325595999999997 53.799999999999997 +-36.877704999999999 25.524087000000002 29.050000000000001 +19.747043000000001 45.363821000000002 48.603847999999999 +-38.239677999999998 22.851068000000001 23.853847999999999 +25.093077000000001 42.639868999999997 58.996152000000002 +14.601050000000001 44.937399999999997 98.400000000000006 +0 47.25 98.400000000000006 +14.755549999999999 45.412950000000002 98.400000000000006 +-40.963622999999998 17.505030000000001 23.853847999999999 +27.766093999999999 41.277892999999999 53.799999999999997 +-38.226050000000001 27.772849999999998 98.400000000000006 +-27.772849999999998 38.226050000000001 98.400000000000006 +-40.963622999999998 17.505030000000001 50.746152000000002 +-42.325595999999997 14.832011 45.549999999999997 +25.093077000000001 42.639868999999997 48.603847999999999 +-47.25 0 98.400000000000006 +-40.963622999999998 17.505030000000001 40.353847999999999 +-38.239677999999998 22.851068000000001 50.746152000000002 +17.074024999999999 46.725797 70.299999999999997 +19.747043000000001 45.363821000000002 75.496151999999995 +43.891249999999999 14.261150000000001 98.016000000000005 +43.796149999999997 14.23025 97.920000000000002 +46.049999999999997 0 97.920000000000002 +-14.755549999999999 45.412950000000002 98.400000000000006 +-36.877704999999999 25.524087000000002 45.549999999999997 +-14.601050000000001 44.937399999999997 98.400000000000006 +37.336150000000004 27.126300000000001 98.016000000000005 +37.255249999999997 27.067499999999999 97.920000000000002 +0 47.75 98.400000000000006 +-38.239677999999998 22.851068000000001 40.353847999999999 +25.093077000000001 42.639868999999997 75.496151999999995 +-37.255249999999997 27.067499999999999 97.920000000000002 +-43.891249999999999 14.261150000000001 98.016000000000005 +-43.796149999999997 14.23025 97.920000000000002 +46.725797 -17.074024999999999 12.550000000000001 +27.766093999999999 41.277892999999999 70.299999999999997 +-46.149999999999999 0 98.016000000000005 +45.363821000000002 -19.747043000000001 17.746151999999999 +27.126300000000001 37.336150000000004 98.016000000000005 +27.067499999999999 37.255249999999997 97.920000000000002 +47.552849999999999 -15.450850000000001 96.239999999999995 +-40.963622999999998 17.505030000000001 67.246151999999995 +-42.325595999999997 14.832011 62.049999999999997 +25.093077000000001 42.639868999999997 65.103847999999999 +45.363821000000002 -19.747043000000001 23.853847999999999 +45.412950000000002 -14.755549999999999 98.400000000000006 +-40.963622999999998 17.505030000000001 56.853847999999999 +-14.23025 43.796149999999997 97.920000000000002 +-27.126300000000001 37.336150000000004 98.016000000000005 +-27.067499999999999 37.255249999999997 97.920000000000002 +-38.239677999999998 22.851068000000001 67.246151999999995 +17.074024999999999 46.725797 86.799999999999997 +-37.336150000000004 27.126300000000001 98.016000000000005 +-36.877704999999999 25.524087000000002 62.049999999999997 +19.747043000000001 45.363821000000002 81.603847999999999 +-38.239677999999998 22.851068000000001 56.853847999999999 +25.093077000000001 42.639868999999997 91.996151999999995 +27.766093999999999 41.277892999999999 86.799999999999997 +-40.963622999999998 17.505030000000001 83.746151999999995 +-42.325595999999997 14.832011 78.549999999999997 +25.093077000000001 42.639868999999997 81.603847999999999 +-44.937399999999997 14.601050000000001 98.400000000000006 +-40.963622999999998 17.505030000000001 73.353847999999999 +-38.239677999999998 22.851068000000001 83.746151999999995 +25.093077000000001 42.639868999999997 9.4961520000000004 +19.747043000000001 45.363821000000002 9.4961520000000004 +-15.4354 47.505249999999997 96.384 +-15.4354 47.505249999999997 96.480000000000004 +-36.877704999999999 25.524087000000002 78.549999999999997 +17.434121000000001 46.542318999999999 5 +1.055264 44.832863000000003 95 +0 45 95.760000000000005 +3.9898180000000001 44.368076000000002 23.853847999999999 +1.0267520000000001 44.837378999999999 29.050000000000001 +-38.239677999999998 22.851068000000001 73.353847999999999 +27.405999000000001 41.461371 5 +3.9898180000000001 44.368076000000002 50.746152000000002 +9.9159480000000002 43.429470999999999 50.746152000000002 +14.029350000000001 43.177950000000003 97.296000000000006 +26.65605 36.688899999999997 97.200000000000003 +3.9898180000000001 44.368076000000002 7.3538480000000002 +0 45 4.7999999999999998 +-47 0 98.352000000000004 +12.879013 42.960169 12.550000000000001 +9.9159480000000002 43.429470999999999 7.3538480000000002 +-27.625900000000001 38.023800000000001 98.352000000000004 +-38.023800000000001 27.625900000000001 98.352000000000004 +-40.963622999999998 17.505030000000001 89.853847999999999 +-42.312489999999997 14.857732 95 +0 50 96.239999999999995 +1.0267520000000001 44.837378999999999 62.049999999999997 +1.0267520000000001 44.837378999999999 78.549999999999997 +-36.890810999999999 25.498366000000001 95 +3.9898180000000001 44.368076000000002 83.746151999999995 +9.9159480000000002 43.429470999999999 83.746151999999995 +3.9898180000000001 44.368076000000002 89.853847999999999 +-14.5238 44.699649999999998 98.352000000000004 +-38.239677999999998 22.851068000000001 89.853847999999999 +1.7992950000000001 49.715021999999998 12.550000000000001 +-47.505249999999997 15.4354 96.384 +12.879013 42.960169 29.050000000000001 +36.729349999999997 26.685449999999999 97.296000000000006 +36.688899999999997 26.65605 97.200000000000003 +9.9159480000000002 43.429470999999999 67.246151999999995 +12.879013 42.960169 62.049999999999997 +12.879013 42.960169 78.549999999999997 +0 47 98.352000000000004 +13.651558 47.837826999999997 12.550000000000001 +-49.950000000000003 0 96.384 +14.5238 44.699649999999998 98.352000000000004 +-40.410400000000003 29.359850000000002 96.480000000000004 +10.688492 48.307125999999997 7.3538480000000002 +-44.368076000000002 3.9898180000000001 25.996151999999999 +-44.837378999999999 1.0267520000000001 20.800000000000001 +-29.359850000000002 40.410400000000003 96.480000000000004 +26.685449999999999 36.729349999999997 97.296000000000006 +27.625900000000001 38.023800000000001 98.352000000000004 +-47.505249999999997 15.4354 96.480000000000004 +4.7623610000000003 49.245724000000003 7.3538480000000002 +-44.368076000000002 3.9898180000000001 15.603847999999999 +3.9898180000000001 44.368076000000002 67.246151999999995 +3.9898180000000001 44.368076000000002 73.353847999999999 +38.023800000000001 27.625900000000001 98.352000000000004 +12.879013 42.960169 45.549999999999997 +9.9159480000000002 43.429470999999999 34.246152000000002 +-49.950000000000003 0 96.480000000000004 +-43.429470999999999 9.9159480000000002 25.996151999999999 +46.126249999999999 14.987299999999999 98.207999999999998 +39.237299999999998 28.5076 98.207999999999998 +46.031149999999997 14.9564 98.256 +39.156399999999998 28.448799999999999 98.256 +10.688492 48.307125999999997 34.246152000000002 +4.7623610000000003 49.245724000000003 34.246152000000002 +-42.960169 12.879013 20.800000000000001 +3.9898180000000001 44.368076000000002 34.246152000000002 +46.850000000000001 0 98.304000000000002 +44.557000000000002 -14.477449999999999 98.304000000000002 +47 0 98.352000000000004 +-44.368076000000002 3.9898180000000001 91.996151999999995 +-42.797550000000001 13.905749999999999 95.760000000000005 +-45 0 95.760000000000005 +1.7992950000000001 49.715021999999998 29.050000000000001 +-43.429470999999999 9.9159480000000002 15.603847999999999 +1.0267520000000001 44.837378999999999 45.549999999999997 +44.699649999999998 14.5238 98.352000000000004 +-42.797550000000001 13.905749999999999 4.7999999999999998 +14.987299999999999 46.126249999999999 98.207999999999998 +14.9564 46.031149999999997 98.256 +28.448799999999999 39.156399999999998 98.256 +47.901049 -13.252389000000001 5 +-45 0 4.7999999999999998 +0 48.5 98.207999999999998 +49.715021999999998 -1.7992950000000001 20.800000000000001 +49.245724000000003 -4.7623610000000003 15.603847999999999 +44.699649999999998 -14.5238 98.352000000000004 +-44.368076000000002 3.9898180000000001 75.496151999999995 +-43.429470999999999 9.9159480000000002 75.496151999999995 +-44.368076000000002 3.9898180000000001 81.603847999999999 +0 48.399999999999999 98.256 +47.837826999999997 -13.651558 20.800000000000001 +48.307125999999997 -10.688492 15.603847999999999 +-42.960169 12.879013 37.299999999999997 +-43.429470999999999 9.9159480000000002 32.103847999999999 +-44.368076000000002 3.9898180000000001 42.496152000000002 +-44.837378999999999 1.0267520000000001 37.299999999999997 +-14.987299999999999 46.126249999999999 98.207999999999998 +49.245724000000003 -4.7623610000000003 25.996151999999999 +49.245724000000003 -4.7623610000000003 32.103847999999999 +-14.9564 46.031149999999997 98.256 +-28.5076 39.237299999999998 98.207999999999998 +48.307125999999997 -10.688492 25.996151999999999 +49.049999999999997 0 97.872 +-43.429470999999999 9.9159480000000002 42.496152000000002 +-39.237299999999998 28.5076 98.207999999999998 +-39.156399999999998 28.448799999999999 98.256 +-28.448799999999999 39.156399999999998 98.256 +48.307125999999997 -10.688492 32.103847999999999 +9.9159480000000002 43.429470999999999 89.853847999999999 +10.688492 48.307125999999997 50.746152000000002 +4.7623610000000003 49.245724000000003 50.746152000000002 +46.649299999999997 15.157299999999999 97.872 +-46.126249999999999 14.987299999999999 98.207999999999998 +-46.031149999999997 14.9564 98.256 +49.715021999999998 -1.7992950000000001 37.299999999999997 +9.9159480000000002 43.429470999999999 40.353847999999999 +3.9898180000000001 44.368076000000002 40.353847999999999 +1.7992950000000001 49.715021999999998 45.549999999999997 +39.682299999999998 28.830850000000002 97.872 +-46.25 0 98.063999999999993 +47.837826999999997 -13.651558 53.799999999999997 +47.837826999999997 -13.651558 70.299999999999997 +28.830850000000002 39.682299999999998 97.872 +13.651558 47.837826999999997 45.549999999999997 +12.850501 42.964685000000003 95 +-44.837378999999999 1.0267520000000001 53.799999999999997 +10.688492 48.307125999999997 40.353847999999999 +15.157299999999999 46.649299999999997 97.872 +-44.368076000000002 3.9898180000000001 58.996152000000002 +49.245724000000003 -4.7623610000000003 58.996152000000002 +49.715021999999998 -1.7992950000000001 53.799999999999997 +49.715021999999998 -1.7992950000000001 70.299999999999997 +49.245724000000003 -4.7623610000000003 65.103847999999999 +9.9159480000000002 43.429470999999999 73.353847999999999 +-15.157299999999999 46.649299999999997 97.872 +48.307125999999997 -10.688492 75.496151999999995 +48.307125999999997 -10.688492 81.603847999999999 +10.688492 48.307125999999997 67.246151999999995 +4.7623610000000003 49.245724000000003 67.246151999999995 +-28.830850000000002 39.682299999999998 97.872 +-39.682299999999998 28.830850000000002 97.872 +1.7992950000000001 49.715021999999998 62.049999999999997 +49.651800999999999 -2.1984650000000001 5 +13.651558 47.837826999999997 62.049999999999997 +-9.9159480000000002 43.429470999999999 91.996151999999995 +-13.905749999999999 42.797550000000001 95.760000000000005 +-9.9159480000000002 43.429470999999999 75.496151999999995 +-3.9898180000000001 44.368076000000002 75.496151999999995 +-9.9159480000000002 43.429470999999999 81.603847999999999 +10.688492 48.307125999999997 56.853847999999999 +4.7623610000000003 49.245724000000003 56.853847999999999 +-1.0267520000000001 44.837378999999999 37.299999999999997 +-3.9898180000000001 44.368076000000002 32.103847999999999 +-1.0267520000000001 44.837378999999999 20.800000000000001 +46.25 0 98.063999999999993 +43.891249999999999 -14.261150000000001 98.016000000000005 +49.245724000000003 -4.7623610000000003 81.603847999999999 +-9.9159480000000002 43.429470999999999 32.103847999999999 +-9.9159480000000002 43.429470999999999 25.996151999999999 +-13.905749999999999 42.797550000000001 4.7999999999999998 +-9.9159480000000002 43.429470999999999 15.603847999999999 +10.688492 48.307125999999997 83.746151999999995 +4.7623610000000003 49.245724000000003 83.746151999999995 +43.986350000000002 14.29205 98.063999999999993 +46.149999999999999 0 98.016000000000005 +-3.9898180000000001 44.368076000000002 9.4961520000000004 +-1.4259219999999999 44.774157000000002 5 +1.7992950000000001 49.715021999999998 78.549999999999997 +-12.879013 42.960169 86.799999999999997 +13.651558 47.837826999999997 78.549999999999997 +-1.0267520000000001 44.837378999999999 53.799999999999997 +-3.9898180000000001 44.368076000000002 48.603847999999999 +-3.9898180000000001 44.368076000000002 42.496152000000002 +44.794750000000001 -14.5547 98.352000000000004 +0 46.149999999999999 98.016000000000005 +14.261150000000001 43.891249999999999 98.016000000000005 +-12.879013 42.960169 53.799999999999997 +38.104700000000001 27.684699999999999 98.352000000000004 +44.794750000000001 14.5547 98.352000000000004 +4.7623610000000003 49.245724000000003 73.353847999999999 +-9.9159480000000002 43.429470999999999 65.103847999999999 +-12.879013 42.960169 70.299999999999997 +-9.9159480000000002 43.429470999999999 58.996152000000002 +27.684699999999999 38.104700000000001 98.352000000000004 +-14.261150000000001 43.891249999999999 98.016000000000005 +4.7623610000000003 49.245724000000003 89.853847999999999 +1.827807 49.710507 95 +49.245724000000003 -4.7623610000000003 9.4961520000000004 +-9.9159480000000002 43.429470999999999 42.496152000000002 +13.623046 47.842343 95 +47.837826999999997 13.651558 12.550000000000001 +10.688492 48.307125999999997 89.853847999999999 +-43.320599999999999 14.075699999999999 97.488 +47.837826999999997 13.651558 29.050000000000001 +49.715021999999998 1.7992950000000001 12.550000000000001 +49.245724000000003 4.7623610000000003 17.746151999999999 +49.245724000000003 4.7623610000000003 23.853847999999999 +47.837826999999997 13.651558 78.549999999999997 +47.837826999999997 13.651558 62.049999999999997 +49.245724000000003 4.7623610000000003 7.3538480000000002 +48.307125999999997 10.688492 50.746152000000002 +-26.773599999999998 36.850700000000003 97.488 +-36.850700000000003 26.773599999999998 97.488 +42.325595999999997 -14.832011 45.549999999999997 +-1.0267520000000001 44.837378999999999 86.799999999999997 +-3.9898180000000001 44.368076000000002 91.996151999999995 +-39.601399999999998 28.772099999999998 97.920000000000002 +40.963622999999998 -17.505030000000001 50.746152000000002 +46.350000000000001 0 98.159999999999997 +42.639868999999997 25.093077000000001 65.103847999999999 +-3.9898180000000001 44.368076000000002 81.603847999999999 +44.081449999999997 -14.322950000000001 98.159999999999997 +-48.950000000000003 0 97.920000000000002 +44.081449999999997 14.322950000000001 98.159999999999997 +40.450850000000003 29.389250000000001 96.239999999999995 +-45.75 0 97.680000000000007 +-12.479844 43.023390999999997 5 +-29.306730000000002 33.549370000000003 15.603847999999999 +-33.549370000000003 29.306730000000002 15.603847999999999 +-29.306730000000002 33.549370000000003 9.4961520000000004 +45.363821000000002 19.747043000000001 65.103847999999999 +-35.670690999999998 27.185409 53.799999999999997 +-33.549370000000003 29.306730000000002 58.996152000000002 +-35.670690999999998 27.185409 70.299999999999997 +-42.797550000000001 -13.905749999999999 4.7999999999999998 +-17.505030000000001 40.963622999999998 17.746151999999999 +-22.851068000000001 38.239677999999998 17.746151999999999 +47.837826999999997 13.651558 45.549999999999997 +48.307125999999997 10.688492 17.746151999999999 +49.715021999999998 1.7992950000000001 29.050000000000001 +48.307125999999997 10.688492 23.853847999999999 +48.307125999999997 10.688492 40.353847999999999 +48.307125999999997 10.688492 34.246152000000002 +-48.399999999999999 0 98.256 +-45.888500000000001 14.91005 98.304000000000002 +48.307125999999997 10.688492 67.246151999999995 +48.307125999999997 10.688492 73.353847999999999 +49.245724000000003 4.7623610000000003 34.246152000000002 +49.245724000000003 4.7623610000000003 40.353847999999999 +48.399999999999999 0 98.256 +45.888500000000001 -14.91005 98.304000000000002 +46.031149999999997 -14.9564 98.256 +47.505249999999997 -15.4354 96.384 +49.245724000000003 4.7623610000000003 73.353847999999999 +47.842343 13.623046 95 +40.963622999999998 -17.505030000000001 7.3538480000000002 +49.710507 1.827807 95 +42.325595999999997 -14.832011 12.550000000000001 +48.307125999999997 10.688492 89.853847999999999 +49.245724000000003 4.7623610000000003 89.853847999999999 +40.963622999999998 -17.505030000000001 17.746151999999999 +38.239677999999998 -22.851068000000001 17.746151999999999 +38.239677999999998 -22.851068000000001 23.853847999999999 +42.325595999999997 -14.832011 29.050000000000001 +41.277892999999999 27.766093999999999 20.800000000000001 +42.639868999999997 25.093077000000001 15.603847999999999 +40.963622999999998 -17.505030000000001 40.353847999999999 +37.497950000000003 27.243849999999998 98.159999999999997 +-27.243849999999998 37.497950000000003 98.159999999999997 +-37.497950000000003 27.243849999999998 98.159999999999997 +38.954149999999998 28.301850000000002 98.304000000000002 +45.793349999999997 14.879149999999999 98.304000000000002 +28.301850000000002 38.954149999999998 98.304000000000002 +14.879149999999999 45.793349999999997 98.304000000000002 +0 48.149999999999999 98.304000000000002 +-38.954149999999998 28.301850000000002 98.304000000000002 +-28.301850000000002 38.954149999999998 98.304000000000002 +48.149999999999999 0 98.304000000000002 +-48.149999999999999 0 98.304000000000002 +49.950000000000003 0 96.384 +-14.879149999999999 45.793349999999997 98.304000000000002 +32.798729999999999 37.041370000000001 40.353847999999999 +43.429470999999999 -9.9159480000000002 15.603847999999999 +42.960169 -12.879013 20.800000000000001 +44.368076000000002 -3.9898180000000001 15.603847999999999 +44.837378999999999 -1.0267520000000001 20.800000000000001 +44.368076000000002 -3.9898180000000001 25.996151999999999 +30.677409000000001 39.162691000000002 78.549999999999997 +43.429470999999999 -9.9159480000000002 25.996151999999999 +43.429470999999999 -9.9159480000000002 32.103847999999999 +42.960169 -12.879013 37.299999999999997 +32.798729999999999 37.041370000000001 73.353847999999999 +44.368076000000002 -3.9898180000000001 32.103847999999999 +44.837378999999999 -1.0267520000000001 37.299999999999997 +45.793349999999997 -14.879149999999999 98.304000000000002 +-45.793349999999997 14.879149999999999 98.304000000000002 +43.429470999999999 -9.9159480000000002 42.496152000000002 +43.429470999999999 -9.9159480000000002 48.603847999999999 +42.960169 -12.879013 53.799999999999997 +-46.5 0 98.207999999999998 +44.368076000000002 -3.9898180000000001 48.603847999999999 +44.837378999999999 -1.0267520000000001 53.799999999999997 +32.798729999999999 37.041370000000001 83.746151999999995 +37.041370000000001 32.798729999999999 83.746151999999995 +44.368076000000002 -3.9898180000000001 58.996152000000002 +43.429470999999999 -9.9159480000000002 58.996152000000002 +43.429470999999999 -9.9159480000000002 65.103847999999999 +37.041370000000001 32.798729999999999 89.853847999999999 +32.798729999999999 37.041370000000001 89.853847999999999 +44.368076000000002 -3.9898180000000001 65.103847999999999 +44.837378999999999 -1.0267520000000001 70.299999999999997 +47.505249999999997 -15.4354 96.480000000000004 +49.950000000000003 0 96.480000000000004 +44.368076000000002 -3.9898180000000001 75.496151999999995 +42.797550000000001 -13.905749999999999 4.7999999999999998 +36.405749999999998 -26.45035 4.7999999999999998 +46.5 0 98.207999999999998 +43.429470999999999 -9.9159480000000002 75.496151999999995 +44.224150000000002 -14.369300000000001 98.207999999999998 +44.224150000000002 14.369300000000001 98.207999999999998 +42.797550000000001 -13.905749999999999 95.760000000000005 +37.619300000000003 27.332000000000001 98.207999999999998 +17.074024999999999 46.725797 20.800000000000001 +25.093077000000001 42.639868999999997 32.103847999999999 +44.368076000000002 -3.9898180000000001 81.603847999999999 +27.332000000000001 37.619300000000003 98.207999999999998 +44.837378999999999 -1.0267520000000001 86.799999999999997 +14.369300000000001 44.224150000000002 98.207999999999998 +0 46.5 98.207999999999998 +44.368076000000002 -3.9898180000000001 91.996151999999995 +-44.224150000000002 14.369300000000001 98.207999999999998 +43.429470999999999 -9.9159480000000002 91.996151999999995 +-14.369300000000001 44.224150000000002 98.207999999999998 +44.774157000000002 -1.4259219999999999 5 +-27.332000000000001 37.619300000000003 98.207999999999998 +27.766093999999999 41.277892999999999 37.299999999999997 +43.023390999999997 -12.479844 5 +43.429470999999999 -9.9159480000000002 9.4961520000000004 +-37.619300000000003 27.332000000000001 98.207999999999998 +42.325595999999997 -14.832011 62.049999999999997 +40.963622999999998 -17.505030000000001 56.853847999999999 +47.505249999999997 15.4354 96.384 +43.429470999999999 9.9159480000000002 17.746151999999999 +42.960169 12.879013 12.550000000000001 +44.837378999999999 1.0267520000000001 12.550000000000001 +44.368076000000002 3.9898180000000001 7.3538480000000002 +43.429470999999999 9.9159480000000002 34.246152000000002 +42.960169 12.879013 29.050000000000001 +44.368076000000002 3.9898180000000001 34.246152000000002 +48 0 98.352000000000004 +44.837378999999999 1.0267520000000001 29.050000000000001 +45.650700000000001 14.832800000000001 98.352000000000004 +38.832799999999999 28.213699999999999 98.352000000000004 +28.213699999999999 38.832799999999999 98.352000000000004 +47.505249999999997 15.4354 96.480000000000004 +14.832800000000001 45.650700000000001 98.352000000000004 +45 0 4.7999999999999998 +43.429470999999999 9.9159480000000002 50.746152000000002 +0 48 98.352000000000004 +42.960169 12.879013 45.549999999999997 +44.368076000000002 3.9898180000000001 50.746152000000002 +-14.832800000000001 45.650700000000001 98.352000000000004 +45 0 95.760000000000005 +-38.832799999999999 28.213699999999999 98.352000000000004 +44.368076000000002 3.9898180000000001 40.353847999999999 +-45.650700000000001 14.832800000000001 98.352000000000004 +43.429470999999999 9.9159480000000002 40.353847999999999 +-48 0 98.352000000000004 +-46.600000000000001 0 98.256 +43.429470999999999 9.9159480000000002 67.246151999999995 +43.429470999999999 9.9159480000000002 56.853847999999999 +42.960169 12.879013 78.549999999999997 +44.837378999999999 1.0267520000000001 78.549999999999997 +44.368076000000002 3.9898180000000001 73.353847999999999 +43.429470999999999 9.9159480000000002 73.353847999999999 +10.688492 48.307125999999997 73.353847999999999 +44.832863000000003 1.055264 95 +42.964685000000003 12.850501 95 +43.429470999999999 9.9159480000000002 89.853847999999999 +44.368076000000002 3.9898180000000001 89.853847999999999 +-13.651558 47.837826999999997 70.299999999999997 +-13.651558 47.837826999999997 86.799999999999997 +-1.7992950000000001 49.715021999999998 20.800000000000001 +-4.7623610000000003 49.245724000000003 15.603847999999999 +-13.651558 47.837826999999997 53.799999999999997 +-14.8019 45.555599999999998 98.352000000000004 +0 47.899999999999999 98.352000000000004 +14.8019 45.555599999999998 98.352000000000004 +-10.688492 48.307125999999997 42.496152000000002 +-10.688492 48.307125999999997 48.603847999999999 +47.899999999999999 0 98.352000000000004 +45.555599999999998 -14.8019 98.352000000000004 +33.549370000000003 29.306730000000002 40.353847999999999 +-32.798729999999999 37.041370000000001 15.603847999999999 +-30.963183000000001 38.876916999999999 5 +-32.798729999999999 37.041370000000001 9.4961520000000004 +27.205822000000001 35.650278 95 +-37.041370000000001 32.798729999999999 65.103847999999999 +29.306730000000002 33.549370000000003 83.746151999999995 +33.549370000000003 29.306730000000002 83.746151999999995 +29.306730000000002 33.549370000000003 89.853847999999999 +29.306730000000002 33.549370000000003 73.353847999999999 +-32.798729999999999 37.041370000000001 65.103847999999999 +-32.798729999999999 37.041370000000001 58.996152000000002 +-37.041370000000001 32.798729999999999 81.603847999999999 +-39.162691000000002 30.677409000000001 86.799999999999997 +-30.677409000000001 39.162691000000002 86.799999999999997 +-32.798729999999999 37.041370000000001 81.603847999999999 +33.549370000000003 29.306730000000002 89.853847999999999 +-37.041370000000001 32.798729999999999 9.4961520000000004 +-38.876916999999999 30.963183000000001 5 +-3.9898180000000001 44.368076000000002 15.603847999999999 +-3.9898180000000001 44.368076000000002 25.996151999999999 +47.100000000000001 0 98.352000000000004 +-36.405749999999998 26.45035 4.7999999999999998 +-26.45035 36.405749999999998 4.7999999999999998 +-26.45035 36.405749999999998 95.760000000000005 +-27.185409 35.670690999999998 20.800000000000001 +-27.471183 35.384917000000002 5 +-36.405749999999998 26.45035 95.760000000000005 +-33.549370000000003 29.306730000000002 9.4961520000000004 +-33.549370000000003 29.306730000000002 25.996151999999999 +-35.670690999999998 27.185409 37.299999999999997 +-35.384917000000002 27.471183 5 +-9.9159480000000002 43.429470999999999 48.603847999999999 +-3.9898180000000001 44.368076000000002 58.996152000000002 +-1.0267520000000001 44.837378999999999 70.299999999999997 +-3.9898180000000001 44.368076000000002 65.103847999999999 +-9.9159480000000002 43.429470999999999 9.4961520000000004 +-25.524087000000002 36.877704999999999 12.550000000000001 +-14.832011 42.325595999999997 12.550000000000001 +-17.505030000000001 40.963622999999998 7.3538480000000002 +-22.851068000000001 38.239677999999998 7.3538480000000002 +-17.505030000000001 40.963622999999998 34.246152000000002 +-22.851068000000001 38.239677999999998 34.246152000000002 +-25.524087000000002 36.877704999999999 29.050000000000001 +-14.832011 42.325595999999997 29.050000000000001 +-17.505030000000001 40.963622999999998 23.853847999999999 +-22.851068000000001 38.239677999999998 23.853847999999999 +-17.505030000000001 40.963622999999998 50.746152000000002 +-22.851068000000001 38.239677999999998 50.746152000000002 +-25.524087000000002 36.877704999999999 45.549999999999997 +-14.832011 42.325595999999997 45.549999999999997 +-17.505030000000001 40.963622999999998 40.353847999999999 +-22.851068000000001 38.239677999999998 40.353847999999999 +-17.505030000000001 40.963622999999998 67.246151999999995 +-22.851068000000001 38.239677999999998 67.246151999999995 +-25.524087000000002 36.877704999999999 62.049999999999997 +-14.832011 42.325595999999997 62.049999999999997 +-17.505030000000001 40.963622999999998 56.853847999999999 +-22.851068000000001 38.239677999999998 56.853847999999999 +-17.505030000000001 40.963622999999998 83.746151999999995 +-22.851068000000001 38.239677999999998 83.746151999999995 +-25.524087000000002 36.877704999999999 78.549999999999997 +-14.832011 42.325595999999997 78.549999999999997 +-17.505030000000001 40.963622999999998 73.353847999999999 +-22.851068000000001 38.239677999999998 73.353847999999999 +-25.498366000000001 36.890810999999999 95 +-22.851068000000001 38.239677999999998 89.853847999999999 +-14.857732 42.312489999999997 95 +-17.505030000000001 40.963622999999998 89.853847999999999 +-29.306730000000002 33.549370000000003 25.996151999999999 +-29.306730000000002 33.549370000000003 32.103847999999999 +-33.549370000000003 29.306730000000002 32.103847999999999 +-29.306730000000002 33.549370000000003 58.996152000000002 +-27.185409 35.670690999999998 53.799999999999997 +-29.306730000000002 33.549370000000003 75.496151999999995 +-33.549370000000003 29.306730000000002 75.496151999999995 +-27.185409 35.670690999999998 70.299999999999997 +-29.306730000000002 33.549370000000003 65.103847999999999 +-33.549370000000003 29.306730000000002 65.103847999999999 +-29.306730000000002 33.549370000000003 91.996151999999995 +-33.549370000000003 29.306730000000002 91.996151999999995 +-35.670690999999998 27.185409 86.799999999999997 +-27.185409 35.670690999999998 86.799999999999997 +-29.306730000000002 33.549370000000003 81.603847999999999 +-33.549370000000003 29.306730000000002 81.603847999999999 +-15.41995 47.457700000000003 96.623999999999995 +-29.330500000000001 40.369950000000003 96.623999999999995 +-40.369950000000003 29.330500000000001 96.623999999999995 +-47.457700000000003 15.41995 96.623999999999995 +-49.899999999999999 0 96.623999999999995 +-26.45035 -36.405749999999998 4.7999999999999998 +-36.405749999999998 -26.45035 4.7999999999999998 +-13.905749999999999 -42.797550000000001 4.7999999999999998 +0 -45 4.7999999999999998 +13.905749999999999 -42.797550000000001 4.7999999999999998 +26.45035 -36.405749999999998 4.7999999999999998 +-42.797550000000001 13.905749999999999 96.239999999999995 +-45 0 96.239999999999995 +-36.405749999999998 26.45035 96.239999999999995 +0 49.899999999999999 96.623999999999995 +-26.45035 36.405749999999998 96.239999999999995 +-15.41995 47.457700000000003 96.719999999999999 +0 49.899999999999999 96.719999999999999 +-29.330500000000001 40.369950000000003 96.719999999999999 +-40.369950000000003 29.330500000000001 96.719999999999999 +-47.457700000000003 15.41995 96.719999999999999 +-49.899999999999999 0 96.719999999999999 +-45.049999999999997 0 96.384 +-42.845100000000002 13.921200000000001 96.384 +-26.479749999999999 36.446199999999997 96.384 +-36.446199999999997 26.479749999999999 96.384 +47.457700000000003 -15.41995 96.623999999999995 +49.899999999999999 0 96.623999999999995 +45 0 96.239999999999995 +42.797550000000001 -13.905749999999999 96.239999999999995 +47.457700000000003 15.41995 96.623999999999995 +42.797550000000001 13.905749999999999 96.239999999999995 +40.369950000000003 29.330500000000001 96.623999999999995 +29.330500000000001 40.369950000000003 96.623999999999995 +36.405749999999998 26.45035 96.239999999999995 +15.41995 47.457700000000003 96.623999999999995 +26.45035 36.405749999999998 96.239999999999995 +13.905749999999999 42.797550000000001 96.239999999999995 +0 45 96.239999999999995 +-13.905749999999999 42.797550000000001 96.239999999999995 +15.41995 47.457700000000003 96.719999999999999 +15.404500000000001 47.410150000000002 96.864000000000004 +0 49.850000000000001 96.864000000000004 +-15.404500000000001 47.410150000000002 96.864000000000004 +-29.301100000000002 40.329500000000003 96.864000000000004 +-40.329500000000003 29.301100000000002 96.864000000000004 +-47.410150000000002 15.404500000000001 96.864000000000004 +-49.850000000000001 0 96.864000000000004 +-45.049999999999997 0 96.480000000000004 +-42.845100000000002 13.921200000000001 96.480000000000004 +-36.446199999999997 26.479749999999999 96.480000000000004 +-26.479749999999999 36.446199999999997 96.480000000000004 +-13.921200000000001 42.845100000000002 96.384 +-13.921200000000001 42.845100000000002 96.480000000000004 +29.2423 40.248600000000003 97.103999999999999 +40.248600000000003 29.2423 97.103999999999999 +15.3736 47.315049999999999 97.103999999999999 +0 49.75 97.103999999999999 +-15.3736 47.315049999999999 97.103999999999999 +-29.2423 40.248600000000003 97.103999999999999 +-40.248600000000003 29.2423 97.103999999999999 +-47.315049999999999 15.3736 97.103999999999999 +-49.75 0 97.103999999999999 +-45.100000000000001 0 96.719999999999999 +-42.892650000000003 13.93665 96.719999999999999 +-36.486649999999997 26.5091 96.719999999999999 +-26.5091 36.486649999999997 96.719999999999999 +-13.93665 42.892650000000003 96.719999999999999 +0 45.100000000000001 96.719999999999999 +47.315049999999999 15.3736 97.103999999999999 +47.219949999999997 15.342700000000001 97.200000000000003 +40.167700000000004 29.18355 97.200000000000003 +29.18355 40.167700000000004 97.200000000000003 +15.342700000000001 47.219949999999997 97.200000000000003 +0 49.649999999999999 97.200000000000003 +-15.342700000000001 47.219949999999997 97.200000000000003 +-29.18355 40.167700000000004 97.200000000000003 +-40.167700000000004 29.18355 97.200000000000003 +-47.219949999999997 15.342700000000001 97.200000000000003 +-49.649999999999999 0 97.200000000000003 +-45.149999999999999 0 96.864000000000004 +-42.940199999999997 13.9521 96.864000000000004 +-26.538499999999999 36.527099999999997 96.864000000000004 +-36.527099999999997 26.538499999999999 96.864000000000004 +-13.9521 42.940199999999997 96.864000000000004 +47.077300000000001 15.29635 97.391999999999996 +40.046349999999997 29.09535 97.391999999999996 +29.09535 40.046349999999997 97.391999999999996 +-15.29635 47.077300000000001 97.391999999999996 +-29.09535 40.046349999999997 97.391999999999996 +-40.046349999999997 29.09535 97.391999999999996 +-47.077300000000001 15.29635 97.391999999999996 +-49.5 0 97.391999999999996 +-45.25 0 97.103999999999999 +-43.035299999999999 13.983000000000001 97.103999999999999 +-26.597300000000001 36.607999999999997 97.103999999999999 +-36.607999999999997 26.597300000000001 97.103999999999999 +-13.983000000000001 43.035299999999999 97.103999999999999 +13.967549999999999 42.987749999999998 96.959999999999994 +0 45.25 97.103999999999999 +45.200000000000003 0 96.959999999999994 +42.987749999999998 -13.967549999999999 96.959999999999994 +42.987749999999998 13.967549999999999 96.959999999999994 +-14.0139 43.130400000000002 97.200000000000003 +0 45.350000000000001 97.200000000000003 +45.25 0 97.103999999999999 +43.035299999999999 -13.983000000000001 97.103999999999999 +45.350000000000001 0 97.200000000000003 +43.130400000000002 -14.0139 97.200000000000003 +43.035299999999999 13.983000000000001 97.103999999999999 +45.549999999999997 0 97.488 +43.320599999999999 -14.075699999999999 97.488 +43.320599999999999 14.075699999999999 97.488 +-14.075699999999999 43.320599999999999 97.488 +36.850700000000003 26.773599999999998 97.488 +14.06025 43.273049999999998 97.391999999999996 +0 45.549999999999997 97.488 +26.744250000000001 36.810250000000003 97.391999999999996 +26.773599999999998 36.850700000000003 97.488 +46.554200000000002 -15.1264 97.920000000000002 +48.950000000000003 0 97.920000000000002 +46.554200000000002 15.1264 97.920000000000002 +39.601399999999998 28.772099999999998 97.920000000000002 +28.772099999999998 39.601399999999998 97.920000000000002 +15.1264 46.554200000000002 97.920000000000002 +0 48.950000000000003 97.920000000000002 +-15.1264 46.554200000000002 97.920000000000002 +-28.772099999999998 39.601399999999998 97.920000000000002 +-43.510849999999998 14.137549999999999 97.680000000000007 +45.75 0 97.680000000000007 +43.510849999999998 -14.137549999999999 97.680000000000007 +-26.891200000000001 37.012549999999997 97.680000000000007 +-37.012549999999997 26.891200000000001 97.680000000000007 +43.510849999999998 14.137549999999999 97.680000000000007 +37.012549999999997 26.891200000000001 97.680000000000007 +-14.137549999999999 43.510849999999998 97.680000000000007 +26.891200000000001 37.012549999999997 97.680000000000007 +14.075699999999999 43.320599999999999 97.488 +0 45.75 97.680000000000007 +14.137549999999999 43.510849999999998 97.680000000000007 +46.459099999999999 -15.095499999999999 98.016000000000005 +48.850000000000001 0 98.016000000000005 +46.459099999999999 15.095499999999999 98.016000000000005 +39.520499999999998 28.7133 98.016000000000005 +28.7133 39.520499999999998 98.016000000000005 +15.095499999999999 46.459099999999999 98.016000000000005 +0 48.850000000000001 98.016000000000005 +-15.095499999999999 46.459099999999999 98.016000000000005 +-28.7133 39.520499999999998 98.016000000000005 +-39.520499999999998 28.7133 98.016000000000005 +-46.459099999999999 15.095499999999999 98.016000000000005 +-48.850000000000001 0 98.016000000000005 +-45.850000000000001 0 97.775999999999996 +-43.60595 14.16845 97.775999999999996 +45.850000000000001 0 97.775999999999996 +43.60595 -14.16845 97.775999999999996 +43.60595 14.16845 97.775999999999996 +-26.949950000000001 37.093449999999997 97.775999999999996 +-37.093449999999997 26.949950000000001 97.775999999999996 +37.093449999999997 26.949950000000001 97.775999999999996 +26.949950000000001 37.093449999999997 97.775999999999996 +-14.16845 43.60595 97.775999999999996 +46.363999999999997 -15.0646 98.063999999999993 +48.75 0 98.063999999999993 +46.363999999999997 15.0646 98.063999999999993 +39.439599999999999 28.65455 98.063999999999993 +28.65455 39.439599999999999 98.063999999999993 +15.0646 46.363999999999997 98.063999999999993 +0 48.75 98.063999999999993 +-15.0646 46.363999999999997 98.063999999999993 +-28.65455 39.439599999999999 98.063999999999993 +-39.439599999999999 28.65455 98.063999999999993 +-46.363999999999997 15.0646 98.063999999999993 +-48.75 0 98.063999999999993 +-45.950000000000003 0 97.872 +45.950000000000003 0 97.872 +43.701050000000002 -14.199350000000001 97.872 +-43.701050000000002 14.199350000000001 97.872 +43.701050000000002 14.199350000000001 97.872 +37.174349999999997 27.008749999999999 97.872 +-37.174349999999997 27.008749999999999 97.872 +27.008749999999999 37.174349999999997 97.872 +14.199350000000001 43.701050000000002 97.872 +-14.199350000000001 43.701050000000002 97.872 +0 45.950000000000003 97.872 +46.268900000000002 -15.0337 98.159999999999997 +48.649999999999999 0 98.159999999999997 +46.268900000000002 15.0337 98.159999999999997 +39.358699999999999 28.595749999999999 98.159999999999997 +28.595749999999999 39.358699999999999 98.159999999999997 +15.0337 46.268900000000002 98.159999999999997 +0 48.649999999999999 98.159999999999997 +-15.0337 46.268900000000002 98.159999999999997 +-28.595749999999999 39.358699999999999 98.159999999999997 +-39.358699999999999 28.595749999999999 98.159999999999997 +-46.268900000000002 15.0337 98.159999999999997 +-48.649999999999999 0 98.159999999999997 +-46.049999999999997 0 97.920000000000002 +43.796149999999997 -14.23025 97.920000000000002 +14.23025 43.796149999999997 97.920000000000002 +0 46.049999999999997 97.920000000000002 +46.126249999999999 -14.987299999999999 98.207999999999998 +48.5 0 98.207999999999998 +28.5076 39.237299999999998 98.207999999999998 +-48.5 0 98.207999999999998 +14.5547 44.794750000000001 98.352000000000004 +0 47.100000000000001 98.352000000000004 +-14.5547 44.794750000000001 98.352000000000004 +-27.684699999999999 38.104700000000001 98.352000000000004 +-38.104700000000001 27.684699999999999 98.352000000000004 +-44.794750000000001 14.5547 98.352000000000004 +-47.100000000000001 0 98.352000000000004 +-50 0 96.239999999999995 +-45 0 95.760000000000005 +42.797550000000001 -13.905749999999999 95.760000000000005 +3 34 35 36 +3 37 38 26 +3 39 40 41 +3 33 30 29 +3 31 42 32 +3 72 73 57 +3 74 40 43 +3 75 76 77 +3 61 69 70 +3 91 100 92 +3 107 18 17 +3 96 103 108 +3 97 80 63 +3 109 99 104 +3 46 40 74 +3 110 111 101 +3 79 112 113 +3 63 56 3 +3 115 109 104 +3 116 114 122 +3 117 123 118 +3 52 89 50 +3 85 93 71 +3 127 123 131 +3 106 105 90 +3 179 2 1 +3 147 184 196 +3 197 25 188 +3 172 189 139 +3 198 13 119 +3 138 8 191 +3 164 199 200 +3 87 205 177 +3 139 189 207 +3 173 10 190 +3 91 82 210 +3 181 201 180 +3 213 214 183 +3 219 217 218 +3 78 54 53 +3 209 146 195 +3 220 221 222 +3 203 223 204 +3 122 130 224 +3 225 3 226 +3 227 228 185 +3 11 229 1006 +3 216 163 157 +3 228 186 185 +3 238 147 239 +3 240 241 163 +3 49 48 86 +3 154 148 242 +3 124 120 253 +3 152 151 145 +3 51 62 153 +3 255 256 214 +3 233 232 257 +3 258 234 236 +3 130 136 237 +3 342 369 376 +3 359 373 360 +3 380 374 194 +3 149 375 368 +3 371 25 12 +3 374 367 175 +3 366 383 357 +3 338 376 356 +3 373 336 337 +3 295 292 302 +3 20 21 384 +3 353 328 329 +3 393 394 395 +3 396 397 398 +3 399 390 392 +3 400 391 21 +3 410 411 206 +3 341 342 208 +3 395 394 412 +3 413 414 415 +3 389 358 382 +3 25 377 42 +3 409 416 405 +3 417 211 418 +3 331 330 399 +3 153 161 429 +3 97 421 81 +3 433 427 432 +3 434 428 424 +3 97 63 430 +3 420 419 63 +3 290 446 294 +3 447 448 298 +3 362 193 363 +3 420 370 384 +3 401 444 334 +3 205 454 449 +3 455 452 71 +3 456 457 458 +3 352 451 435 +3 422 452 1007 +3 381 453 442 +3 205 215 454 +3 425 441 610 +3 594 611 567 +3 598 155 219 +3 612 592 561 +3 162 94 219 +3 620 619 624 +3 626 459 627 +3 628 569 596 +3 608 243 604 +3 630 462 634 +3 574 631 572 +3 633 538 635 +3 171 117 189 +3 633 636 535 +3 314 95 94 +3 638 584 540 +3 463 483 641 +3 654 407 653 +3 585 651 586 +3 272 183 260 +3 650 469 514 +3 660 517 659 +3 530 534 657 +3 318 288 312 +3 637 530 656 +3 276 309 277 +3 555 6 659 +3 182 234 183 +3 301 262 235 +3 522 661 6 +3 521 526 661 +3 530 580 583 +3 315 288 318 +3 267 301 293 +3 559 665 663 +3 556 667 564 +3 588 668 666 +3 327 169 323 +3 652 150 640 +3 7 523 557 +3 578 579 577 +3 587 589 669 +3 150 178 160 +3 590 672 670 +3 333 170 327 +3 664 5 520 +3 590 591 672 +3 160 322 169 +3 626 618 621 +3 675 597 678 +3 527 677 674 +3 597 593 678 +3 617 613 614 +3 170 365 95 +3 681 565 558 +3 606 605 607 +3 680 612 682 +3 477 437 468 +3 637 600 631 +3 607 615 613 +3 682 595 684 +3 468 494 465 +3 676 683 554 +3 609 603 605 +3 647 685 616 +3 525 562 686 +3 689 570 690 +3 630 643 627 +3 476 450 436 +3 690 570 563 +3 692 464 506 +3 688 691 524 +3 83 92 636 +3 470 496 95 +3 573 693 571 +3 646 648 1008 +3 101 642 638 +3 513 95 516 +3 518 489 512 +3 694 695 571 +3 111 121 644 +3 488 489 518 +3 696 576 575 +3 599 654 653 +3 602 673 601 +3 645 129 649 +3 94 16 541 +3 626 622 623 +3 671 658 22 +3 697 10 698 +3 45 582 581 +3 662 673 661 +3 651 133 655 +3 699 165 700 +3 128 547 536 +3 677 687 674 +3 706 705 701 +3 135 128 536 +3 4 119 13 +3 24 60 102 +3 88 64 65 +3 84 76 75 +3 102 68 44 +3 133 132 137 +3 45 58 59 +3 67 66 86 +3 167 709 598 +3 713 40 192 +3 707 303 708 +3 140 166 104 +3 714 249 248 +3 252 167 219 +3 218 157 156 +3 707 244 245 +3 142 23 710 +3 715 716 717 +3 704 265 251 +3 142 141 9 +3 718 250 247 +3 703 702 286 +3 719 230 720 +3 104 98 140 +3 286 702 281 +3 717 725 625 +3 95 27 14 +3 95 347 27 +3 639 144 146 +3 176 169 639 +3 780 779 143 +3 792 723 724 +3 722 790 721 +3 712 737 726 +3 727 740 711 +3 254 372 324 +3 324 372 325 +3 403 168 159 +3 274 271 232 +3 202 212 731 +3 313 304 270 +3 300 299 317 +3 316 321 345 +3 282 287 231 +3 332 320 299 +3 275 282 311 +3 350 736 346 +3 321 350 355 +3 321 326 736 +3 332 299 308 +3 259 261 202 +3 261 266 158 +3 794 372 795 +3 372 796 795 +3 797 383 798 +3 403 408 551 +3 800 403 551 +3 801 403 799 +3 803 403 802 +3 632 403 804 +3 398 397 806 +3 397 736 805 +3 348 378 349 +3 460 379 361 +3 351 353 329 +3 335 381 362 +3 392 382 443 +3 498 741 515 +3 478 497 499 +3 508 473 495 +3 537 475 474 +3 532 329 471 +3 744 507 509 +3 743 744 742 +3 474 743 531 +3 741 503 515 +3 486 339 493 +3 486 543 745 +3 479 484 485 +3 729 480 479 +3 728 487 492 +3 757 756 767 +3 732 748 749 +3 746 553 752 +3 761 758 751 +3 764 763 770 +3 765 766 756 +3 772 773 762 +3 759 760 750 +3 776 472 774 +3 768 776 777 +3 771 772 762 +3 769 775 733 +3 753 754 747 +3 754 755 552 +3 782 733 785 +3 790 789 736 +3 788 791 733 +3 549 781 787 +3 548 550 736 +3 780 739 738 +3 785 786 781 +3 784 783 793 +3 731 737 545 +3 731 732 735 +3 544 546 732 +3 778 734 779 +3 819 817 807 +3 821 820 629 +3 822 679 823 +3 22 826 824 +3 825 828 52 +3 15 28 827 +3 192 830 831 +3 174 808 829 +3 329 193 832 +3 833 818 809 +3 834 811 835 +3 836 810 837 +3 812 839 838 +3 813 814 839 +3 840 815 841 +3 842 816 817 +3 844 843 819 +3 847 845 846 +3 863 849 864 +3 849 865 864 +3 848 850 866 +3 850 867 866 +3 851 852 868 +3 868 852 869 +3 870 853 871 +3 854 855 871 +3 872 856 873 +3 858 874 857 +3 877 875 859 +3 861 876 860 +3 862 878 861 +3 879 55 47 +3 881 61 880 +3 882 883 103 +3 884 125 883 +3 885 886 126 +3 126 886 134 +3 888 187 887 +3 890 185 888 +3 185 187 888 +3 891 246 889 +3 19 892 0 +3 898 897 893 +3 899 895 900 +3 901 900 902 +3 903 896 894 +3 429 438 914 +3 445 916 915 +3 919 461 920 +3 466 467 533 +3 921 466 533 +3 922 542 519 +3 904 905 923 +3 528 925 529 +3 928 908 906 +3 910 929 907 +3 931 909 911 +3 932 929 910 +3 930 933 912 +3 914 934 913 +3 917 918 938 +3 944 539 945 +3 926 947 922 +3 947 946 922 +3 948 924 949 +3 950 953 927 +3 954 930 928 +3 955 951 929 +3 935 956 934 +3 936 958 957 +3 937 959 958 +3 939 961 960 +3 940 941 962 +3 962 941 963 +3 942 943 965 +3 964 942 965 +3 952 971 947 +3 971 968 947 +3 966 967 989 +3 989 967 990 +3 971 991 968 +3 969 970 280 +3 974 291 971 +3 291 991 971 +3 285 973 972 +3 993 976 975 +3 305 307 977 +3 994 305 978 +3 980 995 979 +3 981 982 385 +3 983 984 997 +3 984 985 404 +3 986 987 423 +3 987 988 431 +3 291 294 991 +3 280 992 491 +3 278 284 279 +3 296 502 297 +3 310 290 289 +3 501 994 993 +3 511 306 305 +3 439 998 440 +3 440 998 560 +3 566 568 996 +3 385 387 566 +3 386 997 388 +3 997 404 406 +3 426 427 433 +3 491 482 481 +3 490 278 491 +3 263 264 999 +3 283 269 1001 +3 269 268 1003 +3 319 273 1004 +3 1004 1005 340 +3 1003 1004 344 +3 1002 343 1001 +3 1001 354 1000 +3 1000 364 999 +3 510 374 504 +3 505 402 730 +3 730 395 500 + diff --git a/Constrained_triangulation_3/test/Constrained_triangulation_3/data/bug2.off b/Constrained_triangulation_3/test/Constrained_triangulation_3/data/bug2.off new file mode 100644 index 000000000000..6ac41106dd82 --- /dev/null +++ b/Constrained_triangulation_3/test/Constrained_triangulation_3/data/bug2.off @@ -0,0 +1,19 @@ +OFF +13 2 0 + +-5.9999900000000004 10.012 3.9999899999999999 +-6 10 10 +-6.0072099999999997 4.00481 4.00481 +6.0072099999999997 4.00481 4.00481 +-6.0072099999999997 2.0024000000000002 4.0064099999999998 +-6.0048000000000004 6.0048000000000004 6.0048000000000004 +6.0072099999999997 2.0024000000000002 4.0064099999999998 +-6.0047899999999998 6.0192399999999999 4.00319 +-6.0048000000000004 6.0060099999999998 5.0006000000000004 +-6.0110000000000001 0.85517500000000002 4.0073299999999996 +6.0109899999999996 0.86136599999999997 4.0073299999999996 +-6.00481 5.9986300000000004 10.007999999999999 +-6.0047899999999998 6.0192399999999999 5.0160400000000003 +9 9 2 5 8 12 7 0 1 11 +6 9 10 3 6 4 2 + diff --git a/Constrained_triangulation_3/test/Constrained_triangulation_3/data/bug3-fixed.off b/Constrained_triangulation_3/test/Constrained_triangulation_3/data/bug3-fixed.off new file mode 100644 index 000000000000..cd8ee5797e79 --- /dev/null +++ b/Constrained_triangulation_3/test/Constrained_triangulation_3/data/bug3-fixed.off @@ -0,0 +1,16 @@ +OFF +8 4 0 + +0.41289999999999999 0.15625 -0.067400000000000002 +0.44080000000000003 0.14374999999999999 -0.065199999999999994 +0.40029999999999999 0.17394999999999999 -0.070499999999999993 +0.42680000000000001 0.16245000000000001 -0.068500000000000005 +0.40970000000000001 0.18395 -0.072300000000000003 +0.43359999999999999 0.17535000000000001 -0.070800000000000002 +0.43759999999999999 0.19075 -0.073499999999999996 +0.46029999999999999 0.18435000000000001 -0.072400000000000006 +3 0 3 1 +3 2 4 3 +3 3 4 5 +3 5 6 7 + diff --git a/Constrained_triangulation_3/test/Constrained_triangulation_3/data/bug4-fixed.off b/Constrained_triangulation_3/test/Constrained_triangulation_3/data/bug4-fixed.off new file mode 100644 index 000000000000..44dbc9146ab1 --- /dev/null +++ b/Constrained_triangulation_3/test/Constrained_triangulation_3/data/bug4-fixed.off @@ -0,0 +1,27 @@ +OFF +16 7 0 + +185.80154797792815 6.314845734395881 -138.37941828626168 +185.87791334370158 3.8848603944873195 -138.37275344014969 +185.8220846343909 -5.6613587297849071 -136.31085013313518 +185.8410656525223 5.0573729395164362 -138.67501807936665 +185.80721796422316 6.1344238450376913 -137.33082227481412 +185.83031684350982 5.3994055881827281 -137.3485146794398 +185.8187674038665 5.7669147166102093 -137.33966847712696 +185.83252986996206 -5.3289859446530263 -137.33266393727405 +185.84186628315314 5.0318964597552469 -137.35736088175264 +185.83609156333148 5.2156510239689879 -137.35293778059622 +185.86496516243977 4.2968782029002828 -137.37505328637826 +185.80160282426402 6.3131004956894499 -137.32714866699001 +185.81299268404484 5.9506692808239503 -137.33524537597054 +185.82558201217887 -5.5500703640873645 -137.33569278130571 +185.82454212368816 5.5831601523964682 -137.34409157828338 +185.85919044261811 4.4806327671140238 -137.37063018522184 +3 0 11 4 +3 0 12 6 +3 2 13 7 +3 14 5 3 +3 3 9 8 +3 10 1 3 +3 3 15 10 + diff --git a/Constrained_triangulation_3/test/Constrained_triangulation_3/data/bug5.off b/Constrained_triangulation_3/test/Constrained_triangulation_3/data/bug5.off new file mode 100644 index 000000000000..99c3132caa91 --- /dev/null +++ b/Constrained_triangulation_3/test/Constrained_triangulation_3/data/bug5.off @@ -0,0 +1,36 @@ +OFF +23 9 0 + +0.22012599999999999 3.9465400000000001e-10 -0.17452799999999999 +0.22254199999999999 -0.024537199999999999 -0.17452799999999999 +0.22969899999999999 -0.048132000000000001 -0.17452799999999999 +0.24132200000000001 -0.069877800000000004 -0.17452799999999999 +0.22012599999999999 1.99686e-10 0.18239 +0.256913 -0.088889099999999999 0.18239 +0.22253899999999999 -0.0245212 0.18239 +0.24129200000000001 -0.069834099999999996 0.18239 +-0.145422 -0.019568700000000001 0.053459100000000002 +-0.14779900000000001 2.56918e-09 0.053459100000000002 +-0.12723300000000001 -0.054221900000000003 0.053459100000000002 +-0.138432 -0.0379998 0.053459100000000002 +-0.075883199999999998 -0.081165600000000004 0.053459100000000002 +0.013348 -0.019563000000000001 0.053459100000000002 +0.0063605900000000002 -0.037990299999999998 0.053459100000000002 +-0.14779900000000001 -2.56918e-09 0.0188679 +0.0133469 -0.019568700000000001 0.0188679 +-0.075903100000000001 -0.081163100000000002 0.0188679 +-0.056192300000000001 -0.081165600000000004 0.0188679 +-0.11249099999999999 -0.067281900000000006 0.0188679 +-0.138436 -0.037990299999999998 0.0188679 +-0.12724199999999999 -0.054210800000000003 0.0188679 +-0.145423 -0.019563000000000001 0.0188679 +3 1 0 4 +3 6 2 1 +3 1 4 6 +3 3 7 5 +3 14 13 16 +3 17 12 18 +3 11 20 8 +3 10 19 21 +3 9 22 15 + diff --git a/Constrained_triangulation_3/test/Constrained_triangulation_3/data/bug6.off b/Constrained_triangulation_3/test/Constrained_triangulation_3/data/bug6.off new file mode 100644 index 000000000000..063553f0abd8 --- /dev/null +++ b/Constrained_triangulation_3/test/Constrained_triangulation_3/data/bug6.off @@ -0,0 +1,23 @@ +OFF +13 6 0 + +185.18898585648856 16.966320499379513 -137.07794146876512 +185.19196127302405 16.93088720888337 -136.82186521302503 +185.22200238828486 16.573137108628089 -136.8292854104584 +185.17694071539364 17.10976225901101 -136.81815511430835 +185.20398064811857 16.787752288367066 -137.08161172697817 +183.96211344530562 17.334502712732217 -136.81110800926174 +185.20698183065446 16.752012158755729 -136.82557531174172 +184.18920469320116 17.027738501495833 -137.07471295649836 +184.29442238224937 15.888341147385638 -136.8415239085119 +180.73913860706105 -13.467536383885621 -34.379750337388344 +179.86184934883133 -13.125415608330357 -34.375676328932819 +181.67230056427172 -13.021006010825106 -34.373019686879069 +180.74802078058448 -12.064023272631362 -34.360583543228728 +3 1 5 3 +3 0 7 4 +3 2 5 6 +3 5 2 8 +3 9 11 12 +3 12 10 9 + diff --git a/Constrained_triangulation_3/test/Constrained_triangulation_3/data/bug7.off b/Constrained_triangulation_3/test/Constrained_triangulation_3/data/bug7.off new file mode 100644 index 000000000000..1d4745468eea --- /dev/null +++ b/Constrained_triangulation_3/test/Constrained_triangulation_3/data/bug7.off @@ -0,0 +1,560 @@ +OFF +381 175 0 + +0.050000000699999998 0.050000000699999998 0.050000000699999998 +0.050000000699999998 0.043749999300000002 -0.037500001499999998 +0.050000000699999998 0.043742001099999997 0.037810999900000003 +0.050000000699999998 0.043620001499999998 0.036230001599999999 +0.050000000699999998 0.043536998299999997 -0.035881999900000003 +0.050000000699999998 0.043462999199999998 0.039372000800000001 +0.050000000699999998 0.042913000999999999 -0.034375000699999998 +0.050000000699999998 0.042913000999999999 -0.040624998500000002 +0.050000000699999998 0.042800001800000001 0.040812999000000003 +0.050000000699999998 0.042121999 0.016706999399999999 +0.050000000699999998 0.041919000400000003 -0.033080998799999997 +0.050000000699999998 0.041919000400000003 -0.041919000400000003 +0.050000000699999998 0.041795000399999997 0.042040001600000002 +0.050000000699999998 0.041042998400000003 0.032350998399999997 +0.050000000699999998 0.040957000100000002 0.017706999599999999 +0.050000000699999998 0.040624998500000002 -0.032086998200000001 +0.050000000699999998 0.040624998500000002 -0.042913000999999999 +0.050000000699999998 0.040513999799999999 0.042975000999999999 +0.050000000699999998 0.039632998400000001 0.0316249989 +0.050000000699999998 0.039585001799999998 0.018392000299999999 +0.050000000699999998 0.039117999399999999 -0.031463000900000003 +0.050000000699999998 0.039117999399999999 -0.043536998299999997 +0.050000000699999998 0.039039000900000002 0.043558001499999999 +0.050000000699999998 0.037833999799999997 -0.027458000900000001 +0.050000000699999998 0.037500001499999998 -0.03125 +0.050000000699999998 0.0370969996 -0.0292380005 +0.050000000699999998 0.035923998800000002 -0.0307669993 +0.050000000699999998 0.032614000099999998 -0.0326780006 +0.050000000699999998 0.032086998200000001 -0.034375000699999998 +0.050000000699999998 0.032086998200000001 -0.040624998500000002 +0.050000000699999998 0.031463000900000003 -0.035881999900000003 +0.050000000699999998 0.031463000900000003 -0.039117999399999999 +0.050000000699999998 0.03125 -0.037500001499999998 +0.050000000699999998 0.0307030007 -0.032930001600000001 +0.050000000699999998 0.018717000300000002 -0.036857999900000001 +0.050000000699999998 0.018691999800000001 -0.0383489989 +0.050000000699999998 0.0183879994 -0.035404000400000003 +0.050000000699999998 0.018315000500000001 -0.039790999100000002 +0.050000000699999998 0.017723999899999999 -0.034069001699999997 +0.050000000699999998 0.017606999700000001 -0.041103001700000003 +0.050000000699999998 0.016762999800000001 -0.032930001600000001 +0.050000000699999998 0.0125000002 -0.043749999300000002 +0.050000000699999998 0.0110200001 -0.043572001200000002 +0.050000000699999998 0.0096239997000000001 -0.0430490002 +0.050000000699999998 0.0084309997000000005 -0.0077559999000000003 +0.050000000699999998 0.0083919996 -0.042210001499999997 +0.050000000699999998 0.0082879997999999993 0.0078819999000000005 +0.050000000699999998 0.0073930002000000003 -0.041103001700000003 +0.050000000699999998 0.0067460000999999999 0.0149400001 +0.050000000699999998 0.0066849999000000004 -0.039790999100000002 +0.050000000699999998 0.0066120001000000003 -0.035404000400000003 +0.050000000699999998 0.0063240001999999998 0.0134619996 +0.050000000699999998 0.0063080000999999998 -0.0383489989 +0.050000000699999998 0.0062830001 -0.036857999900000001 +0.050000000699999998 0.0062759998000000003 0.011926000000000001 +0.050000000699999998 -0.0062500000999999999 0.0125000002 +0.050000000699999998 -0.0062830001 -0.036857999900000001 +0.050000000699999998 -0.0063080000999999998 -0.0383489989 +0.050000000699999998 -0.0064630000999999996 0.014117999900000001 +0.050000000699999998 -0.0064630000999999996 0.010882000399999999 +0.050000000699999998 -0.0066120001000000003 -0.035404000400000003 +0.050000000699999998 -0.0066849999000000004 -0.039790999100000002 +0.050000000699999998 -0.0070870001999999996 0.015625 +0.050000000699999998 -0.0072760000000000003 -0.034069001699999997 +0.050000000699999998 -0.0073930002000000003 -0.041103001700000003 +0.050000000699999998 -0.0080810003000000002 0.0080810003000000002 +0.050000000699999998 -0.0083320001000000005 -0.0078419995999999999 +0.050000000699999998 -0.0083919996 -0.042210001499999997 +0.050000000699999998 -0.0093750003999999998 0.0070870001999999996 +0.050000000699999998 -0.0096239997000000001 -0.0430490002 +0.050000000699999998 -0.010882000399999999 0.031463000900000003 +0.050000000699999998 -0.0110200001 -0.043572001200000002 +0.050000000699999998 -0.0125000002 0.03125 +0.050000000699999998 -0.0125000002 0.018750000700000002 +0.050000000699999998 -0.0125000002 -0.043749999300000002 +0.050000000699999998 -0.015625 0.042913000999999999 +0.050000000699999998 -0.016919000100000001 0.041919000400000003 +0.050000000699999998 -0.0183879994 -0.035404000400000003 +0.050000000699999998 -0.018750000700000002 0.0125000002 +0.050000000699999998 -0.019723000000000001 -0.0326780006 +0.050000000699999998 -0.0215039998 -0.031941000400000003 +0.050000000699999998 -0.023033000500000001 -0.0307669993 +0.050000000699999998 -0.024205999400000001 -0.0292380005 +0.050000000699999998 -0.03125 0.0125000002 +0.050000000699999998 -0.031463000900000003 0.014117999900000001 +0.050000000699999998 -0.031463000900000003 -0.035881999900000003 +0.050000000699999998 -0.032086998200000001 0.040624998500000002 +0.050000000699999998 -0.032086998200000001 -0.034375000699999998 +0.050000000699999998 -0.033080998799999997 0.041919000400000003 +0.050000000699999998 -0.033080998799999997 0.033080998799999997 +0.050000000699999998 -0.033080998799999997 0.016919000100000001 +0.050000000699999998 -0.034375000699999998 0.042913000999999999 +0.050000000699999998 -0.034375000699999998 0.032086998200000001 +0.043719999500000002 0.043719999500000002 -0.036887001199999998 +0.043630000199999998 0.043630000199999998 -0.036281000799999998 +0.043630000199999998 0.038718998400000003 -0.043630000199999998 +0.043274000299999997 0.043274000299999997 -0.035108 +0.043274000299999997 0.0398919992 -0.031725998999999998 +0.043274000299999997 0.0398919992 -0.043274000299999997 +0.042697001200000001 0.042697001200000001 -0.034028001099999997 +0.042697001200000001 0.042697001200000001 -0.040972001899999999 +0.042697001200000001 0.040972001899999999 -0.0323030017 +0.042697001200000001 0.040972001899999999 -0.042697001200000001 +0.041919000400000003 0.041919000400000003 -0.033080998799999997 +0.041919000400000003 0.041919000400000003 -0.041919000400000003 +0.033080998799999997 0.041919000400000003 -0.041919000400000003 +0.033080998799999997 0.033080998799999997 -0.033080998799999997 +0.0323030017 0.042697001200000001 -0.040972001899999999 +0.0323030017 0.034028001099999997 -0.0323030017 +0.0323030017 0.0323030017 -0.034028001099999997 +0.031725998999999998 0.043274000299999997 -0.0398919992 +0.031725998999999998 0.0398919992 -0.031725998999999998 +0.031725998999999998 0.035108 -0.031725998999999998 +0.031369999099999997 0.043630000199999998 -0.038718998400000003 +0.031369999099999997 0.038718998400000003 -0.031369999099999997 +0.031369999099999997 0.036281000799999998 -0.031369999099999997 +0.0312799998 0.038113001700000003 -0.0312799998 +0.0312799998 0.036887001199999998 -0.0312799998 +-0.0323030017 0.017697000899999999 -0.034028001099999997 +0.03125 0.037500001499999998 -0.03125 +0.018750000700000002 0.037500001499999998 -0.03125 +0.018750000700000002 0.03125 -0.037500001499999998 +0.018750000700000002 0.018750000700000002 -0.037500001499999998 +0.018747 0.037686999899999997 -0.0279399995 +0.018742000700000001 0.037188000999999998 -0.029075000399999999 +0.018733000400000002 0.0129620004 -0.00039100000000000002 +0.0187309999 0.037987999600000003 -0.026743000400000001 +0.018721999600000001 0.038086000799999999 -0.018721999600000001 +0.018721999600000001 0.038086000799999999 -0.025546999599999998 +0.018719999099999999 0.038113001700000003 -0.0312799998 +0.018719999099999999 0.036887001199999998 -0.0312799998 +0.018719999099999999 0.0312799998 -0.036887001199999998 +0.018719999099999999 0.0312799998 -0.038113001700000003 +0.018719999099999999 0.018719999099999999 -0.036887001199999998 +0.018719999099999999 0.018719999099999999 -0.038113001700000003 +0.018719999099999999 0.0131130004 -0.0062799999000000004 +0.0186730009 0.036520998899999997 -0.030092999299999999 +0.018629999800000002 0.038718998400000003 -0.031369999099999997 +0.018629999800000002 0.036281000799999998 -0.031369999099999997 +0.018629999800000002 0.031369999099999997 -0.036281000799999998 +0.018629999800000002 0.031369999099999997 -0.038718998400000003 +0.018629999800000002 0.018629999800000002 -0.036281000799999998 +0.018629999800000002 0.018629999800000002 -0.038718998400000003 +0.018629999800000002 0.013718999900000001 -0.0063700001000000003 +0.018528999800000001 0.039147999099999997 -0.018528999800000001 +0.018492000200000001 0.0357219987 -0.030960999400000001 +0.0184390005 0.0144459996 -0.00039100000000000002 +0.018273999900000001 0.043274000299999997 -0.0398919992 +0.018273999900000001 0.0398919992 -0.031725998999999998 +0.018273999900000001 0.035108 -0.031725998999999998 +0.018273999900000001 0.031725998999999998 -0.035108 +0.018273999900000001 0.031725998999999998 -0.0398919992 +0.018273999900000001 0.018273999900000001 -0.035108 +0.018273999900000001 0.018273999900000001 -0.0398919992 +0.018273999900000001 0.0148919998 -0.0067260000000000002 +0.018155999499999999 0.040160000299999998 -0.018155999499999999 +0.018123999200000001 0.034775000100000002 -0.031706001599999999 +0.0177979991 0.015815999399999999 -0.00039100000000000002 +0.017697000899999999 0.042697001200000001 -0.040972001899999999 +0.017697000899999999 0.040972001899999999 -0.0323030017 +0.017697000899999999 0.034028001099999997 -0.0323030017 +0.017697000899999999 0.0323030017 -0.034028001099999997 +0.017697000899999999 0.0323030017 -0.040972001899999999 +0.017697000899999999 0.017697000899999999 -0.034028001099999997 +0.017697000899999999 0.017697000899999999 -0.040972001899999999 +0.017697000899999999 0.015971999600000002 -0.0073029999999999996 +0.017613999500000001 0.041092999300000002 -0.017613999500000001 +0.017563000299999999 0.033835999700000001 -0.032232001400000002 +0.016919000100000001 0.041919000400000003 -0.016919000100000001 +0.016919000100000001 0.041919000400000003 -0.033080998799999997 +0.016919000100000001 0.041919000400000003 -0.041919000400000003 +0.016919000100000001 0.033080998799999997 -0.033080998799999997 +0.016919000100000001 0.033080998799999997 -0.041919000400000003 +0.016919000100000001 0.016919000100000001 -0.033080998799999997 +0.016919000100000001 0.016919000100000001 -0.041919000400000003 +0.016797000499999999 0.032960999800000002 -0.0170389991 +0.016797000499999999 0.032960999800000002 -0.032575998500000002 +0.016797000499999999 0.0170389991 -0.00039100000000000002 +0.016797000499999999 0.0170389991 -0.0079610002999999999 +-0.031463000900000003 0.050000000699999998 -0.014117999900000001 +0.015971999600000002 0.042697001200000001 -0.017697000899999999 +0.015971999600000002 0.042697001200000001 -0.0323030017 +0.015971999600000002 0.0323030017 -0.0323030017 +0.015971999600000002 0.0323030017 -0.042697001200000001 +0.015971999600000002 0.017697000899999999 -0.0323030017 +0.015971999600000002 0.017697000899999999 -0.042697001200000001 +0.015846999399999999 0.032221999000000001 -0.017777999900000001 +0.015846999399999999 0.017777999900000001 -0.0072220000000000001 +0.0155229997 0.0179699995 -0.00039100000000000002 +0.0148919998 0.043274000299999997 -0.018273999900000001 +0.0148919998 0.043274000299999997 -0.031725998999999998 +0.0148919998 0.031725998999999998 -0.031725998999999998 +0.0148919998 0.031725998999999998 -0.043274000299999997 +0.0148919998 0.018273999900000001 -0.031725998999999998 +0.0148919998 0.018273999900000001 -0.043274000299999997 +0.014773 0.018322000299999999 -0.0066780001000000004 +0.014055999899999999 0.018552999899999999 -0.00039100000000000002 +0.013718999900000001 0.043630000199999998 -0.018629999800000002 +0.013718999900000001 0.043630000199999998 -0.031369999099999997 +0.013718999900000001 0.031369999099999997 -0.031369999099999997 +0.013718999900000001 0.031369999099999997 -0.043630000199999998 +0.013718999900000001 0.018629999800000002 -0.031369999099999997 +0.013718999900000001 0.018629999800000002 -0.043630000199999998 +0.0136139998 0.018650000900000002 -0.0063499999000000001 +0.0131130004 0.043719999500000002 -0.018719999099999999 +0.0131130004 0.043719999500000002 -0.0312799998 +0.0131130004 0.0312799998 -0.0312799998 +0.0131130004 0.0312799998 -0.043719999500000002 +0.0131130004 0.018719999099999999 -0.0312799998 +0.0131130004 0.018719999099999999 -0.043719999500000002 +-0.043274000299999997 0.0398919992 -0.043274000299999997 +0.0130169997 0.018728999400000002 -0.0062709999999999997 +0.0125000002 0.050000000699999998 -0.043749999300000002 +0.0125000002 0.043749999300000002 -0.018750000700000002 +0.0125000002 0.043749999300000002 -0.03125 +0.0125000002 0.03125 -0.03125 +0.0125000002 0.03125 -0.043749999300000002 +0.0125000002 0.018750000700000002 -0.03125 +0.0125000002 0.018750000700000002 -0.043749999300000002 +0.012489999599999999 0.018750000700000002 -0.00039100000000000002 +0.0118869999 0.043719999500000002 -0.018719999099999999 +0.0118869999 0.043719999500000002 -0.0312799998 +0.0118869999 0.0312799998 -0.0312799998 +0.0118869999 0.0312799998 -0.043719999500000002 +0.0118869999 0.018719999099999999 -0.0312799998 +0.0118869999 0.018719999099999999 -0.043719999500000002 +0.011281000500000001 0.043630000199999998 -0.018629999800000002 +0.011281000500000001 0.043630000199999998 -0.031369999099999997 +-0.050000000699999998 0.014117999900000001 -0.043536998299999997 +-0.050000000699999998 0.015625 -0.042913000999999999 +0.010882000399999999 0.050000000699999998 -0.043536998299999997 +0.0101079997 0.043274000299999997 -0.018273999900000001 +0.0101079997 0.043274000299999997 -0.031725998999999998 +-0.050000000699999998 0.03125 -0.037500001499999998 +-0.050000000699999998 0.031463000900000003 -0.039117999399999999 +-0.050000000699999998 0.031463000900000003 -0.035881999900000003 +0.0090279998000000004 0.042697001200000001 -0.017697000899999999 +0.0090279998000000004 0.042697001200000001 -0.0323030017 +-0.050000000699999998 0.032086998200000001 -0.040624998500000002 +-0.050000000699999998 0.032086998200000001 -0.034375000699999998 +-0.050000000699999998 0.033080998799999997 -0.041919000400000003 +0.0080810003000000002 0.041919000400000003 -0.016919000100000001 +0.0080810003000000002 0.041919000400000003 -0.033080998799999997 +-0.050000000699999998 0.035881999900000003 -0.043536998299999997 +-0.050000000699999998 0.035881999900000003 -0.031463000900000003 +-0.050000000699999998 0.037500001499999998 -0.043749999300000002 +-0.050000000699999998 0.037500001499999998 -0.03125 +0.0073029999999999996 0.040972001899999999 -0.017697000899999999 +0.0073029999999999996 0.040972001899999999 -0.0323030017 +-0.038228999800000003 0.028161000499999998 0.031293001000000001 +-0.050000000699999998 0.039117999399999999 -0.043536998299999997 +-0.050000000699999998 0.040624998500000002 -0.042913000999999999 +0.0070870001999999996 0.050000000699999998 -0.0093750003999999998 +0.0067260000000000002 0.0398919992 -0.018273999900000001 +0.0067260000000000002 0.0398919992 -0.031725998999999998 +-0.050000000699999998 0.041919000400000003 -0.041919000400000003 +-0.050000000699999998 0.043536998299999997 -0.035881999900000003 +-0.042697001200000001 0.0323030017 -0.040972001899999999 +-0.042697001200000001 0.034028001099999997 -0.042697001200000001 +0.0064630000999999996 0.050000000699999998 -0.010882000399999999 +-0.042697001200000001 0.040972001899999999 -0.042697001200000001 +0.0063700001000000003 0.038718998400000003 -0.018629999800000002 +0.0063700001000000003 0.038718998400000003 -0.031369999099999997 +-0.050000000699999998 0.043749999300000002 -0.037500001499999998 +-0.050000000699999998 0.050000000699999998 -0.050000000699999998 +-0.050000000699999998 0.050000000699999998 0.050000000699999998 +0.0062799999000000004 0.038113001700000003 -0.018719999099999999 +0.0062799999000000004 0.038113001700000003 -0.0312799998 +0.0062799999000000004 0.036887001199999998 -0.018719999099999999 +0.0062799999000000004 0.036887001199999998 -0.0312799998 +0.0062500000999999999 0.050000000699999998 -0.0125000002 +0.0062500000999999999 0.037500001499999998 -0.018750000700000002 +0.0062500000999999999 0.037500001499999998 -0.03125 +0.0024999999 0.050000000699999998 0.050000000699999998 +0.0024999999 0.050000000699999998 0.037500001499999998 +-0.041919000400000003 0.033080998799999997 -0.041919000400000003 +-0.041919000400000003 0.041919000400000003 -0.041919000400000003 +-0.0062500000999999999 0.050000000699999998 0.037500001499999998 +-0.0062799999000000004 0.038113001700000003 -0.018719999099999999 +-0.037500001499999998 0.03125 0.03125 +-0.043749999300000002 0.037500001499999998 -0.043749999300000002 +-0.037500001499999998 0.050000000699999998 -0.0062500000999999999 +-0.037500001499999998 0.050000000699999998 0.0062500000999999999 +-0.0063700001000000003 0.038718998400000003 -0.018629999800000002 +-0.0063700001000000003 0.038718998400000003 -0.031369999099999997 +-0.037500001499999998 0.050000000699999998 0.043749999300000002 +-0.037059001600000002 0.027484999999999999 0.031266000100000003 +-0.043749999300000002 0.050000000699999998 -0.0125000002 +-0.0064630000999999996 0.050000000699999998 0.039117999399999999 +-0.0064630000999999996 0.050000000699999998 -0.010882000399999999 +-0.0067260000000000002 0.0398919992 -0.018273999900000001 +-0.0067260000000000002 0.0398919992 -0.031725998999999998 +-0.036887001199999998 0.0312799998 0.0312799998 +-0.040624998500000002 0.050000000699999998 0.0070870001999999996 +-0.040624998500000002 0.050000000699999998 0.042913000999999999 +-0.0070870001999999996 0.050000000699999998 0.040624998500000002 +-0.0070870001999999996 0.050000000699999998 -0.0093750003999999998 +-0.0073029999999999996 0.040972001899999999 -0.017697000899999999 +-0.0073029999999999996 0.040972001899999999 -0.0323030017 +-0.043719999500000002 0.0312799998 -0.038113001700000003 +-0.043719999500000002 0.0312799998 -0.036887001199999998 +-0.043719999500000002 0.036887001199999998 -0.043719999500000002 +-0.043719999500000002 0.036887001199999998 -0.0312799998 +-0.043719999500000002 0.038113001700000003 -0.043719999500000002 +-0.0080810003000000002 0.050000000699999998 0.041919000400000003 +-0.0080810003000000002 0.041919000400000003 -0.016919000100000001 +-0.0080810003000000002 0.041919000400000003 -0.033080998799999997 +-0.043719999500000002 0.043719999500000002 -0.036887001199999998 +-0.036281000799999998 0.031369999099999997 0.031369999099999997 +-0.0093750003999999998 0.050000000699999998 0.042913000999999999 +-0.035904001400000003 0.026818999999999999 0.031456999499999999 +-0.010882000399999999 0.050000000699999998 0.043536998299999997 +-0.010882000399999999 0.050000000699999998 -0.043536998299999997 +-0.039117999399999999 0.050000000699999998 -0.0064630000999999996 +-0.039117999399999999 0.050000000699999998 0.0064630000999999996 +-0.035881999900000003 0.050000000699999998 0.043536998299999997 +-0.039117999399999999 0.050000000699999998 0.043536998299999997 +-0.0125000002 0.050000000699999998 0.043749999300000002 +-0.0125000002 0.050000000699999998 -0.043749999300000002 +-0.0125000002 0.03125 -0.018750000700000002 +-0.0125000002 0.03125 -0.03125 +-0.043630000199999998 0.031369999099999997 -0.038718998400000003 +-0.043630000199999998 0.031369999099999997 -0.036281000799999998 +-0.043630000199999998 0.036281000799999998 -0.043630000199999998 +-0.0131130004 0.0312799998 -0.018719999099999999 +-0.0131130004 0.0312799998 -0.0312799998 +-0.043630000199999998 0.038718998400000003 -0.043630000199999998 +-0.013718999900000001 0.031369999099999997 -0.018629999800000002 +-0.013718999900000001 0.031369999099999997 -0.031369999099999997 +-0.014117999900000001 0.050000000699999998 0.043536998299999997 +-0.0148919998 0.031725998999999998 -0.018273999900000001 +-0.0148919998 0.031725998999999998 -0.031725998999999998 +-0.015971999600000002 0.0323030017 -0.017697000899999999 +-0.015971999600000002 0.0323030017 -0.0323030017 +-0.043536998299999997 0.050000000699999998 -0.035881999900000003 +-0.043536998299999997 0.050000000699999998 -0.014117999900000001 +-0.016919000100000001 0.033080998799999997 -0.016919000100000001 +-0.016919000100000001 0.033080998799999997 -0.033080998799999997 +-0.016919000100000001 0.016919000100000001 -0.016919000100000001 +-0.016919000100000001 0.016919000100000001 -0.033080998799999997 +-0.017697000899999999 0.034028001099999997 -0.017697000899999999 +-0.017697000899999999 0.034028001099999997 -0.0323030017 +-0.017697000899999999 0.0323030017 -0.034028001099999997 +-0.017697000899999999 0.017697000899999999 -0.034028001099999997 +-0.017697000899999999 0.015971999600000002 -0.017697000899999999 +-0.017697000899999999 0.015971999600000002 -0.0323030017 +-0.018273999900000001 0.0398919992 -0.031725998999999998 +-0.018273999900000001 0.035108 -0.018273999900000001 +-0.018273999900000001 0.035108 -0.031725998999999998 +-0.018273999900000001 0.031725998999999998 -0.035108 +-0.018273999900000001 0.018273999900000001 -0.035108 +-0.018273999900000001 0.0148919998 -0.018273999900000001 +-0.018273999900000001 0.0148919998 -0.031725998999999998 +-0.018629999800000002 0.038718998400000003 -0.018629999800000002 +-0.018629999800000002 0.038718998400000003 -0.031369999099999997 +-0.018629999800000002 0.036281000799999998 -0.018629999800000002 +-0.018629999800000002 0.036281000799999998 -0.031369999099999997 +-0.018629999800000002 0.031369999099999997 -0.036281000799999998 +-0.018629999800000002 0.018629999800000002 -0.036281000799999998 +-0.018629999800000002 0.013718999900000001 -0.018629999800000002 +-0.018629999800000002 0.013718999900000001 -0.031369999099999997 +-0.018719999099999999 0.038113001700000003 -0.018719999099999999 +-0.018719999099999999 0.038113001700000003 -0.0312799998 +-0.018719999099999999 0.036887001199999998 -0.018719999099999999 +-0.018719999099999999 0.036887001199999998 -0.0312799998 +-0.018719999099999999 0.0312799998 -0.036887001199999998 +-0.018719999099999999 0.018719999099999999 -0.036887001199999998 +-0.018719999099999999 0.0131130004 -0.018719999099999999 +-0.018719999099999999 0.0131130004 -0.0312799998 +-0.018719999099999999 0.0118869999 -0.018719999099999999 +-0.043274000299999997 0.0148919998 -0.043274000299999997 +-0.018750000700000002 0.050000000699999998 -0.0125000002 +-0.018750000700000002 0.037500001499999998 -0.018750000700000002 +-0.018750000700000002 0.03125 -0.037500001499999998 +-0.018750000700000002 0.018750000700000002 -0.037500001499999998 +-0.018750000700000002 0.0125000002 -0.018750000700000002 +-0.018750000700000002 0.0125000002 -0.03125 +-0.0312799998 0.018719999099999999 -0.036887001199999998 +-0.043274000299999997 0.031725998999999998 -0.0398919992 +-0.043274000299999997 0.031725998999999998 -0.035108 +-0.03125 0.050000000699999998 -0.0125000002 +3 25 20 23 +3 26 24 25 +3 33 28 27 +3 40 38 33 +3 34 33 36 +3 34 30 33 +3 35 32 34 +3 37 31 35 +3 39 29 37 +3 74 41 42 +3 71 74 42 +3 43 71 42 +3 43 69 71 +3 43 45 69 +3 45 47 67 +3 47 49 64 +3 53 50 56 +3 150 161 109 +3 375 369 376 +3 367 375 368 +3 359 367 360 +3 351 359 352 +3 345 339 344 +3 339 338 344 +3 50 63 60 +3 160 149 112 +3 149 138 115 +3 119 117 120 +3 116 119 120 +3 148 114 137 +3 159 111 148 +3 107 170 105 +3 107 110 158 +3 110 113 147 +3 281 313 282 +3 313 293 314 +3 106 171 108 +3 61 52 57 +3 67 47 64 +3 69 45 67 +3 80 77 79 +3 81 85 80 +3 82 87 81 +3 316 294 265 +3 315 285 265 +3 273 317 329 +3 273 309 311 +3 273 304 309 +3 274 277 288 +3 295 274 288 +3 264 287 335 +3 334 264 335 +3 380 371 179 +3 44 46 66 +3 229 228 370 +3 230 212 318 +3 312 230 318 +3 101 15 97 +3 10 103 99 +3 96 4 6 +3 4 94 93 +3 1 4 93 +3 343 118 350 +3 358 377 366 +3 100 11 7 +3 100 104 11 +3 98 16 102 +3 98 95 21 +3 349 342 350 +3 365 357 366 +3 373 365 374 +3 297 305 306 +3 290 297 298 +3 283 290 291 +3 278 283 284 +3 157 165 154 +3 143 146 154 +3 135 125 143 +3 379 235 239 +3 235 322 300 +3 90 89 92 +3 86 76 88 +3 88 75 91 +3 72 73 70 +3 83 78 84 +3 68 66 65 +3 59 54 55 +3 55 51 58 +3 58 48 62 +3 320 325 319 +3 327 324 325 +3 330 327 328 +3 332 330 331 +3 336 332 333 +3 340 336 337 +3 347 340 341 +3 355 347 348 +3 363 355 356 +3 372 363 364 +3 372 362 361 +3 353 354 346 +3 196 203 195 +3 259 270 289 +3 296 252 289 +3 188 196 195 +3 223 225 216 +3 209 216 218 +3 200 207 202 +3 192 200 194 +3 185 174 183 +3 162 172 174 +3 151 162 164 +3 140 151 153 +3 132 140 142 +3 121 132 134 +3 131 121 122 +3 139 131 133 +3 150 139 141 +3 173 161 163 +3 161 152 163 +3 191 184 193 +3 199 191 201 +3 206 199 208 +3 215 206 217 +3 222 215 224 +3 187 178 177 +3 219 211 196 +3 9 13 14 +3 14 18 19 +3 2 3 0 +3 0 8 5 +3 12 0 17 +3 0 22 17 +3 286 279 249 +3 286 308 292 +3 286 310 308 +3 268 269 271 +3 267 271 272 +3 261 266 262 +3 253 261 254 +3 247 253 248 +3 241 247 242 +3 236 241 237 +3 231 236 232 +3 227 221 226 +3 213 220 221 +3 204 213 214 +3 197 204 205 +3 189 197 198 +3 180 189 190 +3 168 180 181 +3 166 168 169 +3 144 155 148 +3 127 144 137 +3 182 186 175 +3 171 182 176 +3 160 171 167 +3 149 160 156 +3 138 149 145 +3 130 138 136 +3 120 130 124 +3 123 126 129 +3 126 128 129 +3 263 307 256 +3 246 302 244 +3 233 299 234 +3 260 276 255 +3 260 255 251 +3 250 326 210 +3 280 303 245 +3 243 323 301 +3 240 275 258 +3 257 275 240 +3 238 234 378 +3 234 321 378 + diff --git a/Constrained_triangulation_3/test/Constrained_triangulation_3/data/bug8.off b/Constrained_triangulation_3/test/Constrained_triangulation_3/data/bug8.off new file mode 100644 index 000000000000..24eab3cc0a76 --- /dev/null +++ b/Constrained_triangulation_3/test/Constrained_triangulation_3/data/bug8.off @@ -0,0 +1,26 @@ +OFF +16 6 0 + +-27.740373000000002 41.290998000000002 95 +-15.450850000000001 47.552849999999999 96.239999999999995 +-17.099747000000001 46.712691999999997 95 +-19.747043000000001 45.363821000000002 89.853847999999999 +-25.093077000000001 42.639868999999997 89.853847999999999 +-29.359850000000002 40.410400000000003 96.384 +-15.4354 47.505249999999997 96.384 +-29.359850000000002 40.410400000000003 96.480000000000004 +-13.651558 47.837826999999997 70.299999999999997 +-13.651558 47.837826999999997 53.799999999999997 +-25.498366000000001 36.890810999999999 95 +-22.851068000000001 38.239677999999998 89.853847999999999 +-17.505030000000001 40.963622999999998 89.853847999999999 +0 49.899999999999999 96.623999999999995 +-15.41995 47.457700000000003 96.719999999999999 +0 49.899999999999999 96.719999999999999 +3 9 1 8 +3 0 10 4 +3 2 10 0 +3 11 12 3 +3 5 7 6 +3 13 14 15 + diff --git a/Constrained_triangulation_3/test/Constrained_triangulation_3/data/bug9.off b/Constrained_triangulation_3/test/Constrained_triangulation_3/data/bug9.off new file mode 100644 index 000000000000..a3d6d7813ee5 --- /dev/null +++ b/Constrained_triangulation_3/test/Constrained_triangulation_3/data/bug9.off @@ -0,0 +1,949 @@ +OFF +485 460 0 + +26.597300000000001 36.607999999999997 97.103999999999999 +26.567900000000002 36.567549999999997 96.959999999999994 +36.567549999999997 26.567900000000002 96.959999999999994 +36.607999999999997 26.597300000000001 97.103999999999999 +29.359850000000002 40.410400000000003 96.480000000000004 +13.983000000000001 43.035299999999999 97.103999999999999 +40.410400000000003 29.359850000000002 96.480000000000004 +15.4354 47.505249999999997 96.480000000000004 +36.405749999999998 26.45035 95.760000000000005 +49.450000000000003 0 97.488 +47.02975 -15.280900000000001 97.488 +49.25 0 97.680000000000007 +42.797550000000001 13.905749999999999 95.760000000000005 +47.02975 15.280900000000001 97.488 +40.005899999999997 29.065999999999999 97.488 +46.839550000000003 15.219099999999999 97.680000000000007 +29.065999999999999 40.005899999999997 97.488 +39.844099999999997 28.948399999999999 97.680000000000007 +15.280900000000001 47.02975 97.488 +0 49.450000000000003 97.488 +0 49.25 97.680000000000007 +-15.280900000000001 47.02975 97.488 +-15.219099999999999 46.839550000000003 97.680000000000007 +-29.065999999999999 40.005899999999997 97.488 +-28.948399999999999 39.844099999999997 97.680000000000007 +-39.844099999999997 28.948399999999999 97.680000000000007 +-40.005899999999997 29.065999999999999 97.488 +-47.02975 15.280900000000001 97.488 +-49.450000000000003 0 97.488 +0 49.950000000000003 96.480000000000004 +-43.130400000000002 14.0139 97.200000000000003 +-45.350000000000001 0 97.200000000000003 +44.557000000000002 14.477449999999999 98.304000000000002 +0 49.149999999999999 97.775999999999996 +-39.763199999999998 28.88965 97.775999999999996 +-36.688899999999997 26.65605 97.200000000000003 +-26.685449999999999 36.729349999999997 97.296000000000006 +-26.65605 36.688899999999997 97.200000000000003 +-49.149999999999999 0 97.775999999999996 +14.601050000000001 44.937399999999997 98.400000000000006 +0 47.25 98.400000000000006 +-38.226050000000001 27.772849999999998 98.400000000000006 +-27.772849999999998 38.226050000000001 98.400000000000006 +-47.25 0 98.400000000000006 +43.891249999999999 14.261150000000001 98.016000000000005 +43.796149999999997 14.23025 97.920000000000002 +46.049999999999997 0 97.920000000000002 +-14.601050000000001 44.937399999999997 98.400000000000006 +37.336150000000004 27.126300000000001 98.016000000000005 +-37.255249999999997 27.067499999999999 97.920000000000002 +-43.891249999999999 14.261150000000001 98.016000000000005 +-43.796149999999997 14.23025 97.920000000000002 +-46.149999999999999 0 98.016000000000005 +27.126300000000001 37.336150000000004 98.016000000000005 +27.067499999999999 37.255249999999997 97.920000000000002 +-14.23025 43.796149999999997 97.920000000000002 +-27.126300000000001 37.336150000000004 98.016000000000005 +-27.067499999999999 37.255249999999997 97.920000000000002 +-37.336150000000004 27.126300000000001 98.016000000000005 +-14.029350000000001 43.177950000000003 97.296000000000006 +-36.810250000000003 26.744250000000001 97.391999999999996 +-44.937399999999997 14.601050000000001 98.400000000000006 +45.399999999999999 0 97.296000000000006 +43.177950000000003 -14.029350000000001 97.296000000000006 +45.5 0 97.391999999999996 +43.273049999999998 -14.06025 97.391999999999996 +0 45.399999999999999 97.296000000000006 +-14.06025 43.273049999999998 97.391999999999996 +43.273049999999998 14.06025 97.391999999999996 +43.177950000000003 14.029350000000001 97.296000000000006 +-44.699649999999998 14.5238 98.352000000000004 +14.029350000000001 43.177950000000003 97.296000000000006 +14.0139 43.130400000000002 97.200000000000003 +26.65605 36.688899999999997 97.200000000000003 +-47 0 98.352000000000004 +0 45.5 97.391999999999996 +-27.625900000000001 38.023800000000001 98.352000000000004 +-38.023800000000001 27.625900000000001 98.352000000000004 +-14.5238 44.699649999999998 98.352000000000004 +36.729349999999997 26.685449999999999 97.296000000000006 +36.688899999999997 26.65605 97.200000000000003 +43.130400000000002 14.0139 97.200000000000003 +0 47 98.352000000000004 +14.5238 44.699649999999998 98.352000000000004 +36.810250000000003 26.744250000000001 97.391999999999996 +26.685449999999999 36.729349999999997 97.296000000000006 +27.625900000000001 38.023800000000001 98.352000000000004 +38.023800000000001 27.625900000000001 98.352000000000004 +46.126249999999999 14.987299999999999 98.207999999999998 +39.237299999999998 28.5076 98.207999999999998 +46.031149999999997 14.9564 98.256 +39.156399999999998 28.448799999999999 98.256 +46.850000000000001 0 98.304000000000002 +47 0 98.352000000000004 +44.699649999999998 14.5238 98.352000000000004 +14.987299999999999 46.126249999999999 98.207999999999998 +28.448799999999999 39.156399999999998 98.256 +0 48.5 98.207999999999998 +44.699649999999998 -14.5238 98.352000000000004 +-14.987299999999999 46.126249999999999 98.207999999999998 +-14.9564 46.031149999999997 98.256 +-28.5076 39.237299999999998 98.207999999999998 +46.649299999999997 -15.157299999999999 97.872 +49.049999999999997 0 97.872 +-39.237299999999998 28.5076 98.207999999999998 +-28.448799999999999 39.156399999999998 98.256 +46.649299999999997 15.157299999999999 97.872 +-46.126249999999999 14.987299999999999 98.207999999999998 +-46.031149999999997 14.9564 98.256 +39.682299999999998 28.830850000000002 97.872 +28.830850000000002 39.682299999999998 97.872 +15.157299999999999 46.649299999999997 97.872 +0 49.049999999999997 97.872 +-15.1882 46.744450000000001 97.775999999999996 +-15.157299999999999 46.649299999999997 97.872 +-28.88965 39.763199999999998 97.775999999999996 +-28.830850000000002 39.682299999999998 97.872 +-39.682299999999998 28.830850000000002 97.872 +-46.649299999999997 15.157299999999999 97.872 +-13.905749999999999 42.797550000000001 95.760000000000005 +46.25 0 98.063999999999993 +43.891249999999999 -14.261150000000001 98.016000000000005 +-13.905749999999999 42.797550000000001 4.7999999999999998 +43.986350000000002 14.29205 98.063999999999993 +46.149999999999999 0 98.016000000000005 +44.794750000000001 -14.5547 98.352000000000004 +0 46.149999999999999 98.016000000000005 +14.261150000000001 43.891249999999999 98.016000000000005 +38.104700000000001 27.684699999999999 98.352000000000004 +44.794750000000001 14.5547 98.352000000000004 +27.684699999999999 38.104700000000001 98.352000000000004 +-14.261150000000001 43.891249999999999 98.016000000000005 +-43.320599999999999 14.075699999999999 97.488 +-26.773599999999998 36.850700000000003 97.488 +-36.850700000000003 26.773599999999998 97.488 +-39.601399999999998 28.772099999999998 97.920000000000002 +-46.554200000000002 15.1264 97.920000000000002 +-49.049999999999997 0 97.872 +-48.950000000000003 0 97.920000000000002 +-45.75 0 97.680000000000007 +-29.306730000000002 33.549370000000003 15.603847999999999 +-33.549370000000003 29.306730000000002 15.603847999999999 +-29.306730000000002 33.549370000000003 9.4961520000000004 +-35.670690999999998 27.185409 53.799999999999997 +-33.549370000000003 29.306730000000002 58.996152000000002 +-35.670690999999998 27.185409 70.299999999999997 +-17.505030000000001 40.963622999999998 17.746151999999999 +-22.851068000000001 38.239677999999998 17.746151999999999 +-48.399999999999999 0 98.256 +48.399999999999999 0 98.256 +46.031149999999997 -14.9564 98.256 +47.505249999999997 -15.4354 96.480000000000004 +49.950000000000003 0 96.480000000000004 +47.505249999999997 15.4354 96.480000000000004 +45 0 95.760000000000005 +47.100000000000001 0 98.352000000000004 +-35.670690999999998 27.185409 20.800000000000001 +-36.405749999999998 26.45035 4.7999999999999998 +-26.45035 36.405749999999998 4.7999999999999998 +-26.45035 36.405749999999998 95.760000000000005 +-27.185409 35.670690999999998 20.800000000000001 +-27.471183 35.384917000000002 5 +-36.405749999999998 26.45035 95.760000000000005 +-33.549370000000003 29.306730000000002 9.4961520000000004 +-33.549370000000003 29.306730000000002 25.996151999999999 +-35.670690999999998 27.185409 37.299999999999997 +-35.384917000000002 27.471183 5 +-33.549370000000003 29.306730000000002 42.496152000000002 +-25.524087000000002 36.877704999999999 12.550000000000001 +-14.832011 42.325595999999997 12.550000000000001 +-17.505030000000001 40.963622999999998 7.3538480000000002 +-17.505030000000001 40.963622999999998 34.246152000000002 +-22.851068000000001 38.239677999999998 34.246152000000002 +-25.524087000000002 36.877704999999999 29.050000000000001 +-14.832011 42.325595999999997 29.050000000000001 +-17.505030000000001 40.963622999999998 23.853847999999999 +-22.851068000000001 38.239677999999998 23.853847999999999 +-17.505030000000001 40.963622999999998 50.746152000000002 +-22.851068000000001 38.239677999999998 50.746152000000002 +-25.524087000000002 36.877704999999999 45.549999999999997 +-14.832011 42.325595999999997 45.549999999999997 +-17.505030000000001 40.963622999999998 40.353847999999999 +-22.851068000000001 38.239677999999998 40.353847999999999 +-17.505030000000001 40.963622999999998 67.246151999999995 +-22.851068000000001 38.239677999999998 67.246151999999995 +-25.524087000000002 36.877704999999999 62.049999999999997 +-14.832011 42.325595999999997 62.049999999999997 +-17.505030000000001 40.963622999999998 56.853847999999999 +-22.851068000000001 38.239677999999998 56.853847999999999 +-17.505030000000001 40.963622999999998 83.746151999999995 +-22.851068000000001 38.239677999999998 83.746151999999995 +-25.524087000000002 36.877704999999999 78.549999999999997 +-14.832011 42.325595999999997 78.549999999999997 +-17.505030000000001 40.963622999999998 73.353847999999999 +-22.851068000000001 38.239677999999998 73.353847999999999 +-25.498366000000001 36.890810999999999 95 +-22.851068000000001 38.239677999999998 89.853847999999999 +-14.857732 42.312489999999997 95 +-17.505030000000001 40.963622999999998 89.853847999999999 +-29.306730000000002 33.549370000000003 25.996151999999999 +-29.306730000000002 33.549370000000003 42.496152000000002 +-27.185409 35.670690999999998 37.299999999999997 +-29.306730000000002 33.549370000000003 32.103847999999999 +-33.549370000000003 29.306730000000002 32.103847999999999 +-29.306730000000002 33.549370000000003 58.996152000000002 +-27.185409 35.670690999999998 53.799999999999997 +-29.306730000000002 33.549370000000003 48.603847999999999 +-33.549370000000003 29.306730000000002 48.603847999999999 +-29.306730000000002 33.549370000000003 75.496151999999995 +-33.549370000000003 29.306730000000002 75.496151999999995 +-27.185409 35.670690999999998 70.299999999999997 +-29.306730000000002 33.549370000000003 65.103847999999999 +-33.549370000000003 29.306730000000002 65.103847999999999 +-29.306730000000002 33.549370000000003 91.996151999999995 +-33.549370000000003 29.306730000000002 91.996151999999995 +-35.670690999999998 27.185409 86.799999999999997 +-27.185409 35.670690999999998 86.799999999999997 +-29.306730000000002 33.549370000000003 81.603847999999999 +-33.549370000000003 29.306730000000002 81.603847999999999 +-36.405749999999998 26.45035 96.239999999999995 +-26.45035 36.405749999999998 96.239999999999995 +-29.330500000000001 40.369950000000003 96.719999999999999 +-40.369950000000003 29.330500000000001 96.719999999999999 +-47.457700000000003 15.41995 96.719999999999999 +-49.899999999999999 0 96.719999999999999 +-45.049999999999997 0 96.384 +-42.845100000000002 13.921200000000001 96.384 +-26.479749999999999 36.446199999999997 96.384 +-36.446199999999997 26.479749999999999 96.384 +47.457700000000003 -15.41995 96.623999999999995 +49.899999999999999 0 96.623999999999995 +45 0 96.239999999999995 +42.797550000000001 -13.905749999999999 96.239999999999995 +47.457700000000003 15.41995 96.623999999999995 +42.797550000000001 13.905749999999999 96.239999999999995 +40.369950000000003 29.330500000000001 96.623999999999995 +29.330500000000001 40.369950000000003 96.623999999999995 +36.405749999999998 26.45035 96.239999999999995 +15.41995 47.457700000000003 96.623999999999995 +26.45035 36.405749999999998 96.239999999999995 +13.905749999999999 42.797550000000001 96.239999999999995 +0 45 96.239999999999995 +-13.905749999999999 42.797550000000001 96.239999999999995 +15.41995 47.457700000000003 96.719999999999999 +15.404500000000001 47.410150000000002 96.864000000000004 +0 49.850000000000001 96.864000000000004 +-15.404500000000001 47.410150000000002 96.864000000000004 +-29.301100000000002 40.329500000000003 96.864000000000004 +-40.329500000000003 29.301100000000002 96.864000000000004 +-47.410150000000002 15.404500000000001 96.864000000000004 +-49.850000000000001 0 96.864000000000004 +-45.049999999999997 0 96.480000000000004 +-42.845100000000002 13.921200000000001 96.480000000000004 +-36.446199999999997 26.479749999999999 96.480000000000004 +-26.479749999999999 36.446199999999997 96.480000000000004 +-13.921200000000001 42.845100000000002 96.384 +-13.921200000000001 42.845100000000002 96.480000000000004 +47.457700000000003 -15.41995 96.719999999999999 +49.899999999999999 0 96.719999999999999 +45.049999999999997 0 96.384 +42.845100000000002 -13.921200000000001 96.384 +47.457700000000003 15.41995 96.719999999999999 +42.845100000000002 13.921200000000001 96.384 +40.369950000000003 29.330500000000001 96.719999999999999 +36.446199999999997 26.479749999999999 96.384 +29.330500000000001 40.369950000000003 96.719999999999999 +26.479749999999999 36.446199999999997 96.384 +13.921200000000001 42.845100000000002 96.384 +0 45.049999999999997 96.384 +29.301100000000002 40.329500000000003 96.864000000000004 +29.271699999999999 40.289050000000003 96.959999999999994 +15.389049999999999 47.3626 96.959999999999994 +0 49.799999999999997 96.959999999999994 +-15.389049999999999 47.3626 96.959999999999994 +-29.271699999999999 40.289050000000003 96.959999999999994 +-40.289050000000003 29.271699999999999 96.959999999999994 +-45.100000000000001 0 96.623999999999995 +-42.892650000000003 13.93665 96.623999999999995 +-26.5091 36.486649999999997 96.623999999999995 +-36.486649999999997 26.5091 96.623999999999995 +0 45.049999999999997 96.480000000000004 +-13.93665 42.892650000000003 96.623999999999995 +47.410150000000002 -15.404500000000001 96.864000000000004 +49.850000000000001 0 96.864000000000004 +42.845100000000002 -13.921200000000001 96.480000000000004 +45.049999999999997 0 96.480000000000004 +42.845100000000002 13.921200000000001 96.480000000000004 +47.410150000000002 15.404500000000001 96.864000000000004 +36.446199999999997 26.479749999999999 96.480000000000004 +0 45.100000000000001 96.719999999999999 +47.3626 -15.389049999999999 96.959999999999994 +45.100000000000001 0 96.623999999999995 +42.892650000000003 -13.93665 96.623999999999995 +49.799999999999997 0 96.959999999999994 +42.892650000000003 13.93665 96.623999999999995 +36.486649999999997 26.5091 96.623999999999995 +47.3626 15.389049999999999 96.959999999999994 +26.5091 36.486649999999997 96.623999999999995 +13.93665 42.892650000000003 96.623999999999995 +47.315049999999999 15.3736 97.103999999999999 +47.219949999999997 15.342700000000001 97.200000000000003 +40.167700000000004 29.18355 97.200000000000003 +29.18355 40.167700000000004 97.200000000000003 +15.342700000000001 47.219949999999997 97.200000000000003 +0 49.649999999999999 97.200000000000003 +-15.342700000000001 47.219949999999997 97.200000000000003 +-29.18355 40.167700000000004 97.200000000000003 +-40.167700000000004 29.18355 97.200000000000003 +-47.219949999999997 15.342700000000001 97.200000000000003 +-49.649999999999999 0 97.200000000000003 +-45.149999999999999 0 96.864000000000004 +-42.940199999999997 13.9521 96.864000000000004 +-26.538499999999999 36.527099999999997 96.864000000000004 +-36.527099999999997 26.538499999999999 96.864000000000004 +-13.9521 42.940199999999997 96.864000000000004 +13.93665 42.892650000000003 96.719999999999999 +0 45.149999999999999 96.864000000000004 +42.892650000000003 -13.93665 96.719999999999999 +45.100000000000001 0 96.719999999999999 +47.315049999999999 -15.3736 97.103999999999999 +42.892650000000003 13.93665 96.719999999999999 +49.75 0 97.103999999999999 +36.486649999999997 26.5091 96.719999999999999 +26.5091 36.486649999999997 96.719999999999999 +49.649999999999999 0 97.200000000000003 +49.600000000000001 0 97.296000000000006 +47.172400000000003 15.327249999999999 97.296000000000006 +40.127249999999997 29.154150000000001 97.296000000000006 +29.154150000000001 40.127249999999997 97.296000000000006 +15.327249999999999 47.172400000000003 97.296000000000006 +0 49.600000000000001 97.296000000000006 +-15.327249999999999 47.172400000000003 97.296000000000006 +-29.154150000000001 40.127249999999997 97.296000000000006 +-40.127249999999997 29.154150000000001 97.296000000000006 +-47.172400000000003 15.327249999999999 97.296000000000006 +-49.600000000000001 0 97.296000000000006 +-45.200000000000003 0 96.959999999999994 +-42.987749999999998 13.967549999999999 96.959999999999994 +-26.567900000000002 36.567549999999997 96.959999999999994 +-36.567549999999997 26.567900000000002 96.959999999999994 +-13.967549999999999 42.987749999999998 96.959999999999994 +13.9521 42.940199999999997 96.864000000000004 +0 45.200000000000003 96.959999999999994 +45.149999999999999 0 96.864000000000004 +42.940199999999997 -13.9521 96.864000000000004 +42.940199999999997 13.9521 96.864000000000004 +47.219949999999997 -15.342700000000001 97.200000000000003 +36.527099999999997 26.538499999999999 96.864000000000004 +26.538499999999999 36.527099999999997 96.864000000000004 +47.172400000000003 -15.327249999999999 97.296000000000006 +47.077300000000001 -15.29635 97.391999999999996 +49.5 0 97.391999999999996 +47.077300000000001 15.29635 97.391999999999996 +40.046349999999997 29.09535 97.391999999999996 +29.09535 40.046349999999997 97.391999999999996 +15.29635 47.077300000000001 97.391999999999996 +0 49.5 97.391999999999996 +-15.29635 47.077300000000001 97.391999999999996 +-29.09535 40.046349999999997 97.391999999999996 +-40.046349999999997 29.09535 97.391999999999996 +-47.077300000000001 15.29635 97.391999999999996 +-49.5 0 97.391999999999996 +-45.25 0 97.103999999999999 +-43.035299999999999 13.983000000000001 97.103999999999999 +-26.597300000000001 36.607999999999997 97.103999999999999 +-36.607999999999997 26.597300000000001 97.103999999999999 +-13.983000000000001 43.035299999999999 97.103999999999999 +13.967549999999999 42.987749999999998 96.959999999999994 +0 45.25 97.103999999999999 +45.200000000000003 0 96.959999999999994 +42.987749999999998 -13.967549999999999 96.959999999999994 +42.987749999999998 13.967549999999999 96.959999999999994 +-14.0139 43.130400000000002 97.200000000000003 +0 45.350000000000001 97.200000000000003 +45.25 0 97.103999999999999 +43.035299999999999 -13.983000000000001 97.103999999999999 +45.350000000000001 0 97.200000000000003 +43.130400000000002 -14.0139 97.200000000000003 +43.035299999999999 13.983000000000001 97.103999999999999 +45.549999999999997 0 97.488 +43.320599999999999 -14.075699999999999 97.488 +43.320599999999999 14.075699999999999 97.488 +-14.075699999999999 43.320599999999999 97.488 +36.850700000000003 26.773599999999998 97.488 +14.06025 43.273049999999998 97.391999999999996 +0 45.549999999999997 97.488 +26.744250000000001 36.810250000000003 97.391999999999996 +26.773599999999998 36.850700000000003 97.488 +46.554200000000002 -15.1264 97.920000000000002 +48.950000000000003 0 97.920000000000002 +46.554200000000002 15.1264 97.920000000000002 +39.601399999999998 28.772099999999998 97.920000000000002 +28.772099999999998 39.601399999999998 97.920000000000002 +15.1264 46.554200000000002 97.920000000000002 +0 48.950000000000003 97.920000000000002 +-15.1264 46.554200000000002 97.920000000000002 +-28.772099999999998 39.601399999999998 97.920000000000002 +-43.510849999999998 14.137549999999999 97.680000000000007 +45.75 0 97.680000000000007 +43.510849999999998 -14.137549999999999 97.680000000000007 +-26.891200000000001 37.012549999999997 97.680000000000007 +-37.012549999999997 26.891200000000001 97.680000000000007 +43.510849999999998 14.137549999999999 97.680000000000007 +37.012549999999997 26.891200000000001 97.680000000000007 +-14.137549999999999 43.510849999999998 97.680000000000007 +26.891200000000001 37.012549999999997 97.680000000000007 +14.075699999999999 43.320599999999999 97.488 +0 45.75 97.680000000000007 +14.137549999999999 43.510849999999998 97.680000000000007 +46.459099999999999 -15.095499999999999 98.016000000000005 +48.850000000000001 0 98.016000000000005 +46.459099999999999 15.095499999999999 98.016000000000005 +39.520499999999998 28.7133 98.016000000000005 +28.7133 39.520499999999998 98.016000000000005 +15.095499999999999 46.459099999999999 98.016000000000005 +0 48.850000000000001 98.016000000000005 +-15.095499999999999 46.459099999999999 98.016000000000005 +-28.7133 39.520499999999998 98.016000000000005 +-39.520499999999998 28.7133 98.016000000000005 +-46.459099999999999 15.095499999999999 98.016000000000005 +-48.850000000000001 0 98.016000000000005 +-45.850000000000001 0 97.775999999999996 +-43.60595 14.16845 97.775999999999996 +45.850000000000001 0 97.775999999999996 +43.60595 -14.16845 97.775999999999996 +43.60595 14.16845 97.775999999999996 +-26.949950000000001 37.093449999999997 97.775999999999996 +-37.093449999999997 26.949950000000001 97.775999999999996 +37.093449999999997 26.949950000000001 97.775999999999996 +26.949950000000001 37.093449999999997 97.775999999999996 +-14.16845 43.60595 97.775999999999996 +14.16845 43.60595 97.775999999999996 +0 45.850000000000001 97.775999999999996 +46.363999999999997 -15.0646 98.063999999999993 +48.75 0 98.063999999999993 +46.363999999999997 15.0646 98.063999999999993 +39.439599999999999 28.65455 98.063999999999993 +28.65455 39.439599999999999 98.063999999999993 +15.0646 46.363999999999997 98.063999999999993 +0 48.75 98.063999999999993 +-15.0646 46.363999999999997 98.063999999999993 +-28.65455 39.439599999999999 98.063999999999993 +-39.439599999999999 28.65455 98.063999999999993 +-46.363999999999997 15.0646 98.063999999999993 +-48.75 0 98.063999999999993 +-45.950000000000003 0 97.872 +45.950000000000003 0 97.872 +43.701050000000002 -14.199350000000001 97.872 +-43.701050000000002 14.199350000000001 97.872 +43.701050000000002 14.199350000000001 97.872 +37.174349999999997 27.008749999999999 97.872 +-27.008749999999999 37.174349999999997 97.872 +-37.174349999999997 27.008749999999999 97.872 +27.008749999999999 37.174349999999997 97.872 +14.199350000000001 43.701050000000002 97.872 +-14.199350000000001 43.701050000000002 97.872 +0 45.950000000000003 97.872 +46.268900000000002 -15.0337 98.159999999999997 +48.649999999999999 0 98.159999999999997 +46.268900000000002 15.0337 98.159999999999997 +39.358699999999999 28.595749999999999 98.159999999999997 +28.595749999999999 39.358699999999999 98.159999999999997 +15.0337 46.268900000000002 98.159999999999997 +0 48.649999999999999 98.159999999999997 +-15.0337 46.268900000000002 98.159999999999997 +-28.595749999999999 39.358699999999999 98.159999999999997 +-39.358699999999999 28.595749999999999 98.159999999999997 +-46.268900000000002 15.0337 98.159999999999997 +-48.649999999999999 0 98.159999999999997 +-46.049999999999997 0 97.920000000000002 +43.796149999999997 -14.23025 97.920000000000002 +14.23025 43.796149999999997 97.920000000000002 +0 46.049999999999997 97.920000000000002 +46.126249999999999 -14.987299999999999 98.207999999999998 +48.5 0 98.207999999999998 +28.5076 39.237299999999998 98.207999999999998 +-48.5 0 98.207999999999998 +14.5547 44.794750000000001 98.352000000000004 +0 47.100000000000001 98.352000000000004 +-14.5547 44.794750000000001 98.352000000000004 +-27.684699999999999 38.104700000000001 98.352000000000004 +-38.104700000000001 27.684699999999999 98.352000000000004 +-44.794750000000001 14.5547 98.352000000000004 +-47.100000000000001 0 98.352000000000004 +42.797550000000001 -13.905749999999999 95.760000000000005 +3 190 189 196 +3 169 119 174 +3 183 186 192 +3 194 191 184 +3 147 146 176 +3 168 173 159 +3 168 147 173 +3 179 178 185 +3 169 170 122 +3 181 182 171 +3 186 119 192 +3 180 181 171 +3 197 119 195 +3 189 119 197 +3 189 197 198 +3 192 193 183 +3 190 196 159 +3 174 175 169 +3 175 176 146 +3 146 169 175 +3 173 172 179 +3 187 188 177 +3 177 180 186 +3 172 171 182 +3 214 159 162 +3 201 202 160 +3 212 145 144 +3 206 207 200 +3 160 159 201 +3 160 140 158 +3 208 210 216 +3 164 199 203 +3 156 165 162 +3 201 205 200 +3 201 159 205 +3 207 143 167 +3 145 215 162 +3 165 143 162 +3 145 209 215 +3 205 206 200 +3 205 159 210 +3 215 214 162 +3 213 216 159 +3 144 204 212 +3 143 145 162 +3 203 165 164 +3 216 217 208 +3 213 159 214 +3 218 215 209 +3 217 218 208 +3 211 212 204 +3 210 211 204 +3 216 210 159 +3 209 208 218 +3 157 163 141 +3 157 158 161 +3 157 166 163 +3 140 142 158 +3 202 203 199 +3 199 160 202 +3 204 205 210 +3 220 227 219 +3 228 226 219 +3 152 229 151 +3 230 229 152 +3 152 153 230 +3 231 154 232 +3 232 154 484 +3 153 233 230 +3 153 6 233 +3 231 234 154 +3 154 234 12 +3 6 235 233 +3 236 235 4 +3 4 235 6 +3 234 237 12 +3 12 237 8 +3 4 7 236 +3 7 238 236 +3 7 29 238 +3 246 221 247 +3 222 248 221 +3 221 248 247 +3 222 223 248 +3 248 223 249 +3 223 224 249 +3 249 224 250 +3 251 225 226 +3 252 251 226 +3 266 267 239 +3 268 241 240 +3 267 268 240 +3 268 255 241 +3 241 255 242 +3 265 243 269 +3 243 244 269 +3 269 244 270 +3 244 271 270 +3 244 245 271 +3 245 272 271 +3 245 246 272 +3 272 246 273 +3 246 247 273 +3 273 247 274 +3 248 275 247 +3 277 276 252 +3 278 279 253 +3 254 278 253 +3 279 277 253 +3 256 278 254 +3 280 281 256 +3 256 255 268 +3 280 256 268 +3 281 278 256 +3 258 282 257 +3 283 282 258 +3 258 261 283 +3 260 284 259 +3 259 284 285 +3 262 259 286 +3 286 259 285 +3 261 287 283 +3 261 263 287 +3 264 262 288 +3 316 289 315 +3 292 317 291 +3 291 317 318 +3 293 319 290 +3 294 291 320 +3 320 291 318 +3 321 319 293 +3 293 296 321 +3 295 294 322 +3 322 294 320 +3 323 297 295 +3 322 323 295 +3 296 299 321 +3 315 298 297 +3 323 315 297 +3 321 299 324 +3 299 300 324 +3 324 300 325 +3 300 326 325 +3 300 301 326 +3 301 327 326 +3 328 327 302 +3 302 327 301 +3 302 303 328 +3 303 329 328 +3 303 304 329 +3 304 330 329 +3 304 305 330 +3 330 305 331 +3 305 306 331 +3 331 306 332 +3 307 333 306 +3 306 333 332 +3 307 308 333 +3 333 308 334 +3 308 309 334 +3 334 309 335 +3 311 336 310 +3 313 337 311 +3 337 336 311 +3 314 338 312 +3 338 339 313 +3 312 338 313 +3 339 337 313 +3 316 340 314 +3 340 338 314 +3 341 315 323 +3 341 316 315 +3 342 340 316 +3 342 316 341 +3 318 317 343 +3 343 317 344 +3 345 320 318 +3 343 345 318 +3 321 346 319 +3 347 322 320 +3 345 347 320 +3 324 346 321 +3 348 323 322 +3 347 348 322 +3 348 341 323 +3 324 349 346 +3 2 1 347 +3 1 367 348 +3 351 10 350 +3 9 10 351 +3 351 352 9 +3 352 13 9 +3 352 353 13 +3 353 14 13 +3 16 14 354 +3 354 14 353 +3 354 355 16 +3 355 18 16 +3 355 356 18 +3 356 19 18 +3 356 357 19 +3 19 357 21 +3 357 358 21 +3 21 358 23 +3 359 26 358 +3 358 26 23 +3 359 360 26 +3 26 360 27 +3 360 361 27 +3 27 361 28 +3 363 31 362 +3 365 30 363 +3 30 31 363 +3 366 37 364 +3 37 35 365 +3 364 37 365 +3 35 30 365 +3 368 372 366 +3 372 37 366 +3 5 367 1 +3 5 368 367 +3 373 372 368 +3 373 368 5 +3 369 370 374 +3 374 370 375 +3 374 375 376 +3 376 375 377 +3 378 371 369 +3 374 378 369 +3 3 2 371 +3 378 3 371 +3 13 15 11 +3 14 17 15 +3 23 26 25 +3 372 36 37 +3 373 59 372 +3 59 36 372 +3 376 377 62 +3 62 377 63 +3 72 5 0 +3 72 373 5 +3 66 59 373 +3 66 373 72 +3 81 378 374 +3 376 81 374 +3 69 81 376 +3 62 69 376 +3 80 3 378 +3 81 80 378 +3 73 0 3 +3 80 73 3 +3 73 72 0 +3 20 22 33 +3 33 22 113 +3 22 24 113 +3 113 24 115 +3 24 25 34 +3 115 24 34 +3 84 79 69 +3 118 38 137 +3 134 132 60 +3 64 65 379 +3 379 65 380 +3 381 68 64 +3 379 381 64 +3 75 382 67 +3 382 133 67 +3 383 84 68 +3 381 383 68 +3 384 71 85 +3 384 75 71 +3 385 382 75 +3 385 75 384 +3 386 85 79 +3 84 386 79 +3 387 386 84 +3 383 387 84 +3 386 384 85 +3 103 388 102 +3 389 388 103 +3 103 106 389 +3 106 390 389 +3 106 109 390 +3 109 391 390 +3 110 392 391 +3 109 110 391 +3 110 111 392 +3 111 393 392 +3 111 112 393 +3 112 394 393 +3 112 114 394 +3 394 114 395 +3 114 116 395 +3 395 116 396 +3 116 117 135 +3 396 116 135 +3 134 397 132 +3 397 139 132 +3 394 395 415 +3 415 395 416 +3 395 396 416 +3 416 396 417 +3 396 135 418 +3 417 396 418 +3 135 136 418 +3 418 136 419 +3 136 138 419 +3 419 138 420 +3 397 421 139 +3 401 422 397 +3 422 421 397 +3 398 399 423 +3 423 399 424 +3 425 402 398 +3 423 425 398 +3 404 426 400 +3 426 427 401 +3 400 426 401 +3 427 422 401 +3 428 403 402 +3 425 428 402 +3 429 405 403 +3 428 429 403 +3 407 430 404 +3 430 426 404 +3 431 408 405 +3 429 431 405 +3 408 407 406 +3 432 430 407 +3 432 407 408 +3 431 432 408 +3 410 433 409 +3 434 433 410 +3 410 411 434 +3 411 435 434 +3 411 412 435 +3 412 436 435 +3 413 437 436 +3 412 413 436 +3 413 414 437 +3 414 438 437 +3 414 415 438 +3 415 439 438 +3 415 416 439 +3 439 416 440 +3 416 417 440 +3 440 417 441 +3 417 418 442 +3 441 417 442 +3 418 419 442 +3 442 419 443 +3 419 420 443 +3 443 420 444 +3 422 445 421 +3 423 424 446 +3 446 424 447 +3 427 448 422 +3 448 445 422 +3 449 425 423 +3 446 449 423 +3 450 428 425 +3 449 450 425 +3 430 451 426 +3 451 452 427 +3 426 451 427 +3 452 448 427 +3 453 429 428 +3 450 453 428 +3 471 454 453 +3 54 471 453 +3 472 456 454 +3 471 472 454 +3 456 55 455 +3 55 57 455 +3 472 55 456 +3 458 473 457 +3 474 473 458 +3 458 459 474 +3 459 88 474 +3 459 460 88 +3 460 89 88 +3 461 475 89 +3 460 461 89 +3 461 462 475 +3 462 95 475 +3 462 463 95 +3 463 97 95 +3 463 464 97 +3 97 464 99 +3 464 465 99 +3 99 465 101 +3 465 466 104 +3 101 465 104 +3 466 467 104 +3 104 467 107 +3 467 468 107 +3 107 468 476 +3 51 52 469 +3 46 470 124 +3 124 470 121 +3 124 44 46 +3 44 48 45 +3 127 471 54 +3 53 127 54 +3 57 56 49 +3 58 50 49 +3 126 472 471 +3 127 126 471 +3 126 131 472 +3 472 131 55 +3 131 56 55 +3 107 476 108 +3 108 476 148 +3 474 150 473 +3 149 150 474 +3 474 88 149 +3 88 90 149 +3 475 96 91 +3 89 475 91 +3 475 95 96 +3 100 101 105 +3 124 121 120 +3 123 44 124 +3 94 32 92 +3 94 87 32 +3 39 477 130 +3 39 40 477 +3 40 478 477 +3 40 47 478 +3 478 47 479 +3 47 42 479 +3 479 42 480 +3 42 41 481 +3 480 42 481 +3 41 61 481 +3 481 61 482 +3 61 43 482 +3 482 43 483 +3 77 76 480 +3 482 483 74 +3 481 77 480 +3 481 482 77 +3 480 76 479 +3 76 78 479 +3 479 78 478 +3 478 82 477 +3 477 83 130 +3 130 86 128 +3 128 87 129 +3 129 94 155 +3 155 93 125 +3 93 98 125 +3 78 82 478 +3 82 83 477 +3 83 86 130 +3 86 87 128 +3 87 94 129 +3 94 93 155 +3 74 70 482 +3 70 77 482 + diff --git a/Constrained_triangulation_3/test/Constrained_triangulation_3/test_ccdt_remeshing.cpp b/Constrained_triangulation_3/test/Constrained_triangulation_3/test_ccdt_remeshing.cpp index 3310fa00a646..45ffaa9c8d22 100644 --- a/Constrained_triangulation_3/test/Constrained_triangulation_3/test_ccdt_remeshing.cpp +++ b/Constrained_triangulation_3/test/Constrained_triangulation_3/test_ccdt_remeshing.cpp @@ -11,6 +11,7 @@ #include #include +#include using K = CGAL::Exact_predicates_inexact_constructions_kernel; @@ -49,20 +50,25 @@ int main(int argc, char* argv[]) namespace Tet_remesh = CGAL::Tetrahedral_remeshing; Tr tr = Tet_remesh::get_remeshing_triangulation(std::move(cdt)); + auto number_of_constrained_facets = [](const Tr& tr) { + auto n = std::count_if(tr.finite_facets().begin(), tr.finite_facets().end(), + [](const auto& f) { + auto [c, i] = f; + return c->is_facet_on_surface(i); + }); + return static_cast(n); + }; + + auto nb = number_of_constrained_facets(tr); + assert(nb == nb_cstr_facets); + CGAL::tetrahedral_isotropic_remeshing(tr, 2., CGAL::parameters::number_of_iterations(3) .remesh_boundaries(false)); std::cout << "Number of vertices in tr: " << tr.number_of_vertices() << std::endl; - auto nb = 0u; - for(auto f : tr.finite_facets()) - { - const Tr::Cell_handle c = f.first; - const int i = f.second; - if(c->is_facet_on_surface(i)) - ++nb; - } + nb = number_of_constrained_facets(tr); assert(nb == nb_cstr_facets); return EXIT_SUCCESS; diff --git a/Constrained_triangulation_3/test/Constrained_triangulation_3/test_constrained_Delaunay_triangulation_3.cpp b/Constrained_triangulation_3/test/Constrained_triangulation_3/test_constrained_Delaunay_triangulation_3.cpp index e14eb01dac49..4f4786477182 100644 --- a/Constrained_triangulation_3/test/Constrained_triangulation_3/test_constrained_Delaunay_triangulation_3.cpp +++ b/Constrained_triangulation_3/test/Constrained_triangulation_3/test_constrained_Delaunay_triangulation_3.cpp @@ -1,9 +1,21 @@ -#include +#include #include #include +#include #include - -#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include using K = CGAL::Exact_predicates_inexact_constructions_kernel; using CDT = CGAL::Conforming_constrained_Delaunay_triangulation_3; diff --git a/Filtered_kernel/include/CGAL/Lazy.h b/Filtered_kernel/include/CGAL/Lazy.h index ec89813c0542..c96bacd51fa0 100644 --- a/Filtered_kernel/include/CGAL/Lazy.h +++ b/Filtered_kernel/include/CGAL/Lazy.h @@ -228,7 +228,7 @@ print_dag(const Return_base_tag&, std::ostream& os, int level) struct Depth_base { -#ifdef CGAL_PROFILE +#if defined(CGAL_PROFILE) || defined(CGAL_LAZY_USE_DEPTH) mutable int depth_; Depth_base() diff --git a/Lab/demo/Lab/Plugins/CDT_3/CDT_3_plugin.cpp b/Lab/demo/Lab/Plugins/CDT_3/CDT_3_plugin.cpp index ab33ceb8e31b..993aaca51ad4 100644 --- a/Lab/demo/Lab/Plugins/CDT_3/CDT_3_plugin.cpp +++ b/Lab/demo/Lab/Plugins/CDT_3/CDT_3_plugin.cpp @@ -37,7 +37,7 @@ struct Vertex_converter Vertex v; v.set_point(Wp{src.point()}); switch(src.ccdt_3_data().vertex_type()) { - case CDT_3_vertex_type::CORNER: + case CDT_3_vertex_type::INPUT_VERTEX: v.set_dimension(0); v.set_index(0); break; diff --git a/Lab/demo/Lab/Plugins/Mesh_3/C3t3_io_plugin.cpp b/Lab/demo/Lab/Plugins/Mesh_3/C3t3_io_plugin.cpp index 4e226a73472e..bbf59d575c61 100644 --- a/Lab/demo/Lab/Plugins/Mesh_3/C3t3_io_plugin.cpp +++ b/Lab/demo/Lab/Plugins/Mesh_3/C3t3_io_plugin.cpp @@ -135,11 +135,11 @@ CGAL_Lab_c3t3_binary_io_plugin::load( CGAL_assertion(!(!in)); item->setName(fileinfo.completeBaseName()); - item->set_valid(false); if(CGAL::IO::read_MEDIT(in, item->c3t3(), CGAL::parameters::verbose(false) .allow_non_manifold(true) + .allow_negative_orientation(true) .rebind_labels(false))) { item->resetCutPlane(); @@ -150,6 +150,7 @@ CGAL_Lab_c3t3_binary_io_plugin::load( } else if(item->c3t3().triangulation().number_of_finite_cells() == 0) { + item->set_valid(false); QMessageBox::warning(CGAL::Three::Three::mainWindow(), tr("C3t3_io_plugin"), tr("No finite cell provided.\n" "Nothing to display."), diff --git a/Lab/demo/Lab/Scene_triangulation_3_item.cpp b/Lab/demo/Lab/Scene_triangulation_3_item.cpp index 629b5be9115b..ec6a0fddd336 100644 --- a/Lab/demo/Lab/Scene_triangulation_3_item.cpp +++ b/Lab/demo/Lab/Scene_triangulation_3_item.cpp @@ -438,7 +438,8 @@ struct Scene_triangulation_3_item_priv { SMALLEST_RAD_RAD, SMALLEST_EDGE_RAD, BIGGEST_VL3_CUBE, - NB_SUBDOMAINS + NB_SUBDOMAINS, + NB_BADLY_ORIENTED_CELLS }; Scene_triangulation_3_item* item; T3 triangulation; @@ -520,6 +521,7 @@ struct Scene_triangulation_3_item_priv { mutable std::size_t nb_subdomains = 0; mutable std::size_t nb_vertices = 0; mutable std::size_t nb_tets = 0; + mutable std::size_t nb_badly_oriented_cells = 0; mutable float smallest_radius_radius = 0.f; mutable float smallest_edge_radius = 0.f; mutable float biggest_v_sma_cube = 0.f; @@ -1837,7 +1839,12 @@ QString Scene_triangulation_3_item::computeStats(int type) const Tr::Bare_point& p1 = wp2p(cit->vertex(1)->point()); const Tr::Bare_point& p2 = wp2p(cit->vertex(2)->point()); const Tr::Bare_point& p3 = wp2p(cit->vertex(3)->point()); - double v = std::abs(CGAL::volume(p0, p1, p2, p3)); + double v = CGAL::volume(p0, p1, p2, p3); + + if(v < 0) + ++d->nb_badly_oriented_cells; + v = std::abs(v); + double circumradius = std::sqrt(CGAL::squared_radius(p0, p1, p2, p3)); //find smallest edge double edges[6]; @@ -1943,6 +1950,8 @@ QString Scene_triangulation_3_item::computeStats(int type) return QString::number(d->biggest_v_sma_cube); case Scene_triangulation_3_item_priv::NB_SUBDOMAINS: return QString::number(d->nb_subdomains); + case Scene_triangulation_3_item_priv::NB_BADLY_ORIENTED_CELLS: + return QString::number(d->nb_badly_oriented_cells); default: return QString(); @@ -1969,6 +1978,7 @@ CGAL::Three::Scene_item::Header_data Scene_triangulation_3_item::header() const data.titles.append(QString("Smallest Edge-Radius Ratio")); data.titles.append(QString("Biggest Vl^3")); data.titles.append(QString("#Subdomains")); + data.titles.append(QString("#Badly Oriented Cells")); return data; } diff --git a/Mesh_2/include/CGAL/Mesh_2/Clusters.h b/Mesh_2/include/CGAL/Mesh_2/Clusters.h index 73c07e795efa..ef33c9647f0f 100644 --- a/Mesh_2/include/CGAL/Mesh_2/Clusters.h +++ b/Mesh_2/include/CGAL/Mesh_2/Clusters.h @@ -351,8 +351,9 @@ update_cluster(Cluster& c, iterator it, Vertex_handle va, squared_distance(c.smallest_angle.first->point(), c.smallest_angle.second->point()) / FT(4); cluster_map.insert(Cluster_map_value_type(va,c)); #ifdef CGAL_MESH_2_DEBUG_CLUSTERS - std::cerr << "Cluster at " << IO::oformat(va, With_point_tag{}) << " is updated. " - << "\n vm: " << IO::oformat(vm, With_point_tag{}) + With_point_tag wpt{{-1}, tr }; + std::cerr << "Cluster at " << IO::oformat(va, wpt) << " is updated. " + << "\n vm: " << IO::oformat(vm, wpt) << "\n reduction: " << reduction << "\n min_sq_len: " << c.minimum_squared_length << "\n"; diff --git a/Mesh_2/include/CGAL/Mesh_2/Refine_edges.h b/Mesh_2/include/CGAL/Mesh_2/Refine_edges.h index a03051e56f71..31367306e30a 100644 --- a/Mesh_2/include/CGAL/Mesh_2/Refine_edges.h +++ b/Mesh_2/include/CGAL/Mesh_2/Refine_edges.h @@ -177,14 +177,15 @@ namespace Mesh_2 { auto is_conform = ( angle(a, p, b) != OBTUSE ); #if CGAL_MESH_2_DEBUG_BAD_EDGES + With_point_tag wpt{{-1}, &tr}; if(!is_conform) { - std::cerr << " edge " << CGAL::IO::oformat(va, CGAL::With_point_tag{}) - << " -- " << CGAL::IO::oformat(vb, CGAL::With_point_tag{}) + std::cerr << " edge " << CGAL::IO::oformat(va, wpt) + << " -- " << CGAL::IO::oformat(vb, wpt) << " is encroached by "; if(encroaching_vertex != Vertex_handle()) { - std::cerr << IO::oformat(encroaching_vertex, With_point_tag{}) << std::endl; + std::cerr << IO::oformat(encroaching_vertex, wpt) << std::endl; } else { - std::cerr << "point " << CGAL::IO::oformat(p) << std::endl; + std::cerr << "point " << CGAL::IO::oformat(p, wpt) << std::endl; } } #endif // CGAL_MESH_2_DEBUG_BAD_EDGES @@ -384,12 +385,15 @@ class Refine_edges_base : } } + With_point_tag with_point_tag; + public: /** \name CONSTRUCTORS */ Refine_edges_base(Tr& tr_) : Container(Is_a_constrained_edge(tr_)), tr(tr_), is_a_constrained_edge(tr_), + with_point_tag{{-1}, &tr_}, converter(tr_) { } @@ -420,8 +424,8 @@ class Refine_edges_base : bool result = tr.is_flipable(fh, i); #if CGAL_MESH_2_DEBUG_REFINEMENT_POINTS std::cerr << " is_flippable(" - << IO::oformat(fh->vertex(tr.cw(i)), With_point_tag{}) << ", " - << IO::oformat(fh->vertex(tr.ccw(i)), With_point_tag{}) << ") = " + << IO::oformat(fh->vertex(tr.cw(i)), with_point_tag) << ", " + << IO::oformat(fh->vertex(tr.ccw(i)), with_point_tag) << ") = " << (result ? "true" : "false") << std::endl; #endif // CGAL_MESH_2_DEBUG_REFINEMENT_POINTS return result; @@ -564,7 +568,7 @@ class Refine_edges_base : if( zone.locate_type == Tr::VERTEX ) { #ifdef CGAL_MESH_2_DEBUG_INSERTIONS std::cerr << "insert(p, zone): returned existing vertex " - << IO::oformat(zone.fh->vertex(zone.i), With_point_tag{}) + << IO::oformat(zone.fh->vertex(zone.i), with_point_tag) << std::endl; #endif // CGAL_MESH_2_DEBUG_INSERTIONS for(auto [f, i]: zone.edges_to_flip) { @@ -573,8 +577,8 @@ class Refine_edges_base : auto va = f->vertex(Tr::cw(i)); auto vb = f->vertex(Tr::ccw(i)); std::cerr << " flipping edge (" - << IO::oformat(va, With_point_tag{}) << ", " - << IO::oformat(vb, With_point_tag{}) << ")\n"; + << IO::oformat(va, with_point_tag) << ", " + << IO::oformat(vb, with_point_tag) << ")\n"; #endif // CGAL_MESH_2_DEBUG_INSERTIONS triangulation_ref_impl().flip(f, i); } @@ -587,7 +591,7 @@ class Refine_edges_base : zone.faces.end() ); #ifdef CGAL_MESH_2_DEBUG_INSERTIONS - std::cerr << " inserted new vertex " << IO::oformat(v, With_point_tag{}) << std::endl; + std::cerr << " inserted new vertex " << IO::oformat(v, with_point_tag) << std::endl; #endif // CGAL_MESH_2_DEBUG_INSERTIONS return v; } @@ -626,8 +630,8 @@ class Refine_edges_base : auto p = midpoint(va->point(), vb->point()); #ifdef CGAL_MESH_2_DEBUG_REFINEMENT_POINTS - std::cerr << "refinement_point_impl(Edge: " << IO::oformat(va, With_point_tag{}) << ", " - << IO::oformat(vb, With_point_tag{}) << ") = "; + std::cerr << "refinement_point_impl(Edge: " << IO::oformat(va, with_point_tag) << ", " + << IO::oformat(vb, with_point_tag) << ") = "; std::cerr << p << '\n'; #endif // CGAL_MESH_2_DEBUG_REFINEMENT_POINTS return maybe_snap_to_existing_vertex(edge, p); @@ -686,7 +690,7 @@ class Refine_edges_base : { #ifdef CGAL_MESH_2_DEBUG_REFINEMENT_POINTS std::cerr << "return point of existing vertex " - << IO::oformat(closest_encroaching_vertex->vertex, With_point_tag{}) << std::endl; + << IO::oformat(closest_encroaching_vertex->vertex, with_point_tag) << std::endl; #endif // CGAL_MESH_2_DEBUG_REFINEMENT_POINTS p = closest_encroaching_vertex->vertex->point(); return p; @@ -810,8 +814,8 @@ class Refine_edges_base : const Vertex_handle& vb = e.first->vertex(tr.ccw(e.second)); #if CGAL_MESH_2_DEBUG_BAD_EDGES std::cerr << " add_constrained_edge_to_be_conformed(" - << IO::oformat(va, With_point_tag{}) << ", " - << IO::oformat(vb, With_point_tag{}) << ")\n"; + << IO::oformat(va, with_point_tag) << ", " + << IO::oformat(vb, with_point_tag) << ")\n"; #endif this->add_bad_element(std::make_pair(va, vb)); // see the Container // base class @@ -823,8 +827,8 @@ class Refine_edges_base : { #if CGAL_MESH_2_DEBUG_BAD_EDGES std::cerr << " add_constrained_edge_to_be_conformed(" - << IO::oformat(va, With_point_tag{}) << ", " - << IO::oformat(vb, With_point_tag{}) << ")\n"; + << IO::oformat(va, with_point_tag) << ", " + << IO::oformat(vb, with_point_tag) << ")\n"; #endif this->add_bad_element(std::make_pair(va, vb)); // see the Container // base class diff --git a/Mesh_2/include/CGAL/Mesh_2/Refine_edges_with_clusters.h b/Mesh_2/include/CGAL/Mesh_2/Refine_edges_with_clusters.h index 755b7b0a849b..ef5f8fd12c3a 100644 --- a/Mesh_2/include/CGAL/Mesh_2/Refine_edges_with_clusters.h +++ b/Mesh_2/include/CGAL/Mesh_2/Refine_edges_with_clusters.h @@ -73,6 +73,7 @@ class Refine_edges_base_with_clusters : mutable bool cluster_splitted; Cluster ca, cb; clusters_iterator ca_it, cb_it; + With_point_tag wpt; public: using Super::triangulation_ref_impl; @@ -80,7 +81,7 @@ class Refine_edges_base_with_clusters : /** \name CONSTRUCTORS */ Refine_edges_base_with_clusters(Tr& tr_, Clusters& c_) - : Super(tr_), clusters(c_) + : Super(tr_), clusters(c_), wpt{{-1}, &tr_} { } @@ -98,8 +99,8 @@ class Refine_edges_base_with_clusters : auto display_return_point = [&](const Point& p) { #ifdef CGAL_MESH_2_DEBUG_REFINEMENT_POINTS std::cerr << "Refine_edges_with_clusters::refinement_point_impl(Edge: (" - << IO::oformat(this->va, With_point_tag{}) << ", " - << IO::oformat(this->vb, With_point_tag{}) << ") = " + << IO::oformat(this->va, wpt) << ", " + << IO::oformat(this->vb, wpt) << ") = " << p << '\n'; #endif // CGAL_MESH_2_DEBUG_REFINEMENT_POINTS return p; @@ -117,8 +118,8 @@ class Refine_edges_base_with_clusters : va_has_a_cluster = true; vb_has_a_cluster = true; #ifdef CGAL_MESH_2_DEBUG_CLUSTERS - std::cerr << "midpoint(" << IO::oformat(this->va, With_point_tag{}) - << " , " << IO::oformat(this->vb, With_point_tag{}) << ")\n"; + std::cerr << "midpoint(" << IO::oformat(this->va, wpt) + << " , " << IO::oformat(this->vb, wpt) << ")\n"; #endif // CGAL_MESH_2_DEBUG_CLUSTERS return display_return_point( this->maybe_snap_to_existing_vertex(edge, midpoint(this->va->point(), this->vb->point()))); @@ -138,8 +139,8 @@ class Refine_edges_base_with_clusters : // no cluster #ifdef CGAL_MESH_2_DEBUG_CLUSTERS - std::cerr << "midpoint(" << IO::oformat(this->va, With_point_tag{}) - << " , " << IO::oformat(this->vb, With_point_tag{}) << ")\n"; + std::cerr << "midpoint(" << IO::oformat(this->va, wpt) + << " , " << IO::oformat(this->vb, wpt) << ")\n"; #endif // CGAL_MESH_2_DEBUG_CLUSTERS return Super::refinement_point_impl(edge); @@ -272,8 +273,9 @@ class Refine_edges_base_with_clusters : const Point& b = vb->point(); #ifdef CGAL_MESH_2_DEBUG_CLUSTERS - std::cerr << "split_cluster_point(" << IO::oformat(va, With_point_tag{}) - << " , " << IO::oformat(vb, With_point_tag{}) << ")\n" + With_point_tag wpt{{-1}, &this->tr}; + std::cerr << "split_cluster_point(" << IO::oformat(va, wpt) + << " , " << IO::oformat(vb, wpt) << ")\n" << " reduced: " << c.is_reduced() << "\nresult: "; #endif // CGAL_MESH_2_DEBUG_CLUSTERS if( c.is_reduced() ) { diff --git a/Mesh_2/include/CGAL/Mesh_2/Refine_faces.h b/Mesh_2/include/CGAL/Mesh_2/Refine_faces.h index a71fe51f5b34..054c44e38bb9 100644 --- a/Mesh_2/include/CGAL/Mesh_2/Refine_faces.h +++ b/Mesh_2/include/CGAL/Mesh_2/Refine_faces.h @@ -13,6 +13,7 @@ #ifndef CGAL_MESH_2_REFINE_FACES_H #define CGAL_MESH_2_REFINE_FACES_H +#include #include #include @@ -106,12 +107,13 @@ class Refine_faces_base : Bad_faces bad_faces; Mesh_2::Face_badness current_badness; + With_point_tag with_point_tag; public: /** \name CONSTRUCTORS */ Refine_faces_base(Tr& t, Criteria& criteria_, Previous& prev) - : Triangulation_traits(t), criteria(criteria_), previous(prev) + : Triangulation_traits(t), criteria(criteria_), previous(prev), with_point_tag{{-1}, &t} { } @@ -194,9 +196,9 @@ class Refine_faces_base : auto v1 = f->vertex(1); auto v2 = f->vertex(2); std::cerr << "refinement_point_impl(Face: " - << IO::oformat(v0, With_point_tag{}) << ", " - << IO::oformat(v1, With_point_tag{}) << ", " - << IO::oformat(v2, With_point_tag{}) << ") = " + << IO::oformat(v0, with_point_tag) << ", " + << IO::oformat(v1, with_point_tag) << ", " + << IO::oformat(v2, with_point_tag) << ") = " << p << '\n'; #endif // CGAL_MESH_2_DEBUG_BAD_FACES return p; @@ -241,7 +243,7 @@ class Refine_faces_base : zone.faces.begin(), zone.faces.end()); #ifdef CGAL_MESH_2_DEBUG_INSERTIONS - std::cerr << " inserted new vertex " << IO::oformat(v, With_point_tag{}) << std::endl; + std::cerr << " inserted new vertex " << IO::oformat(v, with_point_tag) << std::endl; #endif // CGAL_MESH_2_DEBUG_INSERTIONS return v; } @@ -322,9 +324,9 @@ push_in_bad_faces(Face_handle fh, const Quality& q) { #ifdef CGAL_MESH_2_DEBUG_BAD_FACES std::cerr << "push_in_bad_faces(" - << IO::oformat(fh->vertex(0), With_point_tag{}) << ", " - << IO::oformat(fh->vertex(1), With_point_tag{}) << ", " - << IO::oformat(fh->vertex(2), With_point_tag{}) << ")\n"; + << IO::oformat(fh->vertex(0), with_point_tag) << ", " + << IO::oformat(fh->vertex(1), with_point_tag) << ", " + << IO::oformat(fh->vertex(2), with_point_tag) << ")\n"; #endif // CGAL_MESH_2_DEBUG_BAD_FACES CGAL_assertion_code (typename Geom_traits::Orientation_2 orientation = @@ -344,9 +346,9 @@ remove_bad_face(Face_handle fh) { #ifdef CGAL_MESH_2_DEBUG_BAD_FACES std::cerr << "bad_faces.erase(" - << IO::oformat(fh->vertex(0), With_point_tag{}) << ", " - << IO::oformat(fh->vertex(1), With_point_tag{}) << ", " - << IO::oformat(fh->vertex(2), With_point_tag{}) << ")\n"; + << IO::oformat(fh->vertex(0), with_point_tag) << ", " + << IO::oformat(fh->vertex(1), with_point_tag) << ", " + << IO::oformat(fh->vertex(2), with_point_tag) << ")\n"; #endif // CGAL_MESH_2_DEBUG_BAD_FACES bad_faces.erase(fh); } @@ -372,9 +374,9 @@ compute_new_bad_faces(Vertex_handle v) { #ifdef CGAL_MESH_2_DEBUG_BAD_FACES std::cerr << "Skipping bad face with too small bbox: " - << IO::oformat(fc->vertex(0), With_point_tag{}) << ", " - << IO::oformat(fc->vertex(1), With_point_tag{}) << ", " - << IO::oformat(fc->vertex(2), With_point_tag{}) << "\n"; + << IO::oformat(fc->vertex(0), with_point_tag) << ", " + << IO::oformat(fc->vertex(1), with_point_tag) << ", " + << IO::oformat(fc->vertex(2), with_point_tag) << "\n"; std::cerr << "Quality: " << IO::oformat(q) << "\n"; #endif // CGAL_MESH_2_DEBUG_BAD_FACES continue; diff --git a/Mesh_2/test/Mesh_2/test_mesh_obj.cpp b/Mesh_2/test/Mesh_2/test_mesh_obj.cpp index ade586ac99f2..d7f5600be960 100644 --- a/Mesh_2/test/Mesh_2/test_mesh_obj.cpp +++ b/Mesh_2/test/Mesh_2/test_mesh_obj.cpp @@ -7,6 +7,7 @@ // #define CGAL_MESH_2_DEBUG_INSERTIONS 1 // #define CGAL_CDT_2_DEBUG_INTERSECTIONS 1 #include +#include #include #include #include @@ -92,6 +93,7 @@ static auto save_obj(const Obj_data& data, const std::filesystem::path& filename static int run_mesh(const Obj_data& data) { CDT cdt; + [[maybe_unused]] CGAL::With_point_tag with_point_tag{{-1}, &cdt}; double squared_distance = (std::numeric_limits::max)(); for(const std::vector& id_pl : data.polylines) { @@ -103,8 +105,8 @@ static int run_mesh(const Obj_data& data) va->info() = id_pl[pid - 1]; auto vb = cdt.insert(data.points[id_pl[pid]]); vb->info() = id_pl[pid]; - // std::cerr << "Inserting constraint between " << CGAL::IO::oformat(va, CGAL::With_point_tag{}) - // << " and " << CGAL::IO::oformat(vb, CGAL::With_point_tag{}) << "\n"; + // std::cerr << "Inserting constraint between " << CGAL::IO::oformat(va, with_point_tag) + // << " and " << CGAL::IO::oformat(vb, with_point_tag) << "\n"; cdt.insert_constraint(va, vb); } } @@ -119,8 +121,8 @@ static int run_mesh(const Obj_data& data) auto va = fc->vertex(cdt.cw(edge_index)); auto vb = fc->vertex(cdt.ccw(edge_index)); // std::cerr << "Add constrained edge on the convex hull: "; - // std::cerr << CGAL::IO::oformat(va, CGAL::With_point_tag{}) << " " - // << CGAL::IO::oformat(vb, CGAL::With_point_tag{}) << "\n"; + // std::cerr << CGAL::IO::oformat(va, with_point_tag) << " " + // << CGAL::IO::oformat(vb, with_point_tag) << "\n"; cdt.insert_constraint(va, vb); file_stream << "l " << (va->info() + 1 - points_ids_offsets[va->info()]) << " " << (vb->info() + 1 - points_ids_offsets[vb->info()]) << "\n"; diff --git a/Mesh_3/include/CGAL/Mesh_3/C3T3_helpers.h b/Mesh_3/include/CGAL/Mesh_3/C3T3_helpers.h index 4b900e0e6026..6ec21531b65c 100644 --- a/Mesh_3/include/CGAL/Mesh_3/C3T3_helpers.h +++ b/Mesh_3/include/CGAL/Mesh_3/C3T3_helpers.h @@ -2184,7 +2184,7 @@ class C3T3_helpers auto display_vertex(Vertex_handle v) const { return IO::oformat([&,v](std::ostream& os) -> std::ostream&{ - os << IO::oformat(v, With_point_tag{}); + os << IO::oformat(v, With_point_tag{{-1}, &tr_}); if (v != Vertex_handle()) { os << " (dimension: " << c3t3_.in_dimension(v) << ", index.index(): " << c3t3_.index(v).index() << ")"; 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 54f4994839da..9844012664e3 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 @@ -35,6 +35,7 @@ #include #include +#include #include #include #include @@ -532,6 +533,10 @@ class Protect_edges_sizing_field return c3t3_.triangulation().point(vh); } + auto with_point_tag() const { + return With_point_tag{{-1}, &tr()}; + } + protected: using get_curve_output_type = Mesh_domain_get_curves_output_type_t; @@ -727,7 +732,7 @@ class Protect_edges_sizing_field std::cerr << "Register corner #" << key.first << " on curve " << curve_index << " with position_on_curve=" << (position_on_curve - start_position) << "\n" - << " vp: " << IO::oformat(corner_vertices_.at(key.first), With_point_tag{}) << "\n"; + << " vp: " << IO::oformat(corner_vertices_.at(key.first), with_point_tag()) << "\n"; #endif [[maybe_unused]] auto [_, inserted] = corners_on_curves_.try_emplace(key, position_on_curve); CGAL_assertion(true == inserted); @@ -746,7 +751,7 @@ class Protect_edges_sizing_field std::invoke([&] { std::ostringstream ss; ss.copyfmt(std::cerr); - ss << "position_on_curve(v=" << IO::oformat(v, With_point_tag{}) + ss << "position_on_curve(v=" << IO::oformat(v, with_point_tag()) << " (corner index: " << corner_index << ", curve_index=" << curve_index << "): v is a corner but its position is not found!"; return ss.str(); @@ -1126,7 +1131,7 @@ smart_insert_point(const Bare_point& p, Weight w, int dim, const Index& index, #if CGAL_MESH_3_PROTECTION_DEBUG & 16 std::cerr << "Nearest power vertex of (" << p << ") is " - << IO::oformat(nearest_vh, With_point_tag{}) + << IO::oformat(nearest_vh, with_point_tag()) << "at distance: " << sq_d << std::endl; #endif @@ -1362,7 +1367,7 @@ insert_balls_on_edges() if(tr().is_vertex(cwp(p), vp)) { #if CGAL_MESH_3_PROTECTION_DEBUG & 128 - std::cerr << "vp: " << IO::oformat(vp, With_point_tag{}) << "\n"; + std::cerr << "vp: " << IO::oformat(vp, with_point_tag()) << "\n"; std::cerr << "vp.in_dimension(): " << vp->in_dimension() << "\n"; std::cerr << "p_dim: " << p_dim << "\n"; std::cerr << "p_index: " << IO::oformat(p_index) << "\n"; diff --git a/PMP_Boolean_operations/include/CGAL/Polygon_mesh_processing/kernel.h b/PMP_Boolean_operations/include/CGAL/Polygon_mesh_processing/kernel.h index 1962889af7e2..7fa52fa4fe55 100644 --- a/PMP_Boolean_operations/include/CGAL/Polygon_mesh_processing/kernel.h +++ b/PMP_Boolean_operations/include/CGAL/Polygon_mesh_processing/kernel.h @@ -21,8 +21,12 @@ #include #include +#include +#include +#include #include +#include #include #include @@ -75,7 +79,6 @@ kernel(const FaceRange& face_range, constexpr bool is_face_to_face_map = !parameters::is_default_parameter::value; auto f2f_map = choose_parameter(get_parameter(np_out, internal_np::face_to_face_map)); - using Point_3 = typename GT::Point_3; using EPoint_3 = typename EK::Point_3; using EVector_3 = typename EK::Vector_3; using Plane_3 = typename Three_point_cut_plane_traits::Plane_3; @@ -97,10 +100,10 @@ kernel(const FaceRange& face_range, // Build the starting cube KernelPointMap kvpm = get(CGAL::dynamic_vertex_property_t(), kernel); if(is_empty(kernel)) - make_hexahedron(bbox(pm), kernel, parameters::vertex_point_map(vpm_out)); + make_hexahedron(bbox(pm, parameters::vertex_point_map(vpm)), kernel, parameters::vertex_point_map(vpm_out)); for(vertex_descriptor v: vertices(kernel)) put(kvpm, v, to_exact(get(vpm_out, v))); - Bbox_3 bb3 = bbox(kernel); + Bbox_3 bb3 = bbox(kernel, parameters::vertex_point_map(kvpm)); vertex_descriptor start_vertex = *vertices(kernel).begin(); if constexpr(is_face_to_face_map) for(face_descriptor f: faces(kernel)) @@ -115,12 +118,12 @@ kernel(const FaceRange& face_range, std::function value; }; std::array entries {{ - {0, [](const EPoint_3& p){ return to_interval(p.x()).first; }, [](const Bbox_3& b){ return b.xmin(); }}, - {1, [](const EPoint_3& p){ return to_interval(p.x()).second; }, [](const Bbox_3& b){ return b.xmax(); }}, - {2, [](const EPoint_3& p){ return to_interval(p.y()).first; }, [](const Bbox_3& b){ return b.ymin(); }}, - {3, [](const EPoint_3& p){ return to_interval(p.y()).second; }, [](const Bbox_3& b){ return b.ymax(); }}, - {4, [](const EPoint_3& p){ return to_interval(p.z()).first; }, [](const Bbox_3& b){ return b.zmin(); }}, - {5, [](const EPoint_3& p){ return to_interval(p.z()).second; }, [](const Bbox_3& b){ return b.zmax(); }} + {0, [](const EPoint_3& p){ return approx(p).x().inf(); }, [](const Bbox_3& b){ return b.xmin(); }}, + {1, [](const EPoint_3& p){ return approx(p).x().sup(); }, [](const Bbox_3& b){ return b.xmax(); }}, + {2, [](const EPoint_3& p){ return approx(p).y().inf(); }, [](const Bbox_3& b){ return b.ymin(); }}, + {3, [](const EPoint_3& p){ return approx(p).y().sup(); }, [](const Bbox_3& b){ return b.ymax(); }}, + {4, [](const EPoint_3& p){ return approx(p).z().inf(); }, [](const Bbox_3& b){ return b.zmin(); }}, + {5, [](const EPoint_3& p){ return approx(p).z().sup(); }, [](const Bbox_3& b){ return b.zmax(); }} }}; for (const auto& e : entries){ @@ -228,31 +231,66 @@ kernel(const FaceRange& face_range, } // Get the centroid - EPoint_3 centroid(ORIGIN); - for(auto v: vertices(kernel)) - centroid += EVector_3(ORIGIN, get(kvpm, v)) / vertices(kernel).size(); + using AK = typename EK::Approximate_kernel; + using APoint_3 = typename AK::Point_3; - // Approximate the centroid - Point_3 double_centroid(to_double(centroid.x()), to_double(centroid.y()), to_double(centroid.z())); + auto to_approx = [&kernel, &kvpm](vertex_descriptor v) { return approx(get(kvpm, v)); }; + const auto& vrange = vertices(kernel); + + APoint_3 approx_centroid; + { + typename AK::FT::Protector p; + approx_centroid = CGAL::centroid(boost::make_transform_iterator(vrange.begin(), to_approx), + boost::make_transform_iterator(vrange.end(), to_approx)); + } + EPoint_3 double_centroid(to_double(approx_centroid.x()), + to_double(approx_centroid.y()), + to_double(approx_centroid.z())); // todo use converter // Check if the approximate_centroid is inside the kernel - bool is_valid = true; - for(face_descriptor f: faces(kernel)){ - halfedge_descriptor h = halfedge(f, kernel); - Plane_3 plane(get(kvpm,source(h, kernel)), - get(kvpm,target(h, kernel)), - get(kvpm,target(next(h, kernel), kernel))); - if(oriented_side(plane, centroid) != ON_NEGATIVE_SIDE){ - is_valid = false; - break; + auto is_inside_kernel = [&](const EPoint_3& p) { + bool inside = true; + for(face_descriptor f: faces(kernel)){ + halfedge_descriptor h = halfedge(f, kernel); + Plane_3 plane(get(kvpm,source(h, kernel)), + get(kvpm,target(h, kernel)), + get(kvpm,target(next(h, kernel), kernel))); + if(oriented_side(plane, p) != ON_NEGATIVE_SIDE){ + inside = false; + break; + } } + return inside; + }; + + if(is_inside_kernel(double_centroid)) { + *p = from_exact(double_centroid); } // If not, refine the centroid position - if(!is_valid) - centroid.exact(); + // Sum the vectors with a balanced reduction (to limit the depth of the lazy + // expression tree), and divide only once. + auto to_vector = [&kernel, &kvpm](vertex_descriptor v) { return EVector_3(ORIGIN, get(kvpm, v)); }; + const EVector_3 sum = CGAL::divide_and_conquer_reduce<2>(boost::make_transform_iterator(vrange.begin(), to_vector), + boost::make_transform_iterator(vrange.end(), to_vector), + EVector_3(NULL_VECTOR), std::plus()); + EPoint_3 centroid = ORIGIN + sum / vrange.size(); + + double_centroid = EPoint_3(to_double(centroid.x()), to_double(centroid.y()), to_double(centroid.z())); + + if(is_inside_kernel(double_centroid)){ + *p = from_exact(double_centroid); + return; + } + + centroid.exact(); + double_centroid = EPoint_3(to_double(centroid.x()), to_double(centroid.y()), to_double(centroid.z())); + + if(is_inside_kernel(double_centroid)){ + *p = from_exact(double_centroid); + return; + } - // Return the centroid *p = from_exact(centroid); return; } diff --git a/Periodic_2_triangulation_2/include/CGAL/Periodic_2_triangulation_2.h b/Periodic_2_triangulation_2/include/CGAL/Periodic_2_triangulation_2.h index e50c12ae6f7c..c808c8ab8baf 100644 --- a/Periodic_2_triangulation_2/include/CGAL/Periodic_2_triangulation_2.h +++ b/Periodic_2_triangulation_2/include/CGAL/Periodic_2_triangulation_2.h @@ -17,6 +17,7 @@ #include +#include #include #include #include @@ -42,7 +43,6 @@ #include #include -#include namespace CGAL { @@ -330,6 +330,22 @@ class Periodic_2_triangulation_2 //\} + std::array vertices(Face_handle f) const { + return _tds.vertices(f); + } + + std::array vertices(Face_handle f, int i) const { + return _tds.vertices(f, i); + } + + std::array vertices(Edge e) const { + return _tds.vertices(e); + } + + std::array vertices(Vertex_handle v) const { + return _tds.vertices(v); + } + /// \name Number of simplices //\{ /// Returns whether the triangulation is empty. diff --git a/SMDS_3/include/CGAL/Mesh_complex_3_in_triangulation_3.h b/SMDS_3/include/CGAL/Mesh_complex_3_in_triangulation_3.h index 087383422124..15e7ea474ff8 100644 --- a/SMDS_3/include/CGAL/Mesh_complex_3_in_triangulation_3.h +++ b/SMDS_3/include/CGAL/Mesh_complex_3_in_triangulation_3.h @@ -215,15 +215,15 @@ class Mesh_complex_3_in_triangulation_3 /*! Index type. */ - typedef typename Tr::Vertex::Index Index; + typedef typename Tr::Triangulation_data_structure::Vertex::Index Index; /*! Surface index type. */ - typedef typename Tr::Cell::Surface_patch_index Surface_patch_index; + typedef typename Tr::Triangulation_data_structure::Cell::Surface_patch_index Surface_patch_index; /*! Subdomain index type. */ - typedef typename Tr::Cell::Subdomain_index Subdomain_index; + typedef typename Tr::Triangulation_data_structure::Cell::Subdomain_index Subdomain_index; /*! Corner index type. */ diff --git a/SMDS_3/include/CGAL/SMDS_3/tet_soup_to_c3t3.h b/SMDS_3/include/CGAL/SMDS_3/tet_soup_to_c3t3.h index a6eea92dcd0a..150b8c183bd8 100644 --- a/SMDS_3/include/CGAL/SMDS_3/tet_soup_to_c3t3.h +++ b/SMDS_3/include/CGAL/SMDS_3/tet_soup_to_c3t3.h @@ -164,7 +164,6 @@ bool build_finite_cells(Tr& tr, { typedef typename Tr::Vertex_handle Vertex_handle; typedef typename Tr::Cell_handle Cell_handle; - typedef typename Tr::Cell::Surface_patch_index Surface_patch_index; bool success = true; @@ -196,7 +195,6 @@ bool build_finite_cells(Tr& tr, vs[j]->set_dimension(3); } - // this assertion also tests for degeneracy if (allow_negative_orientation) { if(!tr.may_have_badly_oriented_cells()) @@ -206,7 +204,7 @@ bool build_finite_cells(Tr& tr, tr.may_have_badly_oriented_cells(o != CGAL::POSITIVE); } } - else + else // this assertion also tests for degeneracy CGAL_assertion(orientation(cp(tr.point(vs[0])), cp(tr.point(vs[1])), cp(tr.point(vs[2])), cp(tr.point(vs[3]))) == POSITIVE); @@ -256,8 +254,8 @@ bool build_finite_cells(Tr& tr, it = border_facets.find(facet); if(it != border_facets.end()) c->set_surface_patch_index(j, it->second); - else - c->set_surface_patch_index(j, Surface_patch_index()); +// else +// c->set_surface_patch_index(j, Surface_patch_index()); } } } @@ -338,7 +336,7 @@ bool build_infinite_cells(Tr& tr, it->second.emplace_back(opp_c, 0); CGAL_assertion(it->second.size() == 2); - opp_c->set_surface_patch_index(0, c->surface_patch_index(i)); +// opp_c->set_surface_patch_index(0, c->surface_patch_index(i)); } #ifdef CGAL_TET_SOUP_TO_C3T3_DEBUG diff --git a/SMDS_3/include/CGAL/Simplicial_mesh_vertex_base_3.h b/SMDS_3/include/CGAL/Simplicial_mesh_vertex_base_3.h index 9238c4d9b710..0e7a1a481b7f 100644 --- a/SMDS_3/include/CGAL/Simplicial_mesh_vertex_base_3.h +++ b/SMDS_3/include/CGAL/Simplicial_mesh_vertex_base_3.h @@ -39,6 +39,8 @@ #include #include #include +#include +#include namespace CGAL { @@ -113,7 +115,10 @@ private : using Curve_index = CurveIndex; using Corner_index = CornerIndex; - using Index = Variant_with_no_duplicate_t; + using Index_variant = Variant_with_no_duplicate_t; + using Index = std::conditional_t == 1, + std::variant_alternative_t<0, Index_variant>, + Index_variant>; using FT = typename Gt::FT; diff --git a/STL_Extension/include/CGAL/Compact_container.h b/STL_Extension/include/CGAL/Compact_container.h index 1beb7796c328..259afa286148 100644 --- a/STL_Extension/include/CGAL/Compact_container.h +++ b/STL_Extension/include/CGAL/Compact_container.h @@ -1220,17 +1220,18 @@ namespace handle { } // namespace internal -template -class Output_rep > { +template +class Output_rep, Format_tag> { protected: using CC_iterator = CGAL::internal::CC_iterator; using Compact_container = typename CC_iterator::CC; using Time_stamper = typename Compact_container::Time_stamper; CC_iterator it; + CGAL_NO_UNIQUE_ADDRESS Format_tag format; public: - Output_rep( const CC_iterator it) : it(it) {} + Output_rep(const CC_iterator& it, Format_tag format = {}) : it(it), format(std::move(format)) {} std::ostream& operator()( std::ostream& out) const { - return (out << Time_stamper::display_id(it.operator->())); + return (out << IO::oformat(Time_stamper::display_id(it.operator->()), format)); } }; @@ -1240,10 +1241,19 @@ struct With_offset_tag { // from 0 to number_of_vertices-1. }; +template +inline auto with_offset(T&& v) { + return IO::oformat(std::forward(v), With_offset_tag{}); +} + +template struct With_point_tag : public With_offset_tag { + Tr* tr; }; -struct With_point_and_info_tag : public With_point_tag {}; +template +struct With_point_and_info_tag : public With_point_tag { +}; template struct Output_rep, With_offset_tag> @@ -1257,7 +1267,7 @@ struct Output_rep, With_offset_tag> using Base = Output_rep; using Base::Base; - Output_rep(const CC_iterator it, With_offset_tag tag = {}) + Output_rep(const CC_iterator& it, With_offset_tag tag = {}) : Base(it), offset(tag.offset) {} std::ostream& operator()(std::ostream& out) const { @@ -1266,8 +1276,8 @@ struct Output_rep, With_offset_tag> } }; -template -struct Output_rep, With_point_tag> +template +struct Output_rep, With_point_tag> : public Output_rep, With_offset_tag> { using CC_iterator = CGAL::internal::CC_iterator; @@ -1276,15 +1286,17 @@ struct Output_rep, With_point_tag> using Base::Base; - Output_rep(const CC_iterator it, With_point_tag tag = {}) - : Base(it, tag) {} + With_point_tag tag; + + Output_rep(const CC_iterator& it, With_point_tag tag = {}) + : Base(it, tag), tag(tag) {} std::ostream& operator()(std::ostream& out) const { this->Base::operator()(out); if(this->it.operator->() != nullptr) { if(Time_stamper::time_stamp(this->it.operator->()) == 0) return out << "= infinite_vertex()"; - return out << "= " << this->it->point(); + return out << "= " << tag.tr->point(this->it); } else return out; diff --git a/STL_Extension/include/CGAL/algorithm.h b/STL_Extension/include/CGAL/algorithm.h index 8cabe0a3f4b7..881d5e164611 100644 --- a/STL_Extension/include/CGAL/algorithm.h +++ b/STL_Extension/include/CGAL/algorithm.h @@ -24,8 +24,11 @@ #include #include #include +#include #include #include +#include +#include #include #include @@ -386,6 +389,30 @@ OutputIterator transform_n( InputIterator first, Size n, OutputIterator result, } return result; } + + +// Explicit divide-and-conquer reduction algorithm +template +T divide_and_conquer_reduce(RandomIt first, RandomIt last, T init, BinaryOp op) { + auto distance = std::distance(first, last); + + // Base case / Threshold: if the sub-range is small enough, avoid further splitting + if (distance <= Threshold) { + return std::accumulate(first, last, init, op); + } + + // Divide phase + RandomIt mid = std::next(first, distance / 2); + + // Conquer phase (recursively evaluate left and right halves) + // Note: In a real parallel setting, you would spawn threads or tasks for these halves + // `init` is used for both halves, so it must be the identity element of `op` + T left_res = divide_and_conquer_reduce(first, mid, init, op); + T right_res = divide_and_conquer_reduce(mid, last, init, op); + + // Combine phase + return op(left_res, right_res); +} } //namespace CGAL #endif // CGAL_ALGORITHM_H diff --git a/Stream_support/include/CGAL/IO/Indenting_ostream.h b/Stream_support/include/CGAL/IO/Indenting_ostream.h index bff5f78a9858..1de0ba8c8c95 100644 --- a/Stream_support/include/CGAL/IO/Indenting_ostream.h +++ b/Stream_support/include/CGAL/IO/Indenting_ostream.h @@ -22,6 +22,9 @@ #include #include +#include +#include +#include #include #include #include @@ -234,6 +237,10 @@ class Basic_indenting_stream_guard , original_buf_(stream.rdbuf()) , indenting_buf_(*original_buf_, indent_string) { + if(indent_string.empty()) { + // No indentation, just use the original buffer + return; + } if(auto old_buf = dynamic_cast(original_buf_)) { original_indent_string_ = old_buf->indent_string(); old_buf->set_indent_string(original_indent_string_ + indent_string); @@ -300,11 +307,13 @@ using Indenting_wstream_guard = Basic_indenting_stream_guard; * This helper function creates `Basic_indenting_stream_guard` objects for * multiple streams at once. All streams will use the same indentation settings, * and their original streambufs will be automatically restored when the guards - * go out of scope. The guards are returned in a tuple. + * go out of scope. The guards are returned in a tuple. If no stream is + * provided, guards are created for `std::cout`, `std::cerr`, and `std::clog`. * * \tparam Streams The stream types (deduced from arguments) * \param spaces_per_level Number of spaces per indentation level - * \param streams The streams to apply indentation to + * \param streams The streams to apply indentation to. If omitted, the helper + * creates guards for `std::cout`, `std::cerr`, and `std::clog`. * \return A tuple of Basic_indenting_stream_guard objects * * \sa Basic_indenting_stream_guard @@ -316,10 +325,20 @@ using Indenting_wstream_guard = Basic_indenting_stream_guard; * std::cerr << "Indented error\n"; * \endcode */ + /// @{ template auto make_indenting_guards(int spaces_per_level, Streams&... streams) { return std::make_tuple(Basic_indenting_stream_guard(streams, spaces_per_level)...); } +inline auto make_indenting_guards(int spaces_per_level) { + return make_indenting_guards(spaces_per_level, std::cout, std::cerr, std::clog); +} +/// @} + +template +auto make_indenting_guard(Stream& stream, const std::string& indent_string) { + return Basic_indenting_stream_guard(stream, indent_string); +} /** * \ingroup PkgStreamSupportRef @@ -327,19 +346,30 @@ auto make_indenting_guards(int spaces_per_level, Streams&... streams) { * \brief creates indenting guards for multiple streams with a custom indent string. * * This overload allows specifying a custom indentation string instead of a number - * of spaces. + * of spaces. If no stream is provided, guards are created for `std::cout`, + * `std::cerr`, and `std::clog`. * * \tparam Streams The stream types (deduced from arguments) * \param indent_string The indentation string to use - * \param streams The streams to apply indentation to + * \param streams The streams to apply indentation to. If omitted, the helper + * creates guards for `std::cout`, `std::cerr`, and `std::clog`. * \return A tuple of Basic_indenting_stream_guard objects * * \sa Basic_indenting_stream_guard */ + /// @{ template auto make_indenting_guards(const std::string& indent_string, Streams&... streams) { - return std::make_tuple(Basic_indenting_stream_guard(streams, indent_string)...); + if constexpr(sizeof...(Streams) == 0) { + return make_indenting_guards(indent_string, std::cout, std::cerr, std::clog); + } else { + return std::make_tuple(make_indenting_guard(streams, indent_string)...); + } +} +inline auto make_indenting_guards(const std::string& indent_string) { + return make_indenting_guards(indent_string, std::cout, std::cerr, std::clog); } +/// @} } // namespace IO } // namespace CGAL diff --git a/Stream_support/include/CGAL/IO/io.h b/Stream_support/include/CGAL/IO/io.h index 2f109e027c57..27bcfbc25134 100644 --- a/Stream_support/include/CGAL/IO/io.h +++ b/Stream_support/include/CGAL/IO/io.h @@ -18,6 +18,8 @@ #ifndef CGAL_IO_H #define CGAL_IO_H +#include + #include #include @@ -27,12 +29,15 @@ #include #include -#include #include +#include #include #include #include #include +#include +#include +#include #include namespace CGAL { @@ -82,6 +87,160 @@ is in `ASCII` mode. */ enum Mode {ASCII = 0, PRETTY, BINARY}; +/*! +\ingroup PkgStreamSupportRef + +returns the printing mode of the %IO stream `s`. + +\link PkgStreamSupportEnumRef `CGAL::IO::Mode`\endlink +\sa `CGAL::IO::set_mode()` +\sa `CGAL::IO::set_ascii_mode()` +\sa `CGAL::IO::set_binary_mode()` +\sa `CGAL::IO::set_pretty_mode()` +\sa `CGAL::IO::is_ascii()` +\sa `CGAL::IO::is_binary()` +\sa `CGAL::IO::is_pretty()` +*/ +inline Mode get_mode(std::ios& s) +{ + return static_cast(s.iword(Static::get_mode())); +} + +/*! +\ingroup PkgStreamSupportRef + +sets the mode of the %IO stream `s` to be the `ASCII` mode. +Returns the previous mode of `s`. + +\link PkgStreamSupportEnumRef `CGAL::IO::Mode`\endlink +\sa `CGAL::IO::set_mode()` +\sa `CGAL::IO::set_binary_mode()` +\sa `CGAL::IO::set_pretty_mode()` +\sa `CGAL::IO::get_mode()` +\sa `CGAL::IO::is_ascii()` +\sa `CGAL::IO::is_binary()` +\sa `CGAL::IO::is_pretty()` +*/ +inline Mode set_ascii_mode(std::ios& s) +{ + Mode m = get_mode(s); + s.iword(Static::get_mode()) = ASCII; + return m; +} + +/*! +\ingroup PkgStreamSupportRef + +sets the mode of the %IO stream `s` to be the `BINARY` mode. +Returns the previous mode of `s`. + +\link PkgStreamSupportEnumRef `CGAL::IO::Mode`\endlink +\sa `CGAL::IO::set_mode()` +\sa `CGAL::IO::set_ascii_mode()` +\sa `CGAL::IO::set_pretty_mode()` +\sa `CGAL::IO::get_mode()` +\sa `CGAL::IO::is_ascii()` +\sa `CGAL::IO::is_binary()` +\sa `CGAL::IO::is_pretty()` +*/ +inline Mode set_binary_mode(std::ios& s) +{ + Mode m = get_mode(s); + s.iword(Static::get_mode()) = BINARY; + return m; +} + +/*! +\ingroup PkgStreamSupportRef + +sets the mode of the %IO stream `s` to be the `PRETTY` mode. +Returns the previous mode of `s`. + +\link PkgStreamSupportEnumRef `CGAL::IO::Mode`\endlink +\sa `CGAL::IO::set_mode()` +\sa `CGAL::IO::set_ascii_mode()` +\sa `CGAL::IO::set_binary_mode()` +\sa `CGAL::IO::get_mode()` +\sa `CGAL::IO::is_ascii()` +\sa `CGAL::IO::is_binary()` +\sa `CGAL::IO::is_pretty()` +*/ +inline Mode set_pretty_mode(std::ios& s) +{ + Mode m = get_mode(s); + s.iword(Static::get_mode()) = PRETTY; + return m; +} + +/*! +\ingroup PkgStreamSupportRef + +sets the printing mode of the %IO stream `s`. + +\link PkgStreamSupportEnumRef `CGAL::IO::Mode`\endlink +\sa `CGAL::IO::set_ascii_mode()` +\sa `CGAL::IO::set_binary_mode()` +\sa `CGAL::IO::set_pretty_mode()` +\sa `CGAL::IO::get_mode()` +\sa `CGAL::IO::is_ascii()` +\sa `CGAL::IO::is_binary()` +\sa `CGAL::IO::is_pretty()` +*/ +inline Mode set_mode(std::ios& s, Mode m) +{ + Mode old = get_mode(s); + s.iword(Static::get_mode()) = m; + return old; +} + +/*! +\ingroup PkgStreamSupportRef + +checks if the %IO stream `s` is in `PRETTY` mode. + +\link PkgStreamSupportEnumRef `CGAL::IO::Mode`\endlink +\sa `CGAL::IO::set_mode()` +\sa `CGAL::IO::set_ascii_mode()` +\sa `CGAL::IO::set_binary_mode()` +\sa `CGAL::IO::set_pretty_mode()` +\sa `CGAL::IO::get_mode()` +\sa `CGAL::IO::is_ascii()` +\sa `CGAL::IO::is_binary()` +*/ +inline bool is_pretty(std::ios& s) { return s.iword(Static::get_mode()) == PRETTY; } + +/*! +\ingroup PkgStreamSupportRef + +checks if the %IO stream `s` is in `ASCII` mode. + +\link PkgStreamSupportEnumRef `CGAL::IO::Mode`\endlink +\sa `CGAL::IO::set_mode()` +\sa `CGAL::IO::set_ascii_mode()` +\sa `CGAL::IO::set_binary_mode()` +\sa `CGAL::IO::set_pretty_mode()` +\sa `CGAL::IO::get_mode()` +\sa `CGAL::IO::is_binary()` +\sa `CGAL::IO::is_pretty()` +*/ +inline bool is_ascii(std::ios& s) { return s.iword(Static::get_mode()) == ASCII; } + +/*! +\ingroup PkgStreamSupportRef + +checks if the %IO stream `s` is in `BINARY` mode. + +\link PkgStreamSupportEnumRef `CGAL::IO::Mode`\endlink +\sa `CGAL::IO::set_mode()` +\sa `CGAL::IO::set_ascii_mode()` +\sa `CGAL::IO::set_binary_mode()` +\sa `CGAL::IO::set_pretty_mode()` +\sa `CGAL::IO::get_mode()` +\sa `CGAL::IO::is_ascii()` +\sa `CGAL::IO::is_pretty()` +*/ +inline bool is_binary(std::ios& s) { return s.iword(Static::get_mode()) == BINARY; } + } // namespace IO #ifdef DOXYGEN_RUNNING @@ -175,7 +334,7 @@ verify that a given type can be used with `oformat()`. Its value has to be for a type, the class template `Output_rep` defines `is_specialized` to the default value `false`. */ -template +template class Output_rep : public IO_rep_is_not_specialized { @@ -188,17 +347,46 @@ class Output_rep std::ostream& operator()( std::ostream& os) const { return (os << t); } }; +namespace IO { +/*! +\ingroup PkgStreamSupportRef + +Convenience function to construct an output representation (`Output_rep`) for type `T`. + +Generic IO for type `T`. +*/ +template +Output_rep oformat(const T& t) { return Output_rep(t); } + +/*! +\ingroup PkgStreamSupportRef + +Convenience function to construct an output representation (`Output_rep`) for type `T`. + +Generic IO for type `T` with formatting tag. +*/ +template +Output_rep oformat( const T& t, F format) { + if constexpr (std::is_constructible_v, const T&, F&&>) + return Output_rep(t, std::move(format)); + else + return Output_rep(t); +} + +} // namespace IO + template class Output_rep, F> { const std::optional& t; + CGAL_NO_UNIQUE_ADDRESS F format; public: - Output_rep( const std::optional& tt) : t(tt) {} + Output_rep( const std::optional& tt, F format = {}) : t(tt), format(std::move(format)) {} std::ostream& operator()( std::ostream& os) const { if (t==std::nullopt) return (os << "--"); - return (os << t.value()); + return (os << IO::oformat(t.value(), format)); } }; @@ -206,14 +394,45 @@ template class Output_rep, F> { const std::variant& t; + CGAL_NO_UNIQUE_ADDRESS F format; public: - Output_rep( const std::variant& tt) : t(tt) {} + Output_rep( const std::variant& tt, F format = {}) : t(tt), format(std::move(format)) {} std::ostream& operator()( std::ostream& os) const { - std::visit([&os](auto&& v) { os << v; }, t); + std::visit([&os, this](auto&& v) { os << IO::oformat(v, format); }, t); + return os; + } +}; + +template +class Output_rep::type>> + : public IO_rep_is_specialized +{ + const T& value; + CGAL_NO_UNIQUE_ADDRESS F format; + +public: + Output_rep( const T& value, F format = {}) : value(value), format(std::move(format)) {} + + std::ostream& operator()( std::ostream& os) const { + const auto mode = IO::get_mode(os); + const bool is_pretty = (mode != IO::BINARY && std::is_same_v) || mode == IO::PRETTY; + const char* sep = (mode == IO::BINARY) ? "" : (is_pretty ? ", " : " "); + if(is_pretty) os << "("; + print_tuple_impl(os, sep, std::make_index_sequence::value>{}); + if(is_pretty) os << ")"; + return os; + } + +protected: + template + std::ostream& print_tuple_impl(std::ostream& os, const char* sep, std::index_sequence) const + { + ((os << (I == 0 ? "" : sep) << IO::oformat(std::get(value), format)), ...); return os; } + }; template @@ -241,35 +460,6 @@ class Output_rep template std::ostream& operator<<( std::ostream& os, Output_rep rep) { return rep(os); } -namespace IO { - -/*! -\ingroup PkgStreamSupportRef - -Convenience function to construct an output representation (`Output_rep`) for type `T`. - -Generic IO for type `T`. -*/ -template -Output_rep oformat(const T& t) { return Output_rep(t); } - -/*! -\ingroup PkgStreamSupportRef - -Convenience function to construct an output representation (`Output_rep`) for type `T`. - -Generic IO for type `T` with formatting tag. -*/ -template -Output_rep oformat( const T& t, F format) { - if constexpr (std::is_constructible_v, const T&, F>) - return Output_rep(t, format); - else - return Output_rep(t); -} - -} // namespace IO - /*! \ingroup PkgStreamSupportRef @@ -289,6 +479,29 @@ class Input_rep std::istream& operator()( std::istream& is) const { return (is >> t); } }; +/*! \relates Input_rep + \brief stream input to the \c Input_rep calls its \c operator(). + +\brief \cgal defines input operators for classes that are derived +from the class `std::istream`. This allows to read from input streams +as `std::cin`, as well as from `std::istringstream` and `std::ifstream`. +The input operator is defined for all classes in the \cgal `Kernel`. +*/ +template +std::istream& operator>>( std::istream& is, Input_rep rep) { return rep(is); } + +namespace IO { + +/*! +\ingroup PkgStreamSupportRef + +The definition of this function is completely symmetric to `oformat()`. +*/ +template +Input_rep iformat( T& t) { return Input_rep(t); } + +} // namespace IO + template class Input_rep> { @@ -301,7 +514,7 @@ class Input_rep> //! perform the input, calls \c operator\>\> by default. std::istream& operator()( std::istream& is) const { T v; - if(is >> v) t = v; + if(is >> IO::iformat(v)) t = v; return is; } }; @@ -451,29 +664,6 @@ class Input_rep }; #endif -/*! \relates Input_rep - \brief stream input to the \c Input_rep calls its \c operator(). - -\brief \cgal defines input operators for classes that are derived -from the class `std::istream`. This allows to read from input streams -as `std::cin`, as well as from `std::istringstream` and `std::ifstream`. -The input operator is defined for all classes in the \cgal `Kernel`. -*/ -template -std::istream& operator>>( std::istream& is, Input_rep rep) { return rep(is); } - -namespace IO { - -/*! -\ingroup PkgStreamSupportRef - -The definition of this function is completely symmetric to `oformat()`. -*/ -template -Input_rep iformat( T& t) { return Input_rep(t); } - -} // namespace IO - template class Benchmark_rep { @@ -500,160 +690,6 @@ Benchmark_rep bmformat( const T& t) { return Benchmark_rep(t); } template Benchmark_rep bmformat( const T& t, F) { return Benchmark_rep(t); } -/*! -\ingroup PkgStreamSupportRef - -returns the printing mode of the %IO stream `s`. - -\link PkgStreamSupportEnumRef `CGAL::IO::Mode`\endlink -\sa `CGAL::IO::set_mode()` -\sa `CGAL::IO::set_ascii_mode()` -\sa `CGAL::IO::set_binary_mode()` -\sa `CGAL::IO::set_pretty_mode()` -\sa `CGAL::IO::is_ascii()` -\sa `CGAL::IO::is_binary()` -\sa `CGAL::IO::is_pretty()` -*/ -inline Mode get_mode(std::ios& s) -{ - return static_cast(s.iword(Static::get_mode())); -} - -/*! -\ingroup PkgStreamSupportRef - -sets the mode of the %IO stream `s` to be the `ASCII` mode. -Returns the previous mode of `s`. - -\link PkgStreamSupportEnumRef `CGAL::IO::Mode`\endlink -\sa `CGAL::IO::set_mode()` -\sa `CGAL::IO::set_binary_mode()` -\sa `CGAL::IO::set_pretty_mode()` -\sa `CGAL::IO::get_mode()` -\sa `CGAL::IO::is_ascii()` -\sa `CGAL::IO::is_binary()` -\sa `CGAL::IO::is_pretty()` -*/ -inline Mode set_ascii_mode(std::ios& s) -{ - Mode m = get_mode(s); - s.iword(Static::get_mode()) = ASCII; - return m; -} - -/*! -\ingroup PkgStreamSupportRef - -sets the mode of the %IO stream `s` to be the `BINARY` mode. -Returns the previous mode of `s`. - -\link PkgStreamSupportEnumRef `CGAL::IO::Mode`\endlink -\sa `CGAL::IO::set_mode()` -\sa `CGAL::IO::set_ascii_mode()` -\sa `CGAL::IO::set_pretty_mode()` -\sa `CGAL::IO::get_mode()` -\sa `CGAL::IO::is_ascii()` -\sa `CGAL::IO::is_binary()` -\sa `CGAL::IO::is_pretty()` -*/ -inline Mode set_binary_mode(std::ios& s) -{ - Mode m = get_mode(s); - s.iword(Static::get_mode()) = BINARY; - return m; -} - -/*! -\ingroup PkgStreamSupportRef - -sets the mode of the %IO stream `s` to be the `PRETTY` mode. -Returns the previous mode of `s`. - -\link PkgStreamSupportEnumRef `CGAL::IO::Mode`\endlink -\sa `CGAL::IO::set_mode()` -\sa `CGAL::IO::set_ascii_mode()` -\sa `CGAL::IO::set_binary_mode()` -\sa `CGAL::IO::get_mode()` -\sa `CGAL::IO::is_ascii()` -\sa `CGAL::IO::is_binary()` -\sa `CGAL::IO::is_pretty()` -*/ -inline Mode set_pretty_mode(std::ios& s) -{ - Mode m = get_mode(s); - s.iword(Static::get_mode()) = PRETTY; - return m; -} - -/*! -\ingroup PkgStreamSupportRef - -sets the printing mode of the %IO stream `s`. - -\link PkgStreamSupportEnumRef `CGAL::IO::Mode`\endlink -\sa `CGAL::IO::set_ascii_mode()` -\sa `CGAL::IO::set_binary_mode()` -\sa `CGAL::IO::set_pretty_mode()` -\sa `CGAL::IO::get_mode()` -\sa `CGAL::IO::is_ascii()` -\sa `CGAL::IO::is_binary()` -\sa `CGAL::IO::is_pretty()` -*/ -inline Mode set_mode(std::ios& s, Mode m) -{ - Mode old = get_mode(s); - s.iword(Static::get_mode()) = m; - return old; -} - -/*! -\ingroup PkgStreamSupportRef - -checks if the %IO stream `s` is in `PRETTY` mode. - -\link PkgStreamSupportEnumRef `CGAL::IO::Mode`\endlink -\sa `CGAL::IO::set_mode()` -\sa `CGAL::IO::set_ascii_mode()` -\sa `CGAL::IO::set_binary_mode()` -\sa `CGAL::IO::set_pretty_mode()` -\sa `CGAL::IO::get_mode()` -\sa `CGAL::IO::is_ascii()` -\sa `CGAL::IO::is_binary()` -*/ -inline bool is_pretty(std::ios& s) { return s.iword(Static::get_mode()) == PRETTY; } - -/*! -\ingroup PkgStreamSupportRef - -checks if the %IO stream `s` is in `ASCII` mode. - -\link PkgStreamSupportEnumRef `CGAL::IO::Mode`\endlink -\sa `CGAL::IO::set_mode()` -\sa `CGAL::IO::set_ascii_mode()` -\sa `CGAL::IO::set_binary_mode()` -\sa `CGAL::IO::set_pretty_mode()` -\sa `CGAL::IO::get_mode()` -\sa `CGAL::IO::is_binary()` -\sa `CGAL::IO::is_pretty()` -*/ -inline bool is_ascii(std::ios& s) { return s.iword(Static::get_mode()) == ASCII; } - -/*! -\ingroup PkgStreamSupportRef - -checks if the %IO stream `s` is in `BINARY` mode. - -\link PkgStreamSupportEnumRef `CGAL::IO::Mode`\endlink -\sa `CGAL::IO::set_mode()` -\sa `CGAL::IO::set_ascii_mode()` -\sa `CGAL::IO::set_binary_mode()` -\sa `CGAL::IO::set_pretty_mode()` -\sa `CGAL::IO::get_mode()` -\sa `CGAL::IO::is_ascii()` -\sa `CGAL::IO::is_pretty()` -*/ -inline bool is_binary(std::ios& s) { return s.iword(Static::get_mode()) == BINARY; } - } // namespace IO template < class T > @@ -735,10 +771,10 @@ inline std::istream &operator>>(std::istream &is, Color& col) { case ASCII : is >> ir >> ig >> ib >> ia; - r = (unsigned char)ir; - g = (unsigned char)ig; - b = (unsigned char)ib; - a = (unsigned char)ia; + r = static_cast(ir); + g = static_cast(ig); + b = static_cast(ib); + a = static_cast(ia); break; case BINARY : read(is, r); diff --git a/Stream_support/include/CGAL/IO/io_tags.h b/Stream_support/include/CGAL/IO/io_tags.h index 2be296695313..3c794a9aa9cf 100644 --- a/Stream_support/include/CGAL/IO/io_tags.h +++ b/Stream_support/include/CGAL/IO/io_tags.h @@ -18,7 +18,6 @@ #ifndef CGAL_IO_TAGS_H #define CGAL_IO_TAGS_H -#include #include namespace CGAL { @@ -52,6 +51,7 @@ template<> struct Io_traits { typedef io_Read_write Io_tag; }; template<> struct Io_traits { typedef io_Read_write Io_tag; }; struct IO_manip_tag{}; +struct Pretty_tag{}; } //namespace CGAL diff --git a/TDS_2/include/CGAL/Triangulation_data_structure_2.h b/TDS_2/include/CGAL/Triangulation_data_structure_2.h index 884c96ce73d8..e03e004953b7 100644 --- a/TDS_2/include/CGAL/Triangulation_data_structure_2.h +++ b/TDS_2/include/CGAL/Triangulation_data_structure_2.h @@ -17,6 +17,7 @@ #include +#include #include #include #include @@ -137,6 +138,22 @@ class Triangulation_data_structure_2 Vertex_range& vertices() const {return const_cast(this)->_vertices;} + std::array vertices(Face_handle f) const { + return {f->vertex(0), f->vertex(1), f->vertex(2)}; + } + + std::array vertices(Face_handle f, int i) const { + return {f->vertex(ccw(i)), f->vertex(cw(i))}; + } + + std::array vertices(Edge e) const { + return {e.first->vertex(ccw(e.second)), e.first->vertex(cw(e.second))}; + } + + std::array vertices(Vertex_handle v) const { + return {v}; + } + int dimension() const { return _dimension; } size_type number_of_vertices() const {return vertices().size();} size_type number_of_faces() const ; diff --git a/TDS_3/include/CGAL/Triangulation_utils_3.h b/TDS_3/include/CGAL/Triangulation_utils_3.h index 58299cf071aa..f9032e5eaf4d 100644 --- a/TDS_3/include/CGAL/Triangulation_utils_3.h +++ b/TDS_3/include/CGAL/Triangulation_utils_3.h @@ -54,10 +54,6 @@ const int Triangulation_utils_base_3::ccw_map[3] = {1, 2, 0}; template < class T > const int Triangulation_utils_base_3::cw_map[3] = {2, 0, 1}; -// We derive from Triangulation_cw_ccw_2 because we still use cw() and ccw() -// in the 2D part of the code. Ideally, this should go away when we reuse -// T2D entirely. - struct Triangulation_utils_3 : public Triangulation_utils_base_3<> { diff --git a/Tetrahedral_remeshing/include/CGAL/Adaptive_remeshing_sizing_field.h b/Tetrahedral_remeshing/include/CGAL/Adaptive_remeshing_sizing_field.h index b65a4f2d849c..ef3df8263780 100644 --- a/Tetrahedral_remeshing/include/CGAL/Adaptive_remeshing_sizing_field.h +++ b/Tetrahedral_remeshing/include/CGAL/Adaptive_remeshing_sizing_field.h @@ -33,7 +33,6 @@ #include #include -#include #ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG #include diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/collapse_short_edges.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/collapse_short_edges.h index 831e0e94eafe..5c89a4f06979 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/collapse_short_edges.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/collapse_short_edges.h @@ -434,39 +434,73 @@ Collapse_type get_collapse_type(const typename C3t3::Edge& edge, // return NO_COLLAPSE; //} -template -bool is_valid_collapse(const typename C3t3::Edge& edge, - const C3t3& c3t3) + +template +bool is_link_condition_valid(const typename Triangulation::Edge& edge, + const Triangulation& tr) { - typedef typename C3t3::Vertex_handle Vertex_handle; - typedef typename C3t3::Cell_handle Cell_handle; - typedef typename C3t3::Triangulation::Cell_circulator Cell_circulator; + using Vertex_handle = typename Triangulation::Vertex_handle; + using Cell_circulator = typename Triangulation::Cell_circulator; const Vertex_handle v0 = edge.first->vertex(edge.second); const Vertex_handle v1 = edge.first->vertex(edge.third); - Cell_circulator circ = c3t3.triangulation().incident_cells(edge); + if(tr.is_infinite(v0) || tr.is_infinite(v1)) + return false; + + // collect vertices of link(edge) - the "circle" around edge + std::set edge_link_vertices; + Cell_circulator circ = tr.incident_cells(edge); Cell_circulator done = circ; do { - int v0_id = circ->index(v0); - int v1_id = circ->index(v1); - - Cell_handle n0_ch = circ->neighbor(v0_id); - Cell_handle n1_ch = circ->neighbor(v1_id); + for(int k = 0; k < 4; ++k) + { + Vertex_handle vk = circ->vertex(k); + if(vk != v0 && vk != v1) + edge_link_vertices.insert(vk); + } + } while(++circ != done); + + // collect the intersection of neighbors of v0 and neighbors of v1 + std::set neighbors_v0, neighbors_v1; + tr.adjacent_vertices(v0, std::inserter(neighbors_v0, neighbors_v0.end())); + tr.adjacent_vertices(v1, std::inserter(neighbors_v1, neighbors_v1.end())); + + std::set intersection_neighbors_v0v1; + std::set_intersection(neighbors_v0.begin(), neighbors_v0.end(), + neighbors_v1.begin(), neighbors_v1.end(), + std::inserter(intersection_neighbors_v0v1, intersection_neighbors_v0v1.end())); + + if(intersection_neighbors_v0v1 != edge_link_vertices) + return false; // there are vertices shared by v0 and v1 outside edge_link_vertices + + // Check the link condition + // for each pair of vertices in the link, if they are connected by an edge of the triangulation, + // that edge must belong to one of the cells incident to `edge` + // (checking that there are no "chords" in the link that would violate the link condition) + for(Vertex_handle link_vertex : edge_link_vertices) + { + std::vector neighbors; + tr.adjacent_vertices(link_vertex, std::back_inserter(neighbors)); - if (n0_ch->has_vertex(v0) - || n1_ch->has_vertex(v1) - || n0_ch->has_neighbor(n1_ch)) + for(Vertex_handle neighbor : neighbors) { -#ifdef CGAL_DEBUG_TET_REMESHING_IN_PLUGIN - if (c3t3.is_in_complex(edge)) - ++nb_invalid_collapse_short; -#endif - return false; + if(neighbor < link_vertex) // avoid checking the same edge twice + continue; + if(edge_link_vertices.find(neighbor) != edge_link_vertices.end()) + { + // the edge [link_vertex, neighbor] exists + // if facet [v0, link_vertex, neighbor] is not in the triangulation + // then the edge [link_vertex, neighbor] is not part of the link of [v0, v1] + if(!tr.is_facet(v0, link_vertex, neighbor)) + { + CGAL_assertion(!tr.is_facet(v1, link_vertex, neighbor)); + return false; + } + } } } - while (++circ != done); return true; } @@ -477,7 +511,8 @@ template bool collapse_keeps_orientations(const CellRange& star, const typename C3t3::Vertex_handle v_moved, const typename C3t3::Vertex_handle v_other, - const typename C3t3::Triangulation::Geom_traits::Point_3& new_pos) + const typename C3t3::Triangulation::Geom_traits::Point_3& new_pos, + const C3t3& c3t3) { typedef typename C3t3::Triangulation::Geom_traits::Point_3 Point; @@ -490,6 +525,11 @@ bool collapse_keeps_orientations(const CellRange& star, point(ch->vertex(1)->point()), point(ch->vertex(2)->point()), point(ch->vertex(3)->point()) }; + + if(c3t3.triangulation().may_have_badly_oriented_cells() && + CGAL::orientation(pts[0], pts[1], pts[2], pts[3]) != CGAL::POSITIVE) + return true; //in this case we don't care about orientation change, locally + pts[ch->index(v_moved)] = new_pos; if (CGAL::orientation(pts[0], pts[1], pts[2], pts[3]) != CGAL::POSITIVE) return false; @@ -497,102 +537,6 @@ bool collapse_keeps_orientations(const CellRange& star, return true; } -template -bool is_valid_collapse(const typename C3t3::Edge& edge, - const Collapse_type& collapse_type, - const typename C3t3::Triangulation::Point& new_pos, - const C3t3& c3t3) -{ - typedef typename C3t3::Vertex_handle Vertex_handle; - typedef typename C3t3::Cell_handle Cell_handle; - typedef typename C3t3::Triangulation::Point Point; - - const Vertex_handle v0 = edge.first->vertex(edge.second); - const Vertex_handle v1 = edge.first->vertex(edge.third); - -#ifdef CGAL_DEBUG_TET_REMESHING_IN_PLUGIN - const bool in_cx = c3t3.is_in_complex(edge); - if (in_cx) - { - if (collapse_type == TO_MIDPOINT) - nb_test_midpoint++; - else if (collapse_type == TO_V1) - nb_test_v1++; - else - nb_test_v0++; - } -#endif - - if (collapse_type == TO_V1 || collapse_type == TO_MIDPOINT) - { - std::vector cells_to_check; - c3t3.triangulation().finite_incident_cells(v0, - std::back_inserter(cells_to_check)); - - for (const Cell_handle& ch : cells_to_check) - { - if (!ch->has_vertex(v1)) - { - //check orientation - std::array pts = { ch->vertex(0)->point(), - ch->vertex(1)->point(), - ch->vertex(2)->point(), - ch->vertex(3)->point()}; - pts[ch->index(v0)] = new_pos; - if (CGAL::orientation(point(pts[0]), point(pts[1]), point(pts[2]), point(pts[3])) - != CGAL::POSITIVE) - { -#ifdef CGAL_DEBUG_TET_REMESHING_IN_PLUGIN - if (in_cx) - { - if (collapse_type == TO_MIDPOINT) - nb_orientation_midpoint++; - else - nb_orientation_v1++; - } -#endif - return false; - } - } - } - } - if (collapse_type == TO_V0 || collapse_type == TO_MIDPOINT) - { - std::vector cells_to_check; - c3t3.triangulation().finite_incident_cells(v1, - std::back_inserter(cells_to_check)); - - for (const Cell_handle& ch : cells_to_check) - { - if (!ch->has_vertex(v0)) - { - //check orientation - std::array pts = { ch->vertex(0)->point(), - ch->vertex(1)->point(), - ch->vertex(2)->point(), - ch->vertex(3)->point() }; - pts[ch->index(v1)] = new_pos; - if (CGAL::orientation(point(pts[0]), point(pts[1]), point(pts[2]), point(pts[3])) - != CGAL::POSITIVE) - { -#ifdef CGAL_DEBUG_TET_REMESHING_IN_PLUGIN - if (in_cx) - { - if (collapse_type == TO_MIDPOINT) - nb_orientation_midpoint++; - else - nb_orientation_v0++; - } -#endif - return false; - } - } - } - } - - return is_valid_collapse(edge, c3t3); -} - template bool facet_has_edge(const Facet& f, const Vh v0, const Vh v1) { @@ -708,10 +652,10 @@ bool collapse_preserves_surface_star(const typename C3t3::Edge& edge, if(do_opp) n_after_collapse = opp(n_after_collapse); - const double dotref = product(reference_normal, n_after_collapse); + const auto dotref = product(reference_normal, n_after_collapse); if(dotref < 0) return false; - const double dot = product(n_before_collapse, n_after_collapse); + const auto dot = product(n_before_collapse, n_after_collapse); if(dot < 0) return false; @@ -783,8 +727,8 @@ bool are_edge_lengths_valid(const typename C3t3::Edge& edge, } else if (collapse_type == TO_MIDPOINT) { - new_index = max_dimension_index(v0, v1); - new_dim = (std::max)(v0->in_dimension(), v1->in_dimension()); + new_index = max_dimension_index(v0, v1, c3t3); + new_dim = (std::max)(c3t3.in_dimension(v0), c3t3.in_dimension(v1)); #ifdef CGAL_AVERAGE_SIZING_AFTER_COLLAPSE sizing_at_new_pos = sizing_at_midpoint(edge, new_dim, new_index, sizing, c3t3, cell_selector); #else @@ -852,12 +796,12 @@ void merge_surface_patch_indices(const typename C3t3::Facet& f1, if (in_cx_f1 && !in_cx_f2) { typename C3t3::Surface_patch_index patch = c3t3.surface_patch_index(f1); - f2.first->set_surface_patch_index(f2.second, patch); + c3t3.set_surface_patch_index(f2, patch); } else if (in_cx_f2 && !in_cx_f1) { typename C3t3::Surface_patch_index patch = c3t3.surface_patch_index(f2); - f1.first->set_surface_patch_index(f1.second, patch); + c3t3.set_surface_patch_index(f1, patch); } else if(in_cx_f1 && in_cx_f2) { @@ -865,7 +809,7 @@ void merge_surface_patch_indices(const typename C3t3::Facet& f1, typename C3t3::Surface_patch_index patch = c3t3.surface_patch_index(f2); c3t3.remove_from_complex(f2); - f2.first->set_surface_patch_index(f2.second, patch); + c3t3.set_surface_patch_index(f2, patch); } } @@ -1275,7 +1219,7 @@ typename C3t3::Vertex_handle collapse_edge(typename C3t3::Edge& edge, // so it settles all three attempts below at once - and it is the cheap one: // one cell circulation, against a star walk plus an orientation predicate // per cell of the star. - if (!is_valid_collapse(edge, c3t3)) + if(!is_link_condition_valid(edge, c3t3.triangulation())) return Vertex_handle(); // Each attempt below walks the star of v0 and/or of v1, and so do the angle @@ -1306,10 +1250,10 @@ typename C3t3::Vertex_handle collapse_edge(typename C3t3::Edge& edge, const auto orientations_ok = [&](const Collapse_type ct, const Point& pos) { if ((ct == TO_V1 || ct == TO_MIDPOINT) - && !collapse_keeps_orientations(star_of_v0(), v0, v1, point(pos))) + && !collapse_keeps_orientations(star_of_v0(), v0, v1, point(pos), c3t3)) return false; if ((ct == TO_V0 || ct == TO_MIDPOINT) - && !collapse_keeps_orientations(star_of_v1(), v1, v0, point(pos))) + && !collapse_keeps_orientations(star_of_v1(), v1, v0, point(pos), c3t3)) return false; return true; }; @@ -1443,7 +1387,7 @@ auto can_be_collapsed(const typename C3T3::Edge& e, const auto v0 = e.first->vertex(e.second); const auto v1 = e.first->vertex(e.third); - if(v0->in_dimension() != 3 && v1->in_dimension() != 3) + if(c3t3.in_dimension(v0) != 3 && c3t3.in_dimension(v1) != 3) { const auto patch_v0 = patch_cache ? cached_surface_patch_index(v0, c3t3, *patch_cache) diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/flip_edges.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/flip_edges.h index 6cff7befc6de..71e1660e13d5 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/flip_edges.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/flip_edges.h @@ -69,17 +69,17 @@ void update_c3t3_facets(C3t3& c3t3, //on mirror facet const typename C3t3::Surface_patch_index patch = c3t3.surface_patch_index(mf); if (c3t3.is_in_complex(mf)) - f.first->set_surface_patch_index(f.second, patch); + c3t3.set_surface_patch_index(f, patch); else - f.first->set_surface_patch_index(f.second, Surface_patch_index()); + c3t3.set_surface_patch_index(f, Surface_patch_index()); } else { //we are inside the modified zone, c3t3 info is not valid anymore if (c3t3.is_in_complex(f) || c3t3.is_in_complex(mf)) { - f.first->set_surface_patch_index(f.second, Surface_patch_index()); - mf.first->set_surface_patch_index(mf.second, Surface_patch_index()); + c3t3.set_surface_patch_index(f, Surface_patch_index()); + c3t3.set_surface_patch_index(mf, Surface_patch_index()); } } } @@ -205,6 +205,11 @@ Sliver_removal_result flip_3_to_2(typename C3t3::Edge& edge, } else if (criterion == AVERAGE_ANGLE_BASED) { + auto min_dihedral_angle = [](auto&& ...args) { + auto angle = CGAL::Tetrahedral_remeshing::min_dihedral_angle(std::forward(args)...); + return to_double(exact(angle)); + }; + //Current worst dihedral angle double average_min_dh = min_dihedral_angle(tr, ch0); average_min_dh += min_dihedral_angle(tr, ch1); @@ -1160,15 +1165,15 @@ Sliver_removal_result find_best_flip(typename C3t3::Edge& edge, == vertices_around_edge.end()) vertices_around_edge.push_back(vi); - if ( circ->first->subdomain_index() - != circ->first->neighbor(circ->second)->subdomain_index()) + if ( c3t3.subdomain_index(circ->first) + != c3t3.subdomain_index(circ->first->neighbor(circ->second))) { boundary_edge = true; boundary_vertices.insert(vi); } if ( tr.is_infinite(circ->first) - != tr.is_infinite(circ->first->neighbor(circ->second))) + != tr.is_infinite(circ->first->neighbor(circ->second))) { hull_edge = true; //hull_vertices.insert(vi); @@ -1269,7 +1274,7 @@ void collect_subdomains_on_boundary(const C3t3& c3t3, { for (auto v : c3t3.triangulation().vertices(c)) { - const int dim = v->in_dimension(); + const int dim = c3t3.in_dimension(v); if(dim >= 0 && dim < 3) vertices_subdomain_indices[v].insert(c->subdomain_index()); } @@ -1578,8 +1583,8 @@ Sliver_removal_result flip_on_surface(C3T3& c3t3, ch2->set_vertex(ch2->index(vh2), vh3); ch1->set_vertex(ch1->index(vh0), vh1); - c3t3.add_to_complex(ch0, ch0->index(vh4), patch); - c3t3.add_to_complex(ch3, ch3->index(vh4), patch); + c3t3.add_to_complex({ch0, ch0->index(vh4)}, patch); + c3t3.add_to_complex({ch3, ch3->index(vh4)}, patch); for (Cell_handle chi : cells_around_edge) { @@ -1622,8 +1627,8 @@ Sliver_removal_result flip_on_surface(C3T3& c3t3, ci->vertex(j)->set_cell(ci); } - c3t3.add_to_complex(ch0, ch0->index(vh4), patch); - c3t3.add_to_complex(ch3, ch3->index(vh4), patch); + c3t3.add_to_complex({ch0, ch0->index(vh4)}, patch); + c3t3.add_to_complex({ch3, ch3->index(vh4)}, patch); for (Cell_handle chi : cells_around_edge) { @@ -1702,8 +1707,8 @@ Sliver_removal_result flip_on_surface(C3T3& c3t3, ch0->set_vertex(ch0->index(vh5), vh1); ch1->set_vertex(ch1->index(vh4), vh3); - c3t3.add_to_complex(ch0, ch0->index(vh2), patch); - c3t3.add_to_complex(ch1, ch1->index(vh2), patch); + c3t3.add_to_complex({ch0, ch0->index(vh2)}, patch); + c3t3.add_to_complex({ch1, ch1->index(vh2)}, patch); for (Cell_handle chi : cells_around_edge) { @@ -1752,8 +1757,8 @@ Sliver_removal_result flip_on_surface(C3T3& c3t3, ce->vertex(j)->set_cell(ce); } - c3t3.add_to_complex(ch0, ch0->index(vh2), patch); - c3t3.add_to_complex(ch1, ch1->index(vh2), patch); + c3t3.add_to_complex({ch0, ch0->index(vh2)}, patch); + c3t3.add_to_complex({ch1, ch1->index(vh2)}, patch); for (Cell_handle chi : cells_around_edge) { @@ -1910,12 +1915,12 @@ std::size_t flipBoundaryEdges( CGAL_expensive_assertion_code(bool b =) tr.tds().is_facet(vh2, vh3, vh0, c, li, lj, lk); CGAL_expensive_assertion(b); - c3t3.add_to_complex(c, (6 - li - lj - lk), surfi); + c3t3.add_to_complex({c, (6 - li - lj - lk)}, surfi); CGAL_expensive_assertion_code(b = ) tr.tds().is_facet(vh2, vh3, vh1, c, li, lj, lk); CGAL_expensive_assertion(b); - c3t3.add_to_complex(c, (6 - li - lj - lk), surfi); + c3t3.add_to_complex({c, (6 - li - lj - lk)}, surfi); CGAL_expensive_assertion_code(std::size_t nbf_post = std::distance(c3t3.facets_in_complex_begin(), @@ -2010,7 +2015,8 @@ void flip_edges(C3T3& c3t3, vertices_subdomain_indices); #ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG - if(!debug::are_cell_orientations_valid(c3t3.triangulation())) + if(!c3t3.triangulation().may_have_badly_oriented_cells() + && !debug::are_cell_orientations_valid(c3t3.triangulation())) std::cerr << "ERROR in ORIENTATION" << std::endl; #endif diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/peel_slivers.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/peel_slivers.h index 00d0e16f0a1e..792ef5495d06 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/peel_slivers.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/peel_slivers.h @@ -96,9 +96,9 @@ std::size_t peel_slivers(C3T3& c3t3, for (int i = 0; i < 4; ++i) { if (f_on_surface[i]) - c3t3.remove_from_complex(c, i); + c3t3.remove_from_complex({c, i}); else - c3t3.add_to_complex(c, i, patch.value()); + c3t3.add_to_complex({c, i}, patch.value()); } c3t3.remove_from_complex(c); diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h index 47512f50f59e..fec369e4e0d5 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h @@ -137,7 +137,7 @@ class Tetrahedral_remeshing_smoother { CGAL_assertion(!m_flip_smooth_steps); reset_vertex_id_map(c3t3.triangulation()); - reset_free_vertices(c3t3.triangulation()); + reset_free_vertices(c3t3); // once this variable is set to true, // m_vertex_id becomes constant and @@ -169,8 +169,9 @@ class Tetrahedral_remeshing_smoother // this function can be used iff m_vertex_id // has already been initialized - void reset_free_vertices(const Tr& tr) + void reset_free_vertices(const C3t3& c3t3) { + const auto& tr = c3t3.triangulation(); // when flip-smooth steps start, // m_free_vertices should already be initialized // by the last smoothing step. @@ -192,7 +193,7 @@ class Tetrahedral_remeshing_smoother for (auto vi : tr.vertices(c)) { const std::size_t idi = vertex_id(vi); - const int dim = vi->in_dimension(); + const int dim = c3t3.in_dimension(vi); switch (dim) { @@ -206,6 +207,7 @@ class Tetrahedral_remeshing_smoother m_free_vertices[idi] = !m_protect_boundaries && m_smooth_constrained_edges; break; case 0: + case -1: m_free_vertices[idi] = false; break; default: @@ -496,8 +498,6 @@ class Tetrahedral_remeshing_smoother const typename Tr::Point backup = v->point(); //backup v's position const typename Tr::Geom_traits::Point_3 pv = point(backup); - bool valid_orientation = false; - bool angles_improved = true; double frac = 1.0; typename Tr::Geom_traits::Vector_3 move(pv, final_pos); @@ -505,7 +505,11 @@ class Tetrahedral_remeshing_smoother ? max_cosine(tr, inc_cells) : Dihedral_angle_cosine(CGAL::ZERO, 0., 1.);//Dummy unused value + const bool check_orientation = need_to_check_orientation_after_change(tr, inc_cells); + bool valid_try = true; + bool valid_orientation = true; + bool angles_improved = true; do { v->set_point(typename Tr::Point(pv + frac * move)); @@ -516,10 +520,7 @@ class Tetrahedral_remeshing_smoother for (const typename Tr::Cell_handle& ci : inc_cells) { - if (CGAL::POSITIVE != CGAL::orientation(point(ci->vertex(0)->point()), - point(ci->vertex(1)->point()), - point(ci->vertex(2)->point()), - point(ci->vertex(3)->point()))) + if(check_orientation && !is_well_oriented(tr, ci)) { frac = 0.5 * frac; valid_try = false; @@ -640,8 +641,8 @@ class Tetrahedral_remeshing_smoother const Vertex_handle vh0 = e.first->vertex(e.second); const Vertex_handle vh1 = e.first->vertex(e.third); - CGAL_expensive_assertion(is_on_feature(vh0)); - CGAL_expensive_assertion(is_on_feature(vh1)); + CGAL_expensive_assertion(is_on_feature(c3t3, vh0)); + CGAL_expensive_assertion(is_on_feature(c3t3, vh1)); const std::size_t& i0 = vertex_id(vh0); const std::size_t& i1 = vertex_id(vh1); @@ -675,7 +676,7 @@ class Tetrahedral_remeshing_smoother { const std::size_t vid = vertex_id(v); - if (!is_free(vid) || !is_on_feature(v)) + if (!is_free(vid) || !is_on_feature(c3t3, v)) continue; const Point_3 current_pos = point(v->point()); @@ -761,8 +762,8 @@ std::size_t smooth_vertices_on_surfaces(C3t3& c3t3, const std::size_t& i0 = vertex_id(vh0); const std::size_t& i1 = vertex_id(vh1); - const bool vh0_moving = !is_on_feature(vh0) && is_free(i0); - const bool vh1_moving = !is_on_feature(vh1) && is_free(i1); + const bool vh0_moving = !is_on_feature(c3t3, vh0) && is_free(i0); + const bool vh1_moving = !is_on_feature(c3t3, vh1) && is_free(i1); if (!vh0_moving && !vh1_moving) continue; @@ -791,7 +792,7 @@ std::size_t smooth_vertices_on_surfaces(C3t3& c3t3, { const std::size_t vid = vertex_id(v); - if (!is_free(vid) || v->in_dimension() != 2) + if (!is_free(vid) || c3t3.in_dimension(v) != 2) continue; const std::size_t nb_neighbors = moves[vid].neighbors; @@ -804,7 +805,7 @@ std::size_t smooth_vertices_on_surfaces(C3t3& c3t3, CGAL_assertion(si != Surface_patch_index()); CGAL_expensive_assertion_code(auto siv = surface_patch_index(v, c3t3)); - CGAL_expensive_assertion(si == siv); + CGAL_expensive_assertion(si == siv.value()); if (nb_neighbors > 1) { @@ -1054,7 +1055,7 @@ std::size_t smooth_internal_vertices(C3t3& c3t3, reset_vertex_id_map(tr); //are vertices free to move? indices are in `vertex_id` - reset_free_vertices(tr); + reset_free_vertices(c3t3); //collect incident cells using Incident_cells_vector = boost::container::small_vector; @@ -1089,7 +1090,9 @@ std::size_t smooth_internal_vertices(C3t3& c3t3, #endif ); } - CGAL_expensive_assertion(CGAL::Tetrahedral_remeshing::debug::are_cell_orientations_valid(tr)); + CGAL_expensive_assertion( + !tr.may_have_badly_oriented_cells() || + CGAL::Tetrahedral_remeshing::debug::are_cell_orientations_valid(tr)); //// end if(!protect_boundaries) ////////////// INTERNAL VERTICES /////////////////////// @@ -1103,7 +1106,9 @@ std::size_t smooth_internal_vertices(C3t3& c3t3, #endif ); - CGAL_expensive_assertion(CGAL::Tetrahedral_remeshing::debug::are_cell_orientations_valid(tr)); + CGAL_expensive_assertion( + !tr.may_have_badly_oriented_cells() || + CGAL::Tetrahedral_remeshing::debug::are_cell_orientations_valid(tr)); #ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE timer.stop(); @@ -1115,7 +1120,7 @@ std::size_t smooth_internal_vertices(C3t3& c3t3, #endif #ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG CGAL::Tetrahedral_remeshing::debug::dump_vertices_by_dimension( - c3t3.triangulation(), "c3t3_vertices_after_smoothing"); + c3t3, "c3t3_vertices_after_smoothing"); os_surf.close(); os_vol.close(); #endif diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/split_long_edges.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/split_long_edges.h index 8a53ed2ea9e4..f6126c7abba7 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/split_long_edges.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/split_long_edges.h @@ -40,10 +40,10 @@ namespace internal { template -bool positive_orientation_after_edge_split(const typename C3t3::Edge& e, +bool valid_orientation_after_edge_split(const typename C3t3::Edge& e, const typename C3t3::Cell_handle circ, const typename C3t3::Triangulation::Geom_traits::Point_3& steiner, - const C3t3&) + const C3t3& c3t3) { using Point = typename C3t3::Triangulation::Geom_traits::Point_3; @@ -54,6 +54,13 @@ bool positive_orientation_after_edge_split(const typename C3t3::Edge& e, point(circ->vertex(1)->point()), point(circ->vertex(2)->point()), point(circ->vertex(3)->point())}; + + // if the orientation is already bad before split, do not bother checking + // orientation after split, and return true straight away + if(c3t3.triangulation().may_have_badly_oriented_cells() + && CGAL::orientation(pts[0], pts[1], pts[2], pts[3]) != CGAL::POSITIVE) + return true; + // 1st half-cell const int i1 = circ->index(v1); const Point p1 = pts[i1]; @@ -103,7 +110,7 @@ construct_steiner_point(const typename C3t3::Edge& e, do { Cell_handle c = circ; - if(!positive_orientation_after_edge_split(e, c, steiner, c3t3)) + if(!valid_orientation_after_edge_split(e, c, steiner, c3t3)) { steiner_successful = false; break; @@ -151,7 +158,8 @@ typename C3t3::Vertex_handle split_edge(const typename C3t3::Edge& e, else if(nb_patches == 0) dimension = 3; else - CGAL_assertion(false);//e should be in complex + dimension = 1;//e is in complex +// CGAL_assertion(false);//e should be in complex } CGAL_assertion(dimension > 0); @@ -184,7 +192,7 @@ typename C3t3::Vertex_handle split_edge(const typename C3t3::Edge& e, } const Cell_handle c = circ; - if(!positive_orientation_after_edge_split(e, c, m, c3t3)) + if(!valid_orientation_after_edge_split(e, c, m, c3t3)) { const std::optional steiner = construct_steiner_point(e, c3t3); if (steiner != std::nullopt) @@ -233,7 +241,7 @@ typename C3t3::Vertex_handle split_edge(const typename C3t3::Edge& e, // insert midpoint Vertex_handle new_v = tr.tds().insert_in_edge(e); new_v->set_point(typename Tr::Point(m)); - new_v->set_dimension(dimension); + c3t3.set_dimension(new_v, dimension); // update c3t3 with subdomain and surface patch indices std::vector new_cells; @@ -254,16 +262,15 @@ typename C3t3::Vertex_handle split_edge(const typename C3t3::Edge& e, const Facet_info v_and_opp_patch = facets_info.at(mfi); // facet opposite to new_v (status wrt c3t3 is unchanged) - new_cell->set_surface_patch_index(new_cell->index(new_v), - mfi.first->surface_patch_index(mfi.second)); + c3t3.set_surface_patch_index({new_cell, new_cell->index(new_v)}, + c3t3.surface_patch_index(mfi)); // new half-facet (added or not to c3t3 depending on the stored surface patch index) if (Surface_patch_index() == v_and_opp_patch.patch_index_) - new_cell->set_surface_patch_index(new_cell->index(v_and_opp_patch.opp_vertex_), - Surface_patch_index()); + c3t3.set_surface_patch_index({new_cell, new_cell->index(v_and_opp_patch.opp_vertex_)}, + Surface_patch_index()); else - c3t3.add_to_complex(new_cell, - new_cell->index(v_and_opp_patch.opp_vertex_), + c3t3.add_to_complex({new_cell, new_cell->index(v_and_opp_patch.opp_vertex_)}, v_and_opp_patch.patch_index_); // newly created internal facet @@ -272,7 +279,7 @@ typename C3t3::Vertex_handle split_edge(const typename C3t3::Edge& e, const Vertex_handle vi = new_cell->vertex(i); if (vi == v1 || vi == v2) { - new_cell->set_surface_patch_index(i, Surface_patch_index()); + c3t3.set_surface_patch_index({new_cell, i}, Surface_patch_index()); break; } } diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h index 44140a48f6e1..5af89ecfe739 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h @@ -16,7 +16,9 @@ #include #ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE_PROGRESS -#define CGAL_TETRAHEDRAL_REMESHING_VERBOSE +# ifndef CGAL_TETRAHEDRAL_REMESHING_VERBOSE +# define CGAL_TETRAHEDRAL_REMESHING_VERBOSE +# endif #endif #include @@ -91,14 +93,14 @@ template > class Adaptive_remesher { typedef Triangulation Tr; + typedef typename Tr::Geom_traits Gt; typedef typename Tr::Geom_traits::FT FT; - typedef CGAL::Mesh_complex_3_in_triangulation_3 C3t3; - typedef typename C3t3::Cell_handle Cell_handle; typedef typename C3t3::Vertex_handle Vertex_handle; typedef typename C3t3::Edge Edge; @@ -201,7 +203,7 @@ class Adaptive_remesher CGAL::Tetrahedral_remeshing::debug::dump_facets_in_complex(m_c3t3, "1-facets_in_complex_after_split.off"); CGAL::Tetrahedral_remeshing::debug::dump_vertices_by_dimension( - m_c3t3.triangulation(), "1-c3t3_vertices_after_split"); + m_c3t3, "1-c3t3_vertices_after_split"); CGAL::Tetrahedral_remeshing::debug::check_surface_patch_indices(m_c3t3); CGAL::Tetrahedral_remeshing::debug::dump_edges_in_complex(m_c3t3, "1-edges_in_complex_after_split.polylines.txt"); @@ -223,7 +225,7 @@ class Adaptive_remesher CGAL_assertion(tr().tds().is_valid(true)); CGAL_assertion(debug::are_cell_orientations_valid(tr())); CGAL::Tetrahedral_remeshing::debug::dump_vertices_by_dimension( - m_c3t3.triangulation(), "2-c3t3_vertices_after_collapse"); + m_c3t3, "2-c3t3_vertices_after_collapse"); CGAL::Tetrahedral_remeshing::debug::check_surface_patch_indices(m_c3t3); CGAL::Tetrahedral_remeshing::debug::dump_edges_in_complex(m_c3t3, "2-edges_in_complex_after_collapse.polylines.txt"); @@ -244,7 +246,7 @@ class Adaptive_remesher CGAL_assertion(tr().tds().is_valid(true)); CGAL_assertion(debug::are_cell_orientations_valid(tr())); CGAL::Tetrahedral_remeshing::debug::dump_vertices_by_dimension( - m_c3t3.triangulation(), "3-c3t3_vertices_after_flip"); + m_c3t3, "3-c3t3_vertices_after_flip"); CGAL::Tetrahedral_remeshing::debug::check_surface_patch_indices(m_c3t3); CGAL::Tetrahedral_remeshing::debug::dump_edges_in_complex(m_c3t3, "3-edges_in_complex_after_flip.polylines.txt"); @@ -264,7 +266,7 @@ class Adaptive_remesher CGAL_assertion(tr().tds().is_valid(true)); CGAL_assertion(debug::are_cell_orientations_valid(tr())); CGAL::Tetrahedral_remeshing::debug::dump_vertices_by_dimension( - m_c3t3.triangulation(), "4-c3t3_vertices_after_smooth"); + m_c3t3, "4-c3t3_vertices_after_smooth"); CGAL::Tetrahedral_remeshing::debug::check_surface_patch_indices(m_c3t3); CGAL::Tetrahedral_remeshing::debug::dump_edges_in_complex(m_c3t3, "4-edges_in_complex_after_smoothing.polylines.txt"); @@ -328,7 +330,7 @@ class Adaptive_remesher { //reset far points dimension for (Vertex_handle v : m_far_points) - v->set_dimension(-1); + m_c3t3.set_dimension(v, -1); m_c3t3_pbackup->swap(m_c3t3); } else @@ -352,7 +354,7 @@ class Adaptive_remesher #ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG CGAL::Tetrahedral_remeshing::debug::dump_vertices_by_dimension( - m_c3t3.triangulation(), "00-c3t3_vertices_before_init_"); + m_c3t3, "00-c3t3_vertices_before_init_"); #endif if (input_is_c3t3()) @@ -365,14 +367,16 @@ class Adaptive_remesher { if (get(m_cell_selector, cit)) { - const Subdomain_index index = cit->subdomain_index(); + const Subdomain_index index = m_c3t3.subdomain_index(cit); if (m_c3t3.is_in_complex(cit)) m_c3t3.remove_from_complex(cit); const Subdomain_index new_index = (Subdomain_index() != index) ? index : default_subdomain; - m_c3t3.add_to_complex(cit, new_index); + + if(Subdomain_index() != new_index) + m_c3t3.add_to_complex(cit, new_index); #ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG ++nbc; @@ -393,15 +397,15 @@ class Adaptive_remesher for (const Facet& f : tr().finite_facets()) { const Facet mf = tr().mirror_facet(f); - const Subdomain_index s1 = f.first->subdomain_index(); - const Subdomain_index s2 = mf.first->subdomain_index(); + const Subdomain_index s1 = m_c3t3.subdomain_index(f.first); + const Subdomain_index s2 = m_c3t3.subdomain_index(mf.first); if (s1 != s2 || get(fcmap, f) || get(fcmap, mf) || (input_is_c3t3() && m_c3t3.is_in_complex(f)) - || (!input_is_c3t3() && f.first->is_facet_on_surface(f.second))) + || (!input_is_c3t3() && m_c3t3.is_in_complex(f))) { - Surface_patch_index patch = f.first->surface_patch_index(f.second); + Surface_patch_index patch = m_c3t3.surface_patch_index(f); if(patch == Surface_patch_index()) make_surface_patch_index(s1, s2, patch); @@ -470,7 +474,7 @@ class Adaptive_remesher m_c3t3.add_to_complex(vit, ++corner_id); set_dimension(vit, 0); - vit->set_index(corner_id); + //vit->set_index(corner_id); #ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG ++nbv; @@ -492,7 +496,7 @@ class Adaptive_remesher std::cout << "\t Min dihedral angle = " << mdh << std::endl; CGAL::Tetrahedral_remeshing::debug::dump_vertices_by_dimension( - m_c3t3.triangulation(), "0-c3t3_vertices_after_init_"); + m_c3t3, "0-c3t3_vertices_after_init_"); CGAL::Tetrahedral_remeshing::debug::check_surface_patch_indices(m_c3t3); CGAL::Tetrahedral_remeshing::debug::count_far_points(m_c3t3); CGAL::Tetrahedral_remeshing::debug::dump_edges_in_complex(m_c3t3, @@ -504,7 +508,7 @@ class Adaptive_remesher { for (Vertex_handle v : tr().finite_vertex_handles()) { - if (v->in_dimension() == -1) + if (m_c3t3.in_dimension(v) == -1) m_far_points.push_back(v); } } @@ -512,7 +516,7 @@ class Adaptive_remesher private: bool dimension_is_modifiable(const Vertex_handle& v, const int new_dim) const { - const int vdim = v->in_dimension(); + const int vdim = m_c3t3.in_dimension(v); // feature edges and tip/endpoints vertices are kept switch (vdim) { @@ -531,7 +535,7 @@ class Adaptive_remesher void set_dimension(Vertex_handle v, const int new_dim) { if (dimension_is_modifiable(v, new_dim)) - v->set_dimension(new_dim); + m_c3t3.set_dimension(v, new_dim); } bool check_vertex_dimensions() @@ -540,7 +544,7 @@ class Adaptive_remesher { // dimension is -1 for Mesh_3 "far points" // for other vertices, it is in [0; 3] - if (vit->in_dimension() < -1 || vit->in_dimension() > 3) + if (m_c3t3.in_dimension(vit) < -1 || m_c3t3.in_dimension(vit) > 3) return false; } return true; @@ -575,10 +579,13 @@ class Adaptive_remesher = (std::numeric_limits::min)(); for (Cell_handle cit : tr().finite_cell_handles()) { - const Subdomain_index cid = cit->subdomain_index(); + const Subdomain_index cid = m_c3t3.subdomain_index(cit); if (cid > max_index && cid != Subdomain_index()) max_index = cid; } + if(max_index == (std::numeric_limits::min)()) + max_index = Subdomain_index(); + return max_index; } @@ -699,7 +706,9 @@ template + typename CurveIndex = int, + typename C3t3_or_CDT_3 + = CGAL::Mesh_complex_3_in_triangulation_3> struct Adaptive_remesher_type_generator { using Tr = Triangulation; @@ -743,7 +752,9 @@ struct Adaptive_remesher_type_generator >::type; using type = Adaptive_remesher< - Tr, SizingFunction, VCMap, ECMap, FCMap, SelectionFunctor, Visitor>; + Tr, SizingFunction, VCMap, ECMap, FCMap, SelectionFunctor, Visitor, + CornerIndex, CurveIndex, + C3t3_or_CDT_3>; }; }//end namespace internal diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h index 79eada1496cf..4f8bf6ac79ac 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h @@ -25,6 +25,7 @@ #include #include #include +#include #include @@ -287,8 +288,7 @@ Dihedral_angle_cosine cos_dihedral_angle(const typename Gt::Point_3& i, const typename Gt::Point_3& l, const Gt& gt) { - CGAL_expensive_assertion(CGAL::orientation(i, j, k, l) != CGAL::NEGATIVE); - + //valid however orientation(i,j,k,l) is positive or negative typename Gt::Construct_cross_product_vector_3 cross_product = gt.construct_cross_product_vector_3_object(); typename Gt::Compute_scalar_product_3 scalar_product = @@ -365,7 +365,8 @@ Dihedral_angle_cosine max_cos_dihedral_angle(const Point& p, const Vector_3 ps = vector(p, s); const Vector_3 pr = vector(p, r); - //compute normals pointing outside tetrahedron + // compute normals pointing outside tetrahedron if orientation(p,q,r,s) is POSITIVE + // and inside tetrahedron otherwise const Vector_3 n_pqr = cross(qp, qr); if (CGAL::NULL_VECTOR == n_pqr) return Dihedral_angle_cosine(CGAL::POSITIVE, 1., 1.); @@ -528,9 +529,9 @@ bool edges_form_a_sharp_angle(const EdgesVector& incident_edges, CGAL_assertion(shared_vertex != v2); CGAL_assertion(v1 != v2); - const double angle = CGAL::approximate_angle(point(v1->point()), - point(shared_vertex->point()), - point(v2->point())); + const auto angle = CGAL::approximate_angle(point(v1->point()), + point(shared_vertex->point()), + point(v2->point())); return angle < angle_bound; } @@ -667,10 +668,10 @@ Facet canonical_facet(const Facet& f) return (c2 < c) ? std::make_pair(c2, c2->index(c)) : std::make_pair(c, i); } -template -bool is_on_feature(const VertexHandle v) +template +bool is_on_feature(const C3T3& c3t3, const VertexHandle v) { - return (v->in_dimension() == 1 || v->in_dimension() == 0); + return (c3t3.in_dimension(v) == 1 || c3t3.in_dimension(v) == 0); } template @@ -698,6 +699,28 @@ bool is_well_oriented(const Tr& tr, const typename Tr::Cell_handle ch) ch->vertex(3)); } +template +bool need_to_check_orientation_after_change(const Tr& tr, const CellRange& cells) +{ + for (const auto& cell : cells) + { + if (!is_well_oriented(tr, cell)) + { + // if a cell is badly oriented, but the triangulation is known + // to have badly oriented cells, then no need to re-check orientation + // after change. It will remain bad + if(tr.may_have_badly_oriented_cells()) + return false; + else + CGAL_assertion(false);//this function is called before the change, + //so this point should not be reached + } + } + + // all cells are positively oriented + return true; +} + template bool is_boundary(const C3T3& c3t3, const typename C3T3::Facet& f, @@ -717,8 +740,8 @@ bool is_boundary(const C3T3& c3t3, << "\n\t in_complex = " << c3t3.is_in_complex(f) << "\n\t selector(f.first) = " << get(cell_selector, f.first) << "\n\t selector(mirror ) = " << get(cell_selector, mf.first) - << "\n\t subdomain(f.first)= " << f.first->subdomain_index() - << "\n\t subdomain(mirror) = " << mf.first->subdomain_index() + << "\n\t subdomain(f.first)= " << c3t3.subdomain_index(f.first) + << "\n\t subdomain(mirror) = " << c3t3.subdomain_index(mf.first) << std::endl; } @@ -851,21 +874,21 @@ surface_patch_index(const typename C3t3::Vertex_handle v, template void set_index(typename C3t3::Vertex_handle v, const C3t3& c3t3) { - switch (v->in_dimension()) + switch (c3t3.in_dimension(v)) { case 3: - v->set_index(v->cell()->subdomain_index()); + c3t3.set_index(v, c3t3.subdomain_index(v->cell())); break; case 2: CGAL_expensive_assertion(surface_patch_index(v, c3t3) != typename C3t3::Surface_patch_index()); - v->set_index(surface_patch_index(v, c3t3).value()); + c3t3.set_index(v, surface_patch_index(v, c3t3).value()); break; case 1: - v->set_index(typename C3t3::Curve_index(1)); + c3t3.set_index(v, typename C3t3::Curve_index(1)); break; case 0: - v->set_index(Mesh_3::internal::get_index(v->index())); + c3t3.set_index(v, Mesh_3::internal::get_index(c3t3.index(v))); break; case -1://far points from concurrent Mesh_3 break; @@ -924,7 +947,7 @@ OutputIterator incident_subdomains(const typename C3t3::Vertex_handle v, c3t3.triangulation().incident_cells(v, boost::make_function_output_iterator([&](const Cell_handle c) { - *oit++ = c->subdomain_index(); + *oit++ = c3t3.subdomain_index(c); })); return oit; @@ -941,7 +964,7 @@ OutputIterator incident_subdomains(const typename C3t3::Edge& e, Cell_circulator end = circ; do { - *oit++ = circ->subdomain_index(); + *oit++ = c3t3.subdomain_index(circ); } while (++circ != end); return oit; @@ -1282,27 +1305,27 @@ bool is_internal(const typename C3t3::Edge& edge, const C3t3& c3t3, CellSelector cell_selector) { - const typename C3t3::Vertex_handle vs = edge.first->vertex(edge.second); - const typename C3t3::Vertex_handle vt = edge.first->vertex(edge.third); - typedef typename C3t3::Triangulation::Cell_circulator Cell_circulator; Cell_circulator circ = c3t3.triangulation().incident_cells(edge); Cell_circulator done = circ; - const typename C3t3::Subdomain_index si = circ->subdomain_index(); + const typename C3t3::Subdomain_index si = c3t3.subdomain_index(circ); do { if (c3t3.triangulation().is_infinite(circ)) return false; - if (si != circ->subdomain_index()) + if (si != c3t3.subdomain_index(circ)) return false; if (!get(cell_selector, circ)) return false; - if (c3t3.is_in_complex( - circ, - CGAL::Triangulation_utils_3::next_around_edge(circ->index(vs), circ->index(vt)))) + + Cell_circulator ch = circ; + Cell_circulator next_circ = ++circ; + if(c3t3.is_in_complex(ch, ch->index(next_circ))) return false; - } while (++circ != done); + circ = next_circ; + } + while (circ != done); return true; } @@ -1446,7 +1469,7 @@ auto size_at_centroid(const typename C3t3::Cell_handle c, CGAL_assertion(c3t3.is_in_complex(c)); const auto cc = CGAL::centroid(c3t3.triangulation().tetrahedron(c)); - return sizing(cc, 3, c->subdomain_index()); + return sizing(cc, 3, c3t3.subdomain_index(c)); } template @@ -1525,9 +1548,9 @@ auto sizing_at_vertex(const Vertex_handle v, const C3t3& c3t3, const Cell_selector& cell_selector) { - auto size = sizing(point(v->point()), v->in_dimension(), v->index()); + auto size = sizing(point(v->point()), c3t3.in_dimension(v), c3t3.index(v)); - if(v->in_dimension() < 3 && size == 0) + if(c3t3.in_dimension(v) < 3 && size == 0) { std::vector cells; c3t3.triangulation().incident_cells(v, std::back_inserter(cells)); @@ -1559,8 +1582,8 @@ auto sizing_at_midpoint(const typename C3t3::Edge& e, { const auto [u, v] = make_vertex_pair(e); - const FT size_at_u = sizing(cp(u->point()), u->in_dimension(), u->index()); - const FT size_at_v = sizing(cp(v->point()), v->in_dimension(), v->index()); + const FT size_at_u = sizing(cp(u->point()), c3t3.in_dimension(u), c3t3.index(u)); + const FT size_at_v = sizing(cp(v->point()), c3t3.in_dimension(v), c3t3.index(v)); if (size_at_u == 0. || size_at_v == 0.) return average_sizing_in_incident_cells(e, sizing, c3t3, cell_selector); @@ -1623,23 +1646,26 @@ auto min_sizing_in_incident_cells(const typename C3t3::Edge& e, return size_at_uv; } -template +template auto -max_dimension_index(const Vertex_handle v0, const Vertex_handle v1) +max_dimension_index(const typename C3t3::Vertex_handle v0, + const typename C3t3::Vertex_handle v1, + const C3t3& c3t3) { - const int dim0 = v0->in_dimension(); - const int dim1 = v1->in_dimension(); + const int dim0 = c3t3.in_dimension(v0); + const int dim1 = c3t3.in_dimension(v1); - if (dim0 > dim1) return v0->index(); - else if (dim1 > dim0) return v1->index(); - else return v0->index(); //arbitrary choice, any of the two should be fine + if (dim0 > dim1) return c3t3.index(v0); + else if (dim1 > dim0) return c3t3.index(v1); + else return c3t3.index(v0); //arbitrary choice, any of the two should be fine } -template +template auto -max_dimension_index(const std::array& vs) +max_dimension_index(const std::array& vs, + const C3t3& c3t3) { - return max_dimension_index(vs[0], vs[1]); + return max_dimension_index(vs[0], vs[1], c3t3); } template @@ -1656,15 +1682,15 @@ approximate_edge_length(const typename Tr::Edge& e, const Tr& tr) return CGAL::approximate_sqrt(squared_edge_length(e, tr)); } -template -typename Tr::Cell::Subdomain_index +template +typename C3t3::Subdomain_index subdomain_index_at_point_3(const Pt& p, - const typename Tr::Cell_handle hint, - const Tr& tr) + const typename C3t3::Cell_handle hint, + const C3t3& c3t3) { - const typename Tr::Point tr_p(p); - const typename Tr::Cell_handle c = tr.locate(tr_p, hint); - return c->subdomain_index(); + const typename C3t3::Triangulation::Point tr_p(p); + const typename C3t3::Cell_handle c = c3t3.triangulation().locate(tr_p, hint); + return c3t3.subdomain_index(c); } template @@ -1692,7 +1718,7 @@ auto midpoint_with_info(const typename C3t3::Edge& e, const Point_3 midpoint_pt = midpt(cp(u->point()), cp(v->point())); const int midpoint_dim = boundary_edge - ? (std::max)(u->in_dimension(), v->in_dimension()) + ? (std::max)(c3t3.in_dimension(u), c3t3.in_dimension(v)) : 3; // the midpoint lies on `e`, and all the cells incident to an edge that is not // on a boundary share one subdomain : locating the midpoint would return one @@ -1702,7 +1728,7 @@ auto midpoint_with_info(const typename C3t3::Edge& e, == e.first->subdomain_index()); const Index midpoint_index = boundary_edge - ? max_dimension_index(c3t3.triangulation().vertices(e)) + ? max_dimension_index(c3t3.triangulation().vertices(e), c3t3) : Index(e.first->subdomain_index()); return Midpoint_with_info{midpoint_pt, midpoint_dim, midpoint_index}; @@ -1728,8 +1754,8 @@ squared_upper_size_bound(const typename C3t3::Edge& e, const Vertex_handle u = e.first->vertex(e.second); const Vertex_handle v = e.first->vertex(e.third); - const FT size_at_u = sizing(cp(u->point()), u->in_dimension(), u->index()); - const FT size_at_v = sizing(cp(v->point()), v->in_dimension(), v->index()); + const FT size_at_u = sizing(cp(u->point()), c3t3.in_dimension(u), c3t3.index(u)); + const FT size_at_v = sizing(cp(v->point()), c3t3.in_dimension(v), c3t3.index(v)); // if e is on the boundary AND sizing at the boundary is set to 0, // we take the maximum size of the incident cells @@ -1785,8 +1811,8 @@ squared_lower_size_bound(const typename C3t3::Edge& e, const Vertex_handle u = e.first->vertex(e.second); const Vertex_handle v = e.first->vertex(e.third); - const FT size_at_u = sizing(point(u->point()), u->in_dimension(), u->index()); - const FT size_at_v = sizing(point(v->point()), v->in_dimension(), v->index()); + const FT size_at_u = sizing(point(u->point()), c3t3.in_dimension(u), c3t3.index(u)); + const FT size_at_v = sizing(point(v->point()), c3t3.in_dimension(v), c3t3.index(v)); // if e is on the boundary AND sizing at the boundary is set to 0, // we take the minimum size of the incident cells @@ -1985,8 +2011,8 @@ void get_edge_info(const typename C3t3::Edge& edge, } else { - const bool v0_on_feature = is_on_feature(v0); - const bool v1_on_feature = is_on_feature(v1); + const bool v0_on_feature = is_on_feature(c3t3, v0); + const bool v1_on_feature = is_on_feature(c3t3, v1); if (v0_on_feature && v1_on_feature) { if (c3t3.is_in_complex(edge)) { @@ -2092,7 +2118,7 @@ namespace internal if (Subdomain_index() != subdomain) c3t3.add_to_complex(c, subdomain); else - c->set_subdomain_index(Subdomain_index()); + c3t3.set_subdomain_index(c, Subdomain_index()); //update cell_selector property map put(cell_selector, c, selected); @@ -2210,9 +2236,9 @@ void check_surface_patch_indices(const C3t3& c3t3) typedef typename C3t3::Vertex_handle Vertex_handle; for (Vertex_handle v : c3t3.triangulation().finite_vertex_handles()) { - if (v->in_dimension() != 2) + if (c3t3.in_dimension(v) != 2) continue; - CGAL_expensive_assertion(surface_patch_index(v, c3t3) != typename C3t3::Surface_patch_index()); + CGAL_expensive_assertion(surface_patch_index(v, c3t3) != std::nullopt); } } @@ -2229,8 +2255,13 @@ void count_far_points(const C3t3& c3t3) } template -bool are_cell_orientations_valid(const Tr& tr) +bool are_cell_orientations_valid([[maybe_unused]] const Tr& tr) { + // skip the test if we know + // that the input triangulation already has inverted cells + if(tr.may_have_badly_oriented_cells()) + return true; + typedef typename Tr::Geom_traits::Point_3 Point_3; typedef typename Tr::Facet Facet; @@ -2632,10 +2663,12 @@ void dump_cells_with_small_dihedral_angle(const Tr& tr, dump_cells_off(cells, tr, "bad_cells.off"); } -template -void dump_vertices_by_dimension(const Tr& tr, const char* prefix) +template +void dump_vertices_by_dimension(const C3t3& c3t3, const char* prefix) { - typedef typename Tr::Vertex_handle Vertex_handle; + using Tr = typename C3t3::Triangulation; + const Tr& tr = c3t3.triangulation(); + using Vertex_handle = typename Tr::Vertex_handle; std::vector< std::vector > vertices_per_dimension(4); std::size_t nb_far_points = 0; @@ -2644,14 +2677,14 @@ void dump_vertices_by_dimension(const Tr& tr, const char* prefix) vit != tr.finite_vertices_end(); ++vit) { - if (vit->in_dimension() == -1) + if (c3t3.in_dimension(vit) == -1) { ++nb_far_points; continue;//far point } - CGAL_assertion(vit->in_dimension() >= 0 && vit->in_dimension() < 4); + CGAL_assertion(c3t3.in_dimension(vit) >= 0 && c3t3.in_dimension(vit) < 4); - vertices_per_dimension[vit->in_dimension()].push_back(vit); + vertices_per_dimension[c3t3.in_dimension(vit)].push_back(vit); } for (int i = 0; i < 4; ++i) @@ -2706,12 +2739,15 @@ template void dump_medit(const C3t3& c3t3, const char* filename) { std::ofstream os(filename, std::ios::out); - c3t3.output_to_medit(os, true, true); + //CGAL::IO::write_MEDIT(os, c3t3.triangulation()); + //c3t3.output_to_medit(os, true, true); os.close(); } -template -void dump_c3t3(const C3t3& c3t3, const char* filename_no_extension) +template +void dump_c3t3( + const CGAL::Mesh_complex_3_in_triangulation_3& c3t3, + const char* filename_no_extension) { std::string filename_medit(filename_no_extension); filename_medit.append(".mesh"); @@ -2722,6 +2758,18 @@ void dump_c3t3(const C3t3& c3t3, const char* filename_no_extension) dump_binary(c3t3, filename_binary.c_str()); } +template +void dump_c3t3(const CDT_3& cdt3, const char* filename_no_extension) +{ + std::string filename_off(filename_no_extension); + filename_off.append("_facets.off"); + cdt3.dump_constrained_facets_to_off(filename_off.c_str()); +// +// std::string filename_binary(filename_no_extension); +// filename_binary.append(".binary.cgal"); +// dump_binary(c3t3, filename_binary.c_str()); +} + } //namespace debug } //namespace Tetrahedral_remeshing diff --git a/Tetrahedral_remeshing/include/CGAL/tetrahedral_remeshing.h b/Tetrahedral_remeshing/include/CGAL/tetrahedral_remeshing.h index da8766f081e2..e32d43d602a2 100644 --- a/Tetrahedral_remeshing/include/CGAL/tetrahedral_remeshing.h +++ b/Tetrahedral_remeshing/include/CGAL/tetrahedral_remeshing.h @@ -521,6 +521,121 @@ void tetrahedral_isotropic_remeshing( #endif } +//////////////////////////////////////////////////////// +/////// CONFORMING_CONSTRAINED_TRIANGULATION_3 ///////// +//////////////////////////////////////////////////////// + +template > +#endif + > +void tetrahedral_isotropic_remeshing(CDT_3& cdt3, + const SizingFunction& sizing, + const NamedParameters& np = parameters::default_values()) +{ + CGAL_expensive_assertion(cdt3.triangulation().tds().is_valid()); + + using parameters::choose_parameter; + using parameters::get_parameter; + + using Tr = typename CDT_3::Triangulation; + using Remesher_types = + Tetrahedral_remeshing::internal::Adaptive_remesher_type_generator; + + bool remesh_surfaces = choose_parameter(get_parameter(np, internal_np::remesh_boundaries), true); + bool protect = !remesh_surfaces; + std::size_t max_it = choose_parameter(get_parameter(np, internal_np::number_of_iterations), 1); + + bool smooth_constrained_edges = choose_parameter(get_parameter(np, internal_np::smooth_constrained_edges), false); + + auto cell_select = choose_parameter(get_parameter(np, internal_np::cell_selector), + typename Remesher_types::Default_Selection_functor()); + + auto vcmap = choose_parameter(get_parameter(np, internal_np::vertex_is_constrained), + typename Remesher_types::Default_VCMap{}); + + auto ecmap = choose_parameter(get_parameter(np, internal_np::edge_is_constrained), + typename Remesher_types::Default_ECMap{}); + + auto fcmap = choose_parameter(get_parameter(np, internal_np::facet_is_constrained), + typename Remesher_types::Default_FCMap{}); + + // Advanced and non documented parameters + auto visitor = choose_parameter(get_parameter(np, internal_np::visitor), typename Remesher_types::Default_Visitor()); + + Tetrahedral_remeshing::internal::Remeshing_steps steps{ + choose_parameter(get_parameter(np, internal_np::do_split), true), + choose_parameter(get_parameter(np, internal_np::do_collapse), true), + choose_parameter(get_parameter(np, internal_np::do_flip), true), + static_cast( + choose_parameter(get_parameter(np, internal_np::nb_smoothing_iterations), std::size_t{1})), + static_cast( + choose_parameter(get_parameter(np, internal_np::nb_flip_smooth_iterations), std::size_t{3}))}; + +#ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE + std::cout << "Tetrahedral remeshing (" + << "nb_iter = " << max_it << ", " + << "protect = " << std::boolalpha << protect << ")" << std::endl; + + std::cout << "Init tetrahedral remeshing..."; + std::cout.flush(); +#endif + + using Remesher = typename Remesher_types::type; + Remesher remesher(cdt3, sizing, protect, vcmap, ecmap, fcmap, smooth_constrained_edges, cell_select, visitor); + +#ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE + std::cout << "done." << std::endl; + Tetrahedral_remeshing::internal::compute_statistics(remesher.tr(), cell_select, "statistics_begin.txt"); +#endif + + // perform remeshing +#ifdef CGAL_TETRAHEDRAL_REMESHING_NO_EXTRA_ITERATIONS + nb_extra_iterations = 0; +#endif + + remesher.remesh(max_it, steps); + +#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG + const double angle_bound = 5.0; + Tetrahedral_remeshing::debug::dump_cells_with_small_dihedral_angle(cdt3.triangulation(), angle_bound, cell_select, + "bad_cells.mesh"); +#endif +#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG + Tetrahedral_remeshing::internal::compute_statistics(cdt3.triangulation(), cell_select, "statistics_end.txt"); +#endif +} + +template > +#endif + > +void tetrahedral_isotropic_remeshing(CDT_3& cdt3, + const FT target_edge_length, + const NamedParameters& np = parameters::default_values()) +{ + using P = typename CDT_3::Triangulation::Geom_traits::Point_3; + using Index = int;//typename CDT_3::Triangulation::Vertex::Index; + using Sizing_FT = typename CDT_3::Triangulation::Geom_traits::FT; + + const Sizing_FT target_ft = static_cast(target_edge_length); + + tetrahedral_isotropic_remeshing(cdt3, + [target_ft](const P&, const int&, const Index&) + { return target_ft; }, + np); +} + + }//end namespace CGAL #endif //CGAL_TETRAHEDRAL_REMESHING_H diff --git a/Tetrahedral_remeshing/test/Tetrahedral_remeshing/test_tetrahedral_remeshing_from_mesh_file.cpp b/Tetrahedral_remeshing/test/Tetrahedral_remeshing/test_tetrahedral_remeshing_from_mesh_file.cpp index 30c83e1c5334..45fa0c39d21b 100644 --- a/Tetrahedral_remeshing/test/Tetrahedral_remeshing/test_tetrahedral_remeshing_from_mesh_file.cpp +++ b/Tetrahedral_remeshing/test/Tetrahedral_remeshing/test_tetrahedral_remeshing_from_mesh_file.cpp @@ -7,26 +7,96 @@ #include #include +#include +#include + #include #include -#include - typedef CGAL::Exact_predicates_inexact_constructions_kernel K; typedef CGAL::Tetrahedral_remeshing::Remeshing_triangulation_3 Remeshing_triangulation; +typedef Remeshing_triangulation Tr; -int main(int argc, char* argv[]) + +int test(const std::string& filename, const bool perturb_vertices_positions = false) { - const double target_edge_length = (argc > 1) ? atof(argv[1]) : 0.1; + const double target_edge_length = 0.05; - Remeshing_triangulation tr; + std::ifstream in(filename); - std::ifstream in("data/sphere.mesh"); - if (CGAL::SMDS_3::build_triangulation_from_file(in, tr)) + Remeshing_triangulation tr; + if(CGAL::SMDS_3::build_triangulation_from_file(in, tr, + false /*verbose*/, + false /*replace_domain_0*/, + false /*allow_non_manifold*/, + true /*allow_negative_orientation*/)) std::cout << "build triangulation ok" << std::endl; + else + return EXIT_FAILURE; + + if (perturb_vertices_positions) + { + std::cout << "CGAL Random seed = " << CGAL::get_default_random().get_seed() << std::endl; + using P = Remeshing_triangulation::Point; + const int percentage = 10;// 1/percentage = fraction of perturbed vertices + const double max_move = 0.1 * target_edge_length; + + CGAL::Random rng; + int vid = 0; + for (auto v : tr.finite_vertex_handles()) + { + if(++vid % percentage != 0) + continue; + + const P& pv = v->point(); + v->set_point(P{pv.x() + rng.get_double(-1., 1.) * max_move, + pv.y() + rng.get_double(-1., 1.) * max_move, + pv.z() + rng.get_double(-1., 1.) * max_move}); + } + } + + auto count_negative_cells = [&](const Tr& tr) -> unsigned int + { + return std::count_if(tr.finite_cells_begin(), + tr.finite_cells_end(), + [](const auto& c) + { + return CGAL::POSITIVE != CGAL::orientation(c.vertex(0)->point(), + c.vertex(1)->point(), + c.vertex(2)->point(), + c.vertex(3)->point()); + }); + }; + + unsigned int neg = count_negative_cells(tr); + if(neg > 0) + tr.may_have_badly_oriented_cells(true); + std::cout << neg << " finite cells are badly oriented before remeshing" << std::endl; + + CGAL::tetrahedral_isotropic_remeshing(tr, target_edge_length, + CGAL::parameters::number_of_iterations(5) + .remesh_boundaries(false)); + + unsigned int neg2 = count_negative_cells(tr); + if(neg2 > 0) + std::cout << neg2 << " finite cells are badly oriented after remeshing" << std::endl; + + in.close(); + return EXIT_SUCCESS; +} + +int main(int argc, char* argv[]) +{ + std::cout << "Run remeshing from elephant.mesh" << std::endl; + const std::string file1 = CGAL::data_file_path("meshes/elephant.mesh"); + if(test(file1) != EXIT_SUCCESS) + return EXIT_FAILURE; - CGAL::tetrahedral_isotropic_remeshing(tr, target_edge_length); + std::cout << "\n\nRun remeshing from perturbed elephant.mesh" << std::endl; + const std::string file2 = CGAL::data_file_path("meshes/elephant.mesh"); + if(test(file2, true) != EXIT_SUCCESS) + return EXIT_FAILURE; return EXIT_SUCCESS; } diff --git a/Triangulation_2/doc/Triangulation_2/CGAL/Constrained_triangulation_2.h b/Triangulation_2/doc/Triangulation_2/CGAL/Constrained_triangulation_2.h index c8a49fb0ce72..24e9f0e3d8c0 100644 --- a/Triangulation_2/doc/Triangulation_2/CGAL/Constrained_triangulation_2.h +++ b/Triangulation_2/doc/Triangulation_2/CGAL/Constrained_triangulation_2.h @@ -327,8 +327,6 @@ is_valid(bool verbose = false, int level = 0) const; /// @} -}; /* end Constrained_triangulation_2 */ - /*! writes the triangulation as for `Triangulation_2` and, for each face `f`, and integers `i=0,1,2`, writes "C" or "N" depending whether edge @@ -336,7 +334,7 @@ writes "C" or "N" depending whether edge \relates Constrained_triangulation_2 */ template -std::ostream & operator<<(std::ostream& os, const Constrained_triangulation_2 &ct); +friend std::ostream & operator<<(std::ostream& os, const Constrained_triangulation_2 &ct); /*! reads a triangulation from stream `is` and assigns it to c`t`. Data in the stream must have the same format `operator<<` uses. @@ -344,11 +342,20 @@ Note that `ct` is first cleared. \relates Constrained_triangulation_2 */ template -std::istream& operator>>(std::istream& is,Constrained_triangulation_2 Ct& ct); +friend std::istream& operator>>(std::istream& is,Constrained_triangulation_2 Ct& ct); + +}; /* end Constrained_triangulation_2 */ + +/*! +\ingroup PkgTriangulation2TriangulationClasses -/*! Exception used by constrained triangulations configured with +Exception used by constrained triangulations configured with the tags `No_constraint_intersection_tag` or `No_constraint_intersection_requiring_constructions_tag` when the insertion of a new constraint would break the respective conditions associated to each tag. + +\inherit std::runtime_error +\relates Constrained_triangulation_2 */ -class Intersection_of_constraints_exception; +class Intersection_of_constraints_exception{}; + } /* end namespace CGAL */ diff --git a/Triangulation_2/include/CGAL/Constrained_triangulation_2.h b/Triangulation_2/include/CGAL/Constrained_triangulation_2.h index eb71d1223d6a..3ccaa751a878 100644 --- a/Triangulation_2/include/CGAL/Constrained_triangulation_2.h +++ b/Triangulation_2/include/CGAL/Constrained_triangulation_2.h @@ -18,10 +18,15 @@ #include -#include -#include +#include +#include +#include +#include #include +#include +#include +#include #include #include #include @@ -30,6 +35,7 @@ #include #include #include +#include #include #include @@ -43,6 +49,80 @@ struct No_constraint_intersection_requiring_constructions_tag{}; struct Exact_intersections_tag{}; // to be used with an exact number type struct Exact_predicates_tag{}; // to be used with filtered exact number +class Intersection_of_constraints_exception : public std::runtime_error +{ + static auto construct_what() + { + return std::string("Unauthorized intersections of constraints"); + } + + template + struct Can_the_point_be_displayed : std::false_type + {}; + + template + struct Can_the_point_be_displayed< + Tr, + Vertex_handle, + std::void_t() << std::declval().point(std::declval()))>> + : std::true_type + {}; + + template + static inline constexpr bool can_the_point_be_displayed = Can_the_point_be_displayed::value; + + template + static auto with_point(Tr* tr, Vertex_handle v) { + return IO::oformat([v, tr](std::ostream& os) -> auto& { + return os << IO::oformat(v, With_point_tag{{-1}, tr}); + }, IO_manip_tag{}); + } + + template + static auto construct_what(Tr* tr, + Vertex_handle vaa, + Vertex_handle vbb, + Vertex_handle v1, + Vertex_handle v2) + { + if constexpr(can_the_point_be_displayed) { + std::stringstream ss; + ss.copyfmt(std::cerr); + ss << "Unauthorized intersections of constraints: ( " + << with_point(tr, vaa) << " " << with_point(tr, vbb) << " )" << " intersects with (" + << with_point(tr, v1) << ", " << with_point(tr, v2) << ")"; + return ss.str(); + } else { + return std::string("Unauthorized intersections of constraints"); + } + } + + template + static auto construct_what(Tr* tr, + Point p, + Vertex_handle v1, + Vertex_handle v2) + { + if constexpr(can_the_point_be_displayed) { + std::stringstream ss; + ss.copyfmt(std::cerr); + ss << "Unauthorized intersections of constraints: point " + << p << " intersects with (" << with_point(tr, v1) << ", " << with_point(tr, v2) << ")"; + return ss.str(); + } else { + return std::string("Unauthorized intersections of constraints"); + } + } + +public: + template , + Intersection_of_constraints_exception>)>* = nullptr> + Intersection_of_constraints_exception(Arg&& arg, Args&&... args) + : std::runtime_error(construct_what(std::forward(arg), std::forward(args)...)) {} +}; + // This was deprecated and replaced by ` No_constraint_intersection_tag` and `No_constraint_intersection_requiring_constructions_tag` // due to an inconsistency between the code and the documentation. struct CGAL_DEPRECATED No_intersection_tag : @@ -127,14 +207,7 @@ class Constrained_triangulation_2 } }; - - class Intersection_of_constraints_exception : public std::exception - { - const char* what() const throw () - { - return "Unauthorized intersections of constraints"; - } - }; + using Intersection_of_constraints_exception = CGAL::Intersection_of_constraints_exception; typedef boost::filter_iterator @@ -346,7 +419,7 @@ insert_constraint(Vertex_handle vaa, Vertex_handle vbb, OutputIterator out) // then this is an intersection if constexpr (std::is_same_v) { if(fr->is_constrained(dimension() == 1 ? 2 : i)) { - throw Intersection_of_constraints_exception(); + throw Intersection_of_constraints_exception(this, vaa, vbb, vaa, vi); } } @@ -594,7 +667,7 @@ insert_constraint(Vertex_handle vaa, Vertex_handle vbb, OutputIterator out) #ifdef CGAL_CDT_2_DEBUG_INTERSECTIONS auto display_vertex(Vertex_handle v) const { - With_point_tag point_tag; + With_point_tag point_tag{ {-1}, this }; using CGAL::IO::oformat; return IO::oformat(v, point_tag); } @@ -722,12 +795,12 @@ insert(const Point& a, Locate_type lt, Face_handle loc, int li) } if ( lt == Triangulation::EDGE && loc->is_constrained(li) ) { + v1=loc->vertex(ccw(li)); //endpoint of the constraint + v2=loc->vertex(cw(li)); // endpoint of the constraint if constexpr (std::is_same_v) - throw Intersection_of_constraints_exception(); + throw Intersection_of_constraints_exception(this, a, v1, v2); insert_in_constrained_edge = true; - v1=loc->vertex(ccw(li)); //endpoint of the constraint - v2=loc->vertex(cw(li)); // endpoint of the constraint } va = Triangulation::insert(a,lt,loc,li); @@ -837,7 +910,7 @@ insert_constraint(Vertex_handle vaa, Vertex_handle vbb) // then this is an intersection if constexpr (std::is_same_v) { if(fr->is_constrained(dimension() == 1 ? 2 : i)) { - throw Intersection_of_constraints_exception(); + throw Intersection_of_constraints_exception(this, vaa, vbb, vaa, vi); } } @@ -1028,24 +1101,26 @@ intersect(Face_handle f, int i, template typename Constrained_triangulation_2::Vertex_handle Constrained_triangulation_2:: -intersect(Face_handle , int , - Vertex_handle , - Vertex_handle , +intersect(Face_handle f, int i, + Vertex_handle vaa, + Vertex_handle vbb, No_constraint_intersection_tag) { - throw Intersection_of_constraints_exception(); + auto [v1, v2] = this->vertices(f, i); + throw Intersection_of_constraints_exception(this, vaa, vbb, v1, v2); return Vertex_handle() ; } template typename Constrained_triangulation_2::Vertex_handle Constrained_triangulation_2:: -intersect(Face_handle , int , - Vertex_handle , - Vertex_handle , +intersect(Face_handle f, int i, + Vertex_handle vaa, + Vertex_handle vbb, No_constraint_intersection_requiring_constructions_tag) { - throw Intersection_of_constraints_exception(); + auto [v1, v2] = this->vertices(f, i); + throw Intersection_of_constraints_exception(this, vaa, vbb, v1, v2); return Vertex_handle() ; } diff --git a/Triangulation_2/include/CGAL/Constrained_triangulation_plus_2.h b/Triangulation_2/include/CGAL/Constrained_triangulation_plus_2.h index 47f1ab299123..c411543ef74a 100644 --- a/Triangulation_2/include/CGAL/Constrained_triangulation_plus_2.h +++ b/Triangulation_2/include/CGAL/Constrained_triangulation_plus_2.h @@ -1089,12 +1089,12 @@ insert(const Point& a, Locate_type lt, Face_handle loc, int li) if ( lt == Triangulation::EDGE && loc->is_constrained(li) ) { + v1=loc->vertex(ccw(li)); //endpoint of the constraint + v2=loc->vertex(cw(li)); // endpoint of the constraint if(std::is_same::value) - throw typename Tr::Intersection_of_constraints_exception(); + throw typename Tr::Intersection_of_constraints_exception(this, a, v1, v2); insert_in_constrained_edge = true; - v1=loc->vertex(ccw(li)); //endpoint of the constraint - v2=loc->vertex(cw(li)); // endpoint of the constraint } Vertex_handle va = Triangulation::insert(a,lt,loc,li); @@ -1126,24 +1126,26 @@ intersect(Face_handle f, int i, template typename Constrained_triangulation_plus_2:: Vertex_handle Constrained_triangulation_plus_2:: -intersect(Face_handle, int, - Vertex_handle, - Vertex_handle, +intersect(Face_handle f, int i, + Vertex_handle vaa, + Vertex_handle vbb, No_constraint_intersection_tag) { - throw typename Tr::Intersection_of_constraints_exception(); + auto [v1, v2] = this->vertices(f, i); + throw typename Tr::Intersection_of_constraints_exception(this, vaa, vbb, v1, v2); return Vertex_handle(); } template typename Constrained_triangulation_plus_2:: Vertex_handle Constrained_triangulation_plus_2:: -intersect(Face_handle, int, - Vertex_handle, - Vertex_handle, +intersect(Face_handle f, int i, + Vertex_handle vaa, + Vertex_handle vbb, No_constraint_intersection_requiring_constructions_tag) { - throw typename Tr::Intersection_of_constraints_exception(); + auto [v1, v2] = this->vertices(f, i); + throw typename Tr::Intersection_of_constraints_exception(this, vaa, vbb, v1, v2); return Vertex_handle(); } diff --git a/Triangulation_2/include/CGAL/Triangulation_2.h b/Triangulation_2/include/CGAL/Triangulation_2.h index fea1aba15eec..77ca3d6cdbe6 100644 --- a/Triangulation_2/include/CGAL/Triangulation_2.h +++ b/Triangulation_2/include/CGAL/Triangulation_2.h @@ -16,6 +16,7 @@ #include +#include #include #include #include @@ -310,6 +311,22 @@ class Triangulation_2 construct_point(const Point& p) const { return geom_traits().construct_point_2_object()(p); } + std::array vertices(Face_handle f) const { + return _tds.vertices(f); + } + + std::array vertices(Face_handle f, int i) const { + return _tds.vertices(f, i); + } + + std::array vertices(Edge e) const { + return _tds.vertices(e); + } + + std::array vertices(Vertex_handle v) const { + return _tds.vertices(v); + } + const Point& point(Face_handle f, int i) const; const Point& point(Vertex_handle v) const; @@ -653,14 +670,19 @@ projection_traits_has_inexact_negative_orientation(const Point &p, const Point & template void fill_hole(Vertex_handle v, std::list & hole, OutputItFaces fit); - template - void fill_hole_delaunay(std::list & hole, OutputItFaces fit); - void make_hole(Vertex_handle v, std::list & hole, std::set &faces_set); public: void make_hole(Vertex_handle v, std::list & hole); + + // convenience function to get the hole + auto make_hole(Vertex_handle v) { + std::list hole; + make_hole(v, hole); + return hole; + } + // template // Vertex_handle star_hole( Point p, // EdgeIt edge_begin, @@ -2029,33 +2051,36 @@ fill_hole(Vertex_handle v, std::list & hole, OutputItFaces fit) *fit++ = newf; } -template -void -Triangulation_2:: -fill_hole_delaunay(std::list & first_hole) +template +OutputItFaces +fill_hole_delaunay(Triangulation_2& tr, + std::list::Edge>& first_hole, + OutputItFaces fit) { - typedef std::list Hole; - typedef std::list Hole_list; + using Tr = Triangulation_2; + using Vertex_handle = typename Tr::Vertex_handle; + using Edge = typename Tr::Edge; + using Face_handle = typename Tr::Face_handle; - Face_handle f, ff, fn; - int i, ii, in; - Hole_list hole_list; - - hole_list.push_front(first_hole); + auto create_face = [&](auto &&... args) { + Face_handle newf = tr.tds().create_face(std::forward(args)...); + *fit++ = newf; + return newf; + }; + using Hole = std::list; + std::list hole_list{1, first_hole}; while( ! hole_list.empty()) { Hole& hole = hole_list.front(); - typename Hole::iterator hit = hole.begin(); - // if the hole has only three edges, create the triangle if (hole.size() == 3) { - hit = hole.begin(); - f = (*hit).first; i = (*hit).second; - ff = (* ++hit).first; ii = (*hit).second; - fn = (* ++hit).first; in = (*hit).second; - create_face(f,i,ff,ii,fn,in); + auto hit = hole.begin(); + auto [f0, i0] = *hit; ++hit; + auto [f1, i1] = *hit; ++hit; + auto [f2, i2] = *hit; + create_face(f0,i0,f1,i1,f2,i2); hole_list.pop_front(); continue; } @@ -2065,212 +2090,99 @@ fill_hole_delaunay(std::list & first_hole) // and the new triangle adjacent to that edge // cut the hole and push it back + // two helper functions: + auto cw_vertex = [](Edge e) { return e.first->vertex( Tr::cw(e.second)); }; + auto ccw_vertex = [](Edge e) { return e.first->vertex(Tr::ccw(e.second)); }; + // first, ensure that a neighboring face // whose vertices on the hole boundary are finite // is the first of the hole - bool finite= false; - while (!finite){ - ff = (hole.front()).first; - ii = (hole.front()).second; - if ( is_infinite(ff->vertex(cw(ii))) || - is_infinite(ff->vertex(ccw(ii)))) { - hole.push_back(hole.front()); - hole.pop_front(); - } - else finite=true; + for (auto eit = hole.begin(); + tr.is_infinite(cw_vertex(*eit)) || tr.is_infinite(ccw_vertex(*eit)); + eit = hole.begin()) + { + hole.splice(hole.end(), hole, hole.begin()); // push the first element to the end of the list } // take the first neighboring face and pop it; - ff = (hole.front()).first; - ii =(hole.front()).second; + auto first_edge = hole.front(); hole.pop_front(); - Vertex_handle v0 = ff->vertex(cw(ii)); - Vertex_handle v1 = ff->vertex(ccw(ii)); - Vertex_handle v2 = infinite_vertex(); - Vertex_handle v3; - const Point& p0 = v0->point(); - const Point& p1 = v1->point(); - - typename Hole::iterator hdone = hole.end(); - hit = hole.begin(); - typename Hole::iterator cut_after(hit); - - // if tested vertex is c with respect to the vertex opposite - // to nullptr neighbor, - // stop at the before last face; - hdone--; - while( hit != hdone) { - fn = (*hit).first; - in = (*hit).second; - Vertex_handle vv = fn->vertex(ccw(in)); - if (is_infinite(vv)) { - if(is_infinite(v2)) cut_after = hit; - } - else { // vv is a finite vertex - const Point & p = vv->point(); - if (orientation(p0,p1,p) == COUNTERCLOCKWISE) { - if (is_infinite(v2)) { v2=vv; v3=vv; cut_after=hit;} - else{ - // - if (this->side_of_oriented_circle(p0,p1,v3->point(),p,true) == ON_POSITIVE_SIDE){ - v2=vv; v3=vv; cut_after=hit;} - } - } - } - ++hit; - } + const Vertex_handle v0 = cw_vertex(first_edge); + const Vertex_handle v1 = ccw_vertex(first_edge); - // create new triangle and update adjacency relations - Face_handle newf; + // search in `hole` an edge `cut_after`, and its vertex `v2==ccw_vertex(*cut_after)` + // such that the triangle (v0,v1,v2) is a Delaunay triangle + const auto [cut_after, v2] = std::invoke([&]() { + const auto hole_end = hole.cend(); + const auto hole_last_one = std::prev(hole_end); - //update the hole and push back in the Hole_List stack - // if v2 belongs to the neighbor following or preceding *f - // the hole remain a single hole - // otherwise it is split in two holes + auto cut_after = hole_end; + Vertex_handle v2 = tr.infinite_vertex(); - fn = (hole.front()).first; - in = (hole.front()).second; - if (fn->has_vertex(v2, i) && i == fn->ccw(in)) { - newf = create_face(ff,ii,fn,in); - hole.pop_front(); - hole.push_front(Edge( newf,1)); - } - else{ - fn = (hole.back()).first; - in = (hole.back()).second; - if (fn->has_vertex(v2, i) && i== fn->cw(in)) { - newf = create_face(fn,in,ff,ii); - hole.pop_back(); - hole.push_back(Edge(newf,1)); - } - else { - // split the hole in two holes - newf = create_face(ff,ii,v2); - Hole new_hole; - ++cut_after; - while( hole.begin() != cut_after ) - { - new_hole.push_back(hole.front()); - hole.pop_front(); - } + const auto& p0 = v0->point(); + const auto& p1 = v1->point(); - hole.push_front(Edge( newf,1)); - new_hole.push_front(Edge( newf,0)); - hole_list.push_front(new_hole); + for(auto hole_edge_it = hole.cbegin(); hole_edge_it != hole_last_one; ++hole_edge_it) + { + const Vertex_handle vv = ccw_vertex(*hole_edge_it); + if (tr.is_infinite(vv)) { + if(tr.is_infinite(v2)) cut_after = hole_edge_it; + } + else { // vv is a finite vertex + const auto& p = vv->point(); + if (tr.orientation(p0,p1,p) == COUNTERCLOCKWISE) { + if (tr.is_infinite(v2) || + tr.side_of_oriented_circle(p0,p1,v2->point(),p,true) == ON_POSITIVE_SIDE) { + cut_after = hole_edge_it; v2 = vv; + } + } + } } + return std::make_pair(cut_after, v2); + }); + CGAL_assertion(cut_after != hole.cend()); + + // create new triangle (v0, v1, v2) and update adjacency relations + + // Update the hole and push back in the Hole_List stack. + // If v2 belongs to the neighbor following or preceding `first_edge`: + // - then the hole remain a single hole, + // - otherwise it is split in two holes + // Note that `first_edge`, that was the `front()` of the hole, has + // already been popped from it. + const auto& [ff, ii] = first_edge; + if (auto [fn, in] = hole.front(); fn->vertex(Tr::ccw(in)) == v2) { + Face_handle newf = create_face(ff,ii,fn,in); + hole.front() = Edge(newf,1); } - } + else if (auto [fn, in] = hole.back(); fn->vertex(Tr::cw(in)) == v2) { + Face_handle newf = create_face(fn,in,ff,ii); + hole.back() = Edge(newf,1); + } + else { + Face_handle newf = create_face(ff,ii,v2); + + // split the hole in two holes: + // - transfer the range [hole.begin(), cut_after] (`cut_after` included) to `new_hole` + // - `hole` keeps the rest: [cut_after+1, hole.end()( + Hole new_hole; + new_hole.splice(new_hole.end(), hole, hole.begin(), std::next(cut_after)); + new_hole.push_front(Edge(newf,0)); // close the new hole with the edge (newf, 0) + hole_list.push_front(new_hole); // and push it in the stack + + hole.push_front(Edge(newf,1)); // close the hole with the edge (newf, 1) + } + } // while( ! hole_list.empty()) + return fit; } template < class Gt, class Tds > -template void Triangulation_2:: -fill_hole_delaunay(std::list & first_hole, OutputItFaces fit) +fill_hole_delaunay(std::list & first_hole) { - typedef typename Gt::Side_of_oriented_circle_2 In_circle; - typedef std::list Hole; - typedef std::list Hole_list; - - In_circle in_circle = geom_traits().side_of_oriented_circle_2_object(); - - Face_handle f, ff, fn; - int i, ii, in; - Hole_list hole_list; - hole_list.push_front(first_hole); - - while(!hole_list.empty()) { - Hole& hole = hole_list.front(); - typename Hole::iterator hit = hole.begin(); - - if (hole.size() == 3) { - hit = hole.begin(); - f = (*hit).first; i = (*hit).second; - ff = (* ++hit).first; ii = (*hit).second; - fn = (* ++hit).first; in = (*hit).second; - Face_handle newf = create_face(f,i,ff,ii,fn,in); - *fit++ = newf; - hole_list.pop_front(); - continue; - } - - bool finite= false; - while (!finite){ - ff = (hole.front()).first; - ii = (hole.front()).second; - if ( is_infinite(ff->vertex(cw(ii))) || - is_infinite(ff->vertex(ccw(ii)))) { - hole.push_back(hole.front()); - hole.pop_front(); - } else finite=true; - } - - ff = (hole.front()).first; - ii =(hole.front()).second; - hole.pop_front(); - - Vertex_handle v0 = ff->vertex(cw(ii)); - Vertex_handle v1 = ff->vertex(ccw(ii)); - Vertex_handle v2 = infinite_vertex(); - const Point& p0 = v0->point(); - const Point& p1 = v1->point(); - - typename Hole::iterator hdone = hole.end(); - hit = hole.begin(); - typename Hole::iterator cut_after(hit); - - hdone--; - while( hit != hdone) { - fn = (*hit).first; - in = (*hit).second; - Vertex_handle vv = fn->vertex(ccw(in)); - if (is_infinite(vv)) { - if(is_infinite(v2)) cut_after = hit; - } else { // vv is a finite vertex - const Point & p = vv->point(); - if (orientation(p0,p1,p) == CGAL::COUNTERCLOCKWISE) { - if (is_infinite(v2)) { v2 = vv; cut_after = hit;} - else{ - if (in_circle(p0,p1,v2->point(),p) == CGAL::ON_POSITIVE_SIDE){ - v2 = vv; cut_after = hit; - } - } - } - } - ++hit; - } - - Face_handle newf; - - fn = (hole.front()).first; - in = (hole.front()).second; - if (fn->has_vertex(v2, i) && i == fn->ccw(in)) { - newf = create_face(ff,ii,fn,in); - hole.pop_front(); - hole.push_front(Edge( newf,1)); - } else { - fn = (hole.back()).first; - in = (hole.back()).second; - if (fn->has_vertex(v2, i) && i== fn->cw(in)) { - newf = create_face(fn,in,ff,ii); - hole.pop_back(); - hole.push_back(Edge(newf,1)); - } else { - newf = create_face(ff,ii,v2); - Hole new_hole; - ++cut_after; - while( hole.begin() != cut_after ) { - new_hole.push_back(hole.front()); - hole.pop_front(); - } - hole.push_front(Edge(newf, 1)); - new_hole.push_front(Edge(newf, 0)); - hole_list.push_front(new_hole); - } - } - *fit++ = newf; - } + CGAL::fill_hole_delaunay(*this, first_hole, CGAL::Emptyset_iterator{}); } template diff --git a/Triangulation_2/include/CGAL/Triangulation_2/internal/Polyline_constraint_hierarchy_2.h b/Triangulation_2/include/CGAL/Triangulation_2/internal/Polyline_constraint_hierarchy_2.h index 2d0a2fc9c4cc..e401605f1a8b 100644 --- a/Triangulation_2/include/CGAL/Triangulation_2/internal/Polyline_constraint_hierarchy_2.h +++ b/Triangulation_2/include/CGAL/Triangulation_2/internal/Polyline_constraint_hierarchy_2.h @@ -13,17 +13,23 @@ #ifndef CGAL_POLYLINE_CONSTRAINT_HIERARCHY_2_H #define CGAL_POLYLINE_CONSTRAINT_HIERARCHY_2_H +#include #include #include +#include +#include +#include +#include +#include +#include #include #include -#include #include #include -#include #include +#include #include #include @@ -34,6 +40,8 @@ #include #include #include +#include +#include #ifdef CGAL_CDT_2_DEBUG_INTERSECTIONS # define CGAL_DEBUG_POLYLINE_CONSTRAINT_HIERARCHY_2 CGAL_CDT_2_DEBUG_INTERSECTIONS @@ -578,6 +586,9 @@ class Polyline_constraint_hierarchy_2 // Query bool is_subconstraint(T va, T vb) const; + bool is_valid_constraint(Constraint_id cid) const { + return priv.constraints_set.find(cid) != priv.constraints_set.end(); + } Vertex_it vertices_in_constraint_begin(Constraint_id cid) const { return cid.begin(); } diff --git a/Triangulation_2/test/Triangulation_2/issue_4025.cpp b/Triangulation_2/test/Triangulation_2/issue_4025.cpp index 150f7cb60e6b..27517591d2bb 100644 --- a/Triangulation_2/test/Triangulation_2/issue_4025.cpp +++ b/Triangulation_2/test/Triangulation_2/issue_4025.cpp @@ -39,11 +39,6 @@ decltype(auto) value_check_expected(V&& value, [[maybe_unused]] const E& expecte return std::forward(value); }; -auto oformat(Vertex_handle vh) -{ - return CGAL::IO::oformat(vh, CGAL::With_point_tag{}); -}; - int main() { CDTP cdtp; @@ -54,6 +49,11 @@ int main() cdtp.print_hierarchy(std::cout); }; + auto oformat = [tr = &cdtp](Vertex_handle vh) + { + return CGAL::IO::oformat(vh, CGAL::With_point_tag{{-1}, tr }); + }; + const std::array collinear_points = { Point(0,0), Point(0,1), Point(0,2), Point(0,3), Point(0,4), Point(0,5) }; diff --git a/Triangulation_3/include/CGAL/Triangulation_3.h b/Triangulation_3/include/CGAL/Triangulation_3.h index c1edf17efb36..2e2f3243e096 100644 --- a/Triangulation_3/include/CGAL/Triangulation_3.h +++ b/Triangulation_3/include/CGAL/Triangulation_3.h @@ -28,6 +28,12 @@ #include #include #include +#include +#include +#include +#include +#include +#include #include #include @@ -46,13 +52,16 @@ #include #include +#include +#include +#include #include #include #include -#include +#include #include +#include #include -#include #ifndef CGAL_TRIANGULATION_3_DONT_INSERT_RANGE_OF_POINTS_WITH_INFO #include @@ -69,14 +78,19 @@ # include #endif +#include +#include #include +#include #include -#include #include +#include +#include +#include +#include #include #include -#include -#include +#include #define CGAL_TRIANGULATION_3_USE_THE_4_POINTS_CONSTRUCTOR @@ -1110,6 +1124,9 @@ class Triangulation_3 // c will be replaced by one of the new cells return flip(f.first, f.second); } + std::optional edge_preventing_the_flip(Cell_handle c, int i) const; + bool is_flippable(const Facet& f) const { return is_flippable(f.first, f.second); } + bool is_flippable(Cell_handle c, int i) const; bool flip(Cell_handle c, int i); void flip_flippable(const Facet& f) { flip_flippable(f.first, f.second); } void flip_flippable(Cell_handle c, int i); @@ -1667,16 +1684,48 @@ class Triangulation_3 } protected: - typedef Facet Edge_2D; - typedef std::array Vertex_triple; - typedef typename Base::template Vertex_triple_Facet_map_generator< - Vertex_triple, Facet>::type Vertex_triple_Facet_map; - typedef typename Base::template Vertex_handle_unique_hash_map_generator< - Vertex_handle>::type Vertex_handle_unique_hash_map; + using Edge_2D = Facet; + using Vertex_triple = std::array; + + using Vertex_triple_Facet_map = typename Base::template Vertex_triple_Facet_map_generator::type; + using Vertex_handle_unique_hash_map = typename Base::template Vertex_handle_unique_hash_map_generator::type; static Vertex_triple make_vertex_triple(const Facet& f); static void make_canonical_oriented_triple(Vertex_triple& t); + static Vertex_triple make_canonical_oriented_triple(Vertex_triple&& t) { + make_canonical_oriented_triple(t); + return t; + } + + static Vertex_triple make_canonical_oriented_triple(const Facet& f) { + Vertex_triple t = make_vertex_triple(f); + make_canonical_oriented_triple(t); + return t; + } + + static Vertex_triple make_canonical_oriented_triple(Vertex_handle v0, Vertex_handle v1, Vertex_handle v2) { + Vertex_triple t{v0, v1, v2}; + make_canonical_oriented_triple(t); + return t; + } + + template + static Vertex_triple apply_map(Map& m, const Vertex_triple& t) { + return Vertex_triple{m[t[0]], m[t[1]], m[t[2]]}; + } + + template + static Vertex_triple apply_functor(Functor& f, const Triple& t) { + const auto& [t0, t1, t2] = t; + return Vertex_triple{f(t0), f(t1), f(t2)}; + } + + template + static Vertex_triple make_canonical_oriented_mapped_triple(Map& m, const Facet& f) { + return make_canonical_oriented_triple(apply_map(m, make_vertex_triple(f))); + } + template < class VertexRemover > VertexRemover& make_hole_2D(Vertex_handle v, std::list& hole, VertexRemover& remover); @@ -3724,6 +3773,18 @@ template < class GT, class Tds, class Lds > bool Triangulation_3:: flip(Cell_handle c, int i) +{ + if(!is_flippable(c, i)) + return false; + + _tds.flip_flippable(c, i); + return true; +} + +template < class GT, class Tds, class Lds > +std::optional +Triangulation_3:: +edge_preventing_the_flip(Cell_handle c, int i) const { CGAL_precondition((dimension() == 3) && (0<=i) && (i<4) && (number_of_vertices() >= 5)); @@ -3731,51 +3792,33 @@ flip(Cell_handle c, int i) Cell_handle n = c->neighbor(i); int in = n->index(c); if(is_infinite(c) || is_infinite(n)) - return false; - - if(i%2 == 1) - { - if(orientation(c->vertex((i+1)&3)->point(), - c->vertex((i+2)&3)->point(), - n->vertex(in)->point(), - c->vertex(i)->point()) != POSITIVE) - return false; - - if(orientation(c->vertex((i+2)&3)->point(), - c->vertex((i+3)&3)->point(), - n->vertex(in)->point(), - c->vertex(i)->point()) != POSITIVE) - return false; - - if(orientation(c->vertex((i+3)&3)->point(), - c->vertex((i+1)&3)->point(), - n->vertex(in)->point(), - c->vertex(i)->point()) != POSITIVE) - return false; - } - else - { - if(orientation(c->vertex((i+2)&3)->point(), - c->vertex((i+1)&3)->point(), - n->vertex(in)->point(), - c->vertex(i)->point()) != POSITIVE) - return false; - - if(orientation(c->vertex((i+3)&3)->point(), - c->vertex((i+2)&3)->point(), - n->vertex(in)->point(), - c->vertex(i)->point()) != POSITIVE) - return false; - - if(orientation(c->vertex((i+1)&3)->point(), - c->vertex((i+3)&3)->point(), - n->vertex(in)->point(), - c->vertex(i)->point()) != POSITIVE) - return false; - } + return { -1 }; + + Vertex_handle va = c->vertex(i); + Vertex_handle vb = n->vertex(in); + auto face_vert = vertices(Facet{c, i}); + + if(orientation(face_vert[0]->point(), + face_vert[1]->point(), + vb->point(), + va->point()) != POSITIVE) return {2}; + if(orientation(face_vert[1]->point(), + face_vert[2]->point(), + vb->point(), + va->point()) != POSITIVE) return {0}; + if(orientation(face_vert[2]->point(), + face_vert[0]->point(), + vb->point(), + va->point()) != POSITIVE) return {1}; + return std::nullopt; +} - _tds.flip_flippable(c, i); - return true; +template < class GT, class Tds, class Lds > +bool +Triangulation_3:: +is_flippable(Cell_handle c, int i) const +{ + return edge_preventing_the_flip(c, i) == std::nullopt; } template < class GT, class Tds, class Lds > @@ -3783,43 +3826,7 @@ void Triangulation_3:: flip_flippable(Cell_handle c, int i) { - CGAL_precondition((dimension() == 3) && (0<=i) && (i<4) && - (number_of_vertices() >= 5)); - CGAL_precondition_code(Cell_handle n = c->neighbor(i);); - CGAL_precondition_code(int in = n->index(c);); - CGAL_precondition((! is_infinite(c)) &&(! is_infinite(n))); - - if(i%2 == 1) - { - CGAL_precondition(orientation(c->vertex((i+1)&3)->point(), - c->vertex((i+2)&3)->point(), - n->vertex(in)->point(), - c->vertex(i)->point()) == POSITIVE); - CGAL_precondition(orientation(c->vertex((i+2)&3)->point(), - c->vertex((i+3)&3)->point(), - n->vertex(in)->point(), - c->vertex(i)->point()) == POSITIVE); - CGAL_precondition(orientation(c->vertex((i+3)&3)->point(), - c->vertex((i+1)&3)->point(), - n->vertex(in)->point(), - c->vertex(i)->point()) == POSITIVE); - } - else - { - CGAL_precondition(orientation(c->vertex((i+2)&3)->point(), - c->vertex((i+1)&3)->point(), - n->vertex(in)->point(), - c->vertex(i)->point()) == POSITIVE); - CGAL_precondition(orientation(c->vertex((i+3)&3)->point(), - c->vertex((i+2)&3)->point(), - n->vertex(in)->point(), - c->vertex(i)->point()) == POSITIVE); - CGAL_precondition(orientation(c->vertex((i+1)&3)->point(), - c->vertex((i+3)&3)->point(), - n->vertex(in)->point(), - c->vertex(i)->point()) == POSITIVE); - } - + CGAL_precondition(is_flippable(c, i)); _tds.flip_flippable(c, i); } @@ -4511,7 +4518,7 @@ test_dim_down(Vertex_handle v) const } else // dimension() == 1 or 0 { - return number_of_vertices() == (size_type) dimension() + 1; + return number_of_vertices() == static_cast(dimension()) + 1; } return true; @@ -4966,19 +4973,17 @@ create_hole_outer_map(Vertex_handle v, const std::vector& incident_ CGAL_expensive_precondition(! test_dim_down(v)); Vertex_triple_Facet_map outer_map; - for(auto cit = incident_cells.begin(), end = incident_cells.end(); - cit != end; ++cit) - { - int indv = (*cit)->index(v); - Cell_handle opp_cit = (*cit)->neighbor(indv); - Facet f(opp_cit, opp_cit->index(*cit)); - Vertex_triple vt = make_vertex_triple(f); - make_canonical_oriented_triple(vt); + for(auto ch: incident_cells) + { + int indv = ch->index(v); + Cell_handle opp_cit = ch->neighbor(indv); + Facet f(opp_cit, opp_cit->index(ch)); + Vertex_triple vt = make_canonical_oriented_triple(f); outer_map[vt] = f; for(int i=0; i<4; i++) { if(i != indv) - (*cit)->vertex(i)->set_cell(opp_cit); + ch->vertex(i)->set_cell(opp_cit); } } return outer_map; @@ -4995,9 +5000,10 @@ create_triangulation_inner_map(const Triangulation& t, auto create_triangulation_inner_map_aux = [&](const auto& cells_range) { for(auto ch : cells_range) { for(unsigned int index = 0; index < 4; index++) { - Facet f = std::pair(ch, index); - Vertex_triple vt_aux = make_vertex_triple(f); - Vertex_triple vt{vmap[vt_aux[0]], vmap[vt_aux[2]], vmap[vt_aux[1]]}; + const Facet f{ch, index}; + Vertex_triple vt = apply_map(vmap, make_vertex_triple(f)); + using std::swap; + swap(vt[1], vt[2]); // reverse the orientation of the triplet make_canonical_oriented_triple(vt); inner_map[vt] = f; } @@ -5137,14 +5143,13 @@ copy_triangulation_into_hole(const Vertex_handle_unique_hash_map& vmap, *cit++ = new_ch; - // For the other faces check, if they can also be glued + // For the other faces, check if they can also be glued for(unsigned int index = 0; index < 4; index++) { if(index != i_i) { Facet f{new_ch, index}; - Vertex_triple vt = make_vertex_triple(f); - make_canonical_oriented_triple(vt); + Vertex_triple vt = make_canonical_oriented_triple(f); std::swap(vt[1], vt[2]); typename Vertex_triple_Facet_map::iterator oit2 = outer_map.find(vt); @@ -6119,13 +6124,7 @@ _make_big_hole_3D(Vertex_handle v, vstates[v0] = PROCESSED; } - int i1 = vertex_triple_index(k, 0); - int i2 = vertex_triple_index(k, 1); - int i3 = vertex_triple_index(k, 2); - - Vertex_handle v1 = c->vertex(i1); - Vertex_handle v2 = c->vertex(i2); - Vertex_handle v3 = c->vertex(i3); + auto [v1, v2, v3] = this->vertices(Facet{c, k}); Cell_handle opp_cit = c->neighbor(k); int opp_i = tds().mirror_index(c, k); @@ -6168,8 +6167,7 @@ _make_big_hole_3D(Vertex_handle v, } Facet f(opp_cit, opp_i); - Vertex_triple vt = make_vertex_triple(f); - make_canonical_oriented_triple(vt); + Vertex_triple vt = make_canonical_oriented_triple(f); outer_map[vt] = f; v1->set_cell(opp_cit); v2->set_cell(opp_cit); diff --git a/Triangulation_3/include/CGAL/Triangulation_3/internal/Triangulation_segment_traverser_3_impl.h b/Triangulation_3/include/CGAL/Triangulation_3/internal/Triangulation_segment_traverser_3_impl.h index 2f75230ebbd8..9d36635c39fe 100644 --- a/Triangulation_3/include/CGAL/Triangulation_3/internal/Triangulation_segment_traverser_3_impl.h +++ b/Triangulation_3/include/CGAL/Triangulation_3/internal/Triangulation_segment_traverser_3_impl.h @@ -14,7 +14,25 @@ #include +#include + #include +#include +#include +#include +#include + +#include + +#include +#include +#include + +#if CGAL_DEBUG_TRIANGULATION_SEGMENT_TRAVERSER_3 +# include +# include +# include +#endif namespace CGAL { @@ -257,11 +275,48 @@ walk_to_next() { walk_to_next_3_inf( inf ); else { +#if CGAL_DEBUG_TRIANGULATION_SEGMENT_TRAVERSER_3 + CGAL_assertion_code(std::size_t counter = 0); + std::cerr << "Starting walk_to_next_3 loop with backup: " << debug_simplex(_cur) << '\n'; + std::cerr << "source: " << with_point(_s_vertex) << '\n'; + if(_s_vertex == Vertex_handle()) + std::cerr << " _source is " << _source << '\n'; + std::cerr << "target: " << with_point(_t_vertex) << '\n'; + if(_t_vertex == Vertex_handle()) + std::cerr << " _target is " << _target << '\n'; +#endif const Simplex backup = _cur; + boost::container::small_vector visited_cells; + if(cell() != Cell_handle{}) + { + visited_cells.push_back(cell()); + cell()->tds_data().mark_processed(); + } + auto _ = make_scope_exit([&](){ for(auto c : visited_cells) c->tds_data().clear(); }); do { +#if CGAL_DEBUG_TRIANGULATION_SEGMENT_TRAVERSER_3 + CGAL_assertion_code(++counter); + std::cerr << debug_iterator() << '\n'; + if(counter >= _tr->number_of_cells()) + { + std::cerr << "Exceeded maximum number of cells in walk_to_next_3 loop.\n"; + std::cerr << "_s_vertex:\n" << _tr->point(_s_vertex) << '\n'; + std::cerr << "_t_vertex:\n" << _tr->point(_t_vertex) << '\n'; + std::ofstream dump("dump.binary.cgal", std::ios::binary); + IO::set_binary_mode(dump); + dump << *_tr; + dump.close(); + } + CGAL_assertion(counter < _tr->number_of_cells()); +#endif std::pair p = walk_to_next_3(_prev, _cur); _prev = p.first; _cur = p.second; + if(cell() != Cell_handle{}) + { + cell()->tds_data().mark_processed(); + visited_cells.push_back(cell()); + } } while (cell() != Cell_handle()//end && !cell()->has_vertex(_tr->infinite_vertex(), inf) @@ -335,6 +390,13 @@ std::pair::Simplex, Triangulation_segment_cell_iterator_3::walk_to_next_3(const Simplex& prev, const Simplex& cur) const { + auto returned = [](std::pair p) { +#if CGAL_DEBUG_TRIANGULATION_SEGMENT_TRAVERSER_3 + std::cerr << "walk_to_next_3 returns the pair:\n " << debug_simplex(p.first) + << "\n " << debug_simplex(p.second) << '\n'; +#endif + return p; + }; const auto cur_cell = cur.cell; std::array vert = {&(cur_cell->vertex(0)->point()), &(cur_cell->vertex(1)->point()), &(cur_cell->vertex(2)->point()), &(cur_cell->vertex(3)->point())}; @@ -463,7 +525,7 @@ Triangulation_segment_cell_iterator_3::walk_to_next_3(const Simplex& pre } if(!degenerate) { - return {prev_after_walk, cur_after_walk}; + return returned({prev_after_walk, cur_after_walk}); } } @@ -475,6 +537,15 @@ Triangulation_segment_cell_iterator_3::walk_to_next_3(const Simplex& pre int pos = 0; // We keep track of which orientations are calculated. bool calc[6] = {false, false, false, false, false, false}; +#if CGAL_DEBUG_TRIANGULATION_SEGMENT_TRAVERSER_3 + for(int li = 0; li < 4; ++li) + { + auto vertices = _tr->vertices(Facet{cur_cell, li}); + std::cerr << "o[" << li + << "] = " << _tr->orientation(vertices[0]->point(), vertices[1]->point(), vertices[2]->point(), _target) + << '\n'; + } +#endif if(cur.lt == Tr::VERTEX) { // The three planes through the vertex are set to coplanar. @@ -495,8 +566,20 @@ Triangulation_segment_cell_iterator_3::walk_to_next_3(const Simplex& pre // For the remembering stochastic walk, we start trying with a random facet. CGAL_assertion_code(bool incell = true;) - for(int li = 0; li < 4; ++li) + int pass_number = 0; + const int number_of_pass = cur.lt == Tr::VERTEX ? 2 : 1; + int start = 0; + int end = 4; + if(cur.lt == Tr::VERTEX) { + // Then start to look at the facet opposite to the current vertex. + // For the three other facets, the exit type will be `VERTEX` anyway. + start = cur.li; + end = cur.li + 4; + } + + for(int li_ = start; li_ < end || ++pass_number < number_of_pass; ++li_) { + const int li = li_ % 4; // Skip the previous cell. Cell_handle next = cur_cell->neighbor(li); if(next == prev.cell) { @@ -504,7 +587,19 @@ Triangulation_segment_cell_iterator_3::walk_to_next_3(const Simplex& pre pos += li; continue; } +#if CGAL_DEBUG_TRIANGULATION_SEGMENT_TRAVERSER_3 + std::cerr << "Test facet " << li + << ":\n " <vertices(Facet{cur_cell, li}), With_point_tag{}) << '\n'; + if(next->tds_data().processed()) { + std::cerr << " Next cell already processed.\n"; + } +#endif + if(next->tds_data().processed()) { + continue; + } const Point* const backup_vert_li = std::exchange(vert[li], &_target); + auto exit_guard = CGAL::make_scope_exit([&](){ vert[li] = backup_vert_li; }); + bool op_li_is_null = false; if(_t_vertex != Vertex_handle()) { for(int i = 0; i < 4; ++i) { @@ -514,11 +609,14 @@ Triangulation_segment_cell_iterator_3::walk_to_next_3(const Simplex& pre } // Check if the target is on the opposite side of the supporting plane. op[li] = op_li_is_null ? ZERO : _tr->orientation(*vert[0], *vert[1], *vert[2], *vert[3]); +#if CGAL_DEBUG_TRIANGULATION_SEGMENT_TRAVERSER_3 + std::cerr << " Orientation: " << op[li] << '\n'; +#endif if(op[li] == POSITIVE) pos += li; if(op[li] != NEGATIVE) { - vert[li] = backup_vert_li; - continue; + if(pass_number < 1) + continue; } CGAL_assertion_code(incell = false;) @@ -534,6 +632,16 @@ Triangulation_segment_cell_iterator_3::walk_to_next_3(const Simplex& pre if(!calc[oij]) { const Point* const backup_vert_lj = std::exchange(vert[lj], &_source); o[oij] = _tr->orientation(*vert[0], *vert[1], *vert[2], *vert[3]); +#if CGAL_DEBUG_TRIANGULATION_SEGMENT_TRAVERSER_3 + std::cerr << " edge orientation("; + for(int i = 0; i < 4; ++i) { + if(i == li) std::cerr << "_target"; + else if(i == lj) std::cerr << "_source"; + else std::cerr << with_point(cur_cell->vertex(i)); + if(i < 3) std::cerr << ", "; + } + std::cerr << ") = " << o[oij] << '\n'; +#endif vert[lj] = backup_vert_lj; calc[oij] = true; } @@ -552,11 +660,18 @@ Triangulation_segment_cell_iterator_3::walk_to_next_3(const Simplex& pre } else Or -= o[oij]; } +#if CGAL_DEBUG_TRIANGULATION_SEGMENT_TRAVERSER_3 + std::cerr << " Or: " << Or << '\n'; + for(int i = 0; i < 6; ++i) { + auto [v1i, v2i] = edgeVertices(i); + std::cerr << " o[" << v1i << "," << v2i << "]: " + << (calc[i] ? o[i] : -999) << '\n'; + } +#endif if(Or == 0) { // Either the target is not inside the pyramid, // or the pyramid is degenerate. - vert[li] = backup_vert_li; continue; } @@ -567,7 +682,11 @@ Triangulation_segment_cell_iterator_3::walk_to_next_3(const Simplex& pre CGAL_assertion(li == outside); CGAL_assertion(!inside); } - return {{cur_cell, Tr::FACET, li}, {next, Tr::FACET, next->index(cur_cell)}}; +#if CGAL_DEBUG_TRIANGULATION_SEGMENT_TRAVERSER_3 + using Segment_3 = typename Tr::Geom_traits::Segment_3; + CGAL_assertion(do_intersect(Segment_3(_source, _target), _tr->triangle({cur_cell, li}))); +#endif + return returned({{cur_cell, Tr::FACET, li}, {next, Tr::FACET, next->index(cur_cell)}}); } case 2: { if(regular_case) @@ -575,9 +694,9 @@ Triangulation_segment_cell_iterator_3::walk_to_next_3(const Simplex& pre for(int j = 0; j < 4; ++j) { if(li != j && o[5 - edgeIndex(li, j)] == COPLANAR) { Edge opp = opposite_edge(prev.cell, li, j); - return { + return returned({ {cur_cell, Tr::EDGE, opp.second, opp.third}, - {next, Tr::EDGE, next->index(cur_cell->vertex(opp.second)), next->index(cur_cell->vertex(opp.third))}}; + {next, Tr::EDGE, next->index(cur_cell->vertex(opp.second)), next->index(cur_cell->vertex(opp.third))}}); } } CGAL_unreachable(); @@ -588,7 +707,7 @@ Triangulation_segment_cell_iterator_3::walk_to_next_3(const Simplex& pre CGAL_assertion(degenerate); for(int j = 0; j < 4; ++j) { if(li != j && o[5 - edgeIndex(li, j)] == NEGATIVE) { - return {{cur_cell, Tr::VERTEX, j}, {next, Tr::VERTEX, next->index(cur_cell->vertex(j))}}; + return returned({{cur_cell, Tr::VERTEX, j}, {next, Tr::VERTEX, next->index(cur_cell->vertex(j))}}); } } CGAL_unreachable(); @@ -601,8 +720,19 @@ Triangulation_segment_cell_iterator_3::walk_to_next_3(const Simplex& pre } // The target lies inside this cell. +#if CGAL_DEBUG_TRIANGULATION_SEGMENT_TRAVERSER_3 + CGAL_assertion(false == _tr->tetrahedron(cur_cell).has_on_unbounded_side(_target)); + if(!incell) { + std::cerr << "_source:\n" << _source << '\n'; + std::cerr << "_target:\n" << _target << '\n'; + std::ofstream dump("dump.binary.cgal", std::ios::binary); + IO::set_binary_mode(dump); + dump << *_tr; + dump.close(); + } +#endif CGAL_assertion( incell ); - return { + return returned({ std::invoke([&]() -> Simplex { switch( op[0] + op[1] + op[2] + op[3] ) { case 4: @@ -633,7 +763,7 @@ Triangulation_segment_cell_iterator_3::walk_to_next_3(const Simplex& pre } }), { Cell_handle() } - }; + }); } template < class Tr, class Inc > diff --git a/Triangulation_3/include/CGAL/Triangulation_segment_traverser_3.h b/Triangulation_3/include/CGAL/Triangulation_segment_traverser_3.h index cdd383c4418c..547ac4d5f120 100644 --- a/Triangulation_3/include/CGAL/Triangulation_segment_traverser_3.h +++ b/Triangulation_3/include/CGAL/Triangulation_segment_traverser_3.h @@ -133,17 +133,12 @@ class Triangulation_segment_cell_iterator_3 template < class Tr2, class Inc2 > struct Rebind { typedef Triangulation_segment_cell_iterator_3 Other; }; -#if CGAL_DEBUG_TRIANGULATION_SEGMENT_TRAVERSER_3 static auto display_vert(Vertex_handle v) { - std::stringstream os; - os.precision(17); - if(v->time_stamp() == 0) { - os << "inf"; - } else { - os << '#' << v->time_stamp() << "=(" << v->point() << ")"; - } - return os.str(); + return IO::oformat([v](std::ostream& out) -> auto& + { + return out << with_point(v); + }, IO_manip_tag{}); }; static auto display_lt(Locate_type lt) { @@ -180,7 +175,6 @@ class Triangulation_segment_cell_iterator_3 os << " prev: " << debug_simplex(_prev) << "\n cur: " << debug_simplex(_cur); return os.str(); } -#endif // CGAL_DEBUG_TRIANGULATION_SEGMENT_TRAVERSER_3 private: typedef Segment_cell_iterator SCI; @@ -493,6 +487,13 @@ class Triangulation_segment_cell_iterator_3 return ( i==0 || j==0 ) ? i+j-1 : i+j; } + inline std::pair edgeVertices( int index ) const { + CGAL_precondition( index>=0 && index<6 ); + return index < 3 + ? std::make_pair( 0, index+1 ) + : std::make_pair( index-2, index-1 ); + } + bool have_same_entry(const Simplex& s1, const Simplex& s2) const; // Compute the orientation of a point compared to the oriented plane supporting a half-facet.