dust3d/thirdparty/cgal/CGAL-5.1/include/CGAL/partition_is_valid_2.h

303 lines
10 KiB
C++

// Copyright (c) 2000 Max-Planck-Institute Saarbruecken (Germany).
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org).
//
// $URL: https://github.com/CGAL/cgal/blob/v5.1/Partition_2/include/CGAL/partition_is_valid_2.h $
// $Id: partition_is_valid_2.h 0779373 2020-03-26T13:31:46+01:00 Sébastien Loriot
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial
//
//
// Author(s) : Susan Hert <hert@mpi-sb.mpg.de>
#ifndef CGAL_PARTITION_IS_VALID_2_H
#define CGAL_PARTITION_IS_VALID_2_H
#include <CGAL/license/Partition_2.h>
#include <list>
#include <utility>
#include <iterator>
#include <CGAL/Partition_2/partition_assertions.h>
#include <CGAL/Partition_2/Partitioned_polygon_2.h>
#include <CGAL/Partition_2/Partition_vertex_map.h>
#include <CGAL/ch_selected_extreme_points_2.h>
#include <CGAL/Partition_traits_2.h>
#include <CGAL/Partition_is_valid_traits_2.h>
#include <CGAL/Polygon_2.h>
// NOTE: this could possibly be checked using a planar map overlay, but
// then the traits class would have to require lots of other things
// and you have to do many overlaps, not just one so it is
// less efficient.
namespace CGAL {
template <class Circulator1, class Circulator2, class Traits>
bool
polygons_w_steiner_are_equal(Circulator1 orig_first, Circulator2 new_first,
const Traits& traits)
{
typedef typename Circulator1::value_type Point_2;
Circulator1 orig_circ;
Circulator2 new_circ;
// find the first (original) vertex in the list of vertices
for (new_circ = new_first;
*new_circ != *orig_first && ++new_circ != new_first;)
{}
if (new_circ == new_first)
{
#ifdef CGAL_PARTITION_CHECK_DEBUG
std::cout << "first vertex " << *orig_first << " not found "
<< std::endl;
#endif // CGAL_PARTITION_CHECK_DEBUG
return false;
}
// first becomes the first one you found; now look for the others
new_first = new_circ;
orig_circ = orig_first;
Point_2 prev_pt = *new_first;
// keep going until you find all the original vertices, or come back
// to the first new vertex
do
{
if (*new_circ == *orig_circ) // points correspond, so move both
{
prev_pt = *new_circ;
new_circ++;
orig_circ++;
}
else // points don't correspond
{
if (traits.orientation_2_object()(prev_pt, *new_circ, *orig_circ) !=
COLLINEAR)
{
#ifdef CGAL_PARTITION_CHECK_DEBUG
std::cout << *new_circ << " is not collinear with " << prev_pt
<< " and " << *orig_circ << std::endl;
#endif
return false;
}
prev_pt = *new_circ;
new_circ++;
}
}
while (orig_circ != orig_first && new_circ != new_first);
// if they didn't both come back to the beginning, then something is wrong
return (orig_circ == orig_first && new_circ == new_first);
}
template <class Circulator1, class Circulator2>
bool
polygons_are_equal(Circulator1 orig_first, Circulator2 new_first)
{
Circulator1 orig_circ = orig_first;
Circulator2 new_circ;
// find the first (original) vertex in the list of vertices
for (new_circ = new_first;
*new_circ != *orig_first && ++new_circ != new_first;)
{}
new_first = new_circ;
// now look through both lists until you find a vertex that is not
// the same or you reach the end of the vertices
do
{
#ifdef CGAL_PARTITION_CHECK_DEBUG
std::cout << *new_first << " is in the right place " << std::endl;
#endif
orig_circ++; new_circ++;
}
while (*orig_circ == *new_circ &&
orig_circ != orig_first && new_circ != new_first);
return (orig_circ == orig_first && new_circ == new_first);
}
namespace internal {
template<class InputIterator, class ForwardIterator, class Traits>
bool
partition_is_valid_2 (InputIterator point_first, InputIterator point_last,
ForwardIterator poly_first, ForwardIterator poly_last,
const Traits& traits)
{
if (poly_first == poly_last) return (point_first == point_last);
typedef typename Traits::Polygon_2::Vertex_const_iterator
Poly_vtx_iterator;
typedef typename Traits::Point_2 Point_2;
typedef Partition_vertex_map<Traits> P_Vertex_map;
typedef typename Traits::Is_valid Is_valid;
Poly_vtx_iterator vtx_begin, vtx_end;
Is_valid is_valid = traits.is_valid_object(traits);
std::list<Point_2> orig_poly;
for (;point_first != point_last; point_first++)
orig_poly.push_back(*point_first);
CGAL_partition_precondition(orientation_2(orig_poly.begin(),orig_poly.end(),
traits) == COUNTERCLOCKWISE);
P_Vertex_map output_vertex_set(poly_first, poly_last, traits);
if (output_vertex_set.polygons_overlap()) return false;
int poly_num = 0;
for (; poly_first != poly_last; poly_first++, poly_num++)
{
vtx_begin = (*poly_first).vertices_begin();
vtx_end = (*poly_first).vertices_end();
#ifdef CGAL_PARTITION_CHECK_DEBUG
std::cout << "Polygon " << poly_num << " is " << std::endl;
std::cout << *poly_first << std::endl;
#endif
CGAL_partition_assertion (
orientation_2(vtx_begin, vtx_end, traits) == COUNTERCLOCKWISE);
if (!is_valid(vtx_begin, vtx_end))
{
#ifdef CGAL_PARTITION_CHECK_DEBUG
std::cout << "It does NOT have the tested property." << std::endl;
#endif
return false;
}
}
std::list<Point_2> union_polygon;
output_vertex_set.union_vertices(std::back_inserter(union_polygon));
#ifdef CGAL_PARTITION_CHECK_DEBUG
typename std::list<Point_2>::iterator poly_iterator;
std::cout << "union polygon is " << std::endl;
for (poly_iterator = union_polygon.begin();
poly_iterator != union_polygon.end(); poly_iterator++)
{
std::cout << *poly_iterator << " ";
}
std::cout << std::endl;
#endif // CGAL_PARTITION_CHECK_DEBUG
typedef typename std::list<Point_2>::iterator I;
typedef Circulator_from_iterator<I> Circulator;
Circulator orig_poly_circ(orig_poly.begin(), orig_poly.end());
Circulator union_poly_circ(union_polygon.begin(), union_polygon.end());
if (orig_poly.size() == union_polygon.size())
return polygons_are_equal(orig_poly_circ, union_poly_circ);
else
return polygons_w_steiner_are_equal(orig_poly_circ, union_poly_circ,
traits);
}
} // namespace internal
template<class InputIterator, class FowardIterator>
bool
partition_is_valid_2 (InputIterator point_first, InputIterator point_last,
FowardIterator poly_first, FowardIterator poly_last)
{
typedef typename std::iterator_traits<InputIterator>::value_type Point_2;
typedef typename Kernel_traits<Point_2>::Kernel K;
typedef Partition_traits_2<K> Traits;
typedef Is_vacuously_valid<Traits> Is_valid;
Partition_is_valid_traits_2<Traits, Is_valid> validity_traits;
return internal::partition_is_valid_2(point_first, point_last,
poly_first, poly_last, validity_traits);
}
template<class InputIterator, class FowardIterator, class Traits>
bool
partition_is_valid_2 (InputIterator point_first, InputIterator point_last,
FowardIterator poly_first, FowardIterator poly_last,
const Traits& traits)
{
//typedef typename std::iterator_traits<InputIterator>::value_type Point_2;
//typedef typename Kernel_traits<Point_2>::Kernel K;
//typedef Partition_traits_2<K> Traits;
typedef Is_vacuously_valid<Traits> Is_valid;
Partition_is_valid_traits_2<Traits, Is_valid> validity_traits(traits);
return internal::partition_is_valid_2(point_first, point_last,
poly_first, poly_last, validity_traits);
}
template<class InputIterator, class ForwardIterator, class Traits>
bool
convex_partition_is_valid_2(InputIterator point_first,
InputIterator point_last,
ForwardIterator poly_first,
ForwardIterator poly_last,
const Traits& traits)
{
typedef typename Traits::Is_convex_2 Is_convex_2;
Partition_is_valid_traits_2<Traits, Is_convex_2> validity_traits(traits);
return internal::partition_is_valid_2(point_first, point_last, poly_first, poly_last,
validity_traits);
}
template<class InputIterator, class ForwardIterator>
bool
convex_partition_is_valid_2(InputIterator point_first,
InputIterator point_last,
ForwardIterator poly_first,
ForwardIterator poly_last)
{
typedef typename std::iterator_traits<InputIterator>::value_type Point_2;
typedef typename Kernel_traits<Point_2>::Kernel K;
return convex_partition_is_valid_2(point_first, point_last,
poly_first, poly_last,
Partition_traits_2<K>());
}
template<class InputIterator, class ForwardIterator, class Traits>
bool
y_monotone_partition_is_valid_2(InputIterator point_first,
InputIterator point_last,
ForwardIterator poly_first,
ForwardIterator poly_last,
const Traits& traits)
{
typedef typename Traits::Is_y_monotone_2 Is_y_monotone_2;
Partition_is_valid_traits_2<Traits, Is_y_monotone_2> validity_traits(traits);
return internal::partition_is_valid_2(point_first, point_last, poly_first, poly_last,
validity_traits);
}
template<class InputIterator, class ForwardIterator>
bool
y_monotone_partition_is_valid_2(InputIterator point_first,
InputIterator point_last,
ForwardIterator poly_first,
ForwardIterator poly_last)
{
typedef typename std::iterator_traits<InputIterator>::value_type Point_2;
typedef typename Kernel_traits<Point_2>::Kernel K;
return y_monotone_partition_is_valid_2(point_first, point_last,
poly_first, poly_last,
Partition_traits_2<K>());
}
}
#endif // CGAL_PARTITION_IS_VALID_2_H