From c5cbf5e6f2d7d021ef39af5ffb6cf9e67b32e7b6 Mon Sep 17 00:00:00 2001 From: Adam Wulkiewicz Date: Wed, 12 Feb 2014 03:38:26 +0100 Subject: [PATCH 1/2] 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); From b943f3de26f3762104e71364517ae328a734990e Mon Sep 17 00:00:00 2001 From: Adam Wulkiewicz Date: Wed, 12 Feb 2014 16:53:06 +0100 Subject: [PATCH 2/2] get_turns(L,L) another special case handled --- .../detail/overlay/get_turn_info_ll.hpp | 11 +++--- .../overlay/get_turns_linear_linear.cpp | 34 +++++++++++++++++++ 2 files changed, 41 insertions(+), 4 deletions(-) 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 7c99d6d89..8840952db 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 @@ -490,7 +490,9 @@ struct get_turn_info_linear_linear bool append0_first = enable_first && (p0_first || q0_first); bool append0_last = enable_last && (p0_last || q0_last); - result_ignore_ip0 = append0_last; + result_ignore_ip0 = !opposite ? // <=> ip_count == 1 || ip_count == 2 && !opposite + append0_last : + (append0_last && p0j); if ( append0_first || append0_last ) { @@ -529,7 +531,9 @@ struct get_turn_info_linear_linear bool append1_first = enable_first && (p1_first || q1_first); bool append1_last = enable_last && (p1_last || q1_last); - result_ignore_ip1 = append1_last; + result_ignore_ip1 = !opposite ? // <=> ip_count == 2 && !opposite + append1_last : + (append1_last && q1j); if ( append1_first || append1_last ) { @@ -554,8 +558,7 @@ struct get_turn_info_linear_linear } } - return ip_count == 1 ? result_ignore_ip0 : - !opposite ? result_ignore_ip1 : result_ignore_ip0; + return result_ignore_ip0 || result_ignore_ip1; } template diff --git a/test/algorithms/overlay/get_turns_linear_linear.cpp b/test/algorithms/overlay/get_turns_linear_linear.cpp index 5877453a4..57584d41d 100644 --- a/test/algorithms/overlay/get_turns_linear_linear.cpp +++ b/test/algorithms/overlay/get_turns_linear_linear.cpp @@ -138,6 +138,22 @@ void test_geometry(std::string const& wkt1, std::string const& wkt2, test_geometry(wkt1, wkt2, expected); } +struct expected_pusher +{ + expected_pusher & operator()(std::string const& ex) + { + vec.push_back(ex); + return *this; + } + std::vector vec; +}; + +expected_pusher expected(std::string const& ex) +{ + expected_pusher res; + return res(ex); +} + //TEST //#include //#include @@ -192,12 +208,30 @@ void test_all() test_geometry("LINESTRING(0 0,10 0)", "LINESTRING(-1 -1,1 0,10 0,20 -1)", "mii", "txu"); test_geometry("LINESTRING(0 0,10 0)", "LINESTRING(20 -1,10 0,1 0,-1 -1)", "miu", "txi"); + test_geometry("LINESTRING(-1 1,0 0,1 0,4 0,5 5,10 5,15 0,31 0)", + "LINESTRING(-1 -1,0 0,1 0,2 0,2.5 1,3 0,30 0)", + expected("tii")("ecc")("muu")("mii")("muu")("mii")("mux").vec); + test_geometry("LINESTRING(-1 1,0 0,1 0,4 0,5 5,10 5,15 0,31 0)", + "LINESTRING(30 0,3 0,2.5 1,2 0,1 0,0 0,-1 -1)", + expected("tiu")("ecc")("mui")("miu")("mui")("miu")("mui").vec); + test_geometry("LINESTRING(31 0,15 0,10 5,5 5,4 0,1 0,0 0,-1 1)", + "LINESTRING(-1 -1,0 0,1 0,2 0,2.5 1,3 0,30 0)", + expected("tui")("ecc")("miu")("mui")("miu")("mui")("mix").vec); + test_geometry("LINESTRING(31 0,15 0,10 5,5 5,4 0,1 0,0 0,-1 1)", + "LINESTRING(30 0,3 0,2.5 1,2 0,1 0,0 0,-1 -1)", + expected("tuu")("ecc")("mii")("muu")("mii")("muu")("mii").vec); + //if ( boost::is_same::value ) //{ // to_svg("LINESTRING(0 0,1 0,2 0,2.5 0,3 1)", "LINESTRING(0 0,2 0,2.5 0,3 1)", "test11.svg"); // to_svg("LINESTRING(0 0,1 0,2 0,2.5 0,3 1)", "LINESTRING(3 1,2.5 0,2 0,0 0)", "test12.svg"); // to_svg("LINESTRING(-1 1,0 0,1 0,4 0,5 5,10 5,15 0,20 0,30 0,31 1)", "LINESTRING(30 0,3 0,2.5 1,2 0,1 0,0 0,-1 -1)", "test21.svg"); // to_svg("LINESTRING(-1 1,0 0,1 0,4 0,5 5,10 5,15 0,20 0,30 0,31 1)", "LINESTRING(-1 -1,0 0,1 0,2 0,2.5 1,3 0,30 0)", "test22.svg"); + + // to_svg("LINESTRING(-1 1,0 0,1 0,4 0,5 5,10 5,15 0,31 0)", "LINESTRING(-1 -1,0 0,1 0,2 0,2.5 1,3 0,30 0)", "test31.svg"); + // to_svg("LINESTRING(-1 1,0 0,1 0,4 0,5 5,10 5,15 0,31 0)", "LINESTRING(30 0,3 0,2.5 1,2 0,1 0,0 0,-1 -1)", "test32.svg"); + // to_svg("LINESTRING(31 0,15 0,10 5,5 5,4 0,1 0,0 0,-1 1)", "LINESTRING(-1 -1,0 0,1 0,2 0,2.5 1,3 0,30 0)", "test33.svg"); + // to_svg("LINESTRING(31 0,15 0,10 5,5 5,4 0,1 0,0 0,-1 1)", "LINESTRING(30 0,3 0,2.5 1,2 0,1 0,0 0,-1 -1)", "test34.svg"); //} }