diff options
Diffstat (limited to 'boost/geometry/algorithms/detail/overlay/get_turn_info_la.hpp')
-rw-r--r-- | boost/geometry/algorithms/detail/overlay/get_turn_info_la.hpp | 195 |
1 files changed, 131 insertions, 64 deletions
diff --git a/boost/geometry/algorithms/detail/overlay/get_turn_info_la.hpp b/boost/geometry/algorithms/detail/overlay/get_turn_info_la.hpp index 873567bbf5..71946543ee 100644 --- a/boost/geometry/algorithms/detail/overlay/get_turn_info_la.hpp +++ b/boost/geometry/algorithms/detail/overlay/get_turn_info_la.hpp @@ -2,18 +2,20 @@ // Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. -// This file was modified by Oracle on 2013, 2014. -// Modifications copyright (c) 2013-2014 Oracle and/or its affiliates. +// This file was modified by Oracle on 2013, 2014, 2015. +// Modifications copyright (c) 2013-2015 Oracle and/or its affiliates. + +// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle // Use, modification and distribution is subject to the Boost Software License, // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) -// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle - #ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_GET_TURN_INFO_LA_HPP #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_GET_TURN_INFO_LA_HPP +#include <boost/geometry/util/condition.hpp> + #include <boost/geometry/algorithms/detail/overlay/get_turn_info.hpp> #include <boost/geometry/algorithms/detail/overlay/get_turn_info_for_endpoint.hpp> @@ -28,6 +30,8 @@ namespace detail { namespace overlay { template<typename AssignPolicy> struct get_turn_info_linear_areal { + // Currently only Linear spikes are handled + // Areal spikes are ignored static const bool handle_spikes = true; template @@ -122,7 +126,7 @@ struct get_turn_info_linear_areal calculate_spike_operation(tp.operations[0].operation, inters, is_p_last); - AssignPolicy::apply(tp, pi, qi, inters.i_info(), inters.d_info()); + AssignPolicy::apply(tp, pi, qi, inters); *out++ = tp; } @@ -135,7 +139,7 @@ struct get_turn_info_linear_areal replace_operations_i(tp.operations[0].operation, tp.operations[1].operation); - AssignPolicy::apply(tp, pi, qi, inters.i_info(), inters.d_info()); + AssignPolicy::apply(tp, pi, qi, inters); *out++ = tp; } break; @@ -220,9 +224,9 @@ struct get_turn_info_linear_areal inters, is_p_last); // TODO: move this into the append_xxx and call for each turn? - AssignPolicy::apply(tp, pi, qi, inters.i_info(), inters.d_info()); + AssignPolicy::apply(tp, pi, qi, inters); - if ( ! handle_spikes + if ( ! BOOST_GEOMETRY_CONDITION(handle_spikes) || ignore_spike || ! append_opposite_spikes<append_touches>( // for 'i' or 'c' i??? tp, inters, is_p_last, is_q_last, out) ) @@ -256,10 +260,10 @@ struct get_turn_info_linear_areal transformer(tp); // TODO: move this into the append_xxx and call for each turn? - AssignPolicy::apply(tp, pi, qi, inters.i_info(), inters.d_info()); + AssignPolicy::apply(tp, pi, qi, inters); // conditionally handle spikes - if ( ! handle_spikes + if ( ! BOOST_GEOMETRY_CONDITION(handle_spikes) || ! append_collinear_spikes(tp, inters, is_p_last, is_q_last, method_touch, append_equal, out) ) { @@ -273,7 +277,7 @@ struct get_turn_info_linear_areal TurnInfo, AssignPolicy >::apply(pi, qi, - tp, out, inters.i_info(), inters.d_info()); + tp, out, inters); } } } @@ -319,10 +323,10 @@ struct get_turn_info_linear_areal transformer(tp); // TODO: move this into the append_xxx and call for each turn? - AssignPolicy::apply(tp, pi, qi, inters.i_info(), inters.d_info()); + AssignPolicy::apply(tp, pi, qi, inters); // conditionally handle spikes - if ( ! handle_spikes + if ( ! BOOST_GEOMETRY_CONDITION(handle_spikes) || ! append_collinear_spikes(tp, inters, is_p_last, is_q_last, method_replace, version, out) ) { @@ -336,7 +340,7 @@ struct get_turn_info_linear_areal turn_transformer_ec<false> transformer(method_touch_interior); // conditionally handle spikes - if ( handle_spikes ) + if ( BOOST_GEOMETRY_CONDITION(handle_spikes) ) { append_opposite_spikes<append_collinear_opposite>( tp, inters, is_p_last, is_q_last, out); @@ -351,8 +355,9 @@ struct get_turn_info_linear_areal TurnInfo, AssignPolicy >::apply(pi, pj, pk, qi, qj, qk, - tp, out, inters.i_info(), inters.d_info(), - inters.sides(), transformer); + tp, out, inters, + inters.sides(), transformer, + !is_p_last, true); // qk is always valid } } } @@ -360,7 +365,7 @@ struct get_turn_info_linear_areal case '0' : { // degenerate points - if (AssignPolicy::include_degenerate) + if ( BOOST_GEOMETRY_CONDITION(AssignPolicy::include_degenerate) ) { only_convert::apply(tp, inters.i_info()); @@ -376,7 +381,7 @@ struct get_turn_info_linear_areal } // tp.operations[1].position = position_middle; - AssignPolicy::apply(tp, pi, qi, inters.i_info(), inters.d_info()); + AssignPolicy::apply(tp, pi, qi, inters); *out++ = tp; } } @@ -408,20 +413,37 @@ struct get_turn_info_linear_areal if ( is_p_spike ) { - bool going_in = false, going_out = false; - int const pk_q1 = inters.sides().pk_wrt_q1(); - int const pk_q2 = inters.sides().pk_wrt_q2(); + + bool going_in = pk_q1 < 0; // Pk on the right + bool going_out = pk_q1 > 0; // Pk on the left - if ( inters.sides().qk_wrt_q1() <= 0 ) // Q turning R or C + int const qk_q1 = inters.sides().qk_wrt_q1(); + + // special cases + if ( qk_q1 < 0 ) // Q turning R { - going_in = pk_q1 < 0 && pk_q2 < 0; // Pk on the right of both - going_out = pk_q1 > 0 || pk_q2 > 0; // Pk on the left of one of them + // spike on the edge point + // if it's already known that the spike is going out this musn't be checked + if ( ! going_out + && equals::equals_point_point(inters.rpj(), inters.rqj()) ) + { + int const pk_q2 = inters.sides().pk_wrt_q2(); + going_in = pk_q1 < 0 && pk_q2 < 0; // Pk on the right of both + going_out = pk_q1 > 0 || pk_q2 > 0; // Pk on the left of one of them + } } - else + else if ( qk_q1 > 0 ) // Q turning L { - going_in = pk_q1 < 0 || pk_q2 < 0; // Pk on the right of one of them - going_out = pk_q1 > 0 && pk_q2 > 0; // Pk on the left of both + // spike on the edge point + // if it's already known that the spike is going in this musn't be checked + if ( ! going_in + && equals::equals_point_point(inters.rpj(), inters.rqj()) ) + { + int const pk_q2 = inters.sides().pk_wrt_q2(); + going_in = pk_q1 < 0 || pk_q2 < 0; // Pk on the right of one of them + going_out = pk_q1 > 0 && pk_q2 > 0; // Pk on the left of both + } } if ( going_in ) @@ -461,10 +483,16 @@ struct get_turn_info_linear_areal && 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 - && inters.is_spike_q();*/ + /*bool is_q_spike = tp.operations[1].operation == operation_continue + && inters.is_spike_q(); + // both are collinear spikes on the same IP, we can just follow both + if ( is_p_spike && is_q_spike ) + { + return false; + } + // spike on Linear - it's turning back on the boundary of Areal + else*/ if ( is_p_spike ) { tp.method = method; @@ -477,7 +505,18 @@ struct get_turn_info_linear_areal return true; } - + // spike on Areal - Linear is going outside + /*else if ( is_q_spike ) + { + tp.method = method; + tp.operations[0].operation = operation_union; + tp.operations[1].operation = operation_continue; + *out++ = tp; + *out++ = tp; + + return true; + }*/ + return false; } @@ -492,48 +531,71 @@ struct get_turn_info_linear_areal bool is_p_last, bool /*is_q_last*/, OutIt out) { - bool is_p_spike = ( Version == append_touches ? + static const bool is_version_touches = (Version == append_touches); + + bool is_p_spike = ( is_version_touches ? ( tp.operations[0].operation == operation_continue || tp.operations[0].operation == operation_intersection ) : // i ??? true ) && ! is_p_last && 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 - && inters.is_spike_q();*/ + /*bool is_q_spike = ( ( Version == append_touches + && tp.operations[1].operation == operation_continue ) + || ( Version == append_collinear_opposite + && tp.operations[1].operation == operation_none ) ) + && inters.is_spike_q(); - if ( is_p_spike && ( Version == append_touches || inters.d_info().arrival[0] == 1 ) ) + if ( is_p_spike && is_q_spike ) { - if ( Version == append_touches ) - { - tp.operations[0].is_collinear = true; - //tp.operations[1].is_collinear = false; - tp.method = method_touch; - } - else + // u/u or nothing? + return false; + } + else*/ + if ( is_p_spike ) + { + if ( BOOST_GEOMETRY_CONDITION(is_version_touches) + || inters.d_info().arrival[0] == 1 ) { - tp.operations[0].is_collinear = true; - //tp.operations[1].is_collinear = false; - - BOOST_ASSERT(inters.i_info().count > 1); - base_turn_handler::assign_point(tp, method_touch_interior, inters.i_info(), 1); + if ( BOOST_GEOMETRY_CONDITION(is_version_touches) ) + { + tp.operations[0].is_collinear = true; + //tp.operations[1].is_collinear = false; + tp.method = method_touch; + } + else + { + tp.operations[0].is_collinear = true; + //tp.operations[1].is_collinear = false; - AssignPolicy::apply(tp, inters.pi(), inters.qi(), inters.i_info(), inters.d_info()); - } + BOOST_ASSERT(inters.i_info().count > 1); + base_turn_handler::assign_point(tp, method_touch_interior, inters.i_info(), 1); - tp.operations[0].operation = operation_blocked; + AssignPolicy::apply(tp, inters.pi(), inters.qi(), inters); + } + + tp.operations[0].operation = operation_blocked; + tp.operations[1].operation = operation_continue; // boundary + *out++ = tp; + tp.operations[0].operation = operation_continue; // boundary + //tp.operations[1].operation = operation_continue; // boundary + *out++ = tp; + + return true; + } + } + /*else if ( is_q_spike ) + { + tp.operations[0].is_collinear = true; + tp.method = is_version_touches ? method_touch : method_touch_interior; + tp.operations[0].operation = operation_continue; tp.operations[1].operation = operation_continue; // boundary *out++ = tp; - tp.operations[0].operation = operation_continue; // boundary - //tp.operations[1].operation = operation_continue; // boundary *out++ = tp; return true; - } + }*/ return false; } @@ -587,7 +649,7 @@ struct get_turn_info_linear_areal operation_type & op1 = turn.operations[1].operation; // NOTE: probably only if methods are WRT IPs, not segments! - if ( IsFront + if ( BOOST_GEOMETRY_CONDITION(IsFront) || op0 == operation_intersection || op0 == operation_union || op1 == operation_intersection || op1 == operation_union ) { @@ -666,7 +728,9 @@ struct get_turn_info_linear_areal // ANALYSE AND ASSIGN FIRST // IP on the first point of Linear Geometry - if ( EnableFirst && is_p_first && ip0.is_pi && !ip0.is_qi ) // !q0i prevents duplication + bool was_first_point_handled = false; + if ( BOOST_GEOMETRY_CONDITION(EnableFirst) + && is_p_first && ip0.is_pi && !ip0.is_qi ) // !q0i prevents duplication { TurnInfo tp = tp_model; tp.operations[0].position = position_front; @@ -735,14 +799,16 @@ struct get_turn_info_linear_areal // here is_p_first_ip == true tp.operations[0].is_collinear = false; - AssignPolicy::apply(tp, pi, qi, inters.i_info(), inters.d_info()); + AssignPolicy::apply(tp, pi, qi, inters); *out++ = tp; + + was_first_point_handled = true; } // ANALYSE AND ASSIGN LAST // IP on the last point of Linear Geometry - if ( EnableLast + if ( BOOST_GEOMETRY_CONDITION(EnableLast) && is_p_last && ( ip_count > 1 ? (ip1.is_pj && !ip1.is_qi) : (ip0.is_pj && !ip0.is_qi) ) ) // prevents duplication { @@ -783,13 +849,14 @@ struct get_turn_info_linear_areal // equals<> or collinear<> will assign the second point, // we'd like to assign the first one - int ip_index = ip_count > 1 ? 1 : 0; + unsigned int ip_index = ip_count > 1 ? 1 : 0; base_turn_handler::assign_point(tp, tp.method, inters.i_info(), ip_index); - AssignPolicy::apply(tp, pi, qi, inters.i_info(), inters.d_info()); + AssignPolicy::apply(tp, pi, qi, inters); *out++ = tp; - return true; + // don't ignore the first IP if the segment is opposite + return !( opposite && ip_count > 1 ) || was_first_point_handled; } // don't ignore anything for now |