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_POINT_ORDER_HPP
20 #define BOOST_GEOMETRY_CORE_POINT_ORDER_HPP
21 
22 
23 #include <boost/mpl/assert.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 \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_MPL_ASSERT_MSG
101         (
102             false, NOT_IMPLEMENTED_FOR_THIS_GEOMETRY_TYPE
103             , (types<Geometry>)
104         );
105 };
106 
107 template <typename Point>
108 struct point_order<point_tag, Point>
109     : public detail::point_order::clockwise {};
110 
111 template <typename Segment>
112 struct point_order<segment_tag, Segment>
113     : public detail::point_order::clockwise {};
114 
115 
116 template <typename Box>
117 struct point_order<box_tag, Box>
118     : public detail::point_order::clockwise {};
119 
120 template <typename LineString>
121 struct point_order<linestring_tag, LineString>
122     : public detail::point_order::clockwise {};
123 
124 
125 template <typename Ring>
126 struct point_order<ring_tag, Ring>
127 {
128     static const order_selector value
129         = geometry::traits::point_order<Ring>::value;
130 };
131 
132 // Specialization for polygon: the order is the order of its rings
133 template <typename Polygon>
134 struct point_order<polygon_tag, Polygon>
135 {
136     static const order_selector value = core_dispatch::point_order
137         <
138             ring_tag,
139             typename ring_type<polygon_tag, Polygon>::type
140         >::value ;
141 };
142 
143 template <typename MultiPoint>
144 struct point_order<multi_point_tag, MultiPoint>
145     : public detail::point_order::clockwise {};
146 
147 template <typename MultiLinestring>
148 struct point_order<multi_linestring_tag, MultiLinestring>
149     : public detail::point_order::clockwise {};
150 
151 
152 // Specialization for multi_polygon: the order is the order of its polygons
153 template <typename MultiPolygon>
154 struct point_order<multi_polygon_tag, MultiPolygon>
155 {
156     static const order_selector value = core_dispatch::point_order
157         <
158             polygon_tag,
159             typename boost::range_value<MultiPolygon>::type
160         >::value ;
161 };
162 
163 } // namespace core_dispatch
164 #endif // DOXYGEN_NO_DISPATCH
165 
166 
167 /*!
168 \brief \brief_meta{value, point order (clockwise\, counterclockwise),
169     \meta_geometry_type}
170 \tparam Geometry \tparam_geometry
171 \ingroup core
172 
173 \qbk{[include reference/core/point_order.qbk]}
174 */
175 template <typename Geometry>
176 struct point_order
177 {
178     static const order_selector value = core_dispatch::point_order
179         <
180             typename tag<Geometry>::type,
181             typename util::bare_type<Geometry>::type
182         >::value;
183 };
184 
185 }} // namespace boost::geometry
186 
187 #endif // BOOST_GEOMETRY_CORE_POINT_ORDER_HPP
188