blob: a29ad635806d4e853977dae471434450f23e4aec [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_STRATEGIES_CONCEPTS_DISTANCE_CONCEPT_HPP
#define BOOST_GEOMETRY_STRATEGIES_CONCEPTS_DISTANCE_CONCEPT_HPP
#include <vector>
#include <iterator>
#include <boost/concept_check.hpp>
#include <boost/function_types/function_arity.hpp>
#include <boost/function_types/is_member_function_pointer.hpp>
#include <boost/function_types/parameter_types.hpp>
#include <boost/mpl/at.hpp>
#include <boost/mpl/int.hpp>
#include <boost/mpl/plus.hpp>
#include <boost/type_traits.hpp>
#include <boost/geometry/geometries/concepts/point_concept.hpp>
#include <boost/geometry/geometries/segment.hpp>
namespace boost { namespace geometry { namespace concept
{
/*!
\brief Checks strategy for point-segment-distance
\ingroup distance
*/
template <typename Strategy>
struct PointDistanceStrategy
{
#ifndef DOXYGEN_NO_CONCEPT_MEMBERS
private :
struct checker
{
template <typename ApplyMethod>
static void apply(ApplyMethod const&)
{
namespace ft = boost::function_types;
typedef typename ft::parameter_types
<
ApplyMethod
>::type parameter_types;
typedef typename boost::mpl::if_
<
ft::is_member_function_pointer<ApplyMethod>,
boost::mpl::int_<1>,
boost::mpl::int_<0>
>::type base_index;
// 1: inspect and define both arguments of apply
typedef typename boost::remove_reference
<
typename boost::mpl::at
<
parameter_types,
base_index
>::type
>::type ptype1;
typedef typename boost::remove_reference
<
typename boost::mpl::at
<
parameter_types,
typename boost::mpl::plus
<
base_index,
boost::mpl::int_<1>
>::type
>::type
>::type ptype2;
// 2) check if apply-arguments fulfill point concept
BOOST_CONCEPT_ASSERT
(
(concept::ConstPoint<ptype1>)
);
BOOST_CONCEPT_ASSERT
(
(concept::ConstPoint<ptype2>)
);
// 3) must define meta-function return_type
typedef typename strategy::distance::services::return_type<Strategy>::type rtype;
// 4) must define meta-function "similar_type"
typedef typename strategy::distance::services::similar_type
<
Strategy, ptype2, ptype1
>::type stype;
// 5) must define meta-function "comparable_type"
typedef typename strategy::distance::services::comparable_type
<
Strategy
>::type ctype;
// 6) must define meta-function "tag"
typedef typename strategy::distance::services::tag
<
Strategy
>::type tag;
// 7) must implement apply with arguments
Strategy* str;
ptype1 *p1;
ptype2 *p2;
rtype r = str->apply(*p1, *p2);
// 8) must define (meta)struct "get_similar" with apply
stype s = strategy::distance::services::get_similar
<
Strategy,
ptype2, ptype1
>::apply(*str);
// 9) must define (meta)struct "get_comparable" with apply
ctype c = strategy::distance::services::get_comparable
<
Strategy
>::apply(*str);
// 10) must define (meta)struct "result_from_distance" with apply
r = strategy::distance::services::result_from_distance
<
Strategy
>::apply(*str, 1.0);
boost::ignore_unused_variable_warning(str);
boost::ignore_unused_variable_warning(s);
boost::ignore_unused_variable_warning(c);
boost::ignore_unused_variable_warning(r);
}
};
public :
BOOST_CONCEPT_USAGE(PointDistanceStrategy)
{
checker::apply(&Strategy::apply);
}
#endif
};
/*!
\brief Checks strategy for point-segment-distance
\ingroup strategy_concepts
*/
template <typename Strategy>
struct PointSegmentDistanceStrategy
{
#ifndef DOXYGEN_NO_CONCEPT_MEMBERS
private :
struct checker
{
template <typename ApplyMethod>
static void apply(ApplyMethod const&)
{
namespace ft = boost::function_types;
typedef typename ft::parameter_types
<
ApplyMethod
>::type parameter_types;
typedef typename boost::mpl::if_
<
ft::is_member_function_pointer<ApplyMethod>,
boost::mpl::int_<1>,
boost::mpl::int_<0>
>::type base_index;
// 1: inspect and define both arguments of apply
typedef typename boost::remove_reference
<
typename boost::mpl::at
<
parameter_types,
base_index
>::type
>::type ptype;
typedef typename boost::remove_reference
<
typename boost::mpl::at
<
parameter_types,
typename boost::mpl::plus
<
base_index,
boost::mpl::int_<1>
>::type
>::type
>::type sptype;
// 2) check if apply-arguments fulfill point concept
BOOST_CONCEPT_ASSERT
(
(concept::ConstPoint<ptype>)
);
BOOST_CONCEPT_ASSERT
(
(concept::ConstPoint<sptype>)
);
// 3) must define meta-function return_type
typedef typename strategy::distance::services::return_type<Strategy>::type rtype;
// 4) must define underlying point-distance-strategy
typedef typename strategy::distance::services::strategy_point_point<Strategy>::type stype;
BOOST_CONCEPT_ASSERT
(
(concept::PointDistanceStrategy<stype>)
);
Strategy *str;
ptype *p;
sptype *sp1;
sptype *sp2;
rtype r = str->apply(*p, *sp1, *sp2);
boost::ignore_unused_variable_warning(str);
boost::ignore_unused_variable_warning(r);
}
};
public :
BOOST_CONCEPT_USAGE(PointSegmentDistanceStrategy)
{
checker::apply(&Strategy::apply);
}
#endif
};
}}} // namespace boost::geometry::concept
#endif // BOOST_GEOMETRY_STRATEGIES_CONCEPTS_DISTANCE_CONCEPT_HPP