1 // Boost.Geometry (aka GGL, Generic Geometry Library) 2 3 // Copyright (c) 2010-2012 Barend Gehrels, Amsterdam, the Netherlands. 4 5 // This file was modified by Oracle on 2018. 6 // Modifications copyright (c) 2018, Oracle and/or its affiliates. 7 8 // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle 9 10 // Use, modification and distribution is subject to the Boost Software License, 11 // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at 12 // http://www.boost.org/LICENSE_1_0.txt) 13 14 #ifndef BOOST_GEOMETRY_GEOMETRIES_ADAPTED_BOOST_POLYGON_RING_PROXY_HPP 15 #define BOOST_GEOMETRY_GEOMETRIES_ADAPTED_BOOST_POLYGON_RING_PROXY_HPP 16 17 // Adapts Geometries from Boost.Polygon for usage in Boost.Geometry 18 // boost::polygon::polygon_with_holes_data -> boost::geometry::polygon 19 // pair{begin_points, end_points} -> ring_proxy 20 21 #include <boost/polygon/polygon.hpp> 22 #include <boost/range/const_iterator.hpp> 23 #include <boost/range/mutable_iterator.hpp> 24 25 #include <boost/geometry/core/mutable_range.hpp> 26 #include <boost/geometry/core/tag.hpp> 27 28 namespace boost { namespace geometry 29 { 30 31 namespace adapt { namespace bp 32 { 33 34 namespace detail 35 { 36 37 template <bool Mutable> 38 struct modify 39 {}; 40 41 template <> 42 struct modify<true> 43 { 44 template <typename Ring, typename Point> push_backboost::geometry::adapt::bp::detail::modify45 static inline void push_back(Ring& ring, Point const& point) 46 { 47 // Boost.Polygon's polygons are not appendable. So create a temporary vector, 48 // add a record and set it to the original. Of course: this is not efficient. 49 // But there seems no other way (without using a wrapper) 50 std::vector<Point> temporary_vector 51 ( 52 boost::polygon::begin_points(ring), 53 boost::polygon::end_points(ring) 54 ); 55 temporary_vector.push_back(point); 56 boost::polygon::set_points(ring, temporary_vector.begin(), temporary_vector.end()); 57 } 58 59 }; 60 61 template <> 62 struct modify<false> 63 { 64 template <typename Ring, typename Point> push_backboost::geometry::adapt::bp::detail::modify65 static inline void push_back(Ring& /*ring*/, Point const& /*point*/) 66 { 67 } 68 69 }; 70 71 72 } 73 74 75 // Polygon should implement the boost::polygon::polygon_with_holes_concept 76 // Specify constness in the template parameter if necessary 77 template<typename Polygon> 78 class ring_proxy 79 { 80 public : 81 typedef typename boost::polygon::polygon_traits 82 < 83 typename boost::remove_const<Polygon>::type 84 >::iterator_type iterator_type; 85 86 typedef typename boost::polygon::polygon_with_holes_traits 87 < 88 typename boost::remove_const<Polygon>::type 89 >::iterator_holes_type hole_iterator_type; 90 91 static const bool is_mutable = !boost::is_const<Polygon>::type::value; 92 ring_proxy(Polygon & p)93 inline ring_proxy(Polygon& p) 94 : m_polygon_pointer(&p) 95 , m_do_hole(false) 96 {} 97 98 // Constructor used from hole_iterator ring_proxy(Polygon & p,hole_iterator_type hole_it)99 inline ring_proxy(Polygon& p, hole_iterator_type hole_it) 100 : m_polygon_pointer(&p) 101 , m_do_hole(true) 102 , m_hole_it(hole_it) 103 {} 104 105 // Default constructor, for mutable polygons / appending (interior) rings ring_proxy()106 inline ring_proxy() 107 : m_polygon_pointer(&m_polygon_for_default_constructor) 108 , m_do_hole(false) 109 {} 110 111 begin() const112 iterator_type begin() const 113 { 114 return m_do_hole 115 ? boost::polygon::begin_points(*m_hole_it) 116 : boost::polygon::begin_points(*m_polygon_pointer) 117 ; 118 } 119 begin()120 iterator_type begin() 121 { 122 return m_do_hole 123 ? boost::polygon::begin_points(*m_hole_it) 124 : boost::polygon::begin_points(*m_polygon_pointer) 125 ; 126 } 127 end() const128 iterator_type end() const 129 { 130 return m_do_hole 131 ? boost::polygon::end_points(*m_hole_it) 132 : boost::polygon::end_points(*m_polygon_pointer) 133 ; 134 } 135 end()136 iterator_type end() 137 { 138 return m_do_hole 139 ? boost::polygon::end_points(*m_hole_it) 140 : boost::polygon::end_points(*m_polygon_pointer) 141 ; 142 } 143 144 // Mutable clear()145 void clear() 146 { 147 Polygon p; 148 if (m_do_hole) 149 { 150 // Does NOT work see comment above 151 } 152 else 153 { 154 boost::polygon::set_points(*m_polygon_pointer, 155 boost::polygon::begin_points(p), 156 boost::polygon::end_points(p)); 157 } 158 } 159 resize(std::size_t)160 void resize(std::size_t /*new_size*/) 161 { 162 if (m_do_hole) 163 { 164 // Does NOT work see comment above 165 } 166 else 167 { 168 // TODO: implement this by resizing the container 169 } 170 } 171 172 173 174 template <typename Point> push_back(Point const & point)175 void push_back(Point const& point) 176 { 177 if (m_do_hole) 178 { 179 //detail::modify<is_mutable>::push_back(*m_hole_it, point); 180 //std::cout << "HOLE: " << typeid(*m_hole_it).name() << std::endl; 181 //std::cout << "HOLE: " << typeid(m_hole_it).name() << std::endl; 182 //std::cout << "HOLE: " << typeid(hole_iterator_type).name() << std::endl; 183 184 // Note, ths does NOT work because hole_iterator_type is defined 185 // as a const_iterator by Boost.Polygon 186 187 } 188 else 189 { 190 detail::modify<is_mutable>::push_back(*m_polygon_pointer, point); 191 } 192 } 193 194 private : 195 Polygon* m_polygon_pointer; 196 bool m_do_hole; 197 hole_iterator_type m_hole_it; 198 199 Polygon m_polygon_for_default_constructor; 200 }; 201 202 203 204 205 // Support geometry::adapt::bp::ring_proxy for Boost.Range ADP 206 template<typename Polygon> 207 inline typename boost::geometry::adapt::bp::ring_proxy<Polygon>::iterator_type range_begin(boost::geometry::adapt::bp::ring_proxy<Polygon> & proxy)208 range_begin(boost::geometry::adapt::bp::ring_proxy<Polygon>& proxy) 209 { 210 return proxy.begin(); 211 } 212 213 template<typename Polygon> 214 inline typename boost::geometry::adapt::bp::ring_proxy<Polygon const>::iterator_type range_begin(boost::geometry::adapt::bp::ring_proxy<Polygon const> const & proxy)215 range_begin(boost::geometry::adapt::bp::ring_proxy<Polygon const> const& proxy) 216 { 217 return proxy.begin(); 218 } 219 220 template<typename Polygon> 221 inline typename boost::geometry::adapt::bp::ring_proxy<Polygon>::iterator_type range_end(boost::geometry::adapt::bp::ring_proxy<Polygon> & proxy)222 range_end(boost::geometry::adapt::bp::ring_proxy<Polygon>& proxy) 223 { 224 return proxy.end(); 225 } 226 227 template<typename Polygon> 228 inline typename boost::geometry::adapt::bp::ring_proxy<Polygon const>::iterator_type range_end(boost::geometry::adapt::bp::ring_proxy<Polygon const> const & proxy)229 range_end(boost::geometry::adapt::bp::ring_proxy<Polygon const> const& proxy) 230 { 231 return proxy.end(); 232 } 233 234 235 236 237 }} // namespace adapt::bp 238 239 240 namespace traits 241 { 242 243 template <typename Polygon> 244 struct tag<adapt::bp::ring_proxy<Polygon> > 245 { 246 typedef ring_tag type; 247 }; 248 249 250 template <typename Polygon> 251 struct rvalue_type<adapt::bp::ring_proxy<Polygon> > 252 { 253 typedef adapt::bp::ring_proxy<Polygon> type; 254 }; 255 256 template <typename Polygon> 257 struct clear<adapt::bp::ring_proxy<Polygon> > 258 { applyboost::geometry::traits::clear259 static inline void apply(adapt::bp::ring_proxy<Polygon> proxy) 260 { 261 proxy.clear(); 262 } 263 }; 264 265 266 template <typename Polygon> 267 struct resize<adapt::bp::ring_proxy<Polygon> > 268 { applyboost::geometry::traits::resize269 static inline void apply(adapt::bp::ring_proxy<Polygon> proxy, std::size_t new_size) 270 { 271 proxy.resize(new_size); 272 } 273 }; 274 275 template <typename Polygon> 276 struct push_back<adapt::bp::ring_proxy<Polygon> > 277 { applyboost::geometry::traits::push_back278 static inline void apply(adapt::bp::ring_proxy<Polygon> proxy, 279 typename boost::polygon::polygon_traits<Polygon>::point_type const& point) 280 { 281 proxy.push_back(point); 282 } 283 }; 284 285 286 } // namespace traits 287 288 }} // namespace boost::geometry 289 290 // Specialize ring_proxy for Boost.Range 291 namespace boost 292 { 293 template<typename Polygon> 294 struct range_mutable_iterator<geometry::adapt::bp::ring_proxy<Polygon> > 295 { 296 typedef typename geometry::adapt::bp::ring_proxy<Polygon>::iterator_type type; 297 }; 298 299 template<typename Polygon> 300 struct range_const_iterator<geometry::adapt::bp::ring_proxy<Polygon> > 301 { 302 typedef typename geometry::adapt::bp::ring_proxy<Polygon const>::iterator_type type; 303 }; 304 305 } // namespace boost 306 307 308 #endif // BOOST_GEOMETRY_GEOMETRIES_ADAPTED_BOOST_POLYGON_RING_PROXY_HPP 309