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