diff --git a/include/boost/geometry/algorithms/is_not_implemented.hpp b/include/boost/geometry/algorithms/is_not_implemented.hpp new file mode 100644 index 0000000000..6b36268171 --- /dev/null +++ b/include/boost/geometry/algorithms/is_not_implemented.hpp @@ -0,0 +1,190 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2015, Oracle and/or its affiliates. + +// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle + +// 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_IS_NOT_IMPLEMENTED_HPP +#define BOOST_GEOMETRY_ALGORITHMS_IS_NOT_IMPLEMENTED_HPP + + +#include +#include +#include +#include +#include +#include + +#include + + +namespace boost { namespace geometry { + +namespace detail { namespace is_not_implemented { + +template +< + typename Seq, + typename MetaPred, + typename PrevState, + typename First = typename boost::mpl::begin::type, + typename Last = typename boost::mpl::end::type +> +struct for_each +{ + typedef typename for_each + < + Seq, + MetaPred, + typename MetaPred::template apply + < + typename boost::mpl::deref::type, + PrevState + >, + typename boost::mpl::next::type, + Last + >::type type; +}; + +template +< + typename Seq, + typename MetaPred, + typename PrevState, + typename Last +> +struct for_each +{ + typedef PrevState type; +}; + +template +struct reverse +{ + template + struct apply + : MetaPolicy::template apply + {}; +}; + +template +struct metapred +{ + template + struct apply + : boost::mpl::bool_ + < + PrevState::value && + MetaPolicy::template apply::value + > + {}; +}; + +template +struct metapred_2 +{ + template + struct apply + : boost::mpl::bool_ + < + PrevState::value && + for_each + < + Seq2, + metapred, + boost::mpl::bool_ + >::type::value + > + {}; +}; + +}} // namespace detail::is_not_implemented + + +/*! + A utility for checking if an algorithm is not implemented for some Geometries. + For variants it checks all combinations of Geometries and sets value to false + only if all combinations are not implemented. + */ +template +struct is_not_implemented + : MetaPolicy::template apply +{}; + +template +< + typename Geometry1, + BOOST_VARIANT_ENUM_PARAMS(typename T), + typename MetaPolicy +> +struct is_not_implemented + < + Geometry1, + boost::variant, + MetaPolicy + > + : detail::is_not_implemented::for_each + < + typename boost::variant::types, + detail::is_not_implemented::metapred, + boost::mpl::bool_ + >::type +{}; + +template +< + BOOST_VARIANT_ENUM_PARAMS(typename T), + typename Geometry2, + typename MetaPolicy +> +struct is_not_implemented + < + boost::variant, + Geometry2, + MetaPolicy + > + : detail::is_not_implemented::for_each + < + typename boost::variant::types, + detail::is_not_implemented::metapred + < + Geometry2, + detail::is_not_implemented::reverse + >, + boost::mpl::bool_ + >::type +{}; + +template +< + BOOST_VARIANT_ENUM_PARAMS(typename T1), + BOOST_VARIANT_ENUM_PARAMS(typename T2), + typename MetaPolicy +> +struct is_not_implemented + < + boost::variant, + boost::variant, + MetaPolicy + > + : detail::is_not_implemented::for_each + < + typename boost::variant::types, + detail::is_not_implemented::metapred_2 + < + typename boost::variant::types, + MetaPolicy + >, + boost::mpl::bool_ + >::type +{ +}; + +}} // namespace boost::geometry + + +#endif // BOOST_GEOMETRY_ALGORITHMS_IS_NOT_IMPLEMENTED_HPP diff --git a/include/boost/geometry/algorithms/not_implemented.hpp b/include/boost/geometry/algorithms/not_implemented.hpp index 9c416074ed..147ddb23cf 100644 --- a/include/boost/geometry/algorithms/not_implemented.hpp +++ b/include/boost/geometry/algorithms/not_implemented.hpp @@ -8,6 +8,7 @@ // Modifications copyright (c) 2015, Oracle and/or its affiliates. // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle +// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle // Parts of Boost.Geometry are redesigned from Geodan's Geographic Library // (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands. @@ -20,6 +21,7 @@ #ifndef BOOST_GEOMETRY_ALGORITHMS_NOT_IMPLEMENTED_HPP #define BOOST_GEOMETRY_ALGORITHMS_NOT_IMPLEMENTED_HPP +#include #include #include @@ -96,7 +98,7 @@ template <> struct tag_to_term { typedef info::GEOM template struct tag_to_term > { typedef info::DIMENSION type; }; -} +} // namespace nyi template @@ -125,6 +127,99 @@ struct not_implemented {}; +template +< + typename Result = void, + typename Term1 = void, + typename Term2 = void, + typename Term3 = void +> +struct lazy_not_implemented + : nyi::not_implemented_tag +{ +#ifndef BOOST_NO_CXX11_VARIADIC_TEMPLATES + template + static inline Result apply(T1 const&...) + { + not_implemented(); + return Result(); + } +#else + static inline Result apply() + { + not_implemented(); + return Result(); + } + + template + static inline Result apply(T1 const&, T2 const&) + { + not_implemented(); + return Result(); + } + + template + static inline Result apply(T1 const&, T2 const&, T3 const&) + { + not_implemented(); + return Result(); + } + + template + static inline Result apply(T1 const&, T2 const&, T3 const&, T4 const&) + { + not_implemented(); + return Result(); + } +#endif +}; + +template +struct lazy_not_implemented + : nyi::not_implemented_tag +{ +#ifndef BOOST_NO_CXX11_VARIADIC_TEMPLATES + template + static inline void apply(T1 const&...) + { + not_implemented(); + } +#else + static inline void apply() + { + not_implemented(); + } + + template + static inline void apply(T1 const&, T2 const&) + { + not_implemented(); + } + + template + static inline void apply(T1 const&, T2 const&, T3 const&) + { + not_implemented(); + } + + template + static inline void apply(T1 const&, T2 const&, T3 const&, T4 const&) + { + not_implemented(); + } +#endif +}; + + +struct not_implemented_exception + : boost::geometry::exception +{ + const char * what() const throw() + { + return "THIS_OPERATION_IS_NOT_OR_NOT_YET_IMPLEMENTED for passed input types"; + } +}; + }} // namespace boost::geometry diff --git a/include/boost/geometry/algorithms/within.hpp b/include/boost/geometry/algorithms/within.hpp index 9f2b6fedf7..92c045fce7 100644 --- a/include/boost/geometry/algorithms/within.hpp +++ b/include/boost/geometry/algorithms/within.hpp @@ -31,6 +31,7 @@ #include #include +#include #include #include @@ -96,7 +97,8 @@ template typename Tag2 = typename tag::type > struct within - : not_implemented + //: not_implemented + : lazy_not_implemented {}; @@ -349,6 +351,54 @@ struct within } }; + +struct within_metapolicy +{ + template + struct apply + : boost::is_base_of + < + nyi::not_implemented_tag, + dispatch::within + > + {}; +}; + + +template +< + typename Geometry1, + typename Geometry2, + bool NotImplemented = is_not_implemented + < + Geometry1, + Geometry2, + within_metapolicy + >::value +> +struct within_variant +{ + template + static inline bool apply(Geometry1 const& geometry1, + Geometry2 const& geometry2, + Strategy const& strategy) + { + return within::apply(geometry1, geometry2, strategy); + } +}; + +template +struct within_variant +{ + template + static inline bool apply(Geometry1 const& , + Geometry2 const& , + Strategy const& ) + { + throw geometry::not_implemented_exception(); + } +}; + template struct within, Geometry2> { @@ -366,9 +416,10 @@ struct within, Geometry2> template bool operator()(Geometry1 const& geometry1) const { - return within::apply(geometry1, - m_geometry2, - m_strategy); + return within_variant + < + Geometry1, Geometry2 + >::apply(geometry1, m_geometry2, m_strategy); } }; @@ -402,9 +453,10 @@ struct within > template bool operator()(Geometry2 const& geometry2) const { - return within::apply(m_geometry1, - geometry2, - m_strategy); + return within_variant + < + Geometry1, Geometry2 + >::apply(m_geometry1, geometry2, m_strategy); } }; @@ -441,9 +493,10 @@ struct within< bool operator()(Geometry1 const& geometry1, Geometry2 const& geometry2) const { - return within::apply(geometry1, - geometry2, - m_strategy); + return within_variant + < + Geometry1, Geometry2 + >::apply(geometry1, geometry2, m_strategy); } }; diff --git a/test/algorithms/relational_operations/within/Jamfile.v2 b/test/algorithms/relational_operations/within/Jamfile.v2 index b714702152..a870a06934 100644 --- a/test/algorithms/relational_operations/within/Jamfile.v2 +++ b/test/algorithms/relational_operations/within/Jamfile.v2 @@ -21,5 +21,6 @@ test-suite boost-geometry-algorithms-within [ run within_linear_areal.cpp : : : : algorithms_within_linear_areal ] [ run within_linear_linear.cpp : : : : algorithms_within_linear_linear ] [ run within_multi.cpp : : : : algorithms_within_multi ] + [ run within_not_implemented.cpp : : : : algorithms_within_not_implemented ] [ run within_pointlike_geometry.cpp : : : : algorithms_within_pointlike_geometry ] ; diff --git a/test/algorithms/relational_operations/within/within_not_implemented.cpp b/test/algorithms/relational_operations/within/within_not_implemented.cpp new file mode 100644 index 0000000000..c2b8cb0eae --- /dev/null +++ b/test/algorithms/relational_operations/within/within_not_implemented.cpp @@ -0,0 +1,127 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2013-2015 Adam Wulkiewicz, Lodz, Poland. + +// This file was modified by Oracle on 2014, 2015. +// Modifications copyright (c) 2014-2015 Oracle and/or its affiliates. + +// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle + +// 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 "test_within.hpp" + +#include +#include + + +bool true_pred(bg::not_implemented_exception const&) { return true; } + + +int test_main( int , char* [] ) +{ + typedef bg::model::d2::point_xy pt_t; + typedef bg::model::multi_point mpt_t; + typedef bg::model::linestring ls_t; + typedef bg::model::ring ring_t; + typedef bg::model::polygon poly_t; + typedef bg::model::multi_polygon mpoly_t; + + typedef boost::variant var_pt_t; + typedef boost::variant var_po_t; + typedef boost::variant var_pt_po_t; + typedef boost::variant var_po_pt_t; + + pt_t pt(1, 1); + poly_t poly; + boost::geometry::read_wkt("POLYGON((0 0,0 5,5 5,5 0,0 0))", poly); + + var_pt_po_t v1 = pt; + var_pt_po_t v2 = pt; + var_pt_po_t v3 = poly; + + BOOST_CHECK(bg::within(v1, v2)); + BOOST_CHECK(bg::within(v1, v3)); + BOOST_CHECK_EXCEPTION(bg::within(v3, v1), + bg::not_implemented_exception, + true_pred); + + using bg::resolve_variant::within_metapolicy; + + // sanity check + BOOST_CHECK( (within_metapolicy::apply::value)); + BOOST_CHECK(!(within_metapolicy::apply::value)); + BOOST_CHECK(!(within_metapolicy::apply::value)); + BOOST_CHECK(!(within_metapolicy::apply::value)); + + BOOST_CHECK( (bg::is_not_implemented::value)); + BOOST_CHECK(!(bg::is_not_implemented::value)); + BOOST_CHECK(!(bg::is_not_implemented::value)); + BOOST_CHECK(!(bg::is_not_implemented::value)); + + + BOOST_CHECK( (bg::is_not_implemented::value)); + BOOST_CHECK(!(bg::is_not_implemented::value)); + BOOST_CHECK(!(bg::is_not_implemented::value)); + BOOST_CHECK(!(bg::is_not_implemented::value)); + + BOOST_CHECK(!(bg::is_not_implemented::value)); + BOOST_CHECK(!(bg::is_not_implemented::value)); + BOOST_CHECK(!(bg::is_not_implemented::value)); + BOOST_CHECK(!(bg::is_not_implemented::value)); + + + BOOST_CHECK(!(bg::is_not_implemented::value)); + BOOST_CHECK( (bg::is_not_implemented::value)); + BOOST_CHECK(!(bg::is_not_implemented::value)); + BOOST_CHECK(!(bg::is_not_implemented::value)); + + BOOST_CHECK(!(bg::is_not_implemented::value)); + BOOST_CHECK(!(bg::is_not_implemented::value)); + BOOST_CHECK(!(bg::is_not_implemented::value)); + BOOST_CHECK(!(bg::is_not_implemented::value)); + + + BOOST_CHECK(!(bg::is_not_implemented::value)); + BOOST_CHECK(!(bg::is_not_implemented::value)); + BOOST_CHECK(!(bg::is_not_implemented::value)); + BOOST_CHECK(!(bg::is_not_implemented::value)); + + BOOST_CHECK( (bg::is_not_implemented::value)); + BOOST_CHECK(!(bg::is_not_implemented::value)); + BOOST_CHECK(!(bg::is_not_implemented::value)); + BOOST_CHECK(!(bg::is_not_implemented::value)); + + BOOST_CHECK(!(bg::is_not_implemented::value)); + BOOST_CHECK(!(bg::is_not_implemented::value)); + BOOST_CHECK(!(bg::is_not_implemented::value)); + BOOST_CHECK(!(bg::is_not_implemented::value)); + + + typedef boost::variant var_p_ls_t; + typedef boost::variant var_a_t; + typedef boost::variant var_p_ls_po_t; + typedef boost::variant var_ls_a_t; + + // sanity check + BOOST_CHECK( (within_metapolicy::apply::value)); + BOOST_CHECK( (within_metapolicy::apply::value)); + BOOST_CHECK( (within_metapolicy::apply::value)); + BOOST_CHECK( (within_metapolicy::apply::value)); + BOOST_CHECK( (within_metapolicy::apply::value)); + BOOST_CHECK( (within_metapolicy::apply::value)); + BOOST_CHECK( (within_metapolicy::apply::value)); + BOOST_CHECK( (within_metapolicy::apply::value)); + BOOST_CHECK( (within_metapolicy::apply::value)); + + BOOST_CHECK(!(bg::is_not_implemented::value)); + BOOST_CHECK( (bg::is_not_implemented::value)); + BOOST_CHECK(!(bg::is_not_implemented::value)); + BOOST_CHECK(!(bg::is_not_implemented::value)); + + return 0; +}