From 566957de29210114a06d22dc48e3a3174ad876b5 Mon Sep 17 00:00:00 2001 From: Adam Wulkiewicz Date: Wed, 30 Apr 2014 12:57:39 +0200 Subject: [PATCH 1/2] [test][get_turns] Add failing test cases for L/L --- .../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 30760b3bc..57a7e1af4 100644 --- a/test/algorithms/overlay/get_turns_linear_linear.cpp +++ b/test/algorithms/overlay/get_turns_linear_linear.cpp @@ -230,14 +230,16 @@ void test_all() // 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"); //} + // duplicated test_geometry("MULTILINESTRING((0 0,10 0,30 0))", "MULTILINESTRING((0 10,5 0,20 0,20 0,30 0),(2 0,2 0),(3 0,3 0,3 0))", expected("mii")("ccc")("ccc")("txx")); + // spike test_geometry("LINESTRING(2 2,5 -1,15 2,18 0,20 0)", "LINESTRING(30 0,19 0,18 0,0 0)", expected("iuu")("iuu")("tiu")("mxi")); - + // spike test_geometry("MULTILINESTRING((0 0,10 0,5 0))", "MULTILINESTRING((1 0,8 0,4 0))", expected("mii")("mix")("mux")("mui")("mix")("mii")("mxu")("mxi")); @@ -245,6 +247,24 @@ void test_all() /*test_geometry("MULTILINESTRING((0 0,10 0,5 0))", "MULTILINESTRING((1 0,8 0,4 0),(2 0,9 0,5 0))", expected("mii")("ccc")("ccc")("txx"));*/ + + // spike vs endpoint + test_geometry("MULTILINESTRING((0 0,10 0))", + "MULTILINESTRING((-1 0,0 0,-2 0),(11 0,10 0,12 0))", + expected("tuu")("txu")); + // non-spike similar + test_geometry("MULTILINESTRING((0 0,10 0))", + "MULTILINESTRING((-1 0,0 0,2 0))", + expected("tii")("mux")); + test_geometry("MULTILINESTRING((0 0,10 0))", + "MULTILINESTRING((-1 -1,0 0,2 0))", + expected("tii")("mux")); + test_geometry("MULTILINESTRING((0 0,10 0))", + "MULTILINESTRING((2 0,0 0,-1 0))", + expected("tiu")("mui")); + test_geometry("MULTILINESTRING((0 0,10 0))", + "MULTILINESTRING((2 0,0 0,-1 -1))", + expected("tiu")("mui")); } int test_main(int, char* []) From 9f1b9ff7baf9200c7dc0bd0ab27c80dcb0f98af2 Mon Sep 17 00:00:00 2001 From: Barend Gehrels Date: Wed, 30 Apr 2014 17:33:58 +0200 Subject: [PATCH 2/2] [overlay] Calculate ratio for segment intersection where one segment is degenerate --- .../geometry/policies/relate/direction.hpp | 9 +++ .../policies/relate/intersection_points.hpp | 22 +++++++ .../boost/geometry/policies/relate/tupled.hpp | 12 ++++ .../strategies/cartesian/cart_intersect.hpp | 63 ++++++++++++++----- .../segment_intersection_collinear.cpp | 45 ++++++++++--- 5 files changed, 129 insertions(+), 22 deletions(-) diff --git a/include/boost/geometry/policies/relate/direction.hpp b/include/boost/geometry/policies/relate/direction.hpp index 6d4946741..02fed94b1 100644 --- a/include/boost/geometry/policies/relate/direction.hpp +++ b/include/boost/geometry/policies/relate/direction.hpp @@ -273,6 +273,15 @@ struct segments_direction return return_type('0', false); } + template + static inline return_type one_degenerate(Segment const& , + Ratio const& , + bool) + { + // To be decided + return return_type('0', false); + } + static inline return_type disjoint() { return return_type('d', false); diff --git a/include/boost/geometry/policies/relate/intersection_points.hpp b/include/boost/geometry/policies/relate/intersection_points.hpp index c860da288..f16c00795 100644 --- a/include/boost/geometry/policies/relate/intersection_points.hpp +++ b/include/boost/geometry/policies/relate/intersection_points.hpp @@ -189,6 +189,7 @@ struct segments_intersection_points return return_type(); } + // Both degenerate template static inline return_type degenerate(Segment const& segment, bool) { @@ -198,6 +199,27 @@ struct segments_intersection_points set<1>(result.intersections[0], get<0, 1>(segment)); return result; } + + // One degenerate + template + static inline return_type one_degenerate(Segment const& degenerate_segment, + Ratio const& ratio, bool a_degenerate) + { + return_type result; + result.count = 1; + set<0>(result.intersections[0], get<0, 0>(degenerate_segment)); + set<1>(result.intersections[0], get<0, 1>(degenerate_segment)); + if (a_degenerate) + { + // IP lies on ratio w.r.t. segment b + result.fractions[0].assign(Ratio::zero(), ratio); + } + else + { + result.fractions[0].assign(ratio, Ratio::zero()); + } + return result; + } }; diff --git a/include/boost/geometry/policies/relate/tupled.hpp b/include/boost/geometry/policies/relate/tupled.hpp index 543aac6bc..6da9095c4 100644 --- a/include/boost/geometry/policies/relate/tupled.hpp +++ b/include/boost/geometry/policies/relate/tupled.hpp @@ -68,6 +68,18 @@ struct segments_tupled ); } + template + static inline return_type one_degenerate(Segment const& segment, + Ratio const& ratio, + bool a_degenerate) + { + return boost::make_tuple + ( + Policy1::one_degenerate(segment, ratio, a_degenerate), + Policy2::one_degenerate(segment, ratio, a_degenerate) + ); + } + static inline return_type disjoint() { return boost::make_tuple diff --git a/include/boost/geometry/strategies/cartesian/cart_intersect.hpp b/include/boost/geometry/strategies/cartesian/cart_intersect.hpp index b704abe3d..fa939cd23 100644 --- a/include/boost/geometry/strategies/cartesian/cart_intersect.hpp +++ b/include/boost/geometry/strategies/cartesian/cart_intersect.hpp @@ -144,16 +144,6 @@ struct relate_cartesian_segments return Policy::disjoint(); } - // Degenerate cases: segments of single point, lying on other segment, are not disjoint - if (a_is_point) - { - return Policy::degenerate(a, true); - } - if (b_is_point) - { - return Policy::degenerate(b, false); - } - typedef typename select_most_precise < coordinate_type, double @@ -219,19 +209,27 @@ struct relate_cartesian_segments } } - if(collinear) + if (collinear) { bool const collinear_use_first = geometry::math::abs(robust_dx_a) + geometry::math::abs(robust_dx_b) >= geometry::math::abs(robust_dy_a) + geometry::math::abs(robust_dy_b); + + // Degenerate cases: segments of single point, lying on other segment, are not disjoint + // This situation is collinear too + if (collinear_use_first) { - return relate_collinear<0, ratio_type>(a, b, robust_a1, robust_a2, robust_b1, robust_b2); + return relate_collinear<0, ratio_type>(a, b, + robust_a1, robust_a2, robust_b1, robust_b2, + a_is_point, b_is_point); } else { // Y direction contains larger segments (maybe dx is zero) - return relate_collinear<1, ratio_type>(a, b, robust_a1, robust_a2, robust_b1, robust_b2); + return relate_collinear<1, ratio_type>(a, b, + robust_a1, robust_a2, robust_b1, robust_b2, + a_is_point, b_is_point); } } @@ -250,8 +248,23 @@ private: static inline return_type relate_collinear(Segment1 const& a, Segment2 const& b, RobustPoint const& robust_a1, RobustPoint const& robust_a2, - RobustPoint const& robust_b1, RobustPoint const& robust_b2) + RobustPoint const& robust_b1, RobustPoint const& robust_b2, + bool a_is_point, bool b_is_point) { + if (a_is_point) + { + return relate_one_degenerate(a, + get(robust_a1), + get(robust_b1), get(robust_b2), + true); + } + if (b_is_point) + { + return relate_one_degenerate(b, + get(robust_b1), + get(robust_a1), get(robust_a2), + false); + } return relate_collinear(a, b, get(robust_a1), get(robust_a2), @@ -318,6 +331,28 @@ private: return Policy::segments_collinear(a, b, ra_from, ra_to, rb_from, rb_to); } + + /// Relate segments where one is degenerate + template + < + typename RatioType, + typename DegenerateSegment, + typename RobustType + > + static inline return_type relate_one_degenerate( + DegenerateSegment const& degenerate_segment + , RobustType d + , RobustType s1, RobustType s2 + , bool a_degenerate + ) + { + // Calculate the ratios where ds starts in s + // a1--------->a2 (2..6) + // b1/b2 (4..4) + // Ratio: (4-2)/(6-2) + RatioType const ratio(d - s1, s2 - s1); + return Policy::one_degenerate(degenerate_segment, ratio, a_degenerate); + } }; diff --git a/test/strategies/segment_intersection_collinear.cpp b/test/strategies/segment_intersection_collinear.cpp index 43693892a..828b1fb37 100644 --- a/test/strategies/segment_intersection_collinear.cpp +++ b/test/strategies/segment_intersection_collinear.cpp @@ -118,7 +118,8 @@ static void test_segment_ratio(std::string const& case_id, int x3, int y3, int x4, int y4, Pair expected_pair_a1, Pair expected_pair_a2, Pair expected_pair_b1, Pair expected_pair_b2, - int exp_ax1, int exp_ay1, int exp_ax2, int exp_ay2) + int exp_ax1, int exp_ay1, int exp_ax2, int exp_ay2, + std::size_t expected_count = 2) { boost::ignore_unused_variable_warning(case_id); @@ -157,16 +158,20 @@ static void test_segment_ratio(std::string const& case_id, ratio_type expected_b1(expected_pair_b1.first, expected_pair_b1.second); ratio_type expected_b2(expected_pair_b2.first, expected_pair_b2.second); - BOOST_CHECK_EQUAL(is.count, 2u); - BOOST_CHECK_EQUAL(is.fractions[0].robust_ra, expected_a1); - BOOST_CHECK_EQUAL(is.fractions[1].robust_ra, expected_a2); - BOOST_CHECK_EQUAL(is.fractions[0].robust_rb, expected_b1); - BOOST_CHECK_EQUAL(is.fractions[1].robust_rb, expected_b2); + BOOST_CHECK_EQUAL(is.count, expected_count); + BOOST_CHECK_EQUAL(is.fractions[0].robust_ra, expected_a1); + BOOST_CHECK_EQUAL(is.fractions[0].robust_rb, expected_b1); BOOST_CHECK_EQUAL(bg::get<0>(is.intersections[0]), exp_ax1); BOOST_CHECK_EQUAL(bg::get<1>(is.intersections[0]), exp_ay1); - BOOST_CHECK_EQUAL(bg::get<0>(is.intersections[1]), exp_ax2); - BOOST_CHECK_EQUAL(bg::get<1>(is.intersections[1]), exp_ay2); + + if (expected_count == 2) + { + BOOST_CHECK_EQUAL(bg::get<0>(is.intersections[1]), exp_ax2); + BOOST_CHECK_EQUAL(bg::get<1>(is.intersections[1]), exp_ay2); + BOOST_CHECK_EQUAL(is.fractions[1].robust_ra, expected_a2); + BOOST_CHECK_EQUAL(is.fractions[1].robust_rb, expected_b2); + } } @@ -487,6 +492,30 @@ void test_ratios() std::make_pair(0, 1), std::make_pair(1, 3), 5, 0, 6, 0); + // Degenerated one + // a1---------->a2 + // b1/b2 + const int ignored = 99; + test_segment_ratio

("degenerated1", + 2, 0, 6, 0, + 5, 0, 5, 0, + std::make_pair(3, 4), // IP located on 3/4 w.r.t A + std::make_pair(ignored, 1), // not checked + std::make_pair(0, 1), // IP located at any place w.r.t B, so 0 + std::make_pair(ignored, 1), // not checked + 5, 0, + ignored, ignored, + 1); + + test_segment_ratio

("degenerated2", + 5, 0, 5, 0, + 2, 0, 6, 0, + std::make_pair(0, 1), std::make_pair(ignored, 1), + std::make_pair(3, 4), std::make_pair(ignored, 1), + 5, 0, + ignored, ignored, + 1); + // Vertical one like in box_poly5 but in integer test_segment_ratio

("box_poly5", 45, 25, 45, 15,