From 28cf857743a0e58d82c2038a3dda35469c697af6 Mon Sep 17 00:00:00 2001 From: Barend Gehrels Date: Wed, 28 Jan 2015 11:26:41 +0100 Subject: [PATCH 01/23] [buffer] pass turn instead of piece to analysis to be able to use the robust segments it is calculated from (in a later commit) --- .../buffer/buffered_piece_collection.hpp | 1 + .../detail/buffer/turn_in_piece_visitor.hpp | 22 ++++++++++--------- 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/include/boost/geometry/algorithms/detail/buffer/buffered_piece_collection.hpp b/include/boost/geometry/algorithms/detail/buffer/buffered_piece_collection.hpp index 368215537..9a3ad2096 100644 --- a/include/boost/geometry/algorithms/detail/buffer/buffered_piece_collection.hpp +++ b/include/boost/geometry/algorithms/detail/buffer/buffered_piece_collection.hpp @@ -199,6 +199,7 @@ struct buffered_piece_collection std::vector robust_turns; // Used only in insert_rescaled_piece_turns - we might use a map instead typedef robust_ring_type piece_robust_ring_type; + typedef robust_point_type piece_robust_point_type; }; struct robust_original diff --git a/include/boost/geometry/algorithms/detail/buffer/turn_in_piece_visitor.hpp b/include/boost/geometry/algorithms/detail/buffer/turn_in_piece_visitor.hpp index d8344ba75..7cda98895 100644 --- a/include/boost/geometry/algorithms/detail/buffer/turn_in_piece_visitor.hpp +++ b/include/boost/geometry/algorithms/detail/buffer/turn_in_piece_visitor.hpp @@ -331,16 +331,18 @@ class analyse_turn_wrt_piece } public : - template - static inline analyse_result apply(Point const& point, Piece const& piece) + template + static inline analyse_result apply(Turn const& turn, Piece const& piece) { + typedef typename Piece::piece_robust_point_type point_type; + const point_type& point = turn.robust_point; analyse_result code = check_helper_segments(point, piece); if (code != analyse_continue) { return code; } - geometry::equal_to comparator; + geometry::equal_to comparator; if (piece.offsetted_count > 8) { @@ -349,22 +351,22 @@ public : // We try it only once. if (piece.is_monotonic_increasing[0]) { - code = check_monotonic(point, piece, geometry::less()); + code = check_monotonic(point, piece, geometry::less()); if (code != analyse_continue) return code; } else if (piece.is_monotonic_increasing[1]) { - code = check_monotonic(point, piece, geometry::less()); + code = check_monotonic(point, piece, geometry::less()); if (code != analyse_continue) return code; } else if (piece.is_monotonic_decreasing[0]) { - code = check_monotonic(point, piece, geometry::greater()); + code = check_monotonic(point, piece, geometry::greater()); if (code != analyse_continue) return code; } else if (piece.is_monotonic_decreasing[1]) { - code = check_monotonic(point, piece, geometry::greater()); + code = check_monotonic(point, piece, geometry::greater()); if (code != analyse_continue) return code; } } @@ -374,8 +376,8 @@ public : for (int i = 1; i < piece.offsetted_count; i++) { - Point const& previous = piece.robust_ring[i - 1]; - Point const& current = piece.robust_ring[i]; + point_type const& previous = piece.robust_ring[i - 1]; + point_type const& current = piece.robust_ring[i]; // The robust ring can contain duplicates // (on which any side or side-value would return 0) @@ -460,7 +462,7 @@ public: // TODO: mutable_piece to make some on-demand preparations in analyse analyse_result analyse_code - = analyse_turn_wrt_piece::apply(turn.robust_point, piece); + = analyse_turn_wrt_piece::apply(turn, piece); Turn& mutable_turn = m_turns[turn.turn_index]; switch(analyse_code) From a44c7536129129349782d3832ae1edbfb881add4 Mon Sep 17 00:00:00 2001 From: Barend Gehrels Date: Wed, 28 Jan 2015 13:30:42 +0100 Subject: [PATCH 02/23] [overlay] replace intersection_info (old) with (new) to allow getting access to (robust) points used for the segment intersection. This makes dir_info redundant there, because it is included in (new) --- .../detail/disjoint/linear_linear.hpp | 5 +- .../detail/overlay/get_turn_info.hpp | 65 +++++++++---------- .../overlay/get_turn_info_for_endpoint.hpp | 4 +- .../detail/overlay/get_turn_info_la.hpp | 22 +++---- .../detail/overlay/get_turn_info_ll.hpp | 22 +++---- .../detail/overlay/linear_linear.hpp | 5 +- .../test_get_turns_ll_invariance.hpp | 5 +- 7 files changed, 59 insertions(+), 69 deletions(-) diff --git a/include/boost/geometry/algorithms/detail/disjoint/linear_linear.hpp b/include/boost/geometry/algorithms/detail/disjoint/linear_linear.hpp index e569d9b54..91f985edb 100644 --- a/include/boost/geometry/algorithms/detail/disjoint/linear_linear.hpp +++ b/include/boost/geometry/algorithms/detail/disjoint/linear_linear.hpp @@ -98,11 +98,10 @@ struct assign_disjoint_policy typename Info, typename Point1, typename Point2, - typename IntersectionInfo, - typename DirInfo + typename IntersectionInfo > static inline void apply(Info& , Point1 const& , Point2 const&, - IntersectionInfo const&, DirInfo const&) + IntersectionInfo const&) {} }; diff --git a/include/boost/geometry/algorithms/detail/overlay/get_turn_info.hpp b/include/boost/geometry/algorithms/detail/overlay/get_turn_info.hpp index 240b6de03..0a7f53279 100644 --- a/include/boost/geometry/algorithms/detail/overlay/get_turn_info.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/get_turn_info.hpp @@ -503,14 +503,12 @@ struct equal_opposite : public base_turn_handler typename Point1, typename Point2, typename OutputIterator, - typename IntersectionInfo, - typename DirInfo + typename IntersectionInfo > static inline void apply(Point1 const& pi, Point2 const& qi, /* by value: */ TurnInfo tp, OutputIterator& out, - IntersectionInfo const& intersection_info, - DirInfo const& dir_info) + IntersectionInfo const& intersection_info) { // For equal-opposite segments, normally don't do anything. if (AssignPolicy::include_opposite) @@ -520,10 +518,10 @@ struct equal_opposite : public base_turn_handler { tp.operations[i].operation = operation_opposite; } - for (unsigned int i = 0; i < intersection_info.count; i++) + for (unsigned int i = 0; i < intersection_info.i_info().count; i++) { - assign_point(tp, method_none, intersection_info, i); - AssignPolicy::apply(tp, pi, qi, intersection_info, dir_info); + assign_point(tp, method_none, intersection_info.i_info(), i); + AssignPolicy::apply(tp, pi, qi, intersection_info); *out++ = tp; } } @@ -715,7 +713,6 @@ public: typename Point2, typename OutputIterator, typename IntersectionInfo, - typename DirInfo, typename SidePolicy > static inline void apply( @@ -727,10 +724,9 @@ public: OutputIterator& out, IntersectionInfo const& intersection_info, - DirInfo const& dir_info, SidePolicy const& side) { - apply(pi, pj, pk, qi, qj, qk, tp_model, out, intersection_info, dir_info, side, empty_transformer); + apply(pi, pj, pk, qi, qj, qk, tp_model, out, intersection_info, side, empty_transformer); } public: @@ -740,7 +736,6 @@ public: typename Point2, typename OutputIterator, typename IntersectionInfo, - typename DirInfo, typename SidePolicy, typename TurnTransformer > @@ -752,8 +747,7 @@ public: TurnInfo const& tp_model, OutputIterator& out, - IntersectionInfo const& intersection_info, - DirInfo const& dir_info, + IntersectionInfo const& info, SidePolicy const& side, TurnTransformer turn_transformer, bool const is_pk_valid = true, bool const is_qk_valid = true) @@ -761,41 +755,41 @@ public: TurnInfo tp = tp_model; // If P arrives within Q, there is a turn dependent on P - if ( dir_info.arrival[0] == 1 + if ( info.d_info().arrival[0] == 1 && is_pk_valid - && set_tp<0>(pi, pj, pk, side.pk_wrt_p1(), true, qi, qj, side.pk_wrt_q1(), tp, intersection_info) ) + && set_tp<0>(pi, pj, pk, side.pk_wrt_p1(), true, qi, qj, side.pk_wrt_q1(), tp, info.i_info()) ) { turn_transformer(tp); - AssignPolicy::apply(tp, pi, qi, intersection_info, dir_info); + AssignPolicy::apply(tp, pi, qi, info); *out++ = tp; } // If Q arrives within P, there is a turn dependent on Q - if ( dir_info.arrival[1] == 1 + if ( info.d_info().arrival[1] == 1 && is_qk_valid - && set_tp<1>(qi, qj, qk, side.qk_wrt_q1(), false, pi, pj, side.qk_wrt_p1(), tp, intersection_info) ) + && set_tp<1>(qi, qj, qk, side.qk_wrt_q1(), false, pi, pj, side.qk_wrt_p1(), tp, info.i_info()) ) { turn_transformer(tp); - AssignPolicy::apply(tp, pi, qi, intersection_info, dir_info); + AssignPolicy::apply(tp, pi, qi, info); *out++ = tp; } if (AssignPolicy::include_opposite) { // Handle cases not yet handled above - if ((dir_info.arrival[1] == -1 && dir_info.arrival[0] == 0) - || (dir_info.arrival[0] == -1 && dir_info.arrival[1] == 0)) + if ((info.d_info().arrival[1] == -1 && info.d_info().arrival[0] == 0) + || (info.d_info().arrival[0] == -1 && info.d_info().arrival[1] == 0)) { for (int i = 0; i < 2; i++) { tp.operations[i].operation = operation_opposite; } - for (unsigned int i = 0; i < intersection_info.count; i++) + for (unsigned int i = 0; i < info.i_info().count; i++) { - assign_point(tp, method_collinear, intersection_info, i); - AssignPolicy::apply(tp, pi, qi, intersection_info, dir_info); + assign_point(tp, method_collinear, info.i_info(), i); + AssignPolicy::apply(tp, pi, qi, info); *out++ = tp; } } @@ -867,10 +861,9 @@ struct assign_null_policy typename Info, typename Point1, typename Point2, - typename IntersectionInfo, - typename DirInfo + typename IntersectionInfo > - static inline void apply(Info& , Point1 const& , Point2 const&, IntersectionInfo const&, DirInfo const&) + static inline void apply(Info& , Point1 const& , Point2 const&, IntersectionInfo const&) {} }; @@ -933,7 +926,7 @@ struct get_turn_info && inters.i_info().count > 0) { only_convert::apply(tp, inters.i_info()); - AssignPolicy::apply(tp, pi, qi, inters.i_info(), inters.d_info()); + AssignPolicy::apply(tp, pi, qi, inters); *out++ = tp; } break; @@ -968,7 +961,7 @@ struct get_turn_info tp, inters.i_info(), inters.d_info(), swapped_side_calc); } - AssignPolicy::apply(tp, pi, qi, inters.i_info(), inters.d_info()); + AssignPolicy::apply(tp, pi, qi, inters); *out++ = tp; } break; @@ -976,7 +969,7 @@ struct get_turn_info { crosses::apply(pi, pj, pk, qi, qj, qk, tp, inters.i_info(), inters.d_info()); - AssignPolicy::apply(tp, pi, qi, inters.i_info(), inters.d_info()); + AssignPolicy::apply(tp, pi, qi, inters); *out++ = tp; } break; @@ -985,7 +978,7 @@ struct get_turn_info // Both touch (both arrive there) touch::apply(pi, pj, pk, qi, qj, qk, tp, inters.i_info(), inters.d_info(), inters.sides()); - AssignPolicy::apply(tp, pi, qi, inters.i_info(), inters.d_info()); + AssignPolicy::apply(tp, pi, qi, inters); *out++ = tp; } break; @@ -997,7 +990,7 @@ struct get_turn_info // or collinear-and-ending at intersection point equal::apply(pi, pj, pk, qi, qj, qk, tp, inters.i_info(), inters.d_info(), inters.sides()); - AssignPolicy::apply(tp, pi, qi, inters.i_info(), inters.d_info()); + AssignPolicy::apply(tp, pi, qi, inters); *out++ = tp; } else @@ -1007,7 +1000,7 @@ struct get_turn_info TurnInfo, AssignPolicy >::apply(pi, qi, - tp, out, inters.i_info(), inters.d_info()); + tp, out, inters); } } break; @@ -1032,7 +1025,7 @@ struct get_turn_info tp, inters.i_info(), inters.d_info(), inters.sides()); } - AssignPolicy::apply(tp, pi, qi, inters.i_info(), inters.d_info()); + AssignPolicy::apply(tp, pi, qi, inters); *out++ = tp; } else @@ -1042,7 +1035,7 @@ struct get_turn_info TurnInfo, AssignPolicy >::apply(pi, pj, pk, qi, qj, qk, - tp, out, inters.i_info(), inters.d_info(), inters.sides()); + tp, out, inters, inters.sides()); } } break; @@ -1052,7 +1045,7 @@ struct get_turn_info if (AssignPolicy::include_degenerate) { only_convert::apply(tp, inters.i_info()); - AssignPolicy::apply(tp, pi, qi, inters.i_info(), inters.d_info()); + AssignPolicy::apply(tp, pi, qi, inters); *out++ = tp; } } diff --git a/include/boost/geometry/algorithms/detail/overlay/get_turn_info_for_endpoint.hpp b/include/boost/geometry/algorithms/detail/overlay/get_turn_info_for_endpoint.hpp index ca1b9d9d0..b4af0b416 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 @@ -585,7 +585,9 @@ struct get_turn_info_for_endpoint } } - AssignPolicy::apply(tp, pi, qi, result.template get<0>(), result.template get<1>()); + // TODO: this should get an intersection_info, which is unavailable here + // Because the assign_null policy accepts any structure, we pass the result instead for now + AssignPolicy::apply(tp, pi, qi, result); *out++ = tp; } 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 efe996fc0..d314ccbbc 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 @@ -124,7 +124,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; } @@ -137,7 +137,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; @@ -222,7 +222,7 @@ 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 || ignore_spike @@ -258,7 +258,7 @@ 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 @@ -275,7 +275,7 @@ struct get_turn_info_linear_areal TurnInfo, AssignPolicy >::apply(pi, qi, - tp, out, inters.i_info(), inters.d_info()); + tp, out, inters); } } } @@ -321,7 +321,7 @@ 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 @@ -353,7 +353,7 @@ struct get_turn_info_linear_areal TurnInfo, AssignPolicy >::apply(pi, pj, pk, qi, qj, qk, - tp, out, inters.i_info(), inters.d_info(), + tp, out, inters, inters.sides(), transformer, !is_p_last, true); // qk is always valid } @@ -379,7 +379,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; } } @@ -567,7 +567,7 @@ struct get_turn_info_linear_areal BOOST_ASSERT(inters.i_info().count > 1); base_turn_handler::assign_point(tp, method_touch_interior, inters.i_info(), 1); - AssignPolicy::apply(tp, inters.pi(), inters.qi(), inters.i_info(), inters.d_info()); + AssignPolicy::apply(tp, inters.pi(), inters.qi(), inters); } tp.operations[0].operation = operation_blocked; @@ -793,7 +793,7 @@ 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; @@ -846,7 +846,7 @@ struct get_turn_info_linear_areal 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; // don't ignore the first IP if the segment is opposite 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 4f0384877..57542ce64 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 @@ -120,7 +120,7 @@ struct get_turn_info_linear_linear 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; } } @@ -132,7 +132,7 @@ struct get_turn_info_linear_linear 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; @@ -260,7 +260,7 @@ 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, inters.i_info(), inters.d_info()); + AssignPolicy::apply(tp, pi, qi, inters); if ( ! handle_spikes || ! append_opposite_spikes(tp, inters, @@ -298,7 +298,7 @@ struct get_turn_info_linear_linear 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 @@ -318,7 +318,7 @@ struct get_turn_info_linear_linear < TurnInfo, AssignPolicy - >::apply(pi, qi, tp, out, inters.i_info(), inters.d_info()); + >::apply(pi, qi, tp, out, inters); } } } @@ -367,7 +367,7 @@ struct get_turn_info_linear_linear 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 @@ -402,7 +402,7 @@ struct get_turn_info_linear_linear TurnInfo, AssignPolicy >::apply(pi, pj, pk, qi, qj, qk, - tp, out, inters.i_info(), inters.d_info(), inters.sides(), + tp, out, inters, inters.sides(), transformer, !is_p_last, !is_q_last); } } @@ -437,7 +437,7 @@ struct get_turn_info_linear_linear tp.operations[1].position = position_back; } - AssignPolicy::apply(tp, pi, qi, inters.i_info(), inters.d_info()); + AssignPolicy::apply(tp, pi, qi, inters); *out++ = tp; } } @@ -560,8 +560,7 @@ struct get_turn_info_linear_linear base_turn_handler::assign_point(tp, method_touch_interior, inters.i_info(), 1); - AssignPolicy::apply(tp, inters.pi(), inters.qi(), - inters.i_info(), inters.d_info()); + AssignPolicy::apply(tp, inters.pi(), inters.qi(), inters); } tp.operations[0].operation = operation_blocked; @@ -591,8 +590,7 @@ struct get_turn_info_linear_linear 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()); + AssignPolicy::apply(tp, inters.pi(), inters.qi(), inters); } tp.operations[0].operation = operation_intersection; diff --git a/include/boost/geometry/algorithms/detail/overlay/linear_linear.hpp b/include/boost/geometry/algorithms/detail/overlay/linear_linear.hpp index 3a7a7a7f3..d4ebcf296 100644 --- a/include/boost/geometry/algorithms/detail/overlay/linear_linear.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/linear_linear.hpp @@ -144,11 +144,10 @@ protected: typename Info, typename Point1, typename Point2, - typename IntersectionInfo, - typename DirInfo + typename IntersectionInfo > static inline void apply(Info& , Point1 const& , Point2 const& , - IntersectionInfo const& , DirInfo const& ) + IntersectionInfo const& ) { } }; diff --git a/test/algorithms/set_operations/test_get_turns_ll_invariance.hpp b/test/algorithms/set_operations/test_get_turns_ll_invariance.hpp index c0a59c1c4..3e9bb6051 100644 --- a/test/algorithms/set_operations/test_get_turns_ll_invariance.hpp +++ b/test/algorithms/set_operations/test_get_turns_ll_invariance.hpp @@ -44,11 +44,10 @@ private: typename Info, typename Point1, typename Point2, - typename IntersectionInfo, - typename DirInfo + typename IntersectionInfo > static inline void apply(Info& , Point1 const& , Point2 const& , - IntersectionInfo const& , DirInfo const& ) + IntersectionInfo const&) { } }; From f056a0bb54be76a9e74d1e7fe7b447c33abcbf94 Mon Sep 17 00:00:00 2001 From: Barend Gehrels Date: Wed, 28 Jan 2015 13:38:12 +0100 Subject: [PATCH 03/23] [overlay] minor change: replace now longer expressions with p_arrival, q_arrival to enhance readability --- .../algorithms/detail/overlay/get_turn_info.hpp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/include/boost/geometry/algorithms/detail/overlay/get_turn_info.hpp b/include/boost/geometry/algorithms/detail/overlay/get_turn_info.hpp index 0a7f53279..82de1a1c4 100644 --- a/include/boost/geometry/algorithms/detail/overlay/get_turn_info.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/get_turn_info.hpp @@ -754,8 +754,11 @@ public: { TurnInfo tp = tp_model; + int const p_arrival = info.d_info().arrival[0]; + int const q_arrival = info.d_info().arrival[1]; + // If P arrives within Q, there is a turn dependent on P - if ( info.d_info().arrival[0] == 1 + if ( p_arrival == 1 && is_pk_valid && set_tp<0>(pi, pj, pk, side.pk_wrt_p1(), true, qi, qj, side.pk_wrt_q1(), tp, info.i_info()) ) { @@ -766,7 +769,7 @@ public: } // If Q arrives within P, there is a turn dependent on Q - if ( info.d_info().arrival[1] == 1 + if ( q_arrival == 1 && is_qk_valid && set_tp<1>(qi, qj, qk, side.qk_wrt_q1(), false, pi, pj, side.qk_wrt_p1(), tp, info.i_info()) ) { @@ -779,8 +782,8 @@ public: if (AssignPolicy::include_opposite) { // Handle cases not yet handled above - if ((info.d_info().arrival[1] == -1 && info.d_info().arrival[0] == 0) - || (info.d_info().arrival[0] == -1 && info.d_info().arrival[1] == 0)) + if ((q_arrival == -1 && p_arrival == 0) + || (p_arrival == -1 && q_arrival == 0)) { for (int i = 0; i < 2; i++) { From b349fc0f45af99481c4b3e4f6cf5875c8b1ad2c6 Mon Sep 17 00:00:00 2001 From: Barend Gehrels Date: Wed, 28 Jan 2015 14:35:26 +0100 Subject: [PATCH 04/23] [buffer] use turn instead of point in analysis to get their segments later --- .../buffer/buffered_piece_collection.hpp | 1 - .../detail/buffer/turn_in_piece_visitor.hpp | 61 ++++++++++--------- 2 files changed, 31 insertions(+), 31 deletions(-) diff --git a/include/boost/geometry/algorithms/detail/buffer/buffered_piece_collection.hpp b/include/boost/geometry/algorithms/detail/buffer/buffered_piece_collection.hpp index 9a3ad2096..368215537 100644 --- a/include/boost/geometry/algorithms/detail/buffer/buffered_piece_collection.hpp +++ b/include/boost/geometry/algorithms/detail/buffer/buffered_piece_collection.hpp @@ -199,7 +199,6 @@ struct buffered_piece_collection std::vector robust_turns; // Used only in insert_rescaled_piece_turns - we might use a map instead typedef robust_ring_type piece_robust_ring_type; - typedef robust_point_type piece_robust_point_type; }; struct robust_original diff --git a/include/boost/geometry/algorithms/detail/buffer/turn_in_piece_visitor.hpp b/include/boost/geometry/algorithms/detail/buffer/turn_in_piece_visitor.hpp index 7cda98895..b94628aeb 100644 --- a/include/boost/geometry/algorithms/detail/buffer/turn_in_piece_visitor.hpp +++ b/include/boost/geometry/algorithms/detail/buffer/turn_in_piece_visitor.hpp @@ -109,9 +109,9 @@ class analyse_turn_wrt_piece return geometry::covered_by(point, box); } - template + template static inline analyse_result check_segment(Point const& previous, - Point const& current, Point const& point, + Point const& current, Turn const& turn, bool from_monotonic) { typedef typename strategy::side::services::default_strategy @@ -125,12 +125,12 @@ class analyse_turn_wrt_piece < coordinate_type, coordinate_type - >(previous, current, point); + >(previous, current, turn.robust_point); if (twice_area == 0) { // Collinear, only on segment if it is covered by its bbox - if (in_box(previous, current, point)) + if (in_box(previous, current, turn.robust_point)) { return analyse_on_offsetted; } @@ -141,7 +141,7 @@ class analyse_turn_wrt_piece // segment is the hypothenusa. Check if it is close // (within rounding-area) if (twice_area * twice_area < geometry::comparable_distance(previous, current) - && in_box(previous, current, point)) + && in_box(previous, current, turn.robust_point)) { return analyse_near_offsetted; } @@ -161,9 +161,9 @@ class analyse_turn_wrt_piece } - template + template static inline analyse_result check_helper_segment(Point const& s1, - Point const& s2, Point const& point, + Point const& s2, Turn const& turn, bool is_original, Point const& offsetted) { @@ -172,7 +172,7 @@ class analyse_turn_wrt_piece typename cs_tag::type >::type side_strategy; - switch(side_strategy::apply(s1, s2, point)) + switch(side_strategy::apply(s1, s2, turn.robust_point)) { case 1 : return analyse_disjoint; // left of segment @@ -186,11 +186,11 @@ class analyse_turn_wrt_piece geometry::expand(box, s1); geometry::expand(box, s2); - if (geometry::covered_by(point, box)) + if (geometry::covered_by(turn.robust_point, box)) { // It is on the segment if (! is_original - && geometry::comparable_distance(point, offsetted) <= 1) + && geometry::comparable_distance(turn.robust_point, offsetted) <= 1) { // It is close to the offsetted-boundary, take // any rounding-issues into account @@ -217,12 +217,13 @@ class analyse_turn_wrt_piece return analyse_continue; } - template - static inline analyse_result check_helper_segments(Point const& point, Piece const& piece) + template + static inline analyse_result check_helper_segments(Turn const& turn, Piece const& piece) { - geometry::equal_to comparator; + typedef typename Turn::robust_point_type point_type; + geometry::equal_to comparator; - Point points[4]; + point_type points[4]; int helper_count = piece.robust_ring.size() - piece.offsetted_count; if (helper_count == 4) @@ -249,6 +250,7 @@ class analyse_turn_wrt_piece } // First check point-equality + point_type const& point = turn.robust_point; if (comparator(point, points[0]) || comparator(point, points[3])) { return analyse_on_offsetted; @@ -260,7 +262,7 @@ class analyse_turn_wrt_piece // Right side of the piece analyse_result result - = check_helper_segment(points[0], points[1], point, + = check_helper_segment(points[0], points[1], turn, false, points[0]); if (result != analyse_continue) { @@ -268,7 +270,7 @@ class analyse_turn_wrt_piece } // Left side of the piece - result = check_helper_segment(points[2], points[3], point, + result = check_helper_segment(points[2], points[3], turn, false, points[3]); if (result != analyse_continue) { @@ -278,7 +280,7 @@ class analyse_turn_wrt_piece if (! comparator(points[1], points[2])) { // Side of the piece at side of original geometry - result = check_helper_segment(points[1], points[2], point, + result = check_helper_segment(points[1], points[2], turn, true, point); if (result != analyse_continue) { @@ -293,7 +295,7 @@ class analyse_turn_wrt_piece // Not in offsetted-area. This makes a cheap check possible typedef typename strategy::side::services::default_strategy < - typename cs_tag::type + typename cs_tag::type >::type side_strategy; switch(side_strategy::apply(points[3], points[0], point)) @@ -307,15 +309,15 @@ class analyse_turn_wrt_piece return analyse_continue; } - template - static inline analyse_result check_monotonic(Point const& point, Piece const& piece, Compare const& compare) + template + static inline analyse_result check_monotonic(Turn const& turn, Piece const& piece, Compare const& compare) { typedef typename Piece::piece_robust_ring_type ring_type; typedef typename ring_type::const_iterator it_type; it_type end = piece.robust_ring.begin() + piece.offsetted_count; it_type it = std::lower_bound(piece.robust_ring.begin(), end, - point, + turn.robust_point, compare); if (it != end @@ -325,7 +327,7 @@ class analyse_turn_wrt_piece // w.r.t. specified direction, and prev points to a point smaller // We now know if it is inside/outside it_type prev = it - 1; - return check_segment(*prev, *it, point, true); + return check_segment(*prev, *it, turn, true); } return analyse_continue; } @@ -334,9 +336,8 @@ public : template static inline analyse_result apply(Turn const& turn, Piece const& piece) { - typedef typename Piece::piece_robust_point_type point_type; - const point_type& point = turn.robust_point; - analyse_result code = check_helper_segments(point, piece); + typedef typename Turn::robust_point_type point_type; + analyse_result code = check_helper_segments(turn, piece); if (code != analyse_continue) { return code; @@ -351,22 +352,22 @@ public : // We try it only once. if (piece.is_monotonic_increasing[0]) { - code = check_monotonic(point, piece, geometry::less()); + code = check_monotonic(turn, piece, geometry::less()); if (code != analyse_continue) return code; } else if (piece.is_monotonic_increasing[1]) { - code = check_monotonic(point, piece, geometry::less()); + code = check_monotonic(turn, piece, geometry::less()); if (code != analyse_continue) return code; } else if (piece.is_monotonic_decreasing[0]) { - code = check_monotonic(point, piece, geometry::greater()); + code = check_monotonic(turn, piece, geometry::greater()); if (code != analyse_continue) return code; } else if (piece.is_monotonic_decreasing[1]) { - code = check_monotonic(point, piece, geometry::greater()); + code = check_monotonic(turn, piece, geometry::greater()); if (code != analyse_continue) return code; } } @@ -383,7 +384,7 @@ public : // (on which any side or side-value would return 0) if (! comparator(previous, current)) { - code = check_segment(previous, current, point, false); + code = check_segment(previous, current, turn, false); if (code != analyse_continue) { return code; From 2be267d79e7d6fb82dae89af40af1de088ca399a Mon Sep 17 00:00:00 2001 From: Menelaos Karavelas Date: Thu, 29 Jan 2015 23:29:42 +0200 Subject: [PATCH 05/23] [algorithms][is_valid][debug][turns] add display of segment indices --- .../algorithms/detail/is_valid/debug_print_turns.hpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/include/boost/geometry/algorithms/detail/is_valid/debug_print_turns.hpp b/include/boost/geometry/algorithms/detail/is_valid/debug_print_turns.hpp index 6824921b6..d648412e4 100644 --- a/include/boost/geometry/algorithms/detail/is_valid/debug_print_turns.hpp +++ b/include/boost/geometry/algorithms/detail/is_valid/debug_print_turns.hpp @@ -1,6 +1,6 @@ // Boost.Geometry (aka GGL, Generic Geometry Library) -// Copyright (c) 2014, Oracle and/or its affiliates. +// Copyright (c) 2014-2015, Oracle and/or its affiliates. // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle @@ -45,6 +45,10 @@ inline void debug_print_turns(TurnIterator first, TurnIterator beyond) << tit->operations[0].seg_id.ring_index << ", " << tit->operations[1].seg_id.ring_index + << "} {" + << tit->operations[0].seg_id.segment_index + << ", " + << tit->operations[1].seg_id.segment_index << "} " << geometry::dsv(tit->point) << "]"; From e2d15e9eb3e22bb5b1ab044c21b2cdc85746e052 Mon Sep 17 00:00:00 2001 From: Menelaos Karavelas Date: Thu, 29 Jan 2015 23:31:14 +0200 Subject: [PATCH 06/23] [algorithms][is_simple][debug][turns] add debugging support for the boundary (endpoints) of linestrings --- .../is_simple/debug_print_boundary_points.hpp | 83 +++++++++++++------ 1 file changed, 57 insertions(+), 26 deletions(-) diff --git a/include/boost/geometry/algorithms/detail/is_simple/debug_print_boundary_points.hpp b/include/boost/geometry/algorithms/detail/is_simple/debug_print_boundary_points.hpp index 75c37c68f..196d89b92 100644 --- a/include/boost/geometry/algorithms/detail/is_simple/debug_print_boundary_points.hpp +++ b/include/boost/geometry/algorithms/detail/is_simple/debug_print_boundary_points.hpp @@ -1,6 +1,6 @@ // Boost.Geometry (aka GGL, Generic Geometry Library) -// Copyright (c) 2014, Oracle and/or its affiliates. +// Copyright (c) 2014-2015, Oracle and/or its affiliates. // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle @@ -18,6 +18,8 @@ #include #include +#include +#include #include @@ -26,7 +28,8 @@ #include #include -#endif +#include +#endif // BOOST_GEOMETRY_TEST_DEBUG namespace boost { namespace geometry @@ -37,39 +40,67 @@ namespace detail { namespace is_simple #ifdef BOOST_GEOMETRY_TEST_DEBUG -template -inline void debug_print_boundary_points(MultiLinestring const& multilinestring) +template ::type> +struct debug_boundary_points_printer + : not_implemented +{}; + +template +struct debug_boundary_points_printer { - typedef typename point_type::type point_type; - typedef std::vector point_vector; - - point_vector boundary_points; - for (typename boost::range_iterator::type it - = boost::begin(multilinestring); - it != boost::end(multilinestring); ++it) + static inline void apply(Linestring const& linestring) { - if ( boost::size(*it) > 1 - && !geometry::equals(range::front(*it), range::back(*it)) ) + std::cout << "boundary points: "; + std::cout << " " << geometry::dsv(range::front(linestring)); + std::cout << " " << geometry::dsv(range::back(linestring)); + std::cout << std::endl << std::endl; + } +}; + +template +struct debug_boundary_points_printer +{ + static inline void apply(MultiLinestring const& multilinestring) + { + typedef typename point_type::type point_type; + typedef std::vector point_vector; + + point_vector boundary_points; + for (typename boost::range_iterator::type it + = boost::begin(multilinestring); + it != boost::end(multilinestring); ++it) { - boundary_points.push_back( range::front(*it) ); - boundary_points.push_back( range::back(*it) ); + if ( boost::size(*it) > 1 + && !geometry::equals(range::front(*it), range::back(*it)) ) + { + boundary_points.push_back( range::front(*it) ); + boundary_points.push_back( range::back(*it) ); + } } - } - std::sort(boundary_points.begin(), boundary_points.end(), - geometry::less()); + std::sort(boundary_points.begin(), boundary_points.end(), + geometry::less()); - std::cout << "boundary points: "; - for (typename point_vector::const_iterator pit = boundary_points.begin(); - pit != boundary_points.end(); ++pit) - { - std::cout << " " << geometry::dsv(*pit); + std::cout << "boundary points: "; + for (typename point_vector::const_iterator + pit = boundary_points.begin(); + pit != boundary_points.end(); ++pit) + { + std::cout << " " << geometry::dsv(*pit); + } + std::cout << std::endl << std::endl; } - std::cout << std::endl << std::endl; +}; + + +template +inline void debug_print_boundary_points(Linear const& linear) +{ + debug_boundary_points_printer::apply(linear); } #else -template -inline void debug_print_boundary_points(MultiLinestring const&) +template +inline void debug_print_boundary_points(Linear const&) { } #endif // BOOST_GEOMETRY_TEST_DEBUG From eac0dc71bb87d23de189a7fefac6111553473e70 Mon Sep 17 00:00:00 2001 From: Menelaos Karavelas Date: Thu, 29 Jan 2015 23:45:46 +0200 Subject: [PATCH 07/23] [algorithms][is_simple] optimize the computation of turns for multilinestrings: instead of computing the turns for each linestring (through bg::intersects) and then again for the entire multilinestring, avoid computing the turns for the individual linestrings in the multilinestring and compute and process all multilinestring turns together; besides the optimization this approach fixes a bug in bg::intersects in the context of simplicity testing: bg::intersects cannot detect the intersection occuring when a boundary point of linestring is also an internal point of the linestring, as in LINESTRING(4 1,10 8,4 6,4 1,10 5,10 3), for example; --- .../algorithms/detail/is_simple/linear.hpp | 327 ++++++++++-------- 1 file changed, 188 insertions(+), 139 deletions(-) diff --git a/include/boost/geometry/algorithms/detail/is_simple/linear.hpp b/include/boost/geometry/algorithms/detail/is_simple/linear.hpp index 90810d27e..c4487c445 100644 --- a/include/boost/geometry/algorithms/detail/is_simple/linear.hpp +++ b/include/boost/geometry/algorithms/detail/is_simple/linear.hpp @@ -1,6 +1,6 @@ // Boost.Geometry (aka GGL, Generic Geometry Library) -// Copyright (c) 2014, Oracle and/or its affiliates. +// Copyright (c) 2014-2015, Oracle and/or its affiliates. // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle @@ -19,6 +19,7 @@ #include #include #include +#include #include #include @@ -29,8 +30,10 @@ #include #include +#include #include +#include #include #include @@ -54,128 +57,210 @@ namespace detail { namespace is_simple { +template +inline bool check_segment_indices(Turn const& turn, + signed_index_type last_index) +{ + return + (turn.operations[0].seg_id.segment_index == 0 + && turn.operations[1].seg_id.segment_index == last_index) + || + (turn.operations[0].seg_id.segment_index == 0 + && turn.operations[1].seg_id.segment_index == last_index); +} + + +template ::type> +class is_acceptable_turn + : not_implemented +{}; + +template +class is_acceptable_turn +{ +public: + is_acceptable_turn(Linestring const& linestring) + : m_linestring(linestring) + , m_is_closed(geometry::equals(range::front(linestring), + range::back(linestring))) + {} + + template + inline bool apply(Turn const& turn) const + { + BOOST_ASSERT(boost::size(m_linestring) > 1); + return m_is_closed + && turn.method == overlay::method_none + && check_segment_indices(turn, boost::size(m_linestring) - 2) + && geometry::equals(range::front(m_linestring), turn.point); + } + +private: + Linestring const& m_linestring; + bool const m_is_closed; +}; + +template +class is_acceptable_turn +{ +private: + typedef typename boost::range_value::type linestring_type; + typedef is_acceptable_turn base_type; + + template + static inline bool is_boundary_point_of(Point const& point, + Linestring const& linestring) + { + BOOST_ASSERT(boost::size(linestring) > 1); + return + ! geometry::equals(range::front(linestring), + range::back(linestring)) + && + (geometry::equals(point, range::front(linestring)) + || geometry::equals(point, range::back(linestring))); + } + + template + static inline bool is_closing_point_of(Turn const& turn, + Linestring const& linestring) + { + BOOST_ASSERT(boost::size(linestring) > 1); + return + turn.method == overlay::method_none + && + check_segment_indices(turn, boost::size(linestring) - 2) + && + geometry::equals(range::front(linestring), range::back(linestring)) + && + geometry::equals(range::front(linestring), turn.point) + ; + } + + template + static inline bool have_same_boundary_points(Linestring1 const& ls1, + Linestring2 const& ls2) + { + return + geometry::equals(range::front(ls1), range::front(ls2)) + ? + geometry::equals(range::back(ls1), range::back(ls2)) + : + (geometry::equals(range::front(ls1), range::back(ls2)) + && + geometry::equals(range::back(ls1), range::front(ls2))) + ; + } + +public: + is_acceptable_turn(MultiLinestring const& multilinestring) + : m_multilinestring(multilinestring) + {} + + template + inline bool apply(Turn const& turn) const + { + linestring_type const& ls1 = + range::at(m_multilinestring, turn.operations[0].seg_id.multi_index); + + linestring_type const& ls2 = + range::at(m_multilinestring, turn.operations[1].seg_id.multi_index); + + if (turn.operations[0].seg_id.multi_index + == turn.operations[1].seg_id.multi_index) + { + return is_closing_point_of(turn, ls1); + } + + return + is_boundary_point_of(turn.point, ls1) + && is_boundary_point_of(turn.point, ls2) + && + ( boost::size(ls1) != 2 + || boost::size(ls2) != 2 + || ! have_same_boundary_points(ls1, ls2) ); + } + +private: + MultiLinestring const& m_multilinestring; +}; + + +template +inline bool has_self_intersections(Linear const& linear) +{ + typedef typename point_type::type point_type; + + // compute self turns + typedef detail::overlay::turn_info + < + point_type, + geometry::segment_ratio + < + typename geometry::coordinate_type::type + > + > turn_info; + + std::deque turns; + + typedef detail::overlay::get_turn_info + < + detail::disjoint::assign_disjoint_policy + > turn_policy; + + is_acceptable_turn predicate(linear); + detail::overlay::predicate_based_interrupt_policy + < + is_acceptable_turn + > interrupt_policy(predicate); + + detail::self_get_turn_points::get_turns + < + turn_policy + >::apply(linear, + detail::no_rescale_policy(), + turns, + interrupt_policy); + + detail::is_valid::debug_print_turns(turns.begin(), turns.end()); + debug_print_boundary_points(linear); + + return interrupt_policy.has_intersections; +} + + template struct is_simple_linestring { static inline bool apply(Linestring const& linestring) { - return !detail::is_valid::has_duplicates + return ! detail::is_valid::has_duplicates < Linestring, closed >::apply(linestring) - && !detail::is_valid::has_spikes + && ! detail::is_valid::has_spikes < Linestring, closed >::apply(linestring) - && !(CheckSelfIntersections && geometry::intersects(linestring)); + && ! (CheckSelfIntersections && has_self_intersections(linestring)); } }; - template -class is_simple_multilinestring +struct is_simple_multilinestring { -private: - class is_acceptable_turn - { - private: - template - static inline bool is_boundary_point_of(Point const& point, - Linestring const& linestring) - { - BOOST_ASSERT( boost::size(linestring) > 1 ); - return - !geometry::equals(range::front(linestring), - range::back(linestring)) - && - ( geometry::equals(point, range::front(linestring)) - || geometry::equals(point, range::back(linestring)) ); - } - - template - static inline bool is_closing_point_of(Point const& point, - Linestring const& linestring) - { - BOOST_ASSERT( boost::size(linestring) > 1 ); - return - geometry::equals(range::front(linestring), - range::back(linestring)) - && - geometry::equals(range::front(linestring), point) - ; - } - - template - static inline bool have_same_boundary_points(Linestring1 const& ls1, - Linestring2 const& ls2) - { - return - geometry::equals(range::front(ls1), range::front(ls2)) - ? - geometry::equals(range::back(ls1), range::back(ls2)) - : - (geometry::equals(range::front(ls1), range::back(ls2)) - && - geometry::equals(range::back(ls1), range::front(ls2)) - ) - ; - } - - public: - is_acceptable_turn(MultiLinestring const& multilinestring) - : m_multilinestring(multilinestring) - {} - - template - inline bool apply(Turn const& turn) const - { - typedef typename boost::range_value - < - MultiLinestring - >::type linestring; - - linestring const& ls1 = - range::at(m_multilinestring, - turn.operations[0].seg_id.multi_index); - - linestring const& ls2 = - range::at(m_multilinestring, - turn.operations[1].seg_id.multi_index); - - if (turn.operations[0].seg_id.multi_index - == turn.operations[1].seg_id.multi_index) - { - BOOST_ASSERT(is_closing_point_of(turn.point, ls1)); - return true; - } - - return - is_boundary_point_of(turn.point, ls1) - && is_boundary_point_of(turn.point, ls2) - && - ( boost::size(ls1) != 2 - || boost::size(ls2) != 2 - || !have_same_boundary_points(ls1, ls2) ); - } - - private: - MultiLinestring const& m_multilinestring; - }; - - -public: static inline bool apply(MultiLinestring const& multilinestring) { - typedef typename boost::range_value::type linestring; - typedef typename point_type::type point_type; - typedef point_type point; - - // check each of the linestrings for simplicity - if ( !detail::check_iterator_range + // but do not compute self-intersections yet; these will be + // computed for the entire multilinestring + if ( ! detail::check_iterator_range < - is_simple_linestring, + is_simple_linestring + < + typename boost::range_value::type, + false // do not compute self-intersections + >, false // do not allow empty multilinestring >::apply(boost::begin(multilinestring), boost::end(multilinestring)) @@ -184,44 +269,8 @@ public: return false; } - - // compute self turns - typedef detail::overlay::turn_info - < - point_type, - geometry::segment_ratio - < - typename geometry::coordinate_type::type - > - > turn_info; - - std::deque turns; - - typedef detail::overlay::get_turn_info - < - detail::disjoint::assign_disjoint_policy - > turn_policy; - - is_acceptable_turn predicate(multilinestring); - detail::overlay::predicate_based_interrupt_policy - < - is_acceptable_turn - > interrupt_policy(predicate); - - detail::self_get_turn_points::get_turns - < - turn_policy - >::apply(multilinestring, - detail::no_rescale_policy(), - turns, - interrupt_policy); - - detail::is_valid::debug_print_turns(turns.begin(), turns.end()); - debug_print_boundary_points(multilinestring); - - return !interrupt_policy.has_intersections; + return ! has_self_intersections(multilinestring); } - }; From 7d581f649bcfd35dff0a480155968eff490ab364 Mon Sep 17 00:00:00 2001 From: Menelaos Karavelas Date: Thu, 29 Jan 2015 23:46:15 +0200 Subject: [PATCH 08/23] [test][algorithms][is_simple] add more test cases including a linestring whose one boundary point is also an internal point of the linestring (such a linestring is currently not detected as self-intersecting by bg::intersects) --- test/algorithms/is_simple.cpp | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/test/algorithms/is_simple.cpp b/test/algorithms/is_simple.cpp index e4acf36e5..57e32ce7c 100644 --- a/test/algorithms/is_simple.cpp +++ b/test/algorithms/is_simple.cpp @@ -1,7 +1,7 @@ // Boost.Geometry (aka GGL, Generic Geometry Library) // Unit Test -// Copyright (c) 2014, Oracle and/or its affiliates. +// Copyright (c) 2014-2015, Oracle and/or its affiliates. // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle @@ -174,7 +174,20 @@ BOOST_AUTO_TEST_CASE( test_is_simple_linestring ) test_simple(from_wkt("LINESTRING(0 0,3 0,5 0,4 0,2 0)"), false); test_simple(from_wkt("LINESTRING(0 0,3 0,2 0,5 0)"), false); test_simple(from_wkt("LINESTRING(0 0,2 0,2 2,1 0,0 0)"), false); + test_simple(from_wkt("LINESTRING(0 0,1 0,2 0,2 2,1 0,0 0)"), false); + test_simple(from_wkt("LINESTRING(0 0,10 0,10 10,0 10,0 0,0 0)"), false); test_simple(from_wkt("LINESTRING(0 0,0 10,5 10,0 0,10 10,10 5,10 0,0 0)"), false); + test_simple(from_wkt("LINESTRING(0 0,0 0,10 0,10 10,0 10,0 0,0 0)"), + false); + test_simple(from_wkt("LINESTRING(0 0,0 0,0 0,10 0,10 10,0 10,0 0,0 0,0 0,0 0)"), + false); + test_simple(from_wkt("LINESTRING(0 0,0 0,10 0,10 10,10 10,10 10,10 10,10 10,0 10,0 0,0 0)"), + false); + test_simple(from_wkt("LINESTRING(0 0,1 0,2 0,2 2,1 0,1 4,0 0)"), false); + test_simple(from_wkt("LINESTRING(4 1,10 8,4 6,4 1,10 5,10 3)"), + false); + test_simple(from_wkt("LINESTRING(10 3,10 5,4 1,4 6,10 8,4 1)"), + false); } BOOST_AUTO_TEST_CASE( test_is_simple_multilinestring ) @@ -249,7 +262,10 @@ BOOST_AUTO_TEST_CASE( test_is_simple_multilinestring ) false); test_simple(from_wkt("MULTILINESTRING((0 0,1 0,1 1,0 1,0 0),(-1 -1,-1 0,0 0,0 -1,-1 -1))"), false); - test_simple(from_wkt("MULTILINESTRING((0 0,0 10,5 10,0 0,10 10,10 5,10 0,0 0))"), false); + test_simple(from_wkt("MULTILINESTRING((0 0,0 10,5 10,0 0,10 10,10 5,10 0,0 0))"), + false); + test_simple(from_wkt("MULTILINESTRING((4 1,10 8,4 6,4 1,10 5,10 3))"), + false); } BOOST_AUTO_TEST_CASE( test_is_simple_areal ) From dcb6d9ca94bf77616475836a5a6a700b71c5e637 Mon Sep 17 00:00:00 2001 From: Menelaos Karavelas Date: Fri, 30 Jan 2015 01:19:19 +0200 Subject: [PATCH 09/23] [test][algorithms][is_simple] add one more test case --- test/algorithms/is_simple.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/algorithms/is_simple.cpp b/test/algorithms/is_simple.cpp index 57e32ce7c..d6f37c683 100644 --- a/test/algorithms/is_simple.cpp +++ b/test/algorithms/is_simple.cpp @@ -266,6 +266,8 @@ BOOST_AUTO_TEST_CASE( test_is_simple_multilinestring ) false); test_simple(from_wkt("MULTILINESTRING((4 1,10 8,4 6,4 1,10 5,10 3))"), false); + test_simple(from_wkt("MULTILINESTRING((10 3,10 5,4 1,4 6,10 8,4 1))"), + false); } BOOST_AUTO_TEST_CASE( test_is_simple_areal ) From a843e3f7ec43ee4df8122e8aca4f61d257fb9e33 Mon Sep 17 00:00:00 2001 From: Menelaos Karavelas Date: Sun, 1 Feb 2015 11:30:23 +0200 Subject: [PATCH 10/23] [test][algorithms][is_simple] add a few more test cases --- test/algorithms/is_simple.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/algorithms/is_simple.cpp b/test/algorithms/is_simple.cpp index d6f37c683..bd6ceb668 100644 --- a/test/algorithms/is_simple.cpp +++ b/test/algorithms/is_simple.cpp @@ -183,6 +183,8 @@ BOOST_AUTO_TEST_CASE( test_is_simple_linestring ) false); test_simple(from_wkt("LINESTRING(0 0,0 0,10 0,10 10,10 10,10 10,10 10,10 10,0 10,0 0,0 0)"), false); + test_simple(from_wkt("LINESTRING(0 0,1 0,2 0,2 2,1 0)"), false); + test_simple(from_wkt("LINESTRING(1 0,2 2,2 0,1 0,0 0)"), false); test_simple(from_wkt("LINESTRING(0 0,1 0,2 0,2 2,1 0,1 4,0 0)"), false); test_simple(from_wkt("LINESTRING(4 1,10 8,4 6,4 1,10 5,10 3)"), false); From 2c0c882cf4510115ee30341f37221a728150bfae Mon Sep 17 00:00:00 2001 From: Menelaos Karavelas Date: Sun, 1 Feb 2015 11:30:54 +0200 Subject: [PATCH 11/23] [algorithms][is_simple] replace equality testing of turn point and linestring endpoint by using the turn's fraction instead of the geometry::equals algorithm --- include/boost/geometry/algorithms/detail/is_simple/linear.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/boost/geometry/algorithms/detail/is_simple/linear.hpp b/include/boost/geometry/algorithms/detail/is_simple/linear.hpp index c4487c445..e07926e37 100644 --- a/include/boost/geometry/algorithms/detail/is_simple/linear.hpp +++ b/include/boost/geometry/algorithms/detail/is_simple/linear.hpp @@ -92,7 +92,7 @@ public: return m_is_closed && turn.method == overlay::method_none && check_segment_indices(turn, boost::size(m_linestring) - 2) - && geometry::equals(range::front(m_linestring), turn.point); + && turn.operations[0].fraction.is_zero(); } private: @@ -132,7 +132,7 @@ private: && geometry::equals(range::front(linestring), range::back(linestring)) && - geometry::equals(range::front(linestring), turn.point) + turn.operations[0].fraction.is_zero(); ; } From 62450efa253a2229030500c8c773bf187c8c4f24 Mon Sep 17 00:00:00 2001 From: Menelaos Karavelas Date: Mon, 2 Feb 2015 18:56:57 +0200 Subject: [PATCH 12/23] [test][algorithms][sym_difference] add two more test cases (both contain a turn whose point is a spike apex for one of the two geometries and a vertex for the other geometry) --- .../sym_difference_linear_linear.cpp | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/test/algorithms/set_operations/sym_difference/sym_difference_linear_linear.cpp b/test/algorithms/set_operations/sym_difference/sym_difference_linear_linear.cpp index fa14fe307..c0f08eafe 100644 --- a/test/algorithms/set_operations/sym_difference/sym_difference_linear_linear.cpp +++ b/test/algorithms/set_operations/sym_difference/sym_difference_linear_linear.cpp @@ -376,6 +376,17 @@ BOOST_AUTO_TEST_CASE( test_sym_difference_linestring_linestring ) (2 2,5 -1,15 2,18 0))"), "llsdf21" ); + + tester::apply + (from_wkt("LINESTRING(0 -3,5 4,6 6,-3 2,-3 0,-3 -10,9 -2,\ + 9 5,5 -5,-4 -8,9 0)"), + from_wkt("LINESTRING(-3 6,-3 0,-3 5,2 -3,-6 10,5 0,\ + 2 8,-6 1,10 -6)"), + from_wkt("MULTILINESTRING((0 -3,5 4,6 6,-3 2),\ + (-3 0,-3 -10,9 -2,9 5,5 -5,-4 -8,9 0),(-3 6,-3 2),\ + (-3 2,-3 5,2 -3,-6 10,5 0,2 8,-6 1,10 -6))"), + "llsdf22" + ); } @@ -669,6 +680,25 @@ BOOST_AUTO_TEST_CASE( test_sym_difference_multilinestring_linestring ) (17 0,18 1,17 1,16 0),(4 0,3 1))"), "mllsdf04" ); + + tester::apply + (from_wkt("MULTILINESTRING((0 -3,5 4,6 6,-3 2,-3 0,\ + -3 -10,9 -2,9 5,5 -5,-4 -8,9 0),\ + (-7 9,-4 -9,-5 -10,5 3),\ + (-8 -3,-6 6,-9 0,-4 -3,-1 -10),\ + (0 1,7 -1,-2 3,-7 1),\ + (-5 -9,-4 -10,7 -10,0 -6,1 6,2 -1,1 5,-5 -5))"), + from_wkt("LINESTRING(-3 6,-3 0,-3 5,2 -3,-6 10,5 0,2 8,\ + -6 1,10 -6)"), + from_wkt("MULTILINESTRING((0 -3,5 4,6 6,-3 2),\ + (-3 0,-3 -10,9 -2,9 5,5 -5,-4 -8,9 0),\ + (-7 9,-4 -9,-5 -10,5 3),\ + (-8 -3,-6 6,-9 0,-4 -3,-1 -10),\ + (0 1,7 -1,-2 3,-7 1),\ + (-5 -9,-4 -10,7 -10,0 -6,1 6,2 -1,1 5,-5 -5),\ + (-3 6,-3 2),(-3 2,-3 5,2 -3,-6 10,5 0,2 8,-6 1,10 -6))"), + "mllsdf05" + ); } From 76e54e0adec2a34cb244e2516aa24d41ad451d6a Mon Sep 17 00:00:00 2001 From: Menelaos Karavelas Date: Mon, 2 Feb 2015 19:03:42 +0200 Subject: [PATCH 13/23] [test][algorithms][difference] add more test cases (most contain a turn whose point is a spike apex for one of the two geometries and a vertex for the other geometry) --- .../difference/difference_linear_linear.cpp | 74 +++++++++++++++++++ 1 file changed, 74 insertions(+) diff --git a/test/algorithms/set_operations/difference/difference_linear_linear.cpp b/test/algorithms/set_operations/difference/difference_linear_linear.cpp index 6d3d8029e..4add23277 100644 --- a/test/algorithms/set_operations/difference/difference_linear_linear.cpp +++ b/test/algorithms/set_operations/difference/difference_linear_linear.cpp @@ -416,6 +416,55 @@ BOOST_AUTO_TEST_CASE( test_difference_linestring_linestring ) from_wkt("MULTILINESTRING((1 1,2 1))"), "lldf25" ); + + tester::apply + (from_wkt("LINESTRING(6 0,0 0,5 0)"), + from_wkt("LINESTRING(2 0,-10 0)"), + from_wkt("MULTILINESTRING((6 0,2 0),(2 0,5 0))"), + "lldf27a" + ); + + tester::apply + (from_wkt("LINESTRING(6 0,0 0,5 0)"), + from_wkt("LINESTRING(2 0,-1 0,-10 0)"), + from_wkt("MULTILINESTRING((6 0,2 0),(2 0,5 0))"), + "lldf27b" + ); + + tester::apply + (from_wkt("LINESTRING(6 0,0 0,5 0)"), + from_wkt("LINESTRING(2 0,0 0,-10 0)"), + from_wkt("MULTILINESTRING((6 0,2 0),(2 0,5 0))"), + "lldf27c" + ); + + tester::apply + (from_wkt("LINESTRING(2 0,0 0,-10 0)"), + from_wkt("LINESTRING(6 0,0 0,5 0)"), + from_wkt("MULTILINESTRING((0 0,-10 0))"), + "lldf27d" + ); + + tester::apply + (from_wkt("LINESTRING(-3 6,-3 0,-3 5)"), + from_wkt("LINESTRING(-3 2,-3 0,-3 -10)"), + from_wkt("MULTILINESTRING((-3 6,-3 2),(-3 2,-3 5))"), + "lldf28a" + ); + + tester::apply + (from_wkt("LINESTRING(-3 2,-3 0,-3 -10)"), + from_wkt("LINESTRING(-3 6,-3 0,-3 5)"), + from_wkt("MULTILINESTRING((-3 0,-3 -10))"), + "lldf28b" + ); + + tester::apply + (from_wkt("LINESTRING(-3 6,-3 0,-3 5)"), + from_wkt("LINESTRING(-3 2,-3 0,-3 -10)"), + from_wkt("MULTILINESTRING((-3 6,-3 2),(-3 2,-3 5))"), + "lldf28c" + ); } @@ -696,6 +745,31 @@ BOOST_AUTO_TEST_CASE( test_difference_multilinestring_linestring ) from_wkt("MULTILINESTRING((-1 0,-1 10),(0 0,1 0),(19 0,20 0),(25 0,30 0))"), "mlldf05" ); + + tester::apply + (from_wkt("MULTILINESTRING((-3 2,-3 0,-3 -10))"), + from_wkt("LINESTRING(-3 6,-3 0,-3 5)"), + from_wkt("MULTILINESTRING((-3 0,-3 -10))"), + "mlldf06a" + ); + + tester::apply + (from_wkt("MULTILINESTRING((6 6,-3 2,-3 0,-3 -10,9 -2))"), + from_wkt("LINESTRING(-3 6,-3 0,-3 5,2 -3,-6 10,5 0,2 8,\ + -6 1,10 -6)"), + from_wkt("MULTILINESTRING((6 6,-3 2),(-3 0,-3 -10,9 -2))"), + "mlldf06b" + ); + + tester::apply + (from_wkt("MULTILINESTRING((0 -3,5 4,6 6,-3 2,-3 0,-3 -10,\ + 9 -2,9 5,5 -5,-4 -8,9 0))"), + from_wkt("LINESTRING(-3 6,-3 0,-3 5,2 -3,-6 10,5 0,2 8,\ + -6 1,10 -6)"), + from_wkt("MULTILINESTRING((0 -3,5 4,6 6,-3 2),\ + (-3 0,-3 -10,9 -2,9 5,5 -5,-4 -8,9 0))"), + "mlldf06c" + ); } From 5c73173d60ac41ed79cd2e60760ccc55cf298173 Mon Sep 17 00:00:00 2001 From: Adam Wulkiewicz Date: Tue, 3 Feb 2015 18:26:46 +0100 Subject: [PATCH 14/23] [get_turns] Fix the handling of Linear collinear spikes for L/L. --- .../detail/overlay/get_turn_info_ll.hpp | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) 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 731a72e7e..3d939b4d4 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 @@ -293,6 +293,12 @@ struct get_turn_info_linear_linear equal::apply(pi, pj, pk, qi, qj, qk, tp, inters.i_info(), inters.d_info(), inters.sides()); + operation_type spike_op + = ( tp.operations[0].operation != operation_continue + || tp.operations[1].operation != operation_continue ) ? + operation_union : + operation_continue; + // transform turn turn_transformer_ec transformer(method_touch); transformer(tp); @@ -304,7 +310,7 @@ struct get_turn_info_linear_linear if ( ! handle_spikes || ! append_collinear_spikes(tp, inters, is_p_last, is_q_last, - method_touch, operation_union, + method_touch, spike_op, out) ) { *out++ = tp; // no spikes @@ -482,6 +488,14 @@ struct get_turn_info_linear_linear if ( is_p_spike && is_q_spike ) { + if ( tp.method == method_equal + && tp.operations[0].operation == operation_continue + && tp.operations[1].operation == operation_continue ) + { + // treat both non-opposite collinear spikes as no-spikes + return false; + } + tp.method = method; tp.operations[0].operation = operation_blocked; tp.operations[1].operation = operation_blocked; From e08de8e48b7764c80761a1d592f69f2aed3176ed Mon Sep 17 00:00:00 2001 From: Adam Wulkiewicz Date: Tue, 3 Feb 2015 18:55:50 +0100 Subject: [PATCH 15/23] [test][get_turns] Add tests for L/L collinear spikes. --- .../overlay/get_turns_linear_linear.cpp | 22 ++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/test/algorithms/overlay/get_turns_linear_linear.cpp b/test/algorithms/overlay/get_turns_linear_linear.cpp index 12328d3db..04d411da6 100644 --- a/test/algorithms/overlay/get_turns_linear_linear.cpp +++ b/test/algorithms/overlay/get_turns_linear_linear.cpp @@ -21,7 +21,7 @@ #include //TEST -//#include +#include template void test_all() @@ -256,6 +256,26 @@ void test_all() "LINESTRING(2 0,0 0,-10 0)", expected("tiu+=")("mui=+")); + // 03.02.2015 + test_geometry("LINESTRING(-7 -8,3 0,4 -1,-7 10)", + "LINESTRING(-5 -4,3 0,4 -1,7 -4,2 -1)", + expected("tii++")("txu==")("tiu==")("mui=+")); + test_geometry("LINESTRING(-7 -8,3 0,4 -1,-7 10)", + "LINESTRING(-5 -4,3 0,7 -4,2 -1)", + expected("tii++")("mxu==")("miu==")("mui=+")); + + if ( boost::is_same::value ) + { + // FAILING + /*test_geometry("LINESTRING(8 5,5 1,-2 3,1 10)", + "LINESTRING(1.9375 1.875, 1.7441860465116283 1.9302325581395348, -0.7692307692307692 2.6483516483516487, -2 3, -1.0071942446043165 5.316546762589928)", + expected("")); + test_geometry("LINESTRING(8 5,5 1,-2 3,1 10)", + "LINESTRING(1.9375 1.875, 1.7441860465116283 1.9302325581395348, -0.7692307692307692 2.6483516483516487, -2 3, -0.5 6.5)", + expected(""));*/ + } + + // TODO: //test_geometry("LINESTRING(0 0,2 0,1 0)", "LINESTRING(0 1,0 0,2 0)", "1FF00F102"); //test_geometry("LINESTRING(2 0,0 0,1 0)", "LINESTRING(0 1,0 0,2 0)", "1FF00F102"); From c38d764b51a239b267556436cdc7bd7c3925d09a Mon Sep 17 00:00:00 2001 From: Menelaos Karavelas Date: Tue, 3 Feb 2015 21:54:19 +0200 Subject: [PATCH 16/23] [test][algorithms][turns] remove trailing spaces --- test/algorithms/overlay/get_turns_linear_linear.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/algorithms/overlay/get_turns_linear_linear.cpp b/test/algorithms/overlay/get_turns_linear_linear.cpp index 04d411da6..cde102aea 100644 --- a/test/algorithms/overlay/get_turns_linear_linear.cpp +++ b/test/algorithms/overlay/get_turns_linear_linear.cpp @@ -274,7 +274,7 @@ void test_all() "LINESTRING(1.9375 1.875, 1.7441860465116283 1.9302325581395348, -0.7692307692307692 2.6483516483516487, -2 3, -0.5 6.5)", expected(""));*/ } - + // TODO: //test_geometry("LINESTRING(0 0,2 0,1 0)", "LINESTRING(0 1,0 0,2 0)", "1FF00F102"); From fe257ef8b4b384689286dfeebbcf93990d886873 Mon Sep 17 00:00:00 2001 From: Menelaos Karavelas Date: Tue, 3 Feb 2015 21:54:52 +0200 Subject: [PATCH 17/23] [algorithms][detail][overlay][turns L/L] remove trailing spaces --- .../geometry/algorithms/detail/overlay/get_turn_info_ll.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 ad06a12d1..4ab9bb03c 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 @@ -298,7 +298,7 @@ struct get_turn_info_linear_linear || tp.operations[1].operation != operation_continue ) ? operation_union : operation_continue; - + // transform turn turn_transformer_ec transformer(method_touch); transformer(tp); From 2b8528e3181e5e2f4955c472dfe7bc95c452ee85 Mon Sep 17 00:00:00 2001 From: Menelaos Karavelas Date: Tue, 3 Feb 2015 21:57:10 +0200 Subject: [PATCH 18/23] [algorithms][is_valid] fix namespace in comment --- include/boost/geometry/algorithms/detail/is_valid/ring.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/boost/geometry/algorithms/detail/is_valid/ring.hpp b/include/boost/geometry/algorithms/detail/is_valid/ring.hpp index c88df79b0..628fb4df7 100644 --- a/include/boost/geometry/algorithms/detail/is_valid/ring.hpp +++ b/include/boost/geometry/algorithms/detail/is_valid/ring.hpp @@ -1,6 +1,6 @@ // Boost.Geometry (aka GGL, Generic Geometry Library) -// Copyright (c) 2014, Oracle and/or its affiliates. +// Copyright (c) 2014-2015, Oracle and/or its affiliates. // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle @@ -144,7 +144,7 @@ struct is_valid_ring }; -}} // namespace dispatch +}} // namespace detail::is_valid #endif // DOXYGEN_NO_DETAIL From 0f8df37aca1d6693eb934a3934760ba9c9f5db40 Mon Sep 17 00:00:00 2001 From: Menelaos Karavelas Date: Wed, 4 Feb 2015 01:09:35 +0200 Subject: [PATCH 19/23] [test][algorithms][is_valid] add a few more test cases --- test/algorithms/is_valid.cpp | 64 ++++++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) diff --git a/test/algorithms/is_valid.cpp b/test/algorithms/is_valid.cpp index 36e7d78df..ab8d205cc 100644 --- a/test/algorithms/is_valid.cpp +++ b/test/algorithms/is_valid.cpp @@ -604,6 +604,52 @@ void test_open_polygons() false); test::apply(from_wkt("POLYGON((-10 -10,1 0,1 1,0 1),(-10 -10,-10 10,10 10,10 -10))"), false); + + test::apply + (from_wkt("POLYGON((-6 -10,-6.6923076923076925 -6.711538461538462,\ + -9 -7,-8.824742268041238 -6.123711340206185,\ + -10 -6,-8.583333333333332 -4.916666666666667,\ + -8.094117647058823 -2.4705882352941173,-10 -3,\ + -8.526315789473683 -0.05263157894736803,-10 1,\ + -10 10,-7.764705882352941 8.509803921568627,\ + -7.65090909090909 7.789090909090909,-10 10,\ + -7.574468085106383 7.304964539007091,-7.4375 6.4375,\ + -6.5 5.5,-6.4 6,-7.574468085106383 7.304964539007091,\ + -7.65090909090909 7.789090909090909,\ + -6.297029702970297 6.514851485148515,\ + 0 0,-6.297029702970297 6.514851485148515,\ + -4.848484848484849 5.151515151515151,-4 6,\ + -6.117647058823529 7.411764705882352,\ + 0 0,-6.11764705882353 7.411764705882353,\ + -7.764705882352941 8.509803921568627,-8 10,\ + -2.9473684210526314 7.052631578947368,-2 8,\ + -0.17821782178217824 6.633663366336634,1 10,\ + 1.8095238095238098 5.142857142857142,\ + 3.2038834951456314 4.097087378640777,7 7,\ + 3.7142857142857144 3.7142857142857144,\ + 4.4 3.1999999999999997,8 2,\ + 6.540540540540541 1.5945945945945947,10 -1,\ + 7.454545454545455 -4.393939393939394,8 -5,\ + 7.320754716981132 -4.716981132075472,7 -6,\ + 6.062068965517241 -5.117241379310345,\ + 4.9504132231404965 -5.256198347107438,\ + 6.1506849315068495 -7.123287671232877,9 -8,\ + 6.548387096774194 -7.741935483870968,8 -10,\ + 5.906976744186046 -7.674418604651163,\ + 3.9107142857142856 -7.464285714285714,4 -8,\ + 2.8043478260869565 -7.3478260869565215,\ + 1.7829457364341086 -7.24031007751938,2 -8,\ + 1.0728476821192054 -7.1655629139072845,\ + -4.3583617747440275 -6.593856655290103,-5 -9,\ + -5.2020725388601035 -7.720207253886011,-6 -10),\ + (5.127659574468085 -6.808510638297872,\ + 3.72972972972973 -6.378378378378379,\ + 3.571428571428571 -5.428571428571429,\ + 3.8539325842696632 -5.393258426966292,\ + 5.127659574468085 -6.808510638297872),\ + (-5.5 4.5,-6.5 5.5,-6.4 6,\ + -5.263157894736842 4.736842105263158,-5.5 4.5))"), + false); } template @@ -718,6 +764,24 @@ void test_open_multipolygons() // and the invalid case: test::apply(from_wkt("MULTIPOLYGON(((0 0,100 0,100 100,0 100),(3 3,3 97,97 97,97 3)),((2 2,98 2,98 98,2 98),(1 1,1 99,99 99,99 1)))"), false); + + test::apply + (from_wkt("MULTIPOLYGON(((-1 4,8 -10,-10 10,7 -6,8 -2,\ + -10 10,-10 1,-3 -4,4 1,-1 2,4 3,-8 10,-5 -9,-1 6,-5 0)),\ + ((-10 -3,-8 1,2 -8,-2 6,-4 0,8 -5,-1 5,8 2)),\ + ((-6 -10,1 10,4 -8,-7 -2,2 0,-4 3,-10 9)),\ + ((10 -1,-2 8,-7 3,-6 8,-9 -7,7 -5)),\ + ((7 7,-4 -4,9 -8,-10 -6)))"), + false); + + test::apply + (from_wkt("MULTIPOLYGON(((-1 4,8 -10,-10 10,7 -6,8 -2,\ + -10 10,-10 1,-3 -4,4 1,-1 2,4 3,-8 10,-5 -9,-1 6,-5 0)),\ + ((-10 -3,-8 1,2 -8,-2 6,-4 0,8 -5,-1 5,8 2)),\ + ((-6 -10,-10 9,-4 3,2 0,-7 -2,4 -8,1 10)),\ + ((10 -1,-2 8,-7 3,-6 8,-9 -7,7 -5)),\ + ((7 7,-10 -6,9 -8,-4 -4)))"), + false); } BOOST_AUTO_TEST_CASE( test_is_valid_multipolygon ) From 5dfe36bae2bdb4624dd30142c54e5d20984fddd1 Mon Sep 17 00:00:00 2001 From: Menelaos Karavelas Date: Wed, 4 Feb 2015 10:18:14 +0200 Subject: [PATCH 20/23] [test][algorithms][set operations] add missing include --- test/algorithms/set_operations/test_get_turns_ll_invariance.hpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/algorithms/set_operations/test_get_turns_ll_invariance.hpp b/test/algorithms/set_operations/test_get_turns_ll_invariance.hpp index 3e9bb6051..7ea3359f6 100644 --- a/test/algorithms/set_operations/test_get_turns_ll_invariance.hpp +++ b/test/algorithms/set_operations/test_get_turns_ll_invariance.hpp @@ -14,6 +14,8 @@ #include +#include + #include #include From 1f7354ad127245a3fb87ef52651f63ddea5d7fcc Mon Sep 17 00:00:00 2001 From: Menelaos Karavelas Date: Wed, 4 Feb 2015 10:21:10 +0200 Subject: [PATCH 21/23] [test][algorithms][difference L/L] add more test cases --- .../difference/difference_linear_linear.cpp | 70 +++++++++++++++++++ 1 file changed, 70 insertions(+) diff --git a/test/algorithms/set_operations/difference/difference_linear_linear.cpp b/test/algorithms/set_operations/difference/difference_linear_linear.cpp index 4add23277..214c6abba 100644 --- a/test/algorithms/set_operations/difference/difference_linear_linear.cpp +++ b/test/algorithms/set_operations/difference/difference_linear_linear.cpp @@ -465,6 +465,76 @@ BOOST_AUTO_TEST_CASE( test_difference_linestring_linestring ) from_wkt("MULTILINESTRING((-3 6,-3 2),(-3 2,-3 5))"), "lldf28c" ); + + tester::apply + (from_wkt("LINESTRING(-7 -8,3 0,4 -1)"), + from_wkt("LINESTRING(-5 -4,3 0,4 -1,7 -4)"), + from_wkt("MULTILINESTRING((-7 -8,3 0))"), + "lldf29a" + ); + + tester::apply + (from_wkt("LINESTRING(-7 -8,3 0,4 -1,-7 10)"), + from_wkt("LINESTRING(-5 -4,3 0,4 -1,2 -1)"), + from_wkt("MULTILINESTRING((-7 -8,3 0),(3 0,-7 10))"), + "lldf29b" + ); + + tester::apply + (from_wkt("LINESTRING(-7 -8,3 0,4 -1,-7 10)"), + from_wkt("LINESTRING(-5 -4,3 0,4 -1,7 -4,2 -1)"), + from_wkt("MULTILINESTRING((-7 -8,3 0),(3 0,-7 10))"), + "lldf29c" + ); + + tester::apply + (from_wkt("LINESTRING(-5 -4,3 0,4 -1,7 -4,2 -1)"), + from_wkt("LINESTRING(-7 -8,3 0,4 -1,-7 10)"), + from_wkt("MULTILINESTRING((-5 -4,3 0),(4 -1,7 -4,2 -1))"), + "lldf29c-r" + ); + + tester::apply + (from_wkt("LINESTRING(-2 -2,-4 0,1 -8,-2 6,8 5,-7 -8,\ + 3 0,4 -1,-7 10,-4 10)"), + from_wkt("LINESTRING(-5 -4,3 0,4 -1,7 -4,2 -1,-4 -1,-2 6)"), + from_wkt("MULTILINESTRING((-2 -2,-4 0,1 -8,-2 6,8 5,-7 -8,\ + 3 0),(3 0,-7 10,-4 10))"), + "lldf29d" + ); + +#ifdef GEOMETRY_TEST_INCLUDE_FAILING_TESTS + tester::apply + (from_wkt("LINESTRING(8 5,5 1,-2 3,1 10)"), + from_wkt("LINESTRING(1.9375 1.875,\ + 1.7441860465116283 1.9302325581395348,\ + -0.7692307692307692 2.6483516483516487,\ + -2 3,-1.0071942446043165 5.316546762589928)"), + from_wkt("MULTILINESTRING()"), + "lldf30a" + ); + + tester::apply + (from_wkt("LINESTRING(1.9375 1.875,\ + 1.7441860465116283 1.9302325581395348,\ + -0.7692307692307692 2.6483516483516487,\ + -2 3,-1.0071942446043165 5.316546762589928)"), + from_wkt("LINESTRING(8 5,5 1,-2 3,1 10)"), + from_wkt("MULTILINESTRING()"), + "lldf30b" + ); + + tester::apply + (from_wkt("LINESTRING(5 -8,-7 -6,-3 6,-3 1,-5 4,-1 0,8 5,\ + 5 1,-2 3,1 10,8 5,6 2,7 4)"), + from_wkt("LINESTRING(1.9375 1.875,\ + 1.7441860465116283 1.9302325581395348,\ + -0.7692307692307692 2.6483516483516487,\ + -2 3,-1.0071942446043165 5.316546762589928)"), + from_wkt("MULTILINESTRING()"), + "lldf30c" + ); +#endif } From 04814e53038a325ea5952b44104dc11fad5c9407 Mon Sep 17 00:00:00 2001 From: Menelaos Karavelas Date: Wed, 4 Feb 2015 10:27:18 +0200 Subject: [PATCH 22/23] [test][algorithms][union] add one more test case for union(linestring, linestring) --- .../set_operations/union/union_linear_linear.cpp | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/test/algorithms/set_operations/union/union_linear_linear.cpp b/test/algorithms/set_operations/union/union_linear_linear.cpp index 461653d0b..925c8363b 100644 --- a/test/algorithms/set_operations/union/union_linear_linear.cpp +++ b/test/algorithms/set_operations/union/union_linear_linear.cpp @@ -461,6 +461,19 @@ BOOST_AUTO_TEST_CASE( test_union_linestring_linestring ) (2 2,5 -1,15 2,18 0))"), "llu21a" ); + + tester::apply + (from_wkt("LINESTRING(-2 -2,-4 0,1 -8,-2 6,8 5,-7 -8,3 0,\ + 4 -1,-7 10,-4 10)"), + from_wkt("LINESTRING(-5 -4,3 0,4 -1,7 -4,2 -1,-4 -1,-2 6)"), + from_wkt("MULTILINESTRING((-2 -2,-4 0,1 -8,-2 6,8 5,-7 -8,3 0,\ + 4 -1,-7 10,-4 10),(-5 -4,3 0),\ + (4 -1,7 -4,2 -1,-4 -1,-2 6))"), + from_wkt("MULTILINESTRING((-5 -4,3 0,4 -1,7 -4,2 -1,-4 -1,-2 6),\ + (-2 -2,-4 0,1 -8,-2 6,8 5,-7 -8,3 0),\ + (3 0,-7 10,-4 10))"), + "llu22" + ); } From 80ade1ebec984788b2e88e641f8efca20047d15f Mon Sep 17 00:00:00 2001 From: Menelaos Karavelas Date: Wed, 4 Feb 2015 10:30:42 +0200 Subject: [PATCH 23/23] [test][algorithms][sym difference] add one more test case; the test case currently fails because of the way the testing/checking is done, and is currently disabled; the test case will be re-enabled once the testing/checking part is re-designed; --- .../sym_difference_linear_linear.cpp | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/test/algorithms/set_operations/sym_difference/sym_difference_linear_linear.cpp b/test/algorithms/set_operations/sym_difference/sym_difference_linear_linear.cpp index c0f08eafe..bc72e1037 100644 --- a/test/algorithms/set_operations/sym_difference/sym_difference_linear_linear.cpp +++ b/test/algorithms/set_operations/sym_difference/sym_difference_linear_linear.cpp @@ -628,6 +628,30 @@ BOOST_AUTO_TEST_CASE( test_sym_difference_linestring_multilinestring ) (0 1,1 0),(19 0,20 1),(2 2,5 -1,15 2,25 0))"), "lmlsdf18d" ); + +#ifdef GEOMETRY_TEST_INCLUDE_FAILING_TESTS + tester::apply + (from_wkt("LINESTRING(1 5,4 2,1 -1.1,1 6,1 189.7654,2 5,-0.7654 3)"), + from_wkt("MULTILINESTRING((2 5,-0.7654 2),\ + (-1032.34324 4,1 5,9 7,3 9,0.2 5,1 -0.3),\ + (1 0.9,1 6,1 -0.6,2.232432 -0.7654,0.9 3,1 5,\ + -0.7654 9,3 0.1,9 0,-6 8,-0.7 8,0 1,-1032.34324 0))"), + /* + from_wkt("MULTILINESTRING((-0.7654 2,2 5),\ + (1 -0.3,0.2 5,3 9,9 7,1 5,-1032.34 4),\ + (-1032.34 0,0 1,-0.7 8,-6 8,9 0,3 0.1,\ + -0.7654 9,1 5,0.9 3,2.23243 -0.7654,1 -0.6),\ + (-0.7654 3,2 5,1 189.765,1 6),\ + (1 -0.6,1 -1.1,4 2,1 5))"), + */ + from_wkt("MULTILINESTRING((1 5,4 2,1 -1.1,1 -0.6),\ + (1 6,1 189.7654,2 5,-0.7654 3),(2 5,-0.7654 2),\ + (-1032.34324 4,1 5,9 7,3 9,0.2 5,1 -0.3),\ + (1 -0.6,2.232432 -0.7654,0.9 3,1 5,-0.7654 9,\ + 3 0.1,9 0,-6 8,-0.7 8,0 1,-1032.34324 0))"), + "lmlsdf19" + ); +#endif }