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

View File

@ -80,9 +80,11 @@ jobs:
- name: Install
run: |
# gcc-4.8 is not available in Bionic anymore
# Required for compilers not available in ubuntu latest
sudo add-apt-repository "deb http://dk.archive.ubuntu.com/ubuntu/ xenial main"
sudo add-apt-repository "deb http://dk.archive.ubuntu.com/ubuntu/ xenial universe"
sudo add-apt-repository "deb http://dk.archive.ubuntu.com/ubuntu/ bionic main"
sudo add-apt-repository "deb http://dk.archive.ubuntu.com/ubuntu/ bionic universe"
sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test
sudo apt -q -y update
sudo apt -q -y install g++-${{ matrix.version }} g++-${{ matrix.version }}-multilib

View File

@ -1,6 +1,6 @@
# ![Boost.Geometry](doc/other/logo/logo_bkg.png)
Boost.Geometry, part of collection of the [Boost C++ Libraries](http://github.com/boostorg), defines concepts, primitives and algorithms for solving geometry problems.
Boost.Geometry, part of collection of the [Boost C++ Libraries](http://github.com/boostorg), defines concepts, primitives and algorithms for solving geometry problems. Boost.Geometry is a C++14 header-only library.
[![Licence](https://img.shields.io/badge/license-boost-4480cc.png)](http://www.boost.org/LICENSE_1_0.txt)
[![Documentation](https://img.shields.io/badge/-documentation-4480cc.png)](http://boost.org/libs/geometry)

View File

@ -14,6 +14,7 @@ test-suite boost-geometry-extensions-algorithms
[ run distance_info.cpp ]
[ run connect.cpp ]
# [ run offset.cpp ]
[ run parse.cpp ]
[ run midpoints.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) 2009-2012 Mateusz Loskot, London, UK.
// This file was modified by Oracle on 2017-2020.
// Modifications copyright (c) 2017-2020 Oracle and/or its affiliates.
// This file was modified by Oracle on 2017-2021.
// Modifications copyright (c) 2017-2021 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
@ -242,22 +242,23 @@ inline void buffer(GeometryIn const& geometry_in,
geometry::envelope(geometry_in, box);
geometry::buffer(box, box, distance_strategy.max_distance(join_strategy, end_strategy));
typename strategy::intersection::services::default_strategy
typename strategies::relate::services::default_strategy
<
typename cs_tag<GeometryIn>::type
>::type intersection_strategy;
GeometryIn, GeometryIn
>::type strategies;
rescale_policy_type rescale_policy
= 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,
side_strategy,
join_strategy,
end_strategy,
point_strategy,
intersection_strategy,
strategies,
rescale_policy);
}

View File

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

View File

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

View File

@ -193,30 +193,37 @@ struct buffer_less
}
};
template <typename Strategy>
struct piece_get_box
{
explicit piece_get_box(Strategy const& strategy)
: m_strategy(strategy)
{}
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);
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)
{
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
{
explicit piece_overlaps_box(Strategy const& strategy)
: m_strategy(strategy)
{}
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);
@ -235,34 +242,45 @@ struct piece_overlaps_box
}
return ! geometry::detail::disjoint::disjoint_box_box(box, piece.m_piece_border.m_envelope,
DisjointBoxBoxStrategy());
m_strategy);
}
Strategy const& m_strategy;
};
template <typename Strategy>
struct turn_get_box
{
explicit turn_get_box(Strategy const& strategy)
: m_strategy(strategy)
{}
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);
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
{
explicit turn_overlaps_box(Strategy const& strategy)
: m_strategy(strategy)
{}
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);
return ! geometry::detail::disjoint::disjoint_point_box(turn.point, box,
DisjointPointBoxStrategy());
m_strategy);
}
Strategy const& m_strategy;
};
struct enriched_map_buffer_include_policy

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -5,8 +5,8 @@
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
// Copyright (c) 2013-2015 Adam Wulkiewicz, Lodz, Poland.
// This file was modified by Oracle on 2013-2018.
// Modifications copyright (c) 2013-2018, Oracle and/or its affiliates.
// This file was modified by Oracle on 2013-2020.
// Modifications copyright (c) 2013-2020, Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
@ -43,8 +43,23 @@ namespace detail { namespace disjoint
\note Is used from other algorithms, declared separately
to avoid circular references
*/
template <typename Box1, typename Box2, typename Strategy>
inline bool disjoint_box_box(Box1 const& box1, Box2 const& box2, Strategy const&)
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& 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);
}
@ -63,9 +78,10 @@ template <typename Box1, typename Box2, std::size_t DimensionCount>
struct disjoint<Box1, Box2, DimensionCount, box_tag, box_tag, false>
{
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) 2013-2014 Adam Wulkiewicz, Lodz, Poland.
// This file was modified by Oracle on 2013-2017.
// Modifications copyright (c) 2013-2017, Oracle and/or its affiliates.
// This file was modified by Oracle on 2013-2021.
// Modifications copyright (c) 2013-2021, Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
@ -32,7 +32,10 @@
#include <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/relate/services.hpp>
namespace boost { namespace geometry
@ -41,9 +44,14 @@ namespace boost { namespace geometry
namespace resolve_strategy
{
template
<
typename Strategy,
bool IsUmbrella = strategies::detail::is_umbrella_strategy<Strategy>::value
>
struct disjoint
{
template <typename Geometry1, typename Geometry2, typename Strategy>
template <typename Geometry1, typename Geometry2>
static inline bool apply(Geometry1 const& geometry1,
Geometry2 const& geometry2,
Strategy const& strategy)
@ -53,13 +61,35 @@ struct disjoint
Geometry1, Geometry2
>::apply(geometry1, geometry2, strategy);
}
};
template <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>
static inline bool apply(Geometry1 const& geometry1,
Geometry2 const& geometry2,
default_strategy)
{
typedef typename strategy::disjoint::services::default_strategy
typedef typename strategies::relate::services::default_strategy
<
Geometry1, Geometry2
>::type strategy_type;
@ -88,7 +118,10 @@ struct disjoint
Geometry2 const
>();
return resolve_strategy::disjoint::apply(geometry1, geometry2, strategy);
return resolve_strategy::disjoint
<
Strategy
>::apply(geometry1, geometry2, strategy);
}
};

View File

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

View File

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

View File

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

View File

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

View File

@ -5,8 +5,8 @@
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
// Copyright (c) 2013-2015 Adam Wulkiewicz, Lodz, Poland
// This file was modified by Oracle on 2013-2018.
// Modifications copyright (c) 2013-2018, Oracle and/or its affiliates.
// This file was modified by Oracle on 2013-2020.
// Modifications copyright (c) 2013-2020, Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
@ -41,8 +41,26 @@ namespace detail { namespace disjoint
/*!
\brief Internal utility function to detect if point/box are disjoint
*/
template <typename Point, typename Box, typename Strategy>
inline bool disjoint_point_box(Point const& point, Box const& box, Strategy const& )
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& 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)
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>
{
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)
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) 2013-2015 Adam Wulkiewicz, Lodz, Poland
// This file was modified by Oracle on 2013, 2014, 2015, 2017, 2018.
// Modifications copyright (c) 2013-2018, Oracle and/or its affiliates.
// This file was modified by Oracle on 2013-2020.
// Modifications copyright (c) 2013-2020, Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
@ -22,11 +22,14 @@
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_POINT_POINT_HPP
#include <cstddef>
#include <type_traits>
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/algorithms/dispatch/disjoint.hpp>
#include <boost/geometry/strategies/detail.hpp>
// For backward compatibility
#include <boost/geometry/strategies/disjoint.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
\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,
Strategy const& )
{
// ! within(point1, point2)
return ! Strategy::apply(point1, point2);
}
@ -68,9 +89,11 @@ struct disjoint<Point1, Point2, DimensionCount, point_tag, point_tag, false>
{
template <typename Strategy>
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,
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/tags.hpp>
#include <boost/geometry/strategies/relate/services.hpp>
#include <boost/geometry/algorithms/assign.hpp>
@ -164,8 +165,12 @@ struct point_to_ring
Strategy const& strategy)
{
// TODO: pass strategy
if (within::within_point_geometry(point, ring,
strategy.get_point_in_geometry_strategy()))
auto const s = strategies::relate::services::strategy_converter
<
decltype(strategy.get_point_in_geometry_strategy())
>::get(strategy.get_point_in_geometry_strategy());
if (within::within_point_geometry(point, ring, s))
{
return return_type(0);
}
@ -207,11 +212,15 @@ private:
InteriorRingIterator last,
Strategy const& strategy)
{
// TEMP: pass strategy
auto const s = strategies::relate::services::strategy_converter
<
decltype(strategy.get_point_in_geometry_strategy())
>::get(strategy.get_point_in_geometry_strategy());
for (InteriorRingIterator it = first; it != last; ++it)
{
// TODO: pass strategy
if (within::within_point_geometry(point, *it,
strategy.get_point_in_geometry_strategy()))
if (within::within_point_geometry(point, *it, s))
{
// the point is inside a polygon hole, so its distance
// to the polygon its distance to the polygon's
@ -240,9 +249,13 @@ public:
Polygon const& polygon,
Strategy const& strategy)
{
// TODO: pass strategy
if (! within::covered_by_point_geometry(point, exterior_ring(polygon),
strategy.get_point_in_geometry_strategy()))
// TEMP: pass strategy
auto const s = strategies::relate::services::strategy_converter
<
decltype(strategy.get_point_in_geometry_strategy())
>::get(strategy.get_point_in_geometry_strategy());
if (! within::covered_by_point_geometry(point, exterior_ring(polygon), s))
{
// the point is outside the exterior ring, so its distance
// to the polygon is its distance to the polygon's exterior ring
@ -340,8 +353,12 @@ struct point_to_multigeometry<Point, MultiPolygon, Strategy, true>
Strategy const& strategy)
{
// TODO: pass strategy
if (within::covered_by_point_geometry(point, multipolygon,
strategy.get_point_in_geometry_strategy()))
auto const s = strategies::relate::services::strategy_converter
<
decltype(strategy.get_point_in_geometry_strategy())
>::get(strategy.get_point_in_geometry_strategy());
if (within::covered_by_point_geometry(point, multipolygon, s))
{
return 0;
}

View File

@ -58,17 +58,20 @@ namespace detail { namespace distance
{
// TODO: Take strategy
template <typename Segment, typename Box>
inline bool intersects_segment_box(Segment const& segment, Box const& box)
template <typename Segment, typename Box, typename Strategy>
inline bool intersects_segment_box(Segment const& segment, Box const& box,
Strategy const& strategy)
{
typedef typename strategy::disjoint::services::default_strategy
// TODO: pass strategy
auto const s = strategies::relate::services::strategy_converter
<
Segment, Box
>::type strategy_type;
// This is the only strategy defined in distance segment/box
// strategies that carries the information about the spheroid
// so use it for now.
decltype(strategy.get_side_strategy())
>::get(strategy.get_side_strategy());
return ! detail::disjoint::disjoint_segment_box::apply(segment, box,
strategy_type());
return ! detail::disjoint::disjoint_segment_box::apply(segment, box, s);
}
@ -114,7 +117,7 @@ public:
Strategy const& strategy,
bool check_intersection = true)
{
if (check_intersection && intersects_segment_box(segment, box))
if (check_intersection && intersects_segment_box(segment, box, strategy))
{
return 0;
}
@ -229,7 +232,7 @@ public:
Strategy const& strategy,
bool check_intersection = true)
{
if (check_intersection && intersects_segment_box(segment, box))
if (check_intersection && intersects_segment_box(segment, box, strategy))
{
return 0;
}

View File

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

View File

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

View File

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

View File

@ -136,27 +136,6 @@ inline bool has_self_intersections(Geometry const& geometry,
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
#endif // DOXYGEN_NO_DETAIL

View File

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

View File

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

View File

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

View File

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

View File

@ -1,6 +1,6 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2014-2017, Oracle and/or its affiliates.
// Copyright (c) 2014-2020, Oracle and/or its affiliates.
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@ -20,7 +20,8 @@
#include <boost/geometry/algorithms/dispatch/is_simple.hpp>
#include <boost/geometry/core/cs.hpp>
#include <boost/geometry/strategies/default_strategy.hpp>
#include <boost/geometry/strategies/intersection.hpp>
#include <boost/geometry/strategies/detail.hpp>
#include <boost/geometry/strategies/relate/services.hpp>
namespace boost { namespace geometry
@ -29,23 +30,47 @@ namespace boost { namespace geometry
namespace resolve_strategy
{
template
<
typename Strategy,
bool IsUmbrella = strategies::detail::is_umbrella_strategy<Strategy>::value
>
struct is_simple
{
template <typename Geometry, typename Strategy>
template <typename Geometry>
static inline bool apply(Geometry const& geometry,
Strategy const& 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>
static inline bool apply(Geometry const& geometry,
default_strategy)
{
// NOTE: Currently the strategy is only used for Linear geometries
typedef typename strategy::intersection::services::default_strategy
typedef typename strategies::relate::services::default_strategy
<
typename cs_tag<Geometry>::type
Geometry, Geometry
>::type strategy_type;
return dispatch::is_simple<Geometry>::apply(geometry, strategy_type());
@ -65,7 +90,7 @@ struct is_simple
{
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
<
Linear,
typename Strategy::equals_point_point_strategy_type
Linear, Strategy
> is_acceptable_turn_type;
is_acceptable_turn_type predicate(linear);
@ -259,12 +258,12 @@ struct is_simple_linestring
return ! boost::empty(linestring)
&& ! detail::is_valid::has_duplicates
<
Linestring, closed, typename Strategy::cs_tag
>::apply(linestring, policy)
Linestring, closed
>::apply(linestring, policy, strategy)
&& ! detail::is_valid::has_spikes
<
Linestring, closed
>::apply(linestring, policy, strategy.get_side_strategy());
>::apply(linestring, policy, strategy);
}
};

View File

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

View File

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

View File

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

View File

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

View File

@ -1,6 +1,6 @@
// Boost.Geometry
// Copyright (c) 2014-2018, Oracle and/or its affiliates.
// Copyright (c) 2014-2020, Oracle and/or its affiliates.
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@ -25,7 +25,8 @@
#include <boost/geometry/policies/is_valid/failing_reason_policy.hpp>
#include <boost/geometry/policies/is_valid/failure_type_policy.hpp>
#include <boost/geometry/strategies/default_strategy.hpp>
#include <boost/geometry/strategies/intersection.hpp>
#include <boost/geometry/strategies/detail.hpp>
#include <boost/geometry/strategies/relate/services.hpp>
namespace boost { namespace geometry
@ -34,9 +35,14 @@ namespace boost { namespace geometry
namespace resolve_strategy
{
template
<
typename Strategy,
bool IsUmbrella = strategies::detail::is_umbrella_strategy<Strategy>::value
>
struct is_valid
{
template <typename Geometry, typename VisitPolicy, typename Strategy>
template <typename Geometry, typename VisitPolicy>
static inline bool apply(Geometry const& geometry,
VisitPolicy& visitor,
Strategy const& strategy)
@ -44,18 +50,41 @@ struct is_valid
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>
static inline bool apply(Geometry const& geometry,
VisitPolicy& visitor,
default_strategy)
{
// NOTE: Currently the strategy is only used for Areal geometries
typedef typename strategy::intersection::services::default_strategy
typedef typename strategies::relate::services::default_strategy
<
typename cs_tag<Geometry>::type
Geometry, Geometry
>::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>();
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
<
Linestring,
3u,
true,
not_equal_to
<
typename point_type<Linestring>::type,
typename Strategy::equals_point_point_strategy_type
>
>::apply(linestring);
Linestring, 3u, true
>::apply(linestring, strategy);
if (num_distinct < 2u)
{
@ -93,8 +86,7 @@ struct is_valid_linestring
return ! has_spikes
<
Linestring, closed
>::apply(linestring, visitor,
strategy.get_side_strategy());
>::apply(linestring, visitor, strategy);
}
};

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -73,7 +73,7 @@ struct get_turn_without_info
> policy_type;
typename policy_type::return_type const result
= strategy.apply(range_p, range_q, policy_type());
= strategy.relate().apply(range_p, range_q, policy_type());
for (std::size_t i = 0; i < result.count; i++)
{

View File

@ -3,8 +3,8 @@
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2017 Adam Wulkiewicz, Lodz, Poland.
// This file was modified by Oracle on 2015, 2017, 2018, 2019.
// Modifications copyright (c) 2015-2019 Oracle and/or its affiliates.
// This file was modified by Oracle on 2015-2020.
// Modifications copyright (c) 2015-2020 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@ -15,7 +15,6 @@
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_GET_TURN_INFO_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_GET_TURN_INFO_HPP
#include <boost/core/ignore_unused.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/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>
// Silence warning C4127: conditional expression is constant
@ -131,15 +127,7 @@ struct base_turn_handler
return 0;
}
typedef typename select_coordinate_type
<
typename UniqueSubRange1::point_type,
typename UniqueSubRange2::point_type
>::type coordinate_type;
typedef detail::distance_measure<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));
auto const dm = get_distance_measure(range_p.at(range_index), range_p.at(range_index + 1), range_q.at(point_index));
return dm.measure == 0 ? 0 : dm.measure > 0 ? 1 : -1;
}
@ -186,7 +174,8 @@ struct base_turn_handler
{
ti.method = method;
// For touch/touch interior always take the intersection point 0 (there is only one).
// For touch/touch interior always take the intersection point 0
// (usually there is only one - but if collinear is handled as touch, both could be taken).
static int const index = 0;
geometry::convert(info.intersections[index], ti.point);
@ -225,9 +214,8 @@ struct base_turn_handler
{
// TODO: use comparable distance for point-point instead - but that
// causes currently cycling include problems
typedef typename geometry::coordinate_type<Point1>::type ctype;
ctype const dx = get<0>(a) - get<0>(b);
ctype const dy = get<1>(a) - get<1>(b);
auto const dx = get<0>(a) - get<0>(b);
auto const dy = get<1>(a) - get<1>(b);
return dx * dx + dy * dy;
}
@ -259,19 +247,10 @@ struct base_turn_handler
// pk/q2 is considered as collinear, but there might be
// a tiny measurable difference. If so, use that.
// Calculate pk // qj-qk
typedef detail::distance_measure
<
typename select_coordinate_type
<
typename UniqueSubRange1::point_type,
typename UniqueSubRange2::point_type
>::type
> dm_type;
const bool p_closer =
bool const p_closer =
ti.operations[IndexP].remaining_distance
< ti.operations[IndexQ].remaining_distance;
dm_type const dm
auto const dm
= p_closer
? get_distance_measure(range_q.at(index_q - 1),
range_q.at(index_q), range_p.at(index_p))
@ -282,8 +261,7 @@ struct base_turn_handler
{
// Not truely collinear, distinguish for union/intersection
// If p goes left (positive), take that for a union
bool p_left = p_closer ? dm.is_positive() : dm.is_negative();
bool const p_left = p_closer ? dm.is_positive() : dm.is_negative();
ti.operations[IndexP].operation = p_left
? operation_union : operation_intersection;
@ -347,14 +325,9 @@ struct touch_interior : public base_turn_handler
// Therefore handle it as a normal touch (two segments arrive at the
// intersection point). It currently checks for zero, but even a
// distance a little bit larger would do.
typedef typename geometry::coordinate_type
<
typename UniqueSubRange::point_type
>::type coor_t;
coor_t const location = distance_measure(info.intersections[0], non_touching_range.at(1));
coor_t const zero = 0;
bool const result = math::equals(location, zero);
auto const dm = distance_measure(info.intersections[0], non_touching_range.at(1));
decltype(dm) const zero = 0;
bool const result = math::equals(dm, zero);
return result;
}
@ -540,16 +513,8 @@ struct touch : public base_turn_handler
// >----->P qj is LEFT of P1 and pi is LEFT of Q2
// (the other way round is also possible)
typedef typename select_coordinate_type
<
typename UniqueSubRange1::point_type,
typename UniqueSubRange2::point_type
>::type coordinate_type;
typedef detail::distance_measure<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));
auto const dm_qj_p1 = get_distance_measure(range_p.at(0), range_p.at(1), range_q.at(1));
auto const dm_pi_q2 = get_distance_measure(range_q.at(1), range_q.at(2), range_p.at(0));
if (dm_qj_p1.measure > 0 && dm_pi_q2.measure > 0)
{
@ -564,8 +529,8 @@ struct touch : public base_turn_handler
return true;
}
dm_type const dm_pj_q1 = get_distance_measure(range_q.at(0), range_q.at(1), range_p.at(1));
dm_type const dm_qi_p2 = get_distance_measure(range_p.at(1), range_p.at(2), range_q.at(0));
auto const dm_pj_q1 = get_distance_measure(range_q.at(0), range_q.at(1), range_p.at(1));
auto const dm_qi_p2 = get_distance_measure(range_p.at(1), range_p.at(2), range_q.at(0));
if (dm_pj_q1.measure > 0 && dm_qi_p2.measure > 0)
{
@ -813,17 +778,9 @@ struct equal : public base_turn_handler
// They turn to the same side, or continue both collinearly
// Without rescaling, to check for union/intersection,
// try to check side values (without any thresholds)
typedef typename select_coordinate_type
<
typename UniqueSubRange1::point_type,
typename UniqueSubRange2::point_type
>::type coordinate_type;
typedef detail::distance_measure<coordinate_type> dm_type;
dm_type const dm_pk_q2
auto const dm_pk_q2
= get_distance_measure(range_q.at(1), range_q.at(2), range_p.at(2));
dm_type const dm_qk_p2
auto const dm_qk_p2
= get_distance_measure(range_p.at(1), range_p.at(2), range_q.at(2));
if (dm_qk_p2.measure != dm_pk_q2.measure)
@ -965,8 +922,57 @@ template
>
struct collinear : public base_turn_handler
{
template
<
typename IntersectionInfo,
typename UniqueSubRange1,
typename UniqueSubRange2,
typename DirInfo
>
static bool handle_as_equal(IntersectionInfo const& info,
UniqueSubRange1 const& range_p,
UniqueSubRange2 const& range_q,
DirInfo const& dir_info)
{
#if defined(BOOST_GEOMETRY_USE_RESCALING)
return false;
#endif
int const arrival_p = dir_info.arrival[0];
int const arrival_q = dir_info.arrival[1];
if (arrival_p * arrival_q != -1 || info.count != 2)
{
// Code below assumes that either p or q arrives in the other segment
return false;
}
auto const dm = distance_measure(info.intersections[1],
arrival_p == 1 ? range_q.at(1) : range_p.at(1));
decltype(dm) const zero = 0;
return math::equals(dm, zero);
}
/*
arrival P pk//p1 qk//q1 product* case result
Either P arrives within Q (arrival_p == -1) or Q arrives within P.
Typical situation:
^q2
/
^q1
/ ____ ip[1]
//|p1 } this section of p/q is colllinear
q0// | } ____ ip[0]
/ |
/ v
p0 p2
P arrives (at p1) in segment Q (between q0 and q1).
Therefore arrival_p == 1
P (p2) goes to the right (-1). Follow P for intersection, or follow Q for union.
Therefore if (arrival_p==1) and side_p==-1, result = iu
Complete table:
arrival P pk//p1 qk//q1 product case result
1 1 1 CLL1 ui
-1 1 -1 CLL2 iu
1 1 1 CLR1 ui
@ -980,7 +986,9 @@ struct collinear : public base_turn_handler
1 0 0 CC1 cc
-1 0 0 CC2 cc
*product = arrival * (pk//p1 or qk//q1)
Resulting in the rule:
The arrival-info multiplied by the relevant side delivers the result.
product = arrival * (pk//p1 or qk//q1)
Stated otherwise:
- if P arrives: look at turn P
@ -989,13 +997,6 @@ struct collinear : public base_turn_handler
- if P arrives and P turns right: intersection for P
- if Q arrives and Q turns left: union for Q (=intersection for P)
- if Q arrives and Q turns right: intersection for Q (=union for P)
ROBUSTNESS: p and q are collinear, so you would expect
that side qk//p1 == pk//q1. But that is not always the case
in near-epsilon ranges. Then decision logic is different.
If p arrives, q is further, so the angle qk//p1 is (normally)
more precise than pk//p1
*/
template
<
@ -1016,9 +1017,9 @@ struct collinear : public base_turn_handler
// Copy the intersection point in TO direction
assign_point(ti, method_collinear, info, non_opposite_to_index(info));
int const arrival = dir_info.arrival[0];
int const arrival_p = dir_info.arrival[0];
// Should not be 0, this is checked before
BOOST_GEOMETRY_ASSERT(arrival != 0);
BOOST_GEOMETRY_ASSERT(arrival_p != 0);
bool const has_pk = ! range_p.is_last_segment();
bool const has_qk = ! range_q.is_last_segment();
@ -1026,19 +1027,15 @@ struct collinear : public base_turn_handler
int const side_q = has_qk ? side.qk_wrt_q1() : 0;
// If p arrives, use p, else use q
int const side_p_or_q = arrival == 1
int const side_p_or_q = arrival_p == 1
? side_p
: side_q
;
// See comments above,
// resulting in a strange sort of mathematic rule here:
// The arrival-info multiplied by the relevant side
// delivers a consistent result.
// Calculate product according to comments above.
int const product = arrival_p * side_p_or_q;
int const product = arrival * side_p_or_q;
if(product == 0)
if (product == 0)
{
both(ti, operation_continue);
}
@ -1186,11 +1183,11 @@ public:
{
TurnInfo tp = tp_model;
int const p_arrival = info.d_info().arrival[0];
int const q_arrival = info.d_info().arrival[1];
int const arrival_p = info.d_info().arrival[0];
int const arrival_q = info.d_info().arrival[1];
// If P arrives within Q, there is a turn dependent on P
if ( p_arrival == 1
if ( arrival_p == 1
&& ! range_p.is_last_segment()
&& set_tp<0>(side.pk_wrt_p1(), tp, info.i_info()) )
{
@ -1200,7 +1197,7 @@ public:
}
// If Q arrives within P, there is a turn dependent on Q
if ( q_arrival == 1
if ( arrival_q == 1
&& ! range_q.is_last_segment()
&& set_tp<1>(side.qk_wrt_q1(), tp, info.i_info()) )
{
@ -1212,8 +1209,8 @@ public:
if (AssignPolicy::include_opposite)
{
// Handle cases not yet handled above
if ((q_arrival == -1 && p_arrival == 0)
|| (p_arrival == -1 && q_arrival == 0))
if ((arrival_q == -1 && arrival_p == 0)
|| (arrival_p == -1 && arrival_q == 0))
{
for (unsigned int i = 0; i < 2; i++)
{
@ -1396,7 +1393,7 @@ struct get_turn_info
else
{
handler::template apply<1>(range_q, range_p, tp, inters.i_info(), inters.d_info(),
inters.get_swapped_sides(), umbrella_strategy);
inters.swapped_sides(), umbrella_strategy);
*out++ = tp;
}
}
@ -1420,9 +1417,10 @@ struct get_turn_info
// Collinear
if ( ! inters.d_info().opposite )
{
if ( inters.d_info().arrival[0] == 0 )
if (inters.d_info().arrival[0] == 0
|| collinear<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;
}
else

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -63,44 +63,68 @@ template
class multipoint_multipolygon_point
{
private:
template <typename ExpandPointStrategy>
template <typename Strategy>
struct expand_box_point
{
explicit expand_box_point(Strategy const& strategy)
: m_strategy(strategy)
{}
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
{
explicit expand_box_boxpair(Strategy const& strategy)
: m_strategy(strategy)
{}
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
{
explicit overlaps_box_point(Strategy const& strategy)
: m_strategy(strategy)
{}
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
{
explicit overlaps_box_boxpair(Strategy const& strategy)
: m_strategy(strategy)
{}
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>
@ -137,10 +161,10 @@ private:
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,
std::vector<std::pair<Box, SizeT> > & box_pairs,
EnvelopeStrategy const& strategy)
Strategy const& strategy)
{
SizeT index = 0;
for (; first != last; ++first, ++index)
@ -172,29 +196,16 @@ private:
fill_box_pairs(boost::begin(multipolygon),
boost::end(multipolygon),
box_pairs,
strategy.get_envelope_strategy());
// TEMP - envelope umbrella strategy also contains
// expand strategies
using expand_box_strategy_type = decltype(
strategies::envelope::services::strategy_converter
<
typename Strategy::envelope_strategy_type
>::get(strategy.get_envelope_strategy())
.expand(std::declval<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;
box_pairs, strategy);
geometry::partition
<
box_type
>::apply(multipoint, box_pairs, item_visitor,
expand_box_point<expand_point_strategy_type>(),
overlaps_box_point<disjoint_point_box_strategy_type>(),
expand_box_boxpair<expand_box_strategy_type>(),
overlaps_box_boxpair<disjoint_box_box_strategy_type>());
expand_box_point<Strategy>(strategy),
overlaps_box_point<Strategy>(strategy),
expand_box_boxpair<Strategy>(strategy),
overlaps_box_boxpair<Strategy>(strategy));
return oit;
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -29,7 +29,8 @@
#include <boost/geometry/core/topological_dimension.hpp>
#include <boost/geometry/geometries/concepts/check.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/type_traits.hpp>
@ -161,9 +162,15 @@ struct result_handler_type<Geometry1, Geometry2, util::type_sequence<StaticMasks
namespace resolve_strategy {
template
<
typename Strategy,
bool IsUmbrella = strategies::detail::is_umbrella_strategy<Strategy>::value
>
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,
Geometry2 const& geometry2,
ResultHandler & handler,
@ -175,14 +182,37 @@ struct relate
Geometry2
>::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>
static inline void apply(Geometry1 const& geometry1,
Geometry2 const& geometry2,
ResultHandler & handler,
default_strategy)
{
typedef typename strategy::relate::services::default_strategy
typedef typename strategies::relate::services::default_strategy
<
Geometry1,
Geometry2
@ -220,7 +250,7 @@ struct relate
Mask
>::type handler(mask);
resolve_strategy::relate::apply(geometry1, geometry2, handler, strategy);
resolve_strategy::relate<Strategy>::apply(geometry1, geometry2, handler, strategy);
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,
Result & result,
IntersectionStrategy const& intersection_strategy)
Strategy const& strategy)
{
// TODO: If Areal geometry may have infinite size, change the following line:
@ -243,38 +243,34 @@ struct linear_areal
return;
// get and analyse turns
typedef typename turn_info_type<Geometry1, Geometry2, IntersectionStrategy>::type turn_type;
typedef typename turn_info_type<Geometry1, Geometry2, Strategy>::type turn_type;
std::vector<turn_type> turns;
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 ) )
return;
typedef typename IntersectionStrategy::template point_in_geometry_strategy<Geometry1, Geometry2>::type within_strategy_type;
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 typename Strategy::cs_tag cs_tag;
typedef boundary_checker
<
Geometry1,
eq_pp_strategy_type
Strategy
> boundary_checker1_type;
boundary_checker1_type boundary_checker1(geometry1);
boundary_checker1_type boundary_checker1(geometry1, strategy);
no_turns_la_linestring_pred
<
Geometry2,
Result,
within_strategy_type,
Strategy,
boundary_checker1_type,
TransposeResult
> pred1(geometry2,
result,
within_strategy,
strategy,
boundary_checker1);
for_each_disjoint_geometry_if<0, Geometry1>::apply(turns.begin(), turns.end(), geometry1, pred1);
if ( BOOST_GEOMETRY_CONDITION( result.interrupt ) )
@ -302,7 +298,7 @@ struct linear_areal
turns.begin(), turns.end(),
geometry1, geometry2,
boundary_checker1,
intersection_strategy.get_side_strategy());
strategy);
if ( BOOST_GEOMETRY_CONDITION( result.interrupt ) )
return;
@ -395,14 +391,12 @@ struct linear_areal
typedef turns::less<1, turns::less_op_areal_linear<1>, cs_tag> less;
std::sort(it, next, less());
eq_pp_strategy_type const eq_pp_strategy = within_strategy.get_equals_point_point_strategy();
// analyse
areal_boundary_analyser<turn_type> analyser;
for ( turn_iterator rit = it ; rit != next ; ++rit )
{
// if the analyser requests, break the search
if ( !analyser.apply(it, rit, next, eq_pp_strategy) )
if ( !analyser.apply(it, rit, next, strategy) )
break;
}
@ -626,18 +620,20 @@ struct linear_areal
static const std::size_t other_op_id = 1;
template <typename TurnPointCSTag, typename PointP, typename PointQ,
typename SideStrategy,
typename Strategy,
typename Pi = PointP, typename Pj = PointP, typename Pk = PointP,
typename Qi = PointQ, typename Qj = PointQ, typename Qk = PointQ
>
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,
Qi const& qi, Qj const& qj, Qk const& qk,
SideStrategy const& side_strategy)
Qi const& qi, Qj const& qj, Qk const& qk,
Strategy const& strategy)
: m_pi(pi), m_pj(pj), m_pk(pk)
, m_qi(qi), m_qj(qj), m_qk(qk)
, m_side_strategy(side_strategy)
, m_side_strategy(strategy.side())
{}
inline int pk_wrt_p1() const { return m_side_strategy.apply(m_pi, m_pj, m_pk); }
@ -652,7 +648,7 @@ struct linear_areal
Qj const& m_qj;
Qk const& m_qk;
SideStrategy m_side_strategy;
side_strategy_type m_side_strategy;
};
@ -672,12 +668,12 @@ struct linear_areal
typename Geometry,
typename OtherGeometry,
typename BoundaryChecker,
typename SideStrategy>
typename Strategy>
void apply(Result & res, TurnIt it,
Geometry const& geometry,
OtherGeometry const& other_geometry,
BoundaryChecker const& boundary_checker,
SideStrategy const& side_strategy)
Strategy const& strategy)
{
overlay::operation_type op = it->operations[op_id].operation;
@ -706,7 +702,7 @@ struct linear_areal
// real exit point - may be multiple
// we know that we entered and now we exit
if ( ! turn_on_the_same_ip<op_id>(m_exit_watcher.get_exit_turn(), *it,
side_strategy.get_equals_point_point_strategy()) )
strategy) )
{
m_exit_watcher.reset_detected_exit();
@ -749,7 +745,7 @@ struct linear_areal
if ( ( op == overlay::operation_intersection
|| op == overlay::operation_continue )
&& turn_on_the_same_ip<op_id>(m_exit_watcher.get_exit_turn(), *it,
side_strategy.get_equals_point_point_strategy()) )
strategy) )
{
fake_enter_detected = true;
}
@ -770,7 +766,7 @@ struct linear_areal
|| seg_id.multi_index != m_previous_turn_ptr->operations[op_id].seg_id.multi_index ) ) // or the next single-geometry
|| ( m_previous_operation == overlay::operation_union
&& ! turn_on_the_same_ip<op_id>(*m_previous_turn_ptr, *it,
side_strategy.get_equals_point_point_strategy()) )
strategy) )
)
{
update<interior, exterior, '1', TransposeResult>(res);
@ -803,7 +799,7 @@ struct linear_areal
// real interior overlap
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);
m_interior_detected = false;
@ -919,7 +915,7 @@ struct linear_areal
&& calculate_from_inside(geometry,
other_geometry,
*it,
side_strategy);
strategy);
if ( from_inside )
update<interior, interior, '1', TransposeResult>(res);
@ -1020,7 +1016,7 @@ struct linear_areal
&& calculate_from_inside(geometry,
other_geometry,
*it,
side_strategy);
strategy);
if ( first_from_inside )
{
update<interior, interior, '1', TransposeResult>(res);
@ -1208,11 +1204,11 @@ struct linear_areal
// check if the passed turn's segment of Linear geometry arrived
// from the inside or the outside of the Areal geometry
template <typename Turn, typename SideStrategy>
template <typename Turn, typename Strategy>
static inline bool calculate_from_inside(Geometry1 const& geometry1,
Geometry2 const& geometry2,
Turn const& turn,
SideStrategy const& side_strategy)
Strategy const& strategy)
{
typedef typename cs_tag<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);
point1_type qi_conv;
geometry::convert(qi, qi_conv);
bool const is_ip_qj = equals::equals_point_point(turn.point, qj, side_strategy.get_equals_point_point_strategy());
bool const is_ip_qj = equals::equals_point_point(turn.point, qj, strategy);
// TODO: test this!
// BOOST_GEOMETRY_ASSERT(!equals::equals_point_point(turn.point, pi));
// BOOST_GEOMETRY_ASSERT(!equals::equals_point_point(turn.point, qi));
@ -1257,11 +1253,11 @@ struct linear_areal
range2_iterator qk_it = find_next_non_duplicated(boost::begin(range2),
range::pos(range2, q_seg_jk),
boost::end(range2),
side_strategy.get_equals_point_point_strategy());
strategy);
// Will this sequence of points be always correct?
la_side_calculator<cs_tag, point1_type, point2_type, SideStrategy>
side_calc(qi_conv, new_pj, pi, qi, qj, *qk_it, side_strategy);
la_side_calculator<cs_tag, point1_type, point2_type, Strategy>
side_calc(qi_conv, new_pj, pi, qi, qj, *qk_it, strategy);
return calculate_from_inside_sides(side_calc);
}
@ -1270,16 +1266,16 @@ struct linear_areal
point2_type new_qj;
geometry::convert(turn.point, new_qj);
la_side_calculator<cs_tag, point1_type, point2_type, SideStrategy>
side_calc(qi_conv, new_pj, pi, qi, new_qj, qj, side_strategy);
la_side_calculator<cs_tag, point1_type, point2_type, Strategy>
side_calc(qi_conv, new_pj, pi, qi, new_qj, qj, strategy);
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,
EqPPStrategy const& strategy)
Strategy const& strategy)
{
BOOST_GEOMETRY_ASSERT( current != last );
@ -1340,14 +1336,14 @@ struct linear_areal
typename Geometry,
typename OtherGeometry,
typename BoundaryChecker,
typename SideStrategy>
typename Strategy>
static inline void analyse_each_turn(Result & res,
Analyser & analyser,
TurnIt first, TurnIt last,
Geometry const& geometry,
OtherGeometry const& other_geometry,
BoundaryChecker const& boundary_checker,
SideStrategy const& side_strategy)
Strategy const& strategy)
{
if ( first == last )
return;
@ -1357,7 +1353,7 @@ struct linear_areal
analyser.apply(res, it,
geometry, other_geometry,
boundary_checker,
side_strategy);
strategy);
if ( BOOST_GEOMETRY_CONDITION( res.interrupt ) )
return;
@ -1437,9 +1433,9 @@ struct linear_areal
, m_previous_turn_ptr(NULL)
{}
template <typename TurnIt, typename EqPPStrategy>
template <typename TurnIt, typename Strategy>
bool apply(TurnIt /*first*/, TurnIt it, TurnIt last,
EqPPStrategy const& strategy)
Strategy const& strategy)
{
overlay::operation_type op = it->operations[1].operation;
@ -1493,12 +1489,12 @@ struct areal_linear
static const bool interruption_enabled = linear_areal_type::interruption_enabled;
template <typename Result, typename IntersectionStrategy>
template <typename Result, typename Strategy>
static inline void apply(Geometry1 const& geometry1, Geometry2 const& geometry2,
Result & result,
IntersectionStrategy const& intersection_strategy)
Strategy const& strategy)
{
linear_areal_type::apply(geometry2, geometry1, result, intersection_strategy);
linear_areal_type::apply(geometry2, geometry1, result, strategy);
}
};

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -2,8 +2,8 @@
// Copyright (c) 2015 Barend Gehrels, Amsterdam, the Netherlands.
// This file was modified by Oracle on 2018.
// Modifications copyright (c) 2018, Oracle and/or its affiliates.
// This file was modified by Oracle on 2018-2020.
// Modifications copyright (c) 2018-2020, Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Use, modification and distribution is subject to the Boost Software License,
@ -26,28 +26,39 @@ namespace boost { namespace geometry
namespace detail { namespace section
{
template <typename ExpandBoxStrategy>
template <typename Strategy>
struct get_section_box
{
get_section_box(Strategy const& strategy)
: m_strategy(strategy)
{}
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);
geometry::expand(total, section.bounding_box,
ExpandBoxStrategy());
geometry::expand(total, section.bounding_box, m_strategy);
}
Strategy const& m_strategy;
};
template <typename DisjointBoxBoxStrategy>
template <typename Strategy>
struct overlaps_section_box
{
overlaps_section_box(Strategy const& strategy)
: m_strategy(strategy)
{}
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);
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/geometries/concepts/check.hpp>
#include <boost/geometry/geometries/box.hpp>
#include <boost/geometry/geometries/segment.hpp>
#include <boost/geometry/policies/robustness/no_rescale_policy.hpp>
#include <boost/geometry/policies/robustness/robust_point_type.hpp>
@ -336,9 +337,9 @@ struct assign_loop<T, Count, Count>
template <typename CSTag>
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,
EnvelopeStrategy const& strategy)
Strategy const& strategy)
{
geometry::model::referring_segment<Point const> seg(prev, curr);
geometry::envelope(seg, box, strategy);
@ -348,12 +349,12 @@ struct box_first_in_section
template <>
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,
ExpandStrategy const& )
Strategy const& strategy)
{
geometry::envelope(prev, box);
geometry::expand(box, curr);
geometry::envelope(prev, box, strategy);
geometry::expand(box, curr, strategy);
}
};
@ -374,9 +375,9 @@ struct box_next_in_section<cartesian_tag>
{
template <typename Box, typename Point, typename Strategy>
static inline void apply(Box & box, Point const& , Point const& curr,
Strategy const& )
Strategy const& strategy)
{
geometry::expand(box, curr);
geometry::expand(box, curr, strategy);
}
};
@ -391,50 +392,17 @@ struct sectionalize_part
static const std::size_t dimension_count
= util::sequence_size<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
<
typename Iterator,
typename RobustPolicy,
typename Sections,
typename EnvelopeStrategy,
typename ExpandStrategy
typename Strategy
>
static inline void apply(Sections& sections,
Iterator begin, Iterator end,
RobustPolicy const& robust_policy,
EnvelopeStrategy const& envelope_strategy,
ExpandStrategy const& expand_strategy,
Strategy const& strategy,
ring_identifier ring_id,
std::size_t max_count)
{
@ -448,10 +416,10 @@ struct sectionalize_part
);
typedef typename geometry::robust_point_type
<
Point,
RobustPolicy
>::type robust_point_type;
<
Point,
RobustPolicy
>::type robust_point_type;
std::size_t const count = std::distance(begin, end);
if (count == 0)
@ -552,14 +520,14 @@ struct sectionalize_part
// In cartesian this is envelope of previous point expanded with current point
// in non-cartesian this is envelope of a segment
box_first_in_section<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
{
// In cartesian this is expand with current point
// in non-cartesian this is expand with a segment
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;
@ -605,23 +573,21 @@ struct sectionalize_range
typename Range,
typename RobustPolicy,
typename Sections,
typename EnvelopeStrategy,
typename ExpandStrategy
typename Strategy
>
static inline void apply(Range const& range,
RobustPolicy const& robust_policy,
Sections& sections,
EnvelopeStrategy const& envelope_strategy,
ExpandStrategy const& expand_strategy,
Strategy const& strategy,
ring_identifier ring_id,
std::size_t max_count)
{
typedef typename closeable_view<Range const, Closure>::type cview_type;
typedef typename reversible_view
<
cview_type const,
Reverse ? iterate_reverse : iterate_forward
>::type view_type;
<
cview_type const,
Reverse ? iterate_reverse : iterate_forward
>::type view_type;
cview_type cview(range);
view_type view(cview);
@ -641,7 +607,7 @@ struct sectionalize_range
sectionalize_part<Point, DimensionVector>::apply(sections,
boost::begin(view), boost::end(view),
robust_policy, envelope_strategy, expand_strategy,
robust_policy, strategy,
ring_id, max_count);
}
};
@ -658,27 +624,24 @@ struct sectionalize_polygon
typename Polygon,
typename RobustPolicy,
typename Sections,
typename EnvelopeStrategy,
typename ExpandStrategy
typename Strategy
>
static inline void apply(Polygon const& poly,
RobustPolicy const& robust_policy,
Sections& sections,
EnvelopeStrategy const& envelope_strategy,
ExpandStrategy const& expand_strategy,
Strategy const& strategy,
ring_identifier ring_id,
std::size_t max_count)
{
typedef typename point_type<Polygon>::type point_type;
typedef sectionalize_range
<
closure<Polygon>::value, Reverse,
point_type, DimensionVector
> per_range;
<
closure<Polygon>::value, Reverse, point_type, DimensionVector
> per_range;
ring_id.ring_index = -1;
per_range::apply(exterior_ring(poly), robust_policy, sections,
envelope_strategy, expand_strategy, ring_id, max_count);
strategy, ring_id, max_count);
ring_id.ring_index++;
typename interior_return_type<Polygon const>::type
@ -687,7 +650,7 @@ struct sectionalize_polygon
it = boost::begin(rings); it != boost::end(rings); ++it, ++ring_id.ring_index)
{
per_range::apply(*it, robust_policy, sections,
envelope_strategy, expand_strategy, ring_id, max_count);
strategy, ring_id, max_count);
}
}
};
@ -700,14 +663,12 @@ struct sectionalize_box
typename Box,
typename RobustPolicy,
typename Sections,
typename EnvelopeStrategy,
typename ExpandStrategy
typename Strategy
>
static inline void apply(Box const& box,
RobustPolicy const& robust_policy,
Sections& sections,
EnvelopeStrategy const& envelope_strategy,
ExpandStrategy const& expand_strategy,
Strategy const& strategy,
ring_identifier const& ring_id, std::size_t max_count)
{
typedef typename point_type<Box>::type point_type;
@ -735,13 +696,10 @@ struct sectionalize_box
// NOTE: Use cartesian envelope strategy in all coordinate systems
// because edges of a box are not geodesic segments
sectionalize_range
<
closed, false,
point_type,
DimensionVector
>::apply(points, robust_policy, sections,
envelope_strategy, expand_strategy,
ring_id, max_count);
<
closed, false, point_type, DimensionVector
>::apply(points, robust_policy, sections,
strategy, ring_id, max_count);
}
};
@ -753,14 +711,12 @@ struct sectionalize_multi
typename MultiGeometry,
typename RobustPolicy,
typename Sections,
typename EnvelopeStrategy,
typename ExpandStrategy
typename Strategy
>
static inline void apply(MultiGeometry const& multi,
RobustPolicy const& robust_policy,
Sections& sections,
EnvelopeStrategy const& envelope_strategy,
ExpandStrategy const& expand_strategy,
Strategy const& strategy,
ring_identifier ring_id,
std::size_t max_count)
{
@ -771,7 +727,7 @@ struct sectionalize_multi
++it, ++ring_id.multi_index)
{
Policy::apply(*it, robust_policy, sections,
envelope_strategy, expand_strategy,
strategy,
ring_id, max_count);
}
}
@ -983,7 +939,7 @@ struct sectionalize<multi_linestring_tag, MultiLinestring, Reverse, DimensionVec
\param geometry geometry to create sections from
\param robust_policy policy to handle robustness issues
\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 source_index index to assign to the ring_identifiers
\param max_count maximal number of points per section
@ -997,19 +953,15 @@ template
typename Geometry,
typename Sections,
typename RobustPolicy,
typename EnvelopeStrategy,
typename ExpandStrategy
typename Strategy
>
inline void sectionalize(Geometry const& geometry,
RobustPolicy const& robust_policy,
Sections& sections,
EnvelopeStrategy const& envelope_strategy,
ExpandStrategy const& expand_strategy,
Strategy const& strategy,
int source_index = 0,
std::size_t max_count = 10)
{
BOOST_STATIC_ASSERT((! std::is_fundamental<EnvelopeStrategy>::value));
concepts::check<Geometry const>();
typedef typename boost::range_value<Sections>::type section_type;
@ -1044,10 +996,10 @@ inline void sectionalize(Geometry const& geometry,
Reverse,
DimensionVector
>::apply(geometry, robust_policy, sections,
envelope_strategy, expand_strategy,
strategy,
ring_id, max_count);
detail::sectionalize::enlarge_sections(sections, envelope_strategy);
detail::sectionalize::enlarge_sections(sections, strategy);
}
@ -1065,29 +1017,17 @@ inline void sectionalize(Geometry const& geometry,
int source_index = 0,
std::size_t max_count = 10)
{
typedef typename strategy::envelope::services::default_strategy
typedef typename strategies::envelope::services::default_strategy
<
typename tag<Geometry>::type,
typename cs_tag<Geometry>::type
>::type envelope_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;
Geometry,
model::box<typename point_type<Geometry>::type>
>::type strategy_type;
boost::geometry::sectionalize
<
Reverse, DimensionVector
>(geometry, robust_policy, sections,
envelope_strategy_type(),
expand_strategy_type(),
strategy_type(),
source_index, max_count);
}

View File

@ -212,29 +212,24 @@ inline bool point_on_border_within(Geometry1 const& geometry1,
&& 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,
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 point_on_border_within(range, geometry1, point_in_ring_strategy);
return point_on_border_within(range, geometry1, strategy);
});
}
template <typename Geometry1, typename Geometry2>
struct areal_areal
{
template <typename IntersectionStrategy>
template <typename Strategy>
static inline bool apply(Geometry1 const& geometry1,
Geometry2 const& geometry2,
IntersectionStrategy const& strategy)
Strategy const& strategy)
{
typedef typename geometry::point_type<Geometry1>::type point_type;
typedef detail::overlay::turn_info<point_type> turn_info;
@ -411,7 +406,7 @@ struct self_touches
{
concepts::check<Geometry const>();
typedef typename strategy::relate::services::default_strategy
typedef typename strategies::relate::services::default_strategy
<
Geometry, Geometry
>::type strategy_type;
@ -419,18 +414,19 @@ struct self_touches
typedef detail::overlay::turn_info<point_type> turn_info;
typedef detail::overlay::get_turn_info
<
detail::overlay::assign_null_policy
> policy_type;
<
detail::overlay::assign_null_policy
> policy_type;
std::deque<turn_info> turns;
detail::touches::areal_interrupt_policy policy;
strategy_type strategy;
// TODO: skip_adjacent should be set to false
detail::self_get_turn_points::get_turns
<
false, policy_type
>::apply(geometry, strategy, detail::no_rescale_policy(), turns, policy, 0, true);
<
false, policy_type
>::apply(geometry, strategy, detail::no_rescale_policy(),
turns, policy, 0, true);
return policy.result();
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -2,7 +2,7 @@
// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.
// This file was modified by Oracle on 2015, 2017, 2019, 2020.
// This file was modified by Oracle on 2015-2020.
// Modifications copyright (c) 2015-2020 Oracle and/or its affiliates.
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
@ -29,7 +29,8 @@
#include <boost/geometry/geometries/multi_polygon.hpp>
#include <boost/geometry/policies/robustness/get_rescale_policy.hpp>
#include <boost/geometry/strategies/default_strategy.hpp>
#include <boost/geometry/strategies/relate.hpp>
#include <boost/geometry/strategies/detail.hpp>
#include <boost/geometry/strategies/relate/services.hpp>
#include <boost/geometry/util/range.hpp>
@ -497,9 +498,9 @@ template
inline OutputIterator sym_difference_insert(Geometry1 const& geometry1,
Geometry2 const& geometry2, OutputIterator out)
{
typedef typename strategy::intersection::services::default_strategy
typedef typename strategies::relate::services::default_strategy
<
typename cs_tag<GeometryOut>::type
Geometry1, Geometry2
>::type 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 {
template
<
typename Strategy,
bool IsUmbrella = strategies::detail::is_umbrella_strategy<Strategy>::value
>
struct sym_difference
{
template
<
typename Geometry1,
typename Geometry2,
typename Collection,
typename Strategy
>
template <typename Geometry1, typename Geometry2, typename Collection>
static inline void apply(Geometry1 const& geometry1,
Geometry2 const& geometry2,
Collection & output_collection,
@ -535,13 +535,31 @@ struct sym_difference
geometry::detail::output_geometry_back_inserter(output_collection),
strategy);
}
};
template
<
typename Geometry1,
typename Geometry2,
typename Collection
>
template <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
<
decltype(strategy_converter<Strategy>::get(strategy))
>::apply(geometry1, geometry2, output_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,
Geometry2 const& geometry2,
Collection & output_collection,
@ -552,7 +570,10 @@ struct sym_difference
Geometry1, Geometry2
>::type strategy_type;
apply(geometry1, geometry2, output_collection, strategy_type());
sym_difference
<
strategy_type
>::apply(geometry1, geometry2, output_collection, strategy_type());
}
};
@ -571,9 +592,10 @@ struct sym_difference
Collection& output_collection,
Strategy const& strategy)
{
resolve_strategy::sym_difference::apply(geometry1, geometry2,
output_collection,
strategy);
resolve_strategy::sym_difference
<
Strategy
>::apply(geometry1, geometry2, output_collection, strategy);
}
};

View File

@ -18,13 +18,15 @@
#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/reverse_dispatch.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/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/algorithms/detail/intersection/multi.hpp>
@ -349,9 +351,9 @@ inline OutputIterator union_insert(Geometry1 const& geometry1,
concepts::check<Geometry2 const>();
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;
typedef typename geometry::rescale_overlay_policy_type
@ -377,15 +379,14 @@ inline OutputIterator union_insert(Geometry1 const& geometry1,
namespace resolve_strategy {
template
<
typename Strategy,
bool IsUmbrella = strategies::detail::is_umbrella_strategy<Strategy>::value
>
struct union_
{
template
<
typename Geometry1,
typename Geometry2,
typename Collection,
typename Strategy
>
template <typename Geometry1, typename Geometry2, typename Collection>
static inline void apply(Geometry1 const& geometry1,
Geometry2 const& geometry2,
Collection & output_collection,
@ -414,25 +415,46 @@ struct union_
geometry::detail::output_geometry_back_inserter(output_collection),
strategy);
}
};
template
<
typename Geometry1,
typename Geometry2,
typename Collection
>
template <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_
<
decltype(strategy_converter<Strategy>::get(strategy))
>::apply(geometry1, geometry2, output_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,
Geometry2 const& geometry2,
Collection & output_collection,
default_strategy)
{
typedef typename strategy::relate::services::default_strategy
typedef typename strategies::relate::services::default_strategy
<
Geometry1,
Geometry2
>::type strategy_type;
apply(geometry1, geometry2, output_collection, strategy_type());
union_
<
strategy_type
>::apply(geometry1, geometry2, output_collection, strategy_type());
}
};
@ -462,9 +484,10 @@ struct union_
>::type
>::apply();
resolve_strategy::union_::apply(geometry1, geometry2,
output_collection,
strategy);
resolve_strategy::union_
<
Strategy
>::apply(geometry1, geometry2, output_collection, strategy);
}
};

View File

@ -433,7 +433,7 @@ struct dissolver_generic
// 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);
it1 != boost::end(index_vector);
@ -520,7 +520,7 @@ struct dissolver_generic
boost::end(output_collection)),
helper_vector,
strategy,
n, 1);
static_cast<int>(n), 1);
return changed;
}
@ -577,8 +577,8 @@ struct dissolver_generic
std::vector<output_type> unioned_collection;
int size = 0, previous_size = 0;
int n = 0;
std::size_t size = 0, previous_size = 0;
std::size_t n = 0;
bool changed = false;
while(divide_and_conquer<1>

View File

@ -418,6 +418,72 @@ struct dissolve<Polygon, PolygonOut, Reverse, polygon_tag, polygon_tag>
#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
@ -449,9 +515,10 @@ inline OutputIterator dissolve_inserter(Geometry const& geometry,
concepts::check<GeometryOut>();
typedef typename geometry::rescale_policy_type
<
typename geometry::point_type<Geometry>::type
>::type rescale_policy_type;
<
typename geometry::point_type<Geometry>::type,
typename Strategy::cs_tag
>::type rescale_policy_type;
rescale_policy_type robust_policy
= geometry::get_rescale_policy<rescale_policy_type>(
@ -459,15 +526,10 @@ inline OutputIterator dissolve_inserter(Geometry const& geometry,
detail::overlay::overlay_null_visitor visitor;
return dispatch::dissolve
<
Geometry,
GeometryOut,
detail::overlay::do_reverse
return resolve_strategy::dissolve
<
geometry::point_order<Geometry>::value
>::value
>::apply(geometry, robust_policy, out, strategy, visitor);
GeometryOut, Strategy
>::apply(geometry, robust_policy, out, strategy, visitor);
}
/*!
@ -492,9 +554,9 @@ template
inline OutputIterator dissolve_inserter(Geometry const& geometry,
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;
return dissolve_inserter<GeometryOut>(geometry, out, strategy_type());
@ -517,9 +579,10 @@ inline void dissolve(Geometry const& geometry, Collection& output_collection,
concepts::check<geometry_out>();
typedef typename geometry::rescale_policy_type
<
typename geometry::point_type<Geometry>::type
>::type rescale_policy_type;
<
typename geometry::point_type<Geometry>::type,
typename Strategy::cs_tag
>::type rescale_policy_type;
rescale_policy_type robust_policy
= geometry::get_rescale_policy<rescale_policy_type>(
@ -527,17 +590,12 @@ inline void dissolve(Geometry const& geometry, Collection& output_collection,
detail::overlay::overlay_null_visitor visitor;
dispatch::dissolve
<
Geometry,
geometry_out,
detail::overlay::do_reverse
return resolve_strategy::dissolve
<
geometry::point_order<Geometry>::value
>::value
>::apply(geometry, robust_policy,
std::back_inserter(output_collection),
strategy, visitor);
geometry_out, Strategy
>::apply(geometry, robust_policy,
std::back_inserter(output_collection),
strategy, visitor);
}
template
@ -547,9 +605,9 @@ template
>
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;
dissolve(geometry, output_collection, strategy_type());

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