From ed70775ee93708f979f8fac970b5255548e5542a Mon Sep 17 00:00:00 2001 From: Andreas Fabri <andreas.fabri@geometryfactory.com> Date: Mon, 15 Apr 2024 11:28:13 +0100 Subject: [PATCH 01/17] Polygon_repair:: Use move semantics; Add Polygon_2::reserve() --- Polygon/include/CGAL/Multipolygon_with_holes_2.h | 2 ++ Polygon/include/CGAL/Polygon_2.h | 7 +++++++ Polygon/include/CGAL/Polygon_2/Polygon_2_impl.h | 2 ++ .../include/CGAL/Polygon_repair/repair.h | 14 ++++++++------ 4 files changed, 19 insertions(+), 6 deletions(-) diff --git a/Polygon/include/CGAL/Multipolygon_with_holes_2.h b/Polygon/include/CGAL/Multipolygon_with_holes_2.h index 50edf6d592d2..9c81bd955911 100644 --- a/Polygon/include/CGAL/Multipolygon_with_holes_2.h +++ b/Polygon/include/CGAL/Multipolygon_with_holes_2.h @@ -78,6 +78,8 @@ class Multipolygon_with_holes_2 { void add_polygon(const Polygon_2& pgn) { m_polygons.push_back(Polygon_with_holes_2(pgn)); } + void add_polygon(const Polygon_2&& pgn) { m_polygons.push_back(Polygon_with_holes_2(std::forward(pgn))); } + void add_polygon_with_holes(const Polygon_with_holes_2& pgn) { m_polygons.push_back(pgn); } void add_polygon_with_holes(Polygon_with_holes_2&& pgn) { m_polygons.emplace_back(std::move(pgn)); } diff --git a/Polygon/include/CGAL/Polygon_2.h b/Polygon/include/CGAL/Polygon_2.h index b2b7ab7340a8..ff97d3c89932 100644 --- a/Polygon/include/CGAL/Polygon_2.h +++ b/Polygon/include/CGAL/Polygon_2.h @@ -34,6 +34,7 @@ #include <CGAL/enum.h> #include <CGAL/Aff_transformation_2.h> +#include <CGAL/Container_helper.h> #include <CGAL/Polygon_2_algorithms.h> #include <CGAL/Polygon_2/Polygon_2_vertex_circulator.h> @@ -543,6 +544,12 @@ class Polygon_2 { container().resize(s); } + /// Calls `container().reserve(s)` if this is available for `Container`. + void reserve(std::size_t s) + { + internal::reserve(container(),s); + } + /// @} bool identical(const Polygon_2<Traits_P,Container_P> &q) const diff --git a/Polygon/include/CGAL/Polygon_2/Polygon_2_impl.h b/Polygon/include/CGAL/Polygon_2/Polygon_2_impl.h index 8ba112734283..d2b812f4b349 100644 --- a/Polygon/include/CGAL/Polygon_2/Polygon_2_impl.h +++ b/Polygon/include/CGAL/Polygon_2/Polygon_2_impl.h @@ -88,6 +88,7 @@ operator>>(std::istream &is, Polygon_2<Traits_P,Container_P>& p) if (is) { p.erase(p.vertices_begin(),p.vertices_end()); + p.reserve(n); for (int i=0; i<n; i++) { if(is >> point){ p.push_back(point); @@ -146,6 +147,7 @@ transform(const Transformation& t, const Polygon_2<Traits_P,Container_P>& p) { typedef typename Polygon_2<Traits_P,Container_P>::Vertex_const_iterator VI; Polygon_2<Traits_P,Container_P> result; + result.reserve(p.size()); for (VI i = p.vertices_begin(); i != p.vertices_end(); ++i) result.push_back(t(*i)); return result; diff --git a/Polygon_repair/include/CGAL/Polygon_repair/repair.h b/Polygon_repair/include/CGAL/Polygon_repair/repair.h index 0188f1630fb1..8aee2108d2a2 100644 --- a/Polygon_repair/include/CGAL/Polygon_repair/repair.h +++ b/Polygon_repair/include/CGAL/Polygon_repair/repair.h @@ -645,12 +645,14 @@ class Polygon_repair { reconstruct_ring(ring, face, opposite_vertex); // Put ring in polygons - Polygon_2<Kernel, Container> polygon(ring.begin(), ring.end()); + Polygon_2<Kernel, Container> polygon; + polygon.reserve(ring.size()); + polygon.insert(polygon.vertices_end(),ring.begin(), ring.end()); // std::cout << "Reconstructed ring for polygon " << face->label() << " with ccw? " << (polygon.orientation() == CGAL::COUNTERCLOCKWISE) << std::endl; if (polygon.orientation() == CGAL::COUNTERCLOCKWISE) { - polygons[face->label()-1] = polygon; + polygons[face->label()-1] = std::move(polygon); } else { - holes[face->label()-1].insert(polygon); + holes[face->label()-1].insert(std::move(polygon)); } break; } } @@ -658,11 +660,11 @@ class Polygon_repair { // Create polygons with holes and put in multipolygon std::set<Polygon_with_holes_2<Kernel, Container>, Polygon_with_holes_less> ordered_polygons; for (std::size_t i = 0; i < polygons.size(); ++i) { - ordered_polygons.insert(Polygon_with_holes_2<Kernel, Container>(polygons[i], holes[i].begin(), holes[i].end())); + ordered_polygons.insert(Polygon_with_holes_2<Kernel, Container>(std::move(polygons[i]), holes[i].begin(), holes[i].end())); } for (auto const& polygon: ordered_polygons) { // std::cout << "Adding polygon " << polygon << std::endl; - mp.add_polygon_with_holes(polygon); + mp.add_polygon_with_holes(std::move(polygon)); } } @@ -685,7 +687,7 @@ class Polygon_repair { return t; } - Multipolygon_with_holes_2<Kernel, Container> multipolygon() { + const Multipolygon_with_holes_2<Kernel, Container>& multipolygon() { return mp; } From 47ef1a271660de4f46e53ce3c3cdec32e523280a Mon Sep 17 00:00:00 2001 From: Andreas Fabri <andreas.fabri@geometryfactory.com> Date: Mon, 15 Apr 2024 12:06:03 +0100 Subject: [PATCH 02/17] Use std::make_move_iterator() --- Polygon_repair/include/CGAL/Polygon_repair/repair.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Polygon_repair/include/CGAL/Polygon_repair/repair.h b/Polygon_repair/include/CGAL/Polygon_repair/repair.h index 8aee2108d2a2..6254dc0232ad 100644 --- a/Polygon_repair/include/CGAL/Polygon_repair/repair.h +++ b/Polygon_repair/include/CGAL/Polygon_repair/repair.h @@ -660,7 +660,7 @@ class Polygon_repair { // Create polygons with holes and put in multipolygon std::set<Polygon_with_holes_2<Kernel, Container>, Polygon_with_holes_less> ordered_polygons; for (std::size_t i = 0; i < polygons.size(); ++i) { - ordered_polygons.insert(Polygon_with_holes_2<Kernel, Container>(std::move(polygons[i]), holes[i].begin(), holes[i].end())); + ordered_polygons.insert(Polygon_with_holes_2<Kernel, Container>(std::move(polygons[i]), std::make_move_iterator(holes[i].begin()), std::make_move_iterator(holes[i].end()))); } for (auto const& polygon: ordered_polygons) { // std::cout << "Adding polygon " << polygon << std::endl; From 92ccdbcc08860913cf3b7c9b848c07b0004789ca Mon Sep 17 00:00:00 2001 From: Andreas Fabri <andreas.fabri@geometryfactory.com> Date: Mon, 15 Apr 2024 13:07:00 +0100 Subject: [PATCH 03/17] fix forward --- Polygon/include/CGAL/Multipolygon_with_holes_2.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Polygon/include/CGAL/Multipolygon_with_holes_2.h b/Polygon/include/CGAL/Multipolygon_with_holes_2.h index 9c81bd955911..7ed5313e3efc 100644 --- a/Polygon/include/CGAL/Multipolygon_with_holes_2.h +++ b/Polygon/include/CGAL/Multipolygon_with_holes_2.h @@ -78,7 +78,7 @@ class Multipolygon_with_holes_2 { void add_polygon(const Polygon_2& pgn) { m_polygons.push_back(Polygon_with_holes_2(pgn)); } - void add_polygon(const Polygon_2&& pgn) { m_polygons.push_back(Polygon_with_holes_2(std::forward(pgn))); } + void add_polygon(Polygon_2&& pgn) { m_polygons.push_back(Polygon_with_holes_2(std::forward<Polygon_with_holes_2>(pgn))); } void add_polygon_with_holes(const Polygon_with_holes_2& pgn) { m_polygons.push_back(pgn); } From 2af58ecea3ade9f400fad4be7b3934557fa22672 Mon Sep 17 00:00:00 2001 From: Andreas Fabri <andreas.fabri@geometryfactory.com> Date: Mon, 15 Apr 2024 18:45:05 +0100 Subject: [PATCH 04/17] Make read_WKT() work with Multipolygon_with_holes --- .../include/CGAL/Multipolygon_with_holes_2.h | 13 +++++++- .../Polygon_repair/polygons2multipolygon.cpp | 32 +++++++++++++++++++ 2 files changed, 44 insertions(+), 1 deletion(-) create mode 100644 Polygon_repair/examples/Polygon_repair/polygons2multipolygon.cpp diff --git a/Polygon/include/CGAL/Multipolygon_with_holes_2.h b/Polygon/include/CGAL/Multipolygon_with_holes_2.h index 7ed5313e3efc..2449b9dd8eef 100644 --- a/Polygon/include/CGAL/Multipolygon_with_holes_2.h +++ b/Polygon/include/CGAL/Multipolygon_with_holes_2.h @@ -43,7 +43,7 @@ class Multipolygon_with_holes_2 { /// polygon with holes type using Polygon_with_holes_2 = CGAL::Polygon_with_holes_2<Kernel, Container>; - + using value_type = Polygon_with_holes_2; /// @} using Polygon_with_holes_container = std::deque<Polygon_with_holes_2>; @@ -72,10 +72,19 @@ class Multipolygon_with_holes_2 { Polygon_with_holes_iterator polygons_with_holes_end() { return m_polygons.end(); } + Polygon_with_holes_iterator begin() { return m_polygons.begin(); } + + Polygon_with_holes_iterator end() { return m_polygons.end(); } + Polygon_with_holes_const_iterator polygons_with_holes_begin() const { return m_polygons.begin(); } Polygon_with_holes_const_iterator polygons_with_holes_end() const { return m_polygons.end(); } + Polygon_with_holes_const_iterator begin() const { return m_polygons.begin(); } + + Polygon_with_holes_const_iterator end() const { return m_polygons.end(); } + + void add_polygon(const Polygon_2& pgn) { m_polygons.push_back(Polygon_with_holes_2(pgn)); } void add_polygon(Polygon_2&& pgn) { m_polygons.push_back(Polygon_with_holes_2(std::forward<Polygon_with_holes_2>(pgn))); } @@ -84,6 +93,8 @@ class Multipolygon_with_holes_2 { void add_polygon_with_holes(Polygon_with_holes_2&& pgn) { m_polygons.emplace_back(std::move(pgn)); } + void push_back(const Polygon_with_holes_2& pgn) { m_polygons.push_back(pgn); } + void erase_polygon_with_holes(Polygon_with_holes_iterator pit) { m_polygons.erase(pit); } void clear() { m_polygons.clear(); } diff --git a/Polygon_repair/examples/Polygon_repair/polygons2multipolygon.cpp b/Polygon_repair/examples/Polygon_repair/polygons2multipolygon.cpp new file mode 100644 index 000000000000..6e2289728218 --- /dev/null +++ b/Polygon_repair/examples/Polygon_repair/polygons2multipolygon.cpp @@ -0,0 +1,32 @@ +#include <iostream> +#include <fstream> +#include <deque> + +#include <CGAL/Exact_predicates_inexact_constructions_kernel.h> +#include <CGAL/Polygon_repair/repair.h> +#include <CGAL/IO/WKT.h> + +using Kernel = CGAL::Exact_predicates_inexact_constructions_kernel; +using Point_2 = Kernel::Point_2; +using Polygon_2 = CGAL::Polygon_2<Kernel>; +using Polygon_with_holes_2 = CGAL::Polygon_with_holes_2<Kernel>; +using Multipolygon_with_holes_2 = CGAL::Multipolygon_with_holes_2<Kernel>; + +int main(int argc, char* argv[]) +{ + std::ifstream in((argc > 1) ? argv[1] : CGAL::data_file_path("wkt/norway-polygons.wkt")); + + typedef std::vector<Point_2> MultiPoint; + typedef std::vector<Point_2> LineString; + typedef std::deque<LineString> MultiLineString; + + MultiPoint points; + MultiLineString polylines; + Multipolygon_with_holes_2 polygons; + CGAL::IO::read_WKT(in, points,polylines,polygons); + + Multipolygon_with_holes_2 mp = CGAL::Polygon_repair::repair(polygons); + CGAL::IO::write_multi_polygon_WKT(std::cout, mp); + + return 0; +} From 37740a9a2afd9af4261f782092b27c13932b9904 Mon Sep 17 00:00:00 2001 From: Andreas Fabri <andreas.fabri@geometryfactory.com> Date: Tue, 16 Apr 2024 06:41:30 +0100 Subject: [PATCH 05/17] Add smaller data set --- Polygon_repair/examples/Polygon_repair/data/flat.wkt | 4 ++++ .../examples/Polygon_repair/polygons2multipolygon.cpp | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) create mode 100644 Polygon_repair/examples/Polygon_repair/data/flat.wkt diff --git a/Polygon_repair/examples/Polygon_repair/data/flat.wkt b/Polygon_repair/examples/Polygon_repair/data/flat.wkt new file mode 100644 index 000000000000..681cd65d046c --- /dev/null +++ b/Polygon_repair/examples/Polygon_repair/data/flat.wkt @@ -0,0 +1,4 @@ +POLYGON((0 0, 40 0, 40 40, 0 40)) +POLYGON((10 10 , 30 10, 30 30, 0 30)) +POLYGON((1 1, 2 1, 2 2, 1 2)) +POLYGON((11 11, 12 11, 12 12, 11 12)) diff --git a/Polygon_repair/examples/Polygon_repair/polygons2multipolygon.cpp b/Polygon_repair/examples/Polygon_repair/polygons2multipolygon.cpp index 6e2289728218..5b3d8f59d1c8 100644 --- a/Polygon_repair/examples/Polygon_repair/polygons2multipolygon.cpp +++ b/Polygon_repair/examples/Polygon_repair/polygons2multipolygon.cpp @@ -14,7 +14,7 @@ using Multipolygon_with_holes_2 = CGAL::Multipolygon_with_holes_2<Kernel>; int main(int argc, char* argv[]) { - std::ifstream in((argc > 1) ? argv[1] : CGAL::data_file_path("wkt/norway-polygons.wkt")); + std::ifstream in((argc > 1) ? argv[1] : "data/flat.wkt"); typedef std::vector<Point_2> MultiPoint; typedef std::vector<Point_2> LineString; From 2408df555a114549dd59081a6a073c1a20f0d1e3 Mon Sep 17 00:00:00 2001 From: Andreas Fabri <andreas.fabri@geometryfactory.com> Date: Tue, 16 Apr 2024 07:18:03 +0100 Subject: [PATCH 06/17] Add some using --- .../include/CGAL/Polygon_repair/repair.h | 107 ++++++++++-------- 1 file changed, 58 insertions(+), 49 deletions(-) diff --git a/Polygon_repair/include/CGAL/Polygon_repair/repair.h b/Polygon_repair/include/CGAL/Polygon_repair/repair.h index 6254dc0232ad..def03b7dcb00 100644 --- a/Polygon_repair/include/CGAL/Polygon_repair/repair.h +++ b/Polygon_repair/include/CGAL/Polygon_repair/repair.h @@ -298,29 +298,39 @@ bool is_valid(const Multipolygon_with_holes_2<Kernel, Container>& multipolygon) template <class Kernel, class Container = std::vector<typename Kernel::Point_2>> class Polygon_repair { public: + using FT = typename Kernel::FT; + using Point_2 = typename Kernel::Point_2; using Vertex_base = CGAL::Triangulation_vertex_base_2<Kernel>; using Face_base = CGAL::Constrained_triangulation_face_base_2<Kernel>; using Face_base_with_repair_info = internal::Triangulation_face_base_with_repair_info_2<Kernel, Face_base>; using Triangulation_data_structure = CGAL::Triangulation_data_structure_2<Vertex_base, Face_base_with_repair_info>; - using Tag = typename std::conditional<std::is_floating_point<typename Kernel::FT>::value, + using Tag = typename std::conditional<std::is_floating_point<typename FT>::value, CGAL::Exact_predicates_tag, CGAL::Exact_intersections_tag>::type; using Constrained_Delaunay_triangulation = CGAL::Constrained_Delaunay_triangulation_2<Kernel, Triangulation_data_structure, Tag>; using Triangulation = internal::Triangulation_with_even_odd_constraints_2<Constrained_Delaunay_triangulation>; - // TODO: Edge_map and Vertex_map use std::set and set::map with exact kernels since Point_2 can't be hashed otherwise - using Edge_map = typename std::conditional<std::is_floating_point<typename Kernel::FT>::value, - std::unordered_set<std::pair<typename Kernel::Point_2, typename Kernel::Point_2>, - boost::hash<std::pair<typename Kernel::Point_2, typename Kernel::Point_2>>>, - std::set<std::pair<typename Kernel::Point_2, typename Kernel::Point_2>>>::type; - using Vertex_map = typename std::conditional<std::is_floating_point<typename Kernel::FT>::value, - std::unordered_map<typename Kernel::Point_2, typename Triangulation::Vertex_handle>, - std::map<typename Kernel::Point_2, typename Triangulation::Vertex_handle>>::type; + using Vertex_handle = typename Triangulation::Vertex_handle; + using Face_handle = typename Triangulation::Face_handle; + using Face_circulator = typename Triangulation::Face_circulator; + using Edge = typename Triangulation::Edge; + + // TODO: Edge_map and Vertex_map use std::set and std::map with exact kernels since Point_2 can't be hashed otherwise + using Edge_map = typename std::conditional<std::is_floating_point<FT>::value, + std::unordered_set<std::pair<Point_2, Point_2>, + boost::hash<std::pair<Point_2, Point_2>>>, + std::set<std::pair<Point_2, Point_2>>>::type; + using Vertex_map = typename std::conditional<std::is_floating_point<FT>::value, + std::unordered_map<Point_2, Vertex_handle>, + std::map<Point_2, Vertex_handle>>::type; using Validation_tag = CGAL::No_constraint_intersection_tag; using Validation_triangulation = CGAL::Constrained_triangulation_2<Kernel, Triangulation_data_structure, Validation_tag>; + using Polygon_2 = CGAL::Polygon_2<Kernel, Container>; + using Polygon_with_holes_2 = CGAL::Polygon_with_holes_2<Kernel, Container>; + using Multipolygon_with_holes_2 = CGAL::Multipolygon_with_holes_2<Kernel, Container>; + struct Polygon_less { - using Polygon_2 = CGAL::Polygon_2<Kernel, Container>; bool operator()(const Polygon_2& pa, const Polygon_2& pb) const { typename Polygon_2::Vertex_iterator va = pa.vertices_begin(); typename Polygon_2::Vertex_iterator vb = pb.vertices_begin(); @@ -335,7 +345,6 @@ class Polygon_repair { }; struct Polygon_with_holes_less { - using Polygon_with_holes_2 = CGAL::Polygon_with_holes_2<Kernel, Container>; Polygon_less pl; bool operator()(const Polygon_with_holes_2& pa, const Polygon_with_holes_2& pb) const { if (pl(pa.outer_boundary(), pb.outer_boundary())) return true; @@ -358,12 +367,12 @@ class Polygon_repair { /// @{ // Add edges of the polygon to the triangulation - void add_to_triangulation_even_odd(const Polygon_2<Kernel, Container>& polygon) { + void add_to_triangulation_even_odd(const Polygon_2& polygon) { // Get unique edges for (auto const& edge: polygon.edges()) { if (edge.source() == edge.target()) continue; - std::pair<typename Kernel::Point_2, typename Kernel::Point_2> pair = (edge.source() < edge.target())? + std::pair<Point_2, Point_2> pair = (edge.source() < edge.target())? std::make_pair(edge.source(), edge.target()) : std::make_pair(edge.target(), edge.source()); auto inserted = unique_edges.insert(pair); if (!inserted.second) unique_edges.erase(inserted.first); @@ -371,10 +380,10 @@ class Polygon_repair { // Insert vertices Vertex_map vertices; - std::vector<std::pair<typename Triangulation::Vertex_handle, typename Triangulation::Vertex_handle>> edges_to_insert; + std::vector<std::pair<Vertex_handle, Vertex_handle>> edges_to_insert; edges_to_insert.reserve(unique_edges.size()); for (auto const& edge: unique_edges) { - typename Triangulation::Vertex_handle first_vertex, second_vertex; + Vertex_handle first_vertex, second_vertex; typename Vertex_map::const_iterator found = vertices.find(edge.first); if (found == vertices.end()) { first_vertex = t.insert(edge.first, search_start); @@ -399,12 +408,12 @@ class Polygon_repair { } // Add edges of the polygon to the triangulation - void add_to_triangulation_even_odd(const Polygon_with_holes_2<Kernel, Container>& polygon) { + void add_to_triangulation_even_odd(const Polygon_with_holes_2& polygon) { // Get unique edges for (auto const& edge: polygon.outer_boundary().edges()) { if (edge.source() == edge.target()) continue; - std::pair<typename Kernel::Point_2, typename Kernel::Point_2> pair = (edge.source() < edge.target())? + std::pair<Point_2, Point_2> pair = (edge.source() < edge.target())? std::make_pair(edge.source(), edge.target()) : std::make_pair(edge.target(), edge.source()); auto inserted = unique_edges.insert(pair); if (!inserted.second) unique_edges.erase(inserted.first); @@ -412,7 +421,7 @@ class Polygon_repair { for (auto const& hole: polygon.holes()) { for (auto const& edge: hole.edges()) { if (edge.source() == edge.target()) continue; - std::pair<typename Kernel::Point_2, typename Kernel::Point_2> pair = (edge.source() < edge.target())? + std::pair<Point_2, Point_2> pair = (edge.source() < edge.target())? std::make_pair(edge.source(), edge.target()) : std::make_pair(edge.target(), edge.source()); auto inserted = unique_edges.insert(pair); if (!inserted.second) unique_edges.erase(inserted.first); @@ -421,10 +430,10 @@ class Polygon_repair { // Insert vertices Vertex_map vertices; - std::vector<std::pair<typename Triangulation::Vertex_handle, typename Triangulation::Vertex_handle>> edges_to_insert; + std::vector<std::pair<Vertex_handle, Vertex_handle>> edges_to_insert; edges_to_insert.reserve(unique_edges.size()); for (auto const& edge: unique_edges) { - typename Triangulation::Vertex_handle first_vertex, second_vertex; + Vertex_handle first_vertex, second_vertex; typename Vertex_map::const_iterator found = vertices.find(edge.first); if (found == vertices.end()) { first_vertex = t.insert(edge.first, search_start); @@ -449,13 +458,13 @@ class Polygon_repair { } // Add edges of the polygon to the triangulation - void add_to_triangulation_even_odd(const Multipolygon_with_holes_2<Kernel, Container>& multipolygon) { + void add_to_triangulation_even_odd(const Multipolygon_with_holes_2& multipolygon) { // Get unique edges for (auto const& polygon: multipolygon.polygons_with_holes()) { for (auto const& edge: polygon.outer_boundary().edges()) { if (edge.source() == edge.target()) continue; - std::pair<typename Kernel::Point_2, typename Kernel::Point_2> pair = (edge.source() < edge.target())? + std::pair<Point_2, Point_2> pair = (edge.source() < edge.target())? std::make_pair(edge.source(), edge.target()) : std::make_pair(edge.target(), edge.source()); auto inserted = unique_edges.insert(pair); if (!inserted.second) unique_edges.erase(inserted.first); @@ -463,7 +472,7 @@ class Polygon_repair { for (auto const& hole: polygon.holes()) { for (auto const& edge: hole.edges()) { if (edge.source() == edge.target()) continue; - std::pair<typename Kernel::Point_2, typename Kernel::Point_2> pair = (edge.source() < edge.target())? + std::pair<Point_2, Point_2> pair = (edge.source() < edge.target())? std::make_pair(edge.source(), edge.target()) : std::make_pair(edge.target(), edge.source()); auto inserted = unique_edges.insert(pair); if (!inserted.second) unique_edges.erase(inserted.first); @@ -473,10 +482,10 @@ class Polygon_repair { // Insert vertices Vertex_map vertices; - std::vector<std::pair<typename Triangulation::Vertex_handle, typename Triangulation::Vertex_handle>> edges_to_insert; + std::vector<std::pair<Vertex_handle, Vertex_handle>> edges_to_insert; edges_to_insert.reserve(unique_edges.size()); for (auto const& edge: unique_edges) { - typename Triangulation::Vertex_handle first_vertex, second_vertex; + Vertex_handle first_vertex, second_vertex; typename Vertex_map::const_iterator found = vertices.find(edge.first); if (found == vertices.end()) { first_vertex = t.insert(edge.first, search_start); @@ -503,18 +512,18 @@ class Polygon_repair { // Label a region of adjacent triangles without passing through constraints // adjacent triangles that involve passing through constraints are added to to_check template <class T> - static void label_region(T& tt, typename T::Face_handle face, int label, - std::list<typename T::Face_handle>& to_check, + static void label_region(T& tt, Face_handle face, int label, + std::list<Face_handle>& to_check, std::list<int>& to_check_added_by) { // std::cout << "Labelling region with " << label << std::endl; - std::list<typename Triangulation::Face_handle> to_check_in_region; + std::list<Face_handle> to_check_in_region; face->label() = label; to_check_in_region.push_back(face); face->processed() = true; // processed means added to a list (to ensure elements are only added once) while (!to_check_in_region.empty()) { for (int neighbour = 0; neighbour < 3; ++neighbour) { - if (!tt.is_constrained(typename Triangulation::Edge(to_check_in_region.front(), neighbour))) { + if (!tt.is_constrained(Edge(to_check_in_region.front(), neighbour))) { if (to_check_in_region.front()->neighbor(neighbour)->label() == 0) { // unlabeled to_check_in_region.front()->neighbor(neighbour)->label() = label; to_check_in_region.push_back(to_check_in_region.front()->neighbor(neighbour)); @@ -538,15 +547,15 @@ class Polygon_repair { for (auto vertex: t.all_vertex_handles()) { typename Triangulation::Edge_circulator first_edge = t.incident_edges(vertex); typename Triangulation::Edge_circulator current_edge = first_edge; - std::vector<typename Triangulation::Edge> incident_constrained_edges; + std::vector<Edge> incident_constrained_edges; do { if (t.is_constrained(*current_edge)) { incident_constrained_edges.push_back(*current_edge); } ++current_edge; } while (current_edge != first_edge); if (incident_constrained_edges.size() == 2) { - typename Kernel::Point_2 v1 = incident_constrained_edges.front().first->vertex(incident_constrained_edges.front().first->ccw(incident_constrained_edges.front().second))->point(); - typename Kernel::Point_2 v2 = incident_constrained_edges.back().first->vertex(incident_constrained_edges.back().first->ccw(incident_constrained_edges.back().second))->point(); + Point_2 v1 = incident_constrained_edges.front().first->vertex(incident_constrained_edges.front().first->ccw(incident_constrained_edges.front().second))->point(); + Point_2 v2 = incident_constrained_edges.back().first->vertex(incident_constrained_edges.back().first->ccw(incident_constrained_edges.back().second))->point(); if (CGAL::collinear(v1, vertex->point(), v2)) { // std::cout << "Collinear points" << std::endl; // std::cout << "v1: " << v1 << std::endl; @@ -567,7 +576,7 @@ class Polygon_repair { // Label exterior with label -1, marking it as processed and // putting interior triangles adjacent to it in to_check - std::list<typename Triangulation::Face_handle> to_check; + std::list<Face_handle> to_check; std::list<int> to_check_added_by; label_region(t, t.infinite_face(), -1, to_check, to_check_added_by); @@ -589,21 +598,21 @@ class Polygon_repair { } // Reconstruct ring boundary starting from an edge (face + opposite vertex) that is part of it - void reconstruct_ring(std::list<typename Kernel::Point_2>& ring, - typename Triangulation::Face_handle face_adjacent_to_boundary, + void reconstruct_ring(std::list<Point_2>& ring, + Face_handle face_adjacent_to_boundary, int opposite_vertex) { // std::cout << "Reconstructing ring for face " << face_adjacent_to_boundary->label() << "..." << std::endl; // Create ring - typename Triangulation::Face_handle current_face = face_adjacent_to_boundary; + Face_handle current_face = face_adjacent_to_boundary; int current_opposite_vertex = opposite_vertex; do { CGAL_assertion(current_face->label() == face_adjacent_to_boundary->label()); current_face->processed() = true; - typename Triangulation::Vertex_handle pivot_vertex = current_face->vertex(current_face->cw(current_opposite_vertex)); + Vertex_handle pivot_vertex = current_face->vertex(current_face->cw(current_opposite_vertex)); // std::cout << "\tAdding point " << pivot_vertex->point() << std::endl; ring.push_back(pivot_vertex->point()); - typename Triangulation::Face_circulator fc = t.incident_faces(pivot_vertex, current_face); + Face_circulator fc = t.incident_faces(pivot_vertex, current_face); do { ++fc; } while (fc->label() != current_face->label()); @@ -613,8 +622,8 @@ class Polygon_repair { current_opposite_vertex != opposite_vertex); // Start at lexicographically smallest vertex - typename std::list<typename Kernel::Point_2>::iterator smallest_vertex = ring.begin(); - for (typename std::list<typename Kernel::Point_2>::iterator current_vertex = ring.begin(); + typename std::list<Point_2>::iterator smallest_vertex = ring.begin(); + for (typename std::list<Point_2>::iterator current_vertex = ring.begin(); current_vertex != ring.end(); ++current_vertex) { if (*current_vertex < *smallest_vertex) smallest_vertex = current_vertex; } @@ -626,8 +635,8 @@ class Polygon_repair { // Reconstruct multipolygon based on the triangles labeled as inside the polygon void reconstruct_multipolygon() { mp.clear(); - std::vector<Polygon_2<Kernel, Container>> polygons; // outer boundaries - std::vector<std::set<Polygon_2<Kernel, Container>, Polygon_less>> holes; // holes are ordered (per polygon) + std::vector<Polygon_2> polygons; // outer boundaries + std::vector<std::set<Polygon_2, Polygon_less>> holes; // holes are ordered (per polygon) polygons.resize(number_of_polygons); holes.resize(number_of_polygons); @@ -641,11 +650,11 @@ class Polygon_repair { if (face->label() == face->neighbor(opposite_vertex)->label()) continue; // not adjacent to boundary // Reconstruct ring - std::list<typename Kernel::Point_2> ring; + std::list<Point_2> ring; reconstruct_ring(ring, face, opposite_vertex); // Put ring in polygons - Polygon_2<Kernel, Container> polygon; + Polygon_2 polygon; polygon.reserve(ring.size()); polygon.insert(polygon.vertices_end(),ring.begin(), ring.end()); // std::cout << "Reconstructed ring for polygon " << face->label() << " with ccw? " << (polygon.orientation() == CGAL::COUNTERCLOCKWISE) << std::endl; @@ -658,9 +667,9 @@ class Polygon_repair { } // Create polygons with holes and put in multipolygon - std::set<Polygon_with_holes_2<Kernel, Container>, Polygon_with_holes_less> ordered_polygons; + std::set<Polygon_with_holes_2, Polygon_with_holes_less> ordered_polygons; for (std::size_t i = 0; i < polygons.size(); ++i) { - ordered_polygons.insert(Polygon_with_holes_2<Kernel, Container>(std::move(polygons[i]), std::make_move_iterator(holes[i].begin()), std::make_move_iterator(holes[i].end()))); + ordered_polygons.insert(Polygon_with_holes_2(std::move(polygons[i]), std::make_move_iterator(holes[i].begin()), std::make_move_iterator(holes[i].end()))); } for (auto const& polygon: ordered_polygons) { // std::cout << "Adding polygon " << polygon << std::endl; @@ -687,7 +696,7 @@ class Polygon_repair { return t; } - const Multipolygon_with_holes_2<Kernel, Container>& multipolygon() { + const Multipolygon_with_holes_2& multipolygon() { return mp; } @@ -697,9 +706,9 @@ class Polygon_repair { protected: Triangulation t; Edge_map unique_edges; - Multipolygon_with_holes_2<Kernel, Container> mp; + Multipolygon_with_holes_2 mp; int number_of_polygons, number_of_holes; - typename Triangulation::Face_handle search_start; + Face_handle search_start; }; #endif // DOXYGEN_RUNNING From 267ab235992202826b1c86a070376b53d59da2b5 Mon Sep 17 00:00:00 2001 From: Andreas Fabri <andreas.fabri@geometryfactory.com> Date: Tue, 16 Apr 2024 08:22:05 +0100 Subject: [PATCH 07/17] remove typename --- Polygon_repair/include/CGAL/Polygon_repair/repair.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Polygon_repair/include/CGAL/Polygon_repair/repair.h b/Polygon_repair/include/CGAL/Polygon_repair/repair.h index def03b7dcb00..8f420a478d87 100644 --- a/Polygon_repair/include/CGAL/Polygon_repair/repair.h +++ b/Polygon_repair/include/CGAL/Polygon_repair/repair.h @@ -304,7 +304,7 @@ class Polygon_repair { using Face_base = CGAL::Constrained_triangulation_face_base_2<Kernel>; using Face_base_with_repair_info = internal::Triangulation_face_base_with_repair_info_2<Kernel, Face_base>; using Triangulation_data_structure = CGAL::Triangulation_data_structure_2<Vertex_base, Face_base_with_repair_info>; - using Tag = typename std::conditional<std::is_floating_point<typename FT>::value, + using Tag = typename std::conditional<std::is_floating_point<FT>::value, CGAL::Exact_predicates_tag, CGAL::Exact_intersections_tag>::type; using Constrained_Delaunay_triangulation = CGAL::Constrained_Delaunay_triangulation_2<Kernel, Triangulation_data_structure, Tag>; From fcff28f0aa0c6567f145b6fdfb8cf8542bb75eb1 Mon Sep 17 00:00:00 2001 From: Andreas Fabri <andreas.fabri@geometryfactory.com> Date: Tue, 16 Apr 2024 08:22:23 +0100 Subject: [PATCH 08/17] move() -> forward<>() --- Polygon/include/CGAL/General_polygon_with_holes_2.h | 6 +++--- Polygon/include/CGAL/Multipolygon_with_holes_2.h | 2 +- Polygon/include/CGAL/Polygon_with_holes_2.h | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Polygon/include/CGAL/General_polygon_with_holes_2.h b/Polygon/include/CGAL/General_polygon_with_holes_2.h index bb19fcf99436..3034e1128342 100644 --- a/Polygon/include/CGAL/General_polygon_with_holes_2.h +++ b/Polygon/include/CGAL/General_polygon_with_holes_2.h @@ -65,7 +65,7 @@ class General_polygon_with_holes_2 { {} explicit General_polygon_with_holes_2(Polygon_2&& pgn_boundary) : - m_pgn(std::move(pgn_boundary)) + m_pgn(std::forward<Polygon_2>(pgn_boundary)) {} template <typename HolesInputIterator> @@ -80,7 +80,7 @@ class General_polygon_with_holes_2 { General_polygon_with_holes_2(Polygon_2&& pgn_boundary, HolesInputIterator h_begin, HolesInputIterator h_end) : - m_pgn(std::move(pgn_boundary)), + m_pgn(std::forward<Polygon_2>(pgn_boundary)), m_holes(h_begin, h_end) {} @@ -104,7 +104,7 @@ class General_polygon_with_holes_2 { void add_hole(const Polygon_2& pgn_hole) { m_holes.push_back(pgn_hole); } - void add_hole(Polygon_2&& pgn_hole) { m_holes.emplace_back(std::move(pgn_hole)); } + void add_hole(Polygon_2&& pgn_hole) { m_holes.emplace_back(std::forward<Polygon_2>(pgn_hole)); } void erase_hole(Hole_iterator hit) { m_holes.erase(hit); } diff --git a/Polygon/include/CGAL/Multipolygon_with_holes_2.h b/Polygon/include/CGAL/Multipolygon_with_holes_2.h index 2449b9dd8eef..36cad53ecb3d 100644 --- a/Polygon/include/CGAL/Multipolygon_with_holes_2.h +++ b/Polygon/include/CGAL/Multipolygon_with_holes_2.h @@ -91,7 +91,7 @@ class Multipolygon_with_holes_2 { void add_polygon_with_holes(const Polygon_with_holes_2& pgn) { m_polygons.push_back(pgn); } - void add_polygon_with_holes(Polygon_with_holes_2&& pgn) { m_polygons.emplace_back(std::move(pgn)); } + void add_polygon_with_holes(Polygon_with_holes_2&& pgn) { m_polygons.emplace_back(std::forward<Polygon_with_holes_2>(pgn)); } void push_back(const Polygon_with_holes_2& pgn) { m_polygons.push_back(pgn); } diff --git a/Polygon/include/CGAL/Polygon_with_holes_2.h b/Polygon/include/CGAL/Polygon_with_holes_2.h index 23eb826e9b2a..8f85085ed905 100644 --- a/Polygon/include/CGAL/Polygon_with_holes_2.h +++ b/Polygon/include/CGAL/Polygon_with_holes_2.h @@ -65,7 +65,7 @@ class Polygon_with_holes_2 : /*! Move constructor */ explicit Polygon_with_holes_2 (Polygon_2&& pgn_boundary) : - Base (std::move(pgn_boundary)) + Base (std::forward<Polygon_2>(pgn_boundary)) {} /*! Constructor from a polygon (outer boundary) and hole polygons. */ @@ -84,7 +84,7 @@ class Polygon_with_holes_2 : Polygon_with_holes_2 (Polygon_2&& pgn_boundary, HolesInputIterator h_begin, HolesInputIterator h_end) : - Base (std::move(pgn_boundary), h_begin, h_end) + Base (std::forward<Polygon_2>(pgn_boundary), h_begin, h_end) {} /*! Obtain the bounding box of the polygon with holes */ From 3effd785c4019297cd431621a6d31f1fda0d6ab3 Mon Sep 17 00:00:00 2001 From: Andreas Fabri <andreas.fabri@geometryfactory.com> Date: Tue, 16 Apr 2024 09:05:50 +0100 Subject: [PATCH 09/17] Add transform to Polygon_with_holes and Multipolygon_with_holes --- .../doc/Kernel_23/CGAL/Aff_transformation_2.h | 20 ++++---- .../include/CGAL/Multipolygon_with_holes_2.h | 12 +++++ Polygon/include/CGAL/Polygon_with_holes_2.h | 13 +++++ .../Polygon/Multipolygon_with_holes_test.cpp | 49 +++++++++++++++++++ .../test/Polygon/Polygon_with_holes_test.cpp | 8 ++- 5 files changed, 91 insertions(+), 11 deletions(-) create mode 100644 Polygon/test/Polygon/Multipolygon_with_holes_test.cpp diff --git a/Kernel_23/doc/Kernel_23/CGAL/Aff_transformation_2.h b/Kernel_23/doc/Kernel_23/CGAL/Aff_transformation_2.h index bd9fd496af3a..a47111181d44 100644 --- a/Kernel_23/doc/Kernel_23/CGAL/Aff_transformation_2.h +++ b/Kernel_23/doc/Kernel_23/CGAL/Aff_transformation_2.h @@ -45,16 +45,16 @@ therefore do not appear in the constructors. \cgalHeading{Example} \code -typedef Cartesian<double> K; -typedef Aff_transformation_2<K> Transformation; -typedef Point_2<K> Point; -typedef Vector_2<K> Vector; -typedef Direction_2<K> Direction; - -Transformation rotate(ROTATION, sin(pi), cos(pi)); -Transformation rational_rotate(ROTATION,Direction(1,1), 1, 100); -Transformation translate(TRANSLATION, Vector(-2, 0)); -Transformation scale(SCALING, 3); +typedef CGAL::Simple_cartesian<double> K; +typedef CGAL::Aff_transformation_2<K> Transformation; +typedef CGAL::Point_2<K> Point; +typedef CGAL::Vector_2<K> Vector; +typedef CGAL::Direction_2<K> Direction; + +Transformation rotate(CGAL::ROTATION, sin(pi), cos(pi)); +Transformation rational_rotate(CGAL::ROTATION,Direction(1,1), 1, 100); +Transformation translate(CGAL::TRANSLATION, Vector(-2, 0)); +Transformation scale(CGAL::SCALING, 3); Point q(0, 1); q = rational_rotate(q); diff --git a/Polygon/include/CGAL/Multipolygon_with_holes_2.h b/Polygon/include/CGAL/Multipolygon_with_holes_2.h index 36cad53ecb3d..fcdaa3d6b695 100644 --- a/Polygon/include/CGAL/Multipolygon_with_holes_2.h +++ b/Polygon/include/CGAL/Multipolygon_with_holes_2.h @@ -193,6 +193,18 @@ std::ostream& operator<<(std::ostream& os, } } +template <class Transformation, class Kernel, class Container> +Multipolygon_with_holes_2<Kernel, Container> transform(const Transformation& t, + const Multipolygon_with_holes_2<Kernel, Container>& mp) + { + Multipolygon_with_holes_2<Kernel, Container> result; + for(const auto& pwh : mp.polygons_with_holes()){ + result.add_polygon_with_holes(std::move(transform(t, pwh))); + } + return result; + + } + } //namespace CGAL diff --git a/Polygon/include/CGAL/Polygon_with_holes_2.h b/Polygon/include/CGAL/Polygon_with_holes_2.h index 8f85085ed905..fa7bb9e290c9 100644 --- a/Polygon/include/CGAL/Polygon_with_holes_2.h +++ b/Polygon/include/CGAL/Polygon_with_holes_2.h @@ -89,8 +89,21 @@ class Polygon_with_holes_2 : /*! Obtain the bounding box of the polygon with holes */ Bbox_2 bbox() const { return this->outer_boundary().bbox(); } + }; + template <class Transformation, class Kernel, class Container> + Polygon_with_holes_2<Kernel,Container> transform(const Transformation& t, + const Polygon_with_holes_2<Kernel,Container>& pwh) + { + Polygon_with_holes_2<Kernel,Container> result(transform(t, pwh.outer_boundary())); + for(const auto& hole : pwh.holes()){ + result.add_hole(std::move(transform(t, hole))); + } + return result; + } + + //-----------------------------------------------------------------------// // operator<< //-----------------------------------------------------------------------// diff --git a/Polygon/test/Polygon/Multipolygon_with_holes_test.cpp b/Polygon/test/Polygon/Multipolygon_with_holes_test.cpp new file mode 100644 index 000000000000..1257db73f903 --- /dev/null +++ b/Polygon/test/Polygon/Multipolygon_with_holes_test.cpp @@ -0,0 +1,49 @@ +#include <CGAL/Simple_cartesian.h> +#include <CGAL/Polygon_2.h> +#include <CGAL/Polygon_with_holes_2.h> +#include <CGAL/Multipolygon_with_holes_2.h> + +#include <vector> +#include <iostream> +#include <cassert> +#include <iterator> + + +typedef CGAL::Simple_cartesian<double> K; +typedef K::Point_2 Point; +typedef K::Vector_2 Vector_2; +typedef K::Aff_transformation_2 Transformation; + +typedef CGAL::Polygon_2<K> Polygon_2; +typedef CGAL::Polygon_with_holes_2<K> Polygon_with_holes_2; +typedef CGAL::Multipolygon_with_holes_2<K> Multipolygon_with_holes_2; + +int main() +{ + std::array<Point,4> outer = { Point(0, 0), Point(10, 0), Point(10, 10), Point(0, 10) }; + std::array<Point, 4> hole1 = { Point(1, 1), Point(1, 2), Point(2, 2), Point(2, 1) }; + std::array<Point, 4> hole2 = { Point(3, 3), Point(3, 4), Point(4, 4), Point(4, 3) }; + + std::vector<Polygon_2> holes; + holes.reserve(2); + holes.emplace_back(hole1.begin(), hole1.end()); + holes.emplace_back(hole2.begin(), hole2.end()); + + Polygon_2 pouter(outer.begin(), outer.end()); + + Polygon_with_holes_2 pwh(std::move(pouter), std::move_iterator<std::vector<Polygon_2>::iterator>(holes.begin()), std::move_iterator<std::vector<Polygon_2>::iterator>(holes.end())); + + + Transformation translate(CGAL::TRANSLATION, Vector_2(20, 20)); + Polygon_with_holes_2 pwhc = CGAL::transform(translate, pwh); + + Multipolygon_with_holes_2 mp; + mp.add_polygon_with_holes(pwh); + mp.add_polygon_with_holes(pwhc); + + mp = CGAL::transform(Transformation(CGAL::SCALING, 2.0), mp); + + std::cout << mp << std::endl; + + return 0; +} diff --git a/Polygon/test/Polygon/Polygon_with_holes_test.cpp b/Polygon/test/Polygon/Polygon_with_holes_test.cpp index 97a3fc80fd18..482ab1af20d6 100644 --- a/Polygon/test/Polygon/Polygon_with_holes_test.cpp +++ b/Polygon/test/Polygon/Polygon_with_holes_test.cpp @@ -10,7 +10,8 @@ typedef CGAL::Simple_cartesian<double> K; typedef K::Point_2 Point; - +typedef K::Vector_2 Vector_2; +typedef K::Aff_transformation_2 Transformation; typedef CGAL::Polygon_2<K> Polygon_2; typedef CGAL::Polygon_with_holes_2<K> Polygon_with_holes_2; @@ -41,5 +42,10 @@ int main() assert(pwh.outer_boundary().is_empty()); Polygon_with_holes_2 pwh_move_assigned; pwh_move_assigned = std::move(pwh_copy); + + std::cout << pwh_move_assigned << std::endl << "translated by Vector_2(2.0, 2.0)" << std::endl; + Transformation translate(CGAL::TRANSLATION, Vector_2(2, 2)); + pwh_move_assigned = CGAL::transform(translate, pwh_move_assigned); + std::cout << pwh_move_assigned << std::endl; return 0; } From 5d6874df85af784d92169b1607b2ac616327974b Mon Sep 17 00:00:00 2001 From: Andreas Fabri <andreas.fabri@geometryfactory.com> Date: Tue, 16 Apr 2024 10:40:12 +0200 Subject: [PATCH 10/17] Apply suggestions from code review Co-authored-by: Laurent Rineau <Laurent.Rineau@cgal.org> --- Polygon/include/CGAL/General_polygon_with_holes_2.h | 6 +++--- Polygon/include/CGAL/Multipolygon_with_holes_2.h | 6 +++--- Polygon/include/CGAL/Polygon_with_holes_2.h | 6 +++--- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/Polygon/include/CGAL/General_polygon_with_holes_2.h b/Polygon/include/CGAL/General_polygon_with_holes_2.h index 3034e1128342..bb19fcf99436 100644 --- a/Polygon/include/CGAL/General_polygon_with_holes_2.h +++ b/Polygon/include/CGAL/General_polygon_with_holes_2.h @@ -65,7 +65,7 @@ class General_polygon_with_holes_2 { {} explicit General_polygon_with_holes_2(Polygon_2&& pgn_boundary) : - m_pgn(std::forward<Polygon_2>(pgn_boundary)) + m_pgn(std::move(pgn_boundary)) {} template <typename HolesInputIterator> @@ -80,7 +80,7 @@ class General_polygon_with_holes_2 { General_polygon_with_holes_2(Polygon_2&& pgn_boundary, HolesInputIterator h_begin, HolesInputIterator h_end) : - m_pgn(std::forward<Polygon_2>(pgn_boundary)), + m_pgn(std::move(pgn_boundary)), m_holes(h_begin, h_end) {} @@ -104,7 +104,7 @@ class General_polygon_with_holes_2 { void add_hole(const Polygon_2& pgn_hole) { m_holes.push_back(pgn_hole); } - void add_hole(Polygon_2&& pgn_hole) { m_holes.emplace_back(std::forward<Polygon_2>(pgn_hole)); } + void add_hole(Polygon_2&& pgn_hole) { m_holes.emplace_back(std::move(pgn_hole)); } void erase_hole(Hole_iterator hit) { m_holes.erase(hit); } diff --git a/Polygon/include/CGAL/Multipolygon_with_holes_2.h b/Polygon/include/CGAL/Multipolygon_with_holes_2.h index fcdaa3d6b695..39ebd29dff32 100644 --- a/Polygon/include/CGAL/Multipolygon_with_holes_2.h +++ b/Polygon/include/CGAL/Multipolygon_with_holes_2.h @@ -87,11 +87,11 @@ class Multipolygon_with_holes_2 { void add_polygon(const Polygon_2& pgn) { m_polygons.push_back(Polygon_with_holes_2(pgn)); } - void add_polygon(Polygon_2&& pgn) { m_polygons.push_back(Polygon_with_holes_2(std::forward<Polygon_with_holes_2>(pgn))); } + void add_polygon(Polygon_2&& pgn) { m_polygons.emplace_back(std::move(pgn)); } void add_polygon_with_holes(const Polygon_with_holes_2& pgn) { m_polygons.push_back(pgn); } - void add_polygon_with_holes(Polygon_with_holes_2&& pgn) { m_polygons.emplace_back(std::forward<Polygon_with_holes_2>(pgn)); } + void add_polygon_with_holes(Polygon_with_holes_2&& pgn) { m_polygons.emplace_back(std::move(pgn)); } void push_back(const Polygon_with_holes_2& pgn) { m_polygons.push_back(pgn); } @@ -199,7 +199,7 @@ Multipolygon_with_holes_2<Kernel, Container> transform(const Transformation& t, { Multipolygon_with_holes_2<Kernel, Container> result; for(const auto& pwh : mp.polygons_with_holes()){ - result.add_polygon_with_holes(std::move(transform(t, pwh))); + result.add_polygon_with_holes(transform(t, pwh)); } return result; diff --git a/Polygon/include/CGAL/Polygon_with_holes_2.h b/Polygon/include/CGAL/Polygon_with_holes_2.h index fa7bb9e290c9..e551278bdb55 100644 --- a/Polygon/include/CGAL/Polygon_with_holes_2.h +++ b/Polygon/include/CGAL/Polygon_with_holes_2.h @@ -65,7 +65,7 @@ class Polygon_with_holes_2 : /*! Move constructor */ explicit Polygon_with_holes_2 (Polygon_2&& pgn_boundary) : - Base (std::forward<Polygon_2>(pgn_boundary)) + Base (std::move(pgn_boundary)) {} /*! Constructor from a polygon (outer boundary) and hole polygons. */ @@ -84,7 +84,7 @@ class Polygon_with_holes_2 : Polygon_with_holes_2 (Polygon_2&& pgn_boundary, HolesInputIterator h_begin, HolesInputIterator h_end) : - Base (std::forward<Polygon_2>(pgn_boundary), h_begin, h_end) + Base (std::move(pgn_boundary), h_begin, h_end) {} /*! Obtain the bounding box of the polygon with holes */ @@ -98,7 +98,7 @@ class Polygon_with_holes_2 : { Polygon_with_holes_2<Kernel,Container> result(transform(t, pwh.outer_boundary())); for(const auto& hole : pwh.holes()){ - result.add_hole(std::move(transform(t, hole))); + result.add_hole(transform(t, hole)); } return result; } From c8c67472b0f19ce312d7966dec7f6207c9545bef Mon Sep 17 00:00:00 2001 From: Andreas Fabri <andreas.fabri@geometryfactory.com> Date: Tue, 16 Apr 2024 10:28:19 +0100 Subject: [PATCH 11/17] Add Mpwh::bbox() --- Polygon/include/CGAL/Multipolygon_with_holes_2.h | 10 ++++++++++ Polygon/test/Polygon/Multipolygon_with_holes_test.cpp | 2 ++ 2 files changed, 12 insertions(+) diff --git a/Polygon/include/CGAL/Multipolygon_with_holes_2.h b/Polygon/include/CGAL/Multipolygon_with_holes_2.h index 39ebd29dff32..8636626d1a9f 100644 --- a/Polygon/include/CGAL/Multipolygon_with_holes_2.h +++ b/Polygon/include/CGAL/Multipolygon_with_holes_2.h @@ -101,6 +101,16 @@ class Multipolygon_with_holes_2 { Size number_of_polygons_with_holes() const { return static_cast<Size>(m_polygons.size()); } + Bbox_2 bbox() const + { + Bbox_2 bb; + for(const auto& pwh : polygons_with_holes()){ + bb += pwh.bbox(); + } + return bb; + } + + protected: Polygon_with_holes_container m_polygons; }; diff --git a/Polygon/test/Polygon/Multipolygon_with_holes_test.cpp b/Polygon/test/Polygon/Multipolygon_with_holes_test.cpp index 1257db73f903..7592211bd436 100644 --- a/Polygon/test/Polygon/Multipolygon_with_holes_test.cpp +++ b/Polygon/test/Polygon/Multipolygon_with_holes_test.cpp @@ -45,5 +45,7 @@ int main() std::cout << mp << std::endl; + CGAL::Bbox_2 bb = mp.bbox(); + return 0; } From 02dd6ad63d72814fb6f906cabd08c19e1a5afd5a Mon Sep 17 00:00:00 2001 From: Andreas Fabri <andreas.fabri@geometryfactory.com> Date: Wed, 17 Apr 2024 08:05:22 +0100 Subject: [PATCH 12/17] Fix warning in test --- Polygon/test/Polygon/Multipolygon_with_holes_test.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Polygon/test/Polygon/Multipolygon_with_holes_test.cpp b/Polygon/test/Polygon/Multipolygon_with_holes_test.cpp index 7592211bd436..49584c7b0115 100644 --- a/Polygon/test/Polygon/Multipolygon_with_holes_test.cpp +++ b/Polygon/test/Polygon/Multipolygon_with_holes_test.cpp @@ -46,6 +46,6 @@ int main() std::cout << mp << std::endl; CGAL::Bbox_2 bb = mp.bbox(); - + std::cout << bb << std::endl; return 0; } From 6158ffa63e98c9af9d1527741ab2490755ed3413 Mon Sep 17 00:00:00 2001 From: Andreas Fabri <andreas.fabri@geometryfactory.com> Date: Wed, 17 Apr 2024 10:50:13 +0100 Subject: [PATCH 13/17] fix comment in demo --- .../Triangulation_2/Constrained_Delaunay_triangulation_2.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/GraphicsView/demo/Triangulation_2/Constrained_Delaunay_triangulation_2.cpp b/GraphicsView/demo/Triangulation_2/Constrained_Delaunay_triangulation_2.cpp index 990a8952cad2..076ad27660b6 100644 --- a/GraphicsView/demo/Triangulation_2/Constrained_Delaunay_triangulation_2.cpp +++ b/GraphicsView/demo/Triangulation_2/Constrained_Delaunay_triangulation_2.cpp @@ -288,7 +288,7 @@ MainWindow::MainWindow() // Setup input handlers. They get events before the scene gets them // and the input they generate is passed to the triangulation with // the signal/slot mechanism - pi = new CGAL::Qt::GraphicsViewPolylineInput<K>(this, &scene, 0, true); // inputs polylines which are not closed + pi = new CGAL::Qt::GraphicsViewPolylineInput<K>(this, &scene, 0, true); // inputs polylines which are closed QObject::connect(pi, SIGNAL(generate(CGAL::Object)), this, SLOT(processInput(CGAL::Object))); From 8f1086f0509ed75517f79842dd4339bf6675c942 Mon Sep 17 00:00:00 2001 From: Andreas Fabri <andreas.fabri@geometryfactory.com> Date: Thu, 18 Apr 2024 09:57:47 +0100 Subject: [PATCH 14/17] move a using to avoid doxygen warning --- Polygon/include/CGAL/Multipolygon_with_holes_2.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Polygon/include/CGAL/Multipolygon_with_holes_2.h b/Polygon/include/CGAL/Multipolygon_with_holes_2.h index 8636626d1a9f..79e515a2b783 100644 --- a/Polygon/include/CGAL/Multipolygon_with_holes_2.h +++ b/Polygon/include/CGAL/Multipolygon_with_holes_2.h @@ -43,9 +43,10 @@ class Multipolygon_with_holes_2 { /// polygon with holes type using Polygon_with_holes_2 = CGAL::Polygon_with_holes_2<Kernel, Container>; - using value_type = Polygon_with_holes_2; + /// @} + using value_type = Polygon_with_holes_2; using Polygon_with_holes_container = std::deque<Polygon_with_holes_2>; using Polygon_with_holes_iterator = typename Polygon_with_holes_container::iterator; From 29c6a7905f579e4d34d79bcaeb36bb8016f00b0c Mon Sep 17 00:00:00 2001 From: Andreas Fabri <andreas.fabri@geometryfactory.com> Date: Fri, 19 Apr 2024 08:10:46 +0100 Subject: [PATCH 15/17] Add is_empty() --- Polygon/include/CGAL/General_polygon_with_holes_2.h | 13 +++++++++++++ Polygon/include/CGAL/Multipolygon_with_holes_2.h | 9 +++++++++ .../test/Polygon/Multipolygon_with_holes_test.cpp | 1 + Polygon_repair/include/CGAL/Polygon_repair/repair.h | 1 - 4 files changed, 23 insertions(+), 1 deletion(-) diff --git a/Polygon/include/CGAL/General_polygon_with_holes_2.h b/Polygon/include/CGAL/General_polygon_with_holes_2.h index bb19fcf99436..1e47948076e0 100644 --- a/Polygon/include/CGAL/General_polygon_with_holes_2.h +++ b/Polygon/include/CGAL/General_polygon_with_holes_2.h @@ -123,6 +123,19 @@ class General_polygon_with_holes_2 { bool is_plane() const { return (m_pgn.is_empty() && m_holes.empty()); } + bool is_empty() const + { + if(! outer_boundary().is_empty()) { + return false; + } + for(const auto& h : holes()){ + if(! h.is_empty()){ + return false; + } + } + return true; + } + protected: Polygon_2 m_pgn; Holes_container m_holes; diff --git a/Polygon/include/CGAL/Multipolygon_with_holes_2.h b/Polygon/include/CGAL/Multipolygon_with_holes_2.h index 79e515a2b783..6cbf3551e675 100644 --- a/Polygon/include/CGAL/Multipolygon_with_holes_2.h +++ b/Polygon/include/CGAL/Multipolygon_with_holes_2.h @@ -111,6 +111,15 @@ class Multipolygon_with_holes_2 { return bb; } + bool is_empty() const + { + for(const auto& pwh : polygons_with_holes()){ + if(! pwh.is_empty()){ + return false; + } + } + return true; + } protected: Polygon_with_holes_container m_polygons; diff --git a/Polygon/test/Polygon/Multipolygon_with_holes_test.cpp b/Polygon/test/Polygon/Multipolygon_with_holes_test.cpp index 49584c7b0115..18ddb1b7f459 100644 --- a/Polygon/test/Polygon/Multipolygon_with_holes_test.cpp +++ b/Polygon/test/Polygon/Multipolygon_with_holes_test.cpp @@ -47,5 +47,6 @@ int main() CGAL::Bbox_2 bb = mp.bbox(); std::cout << bb << std::endl; + assert(! mp.is_empty()); return 0; } diff --git a/Polygon_repair/include/CGAL/Polygon_repair/repair.h b/Polygon_repair/include/CGAL/Polygon_repair/repair.h index 8f420a478d87..f6f2e84cfeed 100644 --- a/Polygon_repair/include/CGAL/Polygon_repair/repair.h +++ b/Polygon_repair/include/CGAL/Polygon_repair/repair.h @@ -314,7 +314,6 @@ class Polygon_repair { using Face_circulator = typename Triangulation::Face_circulator; using Edge = typename Triangulation::Edge; - // TODO: Edge_map and Vertex_map use std::set and std::map with exact kernels since Point_2 can't be hashed otherwise using Edge_map = typename std::conditional<std::is_floating_point<FT>::value, std::unordered_set<std::pair<Point_2, Point_2>, boost::hash<std::pair<Point_2, Point_2>>>, From 31018d0a5008c4a758633f63709cd54e903ddc48 Mon Sep 17 00:00:00 2001 From: Andreas Fabri <andreas.fabri@geometryfactory.com> Date: Fri, 19 Apr 2024 10:13:40 +0100 Subject: [PATCH 16/17] Apply the rule of five --- Polygon/include/CGAL/General_polygon_with_holes_2.h | 2 +- Polygon/include/CGAL/Multipolygon_with_holes_2.h | 2 +- Polygon/include/CGAL/Polygon_2.h | 12 ++---------- Polygon/include/CGAL/Polygon_with_holes_2.h | 10 ++++------ 4 files changed, 8 insertions(+), 18 deletions(-) diff --git a/Polygon/include/CGAL/General_polygon_with_holes_2.h b/Polygon/include/CGAL/General_polygon_with_holes_2.h index 1e47948076e0..90b3bca3b489 100644 --- a/Polygon/include/CGAL/General_polygon_with_holes_2.h +++ b/Polygon/include/CGAL/General_polygon_with_holes_2.h @@ -57,7 +57,7 @@ class General_polygon_with_holes_2 { typedef unsigned int Size; - General_polygon_with_holes_2() : m_pgn() {} + General_polygon_with_holes_2() = default; explicit General_polygon_with_holes_2(const Polygon_2& pgn_boundary) : diff --git a/Polygon/include/CGAL/Multipolygon_with_holes_2.h b/Polygon/include/CGAL/Multipolygon_with_holes_2.h index 6cbf3551e675..b225e8498e57 100644 --- a/Polygon/include/CGAL/Multipolygon_with_holes_2.h +++ b/Polygon/include/CGAL/Multipolygon_with_holes_2.h @@ -56,7 +56,7 @@ class Multipolygon_with_holes_2 { using Size = unsigned int; /*! %Default constructor. */ - Multipolygon_with_holes_2() {} + Multipolygon_with_holes_2() = default; /*! Constructor from polygons. */ template <typename PolygonsInputIterator> diff --git a/Polygon/include/CGAL/Polygon_2.h b/Polygon/include/CGAL/Polygon_2.h index ff97d3c89932..c3300d939fa4 100644 --- a/Polygon/include/CGAL/Polygon_2.h +++ b/Polygon/include/CGAL/Polygon_2.h @@ -161,11 +161,8 @@ class Polygon_2 { /// Creates an empty polygon. Polygon_2(const Traits & p_traits) : traits(p_traits) {} - /// Copy constructor. - Polygon_2(const Polygon_2<Traits_P,Container_P>& polygon) = default; - - /// Move constructor - Polygon_2(Polygon_2<Traits_P,Container_P>&& polygon) = default; + // Move constructor + // Polygon_2(Polygon_2<Traits_P,Container_P>&& polygon) = default; /// Creates a polygon with vertices from the sequence /// defined by the range \c [first,last). @@ -176,11 +173,6 @@ class Polygon_2 { : d_container(first,last), traits(p_traits) {} -#ifndef DOXYGEN_RUNNING - Polygon_2& operator=(const Polygon_2&) = default; - Polygon_2& operator=(Polygon_2&& p) = default; -#endif - /// @} /// \name Modifiers diff --git a/Polygon/include/CGAL/Polygon_with_holes_2.h b/Polygon/include/CGAL/Polygon_with_holes_2.h index e551278bdb55..032b2c52084d 100644 --- a/Polygon/include/CGAL/Polygon_with_holes_2.h +++ b/Polygon/include/CGAL/Polygon_with_holes_2.h @@ -49,9 +49,7 @@ class Polygon_with_holes_2 : typedef typename Base::Size Size; /*! %Default constructor. */ - Polygon_with_holes_2 () : - Base() - {} + Polygon_with_holes_2 () = default; /*! Constructor from the base class. */ Polygon_with_holes_2 (const Base& base) : @@ -63,7 +61,7 @@ class Polygon_with_holes_2 : Base (pgn_boundary) {} - /*! Move constructor */ + /*! Cconstructor moving a polygon */ explicit Polygon_with_holes_2 (Polygon_2&& pgn_boundary) : Base (std::move(pgn_boundary)) {} @@ -76,7 +74,7 @@ class Polygon_with_holes_2 : Base (pgn_boundary, h_begin, h_end) {} - /*! Move constructor. + /*! Cconstructor moving a polygon. * \note In order to move the hole polygons a * `std::move_iterator` may be used. */ @@ -87,7 +85,7 @@ class Polygon_with_holes_2 : Base (std::move(pgn_boundary), h_begin, h_end) {} - /*! Obtain the bounding box of the polygon with holes */ + /*! returns the bounding box of the polygon with holes */ Bbox_2 bbox() const { return this->outer_boundary().bbox(); } }; From dfa0a124cdff326dc252a284270522c2cc602673 Mon Sep 17 00:00:00 2001 From: Andreas Fabri <andreas.fabri@geometryfactory.com> Date: Fri, 19 Apr 2024 11:29:19 +0200 Subject: [PATCH 17/17] Update Polygon/include/CGAL/Multipolygon_with_holes_2.h --- Polygon/include/CGAL/Multipolygon_with_holes_2.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Polygon/include/CGAL/Multipolygon_with_holes_2.h b/Polygon/include/CGAL/Multipolygon_with_holes_2.h index b225e8498e57..a8b6a32ca2d0 100644 --- a/Polygon/include/CGAL/Multipolygon_with_holes_2.h +++ b/Polygon/include/CGAL/Multipolygon_with_holes_2.h @@ -86,7 +86,7 @@ class Multipolygon_with_holes_2 { Polygon_with_holes_const_iterator end() const { return m_polygons.end(); } - void add_polygon(const Polygon_2& pgn) { m_polygons.push_back(Polygon_with_holes_2(pgn)); } + void add_polygon(const Polygon_2& pgn) { m_polygons.emplace_back(pgn); } void add_polygon(Polygon_2&& pgn) { m_polygons.emplace_back(std::move(pgn)); }