1 // Copyright (c) 2005
2 // Utrecht University (The Netherlands),
3 // ETH Zurich (Switzerland),
4 // INRIA Sophia-Antipolis (France),
5 // Max-Planck-Institute Saarbruecken (Germany),
6 // and Tel-Aviv University (Israel).  All rights reserved.
7 //
8 // This file is part of CGAL (www.cgal.org)
9 //
10 // $URL: https://github.com/CGAL/cgal/blob/v5.3/Polygon/include/CGAL/General_polygon_with_holes_2.h $
11 // $Id: General_polygon_with_holes_2.h 4e519a3 2021-05-05T13:15:37+02:00 Sébastien Loriot
12 // SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial
13 //
14 //
15 // Author(s)     : Baruch Zukerman <baruchzu@post.tau.ac.il>
16 
17 #ifndef CGAL_GENERAL_POLYGON_WITH_HOLES_2_H
18 #define CGAL_GENERAL_POLYGON_WITH_HOLES_2_H
19 
20 #include <deque>
21 #include <iostream>
22 #include <CGAL/IO/io.h>
23 
24 namespace CGAL {
25 
26 /*!
27 \ingroup PkgPolygon2Ref
28 
29 The class `General_polygon_with_holes_2` models the concept
30 `GeneralPolygonWithHoles_2`. It represents a general polygon with
31 holes. It is parameterized with a type `Polygon` used to define
32 the exposed type `General_polygon_2`. This type represents the
33 outer boundary of the general polygon and the outer boundaries of
34 each hole.
35 
36 \tparam Polygon_ must have input and output operators.
37 
38 \cgalModels `GeneralPolygonWithHoles_2`
39 
40 */
41 template <class Polygon_>
42 class General_polygon_with_holes_2
43 {
44 public:
45 
46 /// \name Definition
47 
48 /// @{
49   /// polygon without hole type
50   typedef Polygon_                                                        General_polygon_2;
51 /// @}
52 
53   typedef std::deque<General_polygon_2>               Holes_container;
54 
55   typedef typename Holes_container::iterator          Hole_iterator;
56   typedef typename Holes_container::const_iterator    Hole_const_iterator;
57 
58   typedef unsigned int                                 Size;
59 
General_polygon_with_holes_2()60   General_polygon_with_holes_2() : m_pgn()
61   {}
62 
63 
General_polygon_with_holes_2(const General_polygon_2 & pgn_boundary)64   explicit General_polygon_with_holes_2(const General_polygon_2& pgn_boundary)
65   : m_pgn(pgn_boundary)
66   {}
67 
68 
69   template <class HolesInputIterator>
General_polygon_with_holes_2(const General_polygon_2 & pgn_boundary,HolesInputIterator h_begin,HolesInputIterator h_end)70   General_polygon_with_holes_2(const General_polygon_2& pgn_boundary,
71                        HolesInputIterator h_begin,
72                        HolesInputIterator h_end) : m_pgn(pgn_boundary),
73                                                    m_holes(h_begin, h_end)
74   {}
75 
holes()76   Holes_container& holes()
77   {
78     return m_holes;
79   }
80 
holes()81   const Holes_container& holes() const
82   {
83     return m_holes;
84   }
85 
holes_begin()86   Hole_iterator holes_begin()
87   {
88     return m_holes.begin();
89   }
90 
holes_end()91   Hole_iterator holes_end()
92   {
93     return m_holes.end();
94   }
95 
holes_begin()96   Hole_const_iterator holes_begin() const
97   {
98     return m_holes.begin();
99   }
100 
holes_end()101   Hole_const_iterator holes_end() const
102   {
103     return m_holes.end();
104   }
105 
is_unbounded()106   bool is_unbounded() const
107   {
108     return m_pgn.is_empty();
109   }
110 
outer_boundary()111   General_polygon_2& outer_boundary()
112   {
113     return m_pgn;
114   }
115 
outer_boundary()116   const General_polygon_2& outer_boundary() const
117   {
118     return m_pgn;
119   }
120 
add_hole(const General_polygon_2 & pgn_hole)121   void add_hole(const General_polygon_2& pgn_hole)
122   {
123     m_holes.push_back(pgn_hole);
124   }
125 
erase_hole(Hole_iterator hit)126   void erase_hole(Hole_iterator hit)
127   {
128     m_holes.erase(hit);
129   }
130 
has_holes()131   bool has_holes() const
132   {
133     return (!m_holes.empty());
134   }
135 
number_of_holes()136   Size number_of_holes() const
137   {
138     return static_cast<Size>(m_holes.size());
139   }
140 
clear()141   void clear()
142   {
143     m_pgn.clear();
144     m_holes.clear();
145   }
146 
is_plane()147   bool is_plane() const
148   {
149     return (m_pgn.is_empty() && m_holes.empty());
150   }
151 
152 
153 
154 protected:
155 
156   General_polygon_2           m_pgn;
157   Holes_container            m_holes;
158 };
159 
160 
161 //-----------------------------------------------------------------------//
162 //                          operator<<
163 //-----------------------------------------------------------------------//
164 /*!
165 This operator exports a General_polygon_with_holes_2 to the output stream `out`.
166 
167 An ASCII and a binary format exist. The format can be selected with
168 the \cgal modifiers for streams, `set_ascii_mode(0` and `set_binary_mode()`
169 respectively. The modifier `set_pretty_mode()` can be used to allow for (a
170 few) structuring comments in the output. Otherwise, the output would
171 be free of comments. The default for writing is ASCII without
172 comments.
173 
174 The number of curves of the outer boundary is exported followed by the
175 curves themselves. Then, the number of holes
176 is exported, and for each hole, the number of curves on its outer
177 boundary is exported followed by the curves themselves.
178 
179 \relates General_polygon_with_holes_2
180 */
181 template <class Polygon_>
182 std::ostream
183 &operator<<(std::ostream &os, const General_polygon_with_holes_2<Polygon_>& p)
184 {
185   typename General_polygon_with_holes_2<Polygon_>::Hole_const_iterator hit;
186 
187   switch(IO::get_mode(os)) {
188     case IO::ASCII :
189       os << p.outer_boundary() << ' ' << p.number_of_holes()<< ' ';
190       for (hit = p.holes_begin(); hit != p.holes_end(); ++hit) {
191         os << *hit << ' ';
192       }
193       return os;
194 
195     case IO::BINARY :
196       os << p.outer_boundary()  << p.number_of_holes();
197       for (hit = p.holes_begin(); hit != p.holes_end(); ++hit) {
198         os << *hit;
199       }
200       return os;
201 
202 
203     default:
204       os << "General_polygon_with_holes_2( " << std::endl;
205       os << p.outer_boundary() << " " << p.number_of_holes()<< " ";
206       for (hit = p.holes_begin(); hit != p.holes_end(); ++hit) {
207         os << *hit << " )";
208       }
209       return os;
210   }
211 }
212 
213 //-----------------------------------------------------------------------//
214 //                          operator>>
215 //-----------------------------------------------------------------------//
216 
217 /*!
218 This operator imports a General_polygon_with_holes_2 from the input stream `in`.
219 
220 Both ASCII and binary formats are supported, and the format is automatically detected.
221 
222 The format consists of the number of curves of the outer boundary
223 followed by the curves themselves, followed
224 by the number of holes, and for each hole, the number of curves on its
225 outer boundary is followed by the curves themselves.
226 
227 \relates General_polygon_with_holes_2
228 */
229 template <class Polygon_>
230 std::istream &operator>>(std::istream &is, General_polygon_with_holes_2<Polygon_>& p)
231 {
232   p.clear();
233   is >> p.outer_boundary();
234 
235   unsigned int n_holes;
236   is >> n_holes;
237   if (is)
238   {
239     Polygon_ pgn_hole;
240     for (unsigned int i=0; i<n_holes; i++)
241     {
242       is >> pgn_hole;
243       p.add_hole(pgn_hole);
244     }
245   }
246 
247   return is;
248 }
249 
250 
251 } //namespace CGAL
252 
253 #endif
254