diff options
author | Chanho Park <chanho61.park@samsung.com> | 2014-12-11 18:55:56 +0900 |
---|---|---|
committer | Chanho Park <chanho61.park@samsung.com> | 2014-12-11 18:55:56 +0900 |
commit | 08c1e93fa36a49f49325a07fe91ff92c964c2b6c (patch) | |
tree | 7a7053ceb8874b28ec4b868d4c49b500008a102e /boost/geometry/algorithms/convert.hpp | |
parent | bb4dd8289b351fae6b55e303f189127a394a1edd (diff) | |
download | boost-08c1e93fa36a49f49325a07fe91ff92c964c2b6c.tar.gz boost-08c1e93fa36a49f49325a07fe91ff92c964c2b6c.tar.bz2 boost-08c1e93fa36a49f49325a07fe91ff92c964c2b6c.zip |
Imported Upstream version 1.57.0upstream/1.57.0
Diffstat (limited to 'boost/geometry/algorithms/convert.hpp')
-rw-r--r-- | boost/geometry/algorithms/convert.hpp | 201 |
1 files changed, 174 insertions, 27 deletions
diff --git a/boost/geometry/algorithms/convert.hpp b/boost/geometry/algorithms/convert.hpp index fbbf74c17f..914ef8f420 100644 --- a/boost/geometry/algorithms/convert.hpp +++ b/boost/geometry/algorithms/convert.hpp @@ -3,6 +3,7 @@ // 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. // Parts of Boost.Geometry are redesigned from Geodan's Geographic Library // (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands. @@ -20,6 +21,10 @@ #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/static_visitor.hpp> +#include <boost/variant/apply_visitor.hpp> +#include <boost/variant/variant_fwd.hpp> #include <boost/geometry/arithmetic/arithmetic.hpp> #include <boost/geometry/algorithms/not_implemented.hpp> @@ -31,19 +36,32 @@ #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_DETAIL namespace detail { namespace conversion { @@ -95,7 +113,7 @@ struct box_to_range assign_box_corners_oriented<Reverse>(box, range); if (Close) { - range[4] = range[0]; + range::at(range, 4) = range::at(range, 0); } } }; @@ -115,22 +133,22 @@ struct segment_to_range } }; -template +template < - typename Range1, - typename Range2, + typename Range1, + typename Range2, bool Reverse = false > struct range_to_range { typedef typename reversible_view < - Range1 const, + Range1 const, Reverse ? iterate_reverse : iterate_forward >::type rview_type; typedef typename closeable_view < - rview_type const, + rview_type const, geometry::closure<Range1>::value >::type view_type; @@ -144,13 +162,17 @@ struct range_to_range // point for open output. view_type view(rview); - int n = boost::size(view); + typedef typename boost::range_size<Range1>::type size_type; + size_type n = boost::size(view); if (geometry::closure<Range2>::value == geometry::open) { n--; } - int i = 0; + // 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; @@ -166,7 +188,7 @@ struct polygon_to_polygon { typedef range_to_range < - typename geometry::ring_type<Polygon1>::type, + typename geometry::ring_type<Polygon1>::type, typename geometry::ring_type<Polygon2>::type, geometry::point_order<Polygon1>::value != geometry::point_order<Polygon2>::value @@ -176,7 +198,7 @@ struct polygon_to_polygon { // Clearing managed per ring, and in the resizing of interior rings - per_ring::apply(geometry::exterior_ring(source), + per_ring::apply(geometry::exterior_ring(source), geometry::exterior_ring(destination)); // Container should be resizeable @@ -188,13 +210,15 @@ struct polygon_to_polygon >::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 interior_return_type<Polygon1 const>::type + rings_source = interior_rings(source); + typename interior_return_type<Polygon2>::type + rings_dest = interior_rings(destination); - BOOST_AUTO_TPL(it_source, boost::begin(rings_source)); - BOOST_AUTO_TPL(it_dest, boost::begin(rings_dest)); + 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) { @@ -203,6 +227,37 @@ struct polygon_to_polygon } }; +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 @@ -280,8 +335,8 @@ struct convert<Segment, LineString, segment_tag, linestring_tag, DimensionCount, 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, + < + Ring1, Ring2, geometry::point_order<Ring1>::value != geometry::point_order<Ring2>::value @@ -302,8 +357,8 @@ template <typename Box, typename Ring> struct convert<Box, Ring, box_tag, ring_tag, 2, false> : detail::conversion::box_to_range < - Box, - Ring, + Box, + Ring, geometry::closure<Ring>::value == closed, geometry::point_order<Ring>::value == counterclockwise > @@ -377,16 +432,108 @@ struct convert<Polygon, Ring, polygon_tag, ring_tag, DimensionCount, false> }; +// 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 again + +template <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_DISPATCH +namespace resolve_variant { + +template <typename Geometry1, typename Geometry2> +struct convert +{ + static inline void apply(Geometry1 const& geometry1, Geometry2& geometry2) + { + concept::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 + ) + { + apply_visitor(visitor(geometry2), geometry1); + } +}; + +} + + /*! \brief Converts one geometry to another geometry \details The convert algorithm converts one geometry, e.g. a BOX, to another -geometry, e.g. a RING. This only if it is possible and applicable. -If the point-order is different, or the closure is different between two -geometry types, it will be converted correctly by explicitly reversing the +geometry, 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 two +geometry types, it will be converted correctly by explicitly reversing the points or closing or opening the polygon rings. \ingroup convert \tparam Geometry1 \tparam_geometry @@ -399,13 +546,13 @@ points or closing or opening the polygon rings. template <typename Geometry1, typename Geometry2> inline void convert(Geometry1 const& geometry1, Geometry2& geometry2) { - concept::check_concepts_and_equal_dimensions<Geometry1 const, Geometry2>(); - - dispatch::convert<Geometry1, Geometry2>::apply(geometry1, 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 |