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