diff --git a/AABB_tree/include/CGAL/AABB_traits_2.h b/AABB_tree/include/CGAL/AABB_traits_2.h index 39a5b1b55c4..877565d1877 100644 --- a/AABB_tree/include/CGAL/AABB_traits_2.h +++ b/AABB_tree/include/CGAL/AABB_traits_2.h @@ -484,19 +484,19 @@ public: private: /** - * @brief Computes bounding box of one primitive + * @brief Computes the bounding box of a primitive * @param pr the primitive * @return the bounding box of the primitive \c pr */ template - Bounding_box compute_bbox(const Primitive& pr, const PM&)const + Bounding_box compute_bbox(const Primitive& pr, const PM&) const { return get(bbm, pr.id()); } - Bounding_box compute_bbox(const Primitive& pr, const Default&)const + Bounding_box compute_bbox(const Primitive& pr, const Default&) const { - return GeomTraits().construct_bbox_2_object()(internal::Primitive_helper::get_datum(pr, *this)); + return internal::Primitive_helper::get_datum(pr,*this).bbox(); } /// Comparison functions diff --git a/BGL/include/CGAL/boost/graph/Euler_operations.h b/BGL/include/CGAL/boost/graph/Euler_operations.h index 0a3b7e926db..3c5225638cc 100644 --- a/BGL/include/CGAL/boost/graph/Euler_operations.h +++ b/BGL/include/CGAL/boost/graph/Euler_operations.h @@ -1537,6 +1537,7 @@ does_satisfy_link_condition(typename boost::graph_traits::edge_descriptor * collapses an edge in a graph. * * \tparam Graph must be a model of `MutableFaceGraph` + * * Let `h` be the halfedge of `e`, and let `v0` and `v1` be the source and target vertices of `h`. * Let `p_h` and `p_o_h` be respectively the edges of `prev(h,g)` and `prev(opposite(h, g), g)`. * Let `o_n_h` and `o_n_o_h` be respectively the edges of `opposite(next(h,g))` and `opposite(next(opposite(h, g), g))`. diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/Snapping/snap.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/Snapping/snap.h index 62c893b7f4e..12c338c4739 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/Snapping/snap.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/Snapping/snap.h @@ -105,12 +105,19 @@ void simplify_range(HalfedgeRange& halfedge_range, typedef CGAL::dynamic_halfedge_property_t Halfedge_bool_tag; typedef typename boost::property_map::type Range_halfedges; - const bool all_hedges = (::CGAL::internal::exact_num_halfedges(tm)==halfedge_range.size()); +#ifdef CGAL_PMP_SNAP_DEBUG_OUTPUT + static int i = 0; + std::ofstream out_in("results/before_simplification_" + std::to_string(i++) + ".polylines.txt"); + out_in.precision(17); +#endif - Range_halfedges range_halfedges = get(Halfedge_bool_tag(), tm, all_hedges); - if (!all_hedges) - for(halfedge_descriptor h : halfedge_range) - put(range_halfedges, h, true); + Range_halfedges range_halfedges = get(Halfedge_bool_tag(), tm, false); + for(halfedge_descriptor h : halfedge_range) { +#ifdef CGAL_PMP_SNAP_DEBUG_OUTPUT + out_in << "2 " << get(vpm, source(h, tm)) << " " << get(vpm, target(h, tm)) << "\n"; +#endif + put(range_halfedges, h, true); + } CGAL_postcondition_code(const std::size_t initial_n = halfedge_range.size();) @@ -121,6 +128,9 @@ void simplify_range(HalfedgeRange& halfedge_range, while(!edges_to_test.empty()) { const halfedge_descriptor h = *(edges_to_test.begin()); + CGAL_precondition(is_border(h, tm)); + CGAL_precondition(!is_border(opposite(h, tm), tm)); + edges_to_test.erase(edges_to_test.begin()); const vertex_descriptor vs = source(h, tm); @@ -136,8 +146,7 @@ void simplify_range(HalfedgeRange& halfedge_range, if(gt.compare_squared_distance_3_object()(ps,pt,CGAL::square(max_tol)) == SMALLER) { - const halfedge_descriptor prev_h = prev(h, tm); - const halfedge_descriptor next_h = next(h, tm); + CGAL_precondition_code(const halfedge_descriptor prev_h = prev(h, tm);) const halfedge_descriptor prev_oh = prev(opposite(h, tm), tm); // check that the border has at least 4 edges not to create degenerate volumes @@ -190,19 +199,38 @@ void simplify_range(HalfedgeRange& halfedge_range, if(!CGAL::Euler::does_satisfy_link_condition(edge(h, tm), tm)) continue; + // Since `o_h` is not a border halfedge, `prev(opp(h))` gets replaced with `opp(next(opp(h)))`. + // But `prev(opp(h))` might have been be a border edge whereas `opp(next(opp(h)))` might not be. + // So, if `opp(prev(opp(h)))` was a border halfedge in the range, we must add `next(opp(h))` + // to the range. const halfedge_descriptor opoh = opposite(prev(opposite(h, tm), tm), tm); - if(is_border(opoh, tm)) + bool was_opoh_border_in_range = false; + const halfedge_descriptor noh = next(opposite(h, tm), tm); + + if(is_border(opoh, tm) && get(range_halfedges, opoh)) { + was_opoh_border_in_range = true; edges_to_test.erase(opoh); + } vertex_descriptor v = Euler::collapse_edge(edge(h, tm), tm); + CGAL_postcondition(bool(is_border(v, tm))); + CGAL_postcondition(target(prev_h, tm) == v); put(vpm, v, new_p); put(tolerance_map, v, new_tolerance); - if(get(range_halfedges, prev_h)) - edges_to_test.insert(prev_h); - if(next_h != opoh && get(range_halfedges, next_h)) - edges_to_test.insert(next_h); + if(was_opoh_border_in_range) + { + CGAL_assertion(is_border(noh, tm)); + put(range_halfedges, noh, true); + } + + for(halfedge_descriptor ih : halfedges_around_target(v, tm)) + { + if(get(range_halfedges, ih)) + edges_to_test.insert(ih); + } + ++collapsed_n; } } @@ -693,12 +721,18 @@ std::size_t split_edges(EdgesToSplitContainer& edges_to_split, halfedge_descriptor h_to_split = es.first; CGAL_assertion(is_border(h_to_split, tm_T)); +#ifdef CGAL_PMP_SNAP_DEBUG_PP + std::cout << " -.-.-. Splitting " << edge(h_to_split, tm_T) << " |||| " + << " Vs " << source(h_to_split, tm_T) << " (" << tm_T.point(source(h_to_split, tm_T)) << ")" + << " --- Vt " << target(h_to_split, tm_T) << " (" << tm_T.point(target(h_to_split, tm_T)) << ")" << std::endl; +#endif + Vertices_with_new_position& splitters = es.second; if(splitters.size() > 1) { #ifdef CGAL_PMP_SNAP_DEBUG_PP - std::cout << " _______ Multiple splitting points on the same halfedge" << std::endl; + std::cout << " _______ Multiple splitting points on the same halfedge, sorting..." << std::endl; #endif const Point_ref hsp = get(vpm_T, source(h_to_split, tm_T)); @@ -721,20 +755,36 @@ std::size_t split_edges(EdgesToSplitContainer& edges_to_split, const vertex_descriptor splitter_v = target(splitter_h, tm_S); const Point new_position = is_source_mesh_fixed ? get(vpm_S, splitter_v) : vnp.second; +#ifdef CGAL_PMP_SNAP_DEBUG_PP + std::cout << "With point: " << new_position << " (first choice: " << vnp.second << ")" << std::endl; +#endif + bool do_split = true; // In case of self-snapping, avoid degenerate caps const bool is_same_mesh = (&tm_T == &tm_S); - if(is_same_mesh && target(next(opposite(h_to_split, tm_T), tm_T), tm_T) == splitter_v) + if(is_same_mesh && target(next(opposite(h_to_split, tm_T), tm_T), tm_T) == splitter_v) { +#ifdef CGAL_PMP_SNAP_DEBUG_PP + std::cout << "Reject split (A)" << std::endl; +#endif do_split = false; + } // Do not split if it would create a degenerate needle if((new_position == get(vpm_T, target(h_to_split, tm_T))) || - (new_position == get(vpm_T, source(h_to_split, tm_T)))) + (new_position == get(vpm_T, source(h_to_split, tm_T)))) { +#ifdef CGAL_PMP_SNAP_DEBUG_PP + std::cout << "Reject split (B)" << std::endl; +#endif do_split = false; + } - if(!first_split && new_position == previous_split_position) + if(!first_split && new_position == previous_split_position) { +#ifdef CGAL_PMP_SNAP_DEBUG_PP + std::cout << "Reject split (C)" << std::endl; +#endif do_split = false; + } // check if the new faces after split will not be degenerate const Point& p0 = new_position; @@ -759,13 +809,21 @@ std::size_t split_edges(EdgesToSplitContainer& edges_to_split, if(first_split_face) { - if(p0p2 <= 0 || collinear(p0,p1,p2) || collinear(p0,p2,p3)) + if(p0p2 <= 0 || collinear(p0,p1,p2) || collinear(p0,p2,p3)) { +#ifdef CGAL_PMP_SNAP_DEBUG_PP + std::cout << "Reject split (D)" << std::endl; +#endif do_split = false; + } } else { - if(p1p3 <= 0 || collinear(p0,p1,p3) || collinear(p1,p2,p3)) + if(p1p3 <= 0 || collinear(p0,p1,p3) || collinear(p1,p2,p3)) { +#ifdef CGAL_PMP_SNAP_DEBUG_PP + std::cout << "Reject split (E)" << std::endl; +#endif do_split = false; + } } if(do_split && !is_source_mesh_fixed) @@ -774,6 +832,9 @@ std::size_t split_edges(EdgesToSplitContainer& edges_to_split, { if(!is_border(h,tm_S) && collinear(get(vpm_S, source(h,tm_S)), new_position, get(vpm_S, target(next(h,tm_S),tm_S)))) { +#ifdef CGAL_PMP_SNAP_DEBUG_PP + std::cout << "Reject split (F)" << std::endl; +#endif do_split = false; break; } @@ -784,10 +845,6 @@ std::size_t split_edges(EdgesToSplitContainer& edges_to_split, } #ifdef CGAL_PMP_SNAP_DEBUG_PP - std::cout << " -.-.-. Splitting " << edge(h_to_split, tm_T) << " |||| " - << " Vs " << source(h_to_split, tm_T) << " (" << tm_T.point(source(h_to_split, tm_T)) << ")" - << " --- Vt " << target(h_to_split, tm_T) << " (" << tm_T.point(target(h_to_split, tm_T)) << ")" << std::endl; - std::cout << "With point: " << new_position << " (init: " << vnp.second << ")" << std::endl; std::cout << "Actually split? " << do_split << std::endl; #endif @@ -942,11 +999,11 @@ std::size_t snap_non_conformal_one_way(const HalfedgeRange& halfedge_range_S, for(halfedge_descriptor h : halfedge_range_T) { - CGAL_precondition(is_border(edge(h, tm_T), tm_T)); + CGAL_precondition(is_border_edge(h, tm_T)); if(get(locked_halfedges_T, h)) { #ifdef CGAL_PMP_SNAP_DEBUG_PP - std::cout << edge(h, tm_T) << " is locked and not a valid target" << std::endl; + std::cout << edge(h, tm_T) << " [" << source(h, tm_T) << " - " << target(h, tm_T) << "] is locked and not a valid target" << std::endl; #endif continue; } diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/Snapping/snap_vertices.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/Snapping/snap_vertices.h index 5adbf99ff6f..d7ccabf700e 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/Snapping/snap_vertices.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/Snapping/snap_vertices.h @@ -246,7 +246,7 @@ public: #ifdef CGAL_PMP_SNAP_DEBUG_PP std::cout << "squared distance between " << va << " [" << get(m_vpm_A, va) << "] and " - << vb << " [" << get(m_vpm_B, vb) << "]: " << sq_dist + << vb << " [" << get(m_vpm_B, vb) << "]: " << CGAL::squared_distance(get(m_vpm_A, va), get(m_vpm_B, vb)) << " (tol a/b: " << tol_a << " " << tol_b << ") larger? " << (res == CGAL::LARGER) << std::endl; #endif @@ -755,8 +755,12 @@ std::size_t snap_vertices_two_way(const HalfedgeRange_A& halfedge_range_A, is_empty_range(halfedge_range_B.begin(), halfedge_range_B.end())) return 0; - // Vertex-Vertex snapping is performed by identify points which are already equal - // and grouping them together so that they are moved together + // Vertex-Vertex snapping identifies points which are already equal + // and groups them together so that they are moved together + +#ifdef CGAL_PMP_SNAP_DEBUG_PP + std::cout << "(A) Positions" << std::endl; +#endif // @todo all range building could be parallel (worth it?) Unique_positions unique_positions_A; @@ -766,7 +770,7 @@ std::size_t snap_vertices_two_way(const HalfedgeRange_A& halfedge_range_A, const FT tolerance = get(tolerance_map_A, v); #ifdef CGAL_PMP_SNAP_DEBUG_PP - std::cout << "Pos (A): " << v << " (" << get(vpm_A, v) << ")" << std::endl; + std::cout << " " << get(vpm_A, v) << std::endl; #endif Vertex_container nvc {{ h }}; @@ -784,6 +788,10 @@ std::size_t snap_vertices_two_way(const HalfedgeRange_A& halfedge_range_A, } } +#ifdef CGAL_PMP_SNAP_DEBUG_PP + std::cout << "(B) Positions" << std::endl; +#endif + // same for tm_B (@todo when doing boxes, avoid all that for self snapping + use self_intersection_d) Unique_positions unique_positions_B; for(halfedge_descriptor h : halfedge_range_B) @@ -792,7 +800,7 @@ std::size_t snap_vertices_two_way(const HalfedgeRange_A& halfedge_range_A, const FT tolerance = get(tolerance_map_B, v); #ifdef CGAL_PMP_SNAP_DEBUG_PP - std::cout << "Pos (B): " << v << " (" << get(vpm_B, v) << ")" << std::endl; + std::cout << " " << get(vpm_B, v) << std::endl; #endif Vertex_container nvc {{ h }}; diff --git a/Polygon_mesh_processing/test/Polygon_mesh_processing/CMakeLists.txt b/Polygon_mesh_processing/test/Polygon_mesh_processing/CMakeLists.txt index 73c1aeda5d0..1006e590292 100644 --- a/Polygon_mesh_processing/test/Polygon_mesh_processing/CMakeLists.txt +++ b/Polygon_mesh_processing/test/Polygon_mesh_processing/CMakeLists.txt @@ -143,7 +143,7 @@ else() message(STATUS "NOTICE: Tests are not using Ceres.") endif() -if(CGAL_ENABLE_TESTING) +if(CGAL_ENABLE_TESTING AND TARGET CGAL::Eigen3_support) set_tests_properties( "execution of triangulate_hole_Polyhedron_3_no_delaunay_test" "execution of triangulate_hole_Polyhedron_3_test" diff --git a/Triangulation_2/doc/Triangulation_2/Concepts/TriangulationTraits_2.h b/Triangulation_2/doc/Triangulation_2/Concepts/TriangulationTraits_2.h index 68d24483b34..827ac363719 100644 --- a/Triangulation_2/doc/Triangulation_2/Concepts/TriangulationTraits_2.h +++ b/Triangulation_2/doc/Triangulation_2/Concepts/TriangulationTraits_2.h @@ -248,6 +248,16 @@ Construct_triangle_2 construct_triangle_2_object(); /*! +*/ +Less_x_2 less_x_2_object(); + +/*! + +*/ +Less_y_2 less_y_2_object(); + +/*! + */ Compare_x_2 compare_x_2_object();