Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-08-07 08:47:52

0001 // Boost.Geometry (aka GGL, Generic Geometry Library)
0002 
0003 // Copyright (c) 2007-2025 Barend Gehrels, Amsterdam, the Netherlands.
0004 // Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
0005 // Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
0006 // Copyright (c) 2014-2024 Adam Wulkiewicz, Lodz, Poland.
0007 
0008 // This file was modified by Oracle on 2017-2023.
0009 // Modifications copyright (c) 2017-2023, Oracle and/or its affiliates.
0010 // Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
0011 // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
0012 
0013 // Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
0014 // (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
0015 
0016 // Use, modification and distribution is subject to the Boost Software License,
0017 // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
0018 // http://www.boost.org/LICENSE_1_0.txt)
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/num_points.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/tag_cast.hpp>
0045 #include <boost/geometry/core/tags.hpp>
0046 
0047 #include <boost/geometry/geometries/concepts/check.hpp>
0048 
0049 #include <boost/geometry/util/numeric_cast.hpp>
0050 #include <boost/geometry/util/range.hpp>
0051 
0052 #include <boost/geometry/views/detail/closed_clockwise_view.hpp>
0053 
0054 
0055 namespace boost { namespace geometry
0056 {
0057 
0058 // Silence warning C4127: conditional expression is constant
0059 // Silence warning C4512: assignment operator could not be generated
0060 #if defined(_MSC_VER)
0061 #pragma warning(push)
0062 #pragma warning(disable : 4127 4512)
0063 #endif
0064 
0065 
0066 #ifndef DOXYGEN_NO_DETAIL
0067 namespace detail { namespace conversion
0068 {
0069 
0070 template
0071 <
0072     typename Point,
0073     typename Box,
0074     std::size_t Index,
0075     std::size_t Dimension,
0076     std::size_t DimensionCount
0077 >
0078 struct point_to_box
0079 {
0080     static inline void apply(Point const& point, Box& box)
0081     {
0082         set<Index, Dimension>(box,
0083                 util::numeric_cast<coordinate_type_t<Box>>(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 <bool Close, bool Reverse>
0107 struct box_to_range
0108 {
0109     template <typename Box, typename Range>
0110     static inline void apply(Box const& box, Range& range)
0111     {
0112         traits::resize<Range>::apply(range, Close ? 5 : 4);
0113         assign_box_corners_oriented<Reverse>(box, range);
0114         if (Close)
0115         {
0116             range::at(range, 4) = range::at(range, 0);
0117         }
0118     }
0119 };
0120 
0121 template <typename Segment, typename Range>
0122 struct segment_to_range
0123 {
0124     static inline void apply(Segment const& segment, Range& range)
0125     {
0126         traits::resize<Range>::apply(range, 2);
0127 
0128         auto it = boost::begin(range);
0129 
0130         assign_point_from_index<0>(segment, *it);
0131         ++it;
0132         assign_point_from_index<1>(segment, *it);
0133     }
0134 };
0135 
0136 struct range_to_range
0137 {
0138     struct default_policy
0139     {
0140         template <typename Point1, typename Point2>
0141         static inline void apply(Point1 const& point1, Point2 & point2)
0142         {
0143             geometry::detail::conversion::convert_point_to_point(point1, point2);
0144         }
0145     };
0146 
0147     template <typename Range1, typename Range2>
0148     static inline void apply(Range1 const& source, Range2& destination)
0149     {
0150         apply(source, destination, default_policy());
0151     }
0152 
0153     template <typename ConvertPointPolicy, typename Range1, typename Range2>
0154     static inline ConvertPointPolicy apply(Range1 const& source, Range2& destination,
0155                                            ConvertPointPolicy convert_point)
0156     {
0157         geometry::clear(destination);
0158 
0159         constexpr bool reverse = geometry::point_order<Range1>::value != geometry::point_order<Range2>::value;
0160 
0161         using view_type = detail::closed_clockwise_view
0162             <
0163                 Range1 const,
0164                 geometry::closure<Range1>::value,
0165                 reverse ? counterclockwise : clockwise
0166             >;
0167 
0168         // We consider input always as closed, and skip last
0169         // point for open output.
0170         view_type const view(source);
0171 
0172         auto n = boost::size(view);
0173         if (geometry::closure<Range2>::value == geometry::open)
0174         {
0175             n--;
0176         }
0177 
0178         // If size == 0 && geometry::open <=> n = numeric_limits<size_type>::max()
0179         // but ok, sice below it == end()
0180 
0181         decltype(n) i = 0;
0182         for (auto it = boost::begin(view);
0183             it != boost::end(view) && i < n;
0184             ++it, ++i)
0185         {
0186             typename boost::range_value<Range2>::type point;
0187             convert_point.apply(*it, point);
0188             range::push_back(destination, point);
0189         }
0190 
0191         return convert_point;
0192     }
0193 };
0194 
0195 // Converts a polygon to an output iterator of ranges.
0196 // The iterator is updated such that it can used iteratively.
0197 struct polygon_to_multi_range
0198 {
0199     template <typename Polygon, typename OutputIterator>
0200     static inline void apply(Polygon const& source, OutputIterator& it)
0201     {
0202         range_to_range::apply(geometry::exterior_ring(source), *it++);
0203         for (auto const& ring : geometry::interior_rings(source))
0204         {
0205             range_to_range::apply(ring, *it++);
0206         }
0207     }
0208 };
0209 
0210 template <typename Polygon1, typename Polygon2>
0211 struct polygon_to_polygon
0212 {
0213     static inline void apply(Polygon1 const& source, Polygon2& destination)
0214     {
0215         range_to_range::apply(geometry::exterior_ring(source),
0216             geometry::exterior_ring(destination));
0217 
0218         // Container should be resizeable
0219         traits::resize
0220             <
0221                 std::remove_reference_t
0222                     <
0223                         typename traits::interior_mutable_type<Polygon2>::type
0224                     >
0225             >::apply(interior_rings(destination), num_interior_rings(source));
0226 
0227         auto const& rings_source = interior_rings(source);
0228         auto&& rings_dest = interior_rings(destination);
0229 
0230         auto it_source = boost::begin(rings_source);
0231         auto it_dest = boost::begin(rings_dest);
0232 
0233         for ( ; it_source != boost::end(rings_source); ++it_source, ++it_dest)
0234         {
0235             range_to_range::apply(*it_source, *it_dest);
0236         }
0237     }
0238 };
0239 
0240 struct range_to_multi_point
0241 {
0242     template <typename Range, typename Iterator>
0243     static inline void append_from_source(Range const& source, Iterator& it)
0244     {
0245         for (auto const& point : source)
0246         {
0247             detail::conversion::convert_point_to_point(point, *it);
0248             ++it;
0249         }
0250     }
0251 
0252     template <typename Range, typename MultiPoint>
0253     static inline void apply(Range const& source, MultiPoint& destination)
0254     {
0255         traits::resize<MultiPoint>::apply(destination, boost::size(source));
0256         auto it = boost::begin(destination);
0257         append_from_source(source, it);
0258     }
0259 };
0260 
0261 struct polygon_to_range
0262 {
0263     template <typename Polygon, typename Iterator>
0264     static inline void append_from_polygon(Polygon const& source, Iterator& it)
0265     {
0266         range_to_multi_point::append_from_source(geometry::exterior_ring(source), it);
0267         for (auto const& ring : geometry::interior_rings(source))
0268         {
0269             range_to_multi_point::append_from_source(ring, it);
0270         }
0271     }
0272 
0273     template <typename Polygon, typename MultiPoint>
0274     static inline void apply(Polygon const& source, MultiPoint& destination)
0275     {
0276         traits::resize<MultiPoint>::apply(destination, geometry::num_points(source));
0277         auto it = boost::begin(destination);
0278         append_from_polygon(source, it);
0279     }
0280 };
0281 
0282 struct multi_polygon_to_range
0283 {
0284     template <typename MultiPolygon, typename MultiPoint>
0285     static inline void apply(MultiPolygon const& source, MultiPoint& destination)
0286     {
0287         traits::resize<MultiPoint>::apply(destination, geometry::num_points(source));
0288         auto it = boost::begin(destination);
0289         for (auto const& polygon : source)
0290         {
0291             polygon_to_range::append_from_polygon(polygon, it);
0292         }
0293     }
0294 };
0295 
0296 template <typename Single, typename Multi, typename ConversionAlgorithm>
0297 struct single_to_multi
0298 {
0299     static inline void apply(Single const& single, Multi& multi)
0300     {
0301         traits::resize<Multi>::apply(multi, 1);
0302         ConversionAlgorithm::apply(single, *boost::begin(multi));
0303     }
0304 };
0305 
0306 
0307 template <typename Multi1, typename Multi2, typename ConversionAlgorithm>
0308 struct multi_to_multi
0309 {
0310     static inline void apply(Multi1 const& multi1, Multi2& multi2)
0311     {
0312         traits::resize<Multi2>::apply(multi2, boost::size(multi1));
0313 
0314         auto it1 = boost::begin(multi1);
0315         auto it2 = boost::begin(multi2);
0316 
0317         for (; it1 != boost::end(multi1); ++it1, ++it2)
0318         {
0319             ConversionAlgorithm::apply(*it1, *it2);
0320         }
0321     }
0322 };
0323 
0324 
0325 }} // namespace detail::conversion
0326 #endif // DOXYGEN_NO_DETAIL
0327 
0328 
0329 #ifndef DOXYGEN_NO_DISPATCH
0330 namespace dispatch
0331 {
0332 
0333 // TODO: We could use std::is_assignable instead of std::is_same.
0334 //   Then we should rather check ! std::is_array<Geometry2>::value
0335 //   which is Destination.
0336 
0337 template
0338 <
0339     typename Geometry1, typename Geometry2,
0340     typename Tag1 = tag_t<Geometry1>,
0341     typename Tag2 = tag_t<Geometry2>,
0342     std::size_t DimensionCount = dimension<Geometry1>::value,
0343     bool UseAssignment = std::is_same<Geometry1, Geometry2>::value
0344                          && !std::is_array<Geometry1>::value
0345 >
0346 struct convert
0347     : not_implemented
0348         <
0349             Tag1, Tag2,
0350             std::integral_constant<std::size_t, DimensionCount>
0351         >
0352 {};
0353 
0354 
0355 template
0356 <
0357     typename Geometry1, typename Geometry2,
0358     typename Tag,
0359     std::size_t DimensionCount
0360 >
0361 struct convert<Geometry1, Geometry2, Tag, Tag, DimensionCount, true>
0362 {
0363     // Same geometry type -> copy geometry
0364     static inline void apply(Geometry1 const& source, Geometry2& destination)
0365     {
0366         destination = source;
0367     }
0368 };
0369 
0370 
0371 template <typename Geometry1, typename Geometry2, std::size_t DimensionCount>
0372 struct convert<Geometry1, Geometry2, point_tag, point_tag, DimensionCount, false>
0373     : detail::conversion::point_to_point<Geometry1, Geometry2, 0, DimensionCount>
0374 {};
0375 
0376 
0377 template <typename Box1, typename Box2, std::size_t DimensionCount>
0378 struct convert<Box1, Box2, box_tag, box_tag, DimensionCount, false>
0379     : detail::conversion::indexed_to_indexed<Box1, Box2, 0, DimensionCount>
0380 {};
0381 
0382 
0383 template <typename Segment1, typename Segment2, std::size_t DimensionCount>
0384 struct convert<Segment1, Segment2, segment_tag, segment_tag, DimensionCount, false>
0385     : detail::conversion::indexed_to_indexed<Segment1, Segment2, 0, DimensionCount>
0386 {};
0387 
0388 
0389 template <typename Segment, typename LineString, std::size_t DimensionCount>
0390 struct convert<Segment, LineString, segment_tag, linestring_tag, DimensionCount, false>
0391     : detail::conversion::segment_to_range<Segment, LineString>
0392 {};
0393 
0394 
0395 template <typename Ring1, typename Ring2, std::size_t DimensionCount>
0396 struct convert<Ring1, Ring2, ring_tag, ring_tag, DimensionCount, false>
0397     : detail::conversion::range_to_range
0398 {};
0399 
0400 template <typename LineString1, typename LineString2, std::size_t DimensionCount>
0401 struct convert<LineString1, LineString2, linestring_tag, linestring_tag, DimensionCount, false>
0402     : detail::conversion::range_to_range
0403 {};
0404 
0405 template <typename Polygon1, typename Polygon2, std::size_t DimensionCount>
0406 struct convert<Polygon1, Polygon2, polygon_tag, polygon_tag, DimensionCount, false>
0407     : detail::conversion::polygon_to_polygon<Polygon1, Polygon2>
0408 {};
0409 
0410 template <typename Box, typename LineString>
0411 struct convert<Box, LineString, box_tag, linestring_tag, 2, false>
0412     : detail::conversion::box_to_range<true, false>
0413 {};
0414 
0415 template <typename Box, typename Ring>
0416 struct convert<Box, Ring, box_tag, ring_tag, 2, false>
0417     : detail::conversion::box_to_range
0418         <
0419             geometry::closure<Ring>::value == closed,
0420             geometry::point_order<Ring>::value == counterclockwise
0421         >
0422 {};
0423 
0424 template <typename Box, typename MultiPoint>
0425 struct convert<Box, MultiPoint, box_tag, multi_point_tag, 2, false>
0426     : detail::conversion::box_to_range<false, false>
0427 {};
0428 
0429 
0430 template <typename Box, typename Polygon>
0431 struct convert<Box, Polygon, box_tag, polygon_tag, 2, false>
0432 {
0433     static inline void apply(Box const& box, Polygon& polygon)
0434     {
0435         convert
0436             <
0437                 Box, ring_type_t<Polygon>,
0438                 box_tag, ring_tag,
0439                 2, false
0440             >::apply(box, exterior_ring(polygon));
0441     }
0442 };
0443 
0444 
0445 template <typename Point, typename Box, std::size_t DimensionCount>
0446 struct convert<Point, Box, point_tag, box_tag, DimensionCount, false>
0447 {
0448     static inline void apply(Point const& point, Box& box)
0449     {
0450         detail::conversion::point_to_box
0451             <
0452                 Point, Box, min_corner, 0, DimensionCount
0453             >::apply(point, box);
0454         detail::conversion::point_to_box
0455             <
0456                 Point, Box, max_corner, 0, DimensionCount
0457             >::apply(point, box);
0458     }
0459 };
0460 
0461 
0462 template <typename Ring, typename Polygon, std::size_t DimensionCount>
0463 struct convert<Ring, Polygon, ring_tag, polygon_tag, DimensionCount, false>
0464 {
0465     static inline void apply(Ring const& ring, Polygon& polygon)
0466     {
0467         convert
0468             <
0469                 Ring, ring_type_t<Polygon>,
0470                 ring_tag, ring_tag,
0471                 DimensionCount, false
0472             >::apply(ring, exterior_ring(polygon));
0473     }
0474 };
0475 
0476 // Polygon to ring, this ignores interior rings
0477 template <typename Polygon, typename Ring, std::size_t DimensionCount>
0478 struct convert<Polygon, Ring, polygon_tag, ring_tag, DimensionCount, false>
0479 {
0480     static inline void apply(Polygon const& polygon, Ring& ring)
0481     {
0482         convert
0483             <
0484                 ring_type_t<Polygon>, Ring,
0485                 ring_tag, ring_tag,
0486                 DimensionCount, false
0487             >::apply(exterior_ring(polygon), ring);
0488     }
0489 };
0490 
0491 template <typename LineString, typename MultiPoint, std::size_t DimensionCount>
0492 struct convert<LineString, MultiPoint, linestring_tag, multi_point_tag, DimensionCount, false>
0493     : detail::conversion::range_to_multi_point {};
0494 
0495 template <typename Ring, typename MultiPoint, std::size_t DimensionCount>
0496 struct convert<Ring, MultiPoint, ring_tag, multi_point_tag, DimensionCount, false>
0497     : detail::conversion::range_to_multi_point {};
0498 
0499 template <typename Polygon, typename MultiPoint, std::size_t DimensionCount>
0500 struct convert<Polygon, MultiPoint, polygon_tag, multi_point_tag, DimensionCount, false>
0501     : detail::conversion::polygon_to_range {};
0502 
0503     template <typename MultiPolygon, typename MultiPoint, std::size_t DimensionCount>
0504 struct convert<MultiPolygon, MultiPoint, multi_polygon_tag, multi_point_tag, DimensionCount, false>
0505     : detail::conversion::multi_polygon_to_range {};
0506 
0507 template <typename MultiLineString, typename MultiPoint, std::size_t DimensionCount>
0508 struct convert<MultiLineString, MultiPoint, multi_linestring_tag, multi_point_tag, DimensionCount, false>
0509 {
0510     static inline void apply(MultiLineString const& source, MultiPoint& destination)
0511     {
0512         traits::resize<MultiPoint>::apply(destination, geometry::num_points(source));
0513         auto it = boost::begin(destination);
0514         for (auto const& linestring : source)
0515         {
0516             detail::conversion::range_to_multi_point::append_from_source(linestring, it);
0517         }
0518     }
0519 };
0520 
0521 template <typename Ring, typename MultiLinestring, std::size_t DimensionCount>
0522 struct convert<Ring, MultiLinestring, ring_tag, multi_linestring_tag, DimensionCount, false>
0523 {
0524     static inline void apply(Ring const& source, MultiLinestring& destination)
0525     {
0526         traits::resize<MultiLinestring>::apply(destination, 1);
0527         detail::conversion::range_to_range::apply(source, *boost::begin(destination));
0528     }
0529 };
0530 
0531 template <typename Polygon, typename MultiLinestring, std::size_t DimensionCount>
0532 struct convert<Polygon, MultiLinestring, polygon_tag, multi_linestring_tag, DimensionCount, false>
0533 {
0534     static inline void apply(Polygon const& source, MultiLinestring& destination)
0535     {
0536         traits::resize<MultiLinestring>::apply(destination, 1 + geometry::num_interior_rings(source));
0537         auto it = boost::begin(destination);
0538         detail::conversion::polygon_to_multi_range::apply(source, it);
0539     }
0540 };
0541 
0542 template <typename MultiPolygon, typename MultiLinestring, std::size_t DimensionCount>
0543 struct convert<MultiPolygon, MultiLinestring, multi_polygon_tag, multi_linestring_tag, DimensionCount, false>
0544 {
0545     static inline void apply(MultiPolygon const& source, MultiLinestring& destination)
0546     {
0547         std::size_t ring_count = boost::size(source);
0548         for (auto const& polygon : source)
0549         {
0550             ring_count += geometry::num_interior_rings(polygon);
0551         }
0552         traits::resize<MultiLinestring>::apply(destination, ring_count);
0553 
0554         auto it = boost::begin(destination);
0555         for (auto const& polygon : source)
0556         {
0557             detail::conversion::polygon_to_multi_range::apply(polygon, it);
0558         }
0559     }
0560 };
0561 
0562 template <typename Single, typename Multi, std::size_t DimensionCount>
0563 struct single_to_multi_convert
0564     : detail::conversion::single_to_multi
0565         <
0566             Single,
0567             Multi,
0568             convert
0569                 <
0570                     Single,
0571                     typename boost::range_value<Multi>::type,
0572                     tag_t<Single>,
0573                     single_tag_of_t<tag_t<Multi>>,
0574                     DimensionCount,
0575                     false
0576                 >
0577         >
0578 {};
0579 
0580 template <typename Multi1, typename Multi2, std::size_t DimensionCount>
0581 struct multi_to_multi_convert
0582     : detail::conversion::multi_to_multi
0583         <
0584             Multi1,
0585             Multi2,
0586             convert
0587                 <
0588                     typename boost::range_value<Multi1>::type,
0589                     typename boost::range_value<Multi2>::type,
0590                     single_tag_of_t<tag_t<Multi1>>,
0591                     single_tag_of_t<tag_t<Multi2>>,
0592                     DimensionCount
0593                 >
0594         >
0595 {};
0596 
0597 // Multi to multi of the same tag type
0598 template <typename GeometryIn, typename GeometryOut, std::size_t DimensionCount>
0599 struct convert<GeometryIn, GeometryOut, multi_point_tag, multi_point_tag, DimensionCount, false>
0600     : multi_to_multi_convert<GeometryIn, GeometryOut, DimensionCount> {};
0601 
0602 template <typename GeometryIn, typename GeometryOut, std::size_t DimensionCount>
0603 struct convert<GeometryIn, GeometryOut, multi_linestring_tag, multi_linestring_tag, DimensionCount, false>
0604     : multi_to_multi_convert<GeometryIn, GeometryOut, DimensionCount> {};
0605 
0606 template <typename GeometryIn, typename GeometryOut, std::size_t DimensionCount>
0607 struct convert<GeometryIn, GeometryOut, multi_polygon_tag, multi_polygon_tag, DimensionCount, false>
0608     : multi_to_multi_convert<GeometryIn, GeometryOut, DimensionCount> {};
0609 
0610 // Single to multi of the same topological tag type
0611 template <typename GeometryIn, typename GeometryOut, std::size_t DimensionCount>
0612 struct convert<GeometryIn, GeometryOut, point_tag, multi_point_tag, DimensionCount, false>
0613     : single_to_multi_convert<GeometryIn, GeometryOut, DimensionCount> {};
0614 
0615 template <typename GeometryIn, typename GeometryOut, std::size_t DimensionCount>
0616 struct convert<GeometryIn, GeometryOut, segment_tag, multi_linestring_tag, DimensionCount, false>
0617     : single_to_multi_convert<GeometryIn, GeometryOut, DimensionCount> {};
0618 
0619 template <typename GeometryIn, typename GeometryOut, std::size_t DimensionCount>
0620 struct convert<GeometryIn, GeometryOut, linestring_tag, multi_linestring_tag, DimensionCount, false>
0621     : single_to_multi_convert<GeometryIn, GeometryOut, DimensionCount> {};
0622 
0623 // To multi_polygon (box, ring, polygon)
0624 template <typename GeometryIn, typename GeometryOut, std::size_t DimensionCount>
0625 struct convert<GeometryIn, GeometryOut, box_tag, multi_polygon_tag, DimensionCount, false>
0626     : single_to_multi_convert<GeometryIn, GeometryOut, DimensionCount> {};
0627 
0628 template <typename GeometryIn, typename GeometryOut, std::size_t DimensionCount>
0629 struct convert<GeometryIn, GeometryOut, ring_tag, multi_polygon_tag, DimensionCount, false>
0630     : single_to_multi_convert<GeometryIn, GeometryOut, DimensionCount> {};
0631 
0632 template <typename GeometryIn, typename GeometryOut, std::size_t DimensionCount>
0633 struct convert<GeometryIn, GeometryOut, polygon_tag, multi_polygon_tag, DimensionCount, false>
0634     : single_to_multi_convert<GeometryIn, GeometryOut, DimensionCount> {};
0635 
0636 
0637 } // namespace dispatch
0638 #endif // DOXYGEN_NO_DISPATCH
0639 
0640 
0641 namespace resolve_variant {
0642 
0643 template <typename Geometry1, typename Geometry2>
0644 struct convert
0645 {
0646     static inline void apply(Geometry1 const& geometry1, Geometry2& geometry2)
0647     {
0648         concepts::check_concepts_and_equal_dimensions<Geometry1 const, Geometry2>();
0649         dispatch::convert<Geometry1, Geometry2>::apply(geometry1, geometry2);
0650     }
0651 };
0652 
0653 template <BOOST_VARIANT_ENUM_PARAMS(typename T), typename Geometry2>
0654 struct convert<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Geometry2>
0655 {
0656     struct visitor: static_visitor<void>
0657     {
0658         Geometry2& m_geometry2;
0659 
0660         visitor(Geometry2& geometry2)
0661             : m_geometry2(geometry2)
0662         {}
0663 
0664         template <typename Geometry1>
0665         inline void operator()(Geometry1 const& geometry1) const
0666         {
0667             convert<Geometry1, Geometry2>::apply(geometry1, m_geometry2);
0668         }
0669     };
0670 
0671     static inline void apply(
0672         boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry1,
0673         Geometry2& geometry2
0674     )
0675     {
0676         boost::apply_visitor(visitor(geometry2), geometry1);
0677     }
0678 };
0679 
0680 }
0681 
0682 
0683 /*!
0684 \brief Converts one geometry to another geometry
0685 \details The convert algorithm converts one geometry, e.g. a BOX, to another
0686 geometry, e.g. a RING. This only works if it is possible and applicable.
0687 If the point-order is different, or the closure is different between two
0688 geometry types, it will be converted correctly by explicitly reversing the
0689 points or closing or opening the polygon rings.
0690 \ingroup convert
0691 \tparam Geometry1 \tparam_geometry
0692 \tparam Geometry2 \tparam_geometry
0693 \param geometry1 \param_geometry (source)
0694 \param geometry2 \param_geometry (target)
0695 
0696 \qbk{[include reference/algorithms/convert.qbk]}
0697  */
0698 template <typename Geometry1, typename Geometry2>
0699 inline void convert(Geometry1 const& geometry1, Geometry2& geometry2)
0700 {
0701     resolve_variant::convert<Geometry1, Geometry2>::apply(geometry1, geometry2);
0702 }
0703 
0704 #if defined(_MSC_VER)
0705 #pragma warning(pop)
0706 #endif
0707 
0708 }} // namespace boost::geometry
0709 
0710 #endif // BOOST_GEOMETRY_ALGORITHMS_CONVERT_HPP