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 61aa73bd6..8a6c481d3 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 @@ -166,7 +166,7 @@ struct get_turn_info_linear_areal equal::apply(pi, pj, pk, qi, qj, qk, tp, result.template get<0>(), result.template get<1>(), side_calc); - replacer_of_method_and_operations_ec replacer(method_touch); + replacer_of_method_and_operations_ec replacer(method_touch); replacer(tp.method, tp.operations[0].operation, tp.operations[1].operation); AssignPolicy::apply(tp, pi, qi, result.template get<0>(), result.template get<1>()); @@ -201,7 +201,7 @@ struct get_turn_info_linear_areal equal::apply(pi, pj, pk, qi, qj, qk, tp, result.template get<0>(), result.template get<1>(), side_calc); - replacer_of_method_and_operations_ec replacer(method_touch); + replacer_of_method_and_operations_ec replacer(method_touch); replacer(tp.method, tp.operations[0].operation, tp.operations[1].operation); } else @@ -209,7 +209,7 @@ struct get_turn_info_linear_areal collinear::apply(pi, pj, pk, qi, qj, qk, tp, result.template get<0>(), result.template get<1>(), side_calc); - replacer_of_method_and_operations_ec replacer(method_touch_interior); + replacer_of_method_and_operations_ec replacer(method_touch_interior); replacer(tp.method, tp.operations[0].operation, tp.operations[1].operation); } @@ -218,8 +218,8 @@ struct get_turn_info_linear_areal } else { - // If this always 'm' ? - replacer_of_method_and_operations_ec replacer(method_touch_interior); + // Is this always 'm' ? + replacer_of_method_and_operations_ec replacer(method_touch_interior); collinear_opposite < @@ -274,6 +274,7 @@ struct get_turn_info_linear_areal op1 = operation_union; } + template class replacer_of_method_and_operations_ec { public: @@ -286,8 +287,9 @@ struct get_turn_info_linear_areal operation_type & op1) const { // NOTE: probably only if methods are WRT IPs, not segments! - if ( op0 == operation_intersection || op0 == operation_union - || op1 == operation_intersection || op1 == operation_union ) + if ( IsFront + || op0 == operation_intersection || op0 == operation_union + || op1 == operation_intersection || op1 == operation_union ) { method = m_method; } @@ -331,19 +333,19 @@ struct get_turn_info_linear_areal namespace ov = overlay; typedef ov::get_turn_info_for_endpoint get_info_e; - std::size_t ip_count = result.template get<0>().count; + const std::size_t ip_count = result.template get<0>().count; // no intersection points if ( ip_count == 0 ) return false; - int segment_index0 = tp_model.operations[0].seg_id.segment_index; - int segment_index1 = tp_model.operations[1].seg_id.segment_index; + const int segment_index0 = tp_model.operations[0].seg_id.segment_index; + const int segment_index1 = tp_model.operations[1].seg_id.segment_index; BOOST_ASSERT(segment_index0 >= 0 && segment_index1 >= 0); - bool is_p_first = segment_index0 == 0; - bool is_q_first = segment_index1 == 0; // not used - bool is_p_last = static_cast(segment_index0) + 1 == p_segments_count; - bool is_q_last = static_cast(segment_index1) + 1 == q_segments_count; // not used + const bool is_p_first = segment_index0 == 0; + const bool is_q_first = segment_index1 == 0; // not used + const bool is_p_last = static_cast(segment_index0) + 1 == p_segments_count; + const bool is_q_last = static_cast(segment_index1) + 1 == q_segments_count; // not used if ( !is_p_first && !is_p_last ) return false; @@ -355,14 +357,14 @@ struct get_turn_info_linear_areal bool p0i, p0j, q0i, q0j; // assign false? bool p1i, p1j, q1i, q1j; // assign false? - bool opposite = result.template get<1>().opposite; - bool same_dirs = result.template get<1>().dir_a == 0 && result.template get<1>().dir_b == 0; + const bool opposite = result.template get<1>().opposite; + const bool same_dirs = result.template get<1>().dir_a == 0 && result.template get<1>().dir_b == 0; { - int p_how = result.template get<1>().how_a; - int q_how = result.template get<1>().how_b; - int p_arrival = result.template get<1>().arrival[0]; - int q_arrival = result.template get<1>().arrival[1]; + const int p_how = result.template get<1>().how_a; + const int q_how = result.template get<1>().how_b; + const int p_arrival = result.template get<1>().arrival[0]; + const int q_arrival = result.template get<1>().arrival[1]; get_info_e::handle_segment( is_p_first, is_p_last, p_how, p_arrival, @@ -420,7 +422,7 @@ struct get_turn_info_linear_areal tp, result.template get<0>(), result.template get<1>(), side_calc); } - replacer_of_method_and_operations_ec replacer(replaced_method); + replacer_of_method_and_operations_ec replacer(replaced_method); replacer(tp.method, tp.operations[0].operation, tp.operations[1].operation); // equals<> or collinear<> will assign the second point, @@ -434,10 +436,10 @@ struct get_turn_info_linear_areal // ANALYSE AND ASSIGN LAST // IP on the first point of Linear Geometry - if ( EnableLast && is_p_last && p0j && !q0i ) // !q0i prevents duplication + if ( EnableLast && is_p_last && ( ip_count > 1 ? p1j : p0j ) && !q0i && !q1i ) // !q0i && !q1i prevents duplication { TurnInfo tp = tp_model; - tp.method = q0j ? method_touch : method_touch_interior; + tp.method = ( ip_count > 1 ? q1j : q0j ) ? method_touch : method_touch_interior; tp.operations[0].operation = operation_blocked; tp.operations[1].operation = operation_union; tp.operations[0].position = position_back; @@ -445,7 +447,8 @@ struct get_turn_info_linear_areal // equals<> or collinear<> will assign the second point, // we'd like to assign the first one - geometry::convert(result.template get<0>().intersections[0], tp.point); + std::size_t ip_index = ip_count > 1 ? 1 : 0; + geometry::convert(result.template get<0>().intersections[ip_index], tp.point); AssignPolicy::apply(tp, pi, qi, result.template get<0>(), result.template get<1>()); *out++ = tp; diff --git a/test/algorithms/overlay/get_turns_linear_areal.cpp b/test/algorithms/overlay/get_turns_linear_areal.cpp index a88fe0a14..a3ba4befa 100644 --- a/test/algorithms/overlay/get_turns_linear_areal.cpp +++ b/test/algorithms/overlay/get_turns_linear_areal.cpp @@ -32,6 +32,24 @@ void test_all() typedef bg::model::linestring ls; typedef bg::model::polygon poly; + test_geometry("LINESTRING(15 5,24 5,20 2,19 0,13 -4,1 0,10 0,13 3,15 7,16 10,10 10,8 10,4 6,2 8,1 10)", + "POLYGON((0 0,5 5,0 10,20 10,20 2,19 0,0 0)(10 3,15 3,15 7,10 7,10 3))", + expected("miu")("iuu")("tcu")("tuu")("mcu")("miu")("muu")("tiu")("mcu")("miu")("mcu")("miu")("mxu").vec); + + test_geometry("LINESTRING(5 0,5 5,10 5)", "POLYGON((0 0,0 10,10 10,10 0,0 0))", + "miu", "mxu"); + test_geometry("LINESTRING(0 0,5 5,10 0)", "POLYGON((0 0,0 10,10 10,10 0,0 0))", + "tiu", "txu"); + test_geometry("LINESTRING(0 0,5 0,5 5,10 5,10 0)", "POLYGON((0 0,0 10,10 10,10 0,0 0))", + expected("tcu")("miu")("mcu")("txu").vec); + test_geometry("LINESTRING(10 0,5 0,5 5,10 5,10 10)", "POLYGON((0 0,0 10,10 10,10 0,0 0))", + expected("tcu")("miu")("mcu")("txu").vec); + + test_geometry("LINESTRING(0 0,10 0,10 10)", + "POLYGON((0 0,5 5,0 10,20 10,20 2,19 0,0 0)(10 3,15 3,15 7,10 7,10 3))", + expected("tcu")("miu")("mcu")("miu")("mxu").vec); + + to_svg("LINESTRING(15 5,24 5,20 2,19 0,13 -4,1 0,10 0,13 3,15 7,16 10,10 10,8 10,4 6,2 8,1 10)", "POLYGON((0 0,5 5,0 10,20 10,20 2,19 0,0 0)(10 3,15 3,15 7,10 7,10 3))", "ls_poly1.svg");