diff options
author | DongHun Kwak <dh0128.kwak@samsung.com> | 2017-09-13 11:08:07 +0900 |
---|---|---|
committer | DongHun Kwak <dh0128.kwak@samsung.com> | 2017-09-13 11:09:00 +0900 |
commit | b5c87084afaef42b2d058f68091be31988a6a874 (patch) | |
tree | adef9a65870a41181687e11d57fdf98e7629de3c /boost/geometry/algorithms | |
parent | 34bd32e225e2a8a94104489b31c42e5801cc1f4a (diff) | |
download | boost-b5c87084afaef42b2d058f68091be31988a6a874.tar.gz boost-b5c87084afaef42b2d058f68091be31988a6a874.tar.bz2 boost-b5c87084afaef42b2d058f68091be31988a6a874.zip |
Imported Upstream version 1.64.0upstream/1.64.0
Change-Id: Id9212edd016dd55f21172c427aa7894d1d24148b
Signed-off-by: DongHun Kwak <dh0128.kwak@samsung.com>
Diffstat (limited to 'boost/geometry/algorithms')
97 files changed, 4217 insertions, 1962 deletions
diff --git a/boost/geometry/algorithms/area.hpp b/boost/geometry/algorithms/area.hpp index 4751d4e742..18aea24036 100644 --- a/boost/geometry/algorithms/area.hpp +++ b/boost/geometry/algorithms/area.hpp @@ -4,6 +4,10 @@ // Copyright (c) 2008-2012 Bruno Lalande, Paris, France. // Copyright (c) 2009-2012 Mateusz Loskot, London, UK. +// This file was modified by Oracle on 2017. +// Modifications copyright (c) 2017 Oracle and/or its affiliates. +// 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. @@ -303,7 +307,8 @@ inline typename default_area_result<Geometry>::type area(Geometry const& geometr [heading Available Strategies] \* [link geometry.reference.strategies.strategy_area_surveyor Surveyor (cartesian)] -\* [link geometry.reference.strategies.strategy_area_huiller Huiller (spherical)] +\* [link geometry.reference.strategies.strategy_area_spherical Spherical] +[/link geometry.reference.strategies.strategy_area_geographic Geographic] } */ template <typename Geometry, typename Strategy> diff --git a/boost/geometry/algorithms/buffer.hpp b/boost/geometry/algorithms/buffer.hpp index e1d3c20e44..fd6f0fbe6a 100644 --- a/boost/geometry/algorithms/buffer.hpp +++ b/boost/geometry/algorithms/buffer.hpp @@ -4,6 +4,10 @@ // Copyright (c) 2008-2012 Bruno Lalande, Paris, France. // Copyright (c) 2009-2012 Mateusz Loskot, London, UK. +// This file was modified by Oracle on 2017. +// Modifications copyright (c) 2017 Oracle and/or its affiliates. +// 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. @@ -274,6 +278,11 @@ inline void buffer(GeometryIn const& geometry_in, geometry::envelope(geometry_in, box); geometry::buffer(box, box, distance_strategy.max_distance(join_strategy, end_strategy)); + typename strategy::intersection::services::default_strategy + < + typename cs_tag<GeometryIn>::type + >::type intersection_strategy; + rescale_policy_type rescale_policy = boost::geometry::get_rescale_policy<rescale_policy_type>(box); @@ -283,6 +292,7 @@ inline void buffer(GeometryIn const& geometry_in, join_strategy, end_strategy, point_strategy, + intersection_strategy, rescale_policy); } diff --git a/boost/geometry/algorithms/centroid.hpp b/boost/geometry/algorithms/centroid.hpp index fc2908ab1c..6a58033f37 100644 --- a/boost/geometry/algorithms/centroid.hpp +++ b/boost/geometry/algorithms/centroid.hpp @@ -3,7 +3,7 @@ // Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands. // Copyright (c) 2008-2015 Bruno Lalande, Paris, France. // Copyright (c) 2009-2015 Mateusz Loskot, London, UK. -// Copyright (c) 2014-2015 Adam Wulkiewicz, Lodz, Poland. +// Copyright (c) 2014-2017 Adam Wulkiewicz, Lodz, Poland. // This file was modified by Oracle on 2014, 2015. // Modifications copyright (c) 2014-2015 Oracle and/or its affiliates. @@ -26,6 +26,7 @@ #include <boost/core/ignore_unused.hpp> #include <boost/range.hpp> +#include <boost/throw_exception.hpp> #include <boost/variant/apply_visitor.hpp> #include <boost/variant/static_visitor.hpp> @@ -183,7 +184,7 @@ inline bool range_ok(Range const& range, Point& centroid) else if (n <= 0) { #if ! defined(BOOST_GEOMETRY_CENTROID_NO_THROW) - throw centroid_exception(); + BOOST_THROW_EXCEPTION(centroid_exception()); #else return false; #endif @@ -366,7 +367,7 @@ struct centroid_multi // to calculate the centroid if (geometry::is_empty(multi)) { - throw centroid_exception(); + BOOST_THROW_EXCEPTION(centroid_exception()); } #endif diff --git a/boost/geometry/algorithms/covered_by.hpp b/boost/geometry/algorithms/covered_by.hpp index 2001d5810c..f9d9dcc486 100644 --- a/boost/geometry/algorithms/covered_by.hpp +++ b/boost/geometry/algorithms/covered_by.hpp @@ -4,8 +4,10 @@ // Copyright (c) 2008-2012 Bruno Lalande, Paris, France. // Copyright (c) 2009-2012 Mateusz Loskot, London, UK. -// This file was modified by Oracle on 2013, 2014. -// Modifications copyright (c) 2013, 2014 Oracle and/or its affiliates. +// This file was modified by Oracle on 2013, 2014, 2017. +// Modifications copyright (c) 2013-2017 Oracle and/or its affiliates. + +// 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. @@ -14,8 +16,6 @@ // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) -// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle - #ifndef BOOST_GEOMETRY_ALGORITHMS_COVERED_BY_HPP #define BOOST_GEOMETRY_ALGORITHMS_COVERED_BY_HPP @@ -51,9 +51,13 @@ struct use_point_in_geometry struct use_relate { template <typename Geometry1, typename Geometry2, typename Strategy> - static inline bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2, Strategy const& /*strategy*/) + static inline bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2, Strategy const& strategy) { - return Strategy::apply(geometry1, geometry2); + typedef typename detail::de9im::static_mask_covered_by_type + < + Geometry1, Geometry2 + >::type covered_by_mask; + return geometry::relate(geometry1, geometry2, covered_by_mask(), strategy); } }; @@ -281,23 +285,8 @@ struct covered_by Geometry2 const& geometry2, default_strategy) { - typedef typename point_type<Geometry1>::type point_type1; - typedef typename point_type<Geometry2>::type point_type2; - typedef typename strategy::covered_by::services::default_strategy < - typename tag<Geometry1>::type, - typename tag<Geometry2>::type, - typename tag<Geometry1>::type, - typename tag_cast<typename tag<Geometry2>::type, areal_tag>::type, - typename tag_cast - < - typename cs_tag<point_type1>::type, spherical_tag - >::type, - typename tag_cast - < - typename cs_tag<point_type2>::type, spherical_tag - >::type, Geometry1, Geometry2 >::type strategy_type; diff --git a/boost/geometry/algorithms/crosses.hpp b/boost/geometry/algorithms/crosses.hpp index 73d86ef529..c9e3651ab2 100644 --- a/boost/geometry/algorithms/crosses.hpp +++ b/boost/geometry/algorithms/crosses.hpp @@ -5,8 +5,10 @@ // Copyright (c) 2009-2012 Mateusz Loskot, London, UK. // Copyright (c) 2014 Samuel Debionne, Grenoble, France. -// This file was modified by Oracle on 2014. -// Modifications copyright (c) 2014 Oracle and/or its affiliates. +// This file was modified by Oracle on 2014, 2017. +// Modifications copyright (c) 2014-2017 Oracle and/or its affiliates. + +// 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. @@ -15,8 +17,6 @@ // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) -// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle - #ifndef BOOST_GEOMETRY_ALGORITHMS_CROSSES_HPP #define BOOST_GEOMETRY_ALGORITHMS_CROSSES_HPP @@ -26,12 +26,12 @@ #include <boost/variant/static_visitor.hpp> #include <boost/variant/variant_fwd.hpp> +#include <boost/geometry/algorithms/relate.hpp> +#include <boost/geometry/algorithms/detail/relate/relate_impl.hpp> #include <boost/geometry/core/access.hpp> - #include <boost/geometry/geometries/concepts/check.hpp> +#include <boost/geometry/strategies/default_strategy.hpp> -#include <boost/geometry/algorithms/relate.hpp> -#include <boost/geometry/algorithms/detail/relate/relate_impl.hpp> namespace boost { namespace geometry { @@ -62,20 +62,51 @@ struct crosses #endif // DOXYGEN_NO_DISPATCH +namespace resolve_strategy +{ + +struct crosses +{ + template <typename Geometry1, typename Geometry2, typename Strategy> + static inline bool apply(Geometry1 const& geometry1, + Geometry2 const& geometry2, + Strategy const& strategy) + { + concepts::check<Geometry1 const>(); + concepts::check<Geometry2 const>(); + + return dispatch::crosses<Geometry1, Geometry2>::apply(geometry1, geometry2, strategy); + } + + template <typename Geometry1, typename Geometry2> + static inline bool apply(Geometry1 const& geometry1, + Geometry2 const& geometry2, + default_strategy) + { + typedef typename strategy::relate::services::default_strategy + < + Geometry1, + Geometry2 + >::type strategy_type; + + return apply(geometry1, geometry2, strategy_type()); + } +}; + +} // namespace resolve_strategy + + namespace resolve_variant { template <typename Geometry1, typename Geometry2> struct crosses { - static inline bool - apply( - const Geometry1& geometry1, - const Geometry2& geometry2) + template <typename Strategy> + static inline bool apply(Geometry1 const& geometry1, + Geometry2 const& geometry2, + Strategy const& strategy) { - concepts::check<Geometry1 const>(); - concepts::check<Geometry2 const>(); - - return dispatch::crosses<Geometry1, Geometry2>::apply(geometry1, geometry2); + return resolve_strategy::crosses::apply(geometry1, geometry2, strategy); } }; @@ -83,12 +114,15 @@ namespace resolve_variant template <BOOST_VARIANT_ENUM_PARAMS(typename T), typename Geometry2> struct crosses<variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Geometry2> { + template <typename Strategy> struct visitor: static_visitor<bool> { Geometry2 const& m_geometry2; + Strategy const& m_strategy; - visitor(Geometry2 const& geometry2) + visitor(Geometry2 const& geometry2, Strategy const& strategy) : m_geometry2(geometry2) + , m_strategy(strategy) {} template <typename Geometry1> @@ -98,15 +132,16 @@ namespace resolve_variant < Geometry1, Geometry2 - >::apply(geometry1, m_geometry2); + >::apply(geometry1, m_geometry2, m_strategy); } }; - static inline bool - apply(variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry1, - Geometry2 const& geometry2) + template <typename Strategy> + static inline bool apply(variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry1, + Geometry2 const& geometry2, + Strategy const& strategy) { - return boost::apply_visitor(visitor(geometry2), geometry1); + return boost::apply_visitor(visitor<Strategy>(geometry2, strategy), geometry1); } }; @@ -114,12 +149,15 @@ namespace resolve_variant template <typename Geometry1, BOOST_VARIANT_ENUM_PARAMS(typename T)> struct crosses<Geometry1, variant<BOOST_VARIANT_ENUM_PARAMS(T)> > { + template <typename Strategy> struct visitor: static_visitor<bool> { Geometry1 const& m_geometry1; + Strategy const& m_strategy; - visitor(Geometry1 const& geometry1) + visitor(Geometry1 const& geometry1, Strategy const& strategy) : m_geometry1(geometry1) + , m_strategy(strategy) {} template <typename Geometry2> @@ -129,15 +167,16 @@ namespace resolve_variant < Geometry1, Geometry2 - >::apply(m_geometry1, geometry2); + >::apply(m_geometry1, geometry2, m_strategy); } }; - static inline bool - apply(Geometry1 const& geometry1, - const variant<BOOST_VARIANT_ENUM_PARAMS(T)>& geometry2) + template <typename Strategy> + static inline bool apply(Geometry1 const& geometry1, + variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry2, + Strategy const& strategy) { - return boost::apply_visitor(visitor(geometry1), geometry2); + return boost::apply_visitor(visitor<Strategy>(geometry1, strategy), geometry2); } }; @@ -145,8 +184,15 @@ namespace resolve_variant template <BOOST_VARIANT_ENUM_PARAMS(typename T1), BOOST_VARIANT_ENUM_PARAMS(typename T2)> struct crosses<variant<BOOST_VARIANT_ENUM_PARAMS(T1)>, variant<BOOST_VARIANT_ENUM_PARAMS(T2)> > { + template <typename Strategy> struct visitor: static_visitor<bool> { + Strategy const& m_strategy; + + visitor(Strategy const& strategy) + : m_strategy(strategy) + {} + template <typename Geometry1, typename Geometry2> result_type operator()(Geometry1 const& geometry1, Geometry2 const& geometry2) const @@ -155,15 +201,16 @@ namespace resolve_variant < Geometry1, Geometry2 - >::apply(geometry1, geometry2); + >::apply(geometry1, geometry2, m_strategy); } }; - static inline bool - apply(const variant<BOOST_VARIANT_ENUM_PARAMS(T1)>& geometry1, - const variant<BOOST_VARIANT_ENUM_PARAMS(T2)>& geometry2) + template <typename Strategy> + static inline bool apply(variant<BOOST_VARIANT_ENUM_PARAMS(T1)> const& geometry1, + variant<BOOST_VARIANT_ENUM_PARAMS(T2)> const& geometry2, + Strategy const& strategy) { - return boost::apply_visitor(visitor(), geometry1, geometry2); + return boost::apply_visitor(visitor<Strategy>(strategy), geometry1, geometry2); } }; @@ -175,6 +222,31 @@ namespace resolve_variant \ingroup crosses \tparam Geometry1 \tparam_geometry \tparam Geometry2 \tparam_geometry +\tparam Strategy \tparam_strategy{Crosses} +\param geometry1 \param_geometry +\param geometry2 \param_geometry +\param strategy \param_strategy{crosses} +\return \return_check2{crosses} + +\qbk{distinguish,with strategy} +\qbk{[include reference/algorithms/crosses.qbk]} +*/ +template <typename Geometry1, typename Geometry2, typename Strategy> +inline bool crosses(Geometry1 const& geometry1, + Geometry2 const& geometry2, + Strategy const& strategy) +{ + return resolve_variant::crosses + < + Geometry1, Geometry2 + >::apply(geometry1, geometry2, strategy); +} + +/*! +\brief \brief_check2{crosses} +\ingroup crosses +\tparam Geometry1 \tparam_geometry +\tparam Geometry2 \tparam_geometry \param geometry1 \param_geometry \param geometry2 \param_geometry \return \return_check2{crosses} @@ -184,7 +256,10 @@ namespace resolve_variant template <typename Geometry1, typename Geometry2> inline bool crosses(Geometry1 const& geometry1, Geometry2 const& geometry2) { - return resolve_variant::crosses<Geometry1, Geometry2>::apply(geometry1, geometry2); + return resolve_variant::crosses + < + Geometry1, Geometry2 + >::apply(geometry1, geometry2, default_strategy()); } }} // namespace boost::geometry diff --git a/boost/geometry/algorithms/detail/azimuth.hpp b/boost/geometry/algorithms/detail/azimuth.hpp index 7e0d1691ed..a5863d7d24 100644 --- a/boost/geometry/algorithms/detail/azimuth.hpp +++ b/boost/geometry/algorithms/detail/azimuth.hpp @@ -2,9 +2,10 @@ // Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. -// This file was modified by Oracle on 2014, 2016. -// Modifications copyright (c) 2014-2016, Oracle and/or its affiliates. +// This file was modified by Oracle on 2014, 2016, 2017. +// Modifications copyright (c) 2014-2017, Oracle and/or its affiliates. +// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle // Use, modification and distribution is subject to the Boost Software License, @@ -23,6 +24,7 @@ #include <boost/geometry/algorithms/not_implemented.hpp> +#include <boost/geometry/formulas/spherical.hpp> #include <boost/geometry/formulas/vincenty_inverse.hpp> namespace boost { namespace geometry @@ -69,22 +71,9 @@ struct azimuth<ReturnType, spherical_equatorial_tag> template <typename P1, typename P2, typename Sphere> static inline ReturnType apply(P1 const& p1, P2 const& p2, Sphere const& /*unused*/) { - // http://williams.best.vwh.net/avform.htm#Crs - ReturnType dlon = get_as_radian<0>(p2) - get_as_radian<0>(p1); - ReturnType cos_p2lat = cos(get_as_radian<1>(p2)); - - // An optimization which should kick in often for Boxes - //if ( math::equals(dlon, ReturnType(0)) ) - //if ( get<0>(p1) == get<0>(p2) ) - //{ - // return - sin(get_as_radian<1>(p1)) * cos_p2lat); - //} - - // "An alternative formula, not requiring the pre-computation of d" - // In the formula below dlon is used as "d" - return atan2(sin(dlon) * cos_p2lat, - cos(get_as_radian<1>(p1)) * sin(get_as_radian<1>(p2)) - - sin(get_as_radian<1>(p1)) * cos_p2lat * cos(dlon)); + return geometry::formula::spherical_azimuth<ReturnType, false> + ( get_as_radian<0>(p1), get_as_radian<1>(p1), + get_as_radian<0>(p2), get_as_radian<1>(p2)).azimuth; } template <typename P1, typename P2> diff --git a/boost/geometry/algorithms/detail/buffer/buffer_inserter.hpp b/boost/geometry/algorithms/detail/buffer/buffer_inserter.hpp index 8447532a6c..029053dda3 100644 --- a/boost/geometry/algorithms/detail/buffer/buffer_inserter.hpp +++ b/boost/geometry/algorithms/detail/buffer/buffer_inserter.hpp @@ -2,6 +2,10 @@ // Copyright (c) 2012-2014 Barend Gehrels, Amsterdam, the Netherlands. +// This file was modified by Oracle on 2017. +// Modifications copyright (c) 2017 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) @@ -449,13 +453,14 @@ struct buffer_inserter<point_tag, Point, RingOutput> } }; - +// Not a specialization, but called from specializations of ring and of polygon. +// Calling code starts/finishes ring before/after apply template < typename RingInput, typename RingOutput > -struct buffer_inserter<ring_tag, RingInput, RingOutput> +struct buffer_inserter_ring { typedef typename point_type<RingOutput>::type output_point_type; @@ -568,6 +573,43 @@ struct buffer_inserter<ring_tag, RingInput, RingOutput> template < + typename RingInput, + typename RingOutput +> +struct buffer_inserter<ring_tag, RingInput, RingOutput> +{ + template + < + typename Collection, + typename DistanceStrategy, + typename SideStrategy, + typename JoinStrategy, + typename EndStrategy, + typename PointStrategy, + typename RobustPolicy + > + static inline strategy::buffer::result_code apply(RingInput const& ring, + Collection& collection, + DistanceStrategy const& distance, + SideStrategy const& side_strategy, + JoinStrategy const& join_strategy, + EndStrategy const& end_strategy, + PointStrategy const& point_strategy, + RobustPolicy const& robust_policy) + { + collection.start_new_ring(); + strategy::buffer::result_code const code + = buffer_inserter_ring<RingInput, RingOutput>::apply(ring, + collection, distance, + side_strategy, join_strategy, end_strategy, point_strategy, + robust_policy); + collection.finish_ring(code); + return code; + } +}; + +template +< typename Linestring, typename Polygon > @@ -709,7 +751,7 @@ private: typedef typename ring_type<PolygonInput>::type input_ring_type; typedef typename ring_type<PolygonOutput>::type output_ring_type; - typedef buffer_inserter<ring_tag, input_ring_type, output_ring_type> policy; + typedef buffer_inserter_ring<input_ring_type, output_ring_type> policy; template @@ -854,6 +896,7 @@ template typename JoinStrategy, typename EndStrategy, typename PointStrategy, + typename IntersectionStrategy, typename RobustPolicy, typename VisitPiecesPolicy > @@ -863,6 +906,7 @@ inline void buffer_inserter(GeometryInput const& geometry_input, OutputIterator JoinStrategy const& join_strategy, EndStrategy const& end_strategy, PointStrategy const& point_strategy, + IntersectionStrategy const& intersection_strategy, RobustPolicy const& robust_policy, VisitPiecesPolicy& visit_pieces_policy ) @@ -872,9 +916,10 @@ inline void buffer_inserter(GeometryInput const& geometry_input, OutputIterator typedef detail::buffer::buffered_piece_collection < typename geometry::ring_type<GeometryOutput>::type, + IntersectionStrategy, RobustPolicy > collection_type; - collection_type collection(robust_policy); + collection_type collection(intersection_strategy, robust_policy); collection_type const& const_collection = collection; bool const areal = boost::is_same @@ -961,6 +1006,7 @@ template typename JoinStrategy, typename EndStrategy, typename PointStrategy, + typename IntersectionStrategy, typename RobustPolicy > inline void buffer_inserter(GeometryInput const& geometry_input, OutputIterator out, @@ -969,13 +1015,14 @@ inline void buffer_inserter(GeometryInput const& geometry_input, OutputIterator JoinStrategy const& join_strategy, EndStrategy const& end_strategy, PointStrategy const& point_strategy, + IntersectionStrategy const& intersection_strategy, RobustPolicy const& robust_policy) { detail::buffer::visit_pieces_default_policy visitor; buffer_inserter<GeometryOutput>(geometry_input, out, distance_strategy, side_strategy, join_strategy, end_strategy, point_strategy, - robust_policy, visitor); + intersection_strategy, robust_policy, visitor); } #endif // DOXYGEN_NO_DETAIL diff --git a/boost/geometry/algorithms/detail/buffer/buffer_policies.hpp b/boost/geometry/algorithms/detail/buffer/buffer_policies.hpp index c1f04f93b5..92dcdcc7b0 100644 --- a/boost/geometry/algorithms/detail/buffer/buffer_policies.hpp +++ b/boost/geometry/algorithms/detail/buffer/buffer_policies.hpp @@ -2,6 +2,10 @@ // Copyright (c) 2012-2014 Barend Gehrels, Amsterdam, the Netherlands. +// This file was modified by Oracle on 2017. +// Modifications copyright (c) 2017, 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) @@ -52,6 +56,7 @@ public : typename Rings, typename Turns, typename Geometry, + typename Strategy, typename RobustPolicy, typename Visitor > @@ -63,6 +68,7 @@ public : detail::overlay::traverse_error_type /*traverse_error*/, Geometry const& , Geometry const& , + Strategy const& , RobustPolicy const& , state_type& state, Visitor& /*visitor*/ diff --git a/boost/geometry/algorithms/detail/buffer/buffered_piece_collection.hpp b/boost/geometry/algorithms/detail/buffer/buffered_piece_collection.hpp index e7214428e6..7fbbb790bb 100644 --- a/boost/geometry/algorithms/detail/buffer/buffered_piece_collection.hpp +++ b/boost/geometry/algorithms/detail/buffer/buffered_piece_collection.hpp @@ -2,8 +2,8 @@ // Copyright (c) 2012-2014 Barend Gehrels, Amsterdam, the Netherlands. -// This file was modified by Oracle on 2016. -// Modifications copyright (c) 2016 Oracle and/or its affiliates. +// This file was modified by Oracle on 2016-2017. +// Modifications copyright (c) 2016-2017 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, @@ -117,10 +117,13 @@ enum segment_relation_code */ -template <typename Ring, typename RobustPolicy> +template <typename Ring, typename IntersectionStrategy, typename RobustPolicy> struct buffered_piece_collection { - typedef buffered_piece_collection<Ring, RobustPolicy> this_type; + typedef buffered_piece_collection + < + Ring, IntersectionStrategy, RobustPolicy + > this_type; typedef typename geometry::point_type<Ring>::type point_type; typedef typename geometry::coordinate_type<Ring>::type coordinate_type; @@ -303,7 +306,7 @@ struct buffered_piece_collection cluster_type m_clusters; - + IntersectionStrategy const& m_intersection_strategy; RobustPolicy const& m_robust_policy; struct redundant_turn @@ -314,8 +317,10 @@ struct buffered_piece_collection } }; - buffered_piece_collection(RobustPolicy const& robust_policy) + buffered_piece_collection(IntersectionStrategy const& intersection_strategy, + RobustPolicy const& robust_policy) : m_first_piece_index(-1) + , m_intersection_strategy(intersection_strategy) , m_robust_policy(robust_policy) {} @@ -512,10 +517,11 @@ struct buffered_piece_collection geometry::partition < robust_box_type, - turn_get_box, turn_in_original_ovelaps_box, - original_get_box, original_ovelaps_box, - include_turn_policy, detail::partition::include_all_policy - >::apply(m_turns, robust_originals, visitor); + include_turn_policy, + detail::partition::include_all_policy + >::apply(m_turns, robust_originals, visitor, + turn_get_box(), turn_in_original_ovelaps_box(), + original_get_box(), original_ovelaps_box()); bool const deflate = distance_strategy.negative(); @@ -767,15 +773,17 @@ struct buffered_piece_collection piece_vector_type, buffered_ring_collection<buffered_ring<Ring> >, turn_vector_type, + IntersectionStrategy, RobustPolicy - > visitor(m_pieces, offsetted_rings, m_turns, m_robust_policy); + > visitor(m_pieces, offsetted_rings, m_turns, + m_intersection_strategy, m_robust_policy); geometry::partition < - robust_box_type, - detail::section::get_section_box, - detail::section::overlaps_section_box - >::apply(monotonic_sections, visitor); + robust_box_type + >::apply(monotonic_sections, visitor, + detail::section::get_section_box(), + detail::section::overlaps_section_box()); } insert_rescaled_piece_turns(); @@ -795,10 +803,10 @@ struct buffered_piece_collection geometry::partition < - robust_box_type, - turn_get_box, turn_ovelaps_box, - piece_get_box, piece_ovelaps_box - >::apply(m_turns, m_pieces, visitor); + robust_box_type + >::apply(m_turns, m_pieces, visitor, + turn_get_box(), turn_ovelaps_box(), + piece_get_box(), piece_ovelaps_box()); } } @@ -1354,7 +1362,8 @@ struct buffered_piece_collection traversed_rings.clear(); buffer_overlay_visitor visitor; traverser::apply(offsetted_rings, offsetted_rings, - m_robust_policy, m_turns, traversed_rings, + m_intersection_strategy, m_robust_policy, + m_turns, traversed_rings, m_clusters, visitor); } diff --git a/boost/geometry/algorithms/detail/buffer/get_piece_turns.hpp b/boost/geometry/algorithms/detail/buffer/get_piece_turns.hpp index 3425ee6ffd..178c7bcafe 100644 --- a/boost/geometry/algorithms/detail/buffer/get_piece_turns.hpp +++ b/boost/geometry/algorithms/detail/buffer/get_piece_turns.hpp @@ -2,6 +2,10 @@ // Copyright (c) 2012-2014 Barend Gehrels, Amsterdam, the Netherlands. +// This file was modified by Oracle on 2017. +// Modifications copyright (c) 2017 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) @@ -62,6 +66,7 @@ template typename Pieces, typename Rings, typename Turns, + typename IntersectionStrategy, typename RobustPolicy > class piece_turn_visitor @@ -69,6 +74,7 @@ class piece_turn_visitor Pieces const& m_pieces; Rings const& m_rings; Turns& m_turns; + IntersectionStrategy const& m_intersection_strategy; RobustPolicy const& m_robust_policy; template <typename Piece> @@ -243,7 +249,9 @@ class piece_turn_visitor turn_policy::apply(*prev1, *it1, *next1, *prev2, *it2, *next2, false, false, false, false, - the_model, m_robust_policy, + the_model, + m_intersection_strategy, + m_robust_policy, std::back_inserter(m_turns)); } } @@ -254,10 +262,12 @@ public: piece_turn_visitor(Pieces const& pieces, Rings const& ring_collection, Turns& turns, + IntersectionStrategy const& intersection_strategy, RobustPolicy const& robust_policy) : m_pieces(pieces) , m_rings(ring_collection) , m_turns(turns) + , m_intersection_strategy(intersection_strategy) , m_robust_policy(robust_policy) {} diff --git a/boost/geometry/algorithms/detail/calculate_sum.hpp b/boost/geometry/algorithms/detail/calculate_sum.hpp index b23e70171b..732a2f5753 100644 --- a/boost/geometry/algorithms/detail/calculate_sum.hpp +++ b/boost/geometry/algorithms/detail/calculate_sum.hpp @@ -8,6 +8,10 @@ // Parts of Boost.Geometry are redesigned from Geodan's Geographic Library // (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands. +// This file was modified by Oracle on 2016. +// Modifications copyright (c) 2016 Oracle and/or its affiliates. +// Contributed and/or modified by Vissarion Fysikopoulos, 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) @@ -30,7 +34,7 @@ class calculate_polygon_sum template <typename ReturnType, typename Policy, typename Rings, typename Strategy> static inline ReturnType sum_interior_rings(Rings const& rings, Strategy const& strategy) { - ReturnType sum = ReturnType(); + ReturnType sum = ReturnType(0); for (typename boost::range_iterator<Rings const>::type it = boost::begin(rings); it != boost::end(rings); ++it) { diff --git a/boost/geometry/algorithms/detail/disjoint/areal_areal.hpp b/boost/geometry/algorithms/detail/disjoint/areal_areal.hpp index 284858a130..664c995384 100644 --- a/boost/geometry/algorithms/detail/disjoint/areal_areal.hpp +++ b/boost/geometry/algorithms/detail/disjoint/areal_areal.hpp @@ -5,8 +5,8 @@ // Copyright (c) 2009-2014 Mateusz Loskot, London, UK. // Copyright (c) 2013-2014 Adam Wulkiewicz, Lodz, Poland. -// This file was modified by Oracle on 2013-2014. -// Modifications copyright (c) 2013-2014, Oracle and/or its affiliates. +// This file was modified by Oracle on 2013-2017. +// Modifications copyright (c) 2013-2017, Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle @@ -39,15 +39,45 @@ namespace detail { namespace disjoint { -template<typename Geometry> +template <typename Geometry, typename Tag = typename tag<Geometry>::type> +struct check_each_ring_for_within_call_covered_by +{ + /*! + \tparam Strategy point_in_geometry strategy + */ + template <typename Point, typename Strategy> + static inline bool apply(Point const& p, Geometry const& g, Strategy const& strategy) + { + return geometry::covered_by(p, g, strategy); + } +}; + +template <typename Geometry> +struct check_each_ring_for_within_call_covered_by<Geometry, box_tag> +{ + template <typename Point, typename Strategy> + static inline bool apply(Point const& p, Geometry const& g, Strategy const& ) + { + return geometry::covered_by(p, g); + } +}; + + +/*! +\tparam Strategy point_in_geometry strategy +*/ +template<typename Geometry, typename Strategy> struct check_each_ring_for_within { bool not_disjoint; Geometry const& m_geometry; + Strategy const& m_strategy; - inline check_each_ring_for_within(Geometry const& g) + inline check_each_ring_for_within(Geometry const& g, + Strategy const& strategy) : not_disjoint(false) , m_geometry(g) + , m_strategy(strategy) {} template <typename Range> @@ -56,17 +86,26 @@ struct check_each_ring_for_within typename point_type<Range>::type pt; not_disjoint = not_disjoint || ( geometry::point_on_border(pt, range) - && geometry::covered_by(pt, m_geometry) ); + && check_each_ring_for_within_call_covered_by + < + Geometry + >::apply(pt, m_geometry, m_strategy) ); } }; - -template <typename FirstGeometry, typename SecondGeometry> +/*! +\tparam Strategy point_in_geometry strategy +*/ +template <typename FirstGeometry, typename SecondGeometry, typename Strategy> inline bool rings_containing(FirstGeometry const& geometry1, - SecondGeometry const& geometry2) + SecondGeometry const& geometry2, + Strategy const& strategy) { - check_each_ring_for_within<FirstGeometry> checker(geometry1); + check_each_ring_for_within + < + FirstGeometry, Strategy + > checker(geometry1, strategy); geometry::detail::for_each_range(geometry2, checker); return checker.not_disjoint; } @@ -76,10 +115,15 @@ inline bool rings_containing(FirstGeometry const& geometry1, template <typename Geometry1, typename Geometry2> struct general_areal { - static inline - bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2) + /*! + \tparam Strategy relate (segments intersection) strategy + */ + template <typename Strategy> + static inline bool apply(Geometry1 const& geometry1, + Geometry2 const& geometry2, + Strategy const& strategy) { - if ( ! disjoint_linear<Geometry1, Geometry2>::apply(geometry1, geometry2) ) + if ( ! disjoint_linear<Geometry1, Geometry2>::apply(geometry1, geometry2, strategy) ) { return false; } @@ -90,8 +134,10 @@ struct general_areal // We check that using a point on the border (external boundary), // and see if that is contained in the other geometry. And vice versa. - if ( rings_containing(geometry1, geometry2) - || rings_containing(geometry2, geometry1) ) + if ( rings_containing(geometry1, geometry2, + strategy.template get_point_in_geometry_strategy<Geometry2, Geometry1>()) + || rings_containing(geometry2, geometry1, + strategy.template get_point_in_geometry_strategy<Geometry1, Geometry2>()) ) { return false; } diff --git a/boost/geometry/algorithms/detail/disjoint/box_box.hpp b/boost/geometry/algorithms/detail/disjoint/box_box.hpp index 3b81755e20..f830f8161c 100644 --- a/boost/geometry/algorithms/detail/disjoint/box_box.hpp +++ b/boost/geometry/algorithms/detail/disjoint/box_box.hpp @@ -5,8 +5,8 @@ // Copyright (c) 2009-2015 Mateusz Loskot, London, UK. // Copyright (c) 2013-2015 Adam Wulkiewicz, Lodz, Poland. -// This file was modified by Oracle on 2013-2016. -// Modifications copyright (c) 2013-2016, Oracle and/or its affiliates. +// This file was modified by Oracle on 2013-2017. +// Modifications copyright (c) 2013-2017, Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle @@ -52,6 +52,12 @@ template > struct box_box { + template <typename Strategy> + static inline bool apply(Box1 const& box1, Box2 const& box2, Strategy const&) + { + return apply(box1, box2); + } + static inline bool apply(Box1 const& box1, Box2 const& box2) { if (get<max_corner, Dimension>(box1) < get<min_corner, Dimension>(box2)) @@ -84,6 +90,12 @@ struct box_box<Box1, Box2, DimensionCount, DimensionCount, CSTag> template <typename Box1, typename Box2, std::size_t DimensionCount> struct box_box<Box1, Box2, 0, DimensionCount, spherical_tag> { + template <typename Strategy> + static inline bool apply(Box1 const& box1, Box2 const& box2, Strategy const&) + { + return apply(box1, box2); + } + static inline bool apply(Box1 const& box1, Box2 const& box2) { typedef typename geometry::select_most_precise diff --git a/boost/geometry/algorithms/detail/disjoint/interface.hpp b/boost/geometry/algorithms/detail/disjoint/interface.hpp index ce7fe6d45c..64898e35fe 100644 --- a/boost/geometry/algorithms/detail/disjoint/interface.hpp +++ b/boost/geometry/algorithms/detail/disjoint/interface.hpp @@ -5,8 +5,8 @@ // Copyright (c) 2009-2014 Mateusz Loskot, London, UK. // Copyright (c) 2013-2014 Adam Wulkiewicz, Lodz, Poland. -// This file was modified by Oracle on 2013-2014. -// Modifications copyright (c) 2013-2014, Oracle and/or its affiliates. +// This file was modified by Oracle on 2013-2017. +// Modifications copyright (c) 2013-2017, Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle @@ -27,43 +27,51 @@ #include <boost/variant/static_visitor.hpp> #include <boost/variant/variant_fwd.hpp> +#include <boost/geometry/algorithms/detail/relate/interface.hpp> +#include <boost/geometry/algorithms/dispatch/disjoint.hpp> + #include <boost/geometry/geometries/concepts/check.hpp> -#include <boost/geometry/algorithms/dispatch/disjoint.hpp> +#include <boost/geometry/strategies/disjoint.hpp> namespace boost { namespace geometry { - -#ifndef DOXYGEN_NO_DISPATCH -namespace dispatch +namespace resolve_strategy { - -// If reversal is needed, perform it -template -< - typename Geometry1, typename Geometry2, - std::size_t DimensionCount, - typename Tag1, typename Tag2 -> -struct disjoint<Geometry1, Geometry2, DimensionCount, Tag1, Tag2, true> +struct disjoint { - static inline bool apply(Geometry1 const& g1, Geometry2 const& g2) + template <typename Geometry1, typename Geometry2, typename Strategy> + static inline bool apply(Geometry1 const& geometry1, + Geometry2 const& geometry2, + Strategy const& strategy) { - return disjoint + return dispatch::disjoint + < + Geometry1, Geometry2 + >::apply(geometry1, geometry2, strategy); + } + + template <typename Geometry1, typename Geometry2> + static inline bool apply(Geometry1 const& geometry1, + Geometry2 const& geometry2, + default_strategy) + { + typedef typename strategy::disjoint::services::default_strategy < - Geometry2, Geometry1, - DimensionCount, - Tag2, Tag1 - >::apply(g2, g1); + Geometry1, Geometry2 + >::type strategy_type; + + return dispatch::disjoint + < + Geometry1, Geometry2 + >::apply(geometry1, geometry2, strategy_type()); } }; - -} // namespace dispatch -#endif // DOXYGEN_NO_DISPATCH +} // namespace resolve_strategy namespace resolve_variant { @@ -71,7 +79,8 @@ namespace resolve_variant { template <typename Geometry1, typename Geometry2> struct disjoint { - static inline bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2) + template <typename Strategy> + static inline bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2, Strategy const& strategy) { concepts::check_concepts_and_equal_dimensions < @@ -79,88 +88,135 @@ struct disjoint Geometry2 const >(); - return dispatch::disjoint<Geometry1, Geometry2>::apply(geometry1, geometry2); + return resolve_strategy::disjoint::apply(geometry1, geometry2, strategy); } }; template <BOOST_VARIANT_ENUM_PARAMS(typename T), typename Geometry2> struct disjoint<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Geometry2> { + template <typename Strategy> struct visitor: boost::static_visitor<bool> { Geometry2 const& m_geometry2; + Strategy const& m_strategy; - visitor(Geometry2 const& geometry2): m_geometry2(geometry2) {} + visitor(Geometry2 const& geometry2, Strategy const& strategy) + : m_geometry2(geometry2) + , m_strategy(strategy) + {} template <typename Geometry1> bool operator()(Geometry1 const& geometry1) const { - return disjoint<Geometry1, Geometry2>::apply(geometry1, m_geometry2); + return disjoint<Geometry1, Geometry2>::apply(geometry1, m_geometry2, m_strategy); } }; - static inline bool - apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry1, - Geometry2 const& geometry2) + template <typename Strategy> + static inline bool apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry1, + Geometry2 const& geometry2, + Strategy const& strategy) { - return boost::apply_visitor(visitor(geometry2), geometry1); + return boost::apply_visitor(visitor<Strategy>(geometry2, strategy), geometry1); } }; template <typename Geometry1, BOOST_VARIANT_ENUM_PARAMS(typename T)> struct disjoint<Geometry1, boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> > { + template <typename Strategy> struct visitor: boost::static_visitor<bool> { Geometry1 const& m_geometry1; + Strategy const& m_strategy; - visitor(Geometry1 const& geometry1): m_geometry1(geometry1) {} + visitor(Geometry1 const& geometry1, Strategy const& strategy) + : m_geometry1(geometry1) + , m_strategy(strategy) + {} template <typename Geometry2> bool operator()(Geometry2 const& geometry2) const { - return disjoint<Geometry1, Geometry2>::apply(m_geometry1, geometry2); + return disjoint<Geometry1, Geometry2>::apply(m_geometry1, geometry2, m_strategy); } }; - static inline bool - apply(Geometry1 const& geometry1, - boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry2) + template <typename Strategy> + static inline bool apply(Geometry1 const& geometry1, + boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry2, + Strategy const& strategy) { - return boost::apply_visitor(visitor(geometry1), geometry2); + return boost::apply_visitor(visitor<Strategy>(geometry1, strategy), geometry2); } }; -template < +template +< BOOST_VARIANT_ENUM_PARAMS(typename T1), BOOST_VARIANT_ENUM_PARAMS(typename T2) > -struct disjoint< - boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)>, - boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)> -> +struct disjoint + < + boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)>, + boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)> + > { + template <typename Strategy> struct visitor: boost::static_visitor<bool> { + Strategy const& m_strategy; + + visitor(Strategy const& strategy) + : m_strategy(strategy) + {} + template <typename Geometry1, typename Geometry2> bool operator()(Geometry1 const& geometry1, Geometry2 const& geometry2) const { - return disjoint<Geometry1, Geometry2>::apply(geometry1, geometry2); + return disjoint<Geometry1, Geometry2>::apply(geometry1, geometry2, m_strategy); } }; - static inline bool - apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)> const& geometry1, - boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)> const& geometry2) + template <typename Strategy> + static inline bool apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)> const& geometry1, + boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)> const& geometry2, + Strategy const& strategy) { - return boost::apply_visitor(visitor(), geometry1, geometry2); + return boost::apply_visitor(visitor<Strategy>(strategy), geometry1, geometry2); } }; } // namespace resolve_variant +/*! +\brief \brief_check2{are disjoint} +\ingroup disjoint +\tparam Geometry1 \tparam_geometry +\tparam Geometry2 \tparam_geometry +\tparam Strategy \tparam_strategy{Disjoint} +\param geometry1 \param_geometry +\param geometry2 \param_geometry +\param strategy \param_strategy{disjoint} +\return \return_check2{are disjoint} + +\qbk{distinguish,with strategy} +\qbk{[include reference/algorithms/disjoint.qbk]} +*/ +template <typename Geometry1, typename Geometry2, typename Strategy> +inline bool disjoint(Geometry1 const& geometry1, + Geometry2 const& geometry2, + Strategy const& strategy) +{ + return resolve_variant::disjoint + < + Geometry1, Geometry2 + >::apply(geometry1, geometry2, strategy); +} + /*! \brief \brief_check2{are disjoint} @@ -177,7 +233,10 @@ template <typename Geometry1, typename Geometry2> inline bool disjoint(Geometry1 const& geometry1, Geometry2 const& geometry2) { - return resolve_variant::disjoint<Geometry1, Geometry2>::apply(geometry1, geometry2); + return resolve_variant::disjoint + < + Geometry1, Geometry2 + >::apply(geometry1, geometry2, default_strategy()); } diff --git a/boost/geometry/algorithms/detail/disjoint/linear_areal.hpp b/boost/geometry/algorithms/detail/disjoint/linear_areal.hpp index 6a48b684a1..e6077d3e7f 100644 --- a/boost/geometry/algorithms/detail/disjoint/linear_areal.hpp +++ b/boost/geometry/algorithms/detail/disjoint/linear_areal.hpp @@ -5,8 +5,8 @@ // Copyright (c) 2009-2014 Mateusz Loskot, London, UK. // Copyright (c) 2013-2014 Adam Wulkiewicz, Lodz, Poland. -// This file was modified by Oracle on 2013-2015. -// Modifications copyright (c) 2013-2015, Oracle and/or its affiliates. +// This file was modified by Oracle on 2013-2017. +// Modifications copyright (c) 2013-2017, Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle @@ -61,19 +61,28 @@ template <typename Geometry1, typename Geometry2, typename Tag1OrMulti = typename tag_cast<Tag1, multi_tag>::type> struct disjoint_no_intersections_policy { - static inline bool apply(Geometry1 const& g1, Geometry2 const& g2) + /*! + \tparam Strategy point_in_geometry strategy + */ + template <typename Strategy> + static inline bool apply(Geometry1 const& g1, Geometry2 const& g2, Strategy const& strategy) { typedef typename point_type<Geometry1>::type point1_type; point1_type p; geometry::point_on_border(p, g1); - return !geometry::covered_by(p, g2); + + return !geometry::covered_by(p, g2, strategy); } }; template <typename Geometry1, typename Geometry2, typename Tag1> struct disjoint_no_intersections_policy<Geometry1, Geometry2, Tag1, multi_tag> { - static inline bool apply(Geometry1 const& g1, Geometry2 const& g2) + /*! + \tparam Strategy point_in_geometry strategy + */ + template <typename Strategy> + static inline bool apply(Geometry1 const& g1, Geometry2 const& g2, Strategy const& strategy) { // TODO: use partition or rtree on g2 typedef typename boost::range_iterator<Geometry1 const>::type iterator; @@ -81,7 +90,7 @@ struct disjoint_no_intersections_policy<Geometry1, Geometry2, Tag1, multi_tag> { typedef typename boost::range_value<Geometry1 const>::type value_type; if ( ! disjoint_no_intersections_policy<value_type const, Geometry2> - ::apply(*it, g2) ) + ::apply(*it, g2, strategy) ) { return false; } @@ -96,15 +105,21 @@ template<typename Geometry1, typename Geometry2, = disjoint_no_intersections_policy<Geometry1, Geometry2> > struct disjoint_linear_areal { - static inline bool apply(Geometry1 const& g1, Geometry2 const& g2) + /*! + \tparam Strategy relate (segments intersection) strategy + */ + template <typename Strategy> + static inline bool apply(Geometry1 const& g1, Geometry2 const& g2, Strategy const& strategy) { // if there are intersections - return false - if ( !disjoint_linear<Geometry1, Geometry2>::apply(g1, g2) ) + if ( !disjoint_linear<Geometry1, Geometry2>::apply(g1, g2, strategy) ) { return false; } - return NoIntersectionsPolicy::apply(g1, g2); + return NoIntersectionsPolicy + ::apply(g1, g2, + strategy.template get_point_in_geometry_strategy<Geometry1, Geometry2>()); } }; @@ -126,16 +141,18 @@ template <typename Segment, typename Polygon> class disjoint_segment_areal<Segment, Polygon, polygon_tag> { private: - template <typename InteriorRings> + template <typename InteriorRings, typename Strategy> static inline bool check_interior_rings(InteriorRings const& interior_rings, - Segment const& segment) + Segment const& segment, + Strategy const& strategy) { typedef typename boost::range_value<InteriorRings>::type ring_type; typedef unary_disjoint_geometry_to_query_geometry < Segment, + Strategy, disjoint_range_segment_or_box < ring_type, closure<ring_type>::value, Segment @@ -147,24 +164,27 @@ private: unary_predicate_type >::apply(boost::begin(interior_rings), boost::end(interior_rings), - unary_predicate_type(segment)); + unary_predicate_type(segment, strategy)); } public: - static inline bool apply(Segment const& segment, Polygon const& polygon) + template <typename IntersectionStrategy> + static inline bool apply(Segment const& segment, + Polygon const& polygon, + IntersectionStrategy const& strategy) { typedef typename geometry::ring_type<Polygon>::type ring; if ( !disjoint_range_segment_or_box < ring, closure<Polygon>::value, Segment - >::apply(geometry::exterior_ring(polygon), segment) ) + >::apply(geometry::exterior_ring(polygon), segment, strategy) ) { return false; } - if ( !check_interior_rings(geometry::interior_rings(polygon), segment) ) + if ( !check_interior_rings(geometry::interior_rings(polygon), segment, strategy) ) { return false; } @@ -172,7 +192,8 @@ public: typename point_type<Segment>::type p; detail::assign_point_from_index<0>(segment, p); - return !geometry::covered_by(p, polygon); + return !geometry::covered_by(p, polygon, + strategy.template get_point_in_geometry_strategy<Segment, Polygon>()); } }; @@ -180,13 +201,14 @@ public: template <typename Segment, typename MultiPolygon> struct disjoint_segment_areal<Segment, MultiPolygon, multi_polygon_tag> { - static inline - bool apply(Segment const& segment, MultiPolygon const& multipolygon) + template <typename IntersectionStrategy> + static inline bool apply(Segment const& segment, MultiPolygon const& multipolygon, + IntersectionStrategy const& strategy) { return multirange_constant_size_geometry < MultiPolygon, Segment - >::apply(multipolygon, segment); + >::apply(multipolygon, segment, strategy); } }; @@ -194,20 +216,24 @@ struct disjoint_segment_areal<Segment, MultiPolygon, multi_polygon_tag> template <typename Segment, typename Ring> struct disjoint_segment_areal<Segment, Ring, ring_tag> { - static inline bool apply(Segment const& segment, Ring const& ring) + template <typename IntersectionStrategy> + static inline bool apply(Segment const& segment, + Ring const& ring, + IntersectionStrategy const& strategy) { if ( !disjoint_range_segment_or_box < Ring, closure<Ring>::value, Segment - >::apply(ring, segment) ) + >::apply(ring, segment, strategy) ) { return false; } typename point_type<Segment>::type p; detail::assign_point_from_index<0>(segment, p); - - return !geometry::covered_by(p, ring); + + return !geometry::covered_by(p, ring, + strategy.template get_point_in_geometry_strategy<Segment, Ring>()); } }; @@ -231,14 +257,15 @@ struct disjoint<Linear, Areal, 2, linear_tag, areal_tag, false> template <typename Areal, typename Linear> struct disjoint<Areal, Linear, 2, areal_tag, linear_tag, false> -{ - static inline - bool apply(Areal const& areal, Linear const& linear) +{ + template <typename Strategy> + static inline bool apply(Areal const& areal, Linear const& linear, + Strategy const& strategy) { return detail::disjoint::disjoint_linear_areal < Linear, Areal - >::apply(linear, areal); + >::apply(linear, areal, strategy); } }; @@ -246,12 +273,14 @@ struct disjoint<Areal, Linear, 2, areal_tag, linear_tag, false> template <typename Areal, typename Segment> struct disjoint<Areal, Segment, 2, areal_tag, segment_tag, false> { - static inline bool apply(Areal const& g1, Segment const& g2) + template <typename Strategy> + static inline bool apply(Areal const& g1, Segment const& g2, + Strategy const& strategy) { return detail::disjoint::disjoint_segment_areal < Segment, Areal - >::apply(g2, g1); + >::apply(g2, g1, strategy); } }; diff --git a/boost/geometry/algorithms/detail/disjoint/linear_linear.hpp b/boost/geometry/algorithms/detail/disjoint/linear_linear.hpp index 91f985edb8..989b8df247 100644 --- a/boost/geometry/algorithms/detail/disjoint/linear_linear.hpp +++ b/boost/geometry/algorithms/detail/disjoint/linear_linear.hpp @@ -5,8 +5,8 @@ // Copyright (c) 2009-2014 Mateusz Loskot, London, UK. // Copyright (c) 2013-2014 Adam Wulkiewicz, Lodz, Poland. -// This file was modified by Oracle on 2013-2014. -// Modifications copyright (c) 2013-2014, Oracle and/or its affiliates. +// This file was modified by Oracle on 2013-2017. +// Modifications copyright (c) 2013-2017, Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle @@ -53,7 +53,9 @@ namespace detail { namespace disjoint template <typename Segment1, typename Segment2> struct disjoint_segment { - static inline bool apply(Segment1 const& segment1, Segment2 const& segment2) + template <typename Strategy> + static inline bool apply(Segment1 const& segment1, Segment2 const& segment2, + Strategy const& strategy) { typedef typename point_type<Segment1>::type point_type; @@ -62,23 +64,23 @@ struct disjoint_segment rescale_policy_type robust_policy; typedef segment_intersection_points - < - point_type, - typename segment_ratio_type + < + point_type, + typename segment_ratio_type < point_type, rescale_policy_type >::type - > intersection_return_type; + > intersection_return_type; - intersection_return_type is - = strategy::intersection::relate_cartesian_segments + typedef policies::relate::segments_intersection_points < - policies::relate::segments_intersection_points - < - intersection_return_type - > - >::apply(segment1, segment2, robust_policy); + intersection_return_type + > intersection_policy; + + intersection_return_type is = strategy.apply(segment1, segment2, + intersection_policy(), + robust_policy); return is.count == 0; } @@ -109,8 +111,10 @@ struct assign_disjoint_policy template <typename Geometry1, typename Geometry2> struct disjoint_linear { - static inline - bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2) + template <typename Strategy> + static inline bool apply(Geometry1 const& geometry1, + Geometry2 const& geometry2, + Strategy const& strategy) { typedef typename geometry::point_type<Geometry1>::type point_type; typedef detail::no_rescale_policy rescale_policy_type; @@ -147,7 +151,7 @@ struct disjoint_linear Geometry1, Geometry2, assign_disjoint_policy > >::apply(0, geometry1, 1, geometry2, - rescale_policy_type(), turns, interrupt_policy); + strategy, rescale_policy_type(), turns, interrupt_policy); return !interrupt_policy.has_intersections; } diff --git a/boost/geometry/algorithms/detail/disjoint/linear_segment_or_box.hpp b/boost/geometry/algorithms/detail/disjoint/linear_segment_or_box.hpp index 8d82f7c911..b4c71c8f30 100644 --- a/boost/geometry/algorithms/detail/disjoint/linear_segment_or_box.hpp +++ b/boost/geometry/algorithms/detail/disjoint/linear_segment_or_box.hpp @@ -53,8 +53,10 @@ template > struct disjoint_range_segment_or_box { - static inline - bool apply(Range const& range, SegmentOrBox const& segment_or_box) + template <typename Strategy> + static inline bool apply(Range const& range, + SegmentOrBox const& segment_or_box, + Strategy const& strategy) { typedef typename closeable_view<Range const, Closure>::type view_type; @@ -85,7 +87,8 @@ struct disjoint_range_segment_or_box < point_type, SegmentOrBox >::apply(geometry::range::front<view_type const>(view), - segment_or_box); + segment_or_box, + strategy.template get_point_in_geometry_strategy<Range, SegmentOrBox>()); } else { @@ -99,7 +102,7 @@ struct disjoint_range_segment_or_box if ( !dispatch::disjoint < range_segment, SegmentOrBox - >::apply(rng_segment, segment_or_box) ) + >::apply(rng_segment, segment_or_box, strategy) ) { return false; } diff --git a/boost/geometry/algorithms/detail/disjoint/multipoint_geometry.hpp b/boost/geometry/algorithms/detail/disjoint/multipoint_geometry.hpp index 29e438e546..7c1a93cdb7 100644 --- a/boost/geometry/algorithms/detail/disjoint/multipoint_geometry.hpp +++ b/boost/geometry/algorithms/detail/disjoint/multipoint_geometry.hpp @@ -1,8 +1,9 @@ // Boost.Geometry (aka GGL, Generic Geometry Library) -// Copyright (c) 2014-2015, Oracle and/or its affiliates. +// Copyright (c) 2014-2017, 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 // Licensed under the Boost Software License version 1.0. // http://www.boost.org/users/license.html @@ -14,8 +15,10 @@ #include <vector> #include <boost/range.hpp> +#include <boost/mpl/assert.hpp> #include <boost/geometry/core/assert.hpp> +#include <boost/geometry/core/tag.hpp> #include <boost/geometry/core/tags.hpp> #include <boost/geometry/geometries/box.hpp> @@ -105,36 +108,74 @@ template <typename MultiPoint, typename Linear> class multipoint_linear { private: - // structs for partition -- start - struct expand_box + struct expand_box_point { - template <typename Box, typename Geometry> - static inline void apply(Box& total, Geometry const& geometry) + template <typename Box, typename Point> + static inline void apply(Box& total, Point const& point) { - geometry::expand(total, geometry::return_envelope<Box>(geometry)); + geometry::expand(total, point); } + }; + // TODO: After adding non-cartesian Segment envelope to the library + // this policy should be modified to take envelope strategy. + struct expand_box_segment + { + template <typename Box, typename Segment> + static inline void apply(Box& total, Segment const& segment) + { + geometry::expand(total, geometry::return_envelope<Box>(segment)); + } }; - struct overlaps_box + struct overlaps_box_point { - template <typename Box, typename Geometry> - static inline bool apply(Box const& box, Geometry const& geometry) + template <typename Box, typename Point> + static inline bool apply(Box const& box, Point const& point) { - return ! dispatch::disjoint<Geometry, Box>::apply(geometry, box); + // The default strategy is enough in this case + typedef typename strategy::disjoint::services::default_strategy + < + Point, Box + >::type strategy_type; + return ! dispatch::disjoint<Point, Box>::apply(point, box, strategy_type()); } }; + // TODO: After implementing disjoint Segment/Box for non-cartesian geometries + // this strategy should be passed here. + // TODO: This Segment/Box strategy should somehow be derived from Point/Segment strategy + // which by default is winding containing CS-specific side strategy + // TODO: disjoint Segment/Box will be called in this case which may take + // quite long in non-cartesian CS. So we should consider passing range of bounding boxes + // of segments after calculating them once. + struct overlaps_box_segment + { + template <typename Box, typename Segment> + static inline bool apply(Box const& box, Segment const& segment) + { + typedef typename strategy::disjoint::services::default_strategy + < + Segment, Box + >::type strategy_type; + return ! dispatch::disjoint<Segment, Box>::apply(segment, box, strategy_type()); + } + }; + + template <typename PtSegStrategy> class item_visitor_type { public: - item_visitor_type() : m_intersection_found(false) {} + item_visitor_type(PtSegStrategy const& strategy) + : m_intersection_found(false) + , m_strategy(strategy) + {} template <typename Item1, typename Item2> inline void apply(Item1 const& item1, Item2 const& item2) { if (! m_intersection_found - && ! dispatch::disjoint<Item1, Item2>::apply(item1, item2)) + && ! dispatch::disjoint<Item1, Item2>::apply(item1, item2, m_strategy)) { m_intersection_found = true; } @@ -144,6 +185,7 @@ private: private: bool m_intersection_found; + PtSegStrategy const& m_strategy; }; // structs for partition -- end @@ -172,23 +214,25 @@ private: }; public: - static inline bool apply(MultiPoint const& multipoint, Linear const& linear) + template <typename Strategy> + static inline bool apply(MultiPoint const& multipoint, Linear const& linear, Strategy const& strategy) { - item_visitor_type visitor; + item_visitor_type<Strategy> visitor(strategy); geometry::partition < - geometry::model::box<typename point_type<MultiPoint>::type>, - expand_box, - overlaps_box - >::apply(multipoint, segment_range(linear), visitor); + geometry::model::box<typename point_type<MultiPoint>::type> + >::apply(multipoint, segment_range(linear), visitor, + expand_box_point(), overlaps_box_point(), + expand_box_segment(), overlaps_box_segment()); return ! visitor.intersection_found(); } - static inline bool apply(Linear const& linear, MultiPoint const& multipoint) + template <typename Strategy> + static inline bool apply(Linear const& linear, MultiPoint const& multipoint, Strategy const& strategy) { - return apply(multipoint, linear); + return apply(multipoint, linear, strategy); } }; @@ -240,8 +284,10 @@ struct disjoint multi_point_tag, multi_point_tag, false > { + template <typename Strategy> static inline bool apply(MultiPoint1 const& multipoint1, - MultiPoint2 const& multipoint2) + MultiPoint2 const& multipoint2, + Strategy const& ) { if ( boost::size(multipoint2) < boost::size(multipoint1) ) { diff --git a/boost/geometry/algorithms/detail/disjoint/multirange_geometry.hpp b/boost/geometry/algorithms/detail/disjoint/multirange_geometry.hpp index 78a683e46e..53fb1642af 100644 --- a/boost/geometry/algorithms/detail/disjoint/multirange_geometry.hpp +++ b/boost/geometry/algorithms/detail/disjoint/multirange_geometry.hpp @@ -1,8 +1,9 @@ // Boost.Geometry (aka GGL, Generic Geometry Library) -// Copyright (c) 2014, Oracle and/or its affiliates. +// Copyright (c) 2014-2017, 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 // Licensed under the Boost Software License version 1.0. // http://www.boost.org/users/license.html @@ -25,34 +26,40 @@ namespace detail { namespace disjoint { -template <typename Geometry, typename BinaryPredicate> +template <typename Geometry, typename Strategy, typename BinaryPredicate> class unary_disjoint_geometry_to_query_geometry { public: - unary_disjoint_geometry_to_query_geometry(Geometry const& geometry) + unary_disjoint_geometry_to_query_geometry(Geometry const& geometry, + Strategy const& strategy) : m_geometry(geometry) + , m_strategy(strategy) {} template <typename QueryGeometry> inline bool apply(QueryGeometry const& query_geometry) const { - return BinaryPredicate::apply(query_geometry, m_geometry); + return BinaryPredicate::apply(query_geometry, m_geometry, m_strategy); } private: Geometry const& m_geometry; + Strategy const& m_strategy; }; template<typename MultiRange, typename ConstantSizeGeometry> struct multirange_constant_size_geometry { + template <typename Strategy> static inline bool apply(MultiRange const& multirange, - ConstantSizeGeometry const& constant_size_geometry) + ConstantSizeGeometry const& constant_size_geometry, + Strategy const& strategy) { typedef unary_disjoint_geometry_to_query_geometry < ConstantSizeGeometry, + Strategy, dispatch::disjoint < typename boost::range_value<MultiRange>::type, @@ -64,13 +71,15 @@ struct multirange_constant_size_geometry < unary_predicate_type >::apply(boost::begin(multirange), boost::end(multirange), - unary_predicate_type(constant_size_geometry)); + unary_predicate_type(constant_size_geometry, strategy)); } + template <typename Strategy> static inline bool apply(ConstantSizeGeometry const& constant_size_geometry, - MultiRange const& multirange) + MultiRange const& multirange, + Strategy const& strategy) { - return apply(multirange, constant_size_geometry); + return apply(multirange, constant_size_geometry, strategy); } }; diff --git a/boost/geometry/algorithms/detail/disjoint/point_box.hpp b/boost/geometry/algorithms/detail/disjoint/point_box.hpp index 2f1085ada9..2e6773d221 100644 --- a/boost/geometry/algorithms/detail/disjoint/point_box.hpp +++ b/boost/geometry/algorithms/detail/disjoint/point_box.hpp @@ -5,8 +5,8 @@ // Copyright (c) 2009-2015 Mateusz Loskot, London, UK. // Copyright (c) 2013-2015 Adam Wulkiewicz, Lodz, Poland -// This file was modified by Oracle on 2013-2016. -// Modifications copyright (c) 2013-2016, Oracle and/or its affiliates. +// This file was modified by Oracle on 2013-2017. +// Modifications copyright (c) 2013-2017, Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle @@ -28,7 +28,7 @@ #include <boost/geometry/core/tags.hpp> #include <boost/geometry/algorithms/dispatch/disjoint.hpp> -#include <boost/geometry/strategies/cartesian/point_in_box.hpp> +#include <boost/geometry/strategies/disjoint.hpp> namespace boost { namespace geometry { @@ -44,13 +44,13 @@ namespace detail { namespace disjoint template <typename Point, typename Box> inline bool disjoint_point_box(Point const& point, Box const& box) { + typedef typename strategy::disjoint::services::default_strategy + < + Point, Box + >::type strategy_type; + // ! covered_by(point, box) - return ! strategy::within::relate_point_box_loop - < - strategy::within::covered_by_range, - Point, Box, - 0, dimension<Point>::type::value - >::apply(point, box); + return ! strategy_type::apply(point, box); } @@ -66,15 +66,11 @@ namespace dispatch template <typename Point, typename Box, std::size_t DimensionCount> struct disjoint<Point, Box, DimensionCount, point_tag, box_tag, false> { - static inline bool apply(Point const& point, Box const& box) + template <typename Strategy> + static inline bool apply(Point const& point, Box const& box, Strategy const& ) { // ! covered_by(point, box) - return ! strategy::within::relate_point_box_loop - < - strategy::within::covered_by_range, - Point, Box, - 0, DimensionCount - >::apply(point, box); + return ! Strategy::apply(point, box); } }; diff --git a/boost/geometry/algorithms/detail/disjoint/point_geometry.hpp b/boost/geometry/algorithms/detail/disjoint/point_geometry.hpp index 9ae43f73d0..66bd7c26ce 100644 --- a/boost/geometry/algorithms/detail/disjoint/point_geometry.hpp +++ b/boost/geometry/algorithms/detail/disjoint/point_geometry.hpp @@ -39,11 +39,12 @@ namespace detail { namespace disjoint struct reverse_covered_by { - template <typename Geometry1, typename Geometry2> - static inline - bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2) + template <typename Geometry1, typename Geometry2, typename Strategy> + static inline bool apply(Geometry1 const& geometry1, + Geometry2 const& geometry2, + Strategy const& strategy) { - return ! geometry::covered_by(geometry1, geometry2); + return ! geometry::covered_by(geometry1, geometry2, strategy); } }; diff --git a/boost/geometry/algorithms/detail/disjoint/point_point.hpp b/boost/geometry/algorithms/detail/disjoint/point_point.hpp index 7580b7287b..13ac34d718 100644 --- a/boost/geometry/algorithms/detail/disjoint/point_point.hpp +++ b/boost/geometry/algorithms/detail/disjoint/point_point.hpp @@ -5,8 +5,8 @@ // Copyright (c) 2009-2015 Mateusz Loskot, London, UK. // Copyright (c) 2013-2015 Adam Wulkiewicz, Lodz, Poland -// This file was modified by Oracle on 2013, 2014, 2015. -// Modifications copyright (c) 2013-2015, Oracle and/or its affiliates. +// This file was modified by Oracle on 2013, 2014, 2015, 2017. +// Modifications copyright (c) 2013-2017, Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle @@ -59,6 +59,12 @@ namespace detail { namespace disjoint template <std::size_t Dimension, std::size_t DimensionCount> struct point_point_generic { + template <typename Point1, typename Point2, typename Strategy> + static inline bool apply(Point1 const& p1, Point2 const& p2, Strategy const& ) + { + return apply(p1, p2); + } + template <typename Point1, typename Point2> static inline bool apply(Point1 const& p1, Point2 const& p2) { @@ -75,7 +81,7 @@ template <std::size_t DimensionCount> struct point_point_generic<DimensionCount, DimensionCount> { template <typename Point1, typename Point2> - static inline bool apply(Point1 const&, Point2 const&) + static inline bool apply(Point1 const&, Point2 const& ) { return false; } @@ -135,6 +141,12 @@ private: }; public: + template <typename Point1, typename Point2, typename Strategy> + static inline bool apply(Point1 const& point1, Point2 const& point2, Strategy const& ) + { + return apply(point1, point2); + } + template <typename Point1, typename Point2> static inline bool apply(Point1 const& point1, Point2 const& point2) { diff --git a/boost/geometry/algorithms/detail/disjoint/segment_box.hpp b/boost/geometry/algorithms/detail/disjoint/segment_box.hpp index cc0c7949e3..c2741ce72c 100644 --- a/boost/geometry/algorithms/detail/disjoint/segment_box.hpp +++ b/boost/geometry/algorithms/detail/disjoint/segment_box.hpp @@ -5,8 +5,8 @@ // Copyright (c) 2009-2014 Mateusz Loskot, London, UK. // Copyright (c) 2013-2014 Adam Wulkiewicz, Lodz, Poland. -// This file was modified by Oracle on 2013-2014. -// Modifications copyright (c) 2013-2014, Oracle and/or its affiliates. +// This file was modified by Oracle on 2013-2017. +// Modifications copyright (c) 2013-2017, Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle @@ -22,19 +22,8 @@ #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_SEGMENT_BOX_HPP #include <cstddef> -#include <utility> -#include <boost/numeric/conversion/cast.hpp> - -#include <boost/geometry/util/math.hpp> -#include <boost/geometry/util/calculation_type.hpp> - -#include <boost/geometry/core/access.hpp> #include <boost/geometry/core/tags.hpp> -#include <boost/geometry/core/coordinate_dimension.hpp> -#include <boost/geometry/core/point_type.hpp> - -#include <boost/geometry/algorithms/detail/assign_indexed_point.hpp> #include <boost/geometry/algorithms/dispatch/disjoint.hpp> @@ -47,236 +36,19 @@ namespace boost { namespace geometry namespace detail { namespace disjoint { - -template <std::size_t I> -struct compute_tmin_tmax_per_dim -{ - template <typename SegmentPoint, typename Box, typename RelativeDistance> - static inline void apply(SegmentPoint const& p0, - SegmentPoint const& p1, - Box const& box, - RelativeDistance& ti_min, - RelativeDistance& ti_max, - RelativeDistance& diff) - { - typedef typename coordinate_type<Box>::type box_coordinate_type; - typedef typename coordinate_type - < - SegmentPoint - >::type point_coordinate_type; - - RelativeDistance c_p0 = boost::numeric_cast - < - point_coordinate_type - >( geometry::get<I>(p0) ); - - RelativeDistance c_p1 = boost::numeric_cast - < - point_coordinate_type - >( geometry::get<I>(p1) ); - - RelativeDistance c_b_min = boost::numeric_cast - < - box_coordinate_type - >( geometry::get<geometry::min_corner, I>(box) ); - - RelativeDistance c_b_max = boost::numeric_cast - < - box_coordinate_type - >( geometry::get<geometry::max_corner, I>(box) ); - - if ( geometry::get<I>(p1) >= geometry::get<I>(p0) ) - { - diff = c_p1 - c_p0; - ti_min = c_b_min - c_p0; - ti_max = c_b_max - c_p0; - } - else - { - diff = c_p0 - c_p1; - ti_min = c_p0 - c_b_max; - ti_max = c_p0 - c_b_min; - } - } -}; - - -template -< - typename RelativeDistance, - typename SegmentPoint, - typename Box, - std::size_t I, - std::size_t Dimension -> -struct disjoint_segment_box_impl -{ - template <typename RelativeDistancePair> - static inline bool apply(SegmentPoint const& p0, - SegmentPoint const& p1, - Box const& box, - RelativeDistancePair& t_min, - RelativeDistancePair& t_max) - { - RelativeDistance ti_min, ti_max, diff; - - compute_tmin_tmax_per_dim<I>::apply(p0, p1, box, ti_min, ti_max, diff); - - if ( geometry::math::equals(diff, 0) ) - { - if ( (geometry::math::equals(t_min.second, 0) - && t_min.first > ti_max) - || - (geometry::math::equals(t_max.second, 0) - && t_max.first < ti_min) - || - (math::sign(ti_min) * math::sign(ti_max) > 0) ) - { - return true; - } - } - - RelativeDistance t_min_x_diff = t_min.first * diff; - RelativeDistance t_max_x_diff = t_max.first * diff; - - if ( t_min_x_diff > ti_max * t_min.second - || t_max_x_diff < ti_min * t_max.second ) - { - return true; - } - - if ( ti_min * t_min.second > t_min_x_diff ) - { - t_min.first = ti_min; - t_min.second = diff; - } - if ( ti_max * t_max.second < t_max_x_diff ) - { - t_max.first = ti_max; - t_max.second = diff; - } - - if ( t_min.first > t_min.second || t_max.first < 0 ) - { - return true; - } - - return disjoint_segment_box_impl - < - RelativeDistance, - SegmentPoint, - Box, - I + 1, - Dimension - >::apply(p0, p1, box, t_min, t_max); - } -}; - - -template -< - typename RelativeDistance, - typename SegmentPoint, - typename Box, - std::size_t Dimension -> -struct disjoint_segment_box_impl - < - RelativeDistance, SegmentPoint, Box, 0, Dimension - > -{ - static inline bool apply(SegmentPoint const& p0, - SegmentPoint const& p1, - Box const& box) - { - std::pair<RelativeDistance, RelativeDistance> t_min, t_max; - RelativeDistance diff; - - compute_tmin_tmax_per_dim<0>::apply(p0, p1, box, - t_min.first, t_max.first, diff); - - if ( geometry::math::equals(diff, 0) ) - { - if ( geometry::math::equals(t_min.first, 0) ) { t_min.first = -1; } - if ( geometry::math::equals(t_max.first, 0) ) { t_max.first = 1; } - - if (math::sign(t_min.first) * math::sign(t_max.first) > 0) - { - return true; - } - } - - if ( t_min.first > diff || t_max.first < 0 ) - { - return true; - } - - t_min.second = t_max.second = diff; - - return disjoint_segment_box_impl - < - RelativeDistance, SegmentPoint, Box, 1, Dimension - >::apply(p0, p1, box, t_min, t_max); - } -}; - - -template -< - typename RelativeDistance, - typename SegmentPoint, - typename Box, - std::size_t Dimension -> -struct disjoint_segment_box_impl - < - RelativeDistance, SegmentPoint, Box, Dimension, Dimension - > -{ - template <typename RelativeDistancePair> - static inline bool apply(SegmentPoint const&, SegmentPoint const&, - Box const&, - RelativeDistancePair&, RelativeDistancePair&) - { - return false; - } -}; - - -//========================================================================= - - -template <typename Segment, typename Box> struct disjoint_segment_box -{ - static inline bool apply(Segment const& segment, Box const& box) +{ + template <typename Segment, typename Box, typename Strategy> + static inline bool apply(Segment const& segment, Box const& box, Strategy const& strategy) { - assert_dimension_equal<Segment, Box>(); - - typedef typename util::calculation_type::geometric::binary - < - Segment, Box, void - >::type relative_distance_type; - - typedef typename point_type<Segment>::type segment_point_type; - segment_point_type p0, p1; - geometry::detail::assign_point_from_index<0>(segment, p0); - geometry::detail::assign_point_from_index<1>(segment, p1); - - return disjoint_segment_box_impl - < - relative_distance_type, segment_point_type, Box, - 0, dimension<Box>::value - >::apply(p0, p1, box); + return strategy.apply(segment, box); } }; - }} // namespace detail::disjoint #endif // DOXYGEN_NO_DETAIL - #ifndef DOXYGEN_NO_DISPATCH namespace dispatch { @@ -284,7 +56,7 @@ namespace dispatch template <typename Segment, typename Box, std::size_t DimensionCount> struct disjoint<Segment, Box, DimensionCount, segment_tag, box_tag, false> - : detail::disjoint::disjoint_segment_box<Segment, Box> + : detail::disjoint::disjoint_segment_box {}; diff --git a/boost/geometry/algorithms/detail/envelope/box.hpp b/boost/geometry/algorithms/detail/envelope/box.hpp index 3790262948..795f51392e 100644 --- a/boost/geometry/algorithms/detail/envelope/box.hpp +++ b/boost/geometry/algorithms/detail/envelope/box.hpp @@ -4,9 +4,10 @@ // Copyright (c) 2008-2015 Bruno Lalande, Paris, France. // Copyright (c) 2009-2015 Mateusz Loskot, London, UK. -// This file was modified by Oracle on 2015. -// Modifications copyright (c) 2015, Oracle and/or its affiliates. +// This file was modified by Oracle on 2015, 2016. +// Modifications copyright (c) 2015-2016, Oracle and/or its affiliates. +// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle // Distributed under the Boost Software License, Version 1.0. @@ -97,8 +98,10 @@ struct envelope_indexed_box_on_spheroid struct envelope_box { - template<typename BoxIn, typename BoxOut> - static inline void apply(BoxIn const& box_in, BoxOut& mbr) + template<typename BoxIn, typename BoxOut, typename Strategy> + static inline void apply(BoxIn const& box_in, + BoxOut& mbr, + Strategy const&) { envelope_indexed_box < @@ -115,8 +118,10 @@ struct envelope_box struct envelope_box_on_spheroid { - template <typename BoxIn, typename BoxOut> - static inline void apply(BoxIn const& box_in, BoxOut& mbr) + template <typename BoxIn, typename BoxOut, typename Strategy> + static inline void apply(BoxIn const& box_in, + BoxOut& mbr, + Strategy const&) { BoxIn box_in_normalized = detail::return_normalized<BoxIn>(box_in); diff --git a/boost/geometry/algorithms/detail/envelope/implementation.hpp b/boost/geometry/algorithms/detail/envelope/implementation.hpp index c1dbf8e589..d549700791 100644 --- a/boost/geometry/algorithms/detail/envelope/implementation.hpp +++ b/boost/geometry/algorithms/detail/envelope/implementation.hpp @@ -4,9 +4,10 @@ // Copyright (c) 2008-2015 Bruno Lalande, Paris, France. // Copyright (c) 2009-2015 Mateusz Loskot, London, UK. -// This file was modified by Oracle on 2015. -// Modifications copyright (c) 2015, Oracle and/or its affiliates. +// This file was modified by Oracle on 2015, 2016. +// Modifications copyright (c) 2015-2016, Oracle and/or its affiliates. +// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle // Parts of Boost.Geometry are redesigned from Geodan's Geographic Library @@ -45,8 +46,8 @@ namespace detail { namespace envelope struct envelope_polygon { - template <typename Polygon, typename Box> - static inline void apply(Polygon const& polygon, Box& mbr) + template <typename Polygon, typename Box, typename Strategy> + static inline void apply(Polygon const& polygon, Box& mbr, Strategy const& strategy) { typename ring_return_type<Polygon const>::type ext_ring = exterior_ring(polygon); @@ -57,12 +58,12 @@ struct envelope_polygon envelope_multi_range < envelope_range - >::apply(interior_rings(polygon), mbr); + >::apply(interior_rings(polygon), mbr, strategy); } else { // otherwise, consider only the exterior ring - envelope_range::apply(ext_ring, mbr); + envelope_range::apply(ext_ring, mbr, strategy); } } }; diff --git a/boost/geometry/algorithms/detail/envelope/interface.hpp b/boost/geometry/algorithms/detail/envelope/interface.hpp index befe4e42db..8e9c35b395 100644 --- a/boost/geometry/algorithms/detail/envelope/interface.hpp +++ b/boost/geometry/algorithms/detail/envelope/interface.hpp @@ -4,10 +4,12 @@ // Copyright (c) 2008-2015 Bruno Lalande, Paris, France. // Copyright (c) 2009-2015 Mateusz Loskot, London, UK. -// This file was modified by Oracle on 2015. -// Modifications copyright (c) 2015, Oracle and/or its affiliates. +// This file was modified by Oracle on 2015, 2016, 2017. +// Modifications copyright (c) 2015-2017, Oracle and/or its affiliates. +// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle // 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. @@ -27,54 +29,124 @@ #include <boost/geometry/algorithms/dispatch/envelope.hpp> +#include <boost/geometry/strategies/default_strategy.hpp> +#include <boost/geometry/strategies/envelope.hpp> +#include <boost/geometry/strategies/cartesian/envelope_segment.hpp> +#include <boost/geometry/strategies/spherical/envelope_segment.hpp> +#include <boost/geometry/strategies/geographic/envelope_segment.hpp> namespace boost { namespace geometry { -namespace resolve_variant +namespace resolve_strategy { template <typename Geometry> struct envelope { + template <typename Box, typename Strategy> + static inline void apply(Geometry const& geometry, + Box& box, + Strategy const& strategy) + { + dispatch::envelope<Geometry>::apply(geometry, box, strategy); + } + template <typename Box> - static inline void apply(Geometry const& geometry, Box& box) + static inline void apply(Geometry const& geometry, + Box& box, + default_strategy) + { + typedef typename point_type<Geometry>::type point_type; + typedef typename coordinate_type<point_type>::type coordinate_type; + + typedef typename strategy::envelope::services::default_strategy + < + typename cs_tag<point_type>::type, + coordinate_type + >::type strategy_type; + + dispatch::envelope<Geometry>::apply(geometry, box, strategy_type()); + } +}; + +} // namespace resolve_strategy + +namespace resolve_variant +{ + +template <typename Geometry> +struct envelope +{ + template <typename Box, typename Strategy> + static inline void apply(Geometry const& geometry, + Box& box, + Strategy const& strategy) { concepts::check<Geometry const>(); concepts::check<Box>(); - dispatch::envelope<Geometry>::apply(geometry, box); + resolve_strategy::envelope<Geometry>::apply(geometry, box, strategy); } }; + template <BOOST_VARIANT_ENUM_PARAMS(typename T)> struct envelope<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> > { - template <typename Box> + template <typename Box, typename Strategy> struct visitor: boost::static_visitor<void> { Box& m_box; + Strategy const& m_strategy; - visitor(Box& box): m_box(box) {} + visitor(Box& box, Strategy const& strategy) + : m_box(box) + , m_strategy(strategy) + {} template <typename Geometry> void operator()(Geometry const& geometry) const { - envelope<Geometry>::apply(geometry, m_box); + envelope<Geometry>::apply(geometry, m_box, m_strategy); } }; - template <typename Box> + template <typename Box, typename Strategy> static inline void apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry, - Box& box) + Box& box, + Strategy const& strategy) { - boost::apply_visitor(visitor<Box>(box), geometry); + boost::apply_visitor(visitor<Box, Strategy>(box, strategy), geometry); } }; } // namespace resolve_variant +/*! +\brief \brief_calc{envelope (with strategy)} +\ingroup envelope +\details \details_calc{envelope,\det_envelope}. +\tparam Geometry \tparam_geometry +\tparam Box \tparam_box +\tparam Strategy \tparam_strategy{Envelope} +\param geometry \param_geometry +\param mbr \param_box \param_set{envelope} +\param strategy \param_strategy{envelope} + +\qbk{distinguish,with strategy} +\qbk{[include reference/algorithms/envelope.qbk]} +\qbk{ +[heading Example] +[envelope] [envelope_output] +} +*/ +template<typename Geometry, typename Box, typename Strategy> +inline void envelope(Geometry const& geometry, Box& mbr, Strategy const& strategy) +{ + resolve_variant::envelope<Geometry>::apply(geometry, mbr, strategy); +} /*! \brief \brief_calc{envelope} @@ -94,7 +166,7 @@ struct envelope<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> > template<typename Geometry, typename Box> inline void envelope(Geometry const& geometry, Box& mbr) { - resolve_variant::envelope<Geometry>::apply(geometry, mbr); + resolve_variant::envelope<Geometry>::apply(geometry, mbr, default_strategy()); } @@ -104,6 +176,32 @@ inline void envelope(Geometry const& geometry, Box& mbr) \details \details_calc{return_envelope,\det_envelope}. \details_return{envelope} \tparam Box \tparam_box \tparam Geometry \tparam_geometry +\tparam Strategy \tparam_strategy{Envelope} +\param geometry \param_geometry +\param strategy \param_strategy{envelope} +\return \return_calc{envelope} + +\qbk{distinguish,with strategy} +\qbk{[include reference/algorithms/envelope.qbk]} +\qbk{ +[heading Example] +[return_envelope] [return_envelope_output] +} +*/ +template<typename Box, typename Geometry, typename Strategy> +inline Box return_envelope(Geometry const& geometry, Strategy const& strategy) +{ + Box mbr; + resolve_variant::envelope<Geometry>::apply(geometry, mbr, strategy); + return mbr; +} + +/*! +\brief \brief_calc{envelope} +\ingroup envelope +\details \details_calc{return_envelope,\det_envelope}. \details_return{envelope} +\tparam Box \tparam_box +\tparam Geometry \tparam_geometry \param geometry \param_geometry \return \return_calc{envelope} @@ -117,7 +215,7 @@ template<typename Box, typename Geometry> inline Box return_envelope(Geometry const& geometry) { Box mbr; - resolve_variant::envelope<Geometry>::apply(geometry, mbr); + resolve_variant::envelope<Geometry>::apply(geometry, mbr, default_strategy()); return mbr; } diff --git a/boost/geometry/algorithms/detail/envelope/linear.hpp b/boost/geometry/algorithms/detail/envelope/linear.hpp index 49c3cf3135..09d8a76da5 100644 --- a/boost/geometry/algorithms/detail/envelope/linear.hpp +++ b/boost/geometry/algorithms/detail/envelope/linear.hpp @@ -4,9 +4,10 @@ // Copyright (c) 2008-2015 Bruno Lalande, Paris, France. // Copyright (c) 2009-2015 Mateusz Loskot, London, UK. -// This file was modified by Oracle on 2015. -// Modifications copyright (c) 2015, Oracle and/or its affiliates. +// This file was modified by Oracle on 2015, 2016. +// Modifications copyright (c) 2015-2016, Oracle and/or its affiliates. +// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle // Distributed under the Boost Software License, Version 1.0. @@ -36,12 +37,15 @@ namespace detail { namespace envelope struct envelope_linestring_on_spheroid { - template <typename Linestring, typename Box> - static inline void apply(Linestring const& linestring, Box& mbr) + template <typename Linestring, typename Box, typename Strategy> + static inline void apply(Linestring const& linestring, + Box& mbr, + Strategy const& strategy) { envelope_range::apply(geometry::segments_begin(linestring), geometry::segments_end(linestring), - mbr); + mbr, + strategy); } }; @@ -65,6 +69,11 @@ struct envelope<Linestring, linestring_tag, spherical_equatorial_tag> : detail::envelope::envelope_linestring_on_spheroid {}; +template <typename Linestring> +struct envelope<Linestring, linestring_tag, geographic_tag> + : detail::envelope::envelope_linestring_on_spheroid +{}; + template <typename MultiLinestring, typename CS_Tag> struct envelope @@ -86,6 +95,15 @@ struct envelope > {}; +template <typename MultiLinestring> +struct envelope + < + MultiLinestring, multi_linestring_tag, geographic_tag + > : detail::envelope::envelope_multi_range_on_spheroid + < + detail::envelope::envelope_linestring_on_spheroid + > +{}; } // namespace dispatch #endif // DOXYGEN_NO_DISPATCH diff --git a/boost/geometry/algorithms/detail/envelope/multipoint.hpp b/boost/geometry/algorithms/detail/envelope/multipoint.hpp index 210debfdba..efee4701c9 100644 --- a/boost/geometry/algorithms/detail/envelope/multipoint.hpp +++ b/boost/geometry/algorithms/detail/envelope/multipoint.hpp @@ -1,7 +1,8 @@ // Boost.Geometry (aka GGL, Generic Geometry Library) -// Copyright (c) 2015, Oracle and/or its affiliates. +// Copyright (c) 2015-2016, Oracle and/or its affiliates. +// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle // Distributed under the Boost Software License, Version 1.0. @@ -226,8 +227,8 @@ private: } public: - template <typename MultiPoint, typename Box> - static inline void apply(MultiPoint const& multipoint, Box& mbr) + template <typename MultiPoint, typename Box, typename Strategy> + static inline void apply(MultiPoint const& multipoint, Box& mbr, Strategy const& strategy) { typedef typename point_type<MultiPoint>::type point_type; typedef typename coordinate_type<MultiPoint>::type coordinate_type; @@ -255,7 +256,7 @@ public: return dispatch::envelope < typename boost::range_value<MultiPoint>::type - >::apply(range::front(multipoint), mbr); + >::apply(range::front(multipoint), mbr, strategy); } // analyze the points and put the non-pole ones in the @@ -329,7 +330,7 @@ public: // compute envelope for higher coordinates iterator_type it = boost::begin(multipoint); - envelope_one_point<2, dimension<Box>::value>::apply(*it, mbr); + envelope_one_point<2, dimension<Box>::value>::apply(*it, mbr, strategy); for (++it; it != boost::end(multipoint); ++it) { @@ -338,7 +339,7 @@ public: strategy::compare::default_strategy, strategy::compare::default_strategy, 2, dimension<Box>::value - >::apply(mbr, *it); + >::apply(mbr, *it, strategy); } } }; diff --git a/boost/geometry/algorithms/detail/envelope/point.hpp b/boost/geometry/algorithms/detail/envelope/point.hpp index e914e7e8a0..ee0559bf5f 100644 --- a/boost/geometry/algorithms/detail/envelope/point.hpp +++ b/boost/geometry/algorithms/detail/envelope/point.hpp @@ -4,9 +4,10 @@ // Copyright (c) 2008-2015 Bruno Lalande, Paris, France. // Copyright (c) 2009-2015 Mateusz Loskot, London, UK. -// This file was modified by Oracle on 2015. -// Modifications copyright (c) 2015, Oracle and/or its affiliates. +// This file was modified by Oracle on 2015, 2016. +// Modifications copyright (c) 2015-2016, Oracle and/or its affiliates. +// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle // Distributed under the Boost Software License, Version 1.0. @@ -58,8 +59,8 @@ struct envelope_one_point >::apply(point, box_corner); } - template <typename Point, typename Box> - static inline void apply(Point const& point, Box& mbr) + template <typename Point, typename Box, typename Strategy> + static inline void apply(Point const& point, Box& mbr, Strategy const&) { apply<min_corner>(point, mbr); apply<max_corner>(point, mbr); @@ -69,8 +70,8 @@ struct envelope_one_point struct envelope_point_on_spheroid { - template<typename Point, typename Box> - static inline void apply(Point const& point, Box& mbr) + template<typename Point, typename Box, typename Strategy> + static inline void apply(Point const& point, Box& mbr, Strategy const& strategy) { Point normalized_point = detail::return_normalized<Point>(point); @@ -88,7 +89,7 @@ struct envelope_point_on_spheroid envelope_one_point < 2, dimension<Point>::value - >::apply(normalized_point, mbr); + >::apply(normalized_point, mbr, strategy); } }; diff --git a/boost/geometry/algorithms/detail/envelope/range.hpp b/boost/geometry/algorithms/detail/envelope/range.hpp index 63b518114b..b5591f61ab 100644 --- a/boost/geometry/algorithms/detail/envelope/range.hpp +++ b/boost/geometry/algorithms/detail/envelope/range.hpp @@ -4,9 +4,10 @@ // Copyright (c) 2008-2015 Bruno Lalande, Paris, France. // Copyright (c) 2009-2015 Mateusz Loskot, London, UK. -// This file was modified by Oracle on 2015. -// Modifications copyright (c) 2015, Oracle and/or its affiliates. +// This file was modified by Oracle on 2015, 2016. +// Modifications copyright (c) 2015-2016, Oracle and/or its affiliates. +// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle // Parts of Boost.Geometry are redesigned from Geodan's Geographic Library @@ -51,8 +52,11 @@ namespace detail { namespace envelope // implementation for simple ranges struct envelope_range { - template <typename Iterator, typename Box> - static inline void apply(Iterator first, Iterator last, Box& mbr) + template <typename Iterator, typename Box, typename Strategy> + static inline void apply(Iterator first, + Iterator last, + Box& mbr, + Strategy const& strategy) { typedef typename std::iterator_traits<Iterator>::value_type value_type; @@ -63,20 +67,20 @@ struct envelope_range if (it != last) { // initialize box with first element in range - dispatch::envelope<value_type>::apply(*it, mbr); + dispatch::envelope<value_type>::apply(*it, mbr, strategy); // consider now the remaining elements in the range (if any) for (++it; it != last; ++it) { - dispatch::expand<Box, value_type>::apply(mbr, *it); + dispatch::expand<Box, value_type>::apply(mbr, *it, strategy); } } } - template <typename Range, typename Box> - static inline void apply(Range const& range, Box& mbr) + template <typename Range, typename Box, typename Strategy> + static inline void apply(Range const& range, Box& mbr, Strategy const& strategy) { - return apply(boost::begin(range), boost::end(range), mbr); + return apply(boost::begin(range), boost::end(range), mbr, strategy); } }; @@ -85,8 +89,10 @@ struct envelope_range template <typename EnvelopePolicy> struct envelope_multi_range { - template <typename MultiRange, typename Box> - static inline void apply(MultiRange const& multirange, Box& mbr) + template <typename MultiRange, typename Box, typename Strategy> + static inline void apply(MultiRange const& multirange, + Box& mbr, + Strategy const& strategy) { typedef typename boost::range_iterator < @@ -103,14 +109,14 @@ struct envelope_multi_range if (initialized) { Box helper_mbr; - EnvelopePolicy::apply(*it, helper_mbr); + EnvelopePolicy::apply(*it, helper_mbr, strategy); - dispatch::expand<Box, Box>::apply(mbr, helper_mbr); + dispatch::expand<Box, Box>::apply(mbr, helper_mbr, strategy); } else { // compute the initial envelope - EnvelopePolicy::apply(*it, mbr); + EnvelopePolicy::apply(*it, mbr, strategy); initialized = true; } } @@ -129,8 +135,10 @@ struct envelope_multi_range template <typename EnvelopePolicy> struct envelope_multi_range_on_spheroid { - template <typename MultiRange, typename Box> - static inline void apply(MultiRange const& multirange, Box& mbr) + template <typename MultiRange, typename Box, typename Strategy> + static inline void apply(MultiRange const& multirange, + Box& mbr, + Strategy const& strategy) { typedef typename boost::range_iterator < @@ -147,7 +155,7 @@ struct envelope_multi_range_on_spheroid if (! geometry::is_empty(*it)) { Box helper_box; - EnvelopePolicy::apply(*it, helper_box); + EnvelopePolicy::apply(*it, helper_box, strategy); boxes.push_back(helper_box); } } @@ -159,7 +167,7 @@ struct envelope_multi_range_on_spheroid // and the MBR is simply initialized if (! boxes.empty()) { - envelope_range_of_boxes::apply(boxes, mbr); + envelope_range_of_boxes::apply(boxes, mbr, strategy); } else { diff --git a/boost/geometry/algorithms/detail/envelope/range_of_boxes.hpp b/boost/geometry/algorithms/detail/envelope/range_of_boxes.hpp index 64bdb9b9cb..f61fc422de 100644 --- a/boost/geometry/algorithms/detail/envelope/range_of_boxes.hpp +++ b/boost/geometry/algorithms/detail/envelope/range_of_boxes.hpp @@ -1,7 +1,8 @@ // Boost.Geometry (aka GGL, Generic Geometry Library) -// Copyright (c) 2015, Oracle and/or its affiliates. +// Copyright (c) 2015-2016, Oracle and/or its affiliates. +// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle // Distributed under the Boost Software License, Version 1.0. @@ -149,8 +150,10 @@ struct envelope_range_of_longitudes template <std::size_t Dimension, std::size_t DimensionCount> struct envelope_range_of_boxes_by_expansion { - template <typename RangeOfBoxes, typename Box> - static inline void apply(RangeOfBoxes const& range_of_boxes, Box& mbr) + template <typename RangeOfBoxes, typename Box, typename Strategy> + static inline void apply(RangeOfBoxes const& range_of_boxes, + Box& mbr, + Strategy const& strategy) { typedef typename boost::range_value<RangeOfBoxes>::type box_type; @@ -196,7 +199,7 @@ struct envelope_range_of_boxes_by_expansion min_corner, Dimension, DimensionCount - >::apply(mbr, *it); + >::apply(mbr, *it, strategy); detail::expand::indexed_loop < @@ -205,7 +208,7 @@ struct envelope_range_of_boxes_by_expansion max_corner, Dimension, DimensionCount - >::apply(mbr, *it); + >::apply(mbr, *it, strategy); } } @@ -225,8 +228,10 @@ struct envelope_range_of_boxes } }; - template <typename RangeOfBoxes, typename Box> - static inline void apply(RangeOfBoxes const& range_of_boxes, Box& mbr) + template <typename RangeOfBoxes, typename Box, typename Strategy> + static inline void apply(RangeOfBoxes const& range_of_boxes, + Box& mbr, + Strategy const& strategy) { // boxes in the range are assumed to be normalized already @@ -313,7 +318,7 @@ struct envelope_range_of_boxes envelope_range_of_boxes_by_expansion < 2, dimension<Box>::value - >::apply(range_of_boxes, mbr); + >::apply(range_of_boxes, mbr, strategy); } }; diff --git a/boost/geometry/algorithms/detail/envelope/segment.hpp b/boost/geometry/algorithms/detail/envelope/segment.hpp index 6186e72a3a..7631e84883 100644 --- a/boost/geometry/algorithms/detail/envelope/segment.hpp +++ b/boost/geometry/algorithms/detail/envelope/segment.hpp @@ -4,9 +4,10 @@ // Copyright (c) 2008-2015 Bruno Lalande, Paris, France. // Copyright (c) 2009-2015 Mateusz Loskot, London, UK. -// This file was modified by Oracle on 2015, 2016. -// Modifications copyright (c) 2015-2016, Oracle and/or its affiliates. +// This file was modified by Oracle on 2015-2017. +// Modifications copyright (c) 2015-2017, Oracle and/or its affiliates. +// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle @@ -26,6 +27,7 @@ #include <boost/geometry/core/coordinate_system.hpp> #include <boost/geometry/core/coordinate_type.hpp> #include <boost/geometry/core/cs.hpp> +#include <boost/geometry/core/srs.hpp> #include <boost/geometry/core/point_type.hpp> #include <boost/geometry/core/radian_access.hpp> #include <boost/geometry/core/tags.hpp> @@ -34,10 +36,9 @@ #include <boost/geometry/geometries/helper_geometry.hpp> -#include <boost/geometry/strategies/compare.hpp> +#include <boost/geometry/formulas/vertex_latitude.hpp> #include <boost/geometry/algorithms/detail/assign_indexed_point.hpp> -#include <boost/geometry/algorithms/detail/normalize.hpp> #include <boost/geometry/algorithms/detail/envelope/point.hpp> #include <boost/geometry/algorithms/detail/envelope/transform_units.hpp> @@ -46,7 +47,6 @@ #include <boost/geometry/algorithms/dispatch/envelope.hpp> - namespace boost { namespace geometry { @@ -54,63 +54,36 @@ namespace boost { namespace geometry namespace detail { namespace envelope { - -template <std::size_t Dimension, std::size_t DimensionCount> -struct envelope_one_segment +template <typename CalculationType, typename CS_Tag> +struct envelope_segment_call_vertex_latitude { - template<typename Point, typename Box> - static inline void apply(Point const& p1, Point const& p2, Box& mbr) + template <typename T1, typename T2, typename Strategy> + static inline CalculationType apply(T1 const& lat1, + T2 const& alp1, + Strategy const& ) { - envelope_one_point<Dimension, DimensionCount>::apply(p1, mbr); - detail::expand::point_loop - < - strategy::compare::default_strategy, - strategy::compare::default_strategy, - Dimension, - DimensionCount - >::apply(mbr, p2); + return geometry::formula::vertex_latitude<CalculationType, CS_Tag> + ::apply(lat1, alp1); } }; - -// Computes the MBR of a segment given by (lon1, lat1) and (lon2, -// lat2), and with azimuths a1 and a2 at the two endpoints of the -// segment. -// It is assumed that the spherical coordinates of the segment are -// normalized and in radians. -// The longitudes and latitudes of the endpoints are overridden by -// those of the box. -class compute_mbr_of_segment +template <typename CalculationType> +struct envelope_segment_call_vertex_latitude<CalculationType, geographic_tag> { -private: - // computes the azimuths of the segment with endpoints (lon1, lat1) - // and (lon2, lat2) - // radians - template <typename CalculationType> - static inline void azimuths(CalculationType const& lon1, - CalculationType const& lat1, - CalculationType const& lon2, - CalculationType const& lat2, - CalculationType& a1, - CalculationType& a2) + template <typename T1, typename T2, typename Strategy> + static inline CalculationType apply(T1 const& lat1, + T2 const& alp1, + Strategy const& strategy) { - BOOST_GEOMETRY_ASSERT(lon1 <= lon2); - - CalculationType dlon = lon2 - lon1; - CalculationType sin_dlon = sin(dlon); - CalculationType cos_dlon = cos(dlon); - CalculationType cos_lat1 = cos(lat1); - CalculationType cos_lat2 = cos(lat2); - CalculationType sin_lat1 = sin(lat1); - CalculationType sin_lat2 = sin(lat2); - - a1 = atan2(sin_dlon * cos_lat2, - cos_lat1 * sin_lat2 - sin_lat1 * cos_lat2 * cos_dlon); - - a2 = atan2(-sin_dlon * cos_lat1, - cos_lat2 * sin_lat1 - sin_lat2 * cos_lat1 * cos_dlon); - a2 += math::pi<CalculationType>(); + return geometry::formula::vertex_latitude<CalculationType, geographic_tag> + ::apply(lat1, alp1, strategy.model()); } +}; + +template <typename CS_Tag> +class envelope_segment_impl +{ +private: // degrees or radians template <typename CalculationType> @@ -134,8 +107,8 @@ private: static CalculationType const pi_half = math::half_pi<CalculationType>(); return (a1 < a2) - ? (a1 < pi_half && pi_half < a2) - : (a1 > pi_half && pi_half > a2); + ? (a1 < pi_half && pi_half < a2) + : (a1 > pi_half && pi_half > a2); } // radians or degrees @@ -151,21 +124,13 @@ private: return math::abs(lon1 - lon2) > constants::half_period(); // > pi } - // radians - template <typename CalculationType> - static inline CalculationType max_latitude(CalculationType const& azimuth, - CalculationType const& latitude) - { - // azimuth and latitude are assumed to be in radians - return acos( math::abs(cos(latitude) * sin(azimuth)) ); - } - // degrees or radians - template <typename Units, typename CalculationType> + template <typename Units, typename CalculationType, typename Strategy> static inline void compute_box_corners(CalculationType& lon1, CalculationType& lat1, CalculationType& lon2, - CalculationType& lat2) + CalculationType& lat2, + Strategy const& strategy) { // coordinates are assumed to be in radians BOOST_GEOMETRY_ASSERT(lon1 <= lon2); @@ -175,13 +140,14 @@ private: CalculationType lon2_rad = math::as_radian<Units>(lon2); CalculationType lat2_rad = math::as_radian<Units>(lat2); - CalculationType a1 = 0, a2 = 0; - azimuths(lon1_rad, lat1_rad, lon2_rad, lat2_rad, a1, a2); + CalculationType a1, a2; + strategy.apply(lon1_rad, lat1_rad, lon2_rad, lat2_rad, a1, a2); if (lat1 > lat2) { std::swap(lat1, lat2); std::swap(lat1_rad, lat2_rad); + std::swap(a1, a2); } if (math::equals(a1, a2)) @@ -192,12 +158,16 @@ private: if (contains_pi_half(a1, a2)) { + CalculationType p_max = envelope_segment_call_vertex_latitude + <CalculationType, CS_Tag>::apply(lat1_rad, a1, strategy); + CalculationType const mid_lat = lat1 + lat2; if (mid_lat < 0) { // update using min latitude - CalculationType const lat_min_rad = -max_latitude(a1, lat1_rad); - CalculationType const lat_min = math::from_radian<Units>(lat_min_rad); + CalculationType const lat_min_rad = -p_max; + CalculationType const lat_min + = math::from_radian<Units>(lat_min_rad); if (lat1 > lat_min) { @@ -207,8 +177,9 @@ private: else if (mid_lat > 0) { // update using max latitude - CalculationType const lat_max_rad = max_latitude(a1, lat1_rad); - CalculationType const lat_max = math::from_radian<Units>(lat_max_rad); + CalculationType const lat_max_rad = p_max; + CalculationType const lat_max + = math::from_radian<Units>(lat_max_rad); if (lat2 < lat_max) { @@ -218,11 +189,12 @@ private: } } - template <typename Units, typename CalculationType> + template <typename Units, typename CalculationType, typename Strategy> static inline void apply(CalculationType& lon1, CalculationType& lat1, CalculationType& lon2, - CalculationType& lat2) + CalculationType& lat2, + Strategy const& strategy) { typedef math::detail::constants_on_spheroid < @@ -278,16 +250,22 @@ private: swap(lon1, lat1, lon2, lat2); } - compute_box_corners<Units>(lon1, lat1, lon2, lat2); + compute_box_corners<Units>(lon1, lat1, lon2, lat2, strategy); } public: - template <typename Units, typename CalculationType, typename Box> + template < + typename Units, + typename CalculationType, + typename Box, + typename Strategy + > static inline void apply(CalculationType lon1, CalculationType lat1, CalculationType lon2, CalculationType lat2, - Box& mbr) + Box& mbr, + Strategy const& strategy) { typedef typename coordinate_type<Box>::type box_coordinate_type; @@ -298,7 +276,7 @@ public: helper_box_type radian_mbr; - apply<Units>(lon1, lat1, lon2, lat2); + apply<Units>(lon1, lat1, lon2, lat2, strategy); geometry::set < @@ -324,29 +302,42 @@ public: } }; +template <std::size_t Dimension, std::size_t DimensionCount> +struct envelope_one_segment +{ + template<typename Point, typename Box, typename Strategy> + static inline void apply(Point const& p1, + Point const& p2, + Box& mbr, + Strategy const& strategy) + { + envelope_one_point<Dimension, DimensionCount>::apply(p1, mbr, strategy); + detail::expand::point_loop + < + strategy::compare::default_strategy, + strategy::compare::default_strategy, + Dimension, + DimensionCount + >::apply(mbr, p2, strategy); + } +}; + template <std::size_t DimensionCount> -struct envelope_segment_on_sphere +struct envelope_segment { - template <typename Point, typename Box> - static inline void apply(Point const& p1, Point const& p2, Box& mbr) + template <typename Point, typename Box, typename Strategy> + static inline void apply(Point const& p1, + Point const& p2, + Box& mbr, + Strategy const& strategy) { // first compute the envelope range for the first two coordinates - Point p1_normalized = detail::return_normalized<Point>(p1); - Point p2_normalized = detail::return_normalized<Point>(p2); - - typedef typename coordinate_system<Point>::type::units units_type; - - compute_mbr_of_segment::template apply<units_type>( - geometry::get<0>(p1_normalized), - geometry::get<1>(p1_normalized), - geometry::get<0>(p2_normalized), - geometry::get<1>(p2_normalized), - mbr); + strategy.apply(p1, p2, mbr); // now compute the envelope range for coordinates of // dimension 2 and higher - envelope_one_segment<2, DimensionCount>::apply(p1, p2, mbr); + envelope_one_segment<2, DimensionCount>::apply(p1, p2, mbr, strategy); } template <typename Segment, typename Box> @@ -359,21 +350,6 @@ struct envelope_segment_on_sphere } }; - - -template <std::size_t DimensionCount, typename CS_Tag> -struct envelope_segment - : envelope_one_segment<0, DimensionCount> -{}; - - -template <std::size_t DimensionCount> -struct envelope_segment<DimensionCount, spherical_equatorial_tag> - : envelope_segment_on_sphere<DimensionCount> -{}; - - - }} // namespace detail::envelope #endif // DOXYGEN_NO_DETAIL @@ -383,23 +359,24 @@ namespace dispatch { -template <typename Segment, typename CS_Tag> -struct envelope<Segment, segment_tag, CS_Tag> +template <typename Segment> +struct envelope<Segment, segment_tag> { - template <typename Box> - static inline void apply(Segment const& segment, Box& mbr) + template <typename Box, typename Strategy> + static inline void apply(Segment const& segment, + Box& mbr, + Strategy const& strategy) { typename point_type<Segment>::type p[2]; detail::assign_point_from_index<0>(segment, p[0]); detail::assign_point_from_index<1>(segment, p[1]); detail::envelope::envelope_segment < - dimension<Segment>::value, CS_Tag - >::apply(p[0], p[1], mbr); + dimension<Segment>::value + >::apply(p[0], p[1], mbr, strategy); } }; - } // namespace dispatch #endif // DOXYGEN_NO_DISPATCH diff --git a/boost/geometry/algorithms/detail/equals/collect_vectors.hpp b/boost/geometry/algorithms/detail/equals/collect_vectors.hpp index eab73ea680..9625f18426 100644 --- a/boost/geometry/algorithms/detail/equals/collect_vectors.hpp +++ b/boost/geometry/algorithms/detail/equals/collect_vectors.hpp @@ -3,7 +3,12 @@ // Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands. // Copyright (c) 2008-2014 Bruno Lalande, Paris, France. // Copyright (c) 2009-2014 Mateusz Loskot, London, UK. -// Copyright (c) 2014 Adam Wulkiewicz, Lodz, Poland. +// Copyright (c) 2014-2017 Adam Wulkiewicz, Lodz, Poland. + +// This file was modified by Oracle on 2017. +// Modifications copyright (c) 2017 Oracle and/or its affiliates. + +// 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 +25,7 @@ #include <boost/geometry/algorithms/detail/interior_iterator.hpp> #include <boost/geometry/algorithms/detail/normalize.hpp> +#include <boost/geometry/algorithms/not_implemented.hpp> #include <boost/geometry/core/cs.hpp> #include <boost/geometry/core/interior_rings.hpp> @@ -32,21 +38,37 @@ #include <boost/geometry/util/math.hpp> #include <boost/geometry/util/range.hpp> +#include <boost/geometry/views/detail/normalized_view.hpp> + +#include <boost/geometry/strategies/cartesian/side_by_triangle.hpp> +#include <boost/geometry/strategies/spherical/ssf.hpp> + namespace boost { namespace geometry { +// TODO: dispatch only by SideStrategy instead of Geometry/CSTag? + // Since these vectors (though ray would be a better name) are used in the // implementation of equals() for Areal geometries the internal representation -// should be consistent with the default side strategy for CS because currently -// it's used in other relops. - -template < +// should be consistent with the side strategy. +template +< typename T, typename Geometry, + typename SideStrategy, typename CSTag = typename cs_tag<Geometry>::type > struct collected_vector + : nyi::not_implemented_tag +{}; + +// compatible with side_by_triangle cartesian strategy +template <typename T, typename Geometry, typename CT, typename CSTag> +struct collected_vector + < + T, Geometry, strategy::side::side_by_triangle<CT>, CSTag + > { typedef T type; @@ -136,8 +158,13 @@ private: //T dx_0, dy_0; }; -template <typename T, typename Geometry> -struct collected_vector<T, Geometry, spherical_equatorial_tag> +// Compatible with spherical_side_formula which currently +// is the default spherical and geographical strategy +template <typename T, typename Geometry, typename CT, typename CSTag> +struct collected_vector + < + T, Geometry, strategy::side::spherical_side_formula<CT>, CSTag + > { typedef T type; @@ -232,11 +259,27 @@ private: vector_type next; // used for collinearity check }; -template <typename T, typename Geometry> -struct collected_vector<T, Geometry, spherical_polar_tag> - : public collected_vector<T, Geometry, spherical_equatorial_tag> +// Specialization for spherical polar +template <typename T, typename Geometry, typename CT> +struct collected_vector + < + T, Geometry, + strategy::side::spherical_side_formula<CT>, + spherical_polar_tag + > + : public collected_vector + < + T, Geometry, + strategy::side::spherical_side_formula<CT>, + spherical_equatorial_tag + > { - typedef collected_vector<T, Geometry, spherical_equatorial_tag> base_type; + typedef collected_vector + < + T, Geometry, + strategy::side::spherical_side_formula<CT>, + spherical_equatorial_tag + > base_type; collected_vector() {} @@ -265,24 +308,6 @@ private: } }; -// This is consistent with the currently used default geographic side -// and intersection strategies. Spherical strategies are used by default. -// When default strategies are changed in the future this specialization -// should be changed too. -template <typename T, typename Geometry> -struct collected_vector<T, Geometry, geographic_tag> - : public collected_vector<T, Geometry, spherical_equatorial_tag> -{ - typedef collected_vector<T, Geometry, spherical_equatorial_tag> base_type; - - collected_vector() {} - - template <typename Point> - collected_vector(Point const& p1, Point const& p2) - : base_type(p1, p2) - {} -}; - #ifndef DOXYGEN_NO_DETAIL namespace detail { namespace collect_vectors @@ -297,6 +322,18 @@ struct range_collect_vectors static inline void apply(Collection& collection, Range const& range) { + typedef geometry::detail::normalized_view + < + Range const + > normalized_range_type; + + apply_impl(collection, normalized_range_type(range)); + } + +private: + template <typename NormalizedRange> + static inline void apply_impl(Collection& collection, NormalizedRange const& range) + { if (boost::size(range) < 2) { return; @@ -305,7 +342,7 @@ struct range_collect_vectors typedef typename boost::range_size<Collection>::type collection_size_t; collection_size_t c_old_size = boost::size(collection); - typedef typename boost::range_iterator<Range const>::type iterator; + typedef typename boost::range_iterator<NormalizedRange const>::type iterator; bool is_first = true; iterator it = boost::begin(range); diff --git a/boost/geometry/algorithms/detail/expand/box.hpp b/boost/geometry/algorithms/detail/expand/box.hpp index 4c89e6f1d4..3edb23f5ae 100644 --- a/boost/geometry/algorithms/detail/expand/box.hpp +++ b/boost/geometry/algorithms/detail/expand/box.hpp @@ -5,9 +5,10 @@ // Copyright (c) 2009-2015 Mateusz Loskot, London, UK. // Copyright (c) 2014-2015 Samuel Debionne, Grenoble, France. -// This file was modified by Oracle on 2015. -// Modifications copyright (c) 2015, Oracle and/or its affiliates. +// This file was modified by Oracle on 2015, 2016. +// Modifications copyright (c) 2015-2016, Oracle and/or its affiliates. +// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle // Distributed under the Boost Software License, Version 1.0. @@ -44,16 +45,18 @@ namespace detail { namespace expand struct box_on_spheroid { - template <typename BoxOut, typename BoxIn> - static inline void apply(BoxOut& box_out, BoxIn const& box_in) + template <typename BoxOut, typename BoxIn, typename Strategy> + static inline void apply(BoxOut& box_out, + BoxIn const& box_in, + Strategy const& strategy) { // normalize both boxes and convert box-in to be of type of box-out BoxOut mbrs[2]; - detail::envelope::envelope_box_on_spheroid::apply(box_in, mbrs[0]); - detail::envelope::envelope_box_on_spheroid::apply(box_out, mbrs[1]); + detail::envelope::envelope_box_on_spheroid::apply(box_in, mbrs[0], strategy); + detail::envelope::envelope_box_on_spheroid::apply(box_out, mbrs[1], strategy); // compute the envelope of the two boxes - detail::envelope::envelope_range_of_boxes::apply(mbrs, box_out); + detail::envelope::envelope_range_of_boxes::apply(mbrs, box_out, strategy); } }; diff --git a/boost/geometry/algorithms/detail/expand/indexed.hpp b/boost/geometry/algorithms/detail/expand/indexed.hpp index bdd6eb4506..28cf0e2e4f 100644 --- a/boost/geometry/algorithms/detail/expand/indexed.hpp +++ b/boost/geometry/algorithms/detail/expand/indexed.hpp @@ -5,9 +5,10 @@ // Copyright (c) 2009-2015 Mateusz Loskot, London, UK. // Copyright (c) 2014-2015 Samuel Debionne, Grenoble, France. -// This file was modified by Oracle on 2015. -// Modifications copyright (c) 2015, Oracle and/or its affiliates. +// This file was modified by Oracle on 2015, 2016. +// Modifications copyright (c) 2015-2016, Oracle and/or its affiliates. +// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle // Parts of Boost.Geometry are redesigned from Geodan's Geographic Library @@ -49,8 +50,8 @@ template > struct indexed_loop { - template <typename Box, typename Geometry> - static inline void apply(Box& box, Geometry const& source) + template <typename Box, typename Geometry, typename Strategy> + static inline void apply(Box& box, Geometry const& source, Strategy const& strategy) { typedef typename strategy::compare::detail::select_strategy < @@ -87,7 +88,7 @@ struct indexed_loop < StrategyLess, StrategyGreater, Index, Dimension + 1, DimensionCount - >::apply(box, source); + >::apply(box, source, strategy); } }; @@ -103,8 +104,8 @@ struct indexed_loop Index, DimensionCount, DimensionCount > { - template <typename Box, typename Geometry> - static inline void apply(Box&, Geometry const&) {} + template <typename Box, typename Geometry, typename Strategy> + static inline void apply(Box&, Geometry const&, Strategy const&) {} }; @@ -117,20 +118,22 @@ template > struct expand_indexed { - template <typename Box, typename Geometry> - static inline void apply(Box& box, Geometry const& geometry) + template <typename Box, typename Geometry, typename Strategy> + static inline void apply(Box& box, + Geometry const& geometry, + Strategy const& strategy) { indexed_loop < StrategyLess, StrategyGreater, 0, Dimension, DimensionCount - >::apply(box, geometry); + >::apply(box, geometry, strategy); indexed_loop < StrategyLess, StrategyGreater, 1, Dimension, DimensionCount - >::apply(box, geometry); + >::apply(box, geometry, strategy); } }; diff --git a/boost/geometry/algorithms/detail/expand/interface.hpp b/boost/geometry/algorithms/detail/expand/interface.hpp index 140754af4e..5aacd8e72a 100644 --- a/boost/geometry/algorithms/detail/expand/interface.hpp +++ b/boost/geometry/algorithms/detail/expand/interface.hpp @@ -5,9 +5,10 @@ // Copyright (c) 2009-2015 Mateusz Loskot, London, UK. // Copyright (c) 2014-2015 Samuel Debionne, Grenoble, France. -// This file was modified by Oracle on 2015. -// Modifications copyright (c) 2015, Oracle and/or its affiliates. +// This file was modified by Oracle on 2015, 2016. +// Modifications copyright (c) 2015-2016, Oracle and/or its affiliates. +// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle // Parts of Boost.Geometry are redesigned from Geodan's Geographic Library @@ -28,10 +29,50 @@ #include <boost/geometry/algorithms/dispatch/expand.hpp> +#include <boost/geometry/strategies/default_strategy.hpp> + +#include <boost/geometry/strategies/envelope.hpp> +#include <boost/geometry/strategies/cartesian/envelope_segment.hpp> +#include <boost/geometry/strategies/spherical/envelope_segment.hpp> +#include <boost/geometry/strategies/geographic/envelope_segment.hpp> namespace boost { namespace geometry { +namespace resolve_strategy +{ + +template <typename Geometry> +struct expand +{ + template <typename Box, typename Strategy> + static inline void apply(Box& box, + Geometry const& geometry, + Strategy const& strategy) + { + dispatch::expand<Box, Geometry>::apply(box, geometry, strategy); + } + + template <typename Box> + static inline void apply(Box& box, + Geometry const& geometry, + default_strategy) + { + typedef typename point_type<Geometry>::type point_type; + typedef typename coordinate_type<point_type>::type coordinate_type; + + typedef typename strategy::envelope::services::default_strategy + < + typename cs_tag<point_type>::type, + coordinate_type + >::type strategy_type; + + dispatch::expand<Box, Geometry>::apply(box, geometry, strategy_type()); + } +}; + +} //namespace resolve_strategy + namespace resolve_variant { @@ -39,40 +80,48 @@ namespace resolve_variant template <typename Geometry> struct expand { - template <typename Box> - static inline void apply(Box& box, Geometry const& geometry) + template <typename Box, typename Strategy> + static inline void apply(Box& box, + Geometry const& geometry, + Strategy const& strategy) { concepts::check<Box>(); concepts::check<Geometry const>(); concepts::check_concepts_and_equal_dimensions<Box, Geometry const>(); - dispatch::expand<Box, Geometry>::apply(box, geometry); + resolve_strategy::expand<Geometry>::apply(box, geometry, strategy); } }; template <BOOST_VARIANT_ENUM_PARAMS(typename T)> struct expand<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> > { - template <typename Box> + template <typename Box, typename Strategy> struct visitor: boost::static_visitor<void> { Box& m_box; + Strategy const& m_strategy; - visitor(Box& box) : m_box(box) {} + visitor(Box& box, Strategy const& strategy) + : m_box(box) + , m_strategy(strategy) + {} template <typename Geometry> void operator()(Geometry const& geometry) const { - return expand<Geometry>::apply(m_box, geometry); + return expand<Geometry>::apply(m_box, geometry, m_strategy); } }; - template <class Box> + template <class Box, typename Strategy> static inline void apply(Box& box, - boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry) + boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry, + Strategy const& strategy) { - return boost::apply_visitor(visitor<Box>(box), geometry); + return boost::apply_visitor(visitor<Box, Strategy>(box, strategy), + geometry); } }; @@ -106,21 +155,43 @@ inline void expand(Box& box, Geometry const& geometry, } ***/ +/*! +\brief Expands (with strategy) +\ingroup expand +\tparam Box type of the box +\tparam Geometry \tparam_geometry +\tparam Strategy \tparam_strategy{expand} +\param box box to be expanded using another geometry, mutable +\param geometry \param_geometry geometry which envelope (bounding box) +\param strategy \param_strategy{expand} +will be added to the box + +\qbk{distinguish,with strategy} +\qbk{[include reference/algorithms/expand.qbk]} + */ +template <typename Box, typename Geometry, typename Strategy> +inline void expand(Box& box, Geometry const& geometry, Strategy const& strategy) +{ + + resolve_variant::expand<Geometry>::apply(box, geometry, strategy); +} /*! -\brief Expands a box using the bounding box (envelope) of another geometry (box, point) +\brief Expands a box using the bounding box (envelope) of another geometry +(box, point) \ingroup expand \tparam Box type of the box \tparam Geometry \tparam_geometry \param box box to be expanded using another geometry, mutable -\param geometry \param_geometry geometry which envelope (bounding box) will be added to the box +\param geometry \param_geometry geometry which envelope (bounding box) will be +added to the box \qbk{[include reference/algorithms/expand.qbk]} */ template <typename Box, typename Geometry> inline void expand(Box& box, Geometry const& geometry) { - resolve_variant::expand<Geometry>::apply(box, geometry); + resolve_variant::expand<Geometry>::apply(box, geometry, default_strategy()); } }} // namespace boost::geometry diff --git a/boost/geometry/algorithms/detail/expand/point.hpp b/boost/geometry/algorithms/detail/expand/point.hpp index 56b7f1c738..f0cbd1db02 100644 --- a/boost/geometry/algorithms/detail/expand/point.hpp +++ b/boost/geometry/algorithms/detail/expand/point.hpp @@ -5,9 +5,10 @@ // Copyright (c) 2009-2015 Mateusz Loskot, London, UK. // Copyright (c) 2014-2015 Samuel Debionne, Grenoble, France. -// This file was modified by Oracle on 2015. -// Modifications copyright (c) 2015, Oracle and/or its affiliates. +// This file was modified by Oracle on 2015, 2016. +// Modifications copyright (c) 2015-2016, Oracle and/or its affiliates. +// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle // Parts of Boost.Geometry are redesigned from Geodan's Geographic Library @@ -59,8 +60,8 @@ template > struct point_loop { - template <typename Box, typename Point> - static inline void apply(Box& box, Point const& source) + template <typename Box, typename Point, typename Strategy> + static inline void apply(Box& box, Point const& source, Strategy const& strategy) { typedef typename strategy::compare::detail::select_strategy < @@ -95,22 +96,24 @@ struct point_loop point_loop < StrategyLess, StrategyGreater, Dimension + 1, DimensionCount - >::apply(box, source); + >::apply(box, source, strategy); } }; template < - typename StrategyLess, typename StrategyGreater, std::size_t DimensionCount + typename StrategyLess, + typename StrategyGreater, + std::size_t DimensionCount > struct point_loop < StrategyLess, StrategyGreater, DimensionCount, DimensionCount > { - template <typename Box, typename Point> - static inline void apply(Box&, Point const&) {} + template <typename Box, typename Point, typename Strategy> + static inline void apply(Box&, Point const&, Strategy const&) {} }; @@ -123,8 +126,10 @@ template > struct point_loop_on_spheroid { - template <typename Box, typename Point> - static inline void apply(Box& box, Point const& point) + template <typename Box, typename Point, typename Strategy> + static inline void apply(Box& box, + Point const& point, + Strategy const& strategy) { typedef typename point_type<Box>::type box_point_type; typedef typename coordinate_type<Box>::type box_coordinate_type; @@ -224,7 +229,7 @@ struct point_loop_on_spheroid point_loop < StrategyLess, StrategyGreater, 2, DimensionCount - >::apply(box, point); + >::apply(box, point, strategy); } }; diff --git a/boost/geometry/algorithms/detail/expand/segment.hpp b/boost/geometry/algorithms/detail/expand/segment.hpp index 041c1e175f..0570e944d4 100644 --- a/boost/geometry/algorithms/detail/expand/segment.hpp +++ b/boost/geometry/algorithms/detail/expand/segment.hpp @@ -5,9 +5,10 @@ // Copyright (c) 2009-2015 Mateusz Loskot, London, UK. // Copyright (c) 2014-2015 Samuel Debionne, Grenoble, France. -// This file was modified by Oracle on 2015. -// Modifications copyright (c) 2015, Oracle and/or its affiliates. +// This file was modified by Oracle on 2015, 2016. +// Modifications copyright (c) 2015-2016, Oracle and/or its affiliates. +// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle // Distributed under the Boost Software License, Version 1.0. @@ -39,25 +40,29 @@ namespace boost { namespace geometry namespace detail { namespace expand { - -struct segment_on_sphere +struct segment { - template <typename Box, typename Segment> - static inline void apply(Box& box, Segment const& segment) + template <typename Box, typename Segment, typename Strategy> + static inline void apply(Box& box, + Segment const& segment, + Strategy const& strategy) { Box mbrs[2]; // compute the envelope of the segment - detail::envelope::envelope_segment_on_sphere + typename point_type<Segment>::type p[2]; + detail::assign_point_from_index<0>(segment, p[0]); + detail::assign_point_from_index<1>(segment, p[1]); + detail::envelope::envelope_segment < dimension<Segment>::value - >::apply(segment, mbrs[0]); + >::apply(p[0], p[1], mbrs[0], strategy); // normalize the box - detail::envelope::envelope_box_on_spheroid::apply(box, mbrs[1]); + detail::envelope::envelope_box_on_spheroid::apply(box, mbrs[1], strategy); // compute the envelope of the two boxes - detail::envelope::envelope_range_of_boxes::apply(mbrs, box); + detail::envelope::envelope_range_of_boxes::apply(mbrs, box, strategy); } }; @@ -69,7 +74,6 @@ struct segment_on_sphere namespace dispatch { - template < typename Box, typename Segment, @@ -103,13 +107,27 @@ struct expand StrategyLess, StrategyGreater, box_tag, segment_tag, spherical_equatorial_tag, spherical_equatorial_tag - > : detail::expand::segment_on_sphere + > : detail::expand::segment {}; +template +< + typename Box, typename Segment, + typename StrategyLess, typename StrategyGreater +> +struct expand + < + Box, Segment, + StrategyLess, StrategyGreater, + box_tag, segment_tag, + geographic_tag, geographic_tag + > : detail::expand::segment +{}; } // namespace dispatch #endif // DOXYGEN_NO_DISPATCH }} // namespace boost::geometry + #endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_EXPAND_SEGMENT_HPP diff --git a/boost/geometry/algorithms/detail/flattening.hpp b/boost/geometry/algorithms/detail/flattening.hpp deleted file mode 100644 index 8ed5fd9a89..0000000000 --- a/boost/geometry/algorithms/detail/flattening.hpp +++ /dev/null @@ -1,69 +0,0 @@ -// Boost.Geometry - -// Copyright (c) 2014 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_DETAIL_FLATTENING_HPP -#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_FLATTENING_HPP - -#include <boost/geometry/core/radius.hpp> -#include <boost/geometry/core/tag.hpp> -#include <boost/geometry/core/tags.hpp> - -#include <boost/geometry/algorithms/not_implemented.hpp> - -namespace boost { namespace geometry -{ - -#ifndef DOXYGEN_NO_DISPATCH -namespace detail_dispatch -{ - -template <typename ResultType, typename Geometry, typename Tag = typename tag<Geometry>::type> -struct flattening - : not_implemented<Tag> -{}; - -template <typename ResultType, typename Geometry> -struct flattening<ResultType, Geometry, srs_sphere_tag> -{ - static inline ResultType apply(Geometry const& /*geometry*/) - { - return ResultType(0); - } -}; - -template <typename ResultType, typename Geometry> -struct flattening<ResultType, Geometry, srs_spheroid_tag> -{ - static inline ResultType apply(Geometry const& geometry) - { - return ResultType(get_radius<0>(geometry) - get_radius<2>(geometry)) - / ResultType(get_radius<0>(geometry)); - } -}; - -} // namespace detail_dispatch -#endif // DOXYGEN_NO_DISPATCH - -#ifndef DOXYGEN_NO_DETAIL -namespace detail -{ - -template <typename ResultType, typename Geometry> -ResultType flattening(Geometry const& geometry) -{ - return detail_dispatch::flattening<ResultType, Geometry>::apply(geometry); -} - -} // namespace detail -#endif // DOXYGEN_NO_DETAIL - -}} // namespace boost::geometry - -#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_FLATTENING_HPP diff --git a/boost/geometry/algorithms/detail/has_self_intersections.hpp b/boost/geometry/algorithms/detail/has_self_intersections.hpp index 24746ac627..9a388a4d80 100644 --- a/boost/geometry/algorithms/detail/has_self_intersections.hpp +++ b/boost/geometry/algorithms/detail/has_self_intersections.hpp @@ -1,6 +1,11 @@ // Boost.Geometry (aka GGL, Generic Geometry Library) // Copyright (c) 2011-2012 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2017 Adam Wulkiewicz, Lodz, Poland. + +// This file was modified by Oracle on 2017. +// Modifications copyright (c) 2017 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 @@ -12,6 +17,8 @@ #include <deque> #include <boost/range.hpp> +#include <boost/throw_exception.hpp> + #include <boost/geometry/core/point_type.hpp> #include <boost/geometry/algorithms/detail/overlay/turn_info.hpp> #include <boost/geometry/algorithms/detail/overlay/get_turns.hpp> @@ -59,8 +66,9 @@ namespace detail { namespace overlay { -template <typename Geometry, typename RobustPolicy> +template <typename Geometry, typename Strategy, typename RobustPolicy> inline bool has_self_intersections(Geometry const& geometry, + Strategy const& strategy, RobustPolicy const& robust_policy, bool throw_on_self_intersection = true) { @@ -73,7 +81,7 @@ inline bool has_self_intersections(Geometry const& geometry, std::deque<turn_info> turns; detail::disjoint::disjoint_interrupt_policy policy; - geometry::self_turns<detail::overlay::assign_null_policy>(geometry, robust_policy, turns, policy); + geometry::self_turns<detail::overlay::assign_null_policy>(geometry, strategy, robust_policy, turns, policy); #ifdef BOOST_GEOMETRY_DEBUG_HAS_SELF_INTERSECTIONS bool first = true; @@ -113,7 +121,7 @@ inline bool has_self_intersections(Geometry const& geometry, #if ! defined(BOOST_GEOMETRY_OVERLAY_NO_THROW) if (throw_on_self_intersection) { - throw overlay_invalid_input_exception(); + BOOST_THROW_EXCEPTION(overlay_invalid_input_exception()); } #endif return true; @@ -132,11 +140,16 @@ inline bool has_self_intersections(Geometry const& geometry, typedef typename geometry::rescale_policy_type<point_type>::type rescale_policy_type; + typename strategy::intersection::services::default_strategy + < + typename cs_tag<Geometry>::type + >::type strategy; + rescale_policy_type robust_policy = geometry::get_rescale_policy<rescale_policy_type>(geometry); - return has_self_intersections(geometry, robust_policy, - throw_on_self_intersection); + return has_self_intersections(geometry, strategy, robust_policy, + throw_on_self_intersection); } diff --git a/boost/geometry/algorithms/detail/intersection/interface.hpp b/boost/geometry/algorithms/detail/intersection/interface.hpp index e0955de3d8..0efc9731b5 100644 --- a/boost/geometry/algorithms/detail/intersection/interface.hpp +++ b/boost/geometry/algorithms/detail/intersection/interface.hpp @@ -2,8 +2,8 @@ // Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. -// This file was modified by Oracle on 2014. -// Modifications copyright (c) 2014, Oracle and/or its affiliates. +// This file was modified by Oracle on 2014, 2017. +// Modifications copyright (c) 2014-2017, Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle @@ -15,12 +15,14 @@ #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_INTERSECTION_INTERFACE_HPP -// TODO: those headers probably may be removed -#include <boost/geometry/core/coordinate_dimension.hpp> -#include <boost/geometry/algorithms/intersects.hpp> +#include <boost/variant/apply_visitor.hpp> +#include <boost/variant/static_visitor.hpp> +#include <boost/variant/variant_fwd.hpp> #include <boost/geometry/algorithms/detail/overlay/intersection_insert.hpp> #include <boost/geometry/policies/robustness/get_rescale_policy.hpp> +#include <boost/geometry/strategies/default_strategy.hpp> +#include <boost/geometry/util/range.hpp> namespace boost { namespace geometry @@ -51,10 +53,11 @@ struct intersection typedef typename boost::range_value<GeometryOut>::type OneOut; intersection_insert - < - Geometry1, Geometry2, OneOut, - overlay_intersection - >::apply(geometry1, geometry2, robust_policy, range::back_inserter(geometry_out), strategy); + < + Geometry1, Geometry2, OneOut, + overlay_intersection + >::apply(geometry1, geometry2, robust_policy, + range::back_inserter(geometry_out), strategy); return true; } @@ -84,11 +87,12 @@ struct intersection GeometryOut& out, Strategy const& strategy) { - return intersection< - Geometry2, Geometry1, - Tag2, Tag1, - false - >::apply(g2, g1, robust_policy, out, strategy); + return intersection + < + Geometry2, Geometry1, + Tag2, Tag1, + false + >::apply(g2, g1, robust_policy, out, strategy); } }; @@ -96,47 +100,93 @@ struct intersection } // namespace dispatch #endif // DOXYGEN_NO_DISPATCH - + +namespace resolve_strategy { + +struct intersection +{ + template + < + typename Geometry1, + typename Geometry2, + typename RobustPolicy, + typename GeometryOut, + typename Strategy + > + static inline bool apply(Geometry1 const& geometry1, + Geometry2 const& geometry2, + RobustPolicy const& robust_policy, + GeometryOut & geometry_out, + Strategy const& strategy) + { + return dispatch::intersection + < + Geometry1, + Geometry2 + >::apply(geometry1, geometry2, robust_policy, geometry_out, + strategy); + } + + template + < + typename Geometry1, + typename Geometry2, + typename RobustPolicy, + typename GeometryOut + > + static inline bool apply(Geometry1 const& geometry1, + Geometry2 const& geometry2, + RobustPolicy const& robust_policy, + GeometryOut & geometry_out, + default_strategy) + { + typedef typename strategy::relate::services::default_strategy + < + Geometry1, Geometry2 + >::type strategy_type; + + return dispatch::intersection + < + Geometry1, + Geometry2 + >::apply(geometry1, geometry2, robust_policy, geometry_out, + strategy_type()); + } +}; + +} // resolve_strategy + + namespace resolve_variant { template <typename Geometry1, typename Geometry2> struct intersection { - template <typename GeometryOut> - static inline bool - apply( - const Geometry1& geometry1, - const Geometry2& geometry2, - GeometryOut& geometry_out) + template <typename GeometryOut, typename Strategy> + static inline bool apply(Geometry1 const& geometry1, + Geometry2 const& geometry2, + GeometryOut& geometry_out, + Strategy const& strategy) { concepts::check<Geometry1 const>(); concepts::check<Geometry2 const>(); typedef typename geometry::rescale_overlay_policy_type - < - Geometry1, - Geometry2 - >::type rescale_policy_type; + < + Geometry1, + Geometry2 + >::type rescale_policy_type; rescale_policy_type robust_policy = geometry::get_rescale_policy<rescale_policy_type>(geometry1, geometry2); - typedef intersection_strategies - < - typename cs_tag<Geometry1>::type, - Geometry1, - Geometry2, - typename geometry::point_type<Geometry1>::type, - rescale_policy_type - > strategy; - - return dispatch::intersection - < - Geometry1, - Geometry2 - >::apply(geometry1, geometry2, robust_policy, geometry_out, strategy()); + return resolve_strategy::intersection::apply(geometry1, + geometry2, + robust_policy, + geometry_out, + strategy); } }; @@ -144,40 +194,43 @@ struct intersection template <BOOST_VARIANT_ENUM_PARAMS(typename T), typename Geometry2> struct intersection<variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Geometry2> { - template <typename GeometryOut> + template <typename GeometryOut, typename Strategy> struct visitor: static_visitor<bool> { Geometry2 const& m_geometry2; GeometryOut& m_geometry_out; + Strategy const& m_strategy; visitor(Geometry2 const& geometry2, - GeometryOut& geometry_out) + GeometryOut& geometry_out, + Strategy const& strategy) : m_geometry2(geometry2) , m_geometry_out(geometry_out) + , m_strategy(strategy) {} template <typename Geometry1> - result_type operator()(Geometry1 const& geometry1) const + bool operator()(Geometry1 const& geometry1) const { return intersection - < - Geometry1, - Geometry2 - >::template apply - < - GeometryOut - > - (geometry1, m_geometry2, m_geometry_out); + < + Geometry1, + Geometry2 + >::apply(geometry1, m_geometry2, m_geometry_out, m_strategy); } }; - template <typename GeometryOut> + template <typename GeometryOut, typename Strategy> static inline bool apply(variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry1, Geometry2 const& geometry2, - GeometryOut& geometry_out) + GeometryOut& geometry_out, + Strategy const& strategy) { - return boost::apply_visitor(visitor<GeometryOut>(geometry2, geometry_out), geometry1); + return boost::apply_visitor(visitor<GeometryOut, Strategy>(geometry2, + geometry_out, + strategy), + geometry1); } }; @@ -185,40 +238,43 @@ struct intersection<variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Geometry2> template <typename Geometry1, BOOST_VARIANT_ENUM_PARAMS(typename T)> struct intersection<Geometry1, variant<BOOST_VARIANT_ENUM_PARAMS(T)> > { - template <typename GeometryOut> + template <typename GeometryOut, typename Strategy> struct visitor: static_visitor<bool> { Geometry1 const& m_geometry1; GeometryOut& m_geometry_out; + Strategy const& m_strategy; visitor(Geometry1 const& geometry1, - GeometryOut& geometry_out) + GeometryOut& geometry_out, + Strategy const& strategy) : m_geometry1(geometry1) , m_geometry_out(geometry_out) + , m_strategy(strategy) {} template <typename Geometry2> - result_type operator()(Geometry2 const& geometry2) const + bool operator()(Geometry2 const& geometry2) const { return intersection - < - Geometry1, - Geometry2 - >::template apply - < - GeometryOut - > - (m_geometry1, geometry2, m_geometry_out); + < + Geometry1, + Geometry2 + >::apply(m_geometry1, geometry2, m_geometry_out, m_strategy); } }; - template <typename GeometryOut> + template <typename GeometryOut, typename Strategy> static inline bool apply(Geometry1 const& geometry1, - const variant<BOOST_VARIANT_ENUM_PARAMS(T)>& geometry2, - GeometryOut& geometry_out) + variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry2, + GeometryOut& geometry_out, + Strategy const& strategy) { - return boost::apply_visitor(visitor<GeometryOut>(geometry1, geometry_out), geometry2); + return boost::apply_visitor(visitor<GeometryOut, Strategy>(geometry1, + geometry_out, + strategy), + geometry2); } }; @@ -226,38 +282,39 @@ struct intersection<Geometry1, variant<BOOST_VARIANT_ENUM_PARAMS(T)> > template <BOOST_VARIANT_ENUM_PARAMS(typename T1), BOOST_VARIANT_ENUM_PARAMS(typename T2)> struct intersection<variant<BOOST_VARIANT_ENUM_PARAMS(T1)>, variant<BOOST_VARIANT_ENUM_PARAMS(T2)> > { - template <typename GeometryOut> + template <typename GeometryOut, typename Strategy> struct visitor: static_visitor<bool> { GeometryOut& m_geometry_out; + Strategy const& m_strategy; - visitor(GeometryOut& geometry_out) + visitor(GeometryOut& geometry_out, Strategy const& strategy) : m_geometry_out(geometry_out) + , m_strategy(strategy) {} template <typename Geometry1, typename Geometry2> - result_type operator()(Geometry1 const& geometry1, - Geometry2 const& geometry2) const + bool operator()(Geometry1 const& geometry1, + Geometry2 const& geometry2) const { return intersection - < - Geometry1, - Geometry2 - >::template apply - < - GeometryOut - > - (geometry1, geometry2, m_geometry_out); + < + Geometry1, + Geometry2 + >::apply(geometry1, geometry2, m_geometry_out, m_strategy); } }; - template <typename GeometryOut> + template <typename GeometryOut, typename Strategy> static inline bool - apply(const variant<BOOST_VARIANT_ENUM_PARAMS(T1)>& geometry1, - const variant<BOOST_VARIANT_ENUM_PARAMS(T2)>& geometry2, - GeometryOut& geometry_out) + apply(variant<BOOST_VARIANT_ENUM_PARAMS(T1)> const& geometry1, + variant<BOOST_VARIANT_ENUM_PARAMS(T2)> const& geometry2, + GeometryOut& geometry_out, + Strategy const& strategy) { - return boost::apply_visitor(visitor<GeometryOut>(geometry_out), geometry1, geometry2); + return boost::apply_visitor(visitor<GeometryOut, Strategy>(geometry_out, + strategy), + geometry1, geometry2); } }; @@ -272,32 +329,66 @@ struct intersection<variant<BOOST_VARIANT_ENUM_PARAMS(T1)>, variant<BOOST_VARIAN \tparam Geometry2 \tparam_geometry \tparam GeometryOut Collection of geometries (e.g. std::vector, std::deque, boost::geometry::multi*) of which the value_type fulfills a \p_l_or_c concept, or it is the output geometry (e.g. for a box) +\tparam Strategy \tparam_strategy{Intersection} \param geometry1 \param_geometry \param geometry2 \param_geometry \param geometry_out The output geometry, either a multi_point, multi_polygon, multi_linestring, or a box (for intersection of two boxes) +\param strategy \param_strategy{intersection} +\qbk{distinguish,with strategy} \qbk{[include reference/algorithms/intersection.qbk]} */ template < typename Geometry1, typename Geometry2, - typename GeometryOut + typename GeometryOut, + typename Strategy > inline bool intersection(Geometry1 const& geometry1, - Geometry2 const& geometry2, - GeometryOut& geometry_out) + Geometry2 const& geometry2, + GeometryOut& geometry_out, + Strategy const& strategy) { return resolve_variant::intersection < - Geometry1, - Geometry2 - >::template apply + Geometry1, + Geometry2 + >::apply(geometry1, geometry2, geometry_out, strategy); +} + + +/*! +\brief \brief_calc2{intersection} +\ingroup intersection +\details \details_calc2{intersection, spatial set theoretic intersection}. +\tparam Geometry1 \tparam_geometry +\tparam Geometry2 \tparam_geometry +\tparam GeometryOut Collection of geometries (e.g. std::vector, std::deque, boost::geometry::multi*) of which + the value_type fulfills a \p_l_or_c concept, or it is the output geometry (e.g. for a box) +\param geometry1 \param_geometry +\param geometry2 \param_geometry +\param geometry_out The output geometry, either a multi_point, multi_polygon, + multi_linestring, or a box (for intersection of two boxes) + +\qbk{[include reference/algorithms/intersection.qbk]} +*/ +template +< + typename Geometry1, + typename Geometry2, + typename GeometryOut +> +inline bool intersection(Geometry1 const& geometry1, + Geometry2 const& geometry2, + GeometryOut& geometry_out) +{ + return resolve_variant::intersection < - GeometryOut - > - (geometry1, geometry2, geometry_out); + Geometry1, + Geometry2 + >::apply(geometry1, geometry2, geometry_out, default_strategy()); } diff --git a/boost/geometry/algorithms/detail/is_simple/always_simple.hpp b/boost/geometry/algorithms/detail/is_simple/always_simple.hpp index 91e2ef76bd..5cec5e1924 100644 --- a/boost/geometry/algorithms/detail/is_simple/always_simple.hpp +++ b/boost/geometry/algorithms/detail/is_simple/always_simple.hpp @@ -1,8 +1,9 @@ // Boost.Geometry (aka GGL, Generic Geometry Library) -// Copyright (c) 2014, Oracle and/or its affiliates. +// Copyright (c) 2014-2017, 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 // Licensed under the Boost Software License version 1.0. // http://www.boost.org/users/license.html @@ -27,7 +28,8 @@ namespace detail { namespace is_simple template <typename Geometry> struct always_simple { - static inline bool apply(Geometry const&) + template <typename Strategy> + static inline bool apply(Geometry const&, Strategy const&) { return true; } diff --git a/boost/geometry/algorithms/detail/is_simple/areal.hpp b/boost/geometry/algorithms/detail/is_simple/areal.hpp index a2322e4831..d4d6db9bce 100644 --- a/boost/geometry/algorithms/detail/is_simple/areal.hpp +++ b/boost/geometry/algorithms/detail/is_simple/areal.hpp @@ -1,8 +1,9 @@ // Boost.Geometry (aka GGL, Generic Geometry Library) -// Copyright (c) 2014-2015, Oracle and/or its affiliates. +// Copyright (c) 2014-2017, 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 // Licensed under the Boost Software License version 1.0. // http://www.boost.org/users/license.html @@ -37,6 +38,12 @@ namespace detail { namespace is_simple template <typename Ring> struct is_simple_ring { + template <typename Strategy> + static inline bool apply(Ring const& ring, Strategy const&) + { + return apply(ring); + } + static inline bool apply(Ring const& ring) { simplicity_failure_policy policy; @@ -69,6 +76,12 @@ private: } public: + template <typename Strategy> + static inline bool apply(Polygon const& polygon, Strategy const&) + { + return apply(polygon); + } + static inline bool apply(Polygon const& polygon) { return @@ -119,7 +132,8 @@ struct is_simple<Polygon, polygon_tag> template <typename MultiPolygon> struct is_simple<MultiPolygon, multi_polygon_tag> { - static inline bool apply(MultiPolygon const& multipolygon) + template <typename Strategy> + static inline bool apply(MultiPolygon const& multipolygon, Strategy const&) { return detail::check_iterator_range diff --git a/boost/geometry/algorithms/detail/is_simple/interface.hpp b/boost/geometry/algorithms/detail/is_simple/interface.hpp index 6d425232b0..af0127dc75 100644 --- a/boost/geometry/algorithms/detail/is_simple/interface.hpp +++ b/boost/geometry/algorithms/detail/is_simple/interface.hpp @@ -1,8 +1,9 @@ // Boost.Geometry (aka GGL, Generic Geometry Library) -// Copyright (c) 2014, Oracle and/or its affiliates. +// Copyright (c) 2014-2017, 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 // Licensed under the Boost Software License version 1.0. // http://www.boost.org/users/license.html @@ -17,46 +18,106 @@ #include <boost/geometry/geometries/concepts/check.hpp> #include <boost/geometry/algorithms/dispatch/is_simple.hpp> +#include <boost/geometry/core/cs.hpp> +#include <boost/geometry/strategies/default_strategy.hpp> +#include <boost/geometry/strategies/intersection.hpp> namespace boost { namespace geometry { +namespace resolve_strategy +{ + +struct is_simple +{ + template <typename Geometry, typename Strategy> + static inline bool apply(Geometry const& geometry, + Strategy const& strategy) + { + return dispatch::is_simple<Geometry>::apply(geometry, strategy); + } + + template <typename Geometry> + static inline bool apply(Geometry const& geometry, + default_strategy) + { + // NOTE: Currently the strategy is only used for Linear geometries + typedef typename strategy::intersection::services::default_strategy + < + typename cs_tag<Geometry>::type + >::type strategy_type; + + return dispatch::is_simple<Geometry>::apply(geometry, strategy_type()); + } +}; -namespace resolve_variant { +} // namespace resolve_strategy + +namespace resolve_variant +{ template <typename Geometry> struct is_simple { - static inline bool apply(Geometry const& geometry) + template <typename Strategy> + static inline bool apply(Geometry const& geometry, Strategy const& strategy) { concepts::check<Geometry const>(); - return dispatch::is_simple<Geometry>::apply(geometry); + + return resolve_strategy::is_simple::apply(geometry, strategy); } }; template <BOOST_VARIANT_ENUM_PARAMS(typename T)> struct is_simple<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> > { + template <typename Strategy> struct visitor : boost::static_visitor<bool> { + Strategy const& m_strategy; + + visitor(Strategy const& strategy) + : m_strategy(strategy) + {} + template <typename Geometry> bool operator()(Geometry const& geometry) const { - return is_simple<Geometry>::apply(geometry); + return is_simple<Geometry>::apply(geometry, m_strategy); } }; + template <typename Strategy> static inline bool - apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry) + apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry, + Strategy const& strategy) { - return boost::apply_visitor(visitor(), geometry); + return boost::apply_visitor(visitor<Strategy>(strategy), geometry); } }; } // namespace resolve_variant +/*! +\brief \brief_check{is simple} +\ingroup is_simple +\tparam Geometry \tparam_geometry +\tparam Strategy \tparam_strategy{Is_simple} +\param geometry \param_geometry +\param strategy \param_strategy{is_simple} +\return \return_check{is simple} + +\qbk{distinguish,with strategy} +\qbk{[include reference/algorithms/is_simple.qbk]} +*/ +template <typename Geometry, typename Strategy> +inline bool is_simple(Geometry const& geometry, Strategy const& strategy) +{ + return resolve_variant::is_simple<Geometry>::apply(geometry, strategy); +} + /*! \brief \brief_check{is simple} @@ -70,7 +131,7 @@ struct is_simple<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> > template <typename Geometry> inline bool is_simple(Geometry const& geometry) { - return resolve_variant::is_simple<Geometry>::apply(geometry); + return resolve_variant::is_simple<Geometry>::apply(geometry, default_strategy()); } diff --git a/boost/geometry/algorithms/detail/is_simple/linear.hpp b/boost/geometry/algorithms/detail/is_simple/linear.hpp index 16d7b3a803..52b9d9d1c8 100644 --- a/boost/geometry/algorithms/detail/is_simple/linear.hpp +++ b/boost/geometry/algorithms/detail/is_simple/linear.hpp @@ -1,8 +1,9 @@ // Boost.Geometry (aka GGL, Generic Geometry Library) -// Copyright (c) 2014-2015, Oracle and/or its affiliates. +// Copyright (c) 2014-2017, 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 // Licensed under the Boost Software License version 1.0. // http://www.boost.org/users/license.html @@ -48,6 +49,8 @@ #include <boost/geometry/algorithms/dispatch/is_simple.hpp> +#include <boost/geometry/strategies/intersection.hpp> + namespace boost { namespace geometry { @@ -186,8 +189,8 @@ private: }; -template <typename Linear> -inline bool has_self_intersections(Linear const& linear) +template <typename Linear, typename Strategy> +inline bool has_self_intersections(Linear const& linear, Strategy const& strategy) { typedef typename point_type<Linear>::type point_type; @@ -218,6 +221,7 @@ inline bool has_self_intersections(Linear const& linear) < turn_policy >::apply(linear, + strategy, detail::no_rescale_policy(), turns, interrupt_policy); @@ -243,8 +247,19 @@ struct is_simple_linestring && ! detail::is_valid::has_spikes < Linestring, closed - >::apply(linestring, policy) - && ! (CheckSelfIntersections && has_self_intersections(linestring)); + >::apply(linestring, policy); + } +}; + +template <typename Linestring> +struct is_simple_linestring<Linestring, true> +{ + template <typename Strategy> + static inline bool apply(Linestring const& linestring, + Strategy const& strategy) + { + return is_simple_linestring<Linestring, false>::apply(linestring) + && ! has_self_intersections(linestring, strategy); } }; @@ -252,7 +267,9 @@ struct is_simple_linestring template <typename MultiLinestring> struct is_simple_multilinestring { - static inline bool apply(MultiLinestring const& multilinestring) + template <typename Strategy> + static inline bool apply(MultiLinestring const& multilinestring, + Strategy const& strategy) { // check each of the linestrings for simplicity // but do not compute self-intersections yet; these will be @@ -272,7 +289,7 @@ struct is_simple_multilinestring return false; } - return ! has_self_intersections(multilinestring); + return ! has_self_intersections(multilinestring, strategy); } }; diff --git a/boost/geometry/algorithms/detail/is_simple/multipoint.hpp b/boost/geometry/algorithms/detail/is_simple/multipoint.hpp index f9f43d1cdb..61f0bc9130 100644 --- a/boost/geometry/algorithms/detail/is_simple/multipoint.hpp +++ b/boost/geometry/algorithms/detail/is_simple/multipoint.hpp @@ -1,8 +1,9 @@ // Boost.Geometry (aka GGL, Generic Geometry Library) -// Copyright (c) 2014-2015, Oracle and/or its affiliates. +// Copyright (c) 2014-2017, 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 // Licensed under the Boost Software License version 1.0. // http://www.boost.org/users/license.html @@ -38,7 +39,8 @@ namespace detail { namespace is_simple template <typename MultiPoint> struct is_simple_multipoint { - static inline bool apply(MultiPoint const& multipoint) + template <typename Strategy> + static inline bool apply(MultiPoint const& multipoint, Strategy const&) { if (boost::empty(multipoint)) { diff --git a/boost/geometry/algorithms/detail/is_valid/box.hpp b/boost/geometry/algorithms/detail/is_valid/box.hpp index 863ce625fe..69a4d4e78e 100644 --- a/boost/geometry/algorithms/detail/is_valid/box.hpp +++ b/boost/geometry/algorithms/detail/is_valid/box.hpp @@ -1,6 +1,6 @@ // Boost.Geometry (aka GGL, Generic Geometry Library) -// Copyright (c) 2014-2015, Oracle and/or its affiliates. +// Copyright (c) 2014-2017, 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 @@ -71,8 +71,8 @@ struct has_valid_corners<Box, 0> template <typename Box> struct is_valid_box { - template <typename VisitPolicy> - static inline bool apply(Box const& box, VisitPolicy& visitor) + template <typename VisitPolicy, typename Strategy> + static inline bool apply(Box const& box, VisitPolicy& visitor, Strategy const&) { return ! has_invalid_coordinate<Box>::apply(box, visitor) diff --git a/boost/geometry/algorithms/detail/is_valid/has_valid_self_turns.hpp b/boost/geometry/algorithms/detail/is_valid/has_valid_self_turns.hpp index 0a81213743..b91dc6a697 100644 --- a/boost/geometry/algorithms/detail/is_valid/has_valid_self_turns.hpp +++ b/boost/geometry/algorithms/detail/is_valid/has_valid_self_turns.hpp @@ -1,8 +1,9 @@ // Boost.Geometry (aka GGL, Generic Geometry Library) -// Copyright (c) 2014-2015, Oracle and/or its affiliates. +// Copyright (c) 2014-2017, 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 // Licensed under the Boost Software License version 1.0. // http://www.boost.org/users/license.html @@ -69,10 +70,11 @@ public: > turn_type; // returns true if all turns are valid - template <typename Turns, typename VisitPolicy> + template <typename Turns, typename VisitPolicy, typename Strategy> static inline bool apply(Geometry const& geometry, Turns& turns, - VisitPolicy& visitor) + VisitPolicy& visitor, + Strategy const& strategy) { boost::ignore_unused(visitor); @@ -85,6 +87,7 @@ public: > interrupt_policy; geometry::self_turns<turn_policy>(geometry, + strategy, robust_policy, turns, interrupt_policy); @@ -101,11 +104,11 @@ public: } // returns true if all turns are valid - template <typename VisitPolicy> - static inline bool apply(Geometry const& geometry, VisitPolicy& visitor) + template <typename VisitPolicy, typename Strategy> + static inline bool apply(Geometry const& geometry, VisitPolicy& visitor, Strategy const& strategy) { std::vector<turn_type> turns; - return apply(geometry, turns, visitor); + return apply(geometry, turns, visitor, strategy); } }; diff --git a/boost/geometry/algorithms/detail/is_valid/interface.hpp b/boost/geometry/algorithms/detail/is_valid/interface.hpp index 5a04a92824..ee013377c4 100644 --- a/boost/geometry/algorithms/detail/is_valid/interface.hpp +++ b/boost/geometry/algorithms/detail/is_valid/interface.hpp @@ -1,8 +1,9 @@ // Boost.Geometry (aka GGL, Generic Geometry Library) -// Copyright (c) 2014-2015, Oracle and/or its affiliates. +// Copyright (c) 2014-2017, 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 // Licensed under the Boost Software License version 1.0. // http://www.boost.org/users/license.html @@ -23,48 +24,88 @@ #include <boost/geometry/policies/is_valid/default_policy.hpp> #include <boost/geometry/policies/is_valid/failing_reason_policy.hpp> #include <boost/geometry/policies/is_valid/failure_type_policy.hpp> +#include <boost/geometry/strategies/default_strategy.hpp> +#include <boost/geometry/strategies/intersection.hpp> namespace boost { namespace geometry { + +namespace resolve_strategy +{ + +struct is_valid +{ + template <typename Geometry, typename VisitPolicy, typename Strategy> + static inline bool apply(Geometry const& geometry, + VisitPolicy& visitor, + Strategy const& strategy) + { + return dispatch::is_valid<Geometry>::apply(geometry, visitor, strategy); + } + + template <typename Geometry, typename VisitPolicy> + static inline bool apply(Geometry const& geometry, + VisitPolicy& visitor, + default_strategy) + { + // NOTE: Currently the strategy is only used for Areal geometries + typedef typename strategy::intersection::services::default_strategy + < + typename cs_tag<Geometry>::type + >::type strategy_type; + + return dispatch::is_valid<Geometry>::apply(geometry, visitor, strategy_type()); + } +}; +} // namespace resolve_strategy -namespace resolve_variant { +namespace resolve_variant +{ template <typename Geometry> struct is_valid { - template <typename VisitPolicy> - static inline bool apply(Geometry const& geometry, VisitPolicy& visitor) + template <typename VisitPolicy, typename Strategy> + static inline bool apply(Geometry const& geometry, + VisitPolicy& visitor, + Strategy const& strategy) { concepts::check<Geometry const>(); - return dispatch::is_valid<Geometry>::apply(geometry, visitor); + + return resolve_strategy::is_valid::apply(geometry, visitor, strategy); } }; template <BOOST_VARIANT_ENUM_PARAMS(typename T)> struct is_valid<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> > { - template <typename VisitPolicy> + template <typename VisitPolicy, typename Strategy> struct visitor : boost::static_visitor<bool> { - visitor(VisitPolicy& policy) : m_policy(policy) {} + visitor(VisitPolicy& policy, Strategy const& strategy) + : m_policy(policy) + , m_strategy(strategy) + {} template <typename Geometry> bool operator()(Geometry const& geometry) const { - return is_valid<Geometry>::apply(geometry, m_policy); + return is_valid<Geometry>::apply(geometry, m_policy, m_strategy); } VisitPolicy& m_policy; + Strategy const& m_strategy; }; - template <typename VisitPolicy> + template <typename VisitPolicy, typename Strategy> static inline bool apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry, - VisitPolicy& policy_visitor) + VisitPolicy& policy_visitor, + Strategy const& strategy) { - return boost::apply_visitor(visitor<VisitPolicy>(policy_visitor), + return boost::apply_visitor(visitor<VisitPolicy, Strategy>(policy_visitor, strategy), geometry); } }; @@ -73,10 +114,12 @@ struct is_valid<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> > // Undocumented for now -template <typename Geometry, typename VisitPolicy> -inline bool is_valid(Geometry const& geometry, VisitPolicy& visitor) +template <typename Geometry, typename VisitPolicy, typename Strategy> +inline bool is_valid(Geometry const& geometry, + VisitPolicy& visitor, + Strategy const& strategy) { - return resolve_variant::is_valid<Geometry>::apply(geometry, visitor); + return resolve_variant::is_valid<Geometry>::apply(geometry, visitor, strategy); } @@ -84,6 +127,29 @@ inline bool is_valid(Geometry const& geometry, VisitPolicy& visitor) \brief \brief_check{is valid (in the OGC sense)} \ingroup is_valid \tparam Geometry \tparam_geometry +\tparam Strategy \tparam_strategy{Is_valid} +\param geometry \param_geometry +\param strategy \param_strategy{is_valid} +\return \return_check{is valid (in the OGC sense); +furthermore, the following geometries are considered valid: +multi-geometries with no elements, +linear geometries containing spikes, +areal geometries with duplicate (consecutive) points} + +\qbk{distinguish,with strategy} +\qbk{[include reference/algorithms/is_valid.qbk]} +*/ +template <typename Geometry, typename Strategy> +inline bool is_valid(Geometry const& geometry, Strategy const& strategy) +{ + is_valid_default_policy<> visitor; + return resolve_variant::is_valid<Geometry>::apply(geometry, visitor, strategy); +} + +/*! +\brief \brief_check{is valid (in the OGC sense)} +\ingroup is_valid +\tparam Geometry \tparam_geometry \param geometry \param_geometry \return \return_check{is valid (in the OGC sense); furthermore, the following geometries are considered valid: @@ -96,8 +162,7 @@ inline bool is_valid(Geometry const& geometry, VisitPolicy& visitor) template <typename Geometry> inline bool is_valid(Geometry const& geometry) { - is_valid_default_policy<> policy_visitor; - return geometry::is_valid(geometry, policy_visitor); + return is_valid(geometry, default_strategy()); } @@ -105,6 +170,33 @@ inline bool is_valid(Geometry const& geometry) \brief \brief_check{is valid (in the OGC sense)} \ingroup is_valid \tparam Geometry \tparam_geometry +\tparam Strategy \tparam_strategy{Is_valid} +\param geometry \param_geometry +\param failure An enumeration value indicating that the geometry is + valid or not, and if not valid indicating the reason why +\param strategy \param_strategy{is_valid} +\return \return_check{is valid (in the OGC sense); + furthermore, the following geometries are considered valid: + multi-geometries with no elements, + linear geometries containing spikes, + areal geometries with duplicate (consecutive) points} + +\qbk{distinguish,with failure value and strategy} +\qbk{[include reference/algorithms/is_valid_with_failure.qbk]} +*/ +template <typename Geometry, typename Strategy> +inline bool is_valid(Geometry const& geometry, validity_failure_type& failure, Strategy const& strategy) +{ + failure_type_policy<> visitor; + bool result = resolve_variant::is_valid<Geometry>::apply(geometry, visitor, strategy); + failure = visitor.failure(); + return result; +} + +/*! +\brief \brief_check{is valid (in the OGC sense)} +\ingroup is_valid +\tparam Geometry \tparam_geometry \param geometry \param_geometry \param failure An enumeration value indicating that the geometry is valid or not, and if not valid indicating the reason why @@ -120,10 +212,7 @@ inline bool is_valid(Geometry const& geometry) template <typename Geometry> inline bool is_valid(Geometry const& geometry, validity_failure_type& failure) { - failure_type_policy<> policy_visitor; - bool result = geometry::is_valid(geometry, policy_visitor); - failure = policy_visitor.failure(); - return result; + return is_valid(geometry, failure, default_strategy()); } @@ -131,28 +220,52 @@ inline bool is_valid(Geometry const& geometry, validity_failure_type& failure) \brief \brief_check{is valid (in the OGC sense)} \ingroup is_valid \tparam Geometry \tparam_geometry +\tparam Strategy \tparam_strategy{Is_valid} \param geometry \param_geometry \param message A string containing a message stating if the geometry is valid or not, and if not valid a reason why +\param strategy \param_strategy{is_valid} \return \return_check{is valid (in the OGC sense); furthermore, the following geometries are considered valid: multi-geometries with no elements, linear geometries containing spikes, areal geometries with duplicate (consecutive) points} -\qbk{distinguish,with message} +\qbk{distinguish,with message and strategy} \qbk{[include reference/algorithms/is_valid_with_message.qbk]} */ -template <typename Geometry> -inline bool is_valid(Geometry const& geometry, std::string& message) +template <typename Geometry, typename Strategy> +inline bool is_valid(Geometry const& geometry, std::string& message, Strategy const& strategy) { std::ostringstream stream; - failing_reason_policy<> policy_visitor(stream); - bool result = geometry::is_valid(geometry, policy_visitor); + failing_reason_policy<> visitor(stream); + bool result = resolve_variant::is_valid<Geometry>::apply(geometry, visitor, strategy); message = stream.str(); return result; } +/*! +\brief \brief_check{is valid (in the OGC sense)} +\ingroup is_valid +\tparam Geometry \tparam_geometry +\param geometry \param_geometry +\param message A string containing a message stating if the geometry + is valid or not, and if not valid a reason why +\return \return_check{is valid (in the OGC sense); + furthermore, the following geometries are considered valid: + multi-geometries with no elements, + linear geometries containing spikes, + areal geometries with duplicate (consecutive) points} + +\qbk{distinguish,with message} +\qbk{[include reference/algorithms/is_valid_with_message.qbk]} +*/ +template <typename Geometry> +inline bool is_valid(Geometry const& geometry, std::string& message) +{ + return is_valid(geometry, message, default_strategy()); +} + }} // namespace boost::geometry diff --git a/boost/geometry/algorithms/detail/is_valid/linear.hpp b/boost/geometry/algorithms/detail/is_valid/linear.hpp index a49e077237..6bc6b86cf8 100644 --- a/boost/geometry/algorithms/detail/is_valid/linear.hpp +++ b/boost/geometry/algorithms/detail/is_valid/linear.hpp @@ -1,6 +1,6 @@ // Boost.Geometry (aka GGL, Generic Geometry Library) -// Copyright (c) 2014-2015, Oracle and/or its affiliates. +// Copyright (c) 2014-2017, 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 @@ -77,6 +77,14 @@ struct is_valid_linestring } return ! has_spikes<Linestring, closed>::apply(linestring, visitor); } + + template <typename VisitPolicy, typename Strategy> + static inline bool apply(Linestring const& linestring, + VisitPolicy& visitor, + Strategy const&) + { + return apply(linestring, visitor); + } }; @@ -142,9 +150,10 @@ private: }; public: - template <typename VisitPolicy> + template <typename VisitPolicy, typename Strategy> static inline bool apply(MultiLinestring const& multilinestring, - VisitPolicy& visitor) + VisitPolicy& visitor, + Strategy const&) { if (BOOST_GEOMETRY_CONDITION( AllowEmptyMultiGeometries && boost::empty(multilinestring))) diff --git a/boost/geometry/algorithms/detail/is_valid/multipolygon.hpp b/boost/geometry/algorithms/detail/is_valid/multipolygon.hpp index 0025445c2c..84dacc57f1 100644 --- a/boost/geometry/algorithms/detail/is_valid/multipolygon.hpp +++ b/boost/geometry/algorithms/detail/is_valid/multipolygon.hpp @@ -1,6 +1,6 @@ // Boost.Geometry (aka GGL, Generic Geometry Library) -// Copyright (c) 2014-2015, Oracle and/or its affiliates. +// Copyright (c) 2014-2017, 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 @@ -43,6 +43,8 @@ #include <boost/geometry/algorithms/dispatch/is_valid.hpp> +#include <boost/geometry/strategies/intersection.hpp> + namespace boost { namespace geometry { @@ -109,10 +111,10 @@ private: geometry::partition < - geometry::model::box<typename point_type<MultiPolygon>::type>, - typename base::expand_box, - typename base::overlaps_box - >::apply(polygon_iterators, item_visitor); + geometry::model::box<typename point_type<MultiPolygon>::type> + >::apply(polygon_iterators, item_visitor, + typename base::expand_box(), + typename base::overlaps_box()); if (item_visitor.items_overlap) { @@ -235,23 +237,28 @@ private: } - template <typename VisitPolicy> + template <typename VisitPolicy, typename Strategy> struct per_polygon { - per_polygon(VisitPolicy& policy) : m_policy(policy) {} + per_polygon(VisitPolicy& policy, Strategy const& strategy) + : m_policy(policy) + , m_strategy(strategy) + {} template <typename Polygon> inline bool apply(Polygon const& polygon) const { - return base::apply(polygon, m_policy); + return base::apply(polygon, m_policy, m_strategy); } VisitPolicy& m_policy; + Strategy const& m_strategy; }; public: - template <typename VisitPolicy> + template <typename VisitPolicy, typename Strategy> static inline bool apply(MultiPolygon const& multipolygon, - VisitPolicy& visitor) + VisitPolicy& visitor, + Strategy const& strategy) { typedef debug_validity_phase<MultiPolygon> debug_phase; @@ -266,11 +273,11 @@ public: if (! detail::check_iterator_range < - per_polygon<VisitPolicy>, + per_polygon<VisitPolicy, Strategy>, false // do not check for empty multipolygon (done above) >::apply(boost::begin(multipolygon), boost::end(multipolygon), - per_polygon<VisitPolicy>(visitor))) + per_polygon<VisitPolicy, Strategy>(visitor, strategy))) { return false; } @@ -283,7 +290,7 @@ public: std::deque<typename has_valid_turns::turn_type> turns; bool has_invalid_turns = - ! has_valid_turns::apply(multipolygon, turns, visitor); + ! has_valid_turns::apply(multipolygon, turns, visitor, strategy); debug_print_turns(turns.begin(), turns.end()); if (has_invalid_turns) diff --git a/boost/geometry/algorithms/detail/is_valid/pointlike.hpp b/boost/geometry/algorithms/detail/is_valid/pointlike.hpp index 51035f7a73..f77f7a35eb 100644 --- a/boost/geometry/algorithms/detail/is_valid/pointlike.hpp +++ b/boost/geometry/algorithms/detail/is_valid/pointlike.hpp @@ -1,6 +1,6 @@ // Boost.Geometry (aka GGL, Generic Geometry Library) -// Copyright (c) 2014-2015, Oracle and/or its affiliates. +// Copyright (c) 2014-2017, 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 @@ -36,8 +36,8 @@ namespace dispatch template <typename Point> struct is_valid<Point, point_tag> { - template <typename VisitPolicy> - static inline bool apply(Point const& point, VisitPolicy& visitor) + template <typename VisitPolicy, typename Strategy> + static inline bool apply(Point const& point, VisitPolicy& visitor, Strategy const&) { boost::ignore_unused(visitor); return ! detail::is_valid::has_invalid_coordinate @@ -56,9 +56,10 @@ struct is_valid<Point, point_tag> template <typename MultiPoint, bool AllowEmptyMultiGeometries> struct is_valid<MultiPoint, multi_point_tag, AllowEmptyMultiGeometries> { - template <typename VisitPolicy> + template <typename VisitPolicy, typename Strategy> static inline bool apply(MultiPoint const& multipoint, - VisitPolicy& visitor) + VisitPolicy& visitor, + Strategy const&) { boost::ignore_unused(multipoint, visitor); diff --git a/boost/geometry/algorithms/detail/is_valid/polygon.hpp b/boost/geometry/algorithms/detail/is_valid/polygon.hpp index bbe8e8fc39..f7e22fb8d2 100644 --- a/boost/geometry/algorithms/detail/is_valid/polygon.hpp +++ b/boost/geometry/algorithms/detail/is_valid/polygon.hpp @@ -1,8 +1,9 @@ // Boost.Geometry (aka GGL, Generic Geometry Library) -// Copyright (c) 2014-2015, Oracle and/or its affiliates. +// Copyright (c) 2014-2017, 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 // Licensed under the Boost Software License version 1.0. // http://www.boost.org/users/license.html @@ -74,10 +75,13 @@ class is_valid_polygon protected: typedef debug_validity_phase<Polygon> debug_phase; - template <typename VisitPolicy> + template <typename VisitPolicy, typename Strategy> struct per_ring { - per_ring(VisitPolicy& policy) : m_policy(policy) {} + per_ring(VisitPolicy& policy, Strategy const& strategy) + : m_policy(policy) + , m_strategy(strategy) + {} template <typename Ring> inline bool apply(Ring const& ring) const @@ -85,30 +89,34 @@ protected: return detail::is_valid::is_valid_ring < Ring, false, true - >::apply(ring, m_policy); + >::apply(ring, m_policy, m_strategy); } VisitPolicy& m_policy; + Strategy const& m_strategy; }; - template <typename InteriorRings, typename VisitPolicy> + template <typename InteriorRings, typename VisitPolicy, typename Strategy> static bool has_valid_interior_rings(InteriorRings const& interior_rings, - VisitPolicy& visitor) + VisitPolicy& visitor, + Strategy const& strategy) { return detail::check_iterator_range < - per_ring<VisitPolicy>, + per_ring<VisitPolicy, Strategy>, true // allow for empty interior ring range >::apply(boost::begin(interior_rings), boost::end(interior_rings), - per_ring<VisitPolicy>(visitor)); + per_ring<VisitPolicy, Strategy>(visitor, strategy)); } struct has_valid_rings { - template <typename VisitPolicy> - static inline bool apply(Polygon const& polygon, VisitPolicy& visitor) + template <typename VisitPolicy, typename Strategy> + static inline bool apply(Polygon const& polygon, + VisitPolicy& visitor, + Strategy const& strategy) { typedef typename ring_type<Polygon>::type ring_type; @@ -119,7 +127,7 @@ protected: < ring_type, false // do not check self intersections - >::apply(exterior_ring(polygon), visitor)) + >::apply(exterior_ring(polygon), visitor, strategy)) { return false; } @@ -128,7 +136,8 @@ protected: debug_phase::apply(2); return has_valid_interior_rings(geometry::interior_rings(polygon), - visitor); + visitor, + strategy); } }; @@ -246,10 +255,8 @@ protected: geometry::partition < - geometry::model::box<typename point_type<Polygon>::type>, - expand_box, - overlaps_box - >::apply(ring_iterators, item_visitor); + geometry::model::box<typename point_type<Polygon>::type> + >::apply(ring_iterators, item_visitor, expand_box(), overlaps_box()); if (item_visitor.items_overlap) { @@ -346,10 +353,12 @@ protected: }; public: - template <typename VisitPolicy> - static inline bool apply(Polygon const& polygon, VisitPolicy& visitor) + template <typename VisitPolicy, typename Strategy> + static inline bool apply(Polygon const& polygon, + VisitPolicy& visitor, + Strategy const& strategy) { - if (! has_valid_rings::apply(polygon, visitor)) + if (! has_valid_rings::apply(polygon, visitor, strategy)) { return false; } @@ -366,7 +375,7 @@ public: std::deque<typename has_valid_turns::turn_type> turns; bool has_invalid_turns - = ! has_valid_turns::apply(polygon, turns, visitor); + = ! has_valid_turns::apply(polygon, turns, visitor, strategy); debug_print_turns(turns.begin(), turns.end()); if (has_invalid_turns) diff --git a/boost/geometry/algorithms/detail/is_valid/ring.hpp b/boost/geometry/algorithms/detail/is_valid/ring.hpp index 925c03a472..9ab68fdc48 100644 --- a/boost/geometry/algorithms/detail/is_valid/ring.hpp +++ b/boost/geometry/algorithms/detail/is_valid/ring.hpp @@ -1,6 +1,6 @@ // Boost.Geometry (aka GGL, Generic Geometry Library) -// Copyright (c) 2014-2015, Oracle and/or its affiliates. +// Copyright (c) 2014-2017, 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 @@ -101,26 +101,21 @@ struct ring_area_predicate<ResultType, true> template <typename Ring, bool IsInteriorRing> struct is_properly_oriented { - typedef typename point_type<Ring>::type point_type; - - typedef typename strategy::area::services::default_strategy - < - typename cs_tag<point_type>::type, - point_type - >::type strategy_type; + template <typename VisitPolicy, typename Strategy> + static inline bool apply(Ring const& ring, VisitPolicy& visitor, + Strategy const& strategy) + { + boost::ignore_unused(visitor); - typedef detail::area::ring_area - < - order_as_direction<geometry::point_order<Ring>::value>::value, - geometry::closure<Ring>::value - > ring_area_type; + typedef typename point_type<Ring>::type point_type; - typedef typename default_area_result<Ring>::type area_result_type; + typedef detail::area::ring_area + < + order_as_direction<geometry::point_order<Ring>::value>::value, + geometry::closure<Ring>::value + > ring_area_type; - template <typename VisitPolicy> - static inline bool apply(Ring const& ring, VisitPolicy& visitor) - { - boost::ignore_unused(visitor); + typedef typename default_area_result<Ring>::type area_result_type; typename ring_area_predicate < @@ -128,8 +123,11 @@ struct is_properly_oriented >::type predicate; // Check area - area_result_type const zero = area_result_type(); - if (predicate(ring_area_type::apply(ring, strategy_type()), zero)) + area_result_type const zero = 0; + area_result_type const area + = ring_area_type::apply(ring, + strategy.template get_area_strategy<point_type>()); + if (predicate(area, zero)) { return visitor.template apply<no_failure>(); } @@ -150,8 +148,9 @@ template > struct is_valid_ring { - template <typename VisitPolicy> - static inline bool apply(Ring const& ring, VisitPolicy& visitor) + template <typename VisitPolicy, typename Strategy> + static inline bool apply(Ring const& ring, VisitPolicy& visitor, + Strategy const& strategy) { // return invalid if any of the following condition holds: // (a) the ring's point coordinates are not invalid (e.g., NaN) @@ -198,8 +197,8 @@ struct is_valid_ring && ! has_duplicates<Ring, closure>::apply(ring, visitor) && ! has_spikes<Ring, closure>::apply(ring, visitor) && (! CheckSelfIntersections - || has_valid_self_turns<Ring>::apply(ring, visitor)) - && is_properly_oriented<Ring, IsInteriorRing>::apply(ring, visitor); + || has_valid_self_turns<Ring>::apply(ring, visitor, strategy)) + && is_properly_oriented<Ring, IsInteriorRing>::apply(ring, visitor, strategy); } }; diff --git a/boost/geometry/algorithms/detail/is_valid/segment.hpp b/boost/geometry/algorithms/detail/is_valid/segment.hpp index f92f73381f..30cbf7afdb 100644 --- a/boost/geometry/algorithms/detail/is_valid/segment.hpp +++ b/boost/geometry/algorithms/detail/is_valid/segment.hpp @@ -1,6 +1,6 @@ // Boost.Geometry (aka GGL, Generic Geometry Library) -// Copyright (c) 2014-2015, Oracle and/or its affiliates. +// Copyright (c) 2014-2017, 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 @@ -44,8 +44,8 @@ namespace dispatch template <typename Segment> struct is_valid<Segment, segment_tag> { - template <typename VisitPolicy> - static inline bool apply(Segment const& segment, VisitPolicy& visitor) + template <typename VisitPolicy, typename Strategy> + static inline bool apply(Segment const& segment, VisitPolicy& visitor, Strategy const&) { boost::ignore_unused(visitor); diff --git a/boost/geometry/algorithms/detail/not.hpp b/boost/geometry/algorithms/detail/not.hpp index 43e71e2e37..95cdfa24e6 100644 --- a/boost/geometry/algorithms/detail/not.hpp +++ b/boost/geometry/algorithms/detail/not.hpp @@ -4,10 +4,11 @@ // Copyright (c) 2008-2015 Bruno Lalande, Paris, France. // Copyright (c) 2009-2015 Mateusz Loskot, London, UK. -// This file was modified by Oracle on 2015. -// Modifications copyright (c) 2015, Oracle and/or its affiliates. +// This file was modified by Oracle on 2015, 2017. +// Modifications copyright (c) 2015-2017, 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. @@ -46,6 +47,14 @@ struct not_ { return ! Policy::apply(geometry1, geometry2); } + + template <typename Geometry1, typename Geometry2, typename Strategy> + static inline bool apply(Geometry1 const& geometry1, + Geometry2 const& geometry2, + Strategy const& strategy) + { + return ! Policy::apply(geometry1, geometry2, strategy); + } }; diff --git a/boost/geometry/algorithms/detail/overlay/assign_parents.hpp b/boost/geometry/algorithms/detail/overlay/assign_parents.hpp index 047eb4993e..2408b4b68e 100644 --- a/boost/geometry/algorithms/detail/overlay/assign_parents.hpp +++ b/boost/geometry/algorithms/detail/overlay/assign_parents.hpp @@ -2,6 +2,10 @@ // Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. +// This file was modified by Oracle on 2017. +// Modifications copyright (c) 2017 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) @@ -258,8 +262,9 @@ inline void assign_parents(Geometry1 const& geometry1, geometry::partition < - box_type, ring_info_helper_get_box, ring_info_helper_ovelaps_box - >::apply(vector, visitor); + box_type + >::apply(vector, visitor, ring_info_helper_get_box(), + ring_info_helper_ovelaps_box()); } if (check_for_orientation) diff --git a/boost/geometry/algorithms/detail/overlay/backtrack_check_si.hpp b/boost/geometry/algorithms/detail/overlay/backtrack_check_si.hpp index a8171e1482..9beb8ad64f 100644 --- a/boost/geometry/algorithms/detail/overlay/backtrack_check_si.hpp +++ b/boost/geometry/algorithms/detail/overlay/backtrack_check_si.hpp @@ -2,6 +2,10 @@ // Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. +// This file was modified by Oracle on 2017. +// Modifications copyright (c) 2017, 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) @@ -106,19 +110,27 @@ class backtrack_check_self_intersections public : typedef state state_type; - template <typename Operation, typename Rings, typename Ring, typename Turns, typename RobustPolicy, typename Visitor> + template + < + typename Operation, + typename Rings, typename Ring, typename Turns, + typename Strategy, + typename RobustPolicy, + typename Visitor + > static inline void apply(std::size_t size_at_start, - Rings& rings, Ring& ring, - Turns& turns, - typename boost::range_value<Turns>::type const& turn, - Operation& operation, - traverse_error_type traverse_error, - Geometry1 const& geometry1, - Geometry2 const& geometry2, - RobustPolicy const& robust_policy, - state_type& state, - Visitor& visitor - ) + Rings& rings, + Ring& ring, + Turns& turns, + typename boost::range_value<Turns>::type const& turn, + Operation& operation, + traverse_error_type traverse_error, + Geometry1 const& geometry1, + Geometry2 const& geometry2, + Strategy const& strategy, + RobustPolicy const& robust_policy, + state_type& state, + Visitor& visitor) { visitor.visit_traverse_reject(turns, turn, operation, traverse_error); @@ -128,8 +140,8 @@ public : if (! state.m_checked) { state.m_checked = true; - has_self_intersections(geometry1, robust_policy); - has_self_intersections(geometry2, robust_policy); + has_self_intersections(geometry1, strategy, robust_policy); + has_self_intersections(geometry2, strategy, robust_policy); } // Make bad output clean diff --git a/boost/geometry/algorithms/detail/overlay/follow_linear_linear.hpp b/boost/geometry/algorithms/detail/overlay/follow_linear_linear.hpp index b9e48cdbfc..c249ff57ff 100644 --- a/boost/geometry/algorithms/detail/overlay/follow_linear_linear.hpp +++ b/boost/geometry/algorithms/detail/overlay/follow_linear_linear.hpp @@ -1,5 +1,7 @@ // Boost.Geometry (aka GGL, Generic Geometry Library) +// Copyright (c) 2017 Adam Wulkiewicz, Lodz, Poland. + // Copyright (c) 2014-2015, Oracle and/or its affiliates. // Licensed under the Boost Software License version 1.0. @@ -15,6 +17,7 @@ #include <iterator> #include <boost/range.hpp> +#include <boost/throw_exception.hpp> #include <boost/geometry/core/assert.hpp> #include <boost/geometry/core/tag.hpp> @@ -307,7 +310,7 @@ public: #if ! defined(BOOST_GEOMETRY_OVERLAY_NO_THROW) if (enter_count != 0) { - throw inconsistent_turns_exception(); + BOOST_THROW_EXCEPTION(inconsistent_turns_exception()); } #else BOOST_GEOMETRY_ASSERT(enter_count == 0); diff --git a/boost/geometry/algorithms/detail/overlay/get_intersection_points.hpp b/boost/geometry/algorithms/detail/overlay/get_intersection_points.hpp index 99281eaecb..94667d0ed0 100644 --- a/boost/geometry/algorithms/detail/overlay/get_intersection_points.hpp +++ b/boost/geometry/algorithms/detail/overlay/get_intersection_points.hpp @@ -2,6 +2,11 @@ // Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. +// This file was modified by Oracle on 2017. +// Modifications copyright (c) 2017 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) @@ -39,29 +44,33 @@ template > struct get_turn_without_info { - template <typename RobustPolicy, typename OutputIterator> + template <typename Strategy, typename RobustPolicy, typename OutputIterator> static inline OutputIterator apply( Point1 const& pi, Point1 const& pj, Point1 const& /*pk*/, Point2 const& qi, Point2 const& qj, Point2 const& /*qk*/, bool /*is_p_first*/, bool /*is_p_last*/, bool /*is_q_first*/, bool /*is_q_last*/, TurnInfo const& , + Strategy const& strategy, RobustPolicy const& robust_policy, OutputIterator out) { - typedef intersection_strategies - < - typename cs_tag<typename TurnInfo::point_type>::type, - Point1, - Point2, - typename TurnInfo::point_type, - RobustPolicy - > si; + typedef typename TurnInfo::point_type turn_point_type; - typedef typename si::segment_intersection_strategy_type strategy; + typedef policies::relate::segments_intersection_points + < + segment_intersection_points + < + turn_point_type, + typename geometry::segment_ratio_type + < + turn_point_type, RobustPolicy + >::type + > + > policy_type; typedef model::referring_segment<Point1 const> segment_type1; - typedef model::referring_segment<Point1 const> segment_type2; + typedef model::referring_segment<Point2 const> segment_type2; segment_type1 p1(pi, pj); segment_type2 q1(qi, qj); @@ -75,15 +84,14 @@ struct get_turn_without_info geometry::recalculate(pj_rob, pj, robust_policy); geometry::recalculate(qi_rob, qi, robust_policy); geometry::recalculate(qj_rob, qj, robust_policy); - typename strategy::return_type result - = strategy::apply(p1, q1, robust_policy, - pi_rob, pj_rob, qi_rob, qj_rob); + typename policy_type::return_type result + = strategy.apply(p1, q1, policy_type(), robust_policy, + pi_rob, pj_rob, qi_rob, qj_rob); - for (std::size_t i = 0; i < result.template get<0>().count; i++) + for (std::size_t i = 0; i < result.count; i++) { - TurnInfo tp; - geometry::convert(result.template get<0>().intersections[i], tp.point); + geometry::convert(result.intersections[i], tp.point); *out++ = tp; } @@ -102,12 +110,14 @@ template typename Geometry1, typename Geometry2, typename RobustPolicy, - typename Turns + typename Turns, + typename Strategy > inline void get_intersection_points(Geometry1 const& geometry1, Geometry2 const& geometry2, RobustPolicy const& robust_policy, - Turns& turns) + Turns& turns, + Strategy const& strategy) { concepts::check_concepts_and_equal_dimensions<Geometry1 const, Geometry2 const>(); @@ -142,6 +152,7 @@ inline void get_intersection_points(Geometry1 const& geometry1, >::type::apply( 0, geometry1, 1, geometry2, + strategy, robust_policy, turns, interrupt_policy); } diff --git a/boost/geometry/algorithms/detail/overlay/get_turn_info.hpp b/boost/geometry/algorithms/detail/overlay/get_turn_info.hpp index a4cce3fd32..08bc342186 100644 --- a/boost/geometry/algorithms/detail/overlay/get_turn_info.hpp +++ b/boost/geometry/algorithms/detail/overlay/get_turn_info.hpp @@ -1,9 +1,10 @@ // Boost.Geometry (aka GGL, Generic Geometry Library) // Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2017 Adam Wulkiewicz, Lodz, Poland. -// This file was modified by Oracle on 2015. -// Modifications copyright (c) 2015 Oracle and/or its affiliates. +// This file was modified by Oracle on 2015, 2017. +// Modifications copyright (c) 2015-2017 Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle @@ -16,10 +17,10 @@ #include <boost/core/ignore_unused.hpp> +#include <boost/throw_exception.hpp> #include <boost/geometry/core/access.hpp> #include <boost/geometry/core/assert.hpp> -#include <boost/geometry/strategies/intersection_strategies.hpp> #include <boost/geometry/algorithms/convert.hpp> #include <boost/geometry/algorithms/detail/overlay/turn_info.hpp> @@ -644,7 +645,7 @@ struct collinear : public base_turn_handler // causes currently cycling include problems typedef typename geometry::coordinate_type<Point1>::type ctype; ctype const dx = get<0>(a) - get<0>(b); - ctype const dy = get<1>(b) - get<1>(b); + ctype const dy = get<1>(a) - get<1>(b); return dx * dx + dy * dy; } }; @@ -930,6 +931,7 @@ struct get_turn_info typename Point1, typename Point2, typename TurnInfo, + typename IntersectionStrategy, typename RobustPolicy, typename OutputIterator > @@ -939,13 +941,19 @@ struct get_turn_info bool /*is_p_first*/, bool /*is_p_last*/, bool /*is_q_first*/, bool /*is_q_last*/, TurnInfo const& tp_model, + IntersectionStrategy const& intersection_strategy, RobustPolicy const& robust_policy, OutputIterator out) { - typedef intersection_info<Point1, Point2, typename TurnInfo::point_type, RobustPolicy> - inters_info; + typedef intersection_info + < + Point1, Point2, + typename TurnInfo::point_type, + IntersectionStrategy, + RobustPolicy + > inters_info; - inters_info inters(pi, pj, pk, qi, qj, qk, robust_policy); + inters_info inters(pi, pj, pk, qi, qj, qk, intersection_strategy, robust_policy); char const method = inters.d_info().how; @@ -991,9 +999,12 @@ struct get_turn_info < typename inters_info::cs_tag, typename inters_info::robust_point2_type, - typename inters_info::robust_point1_type + typename inters_info::robust_point1_type, + typename inters_info::side_strategy_type > swapped_side_calc(inters.rqi(), inters.rqj(), inters.rqk(), - inters.rpi(), inters.rpj(), inters.rpk()); + inters.rpi(), inters.rpj(), inters.rpk(), + inters.get_side_strategy()); + policy::template apply<1>(qi, qj, qk, pi, pj, pk, tp, inters.i_info(), inters.d_info(), swapped_side_calc); @@ -1093,7 +1104,7 @@ struct get_turn_info std::cout << "TURN: Unknown method: " << method << std::endl; #endif #if ! defined(BOOST_GEOMETRY_OVERLAY_NO_THROW) - throw turn_info_exception(method); + BOOST_THROW_EXCEPTION(turn_info_exception(method)); #endif } break; diff --git a/boost/geometry/algorithms/detail/overlay/get_turn_info_for_endpoint.hpp b/boost/geometry/algorithms/detail/overlay/get_turn_info_for_endpoint.hpp index 85cdfbc02d..48716634c5 100644 --- a/boost/geometry/algorithms/detail/overlay/get_turn_info_for_endpoint.hpp +++ b/boost/geometry/algorithms/detail/overlay/get_turn_info_for_endpoint.hpp @@ -2,15 +2,15 @@ // Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. -// This file was modified by Oracle on 2013, 2014. -// Modifications copyright (c) 2013-2014 Oracle and/or its affiliates. +// This file was modified by Oracle on 2013, 2014, 2017. +// Modifications copyright (c) 2013-2017 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) -// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle - #ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_GET_TURN_INFO_FOR_ENDPOINT_HPP #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_GET_TURN_INFO_FOR_ENDPOINT_HPP @@ -427,8 +427,11 @@ struct get_turn_info_for_endpoint } else if ( ip_j2 ) { - side_calculator<cs_tag, RobustPoint1, RobustPoint2, RobustPoint2> - side_calc(ri2, ri1, rj1, ri2, rj2, rk2); + side_calculator<cs_tag, + RobustPoint1, RobustPoint2, + typename IntersectionInfo::side_strategy_type, + RobustPoint2> + side_calc(ri2, ri1, rj1, ri2, rj2, rk2, inters.get_side_strategy()); std::pair<operation_type, operation_type> operations = operations_of_equal(side_calc); @@ -478,8 +481,10 @@ struct get_turn_info_for_endpoint } else if ( ip_j2 ) { - side_calculator<cs_tag, RobustPoint1, RobustPoint2, RobustPoint2> - side_calc(ri2, rj1, ri1, ri2, rj2, rk2); + side_calculator<cs_tag, RobustPoint1, RobustPoint2, + typename IntersectionInfo::side_strategy_type, + RobustPoint2> + side_calc(ri2, rj1, ri1, ri2, rj2, rk2, inters.get_side_strategy()); std::pair<operation_type, operation_type> operations = operations_of_equal(side_calc); diff --git a/boost/geometry/algorithms/detail/overlay/get_turn_info_helpers.hpp b/boost/geometry/algorithms/detail/overlay/get_turn_info_helpers.hpp index 3e7da1d797..5f2cb07faf 100644 --- a/boost/geometry/algorithms/detail/overlay/get_turn_info_helpers.hpp +++ b/boost/geometry/algorithms/detail/overlay/get_turn_info_helpers.hpp @@ -2,15 +2,15 @@ // Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. -// This file was modified by Oracle on 2013, 2014, 2015. -// Modifications copyright (c) 2013-2015 Oracle and/or its affiliates. +// This file was modified by Oracle on 2013, 2014, 2015, 2017. +// Modifications copyright (c) 2013-2017 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) -// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle - #ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_GET_TURN_INFO_HELPERS_HPP #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_GET_TURN_INFO_HELPERS_HPP @@ -37,32 +37,27 @@ struct turn_operation_linear }; template <typename TurnPointCSTag, typename PointP, typename PointQ, + typename SideStrategy, typename Pi = PointP, typename Pj = PointP, typename Pk = PointP, typename Qi = PointQ, typename Qj = PointQ, typename Qk = PointQ > struct side_calculator { - // This strategy should be the same as side strategy defined in - // intersection_strategies<> which is used in various places - // of the library - typedef typename strategy::side::services::default_strategy - < - TurnPointCSTag - >::type side; - inline side_calculator(Pi const& pi, Pj const& pj, Pk const& pk, - Qi const& qi, Qj const& qj, Qk const& qk) + Qi const& qi, Qj const& qj, Qk const& qk, + SideStrategy const& side_strategy) : m_pi(pi), m_pj(pj), m_pk(pk) , m_qi(qi), m_qj(qj), m_qk(qk) + , m_side_strategy(side_strategy) {} - inline int pk_wrt_p1() const { return side::apply(m_pi, m_pj, m_pk); } - inline int pk_wrt_q1() const { return side::apply(m_qi, m_qj, m_pk); } - inline int qk_wrt_p1() const { return side::apply(m_pi, m_pj, m_qk); } - inline int qk_wrt_q1() const { return side::apply(m_qi, m_qj, m_qk); } + inline int pk_wrt_p1() const { return m_side_strategy.apply(m_pi, m_pj, m_pk); } + inline int pk_wrt_q1() const { return m_side_strategy.apply(m_qi, m_qj, m_pk); } + inline int qk_wrt_p1() const { return m_side_strategy.apply(m_pi, m_pj, m_qk); } + inline int qk_wrt_q1() const { return m_side_strategy.apply(m_qi, m_qj, m_qk); } - inline int pk_wrt_q2() const { return side::apply(m_qj, m_qk, m_pk); } - inline int qk_wrt_p2() const { return side::apply(m_pj, m_pk, m_qk); } + inline int pk_wrt_q2() const { return m_side_strategy.apply(m_qj, m_qk, m_pk); } + inline int qk_wrt_p2() const { return m_side_strategy.apply(m_pj, m_pk, m_qk); } Pi const& m_pi; Pj const& m_pj; @@ -70,6 +65,8 @@ struct side_calculator Qi const& m_qi; Qj const& m_qj; Qk const& m_qk; + + SideStrategy const& m_side_strategy; }; template <typename Point1, typename Point2, typename RobustPolicy> @@ -99,7 +96,7 @@ struct robust_points robust_point2_type m_rqi, m_rqj, m_rqk; }; -template <typename Point1, typename Point2, typename TurnPoint, typename RobustPolicy> +template <typename Point1, typename Point2, typename TurnPoint, typename IntersectionStrategy, typename RobustPolicy> class intersection_info_base : private robust_points<Point1, Point2, RobustPolicy> { @@ -114,14 +111,17 @@ public: typedef typename cs_tag<TurnPoint>::type cs_tag; - typedef side_calculator<cs_tag, robust_point1_type, robust_point2_type> side_calculator_type; + typedef typename IntersectionStrategy::side_strategy_type side_strategy_type; + typedef side_calculator<cs_tag, robust_point1_type, robust_point2_type, side_strategy_type> side_calculator_type; intersection_info_base(Point1 const& pi, Point1 const& pj, Point1 const& pk, Point2 const& qi, Point2 const& qj, Point2 const& qk, + IntersectionStrategy const& intersection_strategy, RobustPolicy const& robust_policy) : base(pi, pj, pk, qi, qj, qk, robust_policy) , m_side_calc(base::m_rpi, base::m_rpj, base::m_rpk, - base::m_rqi, base::m_rqj, base::m_rqk) + base::m_rqi, base::m_rqj, base::m_rqk, + intersection_strategy.get_side_strategy()) , m_pi(pi), m_pj(pj), m_pk(pk) , m_qi(qi), m_qj(qj), m_qk(qk) {} @@ -155,8 +155,8 @@ private: point2_type const& m_qk; }; -template <typename Point1, typename Point2, typename TurnPoint> -class intersection_info_base<Point1, Point2, TurnPoint, detail::no_rescale_policy> +template <typename Point1, typename Point2, typename TurnPoint, typename IntersectionStrategy> +class intersection_info_base<Point1, Point2, TurnPoint, IntersectionStrategy, detail::no_rescale_policy> { public: typedef Point1 point1_type; @@ -167,12 +167,15 @@ public: typedef typename cs_tag<TurnPoint>::type cs_tag; - typedef side_calculator<cs_tag, Point1, Point2> side_calculator_type; + typedef typename IntersectionStrategy::side_strategy_type side_strategy_type; + typedef side_calculator<cs_tag, Point1, Point2, side_strategy_type> side_calculator_type; intersection_info_base(Point1 const& pi, Point1 const& pj, Point1 const& pk, Point2 const& qi, Point2 const& qj, Point2 const& qk, + IntersectionStrategy const& intersection_strategy, no_rescale_policy const& /*robust_policy*/) - : m_side_calc(pi, pj, pk, qi, qj, qk) + : m_side_calc(pi, pj, pk, qi, qj, qk, + intersection_strategy.get_side_strategy()) {} inline Point1 const& pi() const { return m_side_calc.m_pi; } @@ -203,40 +206,58 @@ template typename Point1, typename Point2, typename TurnPoint, + typename IntersectionStrategy, typename RobustPolicy > class intersection_info - : public intersection_info_base<Point1, Point2, TurnPoint, RobustPolicy> + : public intersection_info_base<Point1, Point2, TurnPoint, IntersectionStrategy, RobustPolicy> { - typedef intersection_info_base<Point1, Point2, TurnPoint, RobustPolicy> base; + typedef intersection_info_base<Point1, Point2, TurnPoint, IntersectionStrategy, RobustPolicy> base; + +public: + typedef segment_intersection_points + < + TurnPoint, + typename geometry::segment_ratio_type + < + TurnPoint, RobustPolicy + >::type + > intersection_point_type; - typedef typename intersection_strategies + // NOTE: formerly defined in intersection_strategies + typedef policies::relate::segments_tupled < - typename base::cs_tag, - Point1, - Point2, - TurnPoint, - RobustPolicy - >::segment_intersection_strategy_type strategy; + policies::relate::segments_intersection_points + < + intersection_point_type + >, + policies::relate::segments_direction + > intersection_policy_type; + + typedef IntersectionStrategy intersection_strategy_type; + typedef typename IntersectionStrategy::side_strategy_type side_strategy_type; -public: typedef model::referring_segment<Point1 const> segment_type1; typedef model::referring_segment<Point2 const> segment_type2; typedef typename base::side_calculator_type side_calculator_type; - typedef typename strategy::return_type result_type; + typedef typename intersection_policy_type::return_type result_type; typedef typename boost::tuples::element<0, result_type>::type i_info_type; // intersection_info typedef typename boost::tuples::element<1, result_type>::type d_info_type; // dir_info intersection_info(Point1 const& pi, Point1 const& pj, Point1 const& pk, Point2 const& qi, Point2 const& qj, Point2 const& qk, + IntersectionStrategy const& intersection_strategy, RobustPolicy const& robust_policy) - : base(pi, pj, pk, qi, qj, qk, robust_policy) - , m_result(strategy::apply(segment_type1(pi, pj), - segment_type2(qi, qj), - robust_policy, - base::rpi(), base::rpj(), - base::rqi(), base::rqj())) + : base(pi, pj, pk, qi, qj, qk, intersection_strategy, robust_policy) + , m_result(intersection_strategy.apply( + segment_type1(pi, pj), + segment_type2(qi, qj), + intersection_policy_type(), + robust_policy, + base::rpi(), base::rpj(), + base::rqi(), base::rqj())) + , m_intersection_strategy(intersection_strategy) , m_robust_policy(robust_policy) {} @@ -244,6 +265,16 @@ public: inline i_info_type const& i_info() const { return m_result.template get<0>(); } inline d_info_type const& d_info() const { return m_result.template get<1>(); } + inline intersection_strategy_type const& get_intersection_strategy() const + { + return m_intersection_strategy; + } + + inline side_strategy_type get_side_strategy() const + { + return m_intersection_strategy.get_side_strategy(); + } + // TODO: it's more like is_spike_ip_p inline bool is_spike_p() const { @@ -307,17 +338,18 @@ private: { typedef model::referring_segment<Point const> seg; - typedef intersection_strategies - < - typename base::cs_tag, Point, Point, Point, RobustPolicy - > si; - - typedef typename si::segment_intersection_strategy_type strategy; - - typename strategy::return_type result - = strategy::apply(seg(i, j), seg(j, k), m_robust_policy); + // no need to calcualte direction info + typedef policies::relate::segments_intersection_points + < + intersection_point_type + > policy_type; + + typename policy_type::return_type const result + = m_intersection_strategy.apply(seg(i, j), seg(j, k), + policy_type(), + m_robust_policy); - return result.template get<0>().count == 2; + return result.count == 2; } template <std::size_t OpId> @@ -344,6 +376,7 @@ private: } result_type m_result; + IntersectionStrategy const& m_intersection_strategy; RobustPolicy const& m_robust_policy; }; diff --git a/boost/geometry/algorithms/detail/overlay/get_turn_info_la.hpp b/boost/geometry/algorithms/detail/overlay/get_turn_info_la.hpp index 121728d822..46c1305cd7 100644 --- a/boost/geometry/algorithms/detail/overlay/get_turn_info_la.hpp +++ b/boost/geometry/algorithms/detail/overlay/get_turn_info_la.hpp @@ -1,9 +1,10 @@ // Boost.Geometry (aka GGL, Generic Geometry Library) // Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2017 Adam Wulkiewicz, Lodz, Poland. -// This file was modified by Oracle on 2013, 2014, 2015. -// Modifications copyright (c) 2013-2015 Oracle and/or its affiliates. +// This file was modified by Oracle on 2013, 2014, 2015, 2017. +// Modifications copyright (c) 2013-2017 Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle @@ -14,6 +15,8 @@ #ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_GET_TURN_INFO_LA_HPP #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_GET_TURN_INFO_LA_HPP +#include <boost/throw_exception.hpp> + #include <boost/geometry/core/assert.hpp> #include <boost/geometry/util/condition.hpp> @@ -41,6 +44,7 @@ struct get_turn_info_linear_areal typename Point1, typename Point2, typename TurnInfo, + typename IntersectionStrategy, typename RobustPolicy, typename OutputIterator > @@ -50,13 +54,19 @@ struct get_turn_info_linear_areal bool is_p_first, bool is_p_last, bool is_q_first, bool is_q_last, TurnInfo const& tp_model, + IntersectionStrategy const& intersection_strategy, RobustPolicy const& robust_policy, OutputIterator out) { - typedef intersection_info<Point1, Point2, typename TurnInfo::point_type, RobustPolicy> - inters_info; + typedef intersection_info + < + Point1, Point2, + typename TurnInfo::point_type, + IntersectionStrategy, + RobustPolicy + > inters_info; - inters_info inters(pi, pj, pk, qi, qj, qk, robust_policy); + inters_info inters(pi, pj, pk, qi, qj, qk, intersection_strategy, robust_policy); char const method = inters.d_info().how; @@ -108,9 +118,11 @@ struct get_turn_info_linear_areal < typename inters_info::cs_tag, typename inters_info::robust_point2_type, - typename inters_info::robust_point1_type + typename inters_info::robust_point1_type, + typename inters_info::side_strategy_type > swapped_side_calc(inters.rqi(), inters.rqj(), inters.rqk(), - inters.rpi(), inters.rpj(), inters.rpk()); + inters.rpi(), inters.rpj(), inters.rpk(), + inters.get_side_strategy()); policy::template apply<1>(qi, qj, qk, pi, pj, pk, tp, inters.i_info(), inters.d_info(), swapped_side_calc); @@ -395,7 +407,7 @@ struct get_turn_info_linear_areal std::cout << "TURN: Unknown method: " << method << std::endl; #endif #if ! defined(BOOST_GEOMETRY_OVERLAY_NO_THROW) - throw turn_info_exception(method); + BOOST_THROW_EXCEPTION(turn_info_exception(method)); #endif } break; @@ -747,6 +759,9 @@ struct get_turn_info_linear_areal } else { + typedef typename IntersectionInfo::robust_point1_type rp1_type; + typedef typename IntersectionInfo::robust_point2_type rp2_type; + method_type replaced_method = method_touch_interior; if ( ip0.is_qj ) @@ -754,11 +769,12 @@ struct get_turn_info_linear_areal side_calculator < typename IntersectionInfo::cs_tag, - typename IntersectionInfo::robust_point1_type, - typename IntersectionInfo::robust_point2_type, - typename IntersectionInfo::robust_point2_type + rp1_type, rp2_type, + typename IntersectionInfo::side_strategy_type, + rp2_type > side_calc(inters.rqi(), inters.rpi(), inters.rpj(), - inters.rqi(), inters.rqj(), inters.rqk()); + inters.rqi(), inters.rqj(), inters.rqk(), + inters.get_side_strategy()); std::pair<operation_type, operation_type> operations = get_info_e::operations_of_equal(side_calc); @@ -773,16 +789,13 @@ struct get_turn_info_linear_areal side_calculator < typename IntersectionInfo::cs_tag, - typename IntersectionInfo::robust_point1_type, - typename IntersectionInfo::robust_point2_type, - typename IntersectionInfo::robust_point2_type, - typename IntersectionInfo::robust_point1_type, - typename IntersectionInfo::robust_point1_type, - typename IntersectionInfo::robust_point2_type, - typename IntersectionInfo::robust_point1_type, - typename IntersectionInfo::robust_point2_type + rp1_type, rp2_type, + typename IntersectionInfo::side_strategy_type, + rp2_type, rp1_type, rp1_type, + rp2_type, rp1_type, rp2_type > side_calc(inters.rqi(), inters.rpi(), inters.rpj(), - inters.rqi(), inters.rpi(), inters.rqj()); + inters.rqi(), inters.rpi(), inters.rqj(), + inters.get_side_strategy()); std::pair<operation_type, operation_type> operations = get_info_e::operations_of_equal(side_calc); @@ -832,9 +845,11 @@ struct get_turn_info_linear_areal typename IntersectionInfo::cs_tag, typename IntersectionInfo::robust_point1_type, typename IntersectionInfo::robust_point2_type, + typename IntersectionInfo::side_strategy_type, typename IntersectionInfo::robust_point2_type > side_calc(inters.rqi(), inters.rpj(), inters.rpi(), - inters.rqi(), inters.rqj(), inters.rqk()); + inters.rqi(), inters.rqj(), inters.rqk(), + inters.get_side_strategy()); std::pair<operation_type, operation_type> operations = get_info_e::operations_of_equal(side_calc); diff --git a/boost/geometry/algorithms/detail/overlay/get_turn_info_ll.hpp b/boost/geometry/algorithms/detail/overlay/get_turn_info_ll.hpp index 6bb3a74bb8..58fd4bb5c7 100644 --- a/boost/geometry/algorithms/detail/overlay/get_turn_info_ll.hpp +++ b/boost/geometry/algorithms/detail/overlay/get_turn_info_ll.hpp @@ -1,19 +1,22 @@ // Boost.Geometry (aka GGL, Generic Geometry Library) // Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2017 Adam Wulkiewicz, Lodz, Poland. -// This file was modified by Oracle on 2013, 2014, 2015. -// Modifications copyright (c) 2013-2015 Oracle and/or its affiliates. +// This file was modified by Oracle on 2013, 2014, 2015, 2017. +// Modifications copyright (c) 2013-2017 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) -// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle - #ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_GET_TURN_INFO_LL_HPP #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_GET_TURN_INFO_LL_HPP +#include <boost/throw_exception.hpp> + #include <boost/geometry/core/assert.hpp> #include <boost/geometry/algorithms/detail/overlay/get_turn_info.hpp> @@ -36,6 +39,7 @@ struct get_turn_info_linear_linear typename Point1, typename Point2, typename TurnInfo, + typename IntersectionStrategy, typename RobustPolicy, typename OutputIterator > @@ -45,13 +49,19 @@ struct get_turn_info_linear_linear bool is_p_first, bool is_p_last, bool is_q_first, bool is_q_last, TurnInfo const& tp_model, + IntersectionStrategy const& strategy, RobustPolicy const& robust_policy, OutputIterator out) { - typedef intersection_info<Point1, Point2, typename TurnInfo::point_type, RobustPolicy> - inters_info; + typedef intersection_info + < + Point1, Point2, + typename TurnInfo::point_type, + IntersectionStrategy, + RobustPolicy + > inters_info; - inters_info inters(pi, pj, pk, qi, qj, qk, robust_policy); + inters_info inters(pi, pj, pk, qi, qj, qk, strategy, robust_policy); char const method = inters.d_info().how; @@ -103,9 +113,11 @@ struct get_turn_info_linear_linear < typename inters_info::cs_tag, typename inters_info::robust_point2_type, - typename inters_info::robust_point1_type + typename inters_info::robust_point1_type, + typename inters_info::side_strategy_type > swapped_side_calc(inters.rqi(), inters.rqj(), inters.rqk(), - inters.rpi(), inters.rpj(), inters.rpk()); + inters.rpi(), inters.rpj(), inters.rpk(), + inters.get_side_strategy()); policy::template apply<1>(qi, qj, qk, pi, pj, pk, tp, inters.i_info(), inters.d_info(), @@ -463,7 +475,7 @@ struct get_turn_info_linear_linear std::cout << "TURN: Unknown method: " << method << std::endl; #endif #if ! defined(BOOST_GEOMETRY_OVERLAY_NO_THROW) - throw turn_info_exception(method); + BOOST_THROW_EXCEPTION(turn_info_exception(method)); #endif } break; diff --git a/boost/geometry/algorithms/detail/overlay/get_turns.hpp b/boost/geometry/algorithms/detail/overlay/get_turns.hpp index 1eb18b74d4..4e97a84a37 100644 --- a/boost/geometry/algorithms/detail/overlay/get_turns.hpp +++ b/boost/geometry/algorithms/detail/overlay/get_turns.hpp @@ -3,15 +3,15 @@ // Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. // Copyright (c) 2014 Adam Wulkiewicz, Lodz, Poland. -// This file was modified by Oracle on 2014, 2016. -// Modifications copyright (c) 2014, 2016 Oracle and/or its affiliates. +// This file was modified by Oracle on 2014, 2016, 2017. +// Modifications copyright (c) 2014-2017 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) -// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle - #ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_GET_TURNS_HPP #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_GET_TURNS_HPP @@ -45,7 +45,6 @@ #include <boost/geometry/iterators/ever_circling_iterator.hpp> -#include <boost/geometry/strategies/cartesian/cart_intersect.hpp> #include <boost/geometry/strategies/intersection_strategies.hpp> #include <boost/geometry/strategies/intersection_result.hpp> @@ -174,11 +173,12 @@ class get_turns_in_sections public : // Returns true if terminated, false if interrupted - template <typename Turns, typename RobustPolicy, typename InterruptPolicy> + template <typename IntersectionStrategy, typename RobustPolicy, typename Turns, typename InterruptPolicy> static inline bool apply( int source_id1, Geometry1 const& geometry1, Section1 const& sec1, int source_id2, Geometry2 const& geometry2, Section2 const& sec2, bool skip_larger, + IntersectionStrategy const& intersection_strategy, RobustPolicy const& robust_policy, Turns& turns, InterruptPolicy& interrupt_policy) @@ -295,7 +295,8 @@ public : TurnPolicy::apply(*prev1, *it1, *nd_next1, *prev2, *it2, *nd_next2, is_1_first, is_1_last, is_2_first, is_2_last, - ti, robust_policy, std::back_inserter(turns)); + ti, intersection_strategy, robust_policy, + std::back_inserter(turns)); if (InterruptPolicy::enabled) { @@ -381,9 +382,10 @@ template < typename Geometry1, typename Geometry2, bool Reverse1, bool Reverse2, - typename Turns, typename TurnPolicy, + typename IntersectionStrategy, typename RobustPolicy, + typename Turns, typename InterruptPolicy > struct section_visitor @@ -392,16 +394,20 @@ struct section_visitor Geometry1 const& m_geometry1; int m_source_id2; Geometry2 const& m_geometry2; + IntersectionStrategy const& m_intersection_strategy; RobustPolicy const& m_rescale_policy; Turns& m_turns; InterruptPolicy& m_interrupt_policy; section_visitor(int id1, Geometry1 const& g1, - int id2, Geometry2 const& g2, - RobustPolicy const& robust_policy, - Turns& turns, InterruptPolicy& ip) + int id2, Geometry2 const& g2, + IntersectionStrategy const& intersection_strategy, + RobustPolicy const& robust_policy, + Turns& turns, + InterruptPolicy& ip) : m_source_id1(id1), m_geometry1(g1) , m_source_id2(id2), m_geometry2(g2) + , m_intersection_strategy(intersection_strategy) , m_rescale_policy(robust_policy) , m_turns(turns) , m_interrupt_policy(ip) @@ -423,6 +429,7 @@ struct section_visitor m_source_id1, m_geometry1, sec1, m_source_id2, m_geometry2, sec2, false, + m_intersection_strategy, m_rescale_policy, m_turns, m_interrupt_policy); } @@ -441,10 +448,11 @@ class get_turns_generic { public: - template <typename RobustPolicy, typename Turns, typename InterruptPolicy> + template <typename IntersectionStrategy, typename RobustPolicy, typename Turns, typename InterruptPolicy> static inline void apply( int source_id1, Geometry1 const& geometry1, int source_id2, Geometry2 const& geometry2, + IntersectionStrategy const& intersection_strategy, RobustPolicy const& robust_policy, Turns& turns, InterruptPolicy& interrupt_policy) @@ -475,15 +483,19 @@ public: < Geometry1, Geometry2, Reverse1, Reverse2, - Turns, TurnPolicy, RobustPolicy, InterruptPolicy - > visitor(source_id1, geometry1, source_id2, geometry2, robust_policy, turns, interrupt_policy); + TurnPolicy, + IntersectionStrategy, RobustPolicy, + Turns, InterruptPolicy + > visitor(source_id1, geometry1, source_id2, geometry2, + intersection_strategy, robust_policy, + turns, interrupt_policy); geometry::partition < - box_type, - detail::section::get_section_box, - detail::section::overlaps_section_box - >::apply(sec1, sec2, visitor); + box_type + >::apply(sec1, sec2, visitor, + detail::section::get_section_box(), + detail::section::overlaps_section_box()); } }; @@ -518,10 +530,11 @@ struct get_turns_cs >::type iterator_type; - template <typename RobustPolicy, typename Turns, typename InterruptPolicy> + template <typename IntersectionStrategy, typename RobustPolicy, typename Turns, typename InterruptPolicy> static inline void apply( int source_id1, Range const& range, int source_id2, Box const& box, + IntersectionStrategy const& intersection_strategy, RobustPolicy const& robust_policy, Turns& turns, InterruptPolicy& interrupt_policy, @@ -593,8 +606,10 @@ struct get_turns_cs // NOTE: some dummy values could be passed below since this would be called only for Polygons and Boxes index == 0, size_type(index) == segments_count1, + intersection_strategy, robust_policy, - turns, interrupt_policy); + turns, + interrupt_policy); // Future performance enhancement: // return if told by the interrupt policy } @@ -622,7 +637,7 @@ private: else return 0; } - template <typename RobustPolicy, typename Turns, typename InterruptPolicy> + template <typename IntersectionStrategy, typename RobustPolicy, typename Turns, typename InterruptPolicy> static inline void get_turns_with_box(segment_identifier const& seg_id, int source_id2, // Points from a range: point_type const& rp0, @@ -635,6 +650,7 @@ private: box_point_type const& bp3, bool const is_range_first, bool const is_range_last, + IntersectionStrategy const& intersection_strategy, RobustPolicy const& robust_policy, // Output Turns& turns, @@ -653,25 +669,29 @@ private: TurnPolicy::apply(rp0, rp1, rp2, bp0, bp1, bp2, is_range_first, is_range_last, true, false, - ti, robust_policy, std::back_inserter(turns)); + ti, intersection_strategy, robust_policy, + std::back_inserter(turns)); ti.operations[1].seg_id = segment_identifier(source_id2, -1, -1, 1); TurnPolicy::apply(rp0, rp1, rp2, bp1, bp2, bp3, is_range_first, is_range_last, false, false, - ti, robust_policy, std::back_inserter(turns)); + ti, intersection_strategy, robust_policy, + std::back_inserter(turns)); ti.operations[1].seg_id = segment_identifier(source_id2, -1, -1, 2); TurnPolicy::apply(rp0, rp1, rp2, bp2, bp3, bp0, is_range_first, is_range_last, false, false, - ti, robust_policy, std::back_inserter(turns)); + ti, intersection_strategy, robust_policy, + std::back_inserter(turns)); ti.operations[1].seg_id = segment_identifier(source_id2, -1, -1, 3); TurnPolicy::apply(rp0, rp1, rp2, bp3, bp0, bp1, is_range_first, is_range_last, false, true, - ti, robust_policy, std::back_inserter(turns)); + ti, intersection_strategy, robust_policy, + std::back_inserter(turns)); if (InterruptPolicy::enabled) { @@ -691,12 +711,14 @@ template > struct get_turns_polygon_cs { - template <typename RobustPolicy, typename Turns, typename InterruptPolicy> + template <typename IntersectionStrategy, typename RobustPolicy, typename Turns, typename InterruptPolicy> static inline void apply( int source_id1, Polygon const& polygon, int source_id2, Box const& box, + IntersectionStrategy const& intersection_strategy, RobustPolicy const& robust_policy, - Turns& turns, InterruptPolicy& interrupt_policy, + Turns& turns, + InterruptPolicy& interrupt_policy, signed_size_type multi_index = -1) { typedef typename geometry::ring_type<Polygon>::type ring_type; @@ -711,8 +733,10 @@ struct get_turns_polygon_cs intersector_type::apply( source_id1, geometry::exterior_ring(polygon), source_id2, box, + intersection_strategy, robust_policy, - turns, interrupt_policy, + turns, + interrupt_policy, multi_index, -1); signed_size_type i = 0; @@ -725,6 +749,7 @@ struct get_turns_polygon_cs intersector_type::apply( source_id1, *it, source_id2, box, + intersection_strategy, robust_policy, turns, interrupt_policy, multi_index, i); @@ -742,12 +767,14 @@ template > struct get_turns_multi_polygon_cs { - template <typename RobustPolicy, typename Turns, typename InterruptPolicy> + template <typename IntersectionStrategy, typename RobustPolicy, typename Turns, typename InterruptPolicy> static inline void apply( int source_id1, Multi const& multi, int source_id2, Box const& box, + IntersectionStrategy const& intersection_strategy, RobustPolicy const& robust_policy, - Turns& turns, InterruptPolicy& interrupt_policy) + Turns& turns, + InterruptPolicy& interrupt_policy) { typedef typename boost::range_iterator < @@ -766,7 +793,8 @@ struct get_turns_multi_polygon_cs Reverse, ReverseBox, TurnPolicy >::apply(source_id1, *it, source_id2, box, - robust_policy, turns, interrupt_policy, i); + intersection_strategy, robust_policy, + turns, interrupt_policy, i); } } }; @@ -918,13 +946,13 @@ template > struct get_turns_reversed { - template <typename RobustPolicy, typename Turns, typename InterruptPolicy> - static inline void apply( - int source_id1, Geometry1 const& g1, - int source_id2, Geometry2 const& g2, - RobustPolicy const& robust_policy, - Turns& turns, - InterruptPolicy& interrupt_policy) + template <typename IntersectionStrategy, typename RobustPolicy, typename Turns, typename InterruptPolicy> + static inline void apply(int source_id1, Geometry1 const& g1, + int source_id2, Geometry2 const& g2, + IntersectionStrategy const& intersection_strategy, + RobustPolicy const& robust_policy, + Turns& turns, + InterruptPolicy& interrupt_policy) { get_turns < @@ -932,8 +960,9 @@ struct get_turns_reversed Geometry2, Geometry1, Reverse2, Reverse1, TurnPolicy - >::apply(source_id2, g2, source_id1, g1, robust_policy, - turns, interrupt_policy); + >::apply(source_id2, g2, source_id1, g1, + intersection_strategy, robust_policy, + turns, interrupt_policy); } }; @@ -951,6 +980,7 @@ struct get_turns_reversed \tparam Turns type of turn-container (e.g. vector of "intersection/turn point"'s) \param geometry1 \param_geometry \param geometry2 \param_geometry +\param intersection_strategy segments intersection strategy \param robust_policy policy to handle robustness issues \param turns container which will contain turn points \param interrupt_policy policy determining if process is stopped @@ -962,15 +992,17 @@ template typename AssignPolicy, typename Geometry1, typename Geometry2, + typename IntersectionStrategy, typename RobustPolicy, typename Turns, typename InterruptPolicy > inline void get_turns(Geometry1 const& geometry1, - Geometry2 const& geometry2, - RobustPolicy const& robust_policy, - Turns& turns, - InterruptPolicy& interrupt_policy) + Geometry2 const& geometry2, + IntersectionStrategy const& intersection_strategy, + RobustPolicy const& robust_policy, + Turns& turns, + InterruptPolicy& interrupt_policy) { concepts::check_concepts_and_equal_dimensions<Geometry1 const, Geometry2 const>(); @@ -996,11 +1028,11 @@ inline void get_turns(Geometry1 const& geometry1, Reverse1, Reverse2, TurnPolicy > - >::type::apply( - 0, geometry1, - 1, geometry2, - robust_policy, - turns, interrupt_policy); + >::type::apply(0, geometry1, + 1, geometry2, + intersection_strategy, + robust_policy, + turns, interrupt_policy); } #if defined(_MSC_VER) diff --git a/boost/geometry/algorithms/detail/overlay/intersection_insert.hpp b/boost/geometry/algorithms/detail/overlay/intersection_insert.hpp index bb82003a23..3244480f48 100644 --- a/boost/geometry/algorithms/detail/overlay/intersection_insert.hpp +++ b/boost/geometry/algorithms/detail/overlay/intersection_insert.hpp @@ -2,10 +2,11 @@ // Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands. -// This file was modified by Oracle on 2014, 2015. -// Modifications copyright (c) 2014-2015 Oracle and/or its affiliates. +// This file was modified by Oracle on 2014, 2015, 2017. +// Modifications copyright (c) 2014-2017 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 // Use, modification and distribution is subject to the Boost Software License, // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at @@ -71,7 +72,7 @@ struct intersection_segment_segment_point Segment2 const& segment2, RobustPolicy const& robust_policy, OutputIterator out, - Strategy const& ) + Strategy const& strategy) { typedef typename point_type<PointOut>::type point_type; @@ -106,16 +107,15 @@ struct intersection_segment_segment_point >::type > intersection_return_type; - typedef strategy::intersection::relate_cartesian_segments + typedef policies::relate::segments_intersection_points < - policies::relate::segments_intersection_points - < - intersection_return_type - > - > policy; + intersection_return_type + > policy_type; - intersection_return_type is = policy::apply(segment1, segment2, - robust_policy, pi_rob, pj_rob, qi_rob, qj_rob); + intersection_return_type + is = strategy.apply(segment1, segment2, + policy_type(), robust_policy, + pi_rob, pj_rob, qi_rob, qj_rob); for (std::size_t i = 0; i < is.count; i++) { @@ -134,13 +134,14 @@ struct intersection_linestring_linestring_point < typename Linestring1, typename Linestring2, typename RobustPolicy, - typename OutputIterator, typename Strategy + typename OutputIterator, + typename Strategy > static inline OutputIterator apply(Linestring1 const& linestring1, Linestring2 const& linestring2, RobustPolicy const& robust_policy, OutputIterator out, - Strategy const& ) + Strategy const& strategy) { typedef typename point_type<PointOut>::type point_type; @@ -151,7 +152,8 @@ struct intersection_linestring_linestring_point > turn_info; std::deque<turn_info> turns; - geometry::get_intersection_points(linestring1, linestring2, robust_policy, turns); + geometry::get_intersection_points(linestring1, linestring2, + robust_policy, turns, strategy); for (typename boost::range_iterator<std::deque<turn_info> const>::type it = boost::begin(turns); it != boost::end(turns); ++it) @@ -295,7 +297,7 @@ struct intersection_of_linestring_with_areal static inline OutputIterator apply(LineString const& linestring, Areal const& areal, RobustPolicy const& robust_policy, OutputIterator out, - Strategy const& ) + Strategy const& strategy) { if (boost::size(linestring) == 0) { @@ -325,7 +327,7 @@ struct intersection_of_linestring_with_areal false, (OverlayType == overlay_intersection ? ReverseAreal : !ReverseAreal), detail::overlay::assign_null_policy - >(linestring, areal, robust_policy, turns, policy); + >(linestring, areal, strategy, robust_policy, turns, policy); if (no_crossing_turns_or_empty(turns)) { @@ -621,7 +623,7 @@ struct intersection_insert static inline OutputIterator apply(Geometry1 const& geometry1, Geometry2 const& geometry2, RobustPolicy const& robust_policy, - OutputIterator out, Strategy const& ) + OutputIterator out, Strategy const& strategy) { typedef detail::overlay::turn_info @@ -635,7 +637,7 @@ struct intersection_insert geometry::get_turns < false, false, detail::overlay::assign_null_policy - >(geometry1, geometry2, robust_policy, turns, policy); + >(geometry1, geometry2, strategy, robust_policy, turns, policy); for (typename std::vector<turn_info>::const_iterator it = turns.begin(); it != turns.end(); ++it) { @@ -996,7 +998,11 @@ inline OutputIterator intersection_insert(Geometry1 const& geometry1, concepts::check<Geometry1 const>(); concepts::check<Geometry2 const>(); - typedef typename Strategy::rescale_policy_type rescale_policy_type; + typedef typename geometry::rescale_policy_type + < + typename geometry::point_type<Geometry1>::type // TODO from both + >::type rescale_policy_type; + rescale_policy_type robust_policy = geometry::get_rescale_policy<rescale_policy_type>(geometry1, geometry2); @@ -1037,22 +1043,13 @@ inline OutputIterator intersection_insert(Geometry1 const& geometry1, concepts::check<Geometry1 const>(); concepts::check<Geometry2 const>(); - typedef typename geometry::rescale_policy_type - < - typename geometry::point_type<Geometry1>::type // TODO from both - >::type rescale_policy_type; - - typedef intersection_strategies + typedef typename strategy::intersection::services::default_strategy < - typename cs_tag<GeometryOut>::type, - Geometry1, - Geometry2, - typename geometry::point_type<GeometryOut>::type, - rescale_policy_type - > strategy; - + typename cs_tag<GeometryOut>::type + >::type strategy_type; + return intersection_insert<GeometryOut>(geometry1, geometry2, out, - strategy()); + strategy_type()); } }} // namespace detail::intersection diff --git a/boost/geometry/algorithms/detail/overlay/linear_linear.hpp b/boost/geometry/algorithms/detail/overlay/linear_linear.hpp index 34517f6590..a74bb33ba1 100644 --- a/boost/geometry/algorithms/detail/overlay/linear_linear.hpp +++ b/boost/geometry/algorithms/detail/overlay/linear_linear.hpp @@ -1,11 +1,12 @@ // Boost.Geometry (aka GGL, Generic Geometry Library) -// Copyright (c) 2014-2015, Oracle and/or its affiliates. +// Copyright (c) 2014-2017, Oracle and/or its affiliates. // Licensed under the Boost Software License version 1.0. // http://www.boost.org/users/license.html // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle +// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle #ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_LINEAR_LINEAR_HPP @@ -158,11 +159,13 @@ protected: typename Turns, typename LinearGeometry1, typename LinearGeometry2, + typename IntersectionStrategy, typename RobustPolicy > static inline void compute_turns(Turns& turns, LinearGeometry1 const& linear1, LinearGeometry2 const& linear2, + IntersectionStrategy const& strategy, RobustPolicy const& robust_policy) { turns.clear(); @@ -180,7 +183,7 @@ protected: assign_policy >, RobustPolicy - >::apply(turns, linear1, linear2, interrupt_policy, robust_policy); + >::apply(turns, linear1, linear2, interrupt_policy, strategy, robust_policy); } @@ -237,7 +240,7 @@ public: Linear2 const& linear2, RobustPolicy const& robust_policy, OutputIterator oit, - Strategy const& ) + Strategy const& strategy) { typedef typename detail::relate::turns::get_turns < @@ -255,7 +258,7 @@ public: typedef std::vector<turn_info> turns_container; turns_container turns; - compute_turns(turns, linear1, linear2, robust_policy); + compute_turns(turns, linear1, linear2, strategy, robust_policy); if ( turns.empty() ) { diff --git a/boost/geometry/algorithms/detail/overlay/overlay.hpp b/boost/geometry/algorithms/detail/overlay/overlay.hpp index 09c80025a0..f1af2f1949 100644 --- a/boost/geometry/algorithms/detail/overlay/overlay.hpp +++ b/boost/geometry/algorithms/detail/overlay/overlay.hpp @@ -3,10 +3,11 @@ // Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands. // Copyright (c) 2013-2015 Adam Wulkiewicz, Lodz, Poland -// This file was modified by Oracle on 2015. -// Modifications copyright (c) 2015, Oracle and/or its affiliates. +// This file was modified by Oracle on 2015, 2017. +// Modifications copyright (c) 2015-2017, 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 // Use, modification and distribution is subject to the Boost Software License, // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at @@ -184,7 +185,7 @@ struct overlay Geometry1 const& geometry1, Geometry2 const& geometry2, RobustPolicy const& robust_policy, OutputIterator out, - Strategy const& , + Strategy const& strategy, Visitor& visitor) { bool const is_empty1 = geometry::is_empty(geometry1); @@ -233,7 +234,7 @@ std::cout << "get turns" << std::endl; < Reverse1, Reverse2, detail::overlay::assign_null_policy - >(geometry1, geometry2, robust_policy, turns, policy); + >(geometry1, geometry2, strategy, robust_policy, turns, policy); visitor.visit_turns(1, turns); @@ -262,6 +263,7 @@ std::cout << "traverse" << std::endl; traverse<Reverse1, Reverse2, Geometry1, Geometry2, OverlayType>::apply ( geometry1, geometry2, + strategy, robust_policy, turns, rings, clusters, diff --git a/boost/geometry/algorithms/detail/overlay/pointlike_linear.hpp b/boost/geometry/algorithms/detail/overlay/pointlike_linear.hpp index 156cb54867..a26f54e008 100644 --- a/boost/geometry/algorithms/detail/overlay/pointlike_linear.hpp +++ b/boost/geometry/algorithms/detail/overlay/pointlike_linear.hpp @@ -1,12 +1,13 @@ // Boost.Geometry (aka GGL, Generic Geometry Library) -// Copyright (c) 2015, Oracle and/or its affiliates. +// Copyright (c) 2015-2017, 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 // Licensed under the Boost Software License version 1.0. // http://www.boost.org/users/license.html -// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle - #ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_POINTLIKE_LINEAR_HPP #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_POINTLIKE_LINEAR_HPP @@ -69,12 +70,12 @@ struct point_linear_point Linear const& linear, RobustPolicy const&, OutputIterator oit, - Strategy const&) + Strategy const& strategy) { action_selector_pl_l < PointOut, OverlayType - >::apply(point, Policy::apply(point, linear), oit); + >::apply(point, Policy::apply(point, linear, strategy), oit); return oit; } }; @@ -95,7 +96,7 @@ struct multipoint_segment_point Segment const& segment, RobustPolicy const&, OutputIterator oit, - Strategy const&) + Strategy const& strategy) { for (typename boost::range_iterator<MultiPoint const>::type it = boost::begin(multipoint); @@ -105,7 +106,7 @@ struct multipoint_segment_point action_selector_pl_l < PointOut, OverlayType - >::apply(*it, Policy::apply(*it, segment), oit); + >::apply(*it, Policy::apply(*it, segment, strategy), oit); } return oit; @@ -145,11 +146,14 @@ private: } }; - template <typename OutputIterator> + template <typename OutputIterator, typename Strategy> class item_visitor_type { public: - item_visitor_type(OutputIterator& oit) : m_oit(oit) {} + item_visitor_type(OutputIterator& oit, Strategy const& strategy) + : m_oit(oit) + , m_strategy(strategy) + {} template <typename Item1, typename Item2> inline void apply(Item1 const& item1, Item2 const& item2) @@ -157,11 +161,12 @@ private: action_selector_pl_l < PointOut, overlay_intersection - >::apply(item1, Policy::apply(item1, item2), m_oit); + >::apply(item1, Policy::apply(item1, item2, m_strategy), m_oit); } private: OutputIterator& m_oit; + Strategy const& m_strategy; }; // structs for partition -- end @@ -189,12 +194,13 @@ private: Linear const& m_linear; }; - template <typename OutputIterator> + template <typename OutputIterator, typename Strategy> static inline OutputIterator get_common_points(MultiPoint const& multipoint, Linear const& linear, - OutputIterator oit) + OutputIterator oit, + Strategy const& strategy) { - item_visitor_type<OutputIterator> item_visitor(oit); + item_visitor_type<OutputIterator, Strategy> item_visitor(oit, strategy); segment_range rng(linear); @@ -203,10 +209,9 @@ private: geometry::model::box < typename boost::range_value<MultiPoint>::type - >, - expand_box, - overlaps_box - >::apply(multipoint, rng, item_visitor); + > + >::apply(multipoint, rng, item_visitor, + expand_box(), overlaps_box()); return oit; } @@ -228,7 +233,8 @@ public: // compute the common points get_common_points(multipoint, linear, - std::back_inserter(common_points)); + std::back_inserter(common_points), + strategy); return multipoint_multipoint_point < diff --git a/boost/geometry/algorithms/detail/overlay/self_turn_points.hpp b/boost/geometry/algorithms/detail/overlay/self_turn_points.hpp index aedf22e1fb..8540ef98a0 100644 --- a/boost/geometry/algorithms/detail/overlay/self_turn_points.hpp +++ b/boost/geometry/algorithms/detail/overlay/self_turn_points.hpp @@ -2,6 +2,11 @@ // Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. +// This file was modified by Oracle on 2017. +// Modifications copyright (c) 2017 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) @@ -61,20 +66,25 @@ template typename Geometry, typename Turns, typename TurnPolicy, + typename IntersectionStrategy, typename RobustPolicy, typename InterruptPolicy > struct self_section_visitor { Geometry const& m_geometry; + IntersectionStrategy const& m_intersection_strategy; RobustPolicy const& m_rescale_policy; Turns& m_turns; InterruptPolicy& m_interrupt_policy; inline self_section_visitor(Geometry const& g, - RobustPolicy const& rp, - Turns& turns, InterruptPolicy& ip) + IntersectionStrategy const& is, + RobustPolicy const& rp, + Turns& turns, + InterruptPolicy& ip) : m_geometry(g) + , m_intersection_strategy(is) , m_rescale_policy(rp) , m_turns(turns) , m_interrupt_policy(ip) @@ -97,6 +107,7 @@ struct self_section_visitor 0, m_geometry, sec1, 0, m_geometry, sec2, false, + m_intersection_strategy, m_rescale_policy, m_turns, m_interrupt_policy); } @@ -116,9 +127,10 @@ struct self_section_visitor template<typename TurnPolicy> struct get_turns { - template <typename Geometry, typename RobustPolicy, typename Turns, typename InterruptPolicy> + template <typename Geometry, typename IntersectionStrategy, typename RobustPolicy, typename Turns, typename InterruptPolicy> static inline bool apply( Geometry const& geometry, + IntersectionStrategy const& intersection_strategy, RobustPolicy const& robust_policy, Turns& turns, InterruptPolicy& interrupt_policy) @@ -142,17 +154,17 @@ struct get_turns self_section_visitor < Geometry, - Turns, TurnPolicy, RobustPolicy, InterruptPolicy - > visitor(geometry, robust_policy, turns, interrupt_policy); + Turns, TurnPolicy, IntersectionStrategy, RobustPolicy, InterruptPolicy + > visitor(geometry, intersection_strategy, robust_policy, turns, interrupt_policy); try { geometry::partition < - box_type, - detail::section::get_section_box, - detail::section::overlaps_section_box - >::apply(sec, visitor); + box_type + >::apply(sec, visitor, + detail::section::get_section_box(), + detail::section::overlaps_section_box()); } catch(self_ip_exception const& ) { @@ -208,9 +220,10 @@ struct self_get_turn_points TurnPolicy > { - template <typename RobustPolicy, typename Turns, typename InterruptPolicy> + template <typename Strategy, typename RobustPolicy, typename Turns, typename InterruptPolicy> static inline bool apply( Box const& , + Strategy const& , RobustPolicy const& , Turns& , InterruptPolicy& ) @@ -259,6 +272,7 @@ struct self_get_turn_points \tparam Turns type of intersection container (e.g. vector of "intersection/turn point"'s) \param geometry geometry + \param strategy strategy to be used \param robust_policy policy to handle robustness issues \param turns container which will contain intersection points \param interrupt_policy policy determining if process is stopped @@ -268,13 +282,15 @@ template < typename AssignPolicy, typename Geometry, + typename IntersectionStrategy, typename RobustPolicy, typename Turns, typename InterruptPolicy > inline void self_turns(Geometry const& geometry, - RobustPolicy const& robust_policy, - Turns& turns, InterruptPolicy& interrupt_policy) + IntersectionStrategy const& strategy, + RobustPolicy const& robust_policy, + Turns& turns, InterruptPolicy& interrupt_policy) { concepts::check<Geometry const>(); @@ -285,7 +301,7 @@ inline void self_turns(Geometry const& geometry, typename tag<Geometry>::type, Geometry, turn_policy - >::apply(geometry, robust_policy, turns, interrupt_policy); + >::apply(geometry, strategy, robust_policy, turns, interrupt_policy); } diff --git a/boost/geometry/algorithms/detail/overlay/traversal.hpp b/boost/geometry/algorithms/detail/overlay/traversal.hpp index 5adc0fcf69..bc828920e9 100644 --- a/boost/geometry/algorithms/detail/overlay/traversal.hpp +++ b/boost/geometry/algorithms/detail/overlay/traversal.hpp @@ -140,10 +140,10 @@ struct traversal { for (int i = 0; i < 2; i++) { - turn_operation_type& op = turn.operations[i]; - if (op.visited.none()) + turn_operation_type& turn_op = turn.operations[i]; + if (turn_op.visited.none()) { - op.visited.set_visited(); + turn_op.visited.set_visited(); } } } diff --git a/boost/geometry/algorithms/detail/overlay/traversal_ring_creator.hpp b/boost/geometry/algorithms/detail/overlay/traversal_ring_creator.hpp index e0dfee19a8..9ab82a77c1 100644 --- a/boost/geometry/algorithms/detail/overlay/traversal_ring_creator.hpp +++ b/boost/geometry/algorithms/detail/overlay/traversal_ring_creator.hpp @@ -2,6 +2,10 @@ // Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. +// This file was modified by Oracle on 2017. +// Modifications copyright (c) 2017, 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) @@ -38,6 +42,7 @@ template typename Geometry2, typename Turns, typename Clusters, + typename IntersectionStrategy, typename RobustPolicy, typename Visitor, typename Backtrack @@ -56,12 +61,14 @@ struct traversal_ring_creator inline traversal_ring_creator(Geometry1 const& geometry1, Geometry2 const& geometry2, Turns& turns, Clusters const& clusters, + IntersectionStrategy const& intersection_strategy, RobustPolicy const& robust_policy, Visitor& visitor) : m_trav(geometry1, geometry2, turns, clusters, robust_policy,visitor) , m_geometry1(geometry1) , m_geometry2(geometry2) , m_turns(turns) , m_clusters(clusters) + , m_intersection_strategy(intersection_strategy) , m_robust_policy(robust_policy) , m_visitor(visitor) { @@ -280,7 +287,8 @@ struct traversal_ring_creator rings, ring, m_turns, start_turn, m_turns[turn_index].operations[op_index], traverse_error, - m_geometry1, m_geometry2, m_robust_policy, + m_geometry1, m_geometry2, + m_intersection_strategy, m_robust_policy, state, m_visitor); } } @@ -314,6 +322,7 @@ private: Geometry2 const& m_geometry2; Turns& m_turns; Clusters const& m_clusters; + IntersectionStrategy const& m_intersection_strategy; RobustPolicy const& m_robust_policy; Visitor& m_visitor; }; diff --git a/boost/geometry/algorithms/detail/overlay/traverse.hpp b/boost/geometry/algorithms/detail/overlay/traverse.hpp index f01e50eb03..058f6c9458 100644 --- a/boost/geometry/algorithms/detail/overlay/traverse.hpp +++ b/boost/geometry/algorithms/detail/overlay/traverse.hpp @@ -58,6 +58,7 @@ class traverse public : template < + typename IntersectionStrategy, typename RobustPolicy, typename Turns, typename Rings, @@ -66,6 +67,7 @@ public : > static inline void apply(Geometry1 const& geometry1, Geometry2 const& geometry2, + IntersectionStrategy const& intersection_strategy, RobustPolicy const& robust_policy, Turns& turns, Rings& rings, Clusters& clusters, @@ -88,10 +90,11 @@ public : Reverse1, Reverse2, OverlayType, Geometry1, Geometry2, Turns, Clusters, + IntersectionStrategy, RobustPolicy, Visitor, Backtrack > trav(geometry1, geometry2, turns, clusters, - robust_policy, visitor); + intersection_strategy, robust_policy, visitor); std::size_t finalized_ring_size = boost::size(rings); diff --git a/boost/geometry/algorithms/detail/partition.hpp b/boost/geometry/algorithms/detail/partition.hpp index 8b19add479..12c6a54661 100644 --- a/boost/geometry/algorithms/detail/partition.hpp +++ b/boost/geometry/algorithms/detail/partition.hpp @@ -2,10 +2,11 @@ // Copyright (c) 2011-2015 Barend Gehrels, Amsterdam, the Netherlands. -// This file was modified by Oracle on 2015. -// Modifications copyright (c) 2015 Oracle and/or its affiliates. +// This file was modified by Oracle on 2015, 2017. +// Modifications copyright (c) 2015-2017 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 // Use, modification and distribution is subject to the Boost Software License, // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at @@ -47,13 +48,14 @@ inline void divide_box(Box const& box, Box& lower_box, Box& upper_box) // Divide forward_range into three subsets: lower, upper and oversized // (not-fitting) // (lower == left or bottom, upper == right or top) -template <typename OverlapsPolicy, typename Box, typename IteratorVector> +template <typename Box, typename IteratorVector, typename OverlapsPolicy> inline void divide_into_subsets(Box const& lower_box, - Box const& upper_box, - IteratorVector const& input, - IteratorVector& lower, - IteratorVector& upper, - IteratorVector& exceeding) + Box const& upper_box, + IteratorVector const& input, + IteratorVector& lower, + IteratorVector& upper, + IteratorVector& exceeding, + OverlapsPolicy const& overlaps_policy) { typedef typename boost::range_iterator < @@ -62,8 +64,8 @@ inline void divide_into_subsets(Box const& lower_box, for(it_type it = boost::begin(input); it != boost::end(input); ++it) { - bool const lower_overlapping = OverlapsPolicy::apply(lower_box, **it); - bool const upper_overlapping = OverlapsPolicy::apply(upper_box, **it); + bool const lower_overlapping = overlaps_policy.apply(lower_box, **it); + bool const upper_overlapping = overlaps_policy.apply(upper_box, **it); if (lower_overlapping && upper_overlapping) { @@ -87,23 +89,24 @@ inline void divide_into_subsets(Box const& lower_box, template < - typename ExpandPolicy, typename Box, - typename IteratorVector + typename IteratorVector, + typename ExpandPolicy > -inline void expand_with_elements(Box& total, IteratorVector const& input) +inline void expand_with_elements(Box& total, IteratorVector const& input, + ExpandPolicy const& expand_policy) { typedef typename boost::range_iterator<IteratorVector const>::type it_type; for(it_type it = boost::begin(input); it != boost::end(input); ++it) { - ExpandPolicy::apply(total, **it); + expand_policy.apply(total, **it); } } // Match forward_range with itself -template <typename Policy, typename IteratorVector> -inline void handle_one(IteratorVector const& input, Policy& policy) +template <typename IteratorVector, typename VisitPolicy> +inline void handle_one(IteratorVector const& input, VisitPolicy& visitor) { if (boost::size(input) == 0) { @@ -118,7 +121,7 @@ inline void handle_one(IteratorVector const& input, Policy& policy) it_type it2 = it1; for (++it2; it2 != boost::end(input); ++it2) { - policy.apply(**it1, **it2); + visitor.apply(**it1, **it2); } } } @@ -126,13 +129,13 @@ inline void handle_one(IteratorVector const& input, Policy& policy) // Match forward range 1 with forward range 2 template < - typename Policy, typename IteratorVector1, - typename IteratorVector2 + typename IteratorVector2, + typename VisitPolicy > inline void handle_two(IteratorVector1 const& input1, - IteratorVector2 const& input2, - Policy& policy) + IteratorVector2 const& input2, + VisitPolicy& visitor) { typedef typename boost::range_iterator < @@ -157,14 +160,14 @@ inline void handle_two(IteratorVector1 const& input1, it2 != boost::end(input2); ++it2) { - policy.apply(**it1, **it2); + visitor.apply(**it1, **it2); } } } template <typename IteratorVector> inline bool recurse_ok(IteratorVector const& input, - std::size_t min_elements, std::size_t level) + std::size_t min_elements, std::size_t level) { return boost::size(input) >= min_elements && level < 100; @@ -172,8 +175,8 @@ inline bool recurse_ok(IteratorVector const& input, template <typename IteratorVector1, typename IteratorVector2> inline bool recurse_ok(IteratorVector1 const& input1, - IteratorVector2 const& input2, - std::size_t min_elements, std::size_t level) + IteratorVector2 const& input2, + std::size_t min_elements, std::size_t level) { return boost::size(input1) >= min_elements && recurse_ok(input2, min_elements, level); @@ -186,103 +189,114 @@ template typename IteratorVector3 > inline bool recurse_ok(IteratorVector1 const& input1, - IteratorVector2 const& input2, - IteratorVector3 const& input3, - std::size_t min_elements, std::size_t level) + IteratorVector2 const& input2, + IteratorVector3 const& input3, + std::size_t min_elements, std::size_t level) { return boost::size(input1) >= min_elements && recurse_ok(input2, input3, min_elements, level); } -template -< - int Dimension, - typename Box, - typename OverlapsPolicy1, - typename OverlapsPolicy2, - typename ExpandPolicy1, - typename ExpandPolicy2, - typename VisitBoxPolicy -> + +template <int Dimension, typename Box> class partition_two_ranges; -template -< - int Dimension, - typename Box, - typename OverlapsPolicy, - typename ExpandPolicy, - typename VisitBoxPolicy -> +template <int Dimension, typename Box> class partition_one_range { - template <typename IteratorVector> - static inline Box get_new_box(IteratorVector const& input) + template <typename IteratorVector, typename ExpandPolicy> + static inline Box get_new_box(IteratorVector const& input, + ExpandPolicy const& expand_policy) { Box box; geometry::assign_inverse(box); - expand_with_elements<ExpandPolicy>(box, input); + expand_with_elements(box, input, expand_policy); return box; } - template <typename Policy, typename IteratorVector> + template + < + typename IteratorVector, + typename VisitPolicy, + typename ExpandPolicy, + typename OverlapsPolicy, + typename VisitBoxPolicy + > static inline void next_level(Box const& box, - IteratorVector const& input, - std::size_t level, std::size_t min_elements, - Policy& policy, VisitBoxPolicy& box_policy) + IteratorVector const& input, + std::size_t level, std::size_t min_elements, + VisitPolicy& visitor, + ExpandPolicy const& expand_policy, + OverlapsPolicy const& overlaps_policy, + VisitBoxPolicy& box_policy) { if (recurse_ok(input, min_elements, level)) { partition_one_range - < - 1 - Dimension, - Box, - OverlapsPolicy, - ExpandPolicy, - VisitBoxPolicy - >::apply(box, input, level + 1, min_elements, policy, box_policy); + < + 1 - Dimension, + Box + >::apply(box, input, level + 1, min_elements, + visitor, expand_policy, overlaps_policy, box_policy); } else { - handle_one(input, policy); + handle_one(input, visitor); } } // Function to switch to two forward ranges if there are // geometries exceeding the separation line - template <typename Policy, typename IteratorVector> + template + < + typename IteratorVector, + typename VisitPolicy, + typename ExpandPolicy, + typename OverlapsPolicy, + typename VisitBoxPolicy + > static inline void next_level2(Box const& box, IteratorVector const& input1, IteratorVector const& input2, std::size_t level, std::size_t min_elements, - Policy& policy, VisitBoxPolicy& box_policy) + VisitPolicy& visitor, + ExpandPolicy const& expand_policy, + OverlapsPolicy const& overlaps_policy, + VisitBoxPolicy& box_policy) { if (recurse_ok(input1, input2, min_elements, level)) { partition_two_ranges - < - 1 - Dimension, - Box, - OverlapsPolicy, OverlapsPolicy, - ExpandPolicy, ExpandPolicy, - VisitBoxPolicy - >::apply(box, input1, input2, level + 1, min_elements, - policy, box_policy); + < + 1 - Dimension, Box + >::apply(box, input1, input2, level + 1, min_elements, + visitor, expand_policy, overlaps_policy, + expand_policy, overlaps_policy, box_policy); } else { - handle_two(input1, input2, policy); + handle_two(input1, input2, visitor); } } public : - template <typename Policy, typename IteratorVector> + template + < + typename IteratorVector, + typename VisitPolicy, + typename ExpandPolicy, + typename OverlapsPolicy, + typename VisitBoxPolicy + > static inline void apply(Box const& box, - IteratorVector const& input, - std::size_t level, - std::size_t min_elements, - Policy& policy, VisitBoxPolicy& box_policy) + IteratorVector const& input, + std::size_t level, + std::size_t min_elements, + VisitPolicy& visitor, + ExpandPolicy const& expand_policy, + OverlapsPolicy const& overlaps_policy, + VisitBoxPolicy& box_policy) { box_policy.apply(box, level); @@ -290,101 +304,121 @@ public : divide_box<Dimension>(box, lower_box, upper_box); IteratorVector lower, upper, exceeding; - divide_into_subsets<OverlapsPolicy>(lower_box, upper_box, - input, lower, upper, exceeding); + divide_into_subsets(lower_box, upper_box, + input, lower, upper, exceeding, + overlaps_policy); if (boost::size(exceeding) > 0) { // Get the box of exceeding-only - Box exceeding_box = get_new_box(exceeding); + Box exceeding_box = get_new_box(exceeding, expand_policy); // Recursively do exceeding elements only, in next dimension they // will probably be less exceeding within the new box next_level(exceeding_box, exceeding, level, min_elements, - policy, box_policy); + visitor, expand_policy, overlaps_policy, box_policy); // Switch to two forward ranges, combine exceeding with // lower resp upper, but not lower/lower, upper/upper next_level2(exceeding_box, exceeding, lower, level, min_elements, - policy, box_policy); + visitor, expand_policy, overlaps_policy, box_policy); next_level2(exceeding_box, exceeding, upper, level, min_elements, - policy, box_policy); + visitor, expand_policy, overlaps_policy, box_policy); } // Recursively call operation both parts - next_level(lower_box, lower, level, min_elements, policy, box_policy); - next_level(upper_box, upper, level, min_elements, policy, box_policy); + next_level(lower_box, lower, level, min_elements, + visitor, expand_policy, overlaps_policy, box_policy); + next_level(upper_box, upper, level, min_elements, + visitor, expand_policy, overlaps_policy, box_policy); } }; template < int Dimension, - typename Box, - typename OverlapsPolicy1, - typename OverlapsPolicy2, - typename ExpandPolicy1, - typename ExpandPolicy2, - typename VisitBoxPolicy + typename Box > class partition_two_ranges { template < - typename Policy, typename IteratorVector1, - typename IteratorVector2 + typename IteratorVector2, + typename VisitPolicy, + typename ExpandPolicy1, + typename OverlapsPolicy1, + typename ExpandPolicy2, + typename OverlapsPolicy2, + typename VisitBoxPolicy > static inline void next_level(Box const& box, IteratorVector1 const& input1, IteratorVector2 const& input2, std::size_t level, std::size_t min_elements, - Policy& policy, VisitBoxPolicy& box_policy) + VisitPolicy& visitor, + ExpandPolicy1 const& expand_policy1, + OverlapsPolicy1 const& overlaps_policy1, + ExpandPolicy2 const& expand_policy2, + OverlapsPolicy2 const& overlaps_policy2, + VisitBoxPolicy& box_policy) { partition_two_ranges < - 1 - Dimension, - Box, - OverlapsPolicy1, - OverlapsPolicy2, - ExpandPolicy1, - ExpandPolicy2, - VisitBoxPolicy + 1 - Dimension, Box >::apply(box, input1, input2, level + 1, min_elements, - policy, box_policy); + visitor, expand_policy1, overlaps_policy1, + expand_policy2, overlaps_policy2, box_policy); } - template <typename ExpandPolicy, typename IteratorVector> - static inline Box get_new_box(IteratorVector const& input) + template <typename IteratorVector, typename ExpandPolicy> + static inline Box get_new_box(IteratorVector const& input, + ExpandPolicy const& expand_policy) { Box box; geometry::assign_inverse(box); - expand_with_elements<ExpandPolicy>(box, input); + expand_with_elements(box, input, expand_policy); return box; } - template <typename IteratorVector1, typename IteratorVector2> + template + < + typename IteratorVector1, typename IteratorVector2, + typename ExpandPolicy1, typename ExpandPolicy2 + > static inline Box get_new_box(IteratorVector1 const& input1, - IteratorVector2 const& input2) + IteratorVector2 const& input2, + ExpandPolicy1 const& expand_policy1, + ExpandPolicy2 const& expand_policy2) { - Box box = get_new_box<ExpandPolicy1>(input1); - expand_with_elements<ExpandPolicy2>(box, input2); + Box box = get_new_box(input1, expand_policy1); + expand_with_elements(box, input2, expand_policy2); return box; } public : template < - typename Policy, typename IteratorVector1, - typename IteratorVector2 + typename IteratorVector2, + typename VisitPolicy, + typename ExpandPolicy1, + typename OverlapsPolicy1, + typename ExpandPolicy2, + typename OverlapsPolicy2, + typename VisitBoxPolicy > static inline void apply(Box const& box, IteratorVector1 const& input1, IteratorVector2 const& input2, std::size_t level, std::size_t min_elements, - Policy& policy, VisitBoxPolicy& box_policy) + VisitPolicy& visitor, + ExpandPolicy1 const& expand_policy1, + OverlapsPolicy1 const& overlaps_policy1, + ExpandPolicy2 const& expand_policy2, + OverlapsPolicy2 const& overlaps_policy2, + VisitBoxPolicy& box_policy) { box_policy.apply(box, level); @@ -393,10 +427,12 @@ public : IteratorVector1 lower1, upper1, exceeding1; IteratorVector2 lower2, upper2, exceeding2; - divide_into_subsets<OverlapsPolicy1>(lower_box, upper_box, - input1, lower1, upper1, exceeding1); - divide_into_subsets<OverlapsPolicy2>(lower_box, upper_box, - input2, lower2, upper2, exceeding2); + divide_into_subsets(lower_box, upper_box, + input1, lower1, upper1, exceeding1, + overlaps_policy1); + divide_into_subsets(lower_box, upper_box, + input2, lower2, upper2, exceeding2, + overlaps_policy2); if (boost::size(exceeding1) > 0) { @@ -404,13 +440,15 @@ public : if (recurse_ok(exceeding1, exceeding2, min_elements, level)) { - Box exceeding_box = get_new_box(exceeding1, exceeding2); + Box exceeding_box = get_new_box(exceeding1, exceeding2, + expand_policy1, expand_policy2); next_level(exceeding_box, exceeding1, exceeding2, level, - min_elements, policy, box_policy); + min_elements, visitor, expand_policy1, overlaps_policy1, + expand_policy2, overlaps_policy2, box_policy); } else { - handle_two(exceeding1, exceeding2, policy); + handle_two(exceeding1, exceeding2, visitor); } // All exceeding from 1 with lower and upper of 2: @@ -419,16 +457,18 @@ public : // the same combinations again and again) if (recurse_ok(lower2, upper2, exceeding1, min_elements, level)) { - Box exceeding_box = get_new_box<ExpandPolicy1>(exceeding1); + Box exceeding_box = get_new_box(exceeding1, expand_policy1); next_level(exceeding_box, exceeding1, lower2, level, - min_elements, policy, box_policy); + min_elements, visitor, expand_policy1, overlaps_policy1, + expand_policy2, overlaps_policy2, box_policy); next_level(exceeding_box, exceeding1, upper2, level, - min_elements, policy, box_policy); + min_elements, visitor, expand_policy1, overlaps_policy1, + expand_policy2, overlaps_policy2, box_policy); } else { - handle_two(exceeding1, lower2, policy); - handle_two(exceeding1, upper2, policy); + handle_two(exceeding1, lower2, visitor); + handle_two(exceeding1, upper2, visitor); } } @@ -437,36 +477,40 @@ public : // All exceeding from 2 with lower and upper of 1: if (recurse_ok(lower1, upper1, exceeding2, min_elements, level)) { - Box exceeding_box = get_new_box<ExpandPolicy2>(exceeding2); + Box exceeding_box = get_new_box(exceeding2, expand_policy2); next_level(exceeding_box, lower1, exceeding2, level, - min_elements, policy, box_policy); + min_elements, visitor, expand_policy1, overlaps_policy1, + expand_policy2, overlaps_policy2, box_policy); next_level(exceeding_box, upper1, exceeding2, level, - min_elements, policy, box_policy); + min_elements, visitor, expand_policy1, overlaps_policy1, + expand_policy2, overlaps_policy2, box_policy); } else { - handle_two(lower1, exceeding2, policy); - handle_two(upper1, exceeding2, policy); + handle_two(lower1, exceeding2, visitor); + handle_two(upper1, exceeding2, visitor); } } if (recurse_ok(lower1, lower2, min_elements, level)) { next_level(lower_box, lower1, lower2, level, - min_elements, policy, box_policy); + min_elements, visitor, expand_policy1, overlaps_policy1, + expand_policy2, overlaps_policy2, box_policy); } else { - handle_two(lower1, lower2, policy); + handle_two(lower1, lower2, visitor); } if (recurse_ok(upper1, upper2, min_elements, level)) { next_level(upper_box, upper1, upper2, level, - min_elements, policy, box_policy); + min_elements, visitor, expand_policy1, overlaps_policy1, + expand_policy2, overlaps_policy2, box_policy); } else { - handle_two(upper1, upper2, policy); + handle_two(upper1, upper2, visitor); } } }; @@ -493,46 +537,86 @@ struct include_all_policy template < typename Box, - typename ExpandPolicy1, - typename OverlapsPolicy1, - typename ExpandPolicy2 = ExpandPolicy1, - typename OverlapsPolicy2 = OverlapsPolicy1, typename IncludePolicy1 = detail::partition::include_all_policy, - typename IncludePolicy2 = detail::partition::include_all_policy, - typename VisitBoxPolicy = detail::partition::visit_no_policy + typename IncludePolicy2 = detail::partition::include_all_policy > class partition { + static const std::size_t default_min_elements = 16; + template < - typename ExpandPolicy, typename IncludePolicy, typename ForwardRange, - typename IteratorVector + typename IteratorVector, + typename ExpandPolicy > static inline void expand_to_range(ForwardRange const& forward_range, - Box& total, IteratorVector& iterator_vector) + Box& total, + IteratorVector& iterator_vector, + ExpandPolicy const& expand_policy) { - for(typename boost::range_iterator<ForwardRange const>::type it - = boost::begin(forward_range); + for(typename boost::range_iterator<ForwardRange const>::type + it = boost::begin(forward_range); it != boost::end(forward_range); ++it) { if (IncludePolicy::apply(*it)) { - ExpandPolicy::apply(total, *it); + expand_policy.apply(total, *it); iterator_vector.push_back(it); } } } -public : - template <typename ForwardRange, typename VisitPolicy> +public: + template + < + typename ForwardRange, + typename VisitPolicy, + typename ExpandPolicy, + typename OverlapsPolicy + > static inline void apply(ForwardRange const& forward_range, - VisitPolicy& visitor, - std::size_t min_elements = 16, - VisitBoxPolicy box_visitor = detail::partition::visit_no_policy() - ) + VisitPolicy& visitor, + ExpandPolicy const& expand_policy, + OverlapsPolicy const& overlaps_policy) + { + apply(forward_range, visitor, expand_policy, overlaps_policy, + default_min_elements, detail::partition::visit_no_policy()); + } + + template + < + typename ForwardRange, + typename VisitPolicy, + typename ExpandPolicy, + typename OverlapsPolicy + > + static inline void apply(ForwardRange const& forward_range, + VisitPolicy& visitor, + ExpandPolicy const& expand_policy, + OverlapsPolicy const& overlaps_policy, + std::size_t min_elements) + { + apply(forward_range, visitor, expand_policy, overlaps_policy, + min_elements, detail::partition::visit_no_policy()); + } + + template + < + typename ForwardRange, + typename VisitPolicy, + typename ExpandPolicy, + typename OverlapsPolicy, + typename VisitBoxPolicy + > + static inline void apply(ForwardRange const& forward_range, + VisitPolicy& visitor, + ExpandPolicy const& expand_policy, + OverlapsPolicy const& overlaps_policy, + std::size_t min_elements, + VisitBoxPolicy box_visitor) { typedef typename boost::range_iterator < @@ -544,17 +628,14 @@ public : std::vector<iterator_type> iterator_vector; Box total; assign_inverse(total); - expand_to_range<ExpandPolicy1, IncludePolicy1>(forward_range, - total, iterator_vector); + expand_to_range<IncludePolicy1>(forward_range, total, + iterator_vector, expand_policy); detail::partition::partition_one_range < - 0, Box, - OverlapsPolicy1, - ExpandPolicy1, - VisitBoxPolicy + 0, Box >::apply(total, iterator_vector, 0, min_elements, - visitor, box_visitor); + visitor, expand_policy, overlaps_policy, box_visitor); } else { @@ -575,15 +656,88 @@ public : < typename ForwardRange1, typename ForwardRange2, - typename VisitPolicy + typename VisitPolicy, + typename ExpandPolicy1, + typename OverlapsPolicy1 + > + static inline void apply(ForwardRange1 const& forward_range1, + ForwardRange2 const& forward_range2, + VisitPolicy& visitor, + ExpandPolicy1 const& expand_policy1, + OverlapsPolicy1 const& overlaps_policy1) + { + apply(forward_range1, forward_range2, visitor, + expand_policy1, overlaps_policy1, expand_policy1, overlaps_policy1, + default_min_elements, detail::partition::visit_no_policy()); + } + + template + < + typename ForwardRange1, + typename ForwardRange2, + typename VisitPolicy, + typename ExpandPolicy1, + typename OverlapsPolicy1, + typename ExpandPolicy2, + typename OverlapsPolicy2 + > + static inline void apply(ForwardRange1 const& forward_range1, + ForwardRange2 const& forward_range2, + VisitPolicy& visitor, + ExpandPolicy1 const& expand_policy1, + OverlapsPolicy1 const& overlaps_policy1, + ExpandPolicy2 const& expand_policy2, + OverlapsPolicy2 const& overlaps_policy2) + { + apply(forward_range1, forward_range2, visitor, + expand_policy1, overlaps_policy1, expand_policy2, overlaps_policy2, + default_min_elements, detail::partition::visit_no_policy()); + } + + template + < + typename ForwardRange1, + typename ForwardRange2, + typename VisitPolicy, + typename ExpandPolicy1, + typename OverlapsPolicy1, + typename ExpandPolicy2, + typename OverlapsPolicy2 + > + static inline void apply(ForwardRange1 const& forward_range1, + ForwardRange2 const& forward_range2, + VisitPolicy& visitor, + ExpandPolicy1 const& expand_policy1, + OverlapsPolicy1 const& overlaps_policy1, + ExpandPolicy2 const& expand_policy2, + OverlapsPolicy2 const& overlaps_policy2, + std::size_t min_elements) + { + apply(forward_range1, forward_range2, visitor, + expand_policy1, overlaps_policy1, expand_policy2, overlaps_policy1, + min_elements, detail::partition::visit_no_policy()); + } + + template + < + typename ForwardRange1, + typename ForwardRange2, + typename VisitPolicy, + typename ExpandPolicy1, + typename OverlapsPolicy1, + typename ExpandPolicy2, + typename OverlapsPolicy2, + typename VisitBoxPolicy > static inline void apply(ForwardRange1 const& forward_range1, - ForwardRange2 const& forward_range2, - VisitPolicy& visitor, - std::size_t min_elements = 16, - VisitBoxPolicy box_visitor - = detail::partition::visit_no_policy() - ) + ForwardRange2 const& forward_range2, + VisitPolicy& visitor, + ExpandPolicy1 const& expand_policy1, + OverlapsPolicy1 const& overlaps_policy1, + ExpandPolicy2 const& expand_policy2, + OverlapsPolicy2 const& overlaps_policy2, + std::size_t min_elements, + VisitBoxPolicy box_visitor) { typedef typename boost::range_iterator < @@ -602,17 +756,18 @@ public : std::vector<iterator_type2> iterator_vector2; Box total; assign_inverse(total); - expand_to_range<ExpandPolicy1, IncludePolicy1>(forward_range1, - total, iterator_vector1); - expand_to_range<ExpandPolicy2, IncludePolicy2>(forward_range2, - total, iterator_vector2); + expand_to_range<IncludePolicy1>(forward_range1, total, + iterator_vector1, expand_policy1); + expand_to_range<IncludePolicy2>(forward_range2, total, + iterator_vector2, expand_policy2); detail::partition::partition_two_ranges < - 0, Box, OverlapsPolicy1, OverlapsPolicy2, - ExpandPolicy1, ExpandPolicy2, VisitBoxPolicy + 0, Box >::apply(total, iterator_vector1, iterator_vector2, - 0, min_elements, visitor, box_visitor); + 0, min_elements, visitor, expand_policy1, + overlaps_policy1, expand_policy2, overlaps_policy2, + box_visitor); } else { diff --git a/boost/geometry/algorithms/detail/relate/areal_areal.hpp b/boost/geometry/algorithms/detail/relate/areal_areal.hpp index a74954326b..800fbb2e96 100644 --- a/boost/geometry/algorithms/detail/relate/areal_areal.hpp +++ b/boost/geometry/algorithms/detail/relate/areal_areal.hpp @@ -2,8 +2,8 @@ // Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. -// This file was modified by Oracle on 2013, 2014, 2015. -// Modifications copyright (c) 2013-2015 Oracle and/or its affiliates. +// This file was modified by Oracle on 2013, 2014, 2015, 2017. +// Modifications copyright (c) 2013-2017 Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle @@ -40,12 +40,21 @@ namespace detail { namespace relate { // Use the rtree in this case! // may be used to set EI and EB for an Areal geometry for which no turns were generated -template <typename OtherAreal, typename Result, bool TransposeResult> +template +< + typename OtherAreal, + typename Result, + typename PointInArealStrategy, + bool TransposeResult +> class no_turns_aa_pred { public: - no_turns_aa_pred(OtherAreal const& other_areal, Result & res) + no_turns_aa_pred(OtherAreal const& other_areal, + Result & res, + PointInArealStrategy const& point_in_areal_strategy) : m_result(res) + , m_point_in_areal_strategy(point_in_areal_strategy) , m_other_areal(other_areal) , m_flags(0) { @@ -68,6 +77,8 @@ public: template <typename Areal> bool operator()(Areal const& areal) { + using detail::within::point_in_geometry; + // if those flags are set nothing will change if ( m_flags == 3 ) { @@ -87,7 +98,9 @@ public: // check if the areal is inside the other_areal // TODO: This is O(N) // Run in a loop O(NM) - optimize! - int const pig = detail::within::point_in_geometry(pt, m_other_areal); + int const pig = point_in_geometry(pt, + m_other_areal, + m_point_in_areal_strategy); //BOOST_GEOMETRY_ASSERT( pig != 0 ); // inside @@ -119,7 +132,9 @@ public: // TODO: O(N) // Optimize! - int const hpig = detail::within::point_in_geometry(range::front(range_ref), m_other_areal); + int const hpig = point_in_geometry(range::front(range_ref), + m_other_areal, + m_point_in_areal_strategy); // hole outside if ( hpig < 0 ) @@ -155,7 +170,9 @@ public: // TODO: O(N) // Optimize! - int const hpig = detail::within::point_in_geometry(range::front(range_ref), m_other_areal); + int const hpig = point_in_geometry(range::front(range_ref), + m_other_areal, + m_point_in_areal_strategy); // hole inside if ( hpig > 0 ) @@ -174,6 +191,7 @@ public: private: Result & m_result; + PointInArealStrategy const& m_point_in_areal_strategy; OtherAreal const& m_other_areal; int m_flags; }; @@ -191,8 +209,10 @@ struct areal_areal typedef typename geometry::point_type<Geometry1>::type point1_type; typedef typename geometry::point_type<Geometry2>::type point2_type; - template <typename Result> - static inline void apply(Geometry1 const& geometry1, Geometry2 const& geometry2, Result & result) + template <typename Result, typename IntersectionStrategy> + static inline void apply(Geometry1 const& geometry1, Geometry2 const& geometry2, + Result & result, + IntersectionStrategy const& intersection_strategy) { // TODO: If Areal geometry may have infinite size, change the following line: @@ -208,16 +228,31 @@ struct areal_areal interrupt_policy_areal_areal<Result> interrupt_policy(geometry1, geometry2, result); - turns::get_turns<Geometry1, Geometry2>::apply(turns, geometry1, geometry2, interrupt_policy); + turns::get_turns<Geometry1, Geometry2>::apply(turns, geometry1, geometry2, interrupt_policy, intersection_strategy); if ( BOOST_GEOMETRY_CONDITION(result.interrupt) ) return; - no_turns_aa_pred<Geometry2, Result, false> pred1(geometry2, result); + typedef typename IntersectionStrategy::template point_in_geometry_strategy + < + Geometry1, Geometry2 + >::type point_in_areal_strategy12_type; + point_in_areal_strategy12_type point_in_areal_strategy12 + = intersection_strategy.template get_point_in_geometry_strategy<Geometry1, Geometry2>(); + typedef typename IntersectionStrategy::template point_in_geometry_strategy + < + Geometry2, Geometry1 + >::type point_in_areal_strategy21_type; + point_in_areal_strategy21_type point_in_areal_strategy21 + = intersection_strategy.template get_point_in_geometry_strategy<Geometry2, Geometry1>(); + + no_turns_aa_pred<Geometry2, Result, point_in_areal_strategy12_type, false> + pred1(geometry2, result, point_in_areal_strategy12); for_each_disjoint_geometry_if<0, Geometry1>::apply(turns.begin(), turns.end(), geometry1, pred1); if ( BOOST_GEOMETRY_CONDITION(result.interrupt) ) return; - no_turns_aa_pred<Geometry1, Result, true> pred2(geometry1, result); + no_turns_aa_pred<Geometry1, Result, point_in_areal_strategy21_type, true> + pred2(geometry1, result, point_in_areal_strategy21); for_each_disjoint_geometry_if<1, Geometry2>::apply(turns.begin(), turns.end(), geometry2, pred2); if ( BOOST_GEOMETRY_CONDITION(result.interrupt) ) return; @@ -256,7 +291,8 @@ struct areal_areal { // analyse rings for which turns were not generated // or only i/i or u/u was generated - uncertain_rings_analyser<0, Result, Geometry1, Geometry2> rings_analyser(result, geometry1, geometry2); + uncertain_rings_analyser<0, Result, Geometry1, Geometry2, point_in_areal_strategy12_type> + rings_analyser(result, geometry1, geometry2, point_in_areal_strategy12); analyse_uncertain_rings<0>::apply(rings_analyser, turns.begin(), turns.end()); if ( BOOST_GEOMETRY_CONDITION(result.interrupt) ) @@ -295,7 +331,8 @@ struct areal_areal { // analyse rings for which turns were not generated // or only i/i or u/u was generated - uncertain_rings_analyser<1, Result, Geometry2, Geometry1> rings_analyser(result, geometry2, geometry1); + uncertain_rings_analyser<1, Result, Geometry2, Geometry1, point_in_areal_strategy21_type> + rings_analyser(result, geometry2, geometry1, point_in_areal_strategy21); analyse_uncertain_rings<1>::apply(rings_analyser, turns.begin(), turns.end()); //if ( result.interrupt ) @@ -565,7 +602,14 @@ struct areal_areal analyser.apply(res); } - template <std::size_t OpId, typename Result, typename Geometry, typename OtherGeometry> + template + < + std::size_t OpId, + typename Result, + typename Geometry, + typename OtherGeometry, + typename PointInArealStrategy + > class uncertain_rings_analyser { static const bool transpose_result = OpId != 0; @@ -574,10 +618,13 @@ struct areal_areal public: inline uncertain_rings_analyser(Result & result, Geometry const& geom, - OtherGeometry const& other_geom) - : geometry(geom), other_geometry(other_geom) + OtherGeometry const& other_geom, + PointInArealStrategy const& point_in_areal_strategy) + : geometry(geom) + , other_geometry(other_geom) , interrupt(result.interrupt) // just in case, could be false as well , m_result(result) + , m_point_in_areal_strategy(point_in_areal_strategy) , m_flags(0) { // check which relations must be analysed @@ -624,7 +671,10 @@ struct areal_areal // TODO: optimize! e.g. use spatial index // O(N) - running it in a loop gives O(NM) - int const pig = detail::within::point_in_geometry(range::front(range_ref), other_geometry); + using detail::within::point_in_geometry; + int const pig = point_in_geometry(range::front(range_ref), + other_geometry, + m_point_in_areal_strategy); //BOOST_GEOMETRY_ASSERT(pig != 0); if ( pig > 0 ) @@ -713,6 +763,7 @@ struct areal_areal private: Result & m_result; + PointInArealStrategy const& m_point_in_areal_strategy; int m_flags; }; diff --git a/boost/geometry/algorithms/detail/relate/implementation.hpp b/boost/geometry/algorithms/detail/relate/implementation.hpp index a6f1545ed1..3bd0f806c1 100644 --- a/boost/geometry/algorithms/detail/relate/implementation.hpp +++ b/boost/geometry/algorithms/detail/relate/implementation.hpp @@ -2,8 +2,8 @@ // Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. -// This file was modified by Oracle on 2013, 2014, 2015. -// Modifications copyright (c) 2013-2015 Oracle and/or its affiliates. +// This file was modified by Oracle on 2013, 2014, 2015, 2017. +// Modifications copyright (c) 2013-2017 Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle @@ -25,6 +25,9 @@ #include <boost/geometry/algorithms/detail/relate/linear_areal.hpp> #include <boost/geometry/algorithms/detail/relate/areal_areal.hpp> +#include <boost/geometry/strategies/intersection.hpp> +#include <boost/geometry/strategies/within.hpp> + namespace boost { namespace geometry { diff --git a/boost/geometry/algorithms/detail/relate/interface.hpp b/boost/geometry/algorithms/detail/relate/interface.hpp index 95d452931c..3575fe2bc4 100644 --- a/boost/geometry/algorithms/detail/relate/interface.hpp +++ b/boost/geometry/algorithms/detail/relate/interface.hpp @@ -2,8 +2,8 @@ // Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. -// This file was modified by Oracle on 2013, 2014, 2015. -// Modifications copyright (c) 2013-2015 Oracle and/or its affiliates. +// This file was modified by Oracle on 2013, 2014, 2015, 2017. +// Modifications copyright (c) 2013-2017 Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle @@ -29,6 +29,7 @@ #include <boost/geometry/algorithms/not_implemented.hpp> #include <boost/geometry/geometries/concepts/check.hpp> #include <boost/geometry/strategies/default_strategy.hpp> +#include <boost/geometry/strategies/relate.hpp> namespace boost { namespace geometry { @@ -186,18 +187,59 @@ struct result_handler_type<Geometry1, Geometry2, StaticSequence, true> > type; }; + }} // namespace detail::relate #endif // DOXYGEN_NO_DETAIL +namespace resolve_strategy { + +struct relate +{ + template <typename Geometry1, typename Geometry2, typename ResultHandler, typename Strategy> + static inline void apply(Geometry1 const& geometry1, + Geometry2 const& geometry2, + ResultHandler & handler, + Strategy const& strategy) + { + dispatch::relate + < + Geometry1, + Geometry2 + >::apply(geometry1, geometry2, handler, strategy); + } + + template <typename Geometry1, typename Geometry2, typename ResultHandler> + static inline void apply(Geometry1 const& geometry1, + Geometry2 const& geometry2, + ResultHandler & handler, + default_strategy) + { + typedef typename strategy::relate::services::default_strategy + < + Geometry1, + Geometry2 + >::type strategy_type; + + dispatch::relate + < + Geometry1, + Geometry2 + >::apply(geometry1, geometry2, handler, strategy_type()); + } +}; + +} // resolve_strategy + namespace resolve_variant { template <typename Geometry1, typename Geometry2> struct relate { - template <typename Mask> + template <typename Mask, typename Strategy> static inline bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2, - Mask const& mask) + Mask const& mask, + Strategy const& strategy) { concepts::check<Geometry1 const>(); concepts::check<Geometry2 const>(); @@ -210,11 +252,7 @@ struct relate Mask >::type handler(mask); - dispatch::relate - < - Geometry1, - Geometry2 - >::apply(geometry1, geometry2, handler); + resolve_strategy::relate::apply(geometry1, geometry2, handler, strategy); return handler.result(); } @@ -223,60 +261,64 @@ struct relate template <BOOST_VARIANT_ENUM_PARAMS(typename T), typename Geometry2> struct relate<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Geometry2> { - template <typename Mask> + template <typename Mask, typename Strategy> struct visitor : boost::static_visitor<bool> { Geometry2 const& m_geometry2; Mask const& m_mask; + Strategy const& m_strategy; - visitor(Geometry2 const& geometry2, Mask const& mask) - : m_geometry2(geometry2), m_mask(mask) {} + visitor(Geometry2 const& geometry2, Mask const& mask, Strategy const& strategy) + : m_geometry2(geometry2), m_mask(mask), m_strategy(strategy) {} template <typename Geometry1> bool operator()(Geometry1 const& geometry1) const { return relate<Geometry1, Geometry2> - ::apply(geometry1, m_geometry2, m_mask); + ::apply(geometry1, m_geometry2, m_mask, m_strategy); } }; - template <typename Mask> + template <typename Mask, typename Strategy> static inline bool apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry1, Geometry2 const& geometry2, - Mask const& mask) + Mask const& mask, + Strategy const& strategy) { - return boost::apply_visitor(visitor<Mask>(geometry2, mask), geometry1); + return boost::apply_visitor(visitor<Mask, Strategy>(geometry2, mask, strategy), geometry1); } }; template <typename Geometry1, BOOST_VARIANT_ENUM_PARAMS(typename T)> struct relate<Geometry1, boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> > { - template <typename Mask> + template <typename Mask, typename Strategy> struct visitor : boost::static_visitor<bool> { Geometry1 const& m_geometry1; Mask const& m_mask; + Strategy const& m_strategy; - visitor(Geometry1 const& geometry1, Mask const& mask) - : m_geometry1(geometry1), m_mask(mask) {} + visitor(Geometry1 const& geometry1, Mask const& mask, Strategy const& strategy) + : m_geometry1(geometry1), m_mask(mask), m_strategy(strategy) {} template <typename Geometry2> bool operator()(Geometry2 const& geometry2) const { return relate<Geometry1, Geometry2> - ::apply(m_geometry1, geometry2, m_mask); + ::apply(m_geometry1, geometry2, m_mask, m_strategy); } }; - template <typename Mask> + template <typename Mask, typename Strategy> static inline bool apply(Geometry1 const& geometry1, boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry2, - Mask const& mask) + Mask const& mask, + Strategy const& strategy) { - return boost::apply_visitor(visitor<Mask>(geometry1, mask), geometry2); + return boost::apply_visitor(visitor<Mask, Strategy>(geometry1, mask, strategy), geometry2); } }; @@ -289,30 +331,32 @@ struct relate< boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)> > { - template <typename Mask> + template <typename Mask, typename Strategy> struct visitor : boost::static_visitor<bool> { Mask const& m_mask; + Strategy const& m_strategy; - visitor(Mask const& mask) - : m_mask(mask) {} + visitor(Mask const& mask, Strategy const& strategy) + : m_mask(mask), m_strategy(strategy) {} template <typename Geometry1, typename Geometry2> bool operator()(Geometry1 const& geometry1, Geometry2 const& geometry2) const { return relate<Geometry1, Geometry2> - ::apply(geometry1, geometry2, m_mask); + ::apply(geometry1, geometry2, m_mask, m_strategy); } }; - template <typename Mask> + template <typename Mask, typename Strategy> static inline bool apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)> const& geometry1, boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)> const& geometry2, - Mask const& mask) + Mask const& mask, + Strategy const& strategy) { - return boost::apply_visitor(visitor<Mask>(mask), geometry1, geometry2); + return boost::apply_visitor(visitor<Mask, Strategy>(mask, strategy), geometry1, geometry2); } }; @@ -324,6 +368,35 @@ struct relate< \tparam Geometry1 \tparam_geometry \tparam Geometry2 \tparam_geometry \tparam Mask An intersection model Mask type. +\tparam Strategy \tparam_strategy{Relate} +\param geometry1 \param_geometry +\param geometry2 \param_geometry +\param mask An intersection model mask object. +\param strategy \param_strategy{relate} +\return true if the relation is compatible with the mask, false otherwise. + +\qbk{distinguish,with strategy} +\qbk{[include reference/algorithms/relate.qbk]} + */ +template <typename Geometry1, typename Geometry2, typename Mask, typename Strategy> +inline bool relate(Geometry1 const& geometry1, + Geometry2 const& geometry2, + Mask const& mask, + Strategy const& strategy) +{ + return resolve_variant::relate + < + Geometry1, + Geometry2 + >::apply(geometry1, geometry2, mask, strategy); +} + +/*! +\brief Checks relation between a pair of geometries defined by a mask. +\ingroup relate +\tparam Geometry1 \tparam_geometry +\tparam Geometry2 \tparam_geometry +\tparam Mask An intersection model Mask type. \param geometry1 \param_geometry \param geometry2 \param_geometry \param mask An intersection model mask object. @@ -340,7 +413,7 @@ inline bool relate(Geometry1 const& geometry1, < Geometry1, Geometry2 - >::apply(geometry1, geometry2, mask); + >::apply(geometry1, geometry2, mask, default_strategy()); } }} // namespace boost::geometry diff --git a/boost/geometry/algorithms/detail/relate/linear_areal.hpp b/boost/geometry/algorithms/detail/relate/linear_areal.hpp index 58ba7bd1af..f1b4fdf81a 100644 --- a/boost/geometry/algorithms/detail/relate/linear_areal.hpp +++ b/boost/geometry/algorithms/detail/relate/linear_areal.hpp @@ -2,8 +2,8 @@ // Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. -// This file was modified by Oracle on 2013, 2014, 2015. -// Modifications copyright (c) 2013-2015 Oracle and/or its affiliates. +// This file was modified by Oracle on 2013, 2014, 2015, 2017. +// Modifications copyright (c) 2013-2017 Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle @@ -46,15 +46,24 @@ namespace detail { namespace relate { // Use the rtree in this case! // may be used to set IE and BE for a Linear geometry for which no turns were generated -template <typename Geometry2, typename Result, typename BoundaryChecker, bool TransposeResult> +template +< + typename Geometry2, + typename Result, + typename PointInArealStrategy, + typename BoundaryChecker, + bool TransposeResult +> class no_turns_la_linestring_pred { public: no_turns_la_linestring_pred(Geometry2 const& geometry2, Result & res, + PointInArealStrategy const& point_in_areal_strategy, BoundaryChecker const& boundary_checker) : m_geometry2(geometry2) , m_result(res) + , m_point_in_areal_strategy(point_in_areal_strategy) , m_boundary_checker(boundary_checker) , m_interrupt_flags(0) { @@ -98,7 +107,9 @@ public: return false; } - int const pig = detail::within::point_in_geometry(range::front(linestring), m_geometry2); + int const pig = detail::within::point_in_geometry(range::front(linestring), + m_geometry2, + m_point_in_areal_strategy); //BOOST_GEOMETRY_ASSERT_MSG(pig != 0, "There should be no IPs"); if ( pig > 0 ) @@ -138,6 +149,7 @@ public: private: Geometry2 const& m_geometry2; Result & m_result; + PointInArealStrategy const& m_point_in_areal_strategy; BoundaryChecker const& m_boundary_checker; unsigned m_interrupt_flags; }; @@ -225,8 +237,10 @@ struct linear_areal > {}; - template <typename Result> - static inline void apply(Geometry1 const& geometry1, Geometry2 const& geometry2, Result & result) + template <typename Result, typename IntersectionStrategy> + static inline void apply(Geometry1 const& geometry1, Geometry2 const& geometry2, + Result & result, + IntersectionStrategy const& intersection_strategy) { // TODO: If Areal geometry may have infinite size, change the following line: @@ -242,7 +256,7 @@ struct linear_areal interrupt_policy_linear_areal<Geometry2, Result> interrupt_policy(geometry2, result); - turns::get_turns<Geometry1, Geometry2>::apply(turns, geometry1, geometry2, interrupt_policy); + turns::get_turns<Geometry1, Geometry2>::apply(turns, geometry1, geometry2, interrupt_policy, intersection_strategy); if ( BOOST_GEOMETRY_CONDITION( result.interrupt ) ) return; @@ -251,9 +265,13 @@ struct linear_areal < Geometry2, Result, + typename IntersectionStrategy::template point_in_geometry_strategy<Geometry1, Geometry2>::type, boundary_checker<Geometry1>, TransposeResult - > pred1(geometry2, result, boundary_checker1); + > pred1(geometry2, + result, + intersection_strategy.template get_point_in_geometry_strategy<Geometry1, Geometry2>(), + boundary_checker1); for_each_disjoint_geometry_if<0, Geometry1>::apply(turns.begin(), turns.end(), geometry1, pred1); if ( BOOST_GEOMETRY_CONDITION( result.interrupt ) ) return; @@ -279,7 +297,8 @@ struct linear_areal analyse_each_turn(result, analyser, turns.begin(), turns.end(), geometry1, geometry2, - boundary_checker1); + boundary_checker1, + intersection_strategy.get_side_strategy()); if ( BOOST_GEOMETRY_CONDITION( result.interrupt ) ) return; @@ -615,11 +634,13 @@ struct linear_areal typename TurnIt, typename Geometry, typename OtherGeometry, - typename BoundaryChecker> + typename BoundaryChecker, + typename SideStrategy> void apply(Result & res, TurnIt it, Geometry const& geometry, OtherGeometry const& other_geometry, - BoundaryChecker const& boundary_checker) + BoundaryChecker const& boundary_checker, + SideStrategy const& side_strategy) { overlay::operation_type op = it->operations[op_id].operation; @@ -856,7 +877,8 @@ struct linear_areal bool const from_inside = first_point && calculate_from_inside(geometry, other_geometry, - *it); + *it, + side_strategy); if ( from_inside ) update<interior, interior, '1', TransposeResult>(res); @@ -956,7 +978,8 @@ struct linear_areal bool const first_from_inside = first_point && calculate_from_inside(geometry, other_geometry, - *it); + *it, + side_strategy); if ( first_from_inside ) { update<interior, interior, '1', TransposeResult>(res); @@ -1144,10 +1167,11 @@ struct linear_areal // check if the passed turn's segment of Linear geometry arrived // from the inside or the outside of the Areal geometry - template <typename Turn> + template <typename Turn, typename SideStrategy> static inline bool calculate_from_inside(Geometry1 const& geometry1, Geometry2 const& geometry2, - Turn const& turn) + Turn const& turn, + SideStrategy const& side_strategy) { typedef typename cs_tag<typename Turn::point_type>::type cs_tag; @@ -1194,16 +1218,18 @@ struct linear_areal boost::end(range2)); // Will this sequence of points be always correct? - overlay::side_calculator<cs_tag, point1_type, point2_type> side_calc(qi_conv, new_pj, pi, qi, qj, *qk_it); + overlay::side_calculator<cs_tag, point1_type, point2_type, SideStrategy> + side_calc(qi_conv, new_pj, pi, qi, qj, *qk_it, side_strategy); return calculate_from_inside_sides(side_calc); } else { - point1_type new_qj; + point2_type new_qj; geometry::convert(turn.point, new_qj); - overlay::side_calculator<cs_tag, point1_type, point2_type> side_calc(qi_conv, new_pj, pi, qi, new_qj, qj); + overlay::side_calculator<cs_tag, point1_type, point2_type, SideStrategy> + side_calc(qi_conv, new_pj, pi, qi, new_qj, qj, side_strategy); return calculate_from_inside_sides(side_calc); } @@ -1270,13 +1296,15 @@ struct linear_areal typename Analyser, typename Geometry, typename OtherGeometry, - typename BoundaryChecker> + typename BoundaryChecker, + typename SideStrategy> static inline void analyse_each_turn(Result & res, Analyser & analyser, TurnIt first, TurnIt last, Geometry const& geometry, OtherGeometry const& other_geometry, - BoundaryChecker const& boundary_checker) + BoundaryChecker const& boundary_checker, + SideStrategy const& side_strategy) { if ( first == last ) return; @@ -1285,7 +1313,8 @@ struct linear_areal { analyser.apply(res, it, geometry, other_geometry, - boundary_checker); + boundary_checker, + side_strategy); if ( BOOST_GEOMETRY_CONDITION( res.interrupt ) ) return; @@ -1420,10 +1449,12 @@ struct areal_linear static const bool interruption_enabled = linear_areal_type::interruption_enabled; - template <typename Result> - static inline void apply(Geometry1 const& geometry1, Geometry2 const& geometry2, Result & result) + template <typename Result, typename IntersectionStrategy> + static inline void apply(Geometry1 const& geometry1, Geometry2 const& geometry2, + Result & result, + IntersectionStrategy const& intersection_strategy) { - linear_areal_type::apply(geometry2, geometry1, result); + linear_areal_type::apply(geometry2, geometry1, result, intersection_strategy); } }; diff --git a/boost/geometry/algorithms/detail/relate/linear_linear.hpp b/boost/geometry/algorithms/detail/relate/linear_linear.hpp index 7a3f373e03..520f2bd775 100644 --- a/boost/geometry/algorithms/detail/relate/linear_linear.hpp +++ b/boost/geometry/algorithms/detail/relate/linear_linear.hpp @@ -2,15 +2,15 @@ // Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. -// This file was modified by Oracle on 2013, 2014, 2015. -// Modifications copyright (c) 2013-2015 Oracle and/or its affiliates. +// This file was modified by Oracle on 2013, 2014, 2015, 2017. +// Modifications copyright (c) 2013-2017 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) -// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle - #ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_LINEAR_LINEAR_HPP #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_LINEAR_LINEAR_HPP @@ -119,8 +119,10 @@ struct linear_linear typedef typename geometry::point_type<Geometry1>::type point1_type; typedef typename geometry::point_type<Geometry2>::type point2_type; - template <typename Result> - static inline void apply(Geometry1 const& geometry1, Geometry2 const& geometry2, Result & result) + template <typename Result, typename IntersectionStrategy> + static inline void apply(Geometry1 const& geometry1, Geometry2 const& geometry2, + Result & result, + IntersectionStrategy const& intersection_strategy) { // The result should be FFFFFFFFF relate::set<exterior, exterior, result_dimension<Geometry1>::value>(result);// FFFFFFFFd, d in [1,9] or T @@ -138,7 +140,7 @@ struct linear_linear Geometry1, Geometry2, detail::get_turns::get_turn_info_type<Geometry1, Geometry2, turns::assign_policy<true> > - >::apply(turns, geometry1, geometry2, interrupt_policy); + >::apply(turns, geometry1, geometry2, interrupt_policy, intersection_strategy); if ( BOOST_GEOMETRY_CONDITION( result.interrupt ) ) return; diff --git a/boost/geometry/algorithms/detail/relate/point_geometry.hpp b/boost/geometry/algorithms/detail/relate/point_geometry.hpp index be08016a16..a0c6c0d49b 100644 --- a/boost/geometry/algorithms/detail/relate/point_geometry.hpp +++ b/boost/geometry/algorithms/detail/relate/point_geometry.hpp @@ -2,8 +2,8 @@ // Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. -// This file was modified by Oracle on 2013, 2014, 2015. -// Modifications copyright (c) 2013-2015 Oracle and/or its affiliates. +// This file was modified by Oracle on 2013, 2014, 2015, 2017. +// Modifications copyright (c) 2013-2017 Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle @@ -37,10 +37,10 @@ struct point_geometry static const bool interruption_enabled = true; - template <typename Result> - static inline void apply(Point const& point, Geometry const& geometry, Result & result) + template <typename Result, typename Strategy> + static inline void apply(Point const& point, Geometry const& geometry, Result & result, Strategy const& strategy) { - int pig = detail::within::point_in_geometry(point, geometry); + int pig = detail::within::point_in_geometry(point, geometry, strategy); if ( pig > 0 ) // within { @@ -95,10 +95,10 @@ struct geometry_point static const bool interruption_enabled = true; - template <typename Result> - static inline void apply(Geometry const& geometry, Point const& point, Result & result) + template <typename Result, typename Strategy> + static inline void apply(Geometry const& geometry, Point const& point, Result & result, Strategy const& strategy) { - point_geometry<Point, Geometry, true>::apply(point, geometry, result); + point_geometry<Point, Geometry, true>::apply(point, geometry, result, strategy); } }; diff --git a/boost/geometry/algorithms/detail/relate/point_point.hpp b/boost/geometry/algorithms/detail/relate/point_point.hpp index e55be08225..b41d346f0b 100644 --- a/boost/geometry/algorithms/detail/relate/point_point.hpp +++ b/boost/geometry/algorithms/detail/relate/point_point.hpp @@ -2,15 +2,15 @@ // Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. -// This file was modified by Oracle on 2013, 2014. -// Modifications copyright (c) 2013, 2014, Oracle and/or its affiliates. +// This file was modified by Oracle on 2013, 2014, 2017. +// Modifications copyright (c) 2013-2017, 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) -// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle - #ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_POINT_POINT_HPP #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_POINT_POINT_HPP @@ -35,8 +35,10 @@ struct point_point { static const bool interruption_enabled = false; - template <typename Result> - static inline void apply(Point1 const& point1, Point2 const& point2, Result & result) + template <typename Result, typename Strategy> + static inline void apply(Point1 const& point1, Point2 const& point2, + Result & result, + Strategy const& /*strategy*/) { bool equal = detail::equals::equals_point_point(point1, point2); if ( equal ) @@ -86,8 +88,10 @@ struct point_multipoint { static const bool interruption_enabled = false; - template <typename Result> - static inline void apply(Point const& point, MultiPoint const& multi_point, Result & result) + template <typename Result, typename Strategy> + static inline void apply(Point const& point, MultiPoint const& multi_point, + Result & result, + Strategy const& /*strategy*/) { if ( boost::empty(multi_point) ) { @@ -122,10 +126,12 @@ struct multipoint_point { static const bool interruption_enabled = false; - template <typename Result> - static inline void apply(MultiPoint const& multi_point, Point const& point, Result & result) + template <typename Result, typename Strategy> + static inline void apply(MultiPoint const& multi_point, Point const& point, + Result & result, + Strategy const& strategy) { - point_multipoint<Point, MultiPoint, true>::apply(point, multi_point, result); + point_multipoint<Point, MultiPoint, true>::apply(point, multi_point, result, strategy); } }; @@ -134,8 +140,10 @@ struct multipoint_multipoint { static const bool interruption_enabled = true; - template <typename Result> - static inline void apply(MultiPoint1 const& multi_point1, MultiPoint2 const& multi_point2, Result & result) + template <typename Result, typename Strategy> + static inline void apply(MultiPoint1 const& multi_point1, MultiPoint2 const& multi_point2, + Result & result, + Strategy const& /*strategy*/) { { // TODO: throw on empty input? diff --git a/boost/geometry/algorithms/detail/relate/relate_impl.hpp b/boost/geometry/algorithms/detail/relate/relate_impl.hpp index e8e422993d..2ec2361c03 100644 --- a/boost/geometry/algorithms/detail/relate/relate_impl.hpp +++ b/boost/geometry/algorithms/detail/relate/relate_impl.hpp @@ -57,7 +57,8 @@ struct relate_impl implemented_tag >::type { - static inline bool apply(Geometry1 const& g1, Geometry2 const& g2) + template <typename Strategy> + static inline bool apply(Geometry1 const& g1, Geometry2 const& g2, Strategy const& strategy) { typename detail::relate::result_handler_type < @@ -66,7 +67,7 @@ struct relate_impl typename StaticMaskTrait<Geometry1, Geometry2>::type >::type handler; - dispatch::relate<Geometry1, Geometry2>::apply(g1, g2, handler); + dispatch::relate<Geometry1, Geometry2>::apply(g1, g2, handler, strategy); return handler.result(); } diff --git a/boost/geometry/algorithms/detail/relate/result.hpp b/boost/geometry/algorithms/detail/relate/result.hpp index a92badf65b..07287dc625 100644 --- a/boost/geometry/algorithms/detail/relate/result.hpp +++ b/boost/geometry/algorithms/detail/relate/result.hpp @@ -1,6 +1,7 @@ // Boost.Geometry (aka GGL, Generic Geometry Library) // Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2017 Adam Wulkiewicz, Lodz, Poland. // This file was modified by Oracle on 2013-2016. // Modifications copyright (c) 2013-2016 Oracle and/or its affiliates. @@ -24,6 +25,7 @@ #include <boost/mpl/is_sequence.hpp> #include <boost/mpl/next.hpp> #include <boost/static_assert.hpp> +#include <boost/throw_exception.hpp> #include <boost/tuple/tuple.hpp> #include <boost/type_traits/integral_constant.hpp> @@ -266,7 +268,7 @@ private: || ( c >= '0' && c <= '9' ); if ( !is_valid ) { - throw geometry::invalid_input_exception(); + BOOST_THROW_EXCEPTION(geometry::invalid_input_exception()); } } diff --git a/boost/geometry/algorithms/detail/relate/turns.hpp b/boost/geometry/algorithms/detail/relate/turns.hpp index 09d74dec3a..6fa05eaf21 100644 --- a/boost/geometry/algorithms/detail/relate/turns.hpp +++ b/boost/geometry/algorithms/detail/relate/turns.hpp @@ -2,8 +2,8 @@ // Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands. -// This file was modified by Oracle on 2013, 2014, 2015. -// Modifications copyright (c) 2013-2015 Oracle and/or its affiliates. +// This file was modified by Oracle on 2013, 2014, 2015, 2017. +// Modifications copyright (c) 2013-2017 Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle @@ -75,28 +75,35 @@ struct get_turns { detail::get_turns::no_interrupt_policy interrupt_policy; - apply(turns, geometry1, geometry2, interrupt_policy); + typename strategy::intersection::services::default_strategy + < + typename cs_tag<Geometry1>::type + >::type intersection_strategy; + + apply(turns, geometry1, geometry2, interrupt_policy, intersection_strategy); } - template <typename Turns, typename InterruptPolicy> + template <typename Turns, typename InterruptPolicy, typename IntersectionStrategy> static inline void apply(Turns & turns, Geometry1 const& geometry1, Geometry2 const& geometry2, - InterruptPolicy & interrupt_policy) + InterruptPolicy & interrupt_policy, + IntersectionStrategy const& intersection_strategy) { RobustPolicy robust_policy = geometry::get_rescale_policy < RobustPolicy >(geometry1, geometry2); - apply(turns, geometry1, geometry2, interrupt_policy, robust_policy); + apply(turns, geometry1, geometry2, interrupt_policy, intersection_strategy, robust_policy); } - template <typename Turns, typename InterruptPolicy> + template <typename Turns, typename InterruptPolicy, typename IntersectionStrategy> static inline void apply(Turns & turns, Geometry1 const& geometry1, Geometry2 const& geometry2, InterruptPolicy & interrupt_policy, + IntersectionStrategy const& intersection_strategy, RobustPolicy const& robust_policy) { static const bool reverse1 = detail::overlay::do_reverse @@ -119,7 +126,8 @@ struct get_turns reverse2, GetTurnPolicy >::apply(0, geometry1, 1, geometry2, - robust_policy, turns, interrupt_policy); + intersection_strategy, robust_policy, + turns, interrupt_policy); } }; diff --git a/boost/geometry/algorithms/detail/relation/interface.hpp b/boost/geometry/algorithms/detail/relation/interface.hpp index e9a9474551..83d27ed72f 100644 --- a/boost/geometry/algorithms/detail/relation/interface.hpp +++ b/boost/geometry/algorithms/detail/relation/interface.hpp @@ -2,8 +2,8 @@ // Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands. -// This file was modified by Oracle on 2013, 2014, 2015. -// Modifications copyright (c) 2013-2015 Oracle and/or its affiliates. +// This file was modified by Oracle on 2013, 2014, 2015, 2017. +// Modifications copyright (c) 2013-2017 Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle @@ -35,16 +35,16 @@ struct result_handler_type<Geometry1, Geometry2, geometry::de9im::matrix, false> }} // namespace detail::relate #endif // DOXYGEN_NO_DETAIL - namespace resolve_variant { template <typename Geometry1, typename Geometry2> struct relation { - template <typename Matrix> + template <typename Matrix, typename Strategy> static inline Matrix apply(Geometry1 const& geometry1, - Geometry2 const& geometry2) + Geometry2 const& geometry2, + Strategy const& strategy) { concepts::check<Geometry1 const>(); concepts::check<Geometry2 const>(); @@ -57,11 +57,7 @@ struct relation Matrix >::type handler; - dispatch::relate - < - Geometry1, - Geometry2 - >::apply(geometry1, geometry2, handler); + resolve_strategy::relate::apply(geometry1, geometry2, handler, strategy); return handler.result(); } @@ -70,56 +66,60 @@ struct relation template <BOOST_VARIANT_ENUM_PARAMS(typename T), typename Geometry2> struct relation<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Geometry2> { - template <typename Matrix> + template <typename Matrix, typename Strategy> struct visitor : boost::static_visitor<Matrix> { Geometry2 const& m_geometry2; + Strategy const& m_strategy; - visitor(Geometry2 const& geometry2) - : m_geometry2(geometry2) {} + visitor(Geometry2 const& geometry2, Strategy const& strategy) + : m_geometry2(geometry2), m_strategy(strategy) {} template <typename Geometry1> Matrix operator()(Geometry1 const& geometry1) const { return relation<Geometry1, Geometry2> - ::template apply<Matrix>(geometry1, m_geometry2); + ::template apply<Matrix>(geometry1, m_geometry2, m_strategy); } }; - template <typename Matrix> + template <typename Matrix, typename Strategy> static inline Matrix apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry1, - Geometry2 const& geometry2) + Geometry2 const& geometry2, + Strategy const& strategy) { - return boost::apply_visitor(visitor<Matrix>(geometry2), geometry1); + return boost::apply_visitor(visitor<Matrix, Strategy>(geometry2, strategy), geometry1); } }; template <typename Geometry1, BOOST_VARIANT_ENUM_PARAMS(typename T)> struct relation<Geometry1, boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> > { - template <typename Matrix> + template <typename Matrix, typename Strategy> struct visitor : boost::static_visitor<Matrix> { Geometry1 const& m_geometry1; + Strategy const& m_strategy; - visitor(Geometry1 const& geometry1) - : m_geometry1(geometry1) {} + visitor(Geometry1 const& geometry1, Strategy const& strategy) + : m_geometry1(geometry1), m_strategy(strategy) {} template <typename Geometry2> Matrix operator()(Geometry2 const& geometry2) const { return relation<Geometry1, Geometry2> - ::template apply<Matrix>(m_geometry1, geometry2); + ::template apply<Matrix>(m_geometry1, geometry2, m_strategy); } }; - template <typename Matrix> + template <typename Matrix, typename Strategy> static inline Matrix apply(Geometry1 const& geometry1, - boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry2) + boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry2, + Strategy const& strategy) { - return boost::apply_visitor(visitor<Matrix>(geometry1), geometry2); + return boost::apply_visitor(visitor<Matrix, Strategy>(geometry1, strategy), geometry2); } }; @@ -134,24 +134,30 @@ struct relation boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)> > { - template <typename Matrix> + template <typename Matrix, typename Strategy> struct visitor : boost::static_visitor<Matrix> { + Strategy const& m_strategy; + + visitor(Strategy const& strategy) + : m_strategy(strategy) {} + template <typename Geometry1, typename Geometry2> Matrix operator()(Geometry1 const& geometry1, Geometry2 const& geometry2) const { return relation<Geometry1, Geometry2> - ::template apply<Matrix>(geometry1, geometry2); + ::template apply<Matrix>(geometry1, geometry2, m_strategy); } }; - template <typename Matrix> + template <typename Matrix, typename Strategy> static inline Matrix apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)> const& geometry1, - boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)> const& geometry2) + boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)> const& geometry2, + Strategy const& strategy) { - return boost::apply_visitor(visitor<Matrix>(), geometry1, geometry2); + return boost::apply_visitor(visitor<Matrix, Strategy>(strategy), geometry1, geometry2); } }; @@ -163,6 +169,33 @@ struct relation \ingroup relation \tparam Geometry1 \tparam_geometry \tparam Geometry2 \tparam_geometry +\tparam Strategy \tparam_strategy{Relation} +\param geometry1 \param_geometry +\param geometry2 \param_geometry +\param strategy \param_strategy{relation} +\return The DE-9IM matrix expressing the relation between geometries. + +\qbk{distinguish,with strategy} +\qbk{[include reference/algorithms/relation.qbk]} + */ +template <typename Geometry1, typename Geometry2, typename Strategy> +inline de9im::matrix relation(Geometry1 const& geometry1, + Geometry2 const& geometry2, + Strategy const& strategy) +{ + return resolve_variant::relation + < + Geometry1, + Geometry2 + >::template apply<de9im::matrix>(geometry1, geometry2, strategy); +} + + +/*! +\brief Calculates the relation between a pair of geometries as defined in DE-9IM. +\ingroup relation +\tparam Geometry1 \tparam_geometry +\tparam Geometry2 \tparam_geometry \param geometry1 \param_geometry \param geometry2 \param_geometry \return The DE-9IM matrix expressing the relation between geometries. @@ -177,7 +210,7 @@ inline de9im::matrix relation(Geometry1 const& geometry1, < Geometry1, Geometry2 - >::template apply<de9im::matrix>(geometry1, geometry2); + >::template apply<de9im::matrix>(geometry1, geometry2, default_strategy()); } diff --git a/boost/geometry/algorithms/detail/throw_on_empty_input.hpp b/boost/geometry/algorithms/detail/throw_on_empty_input.hpp index 2f82e1a8bd..3d45a46d16 100644 --- a/boost/geometry/algorithms/detail/throw_on_empty_input.hpp +++ b/boost/geometry/algorithms/detail/throw_on_empty_input.hpp @@ -3,6 +3,7 @@ // Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands. // Copyright (c) 2008-2015 Bruno Lalande, Paris, France. // Copyright (c) 2009-2015 Mateusz Loskot, London, UK. +// Copyright (c) 2017 Adam Wulkiewicz, Lodz, Poland. // This file was modified by Oracle on 2015. // Modifications copyright (c) 2015, Oracle and/or its affiliates. @@ -16,9 +17,13 @@ #ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_THROW_ON_EMPTY_INPUT_HPP #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_THROW_ON_EMPTY_INPUT_HPP + #include <boost/geometry/core/exception.hpp> #include <boost/geometry/algorithms/is_empty.hpp> +#include <boost/throw_exception.hpp> + + // BSG 2012-02-06: we use this currently only for distance. // For other scalar results area,length,perimeter it is commented on purpose. // Reason is that for distance there is no other choice. distance of two @@ -46,7 +51,7 @@ inline void throw_on_empty_input(Geometry const& geometry) #if ! defined(BOOST_GEOMETRY_EMPTY_INPUT_NO_THROW) if (geometry::is_empty(geometry)) { - throw empty_input_exception(); + BOOST_THROW_EXCEPTION(empty_input_exception()); } #else boost::ignore_unused(geometry); diff --git a/boost/geometry/algorithms/detail/within/point_in_geometry.hpp b/boost/geometry/algorithms/detail/within/point_in_geometry.hpp index a73364c333..a24f4d21e2 100644 --- a/boost/geometry/algorithms/detail/within/point_in_geometry.hpp +++ b/boost/geometry/algorithms/detail/within/point_in_geometry.hpp @@ -5,8 +5,10 @@ // Copyright (c) 2009-2012 Mateusz Loskot, London, UK. // Copyright (c) 2014 Adam Wulkiewicz, Lodz, Poland. -// This file was modified by Oracle on 2013, 2014, 2015. -// Modifications copyright (c) 2013-2015, Oracle and/or its affiliates. +// This file was modified by Oracle on 2013, 2014, 2015, 2017. +// Modifications copyright (c) 2013-2017, Oracle and/or its affiliates. + +// 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. @@ -15,8 +17,6 @@ // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) -// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle - #ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_WITHIN_POINT_IN_GEOMETRY_HPP #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_WITHIN_POINT_IN_GEOMETRY_HPP @@ -35,8 +35,7 @@ #include <boost/geometry/geometries/concepts/check.hpp> #include <boost/geometry/strategies/concepts/within_concept.hpp> #include <boost/geometry/strategies/default_strategy.hpp> -#include <boost/geometry/strategies/within.hpp> -#include <boost/geometry/strategies/covered_by.hpp> +#include <boost/geometry/strategies/relate.hpp> #include <boost/geometry/util/range.hpp> #include <boost/geometry/views/detail/normalized_view.hpp> @@ -46,6 +45,7 @@ namespace boost { namespace geometry { #ifndef DOXYGEN_NO_DETAIL namespace detail { namespace within { + // TODO: is this needed? inline int check_result_type(int result) { @@ -83,50 +83,11 @@ int point_in_range(Point const& point, Range const& range, Strategy const& strat template <typename Geometry, typename Point, typename Range> inline int point_in_range(Point const& point, Range const& range) { - typedef typename point_type<Point>::type point_type1; - typedef typename point_type<Geometry>::type point_type2; - - typedef typename strategy::within::services::default_strategy + typedef typename strategy::point_in_geometry::services::default_strategy < - typename tag<Point>::type, - typename tag<Geometry>::type, - typename tag<Point>::type, - typename tag_cast<typename tag<Geometry>::type, areal_tag>::type, - typename tag_cast - < - typename cs_tag<point_type1>::type, spherical_tag - >::type, - typename tag_cast - < - typename cs_tag<point_type2>::type, spherical_tag - >::type, - Point, - Geometry + Point, Geometry >::type strategy_type; - typedef typename strategy::covered_by::services::default_strategy - < - typename tag<Point>::type, - typename tag<Geometry>::type, - typename tag<Point>::type, - typename tag_cast<typename tag<Geometry>::type, areal_tag>::type, - typename tag_cast - < - typename cs_tag<point_type1>::type, spherical_tag - >::type, - typename tag_cast - < - typename cs_tag<point_type2>::type, spherical_tag - >::type, - Point, - Geometry - >::type strategy_type2; - - static const bool same_strategies = boost::is_same<strategy_type, strategy_type2>::value; - BOOST_MPL_ASSERT_MSG((same_strategies), - DEFAULT_WITHIN_AND_COVERED_BY_STRATEGIES_NOT_COMPATIBLE, - (strategy_type, strategy_type2)); - return point_in_range(point, range, strategy_type()); } @@ -414,50 +375,11 @@ inline int point_in_geometry(Point const& point, Geometry const& geometry, Strat template <typename Point, typename Geometry> inline int point_in_geometry(Point const& point, Geometry const& geometry) { - typedef typename point_type<Point>::type point_type1; - typedef typename point_type<Geometry>::type point_type2; - - typedef typename strategy::within::services::default_strategy + typedef typename strategy::point_in_geometry::services::default_strategy < - typename tag<Point>::type, - typename tag<Geometry>::type, - typename tag<Point>::type, - typename tag_cast<typename tag<Geometry>::type, areal_tag>::type, - typename tag_cast - < - typename cs_tag<point_type1>::type, spherical_tag - >::type, - typename tag_cast - < - typename cs_tag<point_type2>::type, spherical_tag - >::type, - Point, - Geometry + Point, Geometry >::type strategy_type; - typedef typename strategy::covered_by::services::default_strategy - < - typename tag<Point>::type, - typename tag<Geometry>::type, - typename tag<Point>::type, - typename tag_cast<typename tag<Geometry>::type, areal_tag>::type, - typename tag_cast - < - typename cs_tag<point_type1>::type, spherical_tag - >::type, - typename tag_cast - < - typename cs_tag<point_type2>::type, spherical_tag - >::type, - Point, - Geometry - >::type strategy_type2; - - static const bool same_strategies = boost::is_same<strategy_type, strategy_type2>::value; - BOOST_MPL_ASSERT_MSG((same_strategies), - DEFAULT_WITHIN_AND_COVERED_BY_STRATEGIES_NOT_COMPATIBLE, - (strategy_type, strategy_type2)); - return point_in_geometry(point, geometry, strategy_type()); } diff --git a/boost/geometry/algorithms/difference.hpp b/boost/geometry/algorithms/difference.hpp index f7ca48cbe6..c11ceca243 100644 --- a/boost/geometry/algorithms/difference.hpp +++ b/boost/geometry/algorithms/difference.hpp @@ -2,6 +2,11 @@ // Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. +// This file was modified by Oracle on 2017. +// Modifications copyright (c) 2017, 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) @@ -9,10 +14,16 @@ #ifndef BOOST_GEOMETRY_ALGORITHMS_DIFFERENCE_HPP #define BOOST_GEOMETRY_ALGORITHMS_DIFFERENCE_HPP -#include <algorithm> + +#include <boost/variant/apply_visitor.hpp> +#include <boost/variant/static_visitor.hpp> +#include <boost/variant/variant_fwd.hpp> #include <boost/geometry/algorithms/detail/overlay/intersection_insert.hpp> #include <boost/geometry/policies/robustness/get_rescale_policy.hpp> +#include <boost/geometry/strategies/default_strategy.hpp> +#include <boost/geometry/util/range.hpp> + namespace boost { namespace geometry { @@ -49,10 +60,10 @@ template typename Strategy > inline OutputIterator difference_insert(Geometry1 const& geometry1, - Geometry2 const& geometry2, - RobustPolicy const& robust_policy, - OutputIterator out, - Strategy const& strategy) + Geometry2 const& geometry2, + RobustPolicy const& robust_policy, + OutputIterator out, + Strategy const& strategy) { concepts::check<Geometry1 const>(); concepts::check<Geometry2 const>(); @@ -93,25 +104,18 @@ template typename OutputIterator > inline OutputIterator difference_insert(Geometry1 const& geometry1, - Geometry2 const& geometry2, - RobustPolicy const& robust_policy, - OutputIterator out) + Geometry2 const& geometry2, + RobustPolicy const& robust_policy, + OutputIterator out) { - concepts::check<Geometry1 const>(); - concepts::check<Geometry2 const>(); - concepts::check<GeometryOut>(); - - typedef intersection_strategies + typedef typename strategy::relate::services::default_strategy < - typename cs_tag<GeometryOut>::type, Geometry1, - Geometry2, - typename geometry::point_type<GeometryOut>::type, - RobustPolicy - > strategy; + Geometry2 + >::type strategy_type; return difference_insert<GeometryOut>(geometry1, geometry2, - robust_policy, out, strategy()); + robust_policy, out, strategy_type()); } @@ -119,6 +123,215 @@ inline OutputIterator difference_insert(Geometry1 const& geometry1, #endif // DOXYGEN_NO_DETAIL +namespace resolve_strategy { + +struct difference +{ + template + < + typename Geometry1, + typename Geometry2, + typename RobustPolicy, + typename Collection, + typename Strategy + > + static inline void apply(Geometry1 const& geometry1, + Geometry2 const& geometry2, + RobustPolicy const& robust_policy, + Collection & output_collection, + Strategy const& strategy) + { + typedef typename boost::range_value<Collection>::type geometry_out; + + detail::difference::difference_insert<geometry_out>( + geometry1, geometry2, robust_policy, + range::back_inserter(output_collection), + strategy); + } + + template + < + typename Geometry1, + typename Geometry2, + typename RobustPolicy, + typename Collection + > + static inline void apply(Geometry1 const& geometry1, + Geometry2 const& geometry2, + RobustPolicy const& robust_policy, + Collection & output_collection, + default_strategy) + { + typedef typename boost::range_value<Collection>::type geometry_out; + + detail::difference::difference_insert<geometry_out>( + geometry1, geometry2, robust_policy, + range::back_inserter(output_collection)); + } +}; + +} // resolve_strategy + + +namespace resolve_variant +{ + +template <typename Geometry1, typename Geometry2> +struct difference +{ + template <typename Collection, typename Strategy> + static inline void apply(Geometry1 const& geometry1, + Geometry2 const& geometry2, + Collection& output_collection, + Strategy const& strategy) + { + typedef typename geometry::rescale_overlay_policy_type + < + Geometry1, + Geometry2 + >::type rescale_policy_type; + + rescale_policy_type robust_policy + = geometry::get_rescale_policy<rescale_policy_type>(geometry1, + geometry2); + + resolve_strategy::difference::apply(geometry1, geometry2, + robust_policy, + output_collection, + strategy); + } +}; + + +template <BOOST_VARIANT_ENUM_PARAMS(typename T), typename Geometry2> +struct difference<variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Geometry2> +{ + template <typename Collection, typename Strategy> + struct visitor: static_visitor<> + { + Geometry2 const& m_geometry2; + Collection& m_output_collection; + Strategy const& m_strategy; + + visitor(Geometry2 const& geometry2, + Collection& output_collection, + Strategy const& strategy) + : m_geometry2(geometry2) + , m_output_collection(output_collection) + , m_strategy(strategy) + {} + + template <typename Geometry1> + void operator()(Geometry1 const& geometry1) const + { + difference + < + Geometry1, + Geometry2 + >::apply(geometry1, m_geometry2, m_output_collection, m_strategy); + } + }; + + template <typename Collection, typename Strategy> + static inline void + apply(variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry1, + Geometry2 const& geometry2, + Collection& output_collection, + Strategy const& strategy) + { + boost::apply_visitor(visitor<Collection, Strategy>(geometry2, + output_collection, + strategy), + geometry1); + } +}; + + +template <typename Geometry1, BOOST_VARIANT_ENUM_PARAMS(typename T)> +struct difference<Geometry1, variant<BOOST_VARIANT_ENUM_PARAMS(T)> > +{ + template <typename Collection, typename Strategy> + struct visitor: static_visitor<> + { + Geometry1 const& m_geometry1; + Collection& m_output_collection; + Strategy const& m_strategy; + + visitor(Geometry1 const& geometry1, + Collection& output_collection, + Strategy const& strategy) + : m_geometry1(geometry1) + , m_output_collection(output_collection) + , m_strategy(strategy) + {} + + template <typename Geometry2> + void operator()(Geometry2 const& geometry2) const + { + difference + < + Geometry1, + Geometry2 + >::apply(m_geometry1, geometry2, m_output_collection, m_strategy); + } + }; + + template <typename Collection, typename Strategy> + static inline void + apply(Geometry1 const& geometry1, + variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry2, + Collection& output_collection, + Strategy const& strategy) + { + boost::apply_visitor(visitor<Collection, Strategy>(geometry1, + output_collection, + strategy), + geometry2); + } +}; + + +template <BOOST_VARIANT_ENUM_PARAMS(typename T1), BOOST_VARIANT_ENUM_PARAMS(typename T2)> +struct difference<variant<BOOST_VARIANT_ENUM_PARAMS(T1)>, variant<BOOST_VARIANT_ENUM_PARAMS(T2)> > +{ + template <typename Collection, typename Strategy> + struct visitor: static_visitor<> + { + Collection& m_output_collection; + Strategy const& m_strategy; + + visitor(Collection& output_collection, Strategy const& strategy) + : m_output_collection(output_collection) + , m_strategy(strategy) + {} + + template <typename Geometry1, typename Geometry2> + void operator()(Geometry1 const& geometry1, + Geometry2 const& geometry2) const + { + difference + < + Geometry1, + Geometry2 + >::apply(geometry1, geometry2, m_output_collection, m_strategy); + } + }; + + template <typename Collection, typename Strategy> + static inline void + apply(variant<BOOST_VARIANT_ENUM_PARAMS(T1)> const& geometry1, + variant<BOOST_VARIANT_ENUM_PARAMS(T2)> const& geometry2, + Collection& output_collection, + Strategy const& strategy) + { + boost::apply_visitor(visitor<Collection, Strategy>(output_collection, + strategy), + geometry1, geometry2); + } +}; + +} // namespace resolve_variant + /*! \brief_calc2{difference} @@ -127,39 +340,63 @@ inline OutputIterator difference_insert(Geometry1 const& geometry1, \tparam Geometry1 \tparam_geometry \tparam Geometry2 \tparam_geometry \tparam Collection \tparam_output_collection +\tparam Strategy \tparam_strategy{Difference} \param geometry1 \param_geometry \param geometry2 \param_geometry \param output_collection the output collection +\param strategy \param_strategy{difference} +\qbk{distinguish,with strategy} \qbk{[include reference/algorithms/difference.qbk]} */ template < typename Geometry1, typename Geometry2, - typename Collection + typename Collection, + typename Strategy > inline void difference(Geometry1 const& geometry1, - Geometry2 const& geometry2, Collection& output_collection) + Geometry2 const& geometry2, + Collection& output_collection, + Strategy const& strategy) { - concepts::check<Geometry1 const>(); - concepts::check<Geometry2 const>(); - - typedef typename boost::range_value<Collection>::type geometry_out; - concepts::check<geometry_out>(); - - typedef typename geometry::rescale_overlay_policy_type + resolve_variant::difference < Geometry1, Geometry2 - >::type rescale_policy_type; + >::apply(geometry1, geometry2, output_collection, strategy); +} - rescale_policy_type robust_policy - = geometry::get_rescale_policy<rescale_policy_type>(geometry1, geometry2); - detail::difference::difference_insert<geometry_out>( - geometry1, geometry2, robust_policy, - range::back_inserter(output_collection)); +/*! +\brief_calc2{difference} +\ingroup difference +\details \details_calc2{difference, spatial set theoretic difference}. +\tparam Geometry1 \tparam_geometry +\tparam Geometry2 \tparam_geometry +\tparam Collection \tparam_output_collection +\param geometry1 \param_geometry +\param geometry2 \param_geometry +\param output_collection the output collection + +\qbk{[include reference/algorithms/difference.qbk]} +*/ +template +< + typename Geometry1, + typename Geometry2, + typename Collection +> +inline void difference(Geometry1 const& geometry1, + Geometry2 const& geometry2, + Collection& output_collection) +{ + resolve_variant::difference + < + Geometry1, + Geometry2 + >::apply(geometry1, geometry2, output_collection, default_strategy()); } diff --git a/boost/geometry/algorithms/dispatch/disjoint.hpp b/boost/geometry/algorithms/dispatch/disjoint.hpp index 627bcff83c..78015f1a55 100644 --- a/boost/geometry/algorithms/dispatch/disjoint.hpp +++ b/boost/geometry/algorithms/dispatch/disjoint.hpp @@ -5,8 +5,8 @@ // Copyright (c) 2009-2014 Mateusz Loskot, London, UK. // Copyright (c) 2013-2014 Adam Wulkiewicz, Lodz, Poland. -// This file was modified by Oracle on 2013-2014. -// Modifications copyright (c) 2013-2014, Oracle and/or its affiliates. +// This file was modified by Oracle on 2013-2017. +// Modifications copyright (c) 2013-2017, Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle @@ -60,6 +60,29 @@ struct disjoint : not_implemented<Geometry1, Geometry2> {}; + +// If reversal is needed, perform it +template +< + typename Geometry1, typename Geometry2, + std::size_t DimensionCount, + typename Tag1, typename Tag2 +> +struct disjoint<Geometry1, Geometry2, DimensionCount, Tag1, Tag2, true> +{ + template <typename Strategy> + static inline bool apply(Geometry1 const& g1, Geometry2 const& g2, Strategy const& strategy) + { + return disjoint + < + Geometry2, Geometry1, + DimensionCount, + Tag2, Tag1 + >::apply(g2, g1, strategy); + } +}; + + } // namespace dispatch #endif // DOXYGEN_NO_DISPATCH diff --git a/boost/geometry/algorithms/equals.hpp b/boost/geometry/algorithms/equals.hpp index d04d5c7f3a..1479ea66fa 100644 --- a/boost/geometry/algorithms/equals.hpp +++ b/boost/geometry/algorithms/equals.hpp @@ -5,8 +5,8 @@ // Copyright (c) 2009-2015 Mateusz Loskot, London, UK. // Copyright (c) 2014-2015 Adam Wulkiewicz, Lodz, Poland. -// This file was modified by Oracle on 2014, 2015, 2016. -// Modifications copyright (c) 2014-2016 Oracle and/or its affiliates. +// This file was modified by Oracle on 2014, 2015, 2016, 2017. +// Modifications copyright (c) 2014-2017 Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle @@ -26,6 +26,7 @@ #include <vector> #include <boost/range.hpp> +#include <boost/type_traits/is_base_of.hpp> #include <boost/variant/apply_visitor.hpp> #include <boost/variant/static_visitor.hpp> @@ -40,7 +41,6 @@ #include <boost/geometry/geometries/concepts/check.hpp> #include <boost/geometry/algorithms/detail/equals/point_point.hpp> -#include <boost/geometry/algorithms/detail/not.hpp> #include <boost/geometry/algorithms/not_implemented.hpp> // For trivial checks @@ -70,25 +70,44 @@ template std::size_t Dimension, std::size_t DimensionCount > +struct point_point +{ + template <typename Point1, typename Point2, typename Strategy> + static inline bool apply(Point1 const& point1, Point2 const& point2, Strategy const& strategy) + { + return ! detail::disjoint::point_point + < + Point1, Point2, + Dimension, DimensionCount + >::apply(point1, point2, strategy); + } +}; + + +template +< + std::size_t Dimension, + std::size_t DimensionCount +> struct box_box { - template <typename Box1, typename Box2> - static inline bool apply(Box1 const& box1, Box2 const& box2) + template <typename Box1, typename Box2, typename Strategy> + static inline bool apply(Box1 const& box1, Box2 const& box2, Strategy const& strategy) { if (!geometry::math::equals(get<min_corner, Dimension>(box1), get<min_corner, Dimension>(box2)) || !geometry::math::equals(get<max_corner, Dimension>(box1), get<max_corner, Dimension>(box2))) { return false; } - return box_box<Dimension + 1, DimensionCount>::apply(box1, box2); + return box_box<Dimension + 1, DimensionCount>::apply(box1, box2, strategy); } }; template <std::size_t DimensionCount> struct box_box<DimensionCount, DimensionCount> { - template <typename Box1, typename Box2> - static inline bool apply(Box1 const& , Box2 const& ) + template <typename Box1, typename Box2, typename Strategy> + static inline bool apply(Box1 const& , Box2 const& , Strategy const& ) { return true; } @@ -97,8 +116,8 @@ struct box_box<DimensionCount, DimensionCount> struct segment_segment { - template <typename Segment1, typename Segment2> - static inline bool apply(Segment1 const& segment1, Segment2 const& segment2) + template <typename Segment1, typename Segment2, typename Strategy> + static inline bool apply(Segment1 const& segment1, Segment2 const& segment2, Strategy const& ) { return equals::equals_point_point( indexed_point_view<Segment1 const, 0>(segment1), @@ -119,55 +138,75 @@ struct segment_segment struct area_check { - template <typename Geometry1, typename Geometry2> - static inline bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2) + template <typename Geometry1, typename Geometry2, typename Strategy> + static inline bool apply(Geometry1 const& geometry1, + Geometry2 const& geometry2, + Strategy const& strategy) { return geometry::math::equals( - geometry::area(geometry1), - geometry::area(geometry2)); + geometry::area(geometry1, + strategy.template get_area_strategy<Geometry1>()), + geometry::area(geometry2, + strategy.template get_area_strategy<Geometry2>())); } }; struct length_check { - template <typename Geometry1, typename Geometry2> - static inline bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2) + template <typename Geometry1, typename Geometry2, typename Strategy> + static inline bool apply(Geometry1 const& geometry1, + Geometry2 const& geometry2, + Strategy const& strategy) { return geometry::math::equals( - geometry::length(geometry1), - geometry::length(geometry2)); + geometry::length(geometry1, + strategy.template get_distance_strategy<Geometry1>()), + geometry::length(geometry2, + strategy.template get_distance_strategy<Geometry2>())); } }; +template <typename Geometry1, typename Geometry2, typename IntersectionStrategy> +struct collected_vector +{ + typedef typename geometry::select_most_precise + < + typename select_coordinate_type + < + Geometry1, Geometry2 + >::type, + double + >::type calculation_type; + + typedef geometry::collected_vector + < + calculation_type, + Geometry1, + typename IntersectionStrategy::side_strategy_type + > type; +}; + template <typename TrivialCheck> struct equals_by_collection { - template <typename Geometry1, typename Geometry2> - static inline bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2) + template <typename Geometry1, typename Geometry2, typename Strategy> + static inline bool apply(Geometry1 const& geometry1, + Geometry2 const& geometry2, + Strategy const& strategy) { - if (! TrivialCheck::apply(geometry1, geometry2)) + if (! TrivialCheck::apply(geometry1, geometry2, strategy)) { return false; } - typedef typename geometry::select_most_precise - < - typename select_coordinate_type - < - Geometry1, Geometry2 - >::type, - double - >::type calculation_type; - - typedef geometry::collected_vector + typedef typename collected_vector < - calculation_type, - Geometry1 - > collected_vector; + Geometry1, Geometry2, Strategy + >::type collected_vector_type; - std::vector<collected_vector> c1, c2; + std::vector<collected_vector_type> c1, c2; geometry::collect_vectors(c1, geometry1); geometry::collect_vectors(c2, geometry2); @@ -195,6 +234,53 @@ struct equals_by_relate > {}; +// If collect_vectors which is a SideStrategy-dispatched optimization +// is implemented in a way consistent with the Intersection/Side Strategy +// then collect_vectors is used, otherwise relate is used. +// NOTE: the result could be coneptually different for invalid +// geometries in different coordinate systems because collect_vectors +// and relate treat invalid geometries differently. +template<typename TrivialCheck> +struct equals_by_collection_or_relate +{ + template <typename Geometry1, typename Geometry2, typename Strategy> + static inline bool apply(Geometry1 const& geometry1, + Geometry2 const& geometry2, + Strategy const& strategy) + { + typedef typename boost::is_base_of + < + nyi::not_implemented_tag, + typename collected_vector + < + Geometry1, Geometry2, Strategy + >::type + >::type enable_relate_type; + + return apply(geometry1, geometry2, strategy, enable_relate_type()); + } + +private: + template <typename Geometry1, typename Geometry2, typename Strategy> + static inline bool apply(Geometry1 const& geometry1, + Geometry2 const& geometry2, + Strategy const& strategy, + boost::false_type /*enable_relate*/) + { + return equals_by_collection<TrivialCheck>::apply(geometry1, geometry2, strategy); + } + + template <typename Geometry1, typename Geometry2, typename Strategy> + static inline bool apply(Geometry1 const& geometry1, + Geometry2 const& geometry2, + Strategy const& strategy, + boost::true_type /*enable_relate*/) + { + return equals_by_relate<Geometry1, Geometry2>::apply(geometry1, geometry2, strategy); + } +}; + + }} // namespace detail::equals #endif // DOXYGEN_NO_DETAIL @@ -226,7 +312,8 @@ template struct equals<Geometry1, Geometry2, Tag1, Tag2, DimensionCount, true> : equals<Geometry2, Geometry1, Tag2, Tag1, DimensionCount, false> { - static inline bool apply(Geometry1 const& g1, Geometry2 const& g2) + template <typename Strategy> + static inline bool apply(Geometry1 const& g1, Geometry2 const& g2, Strategy const& strategy) { return equals < @@ -234,19 +321,30 @@ struct equals<Geometry1, Geometry2, Tag1, Tag2, DimensionCount, true> Tag2, Tag1, DimensionCount, false - >::apply(g2, g1); + >::apply(g2, g1, strategy); } }; template <typename P1, typename P2, std::size_t DimensionCount, bool Reverse> struct equals<P1, P2, point_tag, point_tag, DimensionCount, Reverse> - : geometry::detail::not_ - < - detail::disjoint::point_point<P1, P2, 0, DimensionCount> - > + : detail::equals::point_point<0, DimensionCount> +{}; + +template <typename MultiPoint1, typename MultiPoint2, std::size_t DimensionCount, bool Reverse> +struct equals<MultiPoint1, MultiPoint2, multi_point_tag, multi_point_tag, DimensionCount, Reverse> + : detail::equals::equals_by_relate<MultiPoint1, MultiPoint2> {}; +template <typename MultiPoint, typename Point, std::size_t DimensionCount, bool Reverse> +struct equals<MultiPoint, Point, multi_point_tag, point_tag, DimensionCount, Reverse> + : detail::equals::equals_by_relate<MultiPoint, Point> +{}; + +template <typename MultiPoint, typename Point, std::size_t DimensionCount, bool Reverse> +struct equals<Point, MultiPoint, point_tag, multi_point_tag, DimensionCount, Reverse> + : detail::equals::equals_by_relate<Point, MultiPoint> +{}; template <typename Box1, typename Box2, std::size_t DimensionCount, bool Reverse> struct equals<Box1, Box2, box_tag, box_tag, DimensionCount, Reverse> @@ -256,19 +354,19 @@ struct equals<Box1, Box2, box_tag, box_tag, DimensionCount, Reverse> template <typename Ring1, typename Ring2, bool Reverse> struct equals<Ring1, Ring2, ring_tag, ring_tag, 2, Reverse> - : detail::equals::equals_by_collection<detail::equals::area_check> + : detail::equals::equals_by_collection_or_relate<detail::equals::area_check> {}; template <typename Polygon1, typename Polygon2, bool Reverse> struct equals<Polygon1, Polygon2, polygon_tag, polygon_tag, 2, Reverse> - : detail::equals::equals_by_collection<detail::equals::area_check> + : detail::equals::equals_by_collection_or_relate<detail::equals::area_check> {}; template <typename Polygon, typename Ring, bool Reverse> struct equals<Polygon, Ring, polygon_tag, ring_tag, 2, Reverse> - : detail::equals::equals_by_collection<detail::equals::area_check> + : detail::equals::equals_by_collection_or_relate<detail::equals::area_check> {}; @@ -290,7 +388,6 @@ struct equals<Segment1, Segment2, segment_tag, segment_tag, DimensionCount, Reve template <typename LineString1, typename LineString2, bool Reverse> struct equals<LineString1, LineString2, linestring_tag, linestring_tag, 2, Reverse> - //: detail::equals::equals_by_collection<detail::equals::length_check> : detail::equals::equals_by_relate<LineString1, LineString2> {}; @@ -313,7 +410,7 @@ struct equals 2, Reverse > - : detail::equals::equals_by_collection<detail::equals::area_check> + : detail::equals::equals_by_collection_or_relate<detail::equals::area_check> {}; @@ -325,7 +422,7 @@ struct equals 2, Reverse > - : detail::equals::equals_by_collection<detail::equals::area_check> + : detail::equals::equals_by_collection_or_relate<detail::equals::area_check> {}; template <typename MultiPolygon, typename Ring, bool Reverse> @@ -336,7 +433,7 @@ struct equals 2, Reverse > - : detail::equals::equals_by_collection<detail::equals::area_check> + : detail::equals::equals_by_collection_or_relate<detail::equals::area_check> {}; @@ -344,80 +441,129 @@ struct equals #endif // DOXYGEN_NO_DISPATCH +namespace resolve_strategy +{ + +struct equals +{ + template <typename Geometry1, typename Geometry2, typename Strategy> + static inline bool apply(Geometry1 const& geometry1, + Geometry2 const& geometry2, + Strategy const& strategy) + { + return dispatch::equals + < + Geometry1, Geometry2 + >::apply(geometry1, geometry2, strategy); + } + + template <typename Geometry1, typename Geometry2> + static inline bool apply(Geometry1 const& geometry1, + Geometry2 const& geometry2, + default_strategy) + { + typedef typename strategy::relate::services::default_strategy + < + Geometry1, + Geometry2 + >::type strategy_type; + + return dispatch::equals + < + Geometry1, Geometry2 + >::apply(geometry1, geometry2, strategy_type()); + } +}; + +} // namespace resolve_strategy + + namespace resolve_variant { template <typename Geometry1, typename Geometry2> struct equals { + template <typename Strategy> static inline bool apply(Geometry1 const& geometry1, - Geometry2 const& geometry2) + Geometry2 const& geometry2, + Strategy const& strategy) { concepts::check_concepts_and_equal_dimensions - < - Geometry1 const, - Geometry2 const - >(); + < + Geometry1 const, + Geometry2 const + >(); - return dispatch::equals<Geometry1, Geometry2> - ::apply(geometry1, geometry2); + return resolve_strategy::equals + ::apply(geometry1, geometry2, strategy); } }; template <BOOST_VARIANT_ENUM_PARAMS(typename T), typename Geometry2> struct equals<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Geometry2> { + template <typename Strategy> struct visitor: static_visitor<bool> { Geometry2 const& m_geometry2; + Strategy const& m_strategy; - visitor(Geometry2 const& geometry2) + visitor(Geometry2 const& geometry2, Strategy const& strategy) : m_geometry2(geometry2) + , m_strategy(strategy) {} template <typename Geometry1> inline bool operator()(Geometry1 const& geometry1) const { return equals<Geometry1, Geometry2> - ::apply(geometry1, m_geometry2); + ::apply(geometry1, m_geometry2, m_strategy); } }; + template <typename Strategy> static inline bool apply( boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry1, - Geometry2 const& geometry2 + Geometry2 const& geometry2, + Strategy const& strategy ) { - return boost::apply_visitor(visitor(geometry2), geometry1); + return boost::apply_visitor(visitor<Strategy>(geometry2, strategy), geometry1); } }; template <typename Geometry1, BOOST_VARIANT_ENUM_PARAMS(typename T)> struct equals<Geometry1, boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> > { + template <typename Strategy> struct visitor: static_visitor<bool> { Geometry1 const& m_geometry1; + Strategy const& m_strategy; - visitor(Geometry1 const& geometry1) + visitor(Geometry1 const& geometry1, Strategy const& strategy) : m_geometry1(geometry1) + , m_strategy(strategy) {} template <typename Geometry2> inline bool operator()(Geometry2 const& geometry2) const { return equals<Geometry1, Geometry2> - ::apply(m_geometry1, geometry2); + ::apply(m_geometry1, geometry2, m_strategy); } }; + template <typename Strategy> static inline bool apply( Geometry1 const& geometry1, - boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry2 + boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry2, + Strategy const& strategy ) { - return boost::apply_visitor(visitor(geometry1), geometry2); + return boost::apply_visitor(visitor<Strategy>(geometry1, strategy), geometry2); } }; @@ -430,24 +576,33 @@ struct equals< boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)> > { + template <typename Strategy> struct visitor: static_visitor<bool> { + Strategy const& m_strategy; + + visitor(Strategy const& strategy) + : m_strategy(strategy) + {} + template <typename Geometry1, typename Geometry2> inline bool operator()(Geometry1 const& geometry1, Geometry2 const& geometry2) const { return equals<Geometry1, Geometry2> - ::apply(geometry1, geometry2); + ::apply(geometry1, geometry2, m_strategy); } }; + template <typename Strategy> static inline bool apply( boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)> const& geometry1, - boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)> const& geometry2 + boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)> const& geometry2, + Strategy const& strategy ) { - return boost::apply_visitor(visitor(), geometry1, geometry2); + return boost::apply_visitor(visitor<Strategy>(strategy), geometry1, geometry2); } }; @@ -464,18 +619,48 @@ struct equals< \ingroup equals \tparam Geometry1 \tparam_geometry \tparam Geometry2 \tparam_geometry +\tparam Strategy \tparam_strategy{Equals} \param geometry1 \param_geometry \param geometry2 \param_geometry +\param strategy \param_strategy{equals} \return \return_check2{are spatially equal} +\qbk{distinguish,with strategy} \qbk{[include reference/algorithms/equals.qbk]} + */ +template <typename Geometry1, typename Geometry2, typename Strategy> +inline bool equals(Geometry1 const& geometry1, + Geometry2 const& geometry2, + Strategy const& strategy) +{ + return resolve_variant::equals + < + Geometry1, Geometry2 + >::apply(geometry1, geometry2, strategy); +} + +/*! +\brief \brief_check{are spatially equal} +\details \details_check12{equals, is spatially equal}. Spatially equal means + that the same point set is included. A box can therefore be spatially equal + to a ring or a polygon, or a linestring can be spatially equal to a + multi-linestring or a segment. This only works theoretically, not all + combinations are implemented yet. +\ingroup equals +\tparam Geometry1 \tparam_geometry +\tparam Geometry2 \tparam_geometry +\param geometry1 \param_geometry +\param geometry2 \param_geometry +\return \return_check2{are spatially equal} + +\qbk{[include reference/algorithms/equals.qbk]} */ template <typename Geometry1, typename Geometry2> inline bool equals(Geometry1 const& geometry1, Geometry2 const& geometry2) { return resolve_variant::equals<Geometry1, Geometry2> - ::apply(geometry1, geometry2); + ::apply(geometry1, geometry2, default_strategy()); } diff --git a/boost/geometry/algorithms/intersects.hpp b/boost/geometry/algorithms/intersects.hpp index 5349db76bb..12ae169f12 100644 --- a/boost/geometry/algorithms/intersects.hpp +++ b/boost/geometry/algorithms/intersects.hpp @@ -4,10 +4,11 @@ // Copyright (c) 2008-2014 Bruno Lalande, Paris, France. // Copyright (c) 2009-2014 Mateusz Loskot, London, UK. -// This file was modified by Oracle on 2013-2014. -// Modifications copyright (c) 2013-2014, Oracle and/or its affiliates. +// This file was modified by Oracle on 2013-2017. +// Modifications copyright (c) 2013-2017, 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. @@ -29,6 +30,8 @@ #include <boost/geometry/policies/robustness/no_rescale_policy.hpp> #include <boost/geometry/policies/robustness/segment_ratio_type.hpp> +#include <boost/geometry/strategies/relate.hpp> + namespace boost { namespace geometry { @@ -52,6 +55,10 @@ inline bool intersects(Geometry const& geometry) concepts::check<Geometry const>(); typedef typename geometry::point_type<Geometry>::type point_type; + typedef typename strategy::relate::services::default_strategy + < + Geometry, Geometry + >::type strategy_type; typedef detail::no_rescale_policy rescale_policy_type; typedef detail::overlay::turn_info @@ -67,13 +74,14 @@ inline bool intersects(Geometry const& geometry) detail::overlay::assign_null_policy > turn_policy; + strategy_type strategy; rescale_policy_type robust_policy; detail::disjoint::disjoint_interrupt_policy policy; detail::self_get_turn_points::get_turns < turn_policy - >::apply(geometry, robust_policy, turns, policy); + >::apply(geometry, strategy, robust_policy, turns, policy); return policy.has_intersections; } @@ -83,6 +91,32 @@ inline bool intersects(Geometry const& geometry) \ingroup intersects \tparam Geometry1 \tparam_geometry \tparam Geometry2 \tparam_geometry +\tparam Strategy \tparam_strategy{Intersects} +\param geometry1 \param_geometry +\param geometry2 \param_geometry +\param strategy \param_strategy{intersects} +\return \return_check2{intersect each other} + +\qbk{distinguish,with strategy} +\qbk{[include reference/algorithms/intersects.qbk]} + */ +template <typename Geometry1, typename Geometry2, typename Strategy> +inline bool intersects(Geometry1 const& geometry1, + Geometry2 const& geometry2, + Strategy const& strategy) +{ + concepts::check<Geometry1 const>(); + concepts::check<Geometry2 const>(); + + return ! geometry::disjoint(geometry1, geometry2, strategy); +} + + +/*! +\brief \brief_check2{have at least one intersection} +\ingroup intersects +\tparam Geometry1 \tparam_geometry +\tparam Geometry2 \tparam_geometry \param geometry1 \param_geometry \param geometry2 \param_geometry \return \return_check2{intersect each other} diff --git a/boost/geometry/algorithms/overlaps.hpp b/boost/geometry/algorithms/overlaps.hpp index 32738c294c..bedf17599b 100644 --- a/boost/geometry/algorithms/overlaps.hpp +++ b/boost/geometry/algorithms/overlaps.hpp @@ -4,8 +4,8 @@ // Copyright (c) 2008-2015 Bruno Lalande, Paris, France. // Copyright (c) 2009-2015 Mateusz Loskot, London, UK. -// This file was modified by Oracle on 2014, 2015. -// Modifications copyright (c) 2014-2015 Oracle and/or its affiliates. +// This file was modified by Oracle on 2014, 2015, 2017. +// Modifications copyright (c) 2014-2017 Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle @@ -113,8 +113,8 @@ struct box_box_loop<DimensionCount, DimensionCount> struct box_box { - template <typename Box1, typename Box2> - static inline bool apply(Box1 const& b1, Box2 const& b2) + template <typename Box1, typename Box2, typename Strategy> + static inline bool apply(Box1 const& b1, Box2 const& b2, Strategy const& /*strategy*/) { bool overlaps = true; bool within1 = true; @@ -137,7 +137,6 @@ struct box_box }} // namespace detail::overlaps #endif // DOXYGEN_NO_DETAIL -//struct not_implemented_for_this_geometry_type : public boost::false_type {}; #ifndef DOXYGEN_NO_DISPATCH namespace dispatch @@ -175,6 +174,35 @@ struct overlaps<Box1, Box2, box_tag, box_tag> \ingroup overlaps \tparam Geometry1 \tparam_geometry \tparam Geometry2 \tparam_geometry +\tparam Strategy \tparam_strategy{Overlaps} +\param geometry1 \param_geometry +\param geometry2 \param_geometry +\param strategy \param_strategy{overlaps} +\return \return_check2{overlap} + +\qbk{distinguish,with strategy} +\qbk{[include reference/algorithms/overlaps.qbk]} +*/ +template <typename Geometry1, typename Geometry2, typename Strategy> +inline bool overlaps(Geometry1 const& geometry1, + Geometry2 const& geometry2, + Strategy const& strategy) +{ + concepts::check<Geometry1 const>(); + concepts::check<Geometry2 const>(); + + return dispatch::overlaps + < + Geometry1, + Geometry2 + >::apply(geometry1, geometry2, strategy); +} + +/*! +\brief \brief_check2{overlap} +\ingroup overlaps +\tparam Geometry1 \tparam_geometry +\tparam Geometry2 \tparam_geometry \param geometry1 \param_geometry \param geometry2 \param_geometry \return \return_check2{overlap} @@ -187,11 +215,17 @@ inline bool overlaps(Geometry1 const& geometry1, Geometry2 const& geometry2) concepts::check<Geometry1 const>(); concepts::check<Geometry2 const>(); + typedef typename strategy::relate::services::default_strategy + < + Geometry1, + Geometry2 + >::type strategy_type; + return dispatch::overlaps < Geometry1, Geometry2 - >::apply(geometry1, geometry2); + >::apply(geometry1, geometry2, strategy_type()); } }} // namespace boost::geometry diff --git a/boost/geometry/algorithms/sym_difference.hpp b/boost/geometry/algorithms/sym_difference.hpp index 33f94c9321..725230cd5b 100644 --- a/boost/geometry/algorithms/sym_difference.hpp +++ b/boost/geometry/algorithms/sym_difference.hpp @@ -2,10 +2,11 @@ // Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands. -// This file was modified by Oracle on 2015. -// Modifications copyright (c) 2015 Oracle and/or its affiliates. +// This file was modified by Oracle on 2015, 2017. +// Modifications copyright (c) 2015-2017 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 // Use, modification and distribution is subject to the Boost Software License, // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at @@ -14,13 +15,21 @@ #ifndef BOOST_GEOMETRY_ALGORITHMS_SYM_DIFFERENCE_HPP #define BOOST_GEOMETRY_ALGORITHMS_SYM_DIFFERENCE_HPP + #include <algorithm> #include <iterator> #include <vector> +#include <boost/variant/apply_visitor.hpp> +#include <boost/variant/static_visitor.hpp> +#include <boost/variant/variant_fwd.hpp> + #include <boost/geometry/algorithms/intersection.hpp> #include <boost/geometry/algorithms/union.hpp> #include <boost/geometry/geometries/multi_polygon.hpp> +#include <boost/geometry/policies/robustness/get_rescale_policy.hpp> +#include <boost/geometry/strategies/default_strategy.hpp> +#include <boost/geometry/util/range.hpp> namespace boost { namespace geometry @@ -276,14 +285,10 @@ inline OutputIterator sym_difference_insert(Geometry1 const& geometry1, concepts::check<Geometry2 const>(); concepts::check<GeometryOut>(); - typedef intersection_strategies + typedef typename strategy::intersection::services::default_strategy < - typename cs_tag<GeometryOut>::type, - Geometry1, - Geometry2, - typename geometry::point_type<GeometryOut>::type, - RobustPolicy - > strategy_type; + typename cs_tag<GeometryOut>::type + >::type strategy_type; return sym_difference_insert<GeometryOut>(geometry1, geometry2, robust_policy, out, strategy_type()); } @@ -292,6 +297,216 @@ inline OutputIterator sym_difference_insert(Geometry1 const& geometry1, #endif // DOXYGEN_NO_DETAIL +namespace resolve_strategy { + +struct sym_difference +{ + template + < + typename Geometry1, + typename Geometry2, + typename RobustPolicy, + typename Collection, + typename Strategy + > + static inline void apply(Geometry1 const& geometry1, + Geometry2 const& geometry2, + RobustPolicy const& robust_policy, + Collection & output_collection, + Strategy const& strategy) + { + typedef typename boost::range_value<Collection>::type geometry_out; + + detail::sym_difference::sym_difference_insert<geometry_out>( + geometry1, geometry2, robust_policy, + range::back_inserter(output_collection), + strategy); + } + + template + < + typename Geometry1, + typename Geometry2, + typename RobustPolicy, + typename Collection + > + static inline void apply(Geometry1 const& geometry1, + Geometry2 const& geometry2, + RobustPolicy const& robust_policy, + Collection & output_collection, + default_strategy) + { + typedef typename boost::range_value<Collection>::type geometry_out; + + detail::sym_difference::sym_difference_insert<geometry_out>( + geometry1, geometry2, robust_policy, + range::back_inserter(output_collection)); + } +}; + +} // resolve_strategy + + +namespace resolve_variant +{ + +template <typename Geometry1, typename Geometry2> +struct sym_difference +{ + template <typename Collection, typename Strategy> + static inline void apply(Geometry1 const& geometry1, + Geometry2 const& geometry2, + Collection& output_collection, + Strategy const& strategy) + { + typedef typename geometry::rescale_overlay_policy_type + < + Geometry1, + Geometry2 + >::type rescale_policy_type; + + rescale_policy_type robust_policy + = geometry::get_rescale_policy<rescale_policy_type>(geometry1, + geometry2); + + resolve_strategy::sym_difference::apply(geometry1, geometry2, + robust_policy, + output_collection, + strategy); + } +}; + + +template <BOOST_VARIANT_ENUM_PARAMS(typename T), typename Geometry2> +struct sym_difference<variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Geometry2> +{ + template <typename Collection, typename Strategy> + struct visitor: static_visitor<> + { + Geometry2 const& m_geometry2; + Collection& m_output_collection; + Strategy const& m_strategy; + + visitor(Geometry2 const& geometry2, + Collection& output_collection, + Strategy const& strategy) + : m_geometry2(geometry2) + , m_output_collection(output_collection) + , m_strategy(strategy) + {} + + template <typename Geometry1> + void operator()(Geometry1 const& geometry1) const + { + sym_difference + < + Geometry1, + Geometry2 + >::apply(geometry1, m_geometry2, m_output_collection, m_strategy); + } + }; + + template <typename Collection, typename Strategy> + static inline void + apply(variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry1, + Geometry2 const& geometry2, + Collection& output_collection, + Strategy const& strategy) + { + boost::apply_visitor(visitor<Collection, Strategy>(geometry2, + output_collection, + strategy), + geometry1); + } +}; + + +template <typename Geometry1, BOOST_VARIANT_ENUM_PARAMS(typename T)> +struct sym_difference<Geometry1, variant<BOOST_VARIANT_ENUM_PARAMS(T)> > +{ + template <typename Collection, typename Strategy> + struct visitor: static_visitor<> + { + Geometry1 const& m_geometry1; + Collection& m_output_collection; + Strategy const& m_strategy; + + visitor(Geometry1 const& geometry1, + Collection& output_collection, + Strategy const& strategy) + : m_geometry1(geometry1) + , m_output_collection(output_collection) + , m_strategy(strategy) + {} + + template <typename Geometry2> + void operator()(Geometry2 const& geometry2) const + { + sym_difference + < + Geometry1, + Geometry2 + >::apply(m_geometry1, geometry2, m_output_collection, m_strategy); + } + }; + + template <typename Collection, typename Strategy> + static inline void + apply(Geometry1 const& geometry1, + variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry2, + Collection& output_collection, + Strategy const& strategy) + { + boost::apply_visitor(visitor<Collection, Strategy>(geometry1, + output_collection, + strategy), + geometry2); + } +}; + + +template <BOOST_VARIANT_ENUM_PARAMS(typename T1), BOOST_VARIANT_ENUM_PARAMS(typename T2)> +struct sym_difference<variant<BOOST_VARIANT_ENUM_PARAMS(T1)>, variant<BOOST_VARIANT_ENUM_PARAMS(T2)> > +{ + template <typename Collection, typename Strategy> + struct visitor: static_visitor<> + { + Collection& m_output_collection; + Strategy const& m_strategy; + + visitor(Collection& output_collection, Strategy const& strategy) + : m_output_collection(output_collection) + , m_strategy(strategy) + {} + + template <typename Geometry1, typename Geometry2> + void operator()(Geometry1 const& geometry1, + Geometry2 const& geometry2) const + { + sym_difference + < + Geometry1, + Geometry2 + >::apply(geometry1, geometry2, m_output_collection, m_strategy); + } + }; + + template <typename Collection, typename Strategy> + static inline void + apply(variant<BOOST_VARIANT_ENUM_PARAMS(T1)> const& geometry1, + variant<BOOST_VARIANT_ENUM_PARAMS(T2)> const& geometry2, + Collection& output_collection, + Strategy const& strategy) + { + boost::apply_visitor(visitor<Collection, Strategy>(output_collection, + strategy), + geometry1, geometry2); + } +}; + +} // namespace resolve_variant + + /*! \brief \brief_calc2{symmetric difference} \ingroup sym_difference @@ -300,39 +515,64 @@ inline OutputIterator sym_difference_insert(Geometry1 const& geometry1, \tparam Geometry2 \tparam_geometry \tparam Collection output collection, either a multi-geometry, or a std::vector<Geometry> / std::deque<Geometry> etc +\tparam Strategy \tparam_strategy{Sym_difference} \param geometry1 \param_geometry \param geometry2 \param_geometry \param output_collection the output collection +\param strategy \param_strategy{sym_difference} +\qbk{distinguish,with strategy} \qbk{[include reference/algorithms/sym_difference.qbk]} */ template < typename Geometry1, typename Geometry2, - typename Collection + typename Collection, + typename Strategy > inline void sym_difference(Geometry1 const& geometry1, - Geometry2 const& geometry2, Collection& output_collection) + Geometry2 const& geometry2, + Collection& output_collection, + Strategy const& strategy) { - concepts::check<Geometry1 const>(); - concepts::check<Geometry2 const>(); - - typedef typename boost::range_value<Collection>::type geometry_out; - concepts::check<geometry_out>(); - - typedef typename geometry::rescale_overlay_policy_type + resolve_variant::sym_difference < Geometry1, Geometry2 - >::type rescale_policy_type; + >::apply(geometry1, geometry2, output_collection, strategy); +} - rescale_policy_type robust_policy - = geometry::get_rescale_policy<rescale_policy_type>(geometry1, geometry2); - detail::sym_difference::sym_difference_insert<geometry_out>( - geometry1, geometry2, robust_policy, - range::back_inserter(output_collection)); +/*! +\brief \brief_calc2{symmetric difference} +\ingroup sym_difference +\details \details_calc2{symmetric difference, spatial set theoretic symmetric difference (XOR)}. +\tparam Geometry1 \tparam_geometry +\tparam Geometry2 \tparam_geometry +\tparam Collection output collection, either a multi-geometry, + or a std::vector<Geometry> / std::deque<Geometry> etc +\param geometry1 \param_geometry +\param geometry2 \param_geometry +\param output_collection the output collection + +\qbk{[include reference/algorithms/sym_difference.qbk]} +*/ +template +< + typename Geometry1, + typename Geometry2, + typename Collection +> +inline void sym_difference(Geometry1 const& geometry1, + Geometry2 const& geometry2, + Collection& output_collection) +{ + resolve_variant::sym_difference + < + Geometry1, + Geometry2 + >::apply(geometry1, geometry2, output_collection, default_strategy()); } diff --git a/boost/geometry/algorithms/touches.hpp b/boost/geometry/algorithms/touches.hpp index 6384cc2a88..49e104d258 100644 --- a/boost/geometry/algorithms/touches.hpp +++ b/boost/geometry/algorithms/touches.hpp @@ -5,8 +5,8 @@ // Copyright (c) 2009-2015 Mateusz Loskot, London, UK. // Copyright (c) 2013-2015 Adam Wulkiewicz, Lodz, Poland. -// This file was modified by Oracle on 2013, 2014, 2015. -// Modifications copyright (c) 2013-2015, Oracle and/or its affiliates. +// This file was modified by Oracle on 2013, 2014, 2015, 2017. +// Modifications copyright (c) 2013-2017, Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle @@ -104,8 +104,8 @@ struct box_box_loop<DimensionCount, DimensionCount> struct box_box { - template <typename Box1, typename Box2> - static inline bool apply(Box1 const& b1, Box2 const& b2) + template <typename Box1, typename Box2, typename Strategy> + static inline bool apply(Box1 const& b1, Box2 const& b2, Strategy const& /*strategy*/) { BOOST_STATIC_ASSERT((boost::is_same < @@ -205,15 +205,17 @@ struct areal_interrupt_policy } }; -template<typename Geometry> +template<typename Geometry, typename PointInRingStrategy> struct check_each_ring_for_within { bool has_within; Geometry const& m_geometry; + PointInRingStrategy const& m_strategy; - inline check_each_ring_for_within(Geometry const& g) + inline check_each_ring_for_within(Geometry const& g, PointInRingStrategy const& strategy) : has_within(false) , m_geometry(g) + , m_strategy(strategy) {} template <typename Range> @@ -221,18 +223,31 @@ struct check_each_ring_for_within { typename geometry::point_type<Range>::type p; geometry::point_on_border(p, range); - if ( !has_within && geometry::within(p, m_geometry) ) + if ( !has_within && geometry::within(p, m_geometry, m_strategy) ) { has_within = true; } } }; -template <typename FirstGeometry, typename SecondGeometry> +template <typename FirstGeometry, typename SecondGeometry, typename IntersectionStrategy> inline bool rings_containing(FirstGeometry const& geometry1, - SecondGeometry const& geometry2) + SecondGeometry const& geometry2, + IntersectionStrategy const& strategy) { - check_each_ring_for_within<FirstGeometry> checker(geometry1); + // NOTE: This strategy could be defined inside IntersectionStrategy + typedef typename IntersectionStrategy::template point_in_geometry_strategy + < + FirstGeometry, SecondGeometry + >::type point_in_ring_strategy_type; + + point_in_ring_strategy_type point_in_ring_strategy + = strategy.template get_point_in_geometry_strategy<FirstGeometry, SecondGeometry>(); + + check_each_ring_for_within + < + FirstGeometry, point_in_ring_strategy_type + > checker(geometry1, point_in_ring_strategy); geometry::detail::for_each_range(geometry2, checker); return checker.has_within; } @@ -240,8 +255,10 @@ inline bool rings_containing(FirstGeometry const& geometry1, template <typename Geometry1, typename Geometry2> struct areal_areal { - static inline - bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2) + template <typename IntersectionStrategy> + static inline bool apply(Geometry1 const& geometry1, + Geometry2 const& geometry2, + IntersectionStrategy const& strategy) { typedef detail::no_rescale_policy rescale_policy_type; typedef typename geometry::point_type<Geometry1>::type point_type; @@ -259,11 +276,11 @@ struct areal_areal detail::overlay::do_reverse<geometry::point_order<Geometry1>::value>::value, detail::overlay::do_reverse<geometry::point_order<Geometry2>::value>::value, detail::overlay::assign_null_policy - >(geometry1, geometry2, robust_policy, turns, policy); + >(geometry1, geometry2, strategy, robust_policy, turns, policy); return policy.result() - && ! geometry::detail::touches::rings_containing(geometry1, geometry2) - && ! geometry::detail::touches::rings_containing(geometry2, geometry1); + && ! geometry::detail::touches::rings_containing(geometry1, geometry2, strategy) + && ! geometry::detail::touches::rings_containing(geometry2, geometry1, strategy); } }; @@ -271,10 +288,10 @@ struct areal_areal struct use_point_in_geometry { - template <typename Point, typename Geometry> - static inline bool apply(Point const& point, Geometry const& geometry) + template <typename Point, typename Geometry, typename Strategy> + static inline bool apply(Point const& point, Geometry const& geometry, Strategy const& strategy) { - return detail::within::point_in_geometry(point, geometry) == 0; + return detail::within::point_in_geometry(point, geometry, strategy) == 0; } }; @@ -288,7 +305,8 @@ namespace dispatch { template < - typename Geometry1, typename Geometry2, + typename Geometry1, + typename Geometry2, typename Tag1 = typename tag<Geometry1>::type, typename Tag2 = typename tag<Geometry2>::type, typename CastedTag1 = typename tag_cast<Tag1, pointlike_tag, linear_tag, areal_tag>::type, @@ -309,18 +327,30 @@ template struct touches<Geometry1, Geometry2, Tag1, Tag2, CastedTag1, CastedTag2, true> : touches<Geometry2, Geometry1, Tag2, Tag1, CastedTag2, CastedTag1, false> { - static inline bool apply(Geometry1 const& g1, Geometry2 const& g2) + template <typename Strategy> + static inline bool apply(Geometry1 const& g1, Geometry2 const& g2, Strategy const& strategy) { - return touches<Geometry2, Geometry1>::apply(g2, g1); + return touches<Geometry2, Geometry1>::apply(g2, g1, strategy); } }; // P/P -template <typename Geometry1, typename Geometry2, typename Tag1, typename Tag2> -struct touches<Geometry1, Geometry2, Tag1, Tag2, pointlike_tag, pointlike_tag, false> +template <typename Geometry1, typename Geometry2, typename Tag2> +struct touches<Geometry1, Geometry2, point_tag, Tag2, pointlike_tag, pointlike_tag, false> { - static inline bool apply(Geometry1 const& , Geometry2 const& ) + template <typename Strategy> + static inline bool apply(Geometry1 const& , Geometry2 const& , Strategy const&) + { + return false; + } +}; + +template <typename Geometry1, typename Geometry2, typename Tag2> +struct touches<Geometry1, Geometry2, multi_point_tag, Tag2, pointlike_tag, pointlike_tag, false> +{ + template <typename Strategy> + static inline bool apply(Geometry1 const&, Geometry2 const&, Strategy const&) { return false; } @@ -403,66 +433,115 @@ struct touches<Areal1, Areal2, ring_tag, ring_tag, areal_tag, areal_tag, false> #endif // DOXYGEN_NO_DISPATCH +namespace resolve_strategy +{ + +struct touches +{ + template <typename Geometry1, typename Geometry2, typename Strategy> + static inline bool apply(Geometry1 const& geometry1, + Geometry2 const& geometry2, + Strategy const& strategy) + { + return dispatch::touches + < + Geometry1, Geometry2 + >::apply(geometry1, geometry2, strategy); + } + + template <typename Geometry1, typename Geometry2> + static inline bool apply(Geometry1 const& geometry1, + Geometry2 const& geometry2, + default_strategy) + { + typedef typename strategy::relate::services::default_strategy + < + Geometry1, + Geometry2 + >::type strategy_type; + + return dispatch::touches + < + Geometry1, Geometry2 + >::apply(geometry1, geometry2, strategy_type()); + } +}; + +} // namespace resolve_strategy + + namespace resolve_variant { template <typename Geometry1, typename Geometry2> struct touches { - static bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2) + template <typename Strategy> + static bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2, Strategy const& strategy) { concepts::check<Geometry1 const>(); concepts::check<Geometry2 const>(); - return dispatch::touches<Geometry1, Geometry2> - ::apply(geometry1, geometry2); + return resolve_strategy::touches::apply(geometry1, geometry2, strategy); } }; template <BOOST_VARIANT_ENUM_PARAMS(typename T), typename Geometry2> struct touches<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Geometry2> { + template <typename Strategy> struct visitor: boost::static_visitor<bool> { Geometry2 const& m_geometry2; + Strategy const& m_strategy; - visitor(Geometry2 const& geometry2): m_geometry2(geometry2) {} + visitor(Geometry2 const& geometry2, Strategy const& strategy) + : m_geometry2(geometry2) + , m_strategy(strategy) + {} template <typename Geometry1> bool operator()(Geometry1 const& geometry1) const { - return touches<Geometry1, Geometry2>::apply(geometry1, m_geometry2); + return touches<Geometry1, Geometry2>::apply(geometry1, m_geometry2, m_strategy); } }; - static inline bool - apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry1, - Geometry2 const& geometry2) + template <typename Strategy> + static inline bool apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry1, + Geometry2 const& geometry2, + Strategy const& strategy) { - return boost::apply_visitor(visitor(geometry2), geometry1); + return boost::apply_visitor(visitor<Strategy>(geometry2, strategy), geometry1); } }; template <typename Geometry1, BOOST_VARIANT_ENUM_PARAMS(typename T)> struct touches<Geometry1, boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> > { + template <typename Strategy> struct visitor: boost::static_visitor<bool> { Geometry1 const& m_geometry1; + Strategy const& m_strategy; - visitor(Geometry1 const& geometry1): m_geometry1(geometry1) {} + visitor(Geometry1 const& geometry1, Strategy const& strategy) + : m_geometry1(geometry1) + , m_strategy(strategy) + {} template <typename Geometry2> bool operator()(Geometry2 const& geometry2) const { - return touches<Geometry1, Geometry2>::apply(m_geometry1, geometry2); + return touches<Geometry1, Geometry2>::apply(m_geometry1, geometry2, m_strategy); } }; - static inline bool - apply(Geometry1 const& geometry1, - boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry2) + template <typename Strategy> + static inline bool apply(Geometry1 const& geometry1, + boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry2, + Strategy const& strategy) { - return boost::apply_visitor(visitor(geometry1), geometry2); + return boost::apply_visitor(visitor<Strategy>(geometry1, strategy), geometry2); } }; @@ -471,21 +550,29 @@ template <BOOST_VARIANT_ENUM_PARAMS(typename T1), struct touches<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)>, boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)> > { + template <typename Strategy> struct visitor: boost::static_visitor<bool> { + Strategy const& m_strategy; + + visitor(Strategy const& strategy) + : m_strategy(strategy) + {} + template <typename Geometry1, typename Geometry2> bool operator()(Geometry1 const& geometry1, Geometry2 const& geometry2) const { - return touches<Geometry1, Geometry2>::apply(geometry1, geometry2); + return touches<Geometry1, Geometry2>::apply(geometry1, geometry2, m_strategy); } }; - static inline bool - apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)> const& geometry1, - boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)> const& geometry2) + template <typename Strategy> + static inline bool apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)> const& geometry1, + boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)> const& geometry2, + Strategy const& strategy) { - return boost::apply_visitor(visitor(), geometry1, geometry2); + return boost::apply_visitor(visitor<Strategy>(strategy), geometry1, geometry2); } }; @@ -496,6 +583,10 @@ struct self_touches { concepts::check<Geometry const>(); + typedef typename strategy::relate::services::default_strategy + < + Geometry, Geometry + >::type strategy_type; typedef detail::no_rescale_policy rescale_policy_type; typedef typename geometry::point_type<Geometry>::type point_type; typedef detail::overlay::turn_info @@ -511,11 +602,12 @@ struct self_touches std::deque<turn_info> turns; detail::touches::areal_interrupt_policy policy; + strategy_type strategy; rescale_policy_type robust_policy; detail::self_get_turn_points::get_turns < policy_type - >::apply(geometry, robust_policy, turns, policy); + >::apply(geometry, strategy, robust_policy, turns, policy); return policy.result(); } @@ -578,7 +670,35 @@ inline bool touches(Geometry const& geometry) template <typename Geometry1, typename Geometry2> inline bool touches(Geometry1 const& geometry1, Geometry2 const& geometry2) { - return resolve_variant::touches<Geometry1, Geometry2>::apply(geometry1, geometry2); + return resolve_variant::touches + < + Geometry1, Geometry2 + >::apply(geometry1, geometry2, default_strategy()); +} + +/*! +\brief \brief_check2{have at least one touching point (tangent - non overlapping)} +\ingroup touches +\tparam Geometry1 \tparam_geometry +\tparam Geometry2 \tparam_geometry +\tparam Strategy \tparam_strategy{Touches} +\param geometry1 \param_geometry +\param geometry2 \param_geometry +\param strategy \param_strategy{touches} +\return \return_check2{touch each other} + +\qbk{distinguish,with strategy} +\qbk{[include reference/algorithms/touches.qbk]} + */ +template <typename Geometry1, typename Geometry2, typename Strategy> +inline bool touches(Geometry1 const& geometry1, + Geometry2 const& geometry2, + Strategy const& strategy) +{ + return resolve_variant::touches + < + Geometry1, Geometry2 + >::apply(geometry1, geometry2, strategy); } diff --git a/boost/geometry/algorithms/union.hpp b/boost/geometry/algorithms/union.hpp index f0e55ec981..d3a2daf66e 100644 --- a/boost/geometry/algorithms/union.hpp +++ b/boost/geometry/algorithms/union.hpp @@ -2,10 +2,11 @@ // Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands. -// This file was modified by Oracle on 2014. -// Modifications copyright (c) 2014 Oracle and/or its affiliates. +// This file was modified by Oracle on 2014, 2017. +// Modifications copyright (c) 2014-2017 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 // Use, modification and distribution is subject to the Boost Software License, // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at @@ -24,6 +25,8 @@ #include <boost/geometry/algorithms/not_implemented.hpp> #include <boost/geometry/algorithms/detail/overlay/overlay.hpp> #include <boost/geometry/policies/robustness/get_rescale_policy.hpp> +#include <boost/geometry/strategies/default_strategy.hpp> +#include <boost/geometry/util/range.hpp> #include <boost/geometry/algorithms/detail/overlay/linear_linear.hpp> #include <boost/geometry/algorithms/detail/overlay/pointlike_pointlike.hpp> @@ -214,14 +217,10 @@ inline OutputIterator union_insert(Geometry1 const& geometry1, Geometry2 >::type rescale_policy_type; - typedef intersection_strategies + typename strategy::intersection::services::default_strategy < - typename cs_tag<GeometryOut>::type, - Geometry1, - Geometry2, - typename geometry::point_type<GeometryOut>::type, - rescale_policy_type - > strategy; + typename cs_tag<GeometryOut>::type + >::type strategy; rescale_policy_type robust_policy = geometry::get_rescale_policy<rescale_policy_type>(geometry1, geometry2); @@ -229,7 +228,7 @@ inline OutputIterator union_insert(Geometry1 const& geometry1, return dispatch::union_insert < Geometry1, Geometry2, GeometryOut - >::apply(geometry1, geometry2, robust_policy, out, strategy()); + >::apply(geometry1, geometry2, robust_policy, out, strategy); } @@ -237,6 +236,228 @@ inline OutputIterator union_insert(Geometry1 const& geometry1, #endif // DOXYGEN_NO_DETAIL +namespace resolve_strategy { + +struct union_ +{ + template + < + typename Geometry1, + typename Geometry2, + typename RobustPolicy, + typename Collection, + typename Strategy + > + static inline void apply(Geometry1 const& geometry1, + Geometry2 const& geometry2, + RobustPolicy const& robust_policy, + Collection & output_collection, + Strategy const& strategy) + { + typedef typename boost::range_value<Collection>::type geometry_out; + + dispatch::union_insert + < + Geometry1, Geometry2, geometry_out + >::apply(geometry1, geometry2, robust_policy, + range::back_inserter(output_collection), + strategy); + } + + template + < + typename Geometry1, + typename Geometry2, + typename RobustPolicy, + typename Collection + > + static inline void apply(Geometry1 const& geometry1, + Geometry2 const& geometry2, + RobustPolicy const& robust_policy, + Collection & output_collection, + default_strategy) + { + typedef typename boost::range_value<Collection>::type geometry_out; + + typedef typename strategy::intersection::services::default_strategy + < + typename cs_tag<geometry_out>::type + >::type strategy_type; + + dispatch::union_insert + < + Geometry1, Geometry2, geometry_out + >::apply(geometry1, geometry2, robust_policy, + range::back_inserter(output_collection), + strategy_type()); + } +}; + +} // resolve_strategy + + +namespace resolve_variant +{ + +template <typename Geometry1, typename Geometry2> +struct union_ +{ + template <typename Collection, typename Strategy> + static inline void apply(Geometry1 const& geometry1, + Geometry2 const& geometry2, + Collection& output_collection, + Strategy const& strategy) + { + concepts::check<Geometry1 const>(); + concepts::check<Geometry2 const>(); + concepts::check<typename boost::range_value<Collection>::type>(); + + typedef typename geometry::rescale_overlay_policy_type + < + Geometry1, + Geometry2 + >::type rescale_policy_type; + + rescale_policy_type robust_policy + = geometry::get_rescale_policy<rescale_policy_type>(geometry1, + geometry2); + + resolve_strategy::union_::apply(geometry1, geometry2, + robust_policy, + output_collection, + strategy); + } +}; + + +template <BOOST_VARIANT_ENUM_PARAMS(typename T), typename Geometry2> +struct union_<variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Geometry2> +{ + template <typename Collection, typename Strategy> + struct visitor: static_visitor<> + { + Geometry2 const& m_geometry2; + Collection& m_output_collection; + Strategy const& m_strategy; + + visitor(Geometry2 const& geometry2, + Collection& output_collection, + Strategy const& strategy) + : m_geometry2(geometry2) + , m_output_collection(output_collection) + , m_strategy(strategy) + {} + + template <typename Geometry1> + void operator()(Geometry1 const& geometry1) const + { + union_ + < + Geometry1, + Geometry2 + >::apply(geometry1, m_geometry2, m_output_collection, m_strategy); + } + }; + + template <typename Collection, typename Strategy> + static inline void + apply(variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry1, + Geometry2 const& geometry2, + Collection& output_collection, + Strategy const& strategy) + { + boost::apply_visitor(visitor<Collection, Strategy>(geometry2, + output_collection, + strategy), + geometry1); + } +}; + + +template <typename Geometry1, BOOST_VARIANT_ENUM_PARAMS(typename T)> +struct union_<Geometry1, variant<BOOST_VARIANT_ENUM_PARAMS(T)> > +{ + template <typename Collection, typename Strategy> + struct visitor: static_visitor<> + { + Geometry1 const& m_geometry1; + Collection& m_output_collection; + Strategy const& m_strategy; + + visitor(Geometry1 const& geometry1, + Collection& output_collection, + Strategy const& strategy) + : m_geometry1(geometry1) + , m_output_collection(output_collection) + , m_strategy(strategy) + {} + + template <typename Geometry2> + void operator()(Geometry2 const& geometry2) const + { + union_ + < + Geometry1, + Geometry2 + >::apply(m_geometry1, geometry2, m_output_collection, m_strategy); + } + }; + + template <typename Collection, typename Strategy> + static inline void + apply(Geometry1 const& geometry1, + variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry2, + Collection& output_collection, + Strategy const& strategy) + { + boost::apply_visitor(visitor<Collection, Strategy>(geometry1, + output_collection, + strategy), + geometry2); + } +}; + + +template <BOOST_VARIANT_ENUM_PARAMS(typename T1), BOOST_VARIANT_ENUM_PARAMS(typename T2)> +struct union_<variant<BOOST_VARIANT_ENUM_PARAMS(T1)>, variant<BOOST_VARIANT_ENUM_PARAMS(T2)> > +{ + template <typename Collection, typename Strategy> + struct visitor: static_visitor<> + { + Collection& m_output_collection; + Strategy const& m_strategy; + + visitor(Collection& output_collection, Strategy const& strategy) + : m_output_collection(output_collection) + , m_strategy(strategy) + {} + + template <typename Geometry1, typename Geometry2> + void operator()(Geometry1 const& geometry1, + Geometry2 const& geometry2) const + { + union_ + < + Geometry1, + Geometry2 + >::apply(geometry1, geometry2, m_output_collection, m_strategy); + } + }; + + template <typename Collection, typename Strategy> + static inline void + apply(variant<BOOST_VARIANT_ENUM_PARAMS(T1)> const& geometry1, + variant<BOOST_VARIANT_ENUM_PARAMS(T2)> const& geometry2, + Collection& output_collection, + Strategy const& strategy) + { + boost::apply_visitor(visitor<Collection, Strategy>(output_collection, + strategy), + geometry1, geometry2); + } +}; + +} // namespace resolve_variant /*! @@ -247,31 +468,66 @@ inline OutputIterator union_insert(Geometry1 const& geometry1, \tparam Geometry2 \tparam_geometry \tparam Collection output collection, either a multi-geometry, or a std::vector<Geometry> / std::deque<Geometry> etc +\tparam Strategy \tparam_strategy{Union_} \param geometry1 \param_geometry \param geometry2 \param_geometry \param output_collection the output collection +\param strategy \param_strategy{union_} \note Called union_ because union is a reserved word. +\qbk{distinguish,with strategy} \qbk{[include reference/algorithms/union.qbk]} */ template < typename Geometry1, typename Geometry2, - typename Collection + typename Collection, + typename Strategy > inline void union_(Geometry1 const& geometry1, - Geometry2 const& geometry2, - Collection& output_collection) + Geometry2 const& geometry2, + Collection& output_collection, + Strategy const& strategy) { - concepts::check<Geometry1 const>(); - concepts::check<Geometry2 const>(); + resolve_variant::union_ + < + Geometry1, + Geometry2 + >::apply(geometry1, geometry2, output_collection, strategy); +} - typedef typename boost::range_value<Collection>::type geometry_out; - concepts::check<geometry_out>(); - detail::union_::union_insert<geometry_out>(geometry1, geometry2, - range::back_inserter(output_collection)); +/*! +\brief Combines two geometries which each other +\ingroup union +\details \details_calc2{union, spatial set theoretic union}. +\tparam Geometry1 \tparam_geometry +\tparam Geometry2 \tparam_geometry +\tparam Collection output collection, either a multi-geometry, + or a std::vector<Geometry> / std::deque<Geometry> etc +\param geometry1 \param_geometry +\param geometry2 \param_geometry +\param output_collection the output collection +\note Called union_ because union is a reserved word. + +\qbk{[include reference/algorithms/union.qbk]} +*/ +template +< + typename Geometry1, + typename Geometry2, + typename Collection +> +inline void union_(Geometry1 const& geometry1, + Geometry2 const& geometry2, + Collection& output_collection) +{ + resolve_variant::union_ + < + Geometry1, + Geometry2 + >::apply(geometry1, geometry2, output_collection, default_strategy()); } diff --git a/boost/geometry/algorithms/within.hpp b/boost/geometry/algorithms/within.hpp index a1e6a58f8d..ba170dd27b 100644 --- a/boost/geometry/algorithms/within.hpp +++ b/boost/geometry/algorithms/within.hpp @@ -4,8 +4,10 @@ // Copyright (c) 2008-2012 Bruno Lalande, Paris, France. // Copyright (c) 2009-2012 Mateusz Loskot, London, UK. -// This file was modified by Oracle on 2013, 2014. -// Modifications copyright (c) 2013, 2014 Oracle and/or its affiliates. +// This file was modified by Oracle on 2013, 2014, 2017. +// Modifications copyright (c) 2013-2017 Oracle and/or its affiliates. + +// 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. @@ -14,8 +16,6 @@ // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) -// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle - #ifndef BOOST_GEOMETRY_ALGORITHMS_WITHIN_HPP #define BOOST_GEOMETRY_ALGORITHMS_WITHIN_HPP @@ -52,6 +52,7 @@ #include <boost/geometry/views/reversible_view.hpp> #include <boost/geometry/algorithms/detail/within/point_in_geometry.hpp> +#include <boost/geometry/algorithms/relate.hpp> #include <boost/geometry/algorithms/detail/overlay/get_turns.hpp> #include <boost/geometry/algorithms/detail/overlay/do_reverse.hpp> @@ -75,9 +76,13 @@ struct use_point_in_geometry struct use_relate { template <typename Geometry1, typename Geometry2, typename Strategy> - static inline bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2, Strategy const& /*strategy*/) + static inline bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2, Strategy const& strategy) { - return Strategy::apply(geometry1, geometry2); + typedef typename detail::de9im::static_mask_within_type + < + Geometry1, Geometry2 + >::type within_mask; + return geometry::relate(geometry1, geometry2, within_mask(), strategy); } }; @@ -300,23 +305,8 @@ struct within Geometry2 const& geometry2, default_strategy) { - typedef typename point_type<Geometry1>::type point_type1; - typedef typename point_type<Geometry2>::type point_type2; - typedef typename strategy::within::services::default_strategy < - typename tag<Geometry1>::type, - typename tag<Geometry2>::type, - typename tag<Geometry1>::type, - typename tag_cast<typename tag<Geometry2>::type, areal_tag>::type, - typename tag_cast - < - typename cs_tag<point_type1>::type, spherical_tag - >::type, - typename tag_cast - < - typename cs_tag<point_type2>::type, spherical_tag - >::type, Geometry1, Geometry2 >::type strategy_type; @@ -517,8 +507,9 @@ inline bool within(Geometry1 const& geometry1, Geometry2 const& geometry2) } */ template<typename Geometry1, typename Geometry2, typename Strategy> -inline bool within(Geometry1 const& geometry1, Geometry2 const& geometry2, - Strategy const& strategy) +inline bool within(Geometry1 const& geometry1, + Geometry2 const& geometry2, + Strategy const& strategy) { return resolve_variant::within < |