diff --git a/.github/workflows/minimal-clang.yml b/.github/workflows/minimal-clang.yml index cceca7af6..b772f0b5b 100644 --- a/.github/workflows/minimal-clang.yml +++ b/.github/workflows/minimal-clang.yml @@ -92,8 +92,11 @@ jobs: - name: Install run: | - sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 15CF4D18AF4F7421 - sudo add-apt-repository "deb http://apt.llvm.org/bionic/ llvm-toolchain-bionic-10 main" + # Required for compilers not available in ubuntu latest + sudo add-apt-repository "deb http://dk.archive.ubuntu.com/ubuntu/ xenial main" + sudo add-apt-repository "deb http://dk.archive.ubuntu.com/ubuntu/ xenial universe" + sudo add-apt-repository "deb http://dk.archive.ubuntu.com/ubuntu/ bionic main" + sudo add-apt-repository "deb http://dk.archive.ubuntu.com/ubuntu/ bionic universe" sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test sudo apt -q -y update sudo apt -q -y install clang-${{ matrix.version }} g++-multilib diff --git a/.github/workflows/minimal-gcc.yml b/.github/workflows/minimal-gcc.yml index 72e8288ab..f08521486 100644 --- a/.github/workflows/minimal-gcc.yml +++ b/.github/workflows/minimal-gcc.yml @@ -80,9 +80,11 @@ jobs: - name: Install run: | - # gcc-4.8 is not available in Bionic anymore + # Required for compilers not available in ubuntu latest sudo add-apt-repository "deb http://dk.archive.ubuntu.com/ubuntu/ xenial main" sudo add-apt-repository "deb http://dk.archive.ubuntu.com/ubuntu/ xenial universe" + sudo add-apt-repository "deb http://dk.archive.ubuntu.com/ubuntu/ bionic main" + sudo add-apt-repository "deb http://dk.archive.ubuntu.com/ubuntu/ bionic universe" sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test sudo apt -q -y update sudo apt -q -y install g++-${{ matrix.version }} g++-${{ matrix.version }}-multilib diff --git a/README.md b/README.md index 3470ac8c4..f8350de1a 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # ![Boost.Geometry](doc/other/logo/logo_bkg.png) -Boost.Geometry, part of collection of the [Boost C++ Libraries](http://github.com/boostorg), defines concepts, primitives and algorithms for solving geometry problems. +Boost.Geometry, part of collection of the [Boost C++ Libraries](http://github.com/boostorg), defines concepts, primitives and algorithms for solving geometry problems. Boost.Geometry is a C++14 header-only library. [![Licence](https://img.shields.io/badge/license-boost-4480cc.png)](http://www.boost.org/LICENSE_1_0.txt) [![Documentation](https://img.shields.io/badge/-documentation-4480cc.png)](http://boost.org/libs/geometry) diff --git a/doc/doxy/doxygen_input/groups/groups.hpp b/doc/doxy/doxygen_input/groups/groups.hpp index 1caf7cf63..d2659b561 100644 --- a/doc/doxy/doxygen_input/groups/groups.hpp +++ b/doc/doxy/doxygen_input/groups/groups.hpp @@ -2,8 +2,8 @@ // // Copyright (c) 2011-2012 Barend Gehrels, Amsterdam, the Netherlands. -// This file was modified by Oracle on 2018. -// Modifications copyright (c) 2018, Oracle and/or its affiliates. +// This file was modified by Oracle on 2018-2021. +// Modifications copyright (c) 2018-2021, 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 @@ -20,6 +20,7 @@ \defgroup area area: calculate area of a Geometry \defgroup arithmetic arithmetic: arithmetic operations on points \defgroup assign assign: assign values to geometries +\defgroup azimuth azimuth: calculate azimuth of a segment defined by a pair of points \defgroup buffer buffer: calculate buffer of a geometry \defgroup centroid centroid: calculate centroid (center of gravity) of a geometry \defgroup clear clear: clear geometries diff --git a/doc/imports.qbk b/doc/imports.qbk index a184f1513..a5fdacf08 100644 --- a/doc/imports.qbk +++ b/doc/imports.qbk @@ -5,7 +5,7 @@ Copyright (c) 2009-2012 Mateusz Loskot, London, UK. Copyright (c) 2009-2012 Bruno Lalande, Paris, France. - Copyright (c) 2018, Oracle and/or its affiliates. + Copyright (c) 2018-2021, 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 @@ -24,6 +24,8 @@ [import src/examples/algorithms/assign_3d_point.cpp] [import src/examples/algorithms/assign_inverse.cpp] [import src/examples/algorithms/assign_points.cpp] +[import src/examples/algorithms/azimuth.cpp] +[import src/examples/algorithms/azimuth_strategy.cpp] [import src/examples/algorithms/buffer_with_strategies.cpp] [import src/examples/algorithms/clear.cpp] [import src/examples/algorithms/centroid.cpp] diff --git a/doc/make_qbk.py b/doc/make_qbk.py index 8a5cb6100..f4d7881e3 100755 --- a/doc/make_qbk.py +++ b/doc/make_qbk.py @@ -6,7 +6,7 @@ # Copyright (c) 2009-2012 Mateusz Loskot (mateusz@loskot.net), London, UK # Copyright (c) 2017 Adam Wulkiewicz, Lodz, Poland # -# Copyright (c) 2018, Oracle and/or its affiliates. +# Copyright (c) 2018-2021, 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, @@ -96,7 +96,7 @@ def cs_to_quickbook(section): call_doxygen() algorithms = ["append", "assign", "make", "clear" - , "area", "buffer", "centroid", "convert", "correct", "covered_by" + , "area", "azimuth", "buffer", "centroid", "convert", "correct", "covered_by" , "convex_hull", "crosses", "densify", "difference" , "discrete_frechet_distance", "discrete_hausdorff_distance", "disjoint" , "distance", "envelope", "equals", "expand", "for_each", "is_empty" diff --git a/doc/quickref.xml b/doc/quickref.xml index bad6b5097..092a7f2ae 100644 --- a/doc/quickref.xml +++ b/doc/quickref.xml @@ -364,6 +364,10 @@ coordinate values) + Azimuth + + azimuth + Buffer buffer diff --git a/doc/reference.qbk b/doc/reference.qbk index aa0be56c0..a9270a5fb 100644 --- a/doc/reference.qbk +++ b/doc/reference.qbk @@ -6,8 +6,8 @@ Copyright (c) 2009-2017 Bruno Lalande, Paris, France. Copyright (c) 2013-2017 Adam Wulkiewicz, Lodz, Poland. - This file was modified by Oracle on 2014, 2017, 2018. - Modifications copyright (c) 2014-2018, Oracle and/or its affiliates. + This file was modified by Oracle on 2014-2021. + Modifications copyright (c) 2014-2021, 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 @@ -80,6 +80,10 @@ [include generated/append.qbk] +[section:azimuth azimuth] +[include generated/azimuth.qbk] +[endsect] + [section:buffer buffer] [include generated/buffer.qbk] [endsect] diff --git a/doc/reference/algorithms/azimuth.qbk b/doc/reference/algorithms/azimuth.qbk new file mode 100644 index 000000000..5b2606661 --- /dev/null +++ b/doc/reference/algorithms/azimuth.qbk @@ -0,0 +1,22 @@ +[/============================================================================ + Boost.Geometry + + Copyright (c) 2021, 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) +=============================================================================/] + +[def __this_function__ azimuth] + +[heading_conformance_no_ogc __this_function__] +[note PostGIS contains an algorithm ST_Azimuth with the same functionality. + See the [@https://postgis.net/docs/ST_Azimuth.html PostGIS documentation]. +] + +[heading Behavior] +The algorithm calculates the azimuth of a segment defined by a pair of points. + +[note The result is in radians.] diff --git a/doc/src/examples/algorithms/azimuth.cpp b/doc/src/examples/algorithms/azimuth.cpp new file mode 100644 index 000000000..0f799920a --- /dev/null +++ b/doc/src/examples/algorithms/azimuth.cpp @@ -0,0 +1,42 @@ +// Boost.Geometry +// QuickBook Example + +// Copyright (c) 2021, 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) + +//[azimuth +//` Shows how to calculate azimuth + +#include + +#include +#include + +int main() +{ + typedef boost::geometry::model::d2::point_xy point_type; + + point_type p1(0, 0); + point_type p2(1, 1); + + auto azimuth = boost::geometry::azimuth(p1, p2); + + std::cout << "azimuth: " << azimuth << std::endl; + + return 0; +} + +//] + +//[azimuth_output +/*` +Output: +[pre +azimuth: 0.785398 +] +*/ +//] diff --git a/doc/src/examples/algorithms/azimuth_strategy.cpp b/doc/src/examples/algorithms/azimuth_strategy.cpp new file mode 100644 index 000000000..2a8ef5178 --- /dev/null +++ b/doc/src/examples/algorithms/azimuth_strategy.cpp @@ -0,0 +1,46 @@ +// Boost.Geometry +// QuickBook Example + +// Copyright (c) 2021, 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) + +//[azimuth_strategy +//` Shows how to calculate azimuth in geographic coordinate system + +#include + +#include +#include + +int main() +{ + namespace bg = boost::geometry; + typedef bg::model::point > point_type; + + point_type p1(0, 0); + point_type p2(1, 1); + + bg::srs::spheroid spheroid(6378137.0, 6356752.3142451793); + bg::strategies::azimuth::geographic<> strategy(spheroid); + + auto azimuth = boost::geometry::azimuth(p1, p2, strategy); + + std::cout << "azimuth: " << azimuth << std::endl; + + return 0; +} + +//] + +//[azimuth_strategy_output +/*` +Output: +[pre +azimuth: 0.788674 +] +*/ +//] diff --git a/example/05_b_overlay_linestring_polygon_example.cpp b/example/05_b_overlay_linestring_polygon_example.cpp index 38349decb..f37165f3e 100644 --- a/example/05_b_overlay_linestring_polygon_example.cpp +++ b/example/05_b_overlay_linestring_polygon_example.cpp @@ -67,12 +67,13 @@ int main(void) #endif // Calculate intersection points (turn points) - typedef bg::segment_ratio_type::type segment_ratio; + typedef bg::detail::segment_ratio_type::type segment_ratio; typedef bg::detail::overlay::turn_info turn_info; std::vector turns; bg::detail::get_turns::no_interrupt_policy policy; bg::detail::no_rescale_policy rescale_policy; - bg::get_turns(ls, p, rescale_policy, turns, policy); + bg::strategy::intersection::services::default_strategy::type>::type intersection_strategy; + bg::get_turns(ls, p, intersection_strategy, rescale_policy, turns, policy); std::cout << "Intersection of linestring/polygon" << std::endl; BOOST_FOREACH(turn_info const& turn, turns) diff --git a/example/c05_custom_point_pointer_example.cpp b/example/c05_custom_point_pointer_example.cpp index d8059fe04..a1d9dbef0 100644 --- a/example/c05_custom_point_pointer_example.cpp +++ b/example/c05_custom_point_pointer_example.cpp @@ -102,10 +102,11 @@ int main() // This works because outputs to a normal struct point, no point* typedef boost::geometry::model::linestring linestring_2d; + boost::geometry::detail::no_rescale_policy rescale_policy; std::vector clipped; boost::geometry::strategy::intersection::liang_barsky strategy; boost::geometry::detail::intersection::clip_range_with_box(cb, - myline, std::back_inserter(clipped), strategy); + myline, rescale_policy, std::back_inserter(clipped), strategy); std::cout << boost::geometry::length(clipped.front()) << std::endl; diff --git a/example/c08_custom_non_std_example.cpp b/example/c08_custom_non_std_example.cpp index 0a545a3de..12bb76840 100644 --- a/example/c08_custom_non_std_example.cpp +++ b/example/c08_custom_non_std_example.cpp @@ -281,7 +281,7 @@ int main() // Create (as an example) a regular polygon const int n = 5; - const double d = (360 / n) * boost::geometry::math::d2r; + const double d = (360 / n) * boost::geometry::math::d2r(); double a = 0; for (int i = 0; i < n + 1; i++, a += d) { diff --git a/include/boost/geometry/algorithms/azimuth.hpp b/include/boost/geometry/algorithms/azimuth.hpp new file mode 100644 index 000000000..2e97eed2f --- /dev/null +++ b/include/boost/geometry/algorithms/azimuth.hpp @@ -0,0 +1,226 @@ +// Boost.Geometry + +// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. + +// This file was modified by Oracle on 2014-2021. +// Modifications copyright (c) 2014-2021, 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, +// 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_AZIMUTH_HPP +#define BOOST_GEOMETRY_ALGORITHMS_AZIMUTH_HPP + + +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include + + +namespace boost { namespace geometry +{ + + +#ifndef DOXYGEN_NO_DETAIL +namespace detail +{ + +} // namespace detail +#endif // DOXYGEN_NO_DETAIL + + +#ifndef DOXYGEN_NO_DISPATCH +namespace dispatch +{ + +template +< + typename Geometry1, typename Geometry2, + typename Tag1 = typename tag::type, + typename Tag2 = typename tag::type +> +struct azimuth : not_implemented +{}; + +template +struct azimuth +{ + template + static auto apply(Point1 const& p1, Point2 const& p2, Strategy const& strategy) + { + typedef typename decltype(strategy.azimuth())::template result_type + < + typename coordinate_type::type, + typename coordinate_type::type + >::type calc_t; + + calc_t result = 0; + calc_t const x1 = geometry::get_as_radian<0>(p1); + calc_t const y1 = geometry::get_as_radian<1>(p1); + calc_t const x2 = geometry::get_as_radian<0>(p2); + calc_t const y2 = geometry::get_as_radian<1>(p2); + + strategy.azimuth().apply(x1, y1, x2, y2, result); + + // NOTE: It is not clear which units we should use for the result. + // For now radians are always returned but a user could expect + // e.g. something like this: + /* + bool const both_degree = std::is_same + < + typename detail::cs_angular_units::type, + geometry::degree + >::value + && std::is_same + < + typename detail::cs_angular_units::type, + geometry::degree + >::value; + if (both_degree) + { + result *= math::r2d(); + } + */ + + return result; + } +}; + +} // namespace dispatch +#endif // DOXYGEN_NO_DISPATCH + + +namespace resolve_strategy +{ + +template +< + typename Strategy, + bool IsUmbrella = strategies::detail::is_umbrella_strategy::value +> +struct azimuth +{ + template + static auto apply(P1 const& p1, P2 const& p2, Strategy const& strategy) + { + return dispatch::azimuth::apply(p1, p2, strategy); + } +}; + +template +struct azimuth +{ + template + static auto apply(P1 const& p1, P2 const& p2, Strategy const& strategy) + { + using strategies::azimuth::services::strategy_converter; + return dispatch::azimuth + < + P1, P2 + >::apply(p1, p2, strategy_converter::get(strategy)); + } +}; + +template <> +struct azimuth +{ + template + static auto apply(P1 const& p1, P2 const& p2, default_strategy) + { + typedef typename strategies::azimuth::services::default_strategy + < + P1, P2 + >::type strategy_type; + + return dispatch::azimuth::apply(p1, p2, strategy_type()); + } +}; + + +} // namespace resolve_strategy + + +namespace resolve_variant +{ +} // namespace resolve_variant + + +/*! +\brief Calculate azimuth of a segment defined by a pair of points. +\ingroup azimuth +\tparam Point1 Type of the first point of a segment. +\tparam Point2 Type of the second point of a segment. +\param point1 First point of a segment. +\param point2 Second point of a segment. +\return Azimuth in radians. + +\qbk{[include reference/algorithms/azimuth.qbk]} + +\qbk{ +[heading Example] +[azimuth] +[azimuth_output] +} +*/ +template +inline auto azimuth(Point1 const& point1, Point2 const& point2) +{ + concepts::check(); + concepts::check(); + + return resolve_strategy::azimuth + < + default_strategy + >::apply(point1, point2, default_strategy()); +} + + +/*! +\brief Calculate azimuth of a segment defined by a pair of points. +\ingroup azimuth +\tparam Point1 Type of the first point of a segment. +\tparam Point2 Type of the second point of a segment. +\tparam Strategy Type of an umbrella strategy defining azimuth strategy. +\param point1 First point of a segment. +\param point2 Second point of a segment. +\param strategy Umbrella strategy defining azimuth strategy. +\return Azimuth in radians. + +\qbk{distinguish,with strategy} +\qbk{[include reference/algorithms/azimuth.qbk]} + +\qbk{ +[heading Example] +[azimuth_strategy] +[azimuth_strategy_output] +} +*/ +template +inline auto azimuth(Point1 const& point1, Point2 const& point2, Strategy const& strategy) +{ + concepts::check(); + concepts::check(); + + return resolve_strategy::azimuth::apply(point1, point2, strategy); +} + + +}} // namespace boost::geometry + + +#endif // BOOST_GEOMETRY_ALGORITHMS_AZIMUTH_HPP diff --git a/include/boost/geometry/algorithms/buffer.hpp b/include/boost/geometry/algorithms/buffer.hpp index 3bf6d2fa5..453b14873 100644 --- a/include/boost/geometry/algorithms/buffer.hpp +++ b/include/boost/geometry/algorithms/buffer.hpp @@ -4,8 +4,8 @@ // Copyright (c) 2008-2012 Bruno Lalande, Paris, France. // Copyright (c) 2009-2012 Mateusz Loskot, London, UK. -// This file was modified by Oracle on 2017-2020. -// Modifications copyright (c) 2017-2020 Oracle and/or its affiliates. +// This file was modified by Oracle on 2017-2021. +// Modifications copyright (c) 2017-2021 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 @@ -242,22 +242,23 @@ 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 strategies::relate::services::default_strategy < - typename cs_tag::type - >::type intersection_strategy; + GeometryIn, GeometryIn + >::type strategies; rescale_policy_type rescale_policy = boost::geometry::get_rescale_policy( - box, intersection_strategy); + box, strategies); - detail::buffer::buffer_inserter(geometry_in, range::back_inserter(geometry_out), + detail::buffer::buffer_inserter(geometry_in, + range::back_inserter(geometry_out), distance_strategy, side_strategy, join_strategy, end_strategy, point_strategy, - intersection_strategy, + strategies, rescale_policy); } diff --git a/include/boost/geometry/algorithms/convex_hull.hpp b/include/boost/geometry/algorithms/convex_hull.hpp index 26bb8509e..d23f6a47f 100644 --- a/include/boost/geometry/algorithms/convex_hull.hpp +++ b/include/boost/geometry/algorithms/convex_hull.hpp @@ -4,11 +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 2014, 2015. -// Modifications copyright (c) 2014-2015 Oracle and/or its affiliates. +// This file was modified by Oracle on 2014, 2015, 2020. +// Modifications copyright (c) 2014-2020 Oracle and/or its affiliates. -// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle +// 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. @@ -20,356 +21,7 @@ #ifndef BOOST_GEOMETRY_ALGORITHMS_CONVEX_HULL_HPP #define BOOST_GEOMETRY_ALGORITHMS_CONVEX_HULL_HPP -#include - -#include -#include -#include - -#include -#include -#include -#include - -#include - -#include -#include -#include - -#include - -#include - -#include -#include -#include - - -namespace boost { namespace geometry -{ - - -#ifndef DOXYGEN_NO_DETAIL -namespace detail { namespace convex_hull -{ - -template -struct hull_insert -{ - - // Member template function (to avoid inconvenient declaration - // of output-iterator-type, from hull_to_geometry) - template - static inline OutputIterator apply(Geometry const& geometry, - OutputIterator out, Strategy const& strategy) - { - typename Strategy::state_type state; - - strategy.apply(geometry, state); - strategy.result(state, out, Order == clockwise, Closure != open); - return out; - } -}; - -struct hull_to_geometry -{ - template - static inline void apply(Geometry const& geometry, OutputGeometry& out, - Strategy const& strategy) - { - hull_insert - < - geometry::point_order::value, - geometry::closure::value - >::apply(geometry, - range::back_inserter( - // Handle linestring, ring and polygon the same: - detail::as_range - < - typename range_type::type - >(out)), strategy); - } -}; - -}} // namespace detail::convex_hull -#endif // DOXYGEN_NO_DETAIL - - -#ifndef DOXYGEN_NO_DISPATCH -namespace dispatch -{ - - -template -< - typename Geometry, - typename Tag = typename tag::type -> -struct convex_hull - : detail::convex_hull::hull_to_geometry -{}; - -template -struct convex_hull -{ - template - static inline void apply(Box const& box, OutputGeometry& out, - Strategy const& ) - { - static bool const Close - = geometry::closure::value == closed; - static bool const Reverse - = geometry::point_order::value == counterclockwise; - - // A hull for boxes is trivial. Any strategy is (currently) skipped. - boost::array::type, 4> range; - geometry::detail::assign_box_corners_oriented(box, range); - geometry::append(out, range); - if (BOOST_GEOMETRY_CONDITION(Close)) - { - geometry::append(out, *boost::begin(range)); - } - } -}; - - - -template -struct convex_hull_insert - : detail::convex_hull::hull_insert -{}; - - -} // namespace dispatch -#endif // DOXYGEN_NO_DISPATCH - - -namespace resolve_strategy { - -struct convex_hull -{ - template - static inline void apply(Geometry const& geometry, - OutputGeometry& out, - Strategy const& strategy) - { - BOOST_CONCEPT_ASSERT( (geometry::concepts::ConvexHullStrategy) ); - dispatch::convex_hull::apply(geometry, out, strategy); - } - - template - static inline void apply(Geometry const& geometry, - OutputGeometry& out, - default_strategy) - { - typedef typename strategy_convex_hull< - Geometry, - typename point_type::type - >::type strategy_type; - - apply(geometry, out, strategy_type()); - } -}; - -struct convex_hull_insert -{ - template - static inline OutputIterator apply(Geometry const& geometry, - OutputIterator& out, - Strategy const& strategy) - { - BOOST_CONCEPT_ASSERT( (geometry::concepts::ConvexHullStrategy) ); - - return dispatch::convex_hull_insert< - geometry::point_order::value, - geometry::closure::value - >::apply(geometry, out, strategy); - } - - template - static inline OutputIterator apply(Geometry const& geometry, - OutputIterator& out, - default_strategy) - { - typedef typename strategy_convex_hull< - Geometry, - typename point_type::type - >::type strategy_type; - - return apply(geometry, out, strategy_type()); - } -}; - -} // namespace resolve_strategy - - -namespace resolve_variant { - -template -struct convex_hull -{ - template - static inline void apply(Geometry const& geometry, OutputGeometry& out, Strategy const& strategy) - { - concepts::check_concepts_and_equal_dimensions< - const Geometry, - OutputGeometry - >(); - - resolve_strategy::convex_hull::apply(geometry, out, strategy); - } -}; - -template -struct convex_hull > -{ - template - struct visitor: boost::static_visitor - { - OutputGeometry& m_out; - Strategy const& m_strategy; - - visitor(OutputGeometry& out, Strategy const& strategy) - : m_out(out), m_strategy(strategy) - {} - - template - void operator()(Geometry const& geometry) const - { - convex_hull::apply(geometry, m_out, m_strategy); - } - }; - - template - static inline void - apply(boost::variant const& geometry, - OutputGeometry& out, - Strategy const& strategy) - { - boost::apply_visitor(visitor(out, strategy), geometry); - } -}; - -template -struct convex_hull_insert -{ - template - static inline OutputIterator apply(Geometry const& geometry, OutputIterator& out, Strategy const& strategy) - { - // Concept: output point type = point type of input geometry - concepts::check(); - concepts::check::type>(); - - return resolve_strategy::convex_hull_insert::apply(geometry, out, strategy); - } -}; - -template -struct convex_hull_insert > -{ - template - struct visitor: boost::static_visitor - { - OutputIterator& m_out; - Strategy const& m_strategy; - - visitor(OutputIterator& out, Strategy const& strategy) - : m_out(out), m_strategy(strategy) - {} - - template - OutputIterator operator()(Geometry const& geometry) const - { - return convex_hull_insert::apply(geometry, m_out, m_strategy); - } - }; - - template - static inline OutputIterator - apply(boost::variant const& geometry, - OutputIterator& out, - Strategy const& strategy) - { - return boost::apply_visitor(visitor(out, strategy), geometry); - } -}; - -} // namespace resolve_variant - - -template -inline void convex_hull(Geometry const& geometry, - OutputGeometry& out, Strategy const& strategy) -{ - if (geometry::is_empty(geometry)) - { - // Leave output empty - return; - } - - resolve_variant::convex_hull::apply(geometry, out, strategy); -} - - -/*! -\brief \brief_calc{convex hull} -\ingroup convex_hull -\details \details_calc{convex_hull,convex hull}. -\tparam Geometry the input geometry type -\tparam OutputGeometry the output geometry type -\param geometry \param_geometry, input geometry -\param hull \param_geometry \param_set{convex hull} - -\qbk{[include reference/algorithms/convex_hull.qbk]} - */ -template -inline void convex_hull(Geometry const& geometry, - OutputGeometry& hull) -{ - geometry::convex_hull(geometry, hull, default_strategy()); -} - -#ifndef DOXYGEN_NO_DETAIL -namespace detail { namespace convex_hull -{ - - -template -inline OutputIterator convex_hull_insert(Geometry const& geometry, - OutputIterator out, Strategy const& strategy) -{ - return resolve_variant::convex_hull_insert - ::apply(geometry, out, strategy); -} - - -/*! -\brief Calculate the convex hull of a geometry, output-iterator version -\ingroup convex_hull -\tparam Geometry the input geometry type -\tparam OutputIterator: an output-iterator -\param geometry the geometry to calculate convex hull from -\param out an output iterator outputing points of the convex hull -\note This overloaded version outputs to an output iterator. -In this case, nothing is known about its point-type or - about its clockwise order. Therefore, the input point-type - and order are copied - - */ -template -inline OutputIterator convex_hull_insert(Geometry const& geometry, - OutputIterator out) -{ - return convex_hull_insert(geometry, out, default_strategy()); -} - - -}} // namespace detail::convex_hull -#endif // DOXYGEN_NO_DETAIL - - -}} // namespace boost::geometry - +#include +#include #endif // BOOST_GEOMETRY_ALGORITHMS_CONVEX_HULL_HPP diff --git a/include/boost/geometry/algorithms/crosses.hpp b/include/boost/geometry/algorithms/crosses.hpp index 6dcbdbe9d..c3656216a 100644 --- a/include/boost/geometry/algorithms/crosses.hpp +++ b/include/boost/geometry/algorithms/crosses.hpp @@ -5,8 +5,8 @@ // Copyright (c) 2009-2012 Mateusz Loskot, London, UK. // Copyright (c) 2014 Samuel Debionne, Grenoble, France. -// This file was modified by Oracle on 2014, 2017. -// Modifications copyright (c) 2014-2017 Oracle and/or its affiliates. +// This file was modified by Oracle on 2014-2020. +// Modifications copyright (c) 2014-2020 Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle @@ -31,6 +31,8 @@ #include #include #include +#include +#include namespace boost { namespace geometry @@ -65,9 +67,14 @@ struct crosses namespace resolve_strategy { +template +< + typename Strategy, + bool IsUmbrella = strategies::detail::is_umbrella_strategy::value +> struct crosses { - template + template static inline bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2, Strategy const& strategy) @@ -75,21 +82,50 @@ struct crosses concepts::check(); concepts::check(); - return dispatch::crosses::apply(geometry1, geometry2, strategy); + return dispatch::crosses + < + Geometry1, Geometry2 + >::apply(geometry1, geometry2, strategy); } +}; +template +struct crosses +{ + template + static inline bool apply(Geometry1 const& geometry1, + Geometry2 const& geometry2, + Strategy const& strategy) + { + //using strategies::crosses::services::strategy_converter; + using strategies::relate::services::strategy_converter; + return crosses + < + decltype(strategy_converter::get(strategy)) + >::apply(geometry1, geometry2, + strategy_converter::get(strategy)); + } +}; + +template <> +struct crosses +{ template static inline bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2, default_strategy) { - typedef typename strategy::relate::services::default_strategy + //typedef typename strategies::crosses::services::default_strategy + typedef typename strategies::relate::services::default_strategy < Geometry1, Geometry2 >::type strategy_type; - return apply(geometry1, geometry2, strategy_type()); + return crosses + < + strategy_type + >::apply(geometry1, geometry2, strategy_type()); } }; @@ -106,7 +142,10 @@ namespace resolve_variant Geometry2 const& geometry2, Strategy const& strategy) { - return resolve_strategy::crosses::apply(geometry1, geometry2, strategy); + return resolve_strategy::crosses + < + Strategy + >::apply(geometry1, geometry2, strategy); } }; diff --git a/include/boost/geometry/algorithms/detail/azimuth.hpp b/include/boost/geometry/algorithms/detail/azimuth.hpp deleted file mode 100644 index 21007778b..000000000 --- a/include/boost/geometry/algorithms/detail/azimuth.hpp +++ /dev/null @@ -1,152 +0,0 @@ -// Boost.Geometry (aka GGL, Generic Geometry Library) - -// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. - -// 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, -// 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_AZIMUTH_HPP -#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_AZIMUTH_HPP - - -#include - -#include -#include -#include -#include - -#include -#include - -#include - -#include - - -namespace boost { namespace geometry -{ - -// An azimuth is an angle between a vector/segment from origin to a point of -// interest and a reference vector. Typically north-based azimuth is used. -// North direction is used as a reference, angle is measured clockwise -// (North - 0deg, East - 90deg). For consistency in 2d cartesian CS -// the reference vector is Y axis, angle is measured clockwise. -// http://en.wikipedia.org/wiki/Azimuth - -#ifndef DOXYGEN_NO_DISPATCH -namespace detail_dispatch -{ - -template -struct azimuth - : not_implemented -{}; - -template -struct azimuth -{ - template - static inline ReturnType apply(P1 const& p1, P2 const& p2, Spheroid const& spheroid) - { - return geometry::formula::vincenty_inverse().apply - ( get_as_radian<0>(p1), get_as_radian<1>(p1), - get_as_radian<0>(p2), get_as_radian<1>(p2), - spheroid ).azimuth; - } - - template - static inline ReturnType apply(P1 const& p1, P2 const& p2) - { - return apply(p1, p2, srs::spheroid()); - } -}; - -template -struct azimuth -{ - template - static inline ReturnType apply(P1 const& p1, P2 const& p2, Sphere const& /*unused*/) - { - return geometry::formula::spherical_azimuth - ( get_as_radian<0>(p1), get_as_radian<1>(p1), - get_as_radian<0>(p2), get_as_radian<1>(p2)).azimuth; - } - - template - static inline ReturnType apply(P1 const& p1, P2 const& p2) - { - return apply(p1, p2, 0); // dummy model - } -}; - -template -struct azimuth - : azimuth -{}; - -template -struct azimuth -{ - template - static inline ReturnType apply(P1 const& p1, P2 const& p2, Plane const& /*unused*/) - { - ReturnType x = get<0>(p2) - get<0>(p1); - ReturnType y = get<1>(p2) - get<1>(p1); - - // NOTE: azimuth 0 is at Y axis, increasing right - // as in spherical/geographic where 0 is at North axis - return atan2(x, y); - } - - template - static inline ReturnType apply(P1 const& p1, P2 const& p2) - { - return apply(p1, p2, 0); // dummy model - } -}; - -} // detail_dispatch -#endif // DOXYGEN_NO_DISPATCH - -#ifndef DOXYGEN_NO_DETAIL -namespace detail -{ - -/// Calculate azimuth between two points. -/// The result is in radians. -template -inline ReturnType azimuth(Point1 const& p1, Point2 const& p2) -{ - return detail_dispatch::azimuth - < - ReturnType, - typename geometry::cs_tag::type - >::apply(p1, p2); -} - -/// Calculate azimuth between two points. -/// The result is in radians. -template -inline ReturnType azimuth(Point1 const& p1, Point2 const& p2, Model const& model) -{ - return detail_dispatch::azimuth - < - ReturnType, - typename geometry::cs_tag::type - >::apply(p1, p2, model); -} - -} // namespace detail -#endif // DOXYGEN_NO_DETAIL - -}} // namespace boost::geometry - -#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_AZIMUTH_HPP diff --git a/include/boost/geometry/algorithms/detail/buffer/buffer_inserter.hpp b/include/boost/geometry/algorithms/detail/buffer/buffer_inserter.hpp index 685fdba66..aefa6e7a6 100644 --- a/include/boost/geometry/algorithms/detail/buffer/buffer_inserter.hpp +++ b/include/boost/geometry/algorithms/detail/buffer/buffer_inserter.hpp @@ -2,8 +2,8 @@ // Copyright (c) 2012-2020 Barend Gehrels, Amsterdam, the Netherlands. -// This file was modified by Oracle on 2017-2020. -// Modifications copyright (c) 2017-2020 Oracle and/or its affiliates. +// This file was modified by Oracle on 2017-2021. +// Modifications copyright (c) 2017-2021 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, @@ -921,7 +921,7 @@ template typename JoinStrategy, typename EndStrategy, typename PointStrategy, - typename IntersectionStrategy, + typename Strategies, typename RobustPolicy, typename VisitPiecesPolicy > @@ -931,7 +931,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, + Strategies const& strategies, RobustPolicy const& robust_policy, VisitPiecesPolicy& visit_pieces_policy ) @@ -941,11 +941,11 @@ inline void buffer_inserter(GeometryInput const& geometry_input, OutputIterator typedef detail::buffer::buffered_piece_collection < typename geometry::ring_type::type, - IntersectionStrategy, + Strategies, DistanceStrategy, RobustPolicy > collection_type; - collection_type collection(intersection_strategy, distance_strategy, robust_policy); + collection_type collection(strategies, distance_strategy, robust_policy); collection_type const& const_collection = collection; bool const areal = util::is_areal::value; @@ -962,7 +962,7 @@ inline void buffer_inserter(GeometryInput const& geometry_input, OutputIterator >::apply(geometry_input, collection, distance_strategy, side_strategy, join_strategy, end_strategy, point_strategy, - robust_policy, intersection_strategy.get_side_strategy()); + robust_policy, strategies.side()); // pass strategies? collection.get_turns(); if (BOOST_GEOMETRY_CONDITION(areal)) @@ -1029,7 +1029,7 @@ template typename JoinStrategy, typename EndStrategy, typename PointStrategy, - typename IntersectionStrategy, + typename Strategies, typename RobustPolicy > inline void buffer_inserter(GeometryInput const& geometry_input, OutputIterator out, @@ -1038,14 +1038,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, + Strategies const& strategies, RobustPolicy const& robust_policy) { detail::buffer::visit_pieces_default_policy visitor; buffer_inserter(geometry_input, out, distance_strategy, side_strategy, join_strategy, end_strategy, point_strategy, - intersection_strategy, robust_policy, visitor); + strategies, robust_policy, visitor); } #endif // DOXYGEN_NO_DETAIL diff --git a/include/boost/geometry/algorithms/detail/buffer/buffer_policies.hpp b/include/boost/geometry/algorithms/detail/buffer/buffer_policies.hpp index 7f865ecc0..05d5c6fda 100644 --- a/include/boost/geometry/algorithms/detail/buffer/buffer_policies.hpp +++ b/include/boost/geometry/algorithms/detail/buffer/buffer_policies.hpp @@ -193,30 +193,37 @@ struct buffer_less } }; +template struct piece_get_box { + explicit piece_get_box(Strategy const& strategy) + : m_strategy(strategy) + {} + template - static inline void apply(Box& total, Piece const& piece) + inline void apply(Box& total, Piece const& piece) const { assert_coordinate_type_equal(total, piece.m_piece_border.m_envelope); - typedef typename strategy::expand::services::default_strategy - < - box_tag, typename cs_tag::type - >::type expand_strategy_type; if (piece.m_piece_border.m_has_envelope) { geometry::expand(total, piece.m_piece_border.m_envelope, - expand_strategy_type()); + m_strategy); } } + + Strategy const& m_strategy; }; -template +template struct piece_overlaps_box { + explicit piece_overlaps_box(Strategy const& strategy) + : m_strategy(strategy) + {} + template - static inline bool apply(Box const& box, Piece const& piece) + inline bool apply(Box const& box, Piece const& piece) const { assert_coordinate_type_equal(box, piece.m_piece_border.m_envelope); @@ -235,34 +242,45 @@ struct piece_overlaps_box } return ! geometry::detail::disjoint::disjoint_box_box(box, piece.m_piece_border.m_envelope, - DisjointBoxBoxStrategy()); + m_strategy); } + + Strategy const& m_strategy; }; +template struct turn_get_box { + explicit turn_get_box(Strategy const& strategy) + : m_strategy(strategy) + {} + template - static inline void apply(Box& total, Turn const& turn) + inline void apply(Box& total, Turn const& turn) const { - typedef typename strategy::expand::services::default_strategy - < - point_tag, typename cs_tag::type - >::type expand_strategy_type; assert_coordinate_type_equal(total, turn.point); - geometry::expand(total, turn.point, expand_strategy_type()); + geometry::expand(total, turn.point, m_strategy); } + + Strategy const& m_strategy; }; -template +template struct turn_overlaps_box { + explicit turn_overlaps_box(Strategy const& strategy) + : m_strategy(strategy) + {} + template - static inline bool apply(Box const& box, Turn const& turn) + inline bool apply(Box const& box, Turn const& turn) const { assert_coordinate_type_equal(turn.point, box); return ! geometry::detail::disjoint::disjoint_point_box(turn.point, box, - DisjointPointBoxStrategy()); + m_strategy); } + + Strategy const& m_strategy; }; struct enriched_map_buffer_include_policy diff --git a/include/boost/geometry/algorithms/detail/buffer/buffered_piece_collection.hpp b/include/boost/geometry/algorithms/detail/buffer/buffered_piece_collection.hpp index 3995f78da..6c852bd65 100644 --- a/include/boost/geometry/algorithms/detail/buffer/buffered_piece_collection.hpp +++ b/include/boost/geometry/algorithms/detail/buffer/buffered_piece_collection.hpp @@ -3,8 +3,8 @@ // Copyright (c) 2012-2014 Barend Gehrels, Amsterdam, the Netherlands. // Copyright (c) 2017 Adam Wulkiewicz, Lodz, Poland. -// This file was modified by Oracle on 2016-2020. -// Modifications copyright (c) 2016-2020 Oracle and/or its affiliates. +// This file was modified by Oracle on 2016-2021. +// Modifications copyright (c) 2016-2021 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,7 +117,7 @@ namespace detail { namespace buffer template < typename Ring, - typename IntersectionStrategy, + typename Strategy, typename DistanceStrategy, typename RobustPolicy > @@ -131,27 +131,6 @@ struct buffered_piece_collection typedef geometry::model::box box_type; - typedef typename IntersectionStrategy::side_strategy_type side_strategy_type; - typedef typename IntersectionStrategy::envelope_strategy_type envelope_strategy_type; - typedef typename IntersectionStrategy::expand_strategy_type expand_strategy_type; - - typedef typename IntersectionStrategy::template area_strategy - < - point_type - >::type area_strategy_type; - - typedef typename area_strategy_type::template result_type - < - point_type - >::type area_result_type; - - typedef typename IntersectionStrategy::template point_in_geometry_strategy - < - point_type, - clockwise_ring_type - >::type point_in_geometry_strategy_type; - - typedef buffer_turn_info < point_type, @@ -232,23 +211,23 @@ struct buffered_piece_collection {} inline original_ring(clockwise_ring_type const& ring, - bool is_interior, bool has_interiors, - envelope_strategy_type const& envelope_strategy, - expand_strategy_type const& expand_strategy) + bool is_interior, bool has_interiors, + Strategy const& strategy) : m_ring(ring) , m_is_interior(is_interior) , m_has_interiors(has_interiors) { - geometry::envelope(m_ring, m_box, envelope_strategy); + geometry::envelope(m_ring, m_box, strategy); // create monotonic sections in x-dimension // The dimension is critical because the direction is later used // in the optimization for within checks using winding strategy // and this strategy is scanning in x direction. typedef std::integer_sequence dimensions; - geometry::sectionalize(m_ring, - detail::no_rescale_policy(), m_sections, - envelope_strategy, expand_strategy); + geometry::sectionalize + < + false, dimensions + >(m_ring, detail::no_rescale_policy(), m_sections, strategy); } clockwise_ring_type m_ring; @@ -295,31 +274,18 @@ struct buffered_piece_collection cluster_type m_clusters; - IntersectionStrategy m_intersection_strategy; + Strategy m_strategy; DistanceStrategy m_distance_strategy; - side_strategy_type m_side_strategy; - area_strategy_type m_area_strategy; - envelope_strategy_type m_envelope_strategy; - expand_strategy_type m_expand_strategy; - point_in_geometry_strategy_type m_point_in_geometry_strategy; - RobustPolicy const& m_robust_policy; - buffered_piece_collection(IntersectionStrategy const& intersection_strategy, + buffered_piece_collection(Strategy const& strategy, DistanceStrategy const& distance_strategy, RobustPolicy const& robust_policy) : m_first_piece_index(-1) , m_deflate(false) , m_has_deflated(false) - , m_intersection_strategy(intersection_strategy) + , m_strategy(strategy) , m_distance_strategy(distance_strategy) - , m_side_strategy(intersection_strategy.get_side_strategy()) - , m_area_strategy(intersection_strategy - .template get_area_strategy()) - , m_envelope_strategy(intersection_strategy.get_envelope_strategy()) - , m_expand_strategy(intersection_strategy.get_expand_strategy()) - , m_point_in_geometry_strategy(intersection_strategy - .template get_point_in_geometry_strategy()) , m_robust_policy(robust_policy) {} @@ -393,8 +359,7 @@ struct buffered_piece_collection it != boost::end(m_linear_end_points); ++it) { - if (detail::equals::equals_point_point(turn.point, *it, - m_intersection_strategy.get_equals_point_point_strategy())) + if (detail::equals::equals_point_point(turn.point, *it, m_strategy)) { turn.is_linear_end_point = true; } @@ -468,20 +433,11 @@ struct buffered_piece_collection // Check if a turn is inside any of the originals inline void check_turn_in_original() { - typedef turn_in_original_overlaps_box - < - typename IntersectionStrategy::disjoint_point_box_strategy_type - > turn_in_original_overlaps_box_type; - typedef original_overlaps_box - < - typename IntersectionStrategy::disjoint_box_box_strategy_type - > original_overlaps_box_type; - turn_in_original_visitor < turn_vector_type, - point_in_geometry_strategy_type - > visitor(m_turns, m_point_in_geometry_strategy); + Strategy + > visitor(m_turns, m_strategy); geometry::partition < @@ -489,8 +445,10 @@ struct buffered_piece_collection include_turn_policy, detail::partition::include_all_policy >::apply(m_turns, original_rings, visitor, - turn_get_box(), turn_in_original_overlaps_box_type(), - original_get_box(), original_overlaps_box_type()); + turn_get_box(m_strategy), + turn_in_original_overlaps_box(m_strategy), + original_get_box(m_strategy), + original_overlaps_box(m_strategy)); bool const deflate = m_distance_strategy.negative(); @@ -560,10 +518,11 @@ struct buffered_piece_collection } // Calculate envelopes for piece borders - border.get_properties_of_border(pc.type == geometry::strategy::buffer::buffered_point, pc.m_center); + border.get_properties_of_border(pc.type == geometry::strategy::buffer::buffered_point, + pc.m_center, m_strategy); if (! pc.is_flat_end && ! pc.is_flat_start) { - border.get_properties_of_offsetted_ring_part(m_side_strategy); + border.get_properties_of_offsetted_ring_part(m_strategy); } } } @@ -580,28 +539,19 @@ struct buffered_piece_collection piece_vector_type, buffered_ring_collection >, turn_vector_type, - IntersectionStrategy, + Strategy, RobustPolicy > visitor(m_pieces, offsetted_rings, m_turns, - m_intersection_strategy, m_robust_policy); + m_strategy, m_robust_policy); - typedef detail::section::get_section_box - < - typename IntersectionStrategy::expand_box_strategy_type - > get_section_box_type; - typedef detail::section::overlaps_section_box - < - typename IntersectionStrategy::disjoint_box_box_strategy_type - > overlaps_section_box_type; + detail::sectionalize::enlarge_sections(monotonic_sections, m_strategy); - detail::sectionalize::enlarge_sections(monotonic_sections, - m_envelope_strategy); geometry::partition < robust_box_type >::apply(monotonic_sections, visitor, - get_section_box_type(), - overlaps_section_box_type()); + detail::section::get_section_box(m_strategy), + detail::section::overlaps_section_box(m_strategy)); } update_turn_administration(); @@ -614,21 +564,14 @@ struct buffered_piece_collection turn_vector_type, piece_vector_type, DistanceStrategy > visitor(m_turns, m_pieces, m_distance_strategy); - typedef turn_overlaps_box - < - typename IntersectionStrategy::disjoint_point_box_strategy_type - > turn_overlaps_box_type; - typedef piece_overlaps_box - < - typename IntersectionStrategy::disjoint_box_box_strategy_type - > piece_overlaps_box_type; - geometry::partition < box_type >::apply(m_turns, m_pieces, visitor, - turn_get_box(), turn_overlaps_box_type(), - piece_get_box(), piece_overlaps_box_type()); + turn_get_box(m_strategy), + turn_overlaps_box(m_strategy), + piece_get_box(m_strategy), + piece_overlaps_box(m_strategy)); } } @@ -771,7 +714,7 @@ struct buffered_piece_collection original_rings.back() = original_ring(clockwise_ring, is_interior, has_interiors, - m_envelope_strategy, m_expand_strategy); + m_strategy); } } @@ -870,6 +813,7 @@ struct buffered_piece_collection boost::begin(ring) + pc.first_seg_id.segment_index, boost::begin(ring) + pc.beyond_last_segment_index, m_robust_policy, + m_strategy, ring_id, 10); } @@ -1042,7 +986,7 @@ struct buffered_piece_collection enrich_intersection_points(m_turns, m_clusters, offsetted_rings, offsetted_rings, m_robust_policy, - m_intersection_strategy); + m_strategy); } // Discards all rings which do have not-OK intersection points only. @@ -1067,8 +1011,6 @@ struct buffered_piece_collection inline bool point_coveredby_original(point_type const& point) { - typedef typename IntersectionStrategy::disjoint_point_box_strategy_type d_pb_strategy_type; - signed_size_type count_in_original = 0; // Check of the robust point of this outputted ring is in @@ -1085,16 +1027,13 @@ struct buffered_piece_collection { continue; } - if (detail::disjoint::disjoint_point_box(point, - original.m_box, - d_pb_strategy_type())) + if (detail::disjoint::disjoint_point_box(point, original.m_box,m_strategy)) { continue; } int const geometry_code - = detail::within::point_in_geometry(point, - original.m_ring, m_point_in_geometry_strategy); + = detail::within::point_in_geometry(point, original.m_ring, m_strategy); if (geometry_code == -1) { @@ -1133,7 +1072,7 @@ struct buffered_piece_collection buffered_ring& ring = *it; if (! ring.has_intersections() && boost::size(ring) > 0u - && geometry::area(ring, m_area_strategy) < 0) + && geometry::area(ring, m_strategy) < 0) { if (! point_coveredby_original(geometry::range::front(ring))) { @@ -1173,7 +1112,7 @@ struct buffered_piece_collection traversed_rings.clear(); buffer_overlay_visitor visitor; traverser::apply(offsetted_rings, offsetted_rings, - m_intersection_strategy, m_robust_policy, + m_strategy, m_robust_policy, m_turns, traversed_rings, turn_info_per_ring, m_clusters, visitor); @@ -1202,7 +1141,14 @@ struct buffered_piece_collection template inline OutputIterator assign(OutputIterator out) const { - typedef detail::overlay::ring_properties properties; + typedef typename geometry::area_result + < + buffered_ring, Strategy + >::type area_result_type; + typedef detail::overlay::ring_properties + < + point_type, area_result_type + > properties; std::map selected; @@ -1218,7 +1164,7 @@ struct buffered_piece_collection if (! it->has_intersections() && ! it->is_untouched_outside_original) { - properties p = properties(*it, m_area_strategy); + properties p = properties(*it, m_strategy); if (p.valid) { ring_identifier id(0, index, -1); @@ -1234,7 +1180,7 @@ struct buffered_piece_collection it != boost::end(traversed_rings); ++it, ++index) { - properties p = properties(*it, m_area_strategy); + properties p = properties(*it, m_strategy); if (p.valid) { ring_identifier id(2, index, -1); @@ -1243,9 +1189,9 @@ struct buffered_piece_collection } detail::overlay::assign_parents(offsetted_rings, traversed_rings, - selected, m_intersection_strategy); + selected, m_strategy); return detail::overlay::add_rings(selected, offsetted_rings, traversed_rings, out, - m_area_strategy); + m_strategy); } }; diff --git a/include/boost/geometry/algorithms/detail/buffer/get_piece_turns.hpp b/include/boost/geometry/algorithms/detail/buffer/get_piece_turns.hpp index 83920f389..09fef7518 100644 --- a/include/boost/geometry/algorithms/detail/buffer/get_piece_turns.hpp +++ b/include/boost/geometry/algorithms/detail/buffer/get_piece_turns.hpp @@ -117,7 +117,7 @@ template typename Pieces, typename Rings, typename Turns, - typename IntersectionStrategy, + typename Strategy, typename RobustPolicy > class piece_turn_visitor @@ -125,7 +125,7 @@ class piece_turn_visitor Pieces const& m_pieces; Rings const& m_rings; Turns& m_turns; - IntersectionStrategy const& m_intersection_strategy; + Strategy const& m_strategy; RobustPolicy const& m_robust_policy; template @@ -271,7 +271,7 @@ class piece_turn_visitor turn_policy::apply(unique_sub_range1, unique_sub_range2, the_model, - m_intersection_strategy, + m_strategy, m_robust_policy, std::back_inserter(m_turns)); } @@ -283,12 +283,12 @@ public: piece_turn_visitor(Pieces const& pieces, Rings const& ring_collection, Turns& turns, - IntersectionStrategy const& intersection_strategy, + Strategy const& strategy, RobustPolicy const& robust_policy) : m_pieces(pieces) , m_rings(ring_collection) , m_turns(turns) - , m_intersection_strategy(intersection_strategy) + , m_strategy(strategy) , m_robust_policy(robust_policy) {} @@ -307,7 +307,7 @@ public: || is_on_same_convex_ring(piece1, piece2) || detail::disjoint::disjoint_box_box(section1.bounding_box, section2.bounding_box, - m_intersection_strategy.get_disjoint_box_box_strategy()) ) + m_strategy) ) { return true; } diff --git a/include/boost/geometry/algorithms/detail/buffer/piece_border.hpp b/include/boost/geometry/algorithms/detail/buffer/piece_border.hpp index 026808edf..ecd03d9c8 100644 --- a/include/boost/geometry/algorithms/detail/buffer/piece_border.hpp +++ b/include/boost/geometry/algorithms/detail/buffer/piece_border.hpp @@ -167,9 +167,11 @@ struct piece_border return result; } - void get_properties_of_border(bool is_point_buffer, Point const& center) + template + void get_properties_of_border(bool is_point_buffer, Point const& center, + Strategy const& strategy) { - m_has_envelope = calculate_envelope(m_envelope); + m_has_envelope = calculate_envelope(m_envelope, strategy); if (m_has_envelope) { // Take roundings into account, enlarge box @@ -182,8 +184,8 @@ struct piece_border } } - template - void get_properties_of_offsetted_ring_part(SideStrategy const& strategy) + template + void get_properties_of_offsetted_ring_part(Strategy const& strategy) { if (! ring_or_original_empty()) { @@ -209,16 +211,16 @@ struct piece_border m_originals[m_original_size++] = point; } - template - bool calculate_envelope(Box& envelope) const + template + bool calculate_envelope(Box& envelope, Strategy const& strategy) const { geometry::assign_inverse(envelope); if (ring_or_original_empty()) { return false; } - expand_envelope(envelope, m_ring->begin() + m_begin, m_ring->begin() + m_end); - expand_envelope(envelope, m_originals.begin(), m_originals.begin() + m_original_size); + expand_envelope(envelope, m_ring->begin() + m_begin, m_ring->begin() + m_end, strategy); + expand_envelope(envelope, m_originals.begin(), m_originals.begin() + m_original_size, strategy); return true; } @@ -333,8 +335,8 @@ private : return true; } - template - bool step(TurnPoint const& point, Point const& p1, Point const& p2, Strategy const & strategy, + template + bool step(TurnPoint const& point, Point const& p1, Point const& p2, TiRStrategy const & strategy, geometry::strategy::buffer::place_on_ring_type place_on_ring, State& state) const { // A step between original/offsetted ring is always convex @@ -357,22 +359,17 @@ private : return strategy.apply(point, p1, p2, dm, place_on_ring, state); } - template - void expand_envelope(Box& envelope, It begin, It end) const + template + void expand_envelope(Box& envelope, It begin, It end, Strategy const& strategy) const { - typedef typename strategy::expand::services::default_strategy - < - point_tag, typename cs_tag::type - >::type expand_strategy_type; - for (It it = begin; it != end; ++it) { - geometry::expand(envelope, *it, expand_strategy_type()); + geometry::expand(envelope, *it, strategy); } } - template - bool is_convex(SideStrategy const& strategy) const + template + bool is_convex(Strategy const& strategy) const { if (ring_or_original_empty()) { @@ -416,8 +413,8 @@ private : return result; } - template - bool is_convex(Point& previous, Point& current, It begin, It end, SideStrategy const& strategy) const + template + bool is_convex(Point& previous, Point& current, It begin, It end, Strategy const& strategy) const { for (It it = begin; it != end; ++it) { @@ -429,19 +426,16 @@ private : return true; } - template - bool is_convex(Point& previous, Point& current, Point const& next, SideStrategy const& strategy) const + template + bool is_convex(Point& previous, Point& current, Point const& next, Strategy const& strategy) const { - typename SideStrategy::equals_point_point_strategy_type const - eq_pp_strategy = strategy.get_equals_point_point_strategy(); - - int const side = strategy.apply(previous, current, next); + int const side = strategy.side().apply(previous, current, next); if (side == 1) { // Next is on the left side of clockwise ring: piece is not convex return false; } - if (! equals::equals_point_point(current, next, eq_pp_strategy)) + if (! equals::equals_point_point(current, next, strategy)) { previous = current; current = next; diff --git a/include/boost/geometry/algorithms/detail/buffer/turn_in_original_visitor.hpp b/include/boost/geometry/algorithms/detail/buffer/turn_in_original_visitor.hpp index d51220dac..b1930dc0c 100644 --- a/include/boost/geometry/algorithms/detail/buffer/turn_in_original_visitor.hpp +++ b/include/boost/geometry/algorithms/detail/buffer/turn_in_original_visitor.hpp @@ -2,8 +2,8 @@ // Copyright (c) 2014 Barend Gehrels, Amsterdam, the Netherlands. -// This file was modified by Oracle on 2016, 2018. -// Modifications copyright (c) 2016-2018 Oracle and/or its affiliates. +// This file was modified by Oracle on 2016-2020. +// Modifications copyright (c) 2016-2020 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, @@ -31,31 +31,40 @@ namespace boost { namespace geometry namespace detail { namespace buffer { + +template struct original_get_box { + explicit original_get_box(Strategy const& strategy) + : m_strategy(strategy) + {} + template - static inline void apply(Box& total, Original const& original) + inline void apply(Box& total, Original const& original) const { assert_coordinate_type_equal(total, original.m_box); - typedef typename strategy::expand::services::default_strategy - < - box_tag, typename cs_tag::type - >::type expand_strategy_type; - - geometry::expand(total, original.m_box, expand_strategy_type()); + geometry::expand(total, original.m_box, m_strategy); } + + Strategy const& m_strategy; }; -template +template struct original_overlaps_box { + explicit original_overlaps_box(Strategy const& strategy) + : m_strategy(strategy) + {} + template - static inline bool apply(Box const& box, Original const& original) + inline bool apply(Box const& box, Original const& original) const { assert_coordinate_type_equal(box, original.m_box); return ! detail::disjoint::disjoint_box_box(box, original.m_box, - DisjointBoxBoxStrategy()); + m_strategy); } + + Strategy const& m_strategy; }; struct include_turn_policy @@ -67,11 +76,15 @@ struct include_turn_policy } }; -template +template struct turn_in_original_overlaps_box { + explicit turn_in_original_overlaps_box(Strategy const& strategy) + : m_strategy(strategy) + {} + template - static inline bool apply(Box const& box, Turn const& turn) + inline bool apply(Box const& box, Turn const& turn) const { if (! turn.is_turn_traversable || turn.within_original) { @@ -80,8 +93,10 @@ struct turn_in_original_overlaps_box } return ! geometry::detail::disjoint::disjoint_point_box( - turn.point, box, DisjointPointBoxStrategy()); + turn.point, box, m_strategy); } + + Strategy const& m_strategy; }; //! Check if specified is in range of specified iterators @@ -210,13 +225,13 @@ inline int point_in_original(Point const& point, Original const& original, } -template +template class turn_in_original_visitor { public: - turn_in_original_visitor(Turns& turns, PointInGeometryStrategy const& strategy) + turn_in_original_visitor(Turns& turns, Strategy const& strategy) : m_mutable_turns(turns) - , m_point_in_geometry_strategy(strategy) + , m_strategy(strategy) {} template @@ -234,13 +249,14 @@ public: return true; } - if (geometry::disjoint(turn.point, original.m_box)) + if (geometry::disjoint(turn.point, original.m_box, m_strategy)) { // Skip all disjoint return true; } - int const code = point_in_original(turn.point, original, m_point_in_geometry_strategy); + int const code = point_in_original(turn.point, original, + m_strategy.relate(turn.point, original.m_ring)); if (code == -1) { @@ -277,7 +293,7 @@ public: private : Turns& m_mutable_turns; - PointInGeometryStrategy const& m_point_in_geometry_strategy; + Strategy const& m_strategy; }; diff --git a/include/boost/geometry/algorithms/detail/closest_feature/range_to_range.hpp b/include/boost/geometry/algorithms/detail/closest_feature/range_to_range.hpp index a3e99bec7..1cf9ddc8a 100644 --- a/include/boost/geometry/algorithms/detail/closest_feature/range_to_range.hpp +++ b/include/boost/geometry/algorithms/detail/closest_feature/range_to_range.hpp @@ -54,13 +54,11 @@ private: QueryRangeIterator& qit_min, Distance& dist_min) { - typedef strategy::index::services::from_strategy - < - Strategy - > index_strategy_from; + using strategies::index::services::strategy_converter; typedef index::parameters < - index::linear<8>, typename index_strategy_from::type + index::linear<8>, + decltype(strategy_converter::get(strategy)) > index_parameters_type; typedef index::rtree rtree_type; @@ -73,7 +71,7 @@ private: // create -- packing algorithm rtree_type rt(rtree_first, rtree_last, index_parameters_type(index::linear<8>(), - index_strategy_from::get(strategy))); + strategy_converter::get(strategy))); RTreeValueType t_v; bool first = true; diff --git a/include/boost/geometry/strategies/agnostic/hull_graham_andrew.hpp b/include/boost/geometry/algorithms/detail/convex_hull/graham_andrew.hpp similarity index 88% rename from include/boost/geometry/strategies/agnostic/hull_graham_andrew.hpp rename to include/boost/geometry/algorithms/detail/convex_hull/graham_andrew.hpp index d948f5240..aab92053a 100644 --- a/include/boost/geometry/strategies/agnostic/hull_graham_andrew.hpp +++ b/include/boost/geometry/algorithms/detail/convex_hull/graham_andrew.hpp @@ -5,6 +5,7 @@ // This file was modified by Oracle on 2014-2020. // Modifications copyright (c) 2014-2020 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 // Parts of Boost.Geometry are redesigned from Geodan's Geographic Library @@ -14,8 +15,8 @@ // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) -#ifndef BOOST_GEOMETRY_STRATEGIES_AGNOSTIC_CONVEX_GRAHAM_ANDREW_HPP -#define BOOST_GEOMETRY_STRATEGIES_AGNOSTIC_CONVEX_GRAHAM_ANDREW_HPP +#ifndef BOOST_GEOMETRY_ALGORITHMS_CONVEX_HULL_GRAHAM_ANDREW_HPP +#define BOOST_GEOMETRY_ALGORITHMS_CONVEX_HULL_GRAHAM_ANDREW_HPP #include @@ -40,14 +41,10 @@ namespace boost { namespace geometry { -namespace strategy { namespace convex_hull -{ - #ifndef DOXYGEN_NO_DETAIL -namespace detail +namespace detail { namespace convex_hull { - template inline void get_extremes(Geometry const& geometry, Point& left, Point& right, @@ -190,8 +187,10 @@ private: public: typedef partitions state_type; - - inline void apply(InputGeometry const& geometry, partitions& state) const + template + inline void apply(InputGeometry const& geometry, + partitions& state, + Strategy& strategy) const { // First pass. // Get min/max (in most cases left / right) points @@ -212,31 +211,30 @@ public: // TODO: User-defined CS-specific less-compare geometry::less less; - detail::get_extremes(geometry, most_left, most_right, less); + detail::convex_hull::get_extremes(geometry, most_left, most_right, less); container_type lower_points, upper_points; - // TODO: User-defiend CS-specific side strategy - typename strategy::side::services::default_strategy::type side; + auto const side_strategy = strategy.side(); // Bounding left/right points // Second pass, now that extremes are found, assign all points // in either lower, either upper - detail::assign_ranges(geometry, most_left, most_right, + detail::convex_hull::assign_ranges(geometry, most_left, most_right, lower_points, upper_points, - side); + side_strategy); // Sort both collections, first on x(, then on y) - detail::sort(lower_points, less); - detail::sort(upper_points, less); + detail::convex_hull::sort(lower_points, less); + detail::convex_hull::sort(upper_points, less); // And decide which point should be in the final hull build_half_hull<-1>(lower_points, state.m_lower_hull, most_left, most_right, - side); + side_strategy); build_half_hull<1>(upper_points, state.m_upper_hull, most_left, most_right, - side); + side_strategy); } @@ -304,8 +302,10 @@ private: template - static inline void output_ranges(container_type const& first, container_type const& second, - OutputIterator out, bool closed) + static inline void output_ranges(container_type const& first, + container_type const& second, + OutputIterator out, + bool closed) { std::copy(boost::begin(first), boost::end(first), out); @@ -327,18 +327,8 @@ private: } }; -}} // namespace strategy::convex_hull - - -#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS -template -struct strategy_convex_hull -{ - typedef strategy::convex_hull::graham_andrew type; -}; -#endif +} // namespace convex_hull }} // namespace boost::geometry - -#endif // BOOST_GEOMETRY_STRATEGIES_AGNOSTIC_CONVEX_GRAHAM_ANDREW_HPP +#endif // BOOST_GEOMETRY_ALGORITHMS_CONVEX_HULL_GRAHAM_ANDREW_HPP diff --git a/include/boost/geometry/algorithms/detail/convex_hull/interface.hpp b/include/boost/geometry/algorithms/detail/convex_hull/interface.hpp new file mode 100644 index 000000000..47088a4ca --- /dev/null +++ b/include/boost/geometry/algorithms/detail/convex_hull/interface.hpp @@ -0,0 +1,394 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// 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. + +// This file was modified by Oracle on 2014, 2015, 2020. +// Modifications copyright (c) 2014-2020 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. + +// 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_CONVEX_HULL_INTERFACE_HPP +#define BOOST_GEOMETRY_ALGORITHMS_CONVEX_HULL_INTERFACE_HPP + +#include + +#include +#include +#include + +#include +#include +#include +#include + +#include + +#include +#include +#include + +#include + +#include + +#include +#include +#include +#include + + +namespace boost { namespace geometry +{ + + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace convex_hull +{ + +template +struct hull_insert +{ + + // Member template function (to avoid inconvenient declaration + // of output-iterator-type, from hull_to_geometry) + template + static inline OutputIterator apply(Geometry const& geometry, + OutputIterator out, + Strategy const& strategy) + { + typedef graham_andrew + < + Geometry, + typename point_type::type + > ConvexHullAlgorithm; + + ConvexHullAlgorithm algorithm; + typename ConvexHullAlgorithm::state_type state; + + algorithm.apply(geometry, state, strategy); + algorithm.result(state, out, Order == clockwise, Closure != open); + + return out; + } +}; + +struct hull_to_geometry +{ + template + static inline void apply(Geometry const& geometry, OutputGeometry& out, + Strategy const& strategy) + { + hull_insert + < + geometry::point_order::value, + geometry::closure::value + >::apply(geometry, + range::back_inserter( + // Handle linestring, ring and polygon the same: + detail::as_range + < + typename range_type::type + >(out)), strategy); + } +}; + +}} // namespace detail::convex_hull +#endif // DOXYGEN_NO_DETAIL + + +#ifndef DOXYGEN_NO_DISPATCH +namespace dispatch +{ + + +template +< + typename Geometry, + typename Tag = typename tag::type +> +struct convex_hull + : detail::convex_hull::hull_to_geometry +{}; + +template +struct convex_hull +{ + template + static inline void apply(Box const& box, + OutputGeometry& out, + Strategy const& ) + { + static bool const Close + = geometry::closure::value == closed; + static bool const Reverse + = geometry::point_order::value == counterclockwise; + + // A hull for boxes is trivial. Any strategy is (currently) skipped. + boost::array::type, 4> range; + geometry::detail::assign_box_corners_oriented(box, range); + geometry::append(out, range); + if (BOOST_GEOMETRY_CONDITION(Close)) + { + geometry::append(out, *boost::begin(range)); + } + } +}; + + + +template +struct convex_hull_insert + : detail::convex_hull::hull_insert +{}; + + +} // namespace dispatch +#endif // DOXYGEN_NO_DISPATCH + + +namespace resolve_strategy { + +struct convex_hull +{ + template + static inline void apply(Geometry const& geometry, + OutputGeometry& out, + Strategy const& strategy) + { + //BOOST_CONCEPT_ASSERT( (geometry::concepts::ConvexHullStrategy) ); + dispatch::convex_hull::apply(geometry, out, strategy); + } + + template + static inline void apply(Geometry const& geometry, + OutputGeometry& out, + default_strategy) + { + typedef typename strategies::convex_hull::services::default_strategy + < + Geometry + >::type strategy_type; + + apply(geometry, out, strategy_type()); + } +}; + +struct convex_hull_insert +{ + template + static inline OutputIterator apply(Geometry const& geometry, + OutputIterator& out, + Strategy const& strategy) + { + //BOOST_CONCEPT_ASSERT( (geometry::concepts::ConvexHullStrategy) ); + + return dispatch::convex_hull_insert< + geometry::point_order::value, + geometry::closure::value + >::apply(geometry, out, strategy); + } + + template + static inline OutputIterator apply(Geometry const& geometry, + OutputIterator& out, + default_strategy) + { + typedef typename strategies::convex_hull::services::default_strategy + < + Geometry + >::type strategy_type; + + return apply(geometry, out, strategy_type()); + } +}; + +} // namespace resolve_strategy + + +namespace resolve_variant { + +template +struct convex_hull +{ + template + static inline void apply(Geometry const& geometry, + OutputGeometry& out, + Strategy const& strategy) + { + concepts::check_concepts_and_equal_dimensions< + const Geometry, + OutputGeometry + >(); + + resolve_strategy::convex_hull::apply(geometry, out, strategy); + } +}; + +template +struct convex_hull > +{ + template + struct visitor: boost::static_visitor + { + OutputGeometry& m_out; + Strategy const& m_strategy; + + visitor(OutputGeometry& out, Strategy const& strategy) + : m_out(out), m_strategy(strategy) + {} + + template + void operator()(Geometry const& geometry) const + { + convex_hull::apply(geometry, m_out, m_strategy); + } + }; + + template + static inline void + apply(boost::variant const& geometry, + OutputGeometry& out, + Strategy const& strategy) + { + boost::apply_visitor(visitor(out, strategy), + geometry); + } +}; + +template +struct convex_hull_insert +{ + template + static inline OutputIterator apply(Geometry const& geometry, + OutputIterator& out, + Strategy const& strategy) + { + // Concept: output point type = point type of input geometry + concepts::check(); + concepts::check::type>(); + + return resolve_strategy::convex_hull_insert::apply(geometry, out, strategy); + } +}; + +template +struct convex_hull_insert > +{ + template + struct visitor: boost::static_visitor + { + OutputIterator& m_out; + Strategy const& m_strategy; + + visitor(OutputIterator& out, Strategy const& strategy) + : m_out(out), m_strategy(strategy) + {} + + template + OutputIterator operator()(Geometry const& geometry) const + { + return convex_hull_insert::apply(geometry, m_out, m_strategy); + } + }; + + template + static inline OutputIterator + apply(boost::variant const& geometry, + OutputIterator& out, + Strategy const& strategy) + { + return boost::apply_visitor(visitor(out, strategy), geometry); + } +}; + +} // namespace resolve_variant + + +template +inline void convex_hull(Geometry const& geometry, + OutputGeometry& out, Strategy const& strategy) +{ + if (geometry::is_empty(geometry)) + { + // Leave output empty + return; + } + + resolve_variant::convex_hull::apply(geometry, out, strategy); +} + + +/*! +\brief \brief_calc{convex hull} +\ingroup convex_hull +\details \details_calc{convex_hull,convex hull}. +\tparam Geometry the input geometry type +\tparam OutputGeometry the output geometry type +\param geometry \param_geometry, input geometry +\param hull \param_geometry \param_set{convex hull} + +\qbk{[include reference/algorithms/convex_hull.qbk]} + */ +template +inline void convex_hull(Geometry const& geometry, + OutputGeometry& hull) +{ + geometry::convex_hull(geometry, hull, default_strategy()); +} + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace convex_hull +{ + + +template +inline OutputIterator convex_hull_insert(Geometry const& geometry, + OutputIterator out, Strategy const& strategy) +{ + return resolve_variant::convex_hull_insert + < + Geometry + >::apply(geometry, out, strategy); +} + + +/*! +\brief Calculate the convex hull of a geometry, output-iterator version +\ingroup convex_hull +\tparam Geometry the input geometry type +\tparam OutputIterator: an output-iterator +\param geometry the geometry to calculate convex hull from +\param out an output iterator outputing points of the convex hull +\note This overloaded version outputs to an output iterator. +In this case, nothing is known about its point-type or + about its clockwise order. Therefore, the input point-type + and order are copied + + */ +template +inline OutputIterator convex_hull_insert(Geometry const& geometry, + OutputIterator out) +{ + return convex_hull_insert(geometry, out, default_strategy()); +} + + +}} // namespace detail::convex_hull +#endif // DOXYGEN_NO_DETAIL + + +}} // namespace boost::geometry + + +#endif // BOOST_GEOMETRY_ALGORITHMS_CONVEX_HULL_INTERFACE_HPP diff --git a/include/boost/geometry/algorithms/detail/course.hpp b/include/boost/geometry/algorithms/detail/course.hpp deleted file mode 100644 index 37424941b..000000000 --- a/include/boost/geometry/algorithms/detail/course.hpp +++ /dev/null @@ -1,40 +0,0 @@ -// Boost.Geometry (aka GGL, Generic Geometry Library) - -// 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. - -// 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_COURSE_HPP -#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_COURSE_HPP - -#include - -namespace boost { namespace geometry -{ - -#ifndef DOXYGEN_NO_DETAIL -namespace detail -{ - -/// Calculate course (bearing) between two points. -/// -/// NOTE: left for convenience and temporary backward compatibility -template -inline ReturnType course(Point1 const& p1, Point2 const& p2) -{ - return azimuth(p1, p2); -} - -} // namespace detail -#endif // DOXYGEN_NO_DETAIL - -}} // namespace boost::geometry - -#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_COURSE_HPP diff --git a/include/boost/geometry/algorithms/detail/covered_by/implementation.hpp b/include/boost/geometry/algorithms/detail/covered_by/implementation.hpp index b180a3d5a..80cdd539f 100644 --- a/include/boost/geometry/algorithms/detail/covered_by/implementation.hpp +++ b/include/boost/geometry/algorithms/detail/covered_by/implementation.hpp @@ -4,8 +4,8 @@ // 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, 2017, 2019. -// Modifications copyright (c) 2013-2019 Oracle and/or its affiliates. +// This file was modified by Oracle on 2013-2020. +// Modifications copyright (c) 2013-2020 Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle @@ -66,8 +66,7 @@ struct covered_by template static inline bool apply(Point const& point, Box const& box, Strategy const& strategy) { - ::boost::ignore_unused(strategy); - return strategy.apply(point, box); + return strategy.covered_by(point, box).apply(point, box); } }; @@ -78,8 +77,7 @@ struct covered_by static inline bool apply(Box1 const& box1, Box2 const& box2, Strategy const& strategy) { assert_dimension_equal(); - ::boost::ignore_unused(strategy); - return strategy.apply(box1, box2); + return strategy.covered_by(box1, box2).apply(box1, box2); } }; diff --git a/include/boost/geometry/algorithms/detail/covered_by/interface.hpp b/include/boost/geometry/algorithms/detail/covered_by/interface.hpp index 4749ed168..d1b4db2a6 100644 --- a/include/boost/geometry/algorithms/detail/covered_by/interface.hpp +++ b/include/boost/geometry/algorithms/detail/covered_by/interface.hpp @@ -4,9 +4,8 @@ // 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, 2017, 2018. -// Modifications copyright (c) 2013-2018 Oracle and/or its affiliates. - +// This file was modified by Oracle on 2013-2021. +// Modifications copyright (c) 2013-2021 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 @@ -30,6 +29,8 @@ #include #include #include +#include +#include namespace boost { namespace geometry @@ -56,9 +57,14 @@ struct covered_by namespace resolve_strategy { +template +< + typename Strategy, + bool IsUmbrella = strategies::detail::is_umbrella_strategy::value +> struct covered_by { - template + template static inline bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2, Strategy const& strategy) @@ -68,23 +74,49 @@ struct covered_by concepts::check(); assert_dimension_equal(); - return dispatch::covered_by::apply(geometry1, - geometry2, - strategy); + return dispatch::covered_by + < + Geometry1, Geometry2 + >::apply(geometry1, geometry2, strategy); } +}; +template +struct covered_by +{ + template + static inline bool apply(Geometry1 const& geometry1, + Geometry2 const& geometry2, + Strategy const& strategy) + { + using strategies::relate::services::strategy_converter; + + return covered_by + < + decltype(strategy_converter::get(strategy)) + >::apply(geometry1, geometry2, + strategy_converter::get(strategy)); + } +}; + +template <> +struct covered_by +{ template static inline bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2, default_strategy) { - typedef typename strategy::covered_by::services::default_strategy + typedef typename strategies::relate::services::default_strategy < Geometry1, Geometry2 >::type strategy_type; - return covered_by::apply(geometry1, geometry2, strategy_type()); + return covered_by + < + strategy_type + >::apply(geometry1, geometry2, strategy_type()); } }; @@ -101,7 +133,7 @@ struct covered_by Geometry2 const& geometry2, Strategy const& strategy) { - return resolve_strategy::covered_by + return resolve_strategy::covered_by ::apply(geometry1, geometry2, strategy); } }; diff --git a/include/boost/geometry/algorithms/detail/disjoint/areal_areal.hpp b/include/boost/geometry/algorithms/detail/disjoint/areal_areal.hpp index b8c778856..934f90c87 100644 --- a/include/boost/geometry/algorithms/detail/disjoint/areal_areal.hpp +++ b/include/boost/geometry/algorithms/detail/disjoint/areal_areal.hpp @@ -60,13 +60,9 @@ inline bool rings_containing(Geometry1 const& geometry1, Geometry2 const& geometry2, Strategy const& strategy) { - // TODO: This will be removed when IntersectionStrategy is replaced with - // UmbrellaStrategy - auto const pgs = strategy.template get_point_in_geometry_strategy(); - return geometry::detail::any_range_of(geometry2, [&](auto const& range) { - return point_on_border_covered_by(range, geometry1, pgs); + return point_on_border_covered_by(range, geometry1, strategy); }); } @@ -116,11 +112,9 @@ struct areal_box Box const& box, Strategy const& strategy) { - // TODO: This will be removed when UmbrellaStrategy is supported - auto const ds = strategy.get_disjoint_segment_box_strategy(); if (! geometry::all_segments_of(areal, [&](auto const& s) { - return disjoint_segment_box::apply(s, box, ds); + return disjoint_segment_box::apply(s, box, strategy); }) ) { return false; @@ -129,8 +123,7 @@ struct areal_box // If there is no intersection of any segment and box, // the box might be located inside areal geometry - if ( point_on_border_covered_by(box, areal, - strategy.template get_point_in_geometry_strategy()) ) + if ( point_on_border_covered_by(box, areal, strategy) ) { return false; } diff --git a/include/boost/geometry/algorithms/detail/disjoint/box_box.hpp b/include/boost/geometry/algorithms/detail/disjoint/box_box.hpp index 67f063321..8092ae4f8 100644 --- a/include/boost/geometry/algorithms/detail/disjoint/box_box.hpp +++ b/include/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-2018. -// Modifications copyright (c) 2013-2018, Oracle and/or its affiliates. +// This file was modified by Oracle on 2013-2020. +// Modifications copyright (c) 2013-2020, 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 @@ -43,8 +43,23 @@ namespace detail { namespace disjoint \note Is used from other algorithms, declared separately to avoid circular references */ -template -inline bool disjoint_box_box(Box1 const& box1, Box2 const& box2, Strategy const&) +template +< + typename Box1, typename Box2, typename Strategy, + std::enable_if_t::value, int> = 0 +> +inline bool disjoint_box_box(Box1 const& box1, Box2 const& box2, Strategy const& strategy) +{ + typedef decltype(strategy.disjoint(box1, box2)) strategy_type; + return strategy_type::apply(box1, box2); +} + +template +< + typename Box1, typename Box2, typename Strategy, + std::enable_if_t::value, int> = 0 +> +inline bool disjoint_box_box(Box1 const& box1, Box2 const& box2, Strategy const& ) { return Strategy::apply(box1, box2); } @@ -63,9 +78,10 @@ template struct disjoint { template - static inline bool apply(Box1 const& box1, Box2 const& box2, Strategy const&) + static inline bool apply(Box1 const& box1, Box2 const& box2, Strategy const& strategy) { - return Strategy::apply(box1, box2); + typedef decltype(strategy.disjoint(box1, box2)) strategy_type; + return strategy_type::apply(box1, box2); } }; diff --git a/include/boost/geometry/algorithms/detail/disjoint/interface.hpp b/include/boost/geometry/algorithms/detail/disjoint/interface.hpp index fc4aecbb0..b7df7345c 100644 --- a/include/boost/geometry/algorithms/detail/disjoint/interface.hpp +++ b/include/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-2017. -// Modifications copyright (c) 2013-2017, Oracle and/or its affiliates. +// This file was modified by Oracle on 2013-2021. +// Modifications copyright (c) 2013-2021, 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 @@ -32,7 +32,10 @@ #include +#include +#include #include +#include namespace boost { namespace geometry @@ -41,9 +44,14 @@ namespace boost { namespace geometry namespace resolve_strategy { +template +< + typename Strategy, + bool IsUmbrella = strategies::detail::is_umbrella_strategy::value +> struct disjoint { - template + template static inline bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2, Strategy const& strategy) @@ -53,13 +61,35 @@ struct disjoint Geometry1, Geometry2 >::apply(geometry1, geometry2, strategy); } +}; +template +struct disjoint +{ + template + static inline bool apply(Geometry1 const& geometry1, + Geometry2 const& geometry2, + Strategy const& strategy) + { + using strategies::relate::services::strategy_converter; + + return dispatch::disjoint + < + Geometry1, Geometry2 + >::apply(geometry1, geometry2, + strategy_converter::get(strategy)); + } +}; + +template <> +struct disjoint +{ template static inline bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2, default_strategy) { - typedef typename strategy::disjoint::services::default_strategy + typedef typename strategies::relate::services::default_strategy < Geometry1, Geometry2 >::type strategy_type; @@ -88,7 +118,10 @@ struct disjoint Geometry2 const >(); - return resolve_strategy::disjoint::apply(geometry1, geometry2, strategy); + return resolve_strategy::disjoint + < + Strategy + >::apply(geometry1, geometry2, strategy); } }; diff --git a/include/boost/geometry/algorithms/detail/disjoint/linear_areal.hpp b/include/boost/geometry/algorithms/detail/disjoint/linear_areal.hpp index a56f56e62..d5045189a 100644 --- a/include/boost/geometry/algorithms/detail/disjoint/linear_areal.hpp +++ b/include/boost/geometry/algorithms/detail/disjoint/linear_areal.hpp @@ -74,7 +74,7 @@ struct disjoint_no_intersections_policy point1_type p; geometry::point_on_border(p, g1); - return !geometry::covered_by(p, g2, strategy); + return ! geometry::covered_by(p, g2, strategy); } }; @@ -120,9 +120,7 @@ struct disjoint_linear_areal return false; } - return NoIntersectionsPolicy - ::apply(g1, g2, - strategy.template get_point_in_geometry_strategy()); + return NoIntersectionsPolicy::apply(g1, g2, strategy); } }; @@ -195,8 +193,7 @@ public: typename point_type::type p; detail::assign_point_from_index<0>(segment, p); - return !geometry::covered_by(p, polygon, - strategy.template get_point_in_geometry_strategy()); + return ! geometry::covered_by(p, polygon, strategy); } }; @@ -235,8 +232,7 @@ struct disjoint_segment_areal typename point_type::type p; detail::assign_point_from_index<0>(segment, p); - return !geometry::covered_by(p, ring, - strategy.template get_point_in_geometry_strategy()); + return ! geometry::covered_by(p, ring, strategy); } }; diff --git a/include/boost/geometry/algorithms/detail/disjoint/linear_linear.hpp b/include/boost/geometry/algorithms/detail/disjoint/linear_linear.hpp index fb9189284..fc8e6a351 100644 --- a/include/boost/geometry/algorithms/detail/disjoint/linear_linear.hpp +++ b/include/boost/geometry/algorithms/detail/disjoint/linear_linear.hpp @@ -65,8 +65,8 @@ struct disjoint_segment detail::segment_as_subrange sub_range1(segment1); detail::segment_as_subrange sub_range2(segment2); - intersection_return_type is = strategy.apply(sub_range1, sub_range2, - intersection_policy()); + intersection_return_type is = strategy.relate().apply(sub_range1, sub_range2, + intersection_policy()); return is.count == 0; } diff --git a/include/boost/geometry/algorithms/detail/disjoint/linear_segment_or_box.hpp b/include/boost/geometry/algorithms/detail/disjoint/linear_segment_or_box.hpp index 0f0036117..1999f10f3 100644 --- a/include/boost/geometry/algorithms/detail/disjoint/linear_segment_or_box.hpp +++ b/include/boost/geometry/algorithms/detail/disjoint/linear_segment_or_box.hpp @@ -58,8 +58,7 @@ struct disjoint_point_segment_or_box return dispatch::disjoint < Point, Segment - >::apply(point, segment, - strategy.template get_point_in_geometry_strategy()); + >::apply(point, segment, strategy); } }; @@ -72,8 +71,7 @@ struct disjoint_point_segment_or_box return dispatch::disjoint < Point, Box - >::apply(point, box, - strategy.get_disjoint_point_box_strategy()); + >::apply(point, box, strategy); } }; diff --git a/include/boost/geometry/algorithms/detail/disjoint/multipoint_geometry.hpp b/include/boost/geometry/algorithms/detail/disjoint/multipoint_geometry.hpp index 54eaae86a..9e3a57a29 100644 --- a/include/boost/geometry/algorithms/detail/disjoint/multipoint_geometry.hpp +++ b/include/boost/geometry/algorithms/detail/disjoint/multipoint_geometry.hpp @@ -125,72 +125,78 @@ template class multipoint_linear { private: - template + template struct expand_box_point { + explicit expand_box_point(Strategy const& strategy) + : m_strategy(strategy) + {} + template - static inline void apply(Box& total, Point const& point) + void apply(Box& total, Point const& point) const { - geometry::expand(total, point, ExpandPointBoxStrategy()); + geometry::expand(total, point, m_strategy); } + + Strategy const& m_strategy; }; - template + template struct expand_box_segment { - explicit expand_box_segment(EnvelopeStrategy const& strategy) + explicit expand_box_segment(Strategy const& strategy) : m_strategy(strategy) {} template - inline void apply(Box& total, Segment const& segment) const + void apply(Box& total, Segment const& segment) const { geometry::expand(total, geometry::return_envelope(segment, m_strategy), - // TEMP - envelope umbrella strategy also contains - // expand strategies - strategies::envelope::services::strategy_converter - < - EnvelopeStrategy - >::get(m_strategy)); + m_strategy); } - EnvelopeStrategy const& m_strategy; + Strategy const& m_strategy; }; - template + template struct overlaps_box_point { + explicit overlaps_box_point(Strategy const& strategy) + : m_strategy(strategy) + {} + template - static inline bool apply(Box const& box, Point const& point) + bool apply(Box const& box, Point const& point) const { - // The default strategy is enough in this case return ! detail::disjoint::disjoint_point_box(point, box, - DisjointPointBoxStrategy()); + m_strategy); } + + Strategy const& m_strategy; }; - template + template struct overlaps_box_segment { - explicit overlaps_box_segment(DisjointStrategy const& strategy) + explicit overlaps_box_segment(Strategy const& strategy) : m_strategy(strategy) {} template - inline bool apply(Box const& box, Segment const& segment) const + bool apply(Box const& box, Segment const& segment) const { return ! dispatch::disjoint::apply(segment, box, m_strategy); } - DisjointStrategy const& m_strategy; + Strategy const& m_strategy; }; - template + template class item_visitor_type { public: - item_visitor_type(PtSegStrategy const& strategy) + item_visitor_type(Strategy const& strategy) : m_intersection_found(false) , m_strategy(strategy) {} @@ -211,7 +217,7 @@ private: private: bool m_intersection_found; - PtSegStrategy const& m_strategy; + Strategy const& m_strategy; }; // structs for partition -- end @@ -245,11 +251,6 @@ public: { item_visitor_type visitor(strategy); - typedef typename Strategy::expand_point_strategy_type expand_point_strategy_type; - typedef typename Strategy::envelope_strategy_type envelope_strategy_type; - typedef typename Strategy::disjoint_strategy_type disjoint_strategy_type; - typedef typename Strategy::disjoint_point_box_strategy_type disjoint_pb_strategy_type; - // TODO: disjoint Segment/Box may be called in partition multiple times // possibly for non-cartesian segments which could be slow. We should consider // passing a range of bounding boxes of segments after calculating them once. @@ -259,16 +260,17 @@ public: < geometry::model::box::type> >::apply(multipoint, segment_range(linear), visitor, - expand_box_point(), - overlaps_box_point(), - expand_box_segment(strategy.get_envelope_strategy()), - overlaps_box_segment(strategy.get_disjoint_strategy())); + expand_box_point(strategy), + overlaps_box_point(strategy), + expand_box_segment(strategy), + overlaps_box_segment(strategy)); return ! visitor.intersection_found(); } template - static inline bool apply(Linear const& linear, MultiPoint const& multipoint, Strategy const& strategy) + static inline bool apply(Linear const& linear, MultiPoint const& multipoint, + Strategy const& strategy) { return apply(multipoint, linear, strategy); } @@ -284,21 +286,19 @@ public: SingleGeometry const& single_geometry, Strategy const& strategy) { - typedef typename Strategy::disjoint_point_box_strategy_type d_pb_strategy_type; - typedef typename point_type::type point1_type; typedef typename point_type::type point2_type; typedef model::box box2_type; box2_type box2; - geometry::envelope(single_geometry, box2, strategy.get_envelope_strategy()); + geometry::envelope(single_geometry, box2, strategy); geometry::detail::expand_by_epsilon(box2); typedef typename boost::range_const_iterator::type iterator; for ( iterator it = boost::begin(multi_point) ; it != boost::end(multi_point) ; ++it ) { // The default strategy is enough for Point/Box - if (! detail::disjoint::disjoint_point_box(*it, box2, d_pb_strategy_type()) + if (! detail::disjoint::disjoint_point_box(*it, box2, strategy) && ! dispatch::disjoint::apply(*it, single_geometry, strategy)) { return false; @@ -309,7 +309,8 @@ public: } template - static inline bool apply(SingleGeometry const& single_geometry, MultiPoint const& multi_point, Strategy const& strategy) + static inline bool apply(SingleGeometry const& single_geometry, MultiPoint const& multi_point, + Strategy const& strategy) { return apply(multi_point, single_geometry, strategy); } @@ -320,56 +321,77 @@ template class multi_point_multi_geometry { private: - template + template struct expand_box_point { + explicit expand_box_point(Strategy const& strategy) + : m_strategy(strategy) + {} + template - static inline void apply(Box& total, Point const& point) + void apply(Box& total, Point const& point) const { - geometry::expand(total, point, ExpandPointStrategy()); + geometry::expand(total, point, m_strategy); } + + Strategy const& m_strategy; }; - template + template struct expand_box_box_pair { + explicit expand_box_box_pair(Strategy const& strategy) + : m_strategy(strategy) + {} + template - inline void apply(Box& total, BoxPair const& box_pair) const + void apply(Box& total, BoxPair const& box_pair) const { - geometry::expand(total, box_pair.first, ExpandBoxStrategy()); + geometry::expand(total, box_pair.first, m_strategy); } + + Strategy const& m_strategy; }; - template + template struct overlaps_box_point { + explicit overlaps_box_point(Strategy const& strategy) + : m_strategy(strategy) + {} + template - static inline bool apply(Box const& box, Point const& point) + bool apply(Box const& box, Point const& point) const { - // The default strategy is enough for Point/Box - return ! detail::disjoint::disjoint_point_box(point, box, - DisjointPointBoxStrategy()); + return ! detail::disjoint::disjoint_point_box(point, box, m_strategy); } + + Strategy const& m_strategy; }; - template + template struct overlaps_box_box_pair { + explicit overlaps_box_box_pair(Strategy const& strategy) + : m_strategy(strategy) + {} + template - inline bool apply(Box const& box, BoxPair const& box_pair) const + bool apply(Box const& box, BoxPair const& box_pair) const { - // The default strategy is enough for Box/Box return ! detail::disjoint::disjoint_box_box(box_pair.first, box, - DisjointBoxBoxStrategy()); + m_strategy); } + + Strategy const& m_strategy; }; - template + template class item_visitor_type { public: item_visitor_type(MultiGeometry const& multi_geometry, - PtSegStrategy const& strategy) + Strategy const& strategy) : m_intersection_found(false) , m_multi_geometry(multi_geometry) , m_strategy(strategy) @@ -378,14 +400,15 @@ private: template inline bool apply(Point const& point, BoxPair const& box_pair) { - typedef typename PtSegStrategy::disjoint_point_box_strategy_type d_pb_strategy_type; - typedef typename boost::range_value::type single_type; // The default strategy is enough for Point/Box if (! m_intersection_found - && ! detail::disjoint::disjoint_point_box(point, box_pair.first, d_pb_strategy_type()) - && ! dispatch::disjoint::apply(point, range::at(m_multi_geometry, box_pair.second), m_strategy)) + && ! detail::disjoint::disjoint_point_box(point, box_pair.first, m_strategy) + && ! dispatch::disjoint + < + Point, single_type + >::apply(point, range::at(m_multi_geometry, box_pair.second), m_strategy)) { m_intersection_found = true; return false; @@ -398,7 +421,7 @@ private: private: bool m_intersection_found; MultiGeometry const& m_multi_geometry; - PtSegStrategy const& m_strategy; + Strategy const& m_strategy; }; // structs for partition -- end @@ -411,53 +434,26 @@ public: typedef model::box box1_type; typedef model::box box2_type; typedef std::pair box_pair_type; - - typename Strategy::envelope_strategy_type const - envelope_strategy = strategy.get_envelope_strategy(); std::size_t count2 = boost::size(multi_geometry); std::vector boxes(count2); for (std::size_t i = 0 ; i < count2 ; ++i) { - geometry::envelope(range::at(multi_geometry, i), boxes[i].first, envelope_strategy); + geometry::envelope(range::at(multi_geometry, i), boxes[i].first, strategy); geometry::detail::expand_by_epsilon(boxes[i].first); boxes[i].second = i; } item_visitor_type visitor(multi_geometry, strategy); - typedef expand_box_point - < - typename Strategy::expand_point_strategy_type - > expand_box_point_type; - typedef overlaps_box_point - < - typename Strategy::disjoint_point_box_strategy_type - > overlaps_box_point_type; - typedef expand_box_box_pair - < - // TEMP - envelope umbrella strategy also contains - // expand strategies - decltype(strategies::envelope::services::strategy_converter - < - typename Strategy::envelope_strategy_type - >::get(strategy.get_envelope_strategy()) - .expand(std::declval(), - std::declval())) - > expand_box_box_pair_type; - typedef overlaps_box_box_pair - < - typename Strategy::disjoint_box_box_strategy_type - > overlaps_box_box_pair_type; - geometry::partition < box1_type >::apply(multi_point, boxes, visitor, - expand_box_point_type(), - overlaps_box_point_type(), - expand_box_box_pair_type(), - overlaps_box_box_pair_type()); + expand_box_point(strategy), + overlaps_box_point(strategy), + expand_box_box_pair(strategy), + overlaps_box_box_pair(strategy)); return ! visitor.intersection_found(); } diff --git a/include/boost/geometry/algorithms/detail/disjoint/point_box.hpp b/include/boost/geometry/algorithms/detail/disjoint/point_box.hpp index b4c402646..99cdda9ed 100644 --- a/include/boost/geometry/algorithms/detail/disjoint/point_box.hpp +++ b/include/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-2018. -// Modifications copyright (c) 2013-2018, Oracle and/or its affiliates. +// This file was modified by Oracle on 2013-2020. +// Modifications copyright (c) 2013-2020, 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 @@ -41,8 +41,26 @@ namespace detail { namespace disjoint /*! \brief Internal utility function to detect if point/box are disjoint */ -template -inline bool disjoint_point_box(Point const& point, Box const& box, Strategy const& ) +template +< + typename Point, typename Box, typename Strategy, + std::enable_if_t::value, int> = 0 +> +inline bool disjoint_point_box(Point const& point, Box const& box, + Strategy const& strategy) +{ + typedef decltype(strategy.covered_by(point, box)) strategy_type; + // ! covered_by(point, box) + return ! strategy_type::apply(point, box); +} + +template +< + typename Point, typename Box, typename Strategy, + std::enable_if_t::value, int> = 0 +> +inline bool disjoint_point_box(Point const& point, Box const& box, + Strategy const& ) { // ! covered_by(point, box) return ! Strategy::apply(point, box); @@ -62,10 +80,12 @@ template struct disjoint { template - static inline bool apply(Point const& point, Box const& box, Strategy const& ) + static inline bool apply(Point const& point, Box const& box, + Strategy const& strategy) { + typedef decltype(strategy.covered_by(point, box)) strategy_type; // ! covered_by(point, box) - return ! Strategy::apply(point, box); + return ! strategy_type::apply(point, box); } }; diff --git a/include/boost/geometry/algorithms/detail/disjoint/point_point.hpp b/include/boost/geometry/algorithms/detail/disjoint/point_point.hpp index f91712934..af28ecaff 100644 --- a/include/boost/geometry/algorithms/detail/disjoint/point_point.hpp +++ b/include/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, 2017, 2018. -// Modifications copyright (c) 2013-2018, Oracle and/or its affiliates. +// This file was modified by Oracle on 2013-2020. +// Modifications copyright (c) 2013-2020, 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,11 +22,14 @@ #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_POINT_POINT_HPP #include +#include #include #include +#include + // For backward compatibility #include #include @@ -46,10 +49,28 @@ namespace detail { namespace disjoint \brief Internal utility function to detect of points are disjoint \note To avoid circular references */ -template +template +< + typename Point1, typename Point2, typename Strategy, + std::enable_if_t::value, int> = 0 +> +inline bool disjoint_point_point(Point1 const& point1, Point2 const& point2, + Strategy const& strategy) +{ + typedef decltype(strategy.relate(point1, point2)) strategy_type; + // ! within(point1, point2) + return ! strategy_type::apply(point1, point2); +} + +template +< + typename Point1, typename Point2, typename Strategy, + std::enable_if_t::value, int> = 0 +> inline bool disjoint_point_point(Point1 const& point1, Point2 const& point2, Strategy const& ) { + // ! within(point1, point2) return ! Strategy::apply(point1, point2); } @@ -68,9 +89,11 @@ struct disjoint { template static inline bool apply(Point1 const& point1, Point2 const& point2, - Strategy const& ) + Strategy const& strategy) { - return ! Strategy::apply(point1, point2); + typedef decltype(strategy.relate(point1, point2)) strategy_type; + // ! within(point1, point2) + return ! strategy_type::apply(point1, point2); } }; diff --git a/include/boost/geometry/algorithms/detail/disjoint/segment_box.hpp b/include/boost/geometry/algorithms/detail/disjoint/segment_box.hpp index ae89d1d6b..575e55bda 100644 --- a/include/boost/geometry/algorithms/detail/disjoint/segment_box.hpp +++ b/include/boost/geometry/algorithms/detail/disjoint/segment_box.hpp @@ -247,7 +247,7 @@ struct disjoint_segment_box Box const& box, Strategy const& strategy) { - return strategy.apply(segment, box); + return strategy.disjoint(segment, box).apply(segment, box); } }; diff --git a/include/boost/geometry/algorithms/detail/distance/point_to_geometry.hpp b/include/boost/geometry/algorithms/detail/distance/point_to_geometry.hpp index 6874fe2d7..1ca1ae1d7 100644 --- a/include/boost/geometry/algorithms/detail/distance/point_to_geometry.hpp +++ b/include/boost/geometry/algorithms/detail/distance/point_to_geometry.hpp @@ -41,6 +41,7 @@ #include #include +#include #include @@ -164,8 +165,12 @@ struct point_to_ring Strategy const& strategy) { // TODO: pass strategy - if (within::within_point_geometry(point, ring, - strategy.get_point_in_geometry_strategy())) + auto const s = strategies::relate::services::strategy_converter + < + decltype(strategy.get_point_in_geometry_strategy()) + >::get(strategy.get_point_in_geometry_strategy()); + + if (within::within_point_geometry(point, ring, s)) { return return_type(0); } @@ -207,11 +212,15 @@ private: InteriorRingIterator last, Strategy const& strategy) { + // TEMP: pass strategy + auto const s = strategies::relate::services::strategy_converter + < + decltype(strategy.get_point_in_geometry_strategy()) + >::get(strategy.get_point_in_geometry_strategy()); + for (InteriorRingIterator it = first; it != last; ++it) { - // TODO: pass strategy - if (within::within_point_geometry(point, *it, - strategy.get_point_in_geometry_strategy())) + if (within::within_point_geometry(point, *it, s)) { // the point is inside a polygon hole, so its distance // to the polygon its distance to the polygon's @@ -240,9 +249,13 @@ public: Polygon const& polygon, Strategy const& strategy) { - // TODO: pass strategy - if (! within::covered_by_point_geometry(point, exterior_ring(polygon), - strategy.get_point_in_geometry_strategy())) + // TEMP: pass strategy + auto const s = strategies::relate::services::strategy_converter + < + decltype(strategy.get_point_in_geometry_strategy()) + >::get(strategy.get_point_in_geometry_strategy()); + + if (! within::covered_by_point_geometry(point, exterior_ring(polygon), s)) { // the point is outside the exterior ring, so its distance // to the polygon is its distance to the polygon's exterior ring @@ -340,8 +353,12 @@ struct point_to_multigeometry Strategy const& strategy) { // TODO: pass strategy - if (within::covered_by_point_geometry(point, multipolygon, - strategy.get_point_in_geometry_strategy())) + auto const s = strategies::relate::services::strategy_converter + < + decltype(strategy.get_point_in_geometry_strategy()) + >::get(strategy.get_point_in_geometry_strategy()); + + if (within::covered_by_point_geometry(point, multipolygon, s)) { return 0; } diff --git a/include/boost/geometry/algorithms/detail/distance/segment_to_box.hpp b/include/boost/geometry/algorithms/detail/distance/segment_to_box.hpp index 1f381970d..296df7ef6 100644 --- a/include/boost/geometry/algorithms/detail/distance/segment_to_box.hpp +++ b/include/boost/geometry/algorithms/detail/distance/segment_to_box.hpp @@ -1,6 +1,6 @@ // Boost.Geometry (aka GGL, Generic Geometry Library) -// Copyright (c) 2014-2020 Oracle and/or its affiliates. +// Copyright (c) 2014-2021 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 @@ -48,6 +48,9 @@ #include #include +// TEMP - remove when distance umbrella strategies are implemented +#include + namespace boost { namespace geometry { @@ -58,17 +61,20 @@ namespace detail { namespace distance { -// TODO: Take strategy -template -inline bool intersects_segment_box(Segment const& segment, Box const& box) +template +inline bool intersects_segment_box(Segment const& segment, Box const& box, + Strategy const& strategy) { - typedef typename strategy::disjoint::services::default_strategy + // TODO: pass strategy + auto const s = strategies::relate::services::strategy_converter < - Segment, Box - >::type strategy_type; + // This is the only strategy defined in distance segment/box + // strategies that carries the information about the spheroid + // so use it for now. + decltype(strategy.get_side_strategy()) + >::get(strategy.get_side_strategy()); - return ! detail::disjoint::disjoint_segment_box::apply(segment, box, - strategy_type()); + return ! detail::disjoint::disjoint_segment_box::apply(segment, box, s); } @@ -114,7 +120,7 @@ public: Strategy const& strategy, bool check_intersection = true) { - if (check_intersection && intersects_segment_box(segment, box)) + if (check_intersection && intersects_segment_box(segment, box, strategy)) { return 0; } @@ -229,7 +235,7 @@ public: Strategy const& strategy, bool check_intersection = true) { - if (check_intersection && intersects_segment_box(segment, box)) + if (check_intersection && intersects_segment_box(segment, box, strategy)) { return 0; } diff --git a/include/boost/geometry/algorithms/detail/equals/implementation.hpp b/include/boost/geometry/algorithms/detail/equals/implementation.hpp index cb422cbc3..f51923474 100644 --- a/include/boost/geometry/algorithms/detail/equals/implementation.hpp +++ b/include/boost/geometry/algorithms/detail/equals/implementation.hpp @@ -64,9 +64,11 @@ template struct point_point { template - static inline bool apply(Point1 const& point1, Point2 const& point2, Strategy const& ) + static inline bool apply(Point1 const& point1, Point2 const& point2, + Strategy const& strategy) { - return Strategy::apply(point1, point2); + typedef decltype(strategy.relate(point1, point2)) strategy_type; + return strategy_type::apply(point1, point2); } }; @@ -107,25 +109,22 @@ struct segment_segment static inline bool apply(Segment1 const& segment1, Segment2 const& segment2, Strategy const& strategy) { - typename Strategy::point_in_point_strategy_type const& - pt_pt_strategy = strategy.get_point_in_point_strategy(); - return equals::equals_point_point( indexed_point_view(segment1), indexed_point_view(segment2), - pt_pt_strategy) + strategy) ? equals::equals_point_point( indexed_point_view(segment1), indexed_point_view(segment2), - pt_pt_strategy) + strategy) : ( equals::equals_point_point( indexed_point_view(segment1), indexed_point_view(segment2), - pt_pt_strategy) + strategy) && equals::equals_point_point( indexed_point_view(segment1), indexed_point_view(segment2), - pt_pt_strategy) + strategy) ); } }; @@ -138,15 +137,13 @@ struct area_check Geometry2 const& geometry2, Strategy const& strategy) { - return geometry::math::equals( - geometry::area(geometry1, - strategy.template get_area_strategy()), - geometry::area(geometry2, - strategy.template get_area_strategy())); + return geometry::math::equals(geometry::area(geometry1, strategy), + geometry::area(geometry2, strategy)); } }; +/* struct length_check { template @@ -154,16 +151,14 @@ struct length_check Geometry2 const& geometry2, Strategy const& strategy) { - return geometry::math::equals( - geometry::length(geometry1, - strategy.template get_distance_strategy()), - geometry::length(geometry2, - strategy.template get_distance_strategy())); + return geometry::math::equals(geometry::length(geometry1, strategy), + geometry::length(geometry2, strategy)); } }; +*/ -template +template struct collected_vector { typedef typename geometry::select_most_precise @@ -179,7 +174,7 @@ struct collected_vector < calculation_type, Geometry1, - typename IntersectionStrategy::side_strategy_type + decltype(std::declval().side()) > type; }; diff --git a/include/boost/geometry/algorithms/detail/equals/interface.hpp b/include/boost/geometry/algorithms/detail/equals/interface.hpp index 1e4918836..bd31e8c2c 100644 --- a/include/boost/geometry/algorithms/detail/equals/interface.hpp +++ b/include/boost/geometry/algorithms/detail/equals/interface.hpp @@ -5,9 +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, 2017, 2019. -// Modifications copyright (c) 2014-2019 Oracle and/or its affiliates. - +// This file was modified by Oracle on 2014-2021. +// Modifications copyright (c) 2014-2021 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 @@ -30,13 +29,16 @@ #include #include +#include +#include #include #include #include -#include +#include +#include namespace boost { namespace geometry @@ -94,9 +96,14 @@ struct equals::value +> struct equals { - template + template static inline bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2, Strategy const& strategy) @@ -106,13 +113,35 @@ struct equals Geometry1, Geometry2 >::apply(geometry1, geometry2, strategy); } +}; +template +struct equals +{ + template + static inline bool apply(Geometry1 const& geometry1, + Geometry2 const& geometry2, + Strategy const& strategy) + { + using strategies::relate::services::strategy_converter; + + return dispatch::equals + < + Geometry1, Geometry2 + >::apply(geometry1, geometry2, + strategy_converter::get(strategy)); + } +}; + +template <> +struct equals +{ template static inline bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2, default_strategy) { - typedef typename strategy::relate::services::default_strategy + typedef typename strategies::relate::services::default_strategy < Geometry1, Geometry2 @@ -145,7 +174,9 @@ struct equals >(); return resolve_strategy::equals - ::apply(geometry1, geometry2, strategy); + < + Strategy + >::apply(geometry1, geometry2, strategy); } }; diff --git a/include/boost/geometry/algorithms/detail/equals/point_point.hpp b/include/boost/geometry/algorithms/detail/equals/point_point.hpp index 06a784284..26eaff95c 100644 --- a/include/boost/geometry/algorithms/detail/equals/point_point.hpp +++ b/include/boost/geometry/algorithms/detail/equals/point_point.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-2018. -// Modifications copyright (c) 2013-2018, Oracle and/or its affiliates. +// This file was modified by Oracle on 2013-2020. +// Modifications copyright (c) 2013-2020, 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,6 +22,11 @@ #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_EQUALS_POINT_POINT_HPP +#include + +#include + + namespace boost { namespace geometry { @@ -33,7 +38,23 @@ namespace detail { namespace equals \brief Internal utility function to detect of points are disjoint \note To avoid circular references */ -template +template +< + typename Point1, typename Point2, typename Strategy, + std::enable_if_t::value, int> = 0 +> +inline bool equals_point_point(Point1 const& point1, Point2 const& point2, + Strategy const& strategy) +{ + typedef decltype(strategy.relate(point1, point2)) strategy_type; + return strategy_type::apply(point1, point2); +} + +template +< + typename Point1, typename Point2, typename Strategy, + std::enable_if_t::value, int> = 0 +> inline bool equals_point_point(Point1 const& point1, Point2 const& point2, Strategy const& ) { diff --git a/include/boost/geometry/algorithms/detail/has_self_intersections.hpp b/include/boost/geometry/algorithms/detail/has_self_intersections.hpp index 5dac1c3ff..805ab6754 100644 --- a/include/boost/geometry/algorithms/detail/has_self_intersections.hpp +++ b/include/boost/geometry/algorithms/detail/has_self_intersections.hpp @@ -136,27 +136,6 @@ inline bool has_self_intersections(Geometry const& geometry, return false; } -// For backward compatibility -template -inline bool has_self_intersections(Geometry const& geometry, - bool throw_on_self_intersection = true) -{ - typedef typename geometry::point_type::type point_type; - typedef typename geometry::rescale_policy_type::type - rescale_policy_type; - - typename strategy::intersection::services::default_strategy - < - typename cs_tag::type - >::type strategy; - - rescale_policy_type robust_policy - = geometry::get_rescale_policy(geometry, strategy); - - return has_self_intersections(geometry, strategy, robust_policy, - throw_on_self_intersection); -} - }} // namespace detail::overlay #endif // DOXYGEN_NO_DETAIL diff --git a/include/boost/geometry/algorithms/detail/intersection/areal_areal.hpp b/include/boost/geometry/algorithms/detail/intersection/areal_areal.hpp index 994c3c7da..9faa1df55 100644 --- a/include/boost/geometry/algorithms/detail/intersection/areal_areal.hpp +++ b/include/boost/geometry/algorithms/detail/intersection/areal_areal.hpp @@ -1,6 +1,6 @@ // Boost.Geometry -// Copyright (c) 2020, Oracle and/or its affiliates. +// Copyright (c) 2020-2021, Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle // Licensed under the Boost Software License version 1.0. @@ -109,10 +109,6 @@ struct intersection_areal_areal_ < areal::index, TupledOut >::type areal_out_type; - typedef typename geometry::tuples::element - < - pointlike::index, TupledOut - >::type pointlike_out_type; // NOTE: The same robust_policy is used in each call of // intersection_insert. Is that correct? @@ -157,11 +153,7 @@ struct intersection_areal_areal_ areal_out_boundary, robust_policy, pointlike::get(geometry_out), - strategy.template get_point_in_geometry_strategy - < - pointlike_out_type, - areal_out_boundary_type - >()); + strategy); } return; diff --git a/include/boost/geometry/algorithms/detail/intersection/interface.hpp b/include/boost/geometry/algorithms/detail/intersection/interface.hpp index e3258eb93..fcd7e959e 100644 --- a/include/boost/geometry/algorithms/detail/intersection/interface.hpp +++ b/include/boost/geometry/algorithms/detail/intersection/interface.hpp @@ -2,9 +2,8 @@ // Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. -// This file was modified by Oracle on 2014, 2017, 2019. -// Modifications copyright (c) 2014-2019, Oracle and/or its affiliates. - +// This file was modified by Oracle on 2014-2020. +// Modifications copyright (c) 2014-2020, 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, @@ -23,6 +22,8 @@ #include #include #include +#include +#include #include @@ -108,14 +109,18 @@ struct intersection namespace resolve_strategy { +template +< + typename Strategy, + bool IsUmbrella = strategies::detail::is_umbrella_strategy::value +> struct intersection { template < typename Geometry1, typename Geometry2, - typename GeometryOut, - typename Strategy + typename GeometryOut > static inline bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2, @@ -140,7 +145,34 @@ struct intersection >::apply(geometry1, geometry2, robust_policy, geometry_out, strategy); } +}; +template +struct intersection +{ + template + < + typename Geometry1, + typename Geometry2, + typename GeometryOut + > + static inline bool apply(Geometry1 const& geometry1, + Geometry2 const& geometry2, + GeometryOut & geometry_out, + Strategy const& strategy) + { + using strategies::relate::services::strategy_converter; + return intersection + < + decltype(strategy_converter::get(strategy)) + >::apply(geometry1, geometry2, geometry_out, + strategy_converter::get(strategy)); + } +}; + +template <> +struct intersection +{ template < typename Geometry1, @@ -152,28 +184,15 @@ struct intersection GeometryOut & geometry_out, default_strategy) { - typedef typename geometry::rescale_overlay_policy_type - < - Geometry1, - Geometry2, - typename geometry::cs_tag::type - >::type rescale_policy_type; - - typename strategy::relate::services::default_strategy + typedef typename strategies::relate::services::default_strategy < Geometry1, Geometry2 - >::type strategy; + >::type strategy_type; - rescale_policy_type robust_policy - = geometry::get_rescale_policy( - geometry1, geometry2, strategy); - - return dispatch::intersection + return intersection < - Geometry1, - Geometry2 - >::apply(geometry1, geometry2, robust_policy, geometry_out, - strategy); + strategy_type + >::apply(geometry1, geometry2, geometry_out, strategy_type()); } }; @@ -195,10 +214,10 @@ struct intersection concepts::check(); concepts::check(); - return resolve_strategy::intersection::apply(geometry1, - geometry2, - geometry_out, - strategy); + return resolve_strategy::intersection + < + Strategy + >::apply(geometry1, geometry2, geometry_out, strategy); } }; diff --git a/include/boost/geometry/algorithms/detail/intersects/implementation.hpp b/include/boost/geometry/algorithms/detail/intersects/implementation.hpp index cbb442ce4..76493f9d4 100644 --- a/include/boost/geometry/algorithms/detail/intersects/implementation.hpp +++ b/include/boost/geometry/algorithms/detail/intersects/implementation.hpp @@ -4,8 +4,8 @@ // Copyright (c) 2008-2014 Bruno Lalande, Paris, France. // Copyright (c) 2009-2014 Mateusz Loskot, London, UK. -// This file was modified by Oracle on 2013-2017. -// Modifications copyright (c) 2013-2017, Oracle and/or its affiliates. +// This file was modified by Oracle on 2013-2020. +// Modifications copyright (c) 2013-2020, 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 @@ -30,7 +30,7 @@ #include #include -#include +#include namespace boost { namespace geometry @@ -48,7 +48,7 @@ struct self_intersects concepts::check(); typedef typename geometry::point_type::type point_type; - typedef typename strategy::relate::services::default_strategy + typedef typename strategies::relate::services::default_strategy < Geometry, Geometry >::type strategy_type; diff --git a/include/boost/geometry/algorithms/detail/is_simple/areal.hpp b/include/boost/geometry/algorithms/detail/is_simple/areal.hpp index 9f75b6903..3c716331b 100644 --- a/include/boost/geometry/algorithms/detail/is_simple/areal.hpp +++ b/include/boost/geometry/algorithms/detail/is_simple/areal.hpp @@ -1,6 +1,6 @@ // Boost.Geometry (aka GGL, Generic Geometry Library) -// Copyright (c) 2014-2020, Oracle and/or its affiliates. +// Copyright (c) 2014-2021, 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 @@ -22,7 +22,6 @@ #include #include -#include #include #include @@ -38,54 +37,36 @@ namespace detail { namespace is_simple { -template -struct is_simple_ring +template +inline bool is_simple_ring(Ring const& ring, Strategy const& strategy) { - static inline bool apply(Ring const& ring) - { - simplicity_failure_policy policy; - return ! boost::empty(ring) - && ! detail::is_valid::has_duplicates - < - Ring, geometry::closure::value, CSTag - >::apply(ring, policy); - } -}; + simplicity_failure_policy policy; + return ! boost::empty(ring) + && ! detail::is_valid::has_duplicates + < + Ring, geometry::closure::value + >::apply(ring, policy, strategy); +} - -template -class is_simple_polygon +template +inline bool are_simple_interior_rings(InteriorRings const& interior_rings, + Strategy const& strategy) { -private: - template - static inline - bool are_simple_interior_rings(InteriorRings const& interior_rings) - { - return - detail::check_iterator_range - < - is_simple_ring - < - typename boost::range_value::type, - CSTag - > - >::apply(boost::begin(interior_rings), - boost::end(interior_rings)); - } + auto const end = boost::end(interior_rings); + return std::find_if(boost::begin(interior_rings), end, + [&](auto const& r) + { + return ! is_simple_ring(r, strategy); + }) == end; // non-simple ring not found + // allow empty ring +} -public: - static inline bool apply(Polygon const& polygon) - { - return - is_simple_ring - < - typename ring_type::type, - CSTag - >::apply(exterior_ring(polygon)) - && - are_simple_interior_rings(geometry::interior_rings(polygon)); - } -}; +template +inline bool is_simple_polygon(Polygon const& polygon, Strategy const& strategy) +{ + return is_simple_ring(geometry::exterior_ring(polygon), strategy) + && are_simple_interior_rings(geometry::interior_rings(polygon), strategy); +} }} // namespace detail::is_simple @@ -107,13 +88,9 @@ template struct is_simple { template - static inline bool apply(Ring const& ring, Strategy const&) + static inline bool apply(Ring const& ring, Strategy const& strategy) { - return detail::is_simple::is_simple_ring - < - Ring, - typename Strategy::cs_tag - >::apply(ring); + return detail::is_simple::is_simple_ring(ring, strategy); } }; @@ -125,13 +102,9 @@ template struct is_simple { template - static inline bool apply(Polygon const& polygon, Strategy const&) + static inline bool apply(Polygon const& polygon, Strategy const& strategy) { - return detail::is_simple::is_simple_polygon - < - Polygon, - typename Strategy::cs_tag - >::apply(polygon); + return detail::is_simple::is_simple_polygon(polygon, strategy); } }; @@ -144,18 +117,14 @@ template struct is_simple { template - static inline bool apply(MultiPolygon const& multipolygon, Strategy const&) + static inline bool apply(MultiPolygon const& multipolygon, Strategy const& strategy) { - return - detail::check_iterator_range - < - detail::is_simple::is_simple_polygon - < - typename boost::range_value::type, - typename Strategy::cs_tag - >, - true // allow empty multi-polygon - >::apply(boost::begin(multipolygon), boost::end(multipolygon)); + auto const end = boost::end(multipolygon); + return std::find_if(boost::begin(multipolygon), end, + [&](auto const& po) { + return ! detail::is_simple::is_simple_polygon(po, strategy); + }) == end; // non-simple polygon not found + // allow empty multi-polygon } }; diff --git a/include/boost/geometry/algorithms/detail/is_simple/interface.hpp b/include/boost/geometry/algorithms/detail/is_simple/interface.hpp index af0127dc7..7703b9ec6 100644 --- a/include/boost/geometry/algorithms/detail/is_simple/interface.hpp +++ b/include/boost/geometry/algorithms/detail/is_simple/interface.hpp @@ -1,6 +1,6 @@ // Boost.Geometry (aka GGL, Generic Geometry Library) -// Copyright (c) 2014-2017, Oracle and/or its affiliates. +// Copyright (c) 2014-2020, 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 @@ -20,7 +20,8 @@ #include #include #include -#include +#include +#include namespace boost { namespace geometry @@ -29,23 +30,47 @@ namespace boost { namespace geometry namespace resolve_strategy { +template +< + typename Strategy, + bool IsUmbrella = strategies::detail::is_umbrella_strategy::value +> struct is_simple { - template + template static inline bool apply(Geometry const& geometry, Strategy const& strategy) { return dispatch::is_simple::apply(geometry, strategy); } +}; +template +struct is_simple +{ + template + static inline bool apply(Geometry const& geometry, + Strategy const& strategy) + { + using strategies::relate::services::strategy_converter; + return dispatch::is_simple + < + Geometry + >::apply(geometry, strategy_converter::get(strategy)); + } +}; + +template <> +struct is_simple +{ template 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 + typedef typename strategies::relate::services::default_strategy < - typename cs_tag::type + Geometry, Geometry >::type strategy_type; return dispatch::is_simple::apply(geometry, strategy_type()); @@ -65,7 +90,7 @@ struct is_simple { concepts::check(); - return resolve_strategy::is_simple::apply(geometry, strategy); + return resolve_strategy::is_simple::apply(geometry, strategy); } }; diff --git a/include/boost/geometry/algorithms/detail/is_simple/linear.hpp b/include/boost/geometry/algorithms/detail/is_simple/linear.hpp index bb1c5a51b..1ae040975 100644 --- a/include/boost/geometry/algorithms/detail/is_simple/linear.hpp +++ b/include/boost/geometry/algorithms/detail/is_simple/linear.hpp @@ -221,8 +221,7 @@ inline bool has_self_intersections(Linear const& linear, Strategy const& strateg typedef is_acceptable_turn < - Linear, - typename Strategy::equals_point_point_strategy_type + Linear, Strategy > is_acceptable_turn_type; is_acceptable_turn_type predicate(linear); @@ -259,12 +258,12 @@ struct is_simple_linestring return ! boost::empty(linestring) && ! detail::is_valid::has_duplicates < - Linestring, closed, typename Strategy::cs_tag - >::apply(linestring, policy) + Linestring, closed + >::apply(linestring, policy, strategy) && ! detail::is_valid::has_spikes < Linestring, closed - >::apply(linestring, policy, strategy.get_side_strategy()); + >::apply(linestring, policy, strategy); } }; diff --git a/include/boost/geometry/algorithms/detail/is_simple/multipoint.hpp b/include/boost/geometry/algorithms/detail/is_simple/multipoint.hpp index 3ef7778b8..536a9e5ed 100644 --- a/include/boost/geometry/algorithms/detail/is_simple/multipoint.hpp +++ b/include/boost/geometry/algorithms/detail/is_simple/multipoint.hpp @@ -42,7 +42,7 @@ template struct is_simple_multipoint { template - static inline bool apply(MultiPoint const& multipoint, Strategy const&) + static inline bool apply(MultiPoint const& multipoint, Strategy const& strategy) { typedef typename Strategy::cs_tag cs_tag; typedef geometry::less @@ -61,10 +61,10 @@ struct is_simple_multipoint std::sort(boost::begin(mp), boost::end(mp), less_type()); simplicity_failure_policy policy; - return !detail::is_valid::has_duplicates + return ! detail::is_valid::has_duplicates < - MultiPoint, closed, cs_tag - >::apply(mp, policy); + MultiPoint, closed + >::apply(mp, policy, strategy); } }; diff --git a/include/boost/geometry/algorithms/detail/is_valid/has_duplicates.hpp b/include/boost/geometry/algorithms/detail/is_valid/has_duplicates.hpp index ca0a7c48b..36391baf8 100644 --- a/include/boost/geometry/algorithms/detail/is_valid/has_duplicates.hpp +++ b/include/boost/geometry/algorithms/detail/is_valid/has_duplicates.hpp @@ -33,11 +33,12 @@ namespace boost { namespace geometry namespace detail { namespace is_valid { -template +template struct has_duplicates { - template - static inline bool apply(Range const& range, VisitPolicy& visitor) + template + static inline bool apply(Range const& range, VisitPolicy& visitor, + Strategy const& ) { boost::ignore_unused(visitor); @@ -58,7 +59,7 @@ struct has_duplicates < typename boost::range_value::type, -1, - CSTag + typename Strategy::cs_tag > equal; const_iterator it = boost::const_begin(view); diff --git a/include/boost/geometry/algorithms/detail/is_valid/has_spikes.hpp b/include/boost/geometry/algorithms/detail/is_valid/has_spikes.hpp index 18f5626b5..574d4bdfc 100644 --- a/include/boost/geometry/algorithms/detail/is_valid/has_spikes.hpp +++ b/include/boost/geometry/algorithms/detail/is_valid/has_spikes.hpp @@ -45,64 +45,27 @@ namespace boost { namespace geometry namespace detail { namespace is_valid { -template -struct equal_to -{ - Point const& m_point; - - equal_to(Point const& point) - : m_point(point) - {} - - template - inline bool operator()(OtherPoint const& other) const - { - return geometry::detail::equals::equals_point_point(m_point, other, Strategy()); - } -}; - -template -struct not_equal_to -{ - Point const& m_point; - - not_equal_to(Point const& point) - : m_point(point) - {} - - template - inline bool operator()(OtherPoint const& other) const - { - return ! geometry::detail::equals::equals_point_point(other, m_point, Strategy()); - } -}; - - template struct has_spikes { - template + template static inline Iterator find_different_from_first(Iterator first, Iterator last, - SideStrategy const& ) + Strategy const& strategy) { - typedef not_equal_to - < - typename point_type::type, - typename SideStrategy::equals_point_point_strategy_type - > not_equal; - - BOOST_GEOMETRY_ASSERT(first != last); - - Iterator second = first; - ++second; - return std::find_if(second, last, not_equal(*first)); + if (first == last) + return last; + auto const& front = *first; + ++first; + return std::find_if(first, last, [&](auto const& pt) { + return ! equals::equals_point_point(pt, front, strategy); + }); } - template + template static inline bool apply_at_closure(View const& view, VisitPolicy& visitor, - SideStrategy const& strategy, + Strategy const& strategy, bool is_linear) { boost::ignore_unused(visitor); @@ -119,10 +82,9 @@ struct has_spikes iterator next = find_different_from_first(cur, boost::end(view), strategy); - if (detail::is_spike_or_equal(*next, *cur, *prev, strategy)) + if (detail::is_spike_or_equal(*next, *cur, *prev, strategy.side())) { - return - ! visitor.template apply(is_linear, *cur); + return ! visitor.template apply(is_linear, *cur); } else { @@ -131,9 +93,9 @@ struct has_spikes } - template + template static inline bool apply(Range const& range, VisitPolicy& visitor, - SideStrategy const& strategy) + Strategy const& strategy) { boost::ignore_unused(visitor); @@ -169,7 +131,7 @@ struct has_spikes // in is_spike_or_equal, but this order calls the side // strategy in the way to correctly detect the spikes, // also in geographic cases going over the pole - if (detail::is_spike_or_equal(*next, *cur, *prev, strategy)) + if (detail::is_spike_or_equal(*next, *cur, *prev, strategy.side())) { return ! visitor.template apply(is_linestring, *cur); @@ -179,9 +141,8 @@ struct has_spikes next = find_different_from_first(cur, boost::end(view), strategy); } - if (geometry::detail::equals:: - equals_point_point(range::front(view), range::back(view), - strategy.get_equals_point_point_strategy())) + if (equals::equals_point_point(range::front(view), range::back(view), + strategy)) { return apply_at_closure(view, visitor, strategy, is_linestring); } diff --git a/include/boost/geometry/algorithms/detail/is_valid/has_valid_self_turns.hpp b/include/boost/geometry/algorithms/detail/is_valid/has_valid_self_turns.hpp index 348dba904..6c33961b3 100644 --- a/include/boost/geometry/algorithms/detail/is_valid/has_valid_self_turns.hpp +++ b/include/boost/geometry/algorithms/detail/is_valid/has_valid_self_turns.hpp @@ -41,7 +41,7 @@ namespace detail { namespace is_valid template < typename Geometry, - typename CSTag + typename CSTag // TODO: remove > class has_valid_self_turns { diff --git a/include/boost/geometry/algorithms/detail/is_valid/interface.hpp b/include/boost/geometry/algorithms/detail/is_valid/interface.hpp index e7f5c5783..4f8d1f543 100644 --- a/include/boost/geometry/algorithms/detail/is_valid/interface.hpp +++ b/include/boost/geometry/algorithms/detail/is_valid/interface.hpp @@ -1,6 +1,6 @@ // Boost.Geometry -// Copyright (c) 2014-2018, Oracle and/or its affiliates. +// Copyright (c) 2014-2020, 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 @@ -25,7 +25,8 @@ #include #include #include -#include +#include +#include namespace boost { namespace geometry @@ -34,9 +35,14 @@ namespace boost { namespace geometry namespace resolve_strategy { +template +< + typename Strategy, + bool IsUmbrella = strategies::detail::is_umbrella_strategy::value +> struct is_valid { - template + template static inline bool apply(Geometry const& geometry, VisitPolicy& visitor, Strategy const& strategy) @@ -44,18 +50,41 @@ struct is_valid return dispatch::is_valid::apply(geometry, visitor, strategy); } +}; + +template +struct is_valid +{ + template + static inline bool apply(Geometry const& geometry, + VisitPolicy& visitor, + Strategy const& strategy) + { + using strategies::relate::services::strategy_converter; + return dispatch::is_valid + < + Geometry + >::apply(geometry, visitor, + strategy_converter::get(strategy)); + } +}; + +template <> +struct is_valid +{ template 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 + typedef typename strategies::relate::services::default_strategy < - typename cs_tag::type + Geometry, Geometry >::type strategy_type; - return dispatch::is_valid::apply(geometry, visitor, strategy_type()); + return dispatch::is_valid::apply(geometry, visitor, + strategy_type()); } }; @@ -74,7 +103,10 @@ struct is_valid { concepts::check(); - return resolve_strategy::is_valid::apply(geometry, visitor, strategy); + return resolve_strategy::is_valid + < + Strategy + >::apply(geometry, visitor, strategy); } }; diff --git a/include/boost/geometry/algorithms/detail/is_valid/linear.hpp b/include/boost/geometry/algorithms/detail/is_valid/linear.hpp index b2905732c..7176cc469 100644 --- a/include/boost/geometry/algorithms/detail/is_valid/linear.hpp +++ b/include/boost/geometry/algorithms/detail/is_valid/linear.hpp @@ -64,15 +64,8 @@ struct is_valid_linestring std::size_t num_distinct = detail::num_distinct_consecutive_points < - Linestring, - 3u, - true, - not_equal_to - < - typename point_type::type, - typename Strategy::equals_point_point_strategy_type - > - >::apply(linestring); + Linestring, 3u, true + >::apply(linestring, strategy); if (num_distinct < 2u) { @@ -93,8 +86,7 @@ struct is_valid_linestring return ! has_spikes < Linestring, closed - >::apply(linestring, visitor, - strategy.get_side_strategy()); + >::apply(linestring, visitor, strategy); } }; diff --git a/include/boost/geometry/algorithms/detail/is_valid/multipolygon.hpp b/include/boost/geometry/algorithms/detail/is_valid/multipolygon.hpp index d0b4264c7..0b3b4c4a7 100644 --- a/include/boost/geometry/algorithms/detail/is_valid/multipolygon.hpp +++ b/include/boost/geometry/algorithms/detail/is_valid/multipolygon.hpp @@ -118,14 +118,6 @@ private: } } - // prepare strategies - typedef typename Strategy::envelope_strategy_type envelope_strategy_type; - envelope_strategy_type const envelope_strategy - = strategy.get_envelope_strategy(); - typedef typename Strategy::disjoint_box_box_strategy_type disjoint_box_box_strategy_type; - disjoint_box_box_strategy_type const disjoint_strategy - = strategy.get_disjoint_box_box_strategy(); - // call partition to check if polygons are disjoint from each other typename base::template item_visitor_type item_visitor(strategy); @@ -133,15 +125,8 @@ private: < geometry::model::box::type> >::apply(polygon_iterators, item_visitor, - typename base::template expand_box - < - envelope_strategy_type - >(envelope_strategy), - typename base::template overlaps_box - < - envelope_strategy_type, - disjoint_box_box_strategy_type - >(envelope_strategy, disjoint_strategy)); + typename base::template expand_box(strategy), + typename base::template overlaps_box(strategy)); if (item_visitor.items_overlap) { diff --git a/include/boost/geometry/algorithms/detail/is_valid/polygon.hpp b/include/boost/geometry/algorithms/detail/is_valid/polygon.hpp index ea27b23d2..72ae593f8 100644 --- a/include/boost/geometry/algorithms/detail/is_valid/polygon.hpp +++ b/include/boost/geometry/algorithms/detail/is_valid/polygon.hpp @@ -185,10 +185,10 @@ protected: }; // structs for partition -- start - template + template struct expand_box { - explicit expand_box(EnvelopeStrategy const& strategy) + explicit expand_box(Strategy const& strategy) : m_strategy(strategy) {} @@ -197,46 +197,38 @@ protected: { geometry::expand(total, item.get_envelope(m_strategy), - // TEMP - envelope umbrella strategy also contains - // expand strategies - strategies::envelope::services::strategy_converter - < - EnvelopeStrategy - >::get(m_strategy)); + m_strategy); } - EnvelopeStrategy const& m_strategy; + Strategy const& m_strategy; }; - template + template struct overlaps_box { - explicit overlaps_box(EnvelopeStrategy const& envelope_strategy, - DisjointBoxBoxStrategy const& disjoint_strategy) - : m_envelope_strategy(envelope_strategy) - , m_disjoint_strategy(disjoint_strategy) + explicit overlaps_box(Strategy const& strategy) + : m_strategy(strategy) {} template inline bool apply(Box const& box, partition_item const& item) const { - return ! geometry::disjoint(item.get_envelope(m_envelope_strategy), + return ! geometry::disjoint(item.get_envelope(m_strategy), box, - m_disjoint_strategy); + m_strategy); } - EnvelopeStrategy const& m_envelope_strategy; - DisjointBoxBoxStrategy const& m_disjoint_strategy; + Strategy const& m_strategy; }; - template + template struct item_visitor_type { bool items_overlap; - WithinStrategy const& m_strategy; + Strategy const& m_strategy; - explicit item_visitor_type(WithinStrategy const& strategy) + explicit item_visitor_type(Strategy const& strategy) : items_overlap(false) , m_strategy(strategy) {} @@ -299,14 +291,6 @@ protected: } } - // prepare strategy - typedef typename std::iterator_traits::value_type inter_ring_type; - typename Strategy::template point_in_geometry_strategy - < - inter_ring_type, ExteriorRing - >::type const in_exterior_strategy - = strategy.template get_point_in_geometry_strategy(); - signed_size_type ring_index = 0; for (RingIterator it = rings_first; it != rings_beyond; ++it, ++ring_index) @@ -314,7 +298,7 @@ protected: // do not examine interior rings that have turns with the // exterior ring if (ring_indices.find(ring_index) == ring_indices.end() - && ! geometry::covered_by(range::front(*it), exterior_ring, in_exterior_strategy)) + && ! geometry::covered_by(range::front(*it), exterior_ring, strategy)) { return visitor.template apply(); } @@ -342,14 +326,6 @@ protected: } } - // prepare strategies - typedef typename Strategy::envelope_strategy_type envelope_strategy_type; - envelope_strategy_type const envelope_strategy - = strategy.get_envelope_strategy(); - typedef typename Strategy::disjoint_box_box_strategy_type disjoint_box_box_strategy_type; - disjoint_box_box_strategy_type const disjoint_strategy - = strategy.get_disjoint_box_box_strategy(); - // call partition to check if interior rings are disjoint from // each other item_visitor_type item_visitor(strategy); @@ -358,15 +334,8 @@ protected: < box_type >::apply(ring_iterators, item_visitor, - expand_box - < - envelope_strategy_type - >(envelope_strategy), - overlaps_box - < - envelope_strategy_type, - disjoint_box_box_strategy_type - >(envelope_strategy, disjoint_strategy)); + expand_box(strategy), + overlaps_box(strategy)); if (item_visitor.items_overlap) { diff --git a/include/boost/geometry/algorithms/detail/is_valid/ring.hpp b/include/boost/geometry/algorithms/detail/is_valid/ring.hpp index 9238780cf..bfa79fb54 100644 --- a/include/boost/geometry/algorithms/detail/is_valid/ring.hpp +++ b/include/boost/geometry/algorithms/detail/is_valid/ring.hpp @@ -92,21 +92,7 @@ struct is_topologically_closed }; - -template -struct ring_area_predicate -{ - typedef std::greater type; -}; - -template -struct ring_area_predicate -{ - typedef std::less type; -}; - - - +// TODO: use calculate_point_order here template struct is_properly_oriented { @@ -122,25 +108,15 @@ struct is_properly_oriented geometry::closure::value > ring_area_type; - typedef typename Strategy::template area_strategy + std::conditional_t < - Ring - >::type::template result_type::type area_result_type; - - typename ring_area_predicate - < - area_result_type, IsInteriorRing - >::type predicate; + IsInteriorRing, std::less<>, std::greater<> + > predicate; // Check area - area_result_type const zero = 0; - area_result_type const area - = ring_area_type::apply(ring, - // TEMP - in the future (umbrella) strategy will be passed here - geometry::strategies::area::services::strategy_converter - < - decltype(strategy.template get_area_strategy()) - >::get(strategy.template get_area_strategy())); + auto const area = ring_area_type::apply(ring, strategy); + decltype(area) const zero = 0; + if (predicate(area, zero)) { return visitor.template apply(); @@ -166,8 +142,6 @@ struct is_valid_ring static inline bool apply(Ring const& ring, VisitPolicy& visitor, Strategy const& strategy) { - typedef typename Strategy::cs_tag cs_tag; - // return invalid if any of the following condition holds: // (a) the ring's point coordinates are not invalid (e.g., NaN) // (b) the ring's size is below the minimal one @@ -199,13 +173,8 @@ struct is_valid_ring view_type const view(ring); if (detail::num_distinct_consecutive_points < - view_type, 4u, true, - not_equal_to - < - typename point_type::type, - typename Strategy::equals_point_point_strategy_type - > - >::apply(view) + view_type, 4u, true + >::apply(view, strategy) < 4u) { return @@ -213,9 +182,9 @@ struct is_valid_ring } return - is_topologically_closed::apply(ring, visitor, strategy.get_equals_point_point_strategy()) - && ! has_duplicates::apply(ring, visitor) - && ! has_spikes::apply(ring, visitor, strategy.get_side_strategy()) + is_topologically_closed::apply(ring, visitor, strategy) + && ! has_duplicates::apply(ring, visitor, strategy) + && ! has_spikes::apply(ring, visitor, strategy) && (! CheckSelfIntersections || has_valid_self_turns::apply(ring, visitor, strategy)) && is_properly_oriented::apply(ring, visitor, strategy); diff --git a/include/boost/geometry/algorithms/detail/is_valid/segment.hpp b/include/boost/geometry/algorithms/detail/is_valid/segment.hpp index 244a6ff3b..b1d27dafd 100644 --- a/include/boost/geometry/algorithms/detail/is_valid/segment.hpp +++ b/include/boost/geometry/algorithms/detail/is_valid/segment.hpp @@ -45,10 +45,8 @@ template struct is_valid { template - static inline bool apply(Segment const& segment, VisitPolicy& visitor, Strategy const&) + static inline bool apply(Segment const& segment, VisitPolicy& visitor, Strategy const& strategy) { - typedef typename Strategy::equals_point_point_strategy_type eq_pp_strategy_type; - boost::ignore_unused(visitor); typename point_type::type p[2]; @@ -62,8 +60,7 @@ struct is_valid { return false; } - else if (! geometry::detail::equals::equals_point_point( - p[0], p[1], eq_pp_strategy_type())) + else if (! detail::equals::equals_point_point(p[0], p[1], strategy)) { return visitor.template apply(); } diff --git a/include/boost/geometry/algorithms/detail/num_distinct_consecutive_points.hpp b/include/boost/geometry/algorithms/detail/num_distinct_consecutive_points.hpp index ca5ac20b8..5acc531d3 100644 --- a/include/boost/geometry/algorithms/detail/num_distinct_consecutive_points.hpp +++ b/include/boost/geometry/algorithms/detail/num_distinct_consecutive_points.hpp @@ -41,12 +41,12 @@ template < typename Range, std::size_t MaximumNumber, - bool AllowDuplicates /* true */, - typename NotEqualTo + bool AllowDuplicates /* true */ > struct num_distinct_consecutive_points { - static inline std::size_t apply(Range const& range) + template + static inline std::size_t apply(Range const& range, Strategy const& strategy) { typedef typename boost::range_iterator::type iterator; @@ -58,26 +58,28 @@ struct num_distinct_consecutive_points } iterator current = boost::begin(range); + iterator const end = boost::end(range); std::size_t counter(0); do { ++counter; - iterator next = std::find_if(current, - boost::end(range), - NotEqualTo(*current)); + iterator next = std::find_if(current, end, [&](auto const& pt) { + return ! equals::equals_point_point(pt, *current, strategy); + }); current = next; } - while ( current != boost::end(range) && counter <= MaximumNumber ); + while ( current != end && counter <= MaximumNumber ); return counter; } }; -template -struct num_distinct_consecutive_points +template +struct num_distinct_consecutive_points { - static inline std::size_t apply(Range const& range) + template + static inline std::size_t apply(Range const& range, Strategy const&) { std::size_t const size = boost::size(range); return (size < MaximumNumber) ? size : MaximumNumber; diff --git a/include/boost/geometry/algorithms/detail/overlaps/interface.hpp b/include/boost/geometry/algorithms/detail/overlaps/interface.hpp index 088b51fe2..fbe0ffdae 100644 --- a/include/boost/geometry/algorithms/detail/overlaps/interface.hpp +++ b/include/boost/geometry/algorithms/detail/overlaps/interface.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, 2017. -// Modifications copyright (c) 2014-2017 Oracle and/or its affiliates. +// This file was modified by Oracle on 2014-2021. +// Modifications copyright (c) 2014-2021 Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle @@ -28,7 +28,9 @@ #include -#include +#include +#include +#include namespace boost { namespace geometry @@ -60,6 +62,68 @@ struct overlaps #endif // DOXYGEN_NO_DISPATCH +namespace resolve_strategy +{ + +template +< + typename Strategy, + bool IsUmbrella = strategies::detail::is_umbrella_strategy::value +> +struct overlaps +{ + template + static inline bool apply(Geometry1 const& geometry1, + Geometry2 const& geometry2, + Strategy const& strategy) + { + return dispatch::overlaps + < + Geometry1, Geometry2 + >::apply(geometry1, geometry2, strategy); + } +}; + +template +struct overlaps +{ + template + static inline bool apply(Geometry1 const& geometry1, + Geometry2 const& geometry2, + Strategy const& strategy) + { + using strategies::relate::services::strategy_converter; + return dispatch::overlaps + < + Geometry1, Geometry2 + >::apply(geometry1, geometry2, + strategy_converter::get(strategy)); + } +}; + +template <> +struct overlaps +{ + template + static inline bool apply(Geometry1 const& geometry1, + Geometry2 const& geometry2, + default_strategy) + { + typedef typename strategies::relate::services::default_strategy + < + Geometry1, Geometry2 + >::type strategy_type; + + return dispatch::overlaps + < + Geometry1, Geometry2 + >::apply(geometry1, geometry2, strategy_type()); + } +}; + +} // namespace resolve_strategy + + /*! \brief \brief_check2{overlap} \ingroup overlaps @@ -82,10 +146,9 @@ inline bool overlaps(Geometry1 const& geometry1, concepts::check(); concepts::check(); - return dispatch::overlaps + return resolve_strategy::overlaps < - Geometry1, - Geometry2 + Strategy >::apply(geometry1, geometry2, strategy); } @@ -111,17 +174,10 @@ inline bool overlaps(Geometry1 const& geometry1, Geometry2 const& geometry2) concepts::check(); concepts::check(); - typedef typename strategy::relate::services::default_strategy - < - Geometry1, - Geometry2 - >::type strategy_type; - - return dispatch::overlaps + return resolve_strategy::overlaps < - Geometry1, - Geometry2 - >::apply(geometry1, geometry2, strategy_type()); + default_strategy + >::apply(geometry1, geometry2, default_strategy()); } }} // namespace boost::geometry diff --git a/include/boost/geometry/algorithms/detail/overlay/add_rings.hpp b/include/boost/geometry/algorithms/detail/overlay/add_rings.hpp index 3f33bb45a..45f2e7f12 100644 --- a/include/boost/geometry/algorithms/detail/overlay/add_rings.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/add_rings.hpp @@ -87,22 +87,17 @@ template typename Geometry2, typename RingCollection, typename OutputIterator, - typename AreaStrategy + typename Strategy > inline OutputIterator add_rings(SelectionMap const& map, Geometry1 const& geometry1, Geometry2 const& geometry2, RingCollection const& collection, OutputIterator out, - AreaStrategy const& area_strategy, + Strategy const& strategy, add_rings_error_handling error_handling = add_rings_ignore_unordered) { typedef typename SelectionMap::const_iterator iterator; - typedef typename AreaStrategy::template result_type - < - GeometryOut - >::type area_type; - area_type const zero = 0; std::size_t const min_num_points = core_detail::closure::minimum_ring_size < geometry::closure @@ -146,7 +141,9 @@ inline OutputIterator add_rings(SelectionMap const& map, // everything is figured out yet (sum of positive/negative rings) if (geometry::num_points(result) >= min_num_points) { - area_type const area = geometry::area(result, area_strategy); + typedef typename geometry::area_result::type area_type; + area_type const area = geometry::area(result, strategy); + area_type const zero = 0; // Ignore if area is 0 if (! math::equals(area, zero)) { @@ -174,16 +171,16 @@ template typename Geometry, typename RingCollection, typename OutputIterator, - typename AreaStrategy + typename Strategy > inline OutputIterator add_rings(SelectionMap const& map, Geometry const& geometry, RingCollection const& collection, OutputIterator out, - AreaStrategy const& area_strategy) + Strategy const& strategy) { Geometry empty; - return add_rings(map, geometry, empty, collection, out, area_strategy); + return add_rings(map, geometry, empty, collection, out, strategy); } diff --git a/include/boost/geometry/algorithms/detail/overlay/append_no_duplicates.hpp b/include/boost/geometry/algorithms/detail/overlay/append_no_duplicates.hpp index c96d721b7..f833fe618 100644 --- a/include/boost/geometry/algorithms/detail/overlay/append_no_duplicates.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/append_no_duplicates.hpp @@ -40,9 +40,9 @@ inline void append_with_duplicates(Range& range, Point const& point) geometry::append(range, point); } -template +template inline void append_no_duplicates(Range& range, Point const& point, - EqPPStrategy const& strategy) + Strategy const& strategy) { if ( boost::empty(range) || ! geometry::detail::equals::equals_point_point(geometry::range::back(range), diff --git a/include/boost/geometry/algorithms/detail/overlay/append_no_dups_or_spikes.hpp b/include/boost/geometry/algorithms/detail/overlay/append_no_dups_or_spikes.hpp index 9466e4122..f304600c0 100644 --- a/include/boost/geometry/algorithms/detail/overlay/append_no_dups_or_spikes.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/append_no_dups_or_spikes.hpp @@ -41,11 +41,11 @@ namespace detail { namespace overlay { // TODO: move this / rename this -template +template inline bool points_equal_or_close(Point1 const& point1, - Point2 const& point2, - EqualsStrategy const& strategy, - RobustPolicy const& robust_policy) + Point2 const& point2, + Strategy const& strategy, + RobustPolicy const& robust_policy) { if (detail::equals::equals_point_point(point1, point2, strategy)) { @@ -79,10 +79,10 @@ inline bool points_equal_or_close(Point1 const& point1, } -template +template inline void append_no_dups_or_spikes(Range& range, Point const& point, - SideStrategy const& strategy, - RobustPolicy const& robust_policy) + Strategy const& strategy, + RobustPolicy const& robust_policy) { #ifdef BOOST_GEOMETRY_DEBUG_INTERSECTION std::cout << " add: (" @@ -93,8 +93,7 @@ inline void append_no_dups_or_spikes(Range& range, Point const& point, // for geometries >= 3 points. // So we have to check the first potential duplicate differently if ( boost::size(range) == 1 - && points_equal_or_close(*(boost::begin(range)), point, - strategy.get_equals_point_point_strategy(), + && points_equal_or_close(*(boost::begin(range)), point, strategy, robust_policy) ) { return; @@ -111,7 +110,7 @@ inline void append_no_dups_or_spikes(Range& range, Point const& point, && point_is_spike_or_equal(point, *(boost::end(range) - 3), *(boost::end(range) - 2), - strategy, + strategy.side(), // TODO: Pass strategy? robust_policy)) { // Use the Concept/traits, so resize and append again @@ -120,10 +119,10 @@ inline void append_no_dups_or_spikes(Range& range, Point const& point, } } -template +template inline void append_no_collinear(Range& range, Point const& point, - SideStrategy const& strategy, - RobustPolicy const& robust_policy) + Strategy const& strategy, + RobustPolicy const& robust_policy) { // Stricter version, not allowing any point in a linear row // (spike, continuation or same point) @@ -133,7 +132,7 @@ inline void append_no_collinear(Range& range, Point const& point, // So we have to check the first potential duplicate differently if ( boost::size(range) == 1 && points_equal_or_close(*(boost::begin(range)), point, - strategy.get_equals_point_point_strategy(), + strategy, robust_policy) ) { return; @@ -150,7 +149,7 @@ inline void append_no_collinear(Range& range, Point const& point, && point_is_collinear(point, *(boost::end(range) - 3), *(boost::end(range) - 2), - strategy, + strategy.side(), // TODO: Pass strategy? robust_policy)) { // Use the Concept/traits, so resize and append again @@ -159,10 +158,10 @@ inline void append_no_collinear(Range& range, Point const& point, } } -template +template inline void clean_closing_dups_and_spikes(Range& range, - SideStrategy const& strategy, - RobustPolicy const& robust_policy) + Strategy const& strategy, + RobustPolicy const& robust_policy) { std::size_t const minsize = core_detail::closure::minimum_ring_size @@ -195,7 +194,9 @@ inline void clean_closing_dups_and_spikes(Range& range, // Check if closing point is a spike (this is so if the second point is // considered as collinear w.r.t. the last segment) - if (point_is_collinear(*second, *ultimate, *first, strategy, robust_policy)) + if (point_is_collinear(*second, *ultimate, *first, + strategy.side(), // TODO: Pass strategy? + robust_policy)) { range::erase(range, first); if (BOOST_GEOMETRY_CONDITION(closed)) diff --git a/include/boost/geometry/algorithms/detail/overlay/assign_parents.hpp b/include/boost/geometry/algorithms/detail/overlay/assign_parents.hpp index ac43d9c07..a4cfac4dc 100644 --- a/include/boost/geometry/algorithms/detail/overlay/assign_parents.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/assign_parents.hpp @@ -127,27 +127,39 @@ struct ring_info_helper }; -template +template struct ring_info_helper_get_box { + ring_info_helper_get_box(Strategy const& strategy) + : m_strategy(strategy) + {} + template - static inline void apply(Box& total, InputItem const& item) + inline void apply(Box& total, InputItem const& item) const { assert_coordinate_type_equal(total, item.envelope); - geometry::expand(total, item.envelope, BoxExpandStrategy()); + geometry::expand(total, item.envelope, m_strategy); } + + Strategy const& m_strategy; }; -template +template struct ring_info_helper_overlaps_box { + ring_info_helper_overlaps_box(Strategy const& strategy) + : m_strategy(strategy) + {} + template - static inline bool apply(Box const& box, InputItem const& item) + inline bool apply(Box const& box, InputItem const& item) const { assert_coordinate_type_equal(box, item.envelope); return ! geometry::detail::disjoint::disjoint_box_box( - box, item.envelope, DisjointBoxBoxStrategy()); + box, item.envelope, m_strategy); } + + Strategy const& m_strategy; }; // Segments intersection Strategy @@ -196,8 +208,7 @@ struct assign_visitor { ring_info_type& inner_in_map = m_ring_map[inner.id]; - if (geometry::covered_by(inner_in_map.point, outer.envelope, - typename Strategy::disjoint_point_box_strategy_type()) + if (geometry::covered_by(inner_in_map.point, outer.envelope, m_strategy) && within_selected_input(inner_in_map, inner.id, outer.id, m_geometry1, m_geometry2, m_collection, m_strategy) @@ -244,10 +255,10 @@ inline void assign_parents(Geometry1 const& geometry1, typedef typename RingMap::mapped_type ring_info_type; typedef typename ring_info_type::point_type point_type; typedef model::box box_type; - typedef typename Strategy::template area_strategy + typedef typename geometry::area_result < - point_type - >::type::template result_type::type area_result_type; + point_type, Strategy // TODO: point_type is technically incorrect + >::type area_result_type; typedef typename RingMap::iterator map_iterator_type; @@ -273,15 +284,15 @@ inline void assign_parents(Geometry1 const& geometry1, { case 0 : geometry::envelope(get_ring::apply(it->first, geometry1), - item.envelope, strategy.get_envelope_strategy()); + item.envelope, strategy); break; case 1 : geometry::envelope(get_ring::apply(it->first, geometry2), - item.envelope, strategy.get_envelope_strategy()); + item.envelope, strategy); break; case 2 : geometry::envelope(get_ring::apply(it->first, collection), - item.envelope, strategy.get_envelope_strategy()); + item.envelope, strategy); break; } @@ -336,19 +347,12 @@ inline void assign_parents(Geometry1 const& geometry1, Strategy > visitor(geometry1, geometry2, collection, ring_map, strategy, check_for_orientation); - typedef ring_info_helper_get_box - < - typename Strategy::expand_box_strategy_type - > expand_box_type; - typedef ring_info_helper_overlaps_box - < - typename Strategy::disjoint_box_box_strategy_type - > overlaps_box_type; - geometry::partition < box_type - >::apply(vector, visitor, expand_box_type(), overlaps_box_type()); + >::apply(vector, visitor, + ring_info_helper_get_box(strategy), + ring_info_helper_overlaps_box(strategy)); } if (check_for_orientation) diff --git a/include/boost/geometry/algorithms/detail/overlay/copy_segment_point.hpp b/include/boost/geometry/algorithms/detail/overlay/copy_segment_point.hpp index 0e36cf004..154b2bb7f 100644 --- a/include/boost/geometry/algorithms/detail/overlay/copy_segment_point.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/copy_segment_point.hpp @@ -2,8 +2,8 @@ // Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. -// This file was modified by Oracle on 2020. -// Modifications copyright (c) 2020, Oracle and/or its affiliates. +// This file was modified by Oracle on 2020-2021. +// Modifications copyright (c) 2020-2021, 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, @@ -29,7 +29,6 @@ #include #include #include -#include #include #include #include @@ -43,12 +42,22 @@ namespace boost { namespace geometry namespace detail { namespace copy_segments { +inline signed_size_type circular_offset(signed_size_type segment_count, signed_size_type index, + signed_size_type offset) +{ + signed_size_type result = (index + offset) % segment_count; + if (result < 0) + { + result += segment_count; + } + return result; +} template struct copy_segment_point_range { static inline bool apply(Range const& range, - SegmentIdentifier const& seg_id, int offset, + SegmentIdentifier const& seg_id, signed_size_type offset, PointOut& point) { typedef typename closeable_view @@ -66,15 +75,13 @@ struct copy_segment_point_range cview_type cview(range); rview_type view(cview); - typedef typename boost::range_iterator::type iterator; - geometry::ever_circling_iterator it(boost::begin(view), boost::end(view), - boost::begin(view) + seg_id.segment_index, true); + std::size_t const segment_count = boost::size(view) - 1; + signed_size_type const target = circular_offset(segment_count, seg_id.segment_index, offset); + BOOST_GEOMETRY_ASSERT(target >= 0 + && std::size_t(target) < boost::size(view)); - for (signed_size_type i = 0; i < offset; ++i, ++it) - { - } + geometry::convert(range::at(view, target), point); - geometry::convert(*it, point); return true; } }; @@ -84,7 +91,7 @@ template ::type, 4> bp; assign_box_corners_oriented(box, bp); - point = bp[index % 4]; + + signed_size_type const target = circular_offset(4, seg_id.segment_index, offset); + BOOST_GEOMETRY_ASSERT(target >= 0 + && std::size_t(target) < bp.size()); + + point = bp[target]; return true; } }; @@ -137,15 +143,11 @@ template struct copy_segment_point_multi { static inline bool apply(MultiGeometry const& multi, - SegmentIdentifier const& seg_id, int offset, + SegmentIdentifier const& seg_id, signed_size_type offset, PointOut& point) { - - BOOST_GEOMETRY_ASSERT - ( - seg_id.multi_index >= 0 - && seg_id.multi_index < int(boost::size(multi)) - ); + BOOST_GEOMETRY_ASSERT(seg_id.multi_index >= 0 + && std::size_t(seg_id.multi_index) < boost::size(multi)); // Call the single-version return Policy::apply(range::at(multi, seg_id.multi_index), seg_id, offset, point); @@ -278,16 +280,13 @@ struct copy_segment_point #endif // DOXYGEN_NO_DISPATCH - - - /*! \brief Helper function, copies a point from a segment \ingroup overlay */ template inline bool copy_segment_point(Geometry const& geometry, - SegmentIdentifier const& seg_id, int offset, + SegmentIdentifier const& seg_id, signed_size_type offset, PointOut& point_out) { concepts::check(); @@ -316,7 +315,7 @@ template typename PointOut > inline bool copy_segment_point(Geometry1 const& geometry1, Geometry2 const& geometry2, - SegmentIdentifier const& seg_id, int offset, + SegmentIdentifier const& seg_id, signed_size_type offset, PointOut& point_out) { concepts::check(); @@ -399,7 +398,6 @@ inline bool copy_segment_points(Geometry1 const& geometry1, Geometry2 const& geo } - }} // namespace boost::geometry #endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_COPY_SEGMENT_POINT_HPP diff --git a/include/boost/geometry/algorithms/detail/overlay/copy_segments.hpp b/include/boost/geometry/algorithms/detail/overlay/copy_segments.hpp index f6833da2c..d084e5984 100644 --- a/include/boost/geometry/algorithms/detail/overlay/copy_segments.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/copy_segments.hpp @@ -61,14 +61,14 @@ struct copy_segments_ring < typename Ring, typename SegmentIdentifier, - typename SideStrategy, + typename Strategy, typename RobustPolicy, typename RangeOut > static inline void apply(Ring const& ring, SegmentIdentifier const& seg_id, signed_size_type to_index, - SideStrategy const& strategy, + Strategy const& strategy, RobustPolicy const& robust_policy, RangeOut& current_output) { @@ -125,10 +125,10 @@ class copy_segments_linestring { private: // remove spikes - template + template static inline void append_to_output(RangeOut& current_output, Point const& point, - SideStrategy const& strategy, + Strategy const& strategy, RobustPolicy const& robust_policy, std::true_type const&) { @@ -138,14 +138,14 @@ private: } // keep spikes - template + template static inline void append_to_output(RangeOut& current_output, Point const& point, - SideStrategy const& strategy, + Strategy const& strategy, RobustPolicy const&, std::false_type const&) { - detail::overlay::append_no_duplicates(current_output, point, strategy.get_equals_point_point_strategy()); + detail::overlay::append_no_duplicates(current_output, point, strategy); } public: diff --git a/include/boost/geometry/algorithms/detail/overlay/enrich_intersection_points.hpp b/include/boost/geometry/algorithms/detail/overlay/enrich_intersection_points.hpp index c0c91d26f..cce0b62b7 100644 --- a/include/boost/geometry/algorithms/detail/overlay/enrich_intersection_points.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/enrich_intersection_points.hpp @@ -524,7 +524,7 @@ inline void enrich_intersection_points(Turns& turns, detail::overlay::enrich_sort( mit->second, turns, geometry1, geometry2, - robust_policy, strategy.get_side_strategy()); + robust_policy, strategy.side()); // TODO: pass strategy } for (typename mapped_vector_type::iterator mit @@ -554,7 +554,7 @@ inline void enrich_intersection_points(Turns& turns, Reverse2, OverlayType >(clusters, turns, target_operation, - geometry1, geometry2, strategy.get_side_strategy()); + geometry1, geometry2, strategy.side()); // TODO: pass strategy detail::overlay::cleanup_clusters(turns, clusters); } diff --git a/include/boost/geometry/algorithms/detail/overlay/follow.hpp b/include/boost/geometry/algorithms/detail/overlay/follow.hpp index 88512479c..afcd2bd82 100644 --- a/include/boost/geometry/algorithms/detail/overlay/follow.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/follow.hpp @@ -62,11 +62,11 @@ template typename Operation, typename LineString, typename Polygon, - typename PtInPolyStrategy + typename Strategy > inline bool last_covered_by(Turn const& /*turn*/, Operation const& op, LineString const& linestring, Polygon const& polygon, - PtInPolyStrategy const& strategy) + Strategy const& strategy) { return geometry::covered_by(range::at(linestring, op.seg_id.segment_index), polygon, strategy); } @@ -78,12 +78,12 @@ template typename Operation, typename LineString, typename Polygon, - typename PtInPolyStrategy + typename Strategy > inline bool is_leaving(Turn const& turn, Operation const& op, bool entered, bool first, LineString const& linestring, Polygon const& polygon, - PtInPolyStrategy const& strategy) + Strategy const& strategy) { if (op.operation == operation_union) { @@ -104,12 +104,12 @@ template typename Operation, typename LineString, typename Polygon, - typename PtInPolyStrategy + typename Strategy > inline bool is_staying_inside(Turn const& turn, Operation const& op, bool entered, bool first, LineString const& linestring, Polygon const& polygon, - PtInPolyStrategy const& strategy) + Strategy const& strategy) { if (turn.method == method_crosses) { @@ -132,11 +132,11 @@ template typename Operation, typename Linestring, typename Polygon, - typename PtInPolyStrategy + typename Strategy > inline bool was_entered(Turn const& turn, Operation const& op, bool first, Linestring const& linestring, Polygon const& polygon, - PtInPolyStrategy const& strategy) + Strategy const& strategy) { if (first && (turn.method == method_collinear || turn.method == method_equal)) { @@ -234,7 +234,7 @@ struct action_selector { // On enter, append the intersection point and remember starting point // TODO: we don't check on spikes for linestrings (?). Consider this. - detail::overlay::append_no_duplicates(current_piece, point, strategy.get_equals_point_point_strategy()); + detail::overlay::append_no_duplicates(current_piece, point, strategy); segment_id = operation.seg_id; } @@ -263,7 +263,7 @@ struct action_selector < false, RemoveSpikes >::apply(linestring, segment_id, index, strategy, robust_policy, current_piece); - detail::overlay::append_no_duplicates(current_piece, point, strategy.get_equals_point_point_strategy()); + detail::overlay::append_no_duplicates(current_piece, point, strategy); if (::boost::size(current_piece) > 1) { *out++ = current_piece; @@ -431,14 +431,6 @@ public : typedef following::action_selector action; - typedef typename Strategy::cs_tag cs_tag; - - typename Strategy::template point_in_geometry_strategy - < - LineString, Polygon - >::type const pt_in_poly_strategy - = strategy.template get_point_in_geometry_strategy(); - // Sort intersection points on segments-along-linestring, and distance // (like in enrich is done for poly/poly) // sort turns by Linear seg_id, then by fraction, then @@ -446,7 +438,8 @@ public : // for different ring id: c, i, u, x typedef relate::turns::less < - 0, relate::turns::less_op_linear_areal_single<0>, cs_tag + 0, relate::turns::less_op_linear_areal_single<0>, + typename Strategy::cs_tag > turn_less; std::sort(boost::begin(turns), boost::end(turns), turn_less()); @@ -460,13 +453,13 @@ public : { turn_operation_iterator_type iit = boost::begin(it->operations); - if (following::was_entered(*it, *iit, first, linestring, polygon, pt_in_poly_strategy)) + if (following::was_entered(*it, *iit, first, linestring, polygon, strategy)) { debug_traverse(*it, *iit, "-> Was entered"); entered = true; } - if (following::is_staying_inside(*it, *iit, entered, first, linestring, polygon, pt_in_poly_strategy)) + if (following::is_staying_inside(*it, *iit, entered, first, linestring, polygon, strategy)) { debug_traverse(*it, *iit, "-> Staying inside"); @@ -482,7 +475,7 @@ public : strategy, robust_policy, linear::get(out)); } - else if (following::is_leaving(*it, *iit, entered, first, linestring, polygon, pt_in_poly_strategy)) + else if (following::is_leaving(*it, *iit, entered, first, linestring, polygon, strategy)) { debug_traverse(*it, *iit, "-> Leaving"); diff --git a/include/boost/geometry/algorithms/detail/overlay/get_intersection_points.hpp b/include/boost/geometry/algorithms/detail/overlay/get_intersection_points.hpp index e7b60c2c0..f0e3dbced 100644 --- a/include/boost/geometry/algorithms/detail/overlay/get_intersection_points.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/get_intersection_points.hpp @@ -73,7 +73,7 @@ struct get_turn_without_info > policy_type; typename policy_type::return_type const result - = strategy.apply(range_p, range_q, policy_type()); + = strategy.relate().apply(range_p, range_q, policy_type()); for (std::size_t i = 0; i < result.count; i++) { diff --git a/include/boost/geometry/algorithms/detail/overlay/get_ring.hpp b/include/boost/geometry/algorithms/detail/overlay/get_ring.hpp index 1cf5b1e9d..4931633b1 100644 --- a/include/boost/geometry/algorithms/detail/overlay/get_ring.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/get_ring.hpp @@ -119,13 +119,12 @@ struct get_ring template -inline std::size_t segment_count_on_ring(Geometry const& geometry, - segment_identifier const& seg_id) +inline std::size_t segment_count_on_ring(Geometry const& geometry, segment_identifier const& seg_id) { typedef typename geometry::tag::type tag; ring_identifier const rid(0, seg_id.multi_index, seg_id.ring_index); // A closed polygon, a triangle of 4 points, including starting point, - // contains 3 segments. So handle as if closed and subtract one. + // contains 3 segments. So handle as if it is closed, and subtract one. return geometry::num_points(detail::overlay::get_ring::apply(rid, geometry), true) - 1; } diff --git a/include/boost/geometry/algorithms/detail/overlay/get_turn_info.hpp b/include/boost/geometry/algorithms/detail/overlay/get_turn_info.hpp index e90910c9b..5383b1e91 100644 --- a/include/boost/geometry/algorithms/detail/overlay/get_turn_info.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/get_turn_info.hpp @@ -3,8 +3,8 @@ // Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. // Copyright (c) 2017 Adam Wulkiewicz, Lodz, Poland. -// This file was modified by Oracle on 2015, 2017, 2018, 2019. -// Modifications copyright (c) 2015-2019 Oracle and/or its affiliates. +// This file was modified by Oracle on 2015-2020. +// Modifications copyright (c) 2015-2020 Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle @@ -15,7 +15,6 @@ #ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_GET_TURN_INFO_HPP #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_GET_TURN_INFO_HPP - #include #include @@ -28,9 +27,6 @@ #include #include -#include - -#include #include // Silence warning C4127: conditional expression is constant @@ -131,15 +127,7 @@ struct base_turn_handler return 0; } - typedef typename select_coordinate_type - < - typename UniqueSubRange1::point_type, - typename UniqueSubRange2::point_type - >::type coordinate_type; - - typedef detail::distance_measure dm_type; - - dm_type const dm = get_distance_measure(range_p.at(range_index), range_p.at(range_index + 1), range_q.at(point_index)); + auto const dm = get_distance_measure(range_p.at(range_index), range_p.at(range_index + 1), range_q.at(point_index)); return dm.measure == 0 ? 0 : dm.measure > 0 ? 1 : -1; } @@ -186,7 +174,8 @@ struct base_turn_handler { ti.method = method; - // For touch/touch interior always take the intersection point 0 (there is only one). + // For touch/touch interior always take the intersection point 0 + // (usually there is only one - but if collinear is handled as touch, both could be taken). static int const index = 0; geometry::convert(info.intersections[index], ti.point); @@ -225,9 +214,8 @@ struct base_turn_handler { // TODO: use comparable distance for point-point instead - but that // causes currently cycling include problems - typedef typename geometry::coordinate_type::type ctype; - ctype const dx = get<0>(a) - get<0>(b); - ctype const dy = get<1>(a) - get<1>(b); + auto const dx = get<0>(a) - get<0>(b); + auto const dy = get<1>(a) - get<1>(b); return dx * dx + dy * dy; } @@ -259,19 +247,10 @@ struct base_turn_handler // pk/q2 is considered as collinear, but there might be // a tiny measurable difference. If so, use that. // Calculate pk // qj-qk - typedef detail::distance_measure - < - typename select_coordinate_type - < - typename UniqueSubRange1::point_type, - typename UniqueSubRange2::point_type - >::type - > dm_type; - - const bool p_closer = + bool const p_closer = ti.operations[IndexP].remaining_distance < ti.operations[IndexQ].remaining_distance; - dm_type const dm + auto const dm = p_closer ? get_distance_measure(range_q.at(index_q - 1), range_q.at(index_q), range_p.at(index_p)) @@ -282,8 +261,7 @@ struct base_turn_handler { // Not truely collinear, distinguish for union/intersection // If p goes left (positive), take that for a union - - bool p_left = p_closer ? dm.is_positive() : dm.is_negative(); + bool const p_left = p_closer ? dm.is_positive() : dm.is_negative(); ti.operations[IndexP].operation = p_left ? operation_union : operation_intersection; @@ -347,14 +325,9 @@ struct touch_interior : public base_turn_handler // Therefore handle it as a normal touch (two segments arrive at the // intersection point). It currently checks for zero, but even a // distance a little bit larger would do. - typedef typename geometry::coordinate_type - < - typename UniqueSubRange::point_type - >::type coor_t; - - coor_t const location = distance_measure(info.intersections[0], non_touching_range.at(1)); - coor_t const zero = 0; - bool const result = math::equals(location, zero); + auto const dm = distance_measure(info.intersections[0], non_touching_range.at(1)); + decltype(dm) const zero = 0; + bool const result = math::equals(dm, zero); return result; } @@ -540,16 +513,8 @@ struct touch : public base_turn_handler // >----->P qj is LEFT of P1 and pi is LEFT of Q2 // (the other way round is also possible) - typedef typename select_coordinate_type - < - typename UniqueSubRange1::point_type, - typename UniqueSubRange2::point_type - >::type coordinate_type; - - typedef detail::distance_measure dm_type; - - dm_type const dm_qj_p1 = get_distance_measure(range_p.at(0), range_p.at(1), range_q.at(1)); - dm_type const dm_pi_q2 = get_distance_measure(range_q.at(1), range_q.at(2), range_p.at(0)); + auto const dm_qj_p1 = get_distance_measure(range_p.at(0), range_p.at(1), range_q.at(1)); + auto const dm_pi_q2 = get_distance_measure(range_q.at(1), range_q.at(2), range_p.at(0)); if (dm_qj_p1.measure > 0 && dm_pi_q2.measure > 0) { @@ -564,8 +529,8 @@ struct touch : public base_turn_handler return true; } - dm_type const dm_pj_q1 = get_distance_measure(range_q.at(0), range_q.at(1), range_p.at(1)); - dm_type const dm_qi_p2 = get_distance_measure(range_p.at(1), range_p.at(2), range_q.at(0)); + auto const dm_pj_q1 = get_distance_measure(range_q.at(0), range_q.at(1), range_p.at(1)); + auto const dm_qi_p2 = get_distance_measure(range_p.at(1), range_p.at(2), range_q.at(0)); if (dm_pj_q1.measure > 0 && dm_qi_p2.measure > 0) { @@ -813,17 +778,9 @@ struct equal : public base_turn_handler // They turn to the same side, or continue both collinearly // Without rescaling, to check for union/intersection, // try to check side values (without any thresholds) - typedef typename select_coordinate_type - < - typename UniqueSubRange1::point_type, - typename UniqueSubRange2::point_type - >::type coordinate_type; - - typedef detail::distance_measure dm_type; - - dm_type const dm_pk_q2 + auto const dm_pk_q2 = get_distance_measure(range_q.at(1), range_q.at(2), range_p.at(2)); - dm_type const dm_qk_p2 + auto const dm_qk_p2 = get_distance_measure(range_p.at(1), range_p.at(2), range_q.at(2)); if (dm_qk_p2.measure != dm_pk_q2.measure) @@ -965,8 +922,57 @@ template > struct collinear : public base_turn_handler { + template + < + typename IntersectionInfo, + typename UniqueSubRange1, + typename UniqueSubRange2, + typename DirInfo + > + static bool handle_as_equal(IntersectionInfo const& info, + UniqueSubRange1 const& range_p, + UniqueSubRange2 const& range_q, + DirInfo const& dir_info) + { +#if defined(BOOST_GEOMETRY_USE_RESCALING) + return false; +#endif + int const arrival_p = dir_info.arrival[0]; + int const arrival_q = dir_info.arrival[1]; + if (arrival_p * arrival_q != -1 || info.count != 2) + { + // Code below assumes that either p or q arrives in the other segment + return false; + } + + auto const dm = distance_measure(info.intersections[1], + arrival_p == 1 ? range_q.at(1) : range_p.at(1)); + decltype(dm) const zero = 0; + return math::equals(dm, zero); + } + /* - arrival P pk//p1 qk//q1 product* case result + Either P arrives within Q (arrival_p == -1) or Q arrives within P. + + Typical situation: + ^q2 + / + ^q1 + / ____ ip[1] + //|p1 } this section of p/q is colllinear + q0// | } ____ ip[0] + / | + / v + p0 p2 + + P arrives (at p1) in segment Q (between q0 and q1). + Therefore arrival_p == 1 + P (p2) goes to the right (-1). Follow P for intersection, or follow Q for union. + Therefore if (arrival_p==1) and side_p==-1, result = iu + + Complete table: + + arrival P pk//p1 qk//q1 product case result 1 1 1 CLL1 ui -1 1 -1 CLL2 iu 1 1 1 CLR1 ui @@ -980,7 +986,9 @@ struct collinear : public base_turn_handler 1 0 0 CC1 cc -1 0 0 CC2 cc - *product = arrival * (pk//p1 or qk//q1) + Resulting in the rule: + The arrival-info multiplied by the relevant side delivers the result. + product = arrival * (pk//p1 or qk//q1) Stated otherwise: - if P arrives: look at turn P @@ -989,13 +997,6 @@ struct collinear : public base_turn_handler - if P arrives and P turns right: intersection for P - if Q arrives and Q turns left: union for Q (=intersection for P) - if Q arrives and Q turns right: intersection for Q (=union for P) - - ROBUSTNESS: p and q are collinear, so you would expect - that side qk//p1 == pk//q1. But that is not always the case - in near-epsilon ranges. Then decision logic is different. - If p arrives, q is further, so the angle qk//p1 is (normally) - more precise than pk//p1 - */ template < @@ -1016,9 +1017,9 @@ struct collinear : public base_turn_handler // Copy the intersection point in TO direction assign_point(ti, method_collinear, info, non_opposite_to_index(info)); - int const arrival = dir_info.arrival[0]; + int const arrival_p = dir_info.arrival[0]; // Should not be 0, this is checked before - BOOST_GEOMETRY_ASSERT(arrival != 0); + BOOST_GEOMETRY_ASSERT(arrival_p != 0); bool const has_pk = ! range_p.is_last_segment(); bool const has_qk = ! range_q.is_last_segment(); @@ -1026,19 +1027,15 @@ struct collinear : public base_turn_handler int const side_q = has_qk ? side.qk_wrt_q1() : 0; // If p arrives, use p, else use q - int const side_p_or_q = arrival == 1 + int const side_p_or_q = arrival_p == 1 ? side_p : side_q ; - // See comments above, - // resulting in a strange sort of mathematic rule here: - // The arrival-info multiplied by the relevant side - // delivers a consistent result. + // Calculate product according to comments above. + int const product = arrival_p * side_p_or_q; - int const product = arrival * side_p_or_q; - - if(product == 0) + if (product == 0) { both(ti, operation_continue); } @@ -1186,11 +1183,11 @@ public: { TurnInfo tp = tp_model; - int const p_arrival = info.d_info().arrival[0]; - int const q_arrival = info.d_info().arrival[1]; + int const arrival_p = info.d_info().arrival[0]; + int const arrival_q = info.d_info().arrival[1]; // If P arrives within Q, there is a turn dependent on P - if ( p_arrival == 1 + if ( arrival_p == 1 && ! range_p.is_last_segment() && set_tp<0>(side.pk_wrt_p1(), tp, info.i_info()) ) { @@ -1200,7 +1197,7 @@ public: } // If Q arrives within P, there is a turn dependent on Q - if ( q_arrival == 1 + if ( arrival_q == 1 && ! range_q.is_last_segment() && set_tp<1>(side.qk_wrt_q1(), tp, info.i_info()) ) { @@ -1212,8 +1209,8 @@ public: if (AssignPolicy::include_opposite) { // Handle cases not yet handled above - if ((q_arrival == -1 && p_arrival == 0) - || (p_arrival == -1 && q_arrival == 0)) + if ((arrival_q == -1 && arrival_p == 0) + || (arrival_p == -1 && arrival_q == 0)) { for (unsigned int i = 0; i < 2; i++) { @@ -1396,7 +1393,7 @@ struct get_turn_info else { handler::template apply<1>(range_q, range_p, tp, inters.i_info(), inters.d_info(), - inters.get_swapped_sides(), umbrella_strategy); + inters.swapped_sides(), umbrella_strategy); *out++ = tp; } } @@ -1420,9 +1417,10 @@ struct get_turn_info // Collinear if ( ! inters.d_info().opposite ) { - - if ( inters.d_info().arrival[0] == 0 ) + if (inters.d_info().arrival[0] == 0 + || collinear::handle_as_equal(inters.i_info(), range_p, range_q, inters.d_info())) { + // Both segments arrive at the second intersection point handle_as_equal = true; } else diff --git a/include/boost/geometry/algorithms/detail/overlay/get_turn_info_for_endpoint.hpp b/include/boost/geometry/algorithms/detail/overlay/get_turn_info_for_endpoint.hpp index c17fcb863..2b56d7dd5 100644 --- a/include/boost/geometry/algorithms/detail/overlay/get_turn_info_for_endpoint.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/get_turn_info_for_endpoint.hpp @@ -2,8 +2,8 @@ // Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. -// This file was modified by Oracle on 2013, 2014, 2017, 2018. -// Modifications copyright (c) 2013-2018 Oracle and/or its affiliates. +// This file was modified by Oracle on 2013-2020. +// Modifications copyright (c) 2013-2020 Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle @@ -111,12 +111,16 @@ namespace detail { namespace overlay { class linear_intersections { public: - template + template + < + typename Point1, typename Point2, typename IntersectionResult, + typename Strategy + > linear_intersections(Point1 const& pi, Point2 const& qi, IntersectionResult const& result, bool is_p_last, bool is_q_last, - EqPPStrategy const& strategy) + Strategy const& strategy) { int arrival_a = result.direction.arrival[0]; int arrival_b = result.direction.arrival[1]; @@ -237,7 +241,7 @@ struct get_turn_info_for_endpoint typename TurnInfo, typename IntersectionInfo, typename OutputIterator, - typename EqPPStrategy + typename Strategy > static inline bool apply(UniqueSubRange1 const& range_p, UniqueSubRange2 const& range_q, @@ -245,7 +249,7 @@ struct get_turn_info_for_endpoint IntersectionInfo const& inters, method_type /*method*/, OutputIterator out, - EqPPStrategy const& strategy) + Strategy const& strategy) { std::size_t ip_count = inters.i_info().count; // no intersection points @@ -398,8 +402,7 @@ struct get_turn_info_for_endpoint { boost::ignore_unused(ip_index, tp_model); - typename IntersectionInfo::side_strategy_type const& sides - = inters.get_side_strategy(); + auto const strategy = inters.strategy(); if ( !first2 && !last2 ) { @@ -409,8 +412,8 @@ struct get_turn_info_for_endpoint // may this give false positives for INTs? typename IntersectionResult::point_type const& inters_pt = inters.i_info().intersections[ip_index]; - BOOST_GEOMETRY_ASSERT(ip_i2 == equals::equals_point_point(i2, inters_pt)); - BOOST_GEOMETRY_ASSERT(ip_j2 == equals::equals_point_point(j2, inters_pt)); + BOOST_GEOMETRY_ASSERT(ip_i2 == equals::equals_point_point(i2, inters_pt, strategy)); + BOOST_GEOMETRY_ASSERT(ip_j2 == equals::equals_point_point(j2, inters_pt, strategy)); #endif if ( ip_i2 ) { @@ -421,6 +424,7 @@ struct get_turn_info_for_endpoint } else if ( ip_j2 ) { + auto const sides = strategy.side(); int const side_pj_q2 = sides.apply(range2.at(1), range2.at(2), range1.at(1)); int const side_pj_q1 = sides.apply(range2.at(0), range2.at(1), range1.at(1)); int const side_qk_q1 = sides.apply(range2.at(0), range2.at(1), range2.at(2)); @@ -460,8 +464,8 @@ struct get_turn_info_for_endpoint // may this give false positives for INTs? typename IntersectionResult::point_type const& inters_pt = inters.i_info().intersections[ip_index]; - BOOST_GEOMETRY_ASSERT(ip_i2 == equals::equals_point_point(i2, inters_pt)); - BOOST_GEOMETRY_ASSERT(ip_j2 == equals::equals_point_point(j2, inters_pt)); + BOOST_GEOMETRY_ASSERT(ip_i2 == equals::equals_point_point(i2, inters_pt, strategy)); + BOOST_GEOMETRY_ASSERT(ip_j2 == equals::equals_point_point(j2, inters_pt, strategy)); #endif if ( ip_i2 ) { @@ -472,6 +476,7 @@ struct get_turn_info_for_endpoint } else if ( ip_j2 ) { + auto const sides = strategy.side(); int const side_pi_q2 = sides.apply(range2.at(1), range2.at(2), range1.at(0)); int const side_pi_q1 = sides.apply(range2.at(0), range2.at(1), range1.at(0)); int const side_qk_q1 = sides.apply(range2.at(0), range2.at(1), range2.at(2)); diff --git a/include/boost/geometry/algorithms/detail/overlay/get_turn_info_helpers.hpp b/include/boost/geometry/algorithms/detail/overlay/get_turn_info_helpers.hpp index 76e0f0258..b82528fa4 100644 --- a/include/boost/geometry/algorithms/detail/overlay/get_turn_info_helpers.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/get_turn_info_helpers.hpp @@ -44,20 +44,20 @@ struct turn_operation_linear template < - typename TurnPointCSTag, typename UniqueSubRange1, typename UniqueSubRange2, - typename SideStrategy + typename Strategy > struct side_calculator { typedef typename UniqueSubRange1::point_type point1_type; typedef typename UniqueSubRange2::point_type point2_type; + typedef decltype(std::declval().side()) side_strategy_type; inline side_calculator(UniqueSubRange1 const& range_p, UniqueSubRange2 const& range_q, - SideStrategy const& side_strategy) - : m_side_strategy(side_strategy) + Strategy const& strategy) + : m_side_strategy(strategy.side()) , m_range_p(range_p) , m_range_q(range_q) {} @@ -84,9 +84,8 @@ struct side_calculator inline point2_type const& get_qj() const { return m_range_q.at(1); } inline point2_type const& get_qk() const { return m_range_q.at(2); } - // Used side-strategy, owned by the calculator, - // created from .get_side_strategy() - SideStrategy m_side_strategy; + // Used side-strategy, owned by the calculator + side_strategy_type m_side_strategy; // Used ranges - owned by get_turns or (for robust points) by intersection_info_base UniqueSubRange1 const& m_range_p; @@ -259,16 +258,14 @@ public: typedef robust_subrange_adapter robust_subrange1; typedef robust_subrange_adapter robust_subrange2; - typedef typename cs_tag::type cs_tag; - - typedef typename UmbrellaStrategy::side_strategy_type side_strategy_type; - typedef side_calculator side_calculator_type; + typedef side_calculator + < + robust_subrange1, robust_subrange2, UmbrellaStrategy + > side_calculator_type; typedef side_calculator < - cs_tag, robust_subrange2, robust_subrange1, - side_strategy_type + robust_subrange2, robust_subrange1, UmbrellaStrategy > robust_swapped_side_calculator_type; intersection_info_base(UniqueSubRange1 const& range_p, @@ -280,9 +277,9 @@ public: , m_robust_calc(range_p, range_q, robust_policy) , m_robust_range_p(range_p, m_robust_calc.m_rpi, m_robust_calc.m_rpj, robust_policy) , m_robust_range_q(range_q, m_robust_calc.m_rqi, m_robust_calc.m_rqj, robust_policy) - , m_side_calc(m_robust_range_p, m_robust_range_q, - umbrella_strategy.get_side_strategy()) - , m_result(umbrella_strategy.apply(range_p, range_q, + , m_side_calc(m_robust_range_p, m_robust_range_q, umbrella_strategy) + , m_swapped_side_calc(m_robust_range_q, m_robust_range_p, umbrella_strategy) + , m_result(umbrella_strategy.relate().apply(range_p, range_q, intersection_policy_type(), m_robust_range_p, m_robust_range_q)) {} @@ -299,13 +296,9 @@ public: inline robust_point2_type const& rqk() const { return m_robust_calc.get_rqk(); } inline side_calculator_type const& sides() const { return m_side_calc; } - - robust_swapped_side_calculator_type get_swapped_sides() const + inline robust_swapped_side_calculator_type const& swapped_sides() const { - robust_swapped_side_calculator_type result( - m_robust_range_q, m_robust_range_p, - m_side_calc.m_side_strategy); - return result; + return m_swapped_side_calc; } private : @@ -319,6 +312,7 @@ private : robust_subrange1 m_robust_range_p; robust_subrange2 m_robust_range_q; side_calculator_type m_side_calc; + robust_swapped_side_calculator_type m_swapped_side_calc; protected : result_type m_result; @@ -347,15 +341,14 @@ public: typedef typename UniqueSubRange1::point_type point1_type; typedef typename UniqueSubRange2::point_type point2_type; - typedef typename UmbrellaStrategy::cs_tag cs_tag; - - typedef typename UmbrellaStrategy::side_strategy_type side_strategy_type; - typedef side_calculator side_calculator_type; + typedef side_calculator + < + UniqueSubRange1, UniqueSubRange2, UmbrellaStrategy + > side_calculator_type; typedef side_calculator < - cs_tag, UniqueSubRange2, UniqueSubRange1, - side_strategy_type + UniqueSubRange2, UniqueSubRange1, UmbrellaStrategy > swapped_side_calculator_type; intersection_info_base(UniqueSubRange1 const& range_p, @@ -364,9 +357,10 @@ public: no_rescale_policy const& ) : m_range_p(range_p) , m_range_q(range_q) - , m_side_calc(range_p, range_q, - umbrella_strategy.get_side_strategy()) - , m_result(umbrella_strategy.apply(range_p, range_q, intersection_policy_type())) + , m_side_calc(range_p, range_q, umbrella_strategy) + , m_swapped_side_calc(range_q, range_p, umbrella_strategy) + , m_result(umbrella_strategy.relate() + .apply(range_p, range_q, intersection_policy_type())) {} inline bool p_is_last_segment() const { return m_range_p.is_last_segment(); } @@ -381,13 +375,9 @@ public: inline point2_type const& rqk() const { return m_side_calc.get_qk(); } inline side_calculator_type const& sides() const { return m_side_calc; } - - swapped_side_calculator_type get_swapped_sides() const + inline swapped_side_calculator_type const& swapped_sides() const { - swapped_side_calculator_type result( - m_range_q, m_range_p, - m_side_calc.m_side_strategy); - return result; + return m_swapped_side_calc; } private : @@ -397,6 +387,7 @@ private : // Owned by this class side_calculator_type m_side_calc; + swapped_side_calculator_type m_swapped_side_calc; protected : result_type m_result; @@ -422,8 +413,6 @@ public: typedef typename UniqueSubRange1::point_type point1_type; typedef typename UniqueSubRange2::point_type point2_type; - typedef UmbrellaStrategy intersection_strategy_type; - typedef typename UmbrellaStrategy::side_strategy_type side_strategy_type; typedef typename UmbrellaStrategy::cs_tag cs_tag; typedef typename base::side_calculator_type side_calculator_type; @@ -437,7 +426,7 @@ public: UmbrellaStrategy const& umbrella_strategy, RobustPolicy const& robust_policy) : base(range_p, range_q, umbrella_strategy, robust_policy) - , m_intersection_strategy(umbrella_strategy) + , m_umbrella_strategy(umbrella_strategy) , m_robust_policy(robust_policy) {} @@ -445,11 +434,6 @@ public: inline i_info_type const& i_info() const { return base::m_result.intersection_points; } inline d_info_type const& d_info() const { return base::m_result.direction; } - 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 { @@ -524,6 +508,11 @@ public: return false; } + UmbrellaStrategy const& strategy() const + { + return m_umbrella_strategy; + } + private: template bool is_ip_j() const @@ -548,7 +537,7 @@ private: } } - UmbrellaStrategy const& m_intersection_strategy; + UmbrellaStrategy const& m_umbrella_strategy; RobustPolicy const& m_robust_policy; }; diff --git a/include/boost/geometry/algorithms/detail/overlay/get_turn_info_la.hpp b/include/boost/geometry/algorithms/detail/overlay/get_turn_info_la.hpp index 5b5273392..20aaa6a43 100644 --- a/include/boost/geometry/algorithms/detail/overlay/get_turn_info_la.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/get_turn_info_la.hpp @@ -3,8 +3,8 @@ // 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, 2017, 2018. -// Modifications copyright (c) 2013-2018 Oracle and/or its affiliates. +// This file was modified by Oracle on 2013-2020. +// Modifications copyright (c) 2013-2020 Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle @@ -79,7 +79,7 @@ struct get_turn_info_linear_areal case 's' : // starts from the middle get_turn_info_for_endpoint(range_p, range_q, tp_model, inters, method_none, out, - umbrella_strategy.get_point_in_point_strategy()); + umbrella_strategy); break; case 'd' : // disjoint: never do anything @@ -89,7 +89,7 @@ struct get_turn_info_linear_areal { if ( get_turn_info_for_endpoint(range_p, range_q, tp_model, inters, method_touch_interior, out, - umbrella_strategy.get_point_in_point_strategy()) ) + umbrella_strategy) ) { // do nothing } @@ -109,7 +109,7 @@ struct get_turn_info_linear_areal // Swap p/q handler::template apply<1>(range_q, range_p, tp, inters.i_info(), inters.d_info(), - inters.get_swapped_sides(), umbrella_strategy); + inters.swapped_sides(), umbrella_strategy); } if ( tp.operations[1].operation == operation_blocked ) @@ -124,7 +124,7 @@ struct get_turn_info_linear_areal // this function assumes that 'u' must be set for a spike calculate_spike_operation(tp.operations[0].operation, inters, - umbrella_strategy.get_point_in_point_strategy()); + umbrella_strategy); *out++ = tp; } @@ -144,7 +144,7 @@ struct get_turn_info_linear_areal // Both touch (both arrive there) if ( get_turn_info_for_endpoint(range_p, range_q, tp_model, inters, method_touch, out, - umbrella_strategy.get_point_in_point_strategy()) ) + umbrella_strategy) ) { // do nothing } @@ -218,7 +218,7 @@ struct get_turn_info_linear_areal bool ignore_spike = calculate_spike_operation(tp.operations[0].operation, inters, - umbrella_strategy.get_point_in_point_strategy()); + umbrella_strategy); if ( ! BOOST_GEOMETRY_CONDITION(handle_spikes) || ignore_spike @@ -234,7 +234,7 @@ struct get_turn_info_linear_areal { if ( get_turn_info_for_endpoint(range_p, range_q, tp_model, inters, method_equal, out, - umbrella_strategy.get_point_in_point_strategy()) ) + umbrella_strategy) ) { // do nothing } @@ -279,7 +279,7 @@ struct get_turn_info_linear_areal if ( get_turn_info_for_endpoint( range_p, range_q, tp_model, inters, method_collinear, out, - umbrella_strategy.get_point_in_point_strategy()) ) + umbrella_strategy) ) { // do nothing } @@ -359,13 +359,13 @@ struct get_turn_info_linear_areal if ( range_p.is_first_segment() && equals::equals_point_point(range_p.at(0), tp.point, - umbrella_strategy.get_point_in_point_strategy()) ) + umbrella_strategy) ) { tp.operations[0].position = position_front; } else if ( range_p.is_last_segment() && equals::equals_point_point(range_p.at(1), tp.point, - umbrella_strategy.get_point_in_point_strategy()) ) + umbrella_strategy) ) { tp.operations[0].position = position_back; } @@ -392,10 +392,10 @@ struct get_turn_info_linear_areal template + typename Strategy> static inline bool calculate_spike_operation(Operation & op, IntersectionInfo const& inters, - EqPPStrategy const& strategy) + Strategy const& strategy) { bool is_p_spike = ( op == operation_union || op == operation_intersection ) && inters.is_spike_p(); @@ -415,7 +415,7 @@ struct get_turn_info_linear_areal // spike on the edge point // if it's already known that the spike is going out this musn't be checked if ( ! going_out - && detail::equals::equals_point_point(inters.rpj(), inters.rqj(), strategy) ) + && equals::equals_point_point(inters.rpj(), inters.rqj(), strategy) ) { int const pk_q2 = inters.sides().pk_wrt_q2(); going_in = pk_q1 < 0 && pk_q2 < 0; // Pk on the right of both @@ -427,7 +427,7 @@ struct get_turn_info_linear_areal // spike on the edge point // if it's already known that the spike is going in this musn't be checked if ( ! going_in - && detail::equals::equals_point_point(inters.rpj(), inters.rqj(), strategy) ) + && equals::equals_point_point(inters.rpj(), inters.rqj(), strategy) ) { int const pk_q2 = inters.sides().pk_wrt_q2(); going_in = pk_q1 < 0 || pk_q2 < 0; // Pk on the right of one of them @@ -679,7 +679,7 @@ struct get_turn_info_linear_areal typename TurnInfo, typename IntersectionInfo, typename OutputIterator, - typename EqPPStrategy> + typename Strategy> static inline bool get_turn_info_for_endpoint( UniqueSubRange1 const& range_p, UniqueSubRange2 const& range_q, @@ -687,7 +687,7 @@ struct get_turn_info_linear_areal IntersectionInfo const& inters, method_type /*method*/, OutputIterator out, - EqPPStrategy const& strategy) + Strategy const& strategy) { namespace ov = overlay; typedef ov::get_turn_info_for_endpoint get_info_e; @@ -705,9 +705,6 @@ struct get_turn_info_linear_areal return false; } - typename IntersectionInfo::side_strategy_type const& sides - = inters.get_side_strategy(); - linear_intersections intersections(range_p.at(0), range_q.at(0), inters.result(), @@ -738,6 +735,8 @@ struct get_turn_info_linear_areal } else { + auto const sides = strategy.side(); + // pi is the intersection point at qj or in the middle of q1 // so consider segments // 1. pi at qj: qi-qj-pj and qi-qj-qk @@ -807,6 +806,8 @@ struct get_turn_info_linear_areal } else //if ( result.template get<0>().count == 1 ) { + auto const sides = strategy.side(); + // pj is the intersection point at qj or in the middle of q1 // so consider segments // 1. pj at qj: qi-qj-pi and qi-qj-qk @@ -863,14 +864,6 @@ struct get_turn_info_linear_areal // don't ignore anything for now return false; } - - template - static inline bool equals_point_point(Point1 const& point1, Point2 const& point2, - IntersectionStrategy const& strategy) - { - return detail::equals::equals_point_point(point1, point2, - strategy.get_point_in_point_strategy()); - } }; }} // namespace detail::overlay diff --git a/include/boost/geometry/algorithms/detail/overlay/get_turn_info_ll.hpp b/include/boost/geometry/algorithms/detail/overlay/get_turn_info_ll.hpp index 0ea937a1e..ccb5e668a 100644 --- a/include/boost/geometry/algorithms/detail/overlay/get_turn_info_ll.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/get_turn_info_ll.hpp @@ -75,7 +75,7 @@ struct get_turn_info_linear_linear get_turn_info_for_endpoint ::apply(range_p, range_q, tp_model, inters, method_none, out, - umbrella_strategy.get_point_in_point_strategy()); + umbrella_strategy); break; case 'd' : // disjoint: never do anything @@ -86,7 +86,7 @@ struct get_turn_info_linear_linear if ( get_turn_info_for_endpoint ::apply(range_p, range_q, tp_model, inters, method_touch_interior, out, - umbrella_strategy.get_point_in_point_strategy()) ) + umbrella_strategy) ) { // do nothing } @@ -110,7 +110,7 @@ struct get_turn_info_linear_linear // Swap p/q policy::template apply<1>(range_q, range_p, tp, inters.i_info(), inters.d_info(), - inters.get_swapped_sides(), + inters.swapped_sides(), umbrella_strategy); } @@ -146,7 +146,7 @@ struct get_turn_info_linear_linear if ( get_turn_info_for_endpoint ::apply(range_p, range_q, tp_model, inters, method_touch, out, - umbrella_strategy.get_point_in_point_strategy()) ) + umbrella_strategy) ) { // do nothing } @@ -278,7 +278,7 @@ struct get_turn_info_linear_linear if ( get_turn_info_for_endpoint ::apply(range_p, range_q, tp_model, inters, method_equal, out, - umbrella_strategy.get_point_in_point_strategy()) ) + umbrella_strategy) ) { // do nothing } @@ -333,7 +333,7 @@ struct get_turn_info_linear_linear if ( get_turn_info_for_endpoint ::apply(range_p, range_q, tp_model, inters, method_collinear, out, - umbrella_strategy.get_point_in_point_strategy()) ) + umbrella_strategy) ) { // do nothing } @@ -416,29 +416,26 @@ struct get_turn_info_linear_linear // degenerate points if ( BOOST_GEOMETRY_CONDITION(AssignPolicy::include_degenerate) ) { - typedef typename UmbrellaStrategy::point_in_point_strategy_type - equals_strategy_type; - only_convert::apply(tp, inters.i_info()); // if any, only one of those should be true if ( range_p.is_first_segment() - && equals::equals_point_point(range_p.at(0), tp.point, equals_strategy_type()) ) + && equals::equals_point_point(range_p.at(0), tp.point, umbrella_strategy) ) { tp.operations[0].position = position_front; } else if ( range_p.is_last_segment() - && equals::equals_point_point(range_p.at(1), tp.point, equals_strategy_type()) ) + && equals::equals_point_point(range_p.at(1), tp.point, umbrella_strategy) ) { tp.operations[0].position = position_back; } else if ( range_q.is_first_segment() - && equals::equals_point_point(range_q.at(0), tp.point, equals_strategy_type()) ) + && equals::equals_point_point(range_q.at(0), tp.point, umbrella_strategy) ) { tp.operations[1].position = position_front; } else if ( range_q.is_last_segment() - && equals::equals_point_point(range_q.at(1), tp.point, equals_strategy_type()) ) + && equals::equals_point_point(range_q.at(1), tp.point, umbrella_strategy) ) { tp.operations[1].position = position_back; } diff --git a/include/boost/geometry/algorithms/detail/overlay/get_turns.hpp b/include/boost/geometry/algorithms/detail/overlay/get_turns.hpp index b8f95f4bf..45db3d252 100644 --- a/include/boost/geometry/algorithms/detail/overlay/get_turns.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/get_turns.hpp @@ -3,8 +3,8 @@ // Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. // Copyright (c) 2014-2017 Adam Wulkiewicz, Lodz, Poland. -// This file was modified by Oracle on 2014-2020. -// Modifications copyright (c) 2014-2020 Oracle and/or its affiliates. +// This file was modified by Oracle on 2014-2021. +// Modifications copyright (c) 2014-2021 Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle @@ -108,7 +108,7 @@ template typename Section, typename Point, typename CircularIterator, - typename IntersectionStrategy, + typename Strategy, typename RobustPolicy > struct unique_sub_range_from_section @@ -118,16 +118,17 @@ struct unique_sub_range_from_section unique_sub_range_from_section(Section const& section, signed_size_type index, CircularIterator circular_iterator, Point const& previous, Point const& current, + Strategy const& strategy, RobustPolicy const& robust_policy) - : m_section(section) - , m_index(index) - , m_previous_point(previous) - , m_current_point(current) - , m_circular_iterator(circular_iterator) - , m_point_retrieved(false) - , m_robust_policy(robust_policy) - { - } + : m_section(section) + , m_index(index) + , m_previous_point(previous) + , m_current_point(current) + , m_circular_iterator(circular_iterator) + , m_point_retrieved(false) + , m_strategy(strategy) + , m_robust_policy(robust_policy) + {} inline bool is_first_segment() const { @@ -170,7 +171,6 @@ private : inline void advance_to_non_duplicate_next(Point const& current, CircularIterator& circular_iterator) const { - typedef typename IntersectionStrategy::point_in_point_strategy_type disjoint_strategy_type; typedef typename robust_point_type::type robust_point_type; robust_point_type current_robust_point; robust_point_type next_robust_point; @@ -187,12 +187,9 @@ private : // So advance to the "non duplicate next" // (the check is defensive, to avoid endless loops) std::size_t check = 0; - while(! detail::disjoint::disjoint_point_point - ( - current_robust_point, next_robust_point, - disjoint_strategy_type() - ) - && check++ < m_section.range_count) + while (! detail::disjoint::disjoint_point_point( + current_robust_point, next_robust_point, m_strategy) + && check++ < m_section.range_count) { circular_iterator++; geometry::recalculate(next_robust_point, *circular_iterator, m_robust_policy); @@ -206,6 +203,7 @@ private : mutable CircularIterator m_circular_iterator; mutable Point m_point; mutable bool m_point_retrieved; + Strategy m_strategy; RobustPolicy m_robust_policy; }; @@ -276,12 +274,12 @@ class get_turns_in_sections public : // Returns true if terminated, false if interrupted - template + template 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, bool skip_adjacent, - IntersectionStrategy const& intersection_strategy, + Strategy const& strategy, RobustPolicy const& robust_policy, Turns& turns, InterruptPolicy& interrupt_policy) @@ -337,11 +335,11 @@ public : unique_sub_range_from_section < areal1, Section1, point1_type, circular1_iterator, - IntersectionStrategy, RobustPolicy + Strategy, RobustPolicy > unique_sub_range1(sec1, index1, circular1_iterator(begin_range_1, end_range_1, next1, true), *prev1, *it1, - robust_policy); + strategy, robust_policy); signed_size_type index2 = sec2.begin_index; signed_size_type ndi2 = sec2.non_duplicate_index; @@ -390,11 +388,11 @@ public : unique_sub_range_from_section < areal2, Section2, point2_type, circular2_iterator, - IntersectionStrategy, RobustPolicy + Strategy, RobustPolicy > unique_sub_range2(sec2, index2, circular2_iterator(begin_range_2, end_range_2, next2), *prev2, *it2, - robust_policy); + strategy, robust_policy); typedef typename boost::range_value::type turn_info; @@ -409,7 +407,7 @@ public : std::size_t const size_before = boost::size(turns); TurnPolicy::apply(unique_sub_range1, unique_sub_range2, - ti, intersection_strategy, robust_policy, + ti, strategy, robust_policy, std::back_inserter(turns)); if (InterruptPolicy::enabled) @@ -464,7 +462,7 @@ template typename Geometry1, typename Geometry2, bool Reverse1, bool Reverse2, typename TurnPolicy, - typename IntersectionStrategy, + typename Strategy, typename RobustPolicy, typename Turns, typename InterruptPolicy @@ -475,20 +473,20 @@ struct section_visitor Geometry1 const& m_geometry1; int m_source_id2; Geometry2 const& m_geometry2; - IntersectionStrategy const& m_intersection_strategy; + Strategy const& m_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, - IntersectionStrategy const& intersection_strategy, + Strategy const& 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_strategy(strategy) , m_rescale_policy(robust_policy) , m_turns(turns) , m_interrupt_policy(ip) @@ -499,7 +497,7 @@ struct section_visitor { if (! detail::disjoint::disjoint_box_box(sec1.bounding_box, sec2.bounding_box, - m_intersection_strategy.get_disjoint_box_box_strategy())) + m_strategy) ) { // false if interrupted return get_turns_in_sections @@ -512,7 +510,7 @@ struct section_visitor >::apply(m_source_id1, m_geometry1, sec1, m_source_id2, m_geometry2, sec2, false, false, - m_intersection_strategy, + m_strategy, m_rescale_policy, m_turns, m_interrupt_policy); } @@ -531,11 +529,11 @@ class get_turns_generic { public: - template + template static inline void apply( int source_id1, Geometry1 const& geometry1, int source_id2, Geometry2 const& geometry2, - IntersectionStrategy const& intersection_strategy, + Strategy const& strategy, RobustPolicy const& robust_policy, Turns& turns, InterruptPolicy& interrupt_policy) @@ -556,15 +554,10 @@ public: sections_type sec1, sec2; typedef std::integer_sequence dimensions; - typename IntersectionStrategy::envelope_strategy_type const - envelope_strategy = intersection_strategy.get_envelope_strategy(); - typename IntersectionStrategy::expand_strategy_type const - expand_strategy = intersection_strategy.get_expand_strategy(); - geometry::sectionalize(geometry1, robust_policy, - sec1, envelope_strategy, expand_strategy, 0); + sec1, strategy, 0); geometry::sectionalize(geometry2, robust_policy, - sec2, envelope_strategy, expand_strategy, 1); + sec2, strategy, 1); // ... and then partition them, intersecting overlapping sections in visitor method section_visitor @@ -572,27 +565,17 @@ public: Geometry1, Geometry2, Reverse1, Reverse2, TurnPolicy, - IntersectionStrategy, RobustPolicy, + Strategy, RobustPolicy, Turns, InterruptPolicy > visitor(source_id1, geometry1, source_id2, geometry2, - intersection_strategy, robust_policy, - turns, interrupt_policy); - - typedef detail::section::get_section_box - < - typename IntersectionStrategy::expand_box_strategy_type - > get_section_box_type; - typedef detail::section::overlaps_section_box - < - typename IntersectionStrategy::disjoint_box_box_strategy_type - > overlaps_section_box_type; + strategy, robust_policy, turns, interrupt_policy); geometry::partition < box_type >::apply(sec1, sec2, visitor, - get_section_box_type(), - overlaps_section_box_type()); + detail::section::get_section_box(strategy), + detail::section::overlaps_section_box(strategy)); } }; @@ -1094,10 +1077,10 @@ template > struct get_turns_reversed { - template + template static inline void apply(int source_id1, Geometry1 const& g1, int source_id2, Geometry2 const& g2, - IntersectionStrategy const& intersection_strategy, + Strategy const& strategy, RobustPolicy const& robust_policy, Turns& turns, InterruptPolicy& interrupt_policy) @@ -1109,7 +1092,7 @@ struct get_turns_reversed Reverse2, Reverse1, TurnPolicy >::apply(source_id2, g2, source_id1, g1, - intersection_strategy, robust_policy, + strategy, robust_policy, turns, interrupt_policy); } }; @@ -1140,14 +1123,14 @@ template typename AssignPolicy, typename Geometry1, typename Geometry2, - typename IntersectionStrategy, + typename Strategy, typename RobustPolicy, typename Turns, typename InterruptPolicy > inline void get_turns(Geometry1 const& geometry1, Geometry2 const& geometry2, - IntersectionStrategy const& intersection_strategy, + Strategy const& strategy, RobustPolicy const& robust_policy, Turns& turns, InterruptPolicy& interrupt_policy) @@ -1178,7 +1161,7 @@ inline void get_turns(Geometry1 const& geometry1, > >::apply(0, geometry1, 1, geometry2, - intersection_strategy, + strategy, robust_policy, turns, interrupt_policy); } diff --git a/include/boost/geometry/algorithms/detail/overlay/handle_colocations.hpp b/include/boost/geometry/algorithms/detail/overlay/handle_colocations.hpp index 960e37032..8d6887d95 100644 --- a/include/boost/geometry/algorithms/detail/overlay/handle_colocations.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/handle_colocations.hpp @@ -831,7 +831,7 @@ inline bool fill_sbs(Sbs& sbs, Point& turn_point, } for (int i = 0; i < 2; i++) { - sbs.add(turn.operations[i], turn_index, i, geometry1, geometry2, first); + sbs.add(turn, turn.operations[i], turn_index, i, geometry1, geometry2, first); first = false; } } diff --git a/include/boost/geometry/algorithms/detail/overlay/handle_self_turns.hpp b/include/boost/geometry/algorithms/detail/overlay/handle_self_turns.hpp index 5323c699b..aec43548d 100644 --- a/include/boost/geometry/algorithms/detail/overlay/handle_self_turns.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/handle_self_turns.hpp @@ -32,48 +32,6 @@ namespace boost { namespace geometry namespace detail { namespace overlay { - -template -< - typename Point, typename Geometry, - typename Tag2 = typename geometry::tag::type -> -struct check_within_strategy -{ - template - static inline typename Strategy::template point_in_geometry_strategy::type - within(Strategy const& strategy) - { - return strategy.template get_point_in_geometry_strategy(); - } - - template - static inline typename Strategy::template point_in_geometry_strategy::type - covered_by(Strategy const& strategy) - { - return strategy.template get_point_in_geometry_strategy(); - } -}; - -template -struct check_within_strategy -{ - template - static inline typename Strategy::within_point_box_strategy_type - within(Strategy const& ) - { - return typename Strategy::within_point_box_strategy_type(); - } - - template - static inline typename Strategy::covered_by_point_box_strategy_type - covered_by(Strategy const&) - { - return typename Strategy::covered_by_point_box_strategy_type(); - } -}; - - template struct check_within { @@ -86,14 +44,10 @@ struct check_within bool apply(Turn const& turn, Geometry0 const& geometry0, Geometry1 const& geometry1, UmbrellaStrategy const& strategy) { - typedef typename Turn::point_type point_type; - // Operations 0 and 1 have the same source index in self-turns return turn.operations[0].seg_id.source_index == 0 - ? geometry::within(turn.point, geometry1, - check_within_strategy::within(strategy)) - : geometry::within(turn.point, geometry0, - check_within_strategy::within(strategy)); + ? geometry::within(turn.point, geometry1, strategy) + : geometry::within(turn.point, geometry0, strategy); } }; @@ -110,15 +64,11 @@ struct check_within bool apply(Turn const& turn, Geometry0 const& geometry0, Geometry1 const& geometry1, UmbrellaStrategy const& strategy) { - typedef typename Turn::point_type point_type; - // difference = intersection(a, reverse(b)) // therefore we should reverse the meaning of within for geometry1 return turn.operations[0].seg_id.source_index == 0 - ? ! geometry::covered_by(turn.point, geometry1, - check_within_strategy::covered_by(strategy)) - : geometry::within(turn.point, geometry0, - check_within_strategy::within(strategy)); + ? ! geometry::covered_by(turn.point, geometry1, strategy) + : geometry::within(turn.point, geometry0, strategy); } }; diff --git a/include/boost/geometry/algorithms/detail/overlay/intersection_insert.hpp b/include/boost/geometry/algorithms/detail/overlay/intersection_insert.hpp index 564d063f9..153fb1cf4 100644 --- a/include/boost/geometry/algorithms/detail/overlay/intersection_insert.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/intersection_insert.hpp @@ -49,6 +49,10 @@ #include #include +#include +#include +#include + #include #include @@ -100,7 +104,7 @@ struct intersection_segment_segment_point detail::segment_as_subrange sub_range2(segment2); intersection_return_type - is = strategy.apply(sub_range1, sub_range2, policy_type()); + is = strategy.relate().apply(sub_range1, sub_range2, policy_type()); for (std::size_t i = 0; i < is.count; i++) { @@ -1535,9 +1539,9 @@ inline OutputIterator intersection_insert(Geometry1 const& geometry1, concepts::check(); concepts::check(); - typedef typename strategy::intersection::services::default_strategy + typedef typename strategies::relate::services::default_strategy < - typename cs_tag::type + Geometry1, Geometry2 >::type strategy_type; return intersection_insert(geometry1, geometry2, out, diff --git a/include/boost/geometry/algorithms/detail/overlay/linear_linear.hpp b/include/boost/geometry/algorithms/detail/overlay/linear_linear.hpp index 2421eebbd..f5d5f7bf4 100644 --- a/include/boost/geometry/algorithms/detail/overlay/linear_linear.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/linear_linear.hpp @@ -147,13 +147,13 @@ protected: typename Turns, typename LinearGeometry1, typename LinearGeometry2, - typename IntersectionStrategy, + typename Strategy, typename RobustPolicy > static inline void compute_turns(Turns& turns, LinearGeometry1 const& linear1, LinearGeometry2 const& linear2, - IntersectionStrategy const& strategy, + Strategy const& strategy, RobustPolicy const& robust_policy) { turns.clear(); @@ -182,14 +182,14 @@ protected: typename LinearGeometry1, typename LinearGeometry2, typename OutputIterator, - typename IntersectionStrategy + typename Strategy > static inline OutputIterator sort_and_follow_turns(Turns& turns, LinearGeometry1 const& linear1, LinearGeometry2 const& linear2, OutputIterator oit, - IntersectionStrategy const& strategy) + Strategy const& strategy) { // remove turns that have no added value turns::filter_continue_turns @@ -217,7 +217,7 @@ protected: FollowIsolatedPoints, !EnableFilterContinueTurns || OverlayType == overlay_intersection >::apply(linear1, linear2, boost::begin(turns), boost::end(turns), - oit, strategy.get_side_strategy()); + oit, strategy); } public: diff --git a/include/boost/geometry/algorithms/detail/overlay/overlay.hpp b/include/boost/geometry/algorithms/detail/overlay/overlay.hpp index b247ef4bd..fbe43afd5 100644 --- a/include/boost/geometry/algorithms/detail/overlay/overlay.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/overlay.hpp @@ -197,20 +197,13 @@ inline OutputIterator return_if_one_input_is_empty(Geometry1 const& geometry1, Geometry2 const& geometry2, OutputIterator out, Strategy const& strategy) { - typedef std::deque - < - typename geometry::ring_type::type - > ring_container_type; - - typedef typename geometry::point_type::type point_type1; + typedef typename geometry::ring_type::type ring_type; + typedef std::deque ring_container_type; typedef ring_properties < - point_type1, - typename Strategy::template area_strategy - < - point_type1 - >::type::template result_type::type + typename geometry::point_type::type, + typename geometry::area_result::type > properties; // Silence warning C4127: conditional expression is constant @@ -239,8 +232,7 @@ inline OutputIterator return_if_one_input_is_empty(Geometry1 const& geometry1, select_rings(geometry1, geometry2, empty, all_of_one_of_them, strategy); ring_container_type rings; assign_parents(geometry1, geometry2, rings, all_of_one_of_them, strategy); - return add_rings(all_of_one_of_them, geometry1, geometry2, rings, out, - strategy.template get_area_strategy()); + return add_rings(all_of_one_of_them, geometry1, geometry2, rings, out, strategy); } @@ -285,10 +277,8 @@ struct overlay > turn_info; typedef std::deque turn_container_type; - typedef std::deque - < - typename geometry::ring_type::type - > ring_container_type; + typedef typename geometry::ring_type::type ring_type; + typedef std::deque ring_container_type; // Define the clusters, mapping cluster_id -> turns typedef std::map @@ -365,12 +355,10 @@ std::cout << "traverse" << std::endl; get_ring_turn_info(turn_info_per_ring, turns, clusters); - typedef typename Strategy::template area_strategy::type area_strategy_type; - typedef ring_properties < point_type, - typename area_strategy_type::template result_type::type + typename geometry::area_result::type > properties; // Select all rings which are NOT touched by any intersection point @@ -379,7 +367,6 @@ std::cout << "traverse" << std::endl; selected_ring_properties, strategy); // Add rings created during traversal - area_strategy_type const area_strategy = strategy.template get_area_strategy(); { ring_identifier id(2, 0, -1); for (typename boost::range_iterator::type @@ -387,7 +374,7 @@ std::cout << "traverse" << std::endl; it != boost::end(rings); ++it) { - selected_ring_properties[id] = properties(*it, area_strategy); + selected_ring_properties[id] = properties(*it, strategy); selected_ring_properties[id].reversed = ReverseOut; id.multi_index++; } @@ -404,7 +391,7 @@ std::cout << "traverse" << std::endl; // The result may be too big, so the area is negative. In this case either // it can be returned or an exception can be thrown. return add_rings(selected_ring_properties, geometry1, geometry2, rings, out, - area_strategy, + strategy, OverlayType == overlay_union ? #if defined(BOOST_GEOMETRY_UNION_THROW_INVALID_OUTPUT_EXCEPTION) add_rings_throw_if_reversed diff --git a/include/boost/geometry/algorithms/detail/overlay/pointlike_areal.hpp b/include/boost/geometry/algorithms/detail/overlay/pointlike_areal.hpp index f1da6aba6..8b62b0752 100644 --- a/include/boost/geometry/algorithms/detail/overlay/pointlike_areal.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/pointlike_areal.hpp @@ -63,44 +63,68 @@ template class multipoint_multipolygon_point { private: - template + template struct expand_box_point { + explicit expand_box_point(Strategy const& strategy) + : m_strategy(strategy) + {} + template - static inline void apply(Box& total, Point const& point) + inline void apply(Box& total, Point const& point) const { - geometry::expand(total, point, ExpandPointStrategy()); + geometry::expand(total, point, m_strategy); } + + Strategy const& m_strategy; }; - template + template struct expand_box_boxpair { + explicit expand_box_boxpair(Strategy const& strategy) + : m_strategy(strategy) + {} + template - static inline void apply(Box1& total, std::pair const& box_pair) + inline void apply(Box1& total, std::pair const& box_pair) const { - geometry::expand(total, box_pair.first, ExpandBoxStrategy()); + geometry::expand(total, box_pair.first, m_strategy); } + + Strategy const& m_strategy; }; - template + template struct overlaps_box_point { + explicit overlaps_box_point(Strategy const& strategy) + : m_strategy(strategy) + {} + template - static inline bool apply(Box const& box, Point const& point) + inline bool apply(Box const& box, Point const& point) const { - return ! geometry::disjoint(point, box, DisjointPointBoxStrategy()); + return ! geometry::disjoint(point, box, m_strategy); } + + Strategy const& m_strategy; }; - template + template struct overlaps_box_boxpair { + explicit overlaps_box_boxpair(Strategy const& strategy) + : m_strategy(strategy) + {} + template - static inline bool apply(Box1 const& box, std::pair const& box_pair) + inline bool apply(Box1 const& box, std::pair const& box_pair) const { - return ! geometry::disjoint(box, box_pair.first, DisjointBoxBoxStrategy()); + return ! geometry::disjoint(box, box_pair.first, m_strategy); } + + Strategy const& m_strategy; }; template @@ -137,10 +161,10 @@ private: Strategy const& m_strategy; }; - template + template static inline void fill_box_pairs(Iterator first, Iterator last, std::vector > & box_pairs, - EnvelopeStrategy const& strategy) + Strategy const& strategy) { SizeT index = 0; for (; first != last; ++first, ++index) @@ -172,29 +196,16 @@ private: fill_box_pairs(boost::begin(multipolygon), boost::end(multipolygon), - box_pairs, - strategy.get_envelope_strategy()); - - // TEMP - envelope umbrella strategy also contains - // expand strategies - using expand_box_strategy_type = decltype( - strategies::envelope::services::strategy_converter - < - typename Strategy::envelope_strategy_type - >::get(strategy.get_envelope_strategy()) - .expand(std::declval(), std::declval())); - typedef typename Strategy::disjoint_box_box_strategy_type disjoint_box_box_strategy_type; - typedef typename Strategy::disjoint_point_box_strategy_type disjoint_point_box_strategy_type; - typedef typename Strategy::expand_point_strategy_type expand_point_strategy_type; + box_pairs, strategy); geometry::partition < box_type >::apply(multipoint, box_pairs, item_visitor, - expand_box_point(), - overlaps_box_point(), - expand_box_boxpair(), - overlaps_box_boxpair()); + expand_box_point(strategy), + overlaps_box_point(strategy), + expand_box_boxpair(strategy), + overlaps_box_boxpair(strategy)); return oit; } diff --git a/include/boost/geometry/algorithms/detail/overlay/pointlike_linear.hpp b/include/boost/geometry/algorithms/detail/overlay/pointlike_linear.hpp index a05ee0b73..bbf62b363 100644 --- a/include/boost/geometry/algorithms/detail/overlay/pointlike_linear.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/pointlike_linear.hpp @@ -127,20 +127,26 @@ class multipoint_linear_point { private: // structs for partition -- start - template + template struct expand_box_point { + expand_box_point(Strategy const& strategy) + : m_strategy(strategy) + {} + template - static inline void apply(Box& total, Point const& point) + inline void apply(Box& total, Point const& point) const { - geometry::expand(total, point, ExpandPointStrategy()); + geometry::expand(total, point, m_strategy); } + + Strategy const& m_strategy; }; - template + template struct expand_box_segment { - explicit expand_box_segment(EnvelopeStrategy const& strategy) + explicit expand_box_segment(Strategy const& strategy) : m_strategy(strategy) {} @@ -149,31 +155,32 @@ private: { geometry::expand(total, geometry::return_envelope(segment, m_strategy), - // TEMP - envelope umbrella strategy also contains - // expand strategies - strategies::envelope::services::strategy_converter - < - EnvelopeStrategy - >::get(m_strategy)); + m_strategy); } - EnvelopeStrategy const& m_strategy; + Strategy const& m_strategy; }; - template + template struct overlaps_box_point { + explicit overlaps_box_point(Strategy const& strategy) + : m_strategy(strategy) + {} + template - static inline bool apply(Box const& box, Point const& point) + inline bool apply(Box const& box, Point const& point) const { - return ! geometry::disjoint(point, box, DisjointPointBoxStrategy()); + return ! geometry::disjoint(point, box, m_strategy); } + + Strategy const& m_strategy; }; - template + template struct overlaps_box_segment { - explicit overlaps_box_segment(DisjointStrategy const& strategy) + explicit overlaps_box_segment(Strategy const& strategy) : m_strategy(strategy) {} @@ -183,7 +190,7 @@ private: return ! geometry::disjoint(segment, box, m_strategy); } - DisjointStrategy const& m_strategy; + Strategy const& m_strategy; }; template @@ -218,7 +225,7 @@ private: typedef geometry::segment_iterator const_iterator; typedef const_iterator iterator; - segment_range(Linear const& linear) + explicit segment_range(Linear const& linear) : m_linear(linear) {} @@ -244,11 +251,6 @@ private: { item_visitor_type item_visitor(oit, strategy); - typedef typename Strategy::envelope_strategy_type envelope_strategy_type; - typedef typename Strategy::disjoint_strategy_type disjoint_strategy_type; - typedef typename Strategy::disjoint_point_box_strategy_type disjoint_point_box_strategy_type; - typedef typename Strategy::expand_point_strategy_type expand_point_strategy_type; - // TODO: disjoint Segment/Box may be called in partition multiple times // possibly for non-cartesian segments which could be slow. We should consider // passing a range of bounding boxes of segments after calculating them once. @@ -261,10 +263,10 @@ private: typename boost::range_value::type > >::apply(multipoint, segment_range(linear), item_visitor, - expand_box_point(), - overlaps_box_point(), - expand_box_segment(strategy.get_envelope_strategy()), - overlaps_box_segment(strategy.get_disjoint_strategy())); + expand_box_point(strategy), + overlaps_box_point(strategy), + expand_box_segment(strategy), + overlaps_box_segment(strategy)); return oit; } diff --git a/include/boost/geometry/algorithms/detail/overlay/range_in_geometry.hpp b/include/boost/geometry/algorithms/detail/overlay/range_in_geometry.hpp index 09a397e0b..6f49f5168 100644 --- a/include/boost/geometry/algorithms/detail/overlay/range_in_geometry.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/range_in_geometry.hpp @@ -98,9 +98,9 @@ struct point_in_geometry_helper { template static inline int apply(Point const& point, Box const& box, - Strategy const&) + Strategy const& strategy) { - return geometry::covered_by(point, box) ? 1 : -1; + return geometry::covered_by(point, box, strategy) ? 1 : -1; } }; @@ -126,15 +126,9 @@ static inline int range_in_geometry(Geometry1 const& geometry1, ++it; } - typename Strategy::template point_in_geometry_strategy - < - Geometry1, Geometry2 - >::type const in_strategy - = strategy.template get_point_in_geometry_strategy(); - for ( ; it != end; ++it) { - result = point_in_geometry_helper::apply(*it, geometry2, in_strategy); + result = point_in_geometry_helper::apply(*it, geometry2, strategy); if (result != 0) { return result; @@ -153,8 +147,7 @@ inline int range_in_geometry(Point1 const& first_point1, Strategy const& strategy) { // check a point on border of geometry1 first - int result = point_in_geometry_helper::apply(first_point1, geometry2, - strategy.template get_point_in_geometry_strategy()); + int result = point_in_geometry_helper::apply(first_point1, geometry2, strategy); if (result == 0) { // if a point is on boundary of geometry2 diff --git a/include/boost/geometry/algorithms/detail/overlay/ring_properties.hpp b/include/boost/geometry/algorithms/detail/overlay/ring_properties.hpp index 7dbc5d5fa..c5341832b 100644 --- a/include/boost/geometry/algorithms/detail/overlay/ring_properties.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/ring_properties.hpp @@ -56,8 +56,8 @@ struct ring_properties , parent_area(-1) {} - template - inline ring_properties(RingOrBox const& ring_or_box, AreaStrategy const& strategy) + template + inline ring_properties(RingOrBox const& ring_or_box, Strategy const& strategy) : reversed(false) , discarded(false) , parent_area(-1) diff --git a/include/boost/geometry/algorithms/detail/overlay/segment_identifier.hpp b/include/boost/geometry/algorithms/detail/overlay/segment_identifier.hpp index b2d6d7f34..4d6c9fc02 100644 --- a/include/boost/geometry/algorithms/detail/overlay/segment_identifier.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/segment_identifier.hpp @@ -27,11 +27,11 @@ namespace boost { namespace geometry { - // Internal struct to uniquely identify a segment // on a linestring,ring // or polygon (needs ring_index) // or multi-geometry (needs multi_index) +// It is always used for clockwise indication (even if the original is anticlockwise) struct segment_identifier { inline segment_identifier() diff --git a/include/boost/geometry/algorithms/detail/overlay/select_rings.hpp b/include/boost/geometry/algorithms/detail/overlay/select_rings.hpp index d0fc67231..1f4313336 100644 --- a/include/boost/geometry/algorithms/detail/overlay/select_rings.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/select_rings.hpp @@ -3,8 +3,8 @@ // Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands. // Copyright (c) 2014 Adam Wulkiewicz, Lodz, Poland. -// This file was modified by Oracle on 2017-2020. -// Modifications copyright (c) 2017-2020 Oracle and/or its affiliates. +// This file was modified by Oracle on 2017-2021. +// Modifications copyright (c) 2017-2021 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, @@ -62,18 +62,18 @@ namespace dispatch template struct select_rings { - template + template static inline void apply(Box const& box, Geometry const& , ring_identifier const& id, RingPropertyMap& ring_properties, - AreaStrategy const& strategy) + Strategy const& strategy) { ring_properties[id] = typename RingPropertyMap::mapped_type(box, strategy); } - template + template static inline void apply(Box const& box, ring_identifier const& id, RingPropertyMap& ring_properties, - AreaStrategy const& strategy) + Strategy const& strategy) { ring_properties[id] = typename RingPropertyMap::mapped_type(box, strategy); } @@ -82,10 +82,10 @@ namespace dispatch template struct select_rings { - template + template static inline void apply(Ring const& ring, Geometry const& , ring_identifier const& id, RingPropertyMap& ring_properties, - AreaStrategy const& strategy) + Strategy const& strategy) { if (boost::size(ring) > 0) { @@ -93,10 +93,10 @@ namespace dispatch } } - template + template static inline void apply(Ring const& ring, ring_identifier const& id, RingPropertyMap& ring_properties, - AreaStrategy const& strategy) + Strategy const& strategy) { if (boost::size(ring) > 0) { @@ -109,10 +109,10 @@ namespace dispatch template struct select_rings { - template + template static inline void apply(Polygon const& polygon, Geometry const& geometry, ring_identifier id, RingPropertyMap& ring_properties, - AreaStrategy const& strategy) + Strategy const& strategy) { typedef typename geometry::ring_type::type ring_type; typedef select_rings per_ring; @@ -129,10 +129,10 @@ namespace dispatch } } - template + template static inline void apply(Polygon const& polygon, ring_identifier id, RingPropertyMap& ring_properties, - AreaStrategy const& strategy) + Strategy const& strategy) { typedef typename geometry::ring_type::type ring_type; typedef select_rings per_ring; @@ -153,10 +153,10 @@ namespace dispatch template struct select_rings { - template + template static inline void apply(Multi const& multi, Geometry const& geometry, ring_identifier id, RingPropertyMap& ring_properties, - AreaStrategy const& strategy) + Strategy const& strategy) { typedef typename boost::range_iterator < @@ -321,16 +321,14 @@ inline void select_rings(Geometry1 const& geometry1, Geometry2 const& geometry2, { typedef typename geometry::tag::type tag1; typedef typename geometry::tag::type tag2; - typedef typename geometry::point_type::type point1_type; - typedef typename geometry::point_type::type point2_type; - + RingPropertyMap all_ring_properties; dispatch::select_rings::apply(geometry1, geometry2, ring_identifier(0, -1, -1), all_ring_properties, - strategy.template get_area_strategy()); + strategy); dispatch::select_rings::apply(geometry2, geometry1, ring_identifier(1, -1, -1), all_ring_properties, - strategy.template get_area_strategy()); + strategy); update_ring_selection(geometry1, geometry2, turn_info_per_ring, all_ring_properties, selected_ring_properties, @@ -351,12 +349,11 @@ inline void select_rings(Geometry const& geometry, Strategy const& strategy) { typedef typename geometry::tag::type tag; - typedef typename geometry::point_type::type point_type; RingPropertyMap all_ring_properties; dispatch::select_rings::apply(geometry, ring_identifier(0, -1, -1), all_ring_properties, - strategy.template get_area_strategy()); + strategy); update_ring_selection(geometry, geometry, turn_info_per_ring, all_ring_properties, selected_ring_properties, diff --git a/include/boost/geometry/algorithms/detail/overlay/self_turn_points.hpp b/include/boost/geometry/algorithms/detail/overlay/self_turn_points.hpp index 740756666..0845390a9 100644 --- a/include/boost/geometry/algorithms/detail/overlay/self_turn_points.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/self_turn_points.hpp @@ -63,14 +63,14 @@ template typename Geometry, typename Turns, typename TurnPolicy, - typename IntersectionStrategy, + typename Strategy, typename RobustPolicy, typename InterruptPolicy > struct self_section_visitor { Geometry const& m_geometry; - IntersectionStrategy const& m_intersection_strategy; + Strategy const& m_strategy; RobustPolicy const& m_rescale_policy; Turns& m_turns; InterruptPolicy& m_interrupt_policy; @@ -78,14 +78,14 @@ struct self_section_visitor bool m_skip_adjacent; inline self_section_visitor(Geometry const& g, - IntersectionStrategy const& is, + Strategy const& s, RobustPolicy const& rp, Turns& turns, InterruptPolicy& ip, int source_index, bool skip_adjacent) : m_geometry(g) - , m_intersection_strategy(is) + , m_strategy(s) , m_rescale_policy(rp) , m_turns(turns) , m_interrupt_policy(ip) @@ -98,7 +98,7 @@ struct self_section_visitor { if (! detail::disjoint::disjoint_box_box(sec1.bounding_box, sec2.bounding_box, - m_intersection_strategy.get_disjoint_box_box_strategy()) + m_strategy) && ! sec1.duplicate && ! sec2.duplicate) { @@ -112,7 +112,7 @@ struct self_section_visitor >::apply(m_source_index, m_geometry, sec1, m_source_index, m_geometry, sec2, false, m_skip_adjacent, - m_intersection_strategy, + m_strategy, m_rescale_policy, m_turns, m_interrupt_policy); } @@ -127,10 +127,10 @@ struct self_section_visitor template struct get_turns { - template + template static inline bool apply( Geometry const& geometry, - IntersectionStrategy const& intersection_strategy, + Strategy const& strategy, RobustPolicy const& robust_policy, Turns& turns, InterruptPolicy& interrupt_policy, @@ -152,32 +152,23 @@ struct get_turns typedef std::integer_sequence dimensions; sections_type sec; - geometry::sectionalize(geometry, robust_policy, sec, - intersection_strategy.get_envelope_strategy(), - intersection_strategy.get_expand_strategy()); + geometry::sectionalize(geometry, robust_policy, + sec, strategy); self_section_visitor < Reverse, Geometry, - Turns, TurnPolicy, IntersectionStrategy, RobustPolicy, InterruptPolicy - > visitor(geometry, intersection_strategy, robust_policy, turns, interrupt_policy, source_index, skip_adjacent); - - typedef detail::section::get_section_box - < - typename IntersectionStrategy::expand_box_strategy_type - > get_section_box_type; - typedef detail::section::overlaps_section_box - < - typename IntersectionStrategy::disjoint_box_box_strategy_type - > overlaps_section_box_type; + Turns, TurnPolicy, Strategy, RobustPolicy, InterruptPolicy + > visitor(geometry, strategy, robust_policy, turns, interrupt_policy, + source_index, skip_adjacent); // false if interrupted geometry::partition < box_type >::apply(sec, visitor, - get_section_box_type(), - overlaps_section_box_type()); + detail::section::get_section_box(strategy), + detail::section::overlaps_section_box(strategy)); return ! interrupt_policy.has_intersections; } @@ -340,13 +331,13 @@ template < typename AssignPolicy, typename Geometry, - typename IntersectionStrategy, + typename Strategy, typename RobustPolicy, typename Turns, typename InterruptPolicy > inline void self_turns(Geometry const& geometry, - IntersectionStrategy const& strategy, + Strategy const& strategy, RobustPolicy const& robust_policy, Turns& turns, InterruptPolicy& interrupt_policy, diff --git a/include/boost/geometry/algorithms/detail/overlay/sort_by_side.hpp b/include/boost/geometry/algorithms/detail/overlay/sort_by_side.hpp index 484a439e0..316f53a02 100644 --- a/include/boost/geometry/algorithms/detail/overlay/sort_by_side.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/sort_by_side.hpp @@ -25,6 +25,9 @@ #include #include +#include +#include +#include namespace boost { namespace geometry { @@ -66,6 +69,8 @@ struct ranked_point , seg_id(si) {} + using point_type = Point; + Point point; rank_type rank; signed_size_type zone; // index of closed zone, in uu turn there would be 2 zones @@ -252,12 +257,14 @@ public : , m_strategy(strategy) {} + template void add_segment_from(signed_size_type turn_index, int op_index, Point const& point_from, - operation_type op, segment_identifier const& si, + Operation const& op, bool is_origin) { - m_ranked_points.push_back(rp(point_from, turn_index, op_index, dir_from, op, si)); + m_ranked_points.push_back(rp(point_from, turn_index, op_index, + dir_from, op.operation, op.seg_id)); if (is_origin) { m_origin = point_from; @@ -265,46 +272,104 @@ public : } } + template void add_segment_to(signed_size_type turn_index, int op_index, Point const& point_to, - operation_type op, segment_identifier const& si) + Operation const& op) { - m_ranked_points.push_back(rp(point_to, turn_index, op_index, dir_to, op, si)); + m_ranked_points.push_back(rp(point_to, turn_index, op_index, + dir_to, op.operation, op.seg_id)); } + template void add_segment(signed_size_type turn_index, int op_index, Point const& point_from, Point const& point_to, - operation_type op, segment_identifier const& si, - bool is_origin) + Operation const& op, bool is_origin) { - add_segment_from(turn_index, op_index, point_from, op, si, is_origin); - add_segment_to(turn_index, op_index, point_to, op, si); + add_segment_from(turn_index, op_index, point_from, op, is_origin); + add_segment_to(turn_index, op_index, point_to, op); + } + + // Returns true if two points are approximately equal, tuned by a giga-epsilon constant + // (if constant is 1.0, for type double, the boundary is about 1.0e-7) + template + static inline bool approximately_equals(Point1 const& a, Point2 const& b, + T const& limit_giga_epsilon) + { + // Including distance would introduce cyclic dependencies. + using coor_t = typename select_coordinate_type::type; + using calc_t = typename geometry::select_most_precise ::type; + constexpr calc_t machine_giga_epsilon = 1.0e9 * std::numeric_limits::epsilon(); + + calc_t const& a0 = geometry::get<0>(a); + calc_t const& b0 = geometry::get<0>(b); + calc_t const& a1 = geometry::get<1>(a); + calc_t const& b1 = geometry::get<1>(b); + calc_t const one = 1.0; + calc_t const c = math::detail::greatest(a0, b0, a1, b1, one); + + // The maximum limit is avoid, for floating point, large limits like 400 + // (which are be calculated using eps) + constexpr calc_t maxlimit = 1.0e-3; + auto const limit = (std::min)(maxlimit, limit_giga_epsilon * machine_giga_epsilon * c); + return std::abs(a0 - b0) <= limit && std::abs(a1 - b1) <= limit; } template - Point add(Operation const& op, signed_size_type turn_index, int op_index, + static Point walk_over_ring(Operation const& op, int offset, + Geometry1 const& geometry1, + Geometry2 const& geometry2) + { + Point point; + geometry::copy_segment_point(geometry1, geometry2, op.seg_id, offset, point); + return point; + } + + template + Point add(Turn const& turn, Operation const& op, signed_size_type turn_index, int op_index, Geometry1 const& geometry1, Geometry2 const& geometry2, bool is_origin) { - Point point1, point2, point3; + Point point_from, point2, point3; geometry::copy_segment_points(geometry1, geometry2, - op.seg_id, point1, point2, point3); - Point const& point_to = op.fraction.is_one() ? point3 : point2; - add_segment(turn_index, op_index, point1, point_to, op.operation, op.seg_id, is_origin); - return point1; + op.seg_id, point_from, point2, point3); + Point point_to = op.fraction.is_one() ? point3 : point2; + + + // If the point is in the neighbourhood (the limit itself is not important), + // then take a point (or more) further back. + // The limit of offset avoids theoretical infinite loops. In practice it currently + // walks max 1 point back in all cases. + int offset = 0; + while (approximately_equals(point_from, turn.point, 1.0) && offset > -10) + { + point_from = walk_over_ring(op, --offset, geometry1, geometry2); + } + + // Similarly for the point to, walk forward + offset = 0; + while (approximately_equals(point_to, turn.point, 1.0) && offset < 10) + { + point_to = walk_over_ring(op, ++offset, geometry1, geometry2); + } + + add_segment(turn_index, op_index, point_from, point_to, op, is_origin); + + return point_from; } - template - void add(Operation const& op, signed_size_type turn_index, int op_index, + template + void add(Turn const& turn, + Operation const& op, signed_size_type turn_index, int op_index, segment_identifier const& departure_seg_id, Geometry1 const& geometry1, Geometry2 const& geometry2, - bool check_origin) + bool is_departure) { - Point const point1 = add(op, turn_index, op_index, geometry1, geometry2, false); + Point potential_origin = add(turn, op, turn_index, op_index, geometry1, geometry2, false); - if (check_origin) + if (is_departure) { bool const is_origin = op.seg_id.source_index == departure_seg_id.source_index @@ -317,7 +382,7 @@ public : if (m_origin_count == 0 || segment_distance < m_origin_segment_distance) { - m_origin = point1; + m_origin = potential_origin; m_origin_segment_distance = segment_distance; } m_origin_count++; @@ -325,25 +390,33 @@ public : } } + template + static signed_size_type segment_count_on_ring(Operation const& op, + Geometry1 const& geometry1, + Geometry2 const& geometry2) + { + // Take wrap into account + // Suppose point_count=10 (10 points, 9 segments), dep.seg_id=7, op.seg_id=2, + // then distance=9-7+2=4, being segments 7,8,0,1 + return op.seg_id.source_index == 0 + ? detail::overlay::segment_count_on_ring(geometry1, op.seg_id) + : detail::overlay::segment_count_on_ring(geometry2, op.seg_id); + } + template static signed_size_type calculate_segment_distance(Operation const& op, segment_identifier const& departure_seg_id, Geometry1 const& geometry1, Geometry2 const& geometry2) { + BOOST_ASSERT(op.seg_id.source_index == departure_seg_id.source_index); + signed_size_type result = op.seg_id.segment_index - departure_seg_id.segment_index; if (op.seg_id.segment_index >= departure_seg_id.segment_index) { // dep.seg_id=5, op.seg_id=7, distance=2, being segments 5,6 - return op.seg_id.segment_index - departure_seg_id.segment_index; + return result; } - // Take wrap into account - // Suppose point_count=10 (10 points, 9 segments), dep.seg_id=7, op.seg_id=2, - // then distance=9-7+2=4, being segments 7,8,0,1 - std::size_t const segment_count - = op.seg_id.source_index == 0 - ? segment_count_on_ring(geometry1, op.seg_id) - : segment_count_on_ring(geometry2, op.seg_id); - return segment_count - departure_seg_id.segment_index + op.seg_id.segment_index; + return segment_count_on_ring(op, geometry1, geometry2) + result; } void apply(Point const& turn_point) diff --git a/include/boost/geometry/algorithms/detail/overlay/traversal.hpp b/include/boost/geometry/algorithms/detail/overlay/traversal.hpp index a6f8b2a9f..f436639cb 100644 --- a/include/boost/geometry/algorithms/detail/overlay/traversal.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/traversal.hpp @@ -748,7 +748,8 @@ public : for (int i = 0; i < 2; i++) { - sbs.add(cluster_turn.operations[i], + sbs.add(cluster_turn, + cluster_turn.operations[i], cluster_turn_index, i, previous_seg_id, m_geometry1, m_geometry2, departure_turn); @@ -823,7 +824,8 @@ public : // Add this turn to the sort-by-side sorter for (int i = 0; i < 2; i++) { - sbs.add(current_turn.operations[i], + sbs.add(current_turn, + current_turn.operations[i], turn_index, i, previous_seg_id, m_geometry1, m_geometry2, true); diff --git a/include/boost/geometry/algorithms/detail/overlay/traversal_ring_creator.hpp b/include/boost/geometry/algorithms/detail/overlay/traversal_ring_creator.hpp index e180c47bf..fd3513ff2 100644 --- a/include/boost/geometry/algorithms/detail/overlay/traversal_ring_creator.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/traversal_ring_creator.hpp @@ -44,7 +44,7 @@ template typename Turns, typename TurnInfoMap, typename Clusters, - typename IntersectionStrategy, + typename Strategy, typename RobustPolicy, typename Visitor, typename Backtrack @@ -55,7 +55,8 @@ struct traversal_ring_creator < Reverse1, Reverse2, OverlayType, Geometry1, Geometry2, Turns, Clusters, - RobustPolicy, typename IntersectionStrategy::side_strategy_type, + RobustPolicy, + decltype(std::declval().side()), Visitor > traversal_type; @@ -68,17 +69,16 @@ struct traversal_ring_creator inline traversal_ring_creator(Geometry1 const& geometry1, Geometry2 const& geometry2, Turns& turns, TurnInfoMap& turn_info_map, Clusters const& clusters, - IntersectionStrategy const& intersection_strategy, + Strategy const& strategy, RobustPolicy const& robust_policy, Visitor& visitor) : m_trav(geometry1, geometry2, turns, clusters, - robust_policy, intersection_strategy.get_side_strategy(), - visitor) + robust_policy, strategy.side(), visitor) , m_geometry1(geometry1) , m_geometry2(geometry2) , m_turns(turns) , m_turn_info_map(turn_info_map) , m_clusters(clusters) - , m_intersection_strategy(intersection_strategy) + , m_strategy(strategy) , m_robust_policy(robust_policy) , m_visitor(visitor) { @@ -113,15 +113,13 @@ struct traversal_ring_creator { geometry::copy_segments(m_geometry1, previous_op.seg_id, to_vertex_index, - m_intersection_strategy.get_side_strategy(), - m_robust_policy, current_ring); + m_strategy, m_robust_policy, current_ring); } else { geometry::copy_segments(m_geometry2, previous_op.seg_id, to_vertex_index, - m_intersection_strategy.get_side_strategy(), - m_robust_policy, current_ring); + m_strategy, m_robust_policy, current_ring); } } @@ -164,8 +162,7 @@ struct traversal_ring_creator turn_type& current_turn = m_turns[turn_index]; turn_operation_type& op = current_turn.operations[op_index]; detail::overlay::append_no_collinear(current_ring, current_turn.point, - m_intersection_strategy.get_side_strategy(), - m_robust_policy); + m_strategy, m_robust_policy); // Register the visit m_trav.set_visited(current_turn, op); @@ -182,8 +179,7 @@ struct traversal_ring_creator turn_operation_type& start_op = m_turns[start_turn_index].operations[start_op_index]; detail::overlay::append_no_collinear(ring, start_turn.point, - m_intersection_strategy.get_side_strategy(), - m_robust_policy); + m_strategy, m_robust_policy); signed_size_type current_turn_index = start_turn_index; int current_op_index = start_op_index; @@ -286,9 +282,7 @@ struct traversal_ring_creator if (geometry::num_points(ring) >= min_num_points) { - clean_closing_dups_and_spikes(ring, - m_intersection_strategy.get_side_strategy(), - m_robust_policy); + clean_closing_dups_and_spikes(ring, m_strategy, m_robust_policy); rings.push_back(ring); m_trav.finalize_visit_info(m_turn_info_map); @@ -297,14 +291,13 @@ struct traversal_ring_creator } else { - Backtrack::apply( - finalized_ring_size, - rings, ring, m_turns, start_turn, - m_turns[turn_index].operations[op_index], - traverse_error, - m_geometry1, m_geometry2, - m_intersection_strategy, m_robust_policy, - state, m_visitor); + Backtrack::apply(finalized_ring_size, + rings, ring, m_turns, start_turn, + m_turns[turn_index].operations[op_index], + traverse_error, + m_geometry1, m_geometry2, + m_strategy, m_robust_policy, + state, m_visitor); } } @@ -413,7 +406,7 @@ private: Turns& m_turns; TurnInfoMap& m_turn_info_map; // contains turn-info information per ring Clusters const& m_clusters; - IntersectionStrategy const& m_intersection_strategy; + Strategy const& m_strategy; RobustPolicy const& m_robust_policy; Visitor& m_visitor; }; diff --git a/include/boost/geometry/algorithms/detail/relate/areal_areal.hpp b/include/boost/geometry/algorithms/detail/relate/areal_areal.hpp index 18be9a255..99df598da 100644 --- a/include/boost/geometry/algorithms/detail/relate/areal_areal.hpp +++ b/include/boost/geometry/algorithms/detail/relate/areal_areal.hpp @@ -209,10 +209,10 @@ struct areal_areal typedef typename geometry::point_type::type point1_type; typedef typename geometry::point_type::type point2_type; - template + template static inline void apply(Geometry1 const& geometry1, Geometry2 const& geometry2, Result & result, - IntersectionStrategy const& intersection_strategy) + Strategy const& strategy) { // TODO: If Areal geometry may have infinite size, change the following line: @@ -226,38 +226,25 @@ struct areal_areal typedef typename turns::get_turns < Geometry1, Geometry2 - >::template turn_info_type::type turn_type; + >::template turn_info_type::type turn_type; std::vector turns; interrupt_policy_areal_areal interrupt_policy(geometry1, geometry2, result); - turns::get_turns::apply(turns, geometry1, geometry2, interrupt_policy, intersection_strategy); + turns::get_turns::apply(turns, geometry1, geometry2, interrupt_policy, strategy); if ( BOOST_GEOMETRY_CONDITION(result.interrupt) ) return; - typedef typename IntersectionStrategy::cs_tag cs_tag; + typedef typename Strategy::cs_tag cs_tag; - 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(); - 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(); - - no_turns_aa_pred - pred1(geometry2, result, point_in_areal_strategy12); + no_turns_aa_pred + pred1(geometry2, result, strategy); 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 - pred2(geometry1, result, point_in_areal_strategy21); + no_turns_aa_pred + pred2(geometry1, result, strategy); for_each_disjoint_geometry_if<1, Geometry2>::apply(turns.begin(), turns.end(), geometry2, pred2); if ( BOOST_GEOMETRY_CONDITION(result.interrupt) ) return; @@ -282,8 +269,7 @@ struct areal_areal { // analyse sorted turns turns_analyser analyser; - analyse_each_turn(result, analyser, turns.begin(), turns.end(), - point_in_areal_strategy12.get_equals_point_point_strategy()); + analyse_each_turn(result, analyser, turns.begin(), turns.end(), strategy); if ( BOOST_GEOMETRY_CONDITION(result.interrupt) ) return; @@ -297,8 +283,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, point_in_areal_strategy12_type> - rings_analyser(result, geometry1, geometry2, point_in_areal_strategy12); + uncertain_rings_analyser<0, Result, Geometry1, Geometry2, Strategy> + rings_analyser(result, geometry1, geometry2, strategy); analyse_uncertain_rings<0>::apply(rings_analyser, turns.begin(), turns.end()); if ( BOOST_GEOMETRY_CONDITION(result.interrupt) ) @@ -323,8 +309,7 @@ struct areal_areal { // analyse sorted turns turns_analyser analyser; - analyse_each_turn(result, analyser, turns.begin(), turns.end(), - point_in_areal_strategy21.get_equals_point_point_strategy()); + analyse_each_turn(result, analyser, turns.begin(), turns.end(), strategy); if ( BOOST_GEOMETRY_CONDITION(result.interrupt) ) return; @@ -338,8 +323,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, point_in_areal_strategy21_type> - rings_analyser(result, geometry2, geometry1, point_in_areal_strategy21); + uncertain_rings_analyser<1, Result, Geometry2, Geometry1, Strategy> + rings_analyser(result, geometry2, geometry1, strategy); analyse_uncertain_rings<1>::apply(rings_analyser, turns.begin(), turns.end()); //if ( result.interrupt ) diff --git a/include/boost/geometry/algorithms/detail/relate/boundary_checker.hpp b/include/boost/geometry/algorithms/detail/relate/boundary_checker.hpp index 89101ff93..487c706e9 100644 --- a/include/boost/geometry/algorithms/detail/relate/boundary_checker.hpp +++ b/include/boost/geometry/algorithms/detail/relate/boundary_checker.hpp @@ -1,6 +1,6 @@ // Boost.Geometry (aka GGL, Generic Geometry Library) -// Copyright (c) 2014-2018 Oracle and/or its affiliates. +// Copyright (c) 2014-2020 Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle @@ -30,27 +30,29 @@ namespace detail { namespace relate { enum boundary_query { boundary_front, boundary_back, boundary_any }; -template ::type> +template +< + typename Geometry, + typename Strategy, + typename Tag = typename geometry::tag::type +> class boundary_checker {}; -template -class boundary_checker +template +class boundary_checker { typedef typename point_type::type point_type; public: - typedef WithinStrategy equals_strategy_type; - - boundary_checker(Geometry const& g) - : has_boundary( boost::size(g) >= 2 - && !detail::equals::equals_point_point(range::front(g), - range::back(g), - equals_strategy_type()) ) + boundary_checker(Geometry const& g, Strategy const& s) + : m_has_boundary( boost::size(g) >= 2 + && ! detail::equals::equals_point_point(range::front(g), + range::back(g), + s) ) #ifdef BOOST_GEOMETRY_DEBUG_RELATE_BOUNDARY_CHECKER - , geometry(g) + , m_geometry(g) #endif + , m_strategy(s) {} template @@ -60,30 +62,34 @@ public: #ifdef BOOST_GEOMETRY_DEBUG_RELATE_BOUNDARY_CHECKER // may give false positives for INT BOOST_GEOMETRY_ASSERT( (BoundaryQuery == boundary_front || BoundaryQuery == boundary_any) - && detail::equals::equals_point_point(pt, range::front(geometry), WithinStrategy()) + && detail::equals::equals_point_point(pt, range::front(m_geometry), m_strategy) || (BoundaryQuery == boundary_back || BoundaryQuery == boundary_any) - && detail::equals::equals_point_point(pt, range::back(geometry), WithinStrategy()) ); + && detail::equals::equals_point_point(pt, range::back(m_geometry), m_strategy) ); #endif - return has_boundary; + return m_has_boundary; + } + + Strategy const& strategy() const + { + return m_strategy; } private: - bool has_boundary; + bool m_has_boundary; #ifdef BOOST_GEOMETRY_DEBUG_RELATE_BOUNDARY_CHECKER - Geometry const& geometry; + Geometry const& m_geometry; #endif + Strategy const& m_strategy; }; -template -class boundary_checker +template +class boundary_checker { typedef typename point_type::type point_type; public: - typedef WithinStrategy equals_strategy_type; - - boundary_checker(Geometry const& g) - : is_filled(false), geometry(g) + boundary_checker(Geometry const& g, Strategy const& s) + : m_is_filled(false), m_geometry(g), m_strategy(s) {} // First call O(NlogN) @@ -91,22 +97,22 @@ public: template bool is_endpoint_boundary(point_type const& pt) const { - typedef geometry::less less_type; + typedef geometry::less less_type; typedef typename boost::range_size::type size_type; - size_type multi_count = boost::size(geometry); + size_type multi_count = boost::size(m_geometry); if ( multi_count < 1 ) return false; - if ( ! is_filled ) + if ( ! m_is_filled ) { //boundary_points.clear(); - boundary_points.reserve(multi_count * 2); + m_boundary_points.reserve(multi_count * 2); typedef typename boost::range_iterator::type multi_iterator; - for ( multi_iterator it = boost::begin(geometry) ; - it != boost::end(geometry) ; ++ it ) + for ( multi_iterator it = boost::begin(m_geometry) ; + it != boost::end(m_geometry) ; ++ it ) { typename boost::range_reference::type ls = *it; @@ -126,33 +132,33 @@ public: point_reference back_pt = range::back(ls); // linear ring or point - no boundary - if (! equals::equals_point_point(front_pt, back_pt, equals_strategy_type())) + if (! equals::equals_point_point(front_pt, back_pt, m_strategy)) { // do not add points containing NaN coordinates // because they cannot be reasonably compared, e.g. with MSVC // an assertion failure is reported in std::equal_range() if (! geometry::has_nan_coordinate(front_pt)) { - boundary_points.push_back(front_pt); + m_boundary_points.push_back(front_pt); } if (! geometry::has_nan_coordinate(back_pt)) { - boundary_points.push_back(back_pt); + m_boundary_points.push_back(back_pt); } } } - std::sort(boundary_points.begin(), - boundary_points.end(), + std::sort(m_boundary_points.begin(), + m_boundary_points.end(), less_type()); - is_filled = true; + m_is_filled = true; } std::size_t equal_points_count = boost::size( - std::equal_range(boundary_points.begin(), - boundary_points.end(), + std::equal_range(m_boundary_points.begin(), + m_boundary_points.end(), pt, less_type()) ); @@ -160,12 +166,18 @@ public: return equal_points_count % 2 != 0;// && equal_points_count > 0; // the number is odd and > 0 } -private: - mutable bool is_filled; - // TODO: store references/pointers instead of points? - mutable std::vector boundary_points; + Strategy const& strategy() const + { + return m_strategy; + } - Geometry const& geometry; +private: + mutable bool m_is_filled; + // TODO: store references/pointers instead of points? + mutable std::vector m_boundary_points; + + Geometry const& m_geometry; + Strategy const& m_strategy; }; }} // namespace detail::relate diff --git a/include/boost/geometry/algorithms/detail/relate/follow_helpers.hpp b/include/boost/geometry/algorithms/detail/relate/follow_helpers.hpp index 139664cc7..d584e81e5 100644 --- a/include/boost/geometry/algorithms/detail/relate/follow_helpers.hpp +++ b/include/boost/geometry/algorithms/detail/relate/follow_helpers.hpp @@ -341,9 +341,9 @@ private: std::vector m_other_entry_points; // TODO: use map here or sorted vector? }; -template +template inline bool turn_on_the_same_ip(Turn const& prev_turn, Turn const& curr_turn, - EqPPStrategy const& strategy) + Strategy const& strategy) { segment_identifier const& prev_seg_id = prev_turn.operations[OpId].seg_id; segment_identifier const& curr_seg_id = curr_turn.operations[OpId].seg_id; diff --git a/include/boost/geometry/algorithms/detail/relate/interface.hpp b/include/boost/geometry/algorithms/detail/relate/interface.hpp index 1c06d65d5..801ad21db 100644 --- a/include/boost/geometry/algorithms/detail/relate/interface.hpp +++ b/include/boost/geometry/algorithms/detail/relate/interface.hpp @@ -29,7 +29,8 @@ #include #include #include -#include +#include +#include #include #include @@ -161,9 +162,15 @@ struct result_handler_type::value +> struct relate { - template + template static inline void apply(Geometry1 const& geometry1, Geometry2 const& geometry2, ResultHandler & handler, @@ -175,14 +182,37 @@ struct relate Geometry2 >::apply(geometry1, geometry2, handler, strategy); } +}; +template +struct relate +{ + template + static inline void apply(Geometry1 const& geometry1, + Geometry2 const& geometry2, + ResultHandler & handler, + Strategy const& strategy) + { + using strategies::relate::services::strategy_converter; + dispatch::relate + < + Geometry1, + Geometry2 + >::apply(geometry1, geometry2, handler, + strategy_converter::get(strategy)); + } +}; + +template <> +struct relate +{ template static inline void apply(Geometry1 const& geometry1, Geometry2 const& geometry2, ResultHandler & handler, default_strategy) { - typedef typename strategy::relate::services::default_strategy + typedef typename strategies::relate::services::default_strategy < Geometry1, Geometry2 @@ -220,7 +250,7 @@ struct relate Mask >::type handler(mask); - resolve_strategy::relate::apply(geometry1, geometry2, handler, strategy); + resolve_strategy::relate::apply(geometry1, geometry2, handler, strategy); return handler.result(); } diff --git a/include/boost/geometry/algorithms/detail/relate/linear_areal.hpp b/include/boost/geometry/algorithms/detail/relate/linear_areal.hpp index 031564898..28823433a 100644 --- a/include/boost/geometry/algorithms/detail/relate/linear_areal.hpp +++ b/include/boost/geometry/algorithms/detail/relate/linear_areal.hpp @@ -229,10 +229,10 @@ struct linear_areal > {}; - template + template static inline void apply(Geometry1 const& geometry1, Geometry2 const& geometry2, Result & result, - IntersectionStrategy const& intersection_strategy) + Strategy const& strategy) { // TODO: If Areal geometry may have infinite size, change the following line: @@ -243,38 +243,34 @@ struct linear_areal return; // get and analyse turns - typedef typename turn_info_type::type turn_type; + typedef typename turn_info_type::type turn_type; std::vector turns; interrupt_policy_linear_areal interrupt_policy(geometry2, result); - turns::get_turns::apply(turns, geometry1, geometry2, interrupt_policy, intersection_strategy); + turns::get_turns::apply(turns, geometry1, geometry2, interrupt_policy, strategy); if ( BOOST_GEOMETRY_CONDITION( result.interrupt ) ) return; - typedef typename IntersectionStrategy::template point_in_geometry_strategy::type within_strategy_type; - within_strategy_type const within_strategy = intersection_strategy.template get_point_in_geometry_strategy(); - - typedef typename IntersectionStrategy::cs_tag cs_tag; - typedef typename within_strategy_type::equals_point_point_strategy_type eq_pp_strategy_type; + typedef typename Strategy::cs_tag cs_tag; typedef boundary_checker < Geometry1, - eq_pp_strategy_type + Strategy > boundary_checker1_type; - boundary_checker1_type boundary_checker1(geometry1); + boundary_checker1_type boundary_checker1(geometry1, strategy); no_turns_la_linestring_pred < Geometry2, Result, - within_strategy_type, + Strategy, boundary_checker1_type, TransposeResult > pred1(geometry2, result, - within_strategy, + strategy, boundary_checker1); for_each_disjoint_geometry_if<0, Geometry1>::apply(turns.begin(), turns.end(), geometry1, pred1); if ( BOOST_GEOMETRY_CONDITION( result.interrupt ) ) @@ -302,7 +298,7 @@ struct linear_areal turns.begin(), turns.end(), geometry1, geometry2, boundary_checker1, - intersection_strategy.get_side_strategy()); + strategy); if ( BOOST_GEOMETRY_CONDITION( result.interrupt ) ) return; @@ -395,14 +391,12 @@ struct linear_areal typedef turns::less<1, turns::less_op_areal_linear<1>, cs_tag> less; std::sort(it, next, less()); - eq_pp_strategy_type const eq_pp_strategy = within_strategy.get_equals_point_point_strategy(); - // analyse areal_boundary_analyser analyser; for ( turn_iterator rit = it ; rit != next ; ++rit ) { // if the analyser requests, break the search - if ( !analyser.apply(it, rit, next, eq_pp_strategy) ) + if ( !analyser.apply(it, rit, next, strategy) ) break; } @@ -626,18 +620,20 @@ struct linear_areal static const std::size_t other_op_id = 1; template struct la_side_calculator { + typedef decltype(std::declval().side()) side_strategy_type; + inline la_side_calculator(Pi const& pi, Pj const& pj, Pk const& pk, - Qi const& qi, Qj const& qj, Qk const& qk, - SideStrategy const& side_strategy) + Qi const& qi, Qj const& qj, Qk const& qk, + Strategy const& strategy) : m_pi(pi), m_pj(pj), m_pk(pk) , m_qi(qi), m_qj(qj), m_qk(qk) - , m_side_strategy(side_strategy) + , m_side_strategy(strategy.side()) {} inline int pk_wrt_p1() const { return m_side_strategy.apply(m_pi, m_pj, m_pk); } @@ -652,7 +648,7 @@ struct linear_areal Qj const& m_qj; Qk const& m_qk; - SideStrategy m_side_strategy; + side_strategy_type m_side_strategy; }; @@ -672,12 +668,12 @@ struct linear_areal typename Geometry, typename OtherGeometry, typename BoundaryChecker, - typename SideStrategy> + typename Strategy> void apply(Result & res, TurnIt it, Geometry const& geometry, OtherGeometry const& other_geometry, BoundaryChecker const& boundary_checker, - SideStrategy const& side_strategy) + Strategy const& strategy) { overlay::operation_type op = it->operations[op_id].operation; @@ -706,7 +702,7 @@ struct linear_areal // real exit point - may be multiple // we know that we entered and now we exit if ( ! turn_on_the_same_ip(m_exit_watcher.get_exit_turn(), *it, - side_strategy.get_equals_point_point_strategy()) ) + strategy) ) { m_exit_watcher.reset_detected_exit(); @@ -749,7 +745,7 @@ struct linear_areal if ( ( op == overlay::operation_intersection || op == overlay::operation_continue ) && turn_on_the_same_ip(m_exit_watcher.get_exit_turn(), *it, - side_strategy.get_equals_point_point_strategy()) ) + strategy) ) { fake_enter_detected = true; } @@ -770,7 +766,7 @@ struct linear_areal || seg_id.multi_index != m_previous_turn_ptr->operations[op_id].seg_id.multi_index ) ) // or the next single-geometry || ( m_previous_operation == overlay::operation_union && ! turn_on_the_same_ip(*m_previous_turn_ptr, *it, - side_strategy.get_equals_point_point_strategy()) ) + strategy) ) ) { update(res); @@ -803,7 +799,7 @@ struct linear_areal // real interior overlap if ( ! turn_on_the_same_ip(*m_previous_turn_ptr, *it, - side_strategy.get_equals_point_point_strategy()) ) + strategy) ) { update(res); m_interior_detected = false; @@ -919,7 +915,7 @@ struct linear_areal && calculate_from_inside(geometry, other_geometry, *it, - side_strategy); + strategy); if ( from_inside ) update(res); @@ -1020,7 +1016,7 @@ struct linear_areal && calculate_from_inside(geometry, other_geometry, *it, - side_strategy); + strategy); if ( first_from_inside ) { update(res); @@ -1208,11 +1204,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 + template static inline bool calculate_from_inside(Geometry1 const& geometry1, Geometry2 const& geometry2, Turn const& turn, - SideStrategy const& side_strategy) + Strategy const& strategy) { typedef typename cs_tag::type cs_tag; @@ -1242,7 +1238,7 @@ struct linear_areal point2_type const& qj = range::at(range2, q_seg_ij + 1); point1_type qi_conv; geometry::convert(qi, qi_conv); - bool const is_ip_qj = equals::equals_point_point(turn.point, qj, side_strategy.get_equals_point_point_strategy()); + bool const is_ip_qj = equals::equals_point_point(turn.point, qj, strategy); // TODO: test this! // BOOST_GEOMETRY_ASSERT(!equals::equals_point_point(turn.point, pi)); // BOOST_GEOMETRY_ASSERT(!equals::equals_point_point(turn.point, qi)); @@ -1257,11 +1253,11 @@ struct linear_areal range2_iterator qk_it = find_next_non_duplicated(boost::begin(range2), range::pos(range2, q_seg_jk), boost::end(range2), - side_strategy.get_equals_point_point_strategy()); + strategy); // Will this sequence of points be always correct? - la_side_calculator - side_calc(qi_conv, new_pj, pi, qi, qj, *qk_it, side_strategy); + la_side_calculator + side_calc(qi_conv, new_pj, pi, qi, qj, *qk_it, strategy); return calculate_from_inside_sides(side_calc); } @@ -1270,16 +1266,16 @@ struct linear_areal point2_type new_qj; geometry::convert(turn.point, new_qj); - la_side_calculator - side_calc(qi_conv, new_pj, pi, qi, new_qj, qj, side_strategy); + la_side_calculator + side_calc(qi_conv, new_pj, pi, qi, new_qj, qj, strategy); return calculate_from_inside_sides(side_calc); } } - template + template static inline It find_next_non_duplicated(It first, It current, It last, - EqPPStrategy const& strategy) + Strategy const& strategy) { BOOST_GEOMETRY_ASSERT( current != last ); @@ -1340,14 +1336,14 @@ struct linear_areal typename Geometry, typename OtherGeometry, typename BoundaryChecker, - typename SideStrategy> + typename Strategy> 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, - SideStrategy const& side_strategy) + Strategy const& strategy) { if ( first == last ) return; @@ -1357,7 +1353,7 @@ struct linear_areal analyser.apply(res, it, geometry, other_geometry, boundary_checker, - side_strategy); + strategy); if ( BOOST_GEOMETRY_CONDITION( res.interrupt ) ) return; @@ -1437,9 +1433,9 @@ struct linear_areal , m_previous_turn_ptr(NULL) {} - template + template bool apply(TurnIt /*first*/, TurnIt it, TurnIt last, - EqPPStrategy const& strategy) + Strategy const& strategy) { overlay::operation_type op = it->operations[1].operation; @@ -1493,12 +1489,12 @@ struct areal_linear static const bool interruption_enabled = linear_areal_type::interruption_enabled; - template + template static inline void apply(Geometry1 const& geometry1, Geometry2 const& geometry2, Result & result, - IntersectionStrategy const& intersection_strategy) + Strategy const& strategy) { - linear_areal_type::apply(geometry2, geometry1, result, intersection_strategy); + linear_areal_type::apply(geometry2, geometry1, result, strategy); } }; diff --git a/include/boost/geometry/algorithms/detail/relate/linear_linear.hpp b/include/boost/geometry/algorithms/detail/relate/linear_linear.hpp index ec8fe428d..fa46db245 100644 --- a/include/boost/geometry/algorithms/detail/relate/linear_linear.hpp +++ b/include/boost/geometry/algorithms/detail/relate/linear_linear.hpp @@ -42,8 +42,6 @@ namespace detail { namespace relate { template class disjoint_linestring_pred { - typedef typename BoundaryChecker::equals_strategy_type equals_strategy_type; - public: disjoint_linestring_pred(Result & res, BoundaryChecker const& boundary_checker) @@ -83,7 +81,7 @@ public: if ( count == 2 && equals::equals_point_point(range::front(linestring), range::back(linestring), - equals_strategy_type()) ) + m_boundary_checker.strategy()) ) { update(m_result); } @@ -122,12 +120,12 @@ struct linear_linear typedef typename geometry::point_type::type point1_type; typedef typename geometry::point_type::type point2_type; - template + template static inline void apply(Geometry1 const& geometry1, Geometry2 const& geometry2, Result & result, - IntersectionStrategy const& intersection_strategy) + Strategy const& strategy) { - typedef typename IntersectionStrategy::cs_tag cs_tag; + typedef typename Strategy::cs_tag cs_tag; // The result should be FFFFFFFFF relate::set::value>(result);// FFFFFFFFd, d in [1,9] or T @@ -138,7 +136,7 @@ struct linear_linear typedef typename turns::get_turns < Geometry1, Geometry2 - >::template turn_info_type::type turn_type; + >::template turn_info_type::type turn_type; std::vector turns; interrupt_policy_linear_linear interrupt_policy(result); @@ -148,28 +146,20 @@ struct linear_linear Geometry1, Geometry2, detail::get_turns::get_turn_info_type > - >::apply(turns, geometry1, geometry2, interrupt_policy, intersection_strategy); + >::apply(turns, geometry1, geometry2, interrupt_policy, strategy); if ( BOOST_GEOMETRY_CONDITION( result.interrupt ) ) return; - typedef boundary_checker - < - Geometry1, - typename IntersectionStrategy::point_in_point_strategy_type - > boundary_checker1_type; - boundary_checker1_type boundary_checker1(geometry1); + typedef boundary_checker boundary_checker1_type; + boundary_checker1_type boundary_checker1(geometry1, strategy); disjoint_linestring_pred pred1(result, boundary_checker1); for_each_disjoint_geometry_if<0, Geometry1>::apply(turns.begin(), turns.end(), geometry1, pred1); if ( BOOST_GEOMETRY_CONDITION( result.interrupt ) ) return; - typedef boundary_checker - < - Geometry2, - typename IntersectionStrategy::point_in_point_strategy_type - > boundary_checker2_type; - boundary_checker2_type boundary_checker2(geometry2); + typedef boundary_checker boundary_checker2_type; + boundary_checker2_type boundary_checker2(geometry2, strategy); disjoint_linestring_pred pred2(result, boundary_checker2); for_each_disjoint_geometry_if<1, Geometry2>::apply(turns.begin(), turns.end(), geometry2, pred2); if ( BOOST_GEOMETRY_CONDITION( result.interrupt ) ) @@ -292,8 +282,6 @@ struct linear_linear BoundaryChecker const& boundary_checker, OtherBoundaryChecker const& other_boundary_checker) { - typedef typename BoundaryChecker::equals_strategy_type equals_strategy_type; - overlay::operation_type const op = it->operations[op_id].operation; segment_identifier const& seg_id = it->operations[op_id].seg_id; @@ -345,7 +333,7 @@ struct linear_linear // we know that we entered and now we exit if ( ! turn_on_the_same_ip(m_exit_watcher.get_exit_turn(), *it, - equals_strategy_type()) ) + boundary_checker.strategy()) ) { m_exit_watcher.reset_detected_exit(); @@ -368,7 +356,7 @@ struct linear_linear if ( op == overlay::operation_intersection && turn_on_the_same_ip(m_exit_watcher.get_exit_turn(), *it, - equals_strategy_type()) ) + boundary_checker.strategy()) ) { fake_enter_detected = true; } @@ -668,14 +656,9 @@ struct linear_linear Geometry const& geometry, OtherGeometry const& other_geometry, BoundaryChecker const& boundary_checker, - OtherBoundaryChecker const& /*other_boundary_checker*/, + OtherBoundaryChecker const& other_boundary_checker, bool first_in_range) { - typedef typename BoundaryChecker::equals_strategy_type - equals_strategy1_type; - typedef typename OtherBoundaryChecker::equals_strategy_type - equals_strategy2_type; - typename detail::single_geometry_return_type::type ls1_ref = detail::single_geometry(geometry, turn.operations[op_id].seg_id); typename detail::single_geometry_return_type::type @@ -745,11 +728,11 @@ struct linear_linear bool const is_point1 = boost::size(ls1_ref) == 2 && equals::equals_point_point(range::front(ls1_ref), range::back(ls1_ref), - equals_strategy1_type()); + boundary_checker.strategy()); bool const is_point2 = boost::size(ls2_ref) == 2 && equals::equals_point_point(range::front(ls2_ref), range::back(ls2_ref), - equals_strategy2_type()); + other_boundary_checker.strategy()); // if the second one is degenerated if ( !is_point1 && is_point2 ) diff --git a/include/boost/geometry/algorithms/detail/relate/multi_point_geometry.hpp b/include/boost/geometry/algorithms/detail/relate/multi_point_geometry.hpp index 12b4ff642..7da7f2be5 100644 --- a/include/boost/geometry/algorithms/detail/relate/multi_point_geometry.hpp +++ b/include/boost/geometry/algorithms/detail/relate/multi_point_geometry.hpp @@ -50,21 +50,20 @@ namespace detail { namespace relate template < typename Geometry, - typename EqPPStrategy, typename Tag = typename tag::type > struct multi_point_geometry_eb { - template + template static inline bool apply(MultiPoint const& , - detail::relate::topology_check const& ) + detail::relate::topology_check const& ) { return true; } }; -template -struct multi_point_geometry_eb +template +struct multi_point_geometry_eb { template struct boundary_visitor @@ -74,26 +73,30 @@ struct multi_point_geometry_eb , m_boundary_found(false) {} - template + template struct find_pred { - find_pred(Point const& point) + find_pred(Point const& point, Strategy const& strategy) : m_point(point) + , m_strategy(strategy) {} template bool operator()(Pt const& pt) const { - return detail::equals::equals_point_point(pt, m_point, EqPPStrategy()); + return detail::equals::equals_point_point(pt, m_point, m_strategy); } Point const& m_point; + Strategy const& m_strategy; }; - template - bool apply(Point const& boundary_point) + template + bool apply(Point const& boundary_point, Strategy const& strategy) { - if (std::find_if(m_points.begin(), m_points.end(), find_pred(boundary_point)) == m_points.end()) + if ( std::find_if(m_points.begin(), m_points.end(), + find_pred(boundary_point, strategy)) + == m_points.end() ) { m_boundary_found = true; return false; @@ -108,9 +111,9 @@ struct multi_point_geometry_eb bool m_boundary_found; }; - template + template static inline bool apply(MultiPoint const& multi_point, - detail::relate::topology_check const& tc) + detail::relate::topology_check const& tc) { boundary_visitor visitor(multi_point); tc.for_each_boundary_point(visitor); @@ -118,12 +121,9 @@ struct multi_point_geometry_eb } }; -template -struct multi_point_geometry_eb +template +struct multi_point_geometry_eb { - // TODO: CS-specific less compare strategy derived from EqPPStrategy - typedef geometry::less less_type; - template struct boundary_visitor { @@ -132,10 +132,13 @@ struct multi_point_geometry_eb , m_boundary_found(false) {} - template - bool apply(Point const& boundary_point) + template + bool apply(Point const& boundary_point, Strategy const&) { - if (! std::binary_search(m_points.begin(), m_points.end(), boundary_point, less_type())) + typedef geometry::less less_type; + + if (! std::binary_search(m_points.begin(), m_points.end(), + boundary_point, less_type()) ) { m_boundary_found = true; return false; @@ -150,13 +153,15 @@ struct multi_point_geometry_eb bool m_boundary_found; }; - template + template static inline bool apply(MultiPoint const& multi_point, - detail::relate::topology_check const& tc) + detail::relate::topology_check const& tc) { typedef typename boost::range_value::type point_type; typedef std::vector points_type; - points_type points(boost::begin(multi_point), boost::end(multi_point)); + typedef geometry::less less_type; + + points_type points(boost::begin(multi_point), boost::end(multi_point)); std::sort(points.begin(), points.end(), less_type()); boundary_visitor visitor(points); @@ -179,11 +184,9 @@ struct multi_point_single_geometry { typedef typename point_type::type point2_type; typedef model::box box2_type; - typedef typename Strategy::equals_point_point_strategy_type eq_pp_strategy_type; - typedef typename Strategy::disjoint_point_box_strategy_type d_pb_strategy_type; box2_type box2; - geometry::envelope(single_geometry, box2, strategy.get_envelope_strategy()); + geometry::envelope(single_geometry, box2, strategy); geometry::detail::expand_by_epsilon(box2); typedef typename boost::range_const_iterator::type iterator; @@ -197,7 +200,7 @@ struct multi_point_single_geometry } // The default strategy is enough for Point/Box - if (detail::disjoint::disjoint_point_box(*it, box2, d_pb_strategy_type())) + if (detail::disjoint::disjoint_point_box(*it, box2, strategy)) { relate::set(result); } @@ -225,14 +228,12 @@ struct multi_point_single_geometry } } - typedef detail::relate::topology_check - < - SingleGeometry, eq_pp_strategy_type - > tc_t; + typedef detail::relate::topology_check tc_t; + if ( relate::may_update(result) || relate::may_update(result) ) { - tc_t tc(single_geometry); + tc_t tc(single_geometry, strategy); if ( relate::may_update(result) && tc.has_interior() ) @@ -245,10 +246,7 @@ struct multi_point_single_geometry if ( relate::may_update(result) && tc.has_boundary() ) { - if (multi_point_geometry_eb - < - SingleGeometry, eq_pp_strategy_type - >::apply(multi_point, tc)) + if (multi_point_geometry_eb::apply(multi_point, tc)) { relate::set(result); } @@ -266,62 +264,88 @@ struct multi_point_single_geometry template class multi_point_multi_geometry_ii_ib { - template + template struct expand_box_point { + expand_box_point(Strategy const& strategy) + : m_strategy(strategy) + {} + template - static inline void apply(Box& total, Point const& point) + inline void apply(Box& total, Point const& point) const { - geometry::expand(total, point, ExpandPointStrategy()); + geometry::expand(total, point, m_strategy); } + + private: + Strategy const& m_strategy; }; - template + template struct expand_box_box_pair { + expand_box_box_pair(Strategy const& strategy) + : m_strategy(strategy) + {} + template - static inline void apply(Box& total, BoxPair const& box_pair) + inline void apply(Box& total, BoxPair const& box_pair) const { - geometry::expand(total, box_pair.first, ExpandBoxStrategy()); + geometry::expand(total, box_pair.first, m_strategy); } + + private: + Strategy const& m_strategy; }; - template + template struct overlaps_box_point { + overlaps_box_point(Strategy const& strategy) + : m_strategy(strategy) + {} + template - static inline bool apply(Box const& box, Point const& point) + inline bool apply(Box const& box, Point const& point) const { // The default strategy is enough for Point/Box return ! detail::disjoint::disjoint_point_box(point, box, - DisjointPointBoxStrategy()); + m_strategy); } + + private: + Strategy const& m_strategy; }; - template + template struct overlaps_box_box_pair { + overlaps_box_box_pair(Strategy const& strategy) + : m_strategy(strategy) + {} + template - static inline bool apply(Box const& box, BoxPair const& box_pair) + inline bool apply(Box const& box, BoxPair const& box_pair) const { // The default strategy is enough for Box/Box return ! detail::disjoint::disjoint_box_box(box_pair.first, box, - DisjointBoxBoxStrategy()); + m_strategy); } + + private: + Strategy const& m_strategy; }; - template + template class item_visitor_type { - typedef typename PtSegStrategy::equals_point_point_strategy_type pp_strategy_type; - typedef typename PtSegStrategy::disjoint_point_box_strategy_type d_pp_strategy_type; - typedef detail::relate::topology_check topology_check_type; + typedef detail::relate::topology_check topology_check_type; public: item_visitor_type(MultiGeometry const& multi_geometry, topology_check_type const& tc, Result & result, - PtSegStrategy const& strategy) + Strategy const& strategy) : m_multi_geometry(multi_geometry) , m_tc(tc) , m_result(result) @@ -332,7 +356,7 @@ class multi_point_multi_geometry_ii_ib inline bool apply(Point const& point, BoxPair const& box_pair) { // The default strategy is enough for Point/Box - if (! detail::disjoint::disjoint_point_box(point, box_pair.first, d_pp_strategy_type())) + if (! detail::disjoint::disjoint_point_box(point, box_pair.first, m_strategy) ) { typename boost::range_value::type const& single = range::at(m_multi_geometry, box_pair.second); @@ -371,7 +395,7 @@ class multi_point_multi_geometry_ii_ib MultiGeometry const& m_multi_geometry; topology_check_type const& m_tc; Result & m_result; - PtSegStrategy const& m_strategy; + Strategy const& m_strategy; }; public: @@ -387,46 +411,21 @@ public: std::vector const& boxes, detail::relate::topology_check < - MultiGeometry, - typename Strategy::equals_point_point_strategy_type + MultiGeometry, Strategy > const& tc, Result & result, Strategy const& strategy) { item_visitor_type visitor(multi_geometry, tc, result, strategy); - typedef expand_box_point - < - typename Strategy::expand_point_strategy_type - > expand_box_point_type; - typedef overlaps_box_point - < - typename Strategy::disjoint_point_box_strategy_type - > overlaps_box_point_type; - typedef expand_box_box_pair - < - // TEMP - envelope umbrella strategy also contains - // expand strategies - decltype(strategies::envelope::services::strategy_converter - < - typename Strategy::envelope_strategy_type - >::get(strategy.get_envelope_strategy()) - .expand(std::declval(), - std::declval())) - > expand_box_box_pair_type; - typedef overlaps_box_box_pair - < - typename Strategy::disjoint_box_box_strategy_type - > overlaps_box_box_pair_type; - geometry::partition < box1_type >::apply(multi_point, boxes, visitor, - expand_box_point_type(), - overlaps_box_point_type(), - expand_box_box_pair_type(), - overlaps_box_box_pair_type()); + expand_box_point(strategy), + overlaps_box_point(strategy), + expand_box_box_pair(strategy), + overlaps_box_box_pair(strategy)); } }; @@ -451,23 +450,18 @@ struct multi_point_multi_geometry_ii_ib_ie std::vector const& boxes, detail::relate::topology_check < - MultiGeometry, - typename Strategy::equals_point_point_strategy_type + MultiGeometry, Strategy > const& tc, Result & result, Strategy const& strategy) { - typedef strategy::index::services::from_strategy - < - Strategy - > index_strategy_from; typedef index::parameters < - index::rstar<4>, typename index_strategy_from::type + index::rstar<4>, Strategy > index_parameters_type; index::rtree rtree(boxes.begin(), boxes.end(), - index_parameters_type(index::rstar<4>(), index_strategy_from::get(strategy))); + index_parameters_type(index::rstar<4>(), strategy)); typedef typename boost::range_const_iterator::type iterator; for ( iterator it = boost::begin(multi_point) ; it != boost::end(multi_point) ; ++it ) @@ -537,22 +531,17 @@ struct multi_point_multi_geometry typedef model::box box2_type; typedef std::pair box_pair_type; - typedef typename Strategy::equals_point_point_strategy_type eq_pp_strategy_type; - - typename Strategy::envelope_strategy_type const - envelope_strategy = strategy.get_envelope_strategy(); - std::size_t count2 = boost::size(multi_geometry); std::vector boxes(count2); for (std::size_t i = 0 ; i < count2 ; ++i) { - geometry::envelope(range::at(multi_geometry, i), boxes[i].first, envelope_strategy); + geometry::envelope(range::at(multi_geometry, i), boxes[i].first, strategy); geometry::detail::expand_by_epsilon(boxes[i].first); boxes[i].second = i; } - typedef detail::relate::topology_check tc_t; - tc_t tc(multi_geometry); + typedef detail::relate::topology_check tc_t; + tc_t tc(multi_geometry, strategy); if ( relate::may_update(result) || relate::may_update(result) @@ -590,10 +579,7 @@ struct multi_point_multi_geometry if ( relate::may_update(result) && tc.has_boundary() ) { - if (multi_point_geometry_eb - < - MultiGeometry, eq_pp_strategy_type - >::apply(multi_point, tc)) + if (multi_point_geometry_eb::apply(multi_point, tc)) { relate::set(result); } diff --git a/include/boost/geometry/algorithms/detail/relate/point_geometry.hpp b/include/boost/geometry/algorithms/detail/relate/point_geometry.hpp index 7b1726abe..501c5f3dd 100644 --- a/include/boost/geometry/algorithms/detail/relate/point_geometry.hpp +++ b/include/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, 2017, 2018. -// Modifications copyright (c) 2013-2018 Oracle and/or its affiliates. +// This file was modified by Oracle on 2013-2020. +// Modifications copyright (c) 2013-2020 Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle @@ -60,11 +60,8 @@ struct point_geometry if ( BOOST_GEOMETRY_CONDITION(result.interrupt) ) return; - typedef detail::relate::topology_check - < - Geometry, - typename Strategy::equals_point_point_strategy_type - > tc_t; + typedef detail::relate::topology_check tc_t; + if ( relate::may_update(result) || relate::may_update(result) ) { @@ -79,7 +76,7 @@ struct point_geometry else { // check if there is a boundary in Geometry - tc_t tc(geometry); + tc_t tc(geometry, strategy); if ( tc.has_interior() ) relate::set(result); if ( tc.has_boundary() ) diff --git a/include/boost/geometry/algorithms/detail/relate/result.hpp b/include/boost/geometry/algorithms/detail/relate/result.hpp index 03bdb8384..c7a83665b 100644 --- a/include/boost/geometry/algorithms/detail/relate/result.hpp +++ b/include/boost/geometry/algorithms/detail/relate/result.hpp @@ -18,6 +18,7 @@ #include #include #include +#include #include #include diff --git a/include/boost/geometry/algorithms/detail/relate/topology_check.hpp b/include/boost/geometry/algorithms/detail/relate/topology_check.hpp index ab42504ec..459c81614 100644 --- a/include/boost/geometry/algorithms/detail/relate/topology_check.hpp +++ b/include/boost/geometry/algorithms/detail/relate/topology_check.hpp @@ -1,6 +1,6 @@ // Boost.Geometry (aka GGL, Generic Geometry Library) -// Copyright (c) 2014-2018, Oracle and/or its affiliates. +// Copyright (c) 2014-2020, Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle @@ -28,15 +28,18 @@ namespace detail { namespace relate { // TODO: change the name for e.g. something with the word "exterior" -template ::type> +template +< + typename Geometry, + typename Strategy, + typename Tag = typename geometry::tag::type +> struct topology_check : not_implemented {}; -//template -//struct topology_check +//template +//struct topology_check //{ // static const char interior = '0'; // static const char boundary = 'F'; @@ -49,14 +52,15 @@ struct topology_check // topology_check(Point const&, IgnoreBoundaryPoint const&) {} //}; -template -struct topology_check +template +struct topology_check { static const char interior = '1'; static const char boundary = '0'; - topology_check(Linestring const& ls) + topology_check(Linestring const& ls, Strategy const& strategy) : m_ls(ls) + , m_strategy(strategy) , m_is_initialized(false) {} @@ -87,8 +91,8 @@ struct topology_check init(); if (m_has_boundary) { - if (visitor.apply(range::front(m_ls))) - visitor.apply(range::back(m_ls)); + if (visitor.apply(range::front(m_ls), m_strategy)) + visitor.apply(range::back(m_ls), m_strategy); } } @@ -104,26 +108,29 @@ private: m_has_boundary = count > 1 && ! detail::equals::equals_point_point(range::front(m_ls), range::back(m_ls), - EqPPStrategy()); + m_strategy); m_is_initialized = true; } Linestring const& m_ls; + Strategy const& m_strategy; + mutable bool m_is_initialized; mutable bool m_has_interior; mutable bool m_has_boundary; }; -template -struct topology_check +template +struct topology_check { static const char interior = '1'; static const char boundary = '0'; - topology_check(MultiLinestring const& mls) + topology_check(MultiLinestring const& mls, Strategy const& strategy) : m_mls(mls) + , m_strategy(strategy) , m_is_initialized(false) {} @@ -163,7 +170,7 @@ struct topology_check } private: - typedef geometry::less less_type; + typedef geometry::less less_type; void init() const { @@ -198,7 +205,7 @@ private: point_reference back_pt = range::back(ls); // don't store boundaries of linear rings, this doesn't change anything - if (! equals::equals_point_point(front_pt, back_pt, EqPPStrategy())) + if (! equals::equals_point_point(front_pt, back_pt, m_strategy)) { // do not add points containing NaN coordinates // because they cannot be reasonably compared, e.g. with MSVC @@ -236,7 +243,7 @@ private: } template - static inline bool find_odd_count(It first, It last) + inline bool find_odd_count(It first, It last) const { interrupting_visitor visitor; for_each_boundary_point(first, last, visitor); @@ -248,7 +255,7 @@ private: bool found; interrupting_visitor() : found(false) {} template - bool apply(Point const&) + bool apply(Point const&, Strategy const&) { found = true; return false; @@ -256,7 +263,7 @@ private: }; template - static void for_each_boundary_point(It first, It last, Visitor& visitor) + void for_each_boundary_point(It first, It last, Visitor& visitor) const { if ( first == last ) return; @@ -267,12 +274,12 @@ private: for ( ; first != last ; ++first, ++prev ) { // the end of the equal points subrange - if ( ! equals::equals_point_point(*first, *prev, EqPPStrategy()) ) + if ( ! equals::equals_point_point(*first, *prev, m_strategy) ) { // odd count -> boundary if ( count % 2 != 0 ) { - if (! visitor.apply(*prev)) + if (! visitor.apply(*prev, m_strategy)) { return; } @@ -289,12 +296,14 @@ private: // odd count -> boundary if ( count % 2 != 0 ) { - visitor.apply(*prev); + visitor.apply(*prev, m_strategy); } } private: MultiLinestring const& m_mls; + Strategy const& m_strategy; + mutable bool m_is_initialized; mutable bool m_has_interior; @@ -313,25 +322,25 @@ struct topology_check_areal static bool has_boundary() { return true; } }; -template -struct topology_check +template +struct topology_check : topology_check_areal { - topology_check(Ring const&) {} + topology_check(Ring const&, Strategy const&) {} }; -template -struct topology_check +template +struct topology_check : topology_check_areal { - topology_check(Polygon const&) {} + topology_check(Polygon const&, Strategy const&) {} }; -template -struct topology_check +template +struct topology_check : topology_check_areal { - topology_check(MultiPolygon const&) {} + topology_check(MultiPolygon const&, Strategy const&) {} template static bool check_boundary_point(Point const& ) { return true; } diff --git a/include/boost/geometry/algorithms/detail/relate/turns.hpp b/include/boost/geometry/algorithms/detail/relate/turns.hpp index 7a5012896..7d8288730 100644 --- a/include/boost/geometry/algorithms/detail/relate/turns.hpp +++ b/include/boost/geometry/algorithms/detail/relate/turns.hpp @@ -84,43 +84,28 @@ struct get_turns > type; }; - template - static inline void apply(Turns & turns, - Geometry1 const& geometry1, - Geometry2 const& geometry2) - { - detail::get_turns::no_interrupt_policy interrupt_policy; - - typename strategy::intersection::services::default_strategy - < - typename cs_tag::type - >::type intersection_strategy; - - apply(turns, geometry1, geometry2, interrupt_policy, intersection_strategy); - } - - template + template static inline void apply(Turns & turns, Geometry1 const& geometry1, Geometry2 const& geometry2, InterruptPolicy & interrupt_policy, - IntersectionStrategy const& intersection_strategy) + Strategy const& strategy) { - typedef typename robust_policy_type::type robust_policy_t; + typedef typename robust_policy_type::type robust_policy_t; robust_policy_t robust_policy = geometry::get_rescale_policy( - geometry1, geometry2, intersection_strategy); + geometry1, geometry2, strategy); - apply(turns, geometry1, geometry2, interrupt_policy, intersection_strategy, robust_policy); + apply(turns, geometry1, geometry2, interrupt_policy, strategy, robust_policy); } - template + template static inline void apply(Turns & turns, Geometry1 const& geometry1, Geometry2 const& geometry2, InterruptPolicy & interrupt_policy, - IntersectionStrategy const& intersection_strategy, + Strategy const& strategy, RobustPolicy const& robust_policy) { static const bool reverse1 = detail::overlay::do_reverse @@ -143,7 +128,7 @@ struct get_turns reverse2, GetTurnPolicy >::apply(0, geometry1, 1, geometry2, - intersection_strategy, robust_policy, + strategy, robust_policy, turns, interrupt_policy); } }; diff --git a/include/boost/geometry/algorithms/detail/relation/interface.hpp b/include/boost/geometry/algorithms/detail/relation/interface.hpp index 6e555116d..e9d940c3e 100644 --- a/include/boost/geometry/algorithms/detail/relation/interface.hpp +++ b/include/boost/geometry/algorithms/detail/relation/interface.hpp @@ -57,7 +57,10 @@ struct relation Matrix >::type handler; - resolve_strategy::relate::apply(geometry1, geometry2, handler, strategy); + resolve_strategy::relate + < + Strategy + >::apply(geometry1, geometry2, handler, strategy); return handler.result(); } diff --git a/include/boost/geometry/algorithms/detail/sections/section_box_policies.hpp b/include/boost/geometry/algorithms/detail/sections/section_box_policies.hpp index 5727ee817..2caaea096 100644 --- a/include/boost/geometry/algorithms/detail/sections/section_box_policies.hpp +++ b/include/boost/geometry/algorithms/detail/sections/section_box_policies.hpp @@ -2,8 +2,8 @@ // Copyright (c) 2015 Barend Gehrels, Amsterdam, the Netherlands. -// This file was modified by Oracle on 2018. -// Modifications copyright (c) 2018, Oracle and/or its affiliates. +// This file was modified by Oracle on 2018-2020. +// Modifications copyright (c) 2018-2020, 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, @@ -26,28 +26,39 @@ namespace boost { namespace geometry namespace detail { namespace section { -template +template struct get_section_box { + get_section_box(Strategy const& strategy) + : m_strategy(strategy) + {} + template - static inline void apply(Box& total, Section const& section) + inline void apply(Box& total, Section const& section) const { assert_coordinate_type_equal(total, section.bounding_box); - geometry::expand(total, section.bounding_box, - ExpandBoxStrategy()); + geometry::expand(total, section.bounding_box, m_strategy); } + + Strategy const& m_strategy; }; -template +template struct overlaps_section_box { + overlaps_section_box(Strategy const& strategy) + : m_strategy(strategy) + {} + template - static inline bool apply(Box const& box, Section const& section) + inline bool apply(Box const& box, Section const& section) const { assert_coordinate_type_equal(box, section.bounding_box); return ! detail::disjoint::disjoint_box_box(box, section.bounding_box, - DisjointBoxBoxStrategy()); + m_strategy); } + + Strategy const& m_strategy; }; diff --git a/include/boost/geometry/algorithms/detail/sections/sectionalize.hpp b/include/boost/geometry/algorithms/detail/sections/sectionalize.hpp index 6478eedb1..b670030c4 100644 --- a/include/boost/geometry/algorithms/detail/sections/sectionalize.hpp +++ b/include/boost/geometry/algorithms/detail/sections/sectionalize.hpp @@ -52,6 +52,7 @@ #include #include +#include #include #include #include @@ -336,9 +337,9 @@ struct assign_loop template struct box_first_in_section { - template + template static inline void apply(Box & box, Point const& prev, Point const& curr, - EnvelopeStrategy const& strategy) + Strategy const& strategy) { geometry::model::referring_segment seg(prev, curr); geometry::envelope(seg, box, strategy); @@ -348,12 +349,12 @@ struct box_first_in_section template <> struct box_first_in_section { - template + template static inline void apply(Box & box, Point const& prev, Point const& curr, - ExpandStrategy const& ) + Strategy const& strategy) { - geometry::envelope(prev, box); - geometry::expand(box, curr); + geometry::envelope(prev, box, strategy); + geometry::expand(box, curr, strategy); } }; @@ -374,9 +375,9 @@ struct box_next_in_section { template static inline void apply(Box & box, Point const& , Point const& curr, - Strategy const& ) + Strategy const& strategy) { - geometry::expand(box, curr); + geometry::expand(box, curr, strategy); } }; @@ -391,50 +392,17 @@ struct sectionalize_part static const std::size_t dimension_count = util::sequence_size::value; - template - < - typename Iterator, - typename RobustPolicy, - typename Sections - > - static inline void apply(Sections& sections, - Iterator begin, Iterator end, - RobustPolicy const& robust_policy, - ring_identifier ring_id, - std::size_t max_count) - { - typedef typename strategy::envelope::services::default_strategy - < - segment_tag, - typename cs_tag::type - >::type envelope_strategy_type; - - typedef typename strategy::expand::services::default_strategy - < - segment_tag, - typename cs_tag::type - >::type expand_strategy_type; - - apply(sections, begin, end, - robust_policy, - envelope_strategy_type(), - expand_strategy_type(), - ring_id, max_count); - } - template < typename Iterator, typename RobustPolicy, typename Sections, - typename EnvelopeStrategy, - typename ExpandStrategy + typename Strategy > static inline void apply(Sections& sections, Iterator begin, Iterator end, RobustPolicy const& robust_policy, - EnvelopeStrategy const& envelope_strategy, - ExpandStrategy const& expand_strategy, + Strategy const& strategy, ring_identifier ring_id, std::size_t max_count) { @@ -448,10 +416,10 @@ struct sectionalize_part ); typedef typename geometry::robust_point_type - < - Point, - RobustPolicy - >::type robust_point_type; + < + Point, + RobustPolicy + >::type robust_point_type; std::size_t const count = std::distance(begin, end); if (count == 0) @@ -552,14 +520,14 @@ struct sectionalize_part // In cartesian this is envelope of previous point expanded with current point // in non-cartesian this is envelope of a segment box_first_in_section::type> - ::apply(section.bounding_box, previous_robust_point, current_robust_point, envelope_strategy); + ::apply(section.bounding_box, previous_robust_point, current_robust_point, strategy); } else { // In cartesian this is expand with current point // in non-cartesian this is expand with a segment box_next_in_section::type> - ::apply(section.bounding_box, previous_robust_point, current_robust_point, expand_strategy); + ::apply(section.bounding_box, previous_robust_point, current_robust_point, strategy); } section.end_index = index + 1; @@ -605,23 +573,21 @@ struct sectionalize_range typename Range, typename RobustPolicy, typename Sections, - typename EnvelopeStrategy, - typename ExpandStrategy + typename Strategy > static inline void apply(Range const& range, RobustPolicy const& robust_policy, Sections& sections, - EnvelopeStrategy const& envelope_strategy, - ExpandStrategy const& expand_strategy, + Strategy const& strategy, ring_identifier ring_id, std::size_t max_count) { typedef typename closeable_view::type cview_type; typedef typename reversible_view - < - cview_type const, - Reverse ? iterate_reverse : iterate_forward - >::type view_type; + < + cview_type const, + Reverse ? iterate_reverse : iterate_forward + >::type view_type; cview_type cview(range); view_type view(cview); @@ -641,7 +607,7 @@ struct sectionalize_range sectionalize_part::apply(sections, boost::begin(view), boost::end(view), - robust_policy, envelope_strategy, expand_strategy, + robust_policy, strategy, ring_id, max_count); } }; @@ -658,27 +624,24 @@ struct sectionalize_polygon typename Polygon, typename RobustPolicy, typename Sections, - typename EnvelopeStrategy, - typename ExpandStrategy + typename Strategy > static inline void apply(Polygon const& poly, RobustPolicy const& robust_policy, Sections& sections, - EnvelopeStrategy const& envelope_strategy, - ExpandStrategy const& expand_strategy, + Strategy const& strategy, ring_identifier ring_id, std::size_t max_count) { typedef typename point_type::type point_type; typedef sectionalize_range - < - closure::value, Reverse, - point_type, DimensionVector - > per_range; + < + closure::value, Reverse, point_type, DimensionVector + > per_range; ring_id.ring_index = -1; per_range::apply(exterior_ring(poly), robust_policy, sections, - envelope_strategy, expand_strategy, ring_id, max_count); + strategy, ring_id, max_count); ring_id.ring_index++; typename interior_return_type::type @@ -687,7 +650,7 @@ struct sectionalize_polygon it = boost::begin(rings); it != boost::end(rings); ++it, ++ring_id.ring_index) { per_range::apply(*it, robust_policy, sections, - envelope_strategy, expand_strategy, ring_id, max_count); + strategy, ring_id, max_count); } } }; @@ -700,14 +663,12 @@ struct sectionalize_box typename Box, typename RobustPolicy, typename Sections, - typename EnvelopeStrategy, - typename ExpandStrategy + typename Strategy > static inline void apply(Box const& box, RobustPolicy const& robust_policy, Sections& sections, - EnvelopeStrategy const& envelope_strategy, - ExpandStrategy const& expand_strategy, + Strategy const& strategy, ring_identifier const& ring_id, std::size_t max_count) { typedef typename point_type::type point_type; @@ -735,13 +696,10 @@ struct sectionalize_box // NOTE: Use cartesian envelope strategy in all coordinate systems // because edges of a box are not geodesic segments sectionalize_range - < - closed, false, - point_type, - DimensionVector - >::apply(points, robust_policy, sections, - envelope_strategy, expand_strategy, - ring_id, max_count); + < + closed, false, point_type, DimensionVector + >::apply(points, robust_policy, sections, + strategy, ring_id, max_count); } }; @@ -753,14 +711,12 @@ struct sectionalize_multi typename MultiGeometry, typename RobustPolicy, typename Sections, - typename EnvelopeStrategy, - typename ExpandStrategy + typename Strategy > static inline void apply(MultiGeometry const& multi, RobustPolicy const& robust_policy, Sections& sections, - EnvelopeStrategy const& envelope_strategy, - ExpandStrategy const& expand_strategy, + Strategy const& strategy, ring_identifier ring_id, std::size_t max_count) { @@ -771,7 +727,7 @@ struct sectionalize_multi ++it, ++ring_id.multi_index) { Policy::apply(*it, robust_policy, sections, - envelope_strategy, expand_strategy, + strategy, ring_id, max_count); } } @@ -983,7 +939,7 @@ struct sectionalize inline void sectionalize(Geometry const& geometry, RobustPolicy const& robust_policy, Sections& sections, - EnvelopeStrategy const& envelope_strategy, - ExpandStrategy const& expand_strategy, + Strategy const& strategy, int source_index = 0, std::size_t max_count = 10) { - BOOST_STATIC_ASSERT((! std::is_fundamental::value)); - concepts::check(); typedef typename boost::range_value::type section_type; @@ -1044,10 +996,10 @@ inline void sectionalize(Geometry const& geometry, Reverse, DimensionVector >::apply(geometry, robust_policy, sections, - envelope_strategy, expand_strategy, + strategy, ring_id, max_count); - detail::sectionalize::enlarge_sections(sections, envelope_strategy); + detail::sectionalize::enlarge_sections(sections, strategy); } @@ -1065,29 +1017,17 @@ inline void sectionalize(Geometry const& geometry, int source_index = 0, std::size_t max_count = 10) { - typedef typename strategy::envelope::services::default_strategy + typedef typename strategies::envelope::services::default_strategy < - typename tag::type, - typename cs_tag::type - >::type envelope_strategy_type; - - typedef typename strategy::expand::services::default_strategy - < - std::conditional_t - < - std::is_same::type, box_tag>::value, - box_tag, - segment_tag - >, - typename cs_tag::type - >::type expand_strategy_type; + Geometry, + model::box::type> + >::type strategy_type; boost::geometry::sectionalize < Reverse, DimensionVector >(geometry, robust_policy, sections, - envelope_strategy_type(), - expand_strategy_type(), + strategy_type(), source_index, max_count); } diff --git a/include/boost/geometry/algorithms/detail/touches/implementation.hpp b/include/boost/geometry/algorithms/detail/touches/implementation.hpp index d8a02d945..bf1b53534 100644 --- a/include/boost/geometry/algorithms/detail/touches/implementation.hpp +++ b/include/boost/geometry/algorithms/detail/touches/implementation.hpp @@ -212,29 +212,24 @@ inline bool point_on_border_within(Geometry1 const& geometry1, && geometry::within(pt, geometry2, strategy); } -template +template inline bool rings_containing(FirstGeometry const& geometry1, SecondGeometry const& geometry2, - IntersectionStrategy const& strategy) + Strategy const& strategy) { - // TODO: This will be removed when IntersectionStrategy is replaced with - // UmbrellaStrategy - auto const point_in_ring_strategy - = strategy.template get_point_in_geometry_strategy(); - return geometry::detail::any_range_of(geometry2, [&](auto const& range) { - return point_on_border_within(range, geometry1, point_in_ring_strategy); + return point_on_border_within(range, geometry1, strategy); }); } template struct areal_areal { - template + template static inline bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2, - IntersectionStrategy const& strategy) + Strategy const& strategy) { typedef typename geometry::point_type::type point_type; typedef detail::overlay::turn_info turn_info; @@ -411,7 +406,7 @@ struct self_touches { concepts::check(); - typedef typename strategy::relate::services::default_strategy + typedef typename strategies::relate::services::default_strategy < Geometry, Geometry >::type strategy_type; @@ -419,18 +414,19 @@ struct self_touches typedef detail::overlay::turn_info turn_info; typedef detail::overlay::get_turn_info - < - detail::overlay::assign_null_policy - > policy_type; + < + detail::overlay::assign_null_policy + > policy_type; std::deque turns; detail::touches::areal_interrupt_policy policy; strategy_type strategy; // TODO: skip_adjacent should be set to false detail::self_get_turn_points::get_turns - < - false, policy_type - >::apply(geometry, strategy, detail::no_rescale_policy(), turns, policy, 0, true); + < + false, policy_type + >::apply(geometry, strategy, detail::no_rescale_policy(), + turns, policy, 0, true); return policy.result(); } diff --git a/include/boost/geometry/algorithms/detail/touches/interface.hpp b/include/boost/geometry/algorithms/detail/touches/interface.hpp index 9f41b3608..39d997463 100644 --- a/include/boost/geometry/algorithms/detail/touches/interface.hpp +++ b/include/boost/geometry/algorithms/detail/touches/interface.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, 2017. -// Modifications copyright (c) 2013-2017, Oracle and/or its affiliates. +// This file was modified by Oracle on 2013-2021. +// Modifications copyright (c) 2013-2021, Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle @@ -35,7 +35,8 @@ #include #include -#include +#include +#include namespace boost { namespace geometry @@ -84,9 +85,14 @@ struct touches namespace resolve_strategy { +template +< + typename Strategy, + bool IsUmbrella = strategies::detail::is_umbrella_strategy::value +> struct touches { - template + template static inline bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2, Strategy const& strategy) @@ -96,13 +102,35 @@ struct touches Geometry1, Geometry2 >::apply(geometry1, geometry2, strategy); } +}; +template +struct touches +{ + template + static inline bool apply(Geometry1 const& geometry1, + Geometry2 const& geometry2, + Strategy const& strategy) + { + using strategies::relate::services::strategy_converter; + + return dispatch::touches + < + Geometry1, Geometry2 + >::apply(geometry1, geometry2, + strategy_converter::get(strategy)); + } +}; + +template <> +struct touches +{ template static inline bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2, default_strategy) { - typedef typename strategy::relate::services::default_strategy + typedef typename strategies::relate::services::default_strategy < Geometry1, Geometry2 @@ -129,7 +157,10 @@ struct touches concepts::check(); concepts::check(); - return resolve_strategy::touches::apply(geometry1, geometry2, strategy); + return resolve_strategy::touches + < + Strategy + >::apply(geometry1, geometry2, strategy); } }; diff --git a/include/boost/geometry/algorithms/detail/within/implementation.hpp b/include/boost/geometry/algorithms/detail/within/implementation.hpp index 9a88e41a5..a402c015a 100644 --- a/include/boost/geometry/algorithms/detail/within/implementation.hpp +++ b/include/boost/geometry/algorithms/detail/within/implementation.hpp @@ -88,8 +88,7 @@ struct within template static inline bool apply(Point const& point, Box const& box, Strategy const& strategy) { - boost::ignore_unused(strategy); - return strategy.apply(point, box); + return strategy.within(point, box).apply(point, box); } }; @@ -100,8 +99,7 @@ struct within static inline bool apply(Box1 const& box1, Box2 const& box2, Strategy const& strategy) { assert_dimension_equal(); - boost::ignore_unused(strategy); - return strategy.apply(box1, box2); + return strategy.within(box1, box2).apply(box1, box2); } }; diff --git a/include/boost/geometry/algorithms/detail/within/interface.hpp b/include/boost/geometry/algorithms/detail/within/interface.hpp index 048cc01f7..1a10ca84d 100644 --- a/include/boost/geometry/algorithms/detail/within/interface.hpp +++ b/include/boost/geometry/algorithms/detail/within/interface.hpp @@ -4,9 +4,8 @@ // 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, 2017, 2018. -// Modifications copyright (c) 2013-2018 Oracle and/or its affiliates. - +// This file was modified by Oracle on 2013-2021. +// Modifications copyright (c) 2013-2021 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 @@ -34,7 +33,8 @@ #include #include #include -#include +#include +#include namespace boost { namespace geometry @@ -63,30 +63,63 @@ struct within namespace resolve_strategy { +template +< + typename Strategy, + bool IsUmbrella = strategies::detail::is_umbrella_strategy::value +> struct within { - template + template static inline bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2, Strategy const& strategy) { concepts::within::check(); - return dispatch::within::apply(geometry1, geometry2, strategy); + return dispatch::within + < + Geometry1, Geometry2 + >::apply(geometry1, geometry2, strategy); } +}; +template +struct within +{ + template + static inline bool apply(Geometry1 const& geometry1, + Geometry2 const& geometry2, + Strategy const& strategy) + { + using strategies::relate::services::strategy_converter; + + return within + < + decltype(strategy_converter::get(strategy)) + >::apply(geometry1, geometry2, + strategy_converter::get(strategy)); + } +}; + +template <> +struct within +{ template static inline bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2, default_strategy) { - typedef typename strategy::within::services::default_strategy + typedef typename strategies::relate::services::default_strategy < Geometry1, Geometry2 >::type strategy_type; - return apply(geometry1, geometry2, strategy_type()); + return within + < + strategy_type + >::apply(geometry1, geometry2, strategy_type()); } }; @@ -108,9 +141,10 @@ struct within concepts::check(); assert_dimension_equal(); - return resolve_strategy::within::apply(geometry1, - geometry2, - strategy); + return resolve_strategy::within + < + Strategy + >::apply(geometry1, geometry2, strategy); } }; diff --git a/include/boost/geometry/algorithms/detail/within/multi_point.hpp b/include/boost/geometry/algorithms/detail/within/multi_point.hpp index 319a782f3..349ef0302 100644 --- a/include/boost/geometry/algorithms/detail/within/multi_point.hpp +++ b/include/boost/geometry/algorithms/detail/within/multi_point.hpp @@ -1,7 +1,6 @@ // Boost.Geometry // Copyright (c) 2017-2020, 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, @@ -54,10 +53,12 @@ struct multi_point_point Point const& point, Strategy const& strategy) { + auto const s = strategy.relate(multi_point, point); + typedef typename boost::range_const_iterator::type iterator; for ( iterator it = boost::begin(multi_point) ; it != boost::end(multi_point) ; ++it ) { - if (! strategy.apply(*it, point)) + if (! s.apply(*it, point)) { return false; } @@ -126,11 +127,9 @@ struct multi_point_single_geometry // Create envelope of geometry box2_type box; - geometry::envelope(linear_or_areal, box, strategy.get_envelope_strategy()); + geometry::envelope(linear_or_areal, box, strategy); geometry::detail::expand_by_epsilon(box); - typedef typename Strategy::disjoint_point_box_strategy_type point_in_box_type; - // Test each Point with envelope and then geometry if needed // If in the exterior, break bool result = false; @@ -138,8 +137,10 @@ struct multi_point_single_geometry typedef typename boost::range_const_iterator::type iterator; for ( iterator it = boost::begin(multi_point) ; it != boost::end(multi_point) ; ++it ) { - int in_val = 0; + typedef decltype(strategy.covered_by(*it, box)) point_in_box_type; + int in_val = 0; + // exterior of box and of geometry if (! point_in_box_type::apply(*it, box) || (in_val = point_in_geometry(*it, linear_or_areal, strategy)) < 0) @@ -173,9 +174,6 @@ struct multi_point_multi_geometry typedef model::box box2_type; static const bool is_linear = util::is_linear::value; - typename Strategy::envelope_strategy_type const - envelope_strategy = strategy.get_envelope_strategy(); - // TODO: box pairs could be constructed on the fly, inside the rtree // Prepare range of envelopes and ids @@ -185,23 +183,16 @@ struct multi_point_multi_geometry box_pair_vector boxes(count2); for (std::size_t i = 0 ; i < count2 ; ++i) { - geometry::envelope(linear_or_areal, boxes[i].first, envelope_strategy); + geometry::envelope(linear_or_areal, boxes[i].first, strategy); geometry::detail::expand_by_epsilon(boxes[i].first); boxes[i].second = i; } // Create R-tree - typedef strategy::index::services::from_strategy - < - Strategy - > index_strategy_from; - typedef index::parameters - < - index::rstar<4>, typename index_strategy_from::type - > index_parameters_type; + typedef index::parameters, Strategy> index_parameters_type; index::rtree rtree(boxes.begin(), boxes.end(), - index_parameters_type(index::rstar<4>(), index_strategy_from::get(strategy))); + index_parameters_type(index::rstar<4>(), strategy)); // For each point find overlapping envelopes and test corresponding single geometries // If a point is in the exterior break diff --git a/include/boost/geometry/algorithms/detail/within/point_in_geometry.hpp b/include/boost/geometry/algorithms/detail/within/point_in_geometry.hpp index b8d69f6e2..3ef02ca90 100644 --- a/include/boost/geometry/algorithms/detail/within/point_in_geometry.hpp +++ b/include/boost/geometry/algorithms/detail/within/point_in_geometry.hpp @@ -7,7 +7,6 @@ // This file was modified by Oracle on 2013-2020. // Modifications copyright (c) 2013-2020, 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 @@ -34,8 +33,6 @@ #include #include -#include -#include #include #include @@ -45,32 +42,13 @@ namespace boost { namespace geometry { #ifndef DOXYGEN_NO_DETAIL namespace detail { namespace within { -template -inline bool equals_point_point(Point1 const& p1, Point2 const& p2, Strategy const& strategy) -{ - return equals::equals_point_point(p1, p2, strategy.get_equals_point_point_strategy()); -} - -// TODO: is this needed? -inline int check_result_type(int result) -{ - return result; -} - -template -inline T check_result_type(T result) -{ - BOOST_GEOMETRY_ASSERT(false); - return result; -} template inline int point_in_range(Point const& point, Range const& range, Strategy const& strategy) { - boost::ignore_unused(strategy); + typename Strategy::state_type state; typedef typename boost::range_iterator::type iterator_type; - typename Strategy::state_type state; iterator_type it = boost::begin(range); iterator_type end = boost::end(range); @@ -82,18 +60,7 @@ int point_in_range(Point const& point, Range const& range, Strategy const& strat } } - return check_result_type(strategy.result(state)); -} - -template -inline int point_in_range(Point const& point, Range const& range) -{ - typedef typename strategy::point_in_geometry::services::default_strategy - < - Point, Geometry - >::type strategy_type; - - return point_in_range(point, range, strategy_type()); + return strategy.result(state); } }} // namespace detail::within @@ -117,8 +84,8 @@ struct point_in_geometry template static inline int apply(Point1 const& point1, Point2 const& point2, Strategy const& strategy) { - boost::ignore_unused(strategy); - return strategy.apply(point1, point2) ? 1 : -1; + typedef decltype(strategy.relate(point1, point2)) strategy_type; + return strategy_type::apply(point1, point2) ? 1 : -1; } }; @@ -128,24 +95,23 @@ struct point_in_geometry template static inline int apply(Point const& point, Segment const& segment, Strategy const& strategy) { - boost::ignore_unused(strategy); - typedef typename geometry::point_type::type point_type; point_type p0, p1; // TODO: don't copy points detail::assign_point_from_index<0>(segment, p0); detail::assign_point_from_index<1>(segment, p1); - typename Strategy::state_type state; - strategy.apply(point, p0, p1, state); - int r = detail::within::check_result_type(strategy.result(state)); + auto const s = strategy.relate(point, segment); + typename decltype(s)::state_type state; + s.apply(point, p0, p1, state); + int r = s.result(state); if ( r != 0 ) return -1; // exterior // if the point is equal to the one of the terminal points - if ( detail::within::equals_point_point(point, p0, strategy) - || detail::within::equals_point_point(point, p1, strategy) ) + if ( detail::equals::equals_point_point(point, p0, strategy) + || detail::equals::equals_point_point(point, p1, strategy) ) return 0; // boundary else return 1; // interior @@ -162,24 +128,37 @@ struct point_in_geometry std::size_t count = boost::size(linestring); if ( count > 1 ) { - if ( detail::within::point_in_range(point, linestring, strategy) != 0 ) + if ( detail::within::point_in_range(point, linestring, + strategy.relate(point, linestring)) != 0 ) + { return -1; // exterior + } + + typedef typename boost::range_value::type point_type; + point_type const& front = range::front(linestring); + point_type const& back = range::back(linestring); // if the linestring doesn't have a boundary - if (detail::within::equals_point_point(range::front(linestring), range::back(linestring), strategy)) + if ( detail::equals::equals_point_point(front, back, strategy) ) + { return 1; // interior + } // else if the point is equal to the one of the terminal points - else if (detail::within::equals_point_point(point, range::front(linestring), strategy) - || detail::within::equals_point_point(point, range::back(linestring), strategy)) + else if ( detail::equals::equals_point_point(point, front, strategy) + || detail::equals::equals_point_point(point, back, strategy) ) + { return 0; // boundary + } else + { return 1; // interior + } } // TODO: for now degenerated linestrings are ignored // throw an exception here? /*else if ( count == 1 ) { - if ( detail::equals::equals_point_point(point, range::front(linestring)) ) + if ( detail::equals::equals_point_point(point, front, strategy) ) return 1; }*/ @@ -202,7 +181,8 @@ struct point_in_geometry } detail::normalized_view view(ring); - return detail::within::point_in_range(point, view, strategy); + return detail::within::point_in_range(point, view, + strategy.relate(point, ring)); } }; @@ -309,12 +289,12 @@ struct point_in_geometry point_type const& back = range::back(*it); // is closed_ring - no boundary - if ( detail::within::equals_point_point(front, back, strategy) ) + if ( detail::equals::equals_point_point(front, back, strategy) ) continue; // is point on boundary - if ( detail::within::equals_point_point(point, front, strategy) - || detail::within::equals_point_point(point, back, strategy) ) + if ( detail::equals::equals_point_point(point, front, strategy) + || detail::equals::equals_point_point(point, back, strategy) ) { ++boundaries; } @@ -371,41 +351,18 @@ inline int point_in_geometry(Point const& point, Geometry const& geometry, Strat return detail_dispatch::within::point_in_geometry::apply(point, geometry, strategy); } -template -inline int point_in_geometry(Point const& point, Geometry const& geometry) -{ - typedef typename strategy::point_in_geometry::services::default_strategy - < - Point, Geometry - >::type strategy_type; - - return point_in_geometry(point, geometry, strategy_type()); -} - template inline bool within_point_geometry(Point const& point, Geometry const& geometry, Strategy const& strategy) { return point_in_geometry(point, geometry, strategy) > 0; } -template -inline bool within_point_geometry(Point const& point, Geometry const& geometry) -{ - return point_in_geometry(point, geometry) > 0; -} - template inline bool covered_by_point_geometry(Point const& point, Geometry const& geometry, Strategy const& strategy) { return point_in_geometry(point, geometry, strategy) >= 0; } -template -inline bool covered_by_point_geometry(Point const& point, Geometry const& geometry) -{ - return point_in_geometry(point, geometry) >= 0; -} - }} // namespace detail::within #endif // DOXYGEN_NO_DETAIL diff --git a/include/boost/geometry/algorithms/difference.hpp b/include/boost/geometry/algorithms/difference.hpp index be96eea5c..addd51f63 100644 --- a/include/boost/geometry/algorithms/difference.hpp +++ b/include/boost/geometry/algorithms/difference.hpp @@ -2,7 +2,7 @@ // Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. -// This file was modified by Oracle on 2017, 2019, 2020. +// This file was modified by Oracle on 2017-2020. // Modifications copyright (c) 2017-2020, Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle @@ -23,6 +23,8 @@ #include #include #include +#include +#include #include @@ -253,7 +255,7 @@ inline OutputIterator difference_insert(Geometry1 const& geometry1, Geometry2 const& geometry2, OutputIterator out) { - typedef typename strategy::relate::services::default_strategy + typedef typename strategies::relate::services::default_strategy < Geometry1, Geometry2 @@ -270,15 +272,14 @@ inline OutputIterator difference_insert(Geometry1 const& geometry1, namespace resolve_strategy { +template +< + typename Strategy, + bool IsUmbrella = strategies::detail::is_umbrella_strategy::value +> struct difference { - template - < - typename Geometry1, - typename Geometry2, - typename Collection, - typename Strategy - > + template static inline void apply(Geometry1 const& geometry1, Geometry2 const& geometry2, Collection & output_collection, @@ -294,25 +295,46 @@ struct difference geometry::detail::output_geometry_back_inserter(output_collection), strategy); } +}; - template - < - typename Geometry1, - typename Geometry2, - typename Collection - > +template +struct difference +{ + template + static inline void apply(Geometry1 const& geometry1, + Geometry2 const& geometry2, + Collection & output_collection, + Strategy const& strategy) + { + using strategies::relate::services::strategy_converter; + + difference + < + decltype(strategy_converter::get(strategy)) + >::apply(geometry1, geometry2, output_collection, + strategy_converter::get(strategy)); + } +}; + +template <> +struct difference +{ + template static inline void apply(Geometry1 const& geometry1, Geometry2 const& geometry2, Collection & output_collection, default_strategy) { - typedef typename strategy::relate::services::default_strategy + typedef typename strategies::relate::services::default_strategy < Geometry1, Geometry2 >::type strategy_type; - apply(geometry1, geometry2, output_collection, strategy_type()); + difference + < + strategy_type + >::apply(geometry1, geometry2, output_collection, strategy_type()); } }; @@ -331,9 +353,10 @@ struct difference Collection& output_collection, Strategy const& strategy) { - resolve_strategy::difference::apply(geometry1, geometry2, - output_collection, - strategy); + resolve_strategy::difference + < + Strategy + >::apply(geometry1, geometry2, output_collection, strategy); } }; diff --git a/include/boost/geometry/algorithms/sym_difference.hpp b/include/boost/geometry/algorithms/sym_difference.hpp index 4d8550bcb..3d33431f9 100644 --- a/include/boost/geometry/algorithms/sym_difference.hpp +++ b/include/boost/geometry/algorithms/sym_difference.hpp @@ -2,7 +2,7 @@ // Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands. -// This file was modified by Oracle on 2015, 2017, 2019, 2020. +// This file was modified by Oracle on 2015-2020. // Modifications copyright (c) 2015-2020 Oracle and/or its affiliates. // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle @@ -29,7 +29,8 @@ #include #include #include -#include +#include +#include #include @@ -497,9 +498,9 @@ template inline OutputIterator sym_difference_insert(Geometry1 const& geometry1, Geometry2 const& geometry2, OutputIterator out) { - typedef typename strategy::intersection::services::default_strategy + typedef typename strategies::relate::services::default_strategy < - typename cs_tag::type + Geometry1, Geometry2 >::type strategy_type; return sym_difference_insert(geometry1, geometry2, out, strategy_type()); @@ -511,15 +512,14 @@ inline OutputIterator sym_difference_insert(Geometry1 const& geometry1, namespace resolve_strategy { +template +< + typename Strategy, + bool IsUmbrella = strategies::detail::is_umbrella_strategy::value +> struct sym_difference { - template - < - typename Geometry1, - typename Geometry2, - typename Collection, - typename Strategy - > + template static inline void apply(Geometry1 const& geometry1, Geometry2 const& geometry2, Collection & output_collection, @@ -535,13 +535,31 @@ struct sym_difference geometry::detail::output_geometry_back_inserter(output_collection), strategy); } +}; - template - < - typename Geometry1, - typename Geometry2, - typename Collection - > +template +struct sym_difference +{ + template + static inline void apply(Geometry1 const& geometry1, + Geometry2 const& geometry2, + Collection & output_collection, + Strategy const& strategy) + { + using strategies::relate::services::strategy_converter; + + sym_difference + < + decltype(strategy_converter::get(strategy)) + >::apply(geometry1, geometry2, output_collection, + strategy_converter::get(strategy)); + } +}; + +template <> +struct sym_difference +{ + template static inline void apply(Geometry1 const& geometry1, Geometry2 const& geometry2, Collection & output_collection, @@ -552,7 +570,10 @@ struct sym_difference Geometry1, Geometry2 >::type strategy_type; - apply(geometry1, geometry2, output_collection, strategy_type()); + sym_difference + < + strategy_type + >::apply(geometry1, geometry2, output_collection, strategy_type()); } }; @@ -571,9 +592,10 @@ struct sym_difference Collection& output_collection, Strategy const& strategy) { - resolve_strategy::sym_difference::apply(geometry1, geometry2, - output_collection, - strategy); + resolve_strategy::sym_difference + < + Strategy + >::apply(geometry1, geometry2, output_collection, strategy); } }; diff --git a/include/boost/geometry/algorithms/union.hpp b/include/boost/geometry/algorithms/union.hpp index 535e8b147..7f507a329 100644 --- a/include/boost/geometry/algorithms/union.hpp +++ b/include/boost/geometry/algorithms/union.hpp @@ -18,13 +18,15 @@ #include +#include +#include #include #include #include -#include -#include #include #include +#include +#include #include #include @@ -349,9 +351,9 @@ inline OutputIterator union_insert(Geometry1 const& geometry1, concepts::check(); geometry::detail::output_geometry_concept_check::apply(); - typename strategy::intersection::services::default_strategy + typename strategies::relate::services::default_strategy < - typename cs_tag::type + Geometry1, Geometry2 >::type strategy; typedef typename geometry::rescale_overlay_policy_type @@ -377,15 +379,14 @@ inline OutputIterator union_insert(Geometry1 const& geometry1, namespace resolve_strategy { +template +< + typename Strategy, + bool IsUmbrella = strategies::detail::is_umbrella_strategy::value +> struct union_ { - template - < - typename Geometry1, - typename Geometry2, - typename Collection, - typename Strategy - > + template static inline void apply(Geometry1 const& geometry1, Geometry2 const& geometry2, Collection & output_collection, @@ -414,25 +415,46 @@ struct union_ geometry::detail::output_geometry_back_inserter(output_collection), strategy); } +}; - template - < - typename Geometry1, - typename Geometry2, - typename Collection - > +template +struct union_ +{ + template + static inline void apply(Geometry1 const& geometry1, + Geometry2 const& geometry2, + Collection & output_collection, + Strategy const& strategy) + { + using strategies::relate::services::strategy_converter; + + union_ + < + decltype(strategy_converter::get(strategy)) + >::apply(geometry1, geometry2, output_collection, + strategy_converter::get(strategy)); + } +}; + +template <> +struct union_ +{ + template static inline void apply(Geometry1 const& geometry1, Geometry2 const& geometry2, Collection & output_collection, default_strategy) { - typedef typename strategy::relate::services::default_strategy + typedef typename strategies::relate::services::default_strategy < Geometry1, Geometry2 >::type strategy_type; - apply(geometry1, geometry2, output_collection, strategy_type()); + union_ + < + strategy_type + >::apply(geometry1, geometry2, output_collection, strategy_type()); } }; @@ -462,9 +484,10 @@ struct union_ >::type >::apply(); - resolve_strategy::union_::apply(geometry1, geometry2, - output_collection, - strategy); + resolve_strategy::union_ + < + Strategy + >::apply(geometry1, geometry2, output_collection, strategy); } }; diff --git a/include/boost/geometry/geometry.hpp b/include/boost/geometry/geometry.hpp index 24b12fab7..9aff956c9 100644 --- a/include/boost/geometry/geometry.hpp +++ b/include/boost/geometry/geometry.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-2020. -// Modifications copyright (c) 2014-2020 Oracle and/or its affiliates. +// This file was modified by Oracle on 2014-2021. +// Modifications copyright (c) 2014-2021 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,7 @@ BOOST_PRAGMA_MESSAGE("CAUTION: Define BOOST_GEOMETRY_DISABLE_DEPRECATED_03_WARNI #include #include #include +#include #include #include #include diff --git a/include/boost/geometry/index/detail/algorithms/bounds.hpp b/include/boost/geometry/index/detail/algorithms/bounds.hpp index 2a0fa9ced..1828a2467 100644 --- a/include/boost/geometry/index/detail/algorithms/bounds.hpp +++ b/include/boost/geometry/index/detail/algorithms/bounds.hpp @@ -4,8 +4,8 @@ // // Copyright (c) 2011-2014 Adam Wulkiewicz, Lodz, Poland. // -// This file was modified by Oracle on 2019. -// Modifications copyright (c) 2019 Oracle and/or its affiliates. +// This file was modified by Oracle on 2019-2020. +// Modifications copyright (c) 2019-2020 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, @@ -80,9 +80,9 @@ struct expand } template - static inline void apply(Bounds & b, Geometry const& g, Strategy const& ) + static inline void apply(Bounds & b, Geometry const& g, Strategy const& s) { - geometry::expand(b, g, typename Strategy::expand_point_strategy_type()); + geometry::expand(b, g, s); } }; @@ -95,9 +95,9 @@ struct expand } template - static inline void apply(Bounds & b, Geometry const& g, Strategy const& ) + static inline void apply(Bounds & b, Geometry const& g, Strategy const& s) { - geometry::expand(b, g, typename Strategy::expand_box_strategy_type()); + geometry::expand(b, g, s); } }; @@ -112,8 +112,9 @@ struct expand template static inline void apply(Bounds & b, Geometry const& g, Strategy const& s) { - index::detail::bounded_view v(g, s); - geometry::expand(b, v, typename Strategy::expand_box_strategy_type()); + geometry::expand(b, geometry::return_envelope(g, s), s); + // requires additional strategy + //geometry::expand(b, g, s); } }; @@ -154,9 +155,9 @@ struct covered_by_bounds } template - static inline bool apply(Geometry const& g, Bounds & b, Strategy const&) + static inline bool apply(Geometry const& g, Bounds & b, Strategy const& s) { - return geometry::covered_by(g, b, typename Strategy::covered_by_point_box_strategy_type()); + return geometry::covered_by(g, b, s); } }; @@ -169,9 +170,9 @@ struct covered_by_bounds } template - static inline bool apply(Geometry const& g, Bounds & b, Strategy const&) + static inline bool apply(Geometry const& g, Bounds & b, Strategy const& s) { - return geometry::covered_by(g, b, typename Strategy::covered_by_box_box_strategy_type()); + return geometry::covered_by(g, b, s); } }; @@ -194,8 +195,7 @@ struct covered_by_bounds typedef geometry::model::box bounds_type; typedef index::detail::bounded_view view_type; - return geometry::covered_by(view_type(g, strategy), b, - typename Strategy::covered_by_box_box_strategy_type()); + return geometry::covered_by(view_type(g, strategy), b, strategy); } }; diff --git a/include/boost/geometry/index/detail/algorithms/intersection_content.hpp b/include/boost/geometry/index/detail/algorithms/intersection_content.hpp index 2fee7b13d..880540bc0 100644 --- a/include/boost/geometry/index/detail/algorithms/intersection_content.hpp +++ b/include/boost/geometry/index/detail/algorithms/intersection_content.hpp @@ -4,8 +4,8 @@ // // Copyright (c) 2011-2018 Adam Wulkiewicz, Lodz, Poland. // -// This file was modified by Oracle on 2019. -// Modifications copyright (c) 2019 Oracle and/or its affiliates. +// This file was modified by Oracle on 2019-2020. +// Modifications copyright (c) 2019-2020 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, @@ -24,10 +24,9 @@ namespace boost { namespace geometry { namespace index { namespace detail { // Util to distinguish between default and non-default index strategy template -inline bool disjoint_box_box(Box const& box1, Box const& box2, Strategy const&) +inline bool disjoint_box_box(Box const& box1, Box const& box2, Strategy const& s) { - return geometry::detail::disjoint::disjoint_box_box(box1, box2, - typename Strategy::disjoint_box_box_strategy_type()); + return geometry::detail::disjoint::disjoint_box_box(box1, box2, s); } template diff --git a/include/boost/geometry/index/detail/bounded_view.hpp b/include/boost/geometry/index/detail/bounded_view.hpp index 7df1fc6ca..6b4d91a64 100644 --- a/include/boost/geometry/index/detail/bounded_view.hpp +++ b/include/boost/geometry/index/detail/bounded_view.hpp @@ -19,7 +19,8 @@ #include #include -#include +#include +#include namespace boost { namespace geometry { @@ -94,24 +95,11 @@ private: template struct bounded_view_base { - template - inline void envelope(Segment const& segment, S const& strategy) - { - geometry::envelope(segment, m_box, - strategy.get_envelope_segment_strategy()); - } - - inline void envelope(Segment const& segment, default_strategy const& ) - { - geometry::envelope(segment, m_box); - } - -public: typedef typename geometry::coordinate_type::type coordinate_type; bounded_view_base(Segment const& segment, Strategy const& strategy) { - envelope(segment, strategy); + geometry::envelope(segment, m_box, strategy); } template @@ -215,10 +203,10 @@ struct bounded_view::type + typename strategies::index::services::default_strategy::type > { - typedef typename strategy::index::services::default_strategy + typedef typename strategies::index::services::default_strategy < Geometry >::type strategy_type; diff --git a/include/boost/geometry/index/detail/distance_predicates.hpp b/include/boost/geometry/index/detail/distance_predicates.hpp index aba951847..9ad44d18d 100644 --- a/include/boost/geometry/index/detail/distance_predicates.hpp +++ b/include/boost/geometry/index/detail/distance_predicates.hpp @@ -100,135 +100,41 @@ struct relation< to_furthest > // ------------------------------------------------------------------ // -template -< - typename G1, typename G2, typename Strategy, - typename Tag1 = typename geometry::tag::type, - typename Tag2 = typename geometry::tag::type -> -struct comparable_distance_call_base -{ - typedef typename geometry::default_comparable_distance_result - < - G1, G2 - >::type result_type; - - static inline result_type apply(G1 const& g1, G2 const& g2, Strategy const&) - { - return geometry::comparable_distance(g1, g2); - } -}; - -template -< - typename G1, typename G2, typename Strategy -> -struct comparable_distance_call_base -{ - typedef typename geometry::comparable_distance_result - < - G1, G2, - typename Strategy::comparable_distance_point_point_strategy_type - >::type result_type; - - static inline result_type apply(G1 const& g1, G2 const& g2, Strategy const& s) - { - return geometry::comparable_distance(g1, g2, - s.get_comparable_distance_point_point_strategy()); - } -}; - -template -< - typename G1, typename G2, typename Strategy -> -struct comparable_distance_call_base -{ - typedef typename geometry::comparable_distance_result - < - G1, G2, - typename Strategy::comparable_distance_point_box_strategy_type - >::type result_type; - - static inline result_type apply(G1 const& g1, G2 const& g2, Strategy const& s) - { - return geometry::comparable_distance(g1, g2, - s.get_comparable_distance_point_box_strategy()); - } -}; - -template -< - typename G1, typename G2, typename Strategy -> -struct comparable_distance_call_base -{ - typedef typename geometry::comparable_distance_result - < - G1, G2, - typename Strategy::comparable_distance_point_segment_strategy_type - >::type result_type; - - static inline result_type apply(G1 const& g1, G2 const& g2, Strategy const& s) - { - return geometry::comparable_distance(g1, g2, - s.get_comparable_distance_point_segment_strategy()); - } -}; - -template -< - typename G1, typename G2, typename Strategy -> -struct comparable_distance_call_base -{ - typedef typename geometry::comparable_distance_result - < - G1, G2, - typename Strategy::comparable_distance_segment_box_strategy_type - >::type result_type; - - static inline result_type apply(G1 const& g1, G2 const& g2, Strategy const& s) - { - return geometry::comparable_distance(g1, g2, - s.get_comparable_distance_segment_box_strategy()); - } -}; - -template -< - typename G1, typename G2, typename Strategy -> -struct comparable_distance_call_base -{ - typedef typename geometry::comparable_distance_result - < - G1, G2, - typename Strategy::comparable_distance_point_segment_strategy_type - >::type result_type; - - static inline result_type apply(G1 const& g1, G2 const& g2, Strategy const& s) - { - return geometry::comparable_distance(g1, g2, - s.get_comparable_distance_point_segment_strategy()); - } -}; - template < typename G1, typename G2, typename Strategy > struct comparable_distance_call - : comparable_distance_call_base -{}; +{ + typedef typename geometry::comparable_distance_result + < + G1, G2, + decltype(std::declval().comparable_distance(std::declval(), + std::declval())) + >::type result_type; + + static inline result_type apply(G1 const& g1, G2 const& g2, Strategy const& s) + { + return geometry::comparable_distance(g1, g2, s.comparable_distance(g1, g2)); + } +}; template < typename G1, typename G2 > struct comparable_distance_call - : comparable_distance_call_base -{}; +{ + typedef typename geometry::default_comparable_distance_result + < + G1, G2 + >::type result_type; + + static inline result_type apply(G1 const& g1, G2 const& g2, default_strategy const&) + { + return geometry::comparable_distance(g1, g2); + } +}; // ------------------------------------------------------------------ // // calculate_distance diff --git a/include/boost/geometry/index/detail/predicates.hpp b/include/boost/geometry/index/detail/predicates.hpp index 1318c1cf0..08bc18e15 100644 --- a/include/boost/geometry/index/detail/predicates.hpp +++ b/include/boost/geometry/index/detail/predicates.hpp @@ -225,9 +225,9 @@ struct spatial_predicate_intersects } template - static inline bool apply(G1 const& g1, G2 const& g2, S const& ) + static inline bool apply(G1 const& g1, G2 const& g2, S const& s) { - return geometry::intersects(g1, g2, typename S::covered_by_point_box_strategy_type()); + return geometry::intersects(g1, g2, s); } }; diff --git a/include/boost/geometry/index/detail/rtree/rstar/insert.hpp b/include/boost/geometry/index/detail/rtree/rstar/insert.hpp index 3f35bcad6..87ef987b8 100644 --- a/include/boost/geometry/index/detail/rtree/rstar/insert.hpp +++ b/include/boost/geometry/index/detail/rtree/rstar/insert.hpp @@ -29,32 +29,32 @@ namespace rstar { // Utility to distinguish between default and non-default index strategy template -struct comparable_distance_point_point +struct comparable_distance { - typedef typename Strategy::comparable_distance_point_point_strategy_type strategy_type; typedef typename geometry::comparable_distance_result < - Point1, Point2, strategy_type + Point1, Point2, + decltype(std::declval().comparable_distance( + std::declval(), std::declval())) >::type result_type; - static inline strategy_type get_strategy(Strategy const& strategy) + static inline result_type call(Point1 const& p1, Point2 const& p2, Strategy const& s) { - return strategy.get_comparable_distance_point_point_strategy(); + return geometry::comparable_distance(p1, p2, s.comparable_distance(p1, p2)); } }; template -struct comparable_distance_point_point +struct comparable_distance { - typedef default_strategy strategy_type; typedef typename geometry::default_comparable_distance_result < Point1, Point2 >::type result_type; - static inline strategy_type get_strategy(default_strategy const& ) + static inline result_type call(Point1 const& p1, Point2 const& p2, default_strategy const& ) { - return strategy_type(); + return geometry::comparable_distance(p1, p2); } }; @@ -88,7 +88,7 @@ public: typedef typename geometry::point_type::type point_type; typedef typename index::detail::strategy_type::type strategy_type; // TODO: awulkiew - change second point_type to the point type of the Indexable? - typedef rstar::comparable_distance_point_point + typedef rstar::comparable_distance < point_type, point_type, strategy_type > comparable_distance_pp; @@ -117,8 +117,7 @@ public: // If constructor is used instead of resize() MS implementation leaks here sorted_elements.reserve(elements_count); // MAY THROW, STRONG (V, E: alloc, copy) - typename comparable_distance_pp::strategy_type - cdist_strategy = comparable_distance_pp::get_strategy(index::detail::get_strategy(parameters)); + auto const& strategy = index::detail::get_strategy(parameters); for ( typename elements_type::const_iterator it = elements.begin() ; it != elements.end() ; ++it ) @@ -126,7 +125,7 @@ public: point_type element_center; geometry::centroid( rtree::element_indexable(*it, translator), element_center); sorted_elements.push_back(std::make_pair( - geometry::comparable_distance(node_center, element_center, cdist_strategy), + comparable_distance_pp::call(node_center, element_center, strategy), *it)); // MAY THROW (V, E: copy) } diff --git a/include/boost/geometry/index/detail/serialization.hpp b/include/boost/geometry/index/detail/serialization.hpp index 14961d7f4..7397790ca 100644 --- a/include/boost/geometry/index/detail/serialization.hpp +++ b/include/boost/geometry/index/detail/serialization.hpp @@ -396,7 +396,7 @@ private: if ( current_level < leafs_level ) { - node_pointer n = rtree::create_node::apply(allocators); // MAY THROW (A) + node_pointer n = rtree::create_node::apply(allocators); // MAY THROW (A) subtree_destroyer auto_remover(n, allocators); internal_node & in = rtree::get(*n); @@ -419,7 +419,7 @@ private: { BOOST_GEOMETRY_INDEX_ASSERT(current_level == leafs_level, "unexpected value"); - node_pointer n = rtree::create_node::apply(allocators); // MAY THROW (A) + node_pointer n = rtree::create_node::apply(allocators); // MAY THROW (A) subtree_destroyer auto_remover(n, allocators); leaf & l = rtree::get(*n); @@ -546,10 +546,11 @@ void load(Archive & ar, boost::geometry::index::rtree & rt, unsig typedef typename view::options_type options_type; typedef typename view::box_type box_type; typedef typename view::allocators_type allocators_type; + typedef typename view::members_holder members_holder; typedef typename options_type::parameters_type parameters_type; typedef typename allocators_type::node_pointer node_pointer; - typedef detail::rtree::subtree_destroyer subtree_destroyer; + typedef detail::rtree::subtree_destroyer subtree_destroyer; view tree(rt); @@ -563,7 +564,7 @@ void load(Archive & ar, boost::geometry::index::rtree & rt, unsig if ( 0 < values_count ) { size_type loaded_values_count = 0; - n = detail::rtree::load + n = detail::rtree::load ::apply(ar, version, leafs_level, loaded_values_count, params, tree.members().translator(), tree.members().allocators()); // MAY THROW subtree_destroyer remover(n, tree.members().allocators()); diff --git a/include/boost/geometry/index/equal_to.hpp b/include/boost/geometry/index/equal_to.hpp index f457f5184..3ce2e1e4c 100644 --- a/include/boost/geometry/index/equal_to.hpp +++ b/include/boost/geometry/index/equal_to.hpp @@ -2,8 +2,8 @@ // // Copyright (c) 2011-2016 Adam Wulkiewicz, Lodz, Poland. // -// This file was modified by Oracle on 2019. -// Modifications copyright (c) 2019 Oracle and/or its affiliates. +// This file was modified by Oracle on 2019-2020. +// Modifications copyright (c) 2019-2020 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, @@ -39,9 +39,9 @@ struct equals } template - inline static bool apply(Geometry const& g1, Geometry const& g2, Strategy const&) + inline static bool apply(Geometry const& g1, Geometry const& g2, Strategy const& s) { - return geometry::equals(g1, g2, typename Strategy::within_point_point_strategy_type()); + return geometry::equals(g1, g2, s); } }; @@ -54,11 +54,9 @@ struct equals } template - inline static bool apply(Geometry const& g1, Geometry const& g2, Strategy const&) + inline static bool apply(Geometry const& g1, Geometry const& g2, Strategy const& s) { - // NOTE: there is no strategy for equals(box, box) so pass dummy variable - // TODO: there should be a strategy even if it is the same for all CSes in case undefined_cs was used - return geometry::equals(g1, g2, 0); + return geometry::equals(g1, g2, s); } }; @@ -73,7 +71,7 @@ struct equals template inline static bool apply(Geometry const& g1, Geometry const& g2, Strategy const& s) { - return geometry::equals(g1, g2, s.get_relate_segment_segment_strategy()); + return geometry::equals(g1, g2, s); } }; diff --git a/include/boost/geometry/io/wkt/read.hpp b/include/boost/geometry/io/wkt/read.hpp index 7d73adf73..d75a44fd1 100644 --- a/include/boost/geometry/io/wkt/read.hpp +++ b/include/boost/geometry/io/wkt/read.hpp @@ -53,6 +53,10 @@ #include +#include +#include +#include + #include #include @@ -303,9 +307,9 @@ private: static inline bool disjoint(point_type const& p1, point_type const& p2) { // TODO: pass strategy - typedef typename strategy::disjoint::services::default_strategy + typedef typename strategies::io::services::default_strategy < - point_type, point_type + point_type >::type strategy_type; return detail::disjoint::disjoint_point_point(p1, p2, strategy_type()); diff --git a/include/boost/geometry/io/wkt/write.hpp b/include/boost/geometry/io/wkt/write.hpp index 6bd584b22..6b1ca59a0 100644 --- a/include/boost/geometry/io/wkt/write.hpp +++ b/include/boost/geometry/io/wkt/write.hpp @@ -48,6 +48,10 @@ #include +#include +#include +#include + #include #include @@ -184,9 +188,9 @@ private: static inline bool disjoint(point_type const& p1, point_type const& p2) { // TODO: pass strategy - typedef typename strategy::disjoint::services::default_strategy + typedef typename strategies::io::services::default_strategy < - point_type, point_type + point_type >::type strategy_type; return detail::disjoint::disjoint_point_point(p1, p2, strategy_type()); diff --git a/include/boost/geometry/policies/robustness/get_rescale_policy.hpp b/include/boost/geometry/policies/robustness/get_rescale_policy.hpp index 64ddb6924..66f949fe4 100644 --- a/include/boost/geometry/policies/robustness/get_rescale_policy.hpp +++ b/include/boost/geometry/policies/robustness/get_rescale_policy.hpp @@ -20,6 +20,7 @@ #include +#include #include #include @@ -96,13 +97,13 @@ inline void scale_box_to_integer_range(Box const& box, template < typename Point, typename RobustPoint, typename Geometry, - typename Factor, typename EnvelopeStrategy + typename Factor, typename Strategy > static inline void init_rescale_policy(Geometry const& geometry, Point& min_point, RobustPoint& min_robust_point, Factor& factor, - EnvelopeStrategy const& strategy) + Strategy const& strategy) { if (geometry::is_empty(geometry)) { @@ -123,15 +124,15 @@ static inline void init_rescale_policy(Geometry const& geometry, template < typename Point, typename RobustPoint, typename Geometry1, typename Geometry2, - typename Factor, typename EnvelopeStrategy1, typename EnvelopeStrategy2 + typename Factor, typename Strategy1, typename Strategy2 > static inline void init_rescale_policy(Geometry1 const& geometry1, Geometry2 const& geometry2, Point& min_point, RobustPoint& min_robust_point, Factor& factor, - EnvelopeStrategy1 const& strategy1, - EnvelopeStrategy2 const& strategy2) + Strategy1 const& strategy1, + Strategy2 const& strategy2) { // Get bounding boxes (when at least one of the geometries is not empty) bool const is_empty1 = geometry::is_empty(geometry1); @@ -161,13 +162,7 @@ static inline void init_rescale_policy(Geometry1 const& geometry1, < model::box >(geometry2, strategy2); - geometry::expand(env, env2, - // TEMP - envelope umbrella strategy also contains - // expand strategies - strategies::envelope::services::strategy_converter - < - EnvelopeStrategy1 - >::get(strategy1)); + geometry::expand(env, env2, strategy1); } scale_box_to_integer_range(env, min_point, min_robust_point, factor); @@ -205,9 +200,9 @@ struct rescale_policy_type template struct get_rescale_policy { - template + template static inline Policy apply(Geometry const& geometry, - EnvelopeStrategy const& strategy) + Strategy const& strategy) { typedef typename point_type::type point_type; typedef typename geometry::coordinate_type::type coordinate_type; @@ -228,10 +223,10 @@ struct get_rescale_policy return Policy(min_point, min_robust_point, factor); } - template + template static inline Policy apply(Geometry1 const& geometry1, Geometry2 const& geometry2, - EnvelopeStrategy1 const& strategy1, - EnvelopeStrategy2 const& strategy2) + Strategy1 const& strategy1, + Strategy2 const& strategy2) { typedef typename point_type::type point_type; typedef typename geometry::coordinate_type::type coordinate_type; @@ -354,177 +349,63 @@ struct rescale_overlay_policy_type::type, - typename CSTag = typename Strategy::cs_tag -> -struct get_envelope_strategy -{ - typedef typename Strategy::envelope_strategy_type type; - - static inline type apply(Strategy const& strategy) - { - return strategy.get_envelope_strategy(); - } -}; - -template -struct get_envelope_strategy -{ - typedef typename Strategy::envelope_box_strategy_type type; - - static inline type apply(Strategy const& ) - { - return type(); - } -}; - -// NOTE: within::xxx_point_point shouldn't have a getter for envelope strategy -// so dispatch by CStag. In the future strategies should probably be redesigned. -template -struct get_envelope_strategy -{ - typedef strategy::envelope::cartesian_point type; - - static inline type apply(Strategy const& ) - { - return type(); - } -}; -template -struct get_envelope_strategy -{ - typedef strategy::envelope::spherical_point type; - - static inline type apply(Strategy const& ) - { - return type(); - } -}; - -template -struct get_envelope_strategy -{ - typedef strategy::envelope::cartesian_point type; - - static inline type apply(Strategy const& ) - { - return type(); - } -}; -template -struct get_envelope_strategy -{ - typedef strategy::envelope::spherical_point type; - - static inline type apply(Strategy const& ) - { - return type(); - } -}; - - -// utility for backward-compatibility either treating the argument as geometry -// or envelope strategy for get_rescale_policy -template -< - typename Geometry2OrStrategy, - typename Tag = typename geometry::tag::type -> -struct get_rescale_policy_geometry_or_strategy -{ - template - static inline Policy apply(Geometry const& geometry, Geometry2OrStrategy const& geometry2) - { - typename geometry::strategy::envelope::services::default_strategy - < - typename geometry::tag::type, - typename geometry::cs_tag::type - >::type strategy1; - typename geometry::strategy::envelope::services::default_strategy - < - typename geometry::tag::type, - typename geometry::cs_tag::type - >::type strategy2; - - return detail::get_rescale_policy::get_rescale_policy - < - Policy - >::apply(geometry, geometry2, strategy1, strategy2); - } -}; - -template -struct get_rescale_policy_geometry_or_strategy -{ - template - static inline Policy apply(Geometry const& geometry, Strategy const& strategy) - { - return detail::get_rescale_policy::get_rescale_policy - < - Policy - >::apply(geometry, - get_envelope_strategy - < - Geometry, Strategy - >::apply(strategy)); - } -}; - - -}} // namespace detail::get_rescale_policy -#endif // DOXYGEN_NO_DETAIL - - template inline Policy get_rescale_policy(Geometry const& geometry) { - typename geometry::strategy::envelope::services::default_strategy + typename geometry::strategies::envelope::services::default_strategy < - typename geometry::tag::type, - typename geometry::cs_tag::type + Geometry, + model::box::type> >::type strategy; return detail::get_rescale_policy::get_rescale_policy::apply(geometry, strategy); } -template -inline Policy get_rescale_policy(Geometry const& geometry, Geometry2OrStrategy const& geometry2_or_strategy) +template +< + typename Policy, typename Geometry, typename Strategy, + std::enable_if_t::type>::value, int> = 0 +> +inline Policy get_rescale_policy(Geometry const& geometry, Strategy const& strategy) { - // if the second argument is a geometry use default strategy - // otherwise assume it's envelope strategy for the first argument - return detail::get_rescale_policy::get_rescale_policy_geometry_or_strategy + return detail::get_rescale_policy::get_rescale_policy < - Geometry2OrStrategy - > ::template apply(geometry, geometry2_or_strategy); + Policy + >::apply(geometry, strategy); } -template +template +< + typename Policy, typename Geometry1, typename Geometry2, + std::enable_if_t::type>::value, int> = 0 +> +inline Policy get_rescale_policy(Geometry1 const& geometry1, Geometry2 const& geometry2) +{ + typename geometry::strategies::envelope::services::default_strategy + < + Geometry1, + model::box::type> + >::type strategy1; + typename geometry::strategies::envelope::services::default_strategy + < + Geometry2, + model::box::type> + >::type strategy2; + + return detail::get_rescale_policy::get_rescale_policy + < + Policy + >::apply(geometry1, geometry2, strategy1, strategy2); +} + +template inline Policy get_rescale_policy(Geometry1 const& geometry1, Geometry2 const& geometry2, - IntersectionStrategy const& strategy) + Strategy const& strategy) { return detail::get_rescale_policy::get_rescale_policy < Policy - >::apply(geometry1, geometry2, - detail::get_rescale_policy::get_envelope_strategy - < - Geometry1, IntersectionStrategy - >::apply(strategy), - detail::get_rescale_policy::get_envelope_strategy - < - Geometry2, IntersectionStrategy - >::apply(strategy)); + >::apply(geometry1, geometry2, strategy, strategy); } diff --git a/include/boost/geometry/policies/robustness/segment_ratio.hpp b/include/boost/geometry/policies/robustness/segment_ratio.hpp index c9e012e90..9f36047e2 100644 --- a/include/boost/geometry/policies/robustness/segment_ratio.hpp +++ b/include/boost/geometry/policies/robustness/segment_ratio.hpp @@ -118,19 +118,63 @@ public : , m_approximation(0) {} - inline segment_ratio(const Type& nominator, const Type& denominator) - : m_numerator(nominator) + inline segment_ratio(const Type& numerator, const Type& denominator) + : m_numerator(numerator) , m_denominator(denominator) { initialize(); } + segment_ratio(segment_ratio const&) = default; + segment_ratio& operator=(segment_ratio const&) = default; + segment_ratio(segment_ratio&&) = default; + segment_ratio& operator=(segment_ratio&&) = default; + + // These are needed because in intersection strategies ratios are assigned + // in fractions and if a user passes CalculationType then ratio Type in + // turns is taken from geometry coordinate_type and the one used in + // a strategy uses Type selected using CalculationType. + // See: detail::overlay::intersection_info_base + // and policies::relate::segments_intersection_points + // in particular segments_collinear() where ratios are assigned. + template friend class segment_ratio; + template + segment_ratio(segment_ratio const& r) + : m_numerator(r.m_numerator) + , m_denominator(r.m_denominator) + { + initialize(); + } + template + segment_ratio& operator=(segment_ratio const& r) + { + m_numerator = r.m_numerator; + m_denominator = r.m_denominator; + initialize(); + return *this; + } + template + segment_ratio(segment_ratio && r) + : m_numerator(std::move(r.m_numerator)) + , m_denominator(std::move(r.m_denominator)) + { + initialize(); + } + template + segment_ratio& operator=(segment_ratio && r) + { + m_numerator = std::move(r.m_numerator); + m_denominator = std::move(r.m_denominator); + initialize(); + return *this; + } + inline Type const& numerator() const { return m_numerator; } inline Type const& denominator() const { return m_denominator; } - inline void assign(const Type& nominator, const Type& denominator) + inline void assign(const Type& numerator, const Type& denominator) { - m_numerator = nominator; + m_numerator = numerator; m_denominator = denominator; initialize(); } diff --git a/include/boost/geometry/strategies/agnostic/point_in_box_by_side.hpp b/include/boost/geometry/strategies/agnostic/point_in_box_by_side.hpp index f87656dbc..5ea58736e 100644 --- a/include/boost/geometry/strategies/agnostic/point_in_box_by_side.hpp +++ b/include/boost/geometry/strategies/agnostic/point_in_box_by_side.hpp @@ -4,8 +4,8 @@ // Copyright (c) 2008-2012 Bruno Lalande, Paris, France. // Copyright (c) 2009-2012 Mateusz Loskot, London, UK. -// This file was modified by Oracle on 2018. -// Modifications copyright (c) 2018 Oracle and/or its affiliates. +// This file was modified by Oracle on 2018-2020. +// Modifications copyright (c) 2018-2020 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 @@ -24,8 +24,10 @@ #include #include #include -#include #include +#include +#include +#include namespace boost { namespace geometry { namespace strategy @@ -34,6 +36,10 @@ namespace boost { namespace geometry { namespace strategy namespace within { +#ifndef DOXYGEN_NO_DETAIL +namespace detail +{ + struct decide_within { static inline bool apply(int side, bool& result) @@ -65,45 +71,181 @@ struct decide_covered_by // This strategy is not suitable for boxes in non-cartesian CSes having edges // longer than 180deg because e.g. the SSF formula picks the side of the closer // longitude, so for long edges the side is the opposite. -template -struct point_in_box_by_side +// Actually it is not suitable for shorter edges either because the edges of +// boxes are defined by meridians and parallels, not great circles or geodesics. +template +inline bool point_in_box_by_side(Point const& point, Box const& box, + Strategy const& strategy) +{ + boost::ignore_unused(strategy); + + // Create (counterclockwise) array of points, the fifth one closes it + // Every point should be on the LEFT side (=1), or ON the border (=0), + // So >= 1 or >= 0 + boost::array::type, 5> bp; + geometry::detail::assign_box_corners_oriented(box, bp); + bp[4] = bp[0]; + + bool result = true; + for (int i = 1; i < 5; i++) + { + int const side = strategy.apply(point, bp[i - 1], bp[i]); + if (! Decide::apply(side, result)) + { + return result; + } + } + + return result; +} + + +} // namespace detail +#endif // DOXYGEN_NO_DETAIL + + +// There should probably be another category of geometry different than box, +// e.g. rectangle or convex_ring. This strategy should probably be an +// algorithm calling side strategy. + +template +struct cartesian_point_box_by_side { template static inline bool apply(Point const& point, Box const& box) { - typedef typename strategy::side::services::default_strategy + return within::detail::point_in_box_by_side < - typename cs_tag::type - >::type side_strategy_type; - - // Create (counterclockwise) array of points, the fifth one closes it - // Every point should be on the LEFT side (=1), or ON the border (=0), - // So >= 1 or >= 0 - boost::array::type, 5> bp; - geometry::detail::assign_box_corners_oriented(box, bp); - bp[4] = bp[0]; - - bool result = true; - side_strategy_type strategy; - boost::ignore_unused(strategy); - - for (int i = 1; i < 5; i++) - { - int const side = strategy.apply(point, bp[i - 1], bp[i]); - if (! Decide::apply(side, result)) - { - return result; - } - } - - return result; + within::detail::decide_within + >(point, box, + strategy::side::side_by_triangle()); } }; +template +struct spherical_point_box_by_side +{ + template + static inline bool apply(Point const& point, Box const& box) + { + return within::detail::point_in_box_by_side + < + within::detail::decide_within + >(point, box, + strategy::side::spherical_side_formula()); + } +}; + +template +< + typename FormulaPolicy = strategy::andoyer, + typename Spheroid = srs::spheroid, + typename CalculationType = void +> +struct geographic_point_box_by_side +{ + geographic_point_box_by_side() = default; + + explicit geographic_point_box_by_side(Spheroid const& spheroid) + : m_side(spheroid) + {} + + template + bool apply(Point const& point, Box const& box) const + { + return within::detail::point_in_box_by_side + < + within::detail::decide_within + >(point, box, m_side); + } + + Spheroid const& model() const + { + return m_side.model(); + } + +private: + strategy::side::geographic + < + FormulaPolicy, Spheroid, CalculationType + > m_side; +}; + } // namespace within +namespace covered_by +{ + + +template +struct cartesian_point_box_by_side +{ + template + static bool apply(Point const& point, Box const& box) + { + return within::detail::point_in_box_by_side + < + within::detail::decide_covered_by + >(point, box, + strategy::side::side_by_triangle()); + } +}; + +template +struct spherical_point_box_by_side +{ + template + static bool apply(Point const& point, Box const& box) + { + return within::detail::point_in_box_by_side + < + within::detail::decide_covered_by + >(point, box, + strategy::side::spherical_side_formula()); + } +}; + +template +< + typename FormulaPolicy = strategy::andoyer, + typename Spheroid = srs::spheroid, + typename CalculationType = void +> +struct geographic_point_box_by_side +{ + geographic_point_box_by_side() = default; + + explicit geographic_point_box_by_side(Spheroid const& spheroid) + : m_side(spheroid) + {} + + template + bool apply(Point const& point, Box const& box) const + { + return within::detail::point_in_box_by_side + < + within::detail::decide_covered_by + >(point, box, m_side); + } + + Spheroid const& model() const + { + return m_side.model(); + } + +private: + strategy::side::geographic + < + FormulaPolicy, Spheroid, CalculationType + > m_side; +}; + + +} + + }}} // namespace boost::geometry::strategy diff --git a/include/boost/geometry/strategies/area/geographic.hpp b/include/boost/geometry/strategies/area/geographic.hpp index 4c04da7be..5f9e1dab7 100644 --- a/include/boost/geometry/strategies/area/geographic.hpp +++ b/include/boost/geometry/strategies/area/geographic.hpp @@ -30,7 +30,8 @@ template typename Spheroid = srs::spheroid, typename CalculationType = void > -class geographic : strategies::detail::geographic_base +class geographic + : public strategies::detail::geographic_base { using base_t = strategies::detail::geographic_base; diff --git a/include/boost/geometry/strategies/area/spherical.hpp b/include/boost/geometry/strategies/area/spherical.hpp index 2486abb7d..8194aeb00 100644 --- a/include/boost/geometry/strategies/area/spherical.hpp +++ b/include/boost/geometry/strategies/area/spherical.hpp @@ -28,7 +28,8 @@ template typename RadiusTypeOrSphere = double, typename CalculationType = void > -class spherical : strategies::detail::spherical_base +class spherical + : public strategies::detail::spherical_base { using base_t = strategies::detail::spherical_base; diff --git a/include/boost/geometry/strategies/azimuth.hpp b/include/boost/geometry/strategies/azimuth.hpp index 1573ad22a..7d1e105d9 100644 --- a/include/boost/geometry/strategies/azimuth.hpp +++ b/include/boost/geometry/strategies/azimuth.hpp @@ -1,6 +1,6 @@ // Boost.Geometry (aka GGL, Generic Geometry Library) -// Copyright (c) 2016-2020 Oracle and/or its affiliates. +// Copyright (c) 2016-2021 Oracle and/or its affiliates. // Contributed and/or modified by Vissarion Fisikopoulos, on behalf of Oracle // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle @@ -26,7 +26,7 @@ namespace strategy { namespace azimuth { namespace services \tparam CSTag tag of coordinate system \tparam CalculationType \tparam_calculation */ -template +template struct default_strategy { BOOST_GEOMETRY_STATIC_ASSERT_FALSE( diff --git a/include/boost/geometry/strategies/azimuth/cartesian.hpp b/include/boost/geometry/strategies/azimuth/cartesian.hpp new file mode 100644 index 000000000..ac6136f89 --- /dev/null +++ b/include/boost/geometry/strategies/azimuth/cartesian.hpp @@ -0,0 +1,63 @@ +// Boost.Geometry + +// Copyright (c) 2021, Oracle and/or its affiliates. + +// 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 + +#ifndef BOOST_GEOMETRY_STRATEGIES_AZIMUTH_CARTESIAN_HPP +#define BOOST_GEOMETRY_STRATEGIES_AZIMUTH_CARTESIAN_HPP + + +// TODO: move this file to boost/geometry/strategy +#include + +#include +#include + + +namespace boost { namespace geometry +{ + +namespace strategies { namespace azimuth +{ + +template +struct cartesian : strategies::detail::cartesian_base +{ + static auto azimuth() + { + return strategy::azimuth::cartesian(); + } +}; + + +namespace services +{ + +template +struct default_strategy +{ + using type = strategies::azimuth::cartesian<>; +}; + + +template +struct strategy_converter > +{ + static auto get(strategy::azimuth::cartesian const&) + { + return strategies::azimuth::cartesian(); + } +}; + + +} // namespace services + +}} // namespace strategies::azimuth + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_STRATEGIES_AZIMUTH_CARTESIAN_HPP diff --git a/include/boost/geometry/strategies/azimuth/geographic.hpp b/include/boost/geometry/strategies/azimuth/geographic.hpp new file mode 100644 index 000000000..a4fac5e60 --- /dev/null +++ b/include/boost/geometry/strategies/azimuth/geographic.hpp @@ -0,0 +1,81 @@ +// Boost.Geometry + +// Copyright (c) 2021, Oracle and/or its affiliates. + +// 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 + +#ifndef BOOST_GEOMETRY_STRATEGIES_AZIMUTH_GEOGRAPHIC_HPP +#define BOOST_GEOMETRY_STRATEGIES_AZIMUTH_GEOGRAPHIC_HPP + + +// TODO: move this file to boost/geometry/strategy +#include + +#include +#include + + +namespace boost { namespace geometry +{ + +namespace strategies { namespace azimuth +{ + +template +< + typename FormulaPolicy = strategy::andoyer, + typename Spheroid = srs::spheroid, + typename CalculationType = void +> +class geographic : strategies::detail::geographic_base +{ + using base_t = strategies::detail::geographic_base; + +public: + geographic() + : base_t() + {} + + explicit geographic(Spheroid const& spheroid) + : base_t(spheroid) + {} + + auto azimuth() const + { + return strategy::azimuth::geographic + < + FormulaPolicy, Spheroid, CalculationType + >(base_t::m_spheroid); + } +}; + + +namespace services +{ + +template +struct default_strategy +{ + using type = strategies::azimuth::geographic<>; +}; + + +template +struct strategy_converter > +{ + static auto get(strategy::azimuth::geographic const& strategy) + { + return strategies::azimuth::geographic(strategy.model()); + } +}; + +} // namespace services + +}} // namespace strategies::azimuth + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_STRATEGIES_AZIMUTH_GEOGRAPHIC_HPP diff --git a/include/boost/geometry/strategies/azimuth/services.hpp b/include/boost/geometry/strategies/azimuth/services.hpp new file mode 100644 index 000000000..11980e5a4 --- /dev/null +++ b/include/boost/geometry/strategies/azimuth/services.hpp @@ -0,0 +1,56 @@ +// Boost.Geometry + +// Copyright (c) 2021, Oracle and/or its affiliates. + +// 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 + +#ifndef BOOST_GEOMETRY_STRATEGIES_AZIMUTH_SERVICES_HPP +#define BOOST_GEOMETRY_STRATEGIES_AZIMUTH_SERVICES_HPP + + +#include +#include + + +namespace boost { namespace geometry +{ + + +namespace strategies { namespace azimuth { + +namespace services +{ + +template +< + typename Point1, typename Point2, + typename CSTag1 = typename geometry::cs_tag::type, + typename CSTag2 = typename geometry::cs_tag::type +> +struct default_strategy +{ + BOOST_GEOMETRY_STATIC_ASSERT_FALSE( + "Not implemented for these Points' coordinate systems.", + Point1, Point2, CSTag1, CSTag2); +}; + +template +struct strategy_converter +{ + BOOST_GEOMETRY_STATIC_ASSERT_FALSE( + "Not implemented for this Strategy.", + Strategy); +}; + + +} // namespace services + +}} // namespace strategies::azimuth + + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_STRATEGIES_AZIMUTH_SERVICES_HPP diff --git a/include/boost/geometry/strategies/azimuth/spherical.hpp b/include/boost/geometry/strategies/azimuth/spherical.hpp new file mode 100644 index 000000000..a87cf927b --- /dev/null +++ b/include/boost/geometry/strategies/azimuth/spherical.hpp @@ -0,0 +1,67 @@ +// Boost.Geometry + +// Copyright (c) 2021, Oracle and/or its affiliates. + +// 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 + +#ifndef BOOST_GEOMETRY_STRATEGIES_AZIMUTH_SPHERICAL_HPP +#define BOOST_GEOMETRY_STRATEGIES_AZIMUTH_SPHERICAL_HPP + + +// TODO: move this file to boost/geometry/strategy +#include + +#include +#include + + +namespace boost { namespace geometry +{ + +namespace strategies { namespace azimuth +{ + +template +class spherical : strategies::detail::spherical_base +{ + using base_t = strategies::detail::spherical_base; + +public: + + static auto azimuth() + { + return strategy::azimuth::spherical(); + } +}; + + +namespace services +{ + + +template +struct default_strategy +{ + using type = strategies::azimuth::spherical<>; +}; + +template +struct strategy_converter > +{ + static auto get(strategy::azimuth::spherical const&) + { + return strategies::azimuth::spherical(); + } +}; + + +} // namespace services + +}} // namespace strategies::azimuth + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_STRATEGIES_AZIMUTH_SPHERICAL_HPP diff --git a/include/boost/geometry/strategies/cartesian.hpp b/include/boost/geometry/strategies/cartesian.hpp index a49cfe6a3..9b4559ad4 100644 --- a/include/boost/geometry/strategies/cartesian.hpp +++ b/include/boost/geometry/strategies/cartesian.hpp @@ -1,6 +1,6 @@ // Boost.Geometry -// Copyright (c) 2020, Oracle and/or its affiliates. +// Copyright (c) 2020-2021, Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle @@ -12,8 +12,13 @@ #include +#include +#include #include #include +#include +#include +#include namespace boost { namespace geometry @@ -25,74 +30,20 @@ namespace strategies template -struct cartesian : strategies::detail::cartesian_base +class cartesian + // derived from the umbrella strategy defining the most strategies + : public strategies::index::cartesian { - // area +public: - template - static auto area(Geometry const&) + static auto azimuth() { - return strategy::area::cartesian(); + return strategy::azimuth::cartesian(); } - // envelope - - template - static auto envelope(Geometry const&, Box const&, - typename util::enable_if_point_t * = nullptr) + static auto point_order() { - return strategy::envelope::cartesian_point(); - } - - template - static auto envelope(Geometry const&, Box const&, - typename util::enable_if_multi_point_t * = nullptr) - { - return strategy::envelope::cartesian_multipoint(); - } - - template - static auto envelope(Geometry const&, Box const&, - typename util::enable_if_box_t * = nullptr) - { - return strategy::envelope::cartesian_box(); - } - - template - static auto envelope(Geometry const&, Box const&, - typename util::enable_if_segment_t * = nullptr) - { - return strategy::envelope::cartesian_segment(); - } - - template - static auto envelope(Geometry const&, Box const&, - typename util::enable_if_polysegmental_t * = nullptr) - { - return strategy::envelope::cartesian(); - } - - // expand - - template - static auto expand(Box const&, Geometry const&, - typename util::enable_if_point_t * = nullptr) - { - return strategy::expand::cartesian_point(); - } - - template - static auto expand(Box const&, Geometry const&, - typename util::enable_if_box_t * = nullptr) - { - return strategy::expand::cartesian_box(); - } - - template - static auto expand(Box const&, Geometry const&, - typename util::enable_if_segment_t * = nullptr) - { - return strategy::expand::cartesian_segment(); + return strategy::point_order::cartesian(); } }; diff --git a/include/boost/geometry/strategies/cartesian/azimuth.hpp b/include/boost/geometry/strategies/cartesian/azimuth.hpp index 2ff16e945..74a9ea12b 100644 --- a/include/boost/geometry/strategies/cartesian/azimuth.hpp +++ b/include/boost/geometry/strategies/cartesian/azimuth.hpp @@ -1,6 +1,6 @@ // Boost.Geometry (aka GGL, Generic Geometry Library) -// Copyright (c) 2016-2018 Oracle and/or its affiliates. +// Copyright (c) 2016-2021 Oracle and/or its affiliates. // Contributed and/or modified by Vissarion Fisikopoulos, on behalf of Oracle // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle @@ -11,32 +11,81 @@ #ifndef BOOST_GEOMETRY_STRATEGIES_CARTESIAN_AZIMUTH_HPP #define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_AZIMUTH_HPP +#include + #include #include +#include +#include + namespace boost { namespace geometry { namespace strategy { namespace azimuth { -template -< - typename CalculationType = void -> +template class cartesian -{}; +{ +public: + template + struct result_type + : geometry::select_most_precise + < + // NOTE: this promotes any integer type to double + typename geometry::promote_floating_point::type, + typename geometry::promote_floating_point::type, + CalculationType + > + {}; + + template + static inline void apply(T1 const& x1, T1 const& y1, + T2 const& x2, T2 const& y2, + Result& a1, Result& a2) + { + compute(x1, y1, x2, y2, a1, a2); + } + template + static inline void apply(T1 const& x1, T1 const& y1, + T2 const& x2, T2 const& y2, + Result& a1) + { + compute(x1, y1, x2, y2, a1, a1); + } + template + static inline void apply_reverse(T1 const& x1, T1 const& y1, + T2 const& x2, T2 const& y2, + Result& a2) + { + compute(x1, y1, x2, y2, a2, a2); + } + +private: + template + static inline void compute(T1 const& x1, T1 const& y1, + T2 const& x2, T2 const& y2, + Result& a1, Result& a2) + { + typedef typename result_type::type calc_t; + + // NOTE: azimuth 0 is at Y axis, increasing right + // as in spherical/geographic where 0 is at North axis + a1 = a2 = atan2(calc_t(x2) - calc_t(x1), calc_t(y2) - calc_t(y1)); + } +}; #ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS namespace services { -template -struct default_strategy +template <> +struct default_strategy { - typedef strategy::azimuth::cartesian type; + typedef strategy::azimuth::cartesian<> type; }; } diff --git a/include/boost/geometry/strategies/cartesian/box_in_box.hpp b/include/boost/geometry/strategies/cartesian/box_in_box.hpp index fef054cdb..a0cb6d9d1 100644 --- a/include/boost/geometry/strategies/cartesian/box_in_box.hpp +++ b/include/boost/geometry/strategies/cartesian/box_in_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 2015, 2016, 2017, 2019. -// Modifications copyright (c) 2016-2019, Oracle and/or its affiliates. +// This file was modified by Oracle on 2015-2020. +// Modifications copyright (c) 2016-2020, Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle @@ -186,11 +186,6 @@ struct relate_box_box_loop }; -} // namespace detail -#endif // DOXYGEN_NO_DETAIL - - -// for backward compatibility template struct box_within_range : within::detail::box_within_coord @@ -226,31 +221,8 @@ struct box_covered_by_range {}; -// for backward compatibility -template -< - typename B1, - typename B2, - template class SubStrategy = box_within_range -> -struct box_in_box -{ - template - static inline bool apply(Box1 const& box1, Box2 const& box2) - { - typedef typename tag_cast - < - typename geometry::cs_tag::type, - spherical_tag - >::type cs_tag; - - return within::detail::relate_box_box_loop - < - SubStrategy, cs_tag, - 0, dimension::type::value - >::apply(box1, box2); - } -}; +} // namespace detail +#endif // DOXYGEN_NO_DETAIL struct cartesian_box_box @@ -260,7 +232,7 @@ struct cartesian_box_box { return within::detail::relate_box_box_loop < - box_within_range, + within::detail::box_within_range, cartesian_tag, 0, dimension::type::value >::apply(box1, box2); @@ -274,7 +246,7 @@ struct spherical_box_box { return within::detail::relate_box_box_loop < - box_within_range, + within::detail::box_within_range, spherical_tag, 0, dimension::type::value >::apply(box1, box2); @@ -296,7 +268,7 @@ struct cartesian_box_box { return within::detail::relate_box_box_loop < - strategy::within::box_covered_by_range, + within::detail::box_covered_by_range, cartesian_tag, 0, dimension::type::value >::apply(box1, box2); @@ -310,7 +282,7 @@ struct spherical_box_box { return within::detail::relate_box_box_loop < - strategy::within::box_covered_by_range, + within::detail::box_covered_by_range, spherical_tag, 0, dimension::type::value >::apply(box1, box2); diff --git a/include/boost/geometry/strategies/cartesian/index.hpp b/include/boost/geometry/strategies/cartesian/index.hpp deleted file mode 100644 index f4a16be5a..000000000 --- a/include/boost/geometry/strategies/cartesian/index.hpp +++ /dev/null @@ -1,198 +0,0 @@ -// Boost.Geometry Index -// -// R-tree strategies -// -// Copyright (c) 2019-2020, 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_STRATEGIES_CARTESIAN_INDEX_HPP -#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_INDEX_HPP - - -#include -#include -#include -#include -#include -#include - -#include -#include -//#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - - -namespace boost { namespace geometry { namespace strategy { namespace index -{ - -template -< - typename CalculationType = void -> -struct cartesian -{ - typedef cartesian_tag cs_tag; - - typedef geometry::strategy::envelope::cartesian_point envelope_point_strategy_type; - typedef geometry::strategy::envelope::cartesian_box envelope_box_strategy_type; - typedef geometry::strategy::envelope::cartesian_segment - < - CalculationType - > envelope_segment_strategy_type; - - static inline envelope_segment_strategy_type get_envelope_segment_strategy() - { - return envelope_segment_strategy_type(); - } - - typedef geometry::strategy::expand::cartesian_point expand_point_strategy_type; - typedef geometry::strategy::expand::cartesian_box expand_box_strategy_type; - typedef geometry::strategy::expand::cartesian_segment expand_segment_strategy_type; - - static inline expand_segment_strategy_type get_expand_segment_strategy() - { - return expand_segment_strategy_type(); - } - - typedef geometry::strategy::covered_by::cartesian_point_box covered_by_point_box_strategy_type; - typedef geometry::strategy::covered_by::cartesian_box_box covered_by_box_box_strategy_type; - typedef geometry::strategy::within::cartesian_point_point within_point_point_strategy_type; - /* - typedef geometry::strategy::within::cartesian_point_box within_point_box_strategy_type; - typedef geometry::strategy::within::cartesian_box_box within_box_box_strategy_type; - typedef geometry::strategy::within::cartesian_winding - < - void, void, CalculationType - > within_point_segment_strategy_type; - - static inline within_point_segment_strategy_type get_within_point_segment_strategy() - { - return within_point_segment_strategy_type(); - } - */ - - // used in equals(Seg, Seg) but only to get_point_in_point_strategy() - typedef geometry::strategy::intersection::cartesian_segments - < - CalculationType - > relate_segment_segment_strategy_type; - - static inline relate_segment_segment_strategy_type get_relate_segment_segment_strategy() - { - return relate_segment_segment_strategy_type(); - } - - // used in intersection_content - typedef geometry::strategy::disjoint::cartesian_box_box disjoint_box_box_strategy_type; - - typedef geometry::strategy::distance::comparable::pythagoras - < - CalculationType - > comparable_distance_point_point_strategy_type; - - static inline comparable_distance_point_point_strategy_type get_comparable_distance_point_point_strategy() - { - return comparable_distance_point_point_strategy_type(); - } - - typedef geometry::strategy::distance::comparable::pythagoras_point_box - < - CalculationType - > comparable_distance_point_box_strategy_type; - - static inline comparable_distance_point_box_strategy_type get_comparable_distance_point_box_strategy() - { - return comparable_distance_point_box_strategy_type(); - } - - // TODO: comparable version should be possible - typedef geometry::strategy::distance::projected_point - < - CalculationType, - geometry::strategy::distance::pythagoras - > comparable_distance_point_segment_strategy_type; - - static inline comparable_distance_point_segment_strategy_type get_comparable_distance_point_segment_strategy() - { - return comparable_distance_point_segment_strategy_type(); - } - - typedef geometry::strategy::distance::cartesian_segment_box - < - CalculationType, - geometry::strategy::distance::pythagoras - > comparable_distance_segment_box_strategy_type; - - static inline comparable_distance_segment_box_strategy_type get_comparable_distance_segment_box_strategy() - { - return comparable_distance_segment_box_strategy_type(); - } -}; - - -namespace services -{ - -template -struct default_strategy -{ - typedef cartesian<> type; -}; - - -// within and relate (MPt, Mls/MPoly) -template -struct from_strategy > -{ - typedef strategy::index::cartesian type; - - static inline type get(within::cartesian_winding const&) - { - return type(); - } -}; - -// distance (MPt, MPt) -template -struct from_strategy > -{ - typedef strategy::index::cartesian type; - - static inline type get(distance::comparable::pythagoras const&) - { - return type(); - } -}; - -// distance (MPt, Linear/Areal) -template -struct from_strategy > -{ - typedef strategy::index::cartesian type; - - static inline type get(distance::projected_point const&) - { - return type(); - } -}; - - -} // namespace services - - -}}}} // namespace boost::geometry::strategy::index - -#endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_INDEX_HPP diff --git a/include/boost/geometry/strategies/cartesian/intersection.hpp b/include/boost/geometry/strategies/cartesian/intersection.hpp index 81efbbc47..f0b471036 100644 --- a/include/boost/geometry/strategies/cartesian/intersection.hpp +++ b/include/boost/geometry/strategies/cartesian/intersection.hpp @@ -436,13 +436,12 @@ struct cartesian_segments point2_type const& q1 = range_q.at(0); point2_type const& q2 = range_q.at(1); - using geometry::detail::equals::equals_point_point; - bool const p_is_point = equals_point_point(p1, p2, point_in_point_strategy_type()); - bool const q_is_point = equals_point_point(q1, q2, point_in_point_strategy_type()); + bool const p_is_point = equals_point_point(p1, p2); + bool const q_is_point = equals_point_point(q1, q2); if (p_is_point && q_is_point) { - return equals_point_point(p1, q2, point_in_point_strategy_type()) + return equals_point_point(p1, q2) ? Policy::degenerate(p, true) : Policy::disjoint() ; @@ -772,6 +771,12 @@ private: : ca1 < cb2 ? 4 : 2 ); } + + template + static inline bool equals_point_point(Point1 const& point1, Point2 const& point2) + { + return strategy::within::cartesian_point_point::apply(point1, point2); + } }; diff --git a/include/boost/geometry/strategies/cartesian/io.hpp b/include/boost/geometry/strategies/cartesian/io.hpp deleted file mode 100644 index d8fda2961..000000000 --- a/include/boost/geometry/strategies/cartesian/io.hpp +++ /dev/null @@ -1,74 +0,0 @@ -// Boost.Geometry - -// Copyright (c) 2019, Oracle and/or its affiliates. - -// 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 - -#ifndef BOOST_GEOMETRY_EXTENSIONS_STRATEGIES_CARTESIAN_IO_HPP -#define BOOST_GEOMETRY_EXTENSIONS_STRATEGIES_CARTESIAN_IO_HPP - - -#include - -#include -#include - - -namespace boost { namespace geometry -{ - -namespace strategy { namespace io -{ - -template -struct cartesian -{ - typedef strategy::point_order::cartesian point_order_strategy_type; - - static inline point_order_strategy_type get_point_order_strategy() - { - return point_order_strategy_type(); - } - - template - struct point_in_geometry_strategy - { - typedef strategy::within::cartesian_winding - < - typename point_type::type, - typename point_type::type, - CalculationType - > type; - }; - - template - static inline typename point_in_geometry_strategy::type - get_point_in_geometry_strategy() - { - typedef typename point_in_geometry_strategy - < - Geometry1, Geometry2 - >::type strategy_type; - return strategy_type(); - } -}; - -namespace services -{ - -template <> -struct default_strategy -{ - typedef cartesian<> type; -}; - -} // namespace services - -}} // namespace strategy::io - -}} // namespace boost::geometry - -#endif // BOOST_GEOMETRY_EXTENSIONS_STRATEGIES_CARTESIAN_IO_HPP diff --git a/include/boost/geometry/strategies/cartesian/side_by_triangle.hpp b/include/boost/geometry/strategies/cartesian/side_by_triangle.hpp index 62eceaadf..ea58e78e7 100644 --- a/include/boost/geometry/strategies/cartesian/side_by_triangle.hpp +++ b/include/boost/geometry/strategies/cartesian/side_by_triangle.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 2015-2020. -// Modifications copyright (c) 2015-2020, Oracle and/or its affiliates. +// This file was modified by Oracle on 2015-2021. +// Modifications copyright (c) 2015-2021, 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 @@ -24,17 +24,17 @@ #include #include -#include -#include -#include +#include #include #include #include #include -#include +#include + +#include namespace boost { namespace geometry @@ -269,8 +269,7 @@ private: template static inline bool equals_point_point(P1 const& p1, P2 const& p2) { - typedef equals_point_point_strategy_type strategy_t; - return geometry::detail::equals::equals_point_point(p1, p2, strategy_t()); + return strategy::within::cartesian_point_point::apply(p1, p2); } }; diff --git a/include/boost/geometry/strategies/concepts/within_concept.hpp b/include/boost/geometry/strategies/concepts/within_concept.hpp index 4616fb981..8775613ec 100644 --- a/include/boost/geometry/strategies/concepts/within_concept.hpp +++ b/include/boost/geometry/strategies/concepts/within_concept.hpp @@ -33,6 +33,8 @@ #include #include +#include + #include @@ -40,6 +42,48 @@ namespace boost { namespace geometry { namespace concepts { +namespace detail +{ + + +template +< + typename Point, typename Geometry, typename Strategy, + bool IsUmbrella = strategies::detail::is_umbrella_strategy::value +> +struct relate_strategy_dispatch +{ + using type = decltype(std::declval().relate( + std::declval(), std::declval())); +}; + +template +struct relate_strategy_dispatch +{ + using type = Strategy; +}; + +template +< + typename Point, typename Geometry, typename Strategy, + bool IsUmbrella = strategies::detail::is_umbrella_strategy::value +> +struct within_strategy_dispatch +{ + using type = decltype(std::declval().within( + std::declval(), std::declval())); +}; + +template +struct within_strategy_dispatch +{ + using type = Strategy; +}; + + +} // namespace detail + + /*! \brief Checks strategy for within (point-in-polygon) \ingroup within @@ -51,8 +95,14 @@ class WithinStrategyPolygonal typedef typename geometry::point_type::type point_of_segment; + // 0) + typedef typename concepts::detail::relate_strategy_dispatch + < + Point, Polygonal, Strategy + >::type strategy_type; + // 1) must define state_type - typedef typename Strategy::state_type state_type; + typedef typename strategy_type::state_type state_type; struct checker { @@ -101,7 +151,7 @@ class WithinStrategyPolygonal // CHECK: calling method apply and result - Strategy const* str = 0; + strategy_type const* str = 0; state_type* st = 0; point_type const* p = 0; segment_point_type const* sp = 0; @@ -117,8 +167,8 @@ class WithinStrategyPolygonal public : BOOST_CONCEPT_USAGE(WithinStrategyPolygonal) { - checker::apply(&Strategy::template apply, - &Strategy::result); + checker::apply(&strategy_type::template apply, + &strategy_type::result); } #endif }; @@ -128,6 +178,12 @@ class WithinStrategyPointBox { #ifndef DOXYGEN_NO_CONCEPT_MEMBERS + // 0) + typedef typename concepts::detail::within_strategy_dispatch + < + Point, Box, Strategy + >::type strategy_type; + struct checker { template @@ -167,7 +223,7 @@ class WithinStrategyPointBox // CHECK: calling method apply - Strategy const* str = 0; + strategy_type const* str = 0; point_type const* p = 0; box_type const* bx = 0; @@ -181,7 +237,7 @@ class WithinStrategyPointBox public : BOOST_CONCEPT_USAGE(WithinStrategyPointBox) { - checker::apply(&Strategy::template apply); + checker::apply(&strategy_type::template apply); } #endif }; @@ -191,6 +247,12 @@ class WithinStrategyBoxBox { #ifndef DOXYGEN_NO_CONCEPT_MEMBERS + // 0) + typedef typename concepts::detail::within_strategy_dispatch + < + Box1, Box2, Strategy + >::type strategy_type; + struct checker { template @@ -230,7 +292,7 @@ class WithinStrategyBoxBox // CHECK: calling method apply - Strategy const* str = 0; + strategy_type const* str = 0; box_type1 const* b1 = 0; box_type2 const* b2 = 0; @@ -244,7 +306,7 @@ class WithinStrategyBoxBox public : BOOST_CONCEPT_USAGE(WithinStrategyBoxBox) { - checker::apply(&Strategy::template apply); + checker::apply(&strategy_type::template apply); } #endif }; diff --git a/include/boost/geometry/strategies/convex_hull/cartesian.hpp b/include/boost/geometry/strategies/convex_hull/cartesian.hpp new file mode 100644 index 000000000..1bef4e389 --- /dev/null +++ b/include/boost/geometry/strategies/convex_hull/cartesian.hpp @@ -0,0 +1,49 @@ +// Boost.Geometry + +// Copyright (c) 2020, Oracle and/or its affiliates. + +// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle + +// Licensed under the Boost Software License version 1.0. +// http://www.boost.org/users/license.html + +#ifndef BOOST_GEOMETRY_STRATEGIES_CONVEX_HULL_CARTESIAN_HPP +#define BOOST_GEOMETRY_STRATEGIES_CONVEX_HULL_CARTESIAN_HPP + + +#include +#include +#include + +namespace boost { namespace geometry +{ + +namespace strategies { namespace convex_hull +{ + +template +class cartesian : public strategies::detail::cartesian_base +{ +public: + static auto side() + { + return strategy::side::side_robust(); + } +}; + +namespace services +{ + +template +struct default_strategy +{ + using type = strategies::convex_hull::cartesian<>; +}; + +} // namespace services + +}} // namespace strategies::convex_hull + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_STRATEGIES_CONVEX_HULL_CARTESIAN_HPP diff --git a/include/boost/geometry/strategies/convex_hull/geographic.hpp b/include/boost/geometry/strategies/convex_hull/geographic.hpp new file mode 100644 index 000000000..f80e1c29d --- /dev/null +++ b/include/boost/geometry/strategies/convex_hull/geographic.hpp @@ -0,0 +1,70 @@ +// Boost.Geometry + +// Copyright (c) 2020, Oracle and/or its affiliates. + +// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle + +// Licensed under the Boost Software License version 1.0. +// http://www.boost.org/users/license.html + +#ifndef BOOST_GEOMETRY_STRATEGIES_CONVEX_HULL_GEOGRAPHIC_HPP +#define BOOST_GEOMETRY_STRATEGIES_CONVEX_HULL_GEOGRAPHIC_HPP + + +#include +#include +#include + + +namespace boost { namespace geometry +{ + +namespace strategies { namespace convex_hull +{ + +template +< + typename FormulaPolicy = strategy::andoyer, + typename Spheroid = srs::spheroid, + typename CalculationType = void +> +class geographic : public strategies::detail::geographic_base +{ + using base_t = strategies::detail::geographic_base; + +public: + geographic() + : base_t() + {} + + explicit geographic(Spheroid const& spheroid) + : base_t(spheroid) + {} + + auto side() const + { + return strategy::side::geographic + < + FormulaPolicy, + Spheroid, + CalculationType + >(base_t::m_spheroid); + } +}; + +namespace services +{ + +template +struct default_strategy +{ + using type = strategies::convex_hull::geographic<>; +}; + +} // namespace services + +}} // namespace strategies::convex_hull + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_STRATEGIES_CONVEX_HULL_GEOGRAPHIC_HPP diff --git a/include/boost/geometry/strategies/convex_hull/services.hpp b/include/boost/geometry/strategies/convex_hull/services.hpp new file mode 100644 index 000000000..7dfd42147 --- /dev/null +++ b/include/boost/geometry/strategies/convex_hull/services.hpp @@ -0,0 +1,49 @@ +// Boost.Geometry + +// Copyright (c) 2020, Oracle and/or its affiliates. + +// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle + +// Licensed under the Boost Software License version 1.0. +// http://www.boost.org/users/license.html + +#ifndef BOOST_GEOMETRY_STRATEGIES_CONVEX_HULL_SERVICES_HPP +#define BOOST_GEOMETRY_STRATEGIES_CONVEX_HULL_SERVICES_HPP + + +#include + +#include + + +namespace boost { namespace geometry +{ + + +namespace strategies { namespace convex_hull { + +namespace services +{ + +template +< + typename Geometry, + typename CSTag = typename geometry::cs_tag::type +> +struct default_strategy +{ + BOOST_MPL_ASSERT_MSG + ( + false, NOT_IMPLEMENTED_FOR_THIS_COORDINATE_SYSTEM + , (types) + ); +}; + +} // namespace services + +}} // namespace strategies::convex_hull + + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_STRATEGIES_CONVEX_HULL_SERVICES_HPP diff --git a/include/boost/geometry/strategies/convex_hull/spherical.hpp b/include/boost/geometry/strategies/convex_hull/spherical.hpp new file mode 100644 index 000000000..0eec8ee82 --- /dev/null +++ b/include/boost/geometry/strategies/convex_hull/spherical.hpp @@ -0,0 +1,50 @@ +// Boost.Geometry + +// Copyright (c) 2020, Oracle and/or its affiliates. + +// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle + +// Licensed under the Boost Software License version 1.0. +// http://www.boost.org/users/license.html + +#ifndef BOOST_GEOMETRY_STRATEGIES_CONVEX_HULL_SPHERICAL_HPP +#define BOOST_GEOMETRY_STRATEGIES_CONVEX_HULL_SPHERICAL_HPP + + +#include +#include +#include + + +namespace boost { namespace geometry +{ + +namespace strategies { namespace convex_hull +{ + +template +class spherical : public strategies::detail::spherical_base +{ +public: + static auto side() + { + return strategy::side::spherical_side_formula(); + } +}; + +namespace services +{ + +template +struct default_strategy +{ + using type = strategies::convex_hull::spherical<>; +}; + +} // namespace services + +}} // namespace strategies::convex_hull + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_STRATEGIES_CONVEX_HULL_SPHERICAL_HPP diff --git a/include/boost/geometry/strategies/detail.hpp b/include/boost/geometry/strategies/detail.hpp index 410423d46..cdb4581b9 100644 --- a/include/boost/geometry/strategies/detail.hpp +++ b/include/boost/geometry/strategies/detail.hpp @@ -44,13 +44,10 @@ struct is_umbrella_strategy struct cartesian_base : umbrella_strategy { - typedef cartesian_tag tag; + typedef cartesian_tag cs_tag; }; -template -< - typename RadiusTypeOrSphere -> +template class spherical_base : umbrella_strategy { protected: @@ -60,7 +57,7 @@ protected: >::type radius_type; public: - typedef spherical_tag tag; + typedef spherical_tag cs_tag; spherical_base() : m_radius(1.0) @@ -80,18 +77,32 @@ public: } protected: + radius_type const& radius() const + { + return m_radius; + } + radius_type m_radius; }; template <> class spherical_base : umbrella_strategy { -public: - typedef spherical_tag tag; +protected: + typedef double radius_type; - srs::sphere model() const +public: + typedef spherical_tag cs_tag; + + srs::sphere model() const { - return srs::sphere(1.0); + return srs::sphere(1.0); + } + +protected: + radius_type radius() const + { + return 1.0; } }; @@ -99,7 +110,7 @@ template class geographic_base : umbrella_strategy { public: - typedef geographic_tag tag; + typedef geographic_tag cs_tag; geographic_base() : m_spheroid() diff --git a/include/boost/geometry/strategies/disjoint.hpp b/include/boost/geometry/strategies/disjoint.hpp index c5413a86d..9a52f5bc2 100644 --- a/include/boost/geometry/strategies/disjoint.hpp +++ b/include/boost/geometry/strategies/disjoint.hpp @@ -18,7 +18,8 @@ #include #include -#include + +#include namespace boost { namespace geometry { namespace strategy { namespace disjoint diff --git a/include/boost/geometry/strategies/envelope/cartesian.hpp b/include/boost/geometry/strategies/envelope/cartesian.hpp index 2fee1ece0..3bce5dbc3 100644 --- a/include/boost/geometry/strategies/envelope/cartesian.hpp +++ b/include/boost/geometry/strategies/envelope/cartesian.hpp @@ -19,12 +19,9 @@ #include #include -#include // TEMP -#include -#include // TEMP - #include #include +#include namespace boost { namespace geometry @@ -34,7 +31,8 @@ namespace strategies { namespace envelope { template -struct cartesian : strategies::detail::cartesian_base +struct cartesian + : strategies::expand::cartesian { template static auto envelope(Geometry const&, Box const&, @@ -70,28 +68,6 @@ struct cartesian : strategies::detail::cartesian_base { return strategy::envelope::cartesian(); } - - template - static auto expand(Box const&, Geometry const&, - typename util::enable_if_point_t * = nullptr) - { - return strategy::expand::cartesian_point(); - } - - // TEMP - template - static auto expand(Box const&, Geometry const&, - typename util::enable_if_box_t * = nullptr) - { - return strategy::expand::cartesian_box(); - } - - template - static auto expand(Box const&, Geometry const&, - typename util::enable_if_segment_t * = nullptr) - { - return strategy::expand::cartesian_segment(); - } }; diff --git a/include/boost/geometry/strategies/envelope/geographic.hpp b/include/boost/geometry/strategies/envelope/geographic.hpp index 236ac6e15..26e1eea70 100644 --- a/include/boost/geometry/strategies/envelope/geographic.hpp +++ b/include/boost/geometry/strategies/envelope/geographic.hpp @@ -19,6 +19,7 @@ #include // TEMP #include +#include namespace boost { namespace geometry @@ -33,9 +34,10 @@ template typename Spheroid = srs::spheroid, typename CalculationType = void > -class geographic : strategies::detail::geographic_base +class geographic + : public strategies::expand::geographic { - using base_t = strategies::detail::geographic_base; + using base_t = strategies::expand::geographic; public: geographic() @@ -86,31 +88,6 @@ public: FormulaPolicy, Spheroid, CalculationType >(base_t::m_spheroid); } - - template - static auto expand(Box const&, Geometry const&, - typename util::enable_if_point_t * = nullptr) - { - return strategy::expand::spherical_point(); - } - - // TEMP - template - static auto expand(Box const&, Geometry const&, - typename util::enable_if_box_t * = nullptr) - { - return strategy::expand::spherical_box(); - } - - template - auto expand(Box const&, Geometry const&, - typename util::enable_if_segment_t * = nullptr) const - { - return strategy::expand::geographic_segment - < - FormulaPolicy, Spheroid, CalculationType - >(base_t::m_spheroid); - } }; diff --git a/include/boost/geometry/strategies/envelope/spherical.hpp b/include/boost/geometry/strategies/envelope/spherical.hpp index 5d2f5cfea..f9e2f1352 100644 --- a/include/boost/geometry/strategies/envelope/spherical.hpp +++ b/include/boost/geometry/strategies/envelope/spherical.hpp @@ -19,12 +19,9 @@ #include #include -#include // TEMP -#include -#include // TEMP - #include #include +#include namespace boost { namespace geometry @@ -33,15 +30,14 @@ namespace boost { namespace geometry namespace strategies { namespace envelope { -template -< - typename CalculationType = void -> -class spherical : strategies::detail::spherical_base +#ifndef DOXYGEN_NO_DETAIL +namespace detail { - using base_t = strategies::detail::spherical_base; -public: +template +struct spherical + : strategies::expand::detail::spherical +{ template static auto envelope(Geometry const&, Box const&, typename util::enable_if_point_t * = nullptr) @@ -76,31 +72,19 @@ public: { return strategy::envelope::spherical(); } - - template - static auto expand(Box const&, Geometry const&, - typename util::enable_if_point_t * = nullptr) - { - return strategy::expand::spherical_point(); - } - - // TEMP - template - static auto expand(Box const&, Geometry const&, - typename util::enable_if_box_t * = nullptr) - { - return strategy::expand::spherical_box(); - } - - template - static auto expand(Box const&, Geometry const&, - typename util::enable_if_segment_t * = nullptr) - { - return strategy::expand::spherical_segment(); - } }; +} // namespace detail +#endif // DOXYGEN_NO_DETAIL + + +template +class spherical + : public strategies::envelope::detail::spherical +{}; + + namespace services { diff --git a/include/boost/geometry/strategies/expand/cartesian.hpp b/include/boost/geometry/strategies/expand/cartesian.hpp index 3f73edf07..0c830e7a3 100644 --- a/include/boost/geometry/strategies/expand/cartesian.hpp +++ b/include/boost/geometry/strategies/expand/cartesian.hpp @@ -30,7 +30,8 @@ namespace strategies { namespace expand template -struct cartesian : strategies::detail::cartesian_base +struct cartesian + : strategies::detail::cartesian_base { template static auto expand(Box const&, Geometry const&, diff --git a/include/boost/geometry/strategies/expand/geographic.hpp b/include/boost/geometry/strategies/expand/geographic.hpp index f07c63622..0812979cd 100644 --- a/include/boost/geometry/strategies/expand/geographic.hpp +++ b/include/boost/geometry/strategies/expand/geographic.hpp @@ -31,7 +31,8 @@ template typename Spheroid = srs::spheroid, typename CalculationType = void > -class geographic : strategies::detail::geographic_base +class geographic + : public strategies::detail::geographic_base { using base_t = strategies::detail::geographic_base; diff --git a/include/boost/geometry/strategies/expand/spherical.hpp b/include/boost/geometry/strategies/expand/spherical.hpp index c81417f23..363a9691f 100644 --- a/include/boost/geometry/strategies/expand/spherical.hpp +++ b/include/boost/geometry/strategies/expand/spherical.hpp @@ -28,15 +28,16 @@ namespace boost { namespace geometry namespace strategies { namespace expand { -template -< - typename CalculationType = void -> -class spherical : strategies::detail::spherical_base -{ - using base_t = strategies::detail::spherical_base; -public: +#ifndef DOXYGEN_NO_DETAIL +namespace detail +{ + + +template +struct spherical + : strategies::detail::spherical_base +{ template static auto expand(Box const&, Geometry const&, typename util::enable_if_point_t * = nullptr) @@ -60,6 +61,16 @@ public: }; +} // namespace detail +#endif // DOXYGEN_NO_DETAIL + + +template +class spherical + : public strategies::expand::detail::spherical +{}; + + namespace services { diff --git a/include/boost/geometry/strategies/geographic.hpp b/include/boost/geometry/strategies/geographic.hpp index c3bc2a4da..815f1e3f3 100644 --- a/include/boost/geometry/strategies/geographic.hpp +++ b/include/boost/geometry/strategies/geographic.hpp @@ -1,6 +1,6 @@ // Boost.Geometry -// Copyright (c) 2020, Oracle and/or its affiliates. +// Copyright (c) 2020-2021, Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle @@ -12,8 +12,13 @@ #include +#include +#include #include #include +#include +#include +#include namespace boost { namespace geometry @@ -31,9 +36,11 @@ template typename Spheroid = srs::spheroid, typename CalculationType = void > -class geographic : strategies::detail::geographic_base +class geographic + // derived from the umbrella strategy defining the most strategies + : public index::geographic { - using base_t = strategies::detail::geographic_base; + using base_t = index::geographic; public: geographic() @@ -44,81 +51,17 @@ public: : base_t(spheroid) {} - // area - - template - auto area(Geometry const&) const + auto azimuth() const { - return strategy::area::geographic - < - FormulaPolicy, SeriesOrder, Spheroid, CalculationType - >(base_t::m_spheroid); - } - - // envelope - - template - static auto envelope(Geometry const&, Box const&, - typename util::enable_if_point_t * = nullptr) - { - return strategy::envelope::spherical_point(); - } - - template - static auto envelope(Geometry const&, Box const&, - typename util::enable_if_multi_point_t * = nullptr) - { - return strategy::envelope::spherical_multipoint(); - } - - template - static auto envelope(Geometry const&, Box const&, - typename util::enable_if_box_t * = nullptr) - { - return strategy::envelope::spherical_box(); - } - - template - auto envelope(Geometry const&, Box const&, - typename util::enable_if_segment_t * = nullptr) const - { - return strategy::envelope::geographic_segment + return strategy::azimuth::geographic < FormulaPolicy, Spheroid, CalculationType >(base_t::m_spheroid); } - template - auto envelope(Geometry const&, Box const&, - typename util::enable_if_polysegmental_t * = nullptr) const + auto point_order() const { - return strategy::envelope::geographic - < - FormulaPolicy, Spheroid, CalculationType - >(base_t::m_spheroid); - } - - // expand - - template - static auto expand(Box const&, Geometry const&, - typename util::enable_if_point_t * = nullptr) - { - return strategy::expand::spherical_point(); - } - - template - static auto expand(Box const&, Geometry const&, - typename util::enable_if_box_t * = nullptr) - { - return strategy::expand::spherical_box(); - } - - template - auto expand(Box const&, Geometry const&, - typename util::enable_if_segment_t * = nullptr) const - { - return strategy::expand::geographic_segment + return strategy::point_order::geographic < FormulaPolicy, Spheroid, CalculationType >(base_t::m_spheroid); diff --git a/include/boost/geometry/strategies/geographic/azimuth.hpp b/include/boost/geometry/strategies/geographic/azimuth.hpp index ca280313d..9e6914d92 100644 --- a/include/boost/geometry/strategies/geographic/azimuth.hpp +++ b/include/boost/geometry/strategies/geographic/azimuth.hpp @@ -1,6 +1,6 @@ // Boost.Geometry (aka GGL, Generic Geometry Library) -// Copyright (c) 2016-2020 Oracle and/or its affiliates. +// Copyright (c) 2016-2021 Oracle and/or its affiliates. // Contributed and/or modified by Vissarion Fisikopoulos, on behalf of Oracle // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle @@ -19,6 +19,8 @@ #include #include +#include + namespace boost { namespace geometry { @@ -34,7 +36,14 @@ template > class geographic { -public : +public: + template + struct result_type + : geometry::select_most_precise + < + T1, T2, CalculationType + > + {}; typedef Spheroid model_type; @@ -51,28 +60,28 @@ public : return m_spheroid; } - template - inline void apply(T const& lon1_rad, T const& lat1_rad, - T const& lon2_rad, T const& lat2_rad, - T& a1, T& a2) const + template + inline void apply(T1 const& lon1_rad, T1 const& lat1_rad, + T2 const& lon2_rad, T2 const& lat2_rad, + Result& a1, Result& a2) const { compute(lon1_rad, lat1_rad, lon2_rad, lat2_rad, a1, a2); } - template - inline void apply(T const& lon1_rad, T const& lat1_rad, - T const& lon2_rad, T const& lat2_rad, - T& a1) const + template + inline void apply(T1 const& lon1_rad, T1 const& lat1_rad, + T2 const& lon2_rad, T2 const& lat2_rad, + Result& a1) const { compute(lon1_rad, lat1_rad, lon2_rad, lat2_rad, a1, a1); } - template - inline void apply_reverse(T const& lon1_rad, T const& lat1_rad, - T const& lon2_rad, T const& lat2_rad, - T& a2) const + template + inline void apply_reverse(T1 const& lon1_rad, T1 const& lat1_rad, + T2 const& lon2_rad, T2 const& lat2_rad, + Result& a2) const { compute(lon1_rad, lat1_rad, lon2_rad, lat2_rad, @@ -85,16 +94,13 @@ private : < bool EnableAzimuth, bool EnableReverseAzimuth, - typename T + typename T1, typename T2, typename Result > - inline void compute(T const& lon1_rad, T const& lat1_rad, - T const& lon2_rad, T const& lat2_rad, - T& a1, T& a2) const + inline void compute(T1 const& lon1_rad, T1 const& lat1_rad, + T2 const& lon2_rad, T2 const& lat2_rad, + Result& a1, Result& a2) const { - typedef std::conditional_t - < - std::is_void::value, T, CalculationType - > calc_t; + typedef typename result_type::type calc_t; typedef typename FormulaPolicy::template inverse < @@ -127,14 +133,13 @@ private : namespace services { -template -struct default_strategy +template <> +struct default_strategy { typedef strategy::azimuth::geographic < strategy::andoyer, - srs::spheroid, - CalculationType + srs::spheroid > type; }; diff --git a/include/boost/geometry/strategies/geographic/disjoint_segment_box.hpp b/include/boost/geometry/strategies/geographic/disjoint_segment_box.hpp index c4b843072..2e06049aa 100644 --- a/include/boost/geometry/strategies/geographic/disjoint_segment_box.hpp +++ b/include/boost/geometry/strategies/geographic/disjoint_segment_box.hpp @@ -93,6 +93,11 @@ public: strategy::disjoint::spherical_box_box()); } + Spheroid const& model() const + { + return m_spheroid; + } + private: Spheroid m_spheroid; }; diff --git a/include/boost/geometry/strategies/geographic/distance_segment_box.hpp b/include/boost/geometry/strategies/geographic/distance_segment_box.hpp index 99b181fa2..491d4da2b 100644 --- a/include/boost/geometry/strategies/geographic/distance_segment_box.hpp +++ b/include/boost/geometry/strategies/geographic/distance_segment_box.hpp @@ -1,6 +1,6 @@ // Boost.Geometry (aka GGL, Generic Geometry Library) -// Copyright (c) 2018-2019 Oracle and/or its affiliates. +// Copyright (c) 2018-2020 Oracle and/or its affiliates. // Contributed and/or modified by Vissarion Fisikopoulos, on behalf of Oracle // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include diff --git a/include/boost/geometry/strategies/geographic/index.hpp b/include/boost/geometry/strategies/geographic/index.hpp deleted file mode 100644 index 216de31ff..000000000 --- a/include/boost/geometry/strategies/geographic/index.hpp +++ /dev/null @@ -1,216 +0,0 @@ -// Boost.Geometry Index -// -// R-tree strategies -// -// Copyright (c) 2019, 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_STRATEGIES_GEOGRAPHIC_INDEX_HPP -#define BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_INDEX_HPP - -#include -#include - -#include -#include // backward compatibility -#include -#include -#include -#include // backward compatibility -#include // backward compatibility -#include -#include - -#include - - -namespace boost { namespace geometry { namespace strategy { namespace index -{ - -template -< - typename FormulaPolicy = strategy::andoyer, - typename Spheroid = geometry::srs::spheroid, - typename CalculationType = void -> -struct geographic - : spherical -{ - typedef geographic_tag cs_tag; - - typedef geometry::strategy::envelope::geographic_segment - < - FormulaPolicy, Spheroid, CalculationType - > envelope_segment_strategy_type; - - inline envelope_segment_strategy_type get_envelope_segment_strategy() const - { - return envelope_segment_strategy_type(m_spheroid); - } - - typedef geometry::strategy::expand::geographic_segment - < - FormulaPolicy, Spheroid, CalculationType - > expand_segment_strategy_type; - - inline expand_segment_strategy_type get_expand_segment_strategy() const - { - return expand_segment_strategy_type(m_spheroid); - } - - // used in equals(Seg, Seg) but only to get_point_in_point_strategy() - typedef geometry::strategy::intersection::geographic_segments - < - FormulaPolicy, - // If index::geographic formula is derived from intersection::geographic_segments - // formula with different Order this may cause an inconsistency - strategy::default_order::value, - Spheroid, - CalculationType - > relate_segment_segment_strategy_type; - - inline relate_segment_segment_strategy_type get_relate_segment_segment_strategy() const - { - return relate_segment_segment_strategy_type(m_spheroid); - } - - typedef geometry::strategy::distance::geographic - < - FormulaPolicy, Spheroid, CalculationType - > comparable_distance_point_point_strategy_type; - - inline comparable_distance_point_point_strategy_type get_comparable_distance_point_point_strategy() const - { - return comparable_distance_point_point_strategy_type(m_spheroid); - } - - typedef geometry::strategy::distance::geographic_cross_track_point_box - < - FormulaPolicy, Spheroid, CalculationType - > comparable_distance_point_box_strategy_type; - - inline comparable_distance_point_box_strategy_type get_comparable_distance_point_box_strategy() const - { - return comparable_distance_point_box_strategy_type(m_spheroid); - } - - typedef geometry::strategy::distance::geographic_cross_track - < - FormulaPolicy, Spheroid, CalculationType - > comparable_distance_point_segment_strategy_type; - - inline comparable_distance_point_segment_strategy_type get_comparable_distance_point_segment_strategy() const - { - return comparable_distance_point_segment_strategy_type(m_spheroid); - } - - typedef geometry::strategy::distance::geographic_segment_box - < - FormulaPolicy, Spheroid, CalculationType - > comparable_distance_segment_box_strategy_type; - - inline comparable_distance_segment_box_strategy_type get_comparable_distance_segment_box_strategy() const - { - return comparable_distance_segment_box_strategy_type(m_spheroid); - } - - geographic() - : m_spheroid() - {} - - explicit geographic(Spheroid const& spheroid) - : m_spheroid(spheroid) - {} - -public: - Spheroid m_spheroid; -}; - - -namespace services -{ - -template -struct default_strategy -{ - typedef geographic<> type; -}; - - -// within and relate (MPt, Mls/MPoly) -template -struct from_strategy > -{ - typedef strategy::index::geographic type; - - static inline type get(within::geographic_winding const& strategy) - { - return type(strategy.model()); - } -}; - -// distance (MPt, MPt) -template -struct from_strategy > -{ - typedef strategy::index::geographic type; - - static inline type get(distance::geographic const& strategy) - { - return type(strategy.model()); - } -}; -template -struct from_strategy > -{ - typedef strategy::index::geographic type; - - static inline type get(distance::andoyer const& strategy) - { - return type(strategy.model()); - } -}; -template -struct from_strategy > -{ - typedef strategy::index::geographic type; - - static inline type get(distance::thomas const& strategy) - { - return type(strategy.model()); - } -}; -template -struct from_strategy > -{ - typedef strategy::index::geographic type; - - static inline type get(distance::vincenty const& strategy) - { - return type(strategy.model()); - } -}; - -// distance (MPt, Linear/Areal) -template -struct from_strategy > -{ - typedef strategy::index::geographic type; - - static inline type get(distance::geographic_cross_track const& strategy) - { - return type(strategy.model()); - } -}; - - -} // namespace services - - -}}}} // namespace boost::geometry::strategy::index - -#endif // BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_INDEX_HPP diff --git a/include/boost/geometry/strategies/geographic/intersection.hpp b/include/boost/geometry/strategies/geographic/intersection.hpp index 56edb8ea0..f157d7542 100644 --- a/include/boost/geometry/strategies/geographic/intersection.hpp +++ b/include/boost/geometry/strategies/geographic/intersection.hpp @@ -72,7 +72,7 @@ namespace strategy { namespace intersection template < typename FormulaPolicy = strategy::andoyer, - unsigned int Order = strategy::default_order::value, + std::size_t Order = strategy::default_order::value, typename Spheroid = srs::spheroid, typename CalculationType = void > @@ -247,6 +247,11 @@ struct geographic_segments : m_spheroid(spheroid) {} + Spheroid model() const + { + return m_spheroid; + } + // Relate segments a and b template < @@ -992,8 +997,7 @@ private: template static inline bool equals_point_point(Point1 const& point1, Point2 const& point2) { - return detail::equals::equals_point_point(point1, point2, - point_in_point_strategy_type()); + return strategy::within::spherical_point_point::apply(point1, point2); } private: diff --git a/include/boost/geometry/strategies/geographic/io.hpp b/include/boost/geometry/strategies/geographic/io.hpp deleted file mode 100644 index c4898ea0c..000000000 --- a/include/boost/geometry/strategies/geographic/io.hpp +++ /dev/null @@ -1,96 +0,0 @@ -// Boost.Geometry - -// Copyright (c) 2019, Oracle and/or its affiliates. - -// 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 - -#ifndef BOOST_GEOMETRY_EXTENSIONS_STRATEGIES_GEOGRAPHIC_IO_HPP -#define BOOST_GEOMETRY_EXTENSIONS_STRATEGIES_GEOGRAPHIC_IO_HPP - - -#include - -#include -#include - - -namespace boost { namespace geometry -{ - -namespace strategy { namespace io -{ - -template - < - typename FormulaPolicy = strategy::andoyer, - typename Spheroid = srs::spheroid, - typename CalculationType = void - > -struct geographic -{ - typedef strategy::point_order::geographic - < - FormulaPolicy, - Spheroid, - CalculationType - > point_order_strategy_type; - - point_order_strategy_type get_point_order_strategy() const - { - return point_order_strategy_type(m_spheroid); - } - - template - struct point_in_geometry_strategy - { - typedef strategy::within::geographic_winding - < - typename point_type::type, - typename point_type::type, - FormulaPolicy, - Spheroid, - CalculationType - > type; - }; - - template - typename point_in_geometry_strategy::type - get_point_in_geometry_strategy() const - { - typedef typename point_in_geometry_strategy - < - Geometry1, Geometry2 - >::type strategy_type; - return strategy_type(m_spheroid); - } - - geographic() - {} - - geographic(Spheroid const& spheroid) - : m_spheroid(spheroid) - {} - -private: - Spheroid m_spheroid; -}; - -namespace services -{ - -template <> -struct default_strategy -{ - typedef geographic<> type; -}; - -} // namespace services - -}} // namespace strategy::io - -}} // namespace boost::geometry - -#endif // BOOST_GEOMETRY_EXTENSIONS_STRATEGIES_GEOGRAPHIC_IO_HPP diff --git a/include/boost/geometry/strategies/geographic/side.hpp b/include/boost/geometry/strategies/geographic/side.hpp index bbcf64f82..901d4eba1 100644 --- a/include/boost/geometry/strategies/geographic/side.hpp +++ b/include/boost/geometry/strategies/geographic/side.hpp @@ -2,8 +2,8 @@ // Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. -// This file was modified by Oracle on 2014-2020. -// Modifications copyright (c) 2014-2020 Oracle and/or its affiliates. +// This file was modified by Oracle on 2014-2021. +// Modifications copyright (c) 2014-2021 Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle @@ -23,18 +23,17 @@ #include -#include -#include -#include - -#include - +//#include #include #include #include #include -//#include +#include + +#include +#include +#include namespace boost { namespace geometry { @@ -108,6 +107,13 @@ public: template inline int apply(P1 const& p1, P2 const& p2, P const& p) const { + if (equals_point_point_strategy_type::apply(p, p1) + || equals_point_point_strategy_type::apply(p, p2) + || equals_point_point_strategy_type::apply(p1, p2)) + { + return 0; + } + typedef typename promote_floating_point < typename select_calculation_type_alt diff --git a/include/boost/geometry/strategies/index.hpp b/include/boost/geometry/strategies/index.hpp deleted file mode 100644 index 3f8fddd8d..000000000 --- a/include/boost/geometry/strategies/index.hpp +++ /dev/null @@ -1,67 +0,0 @@ -// Boost.Geometry Index -// -// R-tree strategies -// -// Copyright (c) 2019-2020, 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_STRATEGIES_INDEX_HPP -#define BOOST_GEOMETRY_STRATEGIES_INDEX_HPP - - -#include -#include -#include - - -namespace boost { namespace geometry { namespace strategy { namespace index -{ - -namespace services -{ - -template -< - typename Geometry, - typename CSTag = typename geometry::cs_tag::type -> -struct default_strategy -{ - /*BOOST_GEOMETRY_STATIC_ASSERT_FALSE( - "Not implemented for this type.", - Geometry);*/ - - typedef geometry::default_strategy type; -}; - - -// TEMP -// Utility to get index strategy from other strategy -// In the final version this utility will probably replaced with some other mechanism -// The issue is cross-dependencies between strategies -template -struct from_strategy -{ - /*BOOST_GEOMETRY_STATIC_ASSERT_FALSE( - "Not implemented for this type.", - Strategy);*/ - - typedef geometry::default_strategy type; - - static inline type get(Strategy const&) - { - return type(); - } -}; - - -} // namespace services - - -}}}} // namespace boost::geometry::strategy::index - -#endif // BOOST_GEOMETRY_STRATEGIES_INDEX_HPP diff --git a/include/boost/geometry/strategies/index/cartesian.hpp b/include/boost/geometry/strategies/index/cartesian.hpp new file mode 100644 index 000000000..fe5d018e2 --- /dev/null +++ b/include/boost/geometry/strategies/index/cartesian.hpp @@ -0,0 +1,146 @@ +// Boost.Geometry + +// Copyright (c) 2020, Oracle and/or its affiliates. + +// 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 + +#ifndef BOOST_GEOMETRY_STRATEGIES_INDEX_CARTESIAN_HPP +#define BOOST_GEOMETRY_STRATEGIES_INDEX_CARTESIAN_HPP + + +// TODO: move to strategy directory +#include +#include +#include + +#include +#include + + +namespace boost { namespace geometry { namespace strategies { namespace index +{ + +template +class cartesian + : public relate::cartesian +{ +public: + template + static auto comparable_distance(Geometry1 const&, Geometry2 const&, + std::enable_if_t + < + util::is_pointlike::value + && util::is_pointlike::value + > * = nullptr) + { + //return geometry::strategy::distance::comparable::pythagoras(); + return geometry::strategy::distance::pythagoras(); + } + + template + static auto comparable_distance(Geometry1 const&, Geometry2 const&, + std::enable_if_t + < + (util::is_pointlike::value + && util::is_segment::value) + || (util::is_segment::value + && util::is_pointlike::value) + > * = nullptr) + { + return geometry::strategy::distance::projected_point + < + CalculationType, + //geometry::strategy::distance::comparable::pythagoras + geometry::strategy::distance::pythagoras + >(); + } + + template + static auto comparable_distance(Geometry1 const&, Geometry2 const&, + std::enable_if_t + < + (util::is_pointlike::value + && util::is_box::value) + || (util::is_box::value + && util::is_pointlike::value) + > * = nullptr) + { + //return geometry::strategy::distance::comparable::pythagoras_point_box(); + return geometry::strategy::distance::pythagoras_point_box(); + } + + template + static auto comparable_distance(Geometry1 const&, Geometry2 const&, + std::enable_if_t + < + (util::is_segment::value + && util::is_box::value) + || (util::is_box::value + && util::is_segment::value) + > * = nullptr) + { + return geometry::strategy::distance::cartesian_segment_box + < + CalculationType, + //geometry::strategy::distance::comparable::pythagoras + geometry::strategy::distance::pythagoras + >(); + } + + template + static auto comparable_distance(Geometry1 const&, Geometry2 const&, + std::enable_if_t + < + util::is_segment::value + && util::is_segment::value + > * = nullptr) + { + return strategy::distance::projected_point + < + CalculationType, + //strategy::distance::comparable::pythagoras + strategy::distance::pythagoras + >(); + } +}; + + +namespace services +{ + +template +struct default_strategy +{ + using type = strategies::index::cartesian<>; +}; + + +// TEMP - needed in distance until umbrella strategies are supported +template +struct strategy_converter> +{ + static auto get(strategy::distance::projected_point const& ) + { + return strategies::index::cartesian(); + } +}; +// TEMP - needed in distance until umbrella strategies are supported +template +struct strategy_converter> +{ + static auto get(strategy::distance::comparable::pythagoras const&) + { + return strategies::index::cartesian(); + } +}; + + +} // namespace services + + +}}}} // namespace boost::geometry::strategy::index + +#endif // BOOST_GEOMETRY_STRATEGIES_INDEX_CARTESIAN_HPP diff --git a/include/boost/geometry/strategies/index/geographic.hpp b/include/boost/geometry/strategies/index/geographic.hpp new file mode 100644 index 000000000..8723eaf12 --- /dev/null +++ b/include/boost/geometry/strategies/index/geographic.hpp @@ -0,0 +1,279 @@ +// Boost.Geometry + +// Copyright (c) 2020, Oracle and/or its affiliates. + +// 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 + +#ifndef BOOST_GEOMETRY_STRATEGIES_INDEX_GEOGRAPHIC_HPP +#define BOOST_GEOMETRY_STRATEGIES_INDEX_GEOGRAPHIC_HPP + + +#include +#include + +// TEMP - move to strategy +#include +#include +#include +#include +#include +#include +#include +#include + + +namespace boost { namespace geometry { namespace strategies { namespace index +{ + +template +< + typename FormulaPolicy = strategy::andoyer, + // TODO: Is SeriesOrder argument needed here? + std::size_t SeriesOrder = strategy::default_order::value, + typename Spheroid = srs::spheroid, + typename CalculationType = void +> +class geographic + : public relate::geographic +{ + typedef relate::geographic base_t; + +public: + geographic() + : base_t() + {} + + explicit geographic(Spheroid const& spheroid) + : base_t(spheroid) + {} + + template + auto comparable_distance(Geometry1 const&, Geometry2 const&, + std::enable_if_t + < + util::is_pointlike::value + && util::is_pointlike::value + > * = nullptr) const + { + return geometry::strategy::distance::geographic + < + FormulaPolicy, Spheroid, CalculationType + >(base_t::m_spheroid); + } + + template + auto comparable_distance(Geometry1 const&, Geometry2 const&, + std::enable_if_t + < + (util::is_pointlike::value + && util::is_segment::value) + || (util::is_segment::value + && util::is_pointlike::value) + > * = nullptr) const + { + return geometry::strategy::distance::geographic_cross_track + < + FormulaPolicy, Spheroid, CalculationType + >(base_t::m_spheroid); + } + + template + auto comparable_distance(Geometry1 const&, Geometry2 const&, + std::enable_if_t + < + (util::is_pointlike::value + && util::is_box::value) + || (util::is_box::value + && util::is_pointlike::value) + > * = nullptr) const + { + return geometry::strategy::distance::geographic_cross_track_point_box + < + FormulaPolicy, Spheroid, CalculationType + >(base_t::m_spheroid); + } + + template + auto comparable_distance(Geometry1 const&, Geometry2 const&, + std::enable_if_t + < + (util::is_segment::value + && util::is_box::value) + || (util::is_box::value + && util::is_segment::value) + > * = nullptr) const + { + return geometry::strategy::distance::geographic_segment_box + < + FormulaPolicy, Spheroid, CalculationType + >(base_t::m_spheroid); + } + + template + auto comparable_distance(Geometry1 const&, Geometry2 const&, + std::enable_if_t + < + util::is_segment::value + && util::is_segment::value + > * = nullptr) const + { + return geometry::strategy::distance::geographic_cross_track + < + FormulaPolicy, Spheroid, CalculationType + >(base_t::m_spheroid); + } +}; + + +namespace services +{ + +template +struct default_strategy +{ + using type = strategies::index::geographic<>; +}; + +// TEMP - needed in distance until umbrella strategies are supported +template +struct strategy_converter> +{ + static auto get(strategy::distance::geographic_cross_track const& strategy) + { + return strategies::index::geographic + < + FormulaPolicy, + strategy::default_order::value, + Spheroid, + CalculationType + >(strategy.model()); + } +}; +// TEMP - needed in distance until umbrella strategies are supported +template +struct strategy_converter> +{ + typedef strategies::index::geographic + < + FormulaPolicy, + strategy::default_order::value, + Spheroid, + CalculationType + > base_strategy; + + struct altered_strategy : base_strategy + { + explicit altered_strategy(Spheroid const& spheroid) + : base_strategy(spheroid) + {} + + // It seems that this declaration is needed because comparable_distance + // is not static function. + using base_strategy::comparable_distance; + + template + auto comparable_distance(Geometry1 const&, Geometry2 const&, + std::enable_if_t + < + (util::is_pointlike::value + && util::is_segment::value) + || (util::is_segment::value + && util::is_pointlike::value) + > * = nullptr) const + { + return geometry::strategy::distance::detail::geographic_cross_track + < + FormulaPolicy, Spheroid, CalculationType, Bisection, EnableClosestPoint + >(base_strategy::m_spheroid); + } + + template + auto comparable_distance(Geometry1 const&, Geometry2 const&, + std::enable_if_t + < + util::is_segment::value + && util::is_segment::value + > * = nullptr) const + { + return geometry::strategy::distance::detail::geographic_cross_track + < + FormulaPolicy, Spheroid, CalculationType, Bisection, EnableClosestPoint + >(base_strategy::m_spheroid); + } + }; + + static auto get(strategy::distance::detail::geographic_cross_track const& strategy) + { + return altered_strategy(strategy.model()); + } +}; +// TEMP - needed in distance until umbrella strategies are supported +template +struct strategy_converter> +{ + static auto get(strategy::distance::geographic const& strategy) + { + return strategies::index::geographic + < + FormulaPolicy, + strategy::default_order::value, + Spheroid, + CalculationType + >(strategy.model()); + } +}; +// TEMP - needed in distance until umbrella strategies are supported +template +struct strategy_converter> +{ + static auto get(strategy::distance::andoyer const& strategy) + { + return strategies::index::geographic + < + strategy::andoyer, + strategy::default_order::value, + Spheroid, + CalculationType + >(strategy.model()); + } +}; +// TEMP - needed in distance until umbrella strategies are supported +template +struct strategy_converter> +{ + static auto get(strategy::distance::thomas const& strategy) + { + return strategies::index::geographic + < + strategy::thomas, + strategy::default_order::value, + Spheroid, + CalculationType + >(strategy.model()); + } +}; +// TEMP - needed in distance until umbrella strategies are supported +template +struct strategy_converter> +{ + static auto get(strategy::distance::vincenty const& strategy) + { + return strategies::index::geographic + < + strategy::vincenty, + strategy::default_order::value, + Spheroid, + CalculationType + >(strategy.model()); + } +}; + +} // namespace services + + +}}}} // namespace boost::geometry::strategy::index + +#endif // BOOST_GEOMETRY_STRATEGIES_INDEX_GEOGRAPHIC_HPP diff --git a/include/boost/geometry/strategies/index/services.hpp b/include/boost/geometry/strategies/index/services.hpp new file mode 100644 index 000000000..f256a3ac3 --- /dev/null +++ b/include/boost/geometry/strategies/index/services.hpp @@ -0,0 +1,50 @@ +// Boost.Geometry + +// Copyright (c) 2020, Oracle and/or its affiliates. + +// 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 + +#ifndef BOOST_GEOMETRY_STRATEGIES_INDEX_SERVICES_HPP +#define BOOST_GEOMETRY_STRATEGIES_INDEX_SERVICES_HPP + + +#include +#include + + +namespace boost { namespace geometry +{ + +namespace strategies { namespace index { namespace services +{ + +template +< + typename Geometry, + typename CSTag = typename geometry::cs_tag::type +> +struct default_strategy +{ + BOOST_GEOMETRY_STATIC_ASSERT_FALSE( + "Not implemented for this coordinate system.", + Geometry, CSTag); +}; + +template +struct strategy_converter +{ + BOOST_GEOMETRY_STATIC_ASSERT_FALSE( + "Not implemented for this Strategy.", + Strategy); +}; + + +}}} // namespace strategy::index::services + + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_STRATEGIES_INDEX_SERVICES_HPP diff --git a/include/boost/geometry/strategies/index/spherical.hpp b/include/boost/geometry/strategies/index/spherical.hpp new file mode 100644 index 000000000..5ffd6ea24 --- /dev/null +++ b/include/boost/geometry/strategies/index/spherical.hpp @@ -0,0 +1,199 @@ +// Boost.Geometry + +// Copyright (c) 2020, Oracle and/or its affiliates. + +// 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 + +#ifndef BOOST_GEOMETRY_STRATEGIES_INDEX_SPHERICAL_HPP +#define BOOST_GEOMETRY_STRATEGIES_INDEX_SPHERICAL_HPP + + +// TEMP - move to strategy +#include +#include +#include +#include + +#include +#include + + +namespace boost { namespace geometry +{ + +namespace strategies { namespace index +{ + +#ifndef DOXYGEN_NO_DETAIL +namespace detail +{ + +template +class spherical + : public strategies::relate::detail::spherical +{ + using base_t = strategies::relate::detail::spherical; + +public: + template + auto comparable_distance(Geometry1 const&, Geometry2 const&, + std::enable_if_t + < + util::is_pointlike::value + && util::is_pointlike::value + > * = nullptr) const + { + //return geometry::strategy::distance::comparable::haversine + return geometry::strategy::distance::haversine + < + typename base_t::radius_type, CalculationType + >(base_t::radius()); + } + + template + auto comparable_distance(Geometry1 const&, Geometry2 const&, + std::enable_if_t + < + (util::is_pointlike::value + && util::is_segment::value) + || (util::is_segment::value + && util::is_pointlike::value) + > * = nullptr) const + { + //return geometry::strategy::distance::comparable::cross_track + return geometry::strategy::distance::cross_track + < + CalculationType, + //geometry::strategy::distance::comparable::haversine + geometry::strategy::distance::haversine + < + typename base_t::radius_type, CalculationType + > + >(base_t::radius()); + } + + template + auto comparable_distance(Geometry1 const&, Geometry2 const&, + std::enable_if_t + < + (util::is_pointlike::value + && util::is_box::value) + || (util::is_box::value + && util::is_pointlike::value) + > * = nullptr) const + { + //return geometry::strategy::distance::comparable::cross_track_point_box + return geometry::strategy::distance::cross_track_point_box + < + CalculationType, + //geometry::strategy::distance::comparable::haversine + geometry::strategy::distance::haversine + < + typename base_t::radius_type, CalculationType + > + >(base_t::radius()); + } + + template + auto comparable_distance(Geometry1 const&, Geometry2 const&, + std::enable_if_t + < + (util::is_segment::value + && util::is_box::value) + || (util::is_box::value + && util::is_segment::value) + > * = nullptr) const + { + return geometry::strategy::distance::spherical_segment_box + < + CalculationType, + //geometry::strategy::distance::comparable::haversine + geometry::strategy::distance::haversine + < + typename base_t::radius_type, CalculationType + > + // TODO: + >(/*base_t::radius()*/); + } + + template + auto comparable_distance(Geometry1 const&, Geometry2 const&, + std::enable_if_t + < + util::is_segment::value + && util::is_segment::value + > * = nullptr) const + { + //return geometry::strategy::distance::comparable::cross_track + return geometry::strategy::distance::cross_track + < + CalculationType, + //geometry::strategy::distance::comparable::haversine + geometry::strategy::distance::haversine + < + typename base_t::radius_type, CalculationType + > + >(base_t::radius()); + } +}; + + +} // namespace detail +#endif // DOXYGEN_NO_DETAIL + + +template +class spherical + : public strategies::index::detail::spherical +{}; + + +namespace services +{ + +template +struct default_strategy +{ + using type = strategies::index::spherical<>; +}; + +template +struct default_strategy +{ + using type = strategies::index::spherical<>; +}; + +template +struct default_strategy +{ + using type = strategies::index::spherical<>; +}; + +// TEMP - needed in distance until umbrella strategies are supported +template +struct strategy_converter> +{ + static auto get(strategy::distance::comparable::cross_track const& ) + { + return strategies::index::spherical(); + } +}; +// TEMP - needed in distance until umbrella strategies are supported +template +struct strategy_converter> +{ + static auto get(strategy::distance::comparable::haversine const&) + { + return strategies::index::spherical(); + } +}; + +} // namespace services + + +}}}} // namespace boost::geometry::strategy::index + +#endif // BOOST_GEOMETRY_STRATEGIES_INDEX_SPHERICAL_HPP diff --git a/include/boost/geometry/strategies/io/cartesian.hpp b/include/boost/geometry/strategies/io/cartesian.hpp new file mode 100644 index 000000000..cd726a425 --- /dev/null +++ b/include/boost/geometry/strategies/io/cartesian.hpp @@ -0,0 +1,77 @@ +// Boost.Geometry + +// Copyright (c) 2019-2020, Oracle and/or its affiliates. + +// 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 + +#ifndef BOOST_GEOMETRY_STRATEGIES_IO_CARTESIAN_HPP +#define BOOST_GEOMETRY_STRATEGIES_IO_CARTESIAN_HPP + + +#include +#include + +#include +#include +#include + + +namespace boost { namespace geometry +{ + +namespace strategies { namespace io +{ + +template +class cartesian + : public strategies::detail::cartesian_base +{ +public: + static auto point_order() + { + return strategy::point_order::cartesian(); + } + + template + static auto relate(Geometry1 const&, Geometry2 const&, + std::enable_if_t + < + util::is_pointlike::value + && util::is_pointlike::value + > * = nullptr) + { + return strategy::within::cartesian_point_point(); + } + + template + static auto relate(Geometry1 const&, Geometry2 const&, + std::enable_if_t + < + util::is_pointlike::value + && ( util::is_linear::value + || util::is_polygonal::value ) + > * = nullptr) + { + return strategy::within::cartesian_winding(); + } +}; + +namespace services +{ + +template +struct default_strategy +{ + typedef cartesian<> type; +}; + +} // namespace services + +}} // namespace strategies::io + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_STRATEGIES_IO_CARTESIAN_HPP diff --git a/include/boost/geometry/strategies/io/geographic.hpp b/include/boost/geometry/strategies/io/geographic.hpp new file mode 100644 index 000000000..ed17c9d4a --- /dev/null +++ b/include/boost/geometry/strategies/io/geographic.hpp @@ -0,0 +1,99 @@ +// Boost.Geometry + +// Copyright (c) 2019-2020, Oracle and/or its affiliates. + +// 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 + +#ifndef BOOST_GEOMETRY_STRATEGIES_IO_GEOGRAPHIC_HPP +#define BOOST_GEOMETRY_STRATEGIES_IO_GEOGRAPHIC_HPP + + +#include +#include + +#include +#include +#include + + +namespace boost { namespace geometry +{ + +namespace strategies { namespace io +{ + +template + < + typename FormulaPolicy = strategy::andoyer, + typename Spheroid = srs::spheroid, + typename CalculationType = void + > +class geographic + : public strategies::detail::geographic_base +{ + using base_t = strategies::detail::geographic_base; + +public: + geographic() + : base_t() + {} + + explicit geographic(Spheroid const& spheroid) + : base_t(spheroid) + {} + + auto point_order() const + { + return strategy::point_order::geographic + < + FormulaPolicy, Spheroid, CalculationType + >(base_t::m_spheroid); + } + + template + static auto relate(Geometry1 const&, Geometry2 const&, + std::enable_if_t + < + util::is_pointlike::value + && util::is_pointlike::value + > * = nullptr) + { + return strategy::within::spherical_point_point(); + } + + template + auto relate(Geometry1 const&, Geometry2 const&, + std::enable_if_t + < + util::is_pointlike::value + && ( util::is_linear::value + || util::is_polygonal::value ) + > * = nullptr) const + { + return strategy::within::geographic_winding + < + void, void, + FormulaPolicy, Spheroid, CalculationType + >(base_t::m_spheroid); + } +}; + +namespace services +{ + +template +struct default_strategy +{ + typedef geographic<> type; +}; + +} // namespace services + +}} // namespace strategies::io + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_STRATEGIES_IO_GEOGRAPHIC_HPP diff --git a/include/boost/geometry/strategies/io.hpp b/include/boost/geometry/strategies/io/services.hpp similarity index 59% rename from include/boost/geometry/strategies/io.hpp rename to include/boost/geometry/strategies/io/services.hpp index c4f956e91..2577f06aa 100644 --- a/include/boost/geometry/strategies/io.hpp +++ b/include/boost/geometry/strategies/io/services.hpp @@ -7,34 +7,39 @@ // Licensed under the Boost Software License version 1.0. // http://www.boost.org/users/license.html -#ifndef BOOST_GEOMETRY_EXTENSIONS_STRATEGIES_IO_HPP -#define BOOST_GEOMETRY_EXTENSIONS_STRATEGIES_IO_HPP +#ifndef BOOST_GEOMETRY_STRATEGIES_IO_SERVICES_HPP +#define BOOST_GEOMETRY_STRATEGIES_IO_SERVICES_HPP +#include #include namespace boost { namespace geometry { -namespace strategy { namespace io +namespace strategies { namespace io { namespace services { -template +template +< + typename Geometry, + typename CSTag = typename geometry::cs_tag::type +> struct default_strategy { BOOST_GEOMETRY_STATIC_ASSERT_FALSE( "Not implemented for this coordinate system.", - CSTag); + Geometry, CSTag); }; } // namespace services -}} // namespace strategy::io +}} // namespace strategies::io }} // namespace boost::geometry -#endif // BOOST_GEOMETRY_EXTENSIONS_STRATEGIES_IO_HPP +#endif // BOOST_GEOMETRY_STRATEGIES_IO_SERVICES_HPP diff --git a/include/boost/geometry/strategies/io/spherical.hpp b/include/boost/geometry/strategies/io/spherical.hpp new file mode 100644 index 000000000..c74515a99 --- /dev/null +++ b/include/boost/geometry/strategies/io/spherical.hpp @@ -0,0 +1,89 @@ +// Boost.Geometry + +// Copyright (c) 2019-2020, Oracle and/or its affiliates. + +// 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 + +#ifndef BOOST_GEOMETRY_STRATEGIES_IO_SPHERICAL_HPP +#define BOOST_GEOMETRY_STRATEGIES_IO_SPHERICAL_HPP + + +#include +#include + +#include +#include +#include + + +namespace boost { namespace geometry +{ + +namespace strategies { namespace io +{ + +template +class spherical + : public strategies::detail::spherical_base +{ +public: + static auto point_order() + { + return strategy::point_order::spherical(); + } + + template + static auto relate(Geometry1 const&, Geometry2 const&, + std::enable_if_t + < + util::is_pointlike::value + && util::is_pointlike::value + > * = nullptr) + { + return strategy::within::spherical_point_point(); + } + + template + static auto relate(Geometry1 const&, Geometry2 const&, + std::enable_if_t + < + util::is_pointlike::value + && ( util::is_linear::value + || util::is_polygonal::value ) + > * = nullptr) + { + return strategy::within::spherical_winding(); + } +}; + +namespace services +{ + +template +struct default_strategy +{ + typedef spherical<> type; +}; + +template +struct default_strategy +{ + typedef spherical<> type; +}; + +template +struct default_strategy +{ + typedef spherical<> type; +}; + +} // namespace services + +}} // namespace strategies::io + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_STRATEGIES_IO_SPHERICAL_HPP diff --git a/include/boost/geometry/strategies/relate.hpp b/include/boost/geometry/strategies/relate.hpp index 481fb38a1..7d388eb51 100644 --- a/include/boost/geometry/strategies/relate.hpp +++ b/include/boost/geometry/strategies/relate.hpp @@ -1,175 +1,21 @@ // Boost.Geometry -// Copyright (c) 2017-2020, Oracle and/or its affiliates. +// Copyright (c) 2020, 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) +// Licensed under the Boost Software License version 1.0. +// http://www.boost.org/users/license.html #ifndef BOOST_GEOMETRY_STRATEGIES_RELATE_HPP #define BOOST_GEOMETRY_STRATEGIES_RELATE_HPP -#include - -#include -#include -#include -#include - -#include -#include -#include +#include +BOOST_PRAGMA_MESSAGE("This include file is deprecated and will be removed in the future.") -namespace boost { namespace geometry -{ - -namespace strategy -{ - -namespace point_in_geometry -{ - -#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS -namespace services -{ - -template -< - typename Point, - typename Geometry, - typename Tag1 = typename tag::type, - typename Tag2 = typename tag::type -> -struct default_strategy - : strategy::within::services::default_strategy - < - Point, - Geometry - > -{ - typedef typename default_strategy::type within_strategy_type; - - typedef typename strategy::covered_by::services::default_strategy - < - Point, - Geometry - >::type covered_by_strategy_type; - - static const bool same_strategies = std::is_same::value; - BOOST_GEOMETRY_STATIC_ASSERT(same_strategies, - "Default within and covered_by strategies not compatible.", - within_strategy_type, covered_by_strategy_type); -}; - -template -struct default_strategy - : strategy::within::services::default_strategy -{}; - -template -struct default_strategy - : strategy::within::services::default_strategy -{}; - - -} // namespace services -#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS - - -} // namespace point_in_geometry - -namespace relate -{ - -#ifndef DOXYGEN_NO_DETAIL -namespace detail -{ - -template -struct default_intersection_strategy - : strategy::intersection::services::default_strategy - < - typename cs_tag::type - > -{}; - -template -struct default_point_in_geometry_strategy - : point_in_geometry::services::default_strategy - < - typename point_type::type, - Geometry - > -{}; - -} // namespace detail -#endif // DOXYGEN_NO_DETAIL - -#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS -namespace services -{ - -template -< - typename Geometry1, - typename Geometry2, - int TopDim1 = geometry::topological_dimension::value, - int TopDim2 = geometry::topological_dimension::value -> -struct default_strategy -{ - BOOST_GEOMETRY_STATIC_ASSERT_FALSE( - "Not implemented for these types.", - Geometry1, Geometry2); -}; - -template -struct default_strategy - : detail::default_point_in_geometry_strategy -{}; - -template -struct default_strategy - : detail::default_point_in_geometry_strategy -{}; - -template -struct default_strategy - : detail::default_point_in_geometry_strategy -{}; - -template -struct default_strategy - : detail::default_intersection_strategy -{}; - -template -struct default_strategy - : detail::default_intersection_strategy -{}; - -template -struct default_strategy - : detail::default_intersection_strategy -{}; - -template -struct default_strategy - : detail::default_intersection_strategy -{}; - -} // namespace services -#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS - -} // namespace relate - -} // namespace strategy - - -}} // namespace boost::geometry +#include #endif // BOOST_GEOMETRY_STRATEGIES_RELATE_HPP diff --git a/include/boost/geometry/strategies/relate/cartesian.hpp b/include/boost/geometry/strategies/relate/cartesian.hpp new file mode 100644 index 000000000..16c6853a3 --- /dev/null +++ b/include/boost/geometry/strategies/relate/cartesian.hpp @@ -0,0 +1,382 @@ +// Boost.Geometry + +// Copyright (c) 2020, Oracle and/or its affiliates. + +// 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 + +#ifndef BOOST_GEOMETRY_STRATEGIES_RELATE_CARTESIAN_HPP +#define BOOST_GEOMETRY_STRATEGIES_RELATE_CARTESIAN_HPP + + +// TEMP - move to strategy +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +#include + + +namespace boost { namespace geometry +{ + +namespace strategies { namespace relate +{ + +template +class cartesian + : public strategies::envelope::cartesian +{ +public: + //area + + template + static auto area(Geometry const&) + { + return strategy::area::cartesian(); + } + + // covered_by + + template + static auto covered_by(Geometry1 const&, Geometry2 const&, + std::enable_if_t + < + util::is_pointlike::value + && util::is_box::value + > * = nullptr) + { + return strategy::covered_by::cartesian_point_box(); + } + + template + static auto covered_by(Geometry1 const&, Geometry2 const&, + std::enable_if_t + < + util::is_box::value + && util::is_box::value + > * = nullptr) + { + return strategy::covered_by::cartesian_box_box(); + } + + // disjoint + + template + static auto disjoint(Geometry1 const&, Geometry2 const&, + std::enable_if_t + < + util::is_box::value + && util::is_box::value + > * = nullptr) + { + return strategy::disjoint::cartesian_box_box(); + } + + template + static auto disjoint(Geometry1 const&, Geometry2 const&, + std::enable_if_t + < + util::is_segment::value + && util::is_box::value + > * = nullptr) + { + // NOTE: Inconsistent name. + return strategy::disjoint::segment_box(); + } + + // relate + + template + static auto relate(Geometry1 const&, Geometry2 const&, + std::enable_if_t + < + util::is_pointlike::value + && util::is_pointlike::value + > * = nullptr) + { + return strategy::within::cartesian_point_point(); + } + + template + static auto relate(Geometry1 const&, Geometry2 const&, + std::enable_if_t + < + util::is_pointlike::value + && ( util::is_linear::value + || util::is_polygonal::value ) + > * = nullptr) + { + return strategy::within::cartesian_winding(); + } + + // The problem is that this strategy is often used with non-geometry ranges. + // So dispatching only by geometry categories is impossible. + // In the past it was taking two segments, now it takes 3-point sub-ranges. + // So dispatching by segments is impossible. + // It could be dispatched by (linear || polygonal || non-geometry point range). + // For now implement as 0-parameter, special case relate. + + //template + static auto relate(/*Geometry1 const&, Geometry2 const&, + std::enable_if_t + < + ( util::is_linear::value + || util::is_polygonal::value ) + && ( util::is_linear::value + || util::is_polygonal::value ) + > * = nullptr*/) + { + return strategy::intersection::cartesian_segments(); + } + + // side + + static auto side() + { + return strategy::side::side_by_triangle(); + } + + // within + + template + static auto within(Geometry1 const&, Geometry2 const&, + std::enable_if_t + < + util::is_pointlike::value + && util::is_box::value + > * = nullptr) + { + return strategy::within::cartesian_point_box(); + } + + template + static auto within(Geometry1 const&, Geometry2 const&, + std::enable_if_t + < + util::is_box::value + && util::is_box::value + > * = nullptr) + { + return strategy::within::cartesian_box_box(); + } +}; + + +namespace services +{ + +template +struct default_strategy +{ + using type = strategies::relate::cartesian<>; +}; + + +template <> +struct strategy_converter +{ + static auto get(strategy::within::cartesian_point_point const& ) + { + return strategies::relate::cartesian<>(); + } +}; + +template <> +struct strategy_converter +{ + static auto get(strategy::within::cartesian_point_box const&) + { + return strategies::relate::cartesian<>(); + } +}; + +template <> +struct strategy_converter +{ + static auto get(strategy::covered_by::cartesian_point_box const&) + { + return strategies::relate::cartesian<>(); + } +}; + +template <> +struct strategy_converter +{ + static auto get(strategy::covered_by::cartesian_box_box const&) + { + return strategies::relate::cartesian<>(); + } +}; + +template <> +struct strategy_converter +{ + static auto get(strategy::disjoint::cartesian_box_box const&) + { + return strategies::relate::cartesian<>(); + } +}; + +template <> +struct strategy_converter +{ + static auto get(strategy::disjoint::segment_box const&) + { + return strategies::relate::cartesian<>(); + } +}; + +template <> +struct strategy_converter +{ + static auto get(strategy::within::cartesian_box_box const&) + { + return strategies::relate::cartesian<>(); + } +}; + +template +struct strategy_converter> +{ + static auto get(strategy::within::cartesian_winding const& ) + { + return strategies::relate::cartesian(); + } +}; + +template +struct strategy_converter> +{ + static auto get(strategy::intersection::cartesian_segments const& ) + { + return strategies::relate::cartesian(); + } +}; + +template +struct strategy_converter> +{ + struct altered_strategy + : strategies::relate::cartesian + { + template + static auto covered_by(Geometry1 const&, Geometry2 const&, + std::enable_if_t + < + util::is_pointlike::value + && util::is_box::value + > * = nullptr) + { + return strategy::covered_by::cartesian_point_box_by_side(); + } + + template + static auto within(Geometry1 const&, Geometry2 const&, + std::enable_if_t + < + util::is_pointlike::value + && util::is_box::value + > * = nullptr) + { + return strategy::within::cartesian_point_box_by_side(); + } + }; + + static auto get(strategy::covered_by::cartesian_point_box_by_side const&) + { + return altered_strategy(); + } + + static auto get(strategy::within::cartesian_point_box_by_side const&) + { + return altered_strategy(); + } +}; + +template +struct strategy_converter> + : strategy_converter> +{}; + +template +struct strategy_converter> +{ + struct altered_strategy + : strategies::relate::cartesian + { + template + static auto relate(Geometry1 const&, Geometry2 const&, + std::enable_if_t + < + util::is_pointlike::value + && ( util::is_linear::value + || util::is_polygonal::value ) + > * = nullptr) + { + return strategy::within::franklin(); + } + }; + + static auto get(strategy::within::franklin const&) + { + return altered_strategy(); + } +}; + +template +struct strategy_converter> +{ + struct altered_strategy + : strategies::relate::cartesian + { + template + static auto relate(Geometry1 const&, Geometry2 const&, + std::enable_if_t + < + util::is_pointlike::value + && ( util::is_linear::value + || util::is_polygonal::value ) + > * = nullptr) + { + return strategy::within::crossings_multiply(); + } + }; + + static auto get(strategy::within::crossings_multiply const&) + { + return altered_strategy(); + } +}; + +// TEMP used in distance segment/box +template +struct strategy_converter> +{ + static auto get(strategy::side::side_by_triangle const&) + { + return strategies::relate::cartesian(); + } +}; + + +} // namespace services + +}} // namespace strategies::relate + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_STRATEGIES_RELATE_CARTESIAN_HPP diff --git a/include/boost/geometry/strategies/relate/geographic.hpp b/include/boost/geometry/strategies/relate/geographic.hpp new file mode 100644 index 000000000..4c9f81d1e --- /dev/null +++ b/include/boost/geometry/strategies/relate/geographic.hpp @@ -0,0 +1,344 @@ +// Boost.Geometry + +// Copyright (c) 2020, Oracle and/or its affiliates. + +// 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 + +#ifndef BOOST_GEOMETRY_STRATEGIES_RELATE_GEOGRAPHIC_HPP +#define BOOST_GEOMETRY_STRATEGIES_RELATE_GEOGRAPHIC_HPP + + +// TEMP - move to strategy +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +#include + + +namespace boost { namespace geometry +{ + +namespace strategies { namespace relate +{ + +template +< + typename FormulaPolicy = strategy::andoyer, + // TODO: Is SeriesOrder argument needed here? + std::size_t SeriesOrder = strategy::default_order::value, + typename Spheroid = srs::spheroid, + typename CalculationType = void +> +class geographic + : public strategies::envelope::geographic +{ + using base_t = strategies::envelope::geographic; + +public: + geographic() + : base_t() + {} + + explicit geographic(Spheroid const& spheroid) + : base_t(spheroid) + {} + + // area + + template + auto area(Geometry const&) const + { + return strategy::area::geographic + < + FormulaPolicy, SeriesOrder, Spheroid, CalculationType + >(base_t::m_spheroid); + } + + // covered_by + + template + static auto covered_by(Geometry1 const&, Geometry2 const&, + std::enable_if_t + < + util::is_pointlike::value + && util::is_box::value + > * = nullptr) + { + return strategy::covered_by::spherical_point_box(); + } + + template + static auto covered_by(Geometry1 const&, Geometry2 const&, + std::enable_if_t + < + util::is_box::value + && util::is_box::value + > * = nullptr) + { + return strategy::covered_by::spherical_box_box(); + } + + // disjoint + + template + static auto disjoint(Geometry1 const&, Geometry2 const&, + std::enable_if_t + < + util::is_box::value + && util::is_box::value + > * = nullptr) + { + return strategy::disjoint::spherical_box_box(); + } + + template + auto disjoint(Geometry1 const&, Geometry2 const&, + std::enable_if_t + < + util::is_segment::value + && util::is_box::value + > * = nullptr) const + { + // NOTE: Inconsistent name + // The only disjoint(Seg, Box) strategy that takes CalculationType. + return strategy::disjoint::segment_box_geographic + < + FormulaPolicy, Spheroid, CalculationType + >(base_t::m_spheroid); + } + + // relate + + template + static auto relate(Geometry1 const&, Geometry2 const&, + std::enable_if_t + < + util::is_pointlike::value + && util::is_pointlike::value + > * = nullptr) + { + return strategy::within::spherical_point_point(); + } + + template + auto relate(Geometry1 const&, Geometry2 const&, + std::enable_if_t + < + util::is_pointlike::value + && ( util::is_linear::value + || util::is_polygonal::value ) + > * = nullptr) const + { + return strategy::within::geographic_winding + < + void, void, FormulaPolicy, Spheroid, CalculationType + >(base_t::m_spheroid); + } + + //template + auto relate(/*Geometry1 const&, Geometry2 const&, + std::enable_if_t + < + ( util::is_linear::value + || util::is_polygonal::value ) + && ( util::is_linear::value + || util::is_polygonal::value ) + > * = nullptr*/) const + { + return strategy::intersection::geographic_segments + < + FormulaPolicy, SeriesOrder, Spheroid, CalculationType + >(base_t::m_spheroid); + } + + // side + + auto side() const + { + return strategy::side::geographic + < + FormulaPolicy, Spheroid, CalculationType + >(base_t::m_spheroid); + } + + // within + + template + static auto within(Geometry1 const&, Geometry2 const&, + std::enable_if_t + < + util::is_pointlike::value + && util::is_box::value + > * = nullptr) + { + return strategy::within::spherical_point_box(); + } + + template + static auto within(Geometry1 const&, Geometry2 const&, + std::enable_if_t + < + util::is_box::value + && util::is_box::value + > * = nullptr) + { + return strategy::within::spherical_box_box(); + } +}; + + +namespace services +{ + +template +struct default_strategy +{ + using type = strategies::relate::geographic<>; +}; + + +template +struct strategy_converter> +{ + static auto get(strategy::disjoint::segment_box_geographic const& s) + { + return strategies::relate::geographic + < + FormulaPolicy, + strategy::default_order::value, + Spheroid, + CalculationType + >(s.model()); + } +}; + +template +struct strategy_converter> +{ + static auto get(strategy::within::geographic_winding const& s) + { + return strategies::relate::geographic + < + FormulaPolicy, + strategy::default_order::value, + Spheroid, + CalculationType + >(s.model()); + } +}; + +template +struct strategy_converter> +{ + static auto get(strategy::intersection::geographic_segments const& s) + { + return strategies::relate::geographic + < + FormulaPolicy, SeriesOrder, Spheroid, CalculationType + >(s.model()); + } +}; + +template +struct strategy_converter> +{ + struct altered_strategy + : strategies::relate::geographic + < + FormulaPolicy, + strategy::default_order::value, + Spheroid, + CalculationType + > + { + altered_strategy(Spheroid const& spheroid) + : strategies::relate::geographic + < + FormulaPolicy, + strategy::default_order::value, + Spheroid, + CalculationType + >(spheroid) + {} + + template + auto covered_by(Geometry1 const&, Geometry2 const&, + std::enable_if_t + < + util::is_pointlike::value + && util::is_box::value + > * = nullptr) const + { + return strategy::covered_by::geographic_point_box_by_side + < + FormulaPolicy, Spheroid, CalculationType + >(this->model()); + } + + template + auto within(Geometry1 const&, Geometry2 const&, + std::enable_if_t + < + util::is_pointlike::value + && util::is_box::value + > * = nullptr) const + { + return strategy::within::geographic_point_box_by_side + < + FormulaPolicy, Spheroid, CalculationType + >(this->model()); + } + }; + + static auto get(strategy::covered_by::geographic_point_box_by_side const& s) + { + return altered_strategy(s.model()); + } + + static auto get(strategy::within::geographic_point_box_by_side const& s) + { + return altered_strategy(s.model()); + } +}; + +template +struct strategy_converter> + : strategy_converter> +{}; + +// TEMP used in distance segment/box +template +struct strategy_converter> +{ + static auto get(strategy::side::geographic const& s) + { + return strategies::relate::geographic + < + FormulaPolicy, + strategy::default_order::value, + Spheroid, + CalculationType + >(s.model()); + } +}; + + +} // namespace services + +}} // namespace strategies::relate + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_STRATEGIES_RELATE_GEOGRAPHIC_HPP diff --git a/include/boost/geometry/strategies/relate/services.hpp b/include/boost/geometry/strategies/relate/services.hpp new file mode 100644 index 000000000..cf9f7c97d --- /dev/null +++ b/include/boost/geometry/strategies/relate/services.hpp @@ -0,0 +1,57 @@ +// Boost.Geometry + +// Copyright (c) 2020, Oracle and/or its affiliates. + +// 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 + +#ifndef BOOST_GEOMETRY_STRATEGIES_RELATE_SERVICES_HPP +#define BOOST_GEOMETRY_STRATEGIES_RELATE_SERVICES_HPP + + +#include +#include + + +namespace boost { namespace geometry +{ + + +namespace strategies { namespace relate { + +namespace services +{ + +template +< + typename Geometry1, + typename Geometry2, + typename CSTag1 = typename geometry::cs_tag::type, + typename CSTag2 = typename geometry::cs_tag::type +> +struct default_strategy +{ + BOOST_GEOMETRY_STATIC_ASSERT_FALSE( + "Not implemented for this Geometry's coordinate system.", + Geometry1, Geometry2, CSTag1, CSTag2); +}; + +template +struct strategy_converter +{ + BOOST_GEOMETRY_STATIC_ASSERT_FALSE( + "Not implemented for this Strategy.", + Strategy); +}; + + +} // namespace services + +}} // namespace strategies::relate + + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_STRATEGIES_RELATE_SERVICES_HPP diff --git a/include/boost/geometry/strategies/relate/spherical.hpp b/include/boost/geometry/strategies/relate/spherical.hpp new file mode 100644 index 000000000..265de7a61 --- /dev/null +++ b/include/boost/geometry/strategies/relate/spherical.hpp @@ -0,0 +1,356 @@ +// Boost.Geometry + +// Copyright (c) 2020, Oracle and/or its affiliates. + +// 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 + +#ifndef BOOST_GEOMETRY_STRATEGIES_RELATE_SPHERICAL_HPP +#define BOOST_GEOMETRY_STRATEGIES_RELATE_SPHERICAL_HPP + + +// TEMP - move to strategy +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +#include + + +namespace boost { namespace geometry +{ + +namespace strategies { namespace relate +{ + +#ifndef DOXYGEN_NO_DETAIL +namespace detail +{ + +template +class spherical + : public strategies::envelope::detail::spherical +{ + using base_t = strategies::envelope::detail::spherical; + +public: + + // area + + template + auto area(Geometry const&) const + { + return strategy::area::spherical + < + typename base_t::radius_type, + CalculationType + >(base_t::radius()); + } + + // covered_by + + template + static auto covered_by(Geometry1 const&, Geometry2 const&, + std::enable_if_t + < + util::is_pointlike::value + && util::is_box::value + > * = nullptr) + { + return strategy::covered_by::spherical_point_box(); + } + + template + static auto covered_by(Geometry1 const&, Geometry2 const&, + std::enable_if_t + < + util::is_box::value + && util::is_box::value + > * = nullptr) + { + return strategy::covered_by::spherical_box_box(); + } + + // disjoint + + template + static auto disjoint(Geometry1 const&, Geometry2 const&, + std::enable_if_t + < + util::is_box::value + && util::is_box::value + > * = nullptr) + { + return strategy::disjoint::spherical_box_box(); + } + + template + static auto disjoint(Geometry1 const&, Geometry2 const&, + std::enable_if_t + < + util::is_segment::value + && util::is_box::value + > * = nullptr) + { + // NOTE: Inconsistent name. + return strategy::disjoint::segment_box_spherical(); + } + + // relate + + template + static auto relate(Geometry1 const&, Geometry2 const&, + std::enable_if_t + < + util::is_pointlike::value + && util::is_pointlike::value + > * = nullptr) + { + return strategy::within::spherical_point_point(); + } + + template + static auto relate(Geometry1 const&, Geometry2 const&, + std::enable_if_t + < + util::is_pointlike::value + && ( util::is_linear::value + || util::is_polygonal::value ) + > * = nullptr) + { + return strategy::within::spherical_winding(); + } + + //template + static auto relate(/*Geometry1 const&, Geometry2 const&, + std::enable_if_t + < + ( util::is_linear::value + || util::is_polygonal::value ) + && ( util::is_linear::value + || util::is_polygonal::value ) + > * = nullptr*/) + { + return strategy::intersection::spherical_segments(); + } + + // side + + static auto side() + { + return strategy::side::spherical_side_formula(); + } + + // within + + template + static auto within(Geometry1 const&, Geometry2 const&, + std::enable_if_t + < + util::is_pointlike::value + && util::is_box::value + > * = nullptr) + { + return strategy::within::spherical_point_box(); + } + + template + static auto within(Geometry1 const&, Geometry2 const&, + std::enable_if_t + < + util::is_box::value + && util::is_box::value + > * = nullptr) + { + return strategy::within::spherical_box_box(); + } +}; + + +} // namespace detail +#endif // DOXYGEN_NO_DETAIL + + +template +class spherical + : public strategies::relate::detail::spherical +{}; + + +namespace services +{ + +template +struct default_strategy +{ + using type = strategies::relate::spherical<>; +}; + +template +struct default_strategy +{ + using type = strategies::relate::spherical<>; +}; + +template +struct default_strategy +{ + using type = strategies::relate::spherical<>; +}; + + +template <> +struct strategy_converter +{ + static auto get(strategy::within::spherical_point_point const& ) + { + return strategies::relate::spherical<>(); + } +}; + +template <> +struct strategy_converter +{ + static auto get(strategy::within::spherical_point_box const&) + { + return strategies::relate::spherical<>(); + } +}; + +template <> +struct strategy_converter +{ + static auto get(strategy::covered_by::spherical_point_box const&) + { + return strategies::relate::spherical<>(); + } +}; + +template <> +struct strategy_converter +{ + static auto get(strategy::covered_by::spherical_box_box const&) + { + return strategies::relate::spherical<>(); + } +}; + +template <> +struct strategy_converter +{ + static auto get(strategy::disjoint::spherical_box_box const&) + { + return strategies::relate::spherical<>(); + } +}; + +template <> +struct strategy_converter +{ + static auto get(strategy::disjoint::segment_box_spherical const&) + { + return strategies::relate::spherical<>(); + } +}; + +template <> +struct strategy_converter +{ + static auto get(strategy::within::spherical_box_box const&) + { + return strategies::relate::spherical<>(); + } +}; + +template +struct strategy_converter> +{ + static auto get(strategy::within::spherical_winding const& ) + { + return strategies::relate::spherical(); + } +}; + +template +struct strategy_converter> +{ + static auto get(strategy::intersection::spherical_segments const& ) + { + return strategies::relate::spherical(); + } +}; + +template +struct strategy_converter> +{ + struct altered_strategy + : strategies::relate::spherical + { + template + static auto covered_by(Geometry1 const&, Geometry2 const&, + std::enable_if_t + < + util::is_pointlike::value + && util::is_box::value + > * = nullptr) + { + return strategy::covered_by::spherical_point_box_by_side(); + } + + template + static auto within(Geometry1 const&, Geometry2 const&, + std::enable_if_t + < + util::is_pointlike::value + && util::is_box::value + > * = nullptr) + { + return strategy::within::spherical_point_box_by_side(); + } + }; + + static auto get(strategy::covered_by::spherical_point_box_by_side const&) + { + return altered_strategy(); + } + + static auto get(strategy::within::spherical_point_box_by_side const&) + { + return altered_strategy(); + } +}; + +template +struct strategy_converter> + : strategy_converter> +{}; + +// TEMP used in distance segment/box +template +struct strategy_converter> +{ + static auto get(strategy::side::spherical_side_formula const& ) + { + return strategies::relate::spherical(); + } +}; + + +} // namespace services + +}} // namespace strategies::relate + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_STRATEGIES_RELATE_SPHERICAL_HPP diff --git a/include/boost/geometry/strategies/spherical.hpp b/include/boost/geometry/strategies/spherical.hpp index 30501a4e2..07495e857 100644 --- a/include/boost/geometry/strategies/spherical.hpp +++ b/include/boost/geometry/strategies/spherical.hpp @@ -1,6 +1,6 @@ // Boost.Geometry -// Copyright (c) 2020, Oracle and/or its affiliates. +// Copyright (c) 2020-2021, Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle @@ -12,8 +12,13 @@ #include +#include +#include #include #include +#include +#include +#include namespace boost { namespace geometry @@ -29,89 +34,34 @@ template typename RadiusTypeOrSphere = double, typename CalculationType = void > -class spherical : strategies::detail::spherical_base +class spherical + // derived from the umbrella strategy defining the most strategies + : public strategies::index::detail::spherical { - using base_t = strategies::detail::spherical_base; + using base_t = strategies::index::detail::spherical; public: - spherical() - : base_t() - {} + spherical() = default; template explicit spherical(RadiusOrSphere const& radius_or_sphere) - : base_t(radius_or_sphere) - {} - - // area - - template - auto area(Geometry const&) const + //: base_t(radius_or_sphere) { - return strategy::area::spherical + // TODO: pass into the constructor + base_t::m_radius = strategy_detail::get_radius < - typename base_t::radius_type, CalculationType - >(base_t::m_radius); + RadiusOrSphere + >::apply(radius_or_sphere); } - // envelope - - template - static auto envelope(Geometry const&, Box const&, - typename util::enable_if_point_t * = nullptr) + static auto azimuth() { - return strategy::envelope::spherical_point(); + return strategy::azimuth::spherical(); } - template - static auto envelope(Geometry const&, Box const&, - typename util::enable_if_multi_point_t * = nullptr) + static auto point_order() { - return strategy::envelope::spherical_multipoint(); - } - - template - static auto envelope(Geometry const&, Box const&, - typename util::enable_if_box_t * = nullptr) - { - return strategy::envelope::spherical_box(); - } - - template - static auto envelope(Geometry const&, Box const&, - typename util::enable_if_segment_t * = nullptr) - { - return strategy::envelope::spherical_segment(); - } - - template - static auto envelope(Geometry const&, Box const&, - typename util::enable_if_polysegmental_t * = nullptr) - { - return strategy::envelope::spherical(); - } - - // expand - - template - static auto expand(Box const&, Geometry const&, - typename util::enable_if_point_t * = nullptr) - { - return strategy::expand::spherical_point(); - } - - template - static auto expand(Box const&, Geometry const&, - typename util::enable_if_box_t * = nullptr) - { - return strategy::expand::spherical_box(); - } - - template - static auto expand(Box const&, Geometry const&, - typename util::enable_if_segment_t * = nullptr) - { - return strategy::expand::spherical_segment(); + return strategy::point_order::spherical(); } }; diff --git a/include/boost/geometry/strategies/spherical/azimuth.hpp b/include/boost/geometry/strategies/spherical/azimuth.hpp index 32339057b..6fcb15ac9 100644 --- a/include/boost/geometry/strategies/spherical/azimuth.hpp +++ b/include/boost/geometry/strategies/spherical/azimuth.hpp @@ -1,6 +1,6 @@ // Boost.Geometry (aka GGL, Generic Geometry Library) -// Copyright (c) 2016-2020 Oracle and/or its affiliates. +// Copyright (c) 2016-2021 Oracle and/or its affiliates. // Contributed and/or modified by Vissarion Fisikopoulos, on behalf of Oracle // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle @@ -14,9 +14,12 @@ #include -#include #include +#include + +#include + namespace boost { namespace geometry { @@ -24,61 +27,58 @@ namespace boost { namespace geometry namespace strategy { namespace azimuth { -template -< - typename CalculationType = void -> +template class spherical { -public : +public: + template + struct result_type + : geometry::select_most_precise + < + T1, T2, CalculationType + > + {}; - inline spherical() - {} - - template - inline void apply(T const& lon1_rad, T const& lat1_rad, - T const& lon2_rad, T const& lat2_rad, - T& a1, T& a2) const + template + static inline void apply(T1 const& lon1_rad, T1 const& lat1_rad, + T2 const& lon2_rad, T2 const& lat2_rad, + Result& a1, Result& a2) { compute(lon1_rad, lat1_rad, lon2_rad, lat2_rad, a1, a2); } - template - inline void apply(T const& lon1_rad, T const& lat1_rad, - T const& lon2_rad, T const& lat2_rad, - T& a1) const + template + static inline void apply(T1 const& lon1_rad, T1 const& lat1_rad, + T2 const& lon2_rad, T2 const& lat2_rad, + Result& a1) { compute(lon1_rad, lat1_rad, lon2_rad, lat2_rad, a1, a1); } - template - inline void apply_reverse(T const& lon1_rad, T const& lat1_rad, - T const& lon2_rad, T const& lat2_rad, - T& a2) const + template + static inline void apply_reverse(T1 const& lon1_rad, T1 const& lat1_rad, + T2 const& lon2_rad, T2 const& lat2_rad, + Result& a2) { compute(lon1_rad, lat1_rad, lon2_rad, lat2_rad, a2, a2); } -private : - +private: template < bool EnableAzimuth, bool EnableReverseAzimuth, - typename T + typename T1, typename T2, typename Result > - inline void compute(T const& lon1_rad, T const& lat1_rad, - T const& lon2_rad, T const& lat2_rad, - T& a1, T& a2) const + static inline void compute(T1 const& lon1_rad, T1 const& lat1_rad, + T2 const& lon2_rad, T2 const& lat2_rad, + Result& a1, Result& a2) { - typedef std::conditional_t - < - std::is_void::value, T, CalculationType - > calc_t; + typedef typename result_type::type calc_t; geometry::formula::result_spherical result = geometry::formula::spherical_azimuth @@ -104,19 +104,12 @@ private : namespace services { -template -struct default_strategy +template <> +struct default_strategy { - typedef strategy::azimuth::spherical type; + typedef strategy::azimuth::spherical<> type; }; -/* -template -struct default_strategy -{ - typedef strategy::azimuth::spherical type; -}; -*/ } #endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS diff --git a/include/boost/geometry/strategies/spherical/distance_segment_box.hpp b/include/boost/geometry/strategies/spherical/distance_segment_box.hpp index c8bd5c34e..0e5af0f6f 100644 --- a/include/boost/geometry/strategies/spherical/distance_segment_box.hpp +++ b/include/boost/geometry/strategies/spherical/distance_segment_box.hpp @@ -19,6 +19,7 @@ #include #include #include +#include #include #include // spherical #include @@ -223,9 +224,9 @@ struct spherical_segment_box typedef Strategy type; }; - inline typename distance_pp_strategy::type get_distance_pp_strategy() const + inline Strategy get_distance_pp_strategy() const { - return typename distance_pp_strategy::type(); + return m_strategy; } // point-segment strategy getters struct distance_ps_strategy @@ -235,7 +236,7 @@ struct spherical_segment_box inline typename distance_ps_strategy::type get_distance_ps_strategy() const { - return typename distance_ps_strategy::type(); + return typename distance_ps_strategy::type(m_strategy.radius()); } struct distance_pb_strategy @@ -245,7 +246,7 @@ struct spherical_segment_box inline typename distance_pb_strategy::type get_distance_pb_strategy() const { - return typename distance_pb_strategy::type(); + return typename distance_pb_strategy::type(m_strategy.radius()); } // TODO: why is the Radius not propagated above? @@ -264,6 +265,19 @@ struct spherical_segment_box return equals_point_point_strategy_type(); } + // constructors + + inline spherical_segment_box() + {} + + explicit inline spherical_segment_box(typename Strategy::radius_type const& r) + : m_strategy(r) + {} + + inline spherical_segment_box(Strategy const& s) + : m_strategy(s) + {} + // methods template -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include - - -namespace boost { namespace geometry { namespace strategy { namespace index -{ - -template -< - typename CalculationType = void -> -struct spherical -{ - typedef spherical_tag cs_tag; - - typedef geometry::strategy::envelope::spherical_point envelope_point_strategy_type; - typedef geometry::strategy::envelope::spherical_box envelope_box_strategy_type; - typedef geometry::strategy::envelope::spherical_segment - < - CalculationType - > envelope_segment_strategy_type; - - static inline envelope_segment_strategy_type get_envelope_segment_strategy() - { - return envelope_segment_strategy_type(); - } - - typedef geometry::strategy::expand::spherical_point expand_point_strategy_type; - typedef geometry::strategy::expand::spherical_box expand_box_strategy_type; - typedef geometry::strategy::expand::spherical_segment - < - CalculationType - > expand_segment_strategy_type; - - static inline expand_segment_strategy_type get_expand_segment_strategy() - { - return expand_segment_strategy_type(); - } - - typedef geometry::strategy::covered_by::spherical_point_box covered_by_point_box_strategy_type; - typedef geometry::strategy::covered_by::spherical_box_box covered_by_box_box_strategy_type; - typedef geometry::strategy::within::spherical_point_point within_point_point_strategy_type; - //typedef geometry::strategy::within::spherical_point_box within_point_box_strategy_type; - //typedef geometry::strategy::within::spherical_box_box within_box_box_strategy_type; - - // used in equals(Seg, Seg) but only to get_point_in_point_strategy() - typedef geometry::strategy::intersection::spherical_segments - < - CalculationType - > relate_segment_segment_strategy_type; - - static inline relate_segment_segment_strategy_type get_relate_segment_segment_strategy() - { - return relate_segment_segment_strategy_type(); - } - - // used in intersection_content - typedef geometry::strategy::disjoint::spherical_box_box disjoint_box_box_strategy_type; - - typedef geometry::strategy::distance::comparable::haversine - < - double, - CalculationType - > comparable_distance_point_point_strategy_type; - - static inline comparable_distance_point_point_strategy_type get_comparable_distance_point_point_strategy() - { - return comparable_distance_point_point_strategy_type(); - } - - // TODO: Comparable version should be possible - typedef geometry::strategy::distance::cross_track_point_box - < - CalculationType, - geometry::strategy::distance::haversine - > comparable_distance_point_box_strategy_type; - - static inline comparable_distance_point_box_strategy_type get_comparable_distance_point_box_strategy() - { - return comparable_distance_point_box_strategy_type(); - } - - // TODO: Radius is not needed in comparable strategy - typedef geometry::strategy::distance::comparable::cross_track - < - CalculationType, - geometry::strategy::distance::comparable::haversine - > comparable_distance_point_segment_strategy_type; - - static inline comparable_distance_point_segment_strategy_type get_comparable_distance_point_segment_strategy() - { - return comparable_distance_point_segment_strategy_type(); - } - - // comparable? - typedef geometry::strategy::distance::spherical_segment_box - < - CalculationType, - geometry::strategy::distance::haversine - > comparable_distance_segment_box_strategy_type; - - static inline comparable_distance_segment_box_strategy_type get_comparable_distance_segment_box_strategy() - { - return comparable_distance_segment_box_strategy_type(); - } -}; - - -namespace services -{ - -template -struct default_strategy -{ - typedef spherical<> type; -}; - -template -struct default_strategy -{ - typedef spherical<> type; -}; - -template -struct default_strategy -{ - typedef spherical<> type; -}; - - -template -struct from_strategy > -{ - typedef strategy::index::spherical type; - - static inline type get(within::spherical_winding const&) - { - return type(); - } -}; - -// distance (MPt, MPt) -template -struct from_strategy > -{ - typedef strategy::index::spherical type; - - static inline type get(distance::comparable::haversine const&) - { - return type(); - } -}; - -// distance (MPt, Linear/Areal) -template -struct from_strategy > -{ - typedef strategy::index::spherical type; - - static inline type get(distance::comparable::cross_track const&) - { - return type(); - } -}; - - -} // namespace services - - -}}}} // namespace boost::geometry::strategy::index - -#endif // BOOST_GEOMETRY_STRATEGIES_SPHERICAL_INDEX_HPP diff --git a/include/boost/geometry/strategies/spherical/intersection.hpp b/include/boost/geometry/strategies/spherical/intersection.hpp index b02c9980d..c78c8a69e 100644 --- a/include/boost/geometry/strategies/spherical/intersection.hpp +++ b/include/boost/geometry/strategies/spherical/intersection.hpp @@ -886,8 +886,7 @@ private: template static inline bool equals_point_point(Point1 const& point1, Point2 const& point2) { - return detail::equals::equals_point_point(point1, point2, - point_in_point_strategy_type()); + return strategy::within::spherical_point_point::apply(point1, point2); } }; diff --git a/include/boost/geometry/strategies/spherical/io.hpp b/include/boost/geometry/strategies/spherical/io.hpp deleted file mode 100644 index d5ff5c36b..000000000 --- a/include/boost/geometry/strategies/spherical/io.hpp +++ /dev/null @@ -1,80 +0,0 @@ -// Boost.Geometry - -// Copyright (c) 2019, Oracle and/or its affiliates. - -// 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 - -#ifndef BOOST_GEOMETRY_EXTENSIONS_STRATEGIES_SPHERICAL_IO_HPP -#define BOOST_GEOMETRY_EXTENSIONS_STRATEGIES_SPHERICAL_IO_HPP - - -#include - -#include -#include - - -namespace boost { namespace geometry -{ - -namespace strategy { namespace io -{ - -template -struct spherical -{ - typedef strategy::point_order::spherical point_order_strategy_type; - - static inline point_order_strategy_type get_point_order_strategy() - { - return point_order_strategy_type(); - } - - template - struct point_in_geometry_strategy - { - typedef strategy::within::spherical_winding - < - typename point_type::type, - typename point_type::type, - CalculationType - > type; - }; - - template - static inline typename point_in_geometry_strategy::type - get_point_in_geometry_strategy() - { - typedef typename point_in_geometry_strategy - < - Geometry1, Geometry2 - >::type strategy_type; - return strategy_type(); - } -}; - -namespace services -{ - -template <> -struct default_strategy -{ - typedef spherical<> type; -}; - -template <> -struct default_strategy -{ - typedef spherical<> type; -}; - -} // namespace services - -}} // namespace strategy::io - -}} // namespace boost::geometry - -#endif // BOOST_GEOMETRY_EXTENSIONS_STRATEGIES_SPHERICAL_IO_HPP diff --git a/include/boost/geometry/strategies/spherical/point_in_poly_winding.hpp b/include/boost/geometry/strategies/spherical/point_in_poly_winding.hpp index 1b0216a76..b94a97ca5 100644 --- a/include/boost/geometry/strategies/spherical/point_in_poly_winding.hpp +++ b/include/boost/geometry/strategies/spherical/point_in_poly_winding.hpp @@ -557,27 +557,13 @@ namespace services template struct default_strategy { - typedef within::detail::spherical_winding_base - < - typename strategy::side::services::default_strategy - < - typename cs_tag::type - >::type, - void - > type; + typedef within::spherical_winding<> type; }; template struct default_strategy { - typedef within::detail::spherical_winding_base - < - typename strategy::side::services::default_strategy - < - typename cs_tag::type - >::type, - void - > type; + typedef within::spherical_winding<> type; }; } // namespace services @@ -595,27 +581,13 @@ namespace strategy { namespace covered_by { namespace services template struct default_strategy { - typedef within::detail::spherical_winding_base - < - typename strategy::side::services::default_strategy - < - typename cs_tag::type - >::type, - void - > type; + typedef within::spherical_winding<> type; }; template struct default_strategy { - typedef within::detail::spherical_winding_base - < - typename strategy::side::services::default_strategy - < - typename cs_tag::type - >::type, - void - > type; + typedef within::spherical_winding<> type; }; }}} // namespace strategy::covered_by::services diff --git a/include/boost/geometry/strategies/spherical/side_by_cross_track.hpp b/include/boost/geometry/strategies/spherical/side_by_cross_track.hpp index 2b195e96f..b5cdb032b 100644 --- a/include/boost/geometry/strategies/spherical/side_by_cross_track.hpp +++ b/include/boost/geometry/strategies/spherical/side_by_cross_track.hpp @@ -2,8 +2,8 @@ // Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. -// This file was modified by Oracle on 2014-2017. -// Modifications copyright (c) 2014-2017, Oracle and/or its affiliates. +// This file was modified by Oracle on 2014-2021. +// Modifications copyright (c) 2014-2021, 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 @@ -15,20 +15,20 @@ #ifndef BOOST_GEOMETRY_STRATEGIES_SPHERICAL_SIDE_BY_CROSS_TRACK_HPP #define BOOST_GEOMETRY_STRATEGIES_SPHERICAL_SIDE_BY_CROSS_TRACK_HPP -#include #include +#include #include #include +//#include +#include +#include + #include #include #include -#include -//#include - - namespace boost { namespace geometry { @@ -50,6 +50,15 @@ public : template static inline int apply(P1 const& p1, P2 const& p2, P const& p) { + typedef strategy::within::spherical_point_point + equals_point_point_strategy_type; + if (equals_point_point_strategy_type::apply(p, p1) + || equals_point_point_strategy_type::apply(p, p2) + || equals_point_point_strategy_type::apply(p1, p2)) + { + return 0; + } + typedef typename promote_floating_point < typename select_calculation_type_alt diff --git a/include/boost/geometry/strategies/strategies.hpp b/include/boost/geometry/strategies/strategies.hpp index f02b9adbe..6682c8322 100644 --- a/include/boost/geometry/strategies/strategies.hpp +++ b/include/boost/geometry/strategies/strategies.hpp @@ -35,7 +35,6 @@ #include #include #include // for backward compatibility -#include #include #include #include @@ -61,7 +60,6 @@ #include #include #include -#include #include #include #include @@ -80,7 +78,6 @@ #include #include #include -#include #include #include #include @@ -100,7 +97,6 @@ #include #include //#include -#include #include //#include #include @@ -112,7 +108,6 @@ #include #include -#include #include #include #include @@ -129,6 +124,7 @@ #include #include #include +#include #include #include diff --git a/include/boost/geometry/strategy/cartesian/area.hpp b/include/boost/geometry/strategy/cartesian/area.hpp index 275b06035..f17453fac 100644 --- a/include/boost/geometry/strategy/cartesian/area.hpp +++ b/include/boost/geometry/strategy/cartesian/area.hpp @@ -112,8 +112,7 @@ public : } template - static inline typename result_type::type - result(state& st) + static inline auto result(state& st) { return st.area(); } diff --git a/include/boost/geometry/strategy/cartesian/in_circle_robust.hpp b/include/boost/geometry/strategy/cartesian/in_circle_robust.hpp new file mode 100644 index 000000000..cf7be86f8 --- /dev/null +++ b/include/boost/geometry/strategy/cartesian/in_circle_robust.hpp @@ -0,0 +1,64 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2019 Tinko Bartels, Berlin, Germany. + +// Contributed and/or modified by Tinko Bartels, +// as part of Google Summer of Code 2019 program. + +// 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_STRATEGY_CARTESIAN_IN_CIRCLE_ROBUST_HPP +#define BOOST_GEOMETRY_STRATEGY_CARTESIAN_IN_CIRCLE_ROBUST_HPP + +#include + +namespace boost { namespace geometry +{ + +namespace strategy { namespace in_circle +{ + +/*! +\brief Adaptive precision predicate to check whether a fourth point lies inside the circumcircle of the first three points: + inside (>0), outside (< 0), on the boundary (0). +\ingroup strategies +\tparam CalculationType \tparam_calculation (numeric_limits::epsilon() and numeric_limits::digits must be supported for calculation type ct) +\tparam Robustness std::size_t value from 0 (fastest) to 2 (default, most precise). +\details This predicate determines whether a fourth point lies inside the circumcircle of the first three points using an algorithm that is adapted from incircle as described in "Adaptive Precision Floating-Point Arithmetic and Fast Robust Geometric Predicates" by Jonathan Richard Shewchuk ( https://dl.acm.org/citation.cfm?doid=237218.237337 ). More information and copies of the paper can also be found at https://www.cs.cmu.edu/~quake/robust.html . It is designed to be adaptive in the sense that it should be fast for inputs that lead to correct results with plain float operations but robust for inputs that require higher precision arithmetics. + */ +template +class in_circle_robust +{ +public: + template + static inline int apply(P1 const& p1, P2 const& p2, P3 const& p3, P const& p) + { + std::array pa { + { boost::geometry::get<0>(p1), boost::geometry::get<1>(p1) }}; + std::array pb { + { boost::geometry::get<0>(p2), boost::geometry::get<1>(p2) }}; + std::array pc { + { boost::geometry::get<0>(p3), boost::geometry::get<1>(p3) }}; + std::array pd { + { boost::geometry::get<0>(p), boost::geometry::get<1>(p) }}; + CalculationType det = + boost::geometry::detail::precise_math::incircle + < + CalculationType, + Robustness + >(pa, pb, pc, pd); + return det > 0 ? 1 + : det < 0 ? -1 : 0; + } + +}; + +} // namespace in_circle + +} // namespace strategy + +}} // namespace boost::geometry::strategy + +#endif // BOOST_GEOMETRY_STRATEGY_CARTESIAN_IN_CIRCLE_ROBUST_HPP diff --git a/include/boost/geometry/strategy/cartesian/precise_area.hpp b/include/boost/geometry/strategy/cartesian/precise_area.hpp new file mode 100644 index 000000000..f9b09de80 --- /dev/null +++ b/include/boost/geometry/strategy/cartesian/precise_area.hpp @@ -0,0 +1,117 @@ +// Boost.Geometry + +// Copyright (c) 2020, Oracle and/or its affiliates. + +// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle + +// Licensed under the Boost Software License version 1.0. +// http://www.boost.org/users/license.html + +#ifndef BOOST_GEOMETRY_STRATEGY_CARTESIAN_PRECISE_AREA_HPP +#define BOOST_GEOMETRY_STRATEGY_CARTESIAN_PRECISE_AREA_HPP + +#include + +//#include +#include +#include +#include +#include +#include +#include + +namespace boost { namespace geometry +{ + +namespace strategy { namespace area +{ + +/*! +\brief Cartesian area calculation +\ingroup strategies +\details Calculates cartesian area using the trapezoidal rule and precise + summation (useful to increase precision with floating point arithmetic) +\tparam CalculationType \tparam_calculation + +\qbk{ +[heading See also] +[link geometry.reference.algorithms.area.area_2_with_strategy area (with strategy)] +} + +*/ +template +< + typename CalculationType = void +> +class precise_cartesian +{ +public : + template + struct result_type + : strategy::area::detail::result_type + < + Geometry, + CalculationType + > + {}; + + template + class state + { + friend class precise_cartesian; + + typedef typename result_type::type return_type; + + public: + inline state() + : sum1(0) + , sum2(0) + { + // Strategy supports only 2D areas + assert_dimension(); + } + + private: + inline return_type area() const + { + return_type const two = 2; + return (sum1 + sum2) / two; + } + + return_type sum1; + return_type sum2; + }; + + template + static inline void apply(PointOfSegment const& p1, + PointOfSegment const& p2, + state& st) + { + typedef typename state::return_type return_type; + + auto const det = (return_type(get<0>(p1)) + return_type(get<0>(p2))) + * (return_type(get<1>(p1)) - return_type(get<1>(p2))); + + auto const res = boost::geometry::detail::precise_math::two_sum(st.sum1, det); + + st.sum1 = res[0]; + st.sum2 += res[1]; + } + + template + static inline auto result(state& st) + { + return st.area(); + } + +}; + + +}} // namespace strategy::area + + + +}} // namespace boost::geometry + + +#endif // BOOST_GEOMETRY_STRATEGY_CARTESIAN_PRECISE_AREA_HPP diff --git a/include/boost/geometry/strategy/cartesian/side_non_robust.hpp b/include/boost/geometry/strategy/cartesian/side_non_robust.hpp new file mode 100644 index 000000000..2ef109cc1 --- /dev/null +++ b/include/boost/geometry/strategy/cartesian/side_non_robust.hpp @@ -0,0 +1,76 @@ +// Boost.Geometry + +// Copyright (c) 2020, Oracle and/or its affiliates. + +// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle + +// Licensed under the Boost Software License version 1.0. +// http://www.boost.org/users/license.html + +#ifndef BOOST_GEOMETRY_STRATEGY_CARTESIAN_SIDE_NON_ROBUST_HPP +#define BOOST_GEOMETRY_STRATEGY_CARTESIAN_SIDE_NON_ROBUST_HPP + +#include +#include +#include + +namespace boost { namespace geometry +{ + +namespace strategy { namespace side +{ + +/*! +\brief Adaptive precision predicate to check at which side of a segment a point lies: + left of segment (>0), right of segment (< 0), on segment (0). +\ingroup strategies +\tparam CalculationType \tparam_calculation +\details This predicate determines at which side of a segment a point lies +*/ +template +< + typename CalculationType = void +> +struct side_non_robust +{ +public: + //! \brief Computes double the signed area of the CCW triangle p1, p2, p + +#ifndef DOXYGEN_SHOULD_SKIP_THIS + template + < + typename P1, + typename P2, + typename P + > + static inline int apply(P1 const& p1, P2 const& p2, P const& p) + { + typedef typename select_calculation_type_alt + < + CalculationType, + P1, + P2, + P + >::type coordinate_type; + typedef typename select_most_precise + < + coordinate_type, + double + >::type promoted_type; + + auto detleft = (promoted_type(get<0>(p1)) - promoted_type(get<0>(p))) + * (promoted_type(get<1>(p2)) - promoted_type(get<1>(p))); + auto detright = (promoted_type(get<1>(p1)) - promoted_type(get<1>(p))) + * (promoted_type(get<0>(p2)) - promoted_type(get<0>(p))); + return detleft > detright ? 1 : (detleft < detright ? -1 : 0 ); + + } +#endif + +}; + +}} // namespace strategy::side + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_STRATEGY_CARTESIAN_SIDE_NON_ROBUST_HPP diff --git a/include/boost/geometry/strategy/cartesian/side_robust.hpp b/include/boost/geometry/strategy/cartesian/side_robust.hpp new file mode 100644 index 000000000..4ee4a1726 --- /dev/null +++ b/include/boost/geometry/strategy/cartesian/side_robust.hpp @@ -0,0 +1,95 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2019 Tinko Bartels, Berlin, Germany. + +// Contributed and/or modified by Tinko Bartels, +// as part of Google Summer of Code 2019 program. + +// 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_STRATEGY_CARTESIAN_SIDE_ROBUST_HPP +#define BOOST_GEOMETRY_STRATEGY_CARTESIAN_SIDE_ROBUST_HPP + +#include +#include +#include + +namespace boost { namespace geometry +{ + +namespace strategy { namespace side +{ + +/*! +\brief Adaptive precision predicate to check at which side of a segment a point lies: + left of segment (>0), right of segment (< 0), on segment (0). +\ingroup strategies +\tparam CalculationType \tparam_calculation (numeric_limits::epsilon() and numeric_limits::digits must be supported for calculation type ct) +\tparam Robustness std::size_t value from 0 (fastest) to 3 (default, guarantees correct results). +\details This predicate determines at which side of a segment a point lies using an algorithm that is adapted from orient2d as described in "Adaptive Precision Floating-Point Arithmetic and Fast Robust Geometric Predicates" by Jonathan Richard Shewchuk ( https://dl.acm.org/citation.cfm?doid=237218.237337 ). More information and copies of the paper can also be found at https://www.cs.cmu.edu/~quake/robust.html . It is designed to be adaptive in the sense that it should be fast for inputs that lead to correct results with plain float operations but robust for inputs that require higher precision arithmetics. + */ +template +< + typename CalculationType = void, + std::size_t Robustness = 3 +> +struct side_robust +{ +public: + //! \brief Computes double the signed area of the CCW triangle p1, p2, p + template + < + typename PromotedType, + typename P1, + typename P2, + typename P + > + static inline PromotedType side_value(P1 const& p1, P2 const& p2, + P const& p) + { + typedef ::boost::geometry::detail::precise_math::vec2d vec2d; + vec2d pa { get<0>(p1), get<1>(p1) }; + vec2d pb { get<0>(p2), get<1>(p2) }; + vec2d pc { get<0>(p), get<1>(p) }; + return ::boost::geometry::detail::precise_math::orient2d + (pa, pb, pc); + } + +#ifndef DOXYGEN_SHOULD_SKIP_THIS + template + < + typename P1, + typename P2, + typename P + > + static inline int apply(P1 const& p1, P2 const& p2, P const& p) + { + typedef typename select_calculation_type_alt + < + CalculationType, + P1, + P2, + P + >::type coordinate_type; + typedef typename select_most_precise + < + coordinate_type, + double + >::type promoted_type; + + promoted_type sv = side_value(p1, p2, p); + return sv > 0 ? 1 + : sv < 0 ? -1 + : 0; + } +#endif + +}; + +}} // namespace strategy::side + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_STRATEGY_CARTESIAN_SIDE_ROBUST_HPP diff --git a/include/boost/geometry/strategy/relate.hpp b/include/boost/geometry/strategy/relate.hpp new file mode 100644 index 000000000..6f9967082 --- /dev/null +++ b/include/boost/geometry/strategy/relate.hpp @@ -0,0 +1,175 @@ +// Boost.Geometry + +// Copyright (c) 2017-2020, 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_STRATEGY_RELATE_HPP +#define BOOST_GEOMETRY_STRATEGY_RELATE_HPP + + +#include + +#include +#include +#include +#include + +#include +#include +#include + + +namespace boost { namespace geometry +{ + +namespace strategy +{ + +namespace point_in_geometry +{ + +#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS +namespace services +{ + +template +< + typename Point, + typename Geometry, + typename Tag1 = typename tag::type, + typename Tag2 = typename tag::type +> +struct default_strategy + : strategy::within::services::default_strategy + < + Point, + Geometry + > +{ + typedef typename default_strategy::type within_strategy_type; + + typedef typename strategy::covered_by::services::default_strategy + < + Point, + Geometry + >::type covered_by_strategy_type; + + static const bool same_strategies = std::is_same::value; + BOOST_GEOMETRY_STATIC_ASSERT(same_strategies, + "Default within and covered_by strategies not compatible.", + within_strategy_type, covered_by_strategy_type); +}; + +template +struct default_strategy + : strategy::within::services::default_strategy +{}; + +template +struct default_strategy + : strategy::within::services::default_strategy +{}; + + +} // namespace services +#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS + + +} // namespace point_in_geometry + +namespace relate +{ + +#ifndef DOXYGEN_NO_DETAIL +namespace detail +{ + +template +struct default_intersection_strategy + : strategy::intersection::services::default_strategy + < + typename cs_tag::type + > +{}; + +template +struct default_point_in_geometry_strategy + : point_in_geometry::services::default_strategy + < + typename point_type::type, + Geometry + > +{}; + +} // namespace detail +#endif // DOXYGEN_NO_DETAIL + +#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS +namespace services +{ + +template +< + typename Geometry1, + typename Geometry2, + int TopDim1 = geometry::topological_dimension::value, + int TopDim2 = geometry::topological_dimension::value +> +struct default_strategy +{ + BOOST_GEOMETRY_STATIC_ASSERT_FALSE( + "Not implemented for these types.", + Geometry1, Geometry2); +}; + +template +struct default_strategy + : detail::default_point_in_geometry_strategy +{}; + +template +struct default_strategy + : detail::default_point_in_geometry_strategy +{}; + +template +struct default_strategy + : detail::default_point_in_geometry_strategy +{}; + +template +struct default_strategy + : detail::default_intersection_strategy +{}; + +template +struct default_strategy + : detail::default_intersection_strategy +{}; + +template +struct default_strategy + : detail::default_intersection_strategy +{}; + +template +struct default_strategy + : detail::default_intersection_strategy +{}; + +} // namespace services +#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS + +} // namespace relate + +} // namespace strategy + + +}} // namespace boost::geometry + + +#endif // BOOST_GEOMETRY_STRATEGY_RELATE_HPP diff --git a/include/boost/geometry/util/precise_math.hpp b/include/boost/geometry/util/precise_math.hpp new file mode 100644 index 000000000..c70762097 --- /dev/null +++ b/include/boost/geometry/util/precise_math.hpp @@ -0,0 +1,614 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2019 Tinko Bartels, Berlin, Germany. + +// Contributed and/or modified by Tinko Bartels, +// as part of Google Summer of Code 2019 program. + +// 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_EXTENSIONS_TRIANGULATION_STRATEGIES_CARTESIAN_DETAIL_PRECISE_MATH_HPP +#define BOOST_GEOMETRY_EXTENSIONS_TRIANGULATION_STRATEGIES_CARTESIAN_DETAIL_PRECISE_MATH_HPP + +#include +#include +#include +#include + +#include + +// The following code is based on "Adaptive Precision Floating-Point Arithmetic +// and Fast Robust Geometric Predicates" by Richard Shewchuk, +// J. Discrete Comput Geom (1997) 18: 305. https://doi.org/10.1007/PL00009321 + +namespace boost { namespace geometry +{ + +namespace detail { namespace precise_math +{ + +// See Theorem 6, page 6 +template +< + typename RealNumber +> +inline std::array fast_two_sum(RealNumber const a, + RealNumber const b) +{ + RealNumber x = a + b; + RealNumber b_virtual = x - a; + return {{x, b - b_virtual}}; +} + +// See Theorem 7, page 7 - 8 +template +< + typename RealNumber +> +inline std::array two_sum(RealNumber const a, + RealNumber const b) +{ + RealNumber x = a + b; + RealNumber b_virtual = x - a; + RealNumber a_virtual = x - b_virtual; + RealNumber b_roundoff = b - b_virtual; + RealNumber a_roundoff = a - a_virtual; + RealNumber y = a_roundoff + b_roundoff; + return {{ x, y }}; +} + +// See bottom of page 8 +template +< + typename RealNumber +> +inline RealNumber two_diff_tail(RealNumber const a, + RealNumber const b, + RealNumber const x) +{ + RealNumber b_virtual = a - x; + RealNumber a_virtual = x + b_virtual; + RealNumber b_roundoff = b_virtual - b; + RealNumber a_roundoff = a - a_virtual; + return a_roundoff + b_roundoff; +} + +// see bottom of page 8 +template +< + typename RealNumber +> +inline std::array two_diff(RealNumber const a, + RealNumber const b) +{ + RealNumber x = a - b; + RealNumber y = two_diff_tail(a, b, x); + return {{ x, y }}; +} + +// see theorem 18, page 19 +template +< + typename RealNumber +> +inline RealNumber two_product_tail(RealNumber const a, + RealNumber const b, + RealNumber const x) +{ + return std::fma(a, b, -x); +} + +// see theorem 18, page 19 +template +< + typename RealNumber +> +inline std::array two_product(RealNumber const a, + RealNumber const b) +{ + RealNumber x = a * b; + RealNumber y = two_product_tail(a, b, x); + return {{ x , y }}; +} + +// see theorem 12, figure 7, page 11 - 12, +// this is the 2 by 2 case for the corresponding diff-method +// note that this method takes input in descending order of magnitude and +// returns components in ascending order of magnitude +template +< + typename RealNumber +> +inline std::array two_two_expansion_diff( + std::array const a, + std::array const b) +{ + std::array h; + std::array Qh = two_diff(a[1], b[1]); + h[0] = Qh[1]; + Qh = two_sum( a[0], Qh[0] ); + RealNumber _j = Qh[0]; + Qh = two_diff(Qh[1], b[0]); + h[1] = Qh[1]; + Qh = two_sum( _j, Qh[0] ); + h[2] = Qh[1]; + h[3] = Qh[0]; + return h; +} + +// see theorem 13, figure 8. This implementation uses zero elimination as +// suggested on page 17, second to last paragraph. Returns the number of +// non-zero components in the result and writes the result to h. +// the merger into a single sequence g is done implicitly +template +< + typename RealNumber, + std::size_t InSize1, + std::size_t InSize2, + std::size_t OutSize +> +inline int fast_expansion_sum_zeroelim( + std::array const& e, + std::array const& f, + std::array & h, + int m = InSize1, + int n = InSize2) +{ + std::array Qh; + int i_e = 0, i_f = 0, i_h = 0; + if (std::abs(f[0]) > std::abs(e[0])) + { + Qh[0] = e[i_e++]; + } + else + { + Qh[0] = f[i_f++]; + } + i_h = 0; + if ((i_e < m) && (i_f < n)) + { + if (std::abs(f[i_f]) > std::abs(e[i_e])) + { + Qh = fast_two_sum(e[i_e++], Qh[0]); + } + else + { + Qh = fast_two_sum(f[i_f++], Qh[0]); + } + if (Qh[1] != 0.0) + { + h[i_h++] = Qh[1]; + } + while ((i_e < m) && (i_f < n)) + { + if (std::abs(f[i_f]) > std::abs(e[i_e])) + { + Qh = two_sum(Qh[0], e[i_e++]); + } + else + { + Qh = two_sum(Qh[0], f[i_f++]); + } + if (Qh[1] != 0.0) + { + h[i_h++] = Qh[1]; + } + } + } + while (i_e < m) + { + Qh = two_sum(Qh[0], e[i_e++]); + if (Qh[1] != 0.0) + { + h[i_h++] = Qh[1]; + } + } + while (i_f < n) + { + Qh = two_sum(Qh[0], f[i_f++]); + if (Qh[1] != 0.0) + { + h[i_h++] = Qh[1]; + } + } + if ((Qh[0] != 0.0) || (i_h == 0)) + { + h[i_h++] = Qh[0]; + } + return i_h; +} + +// see theorem 19, figure 13, page 20 - 21. This implementation uses zero +// elimination as suggested on page 17, second to last paragraph. Returns the +// number of non-zero components in the result and writes the result to h. +template +< + typename RealNumber, + std::size_t InSize +> +inline int scale_expansion_zeroelim( + std::array const& e, + RealNumber const b, + std::array & h, + int e_non_zeros = InSize) +{ + std::array Qh = two_product(e[0], b); + int i_h = 0; + if (Qh[1] != 0) + { + h[i_h++] = Qh[1]; + } + for (int i_e = 1; i_e < e_non_zeros; i_e++) + { + std::array Tt = two_product(e[i_e], b); + Qh = two_sum(Qh[0], Tt[1]); + if (Qh[1] != 0) + { + h[i_h++] = Qh[1]; + } + Qh = fast_two_sum(Tt[0], Qh[0]); + if (Qh[1] != 0) + { + h[i_h++] = Qh[1]; + } + } + if ((Qh[0] != 0.0) || (i_h == 0)) + { + h[i_h++] = Qh[0]; + } + return i_h; +} + +template +struct vec2d +{ + RealNumber x; + RealNumber y; +}; + +template +< + typename RealNumber, + std::size_t Robustness +> +inline RealNumber orient2dtail(vec2d const& p1, + vec2d const& p2, + vec2d const& p3, + std::array& t1, + std::array& t2, + std::array& t3, + std::array& t4, + std::array& t5_01, + std::array& t6_01, + RealNumber const& magnitude + ) +{ + t5_01[1] = two_product_tail(t1[0], t2[0], t5_01[0]); + t6_01[1] = two_product_tail(t3[0], t4[0], t6_01[0]); + std::array tA_03 = two_two_expansion_diff(t5_01, t6_01); + RealNumber det = std::accumulate(tA_03.begin(), tA_03.end(), static_cast(0)); + if(Robustness == 1) return det; + // see p.39, mind the different definition of epsilon for error bound + RealNumber B_relative_bound = + (1 + 3 * std::numeric_limits::epsilon()) + * std::numeric_limits::epsilon(); + RealNumber absolute_bound = B_relative_bound * magnitude; + if (std::abs(det) >= absolute_bound) + { + return det; //B estimate + } + t1[1] = two_diff_tail(p1.x, p3.x, t1[0]); + t2[1] = two_diff_tail(p2.y, p3.y, t2[0]); + t3[1] = two_diff_tail(p1.y, p3.y, t3[0]); + t4[1] = two_diff_tail(p2.x, p3.x, t4[0]); + + if ((t1[1] == 0) && (t3[1] == 0) && (t2[1] == 0) && (t4[1] == 0)) + { + return det; //If all tails are zero, there is noething else to compute + } + RealNumber sub_bound = + (1.5 + 2 * std::numeric_limits::epsilon()) + * std::numeric_limits::epsilon(); + // see p.39, mind the different definition of epsilon for error bound + RealNumber C_relative_bound = + (2.25 + 8 * std::numeric_limits::epsilon()) + * std::numeric_limits::epsilon() + * std::numeric_limits::epsilon(); + absolute_bound = C_relative_bound * magnitude + sub_bound * std::abs(det); + det += (t1[0] * t2[1] + t2[0] * t1[1]) - (t3[0] * t4[1] + t4[0] * t3[1]); + if (Robustness == 2 || std::abs(det) >= absolute_bound) + { + return det; //C estimate + } + std::array D_left; + int D_left_nz; + { + std::array t5_23 = two_product(t1[1], t2[0]); + std::array t6_23 = two_product(t3[1], t4[0]); + std::array tA_47 = two_two_expansion_diff(t5_23, t6_23); + D_left_nz = fast_expansion_sum_zeroelim(tA_03, tA_47, D_left); + } + std::array D_right; + int D_right_nz; + { + std::array t5_45 = two_product(t1[0], t2[1]); + std::array t6_45 = two_product(t3[0], t4[1]); + std::array tA_8_11 = two_two_expansion_diff(t5_45, t6_45); + std::array t5_67 = two_product(t1[1], t2[1]); + std::array t6_67 = two_product(t3[1], t4[1]); + std::array tA_12_15 = two_two_expansion_diff(t5_67, t6_67); + D_right_nz = fast_expansion_sum_zeroelim(tA_8_11, tA_12_15, D_right); + } + std::array D; + int D_nz = fast_expansion_sum_zeroelim(D_left, D_right, D, D_left_nz, D_right_nz); + // only return component of highest magnitude because we mostly care about the sign. + return(D[D_nz - 1]); +} + +// see page 38, Figure 21 for the calculations, notation follows the notation in the figure. +template +< + typename RealNumber, + std::size_t Robustness = 3 +> +inline RealNumber orient2d(vec2d const& p1, + vec2d const& p2, + vec2d const& p3) +{ + if(Robustness == 0) + { + return (p1.x - p3.x) * (p2.y - p3.y) - (p1.y - p3.y) * (p2.x - p3.x); + } + std::array t1, t2, t3, t4; + t1[0] = p1.x - p3.x; + t2[0] = p2.y - p3.y; + t3[0] = p1.y - p3.y; + t4[0] = p2.x - p3.x; + std::array t5_01, t6_01; + t5_01[0] = t1[0] * t2[0]; + t6_01[0] = t3[0] * t4[0]; + RealNumber det = t5_01[0] - t6_01[0]; + RealNumber const magnitude = std::abs(t5_01[0]) + std::abs(t6_01[0]); + + // see p.39, mind the different definition of epsilon for error bound + RealNumber const A_relative_bound = + (1.5 + 4 * std::numeric_limits::epsilon()) + * std::numeric_limits::epsilon(); + RealNumber absolute_bound = A_relative_bound * magnitude; + if ( std::abs(det) >= absolute_bound ) + { + return det; //A estimate + } + + if ( (t5_01[0] > 0 && t6_01[0] <= 0) || (t5_01[0] < 0 && t6_01[0] >= 0) ) + { + //if diagonal and antidiagonal have different sign, the sign of det is + //obvious + return det; + } + return orient2dtail(p1, p2, p3, t1, t2, t3, t4, t5_01, t6_01, magnitude); +} + +// This method adaptively computes increasingly precise approximations of the following +// determinant using Laplace expansion along the last column. +// det A = +// | p1_x - p4_x p1_y - p4_y ( p1_x - p4_x ) ^ 2 + ( p1_y - p4_y ) ^ 2 | +// | p2_x - p4_x p2_y - p4_y ( p2_x - p4_x ) ^ 2 + ( p1_y - p4_y ) ^ 2 | +// | p3_x - p4_x p3_y - p4_y ( p3_x - p4_x ) ^ 2 + ( p3_y - p4_y ) ^ 2 | +// = a_13 * C_13 + a_23 * C_23 + a_33 * C_33 +// where a_ij is the i-j-entry and C_ij is the i_j Cofactor + +template +< + typename RealNumber, + std::size_t Robustness = 2 +> +RealNumber incircle(std::array const& p1, + std::array const& p2, + std::array const& p3, + std::array const& p4) +{ + RealNumber A_11 = p1[0] - p4[0]; + RealNumber A_21 = p2[0] - p4[0]; + RealNumber A_31 = p3[0] - p4[0]; + RealNumber A_12 = p1[1] - p4[1]; + RealNumber A_22 = p2[1] - p4[1]; + RealNumber A_32 = p3[1] - p4[1]; + + std::array A_21_x_A_32, + A_31_x_A_22, + A_31_x_A_12, + A_11_x_A_32, + A_11_x_A_22, + A_21_x_A_12; + A_21_x_A_32[0] = A_21 * A_32; + A_31_x_A_22[0] = A_31 * A_22; + RealNumber A_13 = A_11 * A_11 + A_12 * A_12; + + A_31_x_A_12[0] = A_31 * A_12; + A_11_x_A_32[0] = A_11 * A_32; + RealNumber A_23 = A_21 * A_21 + A_22 * A_22; + + A_11_x_A_22[0] = A_11 * A_22; + A_21_x_A_12[0] = A_21 * A_12; + RealNumber A_33 = A_31 * A_31 + A_32 * A_32; + + RealNumber det = A_13 * (A_21_x_A_32[0] - A_31_x_A_22[0]) + + A_23 * (A_31_x_A_12[0] - A_11_x_A_32[0]) + + A_33 * (A_11_x_A_22[0] - A_21_x_A_12[0]); + if(Robustness == 0) return det; + + RealNumber magnitude = + (std::abs(A_21_x_A_32[0]) + std::abs(A_31_x_A_22[0])) * A_13 + + (std::abs(A_31_x_A_12[0]) + std::abs(A_11_x_A_32[0])) * A_23 + + (std::abs(A_11_x_A_22[0]) + std::abs(A_21_x_A_12[0])) * A_33; + RealNumber A_relative_bound = + (5 + 24 * std::numeric_limits::epsilon()) + * std::numeric_limits::epsilon(); + RealNumber absolute_bound = A_relative_bound * magnitude; + if (std::abs(det) > absolute_bound) + { + return det; + } + // (p2_x - p4_x) * (p3_y - p4_y) + A_21_x_A_32[1] = two_product_tail(A_21, A_32, A_21_x_A_32[0]); + // (p3_x - p4_x) * (p2_y - p4_y) + A_31_x_A_22[1] = two_product_tail(A_31, A_22, A_31_x_A_22[0]); + // (bx - dx) * (cy - dy) - (cx - dx) * (by - dy) + std::array C_13 = two_two_expansion_diff(A_21_x_A_32, A_31_x_A_22); + std::array C_13_x_A11; + // ( (bx - dx) * (cy - dy) - (cx - dx) * (by - dy) ) * ( ax - dx ) + int C_13_x_A11_nz = scale_expansion_zeroelim(C_13, A_11, C_13_x_A11); + std::array C_13_x_A11_sq; + // ( (bx - dx) * (cy - dy) - (cx - dx) * (by - dy) ) * ( ax - dx ) * (ax - dx) + int C_13_x_A11_sq_nz = scale_expansion_zeroelim(C_13_x_A11, + A_11, + C_13_x_A11_sq, + C_13_x_A11_nz); + + std::array C_13_x_A12; + // ( (bx - dx) * (cy - dy) - (cx - dx) * (by - dy) ) * ( ay - dy ) + int C_13_x_A12_nz = scale_expansion_zeroelim(C_13, A_12, C_13_x_A12); + + std::array C_13_x_A12_sq; + // ( (bx - dx) * (cy - dy) - (cx - dx) * (by - dy) ) * ( ay - dy ) * ( ay - dy ) + int C_13_x_A12_sq_nz = scale_expansion_zeroelim(C_13_x_A12, A_12, + C_13_x_A12_sq, + C_13_x_A12_nz); + + std::array A_13_x_C13; + // ( (bx - dx) * (cy - dy) - (cx - dx) * (by - dy) ) + // * ( ( ay - dy ) * ( ay - dy ) + ( ax - dx ) * (ax - dx) ) + int A_13_x_C13_nz = fast_expansion_sum_zeroelim(C_13_x_A11_sq, + C_13_x_A12_sq, + A_13_x_C13, + C_13_x_A11_sq_nz, + C_13_x_A12_sq_nz); + + // (cx - dx) * (ay - dy) + A_31_x_A_12[1] = two_product_tail(A_31, A_12, A_31_x_A_12[0]); + // (ax - dx) * (cy - dy) + A_11_x_A_32[1] = two_product_tail(A_11, A_32, A_11_x_A_32[0]); + // (cx - dx) * (ay - dy) - (ax - dx) * (cy - dy) + std::array C_23 = two_two_expansion_diff(A_31_x_A_12, + A_11_x_A_32); + std::array C_23_x_A_21; + // ( (cx - dx) * (ay - dy) - (ax - dx) * (cy - dy) ) * ( bx - dx ) + int C_23_x_A_21_nz = scale_expansion_zeroelim(C_23, A_21, C_23_x_A_21); + std::array C_23_x_A_21_sq; + // ( (cx - dx) * (ay - dy) - (ax - dx) * (cy - dy) ) * ( bx - dx ) * ( bx - dx ) + int C_23_x_A_21_sq_nz = scale_expansion_zeroelim(C_23_x_A_21, A_21, + C_23_x_A_21_sq, + C_23_x_A_21_nz); + std::array C_23_x_A_22; + // ( (cx - dx) * (ay - dy) - (ax - dx) * (cy - dy) ) * ( by - dy ) + int C_23_x_A_22_nz = scale_expansion_zeroelim(C_23, A_22, C_23_x_A_22); + std::array C_23_x_A_22_sq; + // ( (cx - dx) * (ay - dy) - (ax - dx) * (cy - dy) ) * ( by - dy ) * ( by - dy ) + int C_23_x_A_22_sq_nz = scale_expansion_zeroelim(C_23_x_A_22, A_22, + C_23_x_A_22_sq, + C_23_x_A_22_nz); + std::array A_23_x_C_23; + // ( (cx - dx) * (ay - dy) - (ax - dx) * (cy - dy) ) + // * ( ( bx - dx ) * ( bx - dx ) + ( by - dy ) * ( by - dy ) ) + int A_23_x_C_23_nz = fast_expansion_sum_zeroelim(C_23_x_A_21_sq, + C_23_x_A_22_sq, + A_23_x_C_23, + C_23_x_A_21_sq_nz, + C_23_x_A_22_sq_nz); + + // (ax - dx) * (by - dy) + A_11_x_A_22[1] = two_product_tail(A_11, A_22, A_11_x_A_22[0]); + // (bx - dx) * (ay - dy) + A_21_x_A_12[1] = two_product_tail(A_21, A_12, A_21_x_A_12[0]); + // (ax - dx) * (by - dy) - (bx - dx) * (ay - dy) + std::array C_33 = two_two_expansion_diff(A_11_x_A_22, + A_21_x_A_12); + std::array C_33_x_A31; + // ( (ax - dx) * (by - dy) - (bx - dx) * (ay - dy) ) * ( cx - dx ) + int C_33_x_A31_nz = scale_expansion_zeroelim(C_33, A_31, C_33_x_A31); + std::array C_33_x_A31_sq; + // ( (ax - dx) * (by - dy) - (bx - dx) * (ay - dy) ) * ( cx - dx ) * ( cx - dx ) + int C_33_x_A31_sq_nz = scale_expansion_zeroelim(C_33_x_A31, A_31, + C_33_x_A31_sq, + C_33_x_A31_nz); + std::array C_33_x_A_32; + // ( (ax - dx) * (by - dy) - (bx - dx) * (ay - dy) ) * ( cy - dy ) + int C_33_x_A_32_nz = scale_expansion_zeroelim(C_33, A_32, C_33_x_A_32); + std::array C_33_x_A_32_sq; + // ( (ax - dx) * (by - dy) - (bx - dx) * (ay - dy) ) * ( cy - dy ) * ( cy - dy ) + int C_33_x_A_32_sq_nz = scale_expansion_zeroelim(C_33_x_A_32, A_32, + C_33_x_A_32_sq, + C_33_x_A_32_nz); + + std::array A_33_x_C_33; + int A_33_x_C_33_nz = fast_expansion_sum_zeroelim(C_33_x_A31_sq, + C_33_x_A_32_sq, + A_33_x_C_33, + C_33_x_A31_sq_nz, + C_33_x_A_32_sq_nz); + std::array A_13_x_C13_p_A_13_x_C13; + int A_13_x_C13_p_A_13_x_C13_nz = fast_expansion_sum_zeroelim( + A_13_x_C13, A_23_x_C_23, + A_13_x_C13_p_A_13_x_C13, + A_13_x_C13_nz, + A_23_x_C_23_nz); + std::array det_expansion; + int det_expansion_nz = fast_expansion_sum_zeroelim( + A_13_x_C13_p_A_13_x_C13, + A_33_x_C_33, + det_expansion, + A_13_x_C13_p_A_13_x_C13_nz, + A_33_x_C_33_nz); + + det = std::accumulate(det_expansion.begin(), + det_expansion.begin() + det_expansion_nz, + static_cast(0)); + if(Robustness == 1) return det; + RealNumber B_relative_bound = + (2 + 12 * std::numeric_limits::epsilon()) + * std::numeric_limits::epsilon(); + absolute_bound = B_relative_bound * magnitude; + if (std::abs(det) >= absolute_bound) + { + return det; + } + RealNumber A_11tail = two_diff_tail(p1[0], p4[0], A_11); + RealNumber A_12tail = two_diff_tail(p1[1], p4[1], A_12); + RealNumber A_21tail = two_diff_tail(p2[0], p4[0], A_21); + RealNumber A_22tail = two_diff_tail(p2[1], p4[1], A_22); + RealNumber A_31tail = two_diff_tail(p3[0], p4[0], A_31); + RealNumber A_32tail = two_diff_tail(p3[1], p4[1], A_32); + if ((A_11tail == 0) && (A_21tail == 0) && (A_31tail == 0) + && (A_12tail == 0) && (A_22tail == 0) && (A_32tail == 0)) + { + return det; + } + // RealNumber sub_bound = (1.5 + 2.0 * std::numeric_limits::epsilon()) + // * std::numeric_limits::epsilon(); + // RealNumber C_relative_bound = (11.0 + 72.0 * std::numeric_limits::epsilon()) + // * std::numeric_limits::epsilon() + // * std::numeric_limits::epsilon(); + //absolute_bound = C_relative_bound * magnitude + sub_bound * std::abs(det); + det += ((A_11 * A_11 + A_12 * A_12) * ((A_21 * A_32tail + A_32 * A_21tail) + - (A_22 * A_31tail + A_31 * A_22tail)) + + 2 * (A_11 * A_11tail + A_12 * A_12tail) * (A_21 * A_32 - A_22 * A_31)) + + ((A_21 * A_21 + A_22 * A_22) * ((A_31 * A_12tail + A_12 * A_31tail) + - (A_32 * A_11tail + A_11 * A_32tail)) + + 2 * (A_21 * A_21tail + A_22 * A_22tail) * (A_31 * A_12 - A_32 * A_11)) + + ((A_31 * A_31 + A_32 * A_32) * ((A_11 * A_22tail + A_22 * A_11tail) + - (A_12 * A_21tail + A_21 * A_12tail)) + + 2 * (A_31 * A_31tail + A_32 * A_32tail) * (A_11 * A_22 - A_12 * A_21)); + //if (std::abs(det) >= absolute_bound) + //{ + return det; + //} +} + +}} // namespace detail::precise_math + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_EXTENSIONS_TRIANGULATION_STRATEGIES_CARTESIAN_DETAIL_PRECISE_MATH_HPP diff --git a/index/example/serialize.cpp b/index/example/serialize.cpp index 11ce08bc0..bc50371d5 100644 --- a/index/example/serialize.cpp +++ b/index/example/serialize.cpp @@ -1,7 +1,7 @@ // Boost.Geometry Index // Additional tests -// Copyright (c) 2011-2013 Adam Wulkiewicz, Lodz, Poland. +// Copyright (c) 2011-2021 Adam Wulkiewicz, Lodz, Poland. // Use, modification and distribution is subject to the Boost Software License, // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at @@ -25,13 +25,13 @@ #include #include -template ::value> +template ::value> struct print_tuple { template static inline Os & apply(Os & os, T const& t) { - os << boost::get(t) << ", "; + os << std::get(t) << ", "; return print_tuple::apply(os, t); } }; @@ -51,7 +51,7 @@ int main() namespace bg = boost::geometry; namespace bgi = bg::index; - typedef boost::tuple S; + typedef std::tuple S; typedef bg::model::point P; typedef bg::model::box

B; @@ -81,7 +81,7 @@ int main() std::cout << "vector and tree created in: " << t.elapsed() << std::endl; print_tuple::apply(std::cout, bgi::detail::rtree::utilities::statistics(tree)) << std::endl; - std::cout << boost::get<0>(s) << std::endl; + std::cout << std::get<0>(s) << std::endl; BOOST_FOREACH(V const& v, tree | bgi::adaptors::queried(bgi::intersects(q))) std::cout << bg::wkt(v) << std::endl; diff --git a/meta/libraries.json b/meta/libraries.json index a6648fc39..1ad723ca6 100644 --- a/meta/libraries.json +++ b/meta/libraries.json @@ -20,6 +20,7 @@ "The Boost.Geometry library provides geometric algorithms, primitives and spatial index.", "category": [ "Algorithms", "Data", "Math" - ] + ], + "cxxstd": "14" } ] diff --git a/test/algorithms/Jamfile b/test/algorithms/Jamfile index 0ff096c95..db2d1ce67 100644 --- a/test/algorithms/Jamfile +++ b/test/algorithms/Jamfile @@ -5,8 +5,8 @@ # Copyright (c) 2009-2015 Mateusz Loskot, London, UK. # Copyright (c) 2018 Adam Wulkiewicz, Lodz, Poland. # -# This file was modified by Oracle on 2014, 2015, 2016, 2017. -# Modifications copyright (c) 2014-2017, Oracle and/or its affiliates. +# This file was modified by Oracle on 2014-2021. +# Modifications copyright (c) 2014-2021, Oracle and/or its affiliates. # # Contributed and/or modified by Vissarion Fisikopoulos, on behalf of Oracle # Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle @@ -20,13 +20,12 @@ test-suite boost-geometry-algorithms : [ run append.cpp : : : : algorithms_append ] [ run assign.cpp : : : : algorithms_assign ] + [ run azimuth.cpp : : : : algorithms_azimuth ] [ run centroid.cpp : : : : algorithms_centroid ] [ run centroid_multi.cpp : : : : algorithms_centroid_multi ] [ run comparable_distance.cpp : : : : algorithms_comparable_distance ] [ run convert.cpp : : : : algorithms_convert ] [ run convert_multi.cpp : : : : algorithms_convert_multi ] - [ run convex_hull.cpp : : : : algorithms_convex_hull ] - [ run convex_hull_multi.cpp : : : : algorithms_convex_hull_multi ] [ run correct.cpp : : : : algorithms_correct ] [ run correct_multi.cpp : : : : algorithms_correct_multi ] [ run correct_closure.cpp : : : : algorithms_correct_closure ] @@ -67,6 +66,7 @@ test-suite boost-geometry-algorithms build-project area ; build-project buffer ; build-project covered_by ; +build-project convex_hull ; build-project crosses ; build-project detail ; build-project disjoint ; diff --git a/test/algorithms/area/area.cpp b/test/algorithms/area/area.cpp index 702d81818..478739d2a 100644 --- a/test/algorithms/area/area.cpp +++ b/test/algorithms/area/area.cpp @@ -27,10 +27,13 @@ #include #include +#include + #include #include //#define BOOST_GEOMETRY_TEST_DEBUG +#include #include template @@ -175,6 +178,70 @@ void test_large_integers() BOOST_CHECK_CLOSE(int_area, double_area, 0.0001); } +struct precise_cartesian : bg::strategies::detail::cartesian_base +{ + template + static auto area(Geometry const&) + { + return bg::strategy::area::precise_cartesian<>(); + } +}; + +void test_accurate_sum_strategy() +{ + typedef bg::model::point point_type; + typedef bg::model::point + < + boost::multiprecision::cpp_dec_float_50, + 2, + bg::cs::cartesian + > mp_point_type; + + auto const poly0_string = "POLYGON((0 0,0 1,1 0,0 0))"; + + bg::model::polygon poly0; + bg::read_wkt(poly0_string, poly0); + + BOOST_CHECK_CLOSE(bg::area(poly0), 0.5, 0.0001); + BOOST_CHECK_CLOSE(bg::area(poly0, precise_cartesian()), 0.5, 0.0001); + + bg::model::polygon mp_poly0; + bg::read_wkt(poly0_string, mp_poly0); + + BOOST_CHECK_CLOSE(bg::area(mp_poly0), 0.5, 0.0001); + + auto const poly1_string = "POLYGON((0.10000000000000001 0.10000000000000001,\ + 0.20000000000000001 0.20000000000000004,\ + 0.79999999999999993 0.80000000000000004,\ + 1.267650600228229e30 1.2676506002282291e30,\ + 0.10000000000000001 0.10000000000000001))"; + + bg::model::polygon poly1; + bg::read_wkt(poly1_string, poly1); + + BOOST_CHECK_CLOSE(bg::area(poly1), 0, 0.0001); + BOOST_CHECK_CLOSE(bg::area(poly1, precise_cartesian()), -0.315, 0.0001); + + bg::model::polygon mp_poly1; + bg::read_wkt(poly1_string, mp_poly1); + + BOOST_CHECK_CLOSE(bg::area(mp_poly1), 34720783012552.6, 0.0001); + + auto const poly2_string = "POLYGON((1.267650600228229e30 1.2676506002282291e30,\ + 0.8 0.8,0.2 0.2,0.1 0.1,1.267650600228229e30 1.2676506002282291e30))"; + + bg::model::polygon poly2; + bg::read_wkt(poly2_string, poly2); + + BOOST_CHECK_CLOSE(bg::area(poly2), 0, 0.0001); + BOOST_CHECK_CLOSE(bg::area(poly2, precise_cartesian()), 0.315, 0.0001); + + bg::model::polygon mp_poly2; + bg::read_wkt(poly2_string, mp_poly2); + + BOOST_CHECK_CLOSE(bg::area(mp_poly2), 35000000000000, 0.0001); +} + void test_variant() { typedef bg::model::point double_point_type; @@ -231,6 +298,8 @@ int test_main(int, char* []) test_variant(); + test_accurate_sum_strategy(); + // test_empty_input >(); return 0; diff --git a/test/algorithms/azimuth.cpp b/test/algorithms/azimuth.cpp new file mode 100644 index 000000000..541884771 --- /dev/null +++ b/test/algorithms/azimuth.cpp @@ -0,0 +1,88 @@ +// Boost.Geometry +// Unit Test + +// Copyright (c) 2021, Oracle and/or its affiliates. + +// 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 + + +#include + +#include + +#include + + +template +auto call_azimuth(P const& p1, P const& p2, S const& s) +{ + return bg::azimuth(p1, p2, s); +} + +template +auto call_azimuth(P const& p1, P const& p2, bg::default_strategy const&) +{ + return bg::azimuth(p1, p2); +} + +template +void test_one(P const& p1, P const& p2, double expected, S const& s = S()) +{ + double const result = call_azimuth(p1, p2, s) * bg::math::r2d(); + BOOST_CHECK_CLOSE(result, expected, 0.0001); +} + +template +void test_car() +{ + test_one(P(0, 0), P(0, 0), 0); + test_one(P(0, 0), P(1, 1), 45); + test_one(P(0, 0), P(100, 1), 89.427061302316517); + test_one(P(0, 0), P(-1, 1), -45); + test_one(P(0, 0), P(-100, 1), -89.427061302316517); +} + +template +void test_sph() +{ + test_one(P(0, 0), P(0, 0), 0); + test_one(P(0, 0), P(1, 1), 44.995636455344851); + test_one(P(0, 0), P(100, 1), 88.984576593576293); + test_one(P(0, 0), P(-1, 1), -44.995636455344851); + test_one(P(0, 0), P(-100, 1), -88.984576593576293); +} + +template +void test_geo() +{ + test_one(P(0, 0), P(0, 0), 0); + test_one(P(0, 0), P(1, 1), 45.187718848049521); + test_one(P(0, 0), P(100, 1), 88.986933066023497); + test_one(P(0, 0), P(-1, 1), -45.187718848049521); + test_one(P(0, 0), P(-100, 1), -88.986933066023497); +} + +template +void test_geo_v() +{ + bg::strategies::azimuth::geographic s; + + test_one(P(0, 0), P(0, 0), 0, s); + test_one(P(0, 0), P(1, 1), 45.188040229339755, s); + test_one(P(0, 0), P(100, 1), 88.986914518230208, s); + test_one(P(0, 0), P(-1, 1), -45.188040229339755, s); + test_one(P(0, 0), P(-100, 1), -88.986914518230208, s); +} + +int test_main(int, char* []) +{ + test_car< bg::model::point >(); + test_sph< bg::model::point > >(); + test_geo< bg::model::point > >(); + test_geo_v< bg::model::point > >(); + + return 0; +} diff --git a/test/algorithms/buffer/buffer_multi_point.cpp b/test/algorithms/buffer/buffer_multi_point.cpp index d2dc1b39b..4b6839405 100644 --- a/test/algorithms/buffer/buffer_multi_point.cpp +++ b/test/algorithms/buffer/buffer_multi_point.cpp @@ -3,6 +3,10 @@ // Copyright (c) 2012-2019 Barend Gehrels, Amsterdam, the Netherlands. +// This file was modified by Oracle on 2020. +// Modifications copyright (c) 2020 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) @@ -80,10 +84,10 @@ void test_all() 115057490003226.125, ut_settings(1.0)); { - typename bg::strategy::area::services::default_strategy + typename bg::strategies::relate::services::default_strategy < - typename bg::cs_tag

::type - >::type area_strategy; + multi_point_type, multi_point_type + >::type strategy; multi_point_type g; bg::read_wkt(mysql_report_3, g); @@ -94,7 +98,7 @@ void test_all() distance_strategy(1), side_strategy, bg::strategy::buffer::point_circle(36), - area_strategy, + strategy, 1, 0, 3.12566719800474635, ut_settings(1.0)); } } diff --git a/test/algorithms/buffer/buffer_multi_polygon.cpp b/test/algorithms/buffer/buffer_multi_polygon.cpp index 032b992f2..94535088b 100644 --- a/test/algorithms/buffer/buffer_multi_polygon.cpp +++ b/test/algorithms/buffer/buffer_multi_polygon.cpp @@ -346,6 +346,35 @@ static std::string const nores_wn_2 // Other cases with wrong turn information static std::string const nores_wt_1 = "MULTIPOLYGON(((0 4,0 5,1 4,0 4)),((9 3,9 4,10 4,9 3)),((9 7,10 8,10 7,9 7)),((6 7,7 8,7 7,6 7)),((0 7,0 8,1 8,0 7)),((3 6,4 6,4 5,3 4,3 6)),((3 7,2 6,2 7,3 7)),((3 7,3 8,4 8,4 7,3 7)),((3 3,4 4,4 3,3 3)),((3 3,3 2,2 2,2 3,3 3)),((2 6,2 5,1 5,1 6,2 6)),((6 4,6 3,5 3,5 4,6 4)),((6 4,7 5,7 4,6 4)),((5 1,4 0,4 1,5 1)),((5 1,5 2,6 2,6 1,5 1)))"; +static std::string const nores_wt_2 + = "MULTIPOLYGON(((1 1,2 2,2 1,1 1)),((0 2,0 3,1 3,0 2)),((4 3,5 4,5 3,4 3)),((4 3,3 3,4 4,4 3)))"; + +static std::string const nores_b8e6 + = "MULTIPOLYGON(((4 4,5 5,5 4,4 4)),((4 2,5 2,5 1,3 1,4 2)),((3 1,4 0,3 0,3 1)))"; +static std::string const nores_2881 + = "MULTIPOLYGON(((2 5,2 6,3 5,2 5)),((1 7,0 7,0 8,1 8,1 7)),((1 7,1 6,0 6,1 7)))"; +static std::string const nores_3af0 + = "MULTIPOLYGON(((1 8,0 8,0 9,1 9,1 8)),((1 8,1 7,0 7,1 8)),((2 4,3 5,3 4,2 4)),((2 6,2 7,3 6,2 6)))"; +static std::string const nores_6061 + = "MULTIPOLYGON(((2 8,2 9,3 8,2 8)),((4 3,4 4,5 4,4 3)),((7 2,7 3,8 2,7 2)),((5 3,6 4,6 3,5 3)),((2 6,3 7,3 6,2 6)),((2 3,3 2,3 1,2 1,2 3)),((2 3,3 4,3 3,2 3)))"; + +static std::string const nores_1ea1 + = "MULTIPOLYGON(((2 0,2 1,3 0,2 0)),((7 5,6 4,5 3,5 4,5 5,7 5)),((2 3,1 3,1 4,2 3)),((2 3,2 4,3 3,2 3)))"; +static std::string const nores_804e + = "MULTIPOLYGON(((4 8,4 9,5 8,4 8)),((3 9,3 10,4 10,3 9)),((0 7,0 8,1 7,0 7)),((4 6,3 6,3 7,4 6)),((4 6,4 7,5 7,4 6)))"; +static std::string const nores_37f6 + = "MULTIPOLYGON(((4 1,5 2,5 1,4 1)),((1 0,1 1,2 1,2 0,1 0)),((0 3,0 4,1 4,1 3,0 3)),((2 2,2 3,3 2,2 2)))"; + +static std::string const nores_495d + = "MULTIPOLYGON(((2 0,2 1,3 0,2 0)),((2 3,3 4,3 3,2 3)),((5 1,5 2,6 2,5 1)),((4 3,4 2,3 2,4 3)))"; + +// rescaled +static std::string const res_ebc4 + = "MULTIPOLYGON(((3 9,3 10,4 9,3 9)),((9 5,9 6,10 6,10 5,9 5)),((8 8,8 9,9 9,8 8)),((4 8,3 7,3 8,4 8)),((4 8,5 9,6 9,6 8,4 8)),((4 5,3 4,3 5,4 5)),((4 5,5 6,5 5,4 5)))"; +static std::string const res_8618 + = "MULTIPOLYGON(((6 2,7 3,7 2,6 2)),((4 3,5 4,5 3,4 3)),((3 0,3 1,4 0,3 0)),((8 7,8 8,9 8,8 7)),((0 7,0 8,1 8,1 7,0 7)),((2 2,1 2,1 3,1 4,2 4,2 2)),((2 2,2 1,1 1,2 2)))"; +static std::string const res_3b4d + = "MULTIPOLYGON(((8 0,9 1,9 0,8 0)),((3 4,2 4,2 5,2 6,3 6,3 4)),((3 4,4 3,3 3,3 4)),((3 8,3 9,4 9,3 8)),((0 5,0 6,1 6,0 5)),((7 3,8 4,8 3,7 3)),((5 5,6 6,6 5,5 5)))"; static std::string const neighbouring @@ -482,7 +511,6 @@ void test_all() test_one("rt_p3", rt_p3, join_miter, end_flat, 22.3995, 1.0); test_one("rt_p4", rt_p4, join_miter, end_flat, 33.0563, 1.0); test_one("rt_p5", rt_p5, join_miter, end_flat, 17.0, 1.0); - test_one("rt_p6", rt_p6, join_miter, end_flat, 18.4853, 1.0); test_one("rt_p7", rt_p7, join_miter, end_flat, 26.2279, 1.0); test_one("rt_p8", rt_p8, join_miter, end_flat, 29.0563, 1.0); @@ -558,22 +586,37 @@ void test_all() test_one("nores_mt_6", nores_mt_6, join_round32, end_flat, 16.9018, 1.0); test_one("nores_et_1", nores_et_1, join_round32, end_flat, 18.9866, 1.0); - -#if defined(BOOST_GEOMETRY_USE_RESCALING) || defined(BOOST_GEOMETRY_TEST_FAILURES) test_one("nores_et_2", nores_et_2, join_round32, end_flat, 23.8389, 1.0); test_one("nores_et_3", nores_et_3, join_round32, end_flat, 26.9030, 1.0); -#endif - test_one("nores_et_4", nores_et_4, join_round32, end_flat, 19.9626, 1.0); test_one("nores_et_5", nores_et_5, join_round32, end_flat, 19.9615, 1.0); + test_one("nores_et_6", nores_et_6, join_round32, end_flat, 96.1795, 1.0); + test_one("nores_et_7", nores_et_7, join_round32, end_flat, 105.9577, 1.0); test_one("nores_wn_1", nores_wn_1, join_round32, end_flat, 23.7659, 1.0); test_one("nores_wn_2", nores_wn_2, join_round32, end_flat, 18.2669, 1.0); -#if defined(BOOST_GEOMETRY_USE_RESCALING) || defined(BOOST_GEOMETRY_TEST_FAILURES) - test_one("nores_et_6", nores_et_6, join_round32, end_flat, 96.1795, 1.0); - test_one("nores_et_7", nores_et_7, join_round32, end_flat, 105.9577, 1.0); test_one("nores_wt_1", nores_wt_1, join_round32, end_flat, 80.1609, 1.0); + test_one("nores_wt_2", nores_wt_2, join_round32, end_flat, 22.1102, 1.0); + test_one("nores_b8e6", nores_b8e6, join_round32, end_flat, 19.8528, 1.0); + + test_one("nores_2881", nores_2881, join_round32, end_flat, 16.5517, 1.0); + test_one("nores_6061", nores_6061, join_round32, end_flat, 39.7371, 1.0); + test_one("nores_37f6", nores_37f6, join_round32, end_flat, 26.5339, 1.0); + +#if defined(BOOST_GEOMETRY_USE_RESCALING) || defined(BOOST_GEOMETRY_TEST_FAILURES) + // Cases not yet solved without rescaling (out of 241) + test_one("nores_1ea1", nores_1ea1, join_round32, end_flat, 28.9755, 1.0); + test_one("nores_804e", nores_804e, join_round32, end_flat, 26.4503, 1.0); + test_one("nores_3af0", nores_3af0, join_round32, end_flat, 22.1008, 1.0); + test_one("nores_495d", nores_495d, join_round32, end_flat, 23.4376, 1.0); +#endif + +#if ! defined(BOOST_GEOMETRY_USE_RESCALING) || defined(BOOST_GEOMETRY_TEST_FAILURES) + // Erroneous cases with rescaling (out of 8) + test_one("res_ebc4", res_ebc4, join_round32, end_flat, 43.8877, 1.0); + test_one("res_8618", res_8618, join_round32, end_flat, 48.1085, 1.0); + test_one("res_3b4d", res_3b4d, join_round32, end_flat, 48.4739, 1.0); #endif test_one("neighbouring_small", @@ -619,7 +662,7 @@ int test_main(int, char* []) #endif #if defined(BOOST_GEOMETRY_TEST_FAILURES) - BoostGeometryWriteExpectedFailures(1, 8, 2, 7); + BoostGeometryWriteExpectedFailures(4, 6, 3, 8); #endif return 0; diff --git a/test/algorithms/buffer/buffer_piece_border.cpp b/test/algorithms/buffer/buffer_piece_border.cpp index fd0e8f72d..9626d2bf9 100644 --- a/test/algorithms/buffer/buffer_piece_border.cpp +++ b/test/algorithms/buffer/buffer_piece_border.cpp @@ -103,10 +103,11 @@ Border setup_piece_border(Ring& ring, Ring& original, typedef typename bg::point_type::type point_type; - border.get_properties_of_border(false, point_type()); + bg::strategies::relate::cartesian<> strategy; - bg::strategy::side::side_by_triangle<> side_strategy; - border.get_properties_of_offsetted_ring_part(side_strategy); + border.get_properties_of_border(false, point_type(), strategy); + + border.get_properties_of_offsetted_ring_part(strategy); return border; } diff --git a/test/algorithms/buffer/test_buffer.hpp b/test/algorithms/buffer/test_buffer.hpp index 3f1581635..1042b3e03 100644 --- a/test/algorithms/buffer/test_buffer.hpp +++ b/test/algorithms/buffer/test_buffer.hpp @@ -3,8 +3,8 @@ // Copyright (c) 2010-2019 Barend Gehrels, Amsterdam, the Netherlands. -// This file was modified by Oracle on 2016-2017. -// Modifications copyright (c) 2016-2017, Oracle and/or its affiliates. +// This file was modified by Oracle on 2016-2020. +// Modifications copyright (c) 2016-2020, 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, @@ -137,7 +137,7 @@ template typename DistanceStrategy, typename SideStrategy, typename PointStrategy, - typename AreaStrategy, + typename Strategy, typename Geometry > void test_buffer(std::string const& caseid, @@ -148,7 +148,7 @@ void test_buffer(std::string const& caseid, DistanceStrategy const& distance_strategy, SideStrategy const& side_strategy, PointStrategy const& point_strategy, - AreaStrategy const& area_strategy, + Strategy const& strategy, int expected_count, int expected_holes_count, expectation_limits const& expected_area, @@ -177,7 +177,7 @@ void test_buffer(std::string const& caseid, } else { - bg::envelope(geometry, envelope); + bg::envelope(geometry, envelope, strategy); } std::string join_name = JoinTestProperties::name(); @@ -233,20 +233,12 @@ void test_buffer(std::string const& caseid, typedef typename bg::point_type::type point_type; typedef typename bg::rescale_policy_type::type rescale_policy_type; - typedef typename bg::strategy::intersection::services::default_strategy - < - typename bg::cs_tag::type - >::type strategy_type; - typedef typename strategy_type::envelope_strategy_type envelope_strategy_type; - + // Enlarge the box to get a proper rescale policy bg::buffer(envelope, envelope, distance_strategy.max_distance(join_strategy, end_strategy)); - strategy_type strategy; rescale_policy_type rescale_policy - = bg::get_rescale_policy(envelope); - - envelope_strategy_type envelope_strategy; + = bg::get_rescale_policy(envelope, strategy); buffered.clear(); bg::detail::buffer::buffer_inserter(geometry, @@ -285,7 +277,7 @@ void test_buffer(std::string const& caseid, bg::model::box envelope_output; bg::assign_values(envelope_output, 0, 0, 1, 1); - bg::envelope(buffered, envelope_output, envelope_strategy); + bg::envelope(buffered, envelope_output, strategy); // std::cout << caseid << std::endl; // std::cout << "INPUT: " << bg::wkt(geometry) << std::endl; @@ -318,8 +310,7 @@ void test_buffer(std::string const& caseid, if (settings.test_area) { - typename bg::default_area_result::type area - = bg::area(buffered, area_strategy); + auto const area = bg::area(buffered, strategy); BOOST_CHECK_MESSAGE(expected_area.contains(area, settings.tolerance, settings.use_ln_area), "difference: " << caseid << std::setprecision(20) << " #area expected: " << expected_area @@ -376,14 +367,14 @@ void test_buffer(std::string const& caseid, bg::model::multi_polygon::type - >::type area_strategy; + Geometry, Geometry + >::type strategy; test_buffer(caseid, buffered, geometry, join_strategy, end_strategy, distance_strategy, side_strategy, point_strategy, - area_strategy, + strategy, -1, -1, expected_area, settings); } @@ -432,17 +423,17 @@ void test_one(std::string const& caseid, std::string const& wkt, bg::math::equals(distance_right, same_distance) ? distance_left : distance_right); - typename bg::strategy::area::services::default_strategy + typename bg::strategies::relate::services::default_strategy < - typename bg::cs_tag::type - >::type area_strategy; + Geometry, Geometry + >::type strategy; bg::model::multi_polygon buffered; test_buffer (caseid, buffered, g, join_strategy, end_strategy, distance_strategy, side_strategy, circle_strategy, - area_strategy, + strategy, expected_count, expected_holes_count, expected_area, settings); @@ -463,7 +454,7 @@ void test_one(std::string const& caseid, std::string const& wkt, (caseid + "_sym", buffered, g, join_strategy, end_strategy, sym_distance_strategy, side_strategy, circle_strategy, - area_strategy, + strategy, expected_count, expected_holes_count, expected_area, settings); diff --git a/test/algorithms/buffer/test_buffer_geo.hpp b/test/algorithms/buffer/test_buffer_geo.hpp index efeeee1e2..c7342716f 100644 --- a/test/algorithms/buffer/test_buffer_geo.hpp +++ b/test/algorithms/buffer/test_buffer_geo.hpp @@ -3,6 +3,10 @@ // Copyright (c) 2018-2019 Barend Gehrels, Amsterdam, the Netherlands. +// This file was modified by Oracle on 2020. +// Modifications copyright (c) 2020 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) @@ -44,11 +48,11 @@ void test_one_geo(std::string const& caseid, // Use Thomas strategy to calculate geographic area, because it is // the most precise (unless scale of buffer is only around 1 meter) - bg::strategy::area::geographic - < - bg::strategy::thomas, 5, - bg::srs::spheroid, long double - > area_strategy; + bg::strategies::relate::geographic + < + bg::strategy::thomas, 5, + bg::srs::spheroid, long double + > strategy; bg::model::multi_polygon buffer; @@ -56,7 +60,7 @@ void test_one_geo(std::string const& caseid, (caseid, buffer, input_geometry, join_strategy, end_strategy, distance_strategy, side_strategy, circle_strategy, - area_strategy, + strategy, expected_count, expected_holes_count, expected_area, settings); } diff --git a/test/algorithms/buffer/test_buffer_svg.hpp b/test/algorithms/buffer/test_buffer_svg.hpp index 2c7db78ce..9d0fb9f85 100644 --- a/test/algorithms/buffer/test_buffer_svg.hpp +++ b/test/algorithms/buffer/test_buffer_svg.hpp @@ -2,6 +2,11 @@ // Unit Test Helper // Copyright (c) 2010-2015 Barend Gehrels, Amsterdam, the Netherlands. + +// This file was modified by Oracle on 2020. +// Modifications copyright (c) 2020 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) @@ -207,7 +212,8 @@ private : } #endif - bg::model::ring const& corner = piece.m_piece_border.get_full_ring(); + // NOTE: ring is returned by copy here + auto const& corner = piece.m_piece_border.get_full_ring(); if (m_zoom && do_pieces) { diff --git a/test/algorithms/convex_hull/Jamfile b/test/algorithms/convex_hull/Jamfile new file mode 100644 index 000000000..5bc795811 --- /dev/null +++ b/test/algorithms/convex_hull/Jamfile @@ -0,0 +1,17 @@ +# Boost.Geometry (aka GGL, Generic Geometry Library) +# +# Copyright (c) 2020 Oracle and/or its affiliates. +# +# Contributed and/or modified by Vissarion Fisikopoulos, 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) + +test-suite boost-geometry-algorithms-convex_hull + : + [ run convex_hull.cpp : : : : algorithms_convex_hull ] + [ run convex_hull_multi.cpp : : : : algorithms_convex_hull_multi ] + [ run convex_hull_robust.cpp : : : : algorithms_convex_hull_robust ] + [ run convex_hull_sph_geo.cpp : : : : algorithms_convex_hull_sph_geo ] + ; diff --git a/test/algorithms/convex_hull.cpp b/test/algorithms/convex_hull/convex_hull.cpp similarity index 78% rename from test/algorithms/convex_hull.cpp rename to test/algorithms/convex_hull/convex_hull.cpp index 27d1d7234..0332c1f1e 100644 --- a/test/algorithms/convex_hull.cpp +++ b/test/algorithms/convex_hull/convex_hull.cpp @@ -20,7 +20,7 @@ #include #include -#include +#include "test_convex_hull.hpp" #include #include @@ -29,43 +29,45 @@ template void test_all() { + typedef boost::geometry::strategies::convex_hull::cartesian<> strategy; + // from sample linestring - test_geometry >( + test_geometry, strategy >( "linestring(1.1 1.1, 2.5 2.1, 3.1 3.1, 4.9 1.1, 3.1 1.9)", 5, 4, 3.8); // rectangular, with concavity - test_geometry >( + test_geometry, strategy >( "polygon((1 1, 1 4, 3 4, 3 3, 4 3, 4 4, 5 4, 5 1, 1 1))", 9, 5, 12.0); // from sample polygon, with concavity - test_geometry >( + test_geometry, strategy >( "polygon((2.0 1.3, 2.4 1.7, 2.8 1.8, 3.4 1.2, 3.7 1.6,3.4 2.0, 4.1 3.0" ", 5.3 2.6, 5.4 1.2, 4.9 0.8, 2.9 0.7,2.0 1.3))", 12, 8, 5.245); - test_geometry >( + test_geometry, strategy >( "polygon((2.0 1.3, 2.4 1.7, 2.8 1.8, 3.4 1.2, 3.7 1.6,3.4 2.0, 4.1 3.0" ", 5.3 2.6, 5.4 1.2, 4.9 0.8, 2.9 0.7,2.0 1.3))", 12, 8, 5.245); - test_geometry >("box(0 0,2 2)", 4, 5, 4); + test_geometry, strategy >("box(0 0,2 2)", 4, 5, 4); // https://svn.boost.org/trac/boost/ticket/6443 { - test_geometry >( + test_geometry, strategy >( "polygon((0 0, 2 0))", // note that this polygon is very invalid 2, 4, 0, 4); } // degenerated hulls - test_geometry >( + test_geometry, strategy >( "multipoint(0 0)", 1, 4, 0, 0); - test_geometry >( + test_geometry, strategy >( "multipoint(0 0, 2 0)", 2, 4, 0, 4); - test_geometry >( + test_geometry, strategy >( "linestring(0 0, 2 0)", 2, 4, 0, 4); diff --git a/test/algorithms/convex_hull_multi.cpp b/test/algorithms/convex_hull/convex_hull_multi.cpp similarity index 63% rename from test/algorithms/convex_hull_multi.cpp rename to test/algorithms/convex_hull/convex_hull_multi.cpp index e36041329..a0b93a9bc 100644 --- a/test/algorithms/convex_hull_multi.cpp +++ b/test/algorithms/convex_hull/convex_hull_multi.cpp @@ -21,7 +21,7 @@ #include #include -#include +#include "test_convex_hull.hpp" #include #include @@ -43,33 +43,38 @@ template void test_all() { + typedef boost::geometry::strategies::convex_hull::cartesian<> strategy; + typedef bg::model::multi_point

mp; typedef bg::model::multi_linestring > ml; typedef bg::model::multi_polygon > mpoly; // All points below in upper-points and lower-points - test_geometry("MULTIPOINT((0 0),(5 0),(1 1),(4 1))", 0, 5, 4.0); - test_geometry("MULTIPOINT((0 1),(5 1),(1 0),(4 0))", 0, 5, 4.0); + test_geometry("MULTIPOINT((0 0),(5 0),(1 1),(4 1))", 0, 5, 4.0); + test_geometry("MULTIPOINT((0 1),(5 1),(1 0),(4 0))", 0, 5, 4.0); - // All points in vertical line (this delivers an empty polygon with 3 points and closing point for closed) - test_geometry("MULTIPOINT((1 0),(5 0),(3 0),(4 0),(2 0))", 0, 4, 0.0); + // All points in vertical line (this delivers an empty polygon with 3 points + // and closing point for closed) + test_geometry("MULTIPOINT((1 0),(5 0),(3 0),(4 0),(2 0))", 0, 4, 0.0); // One point only - test_geometry("MULTIPOINT((1 0))", 0, 4, 0.0); + test_geometry("MULTIPOINT((1 0))", 0, 4, 0.0); // Problem of 6019, reproduced by the convex hull robustness test: - test_geometry("MULTIPOINT((2 9),(1 3),(9 4),(1 1),(1 0),(7 9),(2 5),(3 7),(3 6),(2 4))", + test_geometry("MULTIPOINT((2 9),(1 3),(9 4),(1 1),(1 0),(7 9),(2 5),(3 7),(3 6),(2 4))", 0, 6, 48.0); // Ticket 6019: - test_geometry("MULTIPOINT((0 53),(0 103),(0 53),(0 3),(0 3),(0 0),(1 0),(1 1),(2 1),(2 0),(2 0),(2 0),(3 0),(3 1),(4 1),(4 0),(5 0),(0 3),(10 3),(10 2),(10 2),(10 2),(5 2),(5 0),(5 0),(55 0),(105 0))", + test_geometry("MULTIPOINT((0 53),(0 103),(0 53),(0 3),(0 3),(0 0),(1 0),\ + (1 1),(2 1),(2 0),(2 0),(2 0),(3 0),(3 1),(4 1),(4 0),(5 0),(0 3),\ + (10 3),(10 2),(10 2),(10 2),(5 2),(5 0),(5 0),(55 0),(105 0))", 0, 4, 5407.5); // Ticket 6021: - test_geometry("multipoint((0 53), (0 103), (1 53))", 3, 4, 25); + test_geometry("multipoint((0 53), (0 103), (1 53))", 3, 4, 25); - test_geometry("multipoint((1.1 1.1), (2.5 2.1), (3.1 3.1), (4.9 1.1), (3.1 1.9))", 5, 4, 3.8); - test_geometry("multilinestring((2 4, 3 4, 3 5), (4 3,4 4,5 4))", 6, 5, 3.0); - test_geometry("multipolygon(((1 4,1 6,2 5,3 5,4 6,4 4,1 4)), ((4 2,4 3,6 3,6 2,4 2)))", 12, 7, 14.0); + test_geometry("multipoint((1.1 1.1), (2.5 2.1), (3.1 3.1), (4.9 1.1), (3.1 1.9))", 5, 4, 3.8); + test_geometry("multilinestring((2 4, 3 4, 3 5), (4 3,4 4,5 4))", 6, 5, 3.0); + test_geometry("multipolygon(((1 4,1 6,2 5,3 5,4 6,4 4,1 4)), ((4 2,4 3,6 3,6 2,4 2)))", 12, 7, 14.0); test_empty_input(); test_empty_input(); diff --git a/test/algorithms/convex_hull/convex_hull_robust.cpp b/test/algorithms/convex_hull/convex_hull_robust.cpp new file mode 100644 index 000000000..9ee6e55f4 --- /dev/null +++ b/test/algorithms/convex_hull/convex_hull_robust.cpp @@ -0,0 +1,109 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) +// Unit Test + +// Copyright (c) 2020 Oracle and/or its affiliates. +// Contributed and/or modified by Vissarion Fisikopoulos, on behalf of Oracle + +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#include +#include + +#include "test_convex_hull.hpp" + +#include +#include + +#include + +template +void test_all() +{ + typedef bg::model::d2::point_xy P; + typedef bg::model::d2::point_xy Pmp; + + // from sample polygon, with concavity + auto polygon_wkt0 = "polygon((2.0 1.3, 2.4 1.7, 2.8 1.8, 3.4 1.2, 3.7 1.6,\ + 3.4 2.0, 4.1 3.0, 5.3 2.6, 5.4 1.2, 4.9 0.8, 2.9 0.7,2.0 1.3))"; + test_geometry, robust_cartesian>( + polygon_wkt0, 12, 8, 5.245); + test_geometry, non_robust_cartesian_sbt>( + polygon_wkt0, 12, 8, 5.245); + test_geometry, non_robust_cartesian_fast>( + polygon_wkt0, 12, 8, 5.245); + test_geometry, non_robust_cartesian_sbt>( + polygon_wkt0, 12, 8, 5.245); + + // some colinear cases are ok with non robust predicate + auto polygon_wkt1 = "polygon((0.50000000000001621 0.50000000000001243,\ + 7.3000000000000173 7.3000000000000167,\ + 24.00000000000005 24.000000000000053,\ + 24.000000000000068 24.000000000000071,\ + 0 1,8 4,25 26,26 25,19 11))"; + test_geometry, robust_cartesian >( + polygon_wkt1, 9, 7, 137.25); + test_geometry, non_robust_cartesian_sbt >( + polygon_wkt1, 9, 7, 137.25); + test_geometry, non_robust_cartesian_fast >( + polygon_wkt1, 9, 7, 137.25); + test_geometry, non_robust_cartesian_sbt >( + polygon_wkt1, 9, 7, 137.25); + + // slightly non-convex result but areas equal + auto polygon_wkt2 = "polygon((27.643564356435643 -21.881188118811881,\ + 83.366336633663366 15.544554455445542,\ + 4.0 4.0,\ + 73.415841584158414 8.8613861386138595,\ + 27.643564356435643 -21.881188118811881))"; + test_geometry, robust_cartesian >( + polygon_wkt2, 5, 4, 1163.5247524752476); + test_geometry, non_robust_cartesian_sbt >( + polygon_wkt2, 5, 5, 1163.5247524752476); + test_geometry, non_robust_cartesian_fast >( + polygon_wkt2, 5, 4, 1163.5247524752476); + test_geometry, non_robust_cartesian_sbt >( + polygon_wkt2, 5, 4, 1163.5247524752476); + + // wrong orientation / sign in area + // here non_robust_cartesian_sbt computes wrong result with mp arithmetic + // correct results double checked with CGAL 5.1 + auto polygon_wkt3 = "polygon((200.0 49.200000000000003,\ + 100.0 49.600000000000001,\ + -233.33333333333334 50.93333333333333,\ + 166.66666666666669 49.333333333333336,\ + 200.0 49.200000000000003))"; + test_geometry, robust_cartesian, precise_cartesian >( + polygon_wkt3, 5, 4, 1.4210854715202004e-14); + test_geometry, non_robust_cartesian_sbt, precise_cartesian >( + polygon_wkt3, 5, 4, -1.4210854715202004e-14); + test_geometry, non_robust_cartesian_fast, precise_cartesian >( + polygon_wkt3, 5, 4, 1.4210854715202004e-14); + test_geometry, non_robust_cartesian_sbt >( + polygon_wkt3, 5, 5, 1.69333333333333265e-13); + + // missing one point could lead in arbitrary large errors in area + auto polygon_wkt4 = "polygon((0.10000000000000001 0.10000000000000001,\ + 0.20000000000000001 0.20000000000000004,\ + 0.79999999999999993 0.80000000000000004,\ + 1.267650600228229e30 1.2676506002282291e30,\ + 0.10000000000000001 0.10000000000000001))"; + test_geometry, robust_cartesian, precise_cartesian>( + polygon_wkt4, 5, 5, -0.315); + test_geometry, non_robust_cartesian_sbt, precise_cartesian>( + polygon_wkt4, 5, 4, 0); + test_geometry, non_robust_cartesian_fast, precise_cartesian>( + polygon_wkt4, 5, 4, -0.015); + test_geometry, non_robust_cartesian_sbt>( + polygon_wkt4, 5, 5, 3.472078301e+13); +} + + +int test_main(int, char* []) +{ + using boost::multiprecision::cpp_dec_float_50; + test_all(); + + return 0; +} diff --git a/test/algorithms/convex_hull/convex_hull_sph_geo.cpp b/test/algorithms/convex_hull/convex_hull_sph_geo.cpp new file mode 100644 index 000000000..277c3ae8c --- /dev/null +++ b/test/algorithms/convex_hull/convex_hull_sph_geo.cpp @@ -0,0 +1,77 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) +// Unit Test + +// Copyright (c) 2020 Oracle and/or its affiliates. +// Contributed and/or modified by Vissarion Fisikopoulos, on behalf of Oracle + +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#include +#include + +#include "test_convex_hull.hpp" + +#include +#include + + +void test_all() +{ + typedef bg::model::point > + SphericalPoint; + typedef bg::model::point > GeoPoint; + + test_geometry_sph_geo + < + bg::model::polygon, + bg::model::polygon + >("polygon((0 0,2 1,2 -1,0 0))", 4, 4, + 0.00060931217091786914, 24621363089.253811); + + test_geometry_sph_geo + < + bg::model::polygon, + bg::model::polygon + >("polygon((0 0,1 1,0 1,0 0))", 4, 4, + 0.00015229324228191774, 6153992621.4098225); + + //polygon crossing antimeridian + test_geometry_sph_geo + < + bg::model::polygon, + bg::model::polygon + >("polygon((359 0,1 1,1 -1,359 0))", 4, 4, + 0.00060931217091786914, 24621363089.253811); + + test_geometry_sph_geo + < + bg::model::polygon, + bg::model::polygon + >("polygon((1 1, 1 4, 3 4, 3 3, 4 3, 4 4, 5 4, 5 1, 1 1))", + 9, 5, 0.003652987070377825, 147615606532.65408); + + // calculate convex hull with a non-default spherical side strategy + test_geometry + < + bg::model::polygon, + sphrerical_side_by_cross_track<> + >("polygon((359 0,1 1,1 -1,359 0))", 4, 4, + 0.00060931217091786914); + + test_empty_input>(); + test_empty_input>(); + test_empty_input>(); + + test_empty_input>(); + test_empty_input>(); + test_empty_input>(); +} + +int test_main(int, char* []) +{ + test_all(); + + return 0; +} diff --git a/test/algorithms/convex_hull/test_convex_hull.hpp b/test/algorithms/convex_hull/test_convex_hull.hpp new file mode 100644 index 000000000..df1b959b0 --- /dev/null +++ b/test/algorithms/convex_hull/test_convex_hull.hpp @@ -0,0 +1,347 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) +// Unit Test + +// 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. + +// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle +// Contributed and/or modified by Menelaos Karavelas, 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_TEST_CONVEX_HULL_HPP +#define BOOST_GEOMETRY_TEST_CONVEX_HULL_HPP + +#include + +#include + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include + +#include + +#include + + +struct robust_cartesian : boost::geometry::strategies::detail::cartesian_base +{ + static auto side() + { + return boost::geometry::strategy::side::side_robust<>(); + } +}; + +struct non_robust_cartesian_fast : boost::geometry::strategies::detail::cartesian_base +{ + static auto side() + { + return boost::geometry::strategy::side::side_non_robust<>(); + } +}; + +struct non_robust_cartesian_sbt : boost::geometry::strategies::detail::cartesian_base +{ + static auto side() + { + return boost::geometry::strategy::side::side_by_triangle<>(); + } +}; + +template +struct sphrerical_side_by_cross_track : boost::geometry::strategies::detail::spherical_base +{ + static auto side() + { + return boost::geometry::strategy::side::side_by_cross_track<>(); + } +}; + +struct precise_cartesian : boost::geometry::strategies::detail::cartesian_base +{ + template + static auto area(Geometry const&) + { + return boost::geometry::strategy::area::precise_cartesian<>(); + } +}; + + +template +void check_convex_hull(Geometry const& geometry, Hull const& hull, + std::size_t /*size_original*/, std::size_t size_hull, + double expected_area, double expected_perimeter, + bool reverse, AreaStrategy area_strategy) +{ + std::size_t n = bg::num_points(hull); + + BOOST_CHECK_MESSAGE(n == size_hull, + "convex hull: " << bg::wkt(geometry) + << " -> " << bg::wkt(hull) + << " type " + << (typeid(typename bg::coordinate_type::type).name()) + << " -> Expected: " << size_hull + << " detected: " << n); + + + // We omit this check as it is not important for the hull algorithm + // BOOST_CHECK(bg::num_points(geometry) == size_original); + + auto ah = bg::area(hull, area_strategy); + + if (reverse) + { + ah = -ah; + } + + BOOST_CHECK_CLOSE(ah, expected_area, 0.001); + + if ( expected_perimeter >= 0 ) + { + auto ph = bg::perimeter(hull); + + BOOST_CHECK_CLOSE(ph, expected_perimeter, 0.001); + } +} + +namespace resolve_variant { + +struct closure_visitor : public boost::static_visitor +{ + template + bg::closure_selector operator()(Geometry const&) const + { + return bg::closure::value; + } +}; + +template +inline bg::closure_selector get_closure(Geometry const&) +{ + return bg::closure::value; +} + +template +inline bg::closure_selector get_closure(boost::variant const& v) +{ + return boost::apply_visitor(closure_visitor(), v); +} + +} // namespace resolve_variant + + +template +< + typename Hull, + typename Strategy, + typename AreaStrategy +> +struct test_convex_hull +{ + template + static void apply(Geometry const& geometry, + std::size_t size_original, + std::size_t size_hull_closed, + double expected_area, + double expected_perimeter, + bool reverse) + { + bool const is_original_closed = resolve_variant::get_closure(geometry) != bg::open; + static bool const is_hull_closed = bg::closure::value != bg::open; + + // convex_hull_insert() uses the original Geometry as a source of the info + // about the order and closure + std::size_t const size_hull_from_orig = is_original_closed ? + size_hull_closed : size_hull_closed - 1; + std::size_t const size_hull = is_hull_closed ? size_hull_closed : + size_hull_closed - 1; + + Hull hull; + + // Test version with strategy + bg::clear(hull); + bg::convex_hull(geometry, hull.outer(), Strategy()); + check_convex_hull(geometry, hull, size_original, size_hull, + expected_area, expected_perimeter, false, AreaStrategy()); + + // Test version with output iterator and strategy + bg::clear(hull); + bg::detail::convex_hull::convex_hull_insert( + geometry, + std::back_inserter(hull.outer()), Strategy()); + check_convex_hull(geometry, hull, size_original, size_hull_from_orig, + expected_area, expected_perimeter, reverse, AreaStrategy()); + + } +}; + + +template +< + typename Hull, + typename AreaStrategy +> +struct test_convex_hull +{ + template + static void apply(Geometry const& geometry, + std::size_t size_original, + std::size_t size_hull_closed, + double expected_area, + double expected_perimeter, + bool reverse) + { + bool const is_original_closed = resolve_variant::get_closure(geometry) != bg::open; + static bool const is_hull_closed = bg::closure::value != bg::open; + + // convex_hull_insert() uses the original Geometry as a source of the info + // about the order and closure + std::size_t const size_hull_from_orig = is_original_closed ? + size_hull_closed : size_hull_closed - 1; + std::size_t const size_hull = is_hull_closed ? size_hull_closed : + size_hull_closed - 1; + + Hull hull; + + // Test version with output iterator + bg::detail::convex_hull::convex_hull_insert(geometry, + std::back_inserter(hull.outer())); + check_convex_hull(geometry, hull, size_original, size_hull_from_orig, + expected_area, expected_perimeter, reverse, + AreaStrategy()); + + // Test version with ring as output + bg::clear(hull); + bg::convex_hull(geometry, hull.outer()); + check_convex_hull(geometry, hull, size_original, size_hull, expected_area, + expected_perimeter, false, AreaStrategy()); + + // Test version with polygon as output + bg::clear(hull); + bg::convex_hull(geometry, hull); + check_convex_hull(geometry, hull, size_original, size_hull, expected_area, + expected_perimeter, false, AreaStrategy()); + + // Test version with strategy + bg::clear(hull); + bg::convex_hull(geometry, hull.outer(), robust_cartesian()); + check_convex_hull(geometry, hull, size_original, size_hull, expected_area, + expected_perimeter, false, AreaStrategy()); + + // Test version with output iterator and strategy + bg::clear(hull); + bg::detail::convex_hull::convex_hull_insert(geometry, + std::back_inserter(hull.outer()), robust_cartesian()); + check_convex_hull(geometry, hull, size_original, size_hull_from_orig, + expected_area, expected_perimeter, reverse, AreaStrategy()); + + } +}; + + +template +< + typename Geometry, + typename Strategy, + typename AreaStrategy, + bool Clockwise, + bool Closed +> +void test_geometry_order(std::string const& wkt, + std::size_t size_original, + std::size_t size_hull_closed, + double expected_area, + double expected_perimeter = -1.0) +{ + typedef bg::model::polygon + < + typename bg::point_type::type, + Clockwise, + Closed + > hull_type; + + Geometry geometry; + bg::read_wkt(wkt, geometry); + + + test_convex_hull::apply(geometry, size_original, + size_hull_closed, expected_area, expected_perimeter, !Clockwise); + + boost::variant v(geometry); + test_convex_hull::apply(v, size_original, + size_hull_closed, expected_area, expected_perimeter, !Clockwise); +} + +template +< + typename Geometry, + typename Strategy, + typename AreaStrategy = typename bg::strategies::area::services::default_strategy + < + Geometry + >::type +> +void test_geometry(std::string const& wkt, + std::size_t size_original, + std::size_t size_hull_closed, + double expected_area, + double expected_perimeter = -1.0) +{ + test_geometry_order( + wkt, size_original, size_hull_closed, expected_area, expected_perimeter); + test_geometry_order( + wkt, size_original, size_hull_closed, expected_area, expected_perimeter); + test_geometry_order( + wkt, size_original, size_hull_closed, expected_area, expected_perimeter); + test_geometry_order( + wkt, size_original, size_hull_closed, expected_area, expected_perimeter); +} + +template +void test_geometry_sph_geo(std::string const& wkt, + std::size_t size_original, + std::size_t size_hull_closed, + double spherical_expected_area, + double geographic_expected_area) +{ + typedef boost::geometry::strategies::convex_hull::spherical<> SphericalStrategy; + test_geometry(wkt, size_original, + size_hull_closed, spherical_expected_area); + + typedef boost::geometry::strategies::convex_hull::geographic<> GeoStrategy; + test_geometry(wkt, size_original, + size_hull_closed, geographic_expected_area); +} + + +template +void test_empty_input() +{ + Geometry geometry; + bg::model::polygon + < + typename bg::point_type::type + > hull; + + bg::convex_hull(geometry, hull); + BOOST_CHECK_MESSAGE(bg::is_empty(hull), "Output convex hull should be empty" ); +} + + + +#endif diff --git a/test/algorithms/detail/sections/sectionalize.cpp b/test/algorithms/detail/sections/sectionalize.cpp index 48047f667..ce448a1fd 100644 --- a/test/algorithms/detail/sections/sectionalize.cpp +++ b/test/algorithms/detail/sections/sectionalize.cpp @@ -61,18 +61,23 @@ void test_sectionalize_part() sections_type sections; section_type section; - Geometry geometry; geometry.push_back(bg::make(1, 1)); bg::detail::no_rescale_policy rescale_policy; + typename bg::strategies::relate::services::default_strategy + < + Geometry, Geometry + >::type strategy; bg::ring_identifier ring_id; - sectionalize_part::apply(sections, geometry.begin(), geometry.end(), rescale_policy, ring_id, 10); + sectionalize_part::apply(sections, geometry.begin(), geometry.end(), + rescale_policy, strategy, ring_id, 10); // There should not yet be anything generated, because it is only ONE point geometry.push_back(bg::make(2, 2)); - sectionalize_part::apply(sections, geometry.begin(), geometry.end(), rescale_policy, ring_id, 10); + sectionalize_part::apply(sections, geometry.begin(), geometry.end(), + rescale_policy, strategy, ring_id, 10); } diff --git a/test/algorithms/distance/distance_brute_force.hpp b/test/algorithms/distance/distance_brute_force.hpp index 82d0015b8..1e5b8b998 100644 --- a/test/algorithms/distance/distance_brute_force.hpp +++ b/test/algorithms/distance/distance_brute_force.hpp @@ -1,10 +1,11 @@ // Boost.Geometry (aka GGL, Generic Geometry Library) // Unit Test -// Copyright (c) 2014, 2018 Oracle and/or its affiliates. +// Copyright (c) 2014-2020 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 // Licensed under the Boost Software License version 1.0. // http://www.boost.org/users/license.html @@ -16,7 +17,9 @@ #include #include -#include +#include +#include +#include #include #include diff --git a/test/algorithms/distance/distance_geo_linear_box.cpp b/test/algorithms/distance/distance_geo_linear_box.cpp index 4b6aacf30..0d22b5eb4 100644 --- a/test/algorithms/distance/distance_geo_linear_box.cpp +++ b/test/algorithms/distance/distance_geo_linear_box.cpp @@ -1,9 +1,10 @@ // Boost.Geometry (aka GGL, Generic Geometry Library) // Unit Test -// Copyright (c) 2017, 2018 Oracle and/or its affiliates. +// Copyright (c) 2017-2020 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 // Licensed under the Boost Software License version 1.0. // http://www.boost.org/users/license.html @@ -14,7 +15,6 @@ #define BOOST_TEST_MODULE test_distance_geographic_linear_areal #endif -#include #include #include diff --git a/test/algorithms/distance/distance_se_geo_ar_ar.cpp b/test/algorithms/distance/distance_se_geo_ar_ar.cpp index 4e25d7eac..d00517ddc 100644 --- a/test/algorithms/distance/distance_se_geo_ar_ar.cpp +++ b/test/algorithms/distance/distance_se_geo_ar_ar.cpp @@ -1,9 +1,10 @@ // Boost.Geometry (aka GGL, Generic Geometry Library) // Unit Test -// Copyright (c) 2017, 2018 Oracle and/or its affiliates. +// Copyright (c) 2017-2020 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 // Licensed under the Boost Software License version 1.0. // http://www.boost.org/users/license.html @@ -12,7 +13,6 @@ #define BOOST_TEST_MODULE test_distance_geographic_areal_areal #endif -#include #include #include diff --git a/test/algorithms/distance/distance_se_geo_l_ar.cpp b/test/algorithms/distance/distance_se_geo_l_ar.cpp index ae332a0da..a3263ea71 100644 --- a/test/algorithms/distance/distance_se_geo_l_ar.cpp +++ b/test/algorithms/distance/distance_se_geo_l_ar.cpp @@ -1,9 +1,10 @@ // Boost.Geometry (aka GGL, Generic Geometry Library) // Unit Test -// Copyright (c) 2017, 2018 Oracle and/or its affiliates. +// Copyright (c) 2017-2020 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 // Licensed under the Boost Software License version 1.0. // http://www.boost.org/users/license.html @@ -14,7 +15,6 @@ #define BOOST_TEST_MODULE test_distance_geographic_linear_areal #endif -#include #include #include diff --git a/test/algorithms/distance/distance_se_geo_l_l.cpp b/test/algorithms/distance/distance_se_geo_l_l.cpp index f287f5264..9ab18ebd5 100644 --- a/test/algorithms/distance/distance_se_geo_l_l.cpp +++ b/test/algorithms/distance/distance_se_geo_l_l.cpp @@ -1,9 +1,10 @@ // Boost.Geometry (aka GGL, Generic Geometry Library) // Unit Test -// Copyright (c) 2018 Oracle and/or its affiliates. +// Copyright (c) 2018-2020 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 // Licensed under the Boost Software License version 1.0. // http://www.boost.org/users/license.html @@ -14,7 +15,6 @@ #define BOOST_TEST_MODULE test_distance_geographic_linear_linear #endif -#include #include #include diff --git a/test/algorithms/distance/distance_se_geo_pl_ar.cpp b/test/algorithms/distance/distance_se_geo_pl_ar.cpp index 3a9d5f277..e51b4b7cf 100644 --- a/test/algorithms/distance/distance_se_geo_pl_ar.cpp +++ b/test/algorithms/distance/distance_se_geo_pl_ar.cpp @@ -1,9 +1,10 @@ // Boost.Geometry (aka GGL, Generic Geometry Library) // Unit Test -// Copyright (c) 2017-2018, Oracle and/or its affiliates. +// Copyright (c) 2017-2020, 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 // Licensed under the Boost Software License version 1.0. // http://www.boost.org/users/license.html @@ -14,7 +15,6 @@ #define BOOST_TEST_MODULE test_distance_geographic_pointlike_areal #endif -#include #include #include diff --git a/test/algorithms/distance/distance_se_pl_pl.cpp b/test/algorithms/distance/distance_se_pl_pl.cpp index 56c0a6e46..f06bd9a2e 100644 --- a/test/algorithms/distance/distance_se_pl_pl.cpp +++ b/test/algorithms/distance/distance_se_pl_pl.cpp @@ -1,7 +1,7 @@ // Boost.Geometry (aka GGL, Generic Geometry Library) // Unit Test -// Copyright (c) 2014-2018, Oracle and/or its affiliates. +// Copyright (c) 2014-2020, 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 @@ -16,8 +16,6 @@ #define BOOST_TEST_MODULE test_distance_spherical_equatorial_pointlike_pointlike #endif -#include - #include #include diff --git a/test/algorithms/overlay/Jamfile b/test/algorithms/overlay/Jamfile index be413b335..b9575595c 100644 --- a/test/algorithms/overlay/Jamfile +++ b/test/algorithms/overlay/Jamfile @@ -16,6 +16,7 @@ test-suite boost-geometry-algorithms-overlay : [ run assemble.cpp : : : : algorithms_assemble ] + [ run copy_segment_point.cpp : : : : algorithms_copy_segment_point ] [ run get_turn_info.cpp : : : : algorithms_get_turn_info ] [ run get_turns.cpp : : : : algorithms_get_turns ] [ run get_turns_areal_areal.cpp : : : : algorithms_get_turns_areal_areal ] diff --git a/test/algorithms/overlay/copy_segment_point.cpp b/test/algorithms/overlay/copy_segment_point.cpp new file mode 100644 index 000000000..33c3f9536 --- /dev/null +++ b/test/algorithms/overlay/copy_segment_point.cpp @@ -0,0 +1,132 @@ +// Boost.Geometry +// Unit Test + +// Copyright (c) 2020 Barend Gehrels, Amsterdam, the Netherlands. + +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#include + +#include + +#include +#include +#include +#include + +template +void test_basic(GetRing get_ring, std::string const& case_id, int line, + std::string const& wkt, bg::segment_identifier const& id, + int offset, std::size_t expected_index) +{ + using point_type = typename bg::point_type::type; + + Geometry geometry; + bg::read_wkt(wkt, geometry); + + // Check the result + auto ring = get_ring(geometry); + + point_type point; + bg::copy_segment_point(geometry, id, offset, point); + + // Sanity check + bool const expectation_in_range = expected_index < ring.size(); + BOOST_CHECK_MESSAGE(expectation_in_range, "Expectation out of range " << expected_index); + if (! expectation_in_range) + { + return; + } + + point_type const expected_point = ring[expected_index]; + + bool const equal = ! bg::disjoint(point, expected_point); + + BOOST_CHECK_MESSAGE(equal, "copy_segment_point: " << case_id + << " line " << line << " at index " << expected_index + << " not as expected: " + << bg::wkt(point) << " vs " << bg::wkt(expected_point)); +} + +template +void test_geometry(std::string const& case_id, std::string const& wkt, GetRing get_ring) +{ + // Check zero offset, all segment ids + test_basic(get_ring, case_id, __LINE__, wkt, {0, 0, -1, 0}, 0, 0); + test_basic(get_ring, case_id, __LINE__, wkt, {0, 0, -1, 1}, 0, 1); + test_basic(get_ring, case_id, __LINE__, wkt, {0, 0, -1, 2}, 0, 2); + test_basic(get_ring, case_id, __LINE__, wkt, {0, 0, -1, 3}, 0, 3); + + // Check positive offsets, it should endlessly loop around, regardless of direction or closure + bg::segment_identifier const start{0, 0, -1, 0}; + test_basic(get_ring, case_id, __LINE__, wkt, start, 1, 1); + test_basic(get_ring, case_id, __LINE__, wkt, start, 2, 2); + test_basic(get_ring, case_id, __LINE__, wkt, start, 3, 3); + test_basic(get_ring, case_id, __LINE__, wkt, start, 4, 0); + test_basic(get_ring, case_id, __LINE__, wkt, start, 5, 1); + test_basic(get_ring, case_id, __LINE__, wkt, start, 6, 2); + test_basic(get_ring, case_id, __LINE__, wkt, start, 7, 3); + + // Check negative offsets + test_basic(get_ring, case_id, __LINE__, wkt, start, -1, 3); + test_basic(get_ring, case_id, __LINE__, wkt, start, -2, 2); + test_basic(get_ring, case_id, __LINE__, wkt, start, -3, 1); + test_basic(get_ring, case_id, __LINE__, wkt, start, -4, 0); + test_basic(get_ring, case_id, __LINE__, wkt, start, -5, 3); + test_basic(get_ring, case_id, __LINE__, wkt, start, -6, 2); + test_basic(get_ring, case_id, __LINE__, wkt, start, -7, 1); +} + +template +void test_all(std::string const& case_id, std::string const& wkt) +{ + using point_type = bg::model::point; + using polygon_type = bg::model::polygon; + + test_geometry(case_id, wkt, [](polygon_type const& polygon) + { + return bg::exterior_ring(polygon); + }); +} + +template +void test_box(std::string const& case_id, std::string const& wkt) +{ + using point_type = bg::model::point; + using box_type = bg::model::box; + + test_geometry(case_id, wkt, [](box_type const& box) + { + boost::array ring; + bg::detail::assign_box_corners_oriented(box, ring); + return ring; + }); + +} + +void test_circular_offset() +{ + BOOST_CHECK_EQUAL(3, bg::detail::copy_segments::circular_offset(4, 0, -1)); + BOOST_CHECK_EQUAL(2, bg::detail::copy_segments::circular_offset(4, 0, -2)); + BOOST_CHECK_EQUAL(1, bg::detail::copy_segments::circular_offset(4, 0, -3)); + + BOOST_CHECK_EQUAL(6, bg::detail::copy_segments::circular_offset(10, 5, 1)); + BOOST_CHECK_EQUAL(6, bg::detail::copy_segments::circular_offset(10, 5, 11)); + BOOST_CHECK_EQUAL(6, bg::detail::copy_segments::circular_offset(10, 5, 21)); + + BOOST_CHECK_EQUAL(4, bg::detail::copy_segments::circular_offset(10, 5, -1)); + BOOST_CHECK_EQUAL(4, bg::detail::copy_segments::circular_offset(10, 5, -11)); + BOOST_CHECK_EQUAL(4, bg::detail::copy_segments::circular_offset(10, 5, -21)); +} + +int test_main(int, char* []) +{ + test_circular_offset(); + + test_all("closed", "POLYGON((0 2,1 2,1 1,0 1,0 2))"); + test_all("open", "POLYGON((0 2,1 2,1 1,0 1))"); + test_box("box", "BOX(0 0,5 5)"); + return 0; +} diff --git a/test/algorithms/overlay/get_turn_info.cpp b/test/algorithms/overlay/get_turn_info.cpp index 3835f6f47..a70093de4 100644 --- a/test/algorithms/overlay/get_turn_info.cpp +++ b/test/algorithms/overlay/get_turn_info.cpp @@ -3,8 +3,8 @@ // 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. +// This file was modified by Oracle on 2017-2020. +// Modifications copyright (c) 2017-2020, 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, @@ -25,6 +25,9 @@ #include #include +// TEMP +#include + #if defined(TEST_WITH_SVG) # include #endif @@ -74,9 +77,9 @@ void test_with_point(std::string const& caseid, P qj = bg::make

(qj_x, qj_y); P qk = bg::make

(qk_x, qk_y); - typedef typename bg::strategy::intersection::services::default_strategy + typedef typename bg::strategies::relate::services::default_strategy < - typename bg::cs_tag

::type + P, P >::type strategy_type; typedef typename bg::detail::no_rescale_policy rescale_policy_type; diff --git a/test/algorithms/overlay/get_turns.cpp b/test/algorithms/overlay/get_turns.cpp index 1b8d279b9..5db074ab3 100644 --- a/test/algorithms/overlay/get_turns.cpp +++ b/test/algorithms/overlay/get_turns.cpp @@ -64,9 +64,9 @@ struct test_get_turns { typedef typename bg::point_type::type point_type; - typedef typename bg::strategy::intersection::services::default_strategy + typedef typename bg::strategies::relate::services::default_strategy < - typename bg::cs_tag::type + G1, G2 >::type strategy_type; typedef typename bg::rescale_policy_type::type diff --git a/test/algorithms/overlay/get_turns_linear_linear_geo.cpp b/test/algorithms/overlay/get_turns_linear_linear_geo.cpp index 4b3a22d47..de0d82b7f 100644 --- a/test/algorithms/overlay/get_turns_linear_linear_geo.cpp +++ b/test/algorithms/overlay/get_turns_linear_linear_geo.cpp @@ -21,7 +21,7 @@ void test_radian() typedef bg::model::multi_linestring mls; bg::srs::spheroid sph_wgs84(6378137.0, 6356752.3142451793); - boost::geometry::strategy::intersection::geographic_segments<> wgs84(sph_wgs84); + boost::geometry::strategies::relate::geographic<> wgs84(sph_wgs84); test_geometry( "LINESTRING(0 0, -3.14159265358979 0)", diff --git a/test/algorithms/overlay/overlay.cpp b/test/algorithms/overlay/overlay.cpp index f89bfabff..5d3c04b21 100644 --- a/test/algorithms/overlay/overlay.cpp +++ b/test/algorithms/overlay/overlay.cpp @@ -3,8 +3,8 @@ // Copyright (c) 2015 Barend Gehrels, Amsterdam, the Netherlands. -// This file was modified by Oracle on 2017. -// Modifications copyright (c) 2017, Oracle and/or its affiliates. +// This file was modified by Oracle on 2017-2020. +// Modifications copyright (c) 2017-2020, 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, @@ -407,9 +407,9 @@ void test_overlay(std::string const& caseid, OverlayType > overlay; - typedef typename bg::strategy::intersection::services::default_strategy + typedef typename bg::strategies::relate::services::default_strategy < - typename bg::cs_tag::type + Geometry, Geometry >::type strategy_type; strategy_type strategy; diff --git a/test/algorithms/overlay/select_rings.cpp b/test/algorithms/overlay/select_rings.cpp index af43328f5..89f43732f 100644 --- a/test/algorithms/overlay/select_rings.cpp +++ b/test/algorithms/overlay/select_rings.cpp @@ -2,8 +2,8 @@ // // 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. +// This file was modified by Oracle on 2017-2020. +// Modifications copyright (c) 2017-2020 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, @@ -57,9 +57,9 @@ void test_geometry(std::string const& wkt1, std::string const& wkt2, map_type selected; std::map empty; - typedef typename bg::strategy::intersection::services::default_strategy + typedef typename bg::strategies::relate::services::default_strategy < - typename bg::cs_tag::type + Geometry1, Geometry2 >::type strategy_type; bg::detail::overlay::select_rings(geometry1, geometry2, empty, selected, strategy_type()); diff --git a/test/algorithms/overlay/self_intersection_points.cpp b/test/algorithms/overlay/self_intersection_points.cpp index 2d7a42039..16b8ed24f 100644 --- a/test/algorithms/overlay/self_intersection_points.cpp +++ b/test/algorithms/overlay/self_intersection_points.cpp @@ -5,8 +5,8 @@ // 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. +// This file was modified by Oracle on 2017-2020. +// Modifications copyright (c) 2017-2020, 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 @@ -55,9 +55,9 @@ static void test_self_intersection_points(std::string const& case_id, { typedef typename bg::point_type::type point_type; //typedef typename bg::rescale_policy_type::type rescale_policy_type; - typedef typename bg::strategy::intersection::services::default_strategy + typedef typename bg::strategies::relate::services::default_strategy < - typename bg::cs_tag::type + Geometry, Geometry >::type strategy_type; typedef bg::detail::no_rescale_policy rescale_policy_type; typedef bg::detail::overlay::turn_info turn_info; @@ -91,6 +91,12 @@ static void test_self_intersection_points(std::string const& case_id, BOOST_CHECK_EQUAL(expected_count, n); + typedef typename bg::rescale_policy_type::type + default_rescale_policy_type; + + default_rescale_policy_type default_robust_policy + = bg::get_rescale_policy(geometry, strategy); + if (expected_count > 0) { BOOST_CHECK_EQUAL(bg::intersects(geometry), true); @@ -99,7 +105,7 @@ static void test_self_intersection_points(std::string const& case_id, { try { - boost::geometry::detail::overlay::has_self_intersections(geometry); + bg::detail::overlay::has_self_intersections(geometry, strategy, default_robust_policy); BOOST_CHECK_MESSAGE(false, "Case " << case_id << " there are no self-intersections detected!"); } catch(...) @@ -113,7 +119,7 @@ static void test_self_intersection_points(std::string const& case_id, { try { - boost::geometry::detail::overlay::has_self_intersections(geometry); + bg::detail::overlay::has_self_intersections(geometry, strategy, default_robust_policy); } catch(...) { diff --git a/test/algorithms/overlay/sort_by_side.cpp b/test/algorithms/overlay/sort_by_side.cpp index 1e0f42258..2966d2a44 100644 --- a/test/algorithms/overlay/sort_by_side.cpp +++ b/test/algorithms/overlay/sort_by_side.cpp @@ -4,8 +4,8 @@ // Copyright (c) 2016 Barend Gehrels, Amsterdam, the Netherlands. // Copyright (c) 2017 Adam Wulkiewicz, Lodz, Poland. -// This file was modified by Oracle on 2017, 2019. -// Modifications copyright (c) 2017, 2019, Oracle and/or its affiliates. +// This file was modified by Oracle on 2017-2020. +// Modifications copyright (c) 2017-2020, 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, @@ -101,7 +101,7 @@ std::vector gather_cluster_properties( for (int i = 0; i < 2; i++) { turn_operation_type const& op = turn.operations[i]; - sbs.add(op, turn_index, i, geometry1, geometry2, first); + sbs.add(turn, op, turn_index, i, geometry1, geometry2, first); first = false; } } @@ -165,7 +165,7 @@ std::vector apply_overlay( // Gather cluster properties, with test option return ::gather_cluster_properties( clusters, turns, bg::detail::overlay::operation_from_overlay::value, - geometry1, geometry2, strategy.get_side_strategy()); + geometry1, geometry2, strategy.side()); } @@ -197,9 +197,9 @@ void test_sort_by_side(std::string const& case_id, rescale_policy_type robust_policy = bg::get_rescale_policy(g1, g2); - typedef typename bg::strategy::intersection::services::default_strategy + typedef typename bg::strategies::relate::services::default_strategy < - typename bg::cs_tag::type + Geometry, Geometry >::type strategy_type; strategy_type strategy; diff --git a/test/algorithms/overlay/sort_by_side_basic.cpp b/test/algorithms/overlay/sort_by_side_basic.cpp index f37bd38c6..a77f2e4dd 100644 --- a/test/algorithms/overlay/sort_by_side_basic.cpp +++ b/test/algorithms/overlay/sort_by_side_basic.cpp @@ -4,8 +4,8 @@ // Copyright (c) 2017 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. +// This file was modified by Oracle on 2017-2020. +// Modifications copyright (c) 2017-2020, 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, @@ -90,14 +90,14 @@ std::vector apply_get_turns(std::string const& case_id, // Define sorter, sorting counter-clockwise such that polygons are on the // right side - typedef typename Strategy::side_strategy_type side_strategy; + typedef decltype(strategy.side()) side_strategy; typedef bg::detail::overlay::sort_by_side::side_sorter < false, false, overlay_union, point_type, side_strategy, std::less > sbs_type; - sbs_type sbs(strategy.get_side_strategy()); + sbs_type sbs(strategy.side()); std::cout << "Case: " << case_id << std::endl; @@ -120,7 +120,7 @@ std::vector apply_get_turns(std::string const& case_id, has_origin = true; } - sbs.add(turn.operations[i], turn_index, i, + sbs.add(turn, turn.operations[i], turn_index, i, geometry1, geometry2, is_origin); } @@ -256,9 +256,9 @@ void test_basic(std::string const& case_id, rescale_policy_type robust_policy = bg::get_rescale_policy(g1, g2); - typedef typename bg::strategy::intersection::services::default_strategy + typedef typename bg::strategies::relate::services::default_strategy < - typename bg::cs_tag::type + multi_polygon, multi_polygon >::type strategy_type; strategy_type strategy; diff --git a/test/algorithms/overlay/test_get_turns.hpp b/test/algorithms/overlay/test_get_turns.hpp index f761a996d..1a4afc6b5 100644 --- a/test/algorithms/overlay/test_get_turns.hpp +++ b/test/algorithms/overlay/test_get_turns.hpp @@ -4,8 +4,8 @@ // Copyright (c) 2008-2012 Bruno Lalande, Paris, France. // Copyright (c) 2009-2012 Mateusz Loskot, London, UK. -// This file was modified by Oracle on 2014, 2016, 2017, 2018. -// Modifications copyright (c) 2014-2018 Oracle and/or its affiliates. +// This file was modified by Oracle on 2014, 2016-2020. +// Modifications copyright (c) 2014-2020 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 @@ -259,9 +259,9 @@ void check_geometry_range(Geometry1 const& g1, std::string const& wkt2, Expected const& expected) { - typename bg::strategy::intersection::services::default_strategy + typename bg::strategies::relate::services::default_strategy < - typename bg::cs_tag::type + Geometry1, Geometry2 >::type strategy; check_geometry_range(g1, g2, wkt1, wkt2, expected, strategy); diff --git a/test/algorithms/set_operations/check_turn_less.hpp b/test/algorithms/set_operations/check_turn_less.hpp index 147342a22..b93bf6cc7 100644 --- a/test/algorithms/set_operations/check_turn_less.hpp +++ b/test/algorithms/set_operations/check_turn_less.hpp @@ -1,6 +1,6 @@ // Boost.Geometry (aka GGL, Generic Geometry Library) -// Copyright (c) 2015, 2019, Oracle and/or its affiliates. +// Copyright (c) 2015-2020, 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 @@ -11,7 +11,9 @@ #ifndef BOOST_GEOMETRY_TEST_CHECK_TURN_LESS_HPP #define BOOST_GEOMETRY_TEST_CHECK_TURN_LESS_HPP -#include +#include +#include +#include #include "test_set_ops_linear_linear.hpp" @@ -74,9 +76,9 @@ struct check_turn_less static inline void apply(Geometry1 const& geometry1, Geometry2 const& geometry2) { - typedef typename bg::strategy::intersection::services::default_strategy + typedef typename bg::strategies::relate::services::default_strategy < - typename bg::cs_tag::type + Geometry1, Geometry2 >::type strategy_type; typedef bg::detail::no_rescale_policy robust_policy_type; diff --git a/test/algorithms/set_operations/difference/difference_multi.cpp b/test/algorithms/set_operations/difference/difference_multi.cpp index 2203f071f..91e143dff 100644 --- a/test/algorithms/set_operations/difference/difference_multi.cpp +++ b/test/algorithms/set_operations/difference/difference_multi.cpp @@ -524,7 +524,7 @@ int test_main(int, char* []) #if defined(BOOST_GEOMETRY_TEST_FAILURES) // Not yet fully tested for float. // The difference algorithm can generate (additional) slivers - BoostGeometryWriteExpectedFailures(22, 13, 19, 7); + BoostGeometryWriteExpectedFailures(22, 9, 20, 7); #endif return 0; diff --git a/test/algorithms/set_operations/difference/difference_tupled.cpp b/test/algorithms/set_operations/difference/difference_tupled.cpp index 7b3d9e65d..30ecd2d50 100644 --- a/test/algorithms/set_operations/difference/difference_tupled.cpp +++ b/test/algorithms/set_operations/difference/difference_tupled.cpp @@ -14,7 +14,6 @@ #include #include #include -#include #include #include #include diff --git a/test/algorithms/set_operations/difference/test_difference.hpp b/test/algorithms/set_operations/difference/test_difference.hpp index fdbd7d797..3c9ce08a5 100644 --- a/test/algorithms/set_operations/difference/test_difference.hpp +++ b/test/algorithms/set_operations/difference/test_difference.hpp @@ -4,8 +4,8 @@ // Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands. // Copyright (c) 2017 Adam Wulkiewicz, Lodz, Poland. -// This file was modified by Oracle on 2016, 2017, 2019. -// Modifications copyright (c) 2016-2019, Oracle and/or its affiliates. +// This file was modified by Oracle on 2016-2020. +// Modifications copyright (c) 2016-2020, 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, @@ -28,6 +28,7 @@ #include #include +#include #include #include diff --git a/test/algorithms/set_operations/difference/test_difference_linear_linear.hpp b/test/algorithms/set_operations/difference/test_difference_linear_linear.hpp index 14f6b039a..36e5459d7 100644 --- a/test/algorithms/set_operations/difference/test_difference_linear_linear.hpp +++ b/test/algorithms/set_operations/difference/test_difference_linear_linear.hpp @@ -1,6 +1,6 @@ // Boost.Geometry (aka GGL, Generic Geometry Library) -// Copyright (c) 2014-2017, Oracle and/or its affiliates. +// Copyright (c) 2014-2020, 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 @@ -13,6 +13,8 @@ #include +#include + #include #include "../test_set_ops_linear_linear.hpp" #include "../check_turn_less.hpp" diff --git a/test/algorithms/set_operations/intersection/intersection_areal_areal_linear.cpp b/test/algorithms/set_operations/intersection/intersection_areal_areal_linear.cpp index c83c794c0..9a648f996 100644 --- a/test/algorithms/set_operations/intersection/intersection_areal_areal_linear.cpp +++ b/test/algorithms/set_operations/intersection/intersection_areal_areal_linear.cpp @@ -1,13 +1,14 @@ // Boost.Geometry (aka GGL, Generic Geometry Library) // Unit test -// Copyright (c) 2015, Oracle and/or its affiliates. +// Copyright (c) 2015-2020, 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_TEST_MODULE #define BOOST_TEST_MODULE test_intersection_linear_linear_areal #endif @@ -19,8 +20,6 @@ #include -#include - #include #include #include diff --git a/test/algorithms/set_operations/intersection/intersection_multi.cpp b/test/algorithms/set_operations/intersection/intersection_multi.cpp index 585232273..043512267 100644 --- a/test/algorithms/set_operations/intersection/intersection_multi.cpp +++ b/test/algorithms/set_operations/intersection/intersection_multi.cpp @@ -499,7 +499,7 @@ int test_main(int, char* []) #endif #if defined(BOOST_GEOMETRY_TEST_FAILURES) - BoostGeometryWriteExpectedFailures(9, 3, 2, 1); + BoostGeometryWriteExpectedFailures(9, 1, 2, 1); #endif return 0; diff --git a/test/algorithms/set_operations/intersection/intersection_tupled.cpp b/test/algorithms/set_operations/intersection/intersection_tupled.cpp index 3501fcaf5..5957355b3 100644 --- a/test/algorithms/set_operations/intersection/intersection_tupled.cpp +++ b/test/algorithms/set_operations/intersection/intersection_tupled.cpp @@ -14,7 +14,6 @@ #include #include #include -#include #include #include #include diff --git a/test/algorithms/set_operations/intersection/test_intersection.hpp b/test/algorithms/set_operations/intersection/test_intersection.hpp index 49c8aa4b0..12071d1b6 100644 --- a/test/algorithms/set_operations/intersection/test_intersection.hpp +++ b/test/algorithms/set_operations/intersection/test_intersection.hpp @@ -3,8 +3,8 @@ // Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands. -// This file was modified by Oracle on 2016, 2017. -// Modifications copyright (c) 2016-2017, Oracle and/or its affiliates. +// This file was modified by Oracle on 2016-2020. +// Modifications copyright (c) 2016-2020, 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, @@ -18,6 +18,7 @@ #include #include +#include #include #include diff --git a/test/algorithms/set_operations/intersection/test_intersection_linear_linear.hpp b/test/algorithms/set_operations/intersection/test_intersection_linear_linear.hpp index f916b023c..0b47c4f75 100644 --- a/test/algorithms/set_operations/intersection/test_intersection_linear_linear.hpp +++ b/test/algorithms/set_operations/intersection/test_intersection_linear_linear.hpp @@ -1,6 +1,6 @@ // Boost.Geometry (aka GGL, Generic Geometry Library) -// Copyright (c) 2014-2017, Oracle and/or its affiliates. +// Copyright (c) 2014-2020, 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 @@ -13,6 +13,7 @@ #include +#include #include #include diff --git a/test/algorithms/set_operations/sym_difference/sym_difference_tupled.cpp b/test/algorithms/set_operations/sym_difference/sym_difference_tupled.cpp index 0bfa98bcd..0985ed410 100644 --- a/test/algorithms/set_operations/sym_difference/sym_difference_tupled.cpp +++ b/test/algorithms/set_operations/sym_difference/sym_difference_tupled.cpp @@ -14,7 +14,6 @@ #include #include #include -#include #include #include #include diff --git a/test/algorithms/set_operations/sym_difference/test_sym_difference_linear_linear.hpp b/test/algorithms/set_operations/sym_difference/test_sym_difference_linear_linear.hpp index 843345247..c850df8df 100644 --- a/test/algorithms/set_operations/sym_difference/test_sym_difference_linear_linear.hpp +++ b/test/algorithms/set_operations/sym_difference/test_sym_difference_linear_linear.hpp @@ -1,6 +1,6 @@ // Boost.Geometry (aka GGL, Generic Geometry Library) -// Copyright (c) 2014-2017, Oracle and/or its affiliates. +// Copyright (c) 2014-2020, 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 @@ -13,6 +13,8 @@ #include +#include + #include #include "../test_set_ops_linear_linear.hpp" #include diff --git a/test/algorithms/set_operations/test_get_turns_ll_invariance.hpp b/test/algorithms/set_operations/test_get_turns_ll_invariance.hpp index 3fdc3a575..77463a53d 100644 --- a/test/algorithms/set_operations/test_get_turns_ll_invariance.hpp +++ b/test/algorithms/set_operations/test_get_turns_ll_invariance.hpp @@ -1,6 +1,6 @@ // Boost.Geometry (aka GGL, Generic Geometry Library) -// Copyright (c) 2014, 2019, Oracle and/or its affiliates. +// Copyright (c) 2014-2021, 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 @@ -13,6 +13,10 @@ #include +#include +#include +#include + #include #include @@ -66,24 +70,29 @@ private: < typename Turns, typename LinearGeometry1, - typename LinearGeometry2 + typename LinearGeometry2, + typename Strategy > static inline void compute_turns(Turns& turns, LinearGeometry1 const& linear1, - LinearGeometry2 const& linear2) + LinearGeometry2 const& linear2, + Strategy const& strategy) { turns.clear(); + bg_detail::get_turns::no_interrupt_policy interrupt_policy; bg_detail::relate::turns::get_turns < LinearGeometry1, LinearGeometry2, bg_detail::get_turns::get_turn_info_type - < - LinearGeometry1, - LinearGeometry2, - assign_policy - > - >::apply(turns, linear1, linear2); + < + LinearGeometry1, + LinearGeometry2, + assign_policy + > + >::apply(turns, linear1, linear2, + interrupt_policy, + strategy); } @@ -93,7 +102,7 @@ public: static inline void apply(Linear1 const& lineargeometry1, Linear2 const& lineargeometry2) { - typedef typename bg::strategy::relate::services::default_strategy + typedef typename bg::strategies::relate::services::default_strategy < Linear1, Linear2 >::type strategy_type; @@ -124,8 +133,9 @@ public: boost::geometry::reverse(linear2_reverse); turns_container turns_all, rturns_all; - compute_turns(turns_all, linear1, linear2); - compute_turns(rturns_all, linear1, linear2_reverse); + strategy_type strategy; + compute_turns(turns_all, linear1, linear2, strategy); + compute_turns(rturns_all, linear1, linear2_reverse, strategy); turns_container turns_wo_cont(turns_all); turns_container rturns_wo_cont(rturns_all); diff --git a/test/algorithms/set_operations/test_set_ops_linear_linear.hpp b/test/algorithms/set_operations/test_set_ops_linear_linear.hpp index a8749b42b..d9bf57c2c 100644 --- a/test/algorithms/set_operations/test_set_ops_linear_linear.hpp +++ b/test/algorithms/set_operations/test_set_ops_linear_linear.hpp @@ -1,12 +1,13 @@ // Boost.Geometry (aka GGL, Generic Geometry Library) -// Copyright (c) 2014-2015, Oracle and/or its affiliates. +// Copyright (c) 2014-2020, 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_TEST_SET_OPS_LINEAR_LINEAR_HPP #define BOOST_GEOMETRY_TEST_SET_OPS_LINEAR_LINEAR_HPP @@ -17,7 +18,11 @@ #include #include -#include +#include +#include +#include +#include +#include #include #include diff --git a/test/algorithms/set_operations/test_set_ops_pointlike.hpp b/test/algorithms/set_operations/test_set_ops_pointlike.hpp index 6908aa552..1cbe5de84 100644 --- a/test/algorithms/set_operations/test_set_ops_pointlike.hpp +++ b/test/algorithms/set_operations/test_set_ops_pointlike.hpp @@ -22,6 +22,9 @@ namespace bg = ::boost::geometry; #include #include #include +#include +#include +#include #include #include diff --git a/test/algorithms/set_operations/union/test_union.hpp b/test/algorithms/set_operations/union/test_union.hpp index 5d762e2b5..e17012265 100644 --- a/test/algorithms/set_operations/union/test_union.hpp +++ b/test/algorithms/set_operations/union/test_union.hpp @@ -3,8 +3,8 @@ // Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands. -// This file was modified by Oracle on 2015, 2016, 2017. -// Modifications copyright (c) 2015-2017 Oracle and/or its affiliates. +// This file was modified by Oracle on 2015-2020. +// Modifications copyright (c) 2015-2020 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 @@ -26,6 +26,9 @@ #include #include #include +#include +#include +#include #include diff --git a/test/algorithms/set_operations/union/test_union_linear_linear.hpp b/test/algorithms/set_operations/union/test_union_linear_linear.hpp index e4357b603..8f09dc1c5 100644 --- a/test/algorithms/set_operations/union/test_union_linear_linear.hpp +++ b/test/algorithms/set_operations/union/test_union_linear_linear.hpp @@ -1,6 +1,6 @@ // Boost.Geometry (aka GGL, Generic Geometry Library) -// Copyright (c) 2014-2017, Oracle and/or its affiliates. +// Copyright (c) 2014-2020, 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 @@ -13,6 +13,8 @@ #include +#include + #include #include "../test_set_ops_linear_linear.hpp" #include diff --git a/test/algorithms/set_operations/union/union_multi.cpp b/test/algorithms/set_operations/union/union_multi.cpp index 53c70844b..bcc0185a5 100644 --- a/test/algorithms/set_operations/union/union_multi.cpp +++ b/test/algorithms/set_operations/union/union_multi.cpp @@ -489,7 +489,7 @@ int test_main(int, char* []) #endif #if defined(BOOST_GEOMETRY_TEST_FAILURES) - BoostGeometryWriteExpectedFailures(9, 2, 1, 0); + BoostGeometryWriteExpectedFailures(9, 0, 3, 0); #endif return 0; diff --git a/test/algorithms/set_operations/union/union_tupled.cpp b/test/algorithms/set_operations/union/union_tupled.cpp index 494fe1677..72e8acd7e 100644 --- a/test/algorithms/set_operations/union/union_tupled.cpp +++ b/test/algorithms/set_operations/union/union_tupled.cpp @@ -14,7 +14,6 @@ #include #include #include -#include #include #include #include diff --git a/test/algorithms/test_convex_hull.hpp b/test/algorithms/test_convex_hull.hpp deleted file mode 100644 index a3ab82df4..000000000 --- a/test/algorithms/test_convex_hull.hpp +++ /dev/null @@ -1,191 +0,0 @@ -// Boost.Geometry (aka GGL, Generic Geometry Library) -// Unit Test - -// 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. - -// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle -// Contributed and/or modified by Menelaos Karavelas, 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_TEST_CONVEX_HULL_HPP -#define BOOST_GEOMETRY_TEST_CONVEX_HULL_HPP - -#include - -#include - -#include -#include -#include -#include -#include - -#include - -#include - -#include - - -template -void check_convex_hull(Geometry const& geometry, Hull const& hull, - std::size_t /*size_original*/, std::size_t size_hull, - double expected_area, double expected_perimeter, - bool reverse) -{ - std::size_t n = bg::num_points(hull); - - BOOST_CHECK_MESSAGE(n == size_hull, - "convex hull: " << bg::wkt(geometry) - << " -> " << bg::wkt(hull) - << " type " - << (typeid(typename bg::coordinate_type::type).name()) - << " -> Expected: " << size_hull - << " detected: " << n); - - - // We omit this check as it is not important for the hull algorithm - // BOOST_CHECK(bg::num_points(geometry) == size_original); - - typename bg::default_area_result::type ah = bg::area(hull); - if (reverse) - { - ah = -ah; - } - - BOOST_CHECK_CLOSE(ah, expected_area, 0.001); - - if ( expected_perimeter >= 0 ) - { - typename bg::default_length_result::type - ph = bg::perimeter(hull); - - BOOST_CHECK_CLOSE(ph, expected_perimeter, 0.001); - } -} - -namespace resolve_variant { - -struct closure_visitor : public boost::static_visitor -{ - template - bg::closure_selector operator()(Geometry const&) const - { - return bg::closure::value; - } -}; - -template -inline bg::closure_selector get_closure(Geometry const&) -{ - return bg::closure::value; -} - -template -inline bg::closure_selector get_closure(boost::variant const& v) -{ - return boost::apply_visitor(closure_visitor(), v); -} - -} // namespace resolve_variant - -template -void test_convex_hull(Geometry const& geometry, - std::size_t size_original, std::size_t size_hull_closed, - double expected_area, double expected_perimeter, - bool reverse) -{ - bool const is_original_closed = resolve_variant::get_closure(geometry) != bg::open; - static bool const is_hull_closed = bg::closure::value != bg::open; - - // convex_hull_insert() uses the original Geometry as a source of the info about the order and closure - std::size_t const size_hull_from_orig = is_original_closed ? size_hull_closed : size_hull_closed - 1; - std::size_t const size_hull = is_hull_closed ? size_hull_closed : size_hull_closed - 1; - - Hull hull; - - // Test version with output iterator - bg::detail::convex_hull::convex_hull_insert(geometry, std::back_inserter(hull.outer())); - check_convex_hull(geometry, hull, size_original, size_hull_from_orig, expected_area, expected_perimeter, reverse); - - // Test version with ring as output - bg::clear(hull); - bg::convex_hull(geometry, hull.outer()); - check_convex_hull(geometry, hull, size_original, size_hull, expected_area, expected_perimeter, false); - - // Test version with polygon as output - bg::clear(hull); - bg::convex_hull(geometry, hull); - check_convex_hull(geometry, hull, size_original, size_hull, expected_area, expected_perimeter, false); - - // Test version with strategy - bg::clear(hull); - bg::convex_hull(geometry, hull.outer(), Strategy()); - check_convex_hull(geometry, hull, size_original, size_hull, expected_area, expected_perimeter, false); - - // Test version with output iterator and strategy - bg::clear(hull); - bg::detail::convex_hull::convex_hull_insert(geometry, std::back_inserter(hull.outer()), Strategy()); - check_convex_hull(geometry, hull, size_original, size_hull_from_orig, expected_area, expected_perimeter, reverse); -} - - -template -void test_geometry_order(std::string const& wkt, - std::size_t size_original, std::size_t size_hull_closed, - double expected_area, double expected_perimeter = -1.0) -{ - typedef bg::model::polygon - < - typename bg::point_type::type, - Clockwise, - Closed - > hull_type; - - typedef bg::strategy::convex_hull::graham_andrew - < - Geometry, - typename bg::point_type::type - > strategy_type; - - Geometry geometry; - bg::read_wkt(wkt, geometry); - boost::variant v(geometry); - - test_convex_hull(geometry, size_original, size_hull_closed, expected_area, expected_perimeter, !Clockwise); - test_convex_hull(v, size_original, size_hull_closed, expected_area, expected_perimeter, !Clockwise); -} - -template -void test_geometry(std::string const& wkt, - std::size_t size_original, std::size_t size_hull_closed, - double expected_area, double expected_perimeter = -1.0) -{ - test_geometry_order(wkt, size_original, size_hull_closed, expected_area, expected_perimeter); - test_geometry_order(wkt, size_original, size_hull_closed, expected_area, expected_perimeter); - test_geometry_order(wkt, size_original, size_hull_closed, expected_area, expected_perimeter); - test_geometry_order(wkt, size_original, size_hull_closed, expected_area, expected_perimeter); -} - -template -void test_empty_input() -{ - Geometry geometry; - bg::model::polygon - < - typename bg::point_type::type - > hull; - - bg::convex_hull(geometry, hull); - BOOST_CHECK_MESSAGE(bg::is_empty(hull), "Output convex hull should be empty" ); -} - - - -#endif diff --git a/test/algorithms/test_is_valid.hpp b/test/algorithms/test_is_valid.hpp index df0be5b81..0b5f2aed5 100644 --- a/test/algorithms/test_is_valid.hpp +++ b/test/algorithms/test_is_valid.hpp @@ -1,7 +1,7 @@ // Boost.Geometry (aka GGL, Generic Geometry Library) // Unit Test -// Copyright (c) 2014-2017, Oracle and/or its affiliates. +// Copyright (c) 2014-2020, 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 @@ -17,7 +17,10 @@ #include #include -#include +#include +#include +#include +#include #include #include diff --git a/test/algorithms/within/within.cpp b/test/algorithms/within/within.cpp index 9cd98628e..cd5591754 100644 --- a/test/algorithms/within/within.cpp +++ b/test/algorithms/within/within.cpp @@ -3,8 +3,8 @@ // Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands. // Copyright (c) 2013-2015 Adam Wulkiewicz, Lodz, Poland. -// This file was modified by Oracle on 2014, 2015, 2016, 2018. -// Modifications copyright (c) 2014-2018 Oracle and/or its affiliates. +// This file was modified by Oracle on 2014-2020. +// Modifications copyright (c) 2014-2020 Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle @@ -112,16 +112,12 @@ void test_strategy() bg::strategy::within::cartesian_point_box()); BOOST_CHECK_EQUAL(r, true); - r = bg::within(b, b, - bg::strategy::within::box_in_box()); - BOOST_CHECK_EQUAL(r, true); - r = bg::within(b0, b0, - bg::strategy::within::box_in_box()); + bg::strategy::within::cartesian_box_box()); BOOST_CHECK_EQUAL(r, false); r = bg::within(p, b, - bg::strategy::within::point_in_box_by_side<>()); + bg::strategy::within::cartesian_point_box_by_side<>()); BOOST_CHECK_EQUAL(r, true); } diff --git a/test/algorithms/within/within_sph_geo.cpp b/test/algorithms/within/within_sph_geo.cpp index 128f24dda..56d49334f 100644 --- a/test/algorithms/within/within_sph_geo.cpp +++ b/test/algorithms/within/within_sph_geo.cpp @@ -1,6 +1,6 @@ // Boost.Geometry -// Copyright (c) 2016-2018 Oracle and/or its affiliates. +// Copyright (c) 2016-2020 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, @@ -19,7 +19,12 @@ void test_point_box_by_side() // Test spherical boxes // See also http://www.gcmap.com/mapui?P=1E45N-19E45N-19E55N-1E55N-1E45N,10E55.1N,10E45.1N typedef bg::model::box box_t; - bg::strategy::within::point_in_box_by_side<> by_side; + std::conditional_t + < + std::is_same::type, bg::geographic_tag>::value, + bg::strategy::within::geographic_point_box_by_side<>, + bg::strategy::within::spherical_point_box_by_side<> + > by_side; box_t box; bg::read_wkt("POLYGON((1 45,19 55))", box); BOOST_CHECK_EQUAL(bg::within(Point(10, 55.1), box, by_side), true); @@ -32,6 +37,14 @@ void test_point_box_by_side() BOOST_CHECK_EQUAL(bg::within(Point(10, 45.3), box, by_side), false); BOOST_CHECK_EQUAL(bg::within(Point(10, 45.4), box, by_side), true); + bg::strategy::within::spherical_point_box s; + BOOST_CHECK_EQUAL(bg::within(Point(10, 44.9), box, s), false); + BOOST_CHECK_EQUAL(bg::within(Point(10, 45.0), box, s), false); + BOOST_CHECK_EQUAL(bg::within(Point(10, 45.1), box, s), true); + BOOST_CHECK_EQUAL(bg::within(Point(10, 49.9), box, s), true); + BOOST_CHECK_EQUAL(bg::within(Point(10, 55.0), box, s), false); + BOOST_CHECK_EQUAL(bg::within(Point(10, 55.1), box, s), false); + // By default Box is not a polygon in spherical CS, edges are defined by small circles BOOST_CHECK_EQUAL(bg::within(Point(10, 45.1), box), true); BOOST_CHECK_EQUAL(bg::within(Point(10, 54.9), box), true); diff --git a/test/count_set.hpp b/test/count_set.hpp index 751649171..3d69b5ca4 100644 --- a/test/count_set.hpp +++ b/test/count_set.hpp @@ -29,10 +29,6 @@ struct count_set { m_values.insert(static_cast(value)); } - else - { - std::cout << "EMPTY" << std::endl; - } } count_set(std::size_t value1, std::size_t value2) diff --git a/test/cs_undefined/index.cpp b/test/cs_undefined/index.cpp index 008187044..5908aa248 100644 --- a/test/cs_undefined/index.cpp +++ b/test/cs_undefined/index.cpp @@ -1,6 +1,6 @@ // Boost.Geometry -// Copyright (c) 2019, Oracle and/or its affiliates. +// Copyright (c) 2019-2020, Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle @@ -18,6 +18,10 @@ #include +#include +#include +#include + #include namespace bgi = boost::geometry::index; @@ -67,35 +71,35 @@ int test_main(int, char*[]) { geom g; - rtree_test(g.pt, bgi::parameters, bg::strategy::index::cartesian<> >()); - rtree_test(g.pt, bgi::parameters, bg::strategy::index::cartesian<> >()); - rtree_test(g.pt, bgi::parameters, bg::strategy::index::cartesian<> >()); - rtree_test(g.b, bgi::parameters, bg::strategy::index::cartesian<> >()); - rtree_test(g.b, bgi::parameters, bg::strategy::index::cartesian<> >()); - rtree_test(g.b, bgi::parameters, bg::strategy::index::cartesian<> >()); - rtree_test(g.s, bgi::parameters, bg::strategy::index::cartesian<> >()); - rtree_test(g.s, bgi::parameters, bg::strategy::index::cartesian<> >()); - rtree_test(g.s, bgi::parameters, bg::strategy::index::cartesian<> >()); + rtree_test(g.pt, bgi::parameters, bg::strategies::index::cartesian<> >()); + rtree_test(g.pt, bgi::parameters, bg::strategies::index::cartesian<> >()); + rtree_test(g.pt, bgi::parameters, bg::strategies::index::cartesian<> >()); + rtree_test(g.b, bgi::parameters, bg::strategies::index::cartesian<> >()); + rtree_test(g.b, bgi::parameters, bg::strategies::index::cartesian<> >()); + rtree_test(g.b, bgi::parameters, bg::strategies::index::cartesian<> >()); + rtree_test(g.s, bgi::parameters, bg::strategies::index::cartesian<> >()); + rtree_test(g.s, bgi::parameters, bg::strategies::index::cartesian<> >()); + rtree_test(g.s, bgi::parameters, bg::strategies::index::cartesian<> >()); - rtree_test(g.pt, bgi::parameters, bg::strategy::index::spherical<> >()); - rtree_test(g.pt, bgi::parameters, bg::strategy::index::spherical<> >()); - rtree_test(g.pt, bgi::parameters, bg::strategy::index::spherical<> >()); - rtree_test(g.b, bgi::parameters, bg::strategy::index::spherical<> >()); - rtree_test(g.b, bgi::parameters, bg::strategy::index::spherical<> >()); - rtree_test(g.b, bgi::parameters, bg::strategy::index::spherical<> >()); - rtree_test(g.s, bgi::parameters, bg::strategy::index::spherical<> >()); - rtree_test(g.s, bgi::parameters, bg::strategy::index::spherical<> >()); - rtree_test(g.s, bgi::parameters, bg::strategy::index::spherical<> >()); + rtree_test(g.pt, bgi::parameters, bg::strategies::index::spherical<> >()); + rtree_test(g.pt, bgi::parameters, bg::strategies::index::spherical<> >()); + rtree_test(g.pt, bgi::parameters, bg::strategies::index::spherical<> >()); + rtree_test(g.b, bgi::parameters, bg::strategies::index::spherical<> >()); + rtree_test(g.b, bgi::parameters, bg::strategies::index::spherical<> >()); + rtree_test(g.b, bgi::parameters, bg::strategies::index::spherical<> >()); + rtree_test(g.s, bgi::parameters, bg::strategies::index::spherical<> >()); + rtree_test(g.s, bgi::parameters, bg::strategies::index::spherical<> >()); + rtree_test(g.s, bgi::parameters, bg::strategies::index::spherical<> >()); - rtree_test(g.pt, bgi::parameters, bg::strategy::index::geographic<> >()); - rtree_test(g.pt, bgi::parameters, bg::strategy::index::geographic<> >()); - rtree_test(g.pt, bgi::parameters, bg::strategy::index::geographic<> >()); - rtree_test(g.b, bgi::parameters, bg::strategy::index::geographic<> >()); - rtree_test(g.b, bgi::parameters, bg::strategy::index::geographic<> >()); - rtree_test(g.b, bgi::parameters, bg::strategy::index::geographic<> >()); - rtree_test(g.s, bgi::parameters, bg::strategy::index::geographic<> >()); - rtree_test(g.s, bgi::parameters, bg::strategy::index::geographic<> >()); - rtree_test(g.s, bgi::parameters, bg::strategy::index::geographic<> >()); + rtree_test(g.pt, bgi::parameters, bg::strategies::index::geographic<> >()); + rtree_test(g.pt, bgi::parameters, bg::strategies::index::geographic<> >()); + rtree_test(g.pt, bgi::parameters, bg::strategies::index::geographic<> >()); + rtree_test(g.b, bgi::parameters, bg::strategies::index::geographic<> >()); + rtree_test(g.b, bgi::parameters, bg::strategies::index::geographic<> >()); + rtree_test(g.b, bgi::parameters, bg::strategies::index::geographic<> >()); + rtree_test(g.s, bgi::parameters, bg::strategies::index::geographic<> >()); + rtree_test(g.s, bgi::parameters, bg::strategies::index::geographic<> >()); + rtree_test(g.s, bgi::parameters, bg::strategies::index::geographic<> >()); return 0; } diff --git a/test/geometries/initialization.cpp b/test/geometries/initialization.cpp index 23dd11f52..c71ae302b 100644 --- a/test/geometries/initialization.cpp +++ b/test/geometries/initialization.cpp @@ -3,6 +3,10 @@ // Copyright (c) 2014-2015 Adam Wulkiewicz, Lodz, Poland. +// This file was modified by Oracle on 2020. +// Modifications copyright (c) 2020 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) @@ -10,7 +14,7 @@ #include #include -#include +#include #include #include diff --git a/test/iterators/segment_iterator.cpp b/test/iterators/segment_iterator.cpp index f867a524d..fdfe90ef5 100644 --- a/test/iterators/segment_iterator.cpp +++ b/test/iterators/segment_iterator.cpp @@ -47,6 +47,11 @@ #include +// TEMP +#include +#include +#include + #include #include diff --git a/test/strategies/point_in_box.cpp b/test/strategies/point_in_box.cpp index 8ab354cd8..f246923c9 100644 --- a/test/strategies/point_in_box.cpp +++ b/test/strategies/point_in_box.cpp @@ -3,8 +3,8 @@ // Copyright (c) 2010-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-2020. +// Modifications copyright (c) 2014-2020 Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle @@ -21,7 +21,7 @@ void test_box_of(std::string const& wkt_point, std::string const& wkt_box, bool expected_within, bool expected_covered_by) { typedef bg::model::box box_type; - + Point point; box_type box; bg::read_wkt(wkt_point, point); @@ -32,22 +32,26 @@ void test_box_of(std::string const& wkt_point, std::string const& wkt_box, BOOST_CHECK_EQUAL(detected_within, expected_within); BOOST_CHECK_EQUAL(detected_covered_by, expected_covered_by); - // Also test with the non-default agnostic side version - namespace wi = bg::strategy::within; - wi::point_in_box_by_side<> within_strategy; - wi::point_in_box_by_side covered_by_strategy; + // Also test with the non-default side version + bg::strategy::within::cartesian_point_box_by_side<> within_strategy; + bg::strategy::covered_by::cartesian_point_box_by_side<> covered_by_strategy; detected_within = bg::within(point, box, within_strategy); detected_covered_by = bg::covered_by(point, box, covered_by_strategy); BOOST_CHECK_EQUAL(detected_within, expected_within); BOOST_CHECK_EQUAL(detected_covered_by, expected_covered_by); + // BREAKING CHANGE: + // Internally the strategies are converted to umbrella strategy + // and then the umbrella strategy is used to get correct strategy + // for corresponding algorithm. + // PREVIOUSLY: // We might exchange strategies between within/covered by. // So the lines below might seem confusing, but are as intended - detected_within = bg::covered_by(point, box, within_strategy); - detected_covered_by = bg::within(point, box, covered_by_strategy); - BOOST_CHECK_EQUAL(detected_within, expected_within); - BOOST_CHECK_EQUAL(detected_covered_by, expected_covered_by); + //detected_within = bg::covered_by(point, box, within_strategy); + //detected_covered_by = bg::within(point, box, covered_by_strategy); + //BOOST_CHECK_EQUAL(detected_within, expected_within); + //BOOST_CHECK_EQUAL(detected_covered_by, expected_covered_by); // Finally we call the strategies directly detected_within = within_strategy.apply(point, box); diff --git a/test/strategies/segment_intersection.cpp b/test/strategies/segment_intersection.cpp index c0230aabf..ebda67ef7 100644 --- a/test/strategies/segment_intersection.cpp +++ b/test/strategies/segment_intersection.cpp @@ -24,12 +24,6 @@ #include #include - -#include -#include - -#include - #include #include @@ -37,6 +31,12 @@ #include #include +#include + +#include +#include + + BOOST_GEOMETRY_REGISTER_BOOST_TUPLE_CS(cs::cartesian); diff --git a/test/strategies/test_within.hpp b/test/strategies/test_within.hpp index ae9b06dde..f4280beb0 100644 --- a/test/strategies/test_within.hpp +++ b/test/strategies/test_within.hpp @@ -3,8 +3,8 @@ // Copyright (c) 2010-2012 Barend Gehrels, Amsterdam, the Netherlands. -// This file was modified by Oracle on 2014, 2019. -// Modifications copyright (c) 2014, 2019 Oracle and/or its affiliates. +// This file was modified by Oracle on 2014-2020. +// Modifications copyright (c) 2014-2020 Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle @@ -31,6 +31,10 @@ #include #include +// TEMP +#include +#include +#include #include #include diff --git a/test/strategies/winding.cpp b/test/strategies/winding.cpp index ba4ec1b75..fb10d461c 100644 --- a/test/strategies/winding.cpp +++ b/test/strategies/winding.cpp @@ -3,8 +3,8 @@ // Copyright (c) 2010-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-2020. +// Modifications copyright (c) 2014-2020 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, @@ -24,7 +24,7 @@ void test_cartesian() std::string const triangle = "POLYGON((0 0,0 4,6 0,0 0))"; std::string const with_hole = "POLYGON((0 0,0 3,3 3,3 0,0 0),(1 1,2 1,2 2,1 2,1 1))"; - bg::strategy::within::winding s; + bg::strategy::within::cartesian_winding<> s; test_geometry("b1", "POINT(1 1)", box, s, true); @@ -78,7 +78,7 @@ void test_spherical() typedef bg::model::point > point; typedef bg::model::polygon polygon; - bg::strategy::within::winding s; + bg::strategy::within::spherical_winding<> s; // Ticket #9354 diff --git a/test/test_geometries/all_custom_linestring.hpp b/test/test_geometries/all_custom_linestring.hpp index 133fb29a2..a2a3c4a12 100644 --- a/test/test_geometries/all_custom_linestring.hpp +++ b/test/test_geometries/all_custom_linestring.hpp @@ -2,6 +2,11 @@ // Unit Test // Copyright (c) 2011-2012 Barend Gehrels, Amsterdam, the Netherlands. + +// This file was modified by Oracle on 2020. +// Modifications copyright (c) 2020 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) @@ -11,9 +16,6 @@ #include -#include - - #include #include #include diff --git a/test/test_geometries/all_custom_polygon.hpp b/test/test_geometries/all_custom_polygon.hpp index 1ce9286eb..7e385f971 100644 --- a/test/test_geometries/all_custom_polygon.hpp +++ b/test/test_geometries/all_custom_polygon.hpp @@ -3,6 +3,10 @@ // Copyright (c) 2011-2012 Barend Gehrels, Amsterdam, the Netherlands. +// This file was modified by Oracle on 2020. +// Modifications copyright (c) 2020 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) @@ -12,9 +16,6 @@ #include -#include - - #include #include #include diff --git a/test/test_geometries/all_custom_ring.hpp b/test/test_geometries/all_custom_ring.hpp index aa1d37cfe..e49acea9b 100644 --- a/test/test_geometries/all_custom_ring.hpp +++ b/test/test_geometries/all_custom_ring.hpp @@ -3,6 +3,10 @@ // Copyright (c) 2011-2012 Barend Gehrels, Amsterdam, the Netherlands. +// This file was modified by Oracle on 2020. +// Modifications copyright (c) 2020 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) @@ -12,9 +16,6 @@ #include -#include - - #include #include #include diff --git a/test/test_geometries/wrapped_boost_array.hpp b/test/test_geometries/wrapped_boost_array.hpp index 8f4d8e39b..9dc723589 100644 --- a/test/test_geometries/wrapped_boost_array.hpp +++ b/test/test_geometries/wrapped_boost_array.hpp @@ -3,6 +3,10 @@ // Copyright (c) 2010-2012 Barend Gehrels, Amsterdam, the Netherlands. +// This file was modified by Oracle on 2020. +// Modifications copyright (c) 2020 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) @@ -14,7 +18,7 @@ #include #include -#include +#include #include #include