1 // Boost.Geometry (aka GGL, Generic Geometry Library)
2 
3 // Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
4 // Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
5 // Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
6 // Copyright (c) 2014 Adam Wulkiewicz, Lodz, Poland.
7 
8 // Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
9 // (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
10 
11 // Use, modification and distribution is subject to the Boost Software License,
12 // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
13 // http://www.boost.org/LICENSE_1_0.txt)
14 
15 #ifndef BOOST_GEOMETRY_GEOMETRIES_POLYGON_HPP
16 #define BOOST_GEOMETRY_GEOMETRIES_POLYGON_HPP
17 
18 #include <memory>
19 #include <vector>
20 
21 #include <boost/concept/assert.hpp>
22 
23 #include <boost/geometry/core/exterior_ring.hpp>
24 #include <boost/geometry/core/interior_rings.hpp>
25 #include <boost/geometry/core/point_type.hpp>
26 #include <boost/geometry/core/ring_type.hpp>
27 #include <boost/geometry/geometries/concepts/point_concept.hpp>
28 #include <boost/geometry/geometries/ring.hpp>
29 
30 #include <boost/config.hpp>
31 #ifndef BOOST_NO_CXX11_HDR_INITIALIZER_LIST
32 #include <initializer_list>
33 #endif
34 
35 namespace boost { namespace geometry
36 {
37 
38 namespace model
39 {
40 
41 /*!
42 \brief The polygon contains an outer ring and zero or more inner rings.
43 \ingroup geometries
44 \tparam Point point type
45 \tparam ClockWise true for clockwise direction,
46             false for CounterClockWise direction
47 \tparam Closed true for closed polygons (last point == first point),
48             false open points
49 \tparam PointList container type for points,
50             for example std::vector, std::list, std::deque
51 \tparam RingList container type for inner rings,
52             for example std::vector, std::list, std::deque
53 \tparam PointAlloc container-allocator-type, for the points
54 \tparam RingAlloc container-allocator-type, for the rings
55 \note The container collecting the points in the rings can be different
56     from the container collecting the inner rings. They all default to vector.
57 
58 \qbk{[include reference/geometries/polygon.qbk]}
59 \qbk{before.synopsis,
60 [heading Model of]
61 [link geometry.reference.concepts.concept_polygon Polygon Concept]
62 }
63 
64 
65 */
66 template
67 <
68     typename Point,
69     bool ClockWise = true,
70     bool Closed = true,
71     template<typename, typename> class PointList = std::vector,
72     template<typename, typename> class RingList = std::vector,
73     template<typename> class PointAlloc = std::allocator,
74     template<typename> class RingAlloc = std::allocator
75 >
76 class polygon
77 {
78     BOOST_CONCEPT_ASSERT( (concepts::Point<Point>) );
79 
80 public:
81 
82     // Member types
83     typedef Point point_type;
84     typedef ring<Point, ClockWise, Closed, PointList, PointAlloc> ring_type;
85     typedef RingList<ring_type , RingAlloc<ring_type > > inner_container_type;
86 
outer() const87     inline ring_type const& outer() const { return m_outer; }
inners() const88     inline inner_container_type const& inners() const { return m_inners; }
89 
outer()90     inline ring_type& outer() { return m_outer; }
inners()91     inline inner_container_type & inners() { return m_inners; }
92 
93 #ifndef BOOST_NO_CXX11_HDR_INITIALIZER_LIST
94 
95     // default constructor definition is required only
96     // if the constructor taking std::initializer_list is defined
97 
98     /// \constructor_default{polygon}
polygon()99     inline polygon()
100         : m_outer()
101         , m_inners()
102     {}
103 
104     /// \constructor_initializer_list{polygon}
polygon(std::initializer_list<ring_type> l)105     inline polygon(std::initializer_list<ring_type> l)
106         : m_outer(l.size() > 0 ? *l.begin() : ring_type())
107         , m_inners(l.size() > 0 ? l.begin() + 1 : l.begin(), l.end())
108     {}
109 
110 // Commented out for now in order to support Boost.Assign
111 // Without this assignment operator first the object should be created
112 //   from initializer list, then it shoudl be moved.
113 //// Without this workaround in MSVC the assignment operator is ambiguous
114 //#ifndef BOOST_MSVC
115 //    /// \assignment_initializer_list{polygon}
116 //    inline polygon & operator=(std::initializer_list<ring_type> l)
117 //    {
118 //        if ( l.size() > 0 )
119 //        {
120 //            m_outer = *l.begin();
121 //            m_inners.assign(l.begin() + 1, l.end());
122 //        }
123 //        else
124 //        {
125 //            m_outer.clear();
126 //            m_inners.clear();
127 //        }
128 //        return *this;
129 //    }
130 //#endif
131 
132 #endif
133 
134     /// Utility method, clears outer and inner rings
clear()135     inline void clear()
136     {
137         m_outer.clear();
138         m_inners.clear();
139     }
140 
141 private:
142 
143     ring_type m_outer;
144     inner_container_type m_inners;
145 };
146 
147 
148 } // namespace model
149 
150 
151 #ifndef DOXYGEN_NO_TRAITS_SPECIALIZATIONS
152 namespace traits
153 {
154 
155 template
156 <
157     typename Point,
158     bool ClockWise, bool Closed,
159     template<typename, typename> class PointList,
160     template<typename, typename> class RingList,
161     template<typename> class PointAlloc,
162     template<typename> class RingAlloc
163 >
164 struct tag
165 <
166     model::polygon
167         <
168             Point, ClockWise, Closed,
169             PointList, RingList, PointAlloc, RingAlloc
170         >
171 >
172 {
173     typedef polygon_tag type;
174 };
175 
176 template
177 <
178     typename Point,
179     bool ClockWise, bool Closed,
180     template<typename, typename> class PointList,
181     template<typename, typename> class RingList,
182     template<typename> class PointAlloc,
183     template<typename> class RingAlloc
184 >
185 struct ring_const_type
186 <
187     model::polygon
188         <
189             Point, ClockWise, Closed,
190             PointList, RingList, PointAlloc, RingAlloc
191         >
192 >
193 {
194     typedef typename model::polygon
195         <
196             Point, ClockWise, Closed,
197             PointList, RingList,
198             PointAlloc, RingAlloc
199         >::ring_type const& type;
200 };
201 
202 
203 template
204 <
205     typename Point,
206     bool ClockWise, bool Closed,
207     template<typename, typename> class PointList,
208     template<typename, typename> class RingList,
209     template<typename> class PointAlloc,
210     template<typename> class RingAlloc
211 >
212 struct ring_mutable_type
213 <
214     model::polygon
215         <
216             Point, ClockWise, Closed,
217             PointList, RingList, PointAlloc, RingAlloc
218         >
219 >
220 {
221     typedef typename model::polygon
222         <
223             Point, ClockWise, Closed,
224             PointList, RingList,
225             PointAlloc, RingAlloc
226         >::ring_type& type;
227 };
228 
229 template
230 <
231     typename Point,
232     bool ClockWise, bool Closed,
233     template<typename, typename> class PointList,
234     template<typename, typename> class RingList,
235     template<typename> class PointAlloc,
236     template<typename> class RingAlloc
237 >
238 struct interior_const_type
239 <
240     model::polygon
241         <
242             Point, ClockWise, Closed,
243             PointList, RingList,
244             PointAlloc, RingAlloc
245         >
246 >
247 {
248     typedef typename model::polygon
249         <
250             Point, ClockWise, Closed,
251             PointList, RingList,
252             PointAlloc, RingAlloc
253         >::inner_container_type const& type;
254 };
255 
256 
257 template
258 <
259     typename Point,
260     bool ClockWise, bool Closed,
261     template<typename, typename> class PointList,
262     template<typename, typename> class RingList,
263     template<typename> class PointAlloc,
264     template<typename> class RingAlloc
265 >
266 struct interior_mutable_type
267 <
268     model::polygon
269         <
270             Point, ClockWise, Closed,
271             PointList, RingList,
272             PointAlloc, RingAlloc
273         >
274 >
275 {
276     typedef typename model::polygon
277         <
278             Point, ClockWise, Closed,
279             PointList, RingList,
280             PointAlloc, RingAlloc
281         >::inner_container_type& type;
282 };
283 
284 
285 template
286 <
287     typename Point,
288     bool ClockWise, bool Closed,
289     template<typename, typename> class PointList,
290     template<typename, typename> class RingList,
291     template<typename> class PointAlloc,
292     template<typename> class RingAlloc
293 >
294 struct exterior_ring
295 <
296     model::polygon
297         <
298             Point, ClockWise, Closed,
299             PointList, RingList, PointAlloc, RingAlloc
300         >
301 >
302 {
303     typedef model::polygon
304         <
305             Point, ClockWise, Closed,
306             PointList, RingList,
307             PointAlloc, RingAlloc
308         > polygon_type;
309 
getboost::geometry::traits::exterior_ring310     static inline typename polygon_type::ring_type& get(polygon_type& p)
311     {
312         return p.outer();
313     }
314 
getboost::geometry::traits::exterior_ring315     static inline typename polygon_type::ring_type const& get(
316                     polygon_type const& p)
317     {
318         return p.outer();
319     }
320 };
321 
322 template
323 <
324     typename Point,
325     bool ClockWise, bool Closed,
326     template<typename, typename> class PointList,
327     template<typename, typename> class RingList,
328     template<typename> class PointAlloc,
329     template<typename> class RingAlloc
330 >
331 struct interior_rings
332 <
333     model::polygon
334         <
335             Point, ClockWise, Closed,
336             PointList, RingList,
337             PointAlloc, RingAlloc
338         >
339 >
340 {
341     typedef model::polygon
342         <
343             Point, ClockWise, Closed, PointList, RingList,
344             PointAlloc, RingAlloc
345         > polygon_type;
346 
getboost::geometry::traits::interior_rings347     static inline typename polygon_type::inner_container_type& get(
348                     polygon_type& p)
349     {
350         return p.inners();
351     }
352 
getboost::geometry::traits::interior_rings353     static inline typename polygon_type::inner_container_type const& get(
354                     polygon_type const& p)
355     {
356         return p.inners();
357     }
358 };
359 
360 } // namespace traits
361 #endif // DOXYGEN_NO_TRAITS_SPECIALIZATIONS
362 
363 
364 
365 }} // namespace boost::geometry
366 
367 #endif // BOOST_GEOMETRY_GEOMETRIES_POLYGON_HPP
368