update boost on linux
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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
|
||||
@@ -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;
|
||||
|
||||
@@ -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 )
|
||||
|
||||
@@ -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
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user