summaryrefslogtreecommitdiff
path: root/boost/geometry/algorithms/detail/overlay/get_turn_info_for_endpoint.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'boost/geometry/algorithms/detail/overlay/get_turn_info_for_endpoint.hpp')
-rw-r--r--boost/geometry/algorithms/detail/overlay/get_turn_info_for_endpoint.hpp199
1 files changed, 90 insertions, 109 deletions
diff --git a/boost/geometry/algorithms/detail/overlay/get_turn_info_for_endpoint.hpp b/boost/geometry/algorithms/detail/overlay/get_turn_info_for_endpoint.hpp
index f9b4dee2cd..521744df88 100644
--- a/boost/geometry/algorithms/detail/overlay/get_turn_info_for_endpoint.hpp
+++ b/boost/geometry/algorithms/detail/overlay/get_turn_info_for_endpoint.hpp
@@ -2,8 +2,8 @@
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
-// This file was modified by Oracle on 2013, 2014, 2017.
-// 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
@@ -15,8 +15,10 @@
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_GET_TURN_INFO_FOR_ENDPOINT_HPP
#include <boost/core/ignore_unused.hpp>
-#include <boost/geometry/core/assert.hpp>
+
+#include <boost/geometry/algorithms/detail/equals/point_point.hpp>
#include <boost/geometry/algorithms/detail/overlay/get_turn_info.hpp>
+#include <boost/geometry/core/assert.hpp>
#include <boost/geometry/policies/robustness/no_rescale_policy.hpp>
namespace boost { namespace geometry {
@@ -109,11 +111,12 @@ namespace detail { namespace overlay {
class linear_intersections
{
public:
- template <typename Point1, typename Point2, typename IntersectionResult>
+ template <typename Point1, typename Point2, typename IntersectionResult, typename EqPPStrategy>
linear_intersections(Point1 const& pi,
Point2 const& qi,
IntersectionResult const& result,
- bool is_p_last, bool is_q_last)
+ bool is_p_last, bool is_q_last,
+ EqPPStrategy const& strategy)
{
int arrival_a = result.template get<1>().arrival[0];
int arrival_b = result.template get<1>().arrival[1];
@@ -133,10 +136,10 @@ public:
ips[0].is_pi
= equals::equals_point_point(
- pi, result.template get<0>().intersections[0]);
+ pi, result.template get<0>().intersections[0], strategy);
ips[0].is_qi
= equals::equals_point_point(
- qi, result.template get<0>().intersections[0]);
+ qi, result.template get<0>().intersections[0], strategy);
ips[1].is_pj = arrival_a != -1;
ips[1].is_qj = arrival_b != -1;
}
@@ -222,39 +225,53 @@ private:
ip_info ips[2];
};
-template <typename AssignPolicy, bool EnableFirst, bool EnableLast>
+template <bool EnableFirst, bool EnableLast>
struct get_turn_info_for_endpoint
{
+ typedef std::pair<operation_type, operation_type> operations_pair;
+
BOOST_STATIC_ASSERT(EnableFirst || EnableLast);
- template<typename Point1,
- typename Point2,
+ template<typename UniqueSubRange1,
+ typename UniqueSubRange2,
typename TurnInfo,
typename IntersectionInfo,
- typename OutputIterator
+ typename OutputIterator,
+ typename EqPPStrategy
>
- static inline bool apply(Point1 const& pi, Point1 const& pj, Point1 const& pk,
- Point2 const& qi, Point2 const& qj, Point2 const& qk,
- bool is_p_first, bool is_p_last,
- bool is_q_first, bool is_q_last,
+ static inline bool apply(UniqueSubRange1 const& range_p,
+ UniqueSubRange2 const& range_q,
TurnInfo const& tp_model,
IntersectionInfo const& inters,
method_type /*method*/,
- OutputIterator out)
+ OutputIterator out,
+ EqPPStrategy const& strategy)
{
std::size_t ip_count = inters.i_info().count;
// no intersection points
- if ( ip_count == 0 )
+ if (ip_count == 0)
+ {
return false;
+ }
- if ( !is_p_first && !is_p_last && !is_q_first && !is_q_last )
+ if (! range_p.is_first_segment()
+ && ! range_q.is_first_segment()
+ && ! range_p.is_last_segment()
+ && ! range_q.is_last_segment())
+ {
+ // Not an end-point from segment p or q
return false;
+ }
- linear_intersections intersections(pi, qi, inters.result(), is_p_last, is_q_last);
+ linear_intersections intersections(range_p.at(0),
+ range_q.at(0),
+ inters.result(),
+ range_p.is_last_segment(),
+ range_q.is_last_segment(),
+ strategy);
bool append0_last
- = analyse_segment_and_assign_ip(pi, pj, pk, qi, qj, qk,
- is_p_first, is_p_last, is_q_first, is_q_last,
+ = analyse_segment_and_assign_ip(range_p, range_q,
intersections.template get<0>(),
tp_model, inters, 0, out);
@@ -268,8 +285,7 @@ struct get_turn_info_for_endpoint
return result_ignore_ip0;
bool append1_last
- = analyse_segment_and_assign_ip(pi, pj, pk, qi, qj, qk,
- is_p_first, is_p_last, is_q_first, is_q_last,
+ = analyse_segment_and_assign_ip(range_p, range_q,
intersections.template get<1>(),
tp_model, inters, 1, out);
@@ -279,37 +295,25 @@ struct get_turn_info_for_endpoint
return result_ignore_ip0 || result_ignore_ip1;
}
- template <typename Point1,
- typename Point2,
+ template <typename UniqueSubRange1,
+ typename UniqueSubRange2,
typename TurnInfo,
typename IntersectionInfo,
typename OutputIterator>
static inline
- bool analyse_segment_and_assign_ip(Point1 const& pi, Point1 const& pj, Point1 const& pk,
- Point2 const& qi, Point2 const& qj, Point2 const& qk,
- bool is_p_first, bool is_p_last,
- bool is_q_first, bool is_q_last,
+ bool analyse_segment_and_assign_ip(UniqueSubRange1 const& range_p,
+ UniqueSubRange2 const& range_q,
linear_intersections::ip_info const& ip_info,
TurnInfo const& tp_model,
IntersectionInfo const& inters,
unsigned int ip_index,
OutputIterator out)
{
-#ifdef BOOST_GEOMETRY_DEBUG_GET_TURNS_LINEAR_LINEAR
- // may this give false positives for INTs?
- typename IntersectionResult::point_type const&
- inters_pt = result.template get<0>().intersections[ip_index];
- BOOST_GEOMETRY_ASSERT(ip_info.is_pi == equals::equals_point_point(pi, inters_pt));
- BOOST_GEOMETRY_ASSERT(ip_info.is_qi == equals::equals_point_point(qi, inters_pt));
- BOOST_GEOMETRY_ASSERT(ip_info.is_pj == equals::equals_point_point(pj, inters_pt));
- BOOST_GEOMETRY_ASSERT(ip_info.is_qj == equals::equals_point_point(qj, inters_pt));
-#endif
-
// TODO - calculate first/last only if needed
- bool is_p_first_ip = is_p_first && ip_info.is_pi;
- bool is_p_last_ip = is_p_last && ip_info.is_pj;
- bool is_q_first_ip = is_q_first && ip_info.is_qi;
- bool is_q_last_ip = is_q_last && ip_info.is_qj;
+ bool is_p_first_ip = range_p.is_first_segment() && ip_info.is_pi;
+ bool is_p_last_ip = range_p.is_last_segment() && ip_info.is_pj;
+ bool is_q_first_ip = range_q.is_first_segment() && ip_info.is_qi;
+ bool is_q_last_ip = range_q.is_last_segment() && ip_info.is_qj;
bool append_first = EnableFirst && (is_p_first_ip || is_q_first_ip);
bool append_last = EnableLast && (is_p_last_ip || is_q_last_ip);
@@ -318,9 +322,7 @@ struct get_turn_info_for_endpoint
if ( append_first || append_last )
{
- bool handled = handle_internal<0>(pi, pj, pk, qi, qj, qk,
- inters.rpi(), inters.rpj(), inters.rpk(),
- inters.rqi(), inters.rqj(), inters.rqk(),
+ bool handled = handle_internal<0>(range_p, range_q,
is_p_first_ip, is_p_last_ip,
is_q_first_ip, is_q_last_ip,
ip_info.is_qi, ip_info.is_qj,
@@ -328,9 +330,8 @@ struct get_turn_info_for_endpoint
p_operation, q_operation);
if ( !handled )
{
- handle_internal<1>(qi, qj, qk, pi, pj, pk,
- inters.rqi(), inters.rqj(), inters.rqk(),
- inters.rpi(), inters.rpj(), inters.rpk(),
+ // Reverse p/q
+ handle_internal<1>(range_q, range_p,
is_q_first_ip, is_q_last_ip,
is_p_first_ip, is_p_last_ip,
ip_info.is_pi, ip_info.is_pj,
@@ -348,31 +349,29 @@ struct get_turn_info_for_endpoint
// handle spikes
// P is spike and should be handled
- if ( !is_p_last
- && ip_info.is_pj // this check is redundant (also in is_spike_p) but faster
+ if (ip_info.is_pj // this check is redundant (also in is_spike_p) but faster
&& inters.i_info().count == 2
&& inters.is_spike_p() )
{
- assign(pi, qi, inters.result(), ip_index, method, operation_blocked, q_operation,
+ assign(inters.result(), ip_index, method, operation_blocked, q_operation,
p_pos, q_pos, is_p_first_ip, is_q_first_ip, true, false, tp_model, out);
- assign(pi, qi, inters.result(), ip_index, method, operation_intersection, q_operation,
+ assign(inters.result(), ip_index, method, operation_intersection, q_operation,
p_pos, q_pos, is_p_first_ip, is_q_first_ip, true, false, tp_model, out);
}
// Q is spike and should be handled
- else if ( !is_q_last
- && ip_info.is_qj // this check is redundant (also in is_spike_q) but faster
+ else if (ip_info.is_qj // this check is redundant (also in is_spike_q) but faster
&& inters.i_info().count == 2
&& inters.is_spike_q() )
{
- assign(pi, qi, inters.result(), ip_index, method, p_operation, operation_blocked,
+ assign(inters.result(), ip_index, method, p_operation, operation_blocked,
p_pos, q_pos, is_p_first_ip, is_q_first_ip, false, true, tp_model, out);
- assign(pi, qi, inters.result(), ip_index, method, p_operation, operation_intersection,
+ assign(inters.result(), ip_index, method, p_operation, operation_intersection,
p_pos, q_pos, is_p_first_ip, is_q_first_ip, false, true, tp_model, out);
}
// no spikes
else
{
- assign(pi, qi, inters.result(), ip_index, method, p_operation, q_operation,
+ assign(inters.result(), ip_index, method, p_operation, q_operation,
p_pos, q_pos, is_p_first_ip, is_q_first_ip, false, false, tp_model, out);
}
}
@@ -385,25 +384,22 @@ struct get_turn_info_for_endpoint
// however now it's lazily calculated and then it would be always calculated
template<std::size_t G1Index,
- typename Point1,
- typename Point2,
- typename RobustPoint1,
- typename RobustPoint2,
+ typename UniqueRange1,
+ typename UniqueRange2,
typename TurnInfo,
typename IntersectionInfo
>
- static inline bool handle_internal(Point1 const& /*i1*/, Point1 const& /*j1*/, Point1 const& /*k1*/,
- Point2 const& i2, Point2 const& j2, Point2 const& /*k2*/,
- RobustPoint1 const& ri1, RobustPoint1 const& rj1, RobustPoint1 const& /*rk1*/,
- RobustPoint2 const& ri2, RobustPoint2 const& rj2, RobustPoint2 const& rk2,
+ static inline bool handle_internal(UniqueRange1 const& range1,
+ UniqueRange2 const& range2,
bool first1, bool last1, bool first2, bool last2,
bool ip_i2, bool ip_j2, TurnInfo const& tp_model,
IntersectionInfo const& inters, unsigned int ip_index,
operation_type & op1, operation_type & op2)
{
- typedef typename cs_tag<typename TurnInfo::point_type>::type cs_tag;
+ boost::ignore_unused(ip_index, tp_model);
- boost::ignore_unused(i2, j2, ip_index, tp_model);
+ typename IntersectionInfo::side_strategy_type const& sides
+ = inters.get_side_strategy();
if ( !first2 && !last2 )
{
@@ -425,14 +421,11 @@ struct get_turn_info_for_endpoint
}
else if ( ip_j2 )
{
- side_calculator<cs_tag,
- RobustPoint1, RobustPoint2,
- typename IntersectionInfo::side_strategy_type,
- RobustPoint2>
- side_calc(ri2, ri1, rj1, ri2, rj2, rk2, inters.get_side_strategy());
+ int const side_pj_q2 = sides.apply(range2.at(1), range2.at(2), range1.at(1));
+ int const side_pj_q1 = sides.apply(range2.at(0), range2.at(1), range1.at(1));
+ int const side_qk_q1 = sides.apply(range2.at(0), range2.at(1), range2.at(2));
- std::pair<operation_type, operation_type>
- operations = operations_of_equal(side_calc);
+ operations_pair operations = operations_of_equal(side_pj_q2, side_pj_q1, side_qk_q1);
// TODO: must the above be calculated?
// wouldn't it be enough to check if segments are collinear?
@@ -479,13 +472,11 @@ struct get_turn_info_for_endpoint
}
else if ( ip_j2 )
{
- side_calculator<cs_tag, RobustPoint1, RobustPoint2,
- typename IntersectionInfo::side_strategy_type,
- RobustPoint2>
- side_calc(ri2, rj1, ri1, ri2, rj2, rk2, inters.get_side_strategy());
-
- std::pair<operation_type, operation_type>
- operations = operations_of_equal(side_calc);
+ int const side_pi_q2 = sides.apply(range2.at(1), range2.at(2), range1.at(0));
+ int const side_pi_q1 = sides.apply(range2.at(0), range2.at(1), range1.at(0));
+ int const side_qk_q1 = sides.apply(range2.at(0), range2.at(1), range2.at(2));
+
+ operations_pair operations = operations_of_equal(side_pi_q2, side_pi_q1, side_qk_q1);
// TODO: must the above be calculated?
// wouldn't it be enough to check if segments are collinear?
@@ -534,13 +525,10 @@ struct get_turn_info_for_endpoint
( is_ip_last_j ? position_back : position_middle );
}
- template <typename Point1,
- typename Point2,
- typename IntersectionResult,
+ template <typename IntersectionResult,
typename TurnInfo,
typename OutputIterator>
- static inline void assign(Point1 const& pi, Point2 const& qi,
- IntersectionResult const& result,
+ static inline void assign(IntersectionResult const& result,
unsigned int ip_index,
method_type method,
operation_type op0, operation_type op1,
@@ -591,33 +579,27 @@ struct get_turn_info_for_endpoint
}
}
- // TODO: this should get an intersection_info, which is unavailable here
- // Because the assign_null policy accepts any structure, we pass the result instead for now
- AssignPolicy::apply(tp, pi, qi, result);
*out++ = tp;
}
- template <typename SidePolicy>
- static inline std::pair<operation_type, operation_type> operations_of_equal(SidePolicy const& side)
+ static inline operations_pair operations_of_equal(int side_px_q2,
+ int side_px_q1,
+ int side_qk_q1)
{
- int const side_pk_q2 = side.pk_wrt_q2();
- int const side_pk_p = side.pk_wrt_p1();
- int const side_qk_p = side.qk_wrt_p1();
-
- // If pk is collinear with qj-qk, they continue collinearly.
- // This can be on either side of p1 (== q1), or collinear
+ // If px (pi or pj) is collinear with qj-qk (q2), they continue collinearly.
+ // This can be on either side of q1, or collinear
// The second condition checks if they do not continue
// oppositely
- if ( side_pk_q2 == 0 && side_pk_p == side_qk_p )
+ if (side_px_q2 == 0 && side_px_q1 == side_qk_q1)
{
return std::make_pair(operation_continue, operation_continue);
}
// If they turn to same side (not opposite sides)
- if ( ! base_turn_handler::opposite(side_pk_p, side_qk_p) )
+ if ( ! base_turn_handler::opposite(side_px_q1, side_qk_q1) )
{
- // If pk is left of q2 or collinear: p: union, q: intersection
- if ( side_pk_q2 != -1 )
+ // If px is left of q2 or collinear: p: union, q: intersection
+ if (side_px_q2 != -1 )
{
return std::make_pair(operation_union, operation_intersection);
}
@@ -630,7 +612,7 @@ struct get_turn_info_for_endpoint
{
// They turn opposite sides. If p turns left (or collinear),
// p: union, q: intersection
- if ( side_pk_p != -1 )
+ if (side_px_q1 != -1 )
{
return std::make_pair(operation_union, operation_intersection);
}
@@ -641,16 +623,15 @@ struct get_turn_info_for_endpoint
}
}
- static inline bool operations_both(
- std::pair<operation_type, operation_type> const& operations,
- operation_type const op)
+ static inline bool operations_both(operations_pair const& operations,
+ operation_type const op)
{
return operations.first == op && operations.second == op;
}
- static inline bool operations_combination(
- std::pair<operation_type, operation_type> const& operations,
- operation_type const op1, operation_type const op2)
+ static inline bool operations_combination(operations_pair const& operations,
+ operation_type const op1,
+ operation_type const op2)
{
return ( operations.first == op1 && operations.second == op2 )
|| ( operations.first == op2 && operations.second == op1 );