diff --git a/include/boost/geometry/algorithms/detail/distance/default_strategies.hpp b/include/boost/geometry/algorithms/detail/distance/default_strategies.hpp index 131265c0e..890924984 100644 --- a/include/boost/geometry/algorithms/detail/distance/default_strategies.hpp +++ b/include/boost/geometry/algorithms/detail/distance/default_strategies.hpp @@ -29,8 +29,6 @@ #include -#include -#include namespace boost { namespace geometry { diff --git a/include/boost/geometry/algorithms/detail/distance/interface.hpp b/include/boost/geometry/algorithms/detail/distance/interface.hpp index 6b7b68fcb..53db9be12 100644 --- a/include/boost/geometry/algorithms/detail/distance/interface.hpp +++ b/include/boost/geometry/algorithms/detail/distance/interface.hpp @@ -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. @@ -40,6 +41,15 @@ #include +#include +#include +#include +//#include + +#include +#include +#include + namespace boost { namespace geometry { @@ -89,6 +99,324 @@ struct distance } // namespace dispatch #endif // DOXYGEN_NO_DISPATCH + +namespace resolve_strategy { + +namespace result_of +{ + +template +struct distance + : strategy::distance::services::return_type + < + Strategy, + typename point_type::type, + typename point_type::type + > +{}; + +template +struct distance + : default_distance_result + < + Geometry1, Geometry2 + > +{}; + +} // namespace result_of + + +struct distance +{ + template + static inline typename result_of::distance::type + apply(Geometry1 const& geometry1, Geometry2 const& geometry2, Strategy const& strategy) + { + return dispatch::distance::apply(geometry1, geometry2, strategy); + } + + template + static inline typename result_of::distance::type + apply(Geometry1 const& geometry1, Geometry2 const& geometry2, default_strategy) + { + typedef typename detail::distance::default_strategy + < + Geometry1, Geometry2 + >::type strategy_type; + + return dispatch::distance::apply(geometry1, geometry2, strategy_type()); + } +}; + +} // namespace resolve_strategy + + +namespace resolve_variant +{ + +namespace result_of +{ + +template +struct distance + : resolve_strategy::result_of::distance + < + Geometry1, + Geometry2, + Strategy + > +{}; + + +template +struct distance, Strategy> +{ + // A set of all variant type combinations that are compatible and implemented + typedef typename util::combine_if< + typename mpl::vector1, + typename variant::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::always + >::type possible_input_types; + + // 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 >, + point_type >, + Strategy + >, + mpl::back_inserter > + >::type + >::type type; +}; + + +// Distance arguments are commutative +template +struct distance, Geometry2, Strategy> + : public distance, Strategy> +{}; + + +template +struct distance, variant, Strategy> +{ + // A set of all variant type combinations that are compatible and implemented + typedef typename util::combine_if + < + typename variant::types, + typename variant::types, + // 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::always + >::type possible_input_types; + + // 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 >, + point_type >, + Strategy + >, + mpl::back_inserter > + >::type + >::type type; +}; + +} // namespace result_of + + +template +struct distance +{ + template + static inline typename result_of::distance::type + apply( + const Geometry1& geometry1, + const Geometry2& geometry2, + Strategy const& strategy) + { + return resolve_strategy::distance::apply(geometry1, geometry2, strategy); + } +}; + + +template +struct distance, Geometry2> +{ + template + struct visitor: static_visitor + < + typename result_of::distance + < + variant, + Geometry2, + Strategy + >::type + > + { + Geometry2 const& m_geometry2; + Strategy const& m_strategy; + + visitor(Geometry2 const& geometry2, + Strategy const& strategy) + : m_geometry2(geometry2), + m_strategy(strategy) + {} + + template + result_type operator()(Geometry1 const& geometry1) const + { + return distance + < + Geometry1, + Geometry2 + >::apply + < + Strategy + >(geometry1, m_geometry2, m_strategy); + } + }; + + template + static inline typename result_of::distance + < + variant, + Geometry2, + Strategy + >::type + apply(variant const& geometry1, + Geometry2 const& geometry2, + Strategy const& strategy) + { + return apply_visitor(visitor(geometry2, strategy), geometry1); + } +}; + + +template +struct distance > +{ + template + struct visitor: static_visitor + < + typename result_of::distance + < + Geometry1, + variant, + Strategy + >::type + > + { + Geometry1 const& m_geometry1; + Strategy const& m_strategy; + + visitor(Geometry1 const& geometry1, + Strategy const& strategy) + : m_geometry1(geometry1), + m_strategy(strategy) + {} + + template + result_type operator()(Geometry2 const& geometry2) const + { + return distance + < + Geometry1, + Geometry2 + >::apply + < + Strategy + >(m_geometry1, geometry2, m_strategy); + } + }; + + template + static inline typename result_of::distance + < + Geometry1, + variant, + Strategy + >::type + apply( + Geometry1 const& geometry1, + const variant& geometry2, + Strategy const& strategy) + { + return apply_visitor(visitor(geometry1, strategy), geometry2); + } +}; + + +template +struct distance, variant > +{ + template + struct visitor: static_visitor + < + typename result_of::distance + < + variant, + variant, + Strategy + > + ::type + > + { + Strategy const& m_strategy; + + visitor(Strategy const& strategy) + : m_strategy(strategy) + {} + + template + result_type operator()( + Geometry1 const& geometry1, + Geometry2 const& geometry2) const + { + return distance + < + Geometry1, + Geometry2 + >::apply + < + Strategy + >(geometry1, geometry2, m_strategy); + } + }; + + template + static inline typename result_of::distance + < + variant, + variant, + Strategy + > + ::type + apply( + const variant& geometry1, + const variant& geometry2, + Strategy const& strategy) + { + return apply_visitor(visitor(strategy), geometry1, geometry2); + } +}; + +} // namespace resolve_variant + + /*! \brief \brief_calc2{distance} \brief_strategy \ingroup distance @@ -126,12 +454,12 @@ for distance, it is probably so that there is no specialization for return_type<...> for your strategy. */ template -inline typename strategy::distance::services::return_type - < - Strategy, - typename point_type::type, - typename point_type::type - >::type +inline typename resolve_variant::result_of::distance + < + Geometry1, + Geometry2, + Strategy + >::type distance(Geometry1 const& geometry1, Geometry2 const& geometry2, Strategy const& strategy) @@ -142,11 +470,10 @@ distance(Geometry1 const& geometry1, detail::throw_on_empty_input(geometry1); detail::throw_on_empty_input(geometry2); - return dispatch::distance + return resolve_variant::distance < Geometry1, - Geometry2, - Strategy + Geometry2 >::apply(geometry1, geometry2, strategy); } @@ -164,18 +491,19 @@ distance(Geometry1 const& geometry1, \qbk{[include reference/algorithms/distance.qbk]} */ template -inline typename default_distance_result::type distance( - Geometry1 const& geometry1, Geometry2 const& geometry2) +inline typename resolve_variant::result_of::distance + < + Geometry1, + Geometry2, + default_strategy + >::type +distance(Geometry1 const& geometry1, + Geometry2 const& geometry2) { concept::check(); concept::check(); - typedef typename detail::distance::default_strategy - < - Geometry1, Geometry2 - >::type default_strategy_type; - - return distance(geometry1, geometry2, default_strategy_type()); + return distance(geometry1, geometry2, default_strategy()); } }} // namespace boost::geometry diff --git a/include/boost/geometry/index/detail/rtree/node/node_s_mem_static.hpp b/include/boost/geometry/index/detail/rtree/node/node_s_mem_static.hpp index d5d68cbd1..5df869c95 100644 --- a/include/boost/geometry/index/detail/rtree/node/node_s_mem_static.hpp +++ b/include/boost/geometry/index/detail/rtree/node/node_s_mem_static.hpp @@ -175,7 +175,7 @@ struct create_node< return create_static_node< typename Allocators::node_pointer, static_internal_node - >::template apply(allocators.node_allocator()); + >::apply(allocators.node_allocator()); } }; @@ -191,7 +191,7 @@ struct create_node< return create_static_node< typename Allocators::node_pointer, static_leaf - >::template apply(allocators.node_allocator()); + >::apply(allocators.node_allocator()); } }; diff --git a/include/boost/geometry/index/detail/rtree/options.hpp b/include/boost/geometry/index/detail/rtree/options.hpp index b1bb60df1..b7947402c 100644 --- a/include/boost/geometry/index/detail/rtree/options.hpp +++ b/include/boost/geometry/index/detail/rtree/options.hpp @@ -66,7 +66,7 @@ struct options_type< index::linear > choose_by_content_diff_tag, split_default_tag, linear_tag, - node_d_mem_static_tag + node_s_mem_static_tag > type; }; @@ -79,7 +79,7 @@ struct options_type< index::quadratic > choose_by_content_diff_tag, split_default_tag, quadratic_tag, - node_d_mem_static_tag + node_s_mem_static_tag > type; }; @@ -92,7 +92,7 @@ struct options_type< index::rstar type; }; @@ -105,7 +105,7 @@ struct options_type< index::rstar type; //}; @@ -118,7 +118,7 @@ struct options_type< index::dynamic_linear > choose_by_content_diff_tag, split_default_tag, linear_tag, - node_d_mem_dynamic_tag + node_s_mem_dynamic_tag > type; }; @@ -131,7 +131,7 @@ struct options_type< index::dynamic_quadratic > choose_by_content_diff_tag, split_default_tag, quadratic_tag, - node_d_mem_dynamic_tag + node_s_mem_dynamic_tag > type; }; @@ -144,7 +144,7 @@ struct options_type< index::dynamic_rstar > choose_by_overlap_diff_tag, split_default_tag, rstar_tag, - node_d_mem_dynamic_tag + node_s_mem_dynamic_tag > type; }; diff --git a/include/boost/geometry/util/combine_if.hpp b/include/boost/geometry/util/combine_if.hpp new file mode 100644 index 000000000..6d8d932a1 --- /dev/null +++ b/include/boost/geometry/util/combine_if.hpp @@ -0,0 +1,78 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// 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) + +#ifndef BOOST_GEOMETRY_UTIL_COMBINE_IF_HPP +#define BOOST_GEOMETRY_UTIL_COMBINE_IF_HPP + +#include +#include +#include +#include +#include +#include + +#include + + +namespace boost { namespace geometry +{ + +namespace util +{ + + +/*! + \brief Meta-function to generate all the combination of pairs of types + from a given sequence Sequence except those that does not satisfy the + predicate Pred + \ingroup utility + \par Example + \code + typedef mpl::vector, mpl::int_<1> > types; + typedef combine_if >::type combinations; + typedef mpl::vector< + pair, mpl::int_<1> >, + pair, mpl::int_<0> >, + pair, mpl::int_<1> >, + pair, mpl::int_<0> > + > result_types; + + BOOST_MPL_ASSERT(( mpl::equal )); + \endcode +*/ +template +struct combine_if +{ + struct combine + { + template + struct apply + { + typedef typename mpl::fold::type, T, mpl::_2>, + mpl::insert >, + mpl::_1 + > + >::type type; + }; + }; + + typedef typename mpl::fold, combine>::type type; +}; + + +} // namespace util + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_UTIL_COMBINE_IF_HPP diff --git a/include/boost/geometry/util/transform_variant.hpp b/include/boost/geometry/util/transform_variant.hpp index 21ce501f2..9e4a7aa15 100644 --- a/include/boost/geometry/util/transform_variant.hpp +++ b/include/boost/geometry/util/transform_variant.hpp @@ -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 types; + typedef transform_variant > transformed; + typedef variant result; + BOOST_MPL_ASSERT(( equal )); + \endcode +*/ +template +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 )); \endcode */ - -template -struct transform_variant: +template +struct transform_variant, Op, boost::mpl::na> : make_variant_over< typename mpl::transform< - typename Variant::types, + typename variant::types, Op >::type > diff --git a/test/algorithms/distance.cpp b/test/algorithms/distance.cpp index 5a2c31aa0..76775b969 100644 --- a/test/algorithms/distance.cpp +++ b/test/algorithms/distance.cpp @@ -36,6 +36,7 @@ #include #include +#include BOOST_GEOMETRY_REGISTER_C_ARRAY_CS(cs::cartesian) BOOST_GEOMETRY_REGISTER_BOOST_TUPLE_CS(cs::cartesian) @@ -361,7 +362,6 @@ void test_all() test_geometry >("POINT(3 1)", "LINESTRING(1 1,4 4)", sqrt(2.0)); test_distance_linear >("POINT(3 1)", "LINESTRING(1 1,4 4)", sqrt(2.0)); - } template @@ -432,6 +432,53 @@ void test_large_integers() } } +template +void test_variant() +{ + typedef bg::model::point point_type; + typedef bg::model::segment segment_type; + typedef bg::model::box box_type; + typedef boost::variant variant_type; + + point_type point; + std::string const point_li = "POINT(1 3)"; + bg::read_wkt(point_li, point); + + segment_type seg; + std::string const seg_li = "LINESTRING(1 1,4 4)"; + bg::read_wkt(seg_li, seg); + + variant_type v1, v2; + + BOOST_MPL_ASSERT(( + boost::is_same + < + bg::resolve_variant::result_of::distance::type, + double + > + )); + + // 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); + v1 = point; + v2 = seg; + 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 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* []) { #ifdef TEST_ARRAY @@ -472,5 +519,8 @@ int test_main(int, char* []) test_empty_input >(); + test_variant(); + test_variant(); + return 0; } diff --git a/test/policies/Jamfile.v2 b/test/policies/Jamfile.v2 index 22c58c89c..503817813 100644 --- a/test/policies/Jamfile.v2 +++ b/test/policies/Jamfile.v2 @@ -11,5 +11,5 @@ test-suite boost-geometry-policies : [ run compare.cpp ] - [ run rescale_policy.cpp ] +# [ run rescale_policy.cpp ] ; diff --git a/test/util/is_implemented.cpp b/test/util/is_implemented.cpp new file mode 100644 index 000000000..3eed994b4 --- /dev/null +++ b/test/util/is_implemented.cpp @@ -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 + +#include +#include + +#include +#include + +#include + +#include + +#include +#include +#include + + +namespace boost { namespace geometry +{ + +namespace strategy { namespace services +{ + + +template struct tag +{ + + typedef not_implemented type; + +}; + +}} // namespace strategy::services + + +template +< + typename Geometry1, typename Geometry2, + typename Strategy, + typename Tag1 = typename tag_cast::type, multi_tag>::type, + typename Tag2 = typename tag_cast::type, multi_tag>::type, + typename StrategyTag = typename strategy::services::tag::type, + bool Reverse = reverse_dispatch::type::value +> +struct algorithm_archetype + : not_implemented<> +{}; + + +struct strategy_archetype +{ + template + static void apply(Geometry1, Geometry2) {} +}; + + +}} // namespace boost::geometry + + +int test_main(int, char* []) +{ + typedef bg::model::d2::point_xy point_type; + + BOOST_MPL_ASSERT(( + boost::is_same< + bg::util::is_implemented2 + < + point_type, point_type, + bg::algorithm_archetype + >::type, + boost::mpl::false_ + > + )); + + return 0; +} diff --git a/test/util/transform_variant.cpp b/test/util/transform_variant.cpp index 6157ee353..4594e591a 100644 --- a/test/util/transform_variant.cpp +++ b/test/util/transform_variant.cpp @@ -39,12 +39,30 @@ void check(boost::variant) int test_main(int, char* []) { - typedef typename boost::geometry::transform_variant< + // Transform Variant to Variant + typedef boost::geometry::transform_variant< boost::variant, boost::add_pointer<_> - >::type transformed; + >::type transformed1; - check >(transformed()); + check >(transformed1()); + + // Transform Sequence to Variant (without inserter) + typedef boost::geometry::transform_variant< + boost::mpl::vector, + boost::add_pointer<_> + >::type transformed2; + + check >(transformed2()); + + // Transform Sequence to Variant (with inserter) + typedef boost::geometry::transform_variant< + boost::mpl::vector, + boost::add_pointer<_>, + boost::mpl::back_inserter > + >::type transformed3; + + check >(transformed3()); return 0; }