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-2020.
8 // Modifications copyright (c) 2014-2020 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_POINT_ORDER_HPP
20 #define BOOST_GEOMETRY_CORE_POINT_ORDER_HPP
21 
22 
23 #include <boost/range/value_type.hpp>
24 
25 #include <boost/geometry/core/ring_type.hpp>
26 #include <boost/geometry/core/static_assert.hpp>
27 #include <boost/geometry/core/tag.hpp>
28 #include <boost/geometry/core/tags.hpp>
29 #include <boost/geometry/util/type_traits_std.hpp>
30 
31 namespace boost { namespace geometry
32 {
33 
34 /*!
35 \brief Enumerates options for the order of points within polygons
36 \ingroup enum
37 \details The enumeration order_selector describes options for the order of
38     points within a polygon. Polygons can be ordered either clockwise or
39     counterclockwise. The specific order of a polygon type is defined by the
40     point_order metafunction. The point_order metafunction defines a value,
41     which is one of the values enumerated in the order_selector
42 
43 \qbk{
44 [heading See also]
45 [link geometry.reference.core.point_order The point_order metafunction]
46 }
47 */
48 enum order_selector
49 {
50     /// Points are ordered clockwise
51     clockwise = 1,
52     /// Points are ordered counter clockwise
53     counterclockwise = 2,
54     /// Points might be stored in any order, algorithms will determine it on the
55     /// fly (not yet supported)
56     order_undetermined = 0
57 };
58 
59 namespace traits
60 {
61 
62 /*!
63 \brief Traits class indicating the order of contained points within a
64     ring or (multi)polygon, clockwise, counter clockwise or not known.
65 \ingroup traits
66 \tparam Ring ring
67 */
68 template <typename Ring>
69 struct point_order
70 {
71     static const order_selector value = clockwise;
72 };
73 
74 
75 } // namespace traits
76 
77 
78 #ifndef DOXYGEN_NO_DETAIL
79 namespace detail { namespace point_order
80 {
81 
82 struct clockwise
83 {
84     static const order_selector value = geometry::clockwise;
85 };
86 
87 
88 }} // namespace detail::point_order
89 #endif // DOXYGEN_NO_DETAIL
90 
91 
92 
93 #ifndef DOXYGEN_NO_DISPATCH
94 namespace core_dispatch
95 {
96 
97 template <typename Tag, typename Geometry>
98 struct point_order
99 {
100     BOOST_GEOMETRY_STATIC_ASSERT_FALSE(
101         "Not implemented for this Geometry type.",
102         Geometry);
103 };
104 
105 template <typename Point>
106 struct point_order<point_tag, Point>
107     : public detail::point_order::clockwise {};
108 
109 template <typename Segment>
110 struct point_order<segment_tag, Segment>
111     : public detail::point_order::clockwise {};
112 
113 
114 template <typename Box>
115 struct point_order<box_tag, Box>
116     : public detail::point_order::clockwise {};
117 
118 template <typename LineString>
119 struct point_order<linestring_tag, LineString>
120     : public detail::point_order::clockwise {};
121 
122 
123 template <typename Ring>
124 struct point_order<ring_tag, Ring>
125 {
126     static const order_selector value
127         = geometry::traits::point_order<Ring>::value;
128 };
129 
130 // Specialization for polygon: the order is the order of its rings
131 template <typename Polygon>
132 struct point_order<polygon_tag, Polygon>
133 {
134     static const order_selector value = core_dispatch::point_order
135         <
136             ring_tag,
137             typename ring_type<polygon_tag, Polygon>::type
138         >::value ;
139 };
140 
141 template <typename MultiPoint>
142 struct point_order<multi_point_tag, MultiPoint>
143     : public detail::point_order::clockwise {};
144 
145 template <typename MultiLinestring>
146 struct point_order<multi_linestring_tag, MultiLinestring>
147     : public detail::point_order::clockwise {};
148 
149 
150 // Specialization for multi_polygon: the order is the order of its polygons
151 template <typename MultiPolygon>
152 struct point_order<multi_polygon_tag, MultiPolygon>
153 {
154     static const order_selector value = core_dispatch::point_order
155         <
156             polygon_tag,
157             typename boost::range_value<MultiPolygon>::type
158         >::value ;
159 };
160 
161 } // namespace core_dispatch
162 #endif // DOXYGEN_NO_DISPATCH
163 
164 
165 /*!
166 \brief \brief_meta{value, point order (clockwise\, counterclockwise),
167     \meta_geometry_type}
168 \tparam Geometry \tparam_geometry
169 \ingroup core
170 
171 \qbk{[include reference/core/point_order.qbk]}
172 */
173 template <typename Geometry>
174 struct point_order
175 {
176     static const order_selector value = core_dispatch::point_order
177         <
178             typename tag<Geometry>::type,
179             typename util::remove_cptrref<Geometry>::type
180         >::value;
181 };
182 
183 }} // namespace boost::geometry
184 
185 #endif // BOOST_GEOMETRY_CORE_POINT_ORDER_HPP
186