File indexing completed on 2025-01-18 09:35:20
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020 #ifndef BOOST_GEOMETRY_ALGORITHMS_CONVERT_HPP
0021 #define BOOST_GEOMETRY_ALGORITHMS_CONVERT_HPP
0022
0023
0024 #include <cstddef>
0025 #include <type_traits>
0026
0027 #include <boost/numeric/conversion/cast.hpp>
0028 #include <boost/range/begin.hpp>
0029 #include <boost/range/end.hpp>
0030 #include <boost/range/size.hpp>
0031 #include <boost/range/value_type.hpp>
0032 #include <boost/variant/static_visitor.hpp>
0033 #include <boost/variant/variant_fwd.hpp>
0034
0035 #include <boost/geometry/algorithms/clear.hpp>
0036 #include <boost/geometry/algorithms/detail/assign_box_corners.hpp>
0037 #include <boost/geometry/algorithms/detail/assign_indexed_point.hpp>
0038 #include <boost/geometry/algorithms/detail/convert_point_to_point.hpp>
0039 #include <boost/geometry/algorithms/detail/convert_indexed_to_indexed.hpp>
0040 #include <boost/geometry/algorithms/not_implemented.hpp>
0041
0042 #include <boost/geometry/core/closure.hpp>
0043 #include <boost/geometry/core/point_order.hpp>
0044 #include <boost/geometry/core/tags.hpp>
0045
0046 #include <boost/geometry/geometries/concepts/check.hpp>
0047
0048 #include <boost/geometry/util/range.hpp>
0049
0050 #include <boost/geometry/views/detail/closed_clockwise_view.hpp>
0051
0052
0053 namespace boost { namespace geometry
0054 {
0055
0056
0057
0058 #if defined(_MSC_VER)
0059 #pragma warning(push)
0060 #pragma warning(disable : 4127 4512)
0061 #endif
0062
0063
0064 #ifndef DOXYGEN_NO_DETAIL
0065 namespace detail { namespace conversion
0066 {
0067
0068 template
0069 <
0070 typename Point,
0071 typename Box,
0072 std::size_t Index,
0073 std::size_t Dimension,
0074 std::size_t DimensionCount
0075 >
0076 struct point_to_box
0077 {
0078 static inline void apply(Point const& point, Box& box)
0079 {
0080 typedef typename coordinate_type<Box>::type coordinate_type;
0081
0082 set<Index, Dimension>(box,
0083 boost::numeric_cast<coordinate_type>(get<Dimension>(point)));
0084 point_to_box
0085 <
0086 Point, Box,
0087 Index, Dimension + 1, DimensionCount
0088 >::apply(point, box);
0089 }
0090 };
0091
0092
0093 template
0094 <
0095 typename Point,
0096 typename Box,
0097 std::size_t Index,
0098 std::size_t DimensionCount
0099 >
0100 struct point_to_box<Point, Box, Index, DimensionCount, DimensionCount>
0101 {
0102 static inline void apply(Point const& , Box& )
0103 {}
0104 };
0105
0106 template <typename Box, typename Range, bool Close, bool Reverse>
0107 struct box_to_range
0108 {
0109 static inline void apply(Box const& box, Range& range)
0110 {
0111 traits::resize<Range>::apply(range, Close ? 5 : 4);
0112 assign_box_corners_oriented<Reverse>(box, range);
0113 if (Close)
0114 {
0115 range::at(range, 4) = range::at(range, 0);
0116 }
0117 }
0118 };
0119
0120 template <typename Segment, typename Range>
0121 struct segment_to_range
0122 {
0123 static inline void apply(Segment const& segment, Range& range)
0124 {
0125 traits::resize<Range>::apply(range, 2);
0126
0127 auto it = boost::begin(range);
0128
0129 assign_point_from_index<0>(segment, *it);
0130 ++it;
0131 assign_point_from_index<1>(segment, *it);
0132 }
0133 };
0134
0135 template
0136 <
0137 typename Range1,
0138 typename Range2,
0139 bool Reverse = false
0140 >
0141 struct range_to_range
0142 {
0143 struct default_policy
0144 {
0145 template <typename Point1, typename Point2>
0146 static inline void apply(Point1 const& point1, Point2 & point2)
0147 {
0148 geometry::detail::conversion::convert_point_to_point(point1, point2);
0149 }
0150 };
0151
0152 static inline void apply(Range1 const& source, Range2& destination)
0153 {
0154 apply(source, destination, default_policy());
0155 }
0156
0157 template <typename ConvertPointPolicy>
0158 static inline ConvertPointPolicy apply(Range1 const& source, Range2& destination,
0159 ConvertPointPolicy convert_point)
0160 {
0161 geometry::clear(destination);
0162
0163 using view_type = detail::closed_clockwise_view
0164 <
0165 Range1 const,
0166 geometry::closure<Range1>::value,
0167 Reverse ? counterclockwise : clockwise
0168 >;
0169
0170
0171
0172 view_type const view(source);
0173
0174 typedef typename boost::range_size<Range1>::type size_type;
0175 size_type n = boost::size(view);
0176 if (geometry::closure<Range2>::value == geometry::open)
0177 {
0178 n--;
0179 }
0180
0181
0182
0183
0184 size_type i = 0;
0185 for (auto it = boost::begin(view);
0186 it != boost::end(view) && i < n;
0187 ++it, ++i)
0188 {
0189 typename boost::range_value<Range2>::type point;
0190 convert_point.apply(*it, point);
0191 range::push_back(destination, point);
0192 }
0193
0194 return convert_point;
0195 }
0196 };
0197
0198 template <typename Polygon1, typename Polygon2>
0199 struct polygon_to_polygon
0200 {
0201 typedef range_to_range
0202 <
0203 typename geometry::ring_type<Polygon1>::type,
0204 typename geometry::ring_type<Polygon2>::type,
0205 geometry::point_order<Polygon1>::value
0206 != geometry::point_order<Polygon2>::value
0207 > per_ring;
0208
0209 static inline void apply(Polygon1 const& source, Polygon2& destination)
0210 {
0211
0212
0213 per_ring::apply(geometry::exterior_ring(source),
0214 geometry::exterior_ring(destination));
0215
0216
0217 traits::resize
0218 <
0219 typename std::remove_reference
0220 <
0221 typename traits::interior_mutable_type<Polygon2>::type
0222 >::type
0223 >::apply(interior_rings(destination), num_interior_rings(source));
0224
0225 auto const& rings_source = interior_rings(source);
0226 auto&& rings_dest = interior_rings(destination);
0227
0228 auto it_source = boost::begin(rings_source);
0229 auto it_dest = boost::begin(rings_dest);
0230
0231 for ( ; it_source != boost::end(rings_source); ++it_source, ++it_dest)
0232 {
0233 per_ring::apply(*it_source, *it_dest);
0234 }
0235 }
0236 };
0237
0238 template <typename Single, typename Multi, typename Policy>
0239 struct single_to_multi: private Policy
0240 {
0241 static inline void apply(Single const& single, Multi& multi)
0242 {
0243 traits::resize<Multi>::apply(multi, 1);
0244 Policy::apply(single, *boost::begin(multi));
0245 }
0246 };
0247
0248
0249
0250 template <typename Multi1, typename Multi2, typename Policy>
0251 struct multi_to_multi: private Policy
0252 {
0253 static inline void apply(Multi1 const& multi1, Multi2& multi2)
0254 {
0255 traits::resize<Multi2>::apply(multi2, boost::size(multi1));
0256
0257 auto it1 = boost::begin(multi1);
0258 auto it2 = boost::begin(multi2);
0259
0260 for (; it1 != boost::end(multi1); ++it1, ++it2)
0261 {
0262 Policy::apply(*it1, *it2);
0263 }
0264 }
0265 };
0266
0267
0268 }}
0269 #endif
0270
0271
0272 #ifndef DOXYGEN_NO_DISPATCH
0273 namespace dispatch
0274 {
0275
0276
0277
0278
0279
0280 template
0281 <
0282 typename Geometry1, typename Geometry2,
0283 typename Tag1 = typename tag_cast<typename tag<Geometry1>::type, multi_tag>::type,
0284 typename Tag2 = typename tag_cast<typename tag<Geometry2>::type, multi_tag>::type,
0285 std::size_t DimensionCount = dimension<Geometry1>::type::value,
0286 bool UseAssignment = std::is_same<Geometry1, Geometry2>::value
0287 && !std::is_array<Geometry1>::value
0288 >
0289 struct convert
0290 : not_implemented
0291 <
0292 Tag1, Tag2,
0293 std::integral_constant<std::size_t, DimensionCount>
0294 >
0295 {};
0296
0297
0298 template
0299 <
0300 typename Geometry1, typename Geometry2,
0301 typename Tag,
0302 std::size_t DimensionCount
0303 >
0304 struct convert<Geometry1, Geometry2, Tag, Tag, DimensionCount, true>
0305 {
0306
0307 static inline void apply(Geometry1 const& source, Geometry2& destination)
0308 {
0309 destination = source;
0310 }
0311 };
0312
0313
0314 template
0315 <
0316 typename Geometry1, typename Geometry2,
0317 std::size_t DimensionCount
0318 >
0319 struct convert<Geometry1, Geometry2, point_tag, point_tag, DimensionCount, false>
0320 : detail::conversion::point_to_point<Geometry1, Geometry2, 0, DimensionCount>
0321 {};
0322
0323
0324 template
0325 <
0326 typename Box1, typename Box2,
0327 std::size_t DimensionCount
0328 >
0329 struct convert<Box1, Box2, box_tag, box_tag, DimensionCount, false>
0330 : detail::conversion::indexed_to_indexed<Box1, Box2, 0, DimensionCount>
0331 {};
0332
0333
0334 template
0335 <
0336 typename Segment1, typename Segment2,
0337 std::size_t DimensionCount
0338 >
0339 struct convert<Segment1, Segment2, segment_tag, segment_tag, DimensionCount, false>
0340 : detail::conversion::indexed_to_indexed<Segment1, Segment2, 0, DimensionCount>
0341 {};
0342
0343
0344 template <typename Segment, typename LineString, std::size_t DimensionCount>
0345 struct convert<Segment, LineString, segment_tag, linestring_tag, DimensionCount, false>
0346 : detail::conversion::segment_to_range<Segment, LineString>
0347 {};
0348
0349
0350 template <typename Ring1, typename Ring2, std::size_t DimensionCount>
0351 struct convert<Ring1, Ring2, ring_tag, ring_tag, DimensionCount, false>
0352 : detail::conversion::range_to_range
0353 <
0354 Ring1,
0355 Ring2,
0356 geometry::point_order<Ring1>::value
0357 != geometry::point_order<Ring2>::value
0358 >
0359 {};
0360
0361 template <typename LineString1, typename LineString2, std::size_t DimensionCount>
0362 struct convert<LineString1, LineString2, linestring_tag, linestring_tag, DimensionCount, false>
0363 : detail::conversion::range_to_range<LineString1, LineString2>
0364 {};
0365
0366 template <typename Polygon1, typename Polygon2, std::size_t DimensionCount>
0367 struct convert<Polygon1, Polygon2, polygon_tag, polygon_tag, DimensionCount, false>
0368 : detail::conversion::polygon_to_polygon<Polygon1, Polygon2>
0369 {};
0370
0371 template <typename Box, typename Ring>
0372 struct convert<Box, Ring, box_tag, ring_tag, 2, false>
0373 : detail::conversion::box_to_range
0374 <
0375 Box,
0376 Ring,
0377 geometry::closure<Ring>::value == closed,
0378 geometry::point_order<Ring>::value == counterclockwise
0379 >
0380 {};
0381
0382
0383 template <typename Box, typename Polygon>
0384 struct convert<Box, Polygon, box_tag, polygon_tag, 2, false>
0385 {
0386 static inline void apply(Box const& box, Polygon& polygon)
0387 {
0388 typedef typename ring_type<Polygon>::type ring_type;
0389
0390 convert
0391 <
0392 Box, ring_type,
0393 box_tag, ring_tag,
0394 2, false
0395 >::apply(box, exterior_ring(polygon));
0396 }
0397 };
0398
0399
0400 template <typename Point, typename Box, std::size_t DimensionCount>
0401 struct convert<Point, Box, point_tag, box_tag, DimensionCount, false>
0402 {
0403 static inline void apply(Point const& point, Box& box)
0404 {
0405 detail::conversion::point_to_box
0406 <
0407 Point, Box, min_corner, 0, DimensionCount
0408 >::apply(point, box);
0409 detail::conversion::point_to_box
0410 <
0411 Point, Box, max_corner, 0, DimensionCount
0412 >::apply(point, box);
0413 }
0414 };
0415
0416
0417 template <typename Ring, typename Polygon, std::size_t DimensionCount>
0418 struct convert<Ring, Polygon, ring_tag, polygon_tag, DimensionCount, false>
0419 {
0420 static inline void apply(Ring const& ring, Polygon& polygon)
0421 {
0422 typedef typename ring_type<Polygon>::type ring_type;
0423 convert
0424 <
0425 Ring, ring_type,
0426 ring_tag, ring_tag,
0427 DimensionCount, false
0428 >::apply(ring, exterior_ring(polygon));
0429 }
0430 };
0431
0432
0433 template <typename Polygon, typename Ring, std::size_t DimensionCount>
0434 struct convert<Polygon, Ring, polygon_tag, ring_tag, DimensionCount, false>
0435 {
0436 static inline void apply(Polygon const& polygon, Ring& ring)
0437 {
0438 typedef typename ring_type<Polygon>::type ring_type;
0439
0440 convert
0441 <
0442 ring_type, Ring,
0443 ring_tag, ring_tag,
0444 DimensionCount, false
0445 >::apply(exterior_ring(polygon), ring);
0446 }
0447 };
0448
0449
0450
0451
0452
0453
0454 template <typename Multi1, typename Multi2, std::size_t DimensionCount>
0455 struct convert<Multi1, Multi2, multi_tag, multi_tag, DimensionCount, false>
0456 : detail::conversion::multi_to_multi
0457 <
0458 Multi1,
0459 Multi2,
0460 convert
0461 <
0462 typename boost::range_value<Multi1>::type,
0463 typename boost::range_value<Multi2>::type,
0464 typename single_tag_of
0465 <
0466 typename tag<Multi1>::type
0467 >::type,
0468 typename single_tag_of
0469 <
0470 typename tag<Multi2>::type
0471 >::type,
0472 DimensionCount
0473 >
0474 >
0475 {};
0476
0477
0478 template <typename Single, typename Multi, typename SingleTag, std::size_t DimensionCount>
0479 struct convert<Single, Multi, SingleTag, multi_tag, DimensionCount, false>
0480 : detail::conversion::single_to_multi
0481 <
0482 Single,
0483 Multi,
0484 convert
0485 <
0486 Single,
0487 typename boost::range_value<Multi>::type,
0488 typename tag<Single>::type,
0489 typename single_tag_of
0490 <
0491 typename tag<Multi>::type
0492 >::type,
0493 DimensionCount,
0494 false
0495 >
0496 >
0497 {};
0498
0499
0500 }
0501 #endif
0502
0503
0504 namespace resolve_variant {
0505
0506 template <typename Geometry1, typename Geometry2>
0507 struct convert
0508 {
0509 static inline void apply(Geometry1 const& geometry1, Geometry2& geometry2)
0510 {
0511 concepts::check_concepts_and_equal_dimensions<Geometry1 const, Geometry2>();
0512 dispatch::convert<Geometry1, Geometry2>::apply(geometry1, geometry2);
0513 }
0514 };
0515
0516 template <BOOST_VARIANT_ENUM_PARAMS(typename T), typename Geometry2>
0517 struct convert<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Geometry2>
0518 {
0519 struct visitor: static_visitor<void>
0520 {
0521 Geometry2& m_geometry2;
0522
0523 visitor(Geometry2& geometry2)
0524 : m_geometry2(geometry2)
0525 {}
0526
0527 template <typename Geometry1>
0528 inline void operator()(Geometry1 const& geometry1) const
0529 {
0530 convert<Geometry1, Geometry2>::apply(geometry1, m_geometry2);
0531 }
0532 };
0533
0534 static inline void apply(
0535 boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry1,
0536 Geometry2& geometry2
0537 )
0538 {
0539 boost::apply_visitor(visitor(geometry2), geometry1);
0540 }
0541 };
0542
0543 }
0544
0545
0546
0547
0548
0549
0550
0551
0552
0553
0554
0555
0556
0557
0558
0559
0560
0561 template <typename Geometry1, typename Geometry2>
0562 inline void convert(Geometry1 const& geometry1, Geometry2& geometry2)
0563 {
0564 resolve_variant::convert<Geometry1, Geometry2>::apply(geometry1, geometry2);
0565 }
0566
0567 #if defined(_MSC_VER)
0568 #pragma warning(pop)
0569 #endif
0570
0571 }}
0572
0573 #endif