From e6ef0b0328734bb95b2e3baca346b004a12fa83f Mon Sep 17 00:00:00 2001 From: Adam Wulkiewicz Date: Sun, 4 May 2014 01:26:12 +0200 Subject: [PATCH] [get_turns] Use RobustPolicy in a unified way in all three get_turn_info* policies (A/A, L/A, and L/L). Newly introduced intersection_info containing IntersectionResult, SideCalculator and Point refs is used also in get_turn_info for A/A. Robust points are stored only if RobustPolicy is not no_rescale_policy. This commit also fixes an error in get_turn_info - swapped_side_calc created for method_touch_interior ('m') should use robust points just like the original one. --- .../detail/overlay/get_turn_info.hpp | 125 ++----- .../overlay/get_turn_info_for_endpoint.hpp | 180 +--------- .../detail/overlay/get_turn_info_helpers.hpp | 336 ++++++++++++++++++ .../detail/overlay/get_turn_info_la.hpp | 76 ++-- .../detail/overlay/get_turn_info_ll.hpp | 14 +- 5 files changed, 447 insertions(+), 284 deletions(-) create mode 100644 include/boost/geometry/algorithms/detail/overlay/get_turn_info_helpers.hpp diff --git a/include/boost/geometry/algorithms/detail/overlay/get_turn_info.hpp b/include/boost/geometry/algorithms/detail/overlay/get_turn_info.hpp index 376f5a71f..20ccd9208 100644 --- a/include/boost/geometry/algorithms/detail/overlay/get_turn_info.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/get_turn_info.hpp @@ -21,7 +21,7 @@ #include #include - +#include // Silence warning C4127: conditional expression is constant #if defined(_MSC_VER) @@ -60,36 +60,6 @@ public: namespace detail { namespace overlay { -template -struct side_calculator -{ - typedef boost::geometry::strategy::side::side_by_triangle<> side; // todo: get from coordinate system - - inline side_calculator(Pi const& pi, Pj const& pj, Pk const& pk, - Qi const& qi, Qj const& qj, Qk const& qk) - : m_pi(pi), m_pj(pj), m_pk(pk) - , m_qi(qi), m_qj(qj), m_qk(qk) - {} - - inline int pk_wrt_p1() const { return side::apply(m_pi, m_pj, m_pk); } - inline int pk_wrt_q1() const { return side::apply(m_qi, m_qj, m_pk); } - inline int qk_wrt_p1() const { return side::apply(m_pi, m_pj, m_qk); } - inline int qk_wrt_q1() const { return side::apply(m_qi, m_qj, m_qk); } - - inline int pk_wrt_q2() const { return side::apply(m_qj, m_qk, m_pk); } - inline int qk_wrt_p2() const { return side::apply(m_pj, m_pk, m_qk); } - - Pi const& m_pi; - Pj const& m_pj; - Pk const& m_pk; - Qi const& m_qi; - Qj const& m_qj; - Qk const& m_qk; -}; - struct base_turn_handler { // Returns true if both sides are opposite @@ -947,41 +917,12 @@ struct get_turn_info RobustPolicy const& robust_policy, OutputIterator out) { - typedef typename geometry::robust_point_type - < - Point1, RobustPolicy - >::type robust_point_type; + typedef intersection_info + inters_info; - robust_point_type pi_rob, pj_rob, pk_rob, qi_rob, qj_rob, qk_rob; - geometry::recalculate(pi_rob, pi, robust_policy); - geometry::recalculate(pj_rob, pj, robust_policy); - geometry::recalculate(pk_rob, pk, robust_policy); - geometry::recalculate(qi_rob, qi, robust_policy); - geometry::recalculate(qj_rob, qj, robust_policy); - geometry::recalculate(qk_rob, qk, robust_policy); + inters_info inters(pi, pj, pk, qi, qj, qk, robust_policy); - typedef model::referring_segment segment_type1; - typedef model::referring_segment segment_type2; - segment_type1 p1(pi, pj); - segment_type2 q1(qi, qj); - - side_calculator side_calc(pi_rob, pj_rob, pk_rob, qi_rob, qj_rob, qk_rob); - - typedef strategy_intersection - < - typename cs_tag::type, - Point1, - Point2, - typename TurnInfo::point_type, - RobustPolicy - > si; - - typedef typename si::segment_intersection_strategy_type strategy; - - typename strategy::return_type result = strategy::apply(p1, q1, - robust_policy, pi_rob, pj_rob, qi_rob, qj_rob); - - char const method = result.template get<1>().how; + char const method = inters.d_info().how; // Copy, to copy possibly extended fields TurnInfo tp = tp_model; @@ -993,11 +934,10 @@ struct get_turn_info case 'f' : // collinear, "from" case 's' : // starts from the middle if (AssignPolicy::include_no_turn - && result.template get<0>().count > 0) + && inters.i_info().count > 0) { - only_convert::apply(tp, - result.template get<0>()); - AssignPolicy::apply(tp, pi, qi, result.template get<0>(), result.template get<1>()); + only_convert::apply(tp, inters.i_info()); + AssignPolicy::apply(tp, pi, qi, inters.i_info(), inters.d_info()); *out++ = tp; } break; @@ -1013,29 +953,34 @@ struct get_turn_info > policy; // If Q (1) arrives (1) - if (result.template get<1>().arrival[1] == 1) + if ( inters.d_info().arrival[1] == 1 ) { policy::template apply<0>(pi, pj, pk, qi, qj, qk, - tp, result.template get<0>(), result.template get<1>(), - side_calc); + tp, inters.i_info(), inters.d_info(), + inters.sides()); } else { // Swap p/q - side_calculator swapped_side_calc(qi, qj, qk, pi, pj, pk); + side_calculator + < + typename inters_info::robust_point2_type, + typename inters_info::robust_point1_type + > swapped_side_calc(inters.rqi(), inters.rqj(), inters.rqk(), + inters.rpi(), inters.rpj(), inters.rpk()); policy::template apply<1>(qi, qj, qk, pi, pj, pk, - tp, result.template get<0>(), result.template get<1>(), + tp, inters.i_info(), inters.d_info(), swapped_side_calc); } - AssignPolicy::apply(tp, pi, qi, result.template get<0>(), result.template get<1>()); + AssignPolicy::apply(tp, pi, qi, inters.i_info(), inters.d_info()); *out++ = tp; } break; case 'i' : { crosses::apply(pi, pj, pk, qi, qj, qk, - tp, result.template get<0>(), result.template get<1>()); - AssignPolicy::apply(tp, pi, qi, result.template get<0>(), result.template get<1>()); + tp, inters.i_info(), inters.d_info()); + AssignPolicy::apply(tp, pi, qi, inters.i_info(), inters.d_info()); *out++ = tp; } break; @@ -1043,20 +988,20 @@ struct get_turn_info { // Both touch (both arrive there) touch::apply(pi, pj, pk, qi, qj, qk, - tp, result.template get<0>(), result.template get<1>(), side_calc); - AssignPolicy::apply(tp, pi, qi, result.template get<0>(), result.template get<1>()); + tp, inters.i_info(), inters.d_info(), inters.sides()); + AssignPolicy::apply(tp, pi, qi, inters.i_info(), inters.d_info()); *out++ = tp; } break; case 'e': { - if (! result.template get<1>().opposite) + if ( ! inters.d_info().opposite ) { // Both equal // or collinear-and-ending at intersection point equal::apply(pi, pj, pk, qi, qj, qk, - tp, result.template get<0>(), result.template get<1>(), side_calc); - AssignPolicy::apply(tp, pi, qi, result.template get<0>(), result.template get<1>()); + tp, inters.i_info(), inters.d_info(), inters.sides()); + AssignPolicy::apply(tp, pi, qi, inters.i_info(), inters.d_info()); *out++ = tp; } else @@ -1066,21 +1011,21 @@ struct get_turn_info TurnInfo, AssignPolicy >::apply(pi, qi, - tp, out, result.template get<0>(), result.template get<1>()); + tp, out, inters.i_info(), inters.d_info()); } } break; case 'c' : { // Collinear - if (! result.template get<1>().opposite) + if ( ! inters.d_info().opposite ) { - if (result.template get<1>().arrival[0] == 0) + if ( inters.d_info().arrival[0] == 0 ) { // Collinear, but similar thus handled as equal equal::apply(pi, pj, pk, qi, qj, qk, - tp, result.template get<0>(), result.template get<1>(), side_calc); + tp, inters.i_info(), inters.d_info(), inters.sides()); // override assigned method tp.method = method_collinear; @@ -1088,10 +1033,10 @@ struct get_turn_info else { collinear::apply(pi, pj, pk, qi, qj, qk, - tp, result.template get<0>(), result.template get<1>(), side_calc); + tp, inters.i_info(), inters.d_info(), inters.sides()); } - AssignPolicy::apply(tp, pi, qi, result.template get<0>(), result.template get<1>()); + AssignPolicy::apply(tp, pi, qi, inters.i_info(), inters.d_info()); *out++ = tp; } else @@ -1101,7 +1046,7 @@ struct get_turn_info TurnInfo, AssignPolicy >::apply(pi, pj, pk, qi, qj, qk, - tp, out, result.template get<0>(), result.template get<1>(), side_calc); + tp, out, inters.i_info(), inters.d_info(), inters.sides()); } } break; @@ -1110,8 +1055,8 @@ struct get_turn_info // degenerate points if (AssignPolicy::include_degenerate) { - only_convert::apply(tp, result.template get<0>()); - AssignPolicy::apply(tp, pi, qi, result.template get<0>(), result.template get<1>()); + only_convert::apply(tp, inters.i_info()); + AssignPolicy::apply(tp, pi, qi, inters.i_info(), inters.d_info()); *out++ = tp; } } diff --git a/include/boost/geometry/algorithms/detail/overlay/get_turn_info_for_endpoint.hpp b/include/boost/geometry/algorithms/detail/overlay/get_turn_info_for_endpoint.hpp index fca64e3ed..4b910dff5 100644 --- a/include/boost/geometry/algorithms/detail/overlay/get_turn_info_for_endpoint.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/get_turn_info_for_endpoint.hpp @@ -15,177 +15,13 @@ #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_GET_TURN_INFO_FOR_ENDPOINT_HPP #include +#include namespace boost { namespace geometry { #ifndef DOXYGEN_NO_DETAIL namespace detail { namespace overlay { -// TURN_OPERATION - -enum turn_position { position_middle, position_front, position_back }; - -template -struct turn_operation_linear - : public turn_operation -{ - turn_operation_linear() - : position(position_middle) - , is_collinear(false) - {} - - turn_position position; - bool is_collinear; // valid only for Linear geometry -}; - -template -class intersection_info -{ - typedef typename strategy_intersection - < - typename cs_tag::type, - Point1, - Point2, - TurnPoint, - RobustPolicy - >::segment_intersection_strategy_type strategy; - -public: - typedef model::referring_segment segment_type1; - typedef model::referring_segment segment_type2; - typedef side_calculator side_calculator_type; - - typedef typename strategy::return_type result_type; - typedef typename boost::tuples::element<0, result_type>::type i_info_type; // intersection_info - typedef typename boost::tuples::element<1, result_type>::type d_info_type; // dir_info - - intersection_info(Point1 const& pi, Point1 const& pj, Point1 const& pk, - Point2 const& qi, Point2 const& qj, Point2 const& qk, - RobustPolicy const& robust_policy) - : m_result(strategy::apply(segment_type1(pi, pj), - segment_type2(qi, qj), - robust_policy)) - , m_side_calc(pi, pj, pk, qi, qj, qk) - , m_robust_policy(robust_policy) - {} - - inline Point1 const& pi() const { return m_side_calc.m_pi; } - inline Point1 const& pj() const { return m_side_calc.m_pj; } - inline Point1 const& pk() const { return m_side_calc.m_pk; } - - inline Point2 const& qi() const { return m_side_calc.m_qi; } - inline Point2 const& qj() const { return m_side_calc.m_qj; } - inline Point2 const& qk() const { return m_side_calc.m_qk; } - - inline side_calculator_type const& sides() const { return m_side_calc; } - inline result_type const& result() const { return m_result; } - inline i_info_type const& i_info() const { return m_result.template get<0>(); } - inline d_info_type const& d_info() const { return m_result.template get<1>(); } - - // TODO: not it's more like is_spike_ip_p - inline bool is_spike_p() const - { - if ( m_side_calc.pk_wrt_p1() == 0 ) - { - if ( ! is_ip_j<0>() ) - return false; - - int const qk_p1 = m_side_calc.qk_wrt_p1(); - int const qk_p2 = m_side_calc.qk_wrt_p2(); - - if ( qk_p1 == -qk_p2 ) - { - if ( qk_p1 == 0 ) - { - return is_spike_of_collinear(pi(), pj(), pk()); - } - - return true; - } - } - - return false; - } - - // TODO: not it's more like is_spike_ip_q - inline bool is_spike_q() const - { - if ( m_side_calc.qk_wrt_q1() == 0 ) - { - if ( ! is_ip_j<1>() ) - return false; - - int const pk_q1 = m_side_calc.pk_wrt_q1(); - int const pk_q2 = m_side_calc.pk_wrt_q2(); - - if ( pk_q1 == -pk_q2 ) - { - if ( pk_q1 == 0 ) - { - return is_spike_of_collinear(qi(), qj(), qk()); - } - - return true; - } - } - - return false; - } - -private: - template - inline bool is_spike_of_collinear(Point const& i, Point const& j, Point const& k) const - { - typedef model::referring_segment seg_t; - - typedef strategy_intersection - < - typename cs_tag::type, Point, Point, Point, RobustPolicy - > si; - - typedef typename si::segment_intersection_strategy_type strategy; - - typename strategy::return_type result - = strategy::apply(seg_t(i, j), seg_t(j, k), m_robust_policy); - - return result.template get<0>().count == 2; - } - - template - bool is_ip_j() const - { - int arrival = d_info().arrival[OpId]; - bool same_dirs = d_info().dir_a == 0 && d_info().dir_b == 0; - - if ( same_dirs ) - { - if ( i_info().count == 2 ) - { - if ( ! d_info().opposite ) - { - return arrival != -1; - } - else - { - return arrival != -1; - } - } - else - { - return arrival == 0; - } - } - else - { - return arrival == 1; - } - } - - result_type m_result; - side_calculator_type m_side_calc; - RobustPolicy const& m_robust_policy; -}; - // SEGMENT_INTERSECTION RESULT // C H0 H1 A0 A1 O IP1 IP2 @@ -485,6 +321,8 @@ 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(), is_p_first_ip, is_p_last_ip, is_q_first_ip, is_q_last_ip, ip_info.is_qi, ip_info.is_qj, @@ -493,6 +331,8 @@ struct get_turn_info_for_endpoint if ( !handled ) { handle_internal<1>(qi, qj, qk, pi, pj, pk, + inters.rqi(), inters.rqj(), inters.rqk(), + inters.rpi(), inters.rpj(), inters.rpk(), is_q_first_ip, is_q_last_ip, is_p_first_ip, is_p_last_ip, ip_info.is_pi, ip_info.is_pj, @@ -549,11 +389,15 @@ struct get_turn_info_for_endpoint template 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, bool first1, bool last1, bool first2, bool last2, bool ip_i2, bool ip_j2, TurnInfo const& tp_model, IntersectionInfo const& inters, int ip_index, @@ -582,7 +426,8 @@ struct get_turn_info_for_endpoint } else if ( ip_j2 ) { - side_calculator side_calc(i2, i1, j1, i2, j2, k2); + side_calculator + side_calc(ri2, ri1, rj1, ri2, rj2, rk2); std::pair operations = operations_of_equal(side_calc); @@ -632,7 +477,8 @@ struct get_turn_info_for_endpoint } else if ( ip_j2 ) { - side_calculator side_calc(i2, j1, i1, i2, j2, k2); + side_calculator + side_calc(ri2, rj1, ri1, ri2, rj2, rk2); std::pair operations = operations_of_equal(side_calc); diff --git a/include/boost/geometry/algorithms/detail/overlay/get_turn_info_helpers.hpp b/include/boost/geometry/algorithms/detail/overlay/get_turn_info_helpers.hpp new file mode 100644 index 000000000..6b3c54d5f --- /dev/null +++ b/include/boost/geometry/algorithms/detail/overlay/get_turn_info_helpers.hpp @@ -0,0 +1,336 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// 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. + +// 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_OVERLAY_GET_TURN_INFO_HELPERS_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_GET_TURN_INFO_HELPERS_HPP + +#include + +namespace boost { namespace geometry { + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace overlay { + +enum turn_position { position_middle, position_front, position_back }; + +template +struct turn_operation_linear + : public turn_operation +{ + turn_operation_linear() + : position(position_middle) + , is_collinear(false) + {} + + turn_position position; + bool is_collinear; // valid only for Linear geometry +}; + +template +struct side_calculator +{ + typedef boost::geometry::strategy::side::side_by_triangle<> side; // todo: get from coordinate system + + inline side_calculator(Pi const& pi, Pj const& pj, Pk const& pk, + Qi const& qi, Qj const& qj, Qk const& qk) + : m_pi(pi), m_pj(pj), m_pk(pk) + , m_qi(qi), m_qj(qj), m_qk(qk) + {} + + inline int pk_wrt_p1() const { return side::apply(m_pi, m_pj, m_pk); } + inline int pk_wrt_q1() const { return side::apply(m_qi, m_qj, m_pk); } + inline int qk_wrt_p1() const { return side::apply(m_pi, m_pj, m_qk); } + inline int qk_wrt_q1() const { return side::apply(m_qi, m_qj, m_qk); } + + inline int pk_wrt_q2() const { return side::apply(m_qj, m_qk, m_pk); } + inline int qk_wrt_p2() const { return side::apply(m_pj, m_pk, m_qk); } + + Pi const& m_pi; + Pj const& m_pj; + Pk const& m_pk; + Qi const& m_qi; + Qj const& m_qj; + Qk const& m_qk; +}; + +template +struct robust_points +{ + typedef typename geometry::robust_point_type + < + Point1, RobustPolicy + >::type robust_point1_type; + // TODO: define robust_point2_type using Point2? + typedef robust_point1_type robust_point2_type; + + inline robust_points(Point1 const& pi, Point1 const& pj, Point1 const& pk, + Point2 const& qi, Point2 const& qj, Point2 const& qk, + RobustPolicy const& robust_policy) + { + geometry::recalculate(m_rpi, pi, robust_policy); + geometry::recalculate(m_rpj, pj, robust_policy); + geometry::recalculate(m_rpk, pk, robust_policy); + geometry::recalculate(m_rqi, qi, robust_policy); + geometry::recalculate(m_rqj, qj, robust_policy); + geometry::recalculate(m_rqk, qk, robust_policy); + } + + robust_point1_type m_rpi, m_rpj, m_rpk; + robust_point2_type m_rqi, m_rqj, m_rqk; +}; + +template +class intersection_info_base + : private robust_points +{ + typedef robust_points base_t; + +public: + typedef Point1 point1_type; + typedef Point2 point2_type; + + typedef typename base_t::robust_point1_type robust_point1_type; + typedef typename base_t::robust_point2_type robust_point2_type; + + typedef side_calculator side_calculator_type; + + intersection_info_base(Point1 const& pi, Point1 const& pj, Point1 const& pk, + Point2 const& qi, Point2 const& qj, Point2 const& qk, + RobustPolicy const& robust_policy) + : base_t(pi, pj, pk, qi, qj, qk, robust_policy) + , m_side_calc(base_t::m_rpi, base_t::m_rpj, base_t::m_rpk, + base_t::m_rqi, base_t::m_rqj, base_t::m_rqk) + , m_pi(pi), m_pj(pj), m_pk(pk) + , m_qi(qi), m_qj(qj), m_qk(qk) + {} + + inline Point1 const& pi() const { return m_pi; } + inline Point1 const& pj() const { return m_pj; } + inline Point1 const& pk() const { return m_pk; } + + inline Point2 const& qi() const { return m_qi; } + inline Point2 const& qj() const { return m_qj; } + inline Point2 const& qk() const { return m_qk; } + + inline robust_point1_type const& rpi() const { return base_t::m_rpi; } + inline robust_point1_type const& rpj() const { return base_t::m_rpj; } + inline robust_point1_type const& rpk() const { return base_t::m_rpk; } + + inline robust_point2_type const& rqi() const { return base_t::m_rqi; } + inline robust_point2_type const& rqj() const { return base_t::m_rqj; } + inline robust_point2_type const& rqk() const { return base_t::m_rqk; } + + inline side_calculator_type const& sides() const { return m_side_calc; } + +private: + side_calculator_type m_side_calc; + + point1_type const& m_pi; + point1_type const& m_pj; + point1_type const& m_pk; + point2_type const& m_qi; + point2_type const& m_qj; + point2_type const& m_qk; +}; + +template +class intersection_info_base +{ +public: + typedef Point1 point1_type; + typedef Point2 point2_type; + + typedef Point1 robust_point1_type; + typedef Point2 robust_point2_type; + + typedef side_calculator side_calculator_type; + + intersection_info_base(Point1 const& pi, Point1 const& pj, Point1 const& pk, + Point2 const& qi, Point2 const& qj, Point2 const& qk, + no_rescale_policy const& robust_policy) + : m_side_calc(pi, pj, pk, qi, qj, qk) + {} + + inline Point1 const& pi() const { return m_side_calc.m_pi; } + inline Point1 const& pj() const { return m_side_calc.m_pj; } + inline Point1 const& pk() const { return m_side_calc.m_pk; } + + inline Point2 const& qi() const { return m_side_calc.m_qi; } + inline Point2 const& qj() const { return m_side_calc.m_qj; } + inline Point2 const& qk() const { return m_side_calc.m_qk; } + + inline Point1 const& rpi() const { return pi(); } + inline Point1 const& rpj() const { return pj(); } + inline Point1 const& rpk() const { return pk(); } + + inline Point2 const& rqi() const { return qi(); } + inline Point2 const& rqj() const { return qj(); } + inline Point2 const& rqk() const { return qk(); } + + inline side_calculator_type const& sides() const { return m_side_calc; } + +private: + side_calculator_type m_side_calc; +}; + + +template +class intersection_info + : public intersection_info_base +{ + typedef intersection_info_base base_t; + + typedef typename strategy_intersection + < + typename cs_tag::type, + Point1, + Point2, + TurnPoint, + RobustPolicy + >::segment_intersection_strategy_type strategy; + +public: + typedef model::referring_segment segment_type1; + typedef model::referring_segment segment_type2; + typedef typename base_t::side_calculator_type side_calculator_type; + + typedef typename strategy::return_type result_type; + typedef typename boost::tuples::element<0, result_type>::type i_info_type; // intersection_info + typedef typename boost::tuples::element<1, result_type>::type d_info_type; // dir_info + + intersection_info(Point1 const& pi, Point1 const& pj, Point1 const& pk, + Point2 const& qi, Point2 const& qj, Point2 const& qk, + RobustPolicy const& robust_policy) + : base_t(pi, pj, pk, qi, qj, qk, robust_policy) + , m_result(strategy::apply(segment_type1(pi, pj), + segment_type2(qi, qj), + robust_policy)) + , m_robust_policy(robust_policy) + {} + + inline result_type const& result() const { return m_result; } + inline i_info_type const& i_info() const { return m_result.template get<0>(); } + inline d_info_type const& d_info() const { return m_result.template get<1>(); } + + // TODO: it's more like is_spike_ip_p + inline bool is_spike_p() const + { + if ( base_t::sides().pk_wrt_p1() == 0 ) + { + if ( ! is_ip_j<0>() ) + return false; + + int const qk_p1 = base_t::sides().qk_wrt_p1(); + int const qk_p2 = base_t::sides().qk_wrt_p2(); + + if ( qk_p1 == -qk_p2 ) + { + if ( qk_p1 == 0 ) + { + return is_spike_of_collinear(base_t::pi(), base_t::pj(), base_t::pk()); + } + + return true; + } + } + + return false; + } + + // TODO: it's more like is_spike_ip_q + inline bool is_spike_q() const + { + if ( base_t::sides().qk_wrt_q1() == 0 ) + { + if ( ! is_ip_j<1>() ) + return false; + + int const pk_q1 = base_t::sides().pk_wrt_q1(); + int const pk_q2 = base_t::sides().pk_wrt_q2(); + + if ( pk_q1 == -pk_q2 ) + { + if ( pk_q1 == 0 ) + { + return is_spike_of_collinear(base_t::qi(), base_t::qj(), base_t::qk()); + } + + return true; + } + } + + return false; + } + +private: + template + inline bool is_spike_of_collinear(Point const& i, Point const& j, Point const& k) const + { + typedef model::referring_segment seg_t; + + typedef strategy_intersection + < + typename cs_tag::type, Point, Point, Point, RobustPolicy + > si; + + typedef typename si::segment_intersection_strategy_type strategy; + + typename strategy::return_type result + = strategy::apply(seg_t(i, j), seg_t(j, k), m_robust_policy); + + return result.template get<0>().count == 2; + } + + template + bool is_ip_j() const + { + int arrival = d_info().arrival[OpId]; + bool same_dirs = d_info().dir_a == 0 && d_info().dir_b == 0; + + if ( same_dirs ) + { + if ( i_info().count == 2 ) + { + if ( ! d_info().opposite ) + { + return arrival != -1; + } + else + { + return arrival != -1; + } + } + else + { + return arrival == 0; + } + } + else + { + return arrival == 1; + } + } + + result_type m_result; + RobustPolicy const& m_robust_policy; +}; + +}} // namespace detail::overlay +#endif // DOXYGEN_NO_DETAIL + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_GET_TURN_INFO_HELPERS_HPP diff --git a/include/boost/geometry/algorithms/detail/overlay/get_turn_info_la.hpp b/include/boost/geometry/algorithms/detail/overlay/get_turn_info_la.hpp index 3eab8e60e..121963b66 100644 --- a/include/boost/geometry/algorithms/detail/overlay/get_turn_info_la.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/get_turn_info_la.hpp @@ -47,8 +47,10 @@ struct get_turn_info_linear_areal RobustPolicy const& robust_policy, OutputIterator out) { - intersection_info - inters(pi, pj, pk, qi, qj, qk, robust_policy); + typedef intersection_info + inters_info; + + inters_info inters(pi, pj, pk, qi, qj, qk, robust_policy); char const method = inters.d_info().how; @@ -64,7 +66,7 @@ struct get_turn_info_linear_areal get_turn_info_for_endpoint( pi, pj, pk, qi, qj, qk, is_p_first, is_p_last, is_q_first, is_q_last, - tp_model, inters.result(), method_none, out); + tp_model, inters, method_none, out); break; case 'd' : // disjoint: never do anything @@ -75,7 +77,7 @@ struct get_turn_info_linear_areal if ( get_turn_info_for_endpoint( pi, pj, pk, qi, qj, qk, is_p_first, is_p_last, is_q_first, is_q_last, - tp_model, inters.result(), method_touch_interior, out) ) + tp_model, inters, method_touch_interior, out) ) { // do nothing } @@ -96,7 +98,12 @@ struct get_turn_info_linear_areal else { // Swap p/q - side_calculator swapped_side_calc(qi, qj, qk, pi, pj, pk); + side_calculator + < + typename inters_info::robust_point2_type, + typename inters_info::robust_point1_type + > swapped_side_calc(inters.rqi(), inters.rqj(), inters.rqk(), + inters.rpi(), inters.rpj(), inters.rpk()); policy::template apply<1>(qi, qj, qk, pi, pj, pk, tp, inters.i_info(), inters.d_info(), swapped_side_calc); @@ -138,7 +145,7 @@ struct get_turn_info_linear_areal if ( get_turn_info_for_endpoint( pi, pj, pk, qi, qj, qk, is_p_first, is_p_last, is_q_first, is_q_last, - tp_model, inters.result(), method_touch, out) ) + tp_model, inters, method_touch, out) ) { // do nothing } @@ -230,7 +237,7 @@ struct get_turn_info_linear_areal if ( get_turn_info_for_endpoint( pi, pj, pk, qi, qj, qk, is_p_first, is_p_last, is_q_first, is_q_last, - tp_model, inters.result(), method_equal, out) ) + tp_model, inters, method_equal, out) ) { // do nothing } @@ -277,7 +284,7 @@ struct get_turn_info_linear_areal if ( get_turn_info_for_endpoint( pi, pj, pk, qi, qj, qk, is_p_first, is_p_last, is_q_first, is_q_last, - tp_model, inters.result(), method_collinear, out) ) + tp_model, inters, method_collinear, out) ) { // do nothing } @@ -621,7 +628,7 @@ struct get_turn_info_linear_areal typename Point1, typename Point2, typename TurnInfo, - typename IntersectionResult, + typename IntersectionInfo, typename OutputIterator> static inline bool get_turn_info_for_endpoint( Point1 const& pi, Point1 const& pj, Point1 const& pk, @@ -629,14 +636,14 @@ struct get_turn_info_linear_areal bool is_p_first, bool is_p_last, bool is_q_first, bool is_q_last, TurnInfo const& tp_model, - IntersectionResult const& result, + IntersectionInfo const& inters, method_type /*method*/, OutputIterator out) { namespace ov = overlay; typedef ov::get_turn_info_for_endpoint get_info_e; - const std::size_t ip_count = result.template get<0>().count; + const std::size_t ip_count = inters.i_info().count; // no intersection points if ( ip_count == 0 ) return false; @@ -648,11 +655,11 @@ struct get_turn_info_linear_areal if ( !is_p_first && !is_p_last ) return false; - linear_intersections intersections(pi, qi, result, is_p_last, is_q_last); + linear_intersections intersections(pi, qi, inters.result(), is_p_last, is_q_last); linear_intersections::ip_info const& ip0 = intersections.template get<0>(); linear_intersections::ip_info const& ip1 = intersections.template get<1>(); - const bool opposite = result.template get<1>().opposite; + const bool opposite = inters.d_info().opposite; // ANALYSE AND ASSIGN FIRST @@ -675,7 +682,13 @@ struct get_turn_info_linear_areal if ( ip0.is_qj ) { - side_calculator side_calc(qi, pi, pj, qi, qj, qk); + side_calculator + < + typename IntersectionInfo::robust_point1_type, + typename IntersectionInfo::robust_point2_type, + typename IntersectionInfo::robust_point2_type + > side_calc(inters.rqi(), inters.rpi(), inters.rpj(), + inters.rqi(), inters.rqj(), inters.rqk()); std::pair operations = get_info_e::operations_of_equal(side_calc); @@ -687,9 +700,18 @@ struct get_turn_info_linear_areal } else { - side_calculator side_calc(qi, pi, pj, qi, pi, qj); + side_calculator + < + typename IntersectionInfo::robust_point1_type, + typename IntersectionInfo::robust_point2_type, + typename IntersectionInfo::robust_point2_type, + typename IntersectionInfo::robust_point1_type, + typename IntersectionInfo::robust_point1_type, + typename IntersectionInfo::robust_point2_type, + typename IntersectionInfo::robust_point1_type, + typename IntersectionInfo::robust_point2_type + > side_calc(inters.rqi(), inters.rpi(), inters.rpj(), + inters.rqi(), inters.rpi(), inters.rqj()); std::pair operations = get_info_e::operations_of_equal(side_calc); @@ -704,17 +726,17 @@ struct get_turn_info_linear_areal // equals<> or collinear<> will assign the second point, // we'd like to assign the first one - base_turn_handler::assign_point(tp, tp.method, result.template get<0>(), 0); + base_turn_handler::assign_point(tp, tp.method, inters.i_info(), 0); // NOTE: not really needed especially for the first point // for which there is no preceding segment (but consistent with the L/L) - if ( result.template get<0>().count > 1 ) + if ( inters.i_info().count > 1 ) { //BOOST_ASSERT( result.template get<1>().dir_a == 0 && result.template get<1>().dir_b == 0 ); tp.operations[0].is_collinear = true; } - AssignPolicy::apply(tp, pi, qi, result.template get<0>(), result.template get<1>()); + AssignPolicy::apply(tp, pi, qi, inters.i_info(), inters.d_info()); *out++ = tp; } @@ -727,7 +749,7 @@ struct get_turn_info_linear_areal { TurnInfo tp = tp_model; - if ( result.template get<0>().count > 1 ) + if ( inters.i_info().count > 1 ) { //BOOST_ASSERT( result.template get<1>().dir_a == 0 && result.template get<1>().dir_b == 0 ); tp.operations[0].is_collinear = true; @@ -735,7 +757,13 @@ struct get_turn_info_linear_areal } else //if ( result.template get<0>().count == 1 ) { - side_calculator side_calc(qi, pj, pi, qi, qj, qk); + side_calculator + < + typename IntersectionInfo::robust_point1_type, + typename IntersectionInfo::robust_point2_type, + typename IntersectionInfo::robust_point2_type + > side_calc(inters.rqi(), inters.rpj(), inters.rpi(), + inters.rqi(), inters.rqj(), inters.rqk()); std::pair operations = get_info_e::operations_of_equal(side_calc); @@ -760,9 +788,9 @@ struct get_turn_info_linear_areal // equals<> or collinear<> will assign the second point, // we'd like to assign the first one std::size_t ip_index = ip_count > 1 ? 1 : 0; - base_turn_handler::assign_point(tp, tp.method, result.template get<0>(), ip_index); + base_turn_handler::assign_point(tp, tp.method, inters.i_info(), ip_index); - AssignPolicy::apply(tp, pi, qi, result.template get<0>(), result.template get<1>()); + AssignPolicy::apply(tp, pi, qi, inters.i_info(), inters.d_info()); *out++ = tp; return true; diff --git a/include/boost/geometry/algorithms/detail/overlay/get_turn_info_ll.hpp b/include/boost/geometry/algorithms/detail/overlay/get_turn_info_ll.hpp index e7426257e..4ff20d6cc 100644 --- a/include/boost/geometry/algorithms/detail/overlay/get_turn_info_ll.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/get_turn_info_ll.hpp @@ -44,8 +44,10 @@ struct get_turn_info_linear_linear RobustPolicy const& robust_policy, OutputIterator out) { - intersection_info - inters(pi, pj, pk, qi, qj, qk, robust_policy); + typedef intersection_info + inters_info; + + inters_info inters(pi, pj, pk, qi, qj, qk, robust_policy); char const method = inters.d_info().how; @@ -93,7 +95,13 @@ struct get_turn_info_linear_linear else { // Swap p/q - side_calculator swapped_side_calc(qi, qj, qk, pi, pj, pk); + side_calculator + < + typename inters_info::robust_point2_type, + typename inters_info::robust_point1_type + > swapped_side_calc(inters.rqi(), inters.rqj(), inters.rqk(), + inters.rpi(), inters.rpj(), inters.rpk()); + policy::template apply<1>(qi, qj, qk, pi, pj, pk, tp, inters.i_info(), inters.d_info(), swapped_side_calc);