From c5cbf5e6f2d7d021ef39af5ffb6cf9e67b32e7b6 Mon Sep 17 00:00:00 2001 From: Adam Wulkiewicz Date: Wed, 12 Feb 2014 03:38:26 +0100 Subject: [PATCH] relate() - added BoundaryQuery parameter to boundary_checker, makes possible to specify if the boundary should be at the first point, last or might be on both, etc. --- .../detail/relate/linear_linear.hpp | 87 ++++++++++++++----- 1 file changed, 66 insertions(+), 21 deletions(-) diff --git a/include/boost/geometry/algorithms/detail/relate/linear_linear.hpp b/include/boost/geometry/algorithms/detail/relate/linear_linear.hpp index cb9cdc937..2201a853e 100644 --- a/include/boost/geometry/algorithms/detail/relate/linear_linear.hpp +++ b/include/boost/geometry/algorithms/detail/relate/linear_linear.hpp @@ -53,6 +53,8 @@ inline void update_result(result & res) // boundary_checker +enum boundary_query { boundary_front, boundary_back, boundary_front_explicit, boundary_back_explicit, boundary_any }; + template ::type> class boundary_checker {}; @@ -68,7 +70,7 @@ public: , geometry(g) {} - // TODO: optimization expect ENTRY or EXIT + template bool is_boundary(point_type const& pt, segment_identifier const& sid) { // TODO: replace with assert? @@ -77,11 +79,28 @@ public: // TODO: handle also linestrings with points_num == 2 and equals(front, back) - treat like point? - return has_boundary - && ( ( sid.segment_index == 0 - && detail::equals::equals_point_point(pt, range::front(geometry)) ) - || ( sid.segment_index + 2 == geometry::num_points(geometry) - && detail::equals::equals_point_point(pt, range::back(geometry)) ) ); + if ( !has_boundary ) + return false; + + if ( BoundaryQuery == boundary_front_explicit || BoundaryQuery == boundary_back_explicit ) + return true; + + if ( BoundaryQuery == boundary_front ) + return sid.segment_index == 0 + && detail::equals::equals_point_point(pt, range::front(geometry)); + + if ( BoundaryQuery == boundary_back ) + return sid.segment_index + 2 == geometry::num_points(geometry) + && detail::equals::equals_point_point(pt, range::back(geometry)); + + if ( BoundaryQuery == boundary_any ) + return sid.segment_index == 0 + && detail::equals::equals_point_point(pt, range::front(geometry)) + || sid.segment_index + 2 == geometry::num_points(geometry) + && detail::equals::equals_point_point(pt, range::back(geometry)); + + BOOST_ASSERT(false); + return false; } private: @@ -99,7 +118,7 @@ public: : is_filled(false), geometry(g) {} - // TODO: optimization expect ENTRY or EXIT + template bool is_boundary(point_type const& pt, segment_identifier const& sid) { typedef typename boost::range_size::type size_type; @@ -109,8 +128,23 @@ public: if ( multi_count < 1 ) return false; - if ( sid.segment_index != 0 && sid.segment_index + 2 != geometry::num_points(geometry) ) - return false; + if ( BoundaryQuery == boundary_front || BoundaryQuery == boundary_front_explicit ) + { + if ( sid.segment_index != 0 ) + return false; + } + + if ( BoundaryQuery == boundary_back || BoundaryQuery == boundary_back_explicit ) + { + if ( sid.segment_index + 2 != geometry::num_points(geometry) ) + return false; + } + + if ( BoundaryQuery == boundary_any ) + { + if ( sid.segment_index != 0 && sid.segment_index + 2 != geometry::num_points(geometry) ) + return false; + } if ( ! is_filled ) { @@ -444,10 +478,14 @@ struct linear_linear update_result(res); // going inside on boundary point - if ( boundary_checker.is_boundary(it->point, seg_id) ) + if ( boundary_checker.template is_boundary(it->point, seg_id) ) { - // TODO: check operation_blocked here - only for Ls, for MLs it's not enough - if ( other_boundary_checker.is_boundary(it->point, other_id) ) + bool other_b = + it->operations[OtherOpId].operation == overlay::operation_blocked ? + other_boundary_checker.template is_boundary(it->point, other_id) : + other_boundary_checker.template is_boundary(it->point, other_id); + + if ( other_b ) { update_result(res); } @@ -481,12 +519,13 @@ struct linear_linear if ( is_last_point ) { // check if this is indeed the boundary point -// TODO: For Linestring it's enough to check has_boundary -// because we know that this is the last point of the range - if ( boundary_checker.is_boundary(it->point, seg_id) ) + if ( boundary_checker.template is_boundary(it->point, seg_id) ) { - // TODO: check operation_blocked here - only for Ls, for MLs it's not enough - if ( other_boundary_checker.is_boundary(it->point, other_id) ) + bool other_b = + it->operations[OtherOpId].operation == overlay::operation_blocked ? + other_boundary_checker.template is_boundary(it->point, other_id) : + other_boundary_checker.template is_boundary(it->point, other_id); + if ( other_b ) { update_result(res); } @@ -512,11 +551,17 @@ struct linear_linear } else { - // TODO: check operation_blocked here - only for Ls, for MLs it's not enough - if ( boundary_checker.is_boundary(it->point, seg_id) ) + bool this_b = + is_last_point ? + boundary_checker.template is_boundary(it->point, seg_id) : + boundary_checker.template is_boundary(it->point, seg_id); + if ( this_b ) { - // TODO: check operation_blocked here - only for Ls, for MLs it's not enough - if ( other_boundary_checker.is_boundary(it->point, other_id) ) + bool other_b = + it->operations[OtherOpId].operation == overlay::operation_blocked ? + other_boundary_checker.template is_boundary(it->point, other_id) : + other_boundary_checker.template is_boundary(it->point, other_id); + if ( other_b ) update_result(res); else update_result(res);