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 26 #include <boost/geometry/core/ring_type.hpp> 27 #include <boost/geometry/core/tag.hpp> 28 #include <boost/geometry/core/tags.hpp> 29 #include <boost/geometry/util/bare_type.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