From 1cd17cbe452b378bacb7dfaf3611e4569007c8e3 Mon Sep 17 00:00:00 2001 From: Barend Gehrels Date: Fri, 3 Feb 2012 21:14:13 +0000 Subject: [PATCH] Fixed wrong behaviour for intersects/disjoint algorithms for pair of linestrings which were degenerate, or collinear, or one starting in the middle from the other. Also removed the never-used parallel option. Throws an error at unexpected input (robustness errors) [SVN r76859] --- .../overlay/calculate_distance_policy.hpp | 3 + .../detail/overlay/get_turn_info.hpp | 78 ++++++++++++++++--- .../boost/geometry/algorithms/disjoint.hpp | 21 ++++- .../boost/geometry/policies/relate/de9im.hpp | 8 -- .../geometry/policies/relate/direction.hpp | 16 ++-- .../policies/relate/intersection_points.hpp | 5 +- .../boost/geometry/policies/relate/tupled.hpp | 9 --- 7 files changed, 97 insertions(+), 43 deletions(-) diff --git a/include/boost/geometry/algorithms/detail/overlay/calculate_distance_policy.hpp b/include/boost/geometry/algorithms/detail/overlay/calculate_distance_policy.hpp index 6cfdbe1b8..3e6a8897f 100644 --- a/include/boost/geometry/algorithms/detail/overlay/calculate_distance_policy.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/calculate_distance_policy.hpp @@ -30,6 +30,9 @@ namespace detail { namespace overlay */ struct calculate_distance_policy { + static bool const include_no_turn = false; + static bool const include_degenerate = false; + template static inline void apply(Info& info, Point1 const& p1, Point2 const& p2) { 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 4fc91dd0c..782c04469 100644 --- a/include/boost/geometry/algorithms/detail/overlay/get_turn_info.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/get_turn_info.hpp @@ -23,6 +23,25 @@ namespace boost { namespace geometry { +#if ! defined(BOOST_GEOMETRY_OVERLAY_NO_THROW) +class turn_info_exception : public geometry::exception +{ + std::string message; +public: + + // NOTE: "char" will be replaced by enum in future version + inline turn_info_exception(char const method) + { + message = "Boost.Geometry Turn exception: "; + message += method; + } + + virtual char const* what() const throw() + { + return message.c_str(); + } +}; +#endif #ifndef DOXYGEN_NO_DETAIL namespace detail { namespace overlay @@ -677,6 +696,18 @@ struct crosses : public base_turn_handler } }; +template +struct only_convert +{ + template + static inline void apply(TurnInfo& ti, IntersectionInfo const& intersection_info) + { + ti.method = method_collinear; + geometry::convert(intersection_info.intersections[0], ti.point); + ti.operations[0].operation = operation_continue; + ti.operations[1].operation = operation_continue; + } +}; /*! \brief Policy doing nothing @@ -686,6 +717,9 @@ struct crosses : public base_turn_handler */ struct assign_null_policy { + static bool const include_no_turn = false; + static bool const include_degenerate = false; + template static inline void apply(Info& , Point1 const& , Point2 const& ) {} @@ -703,14 +737,16 @@ struct assign_null_policy \tparam TurnInfo type of class getting intersection and turn info \tparam AssignPolicy policy to assign extra info, e.g. to calculate distance from segment's first points - to intersection points + to intersection points. + It also defines if a certain class of points + (degenerate, non-turns) should be included. */ template < typename Point1, typename Point2, typename TurnInfo, - typename AssignPolicy = assign_null_policy + typename AssignPolicy > struct get_turn_info { @@ -749,10 +785,20 @@ struct get_turn_info // Select method and apply switch(method) { - case 'a' : - case 'f' : - case 's' : - case 'd' : + case 'a' : // collinear, "at" + case 'f' : // collinear, "from" + case 's' : // starts from the middle + if (AssignPolicy::include_no_turn + && result.template get<0>().count > 0) + { + only_convert::apply(tp, + result.template get<0>()); + AssignPolicy::apply(tp, pi, qi); + *out++ = tp; + } + break; + + case 'd' : // disjoint: never do anything break; case 'm' : @@ -873,13 +919,23 @@ struct get_turn_info } break; case '0' : - // degenerate points - break; + { + // degenerate points + if (AssignPolicy::include_degenerate) + { + only_convert::apply(tp, result.template get<0>()); + AssignPolicy::apply(tp, pi, qi); + *out++ = tp; + } + } + break; default : -#ifdef BOOST_GEOMETRY_DEBUG_GET_TURNS - std::cout << "get_turns, nyi: " << method << std::endl; + { +#if ! defined(BOOST_GEOMETRY_OVERLAY_NO_THROW) + throw turn_info_exception(method); #endif - break; + } + break; } return out; diff --git a/include/boost/geometry/algorithms/disjoint.hpp b/include/boost/geometry/algorithms/disjoint.hpp index 67cba36a2..8e378510f 100644 --- a/include/boost/geometry/algorithms/disjoint.hpp +++ b/include/boost/geometry/algorithms/disjoint.hpp @@ -44,6 +44,19 @@ namespace boost { namespace geometry namespace detail { namespace disjoint { +struct assign_disjoint_policy +{ + // We want to include all points: + static bool const include_no_turn = true; + static bool const include_degenerate = true; + + // We don't assign extra info: + template + static inline void apply(Info& , Point1 const& , Point2 const& ) + {} +}; + + template struct disjoint_linear { @@ -54,12 +67,14 @@ struct disjoint_linear typedef overlay::turn_info turn_info; std::deque turns; - // Get (and stop on) any intersection + // Specify two policies: + // 1) Stop at any intersection + // 2) In assignment, include also degenerate points (which are normally skipped) disjoint_interrupt_policy policy; geometry::get_turns < - false, false, - overlay::assign_null_policy + false, false, + assign_disjoint_policy >(geometry1, geometry2, turns, policy); if (policy.has_intersections) { diff --git a/include/boost/geometry/policies/relate/de9im.hpp b/include/boost/geometry/policies/relate/de9im.hpp index a4ceb0630..766d80b22 100644 --- a/include/boost/geometry/policies/relate/de9im.hpp +++ b/include/boost/geometry/policies/relate/de9im.hpp @@ -167,14 +167,6 @@ struct segments_de9im true); } - - static inline return_type parallel() - { - return de9im_segment(0,0, - -1, -1, 1, - -1, -1, 0, - 1, 0, 2, false, false, true); - } }; diff --git a/include/boost/geometry/policies/relate/direction.hpp b/include/boost/geometry/policies/relate/direction.hpp index 34c8b668b..65c60907a 100644 --- a/include/boost/geometry/policies/relate/direction.hpp +++ b/include/boost/geometry/policies/relate/direction.hpp @@ -32,6 +32,8 @@ namespace policies { namespace relate struct direction_type { + // NOTE: "char" will be replaced by enum in future version + inline direction_type(side_info const& s, char h, int ha, int hb, int da = 0, int db = 0, @@ -61,6 +63,8 @@ struct direction_type } + // TODO: replace this + // NOTE: "char" will be replaced by enum in future version // "How" is the intersection formed? char how; @@ -236,16 +240,12 @@ struct segments_direction return return_type('d', false); } - - static inline return_type parallel() - { - return return_type('p', false); - } - static inline return_type error(std::string const&) { - // msg - return return_type('d', false); + // Return "E" to denote error + // This will throw an error in get_turn_info + // TODO: change to enum or similar + return return_type('E', false); } private : diff --git a/include/boost/geometry/policies/relate/intersection_points.hpp b/include/boost/geometry/policies/relate/intersection_points.hpp index c360bf47a..69d36f363 100644 --- a/include/boost/geometry/policies/relate/intersection_points.hpp +++ b/include/boost/geometry/policies/relate/intersection_points.hpp @@ -169,10 +169,7 @@ struct segments_intersection_points { return return_type(); } - static inline return_type parallel() - { - return return_type(); - } + static inline return_type degenerate(S1 const& s, bool) { return_type result; diff --git a/include/boost/geometry/policies/relate/tupled.hpp b/include/boost/geometry/policies/relate/tupled.hpp index f74e667ed..853a8a26a 100644 --- a/include/boost/geometry/policies/relate/tupled.hpp +++ b/include/boost/geometry/policies/relate/tupled.hpp @@ -164,15 +164,6 @@ struct segments_tupled ); } - - static inline return_type parallel() - { - return boost::make_tuple - ( - Policy1::parallel(), - Policy2::parallel() - ); - } }; }} // namespace policies::relate