diff --git a/cpp/CMakeLists.txt b/cpp/CMakeLists.txt index 1c6f801d6..375403f1e 100644 --- a/cpp/CMakeLists.txt +++ b/cpp/CMakeLists.txt @@ -119,6 +119,7 @@ add_library(cuspatial src/spatial_window/spatial_window.cu src/spatial/haversine.cu src/spatial/hausdorff.cu + src/spatial/linestring_distance.cu src/spatial/lonlat_to_cartesian.cu src/trajectory/derive_trajectories.cu src/trajectory/trajectory_bounding_boxes.cu diff --git a/cpp/include/cuspatial/distances/linestring_distance.hpp b/cpp/include/cuspatial/distances/linestring_distance.hpp new file mode 100644 index 000000000..d5f3f87f9 --- /dev/null +++ b/cpp/include/cuspatial/distances/linestring_distance.hpp @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2022, NVIDIA CORPORATION. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include +#include + +#include + +namespace cuspatial { + +/** + * @brief Compute shortest distance between pairs of linestrings (a.k.a. polylines) + * + * The shortest distance between two linestrings is defined as the shortest distance + * between all pairs of segments of the two linestrings. If any of the segments intersect, + * the distance is 0. + * + * The following example contains 4 pairs of linestrings. + * + * First pair: + * (0, 1) -> (1, 0) -> (-1, 0) + * (1, 1) -> (2, 1) -> (2, 0) -> (3, 0) + * + * | + * * #---# + * | \ | + * ----O---*---#---# + * | / + * * + * | + * + * The shortest distance between the two linestrings is the distance + * from point (1, 1) to segment (0, 1) -> (1, 0), which is sqrt(2)/2. + * + * Second pair: + * + * (0, 0) -> (0, 1) + * (1, 0) -> (1, 1) -> (1, 2) + * + * These linestrings are parallel. Their distance is 1 (point (0, 0) to point (1, 0)). + * + * Third pair: + * + * (0, 0) -> (2, 2) -> (-2, 0) + * (2, 0) -> (0, 2) + * + * These linestrings intersect, so their distance is 0. + * + * Forth pair: + * + * (2, 2) -> (-2, -2) + * (1, 1) -> (5, 5) -> (10, 0) + * + * These linestrings contain colinear and overlapping sections, so + * their distance is 0. + * + * The input of above example is: + * linestring1_offsets: {0, 3, 5, 8} + * linestring1_points_x: {0, 1, -1, 0, 0, 0, 2, -2, 2, -2} + * linestring1_points_y: {1, 0, 0, 0, 1, 0, 2, 0, 2, -2} + * linestring2_offsets: {0, 4, 7, 9} + * linestring2_points_x: {1, 2, 2, 3, 1, 1, 1, 2, 0, 1, 5, 10} + * linestring2_points_y: {1, 1, 0, 0, 0, 1, 2, 0, 2, 1, 5, 0} + * + * Result: {sqrt(2.0)/2, 1, 0, 0} + * + * @param linestring1_offsets Indices of the first point of the first linestring of each pair. + * @param linestring1_points_x x-components of points in the first linestring of each pair. + * @param linestring1_points_y y-component of points in the first linestring of each pair. + * @param linestring2_offsets Indices of the first point of the second linestring of each pair. + * @param linestring2_points_x x-component of points in the first linestring of each pair. + * @param linestring2_points_y y-component of points in the first linestring of each pair. + * @param mr Device memory resource used to allocate the returned column's device memory. + * @return A column of shortest distances between each pair of linestrings. + * + * @note If any of the linestring contains less than 2 points, the behavior is undefined. + * + * @throw cuspatial::logic_error if `linestring1_offsets.size() != linestring2_offsets.size()` + * @throw cuspatial::logic_error if there is a size mismatch between the x- and y-coordinates of the + * linestring points. + * @throw cuspatial::logic_error if any of the point arrays have mismatched types. + * @throw cuspatial::logic_error if any linestring has fewer than 2 points. + * + */ +std::unique_ptr pairwise_linestring_distance( + cudf::device_span linestring1_offsets, + cudf::column_view const& linestring1_points_x, + cudf::column_view const& linestring1_points_y, + cudf::device_span linestring2_offsets, + cudf::column_view const& linestring2_points_x, + cudf::column_view const& linestring2_points_y, + rmm::mr::device_memory_resource* mr = rmm::mr::get_current_device_resource()); + +} // namespace cuspatial diff --git a/cpp/include/cuspatial/experimental/detail/haversine.cuh b/cpp/include/cuspatial/experimental/detail/haversine.cuh index 938809683..e9831e794 100644 --- a/cpp/include/cuspatial/experimental/detail/haversine.cuh +++ b/cpp/include/cuspatial/experimental/detail/haversine.cuh @@ -19,6 +19,7 @@ #include #include #include +#include #include #include diff --git a/cpp/include/cuspatial/types.hpp b/cpp/include/cuspatial/types.hpp index 2b1adbfb8..08dc36bca 100644 --- a/cpp/include/cuspatial/types.hpp +++ b/cpp/include/cuspatial/types.hpp @@ -18,31 +18,13 @@ #include -namespace cuspatial { +#ifdef __CUDACC__ +#define CUSPATIAL_HOST_DEVICE __host__ __device__ +#else +#define CUSPATIAL_HOST_DEVICE +#endif -/** - * @brief A 2D vector - * - * Used in cuspatial for both Longitude/Latitude (LonLat) coordinate pairs and Cartesian (X/Y) - * coordinate pairs. For LonLat pairs, the `x` member represents Longitude, and `y` represents - * Latitude. - * - * @tparam T the base type for the coordinates - */ -template -struct alignas(2 * sizeof(T)) vec_2d { - using value_type = T; - value_type x; - value_type y; -}; - -template -struct alignas(2 * sizeof(T)) lonlat_2d : vec_2d { -}; - -template -struct alignas(2 * sizeof(T)) cartesian_2d : vec_2d { -}; +namespace cuspatial { /** * @brief A timestamp diff --git a/cpp/include/cuspatial/utility/vec_2d.hpp b/cpp/include/cuspatial/utility/vec_2d.hpp new file mode 100644 index 000000000..33490a946 --- /dev/null +++ b/cpp/include/cuspatial/utility/vec_2d.hpp @@ -0,0 +1,84 @@ +#pragma once +#include + +namespace cuspatial { + +/** + * @brief A 2D vector + * + * Used in cuspatial for both Longitude/Latitude (LonLat) coordinate pairs and Cartesian (X/Y) + * coordinate pairs. For LonLat pairs, the `x` member represents Longitude, and `y` represents + * Latitude. + * + * @tparam T the base type for the coordinates + */ +template +struct alignas(2 * sizeof(T)) vec_2d { + using value_type = T; + value_type x; + value_type y; +}; + +template +struct alignas(2 * sizeof(T)) lonlat_2d : vec_2d { +}; + +template +struct alignas(2 * sizeof(T)) cartesian_2d : vec_2d { +}; + +/** + * @brief Element-wise add of two 2d vectors. + */ +template +vec_2d CUSPATIAL_HOST_DEVICE operator+(vec_2d const& a, vec_2d const& b) +{ + return vec_2d{a.x + b.x, a.y + b.y}; +} + +/** + * @brief Element-wise subtract of two 2d vectors. + */ +template +vec_2d CUSPATIAL_HOST_DEVICE operator-(vec_2d const& a, vec_2d const& b) +{ + return vec_2d{a.x - b.x, a.y - b.y}; +} + +/** + * @brief Scale a 2d vector by ratio @p r. + */ +template +vec_2d CUSPATIAL_HOST_DEVICE operator*(vec_2d vec, T const& r) +{ + return vec_2d{vec.x * r, vec.y * r}; +} + +/** + * @brief Scale a 2d vector by ratio @p r. + */ +template +vec_2d CUSPATIAL_HOST_DEVICE operator*(T const& r, vec_2d vec) +{ + return vec * r; +} + +/** + * @brief Compute dot product of two 2d vectors. + */ +template +T CUSPATIAL_HOST_DEVICE dot(vec_2d const& a, vec_2d const& b) +{ + return a.x * b.x + a.y * b.y; +} + +/** + * @brief Compute 2d determinant of a 2x2 matrix with column vectors @p a and @p b. + */ +template +T CUSPATIAL_HOST_DEVICE det(vec_2d const& a, vec_2d const& b) +{ + return a.x * b.y - a.y * b.x; +} + +} // namespace cuspatial diff --git a/cpp/src/spatial/linestring_distance.cu b/cpp/src/spatial/linestring_distance.cu new file mode 100644 index 000000000..036086ea2 --- /dev/null +++ b/cpp/src/spatial/linestring_distance.cu @@ -0,0 +1,339 @@ +/* + * Copyright (c) 2022, NVIDIA CORPORATION. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include + +#include +#include +#include + +namespace cuspatial { +namespace { + +/** @brief Get the index that is one-past the end point of linestring at @p linestring_idx + * + * @note The last endpoint of the linestring is not included in the offset array, thus + * @p num_points is returned. + */ +template +inline SizeType __device__ +endpoint_index_of_linestring(SizeType const& linestring_idx, + OffsetIterator const& linestring_offsets_begin, + SizeType const& num_linestrings, + SizeType const& num_points) +{ + return (linestring_idx == (num_linestrings - 1) + ? (num_points) + : *(linestring_offsets_begin + linestring_idx + 1)) - + 1; +} + +/** + * @brief Computes shortest distance between @p c and segment ab + */ +template +T __device__ point_to_segment_distance_squared(vec_2d const& c, + vec_2d const& a, + vec_2d const& b) +{ + auto ab = b - a; + auto ac = c - a; + auto l_squared = dot(ab, ab); + if (l_squared == 0) { return dot(ac, ac); } + auto r = dot(ac, ab); + auto bc = c - b; + // If the projection of `c` is outside of segment `ab`, compute point-point distance. + if (r <= 0 or r >= l_squared) { return std::min(dot(ac, ac), dot(bc, bc)); } + auto p = a + (r / l_squared) * ab; + auto pc = c - p; + return dot(pc, pc); +} + +/** + * @brief Computes shortest distance between two segments (ab and cd) that + * doesn't intersect. + */ +template +T __device__ segment_distance_no_intersect_or_colinear(vec_2d const& a, + vec_2d const& b, + vec_2d const& c, + vec_2d const& d) +{ + auto dist_sqr = std::min(std::min(point_to_segment_distance_squared(a, c, d), + point_to_segment_distance_squared(b, c, d)), + std::min(point_to_segment_distance_squared(c, a, b), + point_to_segment_distance_squared(d, a, b))); + return dist_sqr; +} + +/** + * @brief Computes shortest distance between two segments. + * + * If two segments intersect, the distance is 0. Otherwise compute the shortest point + * to segment distance. + */ +template +T __device__ squared_segment_distance(vec_2d const& a, + vec_2d const& b, + vec_2d const& c, + vec_2d const& d) +{ + auto ab = b - a; + auto cd = d - c; + auto denom = det(ab, cd); + + if (denom == 0) { + // Segments parallel or collinear + return segment_distance_no_intersect_or_colinear(a, b, c, d); + } + + auto ac = c - a; + auto r_numer = det(ac, cd); + auto denom_reciprocal = 1 / denom; + auto r = r_numer * denom_reciprocal; + auto s = det(ac, ab) * denom_reciprocal; + if (r >= 0 and r <= 1 and s >= 0 and s <= 1) { return 0.0; } + return segment_distance_no_intersect_or_colinear(a, b, c, d); +} + +/** + * @brief The kernel to compute point to linestring distance + * + * Each thread of the kernel computes the distance between a segment in a linestring in pair 1 + * to a linestring in pair 2. For a segment in pair 1, the linestring index is looked up from + * the offset array and mapped to the linestring in the pair 2. The segment is then computed + * with all segments in the corresponding linestringin pair 2. This forms a local minima of the + * shortest distance, which is then combined with other segment results via an atomic operation + * to form the globally minimum distance between the linestrings. + * + * @tparam CoordinateIterator Iterator to coordinates. Must meet requirements of + * [LegacyRandomAccessIterator][LinkLRAI] and be device-accessible. + * @tparam OffsetIterator Iterator to linestring offsets. Must meet requirements of + * [LegacyRandomAccessIterator][LinkLRAI] and be device-accessible. + * @tparam OutputIterator Iterator to output distances. Must meet requirements of + * [LegacyRandomAccessIterator][LinkLRAI] and be device-accessible. + * + * @param[in] linestring1_offsets_begin Iterator to the begin of the range of linestring offsets + * in pair 1. + * @param[in] linestring1_offsets_end Iterator to the end of the range of linestring offsets + * in pair 1. + * @param[in] linestring1_points_xs_begin Iterator to the begin of the range of x coordinates of + * points in pair 1. + * @param[in] linestring1_points_xs_end Iterator to the end of the range of x coordiantes of points + * in pair 1. + * @param[in] linestring1_points_ys_begin Iterator to the begin of the range of y coordinates of + * points in pair 1. + * @param[in] linestring2_offsets_begin Iterator to the begin of the range of linestring offsets + * in pair 2. + * @param[in] linestring2_points_xs_begin Iterator to the begin of the range of x coordinates of + * points in pair 2. + * @param[in] linestring2_points_xs_end Iterator to the end of the range of x coordiantes of points + * in pair 2. + * @param[in] linestring2_points_ys_begin Iterator to the begin of the range of y coordinates of + * points in pair 2. + * @param[out] distances Iterator to the output range of shortest distances between pairs. + * + * [LinkLRAI]: https://en.cppreference.com/w/cpp/named_req/RandomAccessIterator + * "LegacyRandomAccessIterator" + */ +template +void __global__ pairwise_linestring_distance_kernel(OffsetIterator linestring1_offsets_begin, + OffsetIterator linestring1_offsets_end, + CoordinateIterator linestring1_points_xs_begin, + CoordinateIterator linestring1_points_xs_end, + CoordinateIterator linestring1_points_ys_begin, + OffsetIterator linestring2_offsets_begin, + CoordinateIterator linestring2_points_xs_begin, + CoordinateIterator linestring2_points_xs_end, + CoordinateIterator linestring2_points_ys_begin, + OutputIterator distances) +{ + using T = typename std::iterator_traits::value_type; + + auto const p1_idx = threadIdx.x + blockIdx.x * blockDim.x; + cudf::size_type const num_linestrings = + thrust::distance(linestring1_offsets_begin, linestring1_offsets_end); + cudf::size_type const linestring1_num_points = + thrust::distance(linestring1_points_xs_begin, linestring1_points_xs_end); + cudf::size_type const linestring2_num_points = + thrust::distance(linestring2_points_xs_begin, linestring2_points_xs_end); + + if (p1_idx >= linestring1_num_points) { return; } + + cudf::size_type const linestring_idx = + thrust::distance(linestring1_offsets_begin, + thrust::upper_bound( + thrust::seq, linestring1_offsets_begin, linestring1_offsets_end, p1_idx)) - + 1; + + cudf::size_type ls1_end = endpoint_index_of_linestring( + linestring_idx, linestring1_offsets_begin, num_linestrings, linestring1_num_points); + + if (p1_idx == ls1_end) { + // Current point is the end point of the line string. + return; + } + + cudf::size_type ls2_start = *(linestring2_offsets_begin + linestring_idx); + cudf::size_type ls2_end = endpoint_index_of_linestring( + linestring_idx, linestring2_offsets_begin, num_linestrings, linestring2_num_points); + + vec_2d A{linestring1_points_xs_begin[p1_idx], linestring1_points_ys_begin[p1_idx]}; + vec_2d B{linestring1_points_xs_begin[p1_idx + 1], linestring1_points_ys_begin[p1_idx + 1]}; + + T min_squared_distance = std::numeric_limits::max(); + for (cudf::size_type p2_idx = ls2_start; p2_idx < ls2_end; p2_idx++) { + vec_2d C{linestring2_points_xs_begin[p2_idx], linestring2_points_ys_begin[p2_idx]}; + vec_2d D{linestring2_points_xs_begin[p2_idx + 1], linestring2_points_ys_begin[p2_idx + 1]}; + min_squared_distance = std::min(min_squared_distance, squared_segment_distance(A, B, C, D)); + } + atomicMin(distances + linestring_idx, static_cast(std::sqrt(min_squared_distance))); +} + +} // anonymous namespace + +namespace detail { + +/** + * @brief Functor that launches the kernel to compute pairwise linestring distances. + */ +struct pairwise_linestring_distance_functor { + template + std::enable_if_t::value, std::unique_ptr> operator()( + cudf::device_span linestring1_offsets, + cudf::column_view const& linestring1_points_x, + cudf::column_view const& linestring1_points_y, + cudf::device_span linestring2_offsets, + cudf::column_view const& linestring2_points_x, + cudf::column_view const& linestring2_points_y, + rmm::cuda_stream_view stream, + rmm::mr::device_memory_resource* mr) + { + using namespace cudf; + + auto const num_string_pairs = static_cast(linestring1_offsets.size()); + + auto distances = + make_numeric_column(data_type{type_to_id()}, num_string_pairs, mask_state::UNALLOCATED); + + thrust::fill(rmm::exec_policy(stream), + distances->mutable_view().begin(), + distances->mutable_view().end(), + std::numeric_limits::max()); + + std::size_t constexpr threads_per_block = 64; + std::size_t const num_blocks = + (linestring1_points_x.size() + threads_per_block - 1) / threads_per_block; + + pairwise_linestring_distance_kernel<<>>( + linestring1_offsets.begin(), + linestring1_offsets.end(), + linestring1_points_x.begin(), + linestring1_points_x.end(), + linestring1_points_y.begin(), + linestring2_offsets.begin(), + linestring2_points_x.begin(), + linestring2_points_x.end(), + linestring2_points_y.begin(), + distances->mutable_view().begin()); + + CUSPATIAL_CUDA_TRY(cudaGetLastError()); + + return distances; + } + + template + std::enable_if_t::value, std::unique_ptr> operator()( + Args&&...) + { + CUSPATIAL_FAIL("Linestring distances only supports floating point coordinates."); + } +}; + +std::unique_ptr pairwise_linestring_distance( + cudf::device_span linestring1_offsets, + cudf::column_view const& linestring1_points_x, + cudf::column_view const& linestring1_points_y, + cudf::device_span linestring2_offsets, + cudf::column_view const& linestring2_points_x, + cudf::column_view const& linestring2_points_y, + rmm::cuda_stream_view stream, + rmm::mr::device_memory_resource* mr) +{ + CUSPATIAL_EXPECTS(linestring1_offsets.size() == linestring2_offsets.size(), + "Mismatch number of linestrings in the linestring pair array."); + + CUSPATIAL_EXPECTS(linestring1_points_x.size() == linestring1_points_y.size() and + linestring2_points_x.size() == linestring2_points_y.size(), + "The lengths of linestring coordinates arrays mismatch."); + + CUSPATIAL_EXPECTS(linestring1_points_x.type() == linestring1_points_y.type() and + linestring2_points_x.type() == linestring2_points_y.type() and + linestring1_points_x.type() == linestring2_points_x.type(), + "The types of linestring coordinates arrays mismatch."); + + if (linestring1_offsets.size() == 0) { return cudf::empty_like(linestring1_points_x); } + + return cudf::type_dispatcher(linestring1_points_x.type(), + pairwise_linestring_distance_functor{}, + linestring1_offsets, + linestring1_points_x, + linestring1_points_y, + linestring2_offsets, + linestring2_points_x, + linestring2_points_y, + stream, + mr); +} + +} // namespace detail + +std::unique_ptr pairwise_linestring_distance( + cudf::device_span linestring1_offsets, + cudf::column_view const& linestring1_points_x, + cudf::column_view const& linestring1_points_y, + cudf::device_span linestring2_offsets, + cudf::column_view const& linestring2_points_x, + cudf::column_view const& linestring2_points_y, + rmm::mr::device_memory_resource* mr) +{ + return detail::pairwise_linestring_distance(linestring1_offsets, + linestring1_points_x, + linestring1_points_y, + linestring2_offsets, + linestring2_points_x, + linestring2_points_y, + rmm::cuda_stream_default, + mr); +} + +} // namespace cuspatial diff --git a/cpp/tests/CMakeLists.txt b/cpp/tests/CMakeLists.txt index 3107850d5..b6857003c 100644 --- a/cpp/tests/CMakeLists.txt +++ b/cpp/tests/CMakeLists.txt @@ -77,6 +77,9 @@ ConfigureTest(POLYLINE_BBOX_TEST ConfigureTest(POLYGON_BBOX_TEST spatial/polygon_bbox_test.cu) +ConfigureTest(LINESTRING_DISTANCE_TEST + spatial/linestring_distance_test.cpp spatial/linestring_distance_test_medium.cpp) + ConfigureTest(SHAPEFILE_READER_TEST io/shp/polygon_shapefile_reader_test.cpp) diff --git a/cpp/tests/spatial/linestring_distance_test.cpp b/cpp/tests/spatial/linestring_distance_test.cpp new file mode 100644 index 000000000..87d77e6e9 --- /dev/null +++ b/cpp/tests/spatial/linestring_distance_test.cpp @@ -0,0 +1,471 @@ +/* + * Copyright (c) 2022, NVIDIA CORPORATION. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +#include +#include +#include +#include + +namespace cuspatial { +namespace test { + +using namespace cudf; +using namespace cudf::test; + +template +using wrapper = fixed_width_column_wrapper; + +template +struct PairwiseLinestringDistanceTest : public BaseFixture { +}; + +struct PairwiseLinestringDistanceTestUntyped : public BaseFixture { +}; + +// float and double are logically the same but would require separate tests due to precision. +using TestTypes = FloatingPointTypes; +TYPED_TEST_CASE(PairwiseLinestringDistanceTest, TestTypes); + +constexpr cudf::test::debug_output_level verbosity{cudf::test::debug_output_level::ALL_ERRORS}; + +TYPED_TEST(PairwiseLinestringDistanceTest, OnePairLinestringParallel) +{ + using T = TypeParam; + // Linestring 1: (0.0, 0.0), (1.0, 1.0) + // Linestring 2: (1.0, 0.0), (2.0, 1.0) + wrapper linestring1_offsets{0}; + wrapper linestring1_points_x{0.0, 1.0}; + wrapper linestring1_points_y{0.0, 1.0}; + wrapper linestring2_offsets{0}; + wrapper linestring2_points_x{1.0, 2.0}; + wrapper linestring2_points_y{0.0, 1.0}; + + wrapper expected{0.7071067811865476}; + + auto got = pairwise_linestring_distance(column_view(linestring1_offsets), + linestring1_points_x, + linestring1_points_y, + column_view(linestring2_offsets), + linestring2_points_x, + linestring2_points_y); + expect_columns_equivalent(expected, *got, verbosity); +} + +TYPED_TEST(PairwiseLinestringDistanceTest, OnePairLinestringEndpointsDistance) +{ + using T = TypeParam; + // Linestring 1: (0.0, 0.0), (1.0, 1.0), (2.0, 2.0) + // Linestring 2: (2.0, 0.0), (1.0, -1.0), (0.0, -1.0) + wrapper linestring1_offsets{0}; + wrapper linestring1_points_x{0.0, 1.0, 2.0}; + wrapper linestring1_points_y{0.0, 1.0, 2.0}; + wrapper linestring2_offsets{0}; + wrapper linestring2_points_x{2.0, 1.0, 0.0}; + wrapper linestring2_points_y{0.0, -1.0, -1.0}; + + wrapper expected{1.0}; + + auto got = pairwise_linestring_distance(column_view(linestring1_offsets), + linestring1_points_x, + linestring1_points_y, + column_view(linestring2_offsets), + linestring2_points_x, + linestring2_points_y); + expect_columns_equivalent(expected, *got, verbosity); +} + +TYPED_TEST(PairwiseLinestringDistanceTest, OnePairLinestringProjectionNotOnLine) +{ + using T = TypeParam; + // Linestring 1: (0.0, 0.0), (1.0, 1.0) + // Linestring 2: (3.0, 1.5), (3.0, 2.0) + wrapper linestring1_offsets{0}; + wrapper linestring1_points_x{0.0, 1.0}; + wrapper linestring1_points_y{0.0, 1.0}; + wrapper linestring2_offsets{0}; + wrapper linestring2_points_x{3.0, 3.0}; + wrapper linestring2_points_y{1.5, 2.0}; + + wrapper expected{2.0615528128088303}; + + auto got = pairwise_linestring_distance(column_view(linestring1_offsets), + linestring1_points_x, + linestring1_points_y, + column_view(linestring2_offsets), + linestring2_points_x, + linestring2_points_y); + expect_columns_equivalent(expected, *got, verbosity); +} + +TYPED_TEST(PairwiseLinestringDistanceTest, OnePairLinestringPerpendicular) +{ + using T = TypeParam; + // Linestring 1: (0.0, 0.0), (2.0, 0.0) + // Linestring 2: (1.0, 1.0), (1.0, 2.0) + wrapper linestring1_offsets{0}; + wrapper linestring1_points_x{0.0, 2.0}; + wrapper linestring1_points_y{0.0, 0.0}; + wrapper linestring2_offsets{0}; + wrapper linestring2_points_x{1.0, 1.0}; + wrapper linestring2_points_y{1.0, 2.0}; + + wrapper expected{1.0}; + + auto got = pairwise_linestring_distance(column_view(linestring1_offsets), + linestring1_points_x, + linestring1_points_y, + column_view(linestring2_offsets), + linestring2_points_x, + linestring2_points_y); + expect_columns_equivalent(expected, *got, verbosity); +} + +TYPED_TEST(PairwiseLinestringDistanceTest, OnePairLinestringIntersects) +{ + using T = TypeParam; + // Linestring 1: (0.0, 0.0), (1.0, 1.0) + // Linestring 2: (0.0, 1.0), (1.0, 0.0) + wrapper linestring1_offsets{0}; + wrapper linestring1_points_x{0.0, 1.0}; + wrapper linestring1_points_y{0.0, 1.0}; + wrapper linestring2_offsets{0}; + wrapper linestring2_points_x{0.0, 1.0}; + wrapper linestring2_points_y{1.0, 0.0}; + + wrapper expected{0.0}; + + auto got = pairwise_linestring_distance(column_view(linestring1_offsets), + linestring1_points_x, + linestring1_points_y, + column_view(linestring2_offsets), + linestring2_points_x, + linestring2_points_y); + expect_columns_equivalent(expected, *got, verbosity); +} + +TYPED_TEST(PairwiseLinestringDistanceTest, OnePairLinestringSharedVertex) +{ + using T = TypeParam; + // Linestring 1: (0.0, 0.0), (0.0, 2.0), (2.0, 2.0) + // Linestring 2: (2.0, 2.0), (2.0, 1.0), (1.0, 1.0), (2.5, 0.0) + wrapper linestring1_offsets{0}; + wrapper linestring1_points_x{0.0, 0.0, 2.0}; + wrapper linestring1_points_y{0.0, 2.0, 2.0}; + wrapper linestring2_offsets{0}; + wrapper linestring2_points_x{2.0, 2.0, 1.0, 2.5}; + wrapper linestring2_points_y{2.0, 1.0, 1.0, 0.0}; + + wrapper expected{0.0}; + + auto got = pairwise_linestring_distance(column_view(linestring1_offsets), + linestring1_points_x, + linestring1_points_y, + column_view(linestring2_offsets), + linestring2_points_x, + linestring2_points_y); + expect_columns_equivalent(expected, *got, verbosity); +} + +TYPED_TEST(PairwiseLinestringDistanceTest, OnePairLinestringCoincide) +{ + using T = TypeParam; + // Linestring 1: (0.0, 0.0), (1.0, 0.0), (1.0, 1.0), (0.0, 1.0) + // Linestring 2: (2.0, 1.0), (1.0, 1.0), (1.0, 0.0), (2.0, 0.0), (2.0, 0.5) + wrapper linestring1_offsets{0}; + wrapper linestring1_points_x{0.0, 1.0, 1.0, 0.0}; + wrapper linestring1_points_y{0.0, 0.0, 1.0, 1.0}; + wrapper linestring2_offsets{0}; + wrapper linestring2_points_x{2.0, 1.0, 1.0, 2.0, 2.0}; + wrapper linestring2_points_y{1.0, 1.0, 0.0, 0.0, 0.5}; + + wrapper expected{0.0}; + + auto got = pairwise_linestring_distance(column_view(linestring1_offsets), + linestring1_points_x, + linestring1_points_y, + column_view(linestring2_offsets), + linestring2_points_x, + linestring2_points_y); + expect_columns_equivalent(expected, *got, verbosity); +} + +TYPED_TEST(PairwiseLinestringDistanceTest, OnePairDegenerateCollinearNoIntersect) +{ + using T = TypeParam; + wrapper linestring1_offsets{0}; + wrapper linestring1_points_x{0.0, 0.0}; + wrapper linestring1_points_y{0.0, 1.0}; + wrapper linestring2_offsets{0}; + wrapper linestring2_points_x{0.0, 0.0}; + wrapper linestring2_points_y{2.0, 3.0}; + + wrapper expected{1.0}; + + auto got = pairwise_linestring_distance(column_view(linestring1_offsets), + linestring1_points_x, + linestring1_points_y, + column_view(linestring2_offsets), + linestring2_points_x, + linestring2_points_y); + expect_columns_equivalent(expected, *got, verbosity); +} + +TYPED_TEST(PairwiseLinestringDistanceTest, OnePairCollinearNoIntersect) +{ + using T = TypeParam; + wrapper linestring1_offsets{0}; + wrapper linestring1_points_x{0.0, 1.0}; + wrapper linestring1_points_y{0.0, 1.0}; + wrapper linestring2_offsets{0}; + wrapper linestring2_points_x{2.0, 3.0}; + wrapper linestring2_points_y{2.0, 3.0}; + + wrapper expected{1.4142135623730951}; + + auto got = pairwise_linestring_distance(column_view(linestring1_offsets), + linestring1_points_x, + linestring1_points_y, + column_view(linestring2_offsets), + linestring2_points_x, + linestring2_points_y); + expect_columns_equivalent(expected, *got, verbosity); +} + +TYPED_TEST(PairwiseLinestringDistanceTest, OnePairDegenerateCollinearIntersect) +{ + using T = TypeParam; + wrapper linestring1_offsets{0}; + wrapper linestring1_points_x{0.0, 2.0}; + wrapper linestring1_points_y{0.0, 2.0}; + wrapper linestring2_offsets{0}; + wrapper linestring2_points_x{1.0, 3.0}; + wrapper linestring2_points_y{1.0, 3.0}; + + wrapper expected{0.0}; + + auto got = pairwise_linestring_distance(column_view(linestring1_offsets), + linestring1_points_x, + linestring1_points_y, + column_view(linestring2_offsets), + linestring2_points_x, + linestring2_points_y); + expect_columns_equivalent(expected, *got, verbosity); +} + +TEST_F(PairwiseLinestringDistanceTestUntyped, OnePairDeterminantDoublePrecisionDenormalized) +{ + // Vector ab: (1e-155, 2e-155) + // Vector cd: (2e-155, 1e-155) + // determinant of matrix [a, b] = -3e-310, a denormalized number + + wrapper linestring1_offsets{0}; + wrapper linestring1_points_x{0.0, 1e-155}; + wrapper linestring1_points_y{0.0, 2e-155}; + wrapper linestring2_offsets{0}; + wrapper linestring2_points_x{4e-155, 6e-155}; + wrapper linestring2_points_y{5e-155, 6e-155}; + + wrapper expected{4.24264068711929e-155}; + + auto got = pairwise_linestring_distance(column_view(linestring1_offsets), + linestring1_points_x, + linestring1_points_y, + column_view(linestring2_offsets), + linestring2_points_x, + linestring2_points_y); + expect_columns_equivalent(expected, *got, verbosity); +} + +TEST_F(PairwiseLinestringDistanceTestUntyped, OnePairDeterminantSinglePrecisionDenormalized) +{ + // Vector ab: (1e-20, 2e-20) + // Vector cd: (2e-20, 1e-20) + // determinant of matrix [ab, cd] = -3e-40, a denormalized number + + wrapper linestring1_offsets{0}; + wrapper linestring1_points_x{0.0, 1e-20}; + wrapper linestring1_points_y{0.0, 2e-20}; + wrapper linestring2_offsets{0}; + wrapper linestring2_points_x{4e-20, 6e-20}; + wrapper linestring2_points_y{5e-20, 6e-20}; + + wrapper expected{4.2426405524813e-20}; + + auto got = pairwise_linestring_distance(column_view(linestring1_offsets), + linestring1_points_x, + linestring1_points_y, + column_view(linestring2_offsets), + linestring2_points_x, + linestring2_points_y); + expect_columns_equivalent(expected, *got, verbosity); +} + +TYPED_TEST(PairwiseLinestringDistanceTest, OnePairRandom1) +{ + using T = TypeParam; + wrapper linestring1_offsets{0}; + wrapper linestring1_points_x{-22556.235212018168, -16375.655690574613, -20082.724633593425}; + wrapper linestring1_points_y{41094.0501840996, 42992.319790050366, 33759.13529113619}; + wrapper linestring2_offsets{0}; + wrapper linestring2_points_x{4365.496374409238, 1671.0269165650761}; + wrapper linestring2_points_y{-59857.47177852941, -54931.9723439855}; + + wrapper expected{91319.97744223749}; + + auto got = pairwise_linestring_distance(column_view(linestring1_offsets), + linestring1_points_x, + linestring1_points_y, + column_view(linestring2_offsets), + linestring2_points_x, + linestring2_points_y); + expect_columns_equivalent(expected, *got, verbosity); +} + +TYPED_TEST(PairwiseLinestringDistanceTest, OnePairIntersectFromRealData1) +{ + // Example extracted from a pair of trajectry in geolife dataset + using T = TypeParam; + wrapper linestring1_offsets{0}; + wrapper linestring1_points_x{39.97551667, 39.97585, 39.97598333, 39.9761, 39.97623333}; + wrapper linestring1_points_y{116.33028333, 116.3304, 116.33046667, 116.3305, 116.33056667}; + wrapper linestring2_offsets{0}; + wrapper linestring2_points_x{ + 39.97381667, 39.97341667, 39.9731, 39.97293333, 39.97233333, 39.97218333, 39.97218333, + 39.97215, 39.97168333, 39.97093333, 39.97073333, 39.9705, 39.96991667, 39.96961667, + 39.96918333, 39.96891667, 39.97531667, 39.97533333, 39.97535, 39.97515, 39.97506667, + 39.97508333, 39.9751, 39.97513333, 39.97511667, 39.97503333, 39.97513333, 39.97523333, + 39.97521667, 39.97503333, 39.97463333, 39.97443333, 39.96838333, 39.96808333, 39.96771667, + 39.96745, 39.96735, 39.9673, 39.96718333, 39.96751667, 39.9678, 39.9676, + 39.96741667, 39.9672, 39.97646667, 39.9764, 39.97625, 39.9762, 39.97603333, + 39.97581667, 39.9757, 39.97551667, 39.97535, 39.97543333, 39.97538333}; + wrapper linestring2_points_y{ + 116.34211667, 116.34215, 116.34218333, 116.34221667, 116.34225, 116.34243333, + 116.34296667, 116.34478333, 116.34486667, 116.34485, 116.34468333, 116.34461667, + 116.34465, 116.34465, 116.34466667, 116.34465, 116.33036667, 116.32961667, + 116.3292, 116.32903333, 116.32985, 116.33128333, 116.33195, 116.33618333, + 116.33668333, 116.33818333, 116.34, 116.34045, 116.34183333, 116.342, + 116.34203333, 116.3422, 116.3445, 116.34451667, 116.3445, 116.34453333, + 116.34493333, 116.34506667, 116.3451, 116.34483333, 116.3448, 116.3449, + 116.345, 116.34506667, 116.33006667, 116.33015, 116.33026667, 116.33038333, + 116.33036667, 116.3303, 116.33033333, 116.33035, 116.3304, 116.33078333, + 116.33066667}; + + wrapper expected{0.0}; + + auto got = pairwise_linestring_distance(column_view(linestring1_offsets), + linestring1_points_x, + linestring1_points_y, + column_view(linestring2_offsets), + linestring2_points_x, + linestring2_points_y); + expect_columns_equivalent(expected, *got, verbosity); +} + +TYPED_TEST(PairwiseLinestringDistanceTest, OnePairFromRealData) +{ + // Example extracted from a pair of trajectry in geolife dataset + using T = TypeParam; + wrapper linestring1_offsets{0}; + wrapper linestring1_points_x{39.9752666666667, 39.9752666666667}; + wrapper linestring1_points_y{116.334316666667, 116.334533333333}; + wrapper linestring2_offsets{0}; + wrapper linestring2_points_x{39.9752666666667, 39.9752666666667}; + wrapper linestring2_points_y{116.323966666667, 116.3236}; + + wrapper expected = + std::is_same_v ? wrapper{0.01035308837890625} : wrapper{0.010349999999988313}; + auto got = pairwise_linestring_distance(column_view(linestring1_offsets), + linestring1_points_x, + linestring1_points_y, + column_view(linestring2_offsets), + linestring2_points_x, + linestring2_points_y); + expect_columns_equivalent(expected, *got, verbosity); +} + +TYPED_TEST(PairwiseLinestringDistanceTest, TwoPairs) +{ + using T = TypeParam; + wrapper linestring1_offsets{0, 4}; + wrapper linestring1_points_x{ + 41658.902315589876, + 46600.70359801489, + 47079.510547637154, + 51498.48049880379, + -27429.917796286478, + -21764.269974046114, + -14460.71813363161, + -18226.13032712476, + }; + wrapper linestring1_points_y{14694.11814724456, + 8771.431887804214, + 10199.68027155776, + 17049.62665643919, + -33240.8339287343, + -37974.45515744517, + -31333.481529957502, + -30181.03842467982}; + wrapper linestring2_offsets{0, 2}; + wrapper linestring2_points_x{ + 24046.170375947084, + 20614.007047185743, + 48381.39607717942, + 53346.77764665915, + }; + wrapper linestring2_points_y{ + 27878.56737867571, + 26489.74880629428, + -8366.313156569413, + -2066.3869793077383, + }; + + wrapper expected{22000.86425379464, 66907.56415814416}; + + auto got = pairwise_linestring_distance(column_view(linestring1_offsets), + linestring1_points_x, + linestring1_points_y, + column_view(linestring2_offsets), + linestring2_points_x, + linestring2_points_y); + expect_columns_equivalent(expected, *got, verbosity); +} + +TYPED_TEST(PairwiseLinestringDistanceTest, FourPairs) +{ + using T = TypeParam; + wrapper linestring1_offsets{0, 3, 5, 8}; + wrapper linestring1_points_x{0, 1, -1, 0, 0, 0, 2, -2, 2, -2}; + wrapper linestring1_points_y{1, 0, 0, 0, 1, 0, 2, 0, 2, -2}; + wrapper linestring2_offsets{0, 4, 7, 9}; + wrapper linestring2_points_x{1, 2, 2, 3, 1, 1, 1, 2, 0, 1, 5, 10}; + wrapper linestring2_points_y{1, 1, 0, 0, 0, 1, 2, 0, 2, 1, 5, 0}; + + wrapper expected{std::sqrt(2.0) * 0.5, 1.0, 0.0, 0.0}; + + auto got = pairwise_linestring_distance(column_view(linestring1_offsets), + linestring1_points_x, + linestring1_points_y, + column_view(linestring2_offsets), + linestring2_points_x, + linestring2_points_y); + expect_columns_equivalent(expected, *got, verbosity); +} + +} // namespace test +} // namespace cuspatial diff --git a/cpp/tests/spatial/linestring_distance_test_medium.cpp b/cpp/tests/spatial/linestring_distance_test_medium.cpp new file mode 100644 index 000000000..d99433f1d --- /dev/null +++ b/cpp/tests/spatial/linestring_distance_test_medium.cpp @@ -0,0 +1,1056 @@ +/* + * Copyright (c) 2022, NVIDIA CORPORATION. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +#include +#include +#include +#include + +namespace cuspatial { +namespace test { + +using namespace cudf; +using namespace cudf::test; + +template +using wrapper = fixed_width_column_wrapper; + +template +struct PairwiseLinestringDistanceTest : public BaseFixture { +}; + +// float and double are logically the same but would require separate tests due to precision. +using TestTypes = FloatingPointTypes; +TYPED_TEST_CASE(PairwiseLinestringDistanceTest, TestTypes); + +constexpr cudf::test::debug_output_level verbosity{cudf::test::debug_output_level::ALL_ERRORS}; + +TYPED_TEST(PairwiseLinestringDistanceTest, RandomDataset100) +{ + using T = TypeParam; + wrapper linestring1_offsets{ + 0, 4, 8, 11, 13, 16, 19, 22, 25, 28, 32, 36, 40, 44, 48, 51, 54, + 57, 61, 63, 65, 67, 71, 74, 78, 82, 85, 87, 89, 92, 96, 99, 101, 104, + 108, 112, 115, 119, 123, 127, 130, 132, 135, 137, 141, 145, 147, 150, 153, 155, 158, + 160, 164, 167, 170, 173, 176, 179, 182, 184, 188, 192, 194, 198, 202, 206, 209, 212, + 215, 217, 220, 222, 226, 228, 230, 233, 237, 239, 243, 247, 250, 252, 254, 257, 259, + 263, 266, 269, 273, 276, 280, 283, 286, 290, 294, 298, 300, 302, 306, 308}; + wrapper linestring1_points_x{ + 41658.902315589876, 46600.70359801489, 47079.510547637154, 51498.48049880379, + -27429.917796286478, -21764.269974046114, -14460.71813363161, -18226.13032712476, + -22556.235212018168, -16375.655690574613, -20082.724633593425, 26809.34874258138, + 26656.809525288947, 37540.565197328295, 36984.75276605113, 41981.578395349155, + 24973.02375952172, 19250.902968701903, 20165.256326220195, -30532.18325215106, + -32135.262234862337, -22826.652288925623, -17439.962727300197, -19359.179053658157, + -20575.92273561565, 9500.159032106982, 6568.682357949907, 4981.961021893829, + -21889.03381442112, -23236.68404277722, -20541.236096645694, -20778.38844417717, + -57875.32424881095, -51612.57611847265, -47437.091112564274, -50197.81791907972, + -56989.35149478826, -50735.07273259827, -53459.1335853405, -47317.19439336836, + -6829.050709717398, -2732.682737868703, -5966.9880402461695, 385.7819993385874, + -36083.360810904385, -41081.45575117335, -35733.010967268594, -36247.474479077006, + -46951.78590147328, -47262.641809761204, -47684.95897589372, 38981.49756281363, + 35164.86749845841, 35579.262138939965, 59176.59704717483, 58533.33560306961, + 58725.469004504834, 54054.39482381586, 48926.88038791325, 51732.8876978247, + 53489.896558495035, -44876.184453934664, -47637.45499043422, -58724.07892996805, + -54674.126544740386, 60635.37331725002, 62105.58031557918, -5514.764938002292, + -6644.854901584, -10776.990254158663, -10887.375444705547, -16308.6192426665, + -17943.665926700574, -18590.60450856736, -54635.44517293027, -54223.234081035494, + -55991.88318145398, -55476.50649203067, -16828.926382989048, -20874.261277556023, + -21556.654292334166, -21941.300770415983, 19602.183464230096, 20124.423199257864, + 22857.521915468602, -40252.218652315016, -40615.87902328277, -13227.295520406573, + -13394.780584665317, -41859.97648749311, -41313.45210522428, -38298.22583610271, + 19267.410152329292, 11889.896156569695, 13200.16827668008, 19386.646807861616, + -60021.453586243275, -56555.20891834299, -58162.220568779645, -21564.27114522246, + -26413.185516939815, -8121.46414404954, -2680.751998537391, -2222.8256113393886, + -43496.28457602764, -48670.608599013554, -51456.69654638918, -52025.6273644588, + -49836.99743938117, -46727.06695784684, -37385.58991765429, -37794.42212261821, + 36860.87308416238, 42873.67992713083, 39313.39701688439, 11431.213542784448, + 7647.058473635509, 11107.49195048625, 11643.093760750395, -45871.68320713149, + -45986.98076235849, -46085.965532968825, -46181.67123182361, 25363.379368344074, + 17717.231571577973, 24580.31394401792, 29134.693387320112, 43080.7529227066, + 42441.16001053327, 47976.84240392968, -11900.910297907809, -13187.917157702086, + -9792.284371446513, -11269.14276649128, -5660.728920526542, 11253.80330805089, + 10466.359767099839, -53252.1312259309, -47799.02030720808, -51379.57629207311, + -54427.60141284903, -42057.65623242821, -42664.076601666646, -45804.81458842004, + -45478.89283457703, 47075.997568824576, 53844.0068681668, -22445.721811471412, + -20797.59708432936, -22012.560374600253, -25647.96389715412, -24850.718783507502, + -23637.972304660132, 34882.04958914149, 26678.65752711494, -45859.8782408588, + -51933.96309224814, -52099.29330373669, 34549.11186911959, 28645.239864180556, + 29729.362290067365, 27092.22625228292, 27270.331741995822, 27375.014737974416, + 51556.57410969483, 52515.470545460434, 46638.54343817407, 11226.929260803649, + 12712.496694281563, 8563.557289261611, -45375.67258113653, -44857.41642126795, + -51428.472725871936, 11948.653896420248, 20671.682144587314, 19203.379064891342, + 54438.42614275502, 57867.96483019572, 54260.19148082872, -43454.69314619985, + -49657.47783440756, -48847.36106727273, -12962.581910456334, -11078.09318399874, + 33050.658148590956, 33853.16958578488, 30155.859199122297, 28350.944868052207, + -19670.72089334298, -19640.1421625446, -15653.90150936818, -5820.125752277603, + 60491.9147275399, 61673.61389764642, 3010.22884329714, 7247.472877158092, + 4851.4337295382575, 4824.133938941079, 23504.266167053705, 22480.863815579512, + 24342.637759549954, 24137.50967310437, -34053.41026040829, -32110.577393759428, + -33924.15109989719, -31672.687599811205, 959.7215557354066, 312.56653151161856, + -44.98033879071096, 296.376589694366, 3994.3950419367184, 7696.985767894743, + -6387.18605725986, -8051.394792809615, -10110.413864642014, -19847.050217164695, + -14080.09841584025, -22849.163678809855, -28963.47174786276, -31847.193110264172, + 7105.9171509791195, 11460.775360755784, 58942.469515078075, 58886.86547401938, + 58740.01428115593, 61283.97291509698, -63061.08699755168, -65536.0, + -50035.37045591002, -50081.11003362366, 62116.35229456691, 61865.80519887989, + 62647.124391193276, 56654.5141685885, 63070.85134584749, 61230.41706849119, + 60415.518333547, 55656.31580105885, 46134.25777282618, 968.041379812712, + 5360.019466310152, 3662.5289196361346, 5459.910428930167, 53419.848320399906, + 54341.74882672624, 56149.34611529181, 63518.943955564784, 63041.55390377034, + 55648.26343059204, 56045.45020144504, -14313.208636322757, -14485.732740432964, + -13268.3777837889, -13231.945672727452, -5885.21758056189, -5131.159534487515, + -9074.90834159211, -43855.71514428074, -48053.80969115072, 40831.07071986032, + 43149.63435633618, 47679.105915171785, 48400.939321371276, -9650.464759378563, + -7249.958103471297, -5082.082168062301, -63939.909793905674, -63781.97553502955, + -65311.39108408277, -5848.2556516926925, 317.32328031093675, -812.6531797336165, + -3364.6381580844895, -52564.38671359332, -58093.41581969953, -59668.83618647987, + 14353.60218457671, 13841.579397954565, 9137.396816561348, 8610.296312929777, + -7055.315970087351, -549.2613965357859, 2300.4279681102403, 55435.82976249409, + 55192.80876167619, 50532.24048212488, -49374.35589090375, -47508.15225702733, + -50682.16982805728, -50920.08172662605, 45260.20728762291, 48517.03233951705, + 46124.822155460206, 54828.216215604654, 44771.72815631704, 40575.91154447274, + 40875.303023973545, 45065.28856600735, 15683.489154164097, 23392.984508151996, + 31539.806796075267, 31791.109097684202, -23000.113733128106, -18094.479708501316, + -11357.201200332272, -9345.838925153008, -55479.287132797836, -52287.397277835524, + 10818.487974743519, 9714.158308423997, 3850.7591574230764}; + + wrapper linestring1_points_y{14694.11814724456, + 8771.431887804214, + 10199.68027155776, + 17049.62665643919, + -33240.8339287343, + -37974.45515744517, + -31333.481529957502, + -30181.03842467982, + 41094.0501840996, + 42992.319790050366, + 33759.13529113619, + -44038.61029577575, + -43753.338844714024, + 15638.266868017672, + 17679.849722737585, + 13344.429419617965, + 58735.45872458056, + 57585.91906288884, + 59003.13030366512, + -37453.38802730886, + -36689.9824564741, + -33888.1663960553, + 57339.487213868444, + 51513.83286101961, + 46633.76851694451, + 9451.145716270374, + 6486.956110744754, + 4957.81628227334, + 29939.875040449275, + 29478.765053663003, + 29043.078772533325, + 35716.735488752434, + -59612.15306180189, + -59294.38873712498, + -59127.907287882874, + -55907.11718469079, + -12026.40853005452, + -15241.391847088236, + -10462.08756300849, + -12371.368617841707, + 37044.87138428305, + 33021.25289675412, + 34610.915204761666, + 40011.84905629743, + 25902.54295777333, + 25768.144614748064, + 20564.043901966274, + 22714.109069724822, + 12875.546088919305, + 13893.756714962012, + 13490.506594342487, + 14727.611347924598, + 10689.244931054465, + 17538.521291377492, + 23982.713915777626, + 24390.498281955253, + 24762.865678427796, + -45064.46593058627, + -37966.64921236699, + -46059.58460159569, + -49120.96511713206, + -44360.42961138337, + -45008.80023662591, + 2094.812598127086, + 2085.895936089219, + 2573.1373108541593, + 1104.7361987014294, + 3308.886287290079, + 698.8137866817374, + 5393.567671690889, + 5707.221420960841, + 55013.396940812236, + 55544.470228068916, + 57224.00315655217, + 34758.586091369114, + 31679.59372669221, + 33674.127549160745, + 33712.78136073219, + -31333.200170105112, + -29605.973372869845, + -35481.31451239508, + -35017.537957551656, + 63130.3997634869, + 56201.98002258745, + 59459.34956278938, + 27897.179108036376, + 34867.09647977925, + 49218.47853186974, + 41205.40159441225, + 34123.82321041233, + 29333.279117753587, + 29621.64904140896, + 50324.3631913836, + 49593.72552280869, + 49929.12541850021, + 55527.05140347529, + 55909.86001855173, + 47223.27157870629, + 46241.01648214377, + -43556.091011791155, + -37643.13228249952, + -56220.36407542113, + -62305.120350499754, + -61076.48504318068, + -17972.088889636892, + -21976.442708667066, + -19176.50505543119, + -18904.22729632036, + -19263.800263562145, + -12538.24458831298, + -9827.528489899312, + -10414.915634760691, + 23911.34358298873, + 23596.14312044066, + 17829.62627312683, + 43915.88050116565, + 50879.02714367026, + 49993.15637259206, + 52166.07547584346, + 8607.802738756523, + 2245.0909069522613, + 3368.0297663885935, + 3239.560649157949, + -10327.329631677007, + -14227.688657963068, + -20651.84812237891, + -20154.540583292346, + -53708.2135814389, + -53731.92238527414, + -46216.28781449849, + 29882.832150688133, + 31025.252493533244, + 26838.581081892436, + 27429.718875382947, + 24574.667692997973, + -25008.651718108995, + -25641.114108769514, + -20391.068111358632, + -22136.879760045675, + -22500.143694694954, + -22433.79562519107, + -21445.145056313435, + -12631.148780933434, + -5175.118656235392, + -4974.014748854219, + 27174.33433031141, + 26125.565202999907, + 5947.414031173117, + 4231.314002562816, + 5514.803686442698, + -10242.011092887318, + -5594.456938161081, + -8240.143243956536, + 29690.35080922088, + 28639.788268322274, + -40730.76985862218, + -45679.557409096116, + -45875.37994370673, + 4411.4930198940565, + 254.8442404411453, + 51400.29090932576, + 57412.291246702465, + 61044.43950242366, + 60938.90864558535, + -6739.644077840145, + -8987.498835679566, + -5237.371348479321, + 48448.32078503046, + 40259.71525300039, + 36673.04699761284, + 36335.05760810802, + 36616.26156028952, + 35645.440993282224, + -24706.94842684488, + -21833.197922278516, + -20118.5370559781, + -29144.161044259497, + -28841.39017934311, + -33361.50604871394, + 50273.6558612583, + 53577.41459418893, + 62172.47019181349, + 56440.56024064429, + 51644.12024048194, + -58920.77248277155, + -58722.31903774217, + -61546.90999392407, + -61763.752766007725, + 22684.517798921064, + 22687.978622624778, + 17615.43390847237, + 17014.434363396143, + -44454.646506475365, + -40670.4296948947, + 9528.274005783183, + 15124.702546599536, + 11243.865962023567, + 11227.68978808053, + 33179.85253067702, + 28906.810162650283, + 28007.697772657713, + 27353.98686292031, + -64265.88574718186, + -63130.20151200131, + -65536.0, + -64581.179304206045, + 24452.397751976227, + 23231.56579123238, + 23394.965100601486, + -6558.590930642116, + -3700.7274032742203, + -3191.0326641728143, + 19774.367993523556, + 27694.462346775483, + 29492.85073406865, + -14028.154415987468, + -18353.14544453502, + -36813.45891756001, + -36692.297960659314, + -35588.66043701308, + -39033.80716796027, + -40282.86309943496, + 6787.262920580673, + 5863.573743095374, + 222.51042578771012, + 3999.5819537617244, + -2575.8629341373526, + -9285.81901768746, + 20537.513037427605, + 20464.263706784554, + 45745.60016019519, + 40883.516880131516, + 40468.27973749191, + 16862.303937885663, + 23300.195766204517, + 19510.84090013759, + 11527.62347437564, + 30108.422086075327, + 32185.644483843284, + -30593.64787082193, + -31328.665492243064, + -23533.58815929447, + -18274.379953033775, + -64165.83874253259, + -65536.0, + -65536.0, + -65536.0, + -52961.48936175517, + -54114.30757859672, + -51233.966551424906, + 54248.41327512142, + 55940.25897158489, + 49763.46359174742, + 44703.96058500886, + 52829.13296404347, + 52609.69351861534, + 43460.75312509922, + 9158.508068670606, + 9979.665281410318, + 11222.362498340124, + 13070.612773966097, + 14130.01460673544, + 14714.801284683483, + -57391.84915603173, + -58226.95924387508, + -58745.47381533096, + 15155.582389704374, + 15037.11344237593, + 15343.059647357972, + -31139.67098988675, + -36811.17803062407, + -36621.07177150081, + -34954.03004912029, + -3600.7938606276584, + -4872.609255570671, + -5828.29321364815, + -5228.363965939694, + -4650.89050636443, + 1036.6629270363055, + 6139.780821150885, + 46568.89864530167, + 40189.53608848613, + 49413.6690830616, + 28866.760874538086, + 27631.122043076637, + 31651.373637217555, + 51743.92736162846, + 50894.0772057776, + 54730.606260802306, + 53139.583948321655, + 4527.564954490968, + 12189.838122257905, + 10814.215470535108, + 14090.173961864257, + -38155.22830457595, + -40869.613927092214, + -38550.35052437827, + -39694.9360220942, + 43498.596550403585, + 49508.0115361974, + 17528.07416632102, + 18452.718659632777, + 5502.854897138503, + -1477.9959109331921, + 984.4075834326218, + 1497.5246961748412, + 16890.74546327388, + 11323.02179734331, + 7195.558456095547, + 5524.004040319631, + 12912.134627293335}; + wrapper linestring2_offsets{ + 0, 2, 4, 6, 8, 10, 13, 15, 17, 20, 23, 25, 29, 33, 35, 37, 41, + 45, 47, 51, 53, 56, 59, 63, 66, 69, 71, 73, 76, 79, 82, 84, 86, 89, + 93, 96, 98, 100, 103, 105, 107, 109, 113, 116, 119, 123, 126, 129, 133, 137, 139, + 143, 147, 149, 151, 154, 156, 159, 163, 166, 168, 170, 174, 178, 181, 183, 187, 191, + 195, 197, 200, 203, 205, 209, 213, 216, 220, 224, 226, 229, 233, 236, 239, 241, 245, + 248, 250, 252, 254, 256, 258, 260, 262, 264, 267, 269, 271, 275, 279, 281}; + wrapper linestring2_points_x{24046.170375947084, + 20614.007047185743, + 48381.39607717942, + 53346.77764665915, + 4365.496374409238, + 1671.0269165650761, + 60135.10576713836, + 58117.0215375236, + -51494.78094358275, + -59291.16312346822, + 17527.070262173787, + 16140.128075758206, + 21178.29035078248, + -46247.99797412497, + -41770.15815787812, + 52439.4128584852, + 50908.38296602024, + 64834.271974236326, + 61946.67345113476, + 62022.52832061858, + 34288.18665219756, + 28300.340620382718, + 27656.378043110635, + 30794.000810035635, + 32431.166581550326, + 33756.666022670746, + 29664.709989066603, + 28856.873418914183, + 36401.141148038514, + 17079.944290857253, + 13233.118633426348, + 18010.65672629887, + 21733.55299266447, + -17589.12911703354, + -13615.42999872126, + -16962.899142052956, + -14652.153991738582, + 21114.93723313787, + 12910.922082281972, + 3453.1479188972626, + 9769.675794028683, + 1835.0514383492991, + 7756.834125617577, + 7640.602544577206, + 13341.58730161298, + -28356.501919974988, + -28174.220475611586, + 46825.329124044074, + 44931.59733150601, + 38981.41926874932, + 47795.98186123269, + -11635.295606788517, + -9497.235815058624, + 62099.48615805716, + 65535.0, + 65535.0, + -21737.429366590455, + -29042.47786349059, + -31559.31294702657, + 50336.084698268794, + 54641.49898855221, + 54523.92417903646, + 59810.65384878393, + 26109.768995279854, + 33260.44533620665, + 32718.50253715998, + -17046.478062460723, + -13637.902612846676, + -4048.4940472536837, + -1295.089691202047, + -7280.143953298165, + 23307.510964401692, + 21057.78812228635, + 61422.584748784095, + 64125.26236976497, + 63035.70068773205, + 13293.405087485866, + 8301.321717837485, + 5998.566973034347, + 56807.6229253363, + 57284.20136469141, + 50134.09712451558, + 62815.690002302246, + 65535.0, + 18587.476388271883, + 12698.56647818971, + -11373.280290722301, + -8161.778140116089, + -8351.822845788342, + 47561.334575670524, + 48323.03876944549, + 47791.130474422665, + 51987.019421589604, + -19455.18463768006, + -23739.805394183597, + -22568.658462124997, + 23024.079178510918, + 28644.583218064923, + 7298.377778265756, + 3625.7721728530732, + -21594.37878249857, + -22515.531339327168, + -20627.42673352121, + 6099.222612896439, + 8638.445704296702, + 32011.353490737194, + 33208.75937007324, + 926.164443453119, + 5399.2313731423565, + 28186.645319993637, + 28427.65541715838, + 28433.54857881469, + 28309.21054975733, + 49744.365575383126, + 41951.7110218391, + 40709.44234829844, + 59428.37014680178, + 60774.58995358354, + 57864.97505832654, + -12909.579379351642, + -14169.062767062256, + -9472.376817936885, + -8594.555656534549, + 43445.5342784347, + 44146.51386658679, + 44254.395924099306, + 56695.86940969313, + 57328.3459955809, + 59869.09421652202, + -48476.01256692005, + -40572.476190618385, + -41372.611441455665, + -38102.79223698782, + -34160.875071055634, + -31851.944660451976, + -33560.36758089234, + -38956.59298786371, + 47875.729875354155, + 47054.15007723312, + -15763.28154735428, + -15022.415565328583, + -15505.259361620036, + -19433.918706189022, + 21039.330729276393, + 25459.011149795857, + 24228.2200937306, + 24172.896324114823, + 37641.61613795927, + 40093.808079273986, + -64986.04229495289, + -65536.0, + 28865.9861058433, + 31404.205373670076, + 32824.92139989007, + 44076.96662980942, + 42816.334617183755, + -2337.065372176352, + -2454.820165021252, + -21.24489065693888, + 25862.23076924747, + 19792.249382429145, + 19725.81703503653, + 13486.339170409647, + -14132.32043340936, + -13264.825037065333, + -19408.894071066446, + 61758.285121524066, + 61694.84484358259, + 61864.79059036865, + 65535.0, + -6015.210967517021, + -625.9021770409745, + -1591.306712085287, + 3500.835626990062, + 52952.65614611846, + 47855.49296434603, + 45493.81677973004, + 43215.72762748768, + -62101.353403045774, + -61218.466272761565, + -61234.41962391241, + 21279.822206688157, + 28494.696527078828, + 23243.054165080714, + 22547.3541411588, + 15981.433995230766, + 25826.998040730832, + -57172.87410962715, + -54766.5759124097, + -52573.1116877078, + -49403.2785052861, + -7186.542641911306, + -6831.412373191683, + -5756.376457916045, + 3071.2106591016236, + -40420.610893629855, + -48596.10517985245, + 31670.60357638674, + 28210.377929556533, + 23561.64629790607, + -7393.259429801445, + -7262.980859354975, + -14498.642533421951, + -34278.03300122521, + -27990.859726387403, + -35069.67232490826, + -37033.13416444959, + -37012.08647477349, + -40242.36130845048, + 32002.517735259913, + 30237.44459095604, + 31104.766970006913, + 25197.350474127827, + -41345.515497687134, + -42036.75176539078, + -37844.484580749326, + -63374.289355131164, + -63381.35611551266, + -62896.82969782667, + -65536.0, + 19624.504208243205, + 26889.54650881527, + 27539.646814152253, + 26048.399472263092, + 56254.770257432174, + 56748.84925441912, + 9885.400008618206, + 11165.624242290589, + 14734.845074957582, + 64190.81654132414, + 61300.439943480895, + 65535.0, + 65535.0, + 39049.40622870173, + 35265.00781139653, + 35113.170257716505, + -39954.000140931545, + -35513.47414803935, + -34441.82917511126, + 34088.60614329163, + 28700.380052950874, + -36862.33271057148, + -32859.01583612004, + -31191.871795637373, + -32003.331177652333, + -13107.83700891627, + -14688.500860708387, + -18245.151473017104, + -32525.725628515836, + -33993.91682329715, + -20285.86810731778, + -20033.131856054162, + 27300.596012974405, + 26442.988504072695, + 51574.33506953686, + 48117.52341383863, + -21268.443508450517, + -24169.969300778987, + -333.7059961781342, + 1154.802032476863, + 14199.246880886509, + 20052.224683135122, + 9983.515767545046, + 11151.159484611626, + -56914.308516713114, + -54641.0075204614, + -59020.748909382295, + 44354.7875333885, + 45229.63048249438, + 17233.635105441615, + 22050.24381358763, + -28857.15840988976, + -27129.837207157525, + -27069.304704059105, + -23631.070550460405, + -10729.591221458599, + -8664.132241471627, + -12718.241381101057, + -14303.205344482918, + 55134.27218389536, + 55223.4192757591, + 35717.66938371734, + 35472.01653855634}; + wrapper linestring2_points_y{27878.56737867571, + 26489.74880629428, + -8366.313156569413, + -2066.3869793077383, + -59857.47177852941, + -54931.9723439855, + 38267.53117681052, + 36251.55819542643, + -35492.093406511354, + -30996.522241808714, + -8086.285571402303, + -8722.081551830386, + -10309.220371703479, + -61650.13799282254, + -57748.869143045675, + 36589.77853063609, + 42382.411142883866, + -42009.03475077734, + -43330.160502115265, + -43384.801359486424, + 54315.73045932353, + 51572.7217483208, + 49660.694514521245, + -17613.940599695612, + -25461.00124870416, + 2930.21018621228, + 7242.93476191668, + 7089.2529879860085, + 7935.493948240266, + -16918.249798314413, + -14646.772596539959, + -15149.208298184116, + -14858.399234970673, + 8582.92848550067, + 9399.867477813053, + 65388.53291753703, + 60708.706373685935, + -47038.67484287539, + -44436.974813653, + -46995.81345855274, + -49609.90494990711, + 48347.77610172224, + 44246.251316360154, + 47019.96704512191, + 42963.21484589453, + -63963.528608225024, + -65536.0, + 9787.392704550977, + 13439.672239478117, + 14496.797392844519, + 10148.60153259868, + -22651.800929712503, + -16649.619216575462, + 4650.1450472288125, + 5266.110859827297, + 3936.628491570741, + -53166.445914731725, + -49617.99069091295, + -47231.27985078154, + 8788.390044775617, + 17752.918413051135, + 17785.48180855107, + 10113.020826958591, + -26392.86781490936, + -31199.62771961264, + -23532.925723013777, + 57219.46266513846, + 60642.27166155047, + 61672.0437816363, + -41852.75719372246, + -43849.18942821618, + -717.0576789254337, + -2232.2731039226383, + -22610.261973542678, + -19523.462020800576, + -18869.673007678663, + -2103.483618004, + -10147.547174846575, + -16730.549997477177, + -27317.888774417457, + -27086.391416319588, + -22462.000404223618, + 64266.97812828068, + 65181.25034103983, + -15484.952003835955, + -18101.653694566507, + 17916.24799952947, + 24701.144709586413, + 16320.106016260504, + -61771.384861674625, + -52782.31111036583, + -51611.64259346673, + -58989.588758878, + -7478.666862188162, + -11380.37022343936, + -12709.082125210938, + 5900.72118584835, + 6395.841589041828, + -55978.826431399255, + -55062.60168794985, + 37912.85012154847, + 38262.034642766, + 34956.5884614418, + -35145.05363149654, + -35939.357720932756, + 20628.088617133108, + 11686.499722223638, + -24627.362833606363, + -31482.750775167715, + 31249.7777028766, + 40956.78233333402, + 41382.55735505147, + 40949.902974637465, + -10.964158675378712, + 4770.269588717389, + 3198.097209205037, + 14411.554889602106, + 11842.033811629492, + 9460.225339476907, + 55717.70516195832, + 53617.874969892895, + 54665.959995777615, + 53988.3093805043, + 41378.23077159966, + 40781.74245924522, + 40657.70325237871, + -29453.542015459017, + -28477.80164078998, + -33718.83540943996, + -29773.72523753837, + -31506.14700839999, + -31968.71507990374, + -34365.65716442856, + 52633.69733453568, + 50296.82323369251, + 51932.64482266117, + 51395.3773978117, + -42824.239844062744, + -48565.279343794704, + -29759.144315022422, + -28573.755091528295, + -29102.584349813173, + -26602.17892560728, + -28092.517122859063, + -30812.128281190624, + -32209.51925460922, + -31934.77114210906, + -16784.00232362718, + -16102.651271585919, + 35908.33715749516, + 30399.598745360658, + 34047.384049482804, + 28209.48536627418, + 31638.569927646782, + -43893.614732363516, + -49376.46085597309, + 34161.781762612896, + 34097.1586408793, + 25069.348380772386, + 18388.771898399136, + 19068.829437310942, + 19711.266488167785, + 24161.905632044534, + 44472.64135889089, + 43720.18641032237, + 48340.64725467226, + 6192.966639155318, + 6203.925100411371, + 50177.877934877455, + 47460.44816783662, + -12024.648545975433, + -4535.826811613984, + -3650.5896577858566, + -5506.66998864992, + 29128.118385679612, + 33226.99065949976, + 23780.999647643548, + 28153.639507364693, + 78.10279978545441, + 5285.053409188442, + 5290.62055375181, + 60345.148716865806, + 59151.976112230004, + -50613.88913731222, + -43699.717849091336, + -39309.64770588452, + -39663.51573174535, + 20706.3739822825, + 21403.946896398676, + 22086.225322397677, + 26273.919710552575, + -61710.11359807797, + -60698.66473027073, + -62824.68291452278, + -61261.88209984583, + 18127.01517363607, + 19695.781188654408, + -41486.82735240817, + -41060.330490692075, + -45516.04807930786, + 40633.40566135118, + 41663.87208196797, + 38449.17335973677, + -56644.6926276484, + -63116.90663080004, + 37361.362547205834, + 30364.58784041123, + 30681.304342515174, + 28855.462978012318, + -21987.243717104902, + -27379.028811674485, + -27074.127128785443, + -33362.541325203565, + -58053.93959030788, + -61657.50738405434, + -63873.143833855625, + 37016.129171396096, + 33524.920248630624, + 33784.191693610635, + 39523.342546361375, + -58150.579505434085, + -57528.51151392309, + -56378.35863513876, + -54132.85083611531, + 45463.00317181047, + 43746.11772809386, + 23991.38982378789, + 24328.329001705166, + 24658.683567616314, + -9205.219837602555, + -12202.040491158052, + -8368.457799985794, + -3823.856228930549, + -25743.589685013503, + -24495.380332734436, + -24633.63627818454, + -58013.64463594009, + -65536.0, + -65536.0, + 43594.20653120625, + 42070.82051457739, + 8307.234739860229, + 10956.658157004455, + 15817.792373324339, + 20551.44779746299, + 42872.525866358264, + 38601.73767513557, + 33305.31165731295, + 21915.76596169251, + 22187.083798396245, + 8878.050464641972, + 7329.012948283676, + -8923.000585077694, + -5957.730299055878, + 42988.068045101856, + 41995.973894229064, + 606.5265997462848, + 4584.574914234327, + -15000.66037914269, + -23481.51835062977, + -34169.010785194405, + -27270.698407036958, + -47272.24666691125, + -45805.26551921326, + 37722.89763812795, + 42314.87487608766, + 39496.29702855225, + 53499.2552621721, + 47617.793038744414, + 38604.48437014686, + 44812.19238923583, + -49424.475982191696, + -45186.618133268355, + -45232.76215178083, + -54597.0418612454, + -12119.938636133666, + -15205.054401436506, + -17599.196968326814, + -18083.072472929212, + 56421.5370066538, + 56480.56370818126, + -59201.01835964643, + -59182.15595508969}; + + wrapper expected{ + 22000.86425379464, 66907.56415814416, 91319.97744223749, 85968.18301126428, + 102672.3263797747, 65694.82522031936, 23155.596407172834, 69965.78080466804, + 74404.84663547449, 50401.990020141246, 86674.09733792665, 78620.63597017915, + 50270.741668061564, 21742.759144551062, 57053.338441131185, 59274.33513507705, + 48859.389221588026, 81538.69583988942, 102451.30976584884, 48907.78040391256, + 2541.1783777563724, 54018.73837654963, 80019.79050636332, 99125.18435170795, + 86909.77084040688, 100366.96181026987, 68313.25509221756, 97214.36651018754, + 60564.99623503783, 79060.78098596593, 120581.50538980225, 42683.374059987655, + 72540.83585301196, 97288.29179292868, 13733.85425546725, 15638.255020170804, + 99285.77366088502, 36490.14927299419, 22055.190136582223, 59756.41455959068, + 55999.06431045312, 34499.301972964764, 40783.02779733117, 110287.1568555378, + 66432.78557813511, 13775.437319014114, 84497.96964551898, 25978.924986056714, + 62408.80191071194, 93243.74615580632, 52325.4457234104, 79966.38779743231, + 12679.929187884523, 73553.57489706302, 73768.1449667809, 32163.1673140078, + 76843.7399743497, 62642.67444253966, 7647.299340786608, 70644.00936419012, + 75372.8193039762, 67974.71683210952, 38255.30745023753, 86968.76019213336, + 134523.96397533367, 64474.156010664876, 59565.33783639761, 80474.25882097102, + 38173.63396698884, 47219.681710204335, 80438.60559838371, 107397.04958322046, + 38840.989826087316, 92404.38320717831, 142972.7142246719, 120743.00851595176, + 88624.62602444092, 80480.41611758419, 96883.04928998687, 39384.08522694212, + 93051.51572055934, 106136.58472613667, 35435.02384720026, 7045.002778172422, + 61903.57835829537, 82540.74978755743, 43930.005897185314, 38805.25027105973, + 110525.61810095713, 30289.12339639058, 55190.61741153193, 65184.895015007314, + 113100.29945781764, 105574.82641833455, 85774.24359854191, 2878.1066075084723, + 85871.70969639975, 12523.482980018343, 116504.46834362095, 69644.48579719076}; + + auto got = pairwise_linestring_distance(column_view(linestring1_offsets), + linestring1_points_x, + linestring1_points_y, + column_view(linestring2_offsets), + linestring2_points_x, + linestring2_points_y); + expect_columns_equivalent(expected, *got, verbosity); +} + +} // namespace test +} // namespace cuspatial