boost/geometry/core/access.hpp
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
// Copyright (c) 2008-2012 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2009-2012 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_CORE_ACCESS_HPP
#define BOOST_GEOMETRY_CORE_ACCESS_HPP
#include <cstddef>
#include <boost/core/ignore_unused.hpp>
#include <boost/mpl/assert.hpp>
#include <boost/type_traits/is_pointer.hpp>
#include <boost/type_traits/remove_pointer.hpp>
#include <boost/geometry/core/coordinate_type.hpp>
#include <boost/geometry/core/point_type.hpp>
#include <boost/geometry/core/tag.hpp>
#include <boost/geometry/util/bare_type.hpp>
namespace boost { namespace geometry
{
/// Index of minimum corner of the box.
int const min_corner = 0;
/// Index of maximum corner of the box.
int const max_corner = 1;
namespace traits
{
/*!
\brief Traits class which gives access (get,set) to points.
\ingroup traits
\par Geometries:
/// @li point
\par Specializations should provide, per Dimension
/// @li static inline T get(G const&)
/// @li static inline void set(G&, T const&)
\tparam Geometry geometry-type
\tparam Dimension dimension to access
*/
template <typename Geometry, std::size_t Dimension, typename Enable = void>
struct access
{
BOOST_MPL_ASSERT_MSG
(
false, NOT_IMPLEMENTED_FOR_THIS_POINT_TYPE, (types<Geometry>)
);
};
/*!
\brief Traits class defining "get" and "set" to get
and set point coordinate values
\tparam Geometry geometry (box, segment)
\tparam Index index (min_corner/max_corner for box, 0/1 for segment)
\tparam Dimension dimension
\par Geometries:
- box
- segment
\par Specializations should provide:
- static inline T get(G const&)
- static inline void set(G&, T const&)
\ingroup traits
*/
template <typename Geometry, std::size_t Index, std::size_t Dimension>
struct indexed_access {};
} // namespace traits
#ifndef DOXYGEN_NO_DETAIL
namespace detail
{
template
<
typename Geometry,
typename CoordinateType,
std::size_t Index,
std::size_t Dimension
>
struct indexed_access_non_pointer
{
static inline CoordinateType get(Geometry const& geometry)
{
return traits::indexed_access<Geometry, Index, Dimension>::get(geometry);
}
static inline void set(Geometry& b, CoordinateType const& value)
{
traits::indexed_access<Geometry, Index, Dimension>::set(b, value);
}
};
template
<
typename Geometry,
typename CoordinateType,
std::size_t Index,
std::size_t Dimension
>
struct indexed_access_pointer
{
static inline CoordinateType get(Geometry const* geometry)
{
return traits::indexed_access<typename boost::remove_pointer<Geometry>::type, Index, Dimension>::get(*geometry);
}
static inline void set(Geometry* geometry, CoordinateType const& value)
{
traits::indexed_access<typename boost::remove_pointer<Geometry>::type, Index, Dimension>::set(*geometry, value);
}
};
} // namespace detail
#endif // DOXYGEN_NO_DETAIL
#ifndef DOXYGEN_NO_DISPATCH
namespace core_dispatch
{
template
<
typename Tag,
typename Geometry,
typename
CoordinateType,
std::size_t Dimension,
typename IsPointer
>
struct access
{
//static inline T get(G const&) {}
//static inline void set(G& g, T const& value) {}
};
template
<
typename Tag,
typename Geometry,
typename CoordinateType,
std::size_t Index,
std::size_t Dimension,
typename IsPointer
>
struct indexed_access
{
//static inline T get(G const&) {}
//static inline void set(G& g, T const& value) {}
};
template <typename Point, typename CoordinateType, std::size_t Dimension>
struct access<point_tag, Point, CoordinateType, Dimension, boost::false_type>
{
static inline CoordinateType get(Point const& point)
{
return traits::access<Point, Dimension>::get(point);
}
static inline void set(Point& p, CoordinateType const& value)
{
traits::access<Point, Dimension>::set(p, value);
}
};
template <typename Point, typename CoordinateType, std::size_t Dimension>
struct access<point_tag, Point, CoordinateType, Dimension, boost::true_type>
{
static inline CoordinateType get(Point const* point)
{
return traits::access<typename boost::remove_pointer<Point>::type, Dimension>::get(*point);
}
static inline void set(Point* p, CoordinateType const& value)
{
traits::access<typename boost::remove_pointer<Point>::type, Dimension>::set(*p, value);
}
};
template
<
typename Box,
typename CoordinateType,
std::size_t Index,
std::size_t Dimension
>
struct indexed_access<box_tag, Box, CoordinateType, Index, Dimension, boost::false_type>
: detail::indexed_access_non_pointer<Box, CoordinateType, Index, Dimension>
{};
template
<
typename Box,
typename CoordinateType,
std::size_t Index,
std::size_t Dimension
>
struct indexed_access<box_tag, Box, CoordinateType, Index, Dimension, boost::true_type>
: detail::indexed_access_pointer<Box, CoordinateType, Index, Dimension>
{};
template
<
typename Segment,
typename CoordinateType,
std::size_t Index,
std::size_t Dimension
>
struct indexed_access<segment_tag, Segment, CoordinateType, Index, Dimension, boost::false_type>
: detail::indexed_access_non_pointer<Segment, CoordinateType, Index, Dimension>
{};
template
<
typename Segment,
typename CoordinateType,
std::size_t Index,
std::size_t Dimension
>
struct indexed_access<segment_tag, Segment, CoordinateType, Index, Dimension, boost::true_type>
: detail::indexed_access_pointer<Segment, CoordinateType, Index, Dimension>
{};
} // namespace core_dispatch
#endif // DOXYGEN_NO_DISPATCH
#ifndef DOXYGEN_NO_DETAIL
namespace detail
{
// Two dummy tags to distinguish get/set variants below.
// They don't have to be specified by the user. The functions are distinguished
// by template signature also, but for e.g. GCC this is not enough. So give them
// a different signature.
struct signature_getset_dimension {};
struct signature_getset_index_dimension {};
} // namespace detail
#endif // DOXYGEN_NO_DETAIL
/*!
\brief Get coordinate value of a geometry (usually a point)
\details \details_get_set
\ingroup get
\tparam Dimension \tparam_dimension_required
\tparam Geometry \tparam_geometry (usually a Point Concept)
\param geometry \param_geometry (usually a point)
\return The coordinate value of specified dimension of specified geometry
\qbk{[include reference/core/get_point.qbk]}
*/
template <std::size_t Dimension, typename Geometry>
inline typename coordinate_type<Geometry>::type get(Geometry const& geometry
#ifndef DOXYGEN_SHOULD_SKIP_THIS
, detail::signature_getset_dimension* dummy = 0
#endif
)
{
boost::ignore_unused(dummy);
typedef core_dispatch::access
<
typename tag<Geometry>::type,
typename geometry::util::bare_type<Geometry>::type,
typename coordinate_type<Geometry>::type,
Dimension,
typename boost::is_pointer<Geometry>::type
> coord_access_type;
return coord_access_type::get(geometry);
}
/*!
\brief Set coordinate value of a geometry (usually a point)
\details \details_get_set
\tparam Dimension \tparam_dimension_required
\tparam Geometry \tparam_geometry (usually a Point Concept)
\param geometry geometry to assign coordinate to
\param geometry \param_geometry (usually a point)
\param value The coordinate value to set
\ingroup set
\qbk{[include reference/core/set_point.qbk]}
*/
template <std::size_t Dimension, typename Geometry>
inline void set(Geometry& geometry
, typename coordinate_type<Geometry>::type const& value
#ifndef DOXYGEN_SHOULD_SKIP_THIS
, detail::signature_getset_dimension* dummy = 0
#endif
)
{
boost::ignore_unused(dummy);
typedef core_dispatch::access
<
typename tag<Geometry>::type,
typename geometry::util::bare_type<Geometry>::type,
typename coordinate_type<Geometry>::type,
Dimension,
typename boost::is_pointer<Geometry>::type
> coord_access_type;
coord_access_type::set(geometry, value);
}
/*!
\brief get coordinate value of a Box or Segment
\details \details_get_set
\tparam Index \tparam_index_required
\tparam Dimension \tparam_dimension_required
\tparam Geometry \tparam_box_or_segment
\param geometry \param_geometry
\return coordinate value
\ingroup get
\qbk{distinguish,with index}
\qbk{[include reference/core/get_box.qbk]}
*/
template <std::size_t Index, std::size_t Dimension, typename Geometry>
inline typename coordinate_type<Geometry>::type get(Geometry const& geometry
#ifndef DOXYGEN_SHOULD_SKIP_THIS
, detail::signature_getset_index_dimension* dummy = 0
#endif
)
{
boost::ignore_unused(dummy);
typedef core_dispatch::indexed_access
<
typename tag<Geometry>::type,
typename geometry::util::bare_type<Geometry>::type,
typename coordinate_type<Geometry>::type,
Index,
Dimension,
typename boost::is_pointer<Geometry>::type
> coord_access_type;
return coord_access_type::get(geometry);
}
/*!
\brief set coordinate value of a Box / Segment
\details \details_get_set
\tparam Index \tparam_index_required
\tparam Dimension \tparam_dimension_required
\tparam Geometry \tparam_box_or_segment
\param geometry geometry to assign coordinate to
\param geometry \param_geometry
\param value The coordinate value to set
\ingroup set
\qbk{distinguish,with index}
\qbk{[include reference/core/set_box.qbk]}
*/
template <std::size_t Index, std::size_t Dimension, typename Geometry>
inline void set(Geometry& geometry
, typename coordinate_type<Geometry>::type const& value
#ifndef DOXYGEN_SHOULD_SKIP_THIS
, detail::signature_getset_index_dimension* dummy = 0
#endif
)
{
boost::ignore_unused(dummy);
typedef core_dispatch::indexed_access
<
typename tag<Geometry>::type,
typename geometry::util::bare_type<Geometry>::type,
typename coordinate_type<Geometry>::type,
Index,
Dimension,
typename boost::is_pointer<Geometry>::type
> coord_access_type;
coord_access_type::set(geometry, value);
}
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_CORE_ACCESS_HPP