cgal/Polygon/include/CGAL/Polygon_2.h

627 lines
20 KiB
C++

// Copyright (c) 1997
// Utrecht University (The Netherlands),
// ETH Zurich (Switzerland),
// INRIA Sophia-Antipolis (France),
// Max-Planck-Institute Saarbruecken (Germany),
// and Tel-Aviv University (Israel). All rights reserved.
//
// This file is part of CGAL (www.cgal.org)
//
// $URL$
// $Id$
// SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial
//
//
// Author(s) : Geert-Jan Giezeman <geert@cs.uu.nl>
// Wieger Wesselink
/*!
\file Polygon_2.h
*/
#ifndef CGAL_POLYGON_2_H
#define CGAL_POLYGON_2_H
#include <CGAL/config.h>
#include <vector>
#include <list>
#include <iterator>
#include <CGAL/assertions.h>
#include <CGAL/algorithm.h>
#include <CGAL/circulator.h>
#include <CGAL/Iterator_range.h>
#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>
#include <CGAL/Polygon_2/Polygon_2_edge_iterator.h>
#include <CGAL/Polygon_2/Polygon_2_edge_circulator.h>
namespace CGAL {
/// \ingroup PkgPolygon2Ref
/// The class `Polygon_2` implements polygons. The `Polygon_2` is
/// parameterized by a traits class and a container class. The latter
/// can be any class that fulfills the requirements for an STL
/// container, and has a function `resize()` that takes an `std::size_t` as argument.
/// It defaults to the `std::vector` class.
///
/// \cgalHeading{Implementation}
///
/// The methods `is_simple()`, `is_convex()`, `orientation()`,
/// `oriented_side()`, `bounded_side()`, `bbox()`, `area()`, `left_vertex()`,
/// `right_vertex()`, `top_vertex()` and `bottom_vertex()` are all
/// implemented using the algorithms on sequences of 2D points. See
/// the corresponding global functions for information about which
/// algorithms were used and what complexity they have.
///
template <class Traits_, class Container_
= std::vector<typename Traits_::Point_2> >
class Polygon_2 {
public:
/// \name Types
/// @{
/// The traits type.
typedef Traits_ Traits;
/// The container type.
typedef Container_ Container;
/// The number type of the coordinates of the points of the polygon.
typedef typename Traits_::FT FT;
/// The point type of the polygon.
typedef typename Traits_::Point_2 Point_2;
/// The type of a segment between two points of the polygon.
typedef typename Traits_::Segment_2 Segment_2;
/// @}
typedef typename Container_::difference_type difference_type;
typedef typename Container_::value_type value_type;
typedef typename Container_::pointer pointer;
typedef typename Container_::reference reference;
typedef typename Container_::const_reference const_reference;
//-------------------------------------------------------//
// this intermediary step is required by Sun C++ 4.1
typedef typename Container_::iterator iterator;
typedef typename Container_::const_iterator const_iterator;
//-------------------------------------------------------//
typedef typename Container::iterator Vertex_const_iterator;
typedef Polygon_circulator<Container_> Vertex_const_circulator;
/// \name Iterators
///
/// The following types denote iterators that allow to traverse
/// the vertices and edges of a polygon. Since
/// a polygon can be viewed as a circular as well as a
/// linear data structure both circulators and iterators are
/// defined.
///
/// \note At least conceptually, the circulators and iterators are
/// non-mutable. The enforcement depends on preprocessor flags.
///
/// \note The iterator category is in all cases bidirectional, except
/// for Vertex_iterator, which has the same iterator category as
/// `Container::iterator`. In fact all of them should have
/// the same iterator category as `Container::iterator`. However,
/// due to compiler problems this is currently not possible.
///
/// @{
/// vertex iterator type
typedef typename Container::iterator Vertex_iterator;
/// a range type to iterate over the vertices
typedef Container Vertices;
//typedef typename Container::const_iterator Vertex_const_iterator; ??
#ifdef DOXYGEN_RUNNING
/// vertex circulator type
typedef unspecified_type Vertex_circulator;
/// edge iterator type
typedef unspecified_type Edge_const_iterator;
/// a range type to iterate over the vertices
typedef unspecified_type Edges;
/// edge circular type
typedef unspecified_type Edge_const_circulator;
//
#else
typedef Vertex_const_circulator Vertex_circulator;
typedef Polygon_2_edge_iterator<Traits_,Container_> Edge_const_iterator;
typedef Polygon_2_const_edge_circulator<Traits_,
Container_> Edge_const_circulator;
typedef Polygon_2_edge_iterator<Traits_,Container_,
Tag_false> Vertex_pair_iterator;
typedef Iterator_range<Edge_const_iterator> Edges;
#endif // DOXYGEN_RUNNING
/// @}
/// \name Creation
/// @{
/// Creates an empty polygon.
Polygon_2() = default;
/// Creates an empty polygon.
Polygon_2(const Traits & p_traits) : traits(p_traits) {}
// Move constructor
// Polygon_2(Polygon_2<Traits_,Container_>&& polygon) = default;
/// Creates a polygon with vertices from the sequence
/// defined by the range \c [first,last).
/// The value type of \c InputIterator must be \c Point_2.
template <class InputIterator>
Polygon_2(InputIterator first, InputIterator last,
Traits p_traits = Traits())
: d_container(first,last), traits(p_traits)
{}
/// @}
/// \name Modifiers
/// @{
/// Acts as `*i = q`, except that that would be illegal because
/// the iterator is not mutable.
void set(Vertex_iterator i, const Point_2& q)
{ *i = q; }
/// \cond
void set(Polygon_circulator<Container>const &i, const Point_2& q)
{
*i.mod_iterator() = q;
}
/// \endcond
/// Inserts the vertex `q` before `i`. The return value points to
/// the inserted vertex.
Vertex_iterator insert(Vertex_iterator i, const Point_2& q)
{
return d_container.insert(i,q);
}
/// Inserts the vertex `q` before `i`. The return value points to
/// the inserted vertex.
Vertex_iterator insert(Vertex_circulator i, const Point_2& q)
{
return d_container.insert(i.mod_iterator(),q);
}
/// Inserts the vertices in the range `[first, last)`
/// before `i`. The value type of points in the range
/// `[first,last)` must be `Point_2`.
template <class InputIterator>
void insert(Vertex_iterator i,
InputIterator first,
InputIterator last)
{ d_container.insert(i, first, last); }
/// Inserts the vertices in the range `[first, last)`
/// before `i`. The value type of points in the range
/// `[first,last)` must be `Point_2`.
template <class InputIterator>
void insert(Vertex_circulator i,
InputIterator first,
InputIterator last)
{ d_container.insert(i.mod_iterator(), first, last); }
/// Has the same semantics as `p.insert(p.vertices_end(), q)`.
void push_back(const Point_2& x)
{ d_container.insert(d_container.end(), x); }
/// Erases the vertex pointed to by `i`.
Vertex_iterator erase(Vertex_iterator i)
{
return d_container.erase(i);
}
/// Erases the vertex pointed to by `i`.
Vertex_circulator erase(Vertex_circulator i)
{
auto it = d_container.erase(i.mod_iterator());
if(it == d_container.end()){
it = d_container.begin();
}
return Vertex_circulator(&d_container, it);
}
/// Erases the vertices in the range `[first, last)`.
Vertex_iterator erase(Vertex_iterator first, Vertex_iterator last)
{
return d_container.erase(first, last);
}
/// Erases the vertices in the range `[first, last)`.
void clear()
{
d_container.clear();
}
/// Reverses the orientation of the polygon. The vertex pointed to
/// by `p.vertices_begin()` remains the same.
void reverse_orientation()
{
if (size() <= 1)
return;
typename Container_::iterator i = d_container.begin();
std::reverse(++i, d_container.end());
}
/// @}
/// \name Access Functions
/// The following methods of the class Polygon_2
/// return circulators and iterators that allow to traverse the
/// vertices and edges.
/// @{
/// Returns a constant iterator that allows to traverse the
/// vertices of the polygon.
Vertex_iterator vertices_begin() const
{ return const_cast<Polygon_2&>(*this).d_container.begin(); }
/// Returns the corresponding past-the-end iterator.
Vertex_iterator vertices_end() const
{ return const_cast<Polygon_2&>(*this).d_container.end(); }
/// returns the range of vertices.
const Vertices& vertices() const
{
return d_container;
}
// Vertex_const_circulator vertices_circulator() const
// { return Vertex_const_circulator(&d_container, d_container.begin()); }
/// Returns a constant circulator that allows to traverse the
/// vertices of the polygon.
Vertex_circulator vertices_circulator() const
{
Polygon_2& self = const_cast<Polygon_2&>(*this);
return Vertex_circulator(&self.d_container,
self.d_container.begin());
}
/// Returns a non-mutable iterator that allows to traverse the
/// edges of the polygon.
Edge_const_iterator edges_begin() const
{ return Edge_const_iterator(&d_container, d_container.begin()); }
/// Returns the corresponding past-the-end iterator.
Edge_const_iterator edges_end() const
{ return Edge_const_iterator(&d_container, d_container.end()); }
/// returns the range of edges.
Edges edges() const
{
return make_range(edges_begin(),edges_end());
}
/// Returns a non-mutable circulator that allows to traverse the
/// edges of the polygon.
Edge_const_circulator edges_circulator() const
{ return Edge_const_circulator(vertices_circulator()); }
/// @}
/// \cond SKIP_IN_MANUAL
Vertex_pair_iterator vertex_pairs_begin() const
{ return Vertex_pair_iterator(&d_container, d_container.begin()); }
Vertex_pair_iterator vertex_pairs_end() const
{ return Vertex_pair_iterator(&d_container, d_container.end()); }
/// \endcond
/// \name Predicates
/// @{
/// Returns whether this is a simple polygon.
bool is_simple() const
{
return is_simple_2(d_container.begin(),d_container.end(), traits);
}
/// Returns whether this is convex.
bool is_convex() const
{
return is_convex_2(d_container.begin(),d_container.end(), traits);
}
/// Returns the orientation. If the number of vertices
/// `p.size() < 3` then \c COLLINEAR is returned.
/// \pre `p.is_simple()`.
Orientation orientation() const
{
return orientation_2(d_container.begin(), d_container.end(), traits);
}
/// Returns `ON_POSITIVE_SIDE`, or `ON_NEGATIVE_SIDE`,
/// or `ON_ORIENTED_BOUNDARY`, depending on where point
/// `q` is.
/// \pre `p.is_simple()`.
Oriented_side oriented_side(const Point_2& value) const
{
return oriented_side_2(d_container.begin(), d_container.end(),
value, traits);
}
/// Returns the symbolic constant `ON_BOUNDED_SIDE`,
/// `ON_BOUNDARY` or `ON_UNBOUNDED_SIDE`,
/// depending on where point `q` is. \pre
/// `p.is_simple()`.
Bounded_side bounded_side(const Point_2& value) const
{
CGAL_precondition(is_simple());
return bounded_side_2(d_container.begin(), d_container.end(),
value, traits);
}
/// Returns the smallest bounding box containing this polygon.
Bbox_2 bbox() const
{
return bbox_2(d_container.begin(), d_container.end());
}
/// Returns the signed area of the polygon. This means that the
/// area is positive for counter clockwise polygons and negative
/// for clockwise polygons.
FT area() const
{
return polygon_area_2(d_container.begin(), d_container.end(), traits);
}
/// Returns the leftmost vertex of the polygon with the smallest
/// `x`-coordinate.
Vertex_const_iterator left_vertex() const
{
Polygon_2 &self = const_cast<Polygon_2&>(*this);
return left_vertex_2(self.d_container.begin(),
self.d_container.end(), traits);
}
/// Returns the rightmost vertex of the polygon with the largest
/// `x`-coordinate.
Vertex_const_iterator right_vertex() const
{
Polygon_2 &self = const_cast<Polygon_2&>(*this);
return right_vertex_2(self.d_container.begin(),
self.d_container.end(), traits);
}
/// Returns the topmost vertex of the polygon with the largest
/// `y`-coordinate.
Vertex_const_iterator top_vertex() const
{
Polygon_2 &self = const_cast<Polygon_2&>(*this);
return top_vertex_2(self.d_container.begin(),
self.d_container.end(), traits);
}
/// Returns the bottommost vertex of the polygon with the
/// smallest `y`-coordinate.
Vertex_const_iterator bottom_vertex() const
{
Polygon_2 &self = const_cast<Polygon_2&>(*this);
return bottom_vertex_2(self.d_container.begin(),
self.d_container.end(), traits);
}
/// @}
/// \name Convenience Orientation Functions
/// For convenience we provide the following Boolean functions:
/// @{
/// returns `orientation() == COUNTERCLOCKWISE`
bool is_counterclockwise_oriented() const
{ return orientation() == COUNTERCLOCKWISE; }
/// returns `orientation() == CLOCKWISE`
bool is_clockwise_oriented() const
{ return orientation() == CLOCKWISE; }
/// returns `orientation() == COLLINEAR`
bool is_collinear_oriented() const
{ return orientation() == COLLINEAR; }
/// returns `oriented_side(q) == ON_POSITIVE_SIDE`
bool has_on_positive_side(const Point_2& q) const
{ return oriented_side(q) == ON_POSITIVE_SIDE; }
/// returns `oriented_side(q) == ON_NEGATIVE_SIDE`
bool has_on_negative_side(const Point_2& q) const
{ return oriented_side(q) == ON_NEGATIVE_SIDE; }
/// returns `bounded_side(q) == ON_BOUNDARY`
bool has_on_boundary(const Point_2& q) const
{ return bounded_side(q) == ON_BOUNDARY; }
/// returns `bounded_side(q) == ON_BOUNDED_SIDE`
bool has_on_bounded_side(const Point_2& q) const
{ return bounded_side(q) == ON_BOUNDED_SIDE; }
/// returns `bounded_side(q) == ON_UNBOUNDED_SIDE`
bool has_on_unbounded_side(const Point_2& q) const
{ return bounded_side(q) == ON_UNBOUNDED_SIDE; }
/// @}
/// \name Random Access Methods
/// @{
/// Returns a (const) reference to the `i`-th vertex.
const Point_2& vertex(std::size_t i) const
{
CGAL_precondition( i < d_container.size() );
return *(std::next(d_container.begin(), i));
}
/// Returns a (const) reference to the `i`-th vertex.
const Point_2& operator[](std::size_t i) const
{ return vertex(i); }
/// Returns a reference to the `i`-th vertex.
Point_2& vertex(std::size_t i)
{
CGAL_precondition( i < d_container.size() );
return *(std::next(d_container.begin(), i));
}
/// Returns a reference to the `i`-th vertex.
Point_2& operator[](std::size_t i)
{ return vertex(i); }
/// Returns the `i`-th edge.
Segment_2 edge(std::size_t i) const
{ return *(std::next(edges_begin(), i)); }
/// @}
/// \name Miscellaneous
/// @{
/// Returns the number of vertices of the polygon.
std::size_t size() const
{ return d_container.size(); }
/// Returns `size() == 0`.
bool is_empty() const
{ return d_container.empty(); }
/// Returns a const reference to the sequence of vertices of the polygon.
const Container_& container() const
{ return d_container; }
/// Returns a reference to the sequence of vertices of the polygon.
Container_& container()
{ return d_container; }
/// Returns an iterator to the first vertex of the polygon.
typename Container_::iterator begin()
{
return container().begin();
}
/// Returns an iterator to the element after the last vertex of the polygon.
typename Container_::iterator end()
{
return container().end();
}
/// Returns a const iterator to the first vertex of the polygon.
const typename Container_::const_iterator begin() const
{
return container().begin();
}
/// Returns a const iterator to the element after the last vertex of the polygon.
const typename Container_::const_iterator end() const
{
return container().end();
}
/// Resizes the container. Calls `container().resize(s)`.
void resize(std::size_t s)
{
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_,Container_> &q) const
{ return this == &q; }
Traits_ const &traits_member() const { return traits;}
private:
Container_ d_container;
Traits_ traits;
};
/// \name Global Operators
/// @{
/// Test for equality: two polygons are equal iff there exists a
/// cyclic permutation of the vertices of `p2` such that they are
/// equal to the vertices of `p1`. Note that the template argument
/// `%Container` of `p1` and `p2` may be different.
/// \memberof Polygon_2
template <class Traits_, class Container1_P, class Container2_P>
bool operator==( const Polygon_2<Traits_,Container1_P> &p1,
const Polygon_2<Traits_,Container2_P> &p2 );
/// Test for inequality.
/// \memberof Polygon_2
template <class Traits_, class Container1_P, class Container2_P>
inline
bool
operator!=(const Polygon_2<Traits_,Container1_P> &p1,
const Polygon_2<Traits_,Container2_P> &p2);
/// Returns the image of the polygon \c p under the transformation \c t.
/// \relates Polygon_2
template <class Transformation, class Traits_, class Container_>
Polygon_2<Traits_,Container_>
transform(const Transformation& t, const Polygon_2<Traits_,Container_>& p);
/// @} // global operators
/// \name I/O
/// The information output in the `std::iostream` is the number of points
/// followed by the output of the coordinates of the vertices.
/// @{
/// Reads a polygon from stream `is` and assigns it to `p`.
/// \pre The extract operator must be defined for `Point_2`.
/// \relates Polygon_2
template <class Traits_, class Container_>
std::istream &operator>>(std::istream &is, Polygon_2<Traits_,Container_>& p);
/// Inserts the polygon `p` into the stream `os`.
/// \pre The insert operator must be defined for `Point_2`.
/// \relates Polygon_2
template <class Traits_, class Container_>
std::ostream &operator<<(std::ostream &os, const Polygon_2<Traits_,Container_>& p);
/// @} // IO
} //namespace CGAL
//-----------------------------------------------------------------------//
// implementation
//-----------------------------------------------------------------------//
#include <CGAL/Polygon_2/Polygon_2_impl.h>
namespace CGAL {
template <class Traits_, class Container1_P, class Container2_P>
inline
bool
operator!=(const Polygon_2<Traits_,Container1_P> &x,
const Polygon_2<Traits_,Container2_P> &y)
{
return !(x==y);
}
} //namespace CGAL
#endif