From f671b5830f976438374ad53b7ac497edbf9b652d Mon Sep 17 00:00:00 2001 From: Adam Wulkiewicz Date: Sat, 26 Apr 2014 03:03:58 +0200 Subject: [PATCH 1/3] [get_turns] Refactor get_turns for L/L and L/A. This change prevents duplication and decreases the number of parameters that must be passed to various functions and makes the code more readable. Enclose parts of the code used in both implementations in one class - intersection_info. Move there IntersectionsResult, sides_calculator, spikes checks. Use this class in get_turn_info_linear_*. Provide convenient i_info() and d_info() to allow replacing result.template get<0>() and result.template get<1>() calls. --- .../overlay/get_turn_info_for_endpoint.hpp | 247 +++++++++--------- .../detail/overlay/get_turn_info_la.hpp | 164 ++++-------- .../detail/overlay/get_turn_info_ll.hpp | 163 +++++------- 3 files changed, 253 insertions(+), 321 deletions(-) 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 cab3a4d25..d75b2cc1d 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 @@ -38,96 +38,116 @@ struct turn_operation_linear bool is_collinear; // valid only for Linear geometry }; -// IS_SPIKE - -template -inline bool is_spike_of_collinear(model::referring_segment const& s1, - model::referring_segment const& s2, - RobustPolicy const& robust_policy) +template +class intersection_info { - typedef strategy_intersection + typedef typename 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(s1, s2, robust_policy); - - return result.template get<0>().count == 2; -} + typename cs_tag::type, + Point1, + Point2, + TurnPoint, + RobustPolicy + >::segment_intersection_strategy_type strategy; -template -inline bool is_spike_p(side_calculator const& side_calc, - model::referring_segment const& p1, - model::referring_segment const& p2, - RobustPolicy const& robust_policy) -{ - if ( side_calc.pk_wrt_p1() == 0 ) - { - int const qk_p1 = side_calc.qk_wrt_p1(); - int const qk_p2 = side_calc.qk_wrt_p2(); - - if ( qk_p1 == -qk_p2 ) - { - if ( qk_p1 == 0 ) - { - return is_spike_of_collinear(p1, p2, robust_policy); - } - - return true; - } - } - - return false; -} - -template -inline bool is_spike_q(side_calculator const& side_calc, - model::referring_segment const& q1, - model::referring_segment const& q2, - RobustPolicy const& robust_policy) -{ - if ( side_calc.qk_wrt_q1() == 0 ) - { - int const pk_q1 = side_calc.pk_wrt_q1(); - int const pk_q2 = side_calc.pk_wrt_q2(); - - if ( pk_q1 == -pk_q2 ) - { - if ( pk_q1 == 0 ) - { - return is_spike_of_collinear(q1, q2, robust_policy); - } - - return true; - } - } - - return false; -} - -template -inline bool is_spike_p(Point1 const& pi, Point1 const& pj, Point1 const& pk, - Point2 const& qi, Point2 const& qj, Point2 const& qk, - RobustPolicy const& robust_policy) -{ +public: typedef model::referring_segment segment_type1; - segment_type1 p1(pi, pj), p2(pj, pk); - side_calculator side_calc(pi, pj, pk, qi, qj, qk); - return is_spike_p(side_calc, p1, p2, robust_policy); -} - -template -inline bool is_spike_q(Point1 const& pi, Point1 const& pj, Point1 const& pk, - Point2 const& qi, Point2 const& qj, Point2 const& qk, - RobustPolicy const& robust_policy) -{ typedef model::referring_segment segment_type2; - segment_type2 q1(qi, qj), q2(qj, qk); - side_calculator side_calc(pi, pj, pk, qi, qj, qk); - return is_spike_q(side_calc, q1, q2, robust_policy); -} + 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>(); } + + inline bool is_spike_p() const + { + if ( m_side_calc.pk_wrt_p1() == 0 ) + { + 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(segment_type1(pi(), pj()), + segment_type1(pj(), pk())); + } + + return true; + } + } + + return false; + } + + inline bool is_spike_q() const + { + if ( m_side_calc.qk_wrt_q1() == 0 ) + { + 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(segment_type2(qi(), qj()), + segment_type2(qj(), qk())); + } + + return true; + } + } + + return false; + } + +private: + template + inline bool is_spike_of_collinear( + model::referring_segment const& s1, + model::referring_segment const& s2) const + { + 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(s1, s2, m_robust_policy); + + return result.template get<0>().count == 2; + } + + result_type m_result; + side_calculator_type m_side_calc; + RobustPolicy const& m_robust_policy; +}; // SEGMENT_INTERSECTION RESULT @@ -335,8 +355,7 @@ struct get_turn_info_for_endpoint template static inline bool apply(Point1 const& pi, Point1 const& pj, Point1 const& pk, @@ -344,12 +363,11 @@ struct get_turn_info_for_endpoint bool is_p_first, bool is_p_last, bool is_q_first, bool is_q_last, TurnInfo const& tp_model, - IntersectionResult const& result, - RobustPolicy const& robust_policy, + IntersectionInfo const& inters, method_type /*method*/, OutputIterator out) { - std::size_t ip_count = result.template get<0>().count; + std::size_t ip_count = inters.i_info().count; // no intersection points if ( ip_count == 0 ) return false; @@ -361,17 +379,16 @@ struct get_turn_info_for_endpoint if ( !is_p_first && !is_p_last && !is_q_first && !is_q_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); 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, intersections.template get<0>(), - tp_model, result, 0, - robust_policy, out); + tp_model, inters, 0, out); // NOTE: opposite && ip_count == 1 may be true! - bool opposite = result.template get<1>().opposite; + bool opposite = inters.d_info().opposite; // don't ignore only for collinear opposite bool result_ignore_ip0 = append0_last && ( ip_count == 1 || !opposite ); @@ -383,8 +400,7 @@ struct get_turn_info_for_endpoint = analyse_segment_and_assign_ip(pi, pj, pk, qi, qj, qk, is_p_first, is_p_last, is_q_first, is_q_last, intersections.template get<1>(), - tp_model, result, 1, - robust_policy, out); + tp_model, inters, 1, out); // don't ignore only for collinear opposite bool result_ignore_ip1 = append1_last && !opposite /*&& ip_count == 2*/; @@ -395,8 +411,7 @@ struct get_turn_info_for_endpoint template static inline bool analyse_segment_and_assign_ip(Point1 const& pi, Point1 const& pj, Point1 const& pk, @@ -405,9 +420,8 @@ struct get_turn_info_for_endpoint bool is_q_first, bool is_q_last, linear_intersections::ip_info const& ip_info, TurnInfo const& tp_model, - IntersectionResult const& result, + IntersectionInfo const& inters, int ip_index, - RobustPolicy const& robust_policy, OutputIterator out) { #ifdef BOOST_GEOMETRY_DEBUG_GET_TURNS_LINEAR_LINEAR @@ -437,14 +451,16 @@ struct get_turn_info_for_endpoint is_p_first_ip, is_p_last_ip, is_q_first_ip, is_q_last_ip, ip_info.is_qi, ip_info.is_qj, - tp_model, result, ip_index, p_operation, q_operation); + tp_model, inters.result(), ip_index, + p_operation, q_operation); if ( !handled ) { handle_internal(qi, qj, qk, pi, pj, pk, is_q_first_ip, is_q_last_ip, is_p_first_ip, is_p_last_ip, ip_info.is_pi, ip_info.is_pj, - tp_model, result, ip_index, q_operation, p_operation); + tp_model, inters.result(), ip_index, + q_operation, p_operation); } if ( p_operation != operation_none ) @@ -458,28 +474,28 @@ struct get_turn_info_for_endpoint // P is spike and should be handled if ( !is_p_last && ip_info.is_pj - && result.template get<0>().count == 2 - && is_spike_p(pi, pj, pk, qi, qj, qk, robust_policy) ) + && inters.i_info().count == 2 + && inters.is_spike_p() ) { - assign(pi, qi, result, ip_index, method, operation_blocked, q_operation, + assign(pi, qi, inters.result(), ip_index, method, operation_blocked, q_operation, p_pos, q_pos, tp_model, out); - assign(pi, qi, result, ip_index, method, operation_intersection, q_operation, + assign(pi, qi, inters.result(), ip_index, method, operation_intersection, q_operation, p_pos, q_pos, tp_model, out); } // Q is spike and should be handled else if ( !is_q_last && ip_info.is_qj - && result.template get<0>().count == 2 - && is_spike_q(pi, pj, pk, qi, qj, qk, robust_policy) ) + && inters.i_info().count == 2 + && inters.is_spike_q() ) { - assign(pi, qi, result, ip_index, method, p_operation, operation_blocked, + assign(pi, qi, inters.result(), ip_index, method, p_operation, operation_blocked, p_pos, q_pos, tp_model, out); - assign(pi, qi, result, ip_index, method, p_operation, operation_intersection, + assign(pi, qi, inters.result(), ip_index, method, p_operation, operation_intersection, p_pos, q_pos, tp_model, out); } // no spikes else { - assign(pi, qi, result, ip_index, method, p_operation, q_operation, + assign(pi, qi, inters.result(), ip_index, method, p_operation, q_operation, p_pos, q_pos, tp_model, out); } } @@ -498,12 +514,9 @@ struct get_turn_info_for_endpoint > static inline bool handle_internal(Point1 const& i1, Point1 const& j1, Point1 const& /*k1*/, Point2 const& i2, Point2 const& j2, Point2 const& k2, - bool first1, bool last1, - bool first2, bool last2, - bool ip_i2, bool ip_j2, - TurnInfo const& tp_model, - IntersectionResult const& result, - int ip_index, + bool first1, bool last1, bool first2, bool last2, + bool ip_i2, bool ip_j2, TurnInfo const& tp_model, + IntersectionResult const& result, int ip_index, operation_type & op1, operation_type & op2) { boost::ignore_unused_variable_warning(ip_index); 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 d4063834c..46eb6758c 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,27 +47,10 @@ struct get_turn_info_linear_areal RobustPolicy const& robust_policy, OutputIterator out) { - typedef model::referring_segment segment_type1; - typedef model::referring_segment segment_type2; - segment_type1 p1(pi, pj), p2(pj, pk); - segment_type2 q1(qi, qj), q2(qj, qk); + intersection_info + inters(pi, pj, pk, qi, qj, qk, robust_policy); - side_calculator side_calc(pi, pj, pk, qi, qj, qk); - - 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); - - 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; @@ -81,7 +64,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, result, method_none, out); + tp_model, inters.result(), method_none, out); break; case 'd' : // disjoint: never do anything @@ -92,7 +75,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, result, method_touch_interior, out) ) + tp_model, inters.result(), method_touch_interior, out) ) { // do nothing } @@ -104,18 +87,18 @@ struct get_turn_info_linear_areal > 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); 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); } @@ -130,10 +113,9 @@ struct get_turn_info_linear_areal // this function assumes that 'u' must be set for a spike calculate_spike_operation(tp.operations[0].operation, - side_calc, p1, p2, - is_p_last, robust_policy); + inters, is_p_last); - 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; } @@ -142,11 +124,11 @@ struct get_turn_info_linear_areal case 'i' : { crosses::apply(pi, pj, pk, qi, qj, qk, - tp, result.template get<0>(), result.template get<1>()); + tp, inters.i_info(), inters.d_info()); replace_operations_i(tp.operations[0].operation, tp.operations[1].operation); - 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; @@ -156,14 +138,14 @@ 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, result, method_touch, out) ) + tp_model, inters.result(), method_touch, out) ) { // do nothing } else { touch::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()); if ( tp.operations[1].operation == operation_blocked ) { @@ -177,19 +159,15 @@ struct get_turn_info_linear_areal // this function assumes that 'u' must be set for a spike bool ignore_spike = calculate_spike_operation(tp.operations[0].operation, - side_calc, p1, p2, - is_p_last, robust_policy); + inters, is_p_last); // TODO: move this into the append_xxx and call for each turn? - AssignPolicy::apply(tp, pi, qi, result.template get<0>(), result.template get<1>()); + AssignPolicy::apply(tp, pi, qi, inters.i_info(), inters.d_info()); if ( ! handle_spikes || ignore_spike || ! append_opposite_spikes( // for 'i' or 'c' - tp, result, side_calc, - p1, p2, q1, q2, - is_p_last, is_q_last, - robust_policy, out) ) + tp, inters, is_p_last, is_q_last, out) ) { *out++ = tp; } @@ -201,7 +179,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, result, method_equal, out) ) + tp_model, inters.result(), method_equal, out) ) { // do nothing } @@ -209,26 +187,23 @@ struct get_turn_info_linear_areal { tp.operations[0].is_collinear = true; - 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); + tp, inters.i_info(), inters.d_info(), inters.sides()); replacer_of_method_and_operations_ec replacer(method_touch); replacer(tp.method, tp.operations[0].operation, tp.operations[1].operation); // TODO: move this into the append_xxx and call for each turn? - AssignPolicy::apply(tp, pi, qi, result.template get<0>(), result.template get<1>()); + AssignPolicy::apply(tp, pi, qi, inters.i_info(), inters.d_info()); // conditionally handle spikes if ( ! handle_spikes - || ! append_collinear_spikes( - tp, side_calc, p1, p2, q1, q2, - is_p_last, is_q_last, - method_touch, append_equal, - robust_policy, out) ) + || ! append_collinear_spikes(tp, inters, is_p_last, is_q_last, + method_touch, append_equal, out) ) { *out++ = tp; // no spikes } @@ -240,7 +215,7 @@ struct get_turn_info_linear_areal TurnInfo, AssignPolicy >::apply(pi, qi, - tp, out, result.template get<0>(), result.template get<1>()); + tp, out, inters.i_info(), inters.d_info()); } } } @@ -251,7 +226,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, result, method_collinear, out) ) + tp_model, inters.result(), method_collinear, out) ) { // do nothing } @@ -259,16 +234,16 @@ struct get_turn_info_linear_areal { tp.operations[0].is_collinear = true; - if (! result.template get<1>().opposite) + if ( ! inters.d_info().opposite ) { method_type method_replace = method_touch_interior; append_version_c version = append_collinear; - 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()); method_replace = method_touch; version = append_equal; @@ -276,7 +251,7 @@ struct get_turn_info_linear_areal 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()); //method_replace = method_touch_interior; //version = append_collinear; @@ -286,15 +261,12 @@ struct get_turn_info_linear_areal replacer(tp.method, tp.operations[0].operation, tp.operations[1].operation); // TODO: move this into the append_xxx and call for each turn? - AssignPolicy::apply(tp, pi, qi, result.template get<0>(), result.template get<1>()); + AssignPolicy::apply(tp, pi, qi, inters.i_info(), inters.d_info()); // conditionally handle spikes if ( ! handle_spikes - || ! append_collinear_spikes( - tp, side_calc, p1, p2, q1, q2, - is_p_last, is_q_last, - method_replace, version, - robust_policy, out) ) + || ! append_collinear_spikes(tp, inters, is_p_last, is_q_last, + method_replace, version, out) ) { // no spikes *out++ = tp; @@ -309,10 +281,7 @@ struct get_turn_info_linear_areal if ( handle_spikes ) { append_opposite_spikes( - tp, result, side_calc, - p1, p2, q1, q2, - is_p_last, is_q_last, - robust_policy, out); + tp, inters, is_p_last, is_q_last, out); } // TODO: ignore for spikes? @@ -324,8 +293,8 @@ struct get_turn_info_linear_areal TurnInfo, AssignPolicy >::apply(pi, pj, pk, qi, qj, qk, - tp, out, result.template get<0>(), result.template get<1>(), side_calc, - replacer); + tp, out, inters.i_info(), inters.d_info(), + inters.sides(), replacer); } } } @@ -335,7 +304,7 @@ struct get_turn_info_linear_areal // degenerate points if (AssignPolicy::include_degenerate) { - only_convert::apply(tp, result.template get<0>()); + only_convert::apply(tp, inters.i_info()); if ( is_p_first && equals::equals_point_point(pi, tp.point) ) @@ -349,7 +318,7 @@ struct get_turn_info_linear_areal } // tp.operations[1].position = position_middle; - 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; } } @@ -370,24 +339,19 @@ struct get_turn_info_linear_areal } template + typename IntersectionInfo> static inline bool calculate_spike_operation(Operation & op, - SideCalc const& side_calc, - PSegment const& p1, - PSegment const& p2, - bool is_p_last, - RobustPolicy const& robust_policy) + IntersectionInfo const& inters, + bool is_p_last) { bool is_p_spike = op == operation_union && ! is_p_last - && is_spike_p(side_calc, p1, p2, robust_policy); + && inters.is_spike_p(); // we don't know where the spike is going since for both directions 'u' is set if ( is_p_spike ) { - if ( side_calc.pk_wrt_q1() < 0 && side_calc.pk_wrt_q2() < 0 ) + if ( inters.sides().pk_wrt_q1() < 0 && inters.sides().pk_wrt_q2() < 0 ) { op = operation_intersection; return true; @@ -400,18 +364,13 @@ struct get_turn_info_linear_areal enum append_version_c { append_equal, append_collinear }; template static inline bool append_collinear_spikes(TurnInfo & tp, - SideCalc const& side_calc, - SegmentP const& p1, SegmentP const& p2, - SegmentQ const& q1, SegmentQ const& q2, + IntersectionInfo const& inters, bool is_p_last, bool is_q_last, method_type method, append_version_c version, - RobustPolicy const& robust_policy, OutIt out) + OutIt out) { // method == touch || touch_interior // both position == middle @@ -421,12 +380,12 @@ struct get_turn_info_linear_areal || tp.operations[0].operation == operation_intersection ) : tp.operations[0].operation == operation_continue ) && ! is_p_last - && is_spike_p(side_calc, p1, p2, robust_policy); + && inters.is_spike_p(); // TODO: throw an exception for spike in Areal? /*bool is_q_spike = tp.operations[1].operation == spike_op && ! is_q_last - && is_spike_q(side_calc, q1, q2, robust_policy);*/ + && inters.is_spike_q();*/ if ( is_p_spike ) { @@ -448,35 +407,28 @@ struct get_turn_info_linear_areal template static inline bool append_opposite_spikes(TurnInfo & tp, - Result const& result, - SideCalc const& side_calc, - SegmentP const& p1, SegmentP const& p2, - SegmentQ const& q1, SegmentQ const& q2, + IntersectionInfo const& inters, bool is_p_last, bool is_q_last, - RobustPolicy const& robust_policy, OutIt out) + OutIt out) { bool is_p_spike = ( Version == append_touches ? ( tp.operations[0].operation == operation_continue || tp.operations[0].operation == operation_intersection ) : true ) && ! is_p_last - && is_spike_p(side_calc, p1, p2, robust_policy); + && inters.is_spike_p(); // TODO: throw an exception for spike in Areal? /*bool is_q_spike = ( Version == append_touches ? ( tp.operations[1].operation == operation_continue || tp.operations[1].operation == operation_intersection ) : true ) && ! is_q_last - && is_spike_q(side_calc, q1, q2, robust_policy);*/ + && inters.is_spike_q();*/ - if ( is_p_spike && ( Version == append_touches || result.template get<1>().arrival[0] == 1 ) ) + if ( is_p_spike && ( Version == append_touches || inters.d_info().arrival[0] == 1 ) ) { if ( Version == append_touches ) { @@ -489,12 +441,10 @@ struct get_turn_info_linear_areal //tp.operations[0].is_collinear = true; //tp.operations[1].is_collinear = true; - //tp.method = method_touch_interior; // only because arrival != 0 - BOOST_ASSERT(result.template get<0>().count > 1); - //geometry::convert(result.template get<0>().intersections[1], tp.point); - base_turn_handler::assign_point(tp, method_touch_interior, result.template get<0>(), 1); + BOOST_ASSERT(inters.i_info().count > 1); + base_turn_handler::assign_point(tp, method_touch_interior, inters.i_info(), 1); - AssignPolicy::apply(tp, p1.first, q1.first, result.template get<0>(), result.template get<1>()); + AssignPolicy::apply(tp, inters.pi(), inters.qi(), inters.i_info(), inters.d_info()); } tp.operations[0].operation = operation_blocked; 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 357482d50..4f1cc5232 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,27 +44,10 @@ struct get_turn_info_linear_linear RobustPolicy const& robust_policy, OutputIterator out) { - typedef model::referring_segment segment_type1; - typedef model::referring_segment segment_type2; - segment_type1 p1(pi, pj), p2(pj, pk); - segment_type2 q1(qi, qj), q2(qj, qk); + intersection_info + inters(pi, pj, pk, qi, qj, qk, robust_policy); - side_calculator side_calc(pi, pj, pk, qi, qj, qk); - - 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); - - 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; @@ -78,7 +61,7 @@ struct get_turn_info_linear_linear get_turn_info_for_endpoint ::apply(pi, pj, pk, qi, qj, qk, is_p_first, is_p_last, is_q_first, is_q_last, - tp_model, result, robust_policy, method_none, out); + tp_model, inters, method_none, out); break; case 'd' : // disjoint: never do anything @@ -89,7 +72,7 @@ struct get_turn_info_linear_linear if ( get_turn_info_for_endpoint ::apply(pi, pj, pk, qi, qj, qk, is_p_first, is_p_last, is_q_first, is_q_last, - tp_model, result, robust_policy, method_touch_interior, out) ) + tp_model, inters, method_touch_interior, out) ) { // do nothing } @@ -101,19 +84,19 @@ struct get_turn_info_linear_linear > 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); policy::template apply<1>(qi, qj, qk, pi, pj, pk, - tp, result.template get<0>(), result.template get<1>(), - swapped_side_calc); + tp, inters.i_info(), inters.d_info(), + swapped_side_calc); } if ( tp.operations[0].operation == operation_blocked ) @@ -125,9 +108,11 @@ struct get_turn_info_linear_linear tp.operations[0].is_collinear = true; } - replace_method_and_operations_tm(tp.method, tp.operations[0].operation, tp.operations[1].operation); + replace_method_and_operations_tm(tp.method, + tp.operations[0].operation, + tp.operations[1].operation); - 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; } } @@ -135,11 +120,11 @@ struct get_turn_info_linear_linear case 'i' : { crosses::apply(pi, pj, pk, qi, qj, qk, - tp, result.template get<0>(), result.template get<1>()); + tp, inters.i_info(), inters.d_info()); replace_operations_i(tp.operations[0].operation, tp.operations[1].operation); - 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; @@ -149,14 +134,14 @@ struct get_turn_info_linear_linear if ( get_turn_info_for_endpoint ::apply(pi, pj, pk, qi, qj, qk, is_p_first, is_p_last, is_q_first, is_q_last, - tp_model, result, robust_policy, method_touch, out) ) + tp_model, inters, method_touch, out) ) { // do nothing } else { touch::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()); if ( tp.operations[0].operation == operation_blocked ) { @@ -172,14 +157,12 @@ struct get_turn_info_linear_linear tp.operations[1].operation); // TODO: move this into the append_xxx and call for each turn? - AssignPolicy::apply(tp, pi, qi, result.template get<0>(), result.template get<1>()); + AssignPolicy::apply(tp, pi, qi, inters.i_info(), inters.d_info()); if ( ! handle_spikes - || ! append_opposite_spikes( - tp, result, side_calc, - p1, p2, q1, q2, - is_p_last, is_q_last, - robust_policy, out) ) + || ! append_opposite_spikes(tp, inters, + is_p_last, is_q_last, + out) ) { *out++ = tp; } @@ -191,7 +174,7 @@ struct get_turn_info_linear_linear if ( get_turn_info_for_endpoint ::apply(pi, pj, pk, qi, qj, qk, is_p_first, is_p_last, is_q_first, is_q_last, - tp_model, result, robust_policy, method_equal, out) ) + tp_model, inters, method_equal, out) ) { // do nothing } @@ -200,25 +183,25 @@ struct get_turn_info_linear_linear tp.operations[0].is_collinear = true; tp.operations[1].is_collinear = true; - 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); + tp, inters.i_info(), inters.d_info(), inters.sides()); replacer_of_method_and_operations_ec replacer(method_touch); replacer(tp.method, tp.operations[0].operation, tp.operations[1].operation); // TODO: move this into the append_xxx and call for each turn? - AssignPolicy::apply(tp, pi, qi, result.template get<0>(), result.template get<1>()); + AssignPolicy::apply(tp, pi, qi, inters.i_info(), inters.d_info()); // conditionally handle spikes if ( ! handle_spikes - || ! append_collinear_spikes(tp, side_calc, p1, p2, q1, q2, + || ! append_collinear_spikes(tp, inters, is_p_last, is_q_last, method_touch, operation_union, - robust_policy, out) ) + out) ) { *out++ = tp; // no spikes } @@ -231,8 +214,7 @@ struct get_turn_info_linear_linear < TurnInfo, AssignPolicy - >::apply(pi, qi, - tp, out, result.template get<0>(), result.template get<1>()); + >::apply(pi, qi, tp, out, inters.i_info(), inters.d_info()); } } } @@ -243,7 +225,7 @@ struct get_turn_info_linear_linear if ( get_turn_info_for_endpoint ::apply(pi, pj, pk, qi, qj, qk, is_p_first, is_p_last, is_q_first, is_q_last, - tp_model, result, robust_policy, method_collinear, out) ) + tp_model, inters, method_collinear, out) ) { // do nothing } @@ -252,16 +234,16 @@ struct get_turn_info_linear_linear tp.operations[0].is_collinear = true; tp.operations[1].is_collinear = true; - if (! result.template get<1>().opposite) + if ( ! inters.d_info().opposite ) { method_type method_replace = method_touch_interior; operation_type spike_op = operation_continue; - 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()); method_replace = method_touch; spike_op = operation_union; @@ -269,7 +251,7 @@ struct get_turn_info_linear_linear 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()); //method_replace = method_touch_interior; //spike_op = operation_continue; @@ -279,14 +261,14 @@ struct get_turn_info_linear_linear replacer(tp.method, tp.operations[0].operation, tp.operations[1].operation); // TODO: move this into the append_xxx and call for each turn? - AssignPolicy::apply(tp, pi, qi, result.template get<0>(), result.template get<1>()); + AssignPolicy::apply(tp, pi, qi, inters.i_info(), inters.d_info()); // conditionally handle spikes if ( ! handle_spikes - || ! append_collinear_spikes(tp, side_calc, p1, p2, q1, q2, + || ! append_collinear_spikes(tp, inters, is_p_last, is_q_last, method_replace, spike_op, - robust_policy, out) ) + out) ) { // no spikes *out++ = tp; @@ -300,11 +282,9 @@ struct get_turn_info_linear_linear // conditionally handle spikes if ( handle_spikes ) { - append_opposite_spikes( - tp, result, side_calc, - p1, p2, q1, q2, - is_p_last, is_q_last, - robust_policy, out); + append_opposite_spikes(tp, inters, + is_p_last, is_q_last, + out); } // TODO: ignore for spikes? @@ -316,7 +296,7 @@ struct get_turn_info_linear_linear 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(), replacer, !is_p_last, !is_q_last); } } @@ -327,7 +307,7 @@ struct get_turn_info_linear_linear // degenerate points if (AssignPolicy::include_degenerate) { - only_convert::apply(tp, result.template get<0>()); + only_convert::apply(tp, inters.i_info()); // if any, only one of those should be true if ( is_p_first @@ -351,7 +331,7 @@ struct get_turn_info_linear_linear tp.operations[1].position = position_back; } - 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; } } @@ -372,28 +352,23 @@ struct get_turn_info_linear_linear } template static inline bool append_collinear_spikes(TurnInfo & tp, - SideCalc const& side_calc, - SegmentP const& p1, SegmentP const& p2, - SegmentQ const& q1, SegmentQ const& q2, + IntersectionInfo const& inters_info, bool is_p_last, bool is_q_last, method_type method, operation_type spike_op, - RobustPolicy const& robust_policy, OutIt out) + OutIt out) { // method == touch || touch_interior // both position == middle bool is_p_spike = tp.operations[0].operation == spike_op && ! is_p_last - && is_spike_p(side_calc, p1, p2, robust_policy); + && inters_info.is_spike_p(); bool is_q_spike = tp.operations[1].operation == spike_op && ! is_q_last - && is_spike_q(side_calc, q1, q2, robust_policy); + && inters_info.is_spike_q(); if ( is_p_spike && is_q_spike ) { @@ -439,36 +414,29 @@ struct get_turn_info_linear_linear template static inline bool append_opposite_spikes(TurnInfo & tp, - Result const& result, - SideCalc const& side_calc, - SegmentP const& p1, SegmentP const& p2, - SegmentQ const& q1, SegmentQ const& q2, + IntersectionInfo const& inters, bool is_p_last, bool is_q_last, - RobustPolicy const& robust_policy, OutIt out) + OutIt out) { bool is_p_spike = ( Version == append_touches ? ( tp.operations[0].operation == operation_continue || tp.operations[0].operation == operation_intersection ) : true ) && ! is_p_last - && is_spike_p(side_calc, p1, p2, robust_policy); + && inters.is_spike_p(); bool is_q_spike = ( Version == append_touches ? ( tp.operations[1].operation == operation_continue || tp.operations[1].operation == operation_intersection ) : true ) && ! is_q_last - && is_spike_q(side_calc, q1, q2, robust_policy); + && inters.is_spike_q(); bool res = false; - if ( is_p_spike && ( Version == append_touches || result.template get<1>().arrival[0] == 1 ) ) + if ( is_p_spike && ( Version == append_touches || inters.d_info().arrival[0] == 1 ) ) { if ( Version == append_touches ) { @@ -481,12 +449,13 @@ struct get_turn_info_linear_linear //tp.operations[0].is_collinear = true; //tp.operations[1].is_collinear = true; - //tp.method = method_touch_interior; // only because arrival != 0 - BOOST_ASSERT(result.template get<0>().count > 1); - //geometry::convert(result.template get<0>().intersections[1], tp.point); - base_turn_handler::assign_point(tp, method_touch_interior, result.template get<0>(), 1); + BOOST_ASSERT(inters.i_info().count > 1); + + base_turn_handler::assign_point(tp, method_touch_interior, + inters.i_info(), 1); - AssignPolicy::apply(tp, p1.first, q1.first, result.template get<0>(), result.template get<1>()); + AssignPolicy::apply(tp, inters.pi(), inters.qi(), + inters.i_info(), inters.d_info()); } tp.operations[0].operation = operation_blocked; @@ -499,7 +468,7 @@ struct get_turn_info_linear_linear res = true; } - if ( is_q_spike && ( Version == append_touches || result.template get<1>().arrival[1] == 1 ) ) + if ( is_q_spike && ( Version == append_touches || inters.d_info().arrival[1] == 1 ) ) { if ( Version == append_touches ) { @@ -512,12 +481,12 @@ struct get_turn_info_linear_linear //tp.operations[0].is_collinear = true; //tp.operations[1].is_collinear = true; - //tp.method = method_touch_interior; // only because arrival != 0 - BOOST_ASSERT(result.template get<0>().count > 0); - //geometry::convert(result.template get<0>().intersections[0], tp.point); - base_turn_handler::assign_point(tp, method_touch_interior, result.template get<0>(), 0); + BOOST_ASSERT(inters.i_info().count > 0); - AssignPolicy::apply(tp, p1.first, q1.first, result.template get<0>(), result.template get<1>()); + base_turn_handler::assign_point(tp, method_touch_interior, inters.i_info(), 0); + + AssignPolicy::apply(tp, inters.pi(), inters.qi(), + inters.i_info(), inters.d_info()); } tp.operations[0].operation = operation_intersection; From edfb2c29c07faecb96f15ec3c596e2da7a33dfce Mon Sep 17 00:00:00 2001 From: Adam Wulkiewicz Date: Sat, 26 Apr 2014 03:21:10 +0200 Subject: [PATCH 2/3] [get_turns] Change parameters of intersection_info::is_spike_of_collinear() --- .../detail/overlay/get_turn_info_for_endpoint.hpp | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) 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 d75b2cc1d..5a7b5599b 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 @@ -93,8 +93,7 @@ public: { if ( qk_p1 == 0 ) { - return is_spike_of_collinear(segment_type1(pi(), pj()), - segment_type1(pj(), pk())); + return is_spike_of_collinear(pi(), pj(), pk()); } return true; @@ -115,8 +114,7 @@ public: { if ( pk_q1 == 0 ) { - return is_spike_of_collinear(segment_type2(qi(), qj()), - segment_type2(qj(), qk())); + return is_spike_of_collinear(qi(), qj(), qk()); } return true; @@ -128,10 +126,10 @@ public: private: template - inline bool is_spike_of_collinear( - model::referring_segment const& s1, - model::referring_segment const& s2) const + 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 @@ -139,7 +137,8 @@ private: typedef typename si::segment_intersection_strategy_type strategy; - typename strategy::return_type result = strategy::apply(s1, s2, m_robust_policy); + 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; } From b682b8996bc8ee5aa3b6065f94a26567070d7691 Mon Sep 17 00:00:00 2001 From: Adam Wulkiewicz Date: Sat, 26 Apr 2014 14:23:35 +0200 Subject: [PATCH 3/3] [test] Add intersection test for 1-3d boxes --- test/algorithms/intersection.cpp | 35 ++++++++++++++++++++++++++++++-- 1 file changed, 33 insertions(+), 2 deletions(-) diff --git a/test/algorithms/intersection.cpp b/test/algorithms/intersection.cpp index 19f403bc9..59f9eb672 100644 --- a/test/algorithms/intersection.cpp +++ b/test/algorithms/intersection.cpp @@ -335,7 +335,6 @@ void test_boxes(std::string const& wkt1, std::string const& wkt2, double expecte } } - template void test_point_output() { @@ -401,7 +400,6 @@ void test_areal_linear() } - template void test_all() { @@ -563,6 +561,37 @@ void test_rational() } +template +void test_boxes_per_d(P const& min1, P const& max1, P const& min2, P const& max2, bool expected_result) +{ + typedef bg::model::box

box; + + box box_out; + bool detected = bg::intersection(box(min1, max1), box(min2, max2), box_out); + + BOOST_CHECK_EQUAL(detected, expected_result); + if ( detected && expected_result ) + { + BOOST_CHECK( bg::equals(box_out, box(min2,max1)) ); + } +} + +template +void test_boxes_nd() +{ + typedef bg::model::point p1; + typedef bg::model::point p2; + typedef bg::model::point p3; + typedef bg::model::box b1; + typedef bg::model::box b2; + typedef bg::model::box b3; + + test_boxes_per_d(p1(0), p1(5), p1(3), p1(6), true); + test_boxes_per_d(p2(0,0), p2(5,5), p2(3,3), p2(6,6), true); + test_boxes_per_d(p3(0,0,0), p3(5,5,5), p3(3,3,3), p3(6,6,6), true); +} + + int test_main(int, char* []) { test_all >(); @@ -583,6 +612,8 @@ int test_main(int, char* []) test_rational > >(); #endif + test_boxes_nd(); + return 0; }