// 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) // // $URL$ // $Id$ // SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial // // // Author(s) : Baruch Zukerman #ifndef CGAL_POLYGON_WITH_HOLES_2_H #define CGAL_POLYGON_WITH_HOLES_2_H #include #include #include #include namespace CGAL { /*! \ingroup PkgPolygon2Ref 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`. This polygon type is used to represent the outer boundary and the boundary of the holes (if any exist). \cgalModels{GeneralPolygonWithHoles_2} */ template > class Polygon_with_holes_2 : public General_polygon_with_holes_2 > { public: typedef Kernel Traits; typedef Container_ Container; typedef CGAL::Polygon_2 Polygon_2; typedef General_polygon_with_holes_2 Base; typedef typename Base::Hole_const_iterator Hole_const_iterator; typedef typename Base::Size Size; /*! %Default constructor. */ Polygon_with_holes_2 () = default; /*! 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) {} /*! Cconstructor moving a polygon */ explicit Polygon_with_holes_2 (Polygon_2&& pgn_boundary) : Base (std::move(pgn_boundary)) {} /*! Constructor from a polygon (outer boundary) and hole polygons. */ template Polygon_with_holes_2 (const Polygon_2& pgn_boundary, HolesInputIterator h_begin, HolesInputIterator h_end) : Base (pgn_boundary, h_begin, h_end) {} /*! Cconstructor moving a polygon. * \note In order to move the hole polygons a * `std::move_iterator` may be used. */ template Polygon_with_holes_2 (Polygon_2&& pgn_boundary, HolesInputIterator h_begin, HolesInputIterator h_end) : Base (std::move(pgn_boundary), h_begin, h_end) {} /*! returns the bounding box of the polygon with holes */ Bbox_2 bbox() const { return this->outer_boundary().bbox(); } }; template Polygon_with_holes_2 transform(const Transformation& t, const Polygon_with_holes_2& pwh) { Polygon_with_holes_2 result(transform(t, pwh.outer_boundary())); for(const auto& hole : pwh.holes()){ result.add_hole(transform(t, hole)); } return result; } //-----------------------------------------------------------------------// // operator<< //-----------------------------------------------------------------------// /*! This operator exports a polygon with holes to the output stream `os`. An \ascii and a binary format exist. The format can be selected with the \cgal modifiers for streams, `CGAL::IO::set_ascii_mode()` and `CGAL::IO::set_binary_mode()`, respectively. The modifier `CGAL::IO::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 std::ostream& operator<<(std::ostream &os, const Polygon_with_holes_2& p) { typename Polygon_with_holes_2::Hole_const_iterator i; switch(IO::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 boundary" << std::endl; else { os << "Boundary(" << std::endl; os << p.outer_boundary() << std::endl; } os << "Holes" << std::endl; os << p.number_of_holes()<> //-----------------------------------------------------------------------// /*! This operator imports a polygon with holes from the input stream `is`. Both \ascii and binary formats are supported, and the format is automatically detected. 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 std::istream &operator>>(std::istream &is, Polygon_with_holes_2& p) { typedef CGAL::Polygon_2 Polygon_2; p.clear(); is >> p.outer_boundary(); unsigned int n; // number of holes; is >> n; if(is) { for (unsigned int i=0; i> hole; p.add_hole(std::move(hole)); } } return is; } //-----------------------------------------------------------------------// // operator== //-----------------------------------------------------------------------// template bool operator==(const Polygon_with_holes_2& p1, const Polygon_with_holes_2& p2) { typedef typename Polygon_with_holes_2::Hole_const_iterator HCI; typedef CGAL::Polygon_2 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 tmp_list(p2.holes_begin(), p2.holes_end()); HCI i = p1.holes_begin(); for(; i!= p1.holes_end(); ++i) { typename std::list::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 inline bool operator!=(const Polygon_with_holes_2& p1, const Polygon_with_holes_2& p2) { return (!(p1==p2)); } //-----------------------------------------------------------------------// // operator== //-----------------------------------------------------------------------// template bool operator==(const Polygon_with_holes_2& p1, const Polygon_2& p2) { return (p1.outer_boundary() == p2 && !p1.number_of_holes()); } template inline bool operator==(const Polygon_2& p1, const Polygon_with_holes_2& p2) { return (p2 == p1); } template inline bool operator!=(const Polygon_with_holes_2& p1, const Polygon_2& p2) { return (!(p1==p2)); } template inline bool operator!=(const Polygon_2& p1, const Polygon_with_holes_2& p2) { return (!(p1==p2)); } } //namespace CGAL #endif