276 lines
8.4 KiB
C
276 lines
8.4 KiB
C
|
// Copyright (c) 2005
|
||
|
// 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); you can redistribute it and/or
|
||
|
// modify it under the terms of the GNU Lesser General Public License as
|
||
|
// published by the Free Software Foundation; either version 3 of the License,
|
||
|
// or (at your option) any later version.
|
||
|
//
|
||
|
// Licensees holding a valid commercial license may use this file in
|
||
|
// accordance with the commercial license agreement provided with the software.
|
||
|
//
|
||
|
// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
|
||
|
// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||
|
//
|
||
|
// $URL$
|
||
|
// $Id$
|
||
|
// SPDX-License-Identifier: LGPL-3.0+
|
||
|
//
|
||
|
//
|
||
|
// Author(s) : Baruch Zukerman <baruchzu@post.tau.ac.il>
|
||
|
|
||
|
#ifndef CGAL_POLYGON_WITH_HOLES_2_H
|
||
|
#define CGAL_POLYGON_WITH_HOLES_2_H
|
||
|
|
||
|
#include <CGAL/Polygon_2.h>
|
||
|
#include <CGAL/General_polygon_with_holes_2.h>
|
||
|
#include <vector>
|
||
|
#include <algorithm>
|
||
|
|
||
|
namespace CGAL {
|
||
|
|
||
|
/*!
|
||
|
\ingroup PkgPolygon2
|
||
|
|
||
|
The class `Polygon_with_holes_2` models the concept `GeneralPolygonWithHoles_2`.
|
||
|
It represents a linear polygon with holes. It is parameterized with two
|
||
|
types (`Kernel` and `Container`) that are used to instantiate
|
||
|
the type `Polygon_2<Kernel,Container>`. The latter is used to
|
||
|
represents the outer boundary and the boundary of the holes (if any exist).
|
||
|
|
||
|
\cgalModels `GeneralPolygonWithHoles_2`
|
||
|
|
||
|
*/
|
||
|
template <class Kernel,
|
||
|
class Containter = std::vector<typename Kernel::Point_2> >
|
||
|
class Polygon_with_holes_2 :
|
||
|
public General_polygon_with_holes_2<CGAL::Polygon_2<Kernel, Containter> >
|
||
|
{
|
||
|
public:
|
||
|
|
||
|
typedef CGAL::Polygon_2<Kernel, Containter> Polygon_2;
|
||
|
typedef General_polygon_with_holes_2<Polygon_2> Base;
|
||
|
typedef typename Base::Hole_const_iterator Hole_const_iterator;
|
||
|
typedef typename Base::Size Size;
|
||
|
|
||
|
/*! Default constructor. */
|
||
|
Polygon_with_holes_2 () :
|
||
|
Base()
|
||
|
{}
|
||
|
|
||
|
/*! Constructor from the base class. */
|
||
|
Polygon_with_holes_2 (const Base& base) :
|
||
|
Base (base)
|
||
|
{}
|
||
|
|
||
|
/*! Constructor from a polygon. */
|
||
|
explicit Polygon_with_holes_2 (const Polygon_2& pgn_boundary) :
|
||
|
Base (pgn_boundary)
|
||
|
{}
|
||
|
|
||
|
/*! Constructor from a polygon (outer boundary) and hole polygons. */
|
||
|
template <class HolesInputIterator>
|
||
|
Polygon_with_holes_2 (const Polygon_2& pgn_boundary,
|
||
|
HolesInputIterator h_begin,
|
||
|
HolesInputIterator h_end) :
|
||
|
Base (pgn_boundary, h_begin, h_end)
|
||
|
{}
|
||
|
|
||
|
/*! Obtain the bounding box of the polygon with holes */
|
||
|
Bbox_2 bbox() const { return this->outer_boundary().bbox(); }
|
||
|
};
|
||
|
|
||
|
//-----------------------------------------------------------------------//
|
||
|
// operator<<
|
||
|
//-----------------------------------------------------------------------//
|
||
|
|
||
|
/*!
|
||
|
This operator exports a polygon with holes to the output stream `out`.
|
||
|
|
||
|
An ASCII and a binary format exist. The format can be selected with
|
||
|
the \cgal modifiers for streams, `set_ascii_mode()` and `set_binary_mode()`
|
||
|
respectively. The modifier `set_pretty_mode()` can be used to allow for (a
|
||
|
few) structuring comments in the output. Otherwise, the output would
|
||
|
be free of comments. The default for writing is ASCII without
|
||
|
comments.
|
||
|
|
||
|
The number of points of the outer boundary is exported followed by the
|
||
|
points themselves in counterclockwise order. Then, the number of holes
|
||
|
is exported, and for each hole, the number of points on its outer
|
||
|
boundary is exported followed by the points themselves in clockwise
|
||
|
order.
|
||
|
|
||
|
\relates Polygon_with_holes_2
|
||
|
*/
|
||
|
template <class Kernel_, class Container_>
|
||
|
std::ostream& operator<<(std::ostream &os,
|
||
|
const Polygon_with_holes_2<Kernel_, Container_>& p)
|
||
|
{
|
||
|
typename Polygon_with_holes_2<Kernel_,Container_>::Hole_const_iterator i;
|
||
|
|
||
|
switch(get_mode(os)) {
|
||
|
case IO::ASCII :
|
||
|
os << p.outer_boundary() << ' ' << p.number_of_holes()<<' ';
|
||
|
for (i = p.holes_begin(); i != p.holes_end(); ++i) {
|
||
|
os << *i << ' ';
|
||
|
}
|
||
|
return os;
|
||
|
|
||
|
case IO::BINARY :
|
||
|
os << p.outer_boundary() << p.number_of_holes();
|
||
|
for (i = p.holes_begin(); i != p.holes_end(); ++i) {
|
||
|
os << *i ;
|
||
|
}
|
||
|
return os;
|
||
|
|
||
|
default:
|
||
|
os << "Polygon_with_holes_2(" << std::endl;
|
||
|
if(p.is_unbounded())
|
||
|
os << "No outer bounary" << std::endl;
|
||
|
else
|
||
|
{
|
||
|
os << "Boundary(" << std::endl;
|
||
|
os << p.outer_boundary() << std::endl;
|
||
|
}
|
||
|
|
||
|
os << "Holes" << std::endl;
|
||
|
os << p.number_of_holes()<<std::endl;
|
||
|
for (i = p.holes_begin(); i != p.holes_end(); ++i) {
|
||
|
os <<" "<< *i << std::endl;
|
||
|
}
|
||
|
|
||
|
os << ")" << std::endl;
|
||
|
return os;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------//
|
||
|
// operator>>
|
||
|
//-----------------------------------------------------------------------//
|
||
|
|
||
|
/*!
|
||
|
This operator imports a polygon with holes from the input stream `in`.
|
||
|
|
||
|
An ASCII and a binary format exist. The stream detects the format
|
||
|
automatically and can read both.
|
||
|
|
||
|
The format consists of the number of points of the outer boundary followed
|
||
|
by the points themselves in counterclockwise order, followed by the number of holes,
|
||
|
and for each hole, the number of points of the outer boundary is followed
|
||
|
by the points themselves in clockwise order.
|
||
|
|
||
|
\relates Polygon_with_holes_2
|
||
|
*/
|
||
|
template <class Kernel_, class Container_>
|
||
|
std::istream &operator>>(std::istream &is,
|
||
|
Polygon_with_holes_2<Kernel_, Container_>& p)
|
||
|
{
|
||
|
typedef CGAL::Polygon_2<Kernel_, Container_> Polygon_2;
|
||
|
p.clear();
|
||
|
is >> p.outer_boundary();
|
||
|
|
||
|
unsigned int n; // number of holes;
|
||
|
is >> n;
|
||
|
if(is)
|
||
|
{
|
||
|
for (unsigned int i=0; i<n; i++)
|
||
|
{
|
||
|
Polygon_2 hole;
|
||
|
is >> hole;
|
||
|
p.add_hole(hole);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return is;
|
||
|
}
|
||
|
|
||
|
|
||
|
//-----------------------------------------------------------------------//
|
||
|
// operator==
|
||
|
//-----------------------------------------------------------------------//
|
||
|
template <class Kernel_, class Container_>
|
||
|
bool operator==(const Polygon_with_holes_2<Kernel_, Container_>& p1,
|
||
|
const Polygon_with_holes_2<Kernel_, Container_>& p2)
|
||
|
{
|
||
|
typedef typename
|
||
|
Polygon_with_holes_2<Kernel_, Container_>::Hole_const_iterator HCI;
|
||
|
typedef CGAL::Polygon_2<Kernel_, Container_> Polygon_2;
|
||
|
if(&p1 == &p2)
|
||
|
return (true);
|
||
|
|
||
|
if(p1.number_of_holes() != p2.number_of_holes())
|
||
|
return (false);
|
||
|
|
||
|
if(p1.outer_boundary() != p2.outer_boundary())
|
||
|
return (false);
|
||
|
|
||
|
std::list<Polygon_2> tmp_list(p2.holes_begin(), p2.holes_end());
|
||
|
|
||
|
HCI i = p1.holes_begin();
|
||
|
for(; i!= p1.holes_end(); ++i)
|
||
|
{
|
||
|
typename std::list<Polygon_2>::iterator j =
|
||
|
(std::find(tmp_list.begin(), tmp_list.end(), *i));
|
||
|
|
||
|
if(j == tmp_list.end())
|
||
|
return (false);
|
||
|
|
||
|
tmp_list.erase(j);
|
||
|
}
|
||
|
|
||
|
|
||
|
CGAL_assertion(tmp_list.empty());
|
||
|
return (true);
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------//
|
||
|
// operator!=
|
||
|
//-----------------------------------------------------------------------//
|
||
|
template <class Kernel_, class Container_>
|
||
|
inline bool operator!=(const Polygon_with_holes_2<Kernel_, Container_>& p1,
|
||
|
const Polygon_with_holes_2<Kernel_, Container_>& p2)
|
||
|
{
|
||
|
return (!(p1==p2));
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------//
|
||
|
// operator==
|
||
|
//-----------------------------------------------------------------------//
|
||
|
template <class Kernel_, class Container_>
|
||
|
bool operator==(const Polygon_with_holes_2<Kernel_, Container_>& p1,
|
||
|
const Polygon_2<Kernel_, Container_>& p2)
|
||
|
{
|
||
|
return (p1.outer_boundary() == p2 && !p1.number_of_holes());
|
||
|
}
|
||
|
|
||
|
template <class Kernel_, class Container_>
|
||
|
inline bool operator==(const Polygon_2<Kernel_, Container_>& p1,
|
||
|
const Polygon_with_holes_2<Kernel_, Container_>& p2)
|
||
|
{
|
||
|
return (p2 == p1);
|
||
|
}
|
||
|
|
||
|
template <class Kernel_, class Container_>
|
||
|
inline bool operator!=(const Polygon_with_holes_2<Kernel_, Container_>& p1,
|
||
|
const Polygon_2<Kernel_, Container_>& p2)
|
||
|
{
|
||
|
return (!(p1==p2));
|
||
|
}
|
||
|
|
||
|
template <class Kernel_, class Container_>
|
||
|
inline bool operator!=(const Polygon_2<Kernel_, Container_>& p1,
|
||
|
const Polygon_with_holes_2<Kernel_, Container_>& p2)
|
||
|
{
|
||
|
return (!(p1==p2));
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
} //namespace CGAL
|
||
|
|
||
|
#endif
|