269 lines
7.1 KiB
C++
269 lines
7.1 KiB
C++
// 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
|