From db1c7fc54590bb66e24cfbc65f644140d4b464a8 Mon Sep 17 00:00:00 2001 From: Michael Wang Date: Tue, 25 Apr 2023 11:53:05 -0700 Subject: [PATCH 1/3] initial --- .../cuspatial/detail/utility/linestring.cuh | 22 +++++++----- cpp/include/cuspatial/vec_2d.hpp | 3 +- .../operators/linestrings_test.cu | 26 ++++++++++++++ ...tring_intersection_with_duplicates_test.cu | 35 +++++++++++++++++++ 4 files changed, 76 insertions(+), 10 deletions(-) diff --git a/cpp/include/cuspatial/detail/utility/linestring.cuh b/cpp/include/cuspatial/detail/utility/linestring.cuh index 1a0d427ba..58a00cd36 100644 --- a/cpp/include/cuspatial/detail/utility/linestring.cuh +++ b/cpp/include/cuspatial/detail/utility/linestring.cuh @@ -137,36 +137,40 @@ __forceinline__ T __device__ squared_segment_distance(vec_2d const& a, /** * @internal - * @brief Given two collinear or parallel segments, return their potential overlapping segment + * @brief Given two collinear or parallel segments, return their potential overlapping segment or + * point * * @p a, @p b, @p c, @p d refer to end points of segment ab and cd. * @p center is the geometric center of the segments, used to decondition the coordinates. * - * @return optional end points of overlapping segment + * @return A pair of optional overlapping point or segments */ template -__forceinline__ thrust::optional> __device__ collinear_or_parallel_overlapping_segments( - vec_2d a, vec_2d b, vec_2d c, vec_2d d, vec_2d center = vec_2d{}) +__forceinline__ + + thrust::pair>, thrust::optional>> + __device__ collinear_or_parallel_overlapping_segments( + vec_2d a, vec_2d b, vec_2d c, vec_2d d, vec_2d center = vec_2d{}) { auto ab = b - a; auto ac = c - a; // Parallel - if (not float_equal(det(ab, ac), T{0})) return thrust::nullopt; + if (not float_equal(det(ab, ac), T{0})) return {thrust::nullopt, thrust::nullopt}; // Must be on the same line, sort the endpoints if (b < a) thrust::swap(a, b); if (d < c) thrust::swap(c, d); // Test if not overlap - if (b < c || d < a) return thrust::nullopt; + if (b < c || d < a) return {thrust::nullopt, thrust::nullopt}; // Compute smallest interval between the segments auto e0 = a > c ? a : c; auto e1 = b < d ? b : d; - // Decondition the coordinates - return segment{e0 + center, e1 + center}; + if (e0 == e1) { return {e0 + center, thrust::nullopt}; } + return {thrust::nullopt, segment{e0 + center, e1 + center}}; } /** @@ -192,7 +196,7 @@ segment_intersection(segment const& segment1, segment const& segment2) if (float_equal(denom, T{0})) { // Segments parallel or collinear - return {thrust::nullopt, collinear_or_parallel_overlapping_segments(a, b, c, d, center)}; + return collinear_or_parallel_overlapping_segments(a, b, c, d, center); } auto ac = c - a; diff --git a/cpp/include/cuspatial/vec_2d.hpp b/cpp/include/cuspatial/vec_2d.hpp index 5580baec0..c7e765de4 100644 --- a/cpp/include/cuspatial/vec_2d.hpp +++ b/cpp/include/cuspatial/vec_2d.hpp @@ -17,6 +17,7 @@ #pragma once #include +#include #include #include @@ -58,7 +59,7 @@ class alignas(2 * sizeof(T)) vec_2d { */ friend bool CUSPATIAL_HOST_DEVICE operator==(vec_2d const& lhs, vec_2d const& rhs) { - return (lhs.x == rhs.x) && (lhs.y == rhs.y); + return detail::float_equal(lhs.x, rhs.x) && detail::float_equal(lhs.y, rhs.y); } /** diff --git a/cpp/tests/experimental/operators/linestrings_test.cu b/cpp/tests/experimental/operators/linestrings_test.cu index 1a6eea28b..5f0861913 100644 --- a/cpp/tests/experimental/operators/linestrings_test.cu +++ b/cpp/tests/experimental/operators/linestrings_test.cu @@ -134,6 +134,32 @@ TYPED_TEST(SegmentIntersectionTest, IntersectAtEndPoint) run_single_intersection_test(ab, cd, points_expected, segments_expected); } +TYPED_TEST(SegmentIntersectionTest, IntersectAtEndPoint2) +{ + using T = TypeParam; + + segment ab{{-1.0, 0.0}, {0.0, 0.0}}; + segment cd{{0.0, 0.0}, {0.0, 1.0}}; + + std::vector>> points_expected{vec_2d{0.0, 0.0}}; + std::vector>> segments_expected{thrust::nullopt}; + + run_single_intersection_test(ab, cd, points_expected, segments_expected); +} + +TYPED_TEST(SegmentIntersectionTest, IntersectAtEndPoint3) +{ + using T = TypeParam; + + segment ab{{-1.0, 0.0}, {0.0, 0.0}}; + segment cd{{1.0, 0.0}, {0.0, 0.0}}; + + std::vector>> points_expected{vec_2d{0.0, 0.0}}; + std::vector>> segments_expected{thrust::nullopt}; + + run_single_intersection_test(ab, cd, points_expected, segments_expected); +} + TYPED_TEST(SegmentIntersectionTest, UnparallelDisjoint1) { using T = TypeParam; diff --git a/cpp/tests/experimental/spatial/linestring_intersection_with_duplicates_test.cu b/cpp/tests/experimental/spatial/linestring_intersection_with_duplicates_test.cu index b783b9e2c..01971db8b 100644 --- a/cpp/tests/experimental/spatial/linestring_intersection_with_duplicates_test.cu +++ b/cpp/tests/experimental/spatial/linestring_intersection_with_duplicates_test.cu @@ -656,3 +656,38 @@ TYPED_TEST(LinestringIntersectionDuplicatesTest, TwoPairsMultitoMulti) {}, {}); } + +TYPED_TEST(LinestringIntersectionDuplicatesTest, OnePairWithRings) +{ + using T = TypeParam; + using P = vec_2d; + + using index_t = std::size_t; + + auto multilinestrings1 = make_multilinestring_array({0, 1}, {0, 2}, {{-1, 0}, {0, 0}}); + + auto multilinestrings2 = + make_multilinestring_array({0, 1}, {0, 5}, {{0, 0}, {0, 1}, {1, 1}, {1, 0}, {0, 0}}); + + CUSPATIAL_RUN_TEST(this->template run_single, + multilinestrings1.range(), + multilinestrings2.range(), + // Point offsets + {0, 2}, + // Expected Points + {P{0.0, 0.0}, P{0.0, 0.0}}, + // Segment offsets + {0, 0}, + // Expected segments + {}, + // Point look-back ids + {0, 0}, + {0, 0}, + {0, 0}, + {0, 3}, + // segment look-back ids + {}, + {}, + {}, + {}); +} From fc54ee0961b728368a6d44c8b928b587d23df381 Mon Sep 17 00:00:00 2001 From: Michael Wang Date: Tue, 25 Apr 2023 12:01:42 -0700 Subject: [PATCH 2/3] move test to integration test --- .../spatial/linestring_intersection_test.cu | 22 ++++++++++++ ...tring_intersection_with_duplicates_test.cu | 35 ------------------- 2 files changed, 22 insertions(+), 35 deletions(-) diff --git a/cpp/tests/experimental/spatial/linestring_intersection_test.cu b/cpp/tests/experimental/spatial/linestring_intersection_test.cu index 0ec93957f..4dd5871a2 100644 --- a/cpp/tests/experimental/spatial/linestring_intersection_test.cu +++ b/cpp/tests/experimental/spatial/linestring_intersection_test.cu @@ -278,6 +278,28 @@ TYPED_TEST(LinestringIntersectionTest, SingletoSingleOnePair) expected); } +TYPED_TEST(LinestringIntersectionTest, OnePairWithRings) +{ + using T = TypeParam; + using P = vec_2d; + + using index_t = typename linestring_intersection_result::index_t; + using types_t = typename linestring_intersection_result::types_t; + + auto multilinestrings1 = make_multilinestring_array({0, 1}, {0, 2}, {{-1, 0}, {0, 0}}); + + auto multilinestrings2 = + make_multilinestring_array({0, 1}, {0, 5}, {{0, 0}, {0, 1}, {1, 1}, {1, 0}, {0, 0}}); + + auto expected = make_linestring_intersection_result( + {0, 1}, {0}, {0}, {P{0.0, 0.0}}, {}, {0}, {0}, {0}, {0}, this->stream(), this->mr()); + + CUSPATIAL_RUN_TEST(this->template run_single_test, + multilinestrings1.range(), + multilinestrings2.range(), + expected); +} + TYPED_TEST(LinestringIntersectionTest, SingletoSingleOnePairWithDuplicatePoint) { using T = TypeParam; diff --git a/cpp/tests/experimental/spatial/linestring_intersection_with_duplicates_test.cu b/cpp/tests/experimental/spatial/linestring_intersection_with_duplicates_test.cu index 01971db8b..b783b9e2c 100644 --- a/cpp/tests/experimental/spatial/linestring_intersection_with_duplicates_test.cu +++ b/cpp/tests/experimental/spatial/linestring_intersection_with_duplicates_test.cu @@ -656,38 +656,3 @@ TYPED_TEST(LinestringIntersectionDuplicatesTest, TwoPairsMultitoMulti) {}, {}); } - -TYPED_TEST(LinestringIntersectionDuplicatesTest, OnePairWithRings) -{ - using T = TypeParam; - using P = vec_2d; - - using index_t = std::size_t; - - auto multilinestrings1 = make_multilinestring_array({0, 1}, {0, 2}, {{-1, 0}, {0, 0}}); - - auto multilinestrings2 = - make_multilinestring_array({0, 1}, {0, 5}, {{0, 0}, {0, 1}, {1, 1}, {1, 0}, {0, 0}}); - - CUSPATIAL_RUN_TEST(this->template run_single, - multilinestrings1.range(), - multilinestrings2.range(), - // Point offsets - {0, 2}, - // Expected Points - {P{0.0, 0.0}, P{0.0, 0.0}}, - // Segment offsets - {0, 0}, - // Expected segments - {}, - // Point look-back ids - {0, 0}, - {0, 0}, - {0, 0}, - {0, 3}, - // segment look-back ids - {}, - {}, - {}, - {}); -} From 9efb9149660e0e8e8fd33e87690d99adcf408db2 Mon Sep 17 00:00:00 2001 From: Michael Wang Date: Tue, 25 Apr 2023 17:14:43 -0700 Subject: [PATCH 3/3] fix a dev mistake in python test --- .../cuspatial/tests/binops/test_intersections.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/python/cuspatial/cuspatial/tests/binops/test_intersections.py b/python/cuspatial/cuspatial/tests/binops/test_intersections.py index a3bcb0cd0..37891366a 100644 --- a/python/cuspatial/cuspatial/tests/binops/test_intersections.py +++ b/python/cuspatial/cuspatial/tests/binops/test_intersections.py @@ -88,9 +88,9 @@ def test_one_pair_with_overlap(): expect_ids = pd.DataFrame( { "lhs_linestring_id": [[0]], - "lhs_segment_id": [[0]], + "lhs_segment_id": [[1]], "rhs_linestring_id": [[0]], - "rhs_segment_id": [[0]], + "rhs_segment_id": [[1]], } ) @@ -122,9 +122,9 @@ def test_two_pairs_with_intersect_and_overlap(): expect_ids = pd.DataFrame( { "lhs_linestring_id": [[0], [0, 0]], - "lhs_segment_id": [[0], [1, 0]], + "lhs_segment_id": [[1], [1, 0]], "rhs_linestring_id": [[0], [0, 0]], - "rhs_segment_id": [[0], [0, 2]], + "rhs_segment_id": [[1], [0, 2]], } )