annotate DEPENDENCIES/generic/include/boost/geometry/algorithms/convert.hpp @ 46:d572322e2efe

Fix to .cat file check (was susceptible to DOS line-endings) and subrepo update
author Chris Cannam
date Thu, 07 Aug 2014 14:39:38 +0100
parents 2665513ce2d3
children c530137014c0
rev   line source
Chris@16 1 // Boost.Geometry (aka GGL, Generic Geometry Library)
Chris@16 2
Chris@16 3 // Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
Chris@16 4 // Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
Chris@16 5 // Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
Chris@16 6
Chris@16 7 // Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
Chris@16 8 // (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
Chris@16 9
Chris@16 10 // Use, modification and distribution is subject to the Boost Software License,
Chris@16 11 // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
Chris@16 12 // http://www.boost.org/LICENSE_1_0.txt)
Chris@16 13
Chris@16 14 #ifndef BOOST_GEOMETRY_ALGORITHMS_CONVERT_HPP
Chris@16 15 #define BOOST_GEOMETRY_ALGORITHMS_CONVERT_HPP
Chris@16 16
Chris@16 17
Chris@16 18 #include <cstddef>
Chris@16 19
Chris@16 20 #include <boost/numeric/conversion/cast.hpp>
Chris@16 21 #include <boost/range.hpp>
Chris@16 22 #include <boost/type_traits/is_array.hpp>
Chris@16 23
Chris@16 24 #include <boost/geometry/arithmetic/arithmetic.hpp>
Chris@16 25 #include <boost/geometry/algorithms/not_implemented.hpp>
Chris@16 26 #include <boost/geometry/algorithms/append.hpp>
Chris@16 27 #include <boost/geometry/algorithms/clear.hpp>
Chris@16 28 #include <boost/geometry/algorithms/for_each.hpp>
Chris@16 29 #include <boost/geometry/algorithms/detail/assign_values.hpp>
Chris@16 30 #include <boost/geometry/algorithms/detail/assign_box_corners.hpp>
Chris@16 31 #include <boost/geometry/algorithms/detail/assign_indexed_point.hpp>
Chris@16 32 #include <boost/geometry/algorithms/detail/convert_point_to_point.hpp>
Chris@16 33 #include <boost/geometry/algorithms/detail/convert_indexed_to_indexed.hpp>
Chris@16 34
Chris@16 35 #include <boost/geometry/views/closeable_view.hpp>
Chris@16 36 #include <boost/geometry/views/reversible_view.hpp>
Chris@16 37
Chris@16 38 #include <boost/geometry/core/cs.hpp>
Chris@16 39 #include <boost/geometry/core/closure.hpp>
Chris@16 40 #include <boost/geometry/core/point_order.hpp>
Chris@16 41 #include <boost/geometry/geometries/concepts/check.hpp>
Chris@16 42
Chris@16 43 #include <boost/variant/static_visitor.hpp>
Chris@16 44 #include <boost/variant/apply_visitor.hpp>
Chris@16 45 #include <boost/variant/variant_fwd.hpp>
Chris@16 46
Chris@16 47
Chris@16 48 namespace boost { namespace geometry
Chris@16 49 {
Chris@16 50
Chris@16 51 // Silence warning C4127: conditional expression is constant
Chris@16 52 // Silence warning C4512: assignment operator could not be generated
Chris@16 53 #if defined(_MSC_VER)
Chris@16 54 #pragma warning(push)
Chris@16 55 #pragma warning(disable : 4127 4512)
Chris@16 56 #endif
Chris@16 57
Chris@16 58
Chris@16 59 #ifndef DOXYGEN_NO_DETAIL
Chris@16 60 namespace detail { namespace conversion
Chris@16 61 {
Chris@16 62
Chris@16 63 template
Chris@16 64 <
Chris@16 65 typename Point,
Chris@16 66 typename Box,
Chris@16 67 std::size_t Index,
Chris@16 68 std::size_t Dimension,
Chris@16 69 std::size_t DimensionCount
Chris@16 70 >
Chris@16 71 struct point_to_box
Chris@16 72 {
Chris@16 73 static inline void apply(Point const& point, Box& box)
Chris@16 74 {
Chris@16 75 typedef typename coordinate_type<Box>::type coordinate_type;
Chris@16 76
Chris@16 77 set<Index, Dimension>(box,
Chris@16 78 boost::numeric_cast<coordinate_type>(get<Dimension>(point)));
Chris@16 79 point_to_box
Chris@16 80 <
Chris@16 81 Point, Box,
Chris@16 82 Index, Dimension + 1, DimensionCount
Chris@16 83 >::apply(point, box);
Chris@16 84 }
Chris@16 85 };
Chris@16 86
Chris@16 87
Chris@16 88 template
Chris@16 89 <
Chris@16 90 typename Point,
Chris@16 91 typename Box,
Chris@16 92 std::size_t Index,
Chris@16 93 std::size_t DimensionCount
Chris@16 94 >
Chris@16 95 struct point_to_box<Point, Box, Index, DimensionCount, DimensionCount>
Chris@16 96 {
Chris@16 97 static inline void apply(Point const& , Box& )
Chris@16 98 {}
Chris@16 99 };
Chris@16 100
Chris@16 101 template <typename Box, typename Range, bool Close, bool Reverse>
Chris@16 102 struct box_to_range
Chris@16 103 {
Chris@16 104 static inline void apply(Box const& box, Range& range)
Chris@16 105 {
Chris@16 106 traits::resize<Range>::apply(range, Close ? 5 : 4);
Chris@16 107 assign_box_corners_oriented<Reverse>(box, range);
Chris@16 108 if (Close)
Chris@16 109 {
Chris@16 110 range[4] = range[0];
Chris@16 111 }
Chris@16 112 }
Chris@16 113 };
Chris@16 114
Chris@16 115 template <typename Segment, typename Range>
Chris@16 116 struct segment_to_range
Chris@16 117 {
Chris@16 118 static inline void apply(Segment const& segment, Range& range)
Chris@16 119 {
Chris@16 120 traits::resize<Range>::apply(range, 2);
Chris@16 121
Chris@16 122 typename boost::range_iterator<Range>::type it = boost::begin(range);
Chris@16 123
Chris@16 124 assign_point_from_index<0>(segment, *it);
Chris@16 125 ++it;
Chris@16 126 assign_point_from_index<1>(segment, *it);
Chris@16 127 }
Chris@16 128 };
Chris@16 129
Chris@16 130 template
Chris@16 131 <
Chris@16 132 typename Range1,
Chris@16 133 typename Range2,
Chris@16 134 bool Reverse = false
Chris@16 135 >
Chris@16 136 struct range_to_range
Chris@16 137 {
Chris@16 138 typedef typename reversible_view
Chris@16 139 <
Chris@16 140 Range1 const,
Chris@16 141 Reverse ? iterate_reverse : iterate_forward
Chris@16 142 >::type rview_type;
Chris@16 143 typedef typename closeable_view
Chris@16 144 <
Chris@16 145 rview_type const,
Chris@16 146 geometry::closure<Range1>::value
Chris@16 147 >::type view_type;
Chris@16 148
Chris@16 149 static inline void apply(Range1 const& source, Range2& destination)
Chris@16 150 {
Chris@16 151 geometry::clear(destination);
Chris@16 152
Chris@16 153 rview_type rview(source);
Chris@16 154
Chris@16 155 // We consider input always as closed, and skip last
Chris@16 156 // point for open output.
Chris@16 157 view_type view(rview);
Chris@16 158
Chris@16 159 int n = boost::size(view);
Chris@16 160 if (geometry::closure<Range2>::value == geometry::open)
Chris@16 161 {
Chris@16 162 n--;
Chris@16 163 }
Chris@16 164
Chris@16 165 int i = 0;
Chris@16 166 for (typename boost::range_iterator<view_type const>::type it
Chris@16 167 = boost::begin(view);
Chris@16 168 it != boost::end(view) && i < n;
Chris@16 169 ++it, ++i)
Chris@16 170 {
Chris@16 171 geometry::append(destination, *it);
Chris@16 172 }
Chris@16 173 }
Chris@16 174 };
Chris@16 175
Chris@16 176 template <typename Polygon1, typename Polygon2>
Chris@16 177 struct polygon_to_polygon
Chris@16 178 {
Chris@16 179 typedef range_to_range
Chris@16 180 <
Chris@16 181 typename geometry::ring_type<Polygon1>::type,
Chris@16 182 typename geometry::ring_type<Polygon2>::type,
Chris@16 183 geometry::point_order<Polygon1>::value
Chris@16 184 != geometry::point_order<Polygon2>::value
Chris@16 185 > per_ring;
Chris@16 186
Chris@16 187 static inline void apply(Polygon1 const& source, Polygon2& destination)
Chris@16 188 {
Chris@16 189 // Clearing managed per ring, and in the resizing of interior rings
Chris@16 190
Chris@16 191 per_ring::apply(geometry::exterior_ring(source),
Chris@16 192 geometry::exterior_ring(destination));
Chris@16 193
Chris@16 194 // Container should be resizeable
Chris@16 195 traits::resize
Chris@16 196 <
Chris@16 197 typename boost::remove_reference
Chris@16 198 <
Chris@16 199 typename traits::interior_mutable_type<Polygon2>::type
Chris@16 200 >::type
Chris@16 201 >::apply(interior_rings(destination), num_interior_rings(source));
Chris@16 202
Chris@16 203 typename interior_return_type<Polygon1 const>::type rings_source
Chris@16 204 = interior_rings(source);
Chris@16 205 typename interior_return_type<Polygon2>::type rings_dest
Chris@16 206 = interior_rings(destination);
Chris@16 207
Chris@16 208 BOOST_AUTO_TPL(it_source, boost::begin(rings_source));
Chris@16 209 BOOST_AUTO_TPL(it_dest, boost::begin(rings_dest));
Chris@16 210
Chris@16 211 for ( ; it_source != boost::end(rings_source); ++it_source, ++it_dest)
Chris@16 212 {
Chris@16 213 per_ring::apply(*it_source, *it_dest);
Chris@16 214 }
Chris@16 215 }
Chris@16 216 };
Chris@16 217
Chris@16 218
Chris@16 219 }} // namespace detail::conversion
Chris@16 220 #endif // DOXYGEN_NO_DETAIL
Chris@16 221
Chris@16 222
Chris@16 223 #ifndef DOXYGEN_NO_DISPATCH
Chris@16 224 namespace dispatch
Chris@16 225 {
Chris@16 226
Chris@16 227 template
Chris@16 228 <
Chris@16 229 typename Geometry1, typename Geometry2,
Chris@16 230 typename Tag1 = typename tag_cast<typename tag<Geometry1>::type, multi_tag>::type,
Chris@16 231 typename Tag2 = typename tag_cast<typename tag<Geometry2>::type, multi_tag>::type,
Chris@16 232 std::size_t DimensionCount = dimension<Geometry1>::type::value,
Chris@16 233 bool UseAssignment = boost::is_same<Geometry1, Geometry2>::value
Chris@16 234 && !boost::is_array<Geometry1>::value
Chris@16 235 >
Chris@16 236 struct convert: not_implemented<Tag1, Tag2, mpl::int_<DimensionCount> >
Chris@16 237 {};
Chris@16 238
Chris@16 239
Chris@16 240 template
Chris@16 241 <
Chris@16 242 typename Geometry1, typename Geometry2,
Chris@16 243 typename Tag,
Chris@16 244 std::size_t DimensionCount
Chris@16 245 >
Chris@16 246 struct convert<Geometry1, Geometry2, Tag, Tag, DimensionCount, true>
Chris@16 247 {
Chris@16 248 // Same geometry type -> copy whole geometry
Chris@16 249 static inline void apply(Geometry1 const& source, Geometry2& destination)
Chris@16 250 {
Chris@16 251 destination = source;
Chris@16 252 }
Chris@16 253 };
Chris@16 254
Chris@16 255
Chris@16 256 template
Chris@16 257 <
Chris@16 258 typename Geometry1, typename Geometry2,
Chris@16 259 std::size_t DimensionCount
Chris@16 260 >
Chris@16 261 struct convert<Geometry1, Geometry2, point_tag, point_tag, DimensionCount, false>
Chris@16 262 : detail::conversion::point_to_point<Geometry1, Geometry2, 0, DimensionCount>
Chris@16 263 {};
Chris@16 264
Chris@16 265
Chris@16 266 template
Chris@16 267 <
Chris@16 268 typename Box1, typename Box2,
Chris@16 269 std::size_t DimensionCount
Chris@16 270 >
Chris@16 271 struct convert<Box1, Box2, box_tag, box_tag, DimensionCount, false>
Chris@16 272 : detail::conversion::indexed_to_indexed<Box1, Box2, 0, DimensionCount>
Chris@16 273 {};
Chris@16 274
Chris@16 275
Chris@16 276 template
Chris@16 277 <
Chris@16 278 typename Segment1, typename Segment2,
Chris@16 279 std::size_t DimensionCount
Chris@16 280 >
Chris@16 281 struct convert<Segment1, Segment2, segment_tag, segment_tag, DimensionCount, false>
Chris@16 282 : detail::conversion::indexed_to_indexed<Segment1, Segment2, 0, DimensionCount>
Chris@16 283 {};
Chris@16 284
Chris@16 285
Chris@16 286 template <typename Segment, typename LineString, std::size_t DimensionCount>
Chris@16 287 struct convert<Segment, LineString, segment_tag, linestring_tag, DimensionCount, false>
Chris@16 288 : detail::conversion::segment_to_range<Segment, LineString>
Chris@16 289 {};
Chris@16 290
Chris@16 291
Chris@16 292 template <typename Ring1, typename Ring2, std::size_t DimensionCount>
Chris@16 293 struct convert<Ring1, Ring2, ring_tag, ring_tag, DimensionCount, false>
Chris@16 294 : detail::conversion::range_to_range
Chris@16 295 <
Chris@16 296 Ring1,
Chris@16 297 Ring2,
Chris@16 298 geometry::point_order<Ring1>::value
Chris@16 299 != geometry::point_order<Ring2>::value
Chris@16 300 >
Chris@16 301 {};
Chris@16 302
Chris@16 303 template <typename LineString1, typename LineString2, std::size_t DimensionCount>
Chris@16 304 struct convert<LineString1, LineString2, linestring_tag, linestring_tag, DimensionCount, false>
Chris@16 305 : detail::conversion::range_to_range<LineString1, LineString2>
Chris@16 306 {};
Chris@16 307
Chris@16 308 template <typename Polygon1, typename Polygon2, std::size_t DimensionCount>
Chris@16 309 struct convert<Polygon1, Polygon2, polygon_tag, polygon_tag, DimensionCount, false>
Chris@16 310 : detail::conversion::polygon_to_polygon<Polygon1, Polygon2>
Chris@16 311 {};
Chris@16 312
Chris@16 313 template <typename Box, typename Ring>
Chris@16 314 struct convert<Box, Ring, box_tag, ring_tag, 2, false>
Chris@16 315 : detail::conversion::box_to_range
Chris@16 316 <
Chris@16 317 Box,
Chris@16 318 Ring,
Chris@16 319 geometry::closure<Ring>::value == closed,
Chris@16 320 geometry::point_order<Ring>::value == counterclockwise
Chris@16 321 >
Chris@16 322 {};
Chris@16 323
Chris@16 324
Chris@16 325 template <typename Box, typename Polygon>
Chris@16 326 struct convert<Box, Polygon, box_tag, polygon_tag, 2, false>
Chris@16 327 {
Chris@16 328 static inline void apply(Box const& box, Polygon& polygon)
Chris@16 329 {
Chris@16 330 typedef typename ring_type<Polygon>::type ring_type;
Chris@16 331
Chris@16 332 convert
Chris@16 333 <
Chris@16 334 Box, ring_type,
Chris@16 335 box_tag, ring_tag,
Chris@16 336 2, false
Chris@16 337 >::apply(box, exterior_ring(polygon));
Chris@16 338 }
Chris@16 339 };
Chris@16 340
Chris@16 341
Chris@16 342 template <typename Point, typename Box, std::size_t DimensionCount>
Chris@16 343 struct convert<Point, Box, point_tag, box_tag, DimensionCount, false>
Chris@16 344 {
Chris@16 345 static inline void apply(Point const& point, Box& box)
Chris@16 346 {
Chris@16 347 detail::conversion::point_to_box
Chris@16 348 <
Chris@16 349 Point, Box, min_corner, 0, DimensionCount
Chris@16 350 >::apply(point, box);
Chris@16 351 detail::conversion::point_to_box
Chris@16 352 <
Chris@16 353 Point, Box, max_corner, 0, DimensionCount
Chris@16 354 >::apply(point, box);
Chris@16 355 }
Chris@16 356 };
Chris@16 357
Chris@16 358
Chris@16 359 template <typename Ring, typename Polygon, std::size_t DimensionCount>
Chris@16 360 struct convert<Ring, Polygon, ring_tag, polygon_tag, DimensionCount, false>
Chris@16 361 {
Chris@16 362 static inline void apply(Ring const& ring, Polygon& polygon)
Chris@16 363 {
Chris@16 364 typedef typename ring_type<Polygon>::type ring_type;
Chris@16 365 convert
Chris@16 366 <
Chris@16 367 Ring, ring_type,
Chris@16 368 ring_tag, ring_tag,
Chris@16 369 DimensionCount, false
Chris@16 370 >::apply(ring, exterior_ring(polygon));
Chris@16 371 }
Chris@16 372 };
Chris@16 373
Chris@16 374
Chris@16 375 template <typename Polygon, typename Ring, std::size_t DimensionCount>
Chris@16 376 struct convert<Polygon, Ring, polygon_tag, ring_tag, DimensionCount, false>
Chris@16 377 {
Chris@16 378 static inline void apply(Polygon const& polygon, Ring& ring)
Chris@16 379 {
Chris@16 380 typedef typename ring_type<Polygon>::type ring_type;
Chris@16 381
Chris@16 382 convert
Chris@16 383 <
Chris@16 384 ring_type, Ring,
Chris@16 385 ring_tag, ring_tag,
Chris@16 386 DimensionCount, false
Chris@16 387 >::apply(exterior_ring(polygon), ring);
Chris@16 388 }
Chris@16 389 };
Chris@16 390
Chris@16 391
Chris@16 392 template <typename Geometry1, typename Geometry2>
Chris@16 393 struct devarianted_convert
Chris@16 394 {
Chris@16 395 static inline void apply(Geometry1 const& geometry1, Geometry2& geometry2)
Chris@16 396 {
Chris@16 397 concept::check_concepts_and_equal_dimensions<Geometry1 const, Geometry2>();
Chris@16 398 convert<Geometry1, Geometry2>::apply(geometry1, geometry2);
Chris@16 399 }
Chris@16 400 };
Chris@16 401
Chris@16 402 template <BOOST_VARIANT_ENUM_PARAMS(typename T), typename Geometry2>
Chris@16 403 struct devarianted_convert<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Geometry2>
Chris@16 404 {
Chris@16 405 struct visitor: static_visitor<void>
Chris@16 406 {
Chris@16 407 Geometry2& m_geometry2;
Chris@16 408
Chris@16 409 visitor(Geometry2& geometry2)
Chris@16 410 : m_geometry2(geometry2)
Chris@16 411 {}
Chris@16 412
Chris@16 413 template <typename Geometry1>
Chris@16 414 inline void operator()(Geometry1 const& geometry1) const
Chris@16 415 {
Chris@16 416 devarianted_convert<Geometry1, Geometry2>::apply(geometry1, m_geometry2);
Chris@16 417 }
Chris@16 418 };
Chris@16 419
Chris@16 420 static inline void apply(
Chris@16 421 boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry1,
Chris@16 422 Geometry2& geometry2
Chris@16 423 )
Chris@16 424 {
Chris@16 425 apply_visitor(visitor(geometry2), geometry1);
Chris@16 426 }
Chris@16 427 };
Chris@16 428
Chris@16 429
Chris@16 430 } // namespace dispatch
Chris@16 431 #endif // DOXYGEN_NO_DISPATCH
Chris@16 432
Chris@16 433
Chris@16 434 /*!
Chris@16 435 \brief Converts one geometry to another geometry
Chris@16 436 \details The convert algorithm converts one geometry, e.g. a BOX, to another
Chris@16 437 geometry, e.g. a RING. This only works if it is possible and applicable.
Chris@16 438 If the point-order is different, or the closure is different between two
Chris@16 439 geometry types, it will be converted correctly by explicitly reversing the
Chris@16 440 points or closing or opening the polygon rings.
Chris@16 441 \ingroup convert
Chris@16 442 \tparam Geometry1 \tparam_geometry
Chris@16 443 \tparam Geometry2 \tparam_geometry
Chris@16 444 \param geometry1 \param_geometry (source)
Chris@16 445 \param geometry2 \param_geometry (target)
Chris@16 446
Chris@16 447 \qbk{[include reference/algorithms/convert.qbk]}
Chris@16 448 */
Chris@16 449 template <typename Geometry1, typename Geometry2>
Chris@16 450 inline void convert(Geometry1 const& geometry1, Geometry2& geometry2)
Chris@16 451 {
Chris@16 452 dispatch::devarianted_convert<Geometry1, Geometry2>::apply(geometry1, geometry2);
Chris@16 453 }
Chris@16 454
Chris@16 455 #if defined(_MSC_VER)
Chris@16 456 #pragma warning(pop)
Chris@16 457 #endif
Chris@16 458
Chris@16 459 }} // namespace boost::geometry
Chris@16 460
Chris@16 461 #endif // BOOST_GEOMETRY_ALGORITHMS_CONVERT_HPP