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 | |
7 | // This file was modified by Oracle on 2014. |
8 | // Modifications copyright (c) 2014 Oracle and/or its affiliates. |
9 | |
10 | // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle |
11 | |
12 | // Parts of Boost.Geometry are redesigned from Geodan's Geographic Library |
13 | // (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands. |
14 | |
15 | // Use, modification and distribution is subject to the Boost Software License, |
16 | // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at |
17 | // http://www.boost.org/LICENSE_1_0.txt) |
18 | |
19 | #ifndef BOOST_GEOMETRY_CORE_CLOSURE_HPP |
20 | #define BOOST_GEOMETRY_CORE_CLOSURE_HPP |
21 | |
22 | #include <boost/mpl/assert.hpp> |
23 | #include <boost/mpl/size_t.hpp> |
24 | #include <boost/range/value_type.hpp> |
25 | #include <boost/type_traits/remove_const.hpp> |
26 | |
27 | #include <boost/geometry/core/ring_type.hpp> |
28 | #include <boost/geometry/core/tag.hpp> |
29 | #include <boost/geometry/core/tags.hpp> |
30 | |
31 | namespace boost { namespace geometry |
32 | { |
33 | |
34 | |
35 | /*! |
36 | \brief Enumerates options for defining if polygons are open or closed |
37 | \ingroup enum |
38 | \details The enumeration closure_selector describes options for if a polygon is |
39 | open or closed. In a closed polygon the very first point (per ring) should |
40 | be equal to the very last point. |
41 | The specific closing property of a polygon type is defined by the closure |
42 | metafunction. The closure metafunction defines a value, which is one of the |
43 | values enumerated in the closure_selector |
44 | |
45 | \qbk{ |
46 | [heading See also] |
47 | [link geometry.reference.core.closure The closure metafunction] |
48 | } |
49 | */ |
50 | enum closure_selector |
51 | { |
52 | /// Rings are open: first point and last point are different, algorithms |
53 | /// close them explicitly on the fly |
54 | open = 0, |
55 | /// Rings are closed: first point and last point must be the same |
56 | closed = 1, |
57 | /// (Not yet implemented): algorithms first figure out if ring must be |
58 | /// closed on the fly |
59 | closure_undertermined = -1 |
60 | }; |
61 | |
62 | namespace traits |
63 | { |
64 | |
65 | /*! |
66 | \brief Traits class indicating if points within a |
67 | ring or (multi)polygon are closed (last point == first point), |
68 | open or not known. |
69 | \ingroup traits |
70 | \par Geometries: |
71 | - ring |
72 | \tparam G geometry |
73 | */ |
74 | template <typename G> |
75 | struct closure |
76 | { |
77 | static const closure_selector value = closed; |
78 | }; |
79 | |
80 | |
81 | } // namespace traits |
82 | |
83 | |
84 | #ifndef DOXYGEN_NO_DETAIL |
85 | namespace core_detail { namespace closure |
86 | { |
87 | |
88 | struct closed |
89 | { |
90 | static const closure_selector value = geometry::closed; |
91 | }; |
92 | |
93 | |
94 | /// Metafunction to define the minimum size of a ring: |
95 | /// 3 for open rings, 4 for closed rings |
96 | template <closure_selector Closure> |
97 | struct minimum_ring_size {}; |
98 | |
99 | template <> |
100 | struct minimum_ring_size<geometry::closed> : boost::mpl::size_t<4> {}; |
101 | |
102 | template <> |
103 | struct minimum_ring_size<geometry::open> : boost::mpl::size_t<3> {}; |
104 | |
105 | |
106 | }} // namespace detail::point_order |
107 | #endif // DOXYGEN_NO_DETAIL |
108 | |
109 | |
110 | |
111 | #ifndef DOXYGEN_NO_DISPATCH |
112 | namespace core_dispatch |
113 | { |
114 | |
115 | template <typename Tag, typename Geometry> |
116 | struct closure |
117 | { |
118 | BOOST_MPL_ASSERT_MSG |
119 | ( |
120 | false, NOT_IMPLEMENTED_FOR_THIS_GEOMETRY_TYPE |
121 | , (types<Geometry>) |
122 | ); |
123 | }; |
124 | |
125 | template <typename Box> |
126 | struct closure<point_tag, Box> : public core_detail::closure::closed {}; |
127 | |
128 | template <typename Box> |
129 | struct closure<box_tag, Box> : public core_detail::closure::closed {}; |
130 | |
131 | template <typename Box> |
132 | struct closure<segment_tag, Box> : public core_detail::closure::closed {}; |
133 | |
134 | template <typename LineString> |
135 | struct closure<linestring_tag, LineString> |
136 | : public core_detail::closure::closed {}; |
137 | |
138 | |
139 | template <typename Ring> |
140 | struct closure<ring_tag, Ring> |
141 | { |
142 | static const closure_selector value |
143 | = geometry::traits::closure<Ring>::value; |
144 | }; |
145 | |
146 | // Specialization for Polygon: the closure is the closure of its rings |
147 | template <typename Polygon> |
148 | struct closure<polygon_tag, Polygon> |
149 | { |
150 | static const closure_selector value = core_dispatch::closure |
151 | < |
152 | ring_tag, |
153 | typename ring_type<polygon_tag, Polygon>::type |
154 | >::value ; |
155 | }; |
156 | |
157 | template <typename MultiPoint> |
158 | struct closure<multi_point_tag, MultiPoint> |
159 | : public core_detail::closure::closed {}; |
160 | |
161 | template <typename MultiLinestring> |
162 | struct closure<multi_linestring_tag, MultiLinestring> |
163 | : public core_detail::closure::closed {}; |
164 | |
165 | // Specialization for MultiPolygon: the closure is the closure of Polygon's rings |
166 | template <typename MultiPolygon> |
167 | struct closure<multi_polygon_tag, MultiPolygon> |
168 | { |
169 | static const closure_selector value = core_dispatch::closure |
170 | < |
171 | polygon_tag, |
172 | typename boost::range_value<MultiPolygon>::type |
173 | >::value ; |
174 | }; |
175 | |
176 | } // namespace core_dispatch |
177 | #endif // DOXYGEN_NO_DISPATCH |
178 | |
179 | |
180 | /*! |
181 | \brief \brief_meta{value, closure (clockwise\, counterclockwise), |
182 | \meta_geometry_type} |
183 | \tparam Geometry \tparam_geometry |
184 | \ingroup core |
185 | |
186 | \qbk{[include reference/core/closure.qbk]} |
187 | */ |
188 | template <typename Geometry> |
189 | struct closure |
190 | { |
191 | static const closure_selector value = core_dispatch::closure |
192 | < |
193 | typename tag<Geometry>::type, |
194 | typename util::bare_type<Geometry>::type |
195 | >::value; |
196 | }; |
197 | |
198 | |
199 | }} // namespace boost::geometry |
200 | |
201 | |
202 | #endif // BOOST_GEOMETRY_CORE_CLOSURE_HPP |
203 | |