[distance] Use transform_variant

Remove dependency to is_implemented. Update transform_variant to support
MPL sequence input.
This commit is contained in:
Samuel Debione 2014-05-19 13:52:09 +02:00
parent 595f6fe457
commit 09a8ba53a7
7 changed files with 255 additions and 62 deletions

View File

@ -4,6 +4,7 @@
// Copyright (c) 2008-2014 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2014 Mateusz Loskot, London, UK.
// Copyright (c) 2013-2014 Adam Wulkiewicz, Lodz, Poland.
// Copyright (c) 2014 Samuel Debionne, Grenoble, France.
// This file was modified by Oracle on 2014.
// Modifications copyright (c) 2014, Oracle and/or its affiliates.
@ -43,7 +44,11 @@
#include <boost/geometry/util/compress_variant.hpp>
#include <boost/geometry/util/transform_variant.hpp>
#include <boost/geometry/util/combine_if.hpp>
#include <boost/geometry/util/is_implemented.hpp>
//#include <boost/geometry/util/is_implemented.hpp>
#include <boost/mpl/always.hpp>
#include <boost/mpl/bool.hpp>
#include <boost/mpl/vector.hpp>
namespace boost { namespace geometry
@ -166,30 +171,28 @@ struct distance
template <typename Geometry1, BOOST_VARIANT_ENUM_PARAMS(typename T), typename Strategy>
struct distance<Geometry1, variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Strategy>
{
// A set of of all variant type combinations that are compatible and implemented
typedef typename util::combine_if
<
typename mpl::vector1<Geometry1>,
typename variant<BOOST_VARIANT_ENUM_PARAMS(T)>::types,
util::is_compatible<mpl::_1, mpl::_2>
>::type possible_input_types;
// A set of all variant type combinations that are compatible and implemented
typedef typename util::combine_if<
typename mpl::vector1<Geometry1>,
typename variant<BOOST_VARIANT_ENUM_PARAMS(T)>::types,
// Here we want should remove most of the combinations that are not valid
// mostly to limit the size of the resulting MPL set.
// But is_implementedn is not ready for prime time
//
// util::is_implemented2<mpl::_1, mpl::_2, dispatch::distance<mpl::_1, mpl::_2> >
mpl::always<mpl::true_>
>::type possible_input_types;
// All possible results for these combinations
typedef typename mpl::transform<
possible_input_types,
resolve_strategy::result_of::distance
<
// The (possibly variant) result type resulting from these combinations
typedef typename compress_variant<
typename transform_variant<
possible_input_types,
resolve_strategy::result_of::distance<
point_type<mpl::first<mpl::_> >,
point_type<mpl::second<mpl::_> >,
Strategy
>,
mpl::back_inserter<mpl::vector0<> >
>::type possible_result_types;
// The (possibly variant) result type
typedef typename compress_variant<
typename make_variant_over<
possible_result_types
mpl::back_inserter<mpl::vector0<> >
>::type
>::type type;
};
@ -205,30 +208,29 @@ struct distance<variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Geometry2, Strategy>
template <BOOST_VARIANT_ENUM_PARAMS(typename T), typename Strategy>
struct distance<variant<BOOST_VARIANT_ENUM_PARAMS(T)>, variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Strategy>
{
// A set of of all variant type combinations that are compatible and implemented
// A set of all variant type combinations that are compatible and implemented
typedef typename util::combine_if
<
typename variant<BOOST_VARIANT_ENUM_PARAMS(T)>::types,
typename variant<BOOST_VARIANT_ENUM_PARAMS(T)>::types,
util::is_compatible<mpl::_1, mpl::_2>
// Here we want to try to remove most of the combinations that are not valid
// mostly to limit the size of the resulting MPL vector.
// But is_implementedn is not ready for prime time
//
// util::is_implemented2<mpl::_1, mpl::_2, dispatch::distance<mpl::_1, mpl::_2> >
mpl::always<mpl::true_>
>::type possible_input_types;
// All possible results for these combinations
typedef typename mpl::transform<
possible_input_types,
resolve_strategy::result_of::distance
<
// The (possibly variant) result type resulting from these combinations
typedef typename compress_variant<
typename transform_variant<
possible_input_types,
resolve_strategy::result_of::distance<
point_type<mpl::first<mpl::_> >,
point_type<mpl::second<mpl::_> >,
Strategy
>,
mpl::back_inserter<mpl::vector0<> >
>::type possible_result_types;
// The (possibly variant) result type
typedef typename compress_variant<
typename make_variant_over<
possible_result_types
mpl::back_inserter<mpl::vector0<> >
>::type
>::type type;
};

View File

@ -23,4 +23,4 @@
#include <boost/geometry/algorithms/detail/distance/interface.hpp>
#include <boost/geometry/algorithms/detail/distance/implementation.hpp>
#endif // BOOST_GEOMETRY_ALGORITHMS_DISTANCE_HPP
#endif // BOOST_GEOMETRY_ALGORITHMS_DISTANCE_HPP

View File

@ -15,18 +15,63 @@
#include <boost/mpl/and.hpp>
#include <boost/mpl/not.hpp>
#include <boost/type_traits/is_base_of.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/geometry/core/coordinate_system.hpp>
#include <boost/geometry/core/coordinate_dimension.hpp>
#include <boost/geometry/algorithms/not_implemented.hpp>
namespace boost { namespace geometry
{
namespace util
{
namespace detail
{
template <typename Geometry, typename Algorithm>
struct is_implemented1
: mpl::not_
<
typename is_base_of
<
nyi::not_implemented_tag,
//typename mpl::apply1<Algorithm, Geometry>::type
Algorithm
>::type
>
{};
template <typename Geometry1, typename Geometry2, typename Algorithm>
struct is_implemented2
: mpl::not_
<
typename is_base_of
<
nyi::not_implemented_tag,
//typename mpl::apply2<Algorithm, Geometry1, Geometry2>::type
Algorithm
>::type
>
{};
} // namespace detail
/*!
\brief Meta-function to check whether two geometry types
have the same dimensions and coordinate systems
\ingroup utility
*/
template <typename Geometry1, typename Geometry2>
struct is_same_dimension_and_coordinate_system
struct is_compatible2
: mpl::and_
<
typename is_same
@ -43,25 +88,33 @@ struct is_same_dimension_and_coordinate_system
{};
template <typename Geometry1, typename Geometry2>
struct is_implemented
: mpl::not_
/*!
\brief Meta-function to check whether an Unary Algorithm
is implemented for the given geometry types
\ingroup utility
*/
template <typename Geometry, typename Algorithm>
struct is_implemented1
: mpl::and_
<
typename is_base_of
<
nyi::not_implemented_tag,
geometry::dispatch::distance<Geometry1, Geometry2>
>::type
typename detail::is_implemented1<Geometry, Algorithm>::type
>
{};
template <typename Geometry1, typename Geometry2>
struct is_compatible
/*!
\brief Meta-function to check whether an Binary Algorithm
is implemented for the given geometry types
\ingroup utility
*/
template <typename Geometry1, typename Geometry2, typename Algorithm>
struct is_implemented2
: mpl::and_
<
typename is_same_dimension_and_coordinate_system<Geometry1, Geometry2>::type,
typename is_implemented<Geometry1, Geometry2>::type
// is_compatible is necessary because of some MPL_ASSERT
// shortcuting the not_implemented class when dimension / coordinate system differs
typename is_compatible2<Geometry1, Geometry2>::type,
typename detail::is_implemented2<Geometry1, Geometry2, Algorithm>::type
>
{};

View File

@ -23,10 +23,36 @@ namespace boost { namespace geometry
{
/*!
\brief Meta-function that takes a Sequence type, an MPL lambda
expression and an optional Inserter and returns a variant type over
the same types as the initial variant type, each transformed using
the lambda expression.
\ingroup utility
\par Example
\code
typedef mpl::vector<int, float, long> types;
typedef transform_variant<types, add_pointer<_> > transformed;
typedef variant<int*, float*, long*> result;
BOOST_MPL_ASSERT(( equal<result, transformed> ));
\endcode
*/
template <typename Sequence, typename Op, typename In = boost::mpl::na>
struct transform_variant:
make_variant_over<
typename mpl::transform<
Sequence,
Op,
In
>::type
>
{};
/*!
\brief Meta-function that takes a boost::variant type and an MPL lambda
expression and returns a variant type over the same types as the
initial variant type, each trasnformed using the lambda expression.
initial variant type, each transformed using the lambda expression.
\ingroup utility
\par Example
\code
@ -36,12 +62,11 @@ namespace boost { namespace geometry
BOOST_MPL_ASSERT(( equal<result, transformed> ));
\endcode
*/
template <typename Variant, typename Op>
struct transform_variant:
template <BOOST_VARIANT_ENUM_PARAMS(typename T), typename Op>
struct transform_variant<variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Op, boost::mpl::na> :
make_variant_over<
typename mpl::transform<
typename Variant::types,
typename variant<BOOST_VARIANT_ENUM_PARAMS(T)>::types,
Op
>::type
>

View File

@ -36,7 +36,6 @@
#include <boost/geometry/multi/geometries/multi_polygon.hpp>
#include <boost/geometry/multi/io/wkt/read.hpp>
// includes for variant
#include <boost/variant/variant.hpp>
BOOST_GEOMETRY_REGISTER_C_ARRAY_CS(cs::cartesian)
@ -363,7 +362,6 @@ void test_all()
test_geometry<P, test::wrapped_boost_array<P, 2> >("POINT(3 1)", "LINESTRING(1 1,4 4)", sqrt(2.0));
test_distance_linear<P, bg::model::linestring<P> >("POINT(3 1)", "LINESTRING(1 1,4 4)", sqrt(2.0));
}
template <typename P>
@ -439,7 +437,8 @@ void test_variant()
{
typedef bg::model::point<T, 2, bg::cs::cartesian> point_type;
typedef bg::model::segment<point_type> segment_type;
typedef boost::variant<point_type, segment_type> variant_type;
typedef bg::model::box<point_type> box_type;
typedef boost::variant<point_type, segment_type, box_type> variant_type;
point_type point;
std::string const point_li = "POINT(1 3)";
@ -451,9 +450,6 @@ void test_variant()
variant_type v1, v2;
v1 = point;
v2 = point;
BOOST_MPL_ASSERT((
boost::is_same
<
@ -462,6 +458,9 @@ void test_variant()
>
));
// Default strategy
v1 = point;
v2 = point;
BOOST_CHECK_CLOSE(bg::distance(v1, v2), bg::distance(point, point), 0.0001);
BOOST_CHECK_CLOSE(bg::distance(v1, point), bg::distance(point, point), 0.0001);
BOOST_CHECK_CLOSE(bg::distance(point, v2), bg::distance(point, point), 0.0001);
@ -470,6 +469,14 @@ void test_variant()
BOOST_CHECK_CLOSE(bg::distance(v1, v2), bg::distance(point, seg), 0.0001);
BOOST_CHECK_CLOSE(bg::distance(v1, seg), bg::distance(point, seg), 0.0001);
BOOST_CHECK_CLOSE(bg::distance(point, v2), bg::distance(point, seg), 0.0001);
// User defined strategy
v1 = point;
v2 = point;
bg::strategy::distance::haversine<double> s;
//BOOST_CHECK_CLOSE(bg::distance(v1, v2, s), bg::distance(point, point, s), 0.0001);
//BOOST_CHECK_CLOSE(bg::distance(v1, point, s), bg::distance(point, point, s), 0.0001);
//BOOST_CHECK_CLOSE(bg::distance(point, v2, s), bg::distance(point, point, s), 0.0001);
}
int test_main(int, char* [])

View File

@ -0,0 +1,88 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Unit Test
// Copyright (c) 2014 Samuel Debionne, Grenoble, France.
// 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)
#include <geometry_test_common.hpp>
#include <boost/geometry/core/reverse_dispatch.hpp>
#include <boost/geometry/core/tag_cast.hpp>
#include <boost/geometry/geometries/point_xy.hpp>
#include <boost/geometry/strategies/tags.hpp>
#include <boost/geometry/algorithms/not_implemented.hpp>
#include <boost/geometry/util/is_implemented.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/mpl/assert.hpp>
#include <boost/mpl/bool.hpp>
namespace boost { namespace geometry
{
namespace strategy { namespace services
{
template <typename Strategy> struct tag
{
typedef not_implemented type;
};
}} // namespace strategy::services
template
<
typename Geometry1, typename Geometry2,
typename Strategy,
typename Tag1 = typename tag_cast<typename tag<Geometry1>::type, multi_tag>::type,
typename Tag2 = typename tag_cast<typename tag<Geometry2>::type, multi_tag>::type,
typename StrategyTag = typename strategy::services::tag<Strategy>::type,
bool Reverse = reverse_dispatch<Geometry1, Geometry2>::type::value
>
struct algorithm_archetype
: not_implemented<>
{};
struct strategy_archetype
{
template <typename Geometry1, typename Geometry2>
static void apply(Geometry1, Geometry2) {}
};
}} // namespace boost::geometry
int test_main(int, char* [])
{
typedef bg::model::d2::point_xy<double> point_type;
BOOST_MPL_ASSERT((
boost::is_same<
bg::util::is_implemented2
<
point_type, point_type,
bg::algorithm_archetype<point_type, point_type, bg::strategy_archetype>
>::type,
boost::mpl::false_
>
));
return 0;
}

View File

@ -39,12 +39,30 @@ void check(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>)
int test_main(int, char* [])
{
typedef typename boost::geometry::transform_variant<
// Transform Variant to Variant
typedef boost::geometry::transform_variant<
boost::variant<int, float, long>,
boost::add_pointer<_>
>::type transformed;
>::type transformed1;
check<boost::mpl::vector<int*, float*, long*> >(transformed());
check<boost::mpl::vector<int*, float*, long*> >(transformed1());
// Transform Sequence to Variant (without inserter)
typedef boost::geometry::transform_variant<
boost::mpl::vector<int, float, long>,
boost::add_pointer<_>
>::type transformed2;
check<boost::mpl::vector<int*, float*, long*> >(transformed2());
// Transform Sequence to Variant (with inserter)
typedef boost::geometry::transform_variant<
boost::mpl::vector<int, float, long>,
boost::add_pointer<_>,
boost::mpl::back_inserter<boost::mpl::vector0<> >
>::type transformed3;
check<boost::mpl::vector<int*, float*, long*> >(transformed3());
return 0;
}