annotate DEPENDENCIES/generic/include/boost/geometry/algorithms/transform.hpp @ 133:4acb5d8d80b6 tip

Don't fail environmental check if README.md exists (but .txt and no-suffix don't)
author Chris Cannam
date Tue, 30 Jul 2019 12:25:44 +0100
parents c530137014c0
children
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@101 6 // Copyright (c) 2014 Adam Wulkiewicz, Lodz, Poland.
Chris@16 7
Chris@16 8 // Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
Chris@16 9 // (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
Chris@16 10
Chris@16 11 // Use, modification and distribution is subject to the Boost Software License,
Chris@16 12 // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
Chris@16 13 // http://www.boost.org/LICENSE_1_0.txt)
Chris@16 14
Chris@16 15 #ifndef BOOST_GEOMETRY_ALGORITHMS_TRANSFORM_HPP
Chris@16 16 #define BOOST_GEOMETRY_ALGORITHMS_TRANSFORM_HPP
Chris@16 17
Chris@16 18 #include <cmath>
Chris@16 19 #include <iterator>
Chris@16 20
Chris@16 21 #include <boost/range.hpp>
Chris@101 22 #include <boost/type_traits/remove_reference.hpp>
Chris@101 23
Chris@101 24 #include <boost/variant/apply_visitor.hpp>
Chris@101 25 #include <boost/variant/static_visitor.hpp>
Chris@101 26 #include <boost/variant/variant_fwd.hpp>
Chris@16 27
Chris@16 28 #include <boost/geometry/algorithms/assign.hpp>
Chris@16 29 #include <boost/geometry/algorithms/clear.hpp>
Chris@101 30 #include <boost/geometry/algorithms/detail/interior_iterator.hpp>
Chris@16 31 #include <boost/geometry/algorithms/num_interior_rings.hpp>
Chris@16 32
Chris@16 33 #include <boost/geometry/core/cs.hpp>
Chris@16 34 #include <boost/geometry/core/exterior_ring.hpp>
Chris@16 35 #include <boost/geometry/core/interior_rings.hpp>
Chris@16 36 #include <boost/geometry/core/mutable_range.hpp>
Chris@16 37 #include <boost/geometry/core/ring_type.hpp>
Chris@16 38 #include <boost/geometry/core/tag_cast.hpp>
Chris@101 39 #include <boost/geometry/core/tags.hpp>
Chris@16 40 #include <boost/geometry/geometries/concepts/check.hpp>
Chris@101 41 #include <boost/geometry/strategies/default_strategy.hpp>
Chris@16 42 #include <boost/geometry/strategies/transform.hpp>
Chris@16 43
Chris@16 44
Chris@16 45 namespace boost { namespace geometry
Chris@16 46 {
Chris@16 47
Chris@16 48 #ifndef DOXYGEN_NO_DETAIL
Chris@16 49 namespace detail { namespace transform
Chris@16 50 {
Chris@16 51
Chris@16 52 struct transform_point
Chris@16 53 {
Chris@16 54 template <typename Point1, typename Point2, typename Strategy>
Chris@16 55 static inline bool apply(Point1 const& p1, Point2& p2,
Chris@16 56 Strategy const& strategy)
Chris@16 57 {
Chris@16 58 return strategy.apply(p1, p2);
Chris@16 59 }
Chris@16 60 };
Chris@16 61
Chris@16 62
Chris@16 63 struct transform_box
Chris@16 64 {
Chris@16 65 template <typename Box1, typename Box2, typename Strategy>
Chris@16 66 static inline bool apply(Box1 const& b1, Box2& b2,
Chris@16 67 Strategy const& strategy)
Chris@16 68 {
Chris@16 69 typedef typename point_type<Box1>::type point_type1;
Chris@16 70 typedef typename point_type<Box2>::type point_type2;
Chris@16 71
Chris@16 72 point_type1 lower_left, upper_right;
Chris@16 73 detail::assign::assign_box_2d_corner<min_corner, min_corner>(
Chris@16 74 b1, lower_left);
Chris@16 75 detail::assign::assign_box_2d_corner<max_corner, max_corner>(
Chris@16 76 b1, upper_right);
Chris@16 77
Chris@16 78 point_type2 p1, p2;
Chris@16 79 if (strategy.apply(lower_left, p1) && strategy.apply(upper_right, p2))
Chris@16 80 {
Chris@16 81 // Create a valid box and therefore swap if necessary
Chris@16 82 typedef typename coordinate_type<point_type2>::type coordinate_type;
Chris@16 83 coordinate_type x1 = geometry::get<0>(p1)
Chris@16 84 , y1 = geometry::get<1>(p1)
Chris@16 85 , x2 = geometry::get<0>(p2)
Chris@16 86 , y2 = geometry::get<1>(p2);
Chris@16 87
Chris@16 88 if (x1 > x2) { std::swap(x1, x2); }
Chris@16 89 if (y1 > y2) { std::swap(y1, y2); }
Chris@16 90
Chris@16 91 set<min_corner, 0>(b2, x1);
Chris@16 92 set<min_corner, 1>(b2, y1);
Chris@16 93 set<max_corner, 0>(b2, x2);
Chris@16 94 set<max_corner, 1>(b2, y2);
Chris@16 95
Chris@16 96 return true;
Chris@16 97 }
Chris@16 98 return false;
Chris@16 99 }
Chris@16 100 };
Chris@16 101
Chris@16 102 struct transform_box_or_segment
Chris@16 103 {
Chris@16 104 template <typename Geometry1, typename Geometry2, typename Strategy>
Chris@16 105 static inline bool apply(Geometry1 const& source, Geometry2& target,
Chris@16 106 Strategy const& strategy)
Chris@16 107 {
Chris@16 108 typedef typename point_type<Geometry1>::type point_type1;
Chris@16 109 typedef typename point_type<Geometry2>::type point_type2;
Chris@16 110
Chris@16 111 point_type1 source_point[2];
Chris@16 112 geometry::detail::assign_point_from_index<0>(source, source_point[0]);
Chris@16 113 geometry::detail::assign_point_from_index<1>(source, source_point[1]);
Chris@16 114
Chris@16 115 point_type2 target_point[2];
Chris@16 116 if (strategy.apply(source_point[0], target_point[0])
Chris@16 117 && strategy.apply(source_point[1], target_point[1]))
Chris@16 118 {
Chris@16 119 geometry::detail::assign_point_to_index<0>(target_point[0], target);
Chris@16 120 geometry::detail::assign_point_to_index<1>(target_point[1], target);
Chris@16 121 return true;
Chris@16 122 }
Chris@16 123 return false;
Chris@16 124 }
Chris@16 125 };
Chris@16 126
Chris@16 127
Chris@16 128 template
Chris@16 129 <
Chris@16 130 typename PointOut,
Chris@16 131 typename OutputIterator,
Chris@16 132 typename Range,
Chris@16 133 typename Strategy
Chris@16 134 >
Chris@16 135 inline bool transform_range_out(Range const& range,
Chris@16 136 OutputIterator out, Strategy const& strategy)
Chris@16 137 {
Chris@16 138 PointOut point_out;
Chris@16 139 for(typename boost::range_iterator<Range const>::type
Chris@16 140 it = boost::begin(range);
Chris@16 141 it != boost::end(range);
Chris@16 142 ++it)
Chris@16 143 {
Chris@16 144 if (! transform_point::apply(*it, point_out, strategy))
Chris@16 145 {
Chris@16 146 return false;
Chris@16 147 }
Chris@16 148 *out++ = point_out;
Chris@16 149 }
Chris@16 150 return true;
Chris@16 151 }
Chris@16 152
Chris@16 153
Chris@16 154 struct transform_polygon
Chris@16 155 {
Chris@16 156 template <typename Polygon1, typename Polygon2, typename Strategy>
Chris@16 157 static inline bool apply(Polygon1 const& poly1, Polygon2& poly2,
Chris@16 158 Strategy const& strategy)
Chris@16 159 {
Chris@16 160 typedef typename point_type<Polygon2>::type point2_type;
Chris@16 161
Chris@16 162 geometry::clear(poly2);
Chris@16 163
Chris@16 164 if (!transform_range_out<point2_type>(exterior_ring(poly1),
Chris@16 165 std::back_inserter(exterior_ring(poly2)), strategy))
Chris@16 166 {
Chris@16 167 return false;
Chris@16 168 }
Chris@16 169
Chris@16 170 // Note: here a resizeable container is assumed.
Chris@16 171 traits::resize
Chris@16 172 <
Chris@16 173 typename boost::remove_reference
Chris@16 174 <
Chris@16 175 typename traits::interior_mutable_type<Polygon2>::type
Chris@16 176 >::type
Chris@16 177 >::apply(interior_rings(poly2), num_interior_rings(poly1));
Chris@16 178
Chris@101 179 typename interior_return_type<Polygon1 const>::type
Chris@101 180 rings1 = interior_rings(poly1);
Chris@101 181 typename interior_return_type<Polygon2>::type
Chris@101 182 rings2 = interior_rings(poly2);
Chris@101 183
Chris@101 184 typename detail::interior_iterator<Polygon1 const>::type
Chris@101 185 it1 = boost::begin(rings1);
Chris@101 186 typename detail::interior_iterator<Polygon2>::type
Chris@101 187 it2 = boost::begin(rings2);
Chris@101 188 for ( ; it1 != boost::end(rings1); ++it1, ++it2)
Chris@16 189 {
Chris@101 190 if ( ! transform_range_out<point2_type>(*it1,
Chris@101 191 std::back_inserter(*it2),
Chris@101 192 strategy) )
Chris@16 193 {
Chris@16 194 return false;
Chris@16 195 }
Chris@16 196 }
Chris@16 197
Chris@16 198 return true;
Chris@16 199 }
Chris@16 200 };
Chris@16 201
Chris@16 202
Chris@16 203 template <typename Point1, typename Point2>
Chris@16 204 struct select_strategy
Chris@16 205 {
Chris@16 206 typedef typename strategy::transform::services::default_strategy
Chris@16 207 <
Chris@16 208 typename cs_tag<Point1>::type,
Chris@16 209 typename cs_tag<Point2>::type,
Chris@16 210 typename coordinate_system<Point1>::type,
Chris@16 211 typename coordinate_system<Point2>::type,
Chris@16 212 dimension<Point1>::type::value,
Chris@16 213 dimension<Point2>::type::value,
Chris@16 214 typename point_type<Point1>::type,
Chris@16 215 typename point_type<Point2>::type
Chris@16 216 >::type type;
Chris@16 217 };
Chris@16 218
Chris@16 219 struct transform_range
Chris@16 220 {
Chris@16 221 template <typename Range1, typename Range2, typename Strategy>
Chris@16 222 static inline bool apply(Range1 const& range1,
Chris@16 223 Range2& range2, Strategy const& strategy)
Chris@16 224 {
Chris@16 225 typedef typename point_type<Range2>::type point_type;
Chris@16 226
Chris@16 227 // Should NOT be done here!
Chris@16 228 // geometry::clear(range2);
Chris@16 229 return transform_range_out<point_type>(range1,
Chris@16 230 std::back_inserter(range2), strategy);
Chris@16 231 }
Chris@16 232 };
Chris@16 233
Chris@101 234
Chris@101 235 /*!
Chris@101 236 \brief Is able to transform any multi-geometry, calling the single-version as policy
Chris@101 237 */
Chris@101 238 template <typename Policy>
Chris@101 239 struct transform_multi
Chris@101 240 {
Chris@101 241 template <typename Multi1, typename Multi2, typename S>
Chris@101 242 static inline bool apply(Multi1 const& multi1, Multi2& multi2, S const& strategy)
Chris@101 243 {
Chris@101 244 traits::resize<Multi2>::apply(multi2, boost::size(multi1));
Chris@101 245
Chris@101 246 typename boost::range_iterator<Multi1 const>::type it1
Chris@101 247 = boost::begin(multi1);
Chris@101 248 typename boost::range_iterator<Multi2>::type it2
Chris@101 249 = boost::begin(multi2);
Chris@101 250
Chris@101 251 for (; it1 != boost::end(multi1); ++it1, ++it2)
Chris@101 252 {
Chris@101 253 if (! Policy::apply(*it1, *it2, strategy))
Chris@101 254 {
Chris@101 255 return false;
Chris@101 256 }
Chris@101 257 }
Chris@101 258
Chris@101 259 return true;
Chris@101 260 }
Chris@101 261 };
Chris@101 262
Chris@101 263
Chris@16 264 }} // namespace detail::transform
Chris@16 265 #endif // DOXYGEN_NO_DETAIL
Chris@16 266
Chris@16 267
Chris@16 268 #ifndef DOXYGEN_NO_DISPATCH
Chris@16 269 namespace dispatch
Chris@16 270 {
Chris@16 271
Chris@16 272 template
Chris@16 273 <
Chris@16 274 typename Geometry1, typename Geometry2,
Chris@16 275 typename Tag1 = typename tag_cast<typename tag<Geometry1>::type, multi_tag>::type,
Chris@16 276 typename Tag2 = typename tag_cast<typename tag<Geometry2>::type, multi_tag>::type
Chris@16 277 >
Chris@16 278 struct transform {};
Chris@16 279
Chris@16 280 template <typename Point1, typename Point2>
Chris@16 281 struct transform<Point1, Point2, point_tag, point_tag>
Chris@16 282 : detail::transform::transform_point
Chris@16 283 {
Chris@16 284 };
Chris@16 285
Chris@16 286
Chris@16 287 template <typename Linestring1, typename Linestring2>
Chris@16 288 struct transform
Chris@16 289 <
Chris@16 290 Linestring1, Linestring2,
Chris@16 291 linestring_tag, linestring_tag
Chris@16 292 >
Chris@16 293 : detail::transform::transform_range
Chris@16 294 {
Chris@16 295 };
Chris@16 296
Chris@16 297 template <typename Range1, typename Range2>
Chris@16 298 struct transform<Range1, Range2, ring_tag, ring_tag>
Chris@16 299 : detail::transform::transform_range
Chris@16 300 {
Chris@16 301 };
Chris@16 302
Chris@16 303 template <typename Polygon1, typename Polygon2>
Chris@16 304 struct transform<Polygon1, Polygon2, polygon_tag, polygon_tag>
Chris@16 305 : detail::transform::transform_polygon
Chris@16 306 {
Chris@16 307 };
Chris@16 308
Chris@16 309 template <typename Box1, typename Box2>
Chris@16 310 struct transform<Box1, Box2, box_tag, box_tag>
Chris@16 311 : detail::transform::transform_box
Chris@16 312 {
Chris@16 313 };
Chris@16 314
Chris@16 315 template <typename Segment1, typename Segment2>
Chris@16 316 struct transform<Segment1, Segment2, segment_tag, segment_tag>
Chris@16 317 : detail::transform::transform_box_or_segment
Chris@16 318 {
Chris@16 319 };
Chris@16 320
Chris@101 321 template <typename Multi1, typename Multi2>
Chris@101 322 struct transform
Chris@101 323 <
Chris@101 324 Multi1, Multi2,
Chris@101 325 multi_tag, multi_tag
Chris@101 326 >
Chris@101 327 : detail::transform::transform_multi
Chris@101 328 <
Chris@101 329 dispatch::transform
Chris@101 330 <
Chris@101 331 typename boost::range_value<Multi1>::type,
Chris@101 332 typename boost::range_value<Multi2>::type
Chris@101 333 >
Chris@101 334 >
Chris@101 335 {};
Chris@101 336
Chris@16 337
Chris@16 338 } // namespace dispatch
Chris@16 339 #endif // DOXYGEN_NO_DISPATCH
Chris@16 340
Chris@16 341
Chris@101 342 namespace resolve_strategy {
Chris@101 343
Chris@101 344 struct transform
Chris@101 345 {
Chris@101 346 template <typename Geometry1, typename Geometry2, typename Strategy>
Chris@101 347 static inline bool apply(Geometry1 const& geometry1,
Chris@101 348 Geometry2& geometry2,
Chris@101 349 Strategy const& strategy)
Chris@101 350 {
Chris@101 351 concept::check<Geometry1 const>();
Chris@101 352 concept::check<Geometry2>();
Chris@101 353
Chris@101 354 return dispatch::transform<Geometry1, Geometry2>::apply(
Chris@101 355 geometry1,
Chris@101 356 geometry2,
Chris@101 357 strategy
Chris@101 358 );
Chris@101 359 }
Chris@101 360
Chris@101 361 template <typename Geometry1, typename Geometry2>
Chris@101 362 static inline bool apply(Geometry1 const& geometry1,
Chris@101 363 Geometry2& geometry2,
Chris@101 364 default_strategy)
Chris@101 365 {
Chris@101 366 return apply(
Chris@101 367 geometry1,
Chris@101 368 geometry2,
Chris@101 369 typename detail::transform::select_strategy<Geometry1, Geometry2>::type()
Chris@101 370 );
Chris@101 371 }
Chris@101 372 };
Chris@101 373
Chris@101 374 } // namespace resolve_strategy
Chris@101 375
Chris@101 376
Chris@101 377 namespace resolve_variant {
Chris@101 378
Chris@101 379 template <typename Geometry1, typename Geometry2>
Chris@101 380 struct transform
Chris@101 381 {
Chris@101 382 template <typename Strategy>
Chris@101 383 static inline bool apply(Geometry1 const& geometry1,
Chris@101 384 Geometry2& geometry2,
Chris@101 385 Strategy const& strategy)
Chris@101 386 {
Chris@101 387 return resolve_strategy::transform::apply(
Chris@101 388 geometry1,
Chris@101 389 geometry2,
Chris@101 390 strategy
Chris@101 391 );
Chris@101 392 }
Chris@101 393 };
Chris@101 394
Chris@101 395 template <BOOST_VARIANT_ENUM_PARAMS(typename T), typename Geometry2>
Chris@101 396 struct transform<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Geometry2>
Chris@101 397 {
Chris@101 398 template <typename Strategy>
Chris@101 399 struct visitor: static_visitor<bool>
Chris@101 400 {
Chris@101 401 Geometry2& m_geometry2;
Chris@101 402 Strategy const& m_strategy;
Chris@101 403
Chris@101 404 visitor(Geometry2& geometry2, Strategy const& strategy)
Chris@101 405 : m_geometry2(geometry2)
Chris@101 406 , m_strategy(strategy)
Chris@101 407 {}
Chris@101 408
Chris@101 409 template <typename Geometry1>
Chris@101 410 inline bool operator()(Geometry1 const& geometry1) const
Chris@101 411 {
Chris@101 412 return transform<Geometry1, Geometry2>::apply(
Chris@101 413 geometry1,
Chris@101 414 m_geometry2,
Chris@101 415 m_strategy
Chris@101 416 );
Chris@101 417 }
Chris@101 418 };
Chris@101 419
Chris@101 420 template <typename Strategy>
Chris@101 421 static inline bool apply(
Chris@101 422 boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry1,
Chris@101 423 Geometry2& geometry2,
Chris@101 424 Strategy const& strategy
Chris@101 425 )
Chris@101 426 {
Chris@101 427 return apply_visitor(visitor<Strategy>(geometry2, strategy), geometry1);
Chris@101 428 }
Chris@101 429 };
Chris@101 430
Chris@101 431 } // namespace resolve_variant
Chris@101 432
Chris@101 433
Chris@16 434 /*!
Chris@16 435 \brief Transforms from one geometry to another geometry \brief_strategy
Chris@16 436 \ingroup transform
Chris@16 437 \tparam Geometry1 \tparam_geometry
Chris@16 438 \tparam Geometry2 \tparam_geometry
Chris@16 439 \tparam Strategy strategy
Chris@16 440 \param geometry1 \param_geometry
Chris@16 441 \param geometry2 \param_geometry
Chris@16 442 \param strategy The strategy to be used for transformation
Chris@16 443 \return True if the transformation could be done
Chris@16 444
Chris@16 445 \qbk{distinguish,with strategy}
Chris@16 446
Chris@16 447 \qbk{[include reference/algorithms/transform_with_strategy.qbk]}
Chris@16 448 */
Chris@16 449 template <typename Geometry1, typename Geometry2, typename Strategy>
Chris@16 450 inline bool transform(Geometry1 const& geometry1, Geometry2& geometry2,
Chris@16 451 Strategy const& strategy)
Chris@16 452 {
Chris@101 453 return resolve_variant::transform<Geometry1, Geometry2>
Chris@101 454 ::apply(geometry1, geometry2, strategy);
Chris@16 455 }
Chris@16 456
Chris@16 457
Chris@16 458 /*!
Chris@16 459 \brief Transforms from one geometry to another geometry using a strategy
Chris@16 460 \ingroup transform
Chris@16 461 \tparam Geometry1 \tparam_geometry
Chris@16 462 \tparam Geometry2 \tparam_geometry
Chris@16 463 \param geometry1 \param_geometry
Chris@16 464 \param geometry2 \param_geometry
Chris@16 465 \return True if the transformation could be done
Chris@16 466
Chris@16 467 \qbk{[include reference/algorithms/transform.qbk]}
Chris@16 468 */
Chris@16 469 template <typename Geometry1, typename Geometry2>
Chris@16 470 inline bool transform(Geometry1 const& geometry1, Geometry2& geometry2)
Chris@16 471 {
Chris@101 472 return transform(geometry1, geometry2, default_strategy());
Chris@16 473 }
Chris@16 474
Chris@16 475
Chris@16 476 }} // namespace boost::geometry
Chris@16 477
Chris@16 478
Chris@16 479 #endif // BOOST_GEOMETRY_ALGORITHMS_TRANSFORM_HPP