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..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 @@ -38,96 +38,115 @@ 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(pi(), 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(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; + } + + result_type m_result; + side_calculator_type m_side_calc; + RobustPolicy const& m_robust_policy; +}; // SEGMENT_INTERSECTION RESULT @@ -335,8 +354,7 @@ struct get_turn_info_for_endpoint template static inline bool apply(Point1 const& pi, Point1 const& pj, Point1 const& pk, @@ -344,12 +362,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 +378,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 +399,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 +410,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 +419,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 +450,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 +473,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 +513,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; 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; }