| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581 | // Boost.Geometry (aka GGL, Generic Geometry Library)// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.// Copyright (c) 2014 Adam Wulkiewicz, Lodz, Poland.// This file was modified by Oracle on 2017.// Modifications copyright (c) 2017, Oracle and/or its affiliates.// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.// Use, modification and distribution is subject to the Boost Software License,// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at// http://www.boost.org/LICENSE_1_0.txt)#ifndef BOOST_GEOMETRY_ALGORITHMS_CONVERT_HPP#define BOOST_GEOMETRY_ALGORITHMS_CONVERT_HPP#include <cstddef>#include <boost/numeric/conversion/cast.hpp>#include <boost/range.hpp>#include <boost/type_traits/is_array.hpp>#include <boost/type_traits/remove_reference.hpp>#include <boost/variant/apply_visitor.hpp>#include <boost/variant/static_visitor.hpp>#include <boost/variant/variant_fwd.hpp>#include <boost/geometry/arithmetic/arithmetic.hpp>#include <boost/geometry/algorithms/not_implemented.hpp>#include <boost/geometry/algorithms/clear.hpp>#include <boost/geometry/algorithms/for_each.hpp>#include <boost/geometry/algorithms/detail/assign_box_corners.hpp>#include <boost/geometry/algorithms/detail/assign_indexed_point.hpp>#include <boost/geometry/algorithms/detail/convert_point_to_point.hpp>#include <boost/geometry/algorithms/detail/convert_indexed_to_indexed.hpp>#include <boost/geometry/algorithms/detail/interior_iterator.hpp>#include <boost/geometry/views/closeable_view.hpp>#include <boost/geometry/views/reversible_view.hpp>#include <boost/geometry/util/range.hpp>#include <boost/geometry/core/cs.hpp>#include <boost/geometry/core/closure.hpp>#include <boost/geometry/core/point_order.hpp>#include <boost/geometry/core/tags.hpp>#include <boost/geometry/geometries/concepts/check.hpp>namespace boost { namespace geometry{// Silence warning C4127: conditional expression is constant// Silence warning C4512: assignment operator could not be generated#if defined(_MSC_VER)#pragma warning(push)#pragma warning(disable : 4127 4512)#endif#ifndef DOXYGEN_NO_DETAILnamespace detail { namespace conversion{template<    typename Point,    typename Box,    std::size_t Index,    std::size_t Dimension,    std::size_t DimensionCount>struct point_to_box{    static inline void apply(Point const& point, Box& box)    {        typedef typename coordinate_type<Box>::type coordinate_type;        set<Index, Dimension>(box,                boost::numeric_cast<coordinate_type>(get<Dimension>(point)));        point_to_box            <                Point, Box,                Index, Dimension + 1, DimensionCount            >::apply(point, box);    }};template<    typename Point,    typename Box,    std::size_t Index,    std::size_t DimensionCount>struct point_to_box<Point, Box, Index, DimensionCount, DimensionCount>{    static inline void apply(Point const& , Box& )    {}};template <typename Box, typename Range, bool Close, bool Reverse>struct box_to_range{    static inline void apply(Box const& box, Range& range)    {        traits::resize<Range>::apply(range, Close ? 5 : 4);        assign_box_corners_oriented<Reverse>(box, range);        if (Close)        {            range::at(range, 4) = range::at(range, 0);        }    }};template <typename Segment, typename Range>struct segment_to_range{    static inline void apply(Segment const& segment, Range& range)    {        traits::resize<Range>::apply(range, 2);        typename boost::range_iterator<Range>::type it = boost::begin(range);        assign_point_from_index<0>(segment, *it);        ++it;        assign_point_from_index<1>(segment, *it);    }};template<    typename Range1,    typename Range2,    bool Reverse = false>struct range_to_range{    typedef typename reversible_view        <            Range1 const,            Reverse ? iterate_reverse : iterate_forward        >::type rview_type;    typedef typename closeable_view        <            rview_type const,            geometry::closure<Range1>::value        >::type view_type;    struct default_policy    {        template <typename Point1, typename Point2>        static inline void apply(Point1 const& point1, Point2 & point2)        {            geometry::detail::conversion::convert_point_to_point(point1, point2);        }    };        static inline void apply(Range1 const& source, Range2& destination)    {        apply(source, destination, default_policy());    }    template <typename ConvertPointPolicy>    static inline ConvertPointPolicy apply(Range1 const& source, Range2& destination,                                           ConvertPointPolicy convert_point)    {        geometry::clear(destination);        rview_type rview(source);        // We consider input always as closed, and skip last        // point for open output.        view_type view(rview);        typedef typename boost::range_size<Range1>::type size_type;        size_type n = boost::size(view);        if (geometry::closure<Range2>::value == geometry::open)        {            n--;        }        // If size == 0 && geometry::open <=> n = numeric_limits<size_type>::max()        // but ok, sice below it == end()        size_type i = 0;        for (typename boost::range_iterator<view_type const>::type it            = boost::begin(view);            it != boost::end(view) && i < n;            ++it, ++i)        {            typename boost::range_value<Range2>::type point;            convert_point.apply(*it, point);            range::push_back(destination, point);        }        return convert_point;    }};template <typename Polygon1, typename Polygon2>struct polygon_to_polygon{    typedef range_to_range        <            typename geometry::ring_type<Polygon1>::type,            typename geometry::ring_type<Polygon2>::type,            geometry::point_order<Polygon1>::value                != geometry::point_order<Polygon2>::value        > per_ring;    static inline void apply(Polygon1 const& source, Polygon2& destination)    {        // Clearing managed per ring, and in the resizing of interior rings        per_ring::apply(geometry::exterior_ring(source),            geometry::exterior_ring(destination));        // Container should be resizeable        traits::resize            <                typename boost::remove_reference                <                    typename traits::interior_mutable_type<Polygon2>::type                >::type            >::apply(interior_rings(destination), num_interior_rings(source));        typename interior_return_type<Polygon1 const>::type            rings_source = interior_rings(source);        typename interior_return_type<Polygon2>::type            rings_dest = interior_rings(destination);        typename detail::interior_iterator<Polygon1 const>::type            it_source = boost::begin(rings_source);        typename detail::interior_iterator<Polygon2>::type            it_dest = boost::begin(rings_dest);        for ( ; it_source != boost::end(rings_source); ++it_source, ++it_dest)        {            per_ring::apply(*it_source, *it_dest);        }    }};template <typename Single, typename Multi, typename Policy>struct single_to_multi: private Policy{    static inline void apply(Single const& single, Multi& multi)    {        traits::resize<Multi>::apply(multi, 1);        Policy::apply(single, *boost::begin(multi));    }};template <typename Multi1, typename Multi2, typename Policy>struct multi_to_multi: private Policy{    static inline void apply(Multi1 const& multi1, Multi2& multi2)    {        traits::resize<Multi2>::apply(multi2, boost::size(multi1));        typename boost::range_iterator<Multi1 const>::type it1                = boost::begin(multi1);        typename boost::range_iterator<Multi2>::type it2                = boost::begin(multi2);        for (; it1 != boost::end(multi1); ++it1, ++it2)        {            Policy::apply(*it1, *it2);        }    }};}} // namespace detail::conversion#endif // DOXYGEN_NO_DETAIL#ifndef DOXYGEN_NO_DISPATCHnamespace dispatch{template<    typename Geometry1, typename Geometry2,    typename Tag1 = typename tag_cast<typename tag<Geometry1>::type, multi_tag>::type,    typename Tag2 = typename tag_cast<typename tag<Geometry2>::type, multi_tag>::type,    std::size_t DimensionCount = dimension<Geometry1>::type::value,    bool UseAssignment = boost::is_same<Geometry1, Geometry2>::value                         && !boost::is_array<Geometry1>::value>struct convert: not_implemented<Tag1, Tag2, boost::mpl::int_<DimensionCount> >{};template<    typename Geometry1, typename Geometry2,    typename Tag,    std::size_t DimensionCount>struct convert<Geometry1, Geometry2, Tag, Tag, DimensionCount, true>{    // Same geometry type -> copy whole geometry    static inline void apply(Geometry1 const& source, Geometry2& destination)    {        destination = source;    }};template<    typename Geometry1, typename Geometry2,    std::size_t DimensionCount>struct convert<Geometry1, Geometry2, point_tag, point_tag, DimensionCount, false>    : detail::conversion::point_to_point<Geometry1, Geometry2, 0, DimensionCount>{};template<    typename Box1, typename Box2,    std::size_t DimensionCount>struct convert<Box1, Box2, box_tag, box_tag, DimensionCount, false>    : detail::conversion::indexed_to_indexed<Box1, Box2, 0, DimensionCount>{};template<    typename Segment1, typename Segment2,    std::size_t DimensionCount>struct convert<Segment1, Segment2, segment_tag, segment_tag, DimensionCount, false>    : detail::conversion::indexed_to_indexed<Segment1, Segment2, 0, DimensionCount>{};template <typename Segment, typename LineString, std::size_t DimensionCount>struct convert<Segment, LineString, segment_tag, linestring_tag, DimensionCount, false>    : detail::conversion::segment_to_range<Segment, LineString>{};template <typename Ring1, typename Ring2, std::size_t DimensionCount>struct convert<Ring1, Ring2, ring_tag, ring_tag, DimensionCount, false>    : detail::conversion::range_to_range        <            Ring1,            Ring2,            geometry::point_order<Ring1>::value                != geometry::point_order<Ring2>::value        >{};template <typename LineString1, typename LineString2, std::size_t DimensionCount>struct convert<LineString1, LineString2, linestring_tag, linestring_tag, DimensionCount, false>    : detail::conversion::range_to_range<LineString1, LineString2>{};template <typename Polygon1, typename Polygon2, std::size_t DimensionCount>struct convert<Polygon1, Polygon2, polygon_tag, polygon_tag, DimensionCount, false>    : detail::conversion::polygon_to_polygon<Polygon1, Polygon2>{};template <typename Box, typename Ring>struct convert<Box, Ring, box_tag, ring_tag, 2, false>    : detail::conversion::box_to_range        <            Box,            Ring,            geometry::closure<Ring>::value == closed,            geometry::point_order<Ring>::value == counterclockwise        >{};template <typename Box, typename Polygon>struct convert<Box, Polygon, box_tag, polygon_tag, 2, false>{    static inline void apply(Box const& box, Polygon& polygon)    {        typedef typename ring_type<Polygon>::type ring_type;        convert            <                Box, ring_type,                box_tag, ring_tag,                2, false            >::apply(box, exterior_ring(polygon));    }};template <typename Point, typename Box, std::size_t DimensionCount>struct convert<Point, Box, point_tag, box_tag, DimensionCount, false>{    static inline void apply(Point const& point, Box& box)    {        detail::conversion::point_to_box            <                Point, Box, min_corner, 0, DimensionCount            >::apply(point, box);        detail::conversion::point_to_box            <                Point, Box, max_corner, 0, DimensionCount            >::apply(point, box);    }};template <typename Ring, typename Polygon, std::size_t DimensionCount>struct convert<Ring, Polygon, ring_tag, polygon_tag, DimensionCount, false>{    static inline void apply(Ring const& ring, Polygon& polygon)    {        typedef typename ring_type<Polygon>::type ring_type;        convert            <                Ring, ring_type,                ring_tag, ring_tag,                DimensionCount, false            >::apply(ring, exterior_ring(polygon));    }};template <typename Polygon, typename Ring, std::size_t DimensionCount>struct convert<Polygon, Ring, polygon_tag, ring_tag, DimensionCount, false>{    static inline void apply(Polygon const& polygon, Ring& ring)    {        typedef typename ring_type<Polygon>::type ring_type;        convert            <                ring_type, Ring,                ring_tag, ring_tag,                DimensionCount, false            >::apply(exterior_ring(polygon), ring);    }};// Dispatch for multi <-> multi, specifying their single-version as policy.// Note that, even if the multi-types are mutually different, their single// version types might be the same and therefore we call boost::is_same againtemplate <typename Multi1, typename Multi2, std::size_t DimensionCount>struct convert<Multi1, Multi2, multi_tag, multi_tag, DimensionCount, false>    : detail::conversion::multi_to_multi        <            Multi1,            Multi2,            convert                <                    typename boost::range_value<Multi1>::type,                    typename boost::range_value<Multi2>::type,                    typename single_tag_of                                <                                    typename tag<Multi1>::type                                >::type,                    typename single_tag_of                                <                                    typename tag<Multi2>::type                                >::type,                    DimensionCount                >        >{};template <typename Single, typename Multi, typename SingleTag, std::size_t DimensionCount>struct convert<Single, Multi, SingleTag, multi_tag, DimensionCount, false>    : detail::conversion::single_to_multi        <            Single,            Multi,            convert                <                    Single,                    typename boost::range_value<Multi>::type,                    typename tag<Single>::type,                    typename single_tag_of                                <                                    typename tag<Multi>::type                                >::type,                    DimensionCount,                    false                >        >{};} // namespace dispatch#endif // DOXYGEN_NO_DISPATCHnamespace resolve_variant {template <typename Geometry1, typename Geometry2>struct convert{    static inline void apply(Geometry1 const& geometry1, Geometry2& geometry2)    {        concepts::check_concepts_and_equal_dimensions<Geometry1 const, Geometry2>();        dispatch::convert<Geometry1, Geometry2>::apply(geometry1, geometry2);    }};template <BOOST_VARIANT_ENUM_PARAMS(typename T), typename Geometry2>struct convert<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Geometry2>{    struct visitor: static_visitor<void>    {        Geometry2& m_geometry2;        visitor(Geometry2& geometry2)            : m_geometry2(geometry2)        {}        template <typename Geometry1>        inline void operator()(Geometry1 const& geometry1) const        {            convert<Geometry1, Geometry2>::apply(geometry1, m_geometry2);        }    };    static inline void apply(        boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry1,        Geometry2& geometry2    )    {        boost::apply_visitor(visitor(geometry2), geometry1);    }};}/*!\brief Converts one geometry to another geometry\details The convert algorithm converts one geometry, e.g. a BOX, to anothergeometry, e.g. a RING. This only works if it is possible and applicable.If the point-order is different, or the closure is different between twogeometry types, it will be converted correctly by explicitly reversing thepoints or closing or opening the polygon rings.\ingroup convert\tparam Geometry1 \tparam_geometry\tparam Geometry2 \tparam_geometry\param geometry1 \param_geometry (source)\param geometry2 \param_geometry (target)\qbk{[include reference/algorithms/convert.qbk]} */template <typename Geometry1, typename Geometry2>inline void convert(Geometry1 const& geometry1, Geometry2& geometry2){    resolve_variant::convert<Geometry1, Geometry2>::apply(geometry1, geometry2);}#if defined(_MSC_VER)#pragma warning(pop)#endif}} // namespace boost::geometry#endif // BOOST_GEOMETRY_ALGORITHMS_CONVERT_HPP
 |