Merge branch 'develop' into feature/azimuth

This commit is contained in:
Adam Wulkiewicz 2021-02-16 14:14:13 +01:00
commit ae33a8dc0c
217 changed files with 5746 additions and 4201 deletions

View File

@ -92,8 +92,11 @@ jobs:
- name: Install - name: Install
run: | run: |
sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 15CF4D18AF4F7421 # Required for compilers not available in ubuntu latest
sudo add-apt-repository "deb http://apt.llvm.org/bionic/ llvm-toolchain-bionic-10 main" 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 add-apt-repository -y ppa:ubuntu-toolchain-r/test
sudo apt -q -y update sudo apt -q -y update
sudo apt -q -y install clang-${{ matrix.version }} g++-multilib sudo apt -q -y install clang-${{ matrix.version }} g++-multilib

View File

@ -80,9 +80,11 @@ jobs:
- name: Install - name: Install
run: | 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 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/ 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 add-apt-repository -y ppa:ubuntu-toolchain-r/test
sudo apt -q -y update sudo apt -q -y update
sudo apt -q -y install g++-${{ matrix.version }} g++-${{ matrix.version }}-multilib sudo apt -q -y install g++-${{ matrix.version }} g++-${{ matrix.version }}-multilib

View File

@ -1,6 +1,6 @@
# ![Boost.Geometry](doc/other/logo/logo_bkg.png) # ![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) [![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) [![Documentation](https://img.shields.io/badge/-documentation-4480cc.png)](http://boost.org/libs/geometry)

View File

@ -14,6 +14,7 @@ test-suite boost-geometry-extensions-algorithms
[ run distance_info.cpp ] [ run distance_info.cpp ]
[ run connect.cpp ] [ run connect.cpp ]
# [ run offset.cpp ] # [ run offset.cpp ]
[ run parse.cpp ]
[ run midpoints.cpp ] [ run midpoints.cpp ]
# [ run selected.cpp ] # [ run selected.cpp ]
; ;

View File

@ -0,0 +1,219 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Unit Test
// Copyright (c) 2021 Joni Kerkelä, Oulu, Finland.
// Copyright (c) 2021 Ayush Gupta, Gujarat, India
// 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 <string>
#include <geometry_test_common.hpp>
#include <boost/geometry/core/coordinate_type.hpp>
#include <boost/geometry/extensions/algorithms/parse.hpp>
#include <boost/geometry/geometries/point.hpp>
#include <boost/geometry/util/math.hpp>
#include <test_common/test_point.hpp>
using namespace boost::geometry;
template <typename Geometry, typename T>
void test_parse(std::string const& coordinate_1,
std::string const& coordinate_2,
T expected_result_coord_1,
T expected_result_coord_2)
{
Geometry geometry;
geometry = parse<Geometry>(coordinate_1, coordinate_2);
BOOST_CHECK_CLOSE(((double)bg::get<0>(geometry)), expected_result_coord_1, 1.0e-4);
BOOST_CHECK_CLOSE(((double)bg::get<1>(geometry)), expected_result_coord_2, 1.0e-4);
parse(geometry, coordinate_1, coordinate_2);
BOOST_CHECK_CLOSE(((double)bg::get<0>(geometry)), expected_result_coord_1, 1.0e-4);
BOOST_CHECK_CLOSE(((double)bg::get<1>(geometry)), expected_result_coord_2, 1.0e-4);
}
template <typename P, typename S>
void test_parse_with_parse_strategy(std::string const& coordinate_1, std::string const& coordinate_2,
double expected_result_coord_1, double expected_result_coord_2, S const& strategy)
{
P p;
parse<P, S>(p, coordinate_1, coordinate_2, strategy);
BOOST_CHECK_CLOSE(((double)bg::get<0>(p)), expected_result_coord_1, 1.0e-4);
BOOST_CHECK_CLOSE(((double)bg::get<1>(p)), expected_result_coord_2, 1.0e-4);
}
template <typename P, typename T>
void test_parse_with_point_and_parse_strategy(std::string const& coordinate_1, std::string const& coordinate_2,
double expected_result_coord_1, double expected_result_coord_2, T const& parser)
{
test_parse_with_parse_strategy<P, T>(coordinate_1,
coordinate_2, expected_result_coord_1, expected_result_coord_2, parser);
}
template <typename P, bool as_radian>
void test_all_complex_dms_strategy()
{
typedef typename coordinate_type<P>::type coord_t;
using parser_t = projections::detail::dms_parser<coord_t, as_radian, 'w', 'e', 'n', 's'>;
// with minutes
double expected_dms_result1 = as_radian ? 5.166666666 * bg::math::d2r<double>() : 5.166666666;
double expected_dms_result2 = as_radian ? -5.166666666 * bg::math::d2r<double>() : -5.166666666;
test_parse_with_point_and_parse_strategy<P, parser_t>(std::string("5d10E"), std::string("5d10N"),
expected_dms_result1, expected_dms_result2, parser_t());
// with minutes and indicator
double expected_dms_result3 = as_radian ? (5.16666666 * bg::math::d2r<double>()) : 5.16666666;
double expected_dms_result4 = as_radian ? -(5.16666666 * bg::math::d2r<double>()) : -5.16666666;
test_parse_with_point_and_parse_strategy<P, parser_t>(std::string("5d10'E"), std::string("5d10'N"),
expected_dms_result3, expected_dms_result4, parser_t());
// with minutes/seconds
double expected_dms_result5 = as_radian ? (5.1680555555 * bg::math::d2r<double>()) : 5.1680555555;
double expected_dms_result6 = as_radian ? -(5.16805555555 * bg::math::d2r<double>()) : -5.16805555555;
test_parse_with_point_and_parse_strategy<P, parser_t>(std::string("5d10'05E"), std::string("5d10'05N"),
expected_dms_result5, expected_dms_result6, parser_t());
// with seconds only
double sec = 1 / 3600.0;
double expected_dms_result7 = as_radian ? ((5 + sec) * bg::math::d2r<double>()) : (5 + sec);
double expected_dms_result8 = as_radian ? -((5 + sec) * bg::math::d2r<double>()) : -(5 + sec);
test_parse_with_point_and_parse_strategy<P, parser_t>(std::string("5d1\"E"), std::string("5d1\"N"),
expected_dms_result7, expected_dms_result8, parser_t());
// with spaces and signs
test_parse_with_point_and_parse_strategy<P, parser_t>(std::string("5d 1\" E"), std::string("5d 1\" N"),
expected_dms_result7, expected_dms_result8, parser_t());
test_parse_with_point_and_parse_strategy<P, parser_t>(std::string("+5d 1\" E"), std::string("+5d 1\" N"),
expected_dms_result7, expected_dms_result8, parser_t());
test_parse_with_point_and_parse_strategy<P, parser_t>(std::string("-5d 1\" E"), std::string("-5d 1\" N"),
-expected_dms_result7, -expected_dms_result8, parser_t());
test_parse_with_point_and_parse_strategy<P, parser_t>(std::string("5d 10' 05 E"), std::string("5d 10' 05 N"),
expected_dms_result5, expected_dms_result6, parser_t());
// in radians
double expected_dms_result9 = as_radian ? 5.15 : (5.15 * bg::math::r2d<double>());
double expected_dms_result10 = as_radian ? -5.15 : -(5.15 * bg::math::r2d<double>());
test_parse_with_point_and_parse_strategy<P, parser_t>(std::string("5.15RE"), std::string("5.15RN"),
expected_dms_result9, expected_dms_result10, parser_t());
test_parse_with_point_and_parse_strategy<P, parser_t>(std::string("5.15R E"), std::string("5.15R N"),
expected_dms_result9, expected_dms_result10, parser_t());
// test with random characters in strategy(for generality check)
using parser_t1 = bg::projections::detail::dms_parser<coord_t, true, 'A', 'B', 'C', 'D', 'm', 's', 'o', 'p'>;
test_parse_with_point_and_parse_strategy<P, parser_t1>(std::string("45o 30m 30s A"), std::string("120o 30m 45s D"),
-2.1033408163, 0.7942705942, parser_t1());
test_parse_with_point_and_parse_strategy<P, parser_t1>(std::string("1.75p c"), std::string("5o 40m 55s b"),
0.0991686810, -1.7500000000, parser_t1());
// creating another strategy with returning value as degree
using parser_t2 = bg::projections::detail::dms_parser<coord_t, false>; // return value in degree and rest parameters as default value.
test_parse_with_point_and_parse_strategy<P, parser_t2>(std::string("80d 45' 30\"S"), std::string("150d 30' 30\"E"),
150.5083333333, -80.7583333333, parser_t2());
test_parse_with_point_and_parse_strategy<P, parser_t2>(std::string("15d 10' 20\"N"), std::string("2.75r W"),
-157.5633261332, 15.1722222222, parser_t2());
}
template <typename P, bool as_radian>
void test_all_with_simple_dms_strategy()
{
using coord_t = typename coordinate_type<P>::type;
double generic_expected_result1 = as_radian ? 2 * bg::math::d2r<double>() : 2;
double generic_expected_result2 = as_radian ? -4 * bg::math::d2r<double>() : -4;
using parser_t1 = projections::detail::dms_parser<coord_t, as_radian, 'w', 'e', 'n', 's'>;
test_parse_with_point_and_parse_strategy<P, parser_t1>(std::string("2e"), std::string("4n"),
generic_expected_result1, generic_expected_result2, parser_t1());
test_parse_with_point_and_parse_strategy<P, parser_t1>(std::string("2w"), std::string("4s"),
generic_expected_result2, generic_expected_result1, parser_t1());
test_parse_with_point_and_parse_strategy<P, parser_t1>(std::string("2w"), std::string("4e"),
2 * generic_expected_result1, generic_expected_result1, parser_t1());
test_parse_with_point_and_parse_strategy<P, parser_t1>(std::string("2s"), std::string("4n"),
-(generic_expected_result1), generic_expected_result2, parser_t1());
test_parse_with_point_and_parse_strategy<P, parser_t1>(std::string("4n"), std::string("2s"),
-(generic_expected_result1), generic_expected_result2, parser_t1());
using parser_t2 = projections::detail::dms_parser<coord_t, as_radian, 'n', 'o', 'z', 'w'>;
test_parse_with_point_and_parse_strategy<P, parser_t2>(std::string("2o"), std::string("4z"),
generic_expected_result1, generic_expected_result2, parser_t2());
using parser_t3 = projections::detail::dms_parser<coord_t, as_radian, 'W', 'E', 'N', 'S'>;
test_parse_with_point_and_parse_strategy<P, parser_t3>(std::string("4N"), std::string("2S"),
-(generic_expected_result1), generic_expected_result2, parser_t3());
test_parse_with_point_and_parse_strategy<P, parser_t3>(std::string("4n"), std::string("2s"),
-(generic_expected_result1), generic_expected_result2, parser_t3());
}
template<typename Geometry>
void test_all_without_strategy()
{
using T = typename bg::coordinate_type<Geometry>::type;
T const d2r = math::d2r<T>();
test_parse<Geometry, T>(std::string("1E"), std::string("2N"), 1 * d2r, 2 * d2r);
test_parse<Geometry, T>(std::string("1W"), std::string("2S"), -1 * d2r, -2 * d2r);
test_parse<Geometry, T>(std::string("1E"), std::string("2N"), 1 * d2r, 2 * d2r);
test_parse<Geometry, T>(std::string("1W"), std::string("2S"), -1 * d2r, -2 * d2r);
test_parse<Geometry, T>(std::string("1W"), std::string("2S"), -1 * d2r, -2 * d2r);
test_parse<Geometry, T>(std::string("1W"), std::string("2S"), -1 * d2r, -2 * d2r);
test_parse<Geometry, T>(std::string("1W"), std::string("2S"), -1 * d2r, -2 * d2r);
test_parse<Geometry, T>(std::string("1W"), std::string("2S"), -1 * d2r, -2 * d2r);
// tests for dms strings, values returned in radian(default strategy).
test_parse<Geometry, T>(std::string("45d 30' 30\" N"), std::string("120D 30'45\"W"), -2.1033408163, 0.7942705942);
test_parse<Geometry, T>(std::string("32D45' 57\"n"), std::string("170d 10' 25\"E"), 2.9700910868, 0.5718719189);
test_parse<Geometry, T>(std::string("5d38'40\"S"), std::string("168D 10' 20\"w"), -2.9351602461, -0.0985141822);
test_parse<Geometry, T>(std::string("72D 20'45\"s"), std::string("5d 40' 55\"e"), 0.0991686810, -1.2626735329);
// test for radian and dms strings combined returning values in degree.
test_parse<Geometry, T>(std::string("2.5r N"), std::string("0.75r E"), 0.7500000000, 2.5000000000);
test_parse<Geometry, T>(std::string("1.25r S"), std::string("120D 30' 45\"w"), -2.1033408163, -1.2500000000);
}
void test_without_strategy()
{
test_all_without_strategy<bg::model::point<double, 2, bg::cs::spherical<bg::degree>>>();
test_all_without_strategy<bg::model::point<double, 2, bg::cs::spherical<bg::radian>>>();
test_all_without_strategy<bg::model::point<double, 2, bg::cs::spherical_equatorial<bg::degree>>>();
test_all_without_strategy<bg::model::point<double, 2, bg::cs::spherical_equatorial<bg::radian>>>();
test_all_without_strategy<bg::model::point<double, 2, bg::cs::geographic<bg::degree>>>();
test_all_without_strategy<bg::model::point<double, 2, bg::cs::geographic<bg::radian>>>();
test_all_without_strategy<bg::model::point<double, 2, bg::cs::undefined>>();
test_all_without_strategy<bg::model::point<double, 2, bg::cs::cartesian>>();
}
void test_all()
{
test_without_strategy();
test_all_with_simple_dms_strategy<bg::model::point<double, 2, bg::cs::geographic<bg::degree> >, false>();
test_all_with_simple_dms_strategy<bg::model::point<double, 2, bg::cs::geographic<bg::radian> >, true>();
test_all_complex_dms_strategy<bg::model::point<double, 2, bg::cs::geographic<bg::degree> >, false>();
test_all_complex_dms_strategy<bg::model::point<double, 2, bg::cs::geographic<bg::radian> >, true>();
}
int test_main(int, char* [])
{
test_all();
return 0;
}

View File

@ -4,8 +4,8 @@
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France. // Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK. // Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
// This file was modified by Oracle on 2017-2020. // This file was modified by Oracle on 2017-2021.
// Modifications copyright (c) 2017-2020 Oracle and/or its affiliates. // Modifications copyright (c) 2017-2021 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, 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 // 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::envelope(geometry_in, box);
geometry::buffer(box, box, distance_strategy.max_distance(join_strategy, end_strategy)); 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<GeometryIn>::type GeometryIn, GeometryIn
>::type intersection_strategy; >::type strategies;
rescale_policy_type rescale_policy rescale_policy_type rescale_policy
= boost::geometry::get_rescale_policy<rescale_policy_type>( = boost::geometry::get_rescale_policy<rescale_policy_type>(
box, intersection_strategy); box, strategies);
detail::buffer::buffer_inserter<polygon_type>(geometry_in, range::back_inserter(geometry_out), detail::buffer::buffer_inserter<polygon_type>(geometry_in,
range::back_inserter(geometry_out),
distance_strategy, distance_strategy,
side_strategy, side_strategy,
join_strategy, join_strategy,
end_strategy, end_strategy,
point_strategy, point_strategy,
intersection_strategy, strategies,
rescale_policy); rescale_policy);
} }

View File

@ -5,8 +5,8 @@
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK. // Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
// Copyright (c) 2014 Samuel Debionne, Grenoble, France. // Copyright (c) 2014 Samuel Debionne, Grenoble, France.
// This file was modified by Oracle on 2014, 2017. // This file was modified by Oracle on 2014-2020.
// Modifications copyright (c) 2014-2017 Oracle and/or its affiliates. // 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 Adam Wulkiewicz, on behalf of Oracle
@ -31,6 +31,8 @@
#include <boost/geometry/core/access.hpp> #include <boost/geometry/core/access.hpp>
#include <boost/geometry/geometries/concepts/check.hpp> #include <boost/geometry/geometries/concepts/check.hpp>
#include <boost/geometry/strategies/default_strategy.hpp> #include <boost/geometry/strategies/default_strategy.hpp>
#include <boost/geometry/strategies/detail.hpp>
#include <boost/geometry/strategies/relate/services.hpp>
namespace boost { namespace geometry namespace boost { namespace geometry
@ -65,9 +67,14 @@ struct crosses
namespace resolve_strategy namespace resolve_strategy
{ {
template
<
typename Strategy,
bool IsUmbrella = strategies::detail::is_umbrella_strategy<Strategy>::value
>
struct crosses struct crosses
{ {
template <typename Geometry1, typename Geometry2, typename Strategy> template <typename Geometry1, typename Geometry2>
static inline bool apply(Geometry1 const& geometry1, static inline bool apply(Geometry1 const& geometry1,
Geometry2 const& geometry2, Geometry2 const& geometry2,
Strategy const& strategy) Strategy const& strategy)
@ -75,21 +82,50 @@ struct crosses
concepts::check<Geometry1 const>(); concepts::check<Geometry1 const>();
concepts::check<Geometry2 const>(); concepts::check<Geometry2 const>();
return dispatch::crosses<Geometry1, Geometry2>::apply(geometry1, geometry2, strategy); return dispatch::crosses
<
Geometry1, Geometry2
>::apply(geometry1, geometry2, strategy);
} }
};
template <typename Strategy>
struct crosses<Strategy, false>
{
template <typename Geometry1, typename Geometry2>
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<Strategy>::get(strategy))
>::apply(geometry1, geometry2,
strategy_converter<Strategy>::get(strategy));
}
};
template <>
struct crosses<default_strategy, false>
{
template <typename Geometry1, typename Geometry2> template <typename Geometry1, typename Geometry2>
static inline bool apply(Geometry1 const& geometry1, static inline bool apply(Geometry1 const& geometry1,
Geometry2 const& geometry2, Geometry2 const& geometry2,
default_strategy) default_strategy)
{ {
typedef typename strategy::relate::services::default_strategy //typedef typename strategies::crosses::services::default_strategy
typedef typename strategies::relate::services::default_strategy
< <
Geometry1, Geometry1,
Geometry2 Geometry2
>::type strategy_type; >::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, Geometry2 const& geometry2,
Strategy const& strategy) Strategy const& strategy)
{ {
return resolve_strategy::crosses::apply(geometry1, geometry2, strategy); return resolve_strategy::crosses
<
Strategy
>::apply(geometry1, geometry2, strategy);
} }
}; };

View File

@ -2,8 +2,8 @@
// Copyright (c) 2012-2020 Barend Gehrels, Amsterdam, the Netherlands. // Copyright (c) 2012-2020 Barend Gehrels, Amsterdam, the Netherlands.
// This file was modified by Oracle on 2017-2020. // This file was modified by Oracle on 2017-2021.
// Modifications copyright (c) 2017-2020 Oracle and/or its affiliates. // Modifications copyright (c) 2017-2021 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, 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, // Use, modification and distribution is subject to the Boost Software License,
@ -921,7 +921,7 @@ template
typename JoinStrategy, typename JoinStrategy,
typename EndStrategy, typename EndStrategy,
typename PointStrategy, typename PointStrategy,
typename IntersectionStrategy, typename Strategies,
typename RobustPolicy, typename RobustPolicy,
typename VisitPiecesPolicy typename VisitPiecesPolicy
> >
@ -931,7 +931,7 @@ inline void buffer_inserter(GeometryInput const& geometry_input, OutputIterator
JoinStrategy const& join_strategy, JoinStrategy const& join_strategy,
EndStrategy const& end_strategy, EndStrategy const& end_strategy,
PointStrategy const& point_strategy, PointStrategy const& point_strategy,
IntersectionStrategy const& intersection_strategy, Strategies const& strategies,
RobustPolicy const& robust_policy, RobustPolicy const& robust_policy,
VisitPiecesPolicy& visit_pieces_policy VisitPiecesPolicy& visit_pieces_policy
) )
@ -941,11 +941,11 @@ inline void buffer_inserter(GeometryInput const& geometry_input, OutputIterator
typedef detail::buffer::buffered_piece_collection typedef detail::buffer::buffered_piece_collection
< <
typename geometry::ring_type<GeometryOutput>::type, typename geometry::ring_type<GeometryOutput>::type,
IntersectionStrategy, Strategies,
DistanceStrategy, DistanceStrategy,
RobustPolicy RobustPolicy
> collection_type; > 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; collection_type const& const_collection = collection;
bool const areal = util::is_areal<GeometryInput>::value; bool const areal = util::is_areal<GeometryInput>::value;
@ -962,7 +962,7 @@ inline void buffer_inserter(GeometryInput const& geometry_input, OutputIterator
>::apply(geometry_input, collection, >::apply(geometry_input, collection,
distance_strategy, side_strategy, join_strategy, distance_strategy, side_strategy, join_strategy,
end_strategy, point_strategy, end_strategy, point_strategy,
robust_policy, intersection_strategy.get_side_strategy()); robust_policy, strategies.side()); // pass strategies?
collection.get_turns(); collection.get_turns();
if (BOOST_GEOMETRY_CONDITION(areal)) if (BOOST_GEOMETRY_CONDITION(areal))
@ -1029,7 +1029,7 @@ template
typename JoinStrategy, typename JoinStrategy,
typename EndStrategy, typename EndStrategy,
typename PointStrategy, typename PointStrategy,
typename IntersectionStrategy, typename Strategies,
typename RobustPolicy typename RobustPolicy
> >
inline void buffer_inserter(GeometryInput const& geometry_input, OutputIterator out, 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, JoinStrategy const& join_strategy,
EndStrategy const& end_strategy, EndStrategy const& end_strategy,
PointStrategy const& point_strategy, PointStrategy const& point_strategy,
IntersectionStrategy const& intersection_strategy, Strategies const& strategies,
RobustPolicy const& robust_policy) RobustPolicy const& robust_policy)
{ {
detail::buffer::visit_pieces_default_policy visitor; detail::buffer::visit_pieces_default_policy visitor;
buffer_inserter<GeometryOutput>(geometry_input, out, buffer_inserter<GeometryOutput>(geometry_input, out,
distance_strategy, side_strategy, join_strategy, distance_strategy, side_strategy, join_strategy,
end_strategy, point_strategy, end_strategy, point_strategy,
intersection_strategy, robust_policy, visitor); strategies, robust_policy, visitor);
} }
#endif // DOXYGEN_NO_DETAIL #endif // DOXYGEN_NO_DETAIL

View File

@ -193,30 +193,37 @@ struct buffer_less
} }
}; };
template <typename Strategy>
struct piece_get_box struct piece_get_box
{ {
explicit piece_get_box(Strategy const& strategy)
: m_strategy(strategy)
{}
template <typename Box, typename Piece> template <typename Box, typename Piece>
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); assert_coordinate_type_equal(total, piece.m_piece_border.m_envelope);
typedef typename strategy::expand::services::default_strategy
<
box_tag, typename cs_tag<Box>::type
>::type expand_strategy_type;
if (piece.m_piece_border.m_has_envelope) if (piece.m_piece_border.m_has_envelope)
{ {
geometry::expand(total, piece.m_piece_border.m_envelope, geometry::expand(total, piece.m_piece_border.m_envelope,
expand_strategy_type()); m_strategy);
} }
} }
Strategy const& m_strategy;
}; };
template <typename DisjointBoxBoxStrategy> template <typename Strategy>
struct piece_overlaps_box struct piece_overlaps_box
{ {
explicit piece_overlaps_box(Strategy const& strategy)
: m_strategy(strategy)
{}
template <typename Box, typename Piece> template <typename Box, typename Piece>
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); 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, return ! geometry::detail::disjoint::disjoint_box_box(box, piece.m_piece_border.m_envelope,
DisjointBoxBoxStrategy()); m_strategy);
} }
Strategy const& m_strategy;
}; };
template <typename Strategy>
struct turn_get_box struct turn_get_box
{ {
explicit turn_get_box(Strategy const& strategy)
: m_strategy(strategy)
{}
template <typename Box, typename Turn> template <typename Box, typename Turn>
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<Box>::type
>::type expand_strategy_type;
assert_coordinate_type_equal(total, turn.point); 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 <typename DisjointPointBoxStrategy> template <typename Strategy>
struct turn_overlaps_box struct turn_overlaps_box
{ {
explicit turn_overlaps_box(Strategy const& strategy)
: m_strategy(strategy)
{}
template <typename Box, typename Turn> template <typename Box, typename Turn>
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); assert_coordinate_type_equal(turn.point, box);
return ! geometry::detail::disjoint::disjoint_point_box(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 struct enriched_map_buffer_include_policy

View File

@ -3,8 +3,8 @@
// Copyright (c) 2012-2014 Barend Gehrels, Amsterdam, the Netherlands. // Copyright (c) 2012-2014 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2017 Adam Wulkiewicz, Lodz, Poland. // Copyright (c) 2017 Adam Wulkiewicz, Lodz, Poland.
// This file was modified by Oracle on 2016-2020. // This file was modified by Oracle on 2016-2021.
// Modifications copyright (c) 2016-2020 Oracle and/or its affiliates. // Modifications copyright (c) 2016-2021 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, 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, // Use, modification and distribution is subject to the Boost Software License,
@ -117,7 +117,7 @@ namespace detail { namespace buffer
template template
< <
typename Ring, typename Ring,
typename IntersectionStrategy, typename Strategy,
typename DistanceStrategy, typename DistanceStrategy,
typename RobustPolicy typename RobustPolicy
> >
@ -131,27 +131,6 @@ struct buffered_piece_collection
typedef geometry::model::box<point_type> box_type; typedef geometry::model::box<point_type> 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 typedef buffer_turn_info
< <
point_type, point_type,
@ -233,22 +212,22 @@ struct buffered_piece_collection
inline original_ring(clockwise_ring_type const& ring, inline original_ring(clockwise_ring_type const& ring,
bool is_interior, bool has_interiors, bool is_interior, bool has_interiors,
envelope_strategy_type const& envelope_strategy, Strategy const& strategy)
expand_strategy_type const& expand_strategy)
: m_ring(ring) : m_ring(ring)
, m_is_interior(is_interior) , m_is_interior(is_interior)
, m_has_interiors(has_interiors) , 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 // create monotonic sections in x-dimension
// The dimension is critical because the direction is later used // The dimension is critical because the direction is later used
// in the optimization for within checks using winding strategy // in the optimization for within checks using winding strategy
// and this strategy is scanning in x direction. // and this strategy is scanning in x direction.
typedef std::integer_sequence<std::size_t, 0> dimensions; typedef std::integer_sequence<std::size_t, 0> dimensions;
geometry::sectionalize<false, dimensions>(m_ring, geometry::sectionalize
detail::no_rescale_policy(), m_sections, <
envelope_strategy, expand_strategy); false, dimensions
>(m_ring, detail::no_rescale_policy(), m_sections, strategy);
} }
clockwise_ring_type m_ring; clockwise_ring_type m_ring;
@ -295,31 +274,18 @@ struct buffered_piece_collection
cluster_type m_clusters; cluster_type m_clusters;
IntersectionStrategy m_intersection_strategy; Strategy m_strategy;
DistanceStrategy m_distance_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; RobustPolicy const& m_robust_policy;
buffered_piece_collection(IntersectionStrategy const& intersection_strategy, buffered_piece_collection(Strategy const& strategy,
DistanceStrategy const& distance_strategy, DistanceStrategy const& distance_strategy,
RobustPolicy const& robust_policy) RobustPolicy const& robust_policy)
: m_first_piece_index(-1) : m_first_piece_index(-1)
, m_deflate(false) , m_deflate(false)
, m_has_deflated(false) , m_has_deflated(false)
, m_intersection_strategy(intersection_strategy) , m_strategy(strategy)
, m_distance_strategy(distance_strategy) , m_distance_strategy(distance_strategy)
, m_side_strategy(intersection_strategy.get_side_strategy())
, m_area_strategy(intersection_strategy
.template get_area_strategy<point_type>())
, 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<point_type, clockwise_ring_type>())
, m_robust_policy(robust_policy) , m_robust_policy(robust_policy)
{} {}
@ -393,8 +359,7 @@ struct buffered_piece_collection
it != boost::end(m_linear_end_points); it != boost::end(m_linear_end_points);
++it) ++it)
{ {
if (detail::equals::equals_point_point(turn.point, *it, if (detail::equals::equals_point_point(turn.point, *it, m_strategy))
m_intersection_strategy.get_equals_point_point_strategy()))
{ {
turn.is_linear_end_point = true; turn.is_linear_end_point = true;
} }
@ -468,20 +433,11 @@ struct buffered_piece_collection
// Check if a turn is inside any of the originals // Check if a turn is inside any of the originals
inline void check_turn_in_original() 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_in_original_visitor
< <
turn_vector_type, turn_vector_type,
point_in_geometry_strategy_type Strategy
> visitor(m_turns, m_point_in_geometry_strategy); > visitor(m_turns, m_strategy);
geometry::partition geometry::partition
< <
@ -489,8 +445,10 @@ struct buffered_piece_collection
include_turn_policy, include_turn_policy,
detail::partition::include_all_policy detail::partition::include_all_policy
>::apply(m_turns, original_rings, visitor, >::apply(m_turns, original_rings, visitor,
turn_get_box(), turn_in_original_overlaps_box_type(), turn_get_box<Strategy>(m_strategy),
original_get_box(), original_overlaps_box_type()); turn_in_original_overlaps_box<Strategy>(m_strategy),
original_get_box<Strategy>(m_strategy),
original_overlaps_box<Strategy>(m_strategy));
bool const deflate = m_distance_strategy.negative(); bool const deflate = m_distance_strategy.negative();
@ -560,10 +518,11 @@ struct buffered_piece_collection
} }
// Calculate envelopes for piece borders // 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) 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, piece_vector_type,
buffered_ring_collection<buffered_ring<Ring> >, buffered_ring_collection<buffered_ring<Ring> >,
turn_vector_type, turn_vector_type,
IntersectionStrategy, Strategy,
RobustPolicy RobustPolicy
> visitor(m_pieces, offsetted_rings, m_turns, > visitor(m_pieces, offsetted_rings, m_turns,
m_intersection_strategy, m_robust_policy); m_strategy, m_robust_policy);
typedef detail::section::get_section_box detail::sectionalize::enlarge_sections(monotonic_sections, m_strategy);
<
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_envelope_strategy);
geometry::partition geometry::partition
< <
robust_box_type robust_box_type
>::apply(monotonic_sections, visitor, >::apply(monotonic_sections, visitor,
get_section_box_type(), detail::section::get_section_box<Strategy>(m_strategy),
overlaps_section_box_type()); detail::section::overlaps_section_box<Strategy>(m_strategy));
} }
update_turn_administration(); update_turn_administration();
@ -614,21 +564,14 @@ struct buffered_piece_collection
turn_vector_type, piece_vector_type, DistanceStrategy turn_vector_type, piece_vector_type, DistanceStrategy
> visitor(m_turns, m_pieces, m_distance_strategy); > 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 geometry::partition
< <
box_type box_type
>::apply(m_turns, m_pieces, visitor, >::apply(m_turns, m_pieces, visitor,
turn_get_box(), turn_overlaps_box_type(), turn_get_box<Strategy>(m_strategy),
piece_get_box(), piece_overlaps_box_type()); turn_overlaps_box<Strategy>(m_strategy),
piece_get_box<Strategy>(m_strategy),
piece_overlaps_box<Strategy>(m_strategy));
} }
} }
@ -771,7 +714,7 @@ struct buffered_piece_collection
original_rings.back() original_rings.back()
= original_ring(clockwise_ring, = original_ring(clockwise_ring,
is_interior, has_interiors, 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.first_seg_id.segment_index,
boost::begin(ring) + pc.beyond_last_segment_index, boost::begin(ring) + pc.beyond_last_segment_index,
m_robust_policy, m_robust_policy,
m_strategy,
ring_id, 10); ring_id, 10);
} }
@ -1042,7 +986,7 @@ struct buffered_piece_collection
enrich_intersection_points<false, false, overlay_buffer>(m_turns, enrich_intersection_points<false, false, overlay_buffer>(m_turns,
m_clusters, offsetted_rings, offsetted_rings, m_clusters, offsetted_rings, offsetted_rings,
m_robust_policy, m_robust_policy,
m_intersection_strategy); m_strategy);
} }
// Discards all rings which do have not-OK intersection points only. // 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) 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; signed_size_type count_in_original = 0;
// Check of the robust point of this outputted ring is in // Check of the robust point of this outputted ring is in
@ -1085,16 +1027,13 @@ struct buffered_piece_collection
{ {
continue; continue;
} }
if (detail::disjoint::disjoint_point_box(point, if (detail::disjoint::disjoint_point_box(point, original.m_box,m_strategy))
original.m_box,
d_pb_strategy_type()))
{ {
continue; continue;
} }
int const geometry_code int const geometry_code
= detail::within::point_in_geometry(point, = detail::within::point_in_geometry(point, original.m_ring, m_strategy);
original.m_ring, m_point_in_geometry_strategy);
if (geometry_code == -1) if (geometry_code == -1)
{ {
@ -1133,7 +1072,7 @@ struct buffered_piece_collection
buffered_ring<Ring>& ring = *it; buffered_ring<Ring>& ring = *it;
if (! ring.has_intersections() if (! ring.has_intersections()
&& boost::size(ring) > 0u && 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))) if (! point_coveredby_original(geometry::range::front(ring)))
{ {
@ -1173,7 +1112,7 @@ struct buffered_piece_collection
traversed_rings.clear(); traversed_rings.clear();
buffer_overlay_visitor visitor; buffer_overlay_visitor visitor;
traverser::apply(offsetted_rings, offsetted_rings, traverser::apply(offsetted_rings, offsetted_rings,
m_intersection_strategy, m_robust_policy, m_strategy, m_robust_policy,
m_turns, traversed_rings, m_turns, traversed_rings,
turn_info_per_ring, turn_info_per_ring,
m_clusters, visitor); m_clusters, visitor);
@ -1202,7 +1141,14 @@ struct buffered_piece_collection
template <typename GeometryOutput, typename OutputIterator> template <typename GeometryOutput, typename OutputIterator>
inline OutputIterator assign(OutputIterator out) const inline OutputIterator assign(OutputIterator out) const
{ {
typedef detail::overlay::ring_properties<point_type, area_result_type> properties; typedef typename geometry::area_result
<
buffered_ring<Ring>, Strategy
>::type area_result_type;
typedef detail::overlay::ring_properties
<
point_type, area_result_type
> properties;
std::map<ring_identifier, properties> selected; std::map<ring_identifier, properties> selected;
@ -1218,7 +1164,7 @@ struct buffered_piece_collection
if (! it->has_intersections() if (! it->has_intersections()
&& ! it->is_untouched_outside_original) && ! it->is_untouched_outside_original)
{ {
properties p = properties(*it, m_area_strategy); properties p = properties(*it, m_strategy);
if (p.valid) if (p.valid)
{ {
ring_identifier id(0, index, -1); ring_identifier id(0, index, -1);
@ -1234,7 +1180,7 @@ struct buffered_piece_collection
it != boost::end(traversed_rings); it != boost::end(traversed_rings);
++it, ++index) ++it, ++index)
{ {
properties p = properties(*it, m_area_strategy); properties p = properties(*it, m_strategy);
if (p.valid) if (p.valid)
{ {
ring_identifier id(2, index, -1); ring_identifier id(2, index, -1);
@ -1243,9 +1189,9 @@ struct buffered_piece_collection
} }
detail::overlay::assign_parents<overlay_buffer>(offsetted_rings, traversed_rings, detail::overlay::assign_parents<overlay_buffer>(offsetted_rings, traversed_rings,
selected, m_intersection_strategy); selected, m_strategy);
return detail::overlay::add_rings<GeometryOutput>(selected, offsetted_rings, traversed_rings, out, return detail::overlay::add_rings<GeometryOutput>(selected, offsetted_rings, traversed_rings, out,
m_area_strategy); m_strategy);
} }
}; };

View File

@ -117,7 +117,7 @@ template
typename Pieces, typename Pieces,
typename Rings, typename Rings,
typename Turns, typename Turns,
typename IntersectionStrategy, typename Strategy,
typename RobustPolicy typename RobustPolicy
> >
class piece_turn_visitor class piece_turn_visitor
@ -125,7 +125,7 @@ class piece_turn_visitor
Pieces const& m_pieces; Pieces const& m_pieces;
Rings const& m_rings; Rings const& m_rings;
Turns& m_turns; Turns& m_turns;
IntersectionStrategy const& m_intersection_strategy; Strategy const& m_strategy;
RobustPolicy const& m_robust_policy; RobustPolicy const& m_robust_policy;
template <typename Piece> template <typename Piece>
@ -271,7 +271,7 @@ class piece_turn_visitor
turn_policy::apply(unique_sub_range1, unique_sub_range2, turn_policy::apply(unique_sub_range1, unique_sub_range2,
the_model, the_model,
m_intersection_strategy, m_strategy,
m_robust_policy, m_robust_policy,
std::back_inserter(m_turns)); std::back_inserter(m_turns));
} }
@ -283,12 +283,12 @@ public:
piece_turn_visitor(Pieces const& pieces, piece_turn_visitor(Pieces const& pieces,
Rings const& ring_collection, Rings const& ring_collection,
Turns& turns, Turns& turns,
IntersectionStrategy const& intersection_strategy, Strategy const& strategy,
RobustPolicy const& robust_policy) RobustPolicy const& robust_policy)
: m_pieces(pieces) : m_pieces(pieces)
, m_rings(ring_collection) , m_rings(ring_collection)
, m_turns(turns) , m_turns(turns)
, m_intersection_strategy(intersection_strategy) , m_strategy(strategy)
, m_robust_policy(robust_policy) , m_robust_policy(robust_policy)
{} {}
@ -307,7 +307,7 @@ public:
|| is_on_same_convex_ring(piece1, piece2) || is_on_same_convex_ring(piece1, piece2)
|| detail::disjoint::disjoint_box_box(section1.bounding_box, || detail::disjoint::disjoint_box_box(section1.bounding_box,
section2.bounding_box, section2.bounding_box,
m_intersection_strategy.get_disjoint_box_box_strategy()) ) m_strategy) )
{ {
return true; return true;
} }

View File

@ -167,9 +167,11 @@ struct piece_border
return result; return result;
} }
void get_properties_of_border(bool is_point_buffer, Point const& center) template <typename Strategy>
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) if (m_has_envelope)
{ {
// Take roundings into account, enlarge box // Take roundings into account, enlarge box
@ -182,8 +184,8 @@ struct piece_border
} }
} }
template <typename SideStrategy> template <typename Strategy>
void get_properties_of_offsetted_ring_part(SideStrategy const& strategy) void get_properties_of_offsetted_ring_part(Strategy const& strategy)
{ {
if (! ring_or_original_empty()) if (! ring_or_original_empty())
{ {
@ -209,16 +211,16 @@ struct piece_border
m_originals[m_original_size++] = point; m_originals[m_original_size++] = point;
} }
template <typename Box> template <typename Box, typename Strategy>
bool calculate_envelope(Box& envelope) const bool calculate_envelope(Box& envelope, Strategy const& strategy) const
{ {
geometry::assign_inverse(envelope); geometry::assign_inverse(envelope);
if (ring_or_original_empty()) if (ring_or_original_empty())
{ {
return false; return false;
} }
expand_envelope(envelope, m_ring->begin() + m_begin, m_ring->begin() + m_end); 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); expand_envelope(envelope, m_originals.begin(), m_originals.begin() + m_original_size, strategy);
return true; return true;
} }
@ -333,8 +335,8 @@ private :
return true; return true;
} }
template <typename TurnPoint, typename Strategy, typename State> template <typename TurnPoint, typename TiRStrategy, typename State>
bool step(TurnPoint const& point, Point const& p1, Point const& p2, Strategy const & strategy, 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 geometry::strategy::buffer::place_on_ring_type place_on_ring, State& state) const
{ {
// A step between original/offsetted ring is always convex // 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); return strategy.apply(point, p1, p2, dm, place_on_ring, state);
} }
template <typename It, typename Box> template <typename It, typename Box, typename Strategy>
void expand_envelope(Box& envelope, It begin, It end) const 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<Box>::type
>::type expand_strategy_type;
for (It it = begin; it != end; ++it) for (It it = begin; it != end; ++it)
{ {
geometry::expand(envelope, *it, expand_strategy_type()); geometry::expand(envelope, *it, strategy);
} }
} }
template <typename SideStrategy> template <typename Strategy>
bool is_convex(SideStrategy const& strategy) const bool is_convex(Strategy const& strategy) const
{ {
if (ring_or_original_empty()) if (ring_or_original_empty())
{ {
@ -416,8 +413,8 @@ private :
return result; return result;
} }
template <typename It, typename SideStrategy> template <typename It, typename Strategy>
bool is_convex(Point& previous, Point& current, It begin, It end, SideStrategy const& strategy) const bool is_convex(Point& previous, Point& current, It begin, It end, Strategy const& strategy) const
{ {
for (It it = begin; it != end; ++it) for (It it = begin; it != end; ++it)
{ {
@ -429,19 +426,16 @@ private :
return true; return true;
} }
template <typename SideStrategy> template <typename Strategy>
bool is_convex(Point& previous, Point& current, Point const& next, SideStrategy const& strategy) const bool is_convex(Point& previous, Point& current, Point const& next, Strategy const& strategy) const
{ {
typename SideStrategy::equals_point_point_strategy_type const int const side = strategy.side().apply(previous, current, next);
eq_pp_strategy = strategy.get_equals_point_point_strategy();
int const side = strategy.apply(previous, current, next);
if (side == 1) if (side == 1)
{ {
// Next is on the left side of clockwise ring: piece is not convex // Next is on the left side of clockwise ring: piece is not convex
return false; return false;
} }
if (! equals::equals_point_point(current, next, eq_pp_strategy)) if (! equals::equals_point_point(current, next, strategy))
{ {
previous = current; previous = current;
current = next; current = next;

View File

@ -2,8 +2,8 @@
// Copyright (c) 2014 Barend Gehrels, Amsterdam, the Netherlands. // Copyright (c) 2014 Barend Gehrels, Amsterdam, the Netherlands.
// This file was modified by Oracle on 2016, 2018. // This file was modified by Oracle on 2016-2020.
// Modifications copyright (c) 2016-2018 Oracle and/or its affiliates. // Modifications copyright (c) 2016-2020 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, 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, // Use, modification and distribution is subject to the Boost Software License,
@ -31,31 +31,40 @@ namespace boost { namespace geometry
namespace detail { namespace buffer namespace detail { namespace buffer
{ {
template <typename Strategy>
struct original_get_box struct original_get_box
{ {
explicit original_get_box(Strategy const& strategy)
: m_strategy(strategy)
{}
template <typename Box, typename Original> template <typename Box, typename Original>
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); assert_coordinate_type_equal(total, original.m_box);
typedef typename strategy::expand::services::default_strategy geometry::expand(total, original.m_box, m_strategy);
<
box_tag, typename cs_tag<Box>::type
>::type expand_strategy_type;
geometry::expand(total, original.m_box, expand_strategy_type());
} }
Strategy const& m_strategy;
}; };
template <typename DisjointBoxBoxStrategy> template <typename Strategy>
struct original_overlaps_box struct original_overlaps_box
{ {
explicit original_overlaps_box(Strategy const& strategy)
: m_strategy(strategy)
{}
template <typename Box, typename Original> template <typename Box, typename Original>
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); assert_coordinate_type_equal(box, original.m_box);
return ! detail::disjoint::disjoint_box_box(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 struct include_turn_policy
@ -67,11 +76,15 @@ struct include_turn_policy
} }
}; };
template <typename DisjointPointBoxStrategy> template <typename Strategy>
struct turn_in_original_overlaps_box struct turn_in_original_overlaps_box
{ {
explicit turn_in_original_overlaps_box(Strategy const& strategy)
: m_strategy(strategy)
{}
template <typename Box, typename Turn> template <typename Box, typename Turn>
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) 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( 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 //! 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 <typename Turns, typename PointInGeometryStrategy> template <typename Turns, typename Strategy>
class turn_in_original_visitor class turn_in_original_visitor
{ {
public: public:
turn_in_original_visitor(Turns& turns, PointInGeometryStrategy const& strategy) turn_in_original_visitor(Turns& turns, Strategy const& strategy)
: m_mutable_turns(turns) : m_mutable_turns(turns)
, m_point_in_geometry_strategy(strategy) , m_strategy(strategy)
{} {}
template <typename Turn, typename Original> template <typename Turn, typename Original>
@ -234,13 +249,14 @@ public:
return true; return true;
} }
if (geometry::disjoint(turn.point, original.m_box)) if (geometry::disjoint(turn.point, original.m_box, m_strategy))
{ {
// Skip all disjoint // Skip all disjoint
return true; 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) if (code == -1)
{ {
@ -277,7 +293,7 @@ public:
private : private :
Turns& m_mutable_turns; Turns& m_mutable_turns;
PointInGeometryStrategy const& m_point_in_geometry_strategy; Strategy const& m_strategy;
}; };

View File

@ -54,13 +54,11 @@ private:
QueryRangeIterator& qit_min, QueryRangeIterator& qit_min,
Distance& dist_min) Distance& dist_min)
{ {
typedef strategy::index::services::from_strategy using strategies::index::services::strategy_converter;
<
Strategy
> index_strategy_from;
typedef index::parameters typedef index::parameters
< <
index::linear<8>, typename index_strategy_from::type index::linear<8>,
decltype(strategy_converter<Strategy>::get(strategy))
> index_parameters_type; > index_parameters_type;
typedef index::rtree<RTreeValueType, index_parameters_type> rtree_type; typedef index::rtree<RTreeValueType, index_parameters_type> rtree_type;
@ -73,7 +71,7 @@ private:
// create -- packing algorithm // create -- packing algorithm
rtree_type rt(rtree_first, rtree_last, rtree_type rt(rtree_first, rtree_last,
index_parameters_type(index::linear<8>(), index_parameters_type(index::linear<8>(),
index_strategy_from::get(strategy))); strategy_converter<Strategy>::get(strategy)));
RTreeValueType t_v; RTreeValueType t_v;
bool first = true; bool first = true;

View File

@ -4,8 +4,8 @@
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France. // Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK. // Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
// This file was modified by Oracle on 2013, 2014, 2017, 2019. // This file was modified by Oracle on 2013-2020.
// Modifications copyright (c) 2013-2019 Oracle and/or its affiliates. // 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 Adam Wulkiewicz, on behalf of Oracle
@ -66,8 +66,7 @@ struct covered_by<Point, Box, point_tag, box_tag>
template <typename Strategy> template <typename Strategy>
static inline bool apply(Point const& point, Box const& box, Strategy const& strategy) static inline bool apply(Point const& point, Box const& box, Strategy const& strategy)
{ {
::boost::ignore_unused(strategy); return strategy.covered_by(point, box).apply(point, box);
return strategy.apply(point, box);
} }
}; };
@ -78,8 +77,7 @@ struct covered_by<Box1, Box2, box_tag, box_tag>
static inline bool apply(Box1 const& box1, Box2 const& box2, Strategy const& strategy) static inline bool apply(Box1 const& box1, Box2 const& box2, Strategy const& strategy)
{ {
assert_dimension_equal<Box1, Box2>(); assert_dimension_equal<Box1, Box2>();
::boost::ignore_unused(strategy); return strategy.covered_by(box1, box2).apply(box1, box2);
return strategy.apply(box1, box2);
} }
}; };

View File

@ -4,9 +4,8 @@
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France. // Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK. // Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
// This file was modified by Oracle on 2013, 2014, 2017, 2018. // This file was modified by Oracle on 2013-2021.
// Modifications copyright (c) 2013-2018 Oracle and/or its affiliates. // 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 Adam Wulkiewicz, on behalf of Oracle
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library // Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
@ -30,6 +29,8 @@
#include <boost/geometry/strategies/cartesian/point_in_box.hpp> #include <boost/geometry/strategies/cartesian/point_in_box.hpp>
#include <boost/geometry/strategies/cartesian/box_in_box.hpp> #include <boost/geometry/strategies/cartesian/box_in_box.hpp>
#include <boost/geometry/strategies/default_strategy.hpp> #include <boost/geometry/strategies/default_strategy.hpp>
#include <boost/geometry/strategies/detail.hpp>
#include <boost/geometry/strategies/relate/services.hpp>
namespace boost { namespace geometry namespace boost { namespace geometry
@ -56,9 +57,14 @@ struct covered_by
namespace resolve_strategy { namespace resolve_strategy {
template
<
typename Strategy,
bool IsUmbrella = strategies::detail::is_umbrella_strategy<Strategy>::value
>
struct covered_by struct covered_by
{ {
template <typename Geometry1, typename Geometry2, typename Strategy> template <typename Geometry1, typename Geometry2>
static inline bool apply(Geometry1 const& geometry1, static inline bool apply(Geometry1 const& geometry1,
Geometry2 const& geometry2, Geometry2 const& geometry2,
Strategy const& strategy) Strategy const& strategy)
@ -68,23 +74,49 @@ struct covered_by
concepts::check<Geometry2 const>(); concepts::check<Geometry2 const>();
assert_dimension_equal<Geometry1, Geometry2>(); assert_dimension_equal<Geometry1, Geometry2>();
return dispatch::covered_by<Geometry1, Geometry2>::apply(geometry1, return dispatch::covered_by
geometry2, <
strategy); Geometry1, Geometry2
>::apply(geometry1, geometry2, strategy);
} }
};
template <typename Strategy>
struct covered_by<Strategy, false>
{
template <typename Geometry1, typename Geometry2>
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<Strategy>::get(strategy))
>::apply(geometry1, geometry2,
strategy_converter<Strategy>::get(strategy));
}
};
template <>
struct covered_by<default_strategy, false>
{
template <typename Geometry1, typename Geometry2> template <typename Geometry1, typename Geometry2>
static inline bool apply(Geometry1 const& geometry1, static inline bool apply(Geometry1 const& geometry1,
Geometry2 const& geometry2, Geometry2 const& geometry2,
default_strategy) default_strategy)
{ {
typedef typename strategy::covered_by::services::default_strategy typedef typename strategies::relate::services::default_strategy
< <
Geometry1, Geometry1,
Geometry2 Geometry2
>::type strategy_type; >::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, Geometry2 const& geometry2,
Strategy const& strategy) Strategy const& strategy)
{ {
return resolve_strategy::covered_by return resolve_strategy::covered_by<Strategy>
::apply(geometry1, geometry2, strategy); ::apply(geometry1, geometry2, strategy);
} }
}; };

View File

@ -60,13 +60,9 @@ inline bool rings_containing(Geometry1 const& geometry1,
Geometry2 const& geometry2, Geometry2 const& geometry2,
Strategy const& strategy) Strategy const& strategy)
{ {
// TODO: This will be removed when IntersectionStrategy is replaced with
// UmbrellaStrategy
auto const pgs = strategy.template get_point_in_geometry_strategy<Geometry2, Geometry1>();
return geometry::detail::any_range_of(geometry2, [&](auto const& range) 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, Box const& box,
Strategy const& strategy) 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) 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; return false;
@ -129,8 +123,7 @@ struct areal_box
// If there is no intersection of any segment and box, // If there is no intersection of any segment and box,
// the box might be located inside areal geometry // the box might be located inside areal geometry
if ( point_on_border_covered_by(box, areal, if ( point_on_border_covered_by(box, areal, strategy) )
strategy.template get_point_in_geometry_strategy<Box, Areal>()) )
{ {
return false; return false;
} }

View File

@ -5,8 +5,8 @@
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK. // Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
// Copyright (c) 2013-2015 Adam Wulkiewicz, Lodz, Poland. // Copyright (c) 2013-2015 Adam Wulkiewicz, Lodz, Poland.
// This file was modified by Oracle on 2013-2018. // This file was modified by Oracle on 2013-2020.
// Modifications copyright (c) 2013-2018, Oracle and/or its affiliates. // 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 Adam Wulkiewicz, on behalf of Oracle
// Contributed and/or modified by Menelaos Karavelas, 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 \note Is used from other algorithms, declared separately
to avoid circular references to avoid circular references
*/ */
template <typename Box1, typename Box2, typename Strategy> template
inline bool disjoint_box_box(Box1 const& box1, Box2 const& box2, Strategy const&) <
typename Box1, typename Box2, typename Strategy,
std::enable_if_t<strategies::detail::is_umbrella_strategy<Strategy>::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<! strategies::detail::is_umbrella_strategy<Strategy>::value, int> = 0
>
inline bool disjoint_box_box(Box1 const& box1, Box2 const& box2, Strategy const& )
{ {
return Strategy::apply(box1, box2); return Strategy::apply(box1, box2);
} }
@ -63,9 +78,10 @@ template <typename Box1, typename Box2, std::size_t DimensionCount>
struct disjoint<Box1, Box2, DimensionCount, box_tag, box_tag, false> struct disjoint<Box1, Box2, DimensionCount, box_tag, box_tag, false>
{ {
template <typename Strategy> template <typename Strategy>
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);
} }
}; };

View File

@ -5,8 +5,8 @@
// Copyright (c) 2009-2014 Mateusz Loskot, London, UK. // Copyright (c) 2009-2014 Mateusz Loskot, London, UK.
// Copyright (c) 2013-2014 Adam Wulkiewicz, Lodz, Poland. // Copyright (c) 2013-2014 Adam Wulkiewicz, Lodz, Poland.
// This file was modified by Oracle on 2013-2017. // This file was modified by Oracle on 2013-2021.
// Modifications copyright (c) 2013-2017, Oracle and/or its affiliates. // 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 Adam Wulkiewicz, on behalf of Oracle
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
@ -32,7 +32,10 @@
#include <boost/geometry/geometries/concepts/check.hpp> #include <boost/geometry/geometries/concepts/check.hpp>
#include <boost/geometry/strategies/default_strategy.hpp>
#include <boost/geometry/strategies/detail.hpp>
#include <boost/geometry/strategies/disjoint.hpp> #include <boost/geometry/strategies/disjoint.hpp>
#include <boost/geometry/strategies/relate/services.hpp>
namespace boost { namespace geometry namespace boost { namespace geometry
@ -41,9 +44,14 @@ namespace boost { namespace geometry
namespace resolve_strategy namespace resolve_strategy
{ {
template
<
typename Strategy,
bool IsUmbrella = strategies::detail::is_umbrella_strategy<Strategy>::value
>
struct disjoint struct disjoint
{ {
template <typename Geometry1, typename Geometry2, typename Strategy> template <typename Geometry1, typename Geometry2>
static inline bool apply(Geometry1 const& geometry1, static inline bool apply(Geometry1 const& geometry1,
Geometry2 const& geometry2, Geometry2 const& geometry2,
Strategy const& strategy) Strategy const& strategy)
@ -53,13 +61,35 @@ struct disjoint
Geometry1, Geometry2 Geometry1, Geometry2
>::apply(geometry1, geometry2, strategy); >::apply(geometry1, geometry2, strategy);
} }
};
template <typename Strategy>
struct disjoint<Strategy, false>
{
template <typename Geometry1, typename Geometry2>
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<Strategy>::get(strategy));
}
};
template <>
struct disjoint<default_strategy, false>
{
template <typename Geometry1, typename Geometry2> template <typename Geometry1, typename Geometry2>
static inline bool apply(Geometry1 const& geometry1, static inline bool apply(Geometry1 const& geometry1,
Geometry2 const& geometry2, Geometry2 const& geometry2,
default_strategy) default_strategy)
{ {
typedef typename strategy::disjoint::services::default_strategy typedef typename strategies::relate::services::default_strategy
< <
Geometry1, Geometry2 Geometry1, Geometry2
>::type strategy_type; >::type strategy_type;
@ -88,7 +118,10 @@ struct disjoint
Geometry2 const Geometry2 const
>(); >();
return resolve_strategy::disjoint::apply(geometry1, geometry2, strategy); return resolve_strategy::disjoint
<
Strategy
>::apply(geometry1, geometry2, strategy);
} }
}; };

View File

@ -74,7 +74,7 @@ struct disjoint_no_intersections_policy
point1_type p; point1_type p;
geometry::point_on_border(p, g1); 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 false;
} }
return NoIntersectionsPolicy return NoIntersectionsPolicy::apply(g1, g2, strategy);
::apply(g1, g2,
strategy.template get_point_in_geometry_strategy<Geometry1, Geometry2>());
} }
}; };
@ -195,8 +193,7 @@ public:
typename point_type<Segment>::type p; typename point_type<Segment>::type p;
detail::assign_point_from_index<0>(segment, p); detail::assign_point_from_index<0>(segment, p);
return !geometry::covered_by(p, polygon, return ! geometry::covered_by(p, polygon, strategy);
strategy.template get_point_in_geometry_strategy<Segment, Polygon>());
} }
}; };
@ -235,8 +232,7 @@ struct disjoint_segment_areal<Segment, Ring, ring_tag>
typename point_type<Segment>::type p; typename point_type<Segment>::type p;
detail::assign_point_from_index<0>(segment, p); detail::assign_point_from_index<0>(segment, p);
return !geometry::covered_by(p, ring, return ! geometry::covered_by(p, ring, strategy);
strategy.template get_point_in_geometry_strategy<Segment, Ring>());
} }
}; };

View File

@ -65,7 +65,7 @@ struct disjoint_segment
detail::segment_as_subrange<Segment1> sub_range1(segment1); detail::segment_as_subrange<Segment1> sub_range1(segment1);
detail::segment_as_subrange<Segment2> sub_range2(segment2); detail::segment_as_subrange<Segment2> sub_range2(segment2);
intersection_return_type is = strategy.apply(sub_range1, sub_range2, intersection_return_type is = strategy.relate().apply(sub_range1, sub_range2,
intersection_policy()); intersection_policy());
return is.count == 0; return is.count == 0;

View File

@ -58,8 +58,7 @@ struct disjoint_point_segment_or_box<Segment, segment_tag>
return dispatch::disjoint return dispatch::disjoint
< <
Point, Segment Point, Segment
>::apply(point, segment, >::apply(point, segment, strategy);
strategy.template get_point_in_geometry_strategy<Point, Segment>());
} }
}; };
@ -72,8 +71,7 @@ struct disjoint_point_segment_or_box<Box, box_tag>
return dispatch::disjoint return dispatch::disjoint
< <
Point, Box Point, Box
>::apply(point, box, >::apply(point, box, strategy);
strategy.get_disjoint_point_box_strategy());
} }
}; };

View File

@ -125,72 +125,78 @@ template <typename MultiPoint, typename Linear>
class multipoint_linear class multipoint_linear
{ {
private: private:
template <typename ExpandPointBoxStrategy> template <typename Strategy>
struct expand_box_point struct expand_box_point
{ {
explicit expand_box_point(Strategy const& strategy)
: m_strategy(strategy)
{}
template <typename Box, typename Point> template <typename Box, typename Point>
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 <typename EnvelopeStrategy> template <typename Strategy>
struct expand_box_segment struct expand_box_segment
{ {
explicit expand_box_segment(EnvelopeStrategy const& strategy) explicit expand_box_segment(Strategy const& strategy)
: m_strategy(strategy) : m_strategy(strategy)
{} {}
template <typename Box, typename Segment> template <typename Box, typename Segment>
inline void apply(Box& total, Segment const& segment) const void apply(Box& total, Segment const& segment) const
{ {
geometry::expand(total, geometry::expand(total,
geometry::return_envelope<Box>(segment, m_strategy), geometry::return_envelope<Box>(segment, m_strategy),
// TEMP - envelope umbrella strategy also contains m_strategy);
// expand strategies
strategies::envelope::services::strategy_converter
<
EnvelopeStrategy
>::get(m_strategy));
} }
EnvelopeStrategy const& m_strategy; Strategy const& m_strategy;
}; };
template <typename DisjointPointBoxStrategy> template <typename Strategy>
struct overlaps_box_point struct overlaps_box_point
{ {
explicit overlaps_box_point(Strategy const& strategy)
: m_strategy(strategy)
{}
template <typename Box, typename Point> template <typename Box, typename Point>
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, return ! detail::disjoint::disjoint_point_box(point, box,
DisjointPointBoxStrategy()); m_strategy);
} }
Strategy const& m_strategy;
}; };
template <typename DisjointStrategy> template <typename Strategy>
struct overlaps_box_segment struct overlaps_box_segment
{ {
explicit overlaps_box_segment(DisjointStrategy const& strategy) explicit overlaps_box_segment(Strategy const& strategy)
: m_strategy(strategy) : m_strategy(strategy)
{} {}
template <typename Box, typename Segment> template <typename Box, typename Segment>
inline bool apply(Box const& box, Segment const& segment) const bool apply(Box const& box, Segment const& segment) const
{ {
return ! dispatch::disjoint<Segment, Box>::apply(segment, box, m_strategy); return ! dispatch::disjoint<Segment, Box>::apply(segment, box, m_strategy);
} }
DisjointStrategy const& m_strategy; Strategy const& m_strategy;
}; };
template <typename PtSegStrategy> template <typename Strategy>
class item_visitor_type class item_visitor_type
{ {
public: public:
item_visitor_type(PtSegStrategy const& strategy) item_visitor_type(Strategy const& strategy)
: m_intersection_found(false) : m_intersection_found(false)
, m_strategy(strategy) , m_strategy(strategy)
{} {}
@ -211,7 +217,7 @@ private:
private: private:
bool m_intersection_found; bool m_intersection_found;
PtSegStrategy const& m_strategy; Strategy const& m_strategy;
}; };
// structs for partition -- end // structs for partition -- end
@ -245,11 +251,6 @@ public:
{ {
item_visitor_type<Strategy> visitor(strategy); item_visitor_type<Strategy> 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 // TODO: disjoint Segment/Box may be called in partition multiple times
// possibly for non-cartesian segments which could be slow. We should consider // possibly for non-cartesian segments which could be slow. We should consider
// passing a range of bounding boxes of segments after calculating them once. // passing a range of bounding boxes of segments after calculating them once.
@ -259,16 +260,17 @@ public:
< <
geometry::model::box<typename point_type<MultiPoint>::type> geometry::model::box<typename point_type<MultiPoint>::type>
>::apply(multipoint, segment_range(linear), visitor, >::apply(multipoint, segment_range(linear), visitor,
expand_box_point<expand_point_strategy_type>(), expand_box_point<Strategy>(strategy),
overlaps_box_point<disjoint_pb_strategy_type>(), overlaps_box_point<Strategy>(strategy),
expand_box_segment<envelope_strategy_type>(strategy.get_envelope_strategy()), expand_box_segment<Strategy>(strategy),
overlaps_box_segment<disjoint_strategy_type>(strategy.get_disjoint_strategy())); overlaps_box_segment<Strategy>(strategy));
return ! visitor.intersection_found(); return ! visitor.intersection_found();
} }
template <typename Strategy> template <typename Strategy>
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); return apply(multipoint, linear, strategy);
} }
@ -284,21 +286,19 @@ public:
SingleGeometry const& single_geometry, SingleGeometry const& single_geometry,
Strategy const& strategy) Strategy const& strategy)
{ {
typedef typename Strategy::disjoint_point_box_strategy_type d_pb_strategy_type;
typedef typename point_type<MultiPoint>::type point1_type; typedef typename point_type<MultiPoint>::type point1_type;
typedef typename point_type<SingleGeometry>::type point2_type; typedef typename point_type<SingleGeometry>::type point2_type;
typedef model::box<point2_type> box2_type; typedef model::box<point2_type> box2_type;
box2_type box2; box2_type box2;
geometry::envelope(single_geometry, box2, strategy.get_envelope_strategy()); geometry::envelope(single_geometry, box2, strategy);
geometry::detail::expand_by_epsilon(box2); geometry::detail::expand_by_epsilon(box2);
typedef typename boost::range_const_iterator<MultiPoint>::type iterator; typedef typename boost::range_const_iterator<MultiPoint>::type iterator;
for ( iterator it = boost::begin(multi_point) ; it != boost::end(multi_point) ; ++it ) for ( iterator it = boost::begin(multi_point) ; it != boost::end(multi_point) ; ++it )
{ {
// The default strategy is enough for Point/Box // 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<point1_type, SingleGeometry>::apply(*it, single_geometry, strategy)) && ! dispatch::disjoint<point1_type, SingleGeometry>::apply(*it, single_geometry, strategy))
{ {
return false; return false;
@ -309,7 +309,8 @@ public:
} }
template <typename Strategy> template <typename Strategy>
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); return apply(multi_point, single_geometry, strategy);
} }
@ -320,56 +321,77 @@ template <typename MultiPoint, typename MultiGeometry>
class multi_point_multi_geometry class multi_point_multi_geometry
{ {
private: private:
template <typename ExpandPointStrategy> template <typename Strategy>
struct expand_box_point struct expand_box_point
{ {
explicit expand_box_point(Strategy const& strategy)
: m_strategy(strategy)
{}
template <typename Box, typename Point> template <typename Box, typename Point>
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 <typename ExpandBoxStrategy> template <typename Strategy>
struct expand_box_box_pair struct expand_box_box_pair
{ {
explicit expand_box_box_pair(Strategy const& strategy)
: m_strategy(strategy)
{}
template <typename Box, typename BoxPair> template <typename Box, typename BoxPair>
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 <typename DisjointPointBoxStrategy> template <typename Strategy>
struct overlaps_box_point struct overlaps_box_point
{ {
explicit overlaps_box_point(Strategy const& strategy)
: m_strategy(strategy)
{}
template <typename Box, typename Point> template <typename Box, typename Point>
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, m_strategy);
return ! detail::disjoint::disjoint_point_box(point, box,
DisjointPointBoxStrategy());
} }
Strategy const& m_strategy;
}; };
template <typename DisjointBoxBoxStrategy> template <typename Strategy>
struct overlaps_box_box_pair struct overlaps_box_box_pair
{ {
explicit overlaps_box_box_pair(Strategy const& strategy)
: m_strategy(strategy)
{}
template <typename Box, typename BoxPair> template <typename Box, typename BoxPair>
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, return ! detail::disjoint::disjoint_box_box(box_pair.first, box,
DisjointBoxBoxStrategy()); m_strategy);
} }
Strategy const& m_strategy;
}; };
template <typename PtSegStrategy> template <typename Strategy>
class item_visitor_type class item_visitor_type
{ {
public: public:
item_visitor_type(MultiGeometry const& multi_geometry, item_visitor_type(MultiGeometry const& multi_geometry,
PtSegStrategy const& strategy) Strategy const& strategy)
: m_intersection_found(false) : m_intersection_found(false)
, m_multi_geometry(multi_geometry) , m_multi_geometry(multi_geometry)
, m_strategy(strategy) , m_strategy(strategy)
@ -378,14 +400,15 @@ private:
template <typename Point, typename BoxPair> template <typename Point, typename BoxPair>
inline bool apply(Point const& point, BoxPair const& box_pair) 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<MultiGeometry>::type single_type; typedef typename boost::range_value<MultiGeometry>::type single_type;
// The default strategy is enough for Point/Box // The default strategy is enough for Point/Box
if (! m_intersection_found if (! m_intersection_found
&& ! detail::disjoint::disjoint_point_box(point, box_pair.first, d_pb_strategy_type()) && ! 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)) && ! dispatch::disjoint
<
Point, single_type
>::apply(point, range::at(m_multi_geometry, box_pair.second), m_strategy))
{ {
m_intersection_found = true; m_intersection_found = true;
return false; return false;
@ -398,7 +421,7 @@ private:
private: private:
bool m_intersection_found; bool m_intersection_found;
MultiGeometry const& m_multi_geometry; MultiGeometry const& m_multi_geometry;
PtSegStrategy const& m_strategy; Strategy const& m_strategy;
}; };
// structs for partition -- end // structs for partition -- end
@ -412,52 +435,25 @@ public:
typedef model::box<point2_type> box2_type; typedef model::box<point2_type> box2_type;
typedef std::pair<box2_type, std::size_t> box_pair_type; typedef std::pair<box2_type, std::size_t> box_pair_type;
typename Strategy::envelope_strategy_type const
envelope_strategy = strategy.get_envelope_strategy();
std::size_t count2 = boost::size(multi_geometry); std::size_t count2 = boost::size(multi_geometry);
std::vector<box_pair_type> boxes(count2); std::vector<box_pair_type> boxes(count2);
for (std::size_t i = 0 ; i < count2 ; ++i) 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); geometry::detail::expand_by_epsilon(boxes[i].first);
boxes[i].second = i; boxes[i].second = i;
} }
item_visitor_type<Strategy> visitor(multi_geometry, strategy); item_visitor_type<Strategy> 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<box1_type>(),
std::declval<box2_type>()))
> expand_box_box_pair_type;
typedef overlaps_box_box_pair
<
typename Strategy::disjoint_box_box_strategy_type
> overlaps_box_box_pair_type;
geometry::partition geometry::partition
< <
box1_type box1_type
>::apply(multi_point, boxes, visitor, >::apply(multi_point, boxes, visitor,
expand_box_point_type(), expand_box_point<Strategy>(strategy),
overlaps_box_point_type(), overlaps_box_point<Strategy>(strategy),
expand_box_box_pair_type(), expand_box_box_pair<Strategy>(strategy),
overlaps_box_box_pair_type()); overlaps_box_box_pair<Strategy>(strategy));
return ! visitor.intersection_found(); return ! visitor.intersection_found();
} }

View File

@ -5,8 +5,8 @@
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK. // Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
// Copyright (c) 2013-2015 Adam Wulkiewicz, Lodz, Poland // Copyright (c) 2013-2015 Adam Wulkiewicz, Lodz, Poland
// This file was modified by Oracle on 2013-2018. // This file was modified by Oracle on 2013-2020.
// Modifications copyright (c) 2013-2018, Oracle and/or its affiliates. // 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 Adam Wulkiewicz, on behalf of Oracle
// Contributed and/or modified by Menelaos Karavelas, 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 \brief Internal utility function to detect if point/box are disjoint
*/ */
template <typename Point, typename Box, typename Strategy> template
inline bool disjoint_point_box(Point const& point, Box const& box, Strategy const& ) <
typename Point, typename Box, typename Strategy,
std::enable_if_t<strategies::detail::is_umbrella_strategy<Strategy>::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<! strategies::detail::is_umbrella_strategy<Strategy>::value, int> = 0
>
inline bool disjoint_point_box(Point const& point, Box const& box,
Strategy const& )
{ {
// ! covered_by(point, box) // ! covered_by(point, box)
return ! Strategy::apply(point, box); return ! Strategy::apply(point, box);
@ -62,10 +80,12 @@ template <typename Point, typename Box, std::size_t DimensionCount>
struct disjoint<Point, Box, DimensionCount, point_tag, box_tag, false> struct disjoint<Point, Box, DimensionCount, point_tag, box_tag, false>
{ {
template <typename Strategy> template <typename Strategy>
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) // ! covered_by(point, box)
return ! Strategy::apply(point, box); return ! strategy_type::apply(point, box);
} }
}; };

View File

@ -5,8 +5,8 @@
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK. // Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
// Copyright (c) 2013-2015 Adam Wulkiewicz, Lodz, Poland // Copyright (c) 2013-2015 Adam Wulkiewicz, Lodz, Poland
// This file was modified by Oracle on 2013, 2014, 2015, 2017, 2018. // This file was modified by Oracle on 2013-2020.
// Modifications copyright (c) 2013-2018, Oracle and/or its affiliates. // 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 Adam Wulkiewicz, on behalf of Oracle
// Contributed and/or modified by Menelaos Karavelas, 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 #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_POINT_POINT_HPP
#include <cstddef> #include <cstddef>
#include <type_traits>
#include <boost/geometry/core/tags.hpp> #include <boost/geometry/core/tags.hpp>
#include <boost/geometry/algorithms/dispatch/disjoint.hpp> #include <boost/geometry/algorithms/dispatch/disjoint.hpp>
#include <boost/geometry/strategies/detail.hpp>
// For backward compatibility // For backward compatibility
#include <boost/geometry/strategies/disjoint.hpp> #include <boost/geometry/strategies/disjoint.hpp>
#include <boost/geometry/strategies/cartesian/point_in_point.hpp> #include <boost/geometry/strategies/cartesian/point_in_point.hpp>
@ -46,10 +49,28 @@ namespace detail { namespace disjoint
\brief Internal utility function to detect of points are disjoint \brief Internal utility function to detect of points are disjoint
\note To avoid circular references \note To avoid circular references
*/ */
template <typename Point1, typename Point2, typename Strategy> template
<
typename Point1, typename Point2, typename Strategy,
std::enable_if_t<strategies::detail::is_umbrella_strategy<Strategy>::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<! strategies::detail::is_umbrella_strategy<Strategy>::value, int> = 0
>
inline bool disjoint_point_point(Point1 const& point1, Point2 const& point2, inline bool disjoint_point_point(Point1 const& point1, Point2 const& point2,
Strategy const& ) Strategy const& )
{ {
// ! within(point1, point2)
return ! Strategy::apply(point1, point2); return ! Strategy::apply(point1, point2);
} }
@ -68,9 +89,11 @@ struct disjoint<Point1, Point2, DimensionCount, point_tag, point_tag, false>
{ {
template <typename Strategy> template <typename Strategy>
static inline bool apply(Point1 const& point1, Point2 const& point2, 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);
} }
}; };

View File

@ -247,7 +247,7 @@ struct disjoint_segment_box
Box const& box, Box const& box,
Strategy const& strategy) Strategy const& strategy)
{ {
return strategy.apply(segment, box); return strategy.disjoint(segment, box).apply(segment, box);
} }
}; };

View File

@ -41,6 +41,7 @@
#include <boost/geometry/strategies/distance.hpp> #include <boost/geometry/strategies/distance.hpp>
#include <boost/geometry/strategies/tags.hpp> #include <boost/geometry/strategies/tags.hpp>
#include <boost/geometry/strategies/relate/services.hpp>
#include <boost/geometry/algorithms/assign.hpp> #include <boost/geometry/algorithms/assign.hpp>
@ -164,8 +165,12 @@ struct point_to_ring
Strategy const& strategy) Strategy const& strategy)
{ {
// TODO: pass strategy // TODO: pass strategy
if (within::within_point_geometry(point, ring, auto const s = strategies::relate::services::strategy_converter
strategy.get_point_in_geometry_strategy())) <
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); return return_type(0);
} }
@ -207,11 +212,15 @@ private:
InteriorRingIterator last, InteriorRingIterator last,
Strategy const& strategy) 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) for (InteriorRingIterator it = first; it != last; ++it)
{ {
// TODO: pass strategy if (within::within_point_geometry(point, *it, s))
if (within::within_point_geometry(point, *it,
strategy.get_point_in_geometry_strategy()))
{ {
// the point is inside a polygon hole, so its distance // the point is inside a polygon hole, so its distance
// to the polygon its distance to the polygon's // to the polygon its distance to the polygon's
@ -240,9 +249,13 @@ public:
Polygon const& polygon, Polygon const& polygon,
Strategy const& strategy) Strategy const& strategy)
{ {
// TODO: pass strategy // TEMP: pass strategy
if (! within::covered_by_point_geometry(point, exterior_ring(polygon), auto const s = strategies::relate::services::strategy_converter
strategy.get_point_in_geometry_strategy())) <
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 // the point is outside the exterior ring, so its distance
// to the polygon is its distance to the polygon's exterior ring // to the polygon is its distance to the polygon's exterior ring
@ -340,8 +353,12 @@ struct point_to_multigeometry<Point, MultiPolygon, Strategy, true>
Strategy const& strategy) Strategy const& strategy)
{ {
// TODO: pass strategy // TODO: pass strategy
if (within::covered_by_point_geometry(point, multipolygon, auto const s = strategies::relate::services::strategy_converter
strategy.get_point_in_geometry_strategy())) <
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; return 0;
} }

View File

@ -58,17 +58,20 @@ namespace detail { namespace distance
{ {
// TODO: Take strategy template <typename Segment, typename Box, typename Strategy>
template <typename Segment, typename Box> inline bool intersects_segment_box(Segment const& segment, Box const& box,
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 // This is the only strategy defined in distance segment/box
>::type strategy_type; // 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, return ! detail::disjoint::disjoint_segment_box::apply(segment, box, s);
strategy_type());
} }
@ -114,7 +117,7 @@ public:
Strategy const& strategy, Strategy const& strategy,
bool check_intersection = true) bool check_intersection = true)
{ {
if (check_intersection && intersects_segment_box(segment, box)) if (check_intersection && intersects_segment_box(segment, box, strategy))
{ {
return 0; return 0;
} }
@ -229,7 +232,7 @@ public:
Strategy const& strategy, Strategy const& strategy,
bool check_intersection = true) bool check_intersection = true)
{ {
if (check_intersection && intersects_segment_box(segment, box)) if (check_intersection && intersects_segment_box(segment, box, strategy))
{ {
return 0; return 0;
} }

View File

@ -64,9 +64,11 @@ template
struct point_point struct point_point
{ {
template <typename Point1, typename Point2, typename Strategy> template <typename Point1, typename Point2, typename Strategy>
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, static inline bool apply(Segment1 const& segment1, Segment2 const& segment2,
Strategy const& strategy) 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( return equals::equals_point_point(
indexed_point_view<Segment1 const, 0>(segment1), indexed_point_view<Segment1 const, 0>(segment1),
indexed_point_view<Segment2 const, 0>(segment2), indexed_point_view<Segment2 const, 0>(segment2),
pt_pt_strategy) strategy)
? equals::equals_point_point( ? equals::equals_point_point(
indexed_point_view<Segment1 const, 1>(segment1), indexed_point_view<Segment1 const, 1>(segment1),
indexed_point_view<Segment2 const, 1>(segment2), indexed_point_view<Segment2 const, 1>(segment2),
pt_pt_strategy) strategy)
: ( equals::equals_point_point( : ( equals::equals_point_point(
indexed_point_view<Segment1 const, 0>(segment1), indexed_point_view<Segment1 const, 0>(segment1),
indexed_point_view<Segment2 const, 1>(segment2), indexed_point_view<Segment2 const, 1>(segment2),
pt_pt_strategy) strategy)
&& equals::equals_point_point( && equals::equals_point_point(
indexed_point_view<Segment1 const, 1>(segment1), indexed_point_view<Segment1 const, 1>(segment1),
indexed_point_view<Segment2 const, 0>(segment2), indexed_point_view<Segment2 const, 0>(segment2),
pt_pt_strategy) strategy)
); );
} }
}; };
@ -138,15 +137,13 @@ struct area_check
Geometry2 const& geometry2, Geometry2 const& geometry2,
Strategy const& strategy) Strategy const& strategy)
{ {
return geometry::math::equals( return geometry::math::equals(geometry::area(geometry1, strategy),
geometry::area(geometry1, geometry::area(geometry2, strategy));
strategy.template get_area_strategy<Geometry1>()),
geometry::area(geometry2,
strategy.template get_area_strategy<Geometry2>()));
} }
}; };
/*
struct length_check struct length_check
{ {
template <typename Geometry1, typename Geometry2, typename Strategy> template <typename Geometry1, typename Geometry2, typename Strategy>
@ -154,16 +151,14 @@ struct length_check
Geometry2 const& geometry2, Geometry2 const& geometry2,
Strategy const& strategy) Strategy const& strategy)
{ {
return geometry::math::equals( return geometry::math::equals(geometry::length(geometry1, strategy),
geometry::length(geometry1, geometry::length(geometry2, strategy));
strategy.template get_distance_strategy<Geometry1>()),
geometry::length(geometry2,
strategy.template get_distance_strategy<Geometry2>()));
} }
}; };
*/
template <typename Geometry1, typename Geometry2, typename IntersectionStrategy> template <typename Geometry1, typename Geometry2, typename Strategy>
struct collected_vector struct collected_vector
{ {
typedef typename geometry::select_most_precise typedef typename geometry::select_most_precise
@ -179,7 +174,7 @@ struct collected_vector
< <
calculation_type, calculation_type,
Geometry1, Geometry1,
typename IntersectionStrategy::side_strategy_type decltype(std::declval<Strategy>().side())
> type; > type;
}; };

View File

@ -5,9 +5,8 @@
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK. // Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
// Copyright (c) 2014-2015 Adam Wulkiewicz, Lodz, Poland. // Copyright (c) 2014-2015 Adam Wulkiewicz, Lodz, Poland.
// This file was modified by Oracle on 2014, 2015, 2016, 2017, 2019. // This file was modified by Oracle on 2014-2021.
// Modifications copyright (c) 2014-2019 Oracle and/or its affiliates. // 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 Adam Wulkiewicz, on behalf of Oracle
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
@ -30,13 +29,16 @@
#include <boost/geometry/core/coordinate_dimension.hpp> #include <boost/geometry/core/coordinate_dimension.hpp>
#include <boost/geometry/core/reverse_dispatch.hpp> #include <boost/geometry/core/reverse_dispatch.hpp>
#include <boost/geometry/core/tag.hpp>
#include <boost/geometry/core/tag_cast.hpp>
#include <boost/geometry/geometries/concepts/check.hpp> #include <boost/geometry/geometries/concepts/check.hpp>
#include <boost/geometry/algorithms/not_implemented.hpp> #include <boost/geometry/algorithms/not_implemented.hpp>
#include <boost/geometry/strategies/default_strategy.hpp> #include <boost/geometry/strategies/default_strategy.hpp>
#include <boost/geometry/strategies/relate.hpp> #include <boost/geometry/strategies/detail.hpp>
#include <boost/geometry/strategies/relate/services.hpp>
namespace boost { namespace geometry namespace boost { namespace geometry
@ -94,9 +96,14 @@ struct equals<Geometry1, Geometry2, Tag1, Tag2, CastedTag1, CastedTag2, Dimensio
namespace resolve_strategy namespace resolve_strategy
{ {
template
<
typename Strategy,
bool IsUmbrella = strategies::detail::is_umbrella_strategy<Strategy>::value
>
struct equals struct equals
{ {
template <typename Geometry1, typename Geometry2, typename Strategy> template <typename Geometry1, typename Geometry2>
static inline bool apply(Geometry1 const& geometry1, static inline bool apply(Geometry1 const& geometry1,
Geometry2 const& geometry2, Geometry2 const& geometry2,
Strategy const& strategy) Strategy const& strategy)
@ -106,13 +113,35 @@ struct equals
Geometry1, Geometry2 Geometry1, Geometry2
>::apply(geometry1, geometry2, strategy); >::apply(geometry1, geometry2, strategy);
} }
};
template <typename Strategy>
struct equals<Strategy, false>
{
template <typename Geometry1, typename Geometry2>
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<Strategy>::get(strategy));
}
};
template <>
struct equals<default_strategy, false>
{
template <typename Geometry1, typename Geometry2> template <typename Geometry1, typename Geometry2>
static inline bool apply(Geometry1 const& geometry1, static inline bool apply(Geometry1 const& geometry1,
Geometry2 const& geometry2, Geometry2 const& geometry2,
default_strategy) default_strategy)
{ {
typedef typename strategy::relate::services::default_strategy typedef typename strategies::relate::services::default_strategy
< <
Geometry1, Geometry1,
Geometry2 Geometry2
@ -145,7 +174,9 @@ struct equals
>(); >();
return resolve_strategy::equals return resolve_strategy::equals
::apply(geometry1, geometry2, strategy); <
Strategy
>::apply(geometry1, geometry2, strategy);
} }
}; };

View File

@ -5,8 +5,8 @@
// Copyright (c) 2009-2014 Mateusz Loskot, London, UK. // Copyright (c) 2009-2014 Mateusz Loskot, London, UK.
// Copyright (c) 2013-2014 Adam Wulkiewicz, Lodz, Poland // Copyright (c) 2013-2014 Adam Wulkiewicz, Lodz, Poland
// This file was modified by Oracle on 2013-2018. // This file was modified by Oracle on 2013-2020.
// Modifications copyright (c) 2013-2018, Oracle and/or its affiliates. // 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 Adam Wulkiewicz, on behalf of Oracle
// Contributed and/or modified by Menelaos Karavelas, 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 #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_EQUALS_POINT_POINT_HPP
#include <type_traits>
#include <boost/geometry/strategies/detail.hpp>
namespace boost { namespace geometry namespace boost { namespace geometry
{ {
@ -33,7 +38,23 @@ namespace detail { namespace equals
\brief Internal utility function to detect of points are disjoint \brief Internal utility function to detect of points are disjoint
\note To avoid circular references \note To avoid circular references
*/ */
template <typename Point1, typename Point2, typename Strategy> template
<
typename Point1, typename Point2, typename Strategy,
std::enable_if_t<strategies::detail::is_umbrella_strategy<Strategy>::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<! strategies::detail::is_umbrella_strategy<Strategy>::value, int> = 0
>
inline bool equals_point_point(Point1 const& point1, Point2 const& point2, inline bool equals_point_point(Point1 const& point1, Point2 const& point2,
Strategy const& ) Strategy const& )
{ {

View File

@ -136,27 +136,6 @@ inline bool has_self_intersections(Geometry const& geometry,
return false; return false;
} }
// For backward compatibility
template <typename Geometry>
inline bool has_self_intersections(Geometry const& geometry,
bool throw_on_self_intersection = true)
{
typedef typename geometry::point_type<Geometry>::type point_type;
typedef typename geometry::rescale_policy_type<point_type>::type
rescale_policy_type;
typename strategy::intersection::services::default_strategy
<
typename cs_tag<Geometry>::type
>::type strategy;
rescale_policy_type robust_policy
= geometry::get_rescale_policy<rescale_policy_type>(geometry, strategy);
return has_self_intersections(geometry, strategy, robust_policy,
throw_on_self_intersection);
}
}} // namespace detail::overlay }} // namespace detail::overlay
#endif // DOXYGEN_NO_DETAIL #endif // DOXYGEN_NO_DETAIL

View File

@ -1,6 +1,6 @@
// Boost.Geometry // 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 // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Licensed under the Boost Software License version 1.0. // Licensed under the Boost Software License version 1.0.
@ -109,10 +109,6 @@ struct intersection_areal_areal_<TupledOut, tupled_output_tag>
< <
areal::index, TupledOut areal::index, TupledOut
>::type areal_out_type; >::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 // NOTE: The same robust_policy is used in each call of
// intersection_insert. Is that correct? // intersection_insert. Is that correct?
@ -157,11 +153,7 @@ struct intersection_areal_areal_<TupledOut, tupled_output_tag>
areal_out_boundary, areal_out_boundary,
robust_policy, robust_policy,
pointlike::get(geometry_out), pointlike::get(geometry_out),
strategy.template get_point_in_geometry_strategy strategy);
<
pointlike_out_type,
areal_out_boundary_type
>());
} }
return; return;

View File

@ -2,9 +2,8 @@
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. // Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
// This file was modified by Oracle on 2014, 2017, 2019. // This file was modified by Oracle on 2014-2020.
// Modifications copyright (c) 2014-2019, Oracle and/or its affiliates. // 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 Adam Wulkiewicz, on behalf of Oracle
// Use, modification and distribution is subject to the Boost Software License, // Use, modification and distribution is subject to the Boost Software License,
@ -23,6 +22,8 @@
#include <boost/geometry/algorithms/detail/tupled_output.hpp> #include <boost/geometry/algorithms/detail/tupled_output.hpp>
#include <boost/geometry/policies/robustness/get_rescale_policy.hpp> #include <boost/geometry/policies/robustness/get_rescale_policy.hpp>
#include <boost/geometry/strategies/default_strategy.hpp> #include <boost/geometry/strategies/default_strategy.hpp>
#include <boost/geometry/strategies/detail.hpp>
#include <boost/geometry/strategies/relate/services.hpp>
#include <boost/geometry/util/range.hpp> #include <boost/geometry/util/range.hpp>
@ -108,14 +109,18 @@ struct intersection
namespace resolve_strategy { namespace resolve_strategy {
template
<
typename Strategy,
bool IsUmbrella = strategies::detail::is_umbrella_strategy<Strategy>::value
>
struct intersection struct intersection
{ {
template template
< <
typename Geometry1, typename Geometry1,
typename Geometry2, typename Geometry2,
typename GeometryOut, typename GeometryOut
typename Strategy
> >
static inline bool apply(Geometry1 const& geometry1, static inline bool apply(Geometry1 const& geometry1,
Geometry2 const& geometry2, Geometry2 const& geometry2,
@ -140,7 +145,34 @@ struct intersection
>::apply(geometry1, geometry2, robust_policy, geometry_out, >::apply(geometry1, geometry2, robust_policy, geometry_out,
strategy); strategy);
} }
};
template <typename Strategy>
struct intersection<Strategy, false>
{
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<Strategy>::get(strategy))
>::apply(geometry1, geometry2, geometry_out,
strategy_converter<Strategy>::get(strategy));
}
};
template <>
struct intersection<default_strategy, false>
{
template template
< <
typename Geometry1, typename Geometry1,
@ -152,28 +184,15 @@ struct intersection
GeometryOut & geometry_out, GeometryOut & geometry_out,
default_strategy) default_strategy)
{ {
typedef typename geometry::rescale_overlay_policy_type typedef typename strategies::relate::services::default_strategy
<
Geometry1,
Geometry2,
typename geometry::cs_tag<Geometry1>::type
>::type rescale_policy_type;
typename strategy::relate::services::default_strategy
< <
Geometry1, Geometry2 Geometry1, Geometry2
>::type strategy; >::type strategy_type;
rescale_policy_type robust_policy return intersection
= geometry::get_rescale_policy<rescale_policy_type>(
geometry1, geometry2, strategy);
return dispatch::intersection
< <
Geometry1, strategy_type
Geometry2 >::apply(geometry1, geometry2, geometry_out, strategy_type());
>::apply(geometry1, geometry2, robust_policy, geometry_out,
strategy);
} }
}; };
@ -195,10 +214,10 @@ struct intersection
concepts::check<Geometry1 const>(); concepts::check<Geometry1 const>();
concepts::check<Geometry2 const>(); concepts::check<Geometry2 const>();
return resolve_strategy::intersection::apply(geometry1, return resolve_strategy::intersection
geometry2, <
geometry_out, Strategy
strategy); >::apply(geometry1, geometry2, geometry_out, strategy);
} }
}; };

View File

@ -4,8 +4,8 @@
// Copyright (c) 2008-2014 Bruno Lalande, Paris, France. // Copyright (c) 2008-2014 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2014 Mateusz Loskot, London, UK. // Copyright (c) 2009-2014 Mateusz Loskot, London, UK.
// This file was modified by Oracle on 2013-2017. // This file was modified by Oracle on 2013-2020.
// Modifications copyright (c) 2013-2017, Oracle and/or its affiliates. // 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 Menelaos Karavelas, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@ -30,7 +30,7 @@
#include <boost/geometry/policies/disjoint_interrupt_policy.hpp> #include <boost/geometry/policies/disjoint_interrupt_policy.hpp>
#include <boost/geometry/policies/robustness/no_rescale_policy.hpp> #include <boost/geometry/policies/robustness/no_rescale_policy.hpp>
#include <boost/geometry/strategies/relate.hpp> #include <boost/geometry/strategies/relate/services.hpp>
namespace boost { namespace geometry namespace boost { namespace geometry
@ -48,7 +48,7 @@ struct self_intersects
concepts::check<Geometry const>(); concepts::check<Geometry const>();
typedef typename geometry::point_type<Geometry>::type point_type; typedef typename geometry::point_type<Geometry>::type point_type;
typedef typename strategy::relate::services::default_strategy typedef typename strategies::relate::services::default_strategy
< <
Geometry, Geometry Geometry, Geometry
>::type strategy_type; >::type strategy_type;

View File

@ -1,6 +1,6 @@
// Boost.Geometry (aka GGL, Generic Geometry Library) // 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 Menelaos Karavelas, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@ -22,7 +22,6 @@
#include <boost/geometry/core/ring_type.hpp> #include <boost/geometry/core/ring_type.hpp>
#include <boost/geometry/core/tags.hpp> #include <boost/geometry/core/tags.hpp>
#include <boost/geometry/algorithms/detail/check_iterator_range.hpp>
#include <boost/geometry/algorithms/detail/is_simple/failure_policy.hpp> #include <boost/geometry/algorithms/detail/is_simple/failure_policy.hpp>
#include <boost/geometry/algorithms/detail/is_valid/has_duplicates.hpp> #include <boost/geometry/algorithms/detail/is_valid/has_duplicates.hpp>
@ -38,54 +37,36 @@ namespace detail { namespace is_simple
{ {
template <typename Ring, typename CSTag> template <typename Ring, typename Strategy>
struct is_simple_ring inline bool is_simple_ring(Ring const& ring, Strategy const& strategy)
{ {
static inline bool apply(Ring const& ring)
{
simplicity_failure_policy policy; simplicity_failure_policy policy;
return ! boost::empty(ring) return ! boost::empty(ring)
&& ! detail::is_valid::has_duplicates && ! detail::is_valid::has_duplicates
< <
Ring, geometry::closure<Ring>::value, CSTag Ring, geometry::closure<Ring>::value
>::apply(ring, policy); >::apply(ring, policy, strategy);
} }
};
template <typename InteriorRings, typename Strategy>
template <typename Polygon, typename CSTag> inline bool are_simple_interior_rings(InteriorRings const& interior_rings,
class is_simple_polygon Strategy const& strategy)
{ {
private: auto const end = boost::end(interior_rings);
template <typename InteriorRings> return std::find_if(boost::begin(interior_rings), end,
static inline [&](auto const& r)
bool are_simple_interior_rings(InteriorRings const& interior_rings)
{ {
return return ! is_simple_ring(r, strategy);
detail::check_iterator_range }) == end; // non-simple ring not found
< // allow empty ring
is_simple_ring }
<
typename boost::range_value<InteriorRings>::type,
CSTag
>
>::apply(boost::begin(interior_rings),
boost::end(interior_rings));
}
public: template <typename Polygon, typename Strategy>
static inline bool apply(Polygon const& polygon) inline bool is_simple_polygon(Polygon const& polygon, Strategy const& strategy)
{ {
return return is_simple_ring(geometry::exterior_ring(polygon), strategy)
is_simple_ring && are_simple_interior_rings(geometry::interior_rings(polygon), strategy);
< }
typename ring_type<Polygon>::type,
CSTag
>::apply(exterior_ring(polygon))
&&
are_simple_interior_rings(geometry::interior_rings(polygon));
}
};
}} // namespace detail::is_simple }} // namespace detail::is_simple
@ -107,13 +88,9 @@ template <typename Ring>
struct is_simple<Ring, ring_tag> struct is_simple<Ring, ring_tag>
{ {
template <typename Strategy> template <typename Strategy>
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 return detail::is_simple::is_simple_ring(ring, strategy);
<
Ring,
typename Strategy::cs_tag
>::apply(ring);
} }
}; };
@ -125,13 +102,9 @@ template <typename Polygon>
struct is_simple<Polygon, polygon_tag> struct is_simple<Polygon, polygon_tag>
{ {
template <typename Strategy> template <typename Strategy>
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 return detail::is_simple::is_simple_polygon(polygon, strategy);
<
Polygon,
typename Strategy::cs_tag
>::apply(polygon);
} }
}; };
@ -144,18 +117,14 @@ template <typename MultiPolygon>
struct is_simple<MultiPolygon, multi_polygon_tag> struct is_simple<MultiPolygon, multi_polygon_tag>
{ {
template <typename Strategy> template <typename Strategy>
static inline bool apply(MultiPolygon const& multipolygon, Strategy const&) static inline bool apply(MultiPolygon const& multipolygon, Strategy const& strategy)
{ {
return auto const end = boost::end(multipolygon);
detail::check_iterator_range return std::find_if(boost::begin(multipolygon), end,
< [&](auto const& po) {
detail::is_simple::is_simple_polygon return ! detail::is_simple::is_simple_polygon(po, strategy);
< }) == end; // non-simple polygon not found
typename boost::range_value<MultiPolygon>::type, // allow empty multi-polygon
typename Strategy::cs_tag
>,
true // allow empty multi-polygon
>::apply(boost::begin(multipolygon), boost::end(multipolygon));
} }
}; };

View File

@ -1,6 +1,6 @@
// Boost.Geometry (aka GGL, Generic Geometry Library) // 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 Menelaos Karavelas, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@ -20,7 +20,8 @@
#include <boost/geometry/algorithms/dispatch/is_simple.hpp> #include <boost/geometry/algorithms/dispatch/is_simple.hpp>
#include <boost/geometry/core/cs.hpp> #include <boost/geometry/core/cs.hpp>
#include <boost/geometry/strategies/default_strategy.hpp> #include <boost/geometry/strategies/default_strategy.hpp>
#include <boost/geometry/strategies/intersection.hpp> #include <boost/geometry/strategies/detail.hpp>
#include <boost/geometry/strategies/relate/services.hpp>
namespace boost { namespace geometry namespace boost { namespace geometry
@ -29,23 +30,47 @@ namespace boost { namespace geometry
namespace resolve_strategy namespace resolve_strategy
{ {
template
<
typename Strategy,
bool IsUmbrella = strategies::detail::is_umbrella_strategy<Strategy>::value
>
struct is_simple struct is_simple
{ {
template <typename Geometry, typename Strategy> template <typename Geometry>
static inline bool apply(Geometry const& geometry, static inline bool apply(Geometry const& geometry,
Strategy const& strategy) Strategy const& strategy)
{ {
return dispatch::is_simple<Geometry>::apply(geometry, strategy); return dispatch::is_simple<Geometry>::apply(geometry, strategy);
} }
};
template <typename Strategy>
struct is_simple<Strategy, false>
{
template <typename Geometry>
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<Strategy>::get(strategy));
}
};
template <>
struct is_simple<default_strategy, false>
{
template <typename Geometry> template <typename Geometry>
static inline bool apply(Geometry const& geometry, static inline bool apply(Geometry const& geometry,
default_strategy) default_strategy)
{ {
// NOTE: Currently the strategy is only used for Linear geometries // 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<Geometry>::type Geometry, Geometry
>::type strategy_type; >::type strategy_type;
return dispatch::is_simple<Geometry>::apply(geometry, strategy_type()); return dispatch::is_simple<Geometry>::apply(geometry, strategy_type());
@ -65,7 +90,7 @@ struct is_simple
{ {
concepts::check<Geometry const>(); concepts::check<Geometry const>();
return resolve_strategy::is_simple::apply(geometry, strategy); return resolve_strategy::is_simple<Strategy>::apply(geometry, strategy);
} }
}; };

View File

@ -221,8 +221,7 @@ inline bool has_self_intersections(Linear const& linear, Strategy const& strateg
typedef is_acceptable_turn typedef is_acceptable_turn
< <
Linear, Linear, Strategy
typename Strategy::equals_point_point_strategy_type
> is_acceptable_turn_type; > is_acceptable_turn_type;
is_acceptable_turn_type predicate(linear); is_acceptable_turn_type predicate(linear);
@ -259,12 +258,12 @@ struct is_simple_linestring
return ! boost::empty(linestring) return ! boost::empty(linestring)
&& ! detail::is_valid::has_duplicates && ! detail::is_valid::has_duplicates
< <
Linestring, closed, typename Strategy::cs_tag Linestring, closed
>::apply(linestring, policy) >::apply(linestring, policy, strategy)
&& ! detail::is_valid::has_spikes && ! detail::is_valid::has_spikes
< <
Linestring, closed Linestring, closed
>::apply(linestring, policy, strategy.get_side_strategy()); >::apply(linestring, policy, strategy);
} }
}; };

View File

@ -42,7 +42,7 @@ template <typename MultiPoint>
struct is_simple_multipoint struct is_simple_multipoint
{ {
template <typename Strategy> template <typename Strategy>
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 typename Strategy::cs_tag cs_tag;
typedef geometry::less typedef geometry::less
@ -61,10 +61,10 @@ struct is_simple_multipoint
std::sort(boost::begin(mp), boost::end(mp), less_type()); std::sort(boost::begin(mp), boost::end(mp), less_type());
simplicity_failure_policy policy; simplicity_failure_policy policy;
return !detail::is_valid::has_duplicates return ! detail::is_valid::has_duplicates
< <
MultiPoint, closed, cs_tag MultiPoint, closed
>::apply(mp, policy); >::apply(mp, policy, strategy);
} }
}; };

View File

@ -33,11 +33,12 @@ namespace boost { namespace geometry
namespace detail { namespace is_valid namespace detail { namespace is_valid
{ {
template <typename Range, closure_selector Closure, typename CSTag> template <typename Range, closure_selector Closure>
struct has_duplicates struct has_duplicates
{ {
template <typename VisitPolicy> template <typename VisitPolicy, typename Strategy>
static inline bool apply(Range const& range, VisitPolicy& visitor) static inline bool apply(Range const& range, VisitPolicy& visitor,
Strategy const& )
{ {
boost::ignore_unused(visitor); boost::ignore_unused(visitor);
@ -58,7 +59,7 @@ struct has_duplicates
< <
typename boost::range_value<Range>::type, typename boost::range_value<Range>::type,
-1, -1,
CSTag typename Strategy::cs_tag
> equal; > equal;
const_iterator it = boost::const_begin(view); const_iterator it = boost::const_begin(view);

View File

@ -45,64 +45,27 @@ namespace boost { namespace geometry
namespace detail { namespace is_valid namespace detail { namespace is_valid
{ {
template <typename Point, typename Strategy>
struct equal_to
{
Point const& m_point;
equal_to(Point const& point)
: m_point(point)
{}
template <typename OtherPoint>
inline bool operator()(OtherPoint const& other) const
{
return geometry::detail::equals::equals_point_point(m_point, other, Strategy());
}
};
template <typename Point, typename Strategy>
struct not_equal_to
{
Point const& m_point;
not_equal_to(Point const& point)
: m_point(point)
{}
template <typename OtherPoint>
inline bool operator()(OtherPoint const& other) const
{
return ! geometry::detail::equals::equals_point_point(other, m_point, Strategy());
}
};
template <typename Range, closure_selector Closure> template <typename Range, closure_selector Closure>
struct has_spikes struct has_spikes
{ {
template <typename Iterator, typename SideStrategy> template <typename Iterator, typename Strategy>
static inline Iterator find_different_from_first(Iterator first, static inline Iterator find_different_from_first(Iterator first,
Iterator last, Iterator last,
SideStrategy const& ) Strategy const& strategy)
{ {
typedef not_equal_to if (first == last)
< return last;
typename point_type<Range>::type, auto const& front = *first;
typename SideStrategy::equals_point_point_strategy_type ++first;
> not_equal; return std::find_if(first, last, [&](auto const& pt) {
return ! equals::equals_point_point(pt, front, strategy);
BOOST_GEOMETRY_ASSERT(first != last); });
Iterator second = first;
++second;
return std::find_if(second, last, not_equal(*first));
} }
template <typename View, typename VisitPolicy, typename SideStrategy> template <typename View, typename VisitPolicy, typename Strategy>
static inline bool apply_at_closure(View const& view, VisitPolicy& visitor, static inline bool apply_at_closure(View const& view, VisitPolicy& visitor,
SideStrategy const& strategy, Strategy const& strategy,
bool is_linear) bool is_linear)
{ {
boost::ignore_unused(visitor); boost::ignore_unused(visitor);
@ -119,10 +82,9 @@ struct has_spikes
iterator next = find_different_from_first(cur, boost::end(view), iterator next = find_different_from_first(cur, boost::end(view),
strategy); strategy);
if (detail::is_spike_or_equal(*next, *cur, *prev, strategy)) if (detail::is_spike_or_equal(*next, *cur, *prev, strategy.side()))
{ {
return return ! visitor.template apply<failure_spikes>(is_linear, *cur);
! visitor.template apply<failure_spikes>(is_linear, *cur);
} }
else else
{ {
@ -131,9 +93,9 @@ struct has_spikes
} }
template <typename VisitPolicy, typename SideStrategy> template <typename VisitPolicy, typename Strategy>
static inline bool apply(Range const& range, VisitPolicy& visitor, static inline bool apply(Range const& range, VisitPolicy& visitor,
SideStrategy const& strategy) Strategy const& strategy)
{ {
boost::ignore_unused(visitor); boost::ignore_unused(visitor);
@ -169,7 +131,7 @@ struct has_spikes
// in is_spike_or_equal, but this order calls the side // in is_spike_or_equal, but this order calls the side
// strategy in the way to correctly detect the spikes, // strategy in the way to correctly detect the spikes,
// also in geographic cases going over the pole // 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 return
! visitor.template apply<failure_spikes>(is_linestring, *cur); ! visitor.template apply<failure_spikes>(is_linestring, *cur);
@ -179,9 +141,8 @@ struct has_spikes
next = find_different_from_first(cur, boost::end(view), strategy); next = find_different_from_first(cur, boost::end(view), strategy);
} }
if (geometry::detail::equals:: if (equals::equals_point_point(range::front(view), range::back(view),
equals_point_point(range::front(view), range::back(view), strategy))
strategy.get_equals_point_point_strategy()))
{ {
return apply_at_closure(view, visitor, strategy, is_linestring); return apply_at_closure(view, visitor, strategy, is_linestring);
} }

View File

@ -41,7 +41,7 @@ namespace detail { namespace is_valid
template template
< <
typename Geometry, typename Geometry,
typename CSTag typename CSTag // TODO: remove
> >
class has_valid_self_turns class has_valid_self_turns
{ {

View File

@ -1,6 +1,6 @@
// Boost.Geometry // 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 Menelaos Karavelas, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@ -25,7 +25,8 @@
#include <boost/geometry/policies/is_valid/failing_reason_policy.hpp> #include <boost/geometry/policies/is_valid/failing_reason_policy.hpp>
#include <boost/geometry/policies/is_valid/failure_type_policy.hpp> #include <boost/geometry/policies/is_valid/failure_type_policy.hpp>
#include <boost/geometry/strategies/default_strategy.hpp> #include <boost/geometry/strategies/default_strategy.hpp>
#include <boost/geometry/strategies/intersection.hpp> #include <boost/geometry/strategies/detail.hpp>
#include <boost/geometry/strategies/relate/services.hpp>
namespace boost { namespace geometry namespace boost { namespace geometry
@ -34,9 +35,14 @@ namespace boost { namespace geometry
namespace resolve_strategy namespace resolve_strategy
{ {
template
<
typename Strategy,
bool IsUmbrella = strategies::detail::is_umbrella_strategy<Strategy>::value
>
struct is_valid struct is_valid
{ {
template <typename Geometry, typename VisitPolicy, typename Strategy> template <typename Geometry, typename VisitPolicy>
static inline bool apply(Geometry const& geometry, static inline bool apply(Geometry const& geometry,
VisitPolicy& visitor, VisitPolicy& visitor,
Strategy const& strategy) Strategy const& strategy)
@ -44,18 +50,41 @@ struct is_valid
return dispatch::is_valid<Geometry>::apply(geometry, visitor, strategy); return dispatch::is_valid<Geometry>::apply(geometry, visitor, strategy);
} }
};
template <typename Strategy>
struct is_valid<Strategy, false>
{
template <typename Geometry, typename VisitPolicy>
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<Strategy>::get(strategy));
}
};
template <>
struct is_valid<default_strategy, false>
{
template <typename Geometry, typename VisitPolicy> template <typename Geometry, typename VisitPolicy>
static inline bool apply(Geometry const& geometry, static inline bool apply(Geometry const& geometry,
VisitPolicy& visitor, VisitPolicy& visitor,
default_strategy) default_strategy)
{ {
// NOTE: Currently the strategy is only used for Areal geometries // 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<Geometry>::type Geometry, Geometry
>::type strategy_type; >::type strategy_type;
return dispatch::is_valid<Geometry>::apply(geometry, visitor, strategy_type()); return dispatch::is_valid<Geometry>::apply(geometry, visitor,
strategy_type());
} }
}; };
@ -74,7 +103,10 @@ struct is_valid
{ {
concepts::check<Geometry const>(); concepts::check<Geometry const>();
return resolve_strategy::is_valid::apply(geometry, visitor, strategy); return resolve_strategy::is_valid
<
Strategy
>::apply(geometry, visitor, strategy);
} }
}; };

View File

@ -64,15 +64,8 @@ struct is_valid_linestring
std::size_t num_distinct = detail::num_distinct_consecutive_points std::size_t num_distinct = detail::num_distinct_consecutive_points
< <
Linestring, Linestring, 3u, true
3u, >::apply(linestring, strategy);
true,
not_equal_to
<
typename point_type<Linestring>::type,
typename Strategy::equals_point_point_strategy_type
>
>::apply(linestring);
if (num_distinct < 2u) if (num_distinct < 2u)
{ {
@ -93,8 +86,7 @@ struct is_valid_linestring
return ! has_spikes return ! has_spikes
< <
Linestring, closed Linestring, closed
>::apply(linestring, visitor, >::apply(linestring, visitor, strategy);
strategy.get_side_strategy());
} }
}; };

View File

@ -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 // call partition to check if polygons are disjoint from each other
typename base::template item_visitor_type<Strategy> item_visitor(strategy); typename base::template item_visitor_type<Strategy> item_visitor(strategy);
@ -133,15 +125,8 @@ private:
< <
geometry::model::box<typename point_type<MultiPolygon>::type> geometry::model::box<typename point_type<MultiPolygon>::type>
>::apply(polygon_iterators, item_visitor, >::apply(polygon_iterators, item_visitor,
typename base::template expand_box typename base::template expand_box<Strategy>(strategy),
< typename base::template overlaps_box<Strategy>(strategy));
envelope_strategy_type
>(envelope_strategy),
typename base::template overlaps_box
<
envelope_strategy_type,
disjoint_box_box_strategy_type
>(envelope_strategy, disjoint_strategy));
if (item_visitor.items_overlap) if (item_visitor.items_overlap)
{ {

View File

@ -185,10 +185,10 @@ protected:
}; };
// structs for partition -- start // structs for partition -- start
template <typename EnvelopeStrategy> template <typename Strategy>
struct expand_box struct expand_box
{ {
explicit expand_box(EnvelopeStrategy const& strategy) explicit expand_box(Strategy const& strategy)
: m_strategy(strategy) : m_strategy(strategy)
{} {}
@ -197,46 +197,38 @@ protected:
{ {
geometry::expand(total, geometry::expand(total,
item.get_envelope(m_strategy), item.get_envelope(m_strategy),
// TEMP - envelope umbrella strategy also contains m_strategy);
// expand strategies
strategies::envelope::services::strategy_converter
<
EnvelopeStrategy
>::get(m_strategy));
} }
EnvelopeStrategy const& m_strategy; Strategy const& m_strategy;
}; };
template <typename EnvelopeStrategy, typename DisjointBoxBoxStrategy> template <typename Strategy>
struct overlaps_box struct overlaps_box
{ {
explicit overlaps_box(EnvelopeStrategy const& envelope_strategy, explicit overlaps_box(Strategy const& strategy)
DisjointBoxBoxStrategy const& disjoint_strategy) : m_strategy(strategy)
: m_envelope_strategy(envelope_strategy)
, m_disjoint_strategy(disjoint_strategy)
{} {}
template <typename Box, typename Iterator> template <typename Box, typename Iterator>
inline bool apply(Box const& box, partition_item<Iterator, Box> const& item) const inline bool apply(Box const& box, partition_item<Iterator, Box> const& item) const
{ {
return ! geometry::disjoint(item.get_envelope(m_envelope_strategy), return ! geometry::disjoint(item.get_envelope(m_strategy),
box, box,
m_disjoint_strategy); m_strategy);
} }
EnvelopeStrategy const& m_envelope_strategy; Strategy const& m_strategy;
DisjointBoxBoxStrategy const& m_disjoint_strategy;
}; };
template <typename WithinStrategy> template <typename Strategy>
struct item_visitor_type struct item_visitor_type
{ {
bool items_overlap; 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) : items_overlap(false)
, m_strategy(strategy) , m_strategy(strategy)
{} {}
@ -299,14 +291,6 @@ protected:
} }
} }
// prepare strategy
typedef typename std::iterator_traits<RingIterator>::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<inter_ring_type, ExteriorRing>();
signed_size_type ring_index = 0; signed_size_type ring_index = 0;
for (RingIterator it = rings_first; it != rings_beyond; for (RingIterator it = rings_first; it != rings_beyond;
++it, ++ring_index) ++it, ++ring_index)
@ -314,7 +298,7 @@ protected:
// do not examine interior rings that have turns with the // do not examine interior rings that have turns with the
// exterior ring // exterior ring
if (ring_indices.find(ring_index) == ring_indices.end() 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<failure_interior_rings_outside>(); return visitor.template apply<failure_interior_rings_outside>();
} }
@ -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 // call partition to check if interior rings are disjoint from
// each other // each other
item_visitor_type<Strategy> item_visitor(strategy); item_visitor_type<Strategy> item_visitor(strategy);
@ -358,15 +334,8 @@ protected:
< <
box_type box_type
>::apply(ring_iterators, item_visitor, >::apply(ring_iterators, item_visitor,
expand_box expand_box<Strategy>(strategy),
< overlaps_box<Strategy>(strategy));
envelope_strategy_type
>(envelope_strategy),
overlaps_box
<
envelope_strategy_type,
disjoint_box_box_strategy_type
>(envelope_strategy, disjoint_strategy));
if (item_visitor.items_overlap) if (item_visitor.items_overlap)
{ {

View File

@ -92,21 +92,7 @@ struct is_topologically_closed<Ring, closed>
}; };
// TODO: use calculate_point_order here
template <typename ResultType, bool IsInteriorRing /* false */>
struct ring_area_predicate
{
typedef std::greater<ResultType> type;
};
template <typename ResultType>
struct ring_area_predicate<ResultType, true>
{
typedef std::less<ResultType> type;
};
template <typename Ring, bool IsInteriorRing> template <typename Ring, bool IsInteriorRing>
struct is_properly_oriented struct is_properly_oriented
{ {
@ -122,25 +108,15 @@ struct is_properly_oriented
geometry::closure<Ring>::value geometry::closure<Ring>::value
> ring_area_type; > ring_area_type;
typedef typename Strategy::template area_strategy std::conditional_t
< <
Ring IsInteriorRing, std::less<>, std::greater<>
>::type::template result_type<Ring>::type area_result_type; > predicate;
typename ring_area_predicate
<
area_result_type, IsInteriorRing
>::type predicate;
// Check area // Check area
area_result_type const zero = 0; auto const area = ring_area_type::apply(ring, strategy);
area_result_type const area decltype(area) const zero = 0;
= 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<Ring>())
>::get(strategy.template get_area_strategy<Ring>()));
if (predicate(area, zero)) if (predicate(area, zero))
{ {
return visitor.template apply<no_failure>(); return visitor.template apply<no_failure>();
@ -166,8 +142,6 @@ struct is_valid_ring
static inline bool apply(Ring const& ring, VisitPolicy& visitor, static inline bool apply(Ring const& ring, VisitPolicy& visitor,
Strategy const& strategy) Strategy const& strategy)
{ {
typedef typename Strategy::cs_tag cs_tag;
// return invalid if any of the following condition holds: // return invalid if any of the following condition holds:
// (a) the ring's point coordinates are not invalid (e.g., NaN) // (a) the ring's point coordinates are not invalid (e.g., NaN)
// (b) the ring's size is below the minimal one // (b) the ring's size is below the minimal one
@ -199,13 +173,8 @@ struct is_valid_ring
view_type const view(ring); view_type const view(ring);
if (detail::num_distinct_consecutive_points if (detail::num_distinct_consecutive_points
< <
view_type, 4u, true, view_type, 4u, true
not_equal_to >::apply(view, strategy)
<
typename point_type<Ring>::type,
typename Strategy::equals_point_point_strategy_type
>
>::apply(view)
< 4u) < 4u)
{ {
return return
@ -213,9 +182,9 @@ struct is_valid_ring
} }
return return
is_topologically_closed<Ring, closure>::apply(ring, visitor, strategy.get_equals_point_point_strategy()) is_topologically_closed<Ring, closure>::apply(ring, visitor, strategy)
&& ! has_duplicates<Ring, closure, cs_tag>::apply(ring, visitor) && ! has_duplicates<Ring, closure>::apply(ring, visitor, strategy)
&& ! has_spikes<Ring, closure>::apply(ring, visitor, strategy.get_side_strategy()) && ! has_spikes<Ring, closure>::apply(ring, visitor, strategy)
&& (! CheckSelfIntersections && (! CheckSelfIntersections
|| has_valid_self_turns<Ring, typename Strategy::cs_tag>::apply(ring, visitor, strategy)) || has_valid_self_turns<Ring, typename Strategy::cs_tag>::apply(ring, visitor, strategy))
&& is_properly_oriented<Ring, IsInteriorRing>::apply(ring, visitor, strategy); && is_properly_oriented<Ring, IsInteriorRing>::apply(ring, visitor, strategy);

View File

@ -45,10 +45,8 @@ template <typename Segment>
struct is_valid<Segment, segment_tag> struct is_valid<Segment, segment_tag>
{ {
template <typename VisitPolicy, typename Strategy> template <typename VisitPolicy, typename Strategy>
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); boost::ignore_unused(visitor);
typename point_type<Segment>::type p[2]; typename point_type<Segment>::type p[2];
@ -62,8 +60,7 @@ struct is_valid<Segment, segment_tag>
{ {
return false; return false;
} }
else if (! geometry::detail::equals::equals_point_point( else if (! detail::equals::equals_point_point(p[0], p[1], strategy))
p[0], p[1], eq_pp_strategy_type()))
{ {
return visitor.template apply<no_failure>(); return visitor.template apply<no_failure>();
} }

View File

@ -41,12 +41,12 @@ template
< <
typename Range, typename Range,
std::size_t MaximumNumber, std::size_t MaximumNumber,
bool AllowDuplicates /* true */, bool AllowDuplicates /* true */
typename NotEqualTo
> >
struct num_distinct_consecutive_points struct num_distinct_consecutive_points
{ {
static inline std::size_t apply(Range const& range) template <typename Strategy>
static inline std::size_t apply(Range const& range, Strategy const& strategy)
{ {
typedef typename boost::range_iterator<Range const>::type iterator; typedef typename boost::range_iterator<Range const>::type iterator;
@ -58,26 +58,28 @@ struct num_distinct_consecutive_points
} }
iterator current = boost::begin(range); iterator current = boost::begin(range);
iterator const end = boost::end(range);
std::size_t counter(0); std::size_t counter(0);
do do
{ {
++counter; ++counter;
iterator next = std::find_if(current, iterator next = std::find_if(current, end, [&](auto const& pt) {
boost::end(range), return ! equals::equals_point_point(pt, *current, strategy);
NotEqualTo(*current)); });
current = next; current = next;
} }
while ( current != boost::end(range) && counter <= MaximumNumber ); while ( current != end && counter <= MaximumNumber );
return counter; return counter;
} }
}; };
template <typename Range, std::size_t MaximumNumber, typename NotEqualTo> template <typename Range, std::size_t MaximumNumber>
struct num_distinct_consecutive_points<Range, MaximumNumber, false, NotEqualTo> struct num_distinct_consecutive_points<Range, MaximumNumber, false>
{ {
static inline std::size_t apply(Range const& range) template <typename Strategy>
static inline std::size_t apply(Range const& range, Strategy const&)
{ {
std::size_t const size = boost::size(range); std::size_t const size = boost::size(range);
return (size < MaximumNumber) ? size : MaximumNumber; return (size < MaximumNumber) ? size : MaximumNumber;

View File

@ -4,8 +4,8 @@
// Copyright (c) 2008-2015 Bruno Lalande, Paris, France. // Copyright (c) 2008-2015 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK. // Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
// This file was modified by Oracle on 2014, 2015, 2017. // This file was modified by Oracle on 2014-2021.
// Modifications copyright (c) 2014-2017 Oracle and/or its affiliates. // 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 Adam Wulkiewicz, on behalf of Oracle
@ -28,7 +28,9 @@
#include <boost/geometry/algorithms/detail/relate/relate_impl.hpp> #include <boost/geometry/algorithms/detail/relate/relate_impl.hpp>
#include <boost/geometry/strategies/relate.hpp> #include <boost/geometry/strategies/default_strategy.hpp>
#include <boost/geometry/strategies/detail.hpp>
#include <boost/geometry/strategies/relate/services.hpp>
namespace boost { namespace geometry namespace boost { namespace geometry
@ -60,6 +62,68 @@ struct overlaps
#endif // DOXYGEN_NO_DISPATCH #endif // DOXYGEN_NO_DISPATCH
namespace resolve_strategy
{
template
<
typename Strategy,
bool IsUmbrella = strategies::detail::is_umbrella_strategy<Strategy>::value
>
struct overlaps
{
template <typename Geometry1, typename Geometry2>
static inline bool apply(Geometry1 const& geometry1,
Geometry2 const& geometry2,
Strategy const& strategy)
{
return dispatch::overlaps
<
Geometry1, Geometry2
>::apply(geometry1, geometry2, strategy);
}
};
template <typename Strategy>
struct overlaps<Strategy, false>
{
template <typename Geometry1, typename Geometry2>
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<Strategy>::get(strategy));
}
};
template <>
struct overlaps<default_strategy, false>
{
template <typename Geometry1, typename Geometry2>
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} \brief \brief_check2{overlap}
\ingroup overlaps \ingroup overlaps
@ -82,10 +146,9 @@ inline bool overlaps(Geometry1 const& geometry1,
concepts::check<Geometry1 const>(); concepts::check<Geometry1 const>();
concepts::check<Geometry2 const>(); concepts::check<Geometry2 const>();
return dispatch::overlaps return resolve_strategy::overlaps
< <
Geometry1, Strategy
Geometry2
>::apply(geometry1, geometry2, strategy); >::apply(geometry1, geometry2, strategy);
} }
@ -111,17 +174,10 @@ inline bool overlaps(Geometry1 const& geometry1, Geometry2 const& geometry2)
concepts::check<Geometry1 const>(); concepts::check<Geometry1 const>();
concepts::check<Geometry2 const>(); concepts::check<Geometry2 const>();
typedef typename strategy::relate::services::default_strategy return resolve_strategy::overlaps
< <
Geometry1, default_strategy
Geometry2 >::apply(geometry1, geometry2, default_strategy());
>::type strategy_type;
return dispatch::overlaps
<
Geometry1,
Geometry2
>::apply(geometry1, geometry2, strategy_type());
} }
}} // namespace boost::geometry }} // namespace boost::geometry

View File

@ -87,22 +87,17 @@ template
typename Geometry2, typename Geometry2,
typename RingCollection, typename RingCollection,
typename OutputIterator, typename OutputIterator,
typename AreaStrategy typename Strategy
> >
inline OutputIterator add_rings(SelectionMap const& map, inline OutputIterator add_rings(SelectionMap const& map,
Geometry1 const& geometry1, Geometry2 const& geometry2, Geometry1 const& geometry1, Geometry2 const& geometry2,
RingCollection const& collection, RingCollection const& collection,
OutputIterator out, OutputIterator out,
AreaStrategy const& area_strategy, Strategy const& strategy,
add_rings_error_handling error_handling = add_rings_ignore_unordered) add_rings_error_handling error_handling = add_rings_ignore_unordered)
{ {
typedef typename SelectionMap::const_iterator iterator; 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 std::size_t const min_num_points = core_detail::closure::minimum_ring_size
< <
geometry::closure geometry::closure
@ -146,7 +141,9 @@ inline OutputIterator add_rings(SelectionMap const& map,
// everything is figured out yet (sum of positive/negative rings) // everything is figured out yet (sum of positive/negative rings)
if (geometry::num_points(result) >= min_num_points) if (geometry::num_points(result) >= min_num_points)
{ {
area_type const area = geometry::area(result, area_strategy); typedef typename geometry::area_result<GeometryOut, Strategy>::type area_type;
area_type const area = geometry::area(result, strategy);
area_type const zero = 0;
// Ignore if area is 0 // Ignore if area is 0
if (! math::equals(area, zero)) if (! math::equals(area, zero))
{ {
@ -174,16 +171,16 @@ template
typename Geometry, typename Geometry,
typename RingCollection, typename RingCollection,
typename OutputIterator, typename OutputIterator,
typename AreaStrategy typename Strategy
> >
inline OutputIterator add_rings(SelectionMap const& map, inline OutputIterator add_rings(SelectionMap const& map,
Geometry const& geometry, Geometry const& geometry,
RingCollection const& collection, RingCollection const& collection,
OutputIterator out, OutputIterator out,
AreaStrategy const& area_strategy) Strategy const& strategy)
{ {
Geometry empty; Geometry empty;
return add_rings<GeometryOut>(map, geometry, empty, collection, out, area_strategy); return add_rings<GeometryOut>(map, geometry, empty, collection, out, strategy);
} }

View File

@ -40,9 +40,9 @@ inline void append_with_duplicates(Range& range, Point const& point)
geometry::append(range, point); geometry::append(range, point);
} }
template <typename Range, typename Point, typename EqPPStrategy> template <typename Range, typename Point, typename Strategy>
inline void append_no_duplicates(Range& range, Point const& point, inline void append_no_duplicates(Range& range, Point const& point,
EqPPStrategy const& strategy) Strategy const& strategy)
{ {
if ( boost::empty(range) if ( boost::empty(range)
|| ! geometry::detail::equals::equals_point_point(geometry::range::back(range), || ! geometry::detail::equals::equals_point_point(geometry::range::back(range),

View File

@ -41,10 +41,10 @@ namespace detail { namespace overlay
{ {
// TODO: move this / rename this // TODO: move this / rename this
template <typename Point1, typename Point2, typename EqualsStrategy, typename RobustPolicy> template <typename Point1, typename Point2, typename Strategy, typename RobustPolicy>
inline bool points_equal_or_close(Point1 const& point1, inline bool points_equal_or_close(Point1 const& point1,
Point2 const& point2, Point2 const& point2,
EqualsStrategy const& strategy, Strategy const& strategy,
RobustPolicy const& robust_policy) RobustPolicy const& robust_policy)
{ {
if (detail::equals::equals_point_point(point1, point2, strategy)) if (detail::equals::equals_point_point(point1, point2, strategy))
@ -79,9 +79,9 @@ inline bool points_equal_or_close(Point1 const& point1,
} }
template <typename Range, typename Point, typename SideStrategy, typename RobustPolicy> template <typename Range, typename Point, typename Strategy, typename RobustPolicy>
inline void append_no_dups_or_spikes(Range& range, Point const& point, inline void append_no_dups_or_spikes(Range& range, Point const& point,
SideStrategy const& strategy, Strategy const& strategy,
RobustPolicy const& robust_policy) RobustPolicy const& robust_policy)
{ {
#ifdef BOOST_GEOMETRY_DEBUG_INTERSECTION #ifdef BOOST_GEOMETRY_DEBUG_INTERSECTION
@ -93,8 +93,7 @@ inline void append_no_dups_or_spikes(Range& range, Point const& point,
// for geometries >= 3 points. // for geometries >= 3 points.
// So we have to check the first potential duplicate differently // So we have to check the first potential duplicate differently
if ( boost::size(range) == 1 if ( boost::size(range) == 1
&& points_equal_or_close(*(boost::begin(range)), point, && points_equal_or_close(*(boost::begin(range)), point, strategy,
strategy.get_equals_point_point_strategy(),
robust_policy) ) robust_policy) )
{ {
return; return;
@ -111,7 +110,7 @@ inline void append_no_dups_or_spikes(Range& range, Point const& point,
&& point_is_spike_or_equal(point, && point_is_spike_or_equal(point,
*(boost::end(range) - 3), *(boost::end(range) - 3),
*(boost::end(range) - 2), *(boost::end(range) - 2),
strategy, strategy.side(), // TODO: Pass strategy?
robust_policy)) robust_policy))
{ {
// Use the Concept/traits, so resize and append again // Use the Concept/traits, so resize and append again
@ -120,9 +119,9 @@ inline void append_no_dups_or_spikes(Range& range, Point const& point,
} }
} }
template <typename Range, typename Point, typename SideStrategy, typename RobustPolicy> template <typename Range, typename Point, typename Strategy, typename RobustPolicy>
inline void append_no_collinear(Range& range, Point const& point, inline void append_no_collinear(Range& range, Point const& point,
SideStrategy const& strategy, Strategy const& strategy,
RobustPolicy const& robust_policy) RobustPolicy const& robust_policy)
{ {
// Stricter version, not allowing any point in a linear row // Stricter version, not allowing any point in a linear row
@ -133,7 +132,7 @@ inline void append_no_collinear(Range& range, Point const& point,
// So we have to check the first potential duplicate differently // So we have to check the first potential duplicate differently
if ( boost::size(range) == 1 if ( boost::size(range) == 1
&& points_equal_or_close(*(boost::begin(range)), point, && points_equal_or_close(*(boost::begin(range)), point,
strategy.get_equals_point_point_strategy(), strategy,
robust_policy) ) robust_policy) )
{ {
return; return;
@ -150,7 +149,7 @@ inline void append_no_collinear(Range& range, Point const& point,
&& point_is_collinear(point, && point_is_collinear(point,
*(boost::end(range) - 3), *(boost::end(range) - 3),
*(boost::end(range) - 2), *(boost::end(range) - 2),
strategy, strategy.side(), // TODO: Pass strategy?
robust_policy)) robust_policy))
{ {
// Use the Concept/traits, so resize and append again // Use the Concept/traits, so resize and append again
@ -159,9 +158,9 @@ inline void append_no_collinear(Range& range, Point const& point,
} }
} }
template <typename Range, typename SideStrategy, typename RobustPolicy> template <typename Range, typename Strategy, typename RobustPolicy>
inline void clean_closing_dups_and_spikes(Range& range, inline void clean_closing_dups_and_spikes(Range& range,
SideStrategy const& strategy, Strategy const& strategy,
RobustPolicy const& robust_policy) RobustPolicy const& robust_policy)
{ {
std::size_t const minsize std::size_t const minsize
@ -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 // Check if closing point is a spike (this is so if the second point is
// considered as collinear w.r.t. the last segment) // 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); range::erase(range, first);
if (BOOST_GEOMETRY_CONDITION(closed)) if (BOOST_GEOMETRY_CONDITION(closed))

View File

@ -127,27 +127,39 @@ struct ring_info_helper
}; };
template <typename BoxExpandStrategy> template <typename Strategy>
struct ring_info_helper_get_box struct ring_info_helper_get_box
{ {
ring_info_helper_get_box(Strategy const& strategy)
: m_strategy(strategy)
{}
template <typename Box, typename InputItem> template <typename Box, typename InputItem>
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); 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 <typename DisjointBoxBoxStrategy> template <typename Strategy>
struct ring_info_helper_overlaps_box struct ring_info_helper_overlaps_box
{ {
ring_info_helper_overlaps_box(Strategy const& strategy)
: m_strategy(strategy)
{}
template <typename Box, typename InputItem> template <typename Box, typename InputItem>
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); assert_coordinate_type_equal(box, item.envelope);
return ! geometry::detail::disjoint::disjoint_box_box( return ! geometry::detail::disjoint::disjoint_box_box(
box, item.envelope, DisjointBoxBoxStrategy()); box, item.envelope, m_strategy);
} }
Strategy const& m_strategy;
}; };
// Segments intersection Strategy // Segments intersection Strategy
@ -196,8 +208,7 @@ struct assign_visitor
{ {
ring_info_type& inner_in_map = m_ring_map[inner.id]; ring_info_type& inner_in_map = m_ring_map[inner.id];
if (geometry::covered_by(inner_in_map.point, outer.envelope, if (geometry::covered_by(inner_in_map.point, outer.envelope, m_strategy)
typename Strategy::disjoint_point_box_strategy_type())
&& within_selected_input(inner_in_map, inner.id, outer.id, && within_selected_input(inner_in_map, inner.id, outer.id,
m_geometry1, m_geometry2, m_collection, m_geometry1, m_geometry2, m_collection,
m_strategy) m_strategy)
@ -244,10 +255,10 @@ inline void assign_parents(Geometry1 const& geometry1,
typedef typename RingMap::mapped_type ring_info_type; typedef typename RingMap::mapped_type ring_info_type;
typedef typename ring_info_type::point_type point_type; typedef typename ring_info_type::point_type point_type;
typedef model::box<point_type> box_type; typedef model::box<point_type> box_type;
typedef typename Strategy::template area_strategy typedef typename geometry::area_result
< <
point_type point_type, Strategy // TODO: point_type is technically incorrect
>::type::template result_type<point_type>::type area_result_type; >::type area_result_type;
typedef typename RingMap::iterator map_iterator_type; typedef typename RingMap::iterator map_iterator_type;
@ -273,15 +284,15 @@ inline void assign_parents(Geometry1 const& geometry1,
{ {
case 0 : case 0 :
geometry::envelope(get_ring<tag1>::apply(it->first, geometry1), geometry::envelope(get_ring<tag1>::apply(it->first, geometry1),
item.envelope, strategy.get_envelope_strategy()); item.envelope, strategy);
break; break;
case 1 : case 1 :
geometry::envelope(get_ring<tag2>::apply(it->first, geometry2), geometry::envelope(get_ring<tag2>::apply(it->first, geometry2),
item.envelope, strategy.get_envelope_strategy()); item.envelope, strategy);
break; break;
case 2 : case 2 :
geometry::envelope(get_ring<void>::apply(it->first, collection), geometry::envelope(get_ring<void>::apply(it->first, collection),
item.envelope, strategy.get_envelope_strategy()); item.envelope, strategy);
break; break;
} }
@ -336,19 +347,12 @@ inline void assign_parents(Geometry1 const& geometry1,
Strategy Strategy
> visitor(geometry1, geometry2, collection, ring_map, strategy, check_for_orientation); > 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 geometry::partition
< <
box_type box_type
>::apply(vector, visitor, expand_box_type(), overlaps_box_type()); >::apply(vector, visitor,
ring_info_helper_get_box<Strategy>(strategy),
ring_info_helper_overlaps_box<Strategy>(strategy));
} }
if (check_for_orientation) if (check_for_orientation)

View File

@ -61,14 +61,14 @@ struct copy_segments_ring
< <
typename Ring, typename Ring,
typename SegmentIdentifier, typename SegmentIdentifier,
typename SideStrategy, typename Strategy,
typename RobustPolicy, typename RobustPolicy,
typename RangeOut typename RangeOut
> >
static inline void apply(Ring const& ring, static inline void apply(Ring const& ring,
SegmentIdentifier const& seg_id, SegmentIdentifier const& seg_id,
signed_size_type to_index, signed_size_type to_index,
SideStrategy const& strategy, Strategy const& strategy,
RobustPolicy const& robust_policy, RobustPolicy const& robust_policy,
RangeOut& current_output) RangeOut& current_output)
{ {
@ -125,10 +125,10 @@ class copy_segments_linestring
{ {
private: private:
// remove spikes // remove spikes
template <typename RangeOut, typename Point, typename SideStrategy, typename RobustPolicy> template <typename RangeOut, typename Point, typename Strategy, typename RobustPolicy>
static inline void append_to_output(RangeOut& current_output, static inline void append_to_output(RangeOut& current_output,
Point const& point, Point const& point,
SideStrategy const& strategy, Strategy const& strategy,
RobustPolicy const& robust_policy, RobustPolicy const& robust_policy,
std::true_type const&) std::true_type const&)
{ {
@ -138,14 +138,14 @@ private:
} }
// keep spikes // keep spikes
template <typename RangeOut, typename Point, typename SideStrategy, typename RobustPolicy> template <typename RangeOut, typename Point, typename Strategy, typename RobustPolicy>
static inline void append_to_output(RangeOut& current_output, static inline void append_to_output(RangeOut& current_output,
Point const& point, Point const& point,
SideStrategy const& strategy, Strategy const& strategy,
RobustPolicy const&, RobustPolicy const&,
std::false_type 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: public:

View File

@ -524,7 +524,7 @@ inline void enrich_intersection_points(Turns& turns,
detail::overlay::enrich_sort<Reverse1, Reverse2>( detail::overlay::enrich_sort<Reverse1, Reverse2>(
mit->second, turns, mit->second, turns,
geometry1, geometry2, geometry1, geometry2,
robust_policy, strategy.get_side_strategy()); robust_policy, strategy.side()); // TODO: pass strategy
} }
for (typename mapped_vector_type::iterator mit for (typename mapped_vector_type::iterator mit
@ -554,7 +554,7 @@ inline void enrich_intersection_points(Turns& turns,
Reverse2, Reverse2,
OverlayType OverlayType
>(clusters, turns, target_operation, >(clusters, turns, target_operation,
geometry1, geometry2, strategy.get_side_strategy()); geometry1, geometry2, strategy.side()); // TODO: pass strategy
detail::overlay::cleanup_clusters(turns, clusters); detail::overlay::cleanup_clusters(turns, clusters);
} }

View File

@ -62,11 +62,11 @@ template
typename Operation, typename Operation,
typename LineString, typename LineString,
typename Polygon, typename Polygon,
typename PtInPolyStrategy typename Strategy
> >
inline bool last_covered_by(Turn const& /*turn*/, Operation const& op, inline bool last_covered_by(Turn const& /*turn*/, Operation const& op,
LineString const& linestring, Polygon const& polygon, 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); return geometry::covered_by(range::at(linestring, op.seg_id.segment_index), polygon, strategy);
} }
@ -78,12 +78,12 @@ template
typename Operation, typename Operation,
typename LineString, typename LineString,
typename Polygon, typename Polygon,
typename PtInPolyStrategy typename Strategy
> >
inline bool is_leaving(Turn const& turn, Operation const& op, inline bool is_leaving(Turn const& turn, Operation const& op,
bool entered, bool first, bool entered, bool first,
LineString const& linestring, Polygon const& polygon, LineString const& linestring, Polygon const& polygon,
PtInPolyStrategy const& strategy) Strategy const& strategy)
{ {
if (op.operation == operation_union) if (op.operation == operation_union)
{ {
@ -104,12 +104,12 @@ template
typename Operation, typename Operation,
typename LineString, typename LineString,
typename Polygon, typename Polygon,
typename PtInPolyStrategy typename Strategy
> >
inline bool is_staying_inside(Turn const& turn, Operation const& op, inline bool is_staying_inside(Turn const& turn, Operation const& op,
bool entered, bool first, bool entered, bool first,
LineString const& linestring, Polygon const& polygon, LineString const& linestring, Polygon const& polygon,
PtInPolyStrategy const& strategy) Strategy const& strategy)
{ {
if (turn.method == method_crosses) if (turn.method == method_crosses)
{ {
@ -132,11 +132,11 @@ template
typename Operation, typename Operation,
typename Linestring, typename Linestring,
typename Polygon, typename Polygon,
typename PtInPolyStrategy typename Strategy
> >
inline bool was_entered(Turn const& turn, Operation const& op, bool first, inline bool was_entered(Turn const& turn, Operation const& op, bool first,
Linestring const& linestring, Polygon const& polygon, Linestring const& linestring, Polygon const& polygon,
PtInPolyStrategy const& strategy) Strategy const& strategy)
{ {
if (first && (turn.method == method_collinear || turn.method == method_equal)) if (first && (turn.method == method_collinear || turn.method == method_equal))
{ {
@ -234,7 +234,7 @@ struct action_selector<overlay_intersection, RemoveSpikes>
{ {
// On enter, append the intersection point and remember starting point // On enter, append the intersection point and remember starting point
// TODO: we don't check on spikes for linestrings (?). Consider this. // 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; segment_id = operation.seg_id;
} }
@ -263,7 +263,7 @@ struct action_selector<overlay_intersection, RemoveSpikes>
< <
false, RemoveSpikes false, RemoveSpikes
>::apply(linestring, segment_id, index, strategy, robust_policy, current_piece); >::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) if (::boost::size(current_piece) > 1)
{ {
*out++ = current_piece; *out++ = current_piece;
@ -431,14 +431,6 @@ public :
typedef following::action_selector<OverlayType, RemoveSpikes> action; typedef following::action_selector<OverlayType, RemoveSpikes> 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<LineString, Polygon>();
// Sort intersection points on segments-along-linestring, and distance // Sort intersection points on segments-along-linestring, and distance
// (like in enrich is done for poly/poly) // (like in enrich is done for poly/poly)
// sort turns by Linear seg_id, then by fraction, then // sort turns by Linear seg_id, then by fraction, then
@ -446,7 +438,8 @@ public :
// for different ring id: c, i, u, x // for different ring id: c, i, u, x
typedef relate::turns::less 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; > turn_less;
std::sort(boost::begin(turns), boost::end(turns), 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); 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"); debug_traverse(*it, *iit, "-> Was entered");
entered = true; 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"); debug_traverse(*it, *iit, "-> Staying inside");
@ -482,7 +475,7 @@ public :
strategy, robust_policy, strategy, robust_policy,
linear::get(out)); 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"); debug_traverse(*it, *iit, "-> Leaving");

View File

@ -73,7 +73,7 @@ struct get_turn_without_info
> policy_type; > policy_type;
typename policy_type::return_type const result 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++) for (std::size_t i = 0; i < result.count; i++)
{ {

View File

@ -3,8 +3,8 @@
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. // Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2017 Adam Wulkiewicz, Lodz, Poland. // Copyright (c) 2017 Adam Wulkiewicz, Lodz, Poland.
// This file was modified by Oracle on 2015, 2017, 2018, 2019. // This file was modified by Oracle on 2015-2020.
// Modifications copyright (c) 2015-2019 Oracle and/or its affiliates. // Modifications copyright (c) 2015-2020 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle // 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 #ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_GET_TURN_INFO_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_GET_TURN_INFO_HPP #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_GET_TURN_INFO_HPP
#include <boost/core/ignore_unused.hpp> #include <boost/core/ignore_unused.hpp>
#include <boost/throw_exception.hpp> #include <boost/throw_exception.hpp>
@ -28,9 +27,6 @@
#include <boost/geometry/algorithms/detail/overlay/get_distance_measure.hpp> #include <boost/geometry/algorithms/detail/overlay/get_distance_measure.hpp>
#include <boost/geometry/algorithms/detail/overlay/turn_info.hpp> #include <boost/geometry/algorithms/detail/overlay/turn_info.hpp>
#include <boost/geometry/geometries/segment.hpp>
#include <boost/geometry/policies/robustness/robust_point_type.hpp>
#include <boost/geometry/algorithms/detail/overlay/get_turn_info_helpers.hpp> #include <boost/geometry/algorithms/detail/overlay/get_turn_info_helpers.hpp>
// Silence warning C4127: conditional expression is constant // Silence warning C4127: conditional expression is constant
@ -131,15 +127,7 @@ struct base_turn_handler
return 0; return 0;
} }
typedef typename select_coordinate_type auto const dm = get_distance_measure(range_p.at(range_index), range_p.at(range_index + 1), range_q.at(point_index));
<
typename UniqueSubRange1::point_type,
typename UniqueSubRange2::point_type
>::type coordinate_type;
typedef detail::distance_measure<coordinate_type> 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));
return dm.measure == 0 ? 0 : dm.measure > 0 ? 1 : -1; return dm.measure == 0 ? 0 : dm.measure > 0 ? 1 : -1;
} }
@ -186,7 +174,8 @@ struct base_turn_handler
{ {
ti.method = method; 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; static int const index = 0;
geometry::convert(info.intersections[index], ti.point); 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 // TODO: use comparable distance for point-point instead - but that
// causes currently cycling include problems // causes currently cycling include problems
typedef typename geometry::coordinate_type<Point1>::type ctype; auto const dx = get<0>(a) - get<0>(b);
ctype const dx = get<0>(a) - get<0>(b); auto const dy = get<1>(a) - get<1>(b);
ctype const dy = get<1>(a) - get<1>(b);
return dx * dx + dy * dy; return dx * dx + dy * dy;
} }
@ -259,19 +247,10 @@ struct base_turn_handler
// pk/q2 is considered as collinear, but there might be // pk/q2 is considered as collinear, but there might be
// a tiny measurable difference. If so, use that. // a tiny measurable difference. If so, use that.
// Calculate pk // qj-qk // Calculate pk // qj-qk
typedef detail::distance_measure bool const p_closer =
<
typename select_coordinate_type
<
typename UniqueSubRange1::point_type,
typename UniqueSubRange2::point_type
>::type
> dm_type;
const bool p_closer =
ti.operations[IndexP].remaining_distance ti.operations[IndexP].remaining_distance
< ti.operations[IndexQ].remaining_distance; < ti.operations[IndexQ].remaining_distance;
dm_type const dm auto const dm
= p_closer = p_closer
? get_distance_measure(range_q.at(index_q - 1), ? get_distance_measure(range_q.at(index_q - 1),
range_q.at(index_q), range_p.at(index_p)) 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 // Not truely collinear, distinguish for union/intersection
// If p goes left (positive), take that for a union // If p goes left (positive), take that for a union
bool const p_left = p_closer ? dm.is_positive() : dm.is_negative();
bool p_left = p_closer ? dm.is_positive() : dm.is_negative();
ti.operations[IndexP].operation = p_left ti.operations[IndexP].operation = p_left
? operation_union : operation_intersection; ? 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 // Therefore handle it as a normal touch (two segments arrive at the
// intersection point). It currently checks for zero, but even a // intersection point). It currently checks for zero, but even a
// distance a little bit larger would do. // distance a little bit larger would do.
typedef typename geometry::coordinate_type auto const dm = distance_measure(info.intersections[0], non_touching_range.at(1));
< decltype(dm) const zero = 0;
typename UniqueSubRange::point_type bool const result = math::equals(dm, zero);
>::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);
return result; return result;
} }
@ -540,16 +513,8 @@ struct touch : public base_turn_handler
// >----->P qj is LEFT of P1 and pi is LEFT of Q2 // >----->P qj is LEFT of P1 and pi is LEFT of Q2
// (the other way round is also possible) // (the other way round is also possible)
typedef typename select_coordinate_type 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));
typename UniqueSubRange1::point_type,
typename UniqueSubRange2::point_type
>::type coordinate_type;
typedef detail::distance_measure<coordinate_type> 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));
if (dm_qj_p1.measure > 0 && dm_pi_q2.measure > 0) if (dm_qj_p1.measure > 0 && dm_pi_q2.measure > 0)
{ {
@ -564,8 +529,8 @@ struct touch : public base_turn_handler
return true; return true;
} }
dm_type const dm_pj_q1 = get_distance_measure(range_q.at(0), range_q.at(1), range_p.at(1)); auto 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_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) 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 // They turn to the same side, or continue both collinearly
// Without rescaling, to check for union/intersection, // Without rescaling, to check for union/intersection,
// try to check side values (without any thresholds) // try to check side values (without any thresholds)
typedef typename select_coordinate_type auto const dm_pk_q2
<
typename UniqueSubRange1::point_type,
typename UniqueSubRange2::point_type
>::type coordinate_type;
typedef detail::distance_measure<coordinate_type> dm_type;
dm_type const dm_pk_q2
= get_distance_measure(range_q.at(1), range_q.at(2), range_p.at(2)); = 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)); = get_distance_measure(range_p.at(1), range_p.at(2), range_q.at(2));
if (dm_qk_p2.measure != dm_pk_q2.measure) if (dm_qk_p2.measure != dm_pk_q2.measure)
@ -965,8 +922,57 @@ template
> >
struct collinear : public base_turn_handler 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 CLL1 ui
-1 1 -1 CLL2 iu -1 1 -1 CLL2 iu
1 1 1 CLR1 ui 1 1 1 CLR1 ui
@ -980,7 +986,9 @@ struct collinear : public base_turn_handler
1 0 0 CC1 cc 1 0 0 CC1 cc
-1 0 0 CC2 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: Stated otherwise:
- if P arrives: look at turn P - 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 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 left: union for Q (=intersection for P)
- if Q arrives and Q turns right: intersection for Q (=union 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 template
< <
@ -1016,9 +1017,9 @@ struct collinear : public base_turn_handler
// Copy the intersection point in TO direction // Copy the intersection point in TO direction
assign_point(ti, method_collinear, info, non_opposite_to_index(info)); 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 // 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_pk = ! range_p.is_last_segment();
bool const has_qk = ! range_q.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; int const side_q = has_qk ? side.qk_wrt_q1() : 0;
// If p arrives, use p, else use q // 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_p
: side_q : side_q
; ;
// See comments above, // Calculate product according to comments above.
// resulting in a strange sort of mathematic rule here: int const product = arrival_p * side_p_or_q;
// The arrival-info multiplied by the relevant side
// delivers a consistent result.
int const product = arrival * side_p_or_q; if (product == 0)
if(product == 0)
{ {
both(ti, operation_continue); both(ti, operation_continue);
} }
@ -1186,11 +1183,11 @@ public:
{ {
TurnInfo tp = tp_model; TurnInfo tp = tp_model;
int const p_arrival = info.d_info().arrival[0]; int const arrival_p = info.d_info().arrival[0];
int const q_arrival = info.d_info().arrival[1]; int const arrival_q = info.d_info().arrival[1];
// If P arrives within Q, there is a turn dependent on P // 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() && ! range_p.is_last_segment()
&& set_tp<0>(side.pk_wrt_p1(), tp, info.i_info()) ) && 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 arrives within P, there is a turn dependent on Q
if ( q_arrival == 1 if ( arrival_q == 1
&& ! range_q.is_last_segment() && ! range_q.is_last_segment()
&& set_tp<1>(side.qk_wrt_q1(), tp, info.i_info()) ) && set_tp<1>(side.qk_wrt_q1(), tp, info.i_info()) )
{ {
@ -1212,8 +1209,8 @@ public:
if (AssignPolicy::include_opposite) if (AssignPolicy::include_opposite)
{ {
// Handle cases not yet handled above // Handle cases not yet handled above
if ((q_arrival == -1 && p_arrival == 0) if ((arrival_q == -1 && arrival_p == 0)
|| (p_arrival == -1 && q_arrival == 0)) || (arrival_p == -1 && arrival_q == 0))
{ {
for (unsigned int i = 0; i < 2; i++) for (unsigned int i = 0; i < 2; i++)
{ {
@ -1396,7 +1393,7 @@ struct get_turn_info
else else
{ {
handler::template apply<1>(range_q, range_p, tp, inters.i_info(), inters.d_info(), 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; *out++ = tp;
} }
} }
@ -1420,9 +1417,10 @@ struct get_turn_info
// Collinear // Collinear
if ( ! inters.d_info().opposite ) if ( ! inters.d_info().opposite )
{ {
if (inters.d_info().arrival[0] == 0
if ( inters.d_info().arrival[0] == 0 ) || collinear<TurnInfo>::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; handle_as_equal = true;
} }
else else

View File

@ -2,8 +2,8 @@
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. // Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
// This file was modified by Oracle on 2013, 2014, 2017, 2018. // This file was modified by Oracle on 2013-2020.
// Modifications copyright (c) 2013-2018 Oracle and/or its affiliates. // 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 Adam Wulkiewicz, on behalf of Oracle
@ -111,12 +111,16 @@ namespace detail { namespace overlay {
class linear_intersections class linear_intersections
{ {
public: public:
template <typename Point1, typename Point2, typename IntersectionResult, typename EqPPStrategy> template
<
typename Point1, typename Point2, typename IntersectionResult,
typename Strategy
>
linear_intersections(Point1 const& pi, linear_intersections(Point1 const& pi,
Point2 const& qi, Point2 const& qi,
IntersectionResult const& result, IntersectionResult const& result,
bool is_p_last, bool is_q_last, bool is_p_last, bool is_q_last,
EqPPStrategy const& strategy) Strategy const& strategy)
{ {
int arrival_a = result.direction.arrival[0]; int arrival_a = result.direction.arrival[0];
int arrival_b = result.direction.arrival[1]; int arrival_b = result.direction.arrival[1];
@ -237,7 +241,7 @@ struct get_turn_info_for_endpoint
typename TurnInfo, typename TurnInfo,
typename IntersectionInfo, typename IntersectionInfo,
typename OutputIterator, typename OutputIterator,
typename EqPPStrategy typename Strategy
> >
static inline bool apply(UniqueSubRange1 const& range_p, static inline bool apply(UniqueSubRange1 const& range_p,
UniqueSubRange2 const& range_q, UniqueSubRange2 const& range_q,
@ -245,7 +249,7 @@ struct get_turn_info_for_endpoint
IntersectionInfo const& inters, IntersectionInfo const& inters,
method_type /*method*/, method_type /*method*/,
OutputIterator out, OutputIterator out,
EqPPStrategy const& strategy) Strategy const& strategy)
{ {
std::size_t ip_count = inters.i_info().count; std::size_t ip_count = inters.i_info().count;
// no intersection points // no intersection points
@ -398,8 +402,7 @@ struct get_turn_info_for_endpoint
{ {
boost::ignore_unused(ip_index, tp_model); boost::ignore_unused(ip_index, tp_model);
typename IntersectionInfo::side_strategy_type const& sides auto const strategy = inters.strategy();
= inters.get_side_strategy();
if ( !first2 && !last2 ) if ( !first2 && !last2 )
{ {
@ -409,8 +412,8 @@ struct get_turn_info_for_endpoint
// may this give false positives for INTs? // may this give false positives for INTs?
typename IntersectionResult::point_type const& typename IntersectionResult::point_type const&
inters_pt = inters.i_info().intersections[ip_index]; inters_pt = inters.i_info().intersections[ip_index];
BOOST_GEOMETRY_ASSERT(ip_i2 == equals::equals_point_point(i2, 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)); BOOST_GEOMETRY_ASSERT(ip_j2 == equals::equals_point_point(j2, inters_pt, strategy));
#endif #endif
if ( ip_i2 ) if ( ip_i2 )
{ {
@ -421,6 +424,7 @@ struct get_turn_info_for_endpoint
} }
else if ( ip_j2 ) 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_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_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)); 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? // may this give false positives for INTs?
typename IntersectionResult::point_type const& typename IntersectionResult::point_type const&
inters_pt = inters.i_info().intersections[ip_index]; inters_pt = inters.i_info().intersections[ip_index];
BOOST_GEOMETRY_ASSERT(ip_i2 == equals::equals_point_point(i2, 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)); BOOST_GEOMETRY_ASSERT(ip_j2 == equals::equals_point_point(j2, inters_pt, strategy));
#endif #endif
if ( ip_i2 ) if ( ip_i2 )
{ {
@ -472,6 +476,7 @@ struct get_turn_info_for_endpoint
} }
else if ( ip_j2 ) 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_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_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)); int const side_qk_q1 = sides.apply(range2.at(0), range2.at(1), range2.at(2));

View File

@ -44,20 +44,20 @@ struct turn_operation_linear
template template
< <
typename TurnPointCSTag,
typename UniqueSubRange1, typename UniqueSubRange1,
typename UniqueSubRange2, typename UniqueSubRange2,
typename SideStrategy typename Strategy
> >
struct side_calculator struct side_calculator
{ {
typedef typename UniqueSubRange1::point_type point1_type; typedef typename UniqueSubRange1::point_type point1_type;
typedef typename UniqueSubRange2::point_type point2_type; typedef typename UniqueSubRange2::point_type point2_type;
typedef decltype(std::declval<Strategy>().side()) side_strategy_type;
inline side_calculator(UniqueSubRange1 const& range_p, inline side_calculator(UniqueSubRange1 const& range_p,
UniqueSubRange2 const& range_q, UniqueSubRange2 const& range_q,
SideStrategy const& side_strategy) Strategy const& strategy)
: m_side_strategy(side_strategy) : m_side_strategy(strategy.side())
, m_range_p(range_p) , m_range_p(range_p)
, m_range_q(range_q) , 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_qj() const { return m_range_q.at(1); }
inline point2_type const& get_qk() const { return m_range_q.at(2); } inline point2_type const& get_qk() const { return m_range_q.at(2); }
// Used side-strategy, owned by the calculator, // Used side-strategy, owned by the calculator
// created from .get_side_strategy() side_strategy_type m_side_strategy;
SideStrategy m_side_strategy;
// Used ranges - owned by get_turns or (for robust points) by intersection_info_base // Used ranges - owned by get_turns or (for robust points) by intersection_info_base
UniqueSubRange1 const& m_range_p; UniqueSubRange1 const& m_range_p;
@ -259,16 +258,14 @@ public:
typedef robust_subrange_adapter<robust_point1_type, UniqueSubRange1, RobustPolicy> robust_subrange1; typedef robust_subrange_adapter<robust_point1_type, UniqueSubRange1, RobustPolicy> robust_subrange1;
typedef robust_subrange_adapter<robust_point2_type, UniqueSubRange2, RobustPolicy> robust_subrange2; typedef robust_subrange_adapter<robust_point2_type, UniqueSubRange2, RobustPolicy> robust_subrange2;
typedef typename cs_tag<TurnPoint>::type cs_tag; typedef side_calculator
<
typedef typename UmbrellaStrategy::side_strategy_type side_strategy_type; robust_subrange1, robust_subrange2, UmbrellaStrategy
typedef side_calculator<cs_tag, robust_subrange1, robust_subrange2, > side_calculator_type;
side_strategy_type> side_calculator_type;
typedef side_calculator typedef side_calculator
< <
cs_tag, robust_subrange2, robust_subrange1, robust_subrange2, robust_subrange1, UmbrellaStrategy
side_strategy_type
> robust_swapped_side_calculator_type; > robust_swapped_side_calculator_type;
intersection_info_base(UniqueSubRange1 const& range_p, intersection_info_base(UniqueSubRange1 const& range_p,
@ -280,9 +277,9 @@ public:
, m_robust_calc(range_p, range_q, robust_policy) , 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_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_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, , m_side_calc(m_robust_range_p, m_robust_range_q, umbrella_strategy)
umbrella_strategy.get_side_strategy()) , m_swapped_side_calc(m_robust_range_q, m_robust_range_p, umbrella_strategy)
, m_result(umbrella_strategy.apply(range_p, range_q, , m_result(umbrella_strategy.relate().apply(range_p, range_q,
intersection_policy_type(), intersection_policy_type(),
m_robust_range_p, m_robust_range_q)) 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 robust_point2_type const& rqk() const { return m_robust_calc.get_rqk(); }
inline side_calculator_type const& sides() const { return m_side_calc; } inline side_calculator_type const& sides() const { return m_side_calc; }
inline robust_swapped_side_calculator_type const& swapped_sides() const
robust_swapped_side_calculator_type get_swapped_sides() const
{ {
robust_swapped_side_calculator_type result( return m_swapped_side_calc;
m_robust_range_q, m_robust_range_p,
m_side_calc.m_side_strategy);
return result;
} }
private : private :
@ -319,6 +312,7 @@ private :
robust_subrange1 m_robust_range_p; robust_subrange1 m_robust_range_p;
robust_subrange2 m_robust_range_q; robust_subrange2 m_robust_range_q;
side_calculator_type m_side_calc; side_calculator_type m_side_calc;
robust_swapped_side_calculator_type m_swapped_side_calc;
protected : protected :
result_type m_result; result_type m_result;
@ -347,15 +341,14 @@ public:
typedef typename UniqueSubRange1::point_type point1_type; typedef typename UniqueSubRange1::point_type point1_type;
typedef typename UniqueSubRange2::point_type point2_type; typedef typename UniqueSubRange2::point_type point2_type;
typedef typename UmbrellaStrategy::cs_tag cs_tag; typedef side_calculator
<
typedef typename UmbrellaStrategy::side_strategy_type side_strategy_type; UniqueSubRange1, UniqueSubRange2, UmbrellaStrategy
typedef side_calculator<cs_tag, UniqueSubRange1, UniqueSubRange2, side_strategy_type> side_calculator_type; > side_calculator_type;
typedef side_calculator typedef side_calculator
< <
cs_tag, UniqueSubRange2, UniqueSubRange1, UniqueSubRange2, UniqueSubRange1, UmbrellaStrategy
side_strategy_type
> swapped_side_calculator_type; > swapped_side_calculator_type;
intersection_info_base(UniqueSubRange1 const& range_p, intersection_info_base(UniqueSubRange1 const& range_p,
@ -364,9 +357,10 @@ public:
no_rescale_policy const& ) no_rescale_policy const& )
: m_range_p(range_p) : m_range_p(range_p)
, m_range_q(range_q) , m_range_q(range_q)
, m_side_calc(range_p, range_q, , m_side_calc(range_p, range_q, umbrella_strategy)
umbrella_strategy.get_side_strategy()) , m_swapped_side_calc(range_q, range_p, umbrella_strategy)
, m_result(umbrella_strategy.apply(range_p, range_q, intersection_policy_type())) , 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(); } 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 point2_type const& rqk() const { return m_side_calc.get_qk(); }
inline side_calculator_type const& sides() const { return m_side_calc; } inline side_calculator_type const& sides() const { return m_side_calc; }
inline swapped_side_calculator_type const& swapped_sides() const
swapped_side_calculator_type get_swapped_sides() const
{ {
swapped_side_calculator_type result( return m_swapped_side_calc;
m_range_q, m_range_p,
m_side_calc.m_side_strategy);
return result;
} }
private : private :
@ -397,6 +387,7 @@ private :
// Owned by this class // Owned by this class
side_calculator_type m_side_calc; side_calculator_type m_side_calc;
swapped_side_calculator_type m_swapped_side_calc;
protected : protected :
result_type m_result; result_type m_result;
@ -422,8 +413,6 @@ public:
typedef typename UniqueSubRange1::point_type point1_type; typedef typename UniqueSubRange1::point_type point1_type;
typedef typename UniqueSubRange2::point_type point2_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 UmbrellaStrategy::cs_tag cs_tag;
typedef typename base::side_calculator_type side_calculator_type; typedef typename base::side_calculator_type side_calculator_type;
@ -437,7 +426,7 @@ public:
UmbrellaStrategy const& umbrella_strategy, UmbrellaStrategy const& umbrella_strategy,
RobustPolicy const& robust_policy) RobustPolicy const& robust_policy)
: base(range_p, range_q, umbrella_strategy, 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) , 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 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 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 // TODO: it's more like is_spike_ip_p
inline bool is_spike_p() const inline bool is_spike_p() const
{ {
@ -524,6 +508,11 @@ public:
return false; return false;
} }
UmbrellaStrategy const& strategy() const
{
return m_umbrella_strategy;
}
private: private:
template <std::size_t OpId> template <std::size_t OpId>
bool is_ip_j() const 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; RobustPolicy const& m_robust_policy;
}; };

View File

@ -3,8 +3,8 @@
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. // Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2017 Adam Wulkiewicz, Lodz, Poland. // Copyright (c) 2017 Adam Wulkiewicz, Lodz, Poland.
// This file was modified by Oracle on 2013, 2014, 2015, 2017, 2018. // This file was modified by Oracle on 2013-2020.
// Modifications copyright (c) 2013-2018 Oracle and/or its affiliates. // 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 Adam Wulkiewicz, on behalf of Oracle
@ -79,7 +79,7 @@ struct get_turn_info_linear_areal
case 's' : // starts from the middle case 's' : // starts from the middle
get_turn_info_for_endpoint<true, true>(range_p, range_q, get_turn_info_for_endpoint<true, true>(range_p, range_q,
tp_model, inters, method_none, out, tp_model, inters, method_none, out,
umbrella_strategy.get_point_in_point_strategy()); umbrella_strategy);
break; break;
case 'd' : // disjoint: never do anything case 'd' : // disjoint: never do anything
@ -89,7 +89,7 @@ struct get_turn_info_linear_areal
{ {
if ( get_turn_info_for_endpoint<false, true>(range_p, range_q, if ( get_turn_info_for_endpoint<false, true>(range_p, range_q,
tp_model, inters, method_touch_interior, out, tp_model, inters, method_touch_interior, out,
umbrella_strategy.get_point_in_point_strategy()) ) umbrella_strategy) )
{ {
// do nothing // do nothing
} }
@ -109,7 +109,7 @@ struct get_turn_info_linear_areal
// Swap p/q // Swap p/q
handler::template apply<1>(range_q, range_p, handler::template apply<1>(range_q, range_p,
tp, inters.i_info(), inters.d_info(), 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 ) 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 // this function assumes that 'u' must be set for a spike
calculate_spike_operation(tp.operations[0].operation, calculate_spike_operation(tp.operations[0].operation,
inters, inters,
umbrella_strategy.get_point_in_point_strategy()); umbrella_strategy);
*out++ = tp; *out++ = tp;
} }
@ -144,7 +144,7 @@ struct get_turn_info_linear_areal
// Both touch (both arrive there) // Both touch (both arrive there)
if ( get_turn_info_for_endpoint<false, true>(range_p, range_q, if ( get_turn_info_for_endpoint<false, true>(range_p, range_q,
tp_model, inters, method_touch, out, tp_model, inters, method_touch, out,
umbrella_strategy.get_point_in_point_strategy()) ) umbrella_strategy) )
{ {
// do nothing // do nothing
} }
@ -218,7 +218,7 @@ struct get_turn_info_linear_areal
bool ignore_spike bool ignore_spike
= calculate_spike_operation(tp.operations[0].operation, = calculate_spike_operation(tp.operations[0].operation,
inters, inters,
umbrella_strategy.get_point_in_point_strategy()); umbrella_strategy);
if ( ! BOOST_GEOMETRY_CONDITION(handle_spikes) if ( ! BOOST_GEOMETRY_CONDITION(handle_spikes)
|| ignore_spike || ignore_spike
@ -234,7 +234,7 @@ struct get_turn_info_linear_areal
{ {
if ( get_turn_info_for_endpoint<true, true>(range_p, range_q, if ( get_turn_info_for_endpoint<true, true>(range_p, range_q,
tp_model, inters, method_equal, out, tp_model, inters, method_equal, out,
umbrella_strategy.get_point_in_point_strategy()) ) umbrella_strategy) )
{ {
// do nothing // do nothing
} }
@ -279,7 +279,7 @@ struct get_turn_info_linear_areal
if ( get_turn_info_for_endpoint<true, true>( if ( get_turn_info_for_endpoint<true, true>(
range_p, range_q, range_p, range_q,
tp_model, inters, method_collinear, out, tp_model, inters, method_collinear, out,
umbrella_strategy.get_point_in_point_strategy()) ) umbrella_strategy) )
{ {
// do nothing // do nothing
} }
@ -359,13 +359,13 @@ struct get_turn_info_linear_areal
if ( range_p.is_first_segment() if ( range_p.is_first_segment()
&& equals::equals_point_point(range_p.at(0), tp.point, && 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; tp.operations[0].position = position_front;
} }
else if ( range_p.is_last_segment() else if ( range_p.is_last_segment()
&& equals::equals_point_point(range_p.at(1), tp.point, && 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; tp.operations[0].position = position_back;
} }
@ -392,10 +392,10 @@ struct get_turn_info_linear_areal
template <typename Operation, template <typename Operation,
typename IntersectionInfo, typename IntersectionInfo,
typename EqPPStrategy> typename Strategy>
static inline bool calculate_spike_operation(Operation & op, static inline bool calculate_spike_operation(Operation & op,
IntersectionInfo const& inters, IntersectionInfo const& inters,
EqPPStrategy const& strategy) Strategy const& strategy)
{ {
bool is_p_spike = ( op == operation_union || op == operation_intersection ) bool is_p_spike = ( op == operation_union || op == operation_intersection )
&& inters.is_spike_p(); && inters.is_spike_p();
@ -415,7 +415,7 @@ struct get_turn_info_linear_areal
// spike on the edge point // spike on the edge point
// if it's already known that the spike is going out this musn't be checked // if it's already known that the spike is going out this musn't be checked
if ( ! going_out 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(); int const pk_q2 = inters.sides().pk_wrt_q2();
going_in = pk_q1 < 0 && pk_q2 < 0; // Pk on the right of both 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 // spike on the edge point
// if it's already known that the spike is going in this musn't be checked // if it's already known that the spike is going in this musn't be checked
if ( ! going_in 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(); 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 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 TurnInfo,
typename IntersectionInfo, typename IntersectionInfo,
typename OutputIterator, typename OutputIterator,
typename EqPPStrategy> typename Strategy>
static inline bool get_turn_info_for_endpoint( static inline bool get_turn_info_for_endpoint(
UniqueSubRange1 const& range_p, UniqueSubRange1 const& range_p,
UniqueSubRange2 const& range_q, UniqueSubRange2 const& range_q,
@ -687,7 +687,7 @@ struct get_turn_info_linear_areal
IntersectionInfo const& inters, IntersectionInfo const& inters,
method_type /*method*/, method_type /*method*/,
OutputIterator out, OutputIterator out,
EqPPStrategy const& strategy) Strategy const& strategy)
{ {
namespace ov = overlay; namespace ov = overlay;
typedef ov::get_turn_info_for_endpoint<EnableFirst, EnableLast> get_info_e; typedef ov::get_turn_info_for_endpoint<EnableFirst, EnableLast> get_info_e;
@ -705,9 +705,6 @@ struct get_turn_info_linear_areal
return false; return false;
} }
typename IntersectionInfo::side_strategy_type const& sides
= inters.get_side_strategy();
linear_intersections intersections(range_p.at(0), linear_intersections intersections(range_p.at(0),
range_q.at(0), range_q.at(0),
inters.result(), inters.result(),
@ -738,6 +735,8 @@ struct get_turn_info_linear_areal
} }
else else
{ {
auto const sides = strategy.side();
// pi is the intersection point at qj or in the middle of q1 // pi is the intersection point at qj or in the middle of q1
// so consider segments // so consider segments
// 1. pi at qj: qi-qj-pj and qi-qj-qk // 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 ) 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 // pj is the intersection point at qj or in the middle of q1
// so consider segments // so consider segments
// 1. pj at qj: qi-qj-pi and qi-qj-qk // 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 // don't ignore anything for now
return false; return false;
} }
template <typename Point1, typename Point2, typename IntersectionStrategy>
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 }} // namespace detail::overlay

View File

@ -75,7 +75,7 @@ struct get_turn_info_linear_linear
get_turn_info_for_endpoint<true, true> get_turn_info_for_endpoint<true, true>
::apply(range_p, range_q, ::apply(range_p, range_q,
tp_model, inters, method_none, out, tp_model, inters, method_none, out,
umbrella_strategy.get_point_in_point_strategy()); umbrella_strategy);
break; break;
case 'd' : // disjoint: never do anything case 'd' : // disjoint: never do anything
@ -86,7 +86,7 @@ struct get_turn_info_linear_linear
if ( get_turn_info_for_endpoint<false, true> if ( get_turn_info_for_endpoint<false, true>
::apply(range_p, range_q, ::apply(range_p, range_q,
tp_model, inters, method_touch_interior, out, tp_model, inters, method_touch_interior, out,
umbrella_strategy.get_point_in_point_strategy()) ) umbrella_strategy) )
{ {
// do nothing // do nothing
} }
@ -110,7 +110,7 @@ struct get_turn_info_linear_linear
// Swap p/q // Swap p/q
policy::template apply<1>(range_q, range_p, tp, policy::template apply<1>(range_q, range_p, tp,
inters.i_info(), inters.d_info(), inters.i_info(), inters.d_info(),
inters.get_swapped_sides(), inters.swapped_sides(),
umbrella_strategy); umbrella_strategy);
} }
@ -146,7 +146,7 @@ struct get_turn_info_linear_linear
if ( get_turn_info_for_endpoint<false, true> if ( get_turn_info_for_endpoint<false, true>
::apply(range_p, range_q, ::apply(range_p, range_q,
tp_model, inters, method_touch, out, tp_model, inters, method_touch, out,
umbrella_strategy.get_point_in_point_strategy()) ) umbrella_strategy) )
{ {
// do nothing // do nothing
} }
@ -278,7 +278,7 @@ struct get_turn_info_linear_linear
if ( get_turn_info_for_endpoint<true, true> if ( get_turn_info_for_endpoint<true, true>
::apply(range_p, range_q, ::apply(range_p, range_q,
tp_model, inters, method_equal, out, tp_model, inters, method_equal, out,
umbrella_strategy.get_point_in_point_strategy()) ) umbrella_strategy) )
{ {
// do nothing // do nothing
} }
@ -333,7 +333,7 @@ struct get_turn_info_linear_linear
if ( get_turn_info_for_endpoint<true, true> if ( get_turn_info_for_endpoint<true, true>
::apply(range_p, range_q, ::apply(range_p, range_q,
tp_model, inters, method_collinear, out, tp_model, inters, method_collinear, out,
umbrella_strategy.get_point_in_point_strategy()) ) umbrella_strategy) )
{ {
// do nothing // do nothing
} }
@ -416,29 +416,26 @@ struct get_turn_info_linear_linear
// degenerate points // degenerate points
if ( BOOST_GEOMETRY_CONDITION(AssignPolicy::include_degenerate) ) 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()); only_convert::apply(tp, inters.i_info());
// if any, only one of those should be true // if any, only one of those should be true
if ( range_p.is_first_segment() 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; tp.operations[0].position = position_front;
} }
else if ( range_p.is_last_segment() 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; tp.operations[0].position = position_back;
} }
else if ( range_q.is_first_segment() 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; tp.operations[1].position = position_front;
} }
else if ( range_q.is_last_segment() 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; tp.operations[1].position = position_back;
} }

View File

@ -3,8 +3,8 @@
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. // Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2014-2017 Adam Wulkiewicz, Lodz, Poland. // Copyright (c) 2014-2017 Adam Wulkiewicz, Lodz, Poland.
// This file was modified by Oracle on 2014-2020. // This file was modified by Oracle on 2014-2021.
// Modifications copyright (c) 2014-2020 Oracle and/or its affiliates. // 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 Adam Wulkiewicz, on behalf of Oracle
@ -108,7 +108,7 @@ template
typename Section, typename Section,
typename Point, typename Point,
typename CircularIterator, typename CircularIterator,
typename IntersectionStrategy, typename Strategy,
typename RobustPolicy typename RobustPolicy
> >
struct unique_sub_range_from_section struct unique_sub_range_from_section
@ -118,6 +118,7 @@ struct unique_sub_range_from_section
unique_sub_range_from_section(Section const& section, signed_size_type index, unique_sub_range_from_section(Section const& section, signed_size_type index,
CircularIterator circular_iterator, CircularIterator circular_iterator,
Point const& previous, Point const& current, Point const& previous, Point const& current,
Strategy const& strategy,
RobustPolicy const& robust_policy) RobustPolicy const& robust_policy)
: m_section(section) : m_section(section)
, m_index(index) , m_index(index)
@ -125,9 +126,9 @@ struct unique_sub_range_from_section
, m_current_point(current) , m_current_point(current)
, m_circular_iterator(circular_iterator) , m_circular_iterator(circular_iterator)
, m_point_retrieved(false) , m_point_retrieved(false)
, m_strategy(strategy)
, m_robust_policy(robust_policy) , m_robust_policy(robust_policy)
{ {}
}
inline bool is_first_segment() const 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 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<Point, RobustPolicy>::type robust_point_type; typedef typename robust_point_type<Point, RobustPolicy>::type robust_point_type;
robust_point_type current_robust_point; robust_point_type current_robust_point;
robust_point_type next_robust_point; robust_point_type next_robust_point;
@ -187,11 +187,8 @@ private :
// So advance to the "non duplicate next" // So advance to the "non duplicate next"
// (the check is defensive, to avoid endless loops) // (the check is defensive, to avoid endless loops)
std::size_t check = 0; std::size_t check = 0;
while(! detail::disjoint::disjoint_point_point while (! detail::disjoint::disjoint_point_point(
( current_robust_point, next_robust_point, m_strategy)
current_robust_point, next_robust_point,
disjoint_strategy_type()
)
&& check++ < m_section.range_count) && check++ < m_section.range_count)
{ {
circular_iterator++; circular_iterator++;
@ -206,6 +203,7 @@ private :
mutable CircularIterator m_circular_iterator; mutable CircularIterator m_circular_iterator;
mutable Point m_point; mutable Point m_point;
mutable bool m_point_retrieved; mutable bool m_point_retrieved;
Strategy m_strategy;
RobustPolicy m_robust_policy; RobustPolicy m_robust_policy;
}; };
@ -276,12 +274,12 @@ class get_turns_in_sections
public : public :
// Returns true if terminated, false if interrupted // Returns true if terminated, false if interrupted
template <typename IntersectionStrategy, typename RobustPolicy, typename Turns, typename InterruptPolicy> template <typename Strategy, typename RobustPolicy, typename Turns, typename InterruptPolicy>
static inline bool apply( static inline bool apply(
int source_id1, Geometry1 const& geometry1, Section1 const& sec1, int source_id1, Geometry1 const& geometry1, Section1 const& sec1,
int source_id2, Geometry2 const& geometry2, Section2 const& sec2, int source_id2, Geometry2 const& geometry2, Section2 const& sec2,
bool skip_larger, bool skip_adjacent, bool skip_larger, bool skip_adjacent,
IntersectionStrategy const& intersection_strategy, Strategy const& strategy,
RobustPolicy const& robust_policy, RobustPolicy const& robust_policy,
Turns& turns, Turns& turns,
InterruptPolicy& interrupt_policy) InterruptPolicy& interrupt_policy)
@ -337,11 +335,11 @@ public :
unique_sub_range_from_section unique_sub_range_from_section
< <
areal1, Section1, point1_type, circular1_iterator, areal1, Section1, point1_type, circular1_iterator,
IntersectionStrategy, RobustPolicy Strategy, RobustPolicy
> unique_sub_range1(sec1, index1, > unique_sub_range1(sec1, index1,
circular1_iterator(begin_range_1, end_range_1, next1, true), circular1_iterator(begin_range_1, end_range_1, next1, true),
*prev1, *it1, *prev1, *it1,
robust_policy); strategy, robust_policy);
signed_size_type index2 = sec2.begin_index; signed_size_type index2 = sec2.begin_index;
signed_size_type ndi2 = sec2.non_duplicate_index; signed_size_type ndi2 = sec2.non_duplicate_index;
@ -390,11 +388,11 @@ public :
unique_sub_range_from_section unique_sub_range_from_section
< <
areal2, Section2, point2_type, circular2_iterator, areal2, Section2, point2_type, circular2_iterator,
IntersectionStrategy, RobustPolicy Strategy, RobustPolicy
> unique_sub_range2(sec2, index2, > unique_sub_range2(sec2, index2,
circular2_iterator(begin_range_2, end_range_2, next2), circular2_iterator(begin_range_2, end_range_2, next2),
*prev2, *it2, *prev2, *it2,
robust_policy); strategy, robust_policy);
typedef typename boost::range_value<Turns>::type turn_info; typedef typename boost::range_value<Turns>::type turn_info;
@ -409,7 +407,7 @@ public :
std::size_t const size_before = boost::size(turns); std::size_t const size_before = boost::size(turns);
TurnPolicy::apply(unique_sub_range1, unique_sub_range2, TurnPolicy::apply(unique_sub_range1, unique_sub_range2,
ti, intersection_strategy, robust_policy, ti, strategy, robust_policy,
std::back_inserter(turns)); std::back_inserter(turns));
if (InterruptPolicy::enabled) if (InterruptPolicy::enabled)
@ -464,7 +462,7 @@ template
typename Geometry1, typename Geometry2, typename Geometry1, typename Geometry2,
bool Reverse1, bool Reverse2, bool Reverse1, bool Reverse2,
typename TurnPolicy, typename TurnPolicy,
typename IntersectionStrategy, typename Strategy,
typename RobustPolicy, typename RobustPolicy,
typename Turns, typename Turns,
typename InterruptPolicy typename InterruptPolicy
@ -475,20 +473,20 @@ struct section_visitor
Geometry1 const& m_geometry1; Geometry1 const& m_geometry1;
int m_source_id2; int m_source_id2;
Geometry2 const& m_geometry2; Geometry2 const& m_geometry2;
IntersectionStrategy const& m_intersection_strategy; Strategy const& m_strategy;
RobustPolicy const& m_rescale_policy; RobustPolicy const& m_rescale_policy;
Turns& m_turns; Turns& m_turns;
InterruptPolicy& m_interrupt_policy; InterruptPolicy& m_interrupt_policy;
section_visitor(int id1, Geometry1 const& g1, section_visitor(int id1, Geometry1 const& g1,
int id2, Geometry2 const& g2, int id2, Geometry2 const& g2,
IntersectionStrategy const& intersection_strategy, Strategy const& strategy,
RobustPolicy const& robust_policy, RobustPolicy const& robust_policy,
Turns& turns, Turns& turns,
InterruptPolicy& ip) InterruptPolicy& ip)
: m_source_id1(id1), m_geometry1(g1) : m_source_id1(id1), m_geometry1(g1)
, m_source_id2(id2), m_geometry2(g2) , m_source_id2(id2), m_geometry2(g2)
, m_intersection_strategy(intersection_strategy) , m_strategy(strategy)
, m_rescale_policy(robust_policy) , m_rescale_policy(robust_policy)
, m_turns(turns) , m_turns(turns)
, m_interrupt_policy(ip) , m_interrupt_policy(ip)
@ -499,7 +497,7 @@ struct section_visitor
{ {
if (! detail::disjoint::disjoint_box_box(sec1.bounding_box, if (! detail::disjoint::disjoint_box_box(sec1.bounding_box,
sec2.bounding_box, sec2.bounding_box,
m_intersection_strategy.get_disjoint_box_box_strategy())) m_strategy) )
{ {
// false if interrupted // false if interrupted
return get_turns_in_sections return get_turns_in_sections
@ -512,7 +510,7 @@ struct section_visitor
>::apply(m_source_id1, m_geometry1, sec1, >::apply(m_source_id1, m_geometry1, sec1,
m_source_id2, m_geometry2, sec2, m_source_id2, m_geometry2, sec2,
false, false, false, false,
m_intersection_strategy, m_strategy,
m_rescale_policy, m_rescale_policy,
m_turns, m_interrupt_policy); m_turns, m_interrupt_policy);
} }
@ -531,11 +529,11 @@ class get_turns_generic
{ {
public: public:
template <typename IntersectionStrategy, typename RobustPolicy, typename Turns, typename InterruptPolicy> template <typename Strategy, typename RobustPolicy, typename Turns, typename InterruptPolicy>
static inline void apply( static inline void apply(
int source_id1, Geometry1 const& geometry1, int source_id1, Geometry1 const& geometry1,
int source_id2, Geometry2 const& geometry2, int source_id2, Geometry2 const& geometry2,
IntersectionStrategy const& intersection_strategy, Strategy const& strategy,
RobustPolicy const& robust_policy, RobustPolicy const& robust_policy,
Turns& turns, Turns& turns,
InterruptPolicy& interrupt_policy) InterruptPolicy& interrupt_policy)
@ -556,15 +554,10 @@ public:
sections_type sec1, sec2; sections_type sec1, sec2;
typedef std::integer_sequence<std::size_t, 0, 1> dimensions; typedef std::integer_sequence<std::size_t, 0, 1> 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<Reverse1, dimensions>(geometry1, robust_policy, geometry::sectionalize<Reverse1, dimensions>(geometry1, robust_policy,
sec1, envelope_strategy, expand_strategy, 0); sec1, strategy, 0);
geometry::sectionalize<Reverse2, dimensions>(geometry2, robust_policy, geometry::sectionalize<Reverse2, dimensions>(geometry2, robust_policy,
sec2, envelope_strategy, expand_strategy, 1); sec2, strategy, 1);
// ... and then partition them, intersecting overlapping sections in visitor method // ... and then partition them, intersecting overlapping sections in visitor method
section_visitor section_visitor
@ -572,27 +565,17 @@ public:
Geometry1, Geometry2, Geometry1, Geometry2,
Reverse1, Reverse2, Reverse1, Reverse2,
TurnPolicy, TurnPolicy,
IntersectionStrategy, RobustPolicy, Strategy, RobustPolicy,
Turns, InterruptPolicy Turns, InterruptPolicy
> visitor(source_id1, geometry1, source_id2, geometry2, > visitor(source_id1, geometry1, source_id2, geometry2,
intersection_strategy, robust_policy, strategy, robust_policy, turns, interrupt_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;
geometry::partition geometry::partition
< <
box_type box_type
>::apply(sec1, sec2, visitor, >::apply(sec1, sec2, visitor,
get_section_box_type(), detail::section::get_section_box<Strategy>(strategy),
overlaps_section_box_type()); detail::section::overlaps_section_box<Strategy>(strategy));
} }
}; };
@ -1094,10 +1077,10 @@ template
> >
struct get_turns_reversed struct get_turns_reversed
{ {
template <typename IntersectionStrategy, typename RobustPolicy, typename Turns, typename InterruptPolicy> template <typename Strategy, typename RobustPolicy, typename Turns, typename InterruptPolicy>
static inline void apply(int source_id1, Geometry1 const& g1, static inline void apply(int source_id1, Geometry1 const& g1,
int source_id2, Geometry2 const& g2, int source_id2, Geometry2 const& g2,
IntersectionStrategy const& intersection_strategy, Strategy const& strategy,
RobustPolicy const& robust_policy, RobustPolicy const& robust_policy,
Turns& turns, Turns& turns,
InterruptPolicy& interrupt_policy) InterruptPolicy& interrupt_policy)
@ -1109,7 +1092,7 @@ struct get_turns_reversed
Reverse2, Reverse1, Reverse2, Reverse1,
TurnPolicy TurnPolicy
>::apply(source_id2, g2, source_id1, g1, >::apply(source_id2, g2, source_id1, g1,
intersection_strategy, robust_policy, strategy, robust_policy,
turns, interrupt_policy); turns, interrupt_policy);
} }
}; };
@ -1140,14 +1123,14 @@ template
typename AssignPolicy, typename AssignPolicy,
typename Geometry1, typename Geometry1,
typename Geometry2, typename Geometry2,
typename IntersectionStrategy, typename Strategy,
typename RobustPolicy, typename RobustPolicy,
typename Turns, typename Turns,
typename InterruptPolicy typename InterruptPolicy
> >
inline void get_turns(Geometry1 const& geometry1, inline void get_turns(Geometry1 const& geometry1,
Geometry2 const& geometry2, Geometry2 const& geometry2,
IntersectionStrategy const& intersection_strategy, Strategy const& strategy,
RobustPolicy const& robust_policy, RobustPolicy const& robust_policy,
Turns& turns, Turns& turns,
InterruptPolicy& interrupt_policy) InterruptPolicy& interrupt_policy)
@ -1178,7 +1161,7 @@ inline void get_turns(Geometry1 const& geometry1,
> >
>::apply(0, geometry1, >::apply(0, geometry1,
1, geometry2, 1, geometry2,
intersection_strategy, strategy,
robust_policy, robust_policy,
turns, interrupt_policy); turns, interrupt_policy);
} }

View File

@ -32,48 +32,6 @@ namespace boost { namespace geometry
namespace detail { namespace overlay namespace detail { namespace overlay
{ {
template
<
typename Point, typename Geometry,
typename Tag2 = typename geometry::tag<Geometry>::type
>
struct check_within_strategy
{
template <typename Strategy>
static inline typename Strategy::template point_in_geometry_strategy<Point, Geometry>::type
within(Strategy const& strategy)
{
return strategy.template get_point_in_geometry_strategy<Point, Geometry>();
}
template <typename Strategy>
static inline typename Strategy::template point_in_geometry_strategy<Point, Geometry>::type
covered_by(Strategy const& strategy)
{
return strategy.template get_point_in_geometry_strategy<Point, Geometry>();
}
};
template <typename Point, typename Geometry>
struct check_within_strategy<Point, Geometry, box_tag>
{
template <typename Strategy>
static inline typename Strategy::within_point_box_strategy_type
within(Strategy const& )
{
return typename Strategy::within_point_box_strategy_type();
}
template <typename Strategy>
static inline typename Strategy::covered_by_point_box_strategy_type
covered_by(Strategy const&)
{
return typename Strategy::covered_by_point_box_strategy_type();
}
};
template <overlay_type OverlayType> template <overlay_type OverlayType>
struct check_within struct check_within
{ {
@ -86,14 +44,10 @@ struct check_within
bool apply(Turn const& turn, Geometry0 const& geometry0, bool apply(Turn const& turn, Geometry0 const& geometry0,
Geometry1 const& geometry1, UmbrellaStrategy const& strategy) 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 // Operations 0 and 1 have the same source index in self-turns
return turn.operations[0].seg_id.source_index == 0 return turn.operations[0].seg_id.source_index == 0
? geometry::within(turn.point, geometry1, ? geometry::within(turn.point, geometry1, strategy)
check_within_strategy<point_type, Geometry1>::within(strategy)) : geometry::within(turn.point, geometry0, strategy);
: geometry::within(turn.point, geometry0,
check_within_strategy<point_type, Geometry0>::within(strategy));
} }
}; };
@ -110,15 +64,11 @@ struct check_within<overlay_difference>
bool apply(Turn const& turn, Geometry0 const& geometry0, bool apply(Turn const& turn, Geometry0 const& geometry0,
Geometry1 const& geometry1, UmbrellaStrategy const& strategy) Geometry1 const& geometry1, UmbrellaStrategy const& strategy)
{ {
typedef typename Turn::point_type point_type;
// difference = intersection(a, reverse(b)) // difference = intersection(a, reverse(b))
// therefore we should reverse the meaning of within for geometry1 // therefore we should reverse the meaning of within for geometry1
return turn.operations[0].seg_id.source_index == 0 return turn.operations[0].seg_id.source_index == 0
? ! geometry::covered_by(turn.point, geometry1, ? ! geometry::covered_by(turn.point, geometry1, strategy)
check_within_strategy<point_type, Geometry1>::covered_by(strategy)) : geometry::within(turn.point, geometry0, strategy);
: geometry::within(turn.point, geometry0,
check_within_strategy<point_type, Geometry0>::within(strategy));
} }
}; };

View File

@ -49,6 +49,10 @@
#include <boost/geometry/policies/robustness/segment_ratio_type.hpp> #include <boost/geometry/policies/robustness/segment_ratio_type.hpp>
#include <boost/geometry/policies/robustness/get_rescale_policy.hpp> #include <boost/geometry/policies/robustness/get_rescale_policy.hpp>
#include <boost/geometry/strategies/default_strategy.hpp>
#include <boost/geometry/strategies/detail.hpp>
#include <boost/geometry/strategies/relate/services.hpp>
#include <boost/geometry/views/segment_view.hpp> #include <boost/geometry/views/segment_view.hpp>
#include <boost/geometry/views/detail/boundary_view.hpp> #include <boost/geometry/views/detail/boundary_view.hpp>
@ -100,7 +104,7 @@ struct intersection_segment_segment_point
detail::segment_as_subrange<Segment2> sub_range2(segment2); detail::segment_as_subrange<Segment2> sub_range2(segment2);
intersection_return_type 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++) for (std::size_t i = 0; i < is.count; i++)
{ {
@ -1535,9 +1539,9 @@ inline OutputIterator intersection_insert(Geometry1 const& geometry1,
concepts::check<Geometry1 const>(); concepts::check<Geometry1 const>();
concepts::check<Geometry2 const>(); concepts::check<Geometry2 const>();
typedef typename strategy::intersection::services::default_strategy typedef typename strategies::relate::services::default_strategy
< <
typename cs_tag<GeometryOut>::type Geometry1, Geometry2
>::type strategy_type; >::type strategy_type;
return intersection_insert<GeometryOut>(geometry1, geometry2, out, return intersection_insert<GeometryOut>(geometry1, geometry2, out,

View File

@ -147,13 +147,13 @@ protected:
typename Turns, typename Turns,
typename LinearGeometry1, typename LinearGeometry1,
typename LinearGeometry2, typename LinearGeometry2,
typename IntersectionStrategy, typename Strategy,
typename RobustPolicy typename RobustPolicy
> >
static inline void compute_turns(Turns& turns, static inline void compute_turns(Turns& turns,
LinearGeometry1 const& linear1, LinearGeometry1 const& linear1,
LinearGeometry2 const& linear2, LinearGeometry2 const& linear2,
IntersectionStrategy const& strategy, Strategy const& strategy,
RobustPolicy const& robust_policy) RobustPolicy const& robust_policy)
{ {
turns.clear(); turns.clear();
@ -182,14 +182,14 @@ protected:
typename LinearGeometry1, typename LinearGeometry1,
typename LinearGeometry2, typename LinearGeometry2,
typename OutputIterator, typename OutputIterator,
typename IntersectionStrategy typename Strategy
> >
static inline OutputIterator static inline OutputIterator
sort_and_follow_turns(Turns& turns, sort_and_follow_turns(Turns& turns,
LinearGeometry1 const& linear1, LinearGeometry1 const& linear1,
LinearGeometry2 const& linear2, LinearGeometry2 const& linear2,
OutputIterator oit, OutputIterator oit,
IntersectionStrategy const& strategy) Strategy const& strategy)
{ {
// remove turns that have no added value // remove turns that have no added value
turns::filter_continue_turns turns::filter_continue_turns
@ -217,7 +217,7 @@ protected:
FollowIsolatedPoints, FollowIsolatedPoints,
!EnableFilterContinueTurns || OverlayType == overlay_intersection !EnableFilterContinueTurns || OverlayType == overlay_intersection
>::apply(linear1, linear2, boost::begin(turns), boost::end(turns), >::apply(linear1, linear2, boost::begin(turns), boost::end(turns),
oit, strategy.get_side_strategy()); oit, strategy);
} }
public: public:

View File

@ -197,20 +197,13 @@ inline OutputIterator return_if_one_input_is_empty(Geometry1 const& geometry1,
Geometry2 const& geometry2, Geometry2 const& geometry2,
OutputIterator out, Strategy const& strategy) OutputIterator out, Strategy const& strategy)
{ {
typedef std::deque typedef typename geometry::ring_type<GeometryOut>::type ring_type;
< typedef std::deque<ring_type> ring_container_type;
typename geometry::ring_type<GeometryOut>::type
> ring_container_type;
typedef typename geometry::point_type<Geometry1>::type point_type1;
typedef ring_properties typedef ring_properties
< <
point_type1, typename geometry::point_type<ring_type>::type,
typename Strategy::template area_strategy typename geometry::area_result<ring_type, Strategy>::type
<
point_type1
>::type::template result_type<point_type1>::type
> properties; > properties;
// Silence warning C4127: conditional expression is constant // Silence warning C4127: conditional expression is constant
@ -239,8 +232,7 @@ inline OutputIterator return_if_one_input_is_empty(Geometry1 const& geometry1,
select_rings<OverlayType>(geometry1, geometry2, empty, all_of_one_of_them, strategy); select_rings<OverlayType>(geometry1, geometry2, empty, all_of_one_of_them, strategy);
ring_container_type rings; ring_container_type rings;
assign_parents<OverlayType>(geometry1, geometry2, rings, all_of_one_of_them, strategy); assign_parents<OverlayType>(geometry1, geometry2, rings, all_of_one_of_them, strategy);
return add_rings<GeometryOut>(all_of_one_of_them, geometry1, geometry2, rings, out, return add_rings<GeometryOut>(all_of_one_of_them, geometry1, geometry2, rings, out, strategy);
strategy.template get_area_strategy<point_type1>());
} }
@ -285,10 +277,8 @@ struct overlay
> turn_info; > turn_info;
typedef std::deque<turn_info> turn_container_type; typedef std::deque<turn_info> turn_container_type;
typedef std::deque typedef typename geometry::ring_type<GeometryOut>::type ring_type;
< typedef std::deque<ring_type> ring_container_type;
typename geometry::ring_type<GeometryOut>::type
> ring_container_type;
// Define the clusters, mapping cluster_id -> turns // Define the clusters, mapping cluster_id -> turns
typedef std::map typedef std::map
@ -365,12 +355,10 @@ std::cout << "traverse" << std::endl;
get_ring_turn_info<OverlayType>(turn_info_per_ring, turns, clusters); get_ring_turn_info<OverlayType>(turn_info_per_ring, turns, clusters);
typedef typename Strategy::template area_strategy<point_type>::type area_strategy_type;
typedef ring_properties typedef ring_properties
< <
point_type, point_type,
typename area_strategy_type::template result_type<point_type>::type typename geometry::area_result<ring_type, Strategy>::type
> properties; > properties;
// Select all rings which are NOT touched by any intersection point // Select all rings which are NOT touched by any intersection point
@ -379,7 +367,6 @@ std::cout << "traverse" << std::endl;
selected_ring_properties, strategy); selected_ring_properties, strategy);
// Add rings created during traversal // Add rings created during traversal
area_strategy_type const area_strategy = strategy.template get_area_strategy<point_type>();
{ {
ring_identifier id(2, 0, -1); ring_identifier id(2, 0, -1);
for (typename boost::range_iterator<ring_container_type>::type for (typename boost::range_iterator<ring_container_type>::type
@ -387,7 +374,7 @@ std::cout << "traverse" << std::endl;
it != boost::end(rings); it != boost::end(rings);
++it) ++it)
{ {
selected_ring_properties[id] = properties(*it, area_strategy); selected_ring_properties[id] = properties(*it, strategy);
selected_ring_properties[id].reversed = ReverseOut; selected_ring_properties[id].reversed = ReverseOut;
id.multi_index++; 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 // 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. // it can be returned or an exception can be thrown.
return add_rings<GeometryOut>(selected_ring_properties, geometry1, geometry2, rings, out, return add_rings<GeometryOut>(selected_ring_properties, geometry1, geometry2, rings, out,
area_strategy, strategy,
OverlayType == overlay_union ? OverlayType == overlay_union ?
#if defined(BOOST_GEOMETRY_UNION_THROW_INVALID_OUTPUT_EXCEPTION) #if defined(BOOST_GEOMETRY_UNION_THROW_INVALID_OUTPUT_EXCEPTION)
add_rings_throw_if_reversed add_rings_throw_if_reversed

View File

@ -63,44 +63,68 @@ template
class multipoint_multipolygon_point class multipoint_multipolygon_point
{ {
private: private:
template <typename ExpandPointStrategy> template <typename Strategy>
struct expand_box_point struct expand_box_point
{ {
explicit expand_box_point(Strategy const& strategy)
: m_strategy(strategy)
{}
template <typename Box, typename Point> template <typename Box, typename Point>
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 <typename ExpandBoxStrategy> template <typename Strategy>
struct expand_box_boxpair struct expand_box_boxpair
{ {
explicit expand_box_boxpair(Strategy const& strategy)
: m_strategy(strategy)
{}
template <typename Box1, typename Box2, typename SizeT> template <typename Box1, typename Box2, typename SizeT>
static inline void apply(Box1& total, std::pair<Box2, SizeT> const& box_pair) inline void apply(Box1& total, std::pair<Box2, SizeT> const& box_pair) const
{ {
geometry::expand(total, box_pair.first, ExpandBoxStrategy()); geometry::expand(total, box_pair.first, m_strategy);
} }
Strategy const& m_strategy;
}; };
template <typename DisjointPointBoxStrategy> template <typename Strategy>
struct overlaps_box_point struct overlaps_box_point
{ {
explicit overlaps_box_point(Strategy const& strategy)
: m_strategy(strategy)
{}
template <typename Box, typename Point> template <typename Box, typename Point>
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 <typename DisjointBoxBoxStrategy> template <typename Strategy>
struct overlaps_box_boxpair struct overlaps_box_boxpair
{ {
explicit overlaps_box_boxpair(Strategy const& strategy)
: m_strategy(strategy)
{}
template <typename Box1, typename Box2, typename SizeT> template <typename Box1, typename Box2, typename SizeT>
static inline bool apply(Box1 const& box, std::pair<Box2, SizeT> const& box_pair) inline bool apply(Box1 const& box, std::pair<Box2, SizeT> 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 <typename OutputIterator, typename Strategy> template <typename OutputIterator, typename Strategy>
@ -137,10 +161,10 @@ private:
Strategy const& m_strategy; Strategy const& m_strategy;
}; };
template <typename Iterator, typename Box, typename SizeT, typename EnvelopeStrategy> template <typename Iterator, typename Box, typename SizeT, typename Strategy>
static inline void fill_box_pairs(Iterator first, Iterator last, static inline void fill_box_pairs(Iterator first, Iterator last,
std::vector<std::pair<Box, SizeT> > & box_pairs, std::vector<std::pair<Box, SizeT> > & box_pairs,
EnvelopeStrategy const& strategy) Strategy const& strategy)
{ {
SizeT index = 0; SizeT index = 0;
for (; first != last; ++first, ++index) for (; first != last; ++first, ++index)
@ -172,29 +196,16 @@ private:
fill_box_pairs(boost::begin(multipolygon), fill_box_pairs(boost::begin(multipolygon),
boost::end(multipolygon), boost::end(multipolygon),
box_pairs, box_pairs, strategy);
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<box_type>(), std::declval<box_type>()));
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;
geometry::partition geometry::partition
< <
box_type box_type
>::apply(multipoint, box_pairs, item_visitor, >::apply(multipoint, box_pairs, item_visitor,
expand_box_point<expand_point_strategy_type>(), expand_box_point<Strategy>(strategy),
overlaps_box_point<disjoint_point_box_strategy_type>(), overlaps_box_point<Strategy>(strategy),
expand_box_boxpair<expand_box_strategy_type>(), expand_box_boxpair<Strategy>(strategy),
overlaps_box_boxpair<disjoint_box_box_strategy_type>()); overlaps_box_boxpair<Strategy>(strategy));
return oit; return oit;
} }

View File

@ -127,20 +127,26 @@ class multipoint_linear_point
{ {
private: private:
// structs for partition -- start // structs for partition -- start
template <typename ExpandPointStrategy> template <typename Strategy>
struct expand_box_point struct expand_box_point
{ {
expand_box_point(Strategy const& strategy)
: m_strategy(strategy)
{}
template <typename Box, typename Point> template <typename Box, typename Point>
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 <typename EnvelopeStrategy> template <typename Strategy>
struct expand_box_segment struct expand_box_segment
{ {
explicit expand_box_segment(EnvelopeStrategy const& strategy) explicit expand_box_segment(Strategy const& strategy)
: m_strategy(strategy) : m_strategy(strategy)
{} {}
@ -149,31 +155,32 @@ private:
{ {
geometry::expand(total, geometry::expand(total,
geometry::return_envelope<Box>(segment, m_strategy), geometry::return_envelope<Box>(segment, m_strategy),
// TEMP - envelope umbrella strategy also contains m_strategy);
// expand strategies
strategies::envelope::services::strategy_converter
<
EnvelopeStrategy
>::get(m_strategy));
} }
EnvelopeStrategy const& m_strategy; Strategy const& m_strategy;
}; };
template <typename DisjointPointBoxStrategy> template <typename Strategy>
struct overlaps_box_point struct overlaps_box_point
{ {
explicit overlaps_box_point(Strategy const& strategy)
: m_strategy(strategy)
{}
template <typename Box, typename Point> template <typename Box, typename Point>
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 <typename DisjointStrategy> template <typename Strategy>
struct overlaps_box_segment struct overlaps_box_segment
{ {
explicit overlaps_box_segment(DisjointStrategy const& strategy) explicit overlaps_box_segment(Strategy const& strategy)
: m_strategy(strategy) : m_strategy(strategy)
{} {}
@ -183,7 +190,7 @@ private:
return ! geometry::disjoint(segment, box, m_strategy); return ! geometry::disjoint(segment, box, m_strategy);
} }
DisjointStrategy const& m_strategy; Strategy const& m_strategy;
}; };
template <typename OutputIterator, typename Strategy> template <typename OutputIterator, typename Strategy>
@ -218,7 +225,7 @@ private:
typedef geometry::segment_iterator<Linear const> const_iterator; typedef geometry::segment_iterator<Linear const> const_iterator;
typedef const_iterator iterator; typedef const_iterator iterator;
segment_range(Linear const& linear) explicit segment_range(Linear const& linear)
: m_linear(linear) : m_linear(linear)
{} {}
@ -244,11 +251,6 @@ private:
{ {
item_visitor_type<OutputIterator, Strategy> item_visitor(oit, strategy); item_visitor_type<OutputIterator, Strategy> 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 // TODO: disjoint Segment/Box may be called in partition multiple times
// possibly for non-cartesian segments which could be slow. We should consider // possibly for non-cartesian segments which could be slow. We should consider
// passing a range of bounding boxes of segments after calculating them once. // passing a range of bounding boxes of segments after calculating them once.
@ -261,10 +263,10 @@ private:
typename boost::range_value<MultiPoint>::type typename boost::range_value<MultiPoint>::type
> >
>::apply(multipoint, segment_range(linear), item_visitor, >::apply(multipoint, segment_range(linear), item_visitor,
expand_box_point<expand_point_strategy_type>(), expand_box_point<Strategy>(strategy),
overlaps_box_point<disjoint_point_box_strategy_type>(), overlaps_box_point<Strategy>(strategy),
expand_box_segment<envelope_strategy_type>(strategy.get_envelope_strategy()), expand_box_segment<Strategy>(strategy),
overlaps_box_segment<disjoint_strategy_type>(strategy.get_disjoint_strategy())); overlaps_box_segment<Strategy>(strategy));
return oit; return oit;
} }

View File

@ -98,9 +98,9 @@ struct point_in_geometry_helper<Box, box_tag>
{ {
template <typename Point, typename Strategy> template <typename Point, typename Strategy>
static inline int apply(Point const& point, Box const& box, 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; ++it;
} }
typename Strategy::template point_in_geometry_strategy
<
Geometry1, Geometry2
>::type const in_strategy
= strategy.template get_point_in_geometry_strategy<Geometry1, Geometry2>();
for ( ; it != end; ++it) for ( ; it != end; ++it)
{ {
result = point_in_geometry_helper<Geometry2>::apply(*it, geometry2, in_strategy); result = point_in_geometry_helper<Geometry2>::apply(*it, geometry2, strategy);
if (result != 0) if (result != 0)
{ {
return result; return result;
@ -153,8 +147,7 @@ inline int range_in_geometry(Point1 const& first_point1,
Strategy const& strategy) Strategy const& strategy)
{ {
// check a point on border of geometry1 first // check a point on border of geometry1 first
int result = point_in_geometry_helper<Geometry2>::apply(first_point1, geometry2, int result = point_in_geometry_helper<Geometry2>::apply(first_point1, geometry2, strategy);
strategy.template get_point_in_geometry_strategy<Point1, Geometry2>());
if (result == 0) if (result == 0)
{ {
// if a point is on boundary of geometry2 // if a point is on boundary of geometry2

View File

@ -56,8 +56,8 @@ struct ring_properties
, parent_area(-1) , parent_area(-1)
{} {}
template <typename RingOrBox, typename AreaStrategy> template <typename RingOrBox, typename Strategy>
inline ring_properties(RingOrBox const& ring_or_box, AreaStrategy const& strategy) inline ring_properties(RingOrBox const& ring_or_box, Strategy const& strategy)
: reversed(false) : reversed(false)
, discarded(false) , discarded(false)
, parent_area(-1) , parent_area(-1)

View File

@ -62,18 +62,18 @@ namespace dispatch
template <typename Box> template <typename Box>
struct select_rings<box_tag, Box> struct select_rings<box_tag, Box>
{ {
template <typename Geometry, typename RingPropertyMap, typename AreaStrategy> template <typename Geometry, typename RingPropertyMap, typename Strategy>
static inline void apply(Box const& box, Geometry const& , static inline void apply(Box const& box, Geometry const& ,
ring_identifier const& id, RingPropertyMap& ring_properties, ring_identifier const& id, RingPropertyMap& ring_properties,
AreaStrategy const& strategy) Strategy const& strategy)
{ {
ring_properties[id] = typename RingPropertyMap::mapped_type(box, strategy); ring_properties[id] = typename RingPropertyMap::mapped_type(box, strategy);
} }
template <typename RingPropertyMap, typename AreaStrategy> template <typename RingPropertyMap, typename Strategy>
static inline void apply(Box const& box, static inline void apply(Box const& box,
ring_identifier const& id, RingPropertyMap& ring_properties, ring_identifier const& id, RingPropertyMap& ring_properties,
AreaStrategy const& strategy) Strategy const& strategy)
{ {
ring_properties[id] = typename RingPropertyMap::mapped_type(box, strategy); ring_properties[id] = typename RingPropertyMap::mapped_type(box, strategy);
} }
@ -82,10 +82,10 @@ namespace dispatch
template <typename Ring> template <typename Ring>
struct select_rings<ring_tag, Ring> struct select_rings<ring_tag, Ring>
{ {
template <typename Geometry, typename RingPropertyMap, typename AreaStrategy> template <typename Geometry, typename RingPropertyMap, typename Strategy>
static inline void apply(Ring const& ring, Geometry const& , static inline void apply(Ring const& ring, Geometry const& ,
ring_identifier const& id, RingPropertyMap& ring_properties, ring_identifier const& id, RingPropertyMap& ring_properties,
AreaStrategy const& strategy) Strategy const& strategy)
{ {
if (boost::size(ring) > 0) if (boost::size(ring) > 0)
{ {
@ -93,10 +93,10 @@ namespace dispatch
} }
} }
template <typename RingPropertyMap, typename AreaStrategy> template <typename RingPropertyMap, typename Strategy>
static inline void apply(Ring const& ring, static inline void apply(Ring const& ring,
ring_identifier const& id, RingPropertyMap& ring_properties, ring_identifier const& id, RingPropertyMap& ring_properties,
AreaStrategy const& strategy) Strategy const& strategy)
{ {
if (boost::size(ring) > 0) if (boost::size(ring) > 0)
{ {
@ -109,10 +109,10 @@ namespace dispatch
template <typename Polygon> template <typename Polygon>
struct select_rings<polygon_tag, Polygon> struct select_rings<polygon_tag, Polygon>
{ {
template <typename Geometry, typename RingPropertyMap, typename AreaStrategy> template <typename Geometry, typename RingPropertyMap, typename Strategy>
static inline void apply(Polygon const& polygon, Geometry const& geometry, static inline void apply(Polygon const& polygon, Geometry const& geometry,
ring_identifier id, RingPropertyMap& ring_properties, ring_identifier id, RingPropertyMap& ring_properties,
AreaStrategy const& strategy) Strategy const& strategy)
{ {
typedef typename geometry::ring_type<Polygon>::type ring_type; typedef typename geometry::ring_type<Polygon>::type ring_type;
typedef select_rings<ring_tag, ring_type> per_ring; typedef select_rings<ring_tag, ring_type> per_ring;
@ -129,10 +129,10 @@ namespace dispatch
} }
} }
template <typename RingPropertyMap, typename AreaStrategy> template <typename RingPropertyMap, typename Strategy>
static inline void apply(Polygon const& polygon, static inline void apply(Polygon const& polygon,
ring_identifier id, RingPropertyMap& ring_properties, ring_identifier id, RingPropertyMap& ring_properties,
AreaStrategy const& strategy) Strategy const& strategy)
{ {
typedef typename geometry::ring_type<Polygon>::type ring_type; typedef typename geometry::ring_type<Polygon>::type ring_type;
typedef select_rings<ring_tag, ring_type> per_ring; typedef select_rings<ring_tag, ring_type> per_ring;
@ -153,10 +153,10 @@ namespace dispatch
template <typename Multi> template <typename Multi>
struct select_rings<multi_polygon_tag, Multi> struct select_rings<multi_polygon_tag, Multi>
{ {
template <typename Geometry, typename RingPropertyMap, typename AreaStrategy> template <typename Geometry, typename RingPropertyMap, typename Strategy>
static inline void apply(Multi const& multi, Geometry const& geometry, static inline void apply(Multi const& multi, Geometry const& geometry,
ring_identifier id, RingPropertyMap& ring_properties, ring_identifier id, RingPropertyMap& ring_properties,
AreaStrategy const& strategy) Strategy const& strategy)
{ {
typedef typename boost::range_iterator typedef typename boost::range_iterator
< <
@ -321,16 +321,14 @@ inline void select_rings(Geometry1 const& geometry1, Geometry2 const& geometry2,
{ {
typedef typename geometry::tag<Geometry1>::type tag1; typedef typename geometry::tag<Geometry1>::type tag1;
typedef typename geometry::tag<Geometry2>::type tag2; typedef typename geometry::tag<Geometry2>::type tag2;
typedef typename geometry::point_type<Geometry1>::type point1_type;
typedef typename geometry::point_type<Geometry2>::type point2_type;
RingPropertyMap all_ring_properties; RingPropertyMap all_ring_properties;
dispatch::select_rings<tag1, Geometry1>::apply(geometry1, geometry2, dispatch::select_rings<tag1, Geometry1>::apply(geometry1, geometry2,
ring_identifier(0, -1, -1), all_ring_properties, ring_identifier(0, -1, -1), all_ring_properties,
strategy.template get_area_strategy<point1_type>()); strategy);
dispatch::select_rings<tag2, Geometry2>::apply(geometry2, geometry1, dispatch::select_rings<tag2, Geometry2>::apply(geometry2, geometry1,
ring_identifier(1, -1, -1), all_ring_properties, ring_identifier(1, -1, -1), all_ring_properties,
strategy.template get_area_strategy<point2_type>()); strategy);
update_ring_selection<OverlayType>(geometry1, geometry2, turn_info_per_ring, update_ring_selection<OverlayType>(geometry1, geometry2, turn_info_per_ring,
all_ring_properties, selected_ring_properties, all_ring_properties, selected_ring_properties,
@ -356,7 +354,7 @@ inline void select_rings(Geometry const& geometry,
RingPropertyMap all_ring_properties; RingPropertyMap all_ring_properties;
dispatch::select_rings<tag, Geometry>::apply(geometry, dispatch::select_rings<tag, Geometry>::apply(geometry,
ring_identifier(0, -1, -1), all_ring_properties, ring_identifier(0, -1, -1), all_ring_properties,
strategy.template get_area_strategy<point_type>()); strategy);
update_ring_selection<OverlayType>(geometry, geometry, turn_info_per_ring, update_ring_selection<OverlayType>(geometry, geometry, turn_info_per_ring,
all_ring_properties, selected_ring_properties, all_ring_properties, selected_ring_properties,

View File

@ -63,14 +63,14 @@ template
typename Geometry, typename Geometry,
typename Turns, typename Turns,
typename TurnPolicy, typename TurnPolicy,
typename IntersectionStrategy, typename Strategy,
typename RobustPolicy, typename RobustPolicy,
typename InterruptPolicy typename InterruptPolicy
> >
struct self_section_visitor struct self_section_visitor
{ {
Geometry const& m_geometry; Geometry const& m_geometry;
IntersectionStrategy const& m_intersection_strategy; Strategy const& m_strategy;
RobustPolicy const& m_rescale_policy; RobustPolicy const& m_rescale_policy;
Turns& m_turns; Turns& m_turns;
InterruptPolicy& m_interrupt_policy; InterruptPolicy& m_interrupt_policy;
@ -78,14 +78,14 @@ struct self_section_visitor
bool m_skip_adjacent; bool m_skip_adjacent;
inline self_section_visitor(Geometry const& g, inline self_section_visitor(Geometry const& g,
IntersectionStrategy const& is, Strategy const& s,
RobustPolicy const& rp, RobustPolicy const& rp,
Turns& turns, Turns& turns,
InterruptPolicy& ip, InterruptPolicy& ip,
int source_index, int source_index,
bool skip_adjacent) bool skip_adjacent)
: m_geometry(g) : m_geometry(g)
, m_intersection_strategy(is) , m_strategy(s)
, m_rescale_policy(rp) , m_rescale_policy(rp)
, m_turns(turns) , m_turns(turns)
, m_interrupt_policy(ip) , m_interrupt_policy(ip)
@ -98,7 +98,7 @@ struct self_section_visitor
{ {
if (! detail::disjoint::disjoint_box_box(sec1.bounding_box, if (! detail::disjoint::disjoint_box_box(sec1.bounding_box,
sec2.bounding_box, sec2.bounding_box,
m_intersection_strategy.get_disjoint_box_box_strategy()) m_strategy)
&& ! sec1.duplicate && ! sec1.duplicate
&& ! sec2.duplicate) && ! sec2.duplicate)
{ {
@ -112,7 +112,7 @@ struct self_section_visitor
>::apply(m_source_index, m_geometry, sec1, >::apply(m_source_index, m_geometry, sec1,
m_source_index, m_geometry, sec2, m_source_index, m_geometry, sec2,
false, m_skip_adjacent, false, m_skip_adjacent,
m_intersection_strategy, m_strategy,
m_rescale_policy, m_rescale_policy,
m_turns, m_interrupt_policy); m_turns, m_interrupt_policy);
} }
@ -127,10 +127,10 @@ struct self_section_visitor
template <bool Reverse, typename TurnPolicy> template <bool Reverse, typename TurnPolicy>
struct get_turns struct get_turns
{ {
template <typename Geometry, typename IntersectionStrategy, typename RobustPolicy, typename Turns, typename InterruptPolicy> template <typename Geometry, typename Strategy, typename RobustPolicy, typename Turns, typename InterruptPolicy>
static inline bool apply( static inline bool apply(
Geometry const& geometry, Geometry const& geometry,
IntersectionStrategy const& intersection_strategy, Strategy const& strategy,
RobustPolicy const& robust_policy, RobustPolicy const& robust_policy,
Turns& turns, Turns& turns,
InterruptPolicy& interrupt_policy, InterruptPolicy& interrupt_policy,
@ -152,32 +152,23 @@ struct get_turns
typedef std::integer_sequence<std::size_t, 0, 1> dimensions; typedef std::integer_sequence<std::size_t, 0, 1> dimensions;
sections_type sec; sections_type sec;
geometry::sectionalize<Reverse, dimensions>(geometry, robust_policy, sec, geometry::sectionalize<Reverse, dimensions>(geometry, robust_policy,
intersection_strategy.get_envelope_strategy(), sec, strategy);
intersection_strategy.get_expand_strategy());
self_section_visitor self_section_visitor
< <
Reverse, Geometry, Reverse, Geometry,
Turns, TurnPolicy, IntersectionStrategy, RobustPolicy, InterruptPolicy Turns, TurnPolicy, Strategy, RobustPolicy, InterruptPolicy
> visitor(geometry, intersection_strategy, robust_policy, turns, interrupt_policy, source_index, skip_adjacent); > visitor(geometry, 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;
// false if interrupted // false if interrupted
geometry::partition geometry::partition
< <
box_type box_type
>::apply(sec, visitor, >::apply(sec, visitor,
get_section_box_type(), detail::section::get_section_box<Strategy>(strategy),
overlaps_section_box_type()); detail::section::overlaps_section_box<Strategy>(strategy));
return ! interrupt_policy.has_intersections; return ! interrupt_policy.has_intersections;
} }
@ -340,13 +331,13 @@ template
< <
typename AssignPolicy, typename AssignPolicy,
typename Geometry, typename Geometry,
typename IntersectionStrategy, typename Strategy,
typename RobustPolicy, typename RobustPolicy,
typename Turns, typename Turns,
typename InterruptPolicy typename InterruptPolicy
> >
inline void self_turns(Geometry const& geometry, inline void self_turns(Geometry const& geometry,
IntersectionStrategy const& strategy, Strategy const& strategy,
RobustPolicy const& robust_policy, RobustPolicy const& robust_policy,
Turns& turns, Turns& turns,
InterruptPolicy& interrupt_policy, InterruptPolicy& interrupt_policy,

View File

@ -44,7 +44,7 @@ template
typename Turns, typename Turns,
typename TurnInfoMap, typename TurnInfoMap,
typename Clusters, typename Clusters,
typename IntersectionStrategy, typename Strategy,
typename RobustPolicy, typename RobustPolicy,
typename Visitor, typename Visitor,
typename Backtrack typename Backtrack
@ -55,7 +55,8 @@ struct traversal_ring_creator
< <
Reverse1, Reverse2, OverlayType, Reverse1, Reverse2, OverlayType,
Geometry1, Geometry2, Turns, Clusters, Geometry1, Geometry2, Turns, Clusters,
RobustPolicy, typename IntersectionStrategy::side_strategy_type, RobustPolicy,
decltype(std::declval<Strategy>().side()),
Visitor Visitor
> traversal_type; > traversal_type;
@ -68,17 +69,16 @@ struct traversal_ring_creator
inline traversal_ring_creator(Geometry1 const& geometry1, Geometry2 const& geometry2, inline traversal_ring_creator(Geometry1 const& geometry1, Geometry2 const& geometry2,
Turns& turns, TurnInfoMap& turn_info_map, Turns& turns, TurnInfoMap& turn_info_map,
Clusters const& clusters, Clusters const& clusters,
IntersectionStrategy const& intersection_strategy, Strategy const& strategy,
RobustPolicy const& robust_policy, Visitor& visitor) RobustPolicy const& robust_policy, Visitor& visitor)
: m_trav(geometry1, geometry2, turns, clusters, : m_trav(geometry1, geometry2, turns, clusters,
robust_policy, intersection_strategy.get_side_strategy(), robust_policy, strategy.side(), visitor)
visitor)
, m_geometry1(geometry1) , m_geometry1(geometry1)
, m_geometry2(geometry2) , m_geometry2(geometry2)
, m_turns(turns) , m_turns(turns)
, m_turn_info_map(turn_info_map) , m_turn_info_map(turn_info_map)
, m_clusters(clusters) , m_clusters(clusters)
, m_intersection_strategy(intersection_strategy) , m_strategy(strategy)
, m_robust_policy(robust_policy) , m_robust_policy(robust_policy)
, m_visitor(visitor) , m_visitor(visitor)
{ {
@ -113,15 +113,13 @@ struct traversal_ring_creator
{ {
geometry::copy_segments<Reverse1>(m_geometry1, geometry::copy_segments<Reverse1>(m_geometry1,
previous_op.seg_id, to_vertex_index, previous_op.seg_id, to_vertex_index,
m_intersection_strategy.get_side_strategy(), m_strategy, m_robust_policy, current_ring);
m_robust_policy, current_ring);
} }
else else
{ {
geometry::copy_segments<Reverse2>(m_geometry2, geometry::copy_segments<Reverse2>(m_geometry2,
previous_op.seg_id, to_vertex_index, previous_op.seg_id, to_vertex_index,
m_intersection_strategy.get_side_strategy(), m_strategy, m_robust_policy, current_ring);
m_robust_policy, current_ring);
} }
} }
@ -164,8 +162,7 @@ struct traversal_ring_creator
turn_type& current_turn = m_turns[turn_index]; turn_type& current_turn = m_turns[turn_index];
turn_operation_type& op = current_turn.operations[op_index]; turn_operation_type& op = current_turn.operations[op_index];
detail::overlay::append_no_collinear(current_ring, current_turn.point, detail::overlay::append_no_collinear(current_ring, current_turn.point,
m_intersection_strategy.get_side_strategy(), m_strategy, m_robust_policy);
m_robust_policy);
// Register the visit // Register the visit
m_trav.set_visited(current_turn, op); 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]; turn_operation_type& start_op = m_turns[start_turn_index].operations[start_op_index];
detail::overlay::append_no_collinear(ring, start_turn.point, detail::overlay::append_no_collinear(ring, start_turn.point,
m_intersection_strategy.get_side_strategy(), m_strategy, m_robust_policy);
m_robust_policy);
signed_size_type current_turn_index = start_turn_index; signed_size_type current_turn_index = start_turn_index;
int current_op_index = start_op_index; int current_op_index = start_op_index;
@ -286,9 +282,7 @@ struct traversal_ring_creator
if (geometry::num_points(ring) >= min_num_points) if (geometry::num_points(ring) >= min_num_points)
{ {
clean_closing_dups_and_spikes(ring, clean_closing_dups_and_spikes(ring, m_strategy, m_robust_policy);
m_intersection_strategy.get_side_strategy(),
m_robust_policy);
rings.push_back(ring); rings.push_back(ring);
m_trav.finalize_visit_info(m_turn_info_map); m_trav.finalize_visit_info(m_turn_info_map);
@ -297,13 +291,12 @@ struct traversal_ring_creator
} }
else else
{ {
Backtrack::apply( Backtrack::apply(finalized_ring_size,
finalized_ring_size,
rings, ring, m_turns, start_turn, rings, ring, m_turns, start_turn,
m_turns[turn_index].operations[op_index], m_turns[turn_index].operations[op_index],
traverse_error, traverse_error,
m_geometry1, m_geometry2, m_geometry1, m_geometry2,
m_intersection_strategy, m_robust_policy, m_strategy, m_robust_policy,
state, m_visitor); state, m_visitor);
} }
} }
@ -413,7 +406,7 @@ private:
Turns& m_turns; Turns& m_turns;
TurnInfoMap& m_turn_info_map; // contains turn-info information per ring TurnInfoMap& m_turn_info_map; // contains turn-info information per ring
Clusters const& m_clusters; Clusters const& m_clusters;
IntersectionStrategy const& m_intersection_strategy; Strategy const& m_strategy;
RobustPolicy const& m_robust_policy; RobustPolicy const& m_robust_policy;
Visitor& m_visitor; Visitor& m_visitor;
}; };

View File

@ -209,10 +209,10 @@ struct areal_areal
typedef typename geometry::point_type<Geometry1>::type point1_type; typedef typename geometry::point_type<Geometry1>::type point1_type;
typedef typename geometry::point_type<Geometry2>::type point2_type; typedef typename geometry::point_type<Geometry2>::type point2_type;
template <typename Result, typename IntersectionStrategy> template <typename Result, typename Strategy>
static inline void apply(Geometry1 const& geometry1, Geometry2 const& geometry2, static inline void apply(Geometry1 const& geometry1, Geometry2 const& geometry2,
Result & result, Result & result,
IntersectionStrategy const& intersection_strategy) Strategy const& strategy)
{ {
// TODO: If Areal geometry may have infinite size, change the following line: // TODO: If Areal geometry may have infinite size, change the following line:
@ -226,38 +226,25 @@ struct areal_areal
typedef typename turns::get_turns typedef typename turns::get_turns
< <
Geometry1, Geometry2 Geometry1, Geometry2
>::template turn_info_type<IntersectionStrategy>::type turn_type; >::template turn_info_type<Strategy>::type turn_type;
std::vector<turn_type> turns; std::vector<turn_type> turns;
interrupt_policy_areal_areal<Result> interrupt_policy(geometry1, geometry2, result); interrupt_policy_areal_areal<Result> interrupt_policy(geometry1, geometry2, result);
turns::get_turns<Geometry1, Geometry2>::apply(turns, geometry1, geometry2, interrupt_policy, intersection_strategy); turns::get_turns<Geometry1, Geometry2>::apply(turns, geometry1, geometry2, interrupt_policy, strategy);
if ( BOOST_GEOMETRY_CONDITION(result.interrupt) ) if ( BOOST_GEOMETRY_CONDITION(result.interrupt) )
return; return;
typedef typename IntersectionStrategy::cs_tag cs_tag; typedef typename Strategy::cs_tag cs_tag;
typedef typename IntersectionStrategy::template point_in_geometry_strategy no_turns_aa_pred<Geometry2, Result, Strategy, false>
< pred1(geometry2, result, strategy);
Geometry1, Geometry2
>::type point_in_areal_strategy12_type;
point_in_areal_strategy12_type point_in_areal_strategy12
= intersection_strategy.template get_point_in_geometry_strategy<Geometry1, Geometry2>();
typedef typename IntersectionStrategy::template point_in_geometry_strategy
<
Geometry2, Geometry1
>::type point_in_areal_strategy21_type;
point_in_areal_strategy21_type point_in_areal_strategy21
= intersection_strategy.template get_point_in_geometry_strategy<Geometry2, Geometry1>();
no_turns_aa_pred<Geometry2, Result, point_in_areal_strategy12_type, false>
pred1(geometry2, result, point_in_areal_strategy12);
for_each_disjoint_geometry_if<0, Geometry1>::apply(turns.begin(), turns.end(), geometry1, pred1); for_each_disjoint_geometry_if<0, Geometry1>::apply(turns.begin(), turns.end(), geometry1, pred1);
if ( BOOST_GEOMETRY_CONDITION(result.interrupt) ) if ( BOOST_GEOMETRY_CONDITION(result.interrupt) )
return; return;
no_turns_aa_pred<Geometry1, Result, point_in_areal_strategy21_type, true> no_turns_aa_pred<Geometry1, Result, Strategy, true>
pred2(geometry1, result, point_in_areal_strategy21); pred2(geometry1, result, strategy);
for_each_disjoint_geometry_if<1, Geometry2>::apply(turns.begin(), turns.end(), geometry2, pred2); for_each_disjoint_geometry_if<1, Geometry2>::apply(turns.begin(), turns.end(), geometry2, pred2);
if ( BOOST_GEOMETRY_CONDITION(result.interrupt) ) if ( BOOST_GEOMETRY_CONDITION(result.interrupt) )
return; return;
@ -282,8 +269,7 @@ struct areal_areal
{ {
// analyse sorted turns // analyse sorted turns
turns_analyser<turn_type, 0> analyser; turns_analyser<turn_type, 0> analyser;
analyse_each_turn(result, analyser, turns.begin(), turns.end(), analyse_each_turn(result, analyser, turns.begin(), turns.end(), strategy);
point_in_areal_strategy12.get_equals_point_point_strategy());
if ( BOOST_GEOMETRY_CONDITION(result.interrupt) ) if ( BOOST_GEOMETRY_CONDITION(result.interrupt) )
return; return;
@ -297,8 +283,8 @@ struct areal_areal
{ {
// analyse rings for which turns were not generated // analyse rings for which turns were not generated
// or only i/i or u/u was generated // or only i/i or u/u was generated
uncertain_rings_analyser<0, Result, Geometry1, Geometry2, point_in_areal_strategy12_type> uncertain_rings_analyser<0, Result, Geometry1, Geometry2, Strategy>
rings_analyser(result, geometry1, geometry2, point_in_areal_strategy12); rings_analyser(result, geometry1, geometry2, strategy);
analyse_uncertain_rings<0>::apply(rings_analyser, turns.begin(), turns.end()); analyse_uncertain_rings<0>::apply(rings_analyser, turns.begin(), turns.end());
if ( BOOST_GEOMETRY_CONDITION(result.interrupt) ) if ( BOOST_GEOMETRY_CONDITION(result.interrupt) )
@ -323,8 +309,7 @@ struct areal_areal
{ {
// analyse sorted turns // analyse sorted turns
turns_analyser<turn_type, 1> analyser; turns_analyser<turn_type, 1> analyser;
analyse_each_turn(result, analyser, turns.begin(), turns.end(), analyse_each_turn(result, analyser, turns.begin(), turns.end(), strategy);
point_in_areal_strategy21.get_equals_point_point_strategy());
if ( BOOST_GEOMETRY_CONDITION(result.interrupt) ) if ( BOOST_GEOMETRY_CONDITION(result.interrupt) )
return; return;
@ -338,8 +323,8 @@ struct areal_areal
{ {
// analyse rings for which turns were not generated // analyse rings for which turns were not generated
// or only i/i or u/u was generated // or only i/i or u/u was generated
uncertain_rings_analyser<1, Result, Geometry2, Geometry1, point_in_areal_strategy21_type> uncertain_rings_analyser<1, Result, Geometry2, Geometry1, Strategy>
rings_analyser(result, geometry2, geometry1, point_in_areal_strategy21); rings_analyser(result, geometry2, geometry1, strategy);
analyse_uncertain_rings<1>::apply(rings_analyser, turns.begin(), turns.end()); analyse_uncertain_rings<1>::apply(rings_analyser, turns.begin(), turns.end());
//if ( result.interrupt ) //if ( result.interrupt )

View File

@ -1,6 +1,6 @@
// Boost.Geometry (aka GGL, Generic Geometry Library) // 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 // 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 }; enum boundary_query { boundary_front, boundary_back, boundary_any };
template <typename Geometry, template
typename WithinStrategy, // Point/Point equals (within) strategy <
typename Tag = typename geometry::tag<Geometry>::type> typename Geometry,
typename Strategy,
typename Tag = typename geometry::tag<Geometry>::type
>
class boundary_checker {}; class boundary_checker {};
template <typename Geometry, typename WithinStrategy> template <typename Geometry, typename Strategy>
class boundary_checker<Geometry, WithinStrategy, linestring_tag> class boundary_checker<Geometry, Strategy, linestring_tag>
{ {
typedef typename point_type<Geometry>::type point_type; typedef typename point_type<Geometry>::type point_type;
public: public:
typedef WithinStrategy equals_strategy_type; boundary_checker(Geometry const& g, Strategy const& s)
: m_has_boundary( boost::size(g) >= 2
boundary_checker(Geometry const& g) && ! detail::equals::equals_point_point(range::front(g),
: has_boundary( boost::size(g) >= 2
&& !detail::equals::equals_point_point(range::front(g),
range::back(g), range::back(g),
equals_strategy_type()) ) s) )
#ifdef BOOST_GEOMETRY_DEBUG_RELATE_BOUNDARY_CHECKER #ifdef BOOST_GEOMETRY_DEBUG_RELATE_BOUNDARY_CHECKER
, geometry(g) , m_geometry(g)
#endif #endif
, m_strategy(s)
{} {}
template <boundary_query BoundaryQuery> template <boundary_query BoundaryQuery>
@ -60,30 +62,34 @@ public:
#ifdef BOOST_GEOMETRY_DEBUG_RELATE_BOUNDARY_CHECKER #ifdef BOOST_GEOMETRY_DEBUG_RELATE_BOUNDARY_CHECKER
// may give false positives for INT // may give false positives for INT
BOOST_GEOMETRY_ASSERT( (BoundaryQuery == boundary_front || BoundaryQuery == boundary_any) 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) || (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 #endif
return has_boundary; return m_has_boundary;
}
Strategy const& strategy() const
{
return m_strategy;
} }
private: private:
bool has_boundary; bool m_has_boundary;
#ifdef BOOST_GEOMETRY_DEBUG_RELATE_BOUNDARY_CHECKER #ifdef BOOST_GEOMETRY_DEBUG_RELATE_BOUNDARY_CHECKER
Geometry const& geometry; Geometry const& m_geometry;
#endif #endif
Strategy const& m_strategy;
}; };
template <typename Geometry, typename WithinStrategy> template <typename Geometry, typename Strategy>
class boundary_checker<Geometry, WithinStrategy, multi_linestring_tag> class boundary_checker<Geometry, Strategy, multi_linestring_tag>
{ {
typedef typename point_type<Geometry>::type point_type; typedef typename point_type<Geometry>::type point_type;
public: public:
typedef WithinStrategy equals_strategy_type; boundary_checker(Geometry const& g, Strategy const& s)
: m_is_filled(false), m_geometry(g), m_strategy(s)
boundary_checker(Geometry const& g)
: is_filled(false), geometry(g)
{} {}
// First call O(NlogN) // First call O(NlogN)
@ -91,22 +97,22 @@ public:
template <boundary_query BoundaryQuery> template <boundary_query BoundaryQuery>
bool is_endpoint_boundary(point_type const& pt) const bool is_endpoint_boundary(point_type const& pt) const
{ {
typedef geometry::less<point_type, -1, typename WithinStrategy::cs_tag> less_type; typedef geometry::less<point_type, -1, typename Strategy::cs_tag> less_type;
typedef typename boost::range_size<Geometry>::type size_type; typedef typename boost::range_size<Geometry>::type size_type;
size_type multi_count = boost::size(geometry); size_type multi_count = boost::size(m_geometry);
if ( multi_count < 1 ) if ( multi_count < 1 )
return false; return false;
if ( ! is_filled ) if ( ! m_is_filled )
{ {
//boundary_points.clear(); //boundary_points.clear();
boundary_points.reserve(multi_count * 2); m_boundary_points.reserve(multi_count * 2);
typedef typename boost::range_iterator<Geometry const>::type multi_iterator; typedef typename boost::range_iterator<Geometry const>::type multi_iterator;
for ( multi_iterator it = boost::begin(geometry) ; for ( multi_iterator it = boost::begin(m_geometry) ;
it != boost::end(geometry) ; ++ it ) it != boost::end(m_geometry) ; ++ it )
{ {
typename boost::range_reference<Geometry const>::type typename boost::range_reference<Geometry const>::type
ls = *it; ls = *it;
@ -126,33 +132,33 @@ public:
point_reference back_pt = range::back(ls); point_reference back_pt = range::back(ls);
// linear ring or point - no boundary // 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 // do not add points containing NaN coordinates
// because they cannot be reasonably compared, e.g. with MSVC // because they cannot be reasonably compared, e.g. with MSVC
// an assertion failure is reported in std::equal_range() // an assertion failure is reported in std::equal_range()
if (! geometry::has_nan_coordinate(front_pt)) 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)) 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(), std::sort(m_boundary_points.begin(),
boundary_points.end(), m_boundary_points.end(),
less_type()); less_type());
is_filled = true; m_is_filled = true;
} }
std::size_t equal_points_count std::size_t equal_points_count
= boost::size( = boost::size(
std::equal_range(boundary_points.begin(), std::equal_range(m_boundary_points.begin(),
boundary_points.end(), m_boundary_points.end(),
pt, pt,
less_type()) less_type())
); );
@ -160,12 +166,18 @@ public:
return equal_points_count % 2 != 0;// && equal_points_count > 0; // the number is odd and > 0 return equal_points_count % 2 != 0;// && equal_points_count > 0; // the number is odd and > 0
} }
private: Strategy const& strategy() const
mutable bool is_filled; {
// TODO: store references/pointers instead of points? return m_strategy;
mutable std::vector<point_type> boundary_points; }
Geometry const& geometry; private:
mutable bool m_is_filled;
// TODO: store references/pointers instead of points?
mutable std::vector<point_type> m_boundary_points;
Geometry const& m_geometry;
Strategy const& m_strategy;
}; };
}} // namespace detail::relate }} // namespace detail::relate

View File

@ -341,9 +341,9 @@ private:
std::vector<point_info> m_other_entry_points; // TODO: use map here or sorted vector? std::vector<point_info> m_other_entry_points; // TODO: use map here or sorted vector?
}; };
template <std::size_t OpId, typename Turn, typename EqPPStrategy> template <std::size_t OpId, typename Turn, typename Strategy>
inline bool turn_on_the_same_ip(Turn const& prev_turn, Turn const& curr_turn, 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& prev_seg_id = prev_turn.operations[OpId].seg_id;
segment_identifier const& curr_seg_id = curr_turn.operations[OpId].seg_id; segment_identifier const& curr_seg_id = curr_turn.operations[OpId].seg_id;

View File

@ -29,7 +29,8 @@
#include <boost/geometry/core/topological_dimension.hpp> #include <boost/geometry/core/topological_dimension.hpp>
#include <boost/geometry/geometries/concepts/check.hpp> #include <boost/geometry/geometries/concepts/check.hpp>
#include <boost/geometry/strategies/default_strategy.hpp> #include <boost/geometry/strategies/default_strategy.hpp>
#include <boost/geometry/strategies/relate.hpp> #include <boost/geometry/strategies/detail.hpp>
#include <boost/geometry/strategies/relate/services.hpp>
#include <boost/geometry/util/sequence.hpp> #include <boost/geometry/util/sequence.hpp>
#include <boost/geometry/util/type_traits.hpp> #include <boost/geometry/util/type_traits.hpp>
@ -161,9 +162,15 @@ struct result_handler_type<Geometry1, Geometry2, util::type_sequence<StaticMasks
namespace resolve_strategy { namespace resolve_strategy {
template
<
typename Strategy,
bool IsUmbrella = strategies::detail::is_umbrella_strategy<Strategy>::value
>
struct relate struct relate
{ {
template <typename Geometry1, typename Geometry2, typename ResultHandler, typename Strategy> template <typename Geometry1, typename Geometry2, typename ResultHandler>
static inline void apply(Geometry1 const& geometry1, static inline void apply(Geometry1 const& geometry1,
Geometry2 const& geometry2, Geometry2 const& geometry2,
ResultHandler & handler, ResultHandler & handler,
@ -175,14 +182,37 @@ struct relate
Geometry2 Geometry2
>::apply(geometry1, geometry2, handler, strategy); >::apply(geometry1, geometry2, handler, strategy);
} }
};
template <typename Strategy>
struct relate<Strategy, false>
{
template <typename Geometry1, typename Geometry2, typename ResultHandler>
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<Strategy>::get(strategy));
}
};
template <>
struct relate<default_strategy, false>
{
template <typename Geometry1, typename Geometry2, typename ResultHandler> template <typename Geometry1, typename Geometry2, typename ResultHandler>
static inline void apply(Geometry1 const& geometry1, static inline void apply(Geometry1 const& geometry1,
Geometry2 const& geometry2, Geometry2 const& geometry2,
ResultHandler & handler, ResultHandler & handler,
default_strategy) default_strategy)
{ {
typedef typename strategy::relate::services::default_strategy typedef typename strategies::relate::services::default_strategy
< <
Geometry1, Geometry1,
Geometry2 Geometry2
@ -220,7 +250,7 @@ struct relate
Mask Mask
>::type handler(mask); >::type handler(mask);
resolve_strategy::relate::apply(geometry1, geometry2, handler, strategy); resolve_strategy::relate<Strategy>::apply(geometry1, geometry2, handler, strategy);
return handler.result(); return handler.result();
} }

View File

@ -229,10 +229,10 @@ struct linear_areal
> >
{}; {};
template <typename Result, typename IntersectionStrategy> template <typename Result, typename Strategy>
static inline void apply(Geometry1 const& geometry1, Geometry2 const& geometry2, static inline void apply(Geometry1 const& geometry1, Geometry2 const& geometry2,
Result & result, Result & result,
IntersectionStrategy const& intersection_strategy) Strategy const& strategy)
{ {
// TODO: If Areal geometry may have infinite size, change the following line: // TODO: If Areal geometry may have infinite size, change the following line:
@ -243,38 +243,34 @@ struct linear_areal
return; return;
// get and analyse turns // get and analyse turns
typedef typename turn_info_type<Geometry1, Geometry2, IntersectionStrategy>::type turn_type; typedef typename turn_info_type<Geometry1, Geometry2, Strategy>::type turn_type;
std::vector<turn_type> turns; std::vector<turn_type> turns;
interrupt_policy_linear_areal<Geometry2, Result> interrupt_policy(geometry2, result); interrupt_policy_linear_areal<Geometry2, Result> interrupt_policy(geometry2, result);
turns::get_turns<Geometry1, Geometry2>::apply(turns, geometry1, geometry2, interrupt_policy, intersection_strategy); turns::get_turns<Geometry1, Geometry2>::apply(turns, geometry1, geometry2, interrupt_policy, strategy);
if ( BOOST_GEOMETRY_CONDITION( result.interrupt ) ) if ( BOOST_GEOMETRY_CONDITION( result.interrupt ) )
return; return;
typedef typename IntersectionStrategy::template point_in_geometry_strategy<Geometry1, Geometry2>::type within_strategy_type; typedef typename Strategy::cs_tag cs_tag;
within_strategy_type const within_strategy = intersection_strategy.template get_point_in_geometry_strategy<Geometry1, Geometry2>();
typedef typename IntersectionStrategy::cs_tag cs_tag;
typedef typename within_strategy_type::equals_point_point_strategy_type eq_pp_strategy_type;
typedef boundary_checker typedef boundary_checker
< <
Geometry1, Geometry1,
eq_pp_strategy_type Strategy
> boundary_checker1_type; > boundary_checker1_type;
boundary_checker1_type boundary_checker1(geometry1); boundary_checker1_type boundary_checker1(geometry1, strategy);
no_turns_la_linestring_pred no_turns_la_linestring_pred
< <
Geometry2, Geometry2,
Result, Result,
within_strategy_type, Strategy,
boundary_checker1_type, boundary_checker1_type,
TransposeResult TransposeResult
> pred1(geometry2, > pred1(geometry2,
result, result,
within_strategy, strategy,
boundary_checker1); boundary_checker1);
for_each_disjoint_geometry_if<0, Geometry1>::apply(turns.begin(), turns.end(), geometry1, pred1); for_each_disjoint_geometry_if<0, Geometry1>::apply(turns.begin(), turns.end(), geometry1, pred1);
if ( BOOST_GEOMETRY_CONDITION( result.interrupt ) ) if ( BOOST_GEOMETRY_CONDITION( result.interrupt ) )
@ -302,7 +298,7 @@ struct linear_areal
turns.begin(), turns.end(), turns.begin(), turns.end(),
geometry1, geometry2, geometry1, geometry2,
boundary_checker1, boundary_checker1,
intersection_strategy.get_side_strategy()); strategy);
if ( BOOST_GEOMETRY_CONDITION( result.interrupt ) ) if ( BOOST_GEOMETRY_CONDITION( result.interrupt ) )
return; return;
@ -395,14 +391,12 @@ struct linear_areal
typedef turns::less<1, turns::less_op_areal_linear<1>, cs_tag> less; typedef turns::less<1, turns::less_op_areal_linear<1>, cs_tag> less;
std::sort(it, next, less()); std::sort(it, next, less());
eq_pp_strategy_type const eq_pp_strategy = within_strategy.get_equals_point_point_strategy();
// analyse // analyse
areal_boundary_analyser<turn_type> analyser; areal_boundary_analyser<turn_type> analyser;
for ( turn_iterator rit = it ; rit != next ; ++rit ) for ( turn_iterator rit = it ; rit != next ; ++rit )
{ {
// if the analyser requests, break the search // if the analyser requests, break the search
if ( !analyser.apply(it, rit, next, eq_pp_strategy) ) if ( !analyser.apply(it, rit, next, strategy) )
break; break;
} }
@ -626,18 +620,20 @@ struct linear_areal
static const std::size_t other_op_id = 1; static const std::size_t other_op_id = 1;
template <typename TurnPointCSTag, typename PointP, typename PointQ, template <typename TurnPointCSTag, typename PointP, typename PointQ,
typename SideStrategy, typename Strategy,
typename Pi = PointP, typename Pj = PointP, typename Pk = PointP, typename Pi = PointP, typename Pj = PointP, typename Pk = PointP,
typename Qi = PointQ, typename Qj = PointQ, typename Qk = PointQ typename Qi = PointQ, typename Qj = PointQ, typename Qk = PointQ
> >
struct la_side_calculator struct la_side_calculator
{ {
typedef decltype(std::declval<Strategy>().side()) side_strategy_type;
inline la_side_calculator(Pi const& pi, Pj const& pj, Pk const& pk, inline la_side_calculator(Pi const& pi, Pj const& pj, Pk const& pk,
Qi const& qi, Qj const& qj, Qk const& qk, Qi const& qi, Qj const& qj, Qk const& qk,
SideStrategy const& side_strategy) Strategy const& strategy)
: m_pi(pi), m_pj(pj), m_pk(pk) : m_pi(pi), m_pj(pj), m_pk(pk)
, m_qi(qi), m_qj(qj), m_qk(qk) , 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); } 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; Qj const& m_qj;
Qk const& m_qk; Qk const& m_qk;
SideStrategy m_side_strategy; side_strategy_type m_side_strategy;
}; };
@ -672,12 +668,12 @@ struct linear_areal
typename Geometry, typename Geometry,
typename OtherGeometry, typename OtherGeometry,
typename BoundaryChecker, typename BoundaryChecker,
typename SideStrategy> typename Strategy>
void apply(Result & res, TurnIt it, void apply(Result & res, TurnIt it,
Geometry const& geometry, Geometry const& geometry,
OtherGeometry const& other_geometry, OtherGeometry const& other_geometry,
BoundaryChecker const& boundary_checker, BoundaryChecker const& boundary_checker,
SideStrategy const& side_strategy) Strategy const& strategy)
{ {
overlay::operation_type op = it->operations[op_id].operation; overlay::operation_type op = it->operations[op_id].operation;
@ -706,7 +702,7 @@ struct linear_areal
// real exit point - may be multiple // real exit point - may be multiple
// we know that we entered and now we exit // we know that we entered and now we exit
if ( ! turn_on_the_same_ip<op_id>(m_exit_watcher.get_exit_turn(), *it, if ( ! turn_on_the_same_ip<op_id>(m_exit_watcher.get_exit_turn(), *it,
side_strategy.get_equals_point_point_strategy()) ) strategy) )
{ {
m_exit_watcher.reset_detected_exit(); m_exit_watcher.reset_detected_exit();
@ -749,7 +745,7 @@ struct linear_areal
if ( ( op == overlay::operation_intersection if ( ( op == overlay::operation_intersection
|| op == overlay::operation_continue ) || op == overlay::operation_continue )
&& turn_on_the_same_ip<op_id>(m_exit_watcher.get_exit_turn(), *it, && turn_on_the_same_ip<op_id>(m_exit_watcher.get_exit_turn(), *it,
side_strategy.get_equals_point_point_strategy()) ) strategy) )
{ {
fake_enter_detected = true; 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 || 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 || ( m_previous_operation == overlay::operation_union
&& ! turn_on_the_same_ip<op_id>(*m_previous_turn_ptr, *it, && ! turn_on_the_same_ip<op_id>(*m_previous_turn_ptr, *it,
side_strategy.get_equals_point_point_strategy()) ) strategy) )
) )
{ {
update<interior, exterior, '1', TransposeResult>(res); update<interior, exterior, '1', TransposeResult>(res);
@ -803,7 +799,7 @@ struct linear_areal
// real interior overlap // real interior overlap
if ( ! turn_on_the_same_ip<op_id>(*m_previous_turn_ptr, *it, if ( ! turn_on_the_same_ip<op_id>(*m_previous_turn_ptr, *it,
side_strategy.get_equals_point_point_strategy()) ) strategy) )
{ {
update<interior, interior, '1', TransposeResult>(res); update<interior, interior, '1', TransposeResult>(res);
m_interior_detected = false; m_interior_detected = false;
@ -919,7 +915,7 @@ struct linear_areal
&& calculate_from_inside(geometry, && calculate_from_inside(geometry,
other_geometry, other_geometry,
*it, *it,
side_strategy); strategy);
if ( from_inside ) if ( from_inside )
update<interior, interior, '1', TransposeResult>(res); update<interior, interior, '1', TransposeResult>(res);
@ -1020,7 +1016,7 @@ struct linear_areal
&& calculate_from_inside(geometry, && calculate_from_inside(geometry,
other_geometry, other_geometry,
*it, *it,
side_strategy); strategy);
if ( first_from_inside ) if ( first_from_inside )
{ {
update<interior, interior, '1', TransposeResult>(res); update<interior, interior, '1', TransposeResult>(res);
@ -1208,11 +1204,11 @@ struct linear_areal
// check if the passed turn's segment of Linear geometry arrived // check if the passed turn's segment of Linear geometry arrived
// from the inside or the outside of the Areal geometry // from the inside or the outside of the Areal geometry
template <typename Turn, typename SideStrategy> template <typename Turn, typename Strategy>
static inline bool calculate_from_inside(Geometry1 const& geometry1, static inline bool calculate_from_inside(Geometry1 const& geometry1,
Geometry2 const& geometry2, Geometry2 const& geometry2,
Turn const& turn, Turn const& turn,
SideStrategy const& side_strategy) Strategy const& strategy)
{ {
typedef typename cs_tag<typename Turn::point_type>::type cs_tag; typedef typename cs_tag<typename Turn::point_type>::type cs_tag;
@ -1242,7 +1238,7 @@ struct linear_areal
point2_type const& qj = range::at(range2, q_seg_ij + 1); point2_type const& qj = range::at(range2, q_seg_ij + 1);
point1_type qi_conv; point1_type qi_conv;
geometry::convert(qi, 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! // TODO: test this!
// BOOST_GEOMETRY_ASSERT(!equals::equals_point_point(turn.point, pi)); // BOOST_GEOMETRY_ASSERT(!equals::equals_point_point(turn.point, pi));
// BOOST_GEOMETRY_ASSERT(!equals::equals_point_point(turn.point, qi)); // 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), range2_iterator qk_it = find_next_non_duplicated(boost::begin(range2),
range::pos(range2, q_seg_jk), range::pos(range2, q_seg_jk),
boost::end(range2), boost::end(range2),
side_strategy.get_equals_point_point_strategy()); strategy);
// Will this sequence of points be always correct? // Will this sequence of points be always correct?
la_side_calculator<cs_tag, point1_type, point2_type, SideStrategy> la_side_calculator<cs_tag, point1_type, point2_type, Strategy>
side_calc(qi_conv, new_pj, pi, qi, qj, *qk_it, side_strategy); side_calc(qi_conv, new_pj, pi, qi, qj, *qk_it, strategy);
return calculate_from_inside_sides(side_calc); return calculate_from_inside_sides(side_calc);
} }
@ -1270,16 +1266,16 @@ struct linear_areal
point2_type new_qj; point2_type new_qj;
geometry::convert(turn.point, new_qj); geometry::convert(turn.point, new_qj);
la_side_calculator<cs_tag, point1_type, point2_type, SideStrategy> la_side_calculator<cs_tag, point1_type, point2_type, Strategy>
side_calc(qi_conv, new_pj, pi, qi, new_qj, qj, side_strategy); side_calc(qi_conv, new_pj, pi, qi, new_qj, qj, strategy);
return calculate_from_inside_sides(side_calc); return calculate_from_inside_sides(side_calc);
} }
} }
template <typename It, typename EqPPStrategy> template <typename It, typename Strategy>
static inline It find_next_non_duplicated(It first, It current, It last, static inline It find_next_non_duplicated(It first, It current, It last,
EqPPStrategy const& strategy) Strategy const& strategy)
{ {
BOOST_GEOMETRY_ASSERT( current != last ); BOOST_GEOMETRY_ASSERT( current != last );
@ -1340,14 +1336,14 @@ struct linear_areal
typename Geometry, typename Geometry,
typename OtherGeometry, typename OtherGeometry,
typename BoundaryChecker, typename BoundaryChecker,
typename SideStrategy> typename Strategy>
static inline void analyse_each_turn(Result & res, static inline void analyse_each_turn(Result & res,
Analyser & analyser, Analyser & analyser,
TurnIt first, TurnIt last, TurnIt first, TurnIt last,
Geometry const& geometry, Geometry const& geometry,
OtherGeometry const& other_geometry, OtherGeometry const& other_geometry,
BoundaryChecker const& boundary_checker, BoundaryChecker const& boundary_checker,
SideStrategy const& side_strategy) Strategy const& strategy)
{ {
if ( first == last ) if ( first == last )
return; return;
@ -1357,7 +1353,7 @@ struct linear_areal
analyser.apply(res, it, analyser.apply(res, it,
geometry, other_geometry, geometry, other_geometry,
boundary_checker, boundary_checker,
side_strategy); strategy);
if ( BOOST_GEOMETRY_CONDITION( res.interrupt ) ) if ( BOOST_GEOMETRY_CONDITION( res.interrupt ) )
return; return;
@ -1437,9 +1433,9 @@ struct linear_areal
, m_previous_turn_ptr(NULL) , m_previous_turn_ptr(NULL)
{} {}
template <typename TurnIt, typename EqPPStrategy> template <typename TurnIt, typename Strategy>
bool apply(TurnIt /*first*/, TurnIt it, TurnIt last, bool apply(TurnIt /*first*/, TurnIt it, TurnIt last,
EqPPStrategy const& strategy) Strategy const& strategy)
{ {
overlay::operation_type op = it->operations[1].operation; 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; static const bool interruption_enabled = linear_areal_type::interruption_enabled;
template <typename Result, typename IntersectionStrategy> template <typename Result, typename Strategy>
static inline void apply(Geometry1 const& geometry1, Geometry2 const& geometry2, static inline void apply(Geometry1 const& geometry1, Geometry2 const& geometry2,
Result & result, 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);
} }
}; };

View File

@ -42,8 +42,6 @@ namespace detail { namespace relate {
template <typename Result, typename BoundaryChecker, bool TransposeResult> template <typename Result, typename BoundaryChecker, bool TransposeResult>
class disjoint_linestring_pred class disjoint_linestring_pred
{ {
typedef typename BoundaryChecker::equals_strategy_type equals_strategy_type;
public: public:
disjoint_linestring_pred(Result & res, disjoint_linestring_pred(Result & res,
BoundaryChecker const& boundary_checker) BoundaryChecker const& boundary_checker)
@ -83,7 +81,7 @@ public:
if ( count == 2 if ( count == 2
&& equals::equals_point_point(range::front(linestring), && equals::equals_point_point(range::front(linestring),
range::back(linestring), range::back(linestring),
equals_strategy_type()) ) m_boundary_checker.strategy()) )
{ {
update<interior, exterior, '0', TransposeResult>(m_result); update<interior, exterior, '0', TransposeResult>(m_result);
} }
@ -122,12 +120,12 @@ struct linear_linear
typedef typename geometry::point_type<Geometry1>::type point1_type; typedef typename geometry::point_type<Geometry1>::type point1_type;
typedef typename geometry::point_type<Geometry2>::type point2_type; typedef typename geometry::point_type<Geometry2>::type point2_type;
template <typename Result, typename IntersectionStrategy> template <typename Result, typename Strategy>
static inline void apply(Geometry1 const& geometry1, Geometry2 const& geometry2, static inline void apply(Geometry1 const& geometry1, Geometry2 const& geometry2,
Result & result, 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 // The result should be FFFFFFFFF
relate::set<exterior, exterior, result_dimension<Geometry1>::value>(result);// FFFFFFFFd, d in [1,9] or T relate::set<exterior, exterior, result_dimension<Geometry1>::value>(result);// FFFFFFFFd, d in [1,9] or T
@ -138,7 +136,7 @@ struct linear_linear
typedef typename turns::get_turns typedef typename turns::get_turns
< <
Geometry1, Geometry2 Geometry1, Geometry2
>::template turn_info_type<IntersectionStrategy>::type turn_type; >::template turn_info_type<Strategy>::type turn_type;
std::vector<turn_type> turns; std::vector<turn_type> turns;
interrupt_policy_linear_linear<Result> interrupt_policy(result); interrupt_policy_linear_linear<Result> interrupt_policy(result);
@ -148,28 +146,20 @@ struct linear_linear
Geometry1, Geometry1,
Geometry2, Geometry2,
detail::get_turns::get_turn_info_type<Geometry1, Geometry2, turns::assign_policy<true> > detail::get_turns::get_turn_info_type<Geometry1, Geometry2, turns::assign_policy<true> >
>::apply(turns, geometry1, geometry2, interrupt_policy, intersection_strategy); >::apply(turns, geometry1, geometry2, interrupt_policy, strategy);
if ( BOOST_GEOMETRY_CONDITION( result.interrupt ) ) if ( BOOST_GEOMETRY_CONDITION( result.interrupt ) )
return; return;
typedef boundary_checker typedef boundary_checker<Geometry1, Strategy> boundary_checker1_type;
< boundary_checker1_type boundary_checker1(geometry1, strategy);
Geometry1,
typename IntersectionStrategy::point_in_point_strategy_type
> boundary_checker1_type;
boundary_checker1_type boundary_checker1(geometry1);
disjoint_linestring_pred<Result, boundary_checker1_type, false> pred1(result, boundary_checker1); disjoint_linestring_pred<Result, boundary_checker1_type, false> pred1(result, boundary_checker1);
for_each_disjoint_geometry_if<0, Geometry1>::apply(turns.begin(), turns.end(), geometry1, pred1); for_each_disjoint_geometry_if<0, Geometry1>::apply(turns.begin(), turns.end(), geometry1, pred1);
if ( BOOST_GEOMETRY_CONDITION( result.interrupt ) ) if ( BOOST_GEOMETRY_CONDITION( result.interrupt ) )
return; return;
typedef boundary_checker typedef boundary_checker<Geometry2, Strategy> boundary_checker2_type;
< boundary_checker2_type boundary_checker2(geometry2, strategy);
Geometry2,
typename IntersectionStrategy::point_in_point_strategy_type
> boundary_checker2_type;
boundary_checker2_type boundary_checker2(geometry2);
disjoint_linestring_pred<Result, boundary_checker2_type, true> pred2(result, boundary_checker2); disjoint_linestring_pred<Result, boundary_checker2_type, true> pred2(result, boundary_checker2);
for_each_disjoint_geometry_if<1, Geometry2>::apply(turns.begin(), turns.end(), geometry2, pred2); for_each_disjoint_geometry_if<1, Geometry2>::apply(turns.begin(), turns.end(), geometry2, pred2);
if ( BOOST_GEOMETRY_CONDITION( result.interrupt ) ) if ( BOOST_GEOMETRY_CONDITION( result.interrupt ) )
@ -292,8 +282,6 @@ struct linear_linear
BoundaryChecker const& boundary_checker, BoundaryChecker const& boundary_checker,
OtherBoundaryChecker const& other_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; overlay::operation_type const op = it->operations[op_id].operation;
segment_identifier const& seg_id = it->operations[op_id].seg_id; 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 // we know that we entered and now we exit
if ( ! turn_on_the_same_ip<op_id>(m_exit_watcher.get_exit_turn(), if ( ! turn_on_the_same_ip<op_id>(m_exit_watcher.get_exit_turn(),
*it, *it,
equals_strategy_type()) ) boundary_checker.strategy()) )
{ {
m_exit_watcher.reset_detected_exit(); m_exit_watcher.reset_detected_exit();
@ -368,7 +356,7 @@ struct linear_linear
if ( op == overlay::operation_intersection if ( op == overlay::operation_intersection
&& turn_on_the_same_ip<op_id>(m_exit_watcher.get_exit_turn(), && turn_on_the_same_ip<op_id>(m_exit_watcher.get_exit_turn(),
*it, *it,
equals_strategy_type()) ) boundary_checker.strategy()) )
{ {
fake_enter_detected = true; fake_enter_detected = true;
} }
@ -668,14 +656,9 @@ struct linear_linear
Geometry const& geometry, Geometry const& geometry,
OtherGeometry const& other_geometry, OtherGeometry const& other_geometry,
BoundaryChecker const& boundary_checker, BoundaryChecker const& boundary_checker,
OtherBoundaryChecker const& /*other_boundary_checker*/, OtherBoundaryChecker const& other_boundary_checker,
bool first_in_range) 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<Geometry const>::type typename detail::single_geometry_return_type<Geometry const>::type
ls1_ref = detail::single_geometry(geometry, turn.operations[op_id].seg_id); ls1_ref = detail::single_geometry(geometry, turn.operations[op_id].seg_id);
typename detail::single_geometry_return_type<OtherGeometry const>::type typename detail::single_geometry_return_type<OtherGeometry const>::type
@ -745,11 +728,11 @@ struct linear_linear
bool const is_point1 = boost::size(ls1_ref) == 2 bool const is_point1 = boost::size(ls1_ref) == 2
&& equals::equals_point_point(range::front(ls1_ref), && equals::equals_point_point(range::front(ls1_ref),
range::back(ls1_ref), range::back(ls1_ref),
equals_strategy1_type()); boundary_checker.strategy());
bool const is_point2 = boost::size(ls2_ref) == 2 bool const is_point2 = boost::size(ls2_ref) == 2
&& equals::equals_point_point(range::front(ls2_ref), && equals::equals_point_point(range::front(ls2_ref),
range::back(ls2_ref), range::back(ls2_ref),
equals_strategy2_type()); other_boundary_checker.strategy());
// if the second one is degenerated // if the second one is degenerated
if ( !is_point1 && is_point2 ) if ( !is_point1 && is_point2 )

View File

@ -50,21 +50,20 @@ namespace detail { namespace relate
template template
< <
typename Geometry, typename Geometry,
typename EqPPStrategy,
typename Tag = typename tag<Geometry>::type typename Tag = typename tag<Geometry>::type
> >
struct multi_point_geometry_eb struct multi_point_geometry_eb
{ {
template <typename MultiPoint> template <typename MultiPoint, typename Strategy>
static inline bool apply(MultiPoint const& , static inline bool apply(MultiPoint const& ,
detail::relate::topology_check<Geometry, EqPPStrategy> const& ) detail::relate::topology_check<Geometry, Strategy> const& )
{ {
return true; return true;
} }
}; };
template <typename Geometry, typename EqPPStrategy> template <typename Geometry>
struct multi_point_geometry_eb<Geometry, EqPPStrategy, linestring_tag> struct multi_point_geometry_eb<Geometry, linestring_tag>
{ {
template <typename Points> template <typename Points>
struct boundary_visitor struct boundary_visitor
@ -74,26 +73,30 @@ struct multi_point_geometry_eb<Geometry, EqPPStrategy, linestring_tag>
, m_boundary_found(false) , m_boundary_found(false)
{} {}
template <typename Point> template <typename Point, typename Strategy>
struct find_pred struct find_pred
{ {
find_pred(Point const& point) find_pred(Point const& point, Strategy const& strategy)
: m_point(point) : m_point(point)
, m_strategy(strategy)
{} {}
template <typename Pt> template <typename Pt>
bool operator()(Pt const& pt) const 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; Point const& m_point;
Strategy const& m_strategy;
}; };
template <typename Point> template <typename Point, typename Strategy>
bool apply(Point const& boundary_point) bool apply(Point const& boundary_point, Strategy const& strategy)
{ {
if (std::find_if(m_points.begin(), m_points.end(), find_pred<Point>(boundary_point)) == m_points.end()) if ( std::find_if(m_points.begin(), m_points.end(),
find_pred<Point, Strategy>(boundary_point, strategy))
== m_points.end() )
{ {
m_boundary_found = true; m_boundary_found = true;
return false; return false;
@ -108,9 +111,9 @@ struct multi_point_geometry_eb<Geometry, EqPPStrategy, linestring_tag>
bool m_boundary_found; bool m_boundary_found;
}; };
template <typename MultiPoint> template <typename MultiPoint, typename Strategy>
static inline bool apply(MultiPoint const& multi_point, static inline bool apply(MultiPoint const& multi_point,
detail::relate::topology_check<Geometry, EqPPStrategy> const& tc) detail::relate::topology_check<Geometry, Strategy> const& tc)
{ {
boundary_visitor<MultiPoint> visitor(multi_point); boundary_visitor<MultiPoint> visitor(multi_point);
tc.for_each_boundary_point(visitor); tc.for_each_boundary_point(visitor);
@ -118,12 +121,9 @@ struct multi_point_geometry_eb<Geometry, EqPPStrategy, linestring_tag>
} }
}; };
template <typename Geometry, typename EqPPStrategy> template <typename Geometry>
struct multi_point_geometry_eb<Geometry, EqPPStrategy, multi_linestring_tag> struct multi_point_geometry_eb<Geometry, multi_linestring_tag>
{ {
// TODO: CS-specific less compare strategy derived from EqPPStrategy
typedef geometry::less<void, -1, typename EqPPStrategy::cs_tag> less_type;
template <typename Points> template <typename Points>
struct boundary_visitor struct boundary_visitor
{ {
@ -132,10 +132,13 @@ struct multi_point_geometry_eb<Geometry, EqPPStrategy, multi_linestring_tag>
, m_boundary_found(false) , m_boundary_found(false)
{} {}
template <typename Point> template <typename Point, typename Strategy>
bool apply(Point const& boundary_point) 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<void, -1, typename Strategy::cs_tag> less_type;
if (! std::binary_search(m_points.begin(), m_points.end(),
boundary_point, less_type()) )
{ {
m_boundary_found = true; m_boundary_found = true;
return false; return false;
@ -150,12 +153,14 @@ struct multi_point_geometry_eb<Geometry, EqPPStrategy, multi_linestring_tag>
bool m_boundary_found; bool m_boundary_found;
}; };
template <typename MultiPoint> template <typename MultiPoint, typename Strategy>
static inline bool apply(MultiPoint const& multi_point, static inline bool apply(MultiPoint const& multi_point,
detail::relate::topology_check<Geometry, EqPPStrategy> const& tc) detail::relate::topology_check<Geometry, Strategy> const& tc)
{ {
typedef typename boost::range_value<MultiPoint>::type point_type; typedef typename boost::range_value<MultiPoint>::type point_type;
typedef std::vector<point_type> points_type; typedef std::vector<point_type> points_type;
typedef geometry::less<void, -1, typename Strategy::cs_tag> less_type;
points_type points(boost::begin(multi_point), boost::end(multi_point)); points_type points(boost::begin(multi_point), boost::end(multi_point));
std::sort(points.begin(), points.end(), less_type()); std::sort(points.begin(), points.end(), less_type());
@ -179,11 +184,9 @@ struct multi_point_single_geometry
{ {
typedef typename point_type<SingleGeometry>::type point2_type; typedef typename point_type<SingleGeometry>::type point2_type;
typedef model::box<point2_type> box2_type; typedef model::box<point2_type> 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; box2_type box2;
geometry::envelope(single_geometry, box2, strategy.get_envelope_strategy()); geometry::envelope(single_geometry, box2, strategy);
geometry::detail::expand_by_epsilon(box2); geometry::detail::expand_by_epsilon(box2);
typedef typename boost::range_const_iterator<MultiPoint>::type iterator; typedef typename boost::range_const_iterator<MultiPoint>::type iterator;
@ -197,7 +200,7 @@ struct multi_point_single_geometry
} }
// The default strategy is enough for Point/Box // 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<interior, exterior, '0', Transpose>(result); relate::set<interior, exterior, '0', Transpose>(result);
} }
@ -225,14 +228,12 @@ struct multi_point_single_geometry
} }
} }
typedef detail::relate::topology_check typedef detail::relate::topology_check<SingleGeometry, Strategy> tc_t;
<
SingleGeometry, eq_pp_strategy_type
> tc_t;
if ( relate::may_update<exterior, interior, tc_t::interior, Transpose>(result) if ( relate::may_update<exterior, interior, tc_t::interior, Transpose>(result)
|| relate::may_update<exterior, boundary, tc_t::boundary, Transpose>(result) ) || relate::may_update<exterior, boundary, tc_t::boundary, Transpose>(result) )
{ {
tc_t tc(single_geometry); tc_t tc(single_geometry, strategy);
if ( relate::may_update<exterior, interior, tc_t::interior, Transpose>(result) if ( relate::may_update<exterior, interior, tc_t::interior, Transpose>(result)
&& tc.has_interior() ) && tc.has_interior() )
@ -245,10 +246,7 @@ struct multi_point_single_geometry
if ( relate::may_update<exterior, boundary, tc_t::boundary, Transpose>(result) if ( relate::may_update<exterior, boundary, tc_t::boundary, Transpose>(result)
&& tc.has_boundary() ) && tc.has_boundary() )
{ {
if (multi_point_geometry_eb if (multi_point_geometry_eb<SingleGeometry>::apply(multi_point, tc))
<
SingleGeometry, eq_pp_strategy_type
>::apply(multi_point, tc))
{ {
relate::set<exterior, boundary, tc_t::boundary, Transpose>(result); relate::set<exterior, boundary, tc_t::boundary, Transpose>(result);
} }
@ -266,62 +264,88 @@ struct multi_point_single_geometry
template <typename MultiPoint, typename MultiGeometry, bool Transpose> template <typename MultiPoint, typename MultiGeometry, bool Transpose>
class multi_point_multi_geometry_ii_ib class multi_point_multi_geometry_ii_ib
{ {
template <typename ExpandPointStrategy> template <typename Strategy>
struct expand_box_point struct expand_box_point
{ {
expand_box_point(Strategy const& strategy)
: m_strategy(strategy)
{}
template <typename Box, typename Point> template <typename Box, typename Point>
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 <typename ExpandBoxStrategy> template <typename Strategy>
struct expand_box_box_pair struct expand_box_box_pair
{ {
expand_box_box_pair(Strategy const& strategy)
: m_strategy(strategy)
{}
template <typename Box, typename BoxPair> template <typename Box, typename BoxPair>
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 <typename DisjointPointBoxStrategy> template <typename Strategy>
struct overlaps_box_point struct overlaps_box_point
{ {
overlaps_box_point(Strategy const& strategy)
: m_strategy(strategy)
{}
template <typename Box, typename Point> template <typename Box, typename Point>
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 // The default strategy is enough for Point/Box
return ! detail::disjoint::disjoint_point_box(point, box, return ! detail::disjoint::disjoint_point_box(point, box,
DisjointPointBoxStrategy()); m_strategy);
} }
private:
Strategy const& m_strategy;
}; };
template <typename DisjointBoxBoxStrategy> template <typename Strategy>
struct overlaps_box_box_pair struct overlaps_box_box_pair
{ {
overlaps_box_box_pair(Strategy const& strategy)
: m_strategy(strategy)
{}
template <typename Box, typename BoxPair> template <typename Box, typename BoxPair>
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 // The default strategy is enough for Box/Box
return ! detail::disjoint::disjoint_box_box(box_pair.first, box, return ! detail::disjoint::disjoint_box_box(box_pair.first, box,
DisjointBoxBoxStrategy()); m_strategy);
} }
private:
Strategy const& m_strategy;
}; };
template <typename Result, typename PtSegStrategy> template <typename Result, typename Strategy>
class item_visitor_type class item_visitor_type
{ {
typedef typename PtSegStrategy::equals_point_point_strategy_type pp_strategy_type; typedef detail::relate::topology_check<MultiGeometry, Strategy> topology_check_type;
typedef typename PtSegStrategy::disjoint_point_box_strategy_type d_pp_strategy_type;
typedef detail::relate::topology_check<MultiGeometry, pp_strategy_type> topology_check_type;
public: public:
item_visitor_type(MultiGeometry const& multi_geometry, item_visitor_type(MultiGeometry const& multi_geometry,
topology_check_type const& tc, topology_check_type const& tc,
Result & result, Result & result,
PtSegStrategy const& strategy) Strategy const& strategy)
: m_multi_geometry(multi_geometry) : m_multi_geometry(multi_geometry)
, m_tc(tc) , m_tc(tc)
, m_result(result) , m_result(result)
@ -332,7 +356,7 @@ class multi_point_multi_geometry_ii_ib
inline bool apply(Point const& point, BoxPair const& box_pair) inline bool apply(Point const& point, BoxPair const& box_pair)
{ {
// The default strategy is enough for Point/Box // 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<MultiGeometry>::type const& typename boost::range_value<MultiGeometry>::type const&
single = range::at(m_multi_geometry, box_pair.second); 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; MultiGeometry const& m_multi_geometry;
topology_check_type const& m_tc; topology_check_type const& m_tc;
Result & m_result; Result & m_result;
PtSegStrategy const& m_strategy; Strategy const& m_strategy;
}; };
public: public:
@ -387,46 +411,21 @@ public:
std::vector<box_pair_type> const& boxes, std::vector<box_pair_type> const& boxes,
detail::relate::topology_check detail::relate::topology_check
< <
MultiGeometry, MultiGeometry, Strategy
typename Strategy::equals_point_point_strategy_type
> const& tc, > const& tc,
Result & result, Result & result,
Strategy const& strategy) Strategy const& strategy)
{ {
item_visitor_type<Result, Strategy> visitor(multi_geometry, tc, result, strategy); item_visitor_type<Result, Strategy> 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<box1_type>(),
std::declval<box2_type>()))
> expand_box_box_pair_type;
typedef overlaps_box_box_pair
<
typename Strategy::disjoint_box_box_strategy_type
> overlaps_box_box_pair_type;
geometry::partition geometry::partition
< <
box1_type box1_type
>::apply(multi_point, boxes, visitor, >::apply(multi_point, boxes, visitor,
expand_box_point_type(), expand_box_point<Strategy>(strategy),
overlaps_box_point_type(), overlaps_box_point<Strategy>(strategy),
expand_box_box_pair_type(), expand_box_box_pair<Strategy>(strategy),
overlaps_box_box_pair_type()); overlaps_box_box_pair<Strategy>(strategy));
} }
}; };
@ -451,23 +450,18 @@ struct multi_point_multi_geometry_ii_ib_ie
std::vector<box_pair_type> const& boxes, std::vector<box_pair_type> const& boxes,
detail::relate::topology_check detail::relate::topology_check
< <
MultiGeometry, MultiGeometry, Strategy
typename Strategy::equals_point_point_strategy_type
> const& tc, > const& tc,
Result & result, Result & result,
Strategy const& strategy) Strategy const& strategy)
{ {
typedef strategy::index::services::from_strategy
<
Strategy
> index_strategy_from;
typedef index::parameters typedef index::parameters
< <
index::rstar<4>, typename index_strategy_from::type index::rstar<4>, Strategy
> index_parameters_type; > index_parameters_type;
index::rtree<box_pair_type, index_parameters_type> index::rtree<box_pair_type, index_parameters_type>
rtree(boxes.begin(), boxes.end(), 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<MultiPoint>::type iterator; typedef typename boost::range_const_iterator<MultiPoint>::type iterator;
for ( iterator it = boost::begin(multi_point) ; it != boost::end(multi_point) ; ++it ) 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<point2_type> box2_type; typedef model::box<point2_type> box2_type;
typedef std::pair<box2_type, std::size_t> box_pair_type; typedef std::pair<box2_type, std::size_t> 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::size_t count2 = boost::size(multi_geometry);
std::vector<box_pair_type> boxes(count2); std::vector<box_pair_type> boxes(count2);
for (std::size_t i = 0 ; i < count2 ; ++i) 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); geometry::detail::expand_by_epsilon(boxes[i].first);
boxes[i].second = i; boxes[i].second = i;
} }
typedef detail::relate::topology_check<MultiGeometry, eq_pp_strategy_type> tc_t; typedef detail::relate::topology_check<MultiGeometry, Strategy> tc_t;
tc_t tc(multi_geometry); tc_t tc(multi_geometry, strategy);
if ( relate::may_update<interior, interior, '0', Transpose>(result) if ( relate::may_update<interior, interior, '0', Transpose>(result)
|| relate::may_update<interior, boundary, '0', Transpose>(result) || relate::may_update<interior, boundary, '0', Transpose>(result)
@ -590,10 +579,7 @@ struct multi_point_multi_geometry
if ( relate::may_update<exterior, boundary, tc_t::boundary, Transpose>(result) if ( relate::may_update<exterior, boundary, tc_t::boundary, Transpose>(result)
&& tc.has_boundary() ) && tc.has_boundary() )
{ {
if (multi_point_geometry_eb if (multi_point_geometry_eb<MultiGeometry>::apply(multi_point, tc))
<
MultiGeometry, eq_pp_strategy_type
>::apply(multi_point, tc))
{ {
relate::set<exterior, boundary, tc_t::boundary, Transpose>(result); relate::set<exterior, boundary, tc_t::boundary, Transpose>(result);
} }

View File

@ -2,8 +2,8 @@
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. // Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
// This file was modified by Oracle on 2013, 2014, 2015, 2017, 2018. // This file was modified by Oracle on 2013-2020.
// Modifications copyright (c) 2013-2018 Oracle and/or its affiliates. // 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 Adam Wulkiewicz, on behalf of Oracle
@ -60,11 +60,8 @@ struct point_geometry
if ( BOOST_GEOMETRY_CONDITION(result.interrupt) ) if ( BOOST_GEOMETRY_CONDITION(result.interrupt) )
return; return;
typedef detail::relate::topology_check typedef detail::relate::topology_check<Geometry, Strategy> tc_t;
<
Geometry,
typename Strategy::equals_point_point_strategy_type
> tc_t;
if ( relate::may_update<exterior, interior, tc_t::interior, Transpose>(result) if ( relate::may_update<exterior, interior, tc_t::interior, Transpose>(result)
|| relate::may_update<exterior, boundary, tc_t::boundary, Transpose>(result) ) || relate::may_update<exterior, boundary, tc_t::boundary, Transpose>(result) )
{ {
@ -79,7 +76,7 @@ struct point_geometry
else else
{ {
// check if there is a boundary in Geometry // check if there is a boundary in Geometry
tc_t tc(geometry); tc_t tc(geometry, strategy);
if ( tc.has_interior() ) if ( tc.has_interior() )
relate::set<exterior, interior, tc_t::interior, Transpose>(result); relate::set<exterior, interior, tc_t::interior, Transpose>(result);
if ( tc.has_boundary() ) if ( tc.has_boundary() )

View File

@ -18,6 +18,7 @@
#include <algorithm> #include <algorithm>
#include <cstddef> #include <cstddef>
#include <cstring> #include <cstring>
#include <string>
#include <type_traits> #include <type_traits>
#include <boost/throw_exception.hpp> #include <boost/throw_exception.hpp>

View File

@ -1,6 +1,6 @@
// Boost.Geometry (aka GGL, Generic Geometry Library) // 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 // 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" // TODO: change the name for e.g. something with the word "exterior"
template <typename Geometry, template
typename EqPPStrategy, <
typename Tag = typename geometry::tag<Geometry>::type> typename Geometry,
typename Strategy,
typename Tag = typename geometry::tag<Geometry>::type
>
struct topology_check struct topology_check
: not_implemented<Tag> : not_implemented<Tag>
{}; {};
//template <typename Point> //template <typename Point, typename Strategy>
//struct topology_check<Point, point_tag> //struct topology_check<Point, Strategy, point_tag>
//{ //{
// static const char interior = '0'; // static const char interior = '0';
// static const char boundary = 'F'; // static const char boundary = 'F';
@ -49,14 +52,15 @@ struct topology_check
// topology_check(Point const&, IgnoreBoundaryPoint const&) {} // topology_check(Point const&, IgnoreBoundaryPoint const&) {}
//}; //};
template <typename Linestring, typename EqPPStrategy> template <typename Linestring, typename Strategy>
struct topology_check<Linestring, EqPPStrategy, linestring_tag> struct topology_check<Linestring, Strategy, linestring_tag>
{ {
static const char interior = '1'; static const char interior = '1';
static const char boundary = '0'; static const char boundary = '0';
topology_check(Linestring const& ls) topology_check(Linestring const& ls, Strategy const& strategy)
: m_ls(ls) : m_ls(ls)
, m_strategy(strategy)
, m_is_initialized(false) , m_is_initialized(false)
{} {}
@ -87,8 +91,8 @@ struct topology_check<Linestring, EqPPStrategy, linestring_tag>
init(); init();
if (m_has_boundary) if (m_has_boundary)
{ {
if (visitor.apply(range::front(m_ls))) if (visitor.apply(range::front(m_ls), m_strategy))
visitor.apply(range::back(m_ls)); visitor.apply(range::back(m_ls), m_strategy);
} }
} }
@ -104,26 +108,29 @@ private:
m_has_boundary = count > 1 m_has_boundary = count > 1
&& ! detail::equals::equals_point_point(range::front(m_ls), && ! detail::equals::equals_point_point(range::front(m_ls),
range::back(m_ls), range::back(m_ls),
EqPPStrategy()); m_strategy);
m_is_initialized = true; m_is_initialized = true;
} }
Linestring const& m_ls; Linestring const& m_ls;
Strategy const& m_strategy;
mutable bool m_is_initialized; mutable bool m_is_initialized;
mutable bool m_has_interior; mutable bool m_has_interior;
mutable bool m_has_boundary; mutable bool m_has_boundary;
}; };
template <typename MultiLinestring, typename EqPPStrategy> template <typename MultiLinestring, typename Strategy>
struct topology_check<MultiLinestring, EqPPStrategy, multi_linestring_tag> struct topology_check<MultiLinestring, Strategy, multi_linestring_tag>
{ {
static const char interior = '1'; static const char interior = '1';
static const char boundary = '0'; static const char boundary = '0';
topology_check(MultiLinestring const& mls) topology_check(MultiLinestring const& mls, Strategy const& strategy)
: m_mls(mls) : m_mls(mls)
, m_strategy(strategy)
, m_is_initialized(false) , m_is_initialized(false)
{} {}
@ -163,7 +170,7 @@ struct topology_check<MultiLinestring, EqPPStrategy, multi_linestring_tag>
} }
private: private:
typedef geometry::less<void, -1, typename EqPPStrategy::cs_tag> less_type; typedef geometry::less<void, -1, typename Strategy::cs_tag> less_type;
void init() const void init() const
{ {
@ -198,7 +205,7 @@ private:
point_reference back_pt = range::back(ls); point_reference back_pt = range::back(ls);
// don't store boundaries of linear rings, this doesn't change anything // 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 // do not add points containing NaN coordinates
// because they cannot be reasonably compared, e.g. with MSVC // because they cannot be reasonably compared, e.g. with MSVC
@ -236,7 +243,7 @@ private:
} }
template <typename It> template <typename It>
static inline bool find_odd_count(It first, It last) inline bool find_odd_count(It first, It last) const
{ {
interrupting_visitor visitor; interrupting_visitor visitor;
for_each_boundary_point(first, last, visitor); for_each_boundary_point(first, last, visitor);
@ -248,7 +255,7 @@ private:
bool found; bool found;
interrupting_visitor() : found(false) {} interrupting_visitor() : found(false) {}
template <typename Point> template <typename Point>
bool apply(Point const&) bool apply(Point const&, Strategy const&)
{ {
found = true; found = true;
return false; return false;
@ -256,7 +263,7 @@ private:
}; };
template <typename It, typename Visitor> template <typename It, typename Visitor>
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 ) if ( first == last )
return; return;
@ -267,12 +274,12 @@ private:
for ( ; first != last ; ++first, ++prev ) for ( ; first != last ; ++first, ++prev )
{ {
// the end of the equal points subrange // 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 // odd count -> boundary
if ( count % 2 != 0 ) if ( count % 2 != 0 )
{ {
if (! visitor.apply(*prev)) if (! visitor.apply(*prev, m_strategy))
{ {
return; return;
} }
@ -289,12 +296,14 @@ private:
// odd count -> boundary // odd count -> boundary
if ( count % 2 != 0 ) if ( count % 2 != 0 )
{ {
visitor.apply(*prev); visitor.apply(*prev, m_strategy);
} }
} }
private: private:
MultiLinestring const& m_mls; MultiLinestring const& m_mls;
Strategy const& m_strategy;
mutable bool m_is_initialized; mutable bool m_is_initialized;
mutable bool m_has_interior; mutable bool m_has_interior;
@ -313,25 +322,25 @@ struct topology_check_areal
static bool has_boundary() { return true; } static bool has_boundary() { return true; }
}; };
template <typename Ring, typename EqPPStrategy> template <typename Ring, typename Strategy>
struct topology_check<Ring, EqPPStrategy, ring_tag> struct topology_check<Ring, Strategy, ring_tag>
: topology_check_areal : topology_check_areal
{ {
topology_check(Ring const&) {} topology_check(Ring const&, Strategy const&) {}
}; };
template <typename Polygon, typename EqPPStrategy> template <typename Polygon, typename Strategy>
struct topology_check<Polygon, EqPPStrategy, polygon_tag> struct topology_check<Polygon, Strategy, polygon_tag>
: topology_check_areal : topology_check_areal
{ {
topology_check(Polygon const&) {} topology_check(Polygon const&, Strategy const&) {}
}; };
template <typename MultiPolygon, typename EqPPStrategy> template <typename MultiPolygon, typename Strategy>
struct topology_check<MultiPolygon, EqPPStrategy, multi_polygon_tag> struct topology_check<MultiPolygon, Strategy, multi_polygon_tag>
: topology_check_areal : topology_check_areal
{ {
topology_check(MultiPolygon const&) {} topology_check(MultiPolygon const&, Strategy const&) {}
template <typename Point> template <typename Point>
static bool check_boundary_point(Point const& ) { return true; } static bool check_boundary_point(Point const& ) { return true; }

View File

@ -84,43 +84,28 @@ struct get_turns
> type; > type;
}; };
template <typename Turns> template <typename Turns, typename InterruptPolicy, typename Strategy>
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<Geometry1>::type
>::type intersection_strategy;
apply(turns, geometry1, geometry2, interrupt_policy, intersection_strategy);
}
template <typename Turns, typename InterruptPolicy, typename IntersectionStrategy>
static inline void apply(Turns & turns, static inline void apply(Turns & turns,
Geometry1 const& geometry1, Geometry1 const& geometry1,
Geometry2 const& geometry2, Geometry2 const& geometry2,
InterruptPolicy & interrupt_policy, InterruptPolicy & interrupt_policy,
IntersectionStrategy const& intersection_strategy) Strategy const& strategy)
{ {
typedef typename robust_policy_type<IntersectionStrategy>::type robust_policy_t; typedef typename robust_policy_type<Strategy>::type robust_policy_t;
robust_policy_t robust_policy robust_policy_t robust_policy
= geometry::get_rescale_policy<robust_policy_t>( = geometry::get_rescale_policy<robust_policy_t>(
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 <typename Turns, typename InterruptPolicy, typename IntersectionStrategy, typename RobustPolicy> template <typename Turns, typename InterruptPolicy, typename Strategy, typename RobustPolicy>
static inline void apply(Turns & turns, static inline void apply(Turns & turns,
Geometry1 const& geometry1, Geometry1 const& geometry1,
Geometry2 const& geometry2, Geometry2 const& geometry2,
InterruptPolicy & interrupt_policy, InterruptPolicy & interrupt_policy,
IntersectionStrategy const& intersection_strategy, Strategy const& strategy,
RobustPolicy const& robust_policy) RobustPolicy const& robust_policy)
{ {
static const bool reverse1 = detail::overlay::do_reverse static const bool reverse1 = detail::overlay::do_reverse
@ -143,7 +128,7 @@ struct get_turns
reverse2, reverse2,
GetTurnPolicy GetTurnPolicy
>::apply(0, geometry1, 1, geometry2, >::apply(0, geometry1, 1, geometry2,
intersection_strategy, robust_policy, strategy, robust_policy,
turns, interrupt_policy); turns, interrupt_policy);
} }
}; };

View File

@ -57,7 +57,10 @@ struct relation
Matrix Matrix
>::type handler; >::type handler;
resolve_strategy::relate::apply(geometry1, geometry2, handler, strategy); resolve_strategy::relate
<
Strategy
>::apply(geometry1, geometry2, handler, strategy);
return handler.result(); return handler.result();
} }

View File

@ -2,8 +2,8 @@
// Copyright (c) 2015 Barend Gehrels, Amsterdam, the Netherlands. // Copyright (c) 2015 Barend Gehrels, Amsterdam, the Netherlands.
// This file was modified by Oracle on 2018. // This file was modified by Oracle on 2018-2020.
// Modifications copyright (c) 2018, Oracle and/or its affiliates. // Modifications copyright (c) 2018-2020, Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, 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, // Use, modification and distribution is subject to the Boost Software License,
@ -26,28 +26,39 @@ namespace boost { namespace geometry
namespace detail { namespace section namespace detail { namespace section
{ {
template <typename ExpandBoxStrategy> template <typename Strategy>
struct get_section_box struct get_section_box
{ {
get_section_box(Strategy const& strategy)
: m_strategy(strategy)
{}
template <typename Box, typename Section> template <typename Box, typename Section>
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); assert_coordinate_type_equal(total, section.bounding_box);
geometry::expand(total, section.bounding_box, geometry::expand(total, section.bounding_box, m_strategy);
ExpandBoxStrategy());
} }
Strategy const& m_strategy;
}; };
template <typename DisjointBoxBoxStrategy> template <typename Strategy>
struct overlaps_section_box struct overlaps_section_box
{ {
overlaps_section_box(Strategy const& strategy)
: m_strategy(strategy)
{}
template <typename Box, typename Section> template <typename Box, typename Section>
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); assert_coordinate_type_equal(box, section.bounding_box);
return ! detail::disjoint::disjoint_box_box(box, section.bounding_box, return ! detail::disjoint::disjoint_box_box(box, section.bounding_box,
DisjointBoxBoxStrategy()); m_strategy);
} }
Strategy const& m_strategy;
}; };

View File

@ -52,6 +52,7 @@
#include <boost/geometry/core/tags.hpp> #include <boost/geometry/core/tags.hpp>
#include <boost/geometry/geometries/concepts/check.hpp> #include <boost/geometry/geometries/concepts/check.hpp>
#include <boost/geometry/geometries/box.hpp>
#include <boost/geometry/geometries/segment.hpp> #include <boost/geometry/geometries/segment.hpp>
#include <boost/geometry/policies/robustness/no_rescale_policy.hpp> #include <boost/geometry/policies/robustness/no_rescale_policy.hpp>
#include <boost/geometry/policies/robustness/robust_point_type.hpp> #include <boost/geometry/policies/robustness/robust_point_type.hpp>
@ -336,9 +337,9 @@ struct assign_loop<T, Count, Count>
template <typename CSTag> template <typename CSTag>
struct box_first_in_section struct box_first_in_section
{ {
template <typename Box, typename Point, typename EnvelopeStrategy> template <typename Box, typename Point, typename Strategy>
static inline void apply(Box & box, Point const& prev, Point const& curr, static inline void apply(Box & box, Point const& prev, Point const& curr,
EnvelopeStrategy const& strategy) Strategy const& strategy)
{ {
geometry::model::referring_segment<Point const> seg(prev, curr); geometry::model::referring_segment<Point const> seg(prev, curr);
geometry::envelope(seg, box, strategy); geometry::envelope(seg, box, strategy);
@ -348,12 +349,12 @@ struct box_first_in_section
template <> template <>
struct box_first_in_section<cartesian_tag> struct box_first_in_section<cartesian_tag>
{ {
template <typename Box, typename Point, typename ExpandStrategy> template <typename Box, typename Point, typename Strategy>
static inline void apply(Box & box, Point const& prev, Point const& curr, static inline void apply(Box & box, Point const& prev, Point const& curr,
ExpandStrategy const& ) Strategy const& strategy)
{ {
geometry::envelope(prev, box); geometry::envelope(prev, box, strategy);
geometry::expand(box, curr); geometry::expand(box, curr, strategy);
} }
}; };
@ -374,9 +375,9 @@ struct box_next_in_section<cartesian_tag>
{ {
template <typename Box, typename Point, typename Strategy> template <typename Box, typename Point, typename Strategy>
static inline void apply(Box & box, Point const& , Point const& curr, 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 static const std::size_t dimension_count
= util::sequence_size<DimensionVector>::value; = util::sequence_size<DimensionVector>::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<typename Sections::box_type>::type
>::type envelope_strategy_type;
typedef typename strategy::expand::services::default_strategy
<
segment_tag,
typename cs_tag<typename Sections::box_type>::type
>::type expand_strategy_type;
apply(sections, begin, end,
robust_policy,
envelope_strategy_type(),
expand_strategy_type(),
ring_id, max_count);
}
template template
< <
typename Iterator, typename Iterator,
typename RobustPolicy, typename RobustPolicy,
typename Sections, typename Sections,
typename EnvelopeStrategy, typename Strategy
typename ExpandStrategy
> >
static inline void apply(Sections& sections, static inline void apply(Sections& sections,
Iterator begin, Iterator end, Iterator begin, Iterator end,
RobustPolicy const& robust_policy, RobustPolicy const& robust_policy,
EnvelopeStrategy const& envelope_strategy, Strategy const& strategy,
ExpandStrategy const& expand_strategy,
ring_identifier ring_id, ring_identifier ring_id,
std::size_t max_count) std::size_t max_count)
{ {
@ -552,14 +520,14 @@ struct sectionalize_part
// In cartesian this is envelope of previous point expanded with current point // In cartesian this is envelope of previous point expanded with current point
// in non-cartesian this is envelope of a segment // in non-cartesian this is envelope of a segment
box_first_in_section<typename cs_tag<robust_point_type>::type> box_first_in_section<typename cs_tag<robust_point_type>::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 else
{ {
// In cartesian this is expand with current point // In cartesian this is expand with current point
// in non-cartesian this is expand with a segment // in non-cartesian this is expand with a segment
box_next_in_section<typename cs_tag<robust_point_type>::type> box_next_in_section<typename cs_tag<robust_point_type>::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; section.end_index = index + 1;
@ -605,14 +573,12 @@ struct sectionalize_range
typename Range, typename Range,
typename RobustPolicy, typename RobustPolicy,
typename Sections, typename Sections,
typename EnvelopeStrategy, typename Strategy
typename ExpandStrategy
> >
static inline void apply(Range const& range, static inline void apply(Range const& range,
RobustPolicy const& robust_policy, RobustPolicy const& robust_policy,
Sections& sections, Sections& sections,
EnvelopeStrategy const& envelope_strategy, Strategy const& strategy,
ExpandStrategy const& expand_strategy,
ring_identifier ring_id, ring_identifier ring_id,
std::size_t max_count) std::size_t max_count)
{ {
@ -641,7 +607,7 @@ struct sectionalize_range
sectionalize_part<Point, DimensionVector>::apply(sections, sectionalize_part<Point, DimensionVector>::apply(sections,
boost::begin(view), boost::end(view), boost::begin(view), boost::end(view),
robust_policy, envelope_strategy, expand_strategy, robust_policy, strategy,
ring_id, max_count); ring_id, max_count);
} }
}; };
@ -658,27 +624,24 @@ struct sectionalize_polygon
typename Polygon, typename Polygon,
typename RobustPolicy, typename RobustPolicy,
typename Sections, typename Sections,
typename EnvelopeStrategy, typename Strategy
typename ExpandStrategy
> >
static inline void apply(Polygon const& poly, static inline void apply(Polygon const& poly,
RobustPolicy const& robust_policy, RobustPolicy const& robust_policy,
Sections& sections, Sections& sections,
EnvelopeStrategy const& envelope_strategy, Strategy const& strategy,
ExpandStrategy const& expand_strategy,
ring_identifier ring_id, ring_identifier ring_id,
std::size_t max_count) std::size_t max_count)
{ {
typedef typename point_type<Polygon>::type point_type; typedef typename point_type<Polygon>::type point_type;
typedef sectionalize_range typedef sectionalize_range
< <
closure<Polygon>::value, Reverse, closure<Polygon>::value, Reverse, point_type, DimensionVector
point_type, DimensionVector
> per_range; > per_range;
ring_id.ring_index = -1; ring_id.ring_index = -1;
per_range::apply(exterior_ring(poly), robust_policy, sections, 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++; ring_id.ring_index++;
typename interior_return_type<Polygon const>::type typename interior_return_type<Polygon const>::type
@ -687,7 +650,7 @@ struct sectionalize_polygon
it = boost::begin(rings); it != boost::end(rings); ++it, ++ring_id.ring_index) it = boost::begin(rings); it != boost::end(rings); ++it, ++ring_id.ring_index)
{ {
per_range::apply(*it, robust_policy, sections, 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 Box,
typename RobustPolicy, typename RobustPolicy,
typename Sections, typename Sections,
typename EnvelopeStrategy, typename Strategy
typename ExpandStrategy
> >
static inline void apply(Box const& box, static inline void apply(Box const& box,
RobustPolicy const& robust_policy, RobustPolicy const& robust_policy,
Sections& sections, Sections& sections,
EnvelopeStrategy const& envelope_strategy, Strategy const& strategy,
ExpandStrategy const& expand_strategy,
ring_identifier const& ring_id, std::size_t max_count) ring_identifier const& ring_id, std::size_t max_count)
{ {
typedef typename point_type<Box>::type point_type; typedef typename point_type<Box>::type point_type;
@ -736,12 +697,9 @@ struct sectionalize_box
// because edges of a box are not geodesic segments // because edges of a box are not geodesic segments
sectionalize_range sectionalize_range
< <
closed, false, closed, false, point_type, DimensionVector
point_type,
DimensionVector
>::apply(points, robust_policy, sections, >::apply(points, robust_policy, sections,
envelope_strategy, expand_strategy, strategy, ring_id, max_count);
ring_id, max_count);
} }
}; };
@ -753,14 +711,12 @@ struct sectionalize_multi
typename MultiGeometry, typename MultiGeometry,
typename RobustPolicy, typename RobustPolicy,
typename Sections, typename Sections,
typename EnvelopeStrategy, typename Strategy
typename ExpandStrategy
> >
static inline void apply(MultiGeometry const& multi, static inline void apply(MultiGeometry const& multi,
RobustPolicy const& robust_policy, RobustPolicy const& robust_policy,
Sections& sections, Sections& sections,
EnvelopeStrategy const& envelope_strategy, Strategy const& strategy,
ExpandStrategy const& expand_strategy,
ring_identifier ring_id, ring_identifier ring_id,
std::size_t max_count) std::size_t max_count)
{ {
@ -771,7 +727,7 @@ struct sectionalize_multi
++it, ++ring_id.multi_index) ++it, ++ring_id.multi_index)
{ {
Policy::apply(*it, robust_policy, sections, Policy::apply(*it, robust_policy, sections,
envelope_strategy, expand_strategy, strategy,
ring_id, max_count); ring_id, max_count);
} }
} }
@ -983,7 +939,7 @@ struct sectionalize<multi_linestring_tag, MultiLinestring, Reverse, DimensionVec
\param geometry geometry to create sections from \param geometry geometry to create sections from
\param robust_policy policy to handle robustness issues \param robust_policy policy to handle robustness issues
\param sections structure with sections \param sections structure with sections
\param envelope_strategy strategy for envelope calculation \param strategy strategy for envelope calculation
\param expand_strategy strategy for partitions \param expand_strategy strategy for partitions
\param source_index index to assign to the ring_identifiers \param source_index index to assign to the ring_identifiers
\param max_count maximal number of points per section \param max_count maximal number of points per section
@ -997,19 +953,15 @@ template
typename Geometry, typename Geometry,
typename Sections, typename Sections,
typename RobustPolicy, typename RobustPolicy,
typename EnvelopeStrategy, typename Strategy
typename ExpandStrategy
> >
inline void sectionalize(Geometry const& geometry, inline void sectionalize(Geometry const& geometry,
RobustPolicy const& robust_policy, RobustPolicy const& robust_policy,
Sections& sections, Sections& sections,
EnvelopeStrategy const& envelope_strategy, Strategy const& strategy,
ExpandStrategy const& expand_strategy,
int source_index = 0, int source_index = 0,
std::size_t max_count = 10) std::size_t max_count = 10)
{ {
BOOST_STATIC_ASSERT((! std::is_fundamental<EnvelopeStrategy>::value));
concepts::check<Geometry const>(); concepts::check<Geometry const>();
typedef typename boost::range_value<Sections>::type section_type; typedef typename boost::range_value<Sections>::type section_type;
@ -1044,10 +996,10 @@ inline void sectionalize(Geometry const& geometry,
Reverse, Reverse,
DimensionVector DimensionVector
>::apply(geometry, robust_policy, sections, >::apply(geometry, robust_policy, sections,
envelope_strategy, expand_strategy, strategy,
ring_id, max_count); 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, int source_index = 0,
std::size_t max_count = 10) std::size_t max_count = 10)
{ {
typedef typename strategy::envelope::services::default_strategy typedef typename strategies::envelope::services::default_strategy
< <
typename tag<Geometry>::type, Geometry,
typename cs_tag<Geometry>::type model::box<typename point_type<Geometry>::type>
>::type envelope_strategy_type; >::type strategy_type;
typedef typename strategy::expand::services::default_strategy
<
std::conditional_t
<
std::is_same<typename tag<Geometry>::type, box_tag>::value,
box_tag,
segment_tag
>,
typename cs_tag<Geometry>::type
>::type expand_strategy_type;
boost::geometry::sectionalize boost::geometry::sectionalize
< <
Reverse, DimensionVector Reverse, DimensionVector
>(geometry, robust_policy, sections, >(geometry, robust_policy, sections,
envelope_strategy_type(), strategy_type(),
expand_strategy_type(),
source_index, max_count); source_index, max_count);
} }

View File

@ -212,29 +212,24 @@ inline bool point_on_border_within(Geometry1 const& geometry1,
&& geometry::within(pt, geometry2, strategy); && geometry::within(pt, geometry2, strategy);
} }
template <typename FirstGeometry, typename SecondGeometry, typename IntersectionStrategy> template <typename FirstGeometry, typename SecondGeometry, typename Strategy>
inline bool rings_containing(FirstGeometry const& geometry1, inline bool rings_containing(FirstGeometry const& geometry1,
SecondGeometry const& geometry2, 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<FirstGeometry, SecondGeometry>();
return geometry::detail::any_range_of(geometry2, [&](auto const& range) 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 <typename Geometry1, typename Geometry2> template <typename Geometry1, typename Geometry2>
struct areal_areal struct areal_areal
{ {
template <typename IntersectionStrategy> template <typename Strategy>
static inline bool apply(Geometry1 const& geometry1, static inline bool apply(Geometry1 const& geometry1,
Geometry2 const& geometry2, Geometry2 const& geometry2,
IntersectionStrategy const& strategy) Strategy const& strategy)
{ {
typedef typename geometry::point_type<Geometry1>::type point_type; typedef typename geometry::point_type<Geometry1>::type point_type;
typedef detail::overlay::turn_info<point_type> turn_info; typedef detail::overlay::turn_info<point_type> turn_info;
@ -411,7 +406,7 @@ struct self_touches
{ {
concepts::check<Geometry const>(); concepts::check<Geometry const>();
typedef typename strategy::relate::services::default_strategy typedef typename strategies::relate::services::default_strategy
< <
Geometry, Geometry Geometry, Geometry
>::type strategy_type; >::type strategy_type;
@ -430,7 +425,8 @@ struct self_touches
detail::self_get_turn_points::get_turns detail::self_get_turn_points::get_turns
< <
false, policy_type false, policy_type
>::apply(geometry, strategy, detail::no_rescale_policy(), turns, policy, 0, true); >::apply(geometry, strategy, detail::no_rescale_policy(),
turns, policy, 0, true);
return policy.result(); return policy.result();
} }

View File

@ -5,8 +5,8 @@
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK. // Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
// Copyright (c) 2013-2015 Adam Wulkiewicz, Lodz, Poland. // Copyright (c) 2013-2015 Adam Wulkiewicz, Lodz, Poland.
// This file was modified by Oracle on 2013, 2014, 2015, 2017. // This file was modified by Oracle on 2013-2021.
// Modifications copyright (c) 2013-2017, Oracle and/or its affiliates. // 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 Adam Wulkiewicz, on behalf of Oracle
@ -35,7 +35,8 @@
#include <boost/geometry/geometries/concepts/check.hpp> #include <boost/geometry/geometries/concepts/check.hpp>
#include <boost/geometry/strategies/default_strategy.hpp> #include <boost/geometry/strategies/default_strategy.hpp>
#include <boost/geometry/strategies/relate.hpp> #include <boost/geometry/strategies/detail.hpp>
#include <boost/geometry/strategies/relate/services.hpp>
namespace boost { namespace geometry namespace boost { namespace geometry
@ -84,9 +85,14 @@ struct touches<Geometry1, Geometry2, Tag1, Tag2, CastedTag1, CastedTag2, true>
namespace resolve_strategy namespace resolve_strategy
{ {
template
<
typename Strategy,
bool IsUmbrella = strategies::detail::is_umbrella_strategy<Strategy>::value
>
struct touches struct touches
{ {
template <typename Geometry1, typename Geometry2, typename Strategy> template <typename Geometry1, typename Geometry2>
static inline bool apply(Geometry1 const& geometry1, static inline bool apply(Geometry1 const& geometry1,
Geometry2 const& geometry2, Geometry2 const& geometry2,
Strategy const& strategy) Strategy const& strategy)
@ -96,13 +102,35 @@ struct touches
Geometry1, Geometry2 Geometry1, Geometry2
>::apply(geometry1, geometry2, strategy); >::apply(geometry1, geometry2, strategy);
} }
};
template <typename Strategy>
struct touches<Strategy, false>
{
template <typename Geometry1, typename Geometry2>
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<Strategy>::get(strategy));
}
};
template <>
struct touches<default_strategy, false>
{
template <typename Geometry1, typename Geometry2> template <typename Geometry1, typename Geometry2>
static inline bool apply(Geometry1 const& geometry1, static inline bool apply(Geometry1 const& geometry1,
Geometry2 const& geometry2, Geometry2 const& geometry2,
default_strategy) default_strategy)
{ {
typedef typename strategy::relate::services::default_strategy typedef typename strategies::relate::services::default_strategy
< <
Geometry1, Geometry1,
Geometry2 Geometry2
@ -129,7 +157,10 @@ struct touches
concepts::check<Geometry1 const>(); concepts::check<Geometry1 const>();
concepts::check<Geometry2 const>(); concepts::check<Geometry2 const>();
return resolve_strategy::touches::apply(geometry1, geometry2, strategy); return resolve_strategy::touches
<
Strategy
>::apply(geometry1, geometry2, strategy);
} }
}; };

View File

@ -88,8 +88,7 @@ struct within<Point, Box, point_tag, box_tag>
template <typename Strategy> template <typename Strategy>
static inline bool apply(Point const& point, Box const& box, Strategy const& strategy) static inline bool apply(Point const& point, Box const& box, Strategy const& strategy)
{ {
boost::ignore_unused(strategy); return strategy.within(point, box).apply(point, box);
return strategy.apply(point, box);
} }
}; };
@ -100,8 +99,7 @@ struct within<Box1, Box2, box_tag, box_tag>
static inline bool apply(Box1 const& box1, Box2 const& box2, Strategy const& strategy) static inline bool apply(Box1 const& box1, Box2 const& box2, Strategy const& strategy)
{ {
assert_dimension_equal<Box1, Box2>(); assert_dimension_equal<Box1, Box2>();
boost::ignore_unused(strategy); return strategy.within(box1, box2).apply(box1, box2);
return strategy.apply(box1, box2);
} }
}; };

View File

@ -4,9 +4,8 @@
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France. // Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK. // Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
// This file was modified by Oracle on 2013, 2014, 2017, 2018. // This file was modified by Oracle on 2013-2021.
// Modifications copyright (c) 2013-2018 Oracle and/or its affiliates. // 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 Adam Wulkiewicz, on behalf of Oracle
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library // Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
@ -34,7 +33,8 @@
#include <boost/geometry/geometries/concepts/check.hpp> #include <boost/geometry/geometries/concepts/check.hpp>
#include <boost/geometry/strategies/concepts/within_concept.hpp> #include <boost/geometry/strategies/concepts/within_concept.hpp>
#include <boost/geometry/strategies/default_strategy.hpp> #include <boost/geometry/strategies/default_strategy.hpp>
#include <boost/geometry/strategies/within.hpp> #include <boost/geometry/strategies/detail.hpp>
#include <boost/geometry/strategies/relate/services.hpp>
namespace boost { namespace geometry namespace boost { namespace geometry
@ -63,30 +63,63 @@ struct within
namespace resolve_strategy namespace resolve_strategy
{ {
template
<
typename Strategy,
bool IsUmbrella = strategies::detail::is_umbrella_strategy<Strategy>::value
>
struct within struct within
{ {
template <typename Geometry1, typename Geometry2, typename Strategy> template <typename Geometry1, typename Geometry2>
static inline bool apply(Geometry1 const& geometry1, static inline bool apply(Geometry1 const& geometry1,
Geometry2 const& geometry2, Geometry2 const& geometry2,
Strategy const& strategy) Strategy const& strategy)
{ {
concepts::within::check<Geometry1, Geometry2, Strategy>(); concepts::within::check<Geometry1, Geometry2, Strategy>();
return dispatch::within<Geometry1, Geometry2>::apply(geometry1, geometry2, strategy); return dispatch::within
<
Geometry1, Geometry2
>::apply(geometry1, geometry2, strategy);
} }
};
template <typename Strategy>
struct within<Strategy, false>
{
template <typename Geometry1, typename Geometry2>
static inline bool apply(Geometry1 const& geometry1,
Geometry2 const& geometry2,
Strategy const& strategy)
{
using strategies::relate::services::strategy_converter;
return within
<
decltype(strategy_converter<Strategy>::get(strategy))
>::apply(geometry1, geometry2,
strategy_converter<Strategy>::get(strategy));
}
};
template <>
struct within<default_strategy, false>
{
template <typename Geometry1, typename Geometry2> template <typename Geometry1, typename Geometry2>
static inline bool apply(Geometry1 const& geometry1, static inline bool apply(Geometry1 const& geometry1,
Geometry2 const& geometry2, Geometry2 const& geometry2,
default_strategy) default_strategy)
{ {
typedef typename strategy::within::services::default_strategy typedef typename strategies::relate::services::default_strategy
< <
Geometry1, Geometry1,
Geometry2 Geometry2
>::type strategy_type; >::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<Geometry2 const>(); concepts::check<Geometry2 const>();
assert_dimension_equal<Geometry1, Geometry2>(); assert_dimension_equal<Geometry1, Geometry2>();
return resolve_strategy::within::apply(geometry1, return resolve_strategy::within
geometry2, <
strategy); Strategy
>::apply(geometry1, geometry2, strategy);
} }
}; };

View File

@ -1,7 +1,6 @@
// Boost.Geometry // Boost.Geometry
// Copyright (c) 2017-2020, Oracle and/or its affiliates. // Copyright (c) 2017-2020, Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, 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, // Use, modification and distribution is subject to the Boost Software License,
@ -54,10 +53,12 @@ struct multi_point_point
Point const& point, Point const& point,
Strategy const& strategy) Strategy const& strategy)
{ {
auto const s = strategy.relate(multi_point, point);
typedef typename boost::range_const_iterator<MultiPoint>::type iterator; typedef typename boost::range_const_iterator<MultiPoint>::type iterator;
for ( iterator it = boost::begin(multi_point) ; it != boost::end(multi_point) ; ++it ) 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; return false;
} }
@ -126,11 +127,9 @@ struct multi_point_single_geometry
// Create envelope of geometry // Create envelope of geometry
box2_type box; 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); 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 // Test each Point with envelope and then geometry if needed
// If in the exterior, break // If in the exterior, break
bool result = false; bool result = false;
@ -138,6 +137,8 @@ struct multi_point_single_geometry
typedef typename boost::range_const_iterator<MultiPoint>::type iterator; typedef typename boost::range_const_iterator<MultiPoint>::type iterator;
for ( iterator it = boost::begin(multi_point) ; it != boost::end(multi_point) ; ++it ) for ( iterator it = boost::begin(multi_point) ; it != boost::end(multi_point) ; ++it )
{ {
typedef decltype(strategy.covered_by(*it, box)) point_in_box_type;
int in_val = 0; int in_val = 0;
// exterior of box and of geometry // exterior of box and of geometry
@ -173,9 +174,6 @@ struct multi_point_multi_geometry
typedef model::box<point2_type> box2_type; typedef model::box<point2_type> box2_type;
static const bool is_linear = util::is_linear<LinearOrAreal>::value; static const bool is_linear = util::is_linear<LinearOrAreal>::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 // TODO: box pairs could be constructed on the fly, inside the rtree
// Prepare range of envelopes and ids // Prepare range of envelopes and ids
@ -185,23 +183,16 @@ struct multi_point_multi_geometry
box_pair_vector boxes(count2); box_pair_vector boxes(count2);
for (std::size_t i = 0 ; i < count2 ; ++i) 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); geometry::detail::expand_by_epsilon(boxes[i].first);
boxes[i].second = i; boxes[i].second = i;
} }
// Create R-tree // Create R-tree
typedef strategy::index::services::from_strategy typedef index::parameters<index::rstar<4>, Strategy> index_parameters_type;
<
Strategy
> index_strategy_from;
typedef index::parameters
<
index::rstar<4>, typename index_strategy_from::type
> index_parameters_type;
index::rtree<box_pair_type, index_parameters_type> index::rtree<box_pair_type, index_parameters_type>
rtree(boxes.begin(), boxes.end(), 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 // For each point find overlapping envelopes and test corresponding single geometries
// If a point is in the exterior break // If a point is in the exterior break

View File

@ -7,7 +7,6 @@
// This file was modified by Oracle on 2013-2020. // This file was modified by Oracle on 2013-2020.
// Modifications copyright (c) 2013-2020, Oracle and/or its affiliates. // 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 Adam Wulkiewicz, on behalf of Oracle
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library // Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
@ -34,8 +33,6 @@
#include <boost/geometry/geometries/concepts/check.hpp> #include <boost/geometry/geometries/concepts/check.hpp>
#include <boost/geometry/strategies/concepts/within_concept.hpp> #include <boost/geometry/strategies/concepts/within_concept.hpp>
#include <boost/geometry/strategies/default_strategy.hpp>
#include <boost/geometry/strategies/relate.hpp>
#include <boost/geometry/util/range.hpp> #include <boost/geometry/util/range.hpp>
#include <boost/geometry/views/detail/normalized_view.hpp> #include <boost/geometry/views/detail/normalized_view.hpp>
@ -45,32 +42,13 @@ namespace boost { namespace geometry {
#ifndef DOXYGEN_NO_DETAIL #ifndef DOXYGEN_NO_DETAIL
namespace detail { namespace within { namespace detail { namespace within {
template <typename Point1, typename Point2, typename Strategy>
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 <typename T>
inline T check_result_type(T result)
{
BOOST_GEOMETRY_ASSERT(false);
return result;
}
template <typename Point, typename Range, typename Strategy> inline template <typename Point, typename Range, typename Strategy> inline
int point_in_range(Point const& point, Range const& range, Strategy const& strategy) 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<Range const>::type iterator_type; typedef typename boost::range_iterator<Range const>::type iterator_type;
typename Strategy::state_type state;
iterator_type it = boost::begin(range); iterator_type it = boost::begin(range);
iterator_type end = boost::end(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)); return strategy.result(state);
}
template <typename Geometry, typename Point, typename Range>
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());
} }
}} // namespace detail::within }} // namespace detail::within
@ -117,8 +84,8 @@ struct point_in_geometry<Point2, point_tag>
template <typename Point1, typename Strategy> static inline template <typename Point1, typename Strategy> static inline
int apply(Point1 const& point1, Point2 const& point2, Strategy const& strategy) int apply(Point1 const& point1, Point2 const& point2, Strategy const& strategy)
{ {
boost::ignore_unused(strategy); typedef decltype(strategy.relate(point1, point2)) strategy_type;
return strategy.apply(point1, point2) ? 1 : -1; return strategy_type::apply(point1, point2) ? 1 : -1;
} }
}; };
@ -128,24 +95,23 @@ struct point_in_geometry<Segment, segment_tag>
template <typename Point, typename Strategy> static inline template <typename Point, typename Strategy> static inline
int apply(Point const& point, Segment const& segment, Strategy const& strategy) int apply(Point const& point, Segment const& segment, Strategy const& strategy)
{ {
boost::ignore_unused(strategy);
typedef typename geometry::point_type<Segment>::type point_type; typedef typename geometry::point_type<Segment>::type point_type;
point_type p0, p1; point_type p0, p1;
// TODO: don't copy points // TODO: don't copy points
detail::assign_point_from_index<0>(segment, p0); detail::assign_point_from_index<0>(segment, p0);
detail::assign_point_from_index<1>(segment, p1); detail::assign_point_from_index<1>(segment, p1);
typename Strategy::state_type state; auto const s = strategy.relate(point, segment);
strategy.apply(point, p0, p1, state); typename decltype(s)::state_type state;
int r = detail::within::check_result_type(strategy.result(state)); s.apply(point, p0, p1, state);
int r = s.result(state);
if ( r != 0 ) if ( r != 0 )
return -1; // exterior return -1; // exterior
// if the point is equal to the one of the terminal points // if the point is equal to the one of the terminal points
if ( detail::within::equals_point_point(point, p0, strategy) if ( detail::equals::equals_point_point(point, p0, strategy)
|| detail::within::equals_point_point(point, p1, strategy) ) || detail::equals::equals_point_point(point, p1, strategy) )
return 0; // boundary return 0; // boundary
else else
return 1; // interior return 1; // interior
@ -162,24 +128,37 @@ struct point_in_geometry<Linestring, linestring_tag>
std::size_t count = boost::size(linestring); std::size_t count = boost::size(linestring);
if ( count > 1 ) 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 return -1; // exterior
}
typedef typename boost::range_value<Linestring>::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 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 return 1; // interior
}
// else if the point is equal to the one of the terminal points // 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) else if ( detail::equals::equals_point_point(point, front, strategy)
|| detail::within::equals_point_point(point, range::back(linestring), strategy)) || detail::equals::equals_point_point(point, back, strategy) )
{
return 0; // boundary return 0; // boundary
}
else else
{
return 1; // interior return 1; // interior
} }
}
// TODO: for now degenerated linestrings are ignored // TODO: for now degenerated linestrings are ignored
// throw an exception here? // throw an exception here?
/*else if ( count == 1 ) /*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; return 1;
}*/ }*/
@ -202,7 +181,8 @@ struct point_in_geometry<Ring, ring_tag>
} }
detail::normalized_view<Ring const> view(ring); detail::normalized_view<Ring const> 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<Geometry, multi_linestring_tag>
point_type const& back = range::back(*it); point_type const& back = range::back(*it);
// is closed_ring - no boundary // is closed_ring - no boundary
if ( detail::within::equals_point_point(front, back, strategy) ) if ( detail::equals::equals_point_point(front, back, strategy) )
continue; continue;
// is point on boundary // is point on boundary
if ( detail::within::equals_point_point(point, front, strategy) if ( detail::equals::equals_point_point(point, front, strategy)
|| detail::within::equals_point_point(point, back, strategy) ) || detail::equals::equals_point_point(point, back, strategy) )
{ {
++boundaries; ++boundaries;
} }
@ -371,41 +351,18 @@ inline int point_in_geometry(Point const& point, Geometry const& geometry, Strat
return detail_dispatch::within::point_in_geometry<Geometry>::apply(point, geometry, strategy); return detail_dispatch::within::point_in_geometry<Geometry>::apply(point, geometry, strategy);
} }
template <typename Point, typename Geometry>
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 <typename Point, typename Geometry, typename Strategy> template <typename Point, typename Geometry, typename Strategy>
inline bool within_point_geometry(Point const& point, Geometry const& geometry, Strategy const& strategy) inline bool within_point_geometry(Point const& point, Geometry const& geometry, Strategy const& strategy)
{ {
return point_in_geometry(point, geometry, strategy) > 0; return point_in_geometry(point, geometry, strategy) > 0;
} }
template <typename Point, typename Geometry>
inline bool within_point_geometry(Point const& point, Geometry const& geometry)
{
return point_in_geometry(point, geometry) > 0;
}
template <typename Point, typename Geometry, typename Strategy> template <typename Point, typename Geometry, typename Strategy>
inline bool covered_by_point_geometry(Point const& point, Geometry const& geometry, Strategy const& strategy) inline bool covered_by_point_geometry(Point const& point, Geometry const& geometry, Strategy const& strategy)
{ {
return point_in_geometry(point, geometry, strategy) >= 0; return point_in_geometry(point, geometry, strategy) >= 0;
} }
template <typename Point, typename Geometry>
inline bool covered_by_point_geometry(Point const& point, Geometry const& geometry)
{
return point_in_geometry(point, geometry) >= 0;
}
}} // namespace detail::within }} // namespace detail::within
#endif // DOXYGEN_NO_DETAIL #endif // DOXYGEN_NO_DETAIL

View File

@ -2,7 +2,7 @@
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. // 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. // Modifications copyright (c) 2017-2020, Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@ -23,6 +23,8 @@
#include <boost/geometry/algorithms/detail/overlay/intersection_insert.hpp> #include <boost/geometry/algorithms/detail/overlay/intersection_insert.hpp>
#include <boost/geometry/policies/robustness/get_rescale_policy.hpp> #include <boost/geometry/policies/robustness/get_rescale_policy.hpp>
#include <boost/geometry/strategies/default_strategy.hpp> #include <boost/geometry/strategies/default_strategy.hpp>
#include <boost/geometry/strategies/detail.hpp>
#include <boost/geometry/strategies/relate/services.hpp>
#include <boost/geometry/util/range.hpp> #include <boost/geometry/util/range.hpp>
@ -253,7 +255,7 @@ inline OutputIterator difference_insert(Geometry1 const& geometry1,
Geometry2 const& geometry2, Geometry2 const& geometry2,
OutputIterator out) OutputIterator out)
{ {
typedef typename strategy::relate::services::default_strategy typedef typename strategies::relate::services::default_strategy
< <
Geometry1, Geometry1,
Geometry2 Geometry2
@ -270,15 +272,14 @@ inline OutputIterator difference_insert(Geometry1 const& geometry1,
namespace resolve_strategy { namespace resolve_strategy {
template
<
typename Strategy,
bool IsUmbrella = strategies::detail::is_umbrella_strategy<Strategy>::value
>
struct difference struct difference
{ {
template template <typename Geometry1, typename Geometry2, typename Collection>
<
typename Geometry1,
typename Geometry2,
typename Collection,
typename Strategy
>
static inline void apply(Geometry1 const& geometry1, static inline void apply(Geometry1 const& geometry1,
Geometry2 const& geometry2, Geometry2 const& geometry2,
Collection & output_collection, Collection & output_collection,
@ -294,25 +295,46 @@ struct difference
geometry::detail::output_geometry_back_inserter(output_collection), geometry::detail::output_geometry_back_inserter(output_collection),
strategy); strategy);
} }
};
template template <typename Strategy>
struct difference<Strategy, false>
{
template <typename Geometry1, typename Geometry2, typename Collection>
static inline void apply(Geometry1 const& geometry1,
Geometry2 const& geometry2,
Collection & output_collection,
Strategy const& strategy)
{
using strategies::relate::services::strategy_converter;
difference
< <
typename Geometry1, decltype(strategy_converter<Strategy>::get(strategy))
typename Geometry2, >::apply(geometry1, geometry2, output_collection,
typename Collection strategy_converter<Strategy>::get(strategy));
> }
};
template <>
struct difference<default_strategy, false>
{
template <typename Geometry1, typename Geometry2, typename Collection>
static inline void apply(Geometry1 const& geometry1, static inline void apply(Geometry1 const& geometry1,
Geometry2 const& geometry2, Geometry2 const& geometry2,
Collection & output_collection, Collection & output_collection,
default_strategy) default_strategy)
{ {
typedef typename strategy::relate::services::default_strategy typedef typename strategies::relate::services::default_strategy
< <
Geometry1, Geometry1,
Geometry2 Geometry2
>::type strategy_type; >::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, Collection& output_collection,
Strategy const& strategy) Strategy const& strategy)
{ {
resolve_strategy::difference::apply(geometry1, geometry2, resolve_strategy::difference
output_collection, <
strategy); Strategy
>::apply(geometry1, geometry2, output_collection, strategy);
} }
}; };

View File

@ -2,7 +2,7 @@
// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands. // 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. // 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 Menelaos Karavelas, on behalf of Oracle
@ -29,7 +29,8 @@
#include <boost/geometry/geometries/multi_polygon.hpp> #include <boost/geometry/geometries/multi_polygon.hpp>
#include <boost/geometry/policies/robustness/get_rescale_policy.hpp> #include <boost/geometry/policies/robustness/get_rescale_policy.hpp>
#include <boost/geometry/strategies/default_strategy.hpp> #include <boost/geometry/strategies/default_strategy.hpp>
#include <boost/geometry/strategies/relate.hpp> #include <boost/geometry/strategies/detail.hpp>
#include <boost/geometry/strategies/relate/services.hpp>
#include <boost/geometry/util/range.hpp> #include <boost/geometry/util/range.hpp>
@ -497,9 +498,9 @@ template
inline OutputIterator sym_difference_insert(Geometry1 const& geometry1, inline OutputIterator sym_difference_insert(Geometry1 const& geometry1,
Geometry2 const& geometry2, OutputIterator out) Geometry2 const& geometry2, OutputIterator out)
{ {
typedef typename strategy::intersection::services::default_strategy typedef typename strategies::relate::services::default_strategy
< <
typename cs_tag<GeometryOut>::type Geometry1, Geometry2
>::type strategy_type; >::type strategy_type;
return sym_difference_insert<GeometryOut>(geometry1, geometry2, out, strategy_type()); return sym_difference_insert<GeometryOut>(geometry1, geometry2, out, strategy_type());
@ -511,15 +512,14 @@ inline OutputIterator sym_difference_insert(Geometry1 const& geometry1,
namespace resolve_strategy { namespace resolve_strategy {
template
<
typename Strategy,
bool IsUmbrella = strategies::detail::is_umbrella_strategy<Strategy>::value
>
struct sym_difference struct sym_difference
{ {
template template <typename Geometry1, typename Geometry2, typename Collection>
<
typename Geometry1,
typename Geometry2,
typename Collection,
typename Strategy
>
static inline void apply(Geometry1 const& geometry1, static inline void apply(Geometry1 const& geometry1,
Geometry2 const& geometry2, Geometry2 const& geometry2,
Collection & output_collection, Collection & output_collection,
@ -535,13 +535,31 @@ struct sym_difference
geometry::detail::output_geometry_back_inserter(output_collection), geometry::detail::output_geometry_back_inserter(output_collection),
strategy); strategy);
} }
};
template template <typename Strategy>
struct sym_difference<Strategy, false>
{
template <typename Geometry1, typename Geometry2, typename Collection>
static inline void apply(Geometry1 const& geometry1,
Geometry2 const& geometry2,
Collection & output_collection,
Strategy const& strategy)
{
using strategies::relate::services::strategy_converter;
sym_difference
< <
typename Geometry1, decltype(strategy_converter<Strategy>::get(strategy))
typename Geometry2, >::apply(geometry1, geometry2, output_collection,
typename Collection strategy_converter<Strategy>::get(strategy));
> }
};
template <>
struct sym_difference<default_strategy, false>
{
template <typename Geometry1, typename Geometry2, typename Collection>
static inline void apply(Geometry1 const& geometry1, static inline void apply(Geometry1 const& geometry1,
Geometry2 const& geometry2, Geometry2 const& geometry2,
Collection & output_collection, Collection & output_collection,
@ -552,7 +570,10 @@ struct sym_difference
Geometry1, Geometry2 Geometry1, Geometry2
>::type strategy_type; >::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, Collection& output_collection,
Strategy const& strategy) Strategy const& strategy)
{ {
resolve_strategy::sym_difference::apply(geometry1, geometry2, resolve_strategy::sym_difference
output_collection, <
strategy); Strategy
>::apply(geometry1, geometry2, output_collection, strategy);
} }
}; };

View File

@ -18,13 +18,15 @@
#include <boost/range/value_type.hpp> #include <boost/range/value_type.hpp>
#include <boost/geometry/algorithms/not_implemented.hpp>
#include <boost/geometry/algorithms/detail/overlay/overlay.hpp>
#include <boost/geometry/core/point_order.hpp> #include <boost/geometry/core/point_order.hpp>
#include <boost/geometry/core/reverse_dispatch.hpp> #include <boost/geometry/core/reverse_dispatch.hpp>
#include <boost/geometry/geometries/concepts/check.hpp> #include <boost/geometry/geometries/concepts/check.hpp>
#include <boost/geometry/algorithms/not_implemented.hpp>
#include <boost/geometry/algorithms/detail/overlay/overlay.hpp>
#include <boost/geometry/policies/robustness/get_rescale_policy.hpp> #include <boost/geometry/policies/robustness/get_rescale_policy.hpp>
#include <boost/geometry/strategies/default_strategy.hpp> #include <boost/geometry/strategies/default_strategy.hpp>
#include <boost/geometry/strategies/detail.hpp>
#include <boost/geometry/strategies/relate/services.hpp>
#include <boost/geometry/util/range.hpp> #include <boost/geometry/util/range.hpp>
#include <boost/geometry/algorithms/detail/intersection/multi.hpp> #include <boost/geometry/algorithms/detail/intersection/multi.hpp>
@ -349,9 +351,9 @@ inline OutputIterator union_insert(Geometry1 const& geometry1,
concepts::check<Geometry2 const>(); concepts::check<Geometry2 const>();
geometry::detail::output_geometry_concept_check<GeometryOut>::apply(); geometry::detail::output_geometry_concept_check<GeometryOut>::apply();
typename strategy::intersection::services::default_strategy typename strategies::relate::services::default_strategy
< <
typename cs_tag<GeometryOut>::type Geometry1, Geometry2
>::type strategy; >::type strategy;
typedef typename geometry::rescale_overlay_policy_type typedef typename geometry::rescale_overlay_policy_type
@ -377,15 +379,14 @@ inline OutputIterator union_insert(Geometry1 const& geometry1,
namespace resolve_strategy { namespace resolve_strategy {
template
<
typename Strategy,
bool IsUmbrella = strategies::detail::is_umbrella_strategy<Strategy>::value
>
struct union_ struct union_
{ {
template template <typename Geometry1, typename Geometry2, typename Collection>
<
typename Geometry1,
typename Geometry2,
typename Collection,
typename Strategy
>
static inline void apply(Geometry1 const& geometry1, static inline void apply(Geometry1 const& geometry1,
Geometry2 const& geometry2, Geometry2 const& geometry2,
Collection & output_collection, Collection & output_collection,
@ -414,25 +415,46 @@ struct union_
geometry::detail::output_geometry_back_inserter(output_collection), geometry::detail::output_geometry_back_inserter(output_collection),
strategy); strategy);
} }
};
template template <typename Strategy>
struct union_<Strategy, false>
{
template <typename Geometry1, typename Geometry2, typename Collection>
static inline void apply(Geometry1 const& geometry1,
Geometry2 const& geometry2,
Collection & output_collection,
Strategy const& strategy)
{
using strategies::relate::services::strategy_converter;
union_
< <
typename Geometry1, decltype(strategy_converter<Strategy>::get(strategy))
typename Geometry2, >::apply(geometry1, geometry2, output_collection,
typename Collection strategy_converter<Strategy>::get(strategy));
> }
};
template <>
struct union_<default_strategy, false>
{
template <typename Geometry1, typename Geometry2, typename Collection>
static inline void apply(Geometry1 const& geometry1, static inline void apply(Geometry1 const& geometry1,
Geometry2 const& geometry2, Geometry2 const& geometry2,
Collection & output_collection, Collection & output_collection,
default_strategy) default_strategy)
{ {
typedef typename strategy::relate::services::default_strategy typedef typename strategies::relate::services::default_strategy
< <
Geometry1, Geometry1,
Geometry2 Geometry2
>::type strategy_type; >::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 >::type
>::apply(); >::apply();
resolve_strategy::union_::apply(geometry1, geometry2, resolve_strategy::union_
output_collection, <
strategy); Strategy
>::apply(geometry1, geometry2, output_collection, strategy);
} }
}; };

View File

@ -433,7 +433,7 @@ struct dissolver_generic
// There are less then 16 elements, handle them quadraticly // There are less then 16 elements, handle them quadraticly
int n = boost::size(output_collection); std::size_t n = boost::size(output_collection);
for(iterator_type it1 = boost::begin(index_vector); for(iterator_type it1 = boost::begin(index_vector);
it1 != boost::end(index_vector); it1 != boost::end(index_vector);
@ -520,7 +520,7 @@ struct dissolver_generic
boost::end(output_collection)), boost::end(output_collection)),
helper_vector, helper_vector,
strategy, strategy,
n, 1); static_cast<int>(n), 1);
return changed; return changed;
} }
@ -577,8 +577,8 @@ struct dissolver_generic
std::vector<output_type> unioned_collection; std::vector<output_type> unioned_collection;
int size = 0, previous_size = 0; std::size_t size = 0, previous_size = 0;
int n = 0; std::size_t n = 0;
bool changed = false; bool changed = false;
while(divide_and_conquer<1> while(divide_and_conquer<1>

View File

@ -418,6 +418,72 @@ struct dissolve<Polygon, PolygonOut, Reverse, polygon_tag, polygon_tag>
#endif // DOXYGEN_NO_DISPATCH #endif // DOXYGEN_NO_DISPATCH
namespace resolve_strategy
{
template
<
typename GeometryOut,
typename Strategy,
bool IsUmbrella = strategies::detail::is_umbrella_strategy<Strategy>::value
>
struct dissolve
{
template
<
typename Geometry, typename RescalePolicy, typename OutputIterator,
typename Strategy, typename Visitor
>
static inline OutputIterator apply(Geometry const& geometry,
RescalePolicy const& rescale_policy,
OutputIterator out,
Strategy const& strategy,
Visitor& visitor)
{
dispatch::dissolve
<
Geometry,
GeometryOut,
detail::overlay::do_reverse
<
geometry::point_order<Geometry>::value
>::value
>::apply(geometry, rescale_policy, out, strategy, visitor);
}
};
template <typename GeometryOut, typename Strategy>
struct dissolve<GeometryOut, Strategy, false>
{
template
<
typename Geometry, typename RescalePolicy, typename OutputIterator,
typename Strategy, typename Visitor
>
static inline OutputIterator apply(Geometry const& geometry,
RescalePolicy const& rescale_policy,
OutputIterator out,
Strategy const& strategy,
Visitor& visitor)
{
using strategies::relate::services::strategy_converter;
dispatch::dissolve
<
Geometry,
GeometryOut,
detail::overlay::do_reverse
<
geometry::point_order<Geometry>::value
>::value
>::apply(geometry, rescale_policy, out,
strategy_converter<Strategy>::get(strategy),
visitor);
}
};
} // namespace resolve_strategy
/*! /*!
\brief Removes self intersections from a geometry \brief Removes self intersections from a geometry
@ -450,7 +516,8 @@ inline OutputIterator dissolve_inserter(Geometry const& geometry,
typedef typename geometry::rescale_policy_type typedef typename geometry::rescale_policy_type
< <
typename geometry::point_type<Geometry>::type typename geometry::point_type<Geometry>::type,
typename Strategy::cs_tag
>::type rescale_policy_type; >::type rescale_policy_type;
rescale_policy_type robust_policy rescale_policy_type robust_policy
@ -459,14 +526,9 @@ inline OutputIterator dissolve_inserter(Geometry const& geometry,
detail::overlay::overlay_null_visitor visitor; detail::overlay::overlay_null_visitor visitor;
return dispatch::dissolve return resolve_strategy::dissolve
< <
Geometry, GeometryOut, Strategy
GeometryOut,
detail::overlay::do_reverse
<
geometry::point_order<Geometry>::value
>::value
>::apply(geometry, robust_policy, out, strategy, visitor); >::apply(geometry, robust_policy, out, strategy, visitor);
} }
@ -492,9 +554,9 @@ template
inline OutputIterator dissolve_inserter(Geometry const& geometry, inline OutputIterator dissolve_inserter(Geometry const& geometry,
OutputIterator out) OutputIterator out)
{ {
typedef typename strategy::intersection::services::default_strategy typedef typename strategies::relate::services::default_strategy
< <
typename cs_tag<Geometry>::type Geometry, Geometry
>::type strategy_type; >::type strategy_type;
return dissolve_inserter<GeometryOut>(geometry, out, strategy_type()); return dissolve_inserter<GeometryOut>(geometry, out, strategy_type());
@ -518,7 +580,8 @@ inline void dissolve(Geometry const& geometry, Collection& output_collection,
typedef typename geometry::rescale_policy_type typedef typename geometry::rescale_policy_type
< <
typename geometry::point_type<Geometry>::type typename geometry::point_type<Geometry>::type,
typename Strategy::cs_tag
>::type rescale_policy_type; >::type rescale_policy_type;
rescale_policy_type robust_policy rescale_policy_type robust_policy
@ -527,14 +590,9 @@ inline void dissolve(Geometry const& geometry, Collection& output_collection,
detail::overlay::overlay_null_visitor visitor; detail::overlay::overlay_null_visitor visitor;
dispatch::dissolve return resolve_strategy::dissolve
< <
Geometry, geometry_out, Strategy
geometry_out,
detail::overlay::do_reverse
<
geometry::point_order<Geometry>::value
>::value
>::apply(geometry, robust_policy, >::apply(geometry, robust_policy,
std::back_inserter(output_collection), std::back_inserter(output_collection),
strategy, visitor); strategy, visitor);
@ -547,9 +605,9 @@ template
> >
inline void dissolve(Geometry const& geometry, Collection& output_collection) inline void dissolve(Geometry const& geometry, Collection& output_collection)
{ {
typedef typename strategy::intersection::services::default_strategy typedef typename strategies::relate::services::default_strategy
< <
typename cs_tag<Geometry>::type Geometry, Geometry
>::type strategy_type; >::type strategy_type;
dissolve(geometry, output_collection, strategy_type()); dissolve(geometry, output_collection, strategy_type());

Some files were not shown because too many files have changed in this diff Show More