updated boost on windows

This commit is contained in:
Bassem Girgis
2019-08-13 21:48:48 -05:00
parent 7d77d485fd
commit b40a3bee82
5162 changed files with 473027 additions and 116452 deletions

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.
// Modifications copyright (c) 2013-2017 Oracle and/or its affiliates.
// This file was modified by Oracle on 2013, 2014, 2015, 2017, 2018.
// Modifications copyright (c) 2013-2018 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -277,7 +277,8 @@ struct areal_areal
{
// analyse sorted turns
turns_analyser<turn_type, 0> analyser;
analyse_each_turn(result, analyser, turns.begin(), turns.end());
analyse_each_turn(result, analyser, turns.begin(), turns.end(),
point_in_areal_strategy12.get_equals_point_point_strategy());
if ( BOOST_GEOMETRY_CONDITION(result.interrupt) )
return;
@@ -317,7 +318,8 @@ struct areal_areal
{
// analyse sorted turns
turns_analyser<turn_type, 1> analyser;
analyse_each_turn(result, analyser, turns.begin(), turns.end());
analyse_each_turn(result, analyser, turns.begin(), turns.end(),
point_in_areal_strategy21.get_equals_point_point_strategy());
if ( BOOST_GEOMETRY_CONDITION(result.interrupt) )
return;
@@ -441,9 +443,8 @@ struct areal_areal
, m_exit_detected(false)
{}
template <typename Result,
typename TurnIt>
void apply(Result & result, TurnIt it)
template <typename Result, typename TurnIt, typename EqPPStrategy>
void apply(Result & result, TurnIt it, EqPPStrategy const& strategy)
{
//BOOST_GEOMETRY_ASSERT( it != last );
@@ -468,7 +469,7 @@ struct areal_areal
{
// real exit point - may be multiple
if ( first_in_range
|| ! turn_on_the_same_ip<op_id>(*m_previous_turn_ptr, *it) )
|| ! turn_on_the_same_ip<op_id>(*m_previous_turn_ptr, *it, strategy) )
{
update_exit(result);
m_exit_detected = false;
@@ -484,7 +485,7 @@ struct areal_areal
{
// real entry point
if ( first_in_range
|| ! turn_on_the_same_ip<op_id>(*m_previous_turn_ptr, *it) )
|| ! turn_on_the_same_ip<op_id>(*m_previous_turn_ptr, *it, strategy) )
{
update_enter(result);
m_enter_detected = false;
@@ -581,19 +582,24 @@ struct areal_areal
// call analyser.apply() for each turn in range
// IMPORTANT! The analyser is also called for the end iterator - last
template <typename Result,
typename Analyser,
typename TurnIt>
template
<
typename Result,
typename Analyser,
typename TurnIt,
typename EqPPStrategy
>
static inline void analyse_each_turn(Result & res,
Analyser & analyser,
TurnIt first, TurnIt last)
TurnIt first, TurnIt last,
EqPPStrategy const& strategy)
{
if ( first == last )
return;
for ( TurnIt it = first ; it != last ; ++it )
{
analyser.apply(res, it);
analyser.apply(res, it, strategy);
if ( BOOST_GEOMETRY_CONDITION(res.interrupt) )
return;

View File

@@ -1,23 +1,26 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2014 Oracle and/or its affiliates.
// Copyright (c) 2014-2018 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_BOUNDARY_CHECKER_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_BOUNDARY_CHECKER_HPP
#include <boost/geometry/util/range.hpp>
#include <boost/geometry/algorithms/num_points.hpp>
#include <boost/geometry/algorithms/detail/sub_range.hpp>
#include <boost/core/ignore_unused.hpp>
#include <boost/geometry/algorithms/detail/equals/point_point.hpp>
#include <boost/geometry/algorithms/detail/sub_range.hpp>
#include <boost/geometry/algorithms/num_points.hpp>
#include <boost/geometry/policies/compare.hpp>
#include <boost/geometry/util/has_nan_coordinate.hpp>
#include <boost/geometry/util/range.hpp>
namespace boost { namespace geometry
{
@@ -28,46 +31,57 @@ 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>
class boundary_checker {};
template <typename Geometry>
class boundary_checker<Geometry, linestring_tag>
template <typename Geometry, typename WithinStrategy>
class boundary_checker<Geometry, WithinStrategy, 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)) )
&& !detail::equals::equals_point_point(range::front(g),
range::back(g),
equals_strategy_type()) )
#ifdef BOOST_GEOMETRY_DEBUG_RELATE_BOUNDARY_CHECKER
, geometry(g)
#endif
{}
template <boundary_query BoundaryQuery>
bool is_endpoint_boundary(point_type const& pt) const
{
boost::ignore_unused_variable_warning(pt);
boost::ignore_unused(pt);
#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))
&& detail::equals::equals_point_point(pt, range::front(geometry), WithinStrategy())
|| (BoundaryQuery == boundary_back || BoundaryQuery == boundary_any)
&& detail::equals::equals_point_point(pt, range::back(geometry)) );
&& detail::equals::equals_point_point(pt, range::back(geometry), WithinStrategy()) );
#endif
return has_boundary;
}
private:
bool has_boundary;
#ifdef BOOST_GEOMETRY_DEBUG_RELATE_BOUNDARY_CHECKER
Geometry const& geometry;
#endif
};
template <typename Geometry>
class boundary_checker<Geometry, multi_linestring_tag>
template <typename Geometry, typename WithinStrategy>
class boundary_checker<Geometry, WithinStrategy, 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)
{}
@@ -110,7 +124,7 @@ public:
point_reference back_pt = range::back(ls);
// linear ring or point - no boundary
if (! equals::equals_point_point(front_pt, back_pt))
if (! equals::equals_point_point(front_pt, back_pt, equals_strategy_type()))
{
// do not add points containing NaN coordinates
// because they cannot be reasonably compared, e.g. with MSVC

View File

@@ -2,23 +2,33 @@
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
// This file was modified by Oracle on 2013, 2014.
// Modifications copyright (c) 2013-2014 Oracle and/or its affiliates.
// This file was modified by Oracle on 2013, 2014, 2018.
// Modifications copyright (c) 2013-2018 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_FOLLOW_HELPERS_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_FOLLOW_HELPERS_HPP
#include <vector>
#include <boost/core/ignore_unused.hpp>
#include <boost/geometry/algorithms/detail/overlay/get_turn_info_helpers.hpp>
#include <boost/geometry/algorithms/detail/overlay/overlay_type.hpp>
#include <boost/geometry/algorithms/detail/overlay/segment_identifier.hpp>
#include <boost/geometry/algorithms/detail/relate/boundary_checker.hpp>
#include <boost/geometry/algorithms/not_implemented.hpp>
#include <boost/geometry/core/assert.hpp>
#include <boost/geometry/util/condition.hpp>
#include <boost/geometry/util/range.hpp>
//#include <boost/geometry/algorithms/detail/sub_range.hpp>
namespace boost { namespace geometry
{
@@ -94,7 +104,7 @@ struct for_each_disjoint_geometry_if<OpId, Geometry, Tag, true>
BOOST_GEOMETRY_ASSERT(first != last);
const std::size_t count = boost::size(geometry);
boost::ignore_unused_variable_warning(count);
boost::ignore_unused(count);
// O(I)
// gather info about turns generated for contained geometries
@@ -331,8 +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>
inline bool turn_on_the_same_ip(Turn const& prev_turn, Turn const& curr_turn)
template <std::size_t OpId, typename Turn, typename EqPPStrategy>
inline bool turn_on_the_same_ip(Turn const& prev_turn, Turn const& curr_turn,
EqPPStrategy 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;
@@ -352,7 +363,7 @@ inline bool turn_on_the_same_ip(Turn const& prev_turn, Turn const& curr_turn)
return false;
}
return detail::equals::equals_point_point(prev_turn.point, curr_turn.point);
return detail::equals::equals_point_point(prev_turn.point, curr_turn.point, strategy);
}
template <boundary_query BoundaryQuery,
@@ -373,7 +384,7 @@ static inline bool is_ip_on_boundary(IntersectionPoint const& ip,
BoundaryChecker & boundary_checker,
segment_identifier const& seg_id)
{
boost::ignore_unused_variable_warning(seg_id);
boost::ignore_unused(seg_id);
bool res = false;

View File

@@ -23,6 +23,7 @@
#include <boost/geometry/algorithms/detail/relate/point_geometry.hpp>
#include <boost/geometry/algorithms/detail/relate/linear_linear.hpp>
#include <boost/geometry/algorithms/detail/relate/linear_areal.hpp>
#include <boost/geometry/algorithms/detail/relate/multi_point_geometry.hpp>
#include <boost/geometry/algorithms/detail/relate/areal_areal.hpp>
#include <boost/geometry/strategies/intersection.hpp>
@@ -81,6 +82,16 @@ struct relate<Geometry, Point, Tag1, point_tag, TopDim1, 0, true>
: detail::relate::geometry_point<Geometry, Point>
{};
template <typename MultiPoint, typename Geometry, typename Tag2, int TopDim2>
struct relate<MultiPoint, Geometry, multi_point_tag, Tag2, 0, TopDim2, false>
: detail::relate::multi_point_geometry<MultiPoint, Geometry>
{};
template <typename Geometry, typename MultiPoint, typename Tag1, int TopDim1>
struct relate<Geometry, MultiPoint, Tag1, multi_point_tag, TopDim1, 0, false>
: detail::relate::geometry_multi_point<Geometry, MultiPoint>
{};
template <typename Linear1, typename Linear2, typename Tag1, typename Tag2>
struct relate<Linear1, Linear2, Tag1, Tag2, 1, 1, true>

View File

@@ -1,83 +0,0 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands.
// This file was modified by Oracle on 2014.
// Modifications copyright (c) 2014, Oracle and/or its affiliates.
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_LESS_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_LESS_HPP
#include <boost/geometry/core/coordinate_dimension.hpp>
#include <boost/geometry/core/coordinate_type.hpp>
#include <boost/geometry/util/math.hpp>
namespace boost { namespace geometry
{
#ifndef DOXYGEN_NO_DISPATCH
namespace detail_dispatch { namespace relate {
// TODO: Integrate it with geometry::less?
template <typename Point1,
typename Point2,
std::size_t I = 0,
std::size_t D = geometry::dimension<Point1>::value>
struct less
{
static inline bool apply(Point1 const& left, Point2 const& right)
{
typename geometry::coordinate_type<Point1>::type
cleft = geometry::get<I>(left);
typename geometry::coordinate_type<Point2>::type
cright = geometry::get<I>(right);
if ( geometry::math::equals(cleft, cright) )
{
return less<Point1, Point2, I + 1, D>::apply(left, right);
}
else
{
return cleft < cright;
}
}
};
template <typename Point1, typename Point2, std::size_t D>
struct less<Point1, Point2, D, D>
{
static inline bool apply(Point1 const&, Point2 const&)
{
return false;
}
};
}} // namespace detail_dispatch::relate
#endif
#ifndef DOXYGEN_NO_DETAIL
namespace detail { namespace relate {
struct less
{
template <typename Point1, typename Point2>
inline bool operator()(Point1 const& point1, Point2 const& point2) const
{
return detail_dispatch::relate::less<Point1, Point2>::apply(point1, point2);
}
};
}} // namespace detail::relate
#endif // DOXYGEN_NO_DETAIL
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_LESS_HPP

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.
// Modifications copyright (c) 2013-2017 Oracle and/or its affiliates.
// This file was modified by Oracle on 2013, 2014, 2015, 2017, 2018.
// Modifications copyright (c) 2013-2018 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -260,17 +260,28 @@ struct linear_areal
if ( BOOST_GEOMETRY_CONDITION( result.interrupt ) )
return;
boundary_checker<Geometry1> boundary_checker1(geometry1);
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 within_strategy_type::equals_point_point_strategy_type eq_pp_strategy_type;
typedef boundary_checker
<
Geometry1,
eq_pp_strategy_type
> boundary_checker1_type;
boundary_checker1_type boundary_checker1(geometry1);
no_turns_la_linestring_pred
<
Geometry2,
Result,
typename IntersectionStrategy::template point_in_geometry_strategy<Geometry1, Geometry2>::type,
boundary_checker<Geometry1>,
within_strategy_type,
boundary_checker1_type,
TransposeResult
> pred1(geometry2,
result,
intersection_strategy.template get_point_in_geometry_strategy<Geometry1, Geometry2>(),
within_strategy,
boundary_checker1);
for_each_disjoint_geometry_if<0, Geometry1>::apply(turns.begin(), turns.end(), geometry1, pred1);
if ( BOOST_GEOMETRY_CONDITION( result.interrupt ) )
@@ -391,12 +402,14 @@ struct linear_areal
typedef turns::less<1, turns::less_op_areal_linear<1> > 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) )
if ( !analyser.apply(it, rit, next, eq_pp_strategy) )
break;
}
@@ -619,6 +632,37 @@ struct linear_areal
static const std::size_t op_id = 0;
static const std::size_t other_op_id = 1;
template <typename TurnPointCSTag, typename PointP, typename PointQ,
typename SideStrategy,
typename Pi = PointP, typename Pj = PointP, typename Pk = PointP,
typename Qi = PointQ, typename Qj = PointQ, typename Qk = PointQ
>
struct la_side_calculator
{
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)
: m_pi(pi), m_pj(pj), m_pk(pk)
, m_qi(qi), m_qj(qj), m_qk(qk)
, m_side_strategy(side_strategy)
{}
inline int pk_wrt_p1() const { return m_side_strategy.apply(m_pi, m_pj, m_pk); }
inline int qk_wrt_p1() const { return m_side_strategy.apply(m_pi, m_pj, m_qk); }
inline int pk_wrt_q2() const { return m_side_strategy.apply(m_qj, m_qk, m_pk); }
private :
Pi const& m_pi;
Pj const& m_pj;
Pk const& m_pk;
Qi const& m_qi;
Qj const& m_qj;
Qk const& m_qk;
SideStrategy m_side_strategy;
};
public:
turns_analyser()
: m_previous_turn_ptr(NULL)
@@ -668,7 +712,8 @@ 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) )
if ( ! turn_on_the_same_ip<op_id>(m_exit_watcher.get_exit_turn(), *it,
side_strategy.get_equals_point_point_strategy()) )
{
m_exit_watcher.reset_detected_exit();
@@ -710,7 +755,8 @@ 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) )
&& turn_on_the_same_ip<op_id>(m_exit_watcher.get_exit_turn(), *it,
side_strategy.get_equals_point_point_strategy()) )
{
fake_enter_detected = true;
}
@@ -730,7 +776,8 @@ struct linear_areal
&& ( op != overlay::operation_blocked // operation different than block
|| 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) )
&& ! turn_on_the_same_ip<op_id>(*m_previous_turn_ptr, *it,
side_strategy.get_equals_point_point_strategy()) )
)
{
update<interior, exterior, '1', TransposeResult>(res);
@@ -762,7 +809,8 @@ struct linear_areal
BOOST_GEOMETRY_ASSERT_MSG(m_previous_turn_ptr, "non-NULL ptr expected");
// real interior overlap
if ( ! turn_on_the_same_ip<op_id>(*m_previous_turn_ptr, *it) )
if ( ! turn_on_the_same_ip<op_id>(*m_previous_turn_ptr, *it,
side_strategy.get_equals_point_point_strategy()) )
{
update<interior, interior, '1', TransposeResult>(res);
m_interior_detected = false;
@@ -1201,7 +1249,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);
bool const is_ip_qj = equals::equals_point_point(turn.point, qj, side_strategy.get_equals_point_point_strategy());
// TODO: test this!
// BOOST_GEOMETRY_ASSERT(!equals::equals_point_point(turn.point, pi));
// BOOST_GEOMETRY_ASSERT(!equals::equals_point_point(turn.point, qi));
@@ -1215,10 +1263,11 @@ struct linear_areal
// It would be good to replace it with some O(1) mechanism
range2_iterator qk_it = find_next_non_duplicated(boost::begin(range2),
range::pos(range2, q_seg_jk),
boost::end(range2));
boost::end(range2),
side_strategy.get_equals_point_point_strategy());
// Will this sequence of points be always correct?
overlay::side_calculator<cs_tag, point1_type, point2_type, SideStrategy>
la_side_calculator<cs_tag, point1_type, point2_type, SideStrategy>
side_calc(qi_conv, new_pj, pi, qi, qj, *qk_it, side_strategy);
return calculate_from_inside_sides(side_calc);
@@ -1228,15 +1277,16 @@ struct linear_areal
point2_type new_qj;
geometry::convert(turn.point, new_qj);
overlay::side_calculator<cs_tag, point1_type, point2_type, SideStrategy>
la_side_calculator<cs_tag, point1_type, point2_type, SideStrategy>
side_calc(qi_conv, new_pj, pi, qi, new_qj, qj, side_strategy);
return calculate_from_inside_sides(side_calc);
}
}
template <typename It>
static inline It find_next_non_duplicated(It first, It current, It last)
template <typename It, typename EqPPStrategy>
static inline It find_next_non_duplicated(It first, It current, It last,
EqPPStrategy const& strategy)
{
BOOST_GEOMETRY_ASSERT( current != last );
@@ -1244,14 +1294,14 @@ struct linear_areal
for ( ++it ; it != last ; ++it )
{
if ( !equals::equals_point_point(*current, *it) )
if ( !equals::equals_point_point(*current, *it, strategy) )
return it;
}
// if not found start from the beginning
for ( it = first ; it != current ; ++it )
{
if ( !equals::equals_point_point(*current, *it) )
if ( !equals::equals_point_point(*current, *it, strategy) )
return it;
}
@@ -1394,8 +1444,9 @@ struct linear_areal
, m_previous_turn_ptr(NULL)
{}
template <typename TurnIt>
bool apply(TurnIt /*first*/, TurnIt it, TurnIt last)
template <typename TurnIt, typename EqPPStrategy>
bool apply(TurnIt /*first*/, TurnIt it, TurnIt last,
EqPPStrategy const& strategy)
{
overlay::operation_type op = it->operations[1].operation;
@@ -1410,7 +1461,7 @@ struct linear_areal
if ( is_union_detected )
{
BOOST_GEOMETRY_ASSERT(m_previous_turn_ptr != NULL);
if ( !detail::equals::equals_point_point(it->point, m_previous_turn_ptr->point) )
if ( !detail::equals::equals_point_point(it->point, m_previous_turn_ptr->point, strategy) )
{
// break
return false;

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.
// Modifications copyright (c) 2013-2017 Oracle and/or its affiliates.
// This file was modified by Oracle on 2013, 2014, 2015, 2017, 2018.
// Modifications copyright (c) 2013-2018 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -42,6 +42,8 @@ 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)
@@ -80,7 +82,8 @@ public:
// point-like linestring
if ( count == 2
&& equals::equals_point_point(range::front(linestring),
range::back(linestring)) )
range::back(linestring),
equals_strategy_type()) )
{
update<interior, exterior, '0', TransposeResult>(m_result);
}
@@ -145,14 +148,24 @@ struct linear_linear
if ( BOOST_GEOMETRY_CONDITION( result.interrupt ) )
return;
boundary_checker<Geometry1> boundary_checker1(geometry1);
disjoint_linestring_pred<Result, boundary_checker<Geometry1>, false> pred1(result, boundary_checker1);
typedef boundary_checker
<
Geometry1,
typename IntersectionStrategy::point_in_point_strategy_type
> boundary_checker1_type;
boundary_checker1_type boundary_checker1(geometry1);
disjoint_linestring_pred<Result, boundary_checker1_type, false> pred1(result, boundary_checker1);
for_each_disjoint_geometry_if<0, Geometry1>::apply(turns.begin(), turns.end(), geometry1, pred1);
if ( BOOST_GEOMETRY_CONDITION( result.interrupt ) )
return;
boundary_checker<Geometry2> boundary_checker2(geometry2);
disjoint_linestring_pred<Result, boundary_checker<Geometry2>, true> pred2(result, boundary_checker2);
typedef boundary_checker
<
Geometry2,
typename IntersectionStrategy::point_in_point_strategy_type
> boundary_checker2_type;
boundary_checker2_type boundary_checker2(geometry2);
disjoint_linestring_pred<Result, boundary_checker2_type, true> pred2(result, boundary_checker2);
for_each_disjoint_geometry_if<1, Geometry2>::apply(turns.begin(), turns.end(), geometry2, pred2);
if ( BOOST_GEOMETRY_CONDITION( result.interrupt ) )
return;
@@ -274,6 +287,8 @@ 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;
@@ -323,7 +338,9 @@ struct linear_linear
{
// 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) )
if ( ! turn_on_the_same_ip<op_id>(m_exit_watcher.get_exit_turn(),
*it,
equals_strategy_type()) )
{
m_exit_watcher.reset_detected_exit();
@@ -344,7 +361,9 @@ struct linear_linear
return;
if ( op == overlay::operation_intersection
&& turn_on_the_same_ip<op_id>(m_exit_watcher.get_exit_turn(), *it) )
&& turn_on_the_same_ip<op_id>(m_exit_watcher.get_exit_turn(),
*it,
equals_strategy_type()) )
{
fake_enter_detected = true;
}
@@ -647,6 +666,11 @@ struct linear_linear
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
@@ -714,9 +738,13 @@ struct linear_linear
// here we don't know which one is degenerated
bool const is_point1 = boost::size(ls1_ref) == 2
&& equals::equals_point_point(range::front(ls1_ref), range::back(ls1_ref));
&& equals::equals_point_point(range::front(ls1_ref),
range::back(ls1_ref),
equals_strategy1_type());
bool const is_point2 = boost::size(ls2_ref) == 2
&& equals::equals_point_point(range::front(ls2_ref), range::back(ls2_ref));
&& equals::equals_point_point(range::front(ls2_ref),
range::back(ls2_ref),
equals_strategy2_type());
// if the second one is degenerated
if ( !is_point1 && is_point2 )

View File

@@ -0,0 +1,615 @@
// Boost.Geometry
// Copyright (c) 2017-2018 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_MULTI_POINT_GEOMETRY_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_MULTI_POINT_GEOMETRY_HPP
#include <boost/range.hpp>
#include <boost/geometry/algorithms/detail/disjoint/box_box.hpp>
#include <boost/geometry/algorithms/detail/disjoint/point_box.hpp>
#include <boost/geometry/algorithms/detail/expand_by_epsilon.hpp>
#include <boost/geometry/algorithms/detail/partition.hpp>
#include <boost/geometry/algorithms/detail/relate/result.hpp>
#include <boost/geometry/algorithms/detail/relate/topology_check.hpp>
#include <boost/geometry/algorithms/detail/within/point_in_geometry.hpp>
#include <boost/geometry/algorithms/envelope.hpp>
#include <boost/geometry/core/is_areal.hpp>
#include <boost/geometry/core/point_type.hpp>
#include <boost/geometry/geometries/box.hpp>
#include <boost/geometry/index/rtree.hpp>
namespace boost { namespace geometry
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail { namespace relate
{
template
<
typename Geometry,
typename EqPPStrategy,
typename Tag = typename tag<Geometry>::type
>
struct multi_point_geometry_eb
{
template <typename MultiPoint>
static inline bool apply(MultiPoint const& ,
detail::relate::topology_check<Geometry, EqPPStrategy> const& )
{
return true;
}
};
template <typename Geometry, typename EqPPStrategy>
struct multi_point_geometry_eb<Geometry, EqPPStrategy, linestring_tag>
{
template <typename Points>
struct boundary_visitor
{
boundary_visitor(Points const& points)
: m_points(points)
, m_boundary_found(false)
{}
template <typename Point>
struct find_pred
{
find_pred(Point const& point)
: m_point(point)
{}
template <typename Pt>
bool operator()(Pt const& pt) const
{
return detail::equals::equals_point_point(pt, m_point, EqPPStrategy());
}
Point const& m_point;
};
template <typename Point>
bool apply(Point const& boundary_point)
{
if (std::find_if(m_points.begin(), m_points.end(), find_pred<Point>(boundary_point)) == m_points.end())
{
m_boundary_found = true;
return false;
}
return true;
}
bool result() const { return m_boundary_found; }
private:
Points const& m_points;
bool m_boundary_found;
};
template <typename MultiPoint>
static inline bool apply(MultiPoint const& multi_point,
detail::relate::topology_check<Geometry, EqPPStrategy> const& tc)
{
boundary_visitor<MultiPoint> visitor(multi_point);
tc.for_each_boundary_point(visitor);
return visitor.result();
}
};
template <typename Geometry, typename EqPPStrategy>
struct multi_point_geometry_eb<Geometry, EqPPStrategy, multi_linestring_tag>
{
// TODO: CS-specific less compare strategy derived from EqPPStrategy
typedef geometry::less<> less_type;
template <typename Points>
struct boundary_visitor
{
boundary_visitor(Points const& points)
: m_points(points)
, m_boundary_found(false)
{}
template <typename Point>
bool apply(Point const& boundary_point)
{
if (! std::binary_search(m_points.begin(), m_points.end(), boundary_point, less_type()))
{
m_boundary_found = true;
return false;
}
return true;
}
bool result() const { return m_boundary_found; }
private:
Points const& m_points;
bool m_boundary_found;
};
template <typename MultiPoint>
static inline bool apply(MultiPoint const& multi_point,
detail::relate::topology_check<Geometry, EqPPStrategy> 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));
std::sort(points.begin(), points.end(), less_type());
boundary_visitor<points_type> visitor(points);
tc.for_each_boundary_point(visitor);
return visitor.result();
}
};
// SingleGeometry - Linear or Areal
template <typename MultiPoint, typename SingleGeometry, bool Transpose = false>
struct multi_point_single_geometry
{
static const bool interruption_enabled = true;
template <typename Result, typename Strategy>
static inline void apply(MultiPoint const& multi_point,
SingleGeometry const& single_geometry,
Result & result,
Strategy const& strategy)
{
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::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 )
{
if (! (relate::may_update<interior, interior, '0', Transpose>(result)
|| relate::may_update<interior, boundary, '0', Transpose>(result)
|| relate::may_update<interior, exterior, '0', Transpose>(result) ) )
{
break;
}
// The default strategy is enough for Point/Box
if (detail::disjoint::disjoint_point_box(*it, box2, d_pb_strategy_type()))
{
relate::set<interior, exterior, '0', Transpose>(result);
}
else
{
int in_val = detail::within::point_in_geometry(*it, single_geometry, strategy);
if (in_val > 0) // within
{
relate::set<interior, interior, '0', Transpose>(result);
}
else if (in_val == 0)
{
relate::set<interior, boundary, '0', Transpose>(result);
}
else // in_val < 0 - not within
{
relate::set<interior, exterior, '0', Transpose>(result);
}
}
if ( BOOST_GEOMETRY_CONDITION(result.interrupt) )
{
return;
}
}
typedef detail::relate::topology_check
<
SingleGeometry, eq_pp_strategy_type
> 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);
if ( relate::may_update<exterior, interior, tc_t::interior, Transpose>(result)
&& tc.has_interior() )
{
// TODO: this is not true if a linestring is degenerated to a point
// then the interior has topological dimension = 0, not 1
relate::set<exterior, interior, tc_t::interior, Transpose>(result);
}
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))
{
relate::set<exterior, boundary, tc_t::boundary, Transpose>(result);
}
}
}
relate::set<exterior, exterior, result_dimension<MultiPoint>::value, Transpose>(result);
}
};
// MultiGeometry - Linear or Areal
// part of the algorithm calculating II and IB when no IE has to be calculated
// using partition()
template <typename MultiPoint, typename MultiGeometry, bool Transpose>
class multi_point_multi_geometry_ii_ib
{
struct expand_box_point
{
template <typename Box, typename Point>
static inline void apply(Box& total, Point const& point)
{
geometry::expand(total, point);
}
};
struct expand_box_box_pair
{
template <typename Box, typename BoxPair>
static inline void apply(Box& total, BoxPair const& box_pair)
{
geometry::expand(total, box_pair.first);
}
};
template <typename DisjointPointBoxStrategy>
struct overlaps_box_point
{
template <typename Box, typename Point>
static inline bool apply(Box const& box, Point const& point)
{
// The default strategy is enough for Point/Box
return ! detail::disjoint::disjoint_point_box(point, box,
DisjointPointBoxStrategy());
}
};
template <typename DisjointBoxBoxStrategy>
struct overlaps_box_box_pair
{
template <typename Box, typename BoxPair>
static inline bool apply(Box const& box, BoxPair const& box_pair)
{
// The default strategy is enough for Box/Box
return ! detail::disjoint::disjoint_box_box(box_pair.first, box,
DisjointBoxBoxStrategy());
}
};
template <typename Result, typename PtSegStrategy>
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;
public:
item_visitor_type(MultiGeometry const& multi_geometry,
topology_check_type const& tc,
Result & result,
PtSegStrategy const& strategy)
: m_multi_geometry(multi_geometry)
, m_tc(tc)
, m_result(result)
, m_strategy(strategy)
{}
template <typename Point, typename BoxPair>
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()))
{
typename boost::range_value<MultiGeometry>::type const&
single = range::at(m_multi_geometry, box_pair.second);
int in_val = detail::within::point_in_geometry(point, single, m_strategy);
if (in_val > 0) // within
{
relate::set<interior, interior, '0', Transpose>(m_result);
}
else if (in_val == 0)
{
if (m_tc.check_boundary_point(point))
relate::set<interior, boundary, '0', Transpose>(m_result);
else
relate::set<interior, interior, '0', Transpose>(m_result);
}
}
if ( BOOST_GEOMETRY_CONDITION(m_result.interrupt) )
{
return false;
}
if (! (relate::may_update<interior, interior, '0', Transpose>(m_result)
|| relate::may_update<interior, boundary, '0', Transpose>(m_result) ) )
{
return false;
}
return true;
}
private:
MultiGeometry const& m_multi_geometry;
topology_check_type const& m_tc;
Result & m_result;
PtSegStrategy const& m_strategy;
};
public:
typedef typename point_type<MultiPoint>::type point1_type;
typedef typename point_type<MultiGeometry>::type point2_type;
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;
template <typename Result, typename Strategy>
static inline void apply(MultiPoint const& multi_point,
MultiGeometry const& multi_geometry,
std::vector<box_pair_type> const& boxes,
detail::relate::topology_check
<
MultiGeometry,
typename Strategy::equals_point_point_strategy_type
> const& tc,
Result & result,
Strategy const& strategy)
{
item_visitor_type<Result, Strategy> visitor(multi_geometry, tc, result, strategy);
typedef overlaps_box_point
<
typename Strategy::disjoint_point_box_strategy_type
> overlaps_box_point_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(),
overlaps_box_point_type(),
expand_box_box_pair(),
overlaps_box_box_pair_type());
}
};
// MultiGeometry - Linear or Areal
// part of the algorithm calculating II, IB and IE
// using rtree
template <typename MultiPoint, typename MultiGeometry, bool Transpose>
struct multi_point_multi_geometry_ii_ib_ie
{
typedef typename point_type<MultiPoint>::type point1_type;
typedef typename point_type<MultiGeometry>::type point2_type;
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;
typedef std::vector<box_pair_type> boxes_type;
typedef typename boxes_type::const_iterator boxes_iterator;
template <typename Result, typename Strategy>
static inline void apply(MultiPoint const& multi_point,
MultiGeometry const& multi_geometry,
std::vector<box_pair_type> const& boxes,
detail::relate::topology_check
<
MultiGeometry,
typename Strategy::equals_point_point_strategy_type
> const& tc,
Result & result,
Strategy const& strategy)
{
index::rtree<box_pair_type, index::rstar<4> > rt(boxes.begin(), boxes.end());
typedef typename boost::range_const_iterator<MultiPoint>::type iterator;
for ( iterator it = boost::begin(multi_point) ; it != boost::end(multi_point) ; ++it )
{
if (! (relate::may_update<interior, interior, '0', Transpose>(result)
|| relate::may_update<interior, boundary, '0', Transpose>(result)
|| relate::may_update<interior, exterior, '0', Transpose>(result) ) )
{
return;
}
typename boost::range_value<MultiPoint>::type const& point = *it;
boxes_type boxes_found;
rt.query(index::intersects(point), std::back_inserter(boxes_found));
bool found_ii_or_ib = false;
for (boxes_iterator bi = boxes_found.begin() ; bi != boxes_found.end() ; ++bi)
{
typename boost::range_value<MultiGeometry>::type const&
single = range::at(multi_geometry, bi->second);
int in_val = detail::within::point_in_geometry(point, single, strategy);
if (in_val > 0) // within
{
relate::set<interior, interior, '0', Transpose>(result);
found_ii_or_ib = true;
}
else if (in_val == 0) // on boundary of single
{
if (tc.check_boundary_point(point))
relate::set<interior, boundary, '0', Transpose>(result);
else
relate::set<interior, interior, '0', Transpose>(result);
found_ii_or_ib = true;
}
}
// neither interior nor boundary found -> exterior
if (found_ii_or_ib == false)
{
relate::set<interior, exterior, '0', Transpose>(result);
}
if ( BOOST_GEOMETRY_CONDITION(result.interrupt) )
{
return;
}
}
}
};
// MultiGeometry - Linear or Areal
template <typename MultiPoint, typename MultiGeometry, bool Transpose = false>
struct multi_point_multi_geometry
{
static const bool interruption_enabled = true;
template <typename Result, typename Strategy>
static inline void apply(MultiPoint const& multi_point,
MultiGeometry const& multi_geometry,
Result & result,
Strategy const& strategy)
{
typedef typename point_type<MultiGeometry>::type point2_type;
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::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);
if ( relate::may_update<interior, interior, '0', Transpose>(result)
|| relate::may_update<interior, boundary, '0', Transpose>(result)
|| relate::may_update<interior, exterior, '0', Transpose>(result) )
{
// If there is no need to calculate IE, use partition
if (! relate::may_update<interior, exterior, '0', Transpose>(result) )
{
multi_point_multi_geometry_ii_ib<MultiPoint, MultiGeometry, Transpose>
::apply(multi_point, multi_geometry, boxes, tc, result, strategy);
}
else // otherwise use rtree
{
multi_point_multi_geometry_ii_ib_ie<MultiPoint, MultiGeometry, Transpose>
::apply(multi_point, multi_geometry, boxes, tc, result, strategy);
}
}
if ( BOOST_GEOMETRY_CONDITION(result.interrupt) )
{
return;
}
if ( relate::may_update<exterior, interior, tc_t::interior, Transpose>(result)
|| relate::may_update<exterior, boundary, tc_t::boundary, Transpose>(result) )
{
if ( relate::may_update<exterior, interior, tc_t::interior, Transpose>(result)
&& tc.has_interior() )
{
// TODO: this is not true if a linestring is degenerated to a point
// then the interior has topological dimension = 0, not 1
relate::set<exterior, interior, tc_t::interior, Transpose>(result);
}
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))
{
relate::set<exterior, boundary, tc_t::boundary, Transpose>(result);
}
}
}
relate::set<exterior, exterior, result_dimension<MultiPoint>::value, Transpose>(result);
}
};
template
<
typename MultiPoint, typename Geometry,
bool Transpose = false,
bool isMulti = boost::is_same
<
typename tag_cast
<
typename tag<Geometry>::type, multi_tag
>::type,
multi_tag
>::value
>
struct multi_point_geometry
: multi_point_single_geometry<MultiPoint, Geometry, Transpose>
{};
template <typename MultiPoint, typename Geometry, bool Transpose>
struct multi_point_geometry<MultiPoint, Geometry, Transpose, true>
: multi_point_multi_geometry<MultiPoint, Geometry, Transpose>
{};
// transposed result of multi_point_geometry
template <typename Geometry, typename MultiPoint>
struct geometry_multi_point
{
static const bool interruption_enabled = true;
template <typename Result, typename Strategy>
static inline void apply(Geometry const& geometry, MultiPoint const& multi_point,
Result & result, Strategy const& strategy)
{
multi_point_geometry<MultiPoint, Geometry, true>::apply(multi_point, geometry, result, strategy);
}
};
}} // namespace detail::relate
#endif // DOXYGEN_NO_DETAIL
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_MULTI_POINT_GEOMETRY_HPP

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.
// Modifications copyright (c) 2013-2017 Oracle and/or its affiliates.
// This file was modified by Oracle on 2013, 2014, 2015, 2017, 2018.
// Modifications copyright (c) 2013-2018 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -60,29 +60,31 @@ struct point_geometry
if ( BOOST_GEOMETRY_CONDITION(result.interrupt) )
return;
// the point is on the boundary
if ( pig == 0 )
typedef detail::relate::topology_check
<
Geometry,
typename Strategy::equals_point_point_strategy_type
> tc_t;
if ( relate::may_update<exterior, interior, tc_t::interior, Transpose>(result)
|| relate::may_update<exterior, boundary, tc_t::boundary, Transpose>(result) )
{
// NOTE: even for MLs, if there is at least one boundary point,
// somewhere there must be another one
// check if there are other boundaries outside
typedef detail::relate::topology_check<Geometry> tc_t;
//tc_t tc(geometry, point);
//if ( tc.has_interior )
// the point is on the boundary
if ( pig == 0 )
{
// NOTE: even for MLs, if there is at least one boundary point,
// somewhere there must be another one
relate::set<exterior, interior, tc_t::interior, Transpose>(result);
//if ( tc.has_boundary )
relate::set<exterior, boundary, tc_t::boundary, Transpose>(result);
}
else
{
// check if there is a boundary in Geometry
typedef detail::relate::topology_check<Geometry> tc_t;
tc_t tc(geometry);
if ( tc.has_interior )
relate::set<exterior, interior, tc_t::interior, Transpose>(result);
if ( tc.has_boundary )
relate::set<exterior, boundary, tc_t::boundary, Transpose>(result);
}
else
{
// check if there is a boundary in Geometry
tc_t tc(geometry);
if ( tc.has_interior() )
relate::set<exterior, interior, tc_t::interior, Transpose>(result);
if ( tc.has_boundary() )
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, 2017.
// Modifications copyright (c) 2013-2017, Oracle and/or its affiliates.
// This file was modified by Oracle on 2013, 2014, 2017, 2018.
// Modifications copyright (c) 2013-2018, Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -21,9 +21,10 @@
#include <boost/geometry/algorithms/detail/equals/point_point.hpp>
#include <boost/geometry/algorithms/detail/within/point_in_geometry.hpp>
#include <boost/geometry/algorithms/detail/relate/less.hpp>
#include <boost/geometry/algorithms/detail/relate/result.hpp>
#include <boost/geometry/policies/compare.hpp>
namespace boost { namespace geometry
{
@@ -38,9 +39,9 @@ struct point_point
template <typename Result, typename Strategy>
static inline void apply(Point1 const& point1, Point2 const& point2,
Result & result,
Strategy const& /*strategy*/)
Strategy const& strategy)
{
bool equal = detail::equals::equals_point_point(point1, point2);
bool equal = detail::equals::equals_point_point(point1, point2, strategy);
if ( equal )
{
relate::set<interior, interior, '0'>(result);
@@ -55,8 +56,10 @@ struct point_point
}
};
template <typename Point, typename MultiPoint>
std::pair<bool, bool> point_multipoint_check(Point const& point, MultiPoint const& multi_point)
template <typename Point, typename MultiPoint, typename EqPPStrategy>
std::pair<bool, bool> point_multipoint_check(Point const& point,
MultiPoint const& multi_point,
EqPPStrategy const& strategy)
{
bool found_inside = false;
bool found_outside = false;
@@ -69,7 +72,7 @@ std::pair<bool, bool> point_multipoint_check(Point const& point, MultiPoint cons
iterator last = boost::end(multi_point);
for ( ; it != last ; ++it )
{
bool ii = detail::equals::equals_point_point(point, *it);
bool ii = detail::equals::equals_point_point(point, *it, strategy);
if ( ii )
found_inside = true;
@@ -91,7 +94,7 @@ struct point_multipoint
template <typename Result, typename Strategy>
static inline void apply(Point const& point, MultiPoint const& multi_point,
Result & result,
Strategy const& /*strategy*/)
Strategy const& strategy)
{
if ( boost::empty(multi_point) )
{
@@ -100,7 +103,7 @@ struct point_multipoint
return;
}
std::pair<bool, bool> rel = point_multipoint_check(point, multi_point);
std::pair<bool, bool> rel = point_multipoint_check(point, multi_point, strategy);
if ( rel.first ) // some point of MP is equal to P
{
@@ -165,22 +168,41 @@ struct multipoint_multipoint
}
}
// TODO: ADD A CHECK TO THE RESULT INDICATING IF THE FIRST AND/OR SECOND GEOMETRY MUST BE ANALYSED
// The geometry containing smaller number of points will be analysed first
if ( boost::size(multi_point1) < boost::size(multi_point2) )
{
search_both<false>(multi_point1, multi_point2, result);
}
else
{
search_both<true>(multi_point2, multi_point1, result);
}
// TODO: if I/I is set for one MPt, this won't be changed when the other one in analysed
// so if e.g. only I/I must be analysed we musn't check the other MPt
relate::set<exterior, exterior, result_dimension<MultiPoint1>::value>(result);
}
// TODO: Also, the geometry with the smaller number of points may be analysed first
//if ( boost::size(multi_point1) < boost::size(multi_point2) )
template <bool Transpose, typename MPt1, typename MPt2, typename Result>
static inline void search_both(MPt1 const& first_sorted_mpt, MPt2 const& first_iterated_mpt,
Result & result)
{
if ( relate::may_update<interior, interior, '0'>(result)
|| relate::may_update<interior, exterior, '0'>(result)
|| relate::may_update<exterior, interior, '0'>(result) )
{
// NlogN + MlogN
bool is_disjoint = search<Transpose>(first_sorted_mpt, first_iterated_mpt, result);
// NlogN + MlogN
bool all_handled = search<false>(multi_point1, multi_point2, result);
if ( BOOST_GEOMETRY_CONDITION(all_handled || result.interrupt) )
return;
if ( BOOST_GEOMETRY_CONDITION(is_disjoint || result.interrupt) )
return;
}
// MlogM + NlogM
search<true>(multi_point2, multi_point1, result);
if ( relate::may_update<interior, interior, '0'>(result)
|| relate::may_update<interior, exterior, '0'>(result)
|| relate::may_update<exterior, interior, '0'>(result) )
{
// MlogM + NlogM
search<! Transpose>(first_iterated_mpt, first_sorted_mpt, result);
}
}
template <bool Transpose,
@@ -194,7 +216,9 @@ struct multipoint_multipoint
// sort points from the 1 MPt
typedef typename geometry::point_type<SortedMultiPoint>::type point_type;
std::vector<point_type> points(boost::begin(sorted_mpt), boost::end(sorted_mpt));
std::sort(points.begin(), points.end(), less());
geometry::less<> const less = geometry::less<>();
std::sort(points.begin(), points.end(), less);
bool found_inside = false;
bool found_outside = false;
@@ -205,7 +229,7 @@ struct multipoint_multipoint
it != boost::end(iterated_mpt) ; ++it )
{
bool ii =
std::binary_search(points.begin(), points.end(), *it, less());
std::binary_search(points.begin(), points.end(), *it, less);
if ( ii )
found_inside = true;
else
@@ -215,9 +239,6 @@ struct multipoint_multipoint
break;
}
// an optimization
bool all_handled = false;
if ( found_inside ) // some point of MP2 is equal to some of MP1
{
// TODO: if I/I is set for one MPt, this won't be changed when the other one in analysed
@@ -234,14 +255,10 @@ struct multipoint_multipoint
{
relate::set<interior, exterior, '0', Transpose>(result);
relate::set<exterior, interior, '0', Transpose>(result);
// if no point is intersecting the other MPt then we musn't analyse the reversed case
all_handled = true;
}
relate::set<exterior, exterior, result_dimension<point_type>::value, Transpose>(result);
return all_handled;
// if no point is intersecting the other MPt then we musn't analyse the reversed case
return ! found_inside;
}
};

View File

@@ -3,8 +3,8 @@
// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2017 Adam Wulkiewicz, Lodz, Poland.
// This file was modified by Oracle on 2013-2016.
// Modifications copyright (c) 2013-2016 Oracle and/or its affiliates.
// This file was modified by Oracle on 2013-2018.
// Modifications copyright (c) 2013-2018 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -16,6 +16,7 @@
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_RESULT_HPP
#include <cstddef>
#include <cstring>
#include <boost/mpl/assert.hpp>
#include <boost/mpl/at.hpp>
@@ -24,6 +25,7 @@
#include <boost/mpl/end.hpp>
#include <boost/mpl/is_sequence.hpp>
#include <boost/mpl/next.hpp>
#include <boost/mpl/size.hpp>
#include <boost/static_assert.hpp>
#include <boost/throw_exception.hpp>
#include <boost/tuple/tuple.hpp>

View File

@@ -1,22 +1,25 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2014, Oracle and/or its affiliates.
// Copyright (c) 2014-2018, Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_TOPOLOGY_CHECK_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_TOPOLOGY_CHECK_HPP
#include <boost/geometry/util/range.hpp>
#include <boost/geometry/algorithms/detail/equals/point_point.hpp>
#include <boost/geometry/algorithms/not_implemented.hpp>
#include <boost/geometry/policies/compare.hpp>
#include <boost/geometry/util/has_nan_coordinate.hpp>
#include <boost/geometry/util/range.hpp>
namespace boost { namespace geometry {
@@ -26,6 +29,7 @@ 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>
struct topology_check
: not_implemented<Tag>
@@ -45,68 +49,134 @@ struct topology_check
// topology_check(Point const&, IgnoreBoundaryPoint const&) {}
//};
template <typename Linestring>
struct topology_check<Linestring, linestring_tag>
template <typename Linestring, typename EqPPStrategy>
struct topology_check<Linestring, EqPPStrategy, linestring_tag>
{
static const char interior = '1';
static const char boundary = '0';
bool has_interior;
bool has_boundary;
topology_check(Linestring const& ls)
: m_ls(ls)
, m_is_initialized(false)
{}
bool has_interior() const
{
init(ls, 0); /*dummy param*/
init();
return m_has_interior;
}
template <typename IgnoreBoundaryPoint>
topology_check(Linestring const& ls, IgnoreBoundaryPoint const& ibp)
bool has_boundary() const
{
init(ls, ibp); /*dummy param, won't be used*/
init();
return m_has_boundary;
}
// Even if some point is on the boundary, if the Linestring has the boundary,
// there will be second boundary point different than IgnoreBoundaryPoint
template <typename IgnoreBoundaryPoint>
void init(Linestring const& ls, IgnoreBoundaryPoint const&)
/*template <typename Point>
bool check_boundary_point(Point const& point) const
{
std::size_t count = boost::size(ls);
has_interior = count > 0;
init();
return m_has_boundary
&& ( equals::equals_point_point(point, range::front(m_ls))
|| equals::equals_point_point(point, range::back(m_ls)) );
}*/
template <typename Visitor>
void for_each_boundary_point(Visitor & visitor) const
{
init();
if (m_has_boundary)
{
if (visitor.apply(range::front(m_ls)))
visitor.apply(range::back(m_ls));
}
}
private:
void init() const
{
if (m_is_initialized)
return;
std::size_t count = boost::size(m_ls);
m_has_interior = count > 0;
// NOTE: Linestring with all points equal is treated as 1d linear ring
has_boundary = count > 1
&& ! detail::equals::equals_point_point(range::front(ls), range::back(ls));
m_has_boundary = count > 1
&& ! detail::equals::equals_point_point(range::front(m_ls),
range::back(m_ls),
EqPPStrategy());
m_is_initialized = true;
}
Linestring const& m_ls;
mutable bool m_is_initialized;
mutable bool m_has_interior;
mutable bool m_has_boundary;
};
template <typename MultiLinestring>
struct topology_check<MultiLinestring, multi_linestring_tag>
template <typename MultiLinestring, typename EqPPStrategy>
struct topology_check<MultiLinestring, EqPPStrategy, multi_linestring_tag>
{
static const char interior = '1';
static const char boundary = '0';
bool has_interior;
bool has_boundary;
topology_check(MultiLinestring const& mls)
: m_mls(mls)
, m_is_initialized(false)
{}
bool has_interior() const
{
init(mls, not_ignoring_counter());
init();
return m_has_interior;
}
template <typename IgnoreBoundaryPoint>
topology_check(MultiLinestring const& mls, IgnoreBoundaryPoint const& ibp)
bool has_boundary() const
{
init(mls, ignoring_counter<IgnoreBoundaryPoint>(ibp));
init();
return m_has_boundary;
}
template <typename OddCounter>
void init(MultiLinestring const& mls, OddCounter const& odd_counter)
template <typename Point>
bool check_boundary_point(Point const& point) const
{
typedef typename geometry::point_type<MultiLinestring>::type point_type;
std::vector<point_type> endpoints;
endpoints.reserve(boost::size(mls) * 2);
init();
if (! m_has_boundary)
return false;
std::size_t count = count_equal(m_endpoints.begin(), m_endpoints.end(), point);
return count % 2 != 0; // odd count -> boundary
}
template <typename Visitor>
void for_each_boundary_point(Visitor & visitor) const
{
init();
if (m_has_boundary)
{
for_each_boundary_point(m_endpoints.begin(), m_endpoints.end(), visitor);
}
}
private:
// TODO: CS-specific less derived from EqPPStrategy
typedef geometry::less<> less_type;
void init() const
{
if (m_is_initialized)
return;
m_endpoints.reserve(boost::size(m_mls) * 2);
m_has_interior = false;
typedef typename boost::range_iterator<MultiLinestring const>::type ls_iterator;
for ( ls_iterator it = boost::begin(mls) ; it != boost::end(mls) ; ++it )
for ( ls_iterator it = boost::begin(m_mls) ; it != boost::end(m_mls) ; ++it )
{
typename boost::range_reference<MultiLinestring const>::type
ls = *it;
@@ -115,7 +185,7 @@ struct topology_check<MultiLinestring, multi_linestring_tag>
if (count > 0)
{
has_interior = true;
m_has_interior = true;
}
if (count > 1)
@@ -129,7 +199,7 @@ struct topology_check<MultiLinestring, multi_linestring_tag>
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))
if (! equals::equals_point_point(front_pt, back_pt, EqPPStrategy()))
{
// do not add points containing NaN coordinates
// because they cannot be reasonably compared, e.g. with MSVC
@@ -138,62 +208,59 @@ struct topology_check<MultiLinestring, multi_linestring_tag>
// is not used anywhere in the code, still it's safer this way
if (! geometry::has_nan_coordinate(front_pt))
{
endpoints.push_back(front_pt);
m_endpoints.push_back(front_pt);
}
if (! geometry::has_nan_coordinate(back_pt))
{
endpoints.push_back(back_pt);
m_endpoints.push_back(back_pt);
}
}
}
}
has_boundary = false;
m_has_boundary = false;
if ( !endpoints.empty() )
if (! m_endpoints.empty() )
{
std::sort(endpoints.begin(), endpoints.end(), geometry::less<point_type>());
has_boundary = odd_counter(endpoints.begin(), endpoints.end());
std::sort(m_endpoints.begin(), m_endpoints.end(), less_type());
m_has_boundary = find_odd_count(m_endpoints.begin(), m_endpoints.end());
}
m_is_initialized = true;
}
struct not_ignoring_counter
template <typename It, typename Point>
static inline std::size_t count_equal(It first, It last, Point const& point)
{
template <typename It>
bool operator()(It first, It last) const
{
return find_odd_count(first, last);
}
};
template <typename Point>
struct ignoring_counter
{
ignoring_counter(Point const& pt) : m_pt(pt) {}
template <typename It>
bool operator()(It first, It last) const
{
typedef typename std::iterator_traits<It>::value_type point_type;
std::pair<It, It> ignore_range
= std::equal_range(first, last, m_pt,
geometry::less<point_type>());
if ( find_odd_count(first, ignore_range.first) )
return true;
return find_odd_count(ignore_range.second, last);
}
Point const& m_pt;
};
std::pair<It, It> rng = std::equal_range(first, last, point, less_type());
return (std::size_t)std::distance(rng.first, rng.second);
}
template <typename It>
static inline bool find_odd_count(It first, It last)
{
if ( first == last )
interrupting_visitor visitor;
for_each_boundary_point(first, last, visitor);
return visitor.found;
}
struct interrupting_visitor
{
bool found;
interrupting_visitor() : found(false) {}
template <typename Point>
bool apply(Point const&)
{
found = true;
return false;
}
};
template <typename It, typename Visitor>
static void for_each_boundary_point(It first, It last, Visitor& visitor)
{
if ( first == last )
return;
std::size_t count = 1;
It prev = first;
@@ -201,10 +268,16 @@ struct topology_check<MultiLinestring, multi_linestring_tag>
for ( ; first != last ; ++first, ++prev )
{
// the end of the equal points subrange
if ( ! equals::equals_point_point(*first, *prev) )
if ( ! equals::equals_point_point(*first, *prev, EqPPStrategy()) )
{
// odd count -> boundary
if ( count % 2 != 0 )
return true;
{
if (! visitor.apply(*prev))
{
return;
}
}
count = 1;
}
@@ -214,47 +287,55 @@ struct topology_check<MultiLinestring, multi_linestring_tag>
}
}
return count % 2 != 0;
// odd count -> boundary
if ( count % 2 != 0 )
{
visitor.apply(*prev);
}
}
private:
MultiLinestring const& m_mls;
mutable bool m_is_initialized;
mutable bool m_has_interior;
mutable bool m_has_boundary;
typedef typename geometry::point_type<MultiLinestring>::type point_type;
mutable std::vector<point_type> m_endpoints;
};
template <typename Ring>
struct topology_check<Ring, ring_tag>
struct topology_check_areal
{
static const char interior = '2';
static const char boundary = '1';
static const bool has_interior = true;
static const bool has_boundary = true;
static bool has_interior() { return true; }
static bool has_boundary() { return true; }
};
template <typename Ring, typename EqPPStrategy>
struct topology_check<Ring, EqPPStrategy, ring_tag>
: topology_check_areal
{
topology_check(Ring const&) {}
template <typename P>
topology_check(Ring const&, P const&) {}
};
template <typename Polygon>
struct topology_check<Polygon, polygon_tag>
template <typename Polygon, typename EqPPStrategy>
struct topology_check<Polygon, EqPPStrategy, polygon_tag>
: topology_check_areal
{
static const char interior = '2';
static const char boundary = '1';
static const bool has_interior = true;
static const bool has_boundary = true;
topology_check(Polygon const&) {}
template <typename P>
topology_check(Polygon const&, P const&) {}
};
template <typename MultiPolygon>
struct topology_check<MultiPolygon, multi_polygon_tag>
template <typename MultiPolygon, typename EqPPStrategy>
struct topology_check<MultiPolygon, EqPPStrategy, multi_polygon_tag>
: topology_check_areal
{
static const char interior = '2';
static const char boundary = '1';
static const bool has_interior = true;
static const bool has_boundary = true;
topology_check(MultiPolygon const&) {}
template <typename P>
topology_check(MultiPolygon const&, P const&) {}
template <typename Point>
static bool check_boundary_point(Point const& ) { return true; }
};
}} // namespace detail::relate

View File

@@ -48,7 +48,11 @@ template
<
Geometry1, Geometry2, assign_policy<>
>,
typename RobustPolicy = detail::no_rescale_policy
typename RobustPolicy = typename geometry::rescale_overlay_policy_type
<
Geometry1,
Geometry2
>::type
>
struct get_turns
{