summaryrefslogtreecommitdiff
path: root/boost/geometry/algorithms/convert.hpp
diff options
context:
space:
mode:
authorChanho Park <chanho61.park@samsung.com>2014-12-11 18:55:56 +0900
committerChanho Park <chanho61.park@samsung.com>2014-12-11 18:55:56 +0900
commit08c1e93fa36a49f49325a07fe91ff92c964c2b6c (patch)
tree7a7053ceb8874b28ec4b868d4c49b500008a102e /boost/geometry/algorithms/convert.hpp
parentbb4dd8289b351fae6b55e303f189127a394a1edd (diff)
downloadboost-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.hpp201
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