From 533543e86b735e19f449fb178baf25ca848c4ded Mon Sep 17 00:00:00 2001 From: Barend Gehrels Date: Wed, 14 Oct 2015 17:15:53 +0200 Subject: [PATCH] [traverse][robustness] in case of cc, instead of arbitrary candidate, take candidate with largest remaining distance. This fixes some errors if rescaling is turned off. --- .../detail/overlay/get_turn_info.hpp | 26 +++++++++++++++++-- .../detail/overlay/get_turn_info_helpers.hpp | 4 +-- .../algorithms/detail/overlay/get_turns.hpp | 6 ++--- .../detail/overlay/traversal_info.hpp | 2 +- .../algorithms/detail/overlay/traverse.hpp | 24 +++++++++++++++++ .../algorithms/detail/overlay/turn_info.hpp | 9 +++++-- .../algorithms/detail/relate/turns.hpp | 4 +-- test/algorithms/overlay/get_turns.cpp | 2 +- .../algorithms/set_operations/union/union.cpp | 6 +---- 9 files changed, 65 insertions(+), 18 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 717f0b47a..ac36c530b 100644 --- a/include/boost/geometry/algorithms/detail/overlay/get_turn_info.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/get_turn_info.hpp @@ -585,8 +585,8 @@ struct collinear : public base_turn_handler typename SidePolicy > static inline void apply( - Point1 const& , Point1 const& , Point1 const& , - Point2 const& , Point2 const& , Point2 const& , + Point1 const& , Point1 const& pj, Point1 const& pk, + Point2 const& , Point2 const& qj, Point2 const& qk, TurnInfo& ti, IntersectionInfo const& info, DirInfo const& dir_info, @@ -623,8 +623,30 @@ struct collinear : public base_turn_handler { ui_else_iu(product == 1, ti); } + + // Calculate remaining distance. If it continues collinearly it is + // measured until the end of the next segment + ti.operations[0].remaining_distance + = side_p == 0 + ? distance_measure(ti.point, pk) + : distance_measure(ti.point, pj); + ti.operations[1].remaining_distance + = side_q == 0 + ? distance_measure(ti.point, qk) + : distance_measure(ti.point, qj); } + template + static inline typename geometry::coordinate_type::type + distance_measure(Point1 const& a, Point2 const& b) + { + // TODO: use comparable distance for point-point instead - but that + // causes currently cycling include problems + typedef typename geometry::coordinate_type::type ctype; + ctype const dx = get<0>(a) - get<0>(b); + ctype const dy = get<1>(b) - get<1>(b); + return dx * dx + dy * dy; + } }; template diff --git a/include/boost/geometry/algorithms/detail/overlay/get_turn_info_helpers.hpp b/include/boost/geometry/algorithms/detail/overlay/get_turn_info_helpers.hpp index e4f8de42e..ee0a93ae7 100644 --- a/include/boost/geometry/algorithms/detail/overlay/get_turn_info_helpers.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/get_turn_info_helpers.hpp @@ -23,9 +23,9 @@ namespace detail { namespace overlay { enum turn_position { position_middle, position_front, position_back }; -template +template struct turn_operation_linear - : public turn_operation + : public turn_operation { turn_operation_linear() : position(position_middle) diff --git a/include/boost/geometry/algorithms/detail/overlay/get_turns.hpp b/include/boost/geometry/algorithms/detail/overlay/get_turns.hpp index 098c7b564..b2b97c033 100644 --- a/include/boost/geometry/algorithms/detail/overlay/get_turns.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/get_turns.hpp @@ -802,19 +802,19 @@ template ::type, typename TagBase2 = typename topological_tag_base::type> struct turn_operation_type { - typedef overlay::turn_operation type; + typedef overlay::turn_operation::type, SegmentRatio> type; }; template struct turn_operation_type { - typedef overlay::turn_operation_linear type; + typedef overlay::turn_operation_linear::type, SegmentRatio> type; }; template struct turn_operation_type { - typedef overlay::turn_operation_linear type; + typedef overlay::turn_operation_linear::type, SegmentRatio> type; }; }} // namespace detail::get_turns diff --git a/include/boost/geometry/algorithms/detail/overlay/traversal_info.hpp b/include/boost/geometry/algorithms/detail/overlay/traversal_info.hpp index 6ee32c17c..8cabfb0d8 100644 --- a/include/boost/geometry/algorithms/detail/overlay/traversal_info.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/traversal_info.hpp @@ -25,7 +25,7 @@ namespace detail { namespace overlay template -struct traversal_turn_operation : public turn_operation +struct traversal_turn_operation : public turn_operation { enrichment_info enriched; visit_info visited; diff --git a/include/boost/geometry/algorithms/detail/overlay/traverse.hpp b/include/boost/geometry/algorithms/detail/overlay/traverse.hpp index 803a16471..45e15d13d 100644 --- a/include/boost/geometry/algorithms/detail/overlay/traverse.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/traverse.hpp @@ -174,7 +174,17 @@ inline bool select_next_ip(operation_type operation, { return false; } + bool has_tp = false; + + typedef typename std::iterator_traits + < + Iterator + >::value_type operation_type; + + typename operation_type::comparable_distance_type + max_remaining_distance = 0; + selected = boost::end(turn.operations); for (Iterator it = boost::begin(turn.operations); it != boost::end(turn.operations); @@ -206,10 +216,24 @@ inline bool select_next_ip(operation_type operation, ) ) { + if (it->operation == operation_continue) + { + max_remaining_distance = it->remaining_distance; + } selected = it; debug_traverse(turn, *it, " Candidate"); has_tp = true; } + + if (it->operation == operation_continue && has_tp) + { + if (it->remaining_distance > max_remaining_distance) + { + max_remaining_distance = it->remaining_distance; + selected = it; + debug_traverse(turn, *it, " Candidate override"); + } + } } if (has_tp) diff --git a/include/boost/geometry/algorithms/detail/overlay/turn_info.hpp b/include/boost/geometry/algorithms/detail/overlay/turn_info.hpp index 26669a4b1..6cb4d9cbb 100644 --- a/include/boost/geometry/algorithms/detail/overlay/turn_info.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/turn_info.hpp @@ -12,6 +12,7 @@ #include +#include #include namespace boost { namespace geometry @@ -54,15 +55,19 @@ enum method_type The class is to be included in the turn_info class, either direct or a derived or similar class with more (e.g. enrichment) information. */ -template +template struct turn_operation { operation_type operation; segment_identifier seg_id; SegmentRatio fraction; + typedef typename coordinate_type::type comparable_distance_type; + comparable_distance_type remaining_distance; + inline turn_operation() : operation(operation_none) + , remaining_distance(0) {} }; @@ -80,7 +85,7 @@ template < typename Point, typename SegmentRatio, - typename Operation = turn_operation, + typename Operation = turn_operation, typename Container = boost::array > struct turn_info diff --git a/include/boost/geometry/algorithms/detail/relate/turns.hpp b/include/boost/geometry/algorithms/detail/relate/turns.hpp index d54948e1f..09d74dec3 100644 --- a/include/boost/geometry/algorithms/detail/relate/turns.hpp +++ b/include/boost/geometry/algorithms/detail/relate/turns.hpp @@ -128,8 +128,8 @@ struct get_turns template struct op_to_int { - template - inline int operator()(detail::overlay::turn_operation const& op) const + template + inline int operator()(Operation const& op) const { switch(op.operation) { diff --git a/test/algorithms/overlay/get_turns.cpp b/test/algorithms/overlay/get_turns.cpp index 90cc08277..4efea8e41 100644 --- a/test/algorithms/overlay/get_turns.cpp +++ b/test/algorithms/overlay/get_turns.cpp @@ -44,7 +44,7 @@ // To test that "get_turns" can be called using additional information template -struct my_turn_op : public bg::detail::overlay::turn_operation +struct my_turn_op : public bg::detail::overlay::turn_operation { }; diff --git a/test/algorithms/set_operations/union/union.cpp b/test/algorithms/set_operations/union/union.cpp index 09c993db8..9cf245de7 100644 --- a/test/algorithms/set_operations/union/union.cpp +++ b/test/algorithms/set_operations/union/union.cpp @@ -248,7 +248,7 @@ void test_areal() 1, 0, -1, - 313.36036462, 0.01); + 313.36036462, 0.1); // SQL Server gives: 313.360374193241 // PostGIS gives: 313.360364623393 @@ -319,10 +319,8 @@ void test_areal() 1, 0, if_typed(18, 23), 4.60853); #endif -#if ! defined(BOOST_GEOMETRY_NO_ROBUSTNESS) test_one("buffer_rt_g", buffer_rt_g[0], buffer_rt_g[1], 1, 0, if_typed(18, 17), 16.571); -#endif test_one("buffer_rt_g_rev", buffer_rt_g[1], buffer_rt_g[0], 1, 0, if_typed(18, 17), 16.571); @@ -355,10 +353,8 @@ void test_areal() test_one("buffer_rt_m2_rev", buffer_rt_m2[1], buffer_rt_m2[0], 1, 0, if_typed_tt(20, 19), 21.4853); -#if ! defined(BOOST_GEOMETRY_NO_ROBUSTNESS) test_one("buffer_rt_q", buffer_rt_q[0], buffer_rt_q[1], 1, 0, 18, 18.5710); -#endif test_one("buffer_rt_q_rev", buffer_rt_q[1], buffer_rt_q[0], 1, 0, 18, 18.5710);