Polygon_repair: Add overloads for Non_zero_rule (#8929)

## Summary of Changes

The repair function for the `Non_zero_rule` was only implemented for
`Polygon_with_holes`. This PR adds the overload for `Polygon_2` and
`Multipolygon_with_holes_2`.

## Release Management

* Affected package(s): Polygon_repair
* License and copyright ownership:  unchanged
This commit is contained in:
Sebastien Loriot 2025-06-26 21:47:06 +02:00 committed by GitHub
commit dcfb725591
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 74 additions and 9 deletions

View File

@ -135,7 +135,7 @@ sets the polygon as input of the winding number computation.
void
insert(const Polygon_2& p)
{
Constraint_id cidA = cdt.insert_constraint(p.vertices_begin(), p.vertices_end(), true);
cdt.insert_constraint(p.vertices_begin(), p.vertices_end(), true);
}
/*!
@ -144,9 +144,9 @@ sets the polygon as input of the winding number computation.
void
insert(const Polygon_with_holes_2& pwh)
{
Constraint_id cidA = cdt.insert_constraint(pwh.outer_boundary().vertices_begin(), pwh.outer_boundary().vertices_end(), true);
cdt.insert_constraint(pwh.outer_boundary().vertices_begin(), pwh.outer_boundary().vertices_end(), true);
for(auto const& hole : pwh.holes()){
cidA = cdt.insert_constraint(hole.vertices_begin(), hole.vertices_end(), true);
cdt.insert_constraint(hole.vertices_begin(), hole.vertices_end(), true);
}
}
@ -157,9 +157,9 @@ sets the polygon as input of the winding number computation.
insert(const Multipolygon_with_holes_2& mpwh)
{
for(const auto& pwh : mpwh.polygons_with_holes()){
Constraint_id cidA = cdt.insert_constraint(pwh.outer_boundary().vertices_begin(), pwh.outer_boundary().vertices_end(), true);
cdt.insert_constraint(pwh.outer_boundary().vertices_begin(), pwh.outer_boundary().vertices_end(), true);
for(auto const& hole : pwh.holes()){
cidA = cdt.insert_constraint(hole.vertices_begin(), hole.vertices_end(), true);
cdt.insert_constraint(hole.vertices_begin(), hole.vertices_end(), true);
}
}
}

View File

@ -77,6 +77,17 @@ Multipolygon_with_holes_2<Kernel, Container> repair(const Polygon_with_holes_2<K
}
template <class Kernel, class Container>
Multipolygon_with_holes_2<Kernel, Container> repair(const Polygon_2<Kernel, Container>& p, Non_zero_rule)
{
Winding<Kernel> winding;
winding.insert(p);
winding.label();
winding.label_domains();
return winding();
}
template <class Kernel, class Container>
Multipolygon_with_holes_2<Kernel, Container> repair(const Polygon_with_holes_2<Kernel, Container>& p, Non_zero_rule)
{
@ -93,7 +104,8 @@ Multipolygon_with_holes_2<Kernel, Container> repair(const Polygon_with_holes_2<K
/// \tparam Kernel parameter of the input and output polygons. Must be model of `ConstrainedDelaunayTriangulationTraits_2 `
/// \tparam Container parameter of the input and output polygons
/// \tparam Rule may be any \ref PkgPolygonRepairRules
/// \pre If the rule is the `Union_rule` or `Non_zero_rule`, each polygon with hole must be free of self-intersections
/// \pre If the rule is the `Union_rule` or `Non_zero_rule`, each polygon with hole must be free of self-intersections,
/// the outer boundary of each polygon with holes must be counterclockwise and the holes clockwise oriented.
template <class Kernel, class Container, class Rule = Even_odd_rule>
Multipolygon_with_holes_2<Kernel, Container> repair(const Multipolygon_with_holes_2<Kernel, Container>& p, Rule = Rule())
{
@ -107,6 +119,17 @@ Multipolygon_with_holes_2<Kernel, Container> repair(const Multipolygon_with_hole
}
template <class Kernel, class Container>
Multipolygon_with_holes_2<Kernel, Container> repair(const Multipolygon_with_holes_2<Kernel, Container>& p, Non_zero_rule)
{
Winding<Kernel> winding;
winding.insert(p);
winding.label();
winding.label_domains();
return winding();
}
template <class Kernel, class Container>
Multipolygon_with_holes_2<Kernel, Container> repair(const Multipolygon_with_holes_2<Kernel, Container>& p, Union_rule)
{
@ -791,7 +814,8 @@ protected:
/// computes the union of all polygons with holes in `p`
/// \tparam Kernel parameter of the input and output polygons. Must be model of `ConstrainedDelaunayTriangulationTraits_2 `
/// \tparam Container parameter of the input and output polygons
/// \pre Each polygon with hole must be free of self-intersections
/// \pre Each polygon with holes must be free of self-intersections,
/// the outer boundaries must be counterclockwise and the holes clockwise oriented.
template <typename Kernel, typename Container>
Multipolygon_with_holes_2<Kernel,Container>
join(const Multipolygon_with_holes_2<Kernel,Container>& pa)
@ -816,7 +840,8 @@ join(const Multipolygon_with_holes_2<Kernel,Container>& pa)
/// \tparam Container parameter of the input and output polygons
/// \tparam PA must be `Polygon_2<Kernel, Container>`, or `Polygon_with_holes_2<Kernel, Container>`, or `Multipolygon_with_holes_2<Kernel, Container>`
/// \tparam PB must be `Polygon_2<Kernel, Container>`, or `Polygon_with_holes_2<Kernel, Container>`, or `Multipolygon_with_holes_2<Kernel, Container>`
/// \pre The polygons `pa` and `pb` must be free of self-intersections
/// \pre The polygons `pa` and `pb` must be free of self-intersections,
/// the outer boundaries must be counterclockwise and the holes clockwise oriented.
template <typename PA, typename PB, typename Kernel = Default, typename Container = Default>
#ifdef DOXYGEN_RUNNING
Multipolygon_with_holes_2<Kernel,Container>
@ -848,7 +873,8 @@ join(const PA& pa, const PB& pb, const Kernel& = Default(), const Container& = D
/// computes the intersection of all polygons with holes in `p`
/// \tparam Kernel parameter of the input and output polygons. Must be model of `ConstrainedDelaunayTriangulationTraits_2 `
/// \tparam Container parameter of the input and output polygons
/// \pre Each polygon with hole must be free of self-intersections
/// \pre Each polygon with holes must be free of self-intersections
/// the outer boundaries must be counterclockwise and the holes clockwise oriented.
template <typename Kernel, typename Container>
Multipolygon_with_holes_2<Kernel,Container>
intersect(const Multipolygon_with_holes_2<Kernel,Container>& p)
@ -880,6 +906,7 @@ intersect(const Multipolygon_with_holes_2<Kernel,Container>& p)
/// \tparam PA must be `Polygon_2<Kernel, Container>`, or `Polygon_with_holes_2<Kernel, Container>`, or `Multipolygon_with_holes_2<Kernel, Container>`
/// \tparam PB must be `Polygon_2<Kernel, Container>`, or `Polygon_with_holes_2<Kernel, Container>`, or `Multipolygon_with_holes_2<Kernel, Container>`
/// \pre The polygons `pa` and `pb` must be free of self-intersections
/// the outer boundaries must be counterclockwise and the holes clockwise oriented.
template <typename PA, typename PB, typename Kernel = Default, typename Container = Default>
#ifdef DOXYGEN_RUNNING
Multipolygon_with_holes_2<Kernel, Container>

View File

@ -18,6 +18,7 @@ find_package(CGAL REQUIRED OPTIONAL_COMPONENTS Qt6)
create_single_source_cgal_program( "draw_test_polygons.cpp" )
create_single_source_cgal_program( "exact_test.cpp")
create_single_source_cgal_program( "repair_polygon_2_test.cpp" )
create_single_source_cgal_program( "repair_polygon_non_zero_2_test.cpp" )
if(CGAL_Qt6_FOUND)
target_link_libraries(draw_test_polygons PRIVATE CGAL::CGAL_Basic_viewer)

View File

@ -0,0 +1,37 @@
#include <CGAL/Polygon_repair/repair.h>
#include <CGAL/IO/WKT.h>
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
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>;
using Polygon_repair = CGAL::Polygon_repair::Polygon_repair<Kernel>;
int main() {
std::string polygon("POLYGON((0 0, 3 0, 3 3, 4 3,0 0))");
std::istringstream in(polygon);
Polygon_with_holes_2 pwh;
CGAL::IO::read_polygon_WKT(in, pwh);
Polygon_2 outer = pwh.outer_boundary();
Multipolygon_with_holes_2 rmp;
rmp = CGAL::Polygon_repair::repair(outer, CGAL::Polygon_repair::Non_zero_rule());
rmp = CGAL::Polygon_repair::repair(pwh, CGAL::Polygon_repair::Non_zero_rule());
rmp = CGAL::Polygon_repair::repair(rmp, CGAL::Polygon_repair::Non_zero_rule());
std::cout << "done" << std::endl;
return 0;
}