blob: b90e008c1d9c9a248799d1c91f5942688d920234 [file] [log] [blame]
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2007-2011 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2008-2011 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2011 Mateusz Loskot, London, UK.
// 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_DETAIL_CONVERT_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_CONVERT_HPP
#include <cstddef>
#include <boost/numeric/conversion/cast.hpp>
#include <boost/range.hpp>
#include <boost/geometry/arithmetic/arithmetic.hpp>
#include <boost/geometry/algorithms/append.hpp>
#include <boost/geometry/algorithms/clear.hpp>
#include <boost/geometry/algorithms/for_each.hpp>
#include <boost/geometry/algorithms/detail/assign_values.hpp>
#include <boost/geometry/algorithms/detail/convert_point_to_point.hpp>
#include <boost/geometry/core/cs.hpp>
#include <boost/geometry/geometries/concepts/check.hpp>
namespace boost { namespace geometry
{
#ifndef DOXYGEN_NO_DETAIL
namespace 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& )
{}
};
}} // namespace detail::conversion
#endif // DOXYGEN_NO_DETAIL
#ifndef DOXYGEN_NO_DISPATCH
namespace dispatch
{
template
<
typename Tag1, typename Tag2,
std::size_t DimensionCount,
typename Geometry1, typename Geometry2
>
struct convert
{
};
template
<
typename Tag,
std::size_t DimensionCount,
typename Geometry1, typename Geometry2
>
struct convert<Tag, Tag, DimensionCount, Geometry1, Geometry2>
{
// Same geometry type -> copy coordinates from G1 to G2
// Actually: we try now to just copy it
static inline void apply(Geometry1 const& source, Geometry2& destination)
{
destination = source;
}
};
template
<
std::size_t DimensionCount,
typename Geometry1, typename Geometry2
>
struct convert<point_tag, point_tag, DimensionCount, Geometry1, Geometry2>
: detail::conversion::point_to_point<Geometry1, Geometry2, 0, DimensionCount>
{};
template <std::size_t DimensionCount, typename Ring1, typename Ring2>
struct convert<ring_tag, ring_tag, DimensionCount, Ring1, Ring2>
{
static inline void apply(Ring1 const& source, Ring2& destination)
{
geometry::clear(destination);
for (typename boost::range_iterator<Ring1 const>::type it
= boost::begin(source);
it != boost::end(source);
++it)
{
geometry::append(destination, *it);
}
}
};
template <typename Box, typename Ring>
struct convert<box_tag, ring_tag, 2, Box, Ring>
{
static inline void apply(Box const& box, Ring& ring)
{
// go from box to ring -> add coordinates in correct order
geometry::clear(ring);
typename point_type<Box>::type point;
geometry::assign_values(point, get<min_corner, 0>(box), get<min_corner, 1>(box));
geometry::append(ring, point);
geometry::assign_values(point, get<min_corner, 0>(box), get<max_corner, 1>(box));
geometry::append(ring, point);
geometry::assign_values(point, get<max_corner, 0>(box), get<max_corner, 1>(box));
geometry::append(ring, point);
geometry::assign_values(point, get<max_corner, 0>(box), get<min_corner, 1>(box));
geometry::append(ring, point);
geometry::assign_values(point, get<min_corner, 0>(box), get<min_corner, 1>(box));
geometry::append(ring, point);
}
};
template <typename Box, typename Polygon>
struct convert<box_tag, polygon_tag, 2, Box, Polygon>
{
static inline void apply(Box const& box, Polygon& polygon)
{
typedef typename ring_type<Polygon>::type ring_type;
convert
<
box_tag, ring_tag,
2, Box, ring_type
>::apply(box, exterior_ring(polygon));
}
};
template <typename Point, std::size_t DimensionCount, typename Box>
struct convert<point_tag, box_tag, DimensionCount, Point, Box>
{
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, std::size_t DimensionCount, typename Polygon>
struct convert<ring_tag, polygon_tag, DimensionCount, Ring, Polygon>
{
static inline void apply(Ring const& ring, Polygon& polygon)
{
typedef typename ring_type<Polygon>::type ring_type;
convert
<
ring_tag, ring_tag, DimensionCount,
Ring, ring_type
>::apply(ring, exterior_ring(polygon));
}
};
template <typename Polygon, std::size_t DimensionCount, typename Ring>
struct convert<polygon_tag, ring_tag, DimensionCount, Polygon, Ring>
{
static inline void apply(Polygon const& polygon, Ring& ring)
{
typedef typename ring_type<Polygon>::type ring_type;
convert
<
ring_tag, ring_tag, DimensionCount,
ring_type, Ring
>::apply(exterior_ring(polygon), ring);
}
};
} // namespace dispatch
#endif // DOXYGEN_NO_DISPATCH
/*!
\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.
\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)
{
concept::check_concepts_and_equal_dimensions<Geometry1 const, Geometry2>();
dispatch::convert
<
typename tag<Geometry1>::type,
typename tag<Geometry2>::type,
dimension<Geometry1>::type::value,
Geometry1,
Geometry2
>::apply(geometry1, geometry2);
}
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_CONVERT_HPP