Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Column API for linestring-polygon distance #1030

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
7022c1d
initial
isVoid Mar 24, 2023
5686be3
add segment iterator and tests
isVoid Mar 28, 2023
a74af14
WIP
isVoid Mar 28, 2023
1c28faa
making progress towards getting the right index
isVoid Mar 29, 2023
243d2d9
commiting progress
isVoid Mar 29, 2023
0da0afc
able to get the right segment combinations from within the kernel, ne…
isVoid Mar 31, 2023
49e43aa
[skip-ci] initial port from feature/linestring_polygon_distance_header
isVoid Mar 31, 2023
e8e45d0
Apply suggestions from code review
isVoid Mar 31, 2023
fadf5c8
Update cpp/include/cuspatial/experimental/detail/functors.cuh
isVoid Mar 31, 2023
fe31542
address review comments
isVoid Mar 31, 2023
af0c35e
address review comments
isVoid Mar 31, 2023
05bf7ff
[skip-ci] address review coments
isVoid Mar 31, 2023
2435126
Add docstrings for functors
isVoid Mar 31, 2023
98a4a0f
[skip-ci] adds linestring_count test
isVoid Apr 1, 2023
9b72723
[skip-ci] revert removed code
isVoid Apr 1, 2023
6971200
style
isVoid Apr 1, 2023
6f7a226
update unexpected changes
isVoid Apr 1, 2023
641934f
license
isVoid Apr 1, 2023
c580876
Merge branch 'feature/segment_iterators' into feature/linestring_poly…
isVoid Apr 1, 2023
890e95b
Update cpp/include/cuspatial/experimental/detail/ranges/multilinestri…
isVoid Apr 1, 2023
040e432
making a bit of progress
isVoid Apr 2, 2023
7c3603c
fix broken multilinestring->multipoint constructor
isVoid Apr 2, 2023
5966ad0
Merge branch 'feature/segment_iterators' of github.com:isVoid/cuspati…
isVoid Apr 2, 2023
70ca1b6
fix broken multilinestring->multipoint constructor
isVoid Apr 2, 2023
9205533
passing existing tests
isVoid Apr 3, 2023
4bb3ca3
fix wrong test setup and update docs
isVoid Apr 3, 2023
9f34700
Merge branch 'feature/segment_iterators' into feature/linestring_poly…
isVoid Apr 3, 2023
8f20feb
style
isVoid Apr 3, 2023
3ffe5ee
Delete point_in_multipolygon.cuh
isVoid Apr 3, 2023
894f870
Delete linestring_polygon_distance.hpp
isVoid Apr 3, 2023
2b99555
cleanup - first round
isVoid Apr 3, 2023
656d093
Merge branch 'feature/linestring_polygon_distance_header' of github.c…
isVoid Apr 3, 2023
62d821f
merge duplicate code
isVoid Apr 3, 2023
76e5b7e
initial
isVoid Apr 3, 2023
7d22749
add missing header
isVoid Apr 3, 2023
9051944
style
isVoid Apr 3, 2023
075d12a
Merge branch 'feature/linestring_polygon_distance_header' into featur…
isVoid Apr 3, 2023
5ed7616
add tests
isVoid Apr 3, 2023
a160f71
style
isVoid Apr 3, 2023
1d52bb0
Merge branch 'branch-23.06' of https://github.com/rapidsai/cuspatial …
isVoid Apr 7, 2023
471be4c
Update cpp/include/cuspatial/distance/linestring_polygon_distance.hpp
isVoid Apr 18, 2023
3a95d60
Merge branch 'branch-23.06' into feature/linestring_polygon_distance_…
isVoid Apr 18, 2023
7d95117
remove data tests in cpp
isVoid Apr 18, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions cpp/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,7 @@ add_library(cuspatial
src/spatial/point_distance.cu
src/spatial/point_linestring_distance.cu
src/spatial/point_polygon_distance.cu
src/spatial/linestring_polygon_distance.cu
src/spatial/point_linestring_nearest_points.cu
src/spatial/sinusoidal_projection.cu
src/trajectory/derive_trajectories.cu
Expand Down
49 changes: 49 additions & 0 deletions cpp/include/cuspatial/distance/linestring_polygon_distance.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/*
* Copyright (c) 2023, 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 <cuspatial/column/geometry_column_view.hpp>

#include <cudf/column/column_view.hpp>

#include <optional>

namespace cuspatial {

/**
* @ingroup distance
* @brief Compute pairwise (multi)linestring-to-(multi)polygon Cartesian distance
*
* @param multilinestrings Geometry column of multilinestrings
* @param multipolygons Geometry column of multipolygons
* @param mr Device memory resource used to allocate the returned column.
* @return Column of distances between each pair of input geometries, same type as input coordinate
* types.
*
* @throw cuspatial::logic_error if `multilinestrings` and `multipolygons` have different coordinate
* types.
* @throw cuspatial::logic_error if `multilinestrings` is not a linestring column and
* `multipolygons` is not a polygon column.
* @throw cuspatial::logic_error if input column sizes mismatch.
*/

std::unique_ptr<cudf::column> pairwise_linestring_polygon_distance(
geometry_column_view const& multilinestrings,
geometry_column_view const& multipolygons,
rmm::mr::device_memory_resource* mr = rmm::mr::get_current_device_resource());

} // namespace cuspatial
Original file line number Diff line number Diff line change
Expand Up @@ -54,10 +54,11 @@ struct to_multipoint_functor {
} // namespace detail

template <typename GeometryIterator, typename VecIterator>
multipoint_range<GeometryIterator, VecIterator>::multipoint_range(GeometryIterator geometry_begin,
GeometryIterator geometry_end,
VecIterator points_begin,
VecIterator points_end)
CUSPATIAL_HOST_DEVICE multipoint_range<GeometryIterator, VecIterator>::multipoint_range(
GeometryIterator geometry_begin,
GeometryIterator geometry_end,
VecIterator points_begin,
VecIterator points_end)
: _geometry_begin(geometry_begin),
_geometry_end(geometry_end),
_points_begin(points_begin),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,10 +57,10 @@ class multipoint_range {
/**
* @brief Construct a new multipoint array object
*/
multipoint_range(GeometryIterator geometry_begin,
GeometryIterator geometry_end,
VecIterator points_begin,
VecIterator points_end);
CUSPATIAL_HOST_DEVICE multipoint_range(GeometryIterator geometry_begin,
GeometryIterator geometry_end,
VecIterator points_begin,
VecIterator points_end);
/**
* @brief Returns the number of multipoints in the array.
*/
Expand Down
127 changes: 127 additions & 0 deletions cpp/src/spatial/linestring_polygon_distance.cu
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
/*
* Copyright (c) 2023, 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 "../utility/iterator.hpp"
#include "../utility/multi_geometry_dispatch.hpp"

#include <cudf/column/column.hpp>
#include <cudf/column/column_device_view.cuh>
#include <cudf/column/column_factories.hpp>
#include <cudf/column/column_view.hpp>
#include <cudf/copying.hpp>
#include <cudf/types.hpp>
#include <cudf/utilities/traits.hpp>
#include <cudf/utilities/type_dispatcher.hpp>

#include <rmm/cuda_stream_view.hpp>

#include <cuspatial/column/geometry_column_view.hpp>
#include <cuspatial/detail/iterator.hpp>
#include <cuspatial/error.hpp>
#include <cuspatial/experimental/iterator_factory.cuh>
#include <cuspatial/experimental/linestring_polygon_distance.cuh>
#include <cuspatial/experimental/ranges/multilinestring_range.cuh>
#include <cuspatial/experimental/ranges/multipolygon_range.cuh>
#include <cuspatial/types.hpp>

#include <thrust/iterator/counting_iterator.h>

#include <memory>
#include <type_traits>

namespace cuspatial {

namespace detail {

namespace {

template <collection_type_id is_multi_linestring, collection_type_id is_multi_polygon>
struct pairwise_linestring_polygon_distance_impl {
using SizeType = cudf::device_span<cudf::size_type const>::size_type;

template <typename T, CUDF_ENABLE_IF(std::is_floating_point_v<T>)>
std::unique_ptr<cudf::column> operator()(geometry_column_view const& multilinestrings,
geometry_column_view const& multipolygons,
rmm::cuda_stream_view stream,
rmm::mr::device_memory_resource* mr)
{
auto multilinestrings_range =
make_multilinestring_range<is_multi_linestring, T, cudf::size_type>(multilinestrings);
auto multipolygons_range =
make_multipolygon_range<is_multi_polygon, T, cudf::size_type>(multipolygons);

auto output = cudf::make_numeric_column(multilinestrings.coordinate_type(),
multilinestrings.size(),
cudf::mask_state::UNALLOCATED,
stream,
mr);

cuspatial::pairwise_linestring_polygon_distance(
multilinestrings_range, multipolygons_range, output->mutable_view().begin<T>(), stream);
return output;
}

template <typename T, CUDF_ENABLE_IF(!std::is_floating_point_v<T>), typename... Args>
std::unique_ptr<cudf::column> operator()(Args&&...)

{
CUSPATIAL_FAIL("linestring-polygon distance API only supports floating point coordinates.");
}
};

} // namespace

template <collection_type_id is_multi_linestring, collection_type_id is_multi_polygon>
struct pairwise_linestring_polygon_distance {
std::unique_ptr<cudf::column> operator()(geometry_column_view const& multilinestrings,
geometry_column_view const& multipolygons,
rmm::cuda_stream_view stream,
rmm::mr::device_memory_resource* mr)
{
return cudf::type_dispatcher(
multilinestrings.coordinate_type(),
pairwise_linestring_polygon_distance_impl<is_multi_linestring, is_multi_polygon>{},
multilinestrings,
multipolygons,
stream,
mr);
}
};

} // namespace detail

std::unique_ptr<cudf::column> pairwise_linestring_polygon_distance(
geometry_column_view const& multilinestrings,
geometry_column_view const& multipolygons,
rmm::mr::device_memory_resource* mr)
{
CUSPATIAL_EXPECTS(multilinestrings.geometry_type() == geometry_type_id::LINESTRING &&
multipolygons.geometry_type() == geometry_type_id::POLYGON,
"Unexpected input geometry types.");

CUSPATIAL_EXPECTS(multilinestrings.coordinate_type() == multipolygons.coordinate_type(),
"Input geometries must have the same coordinate data types.");

return multi_geometry_double_dispatch<detail::pairwise_linestring_polygon_distance>(
multilinestrings.collection_type(),
multipolygons.collection_type(),
multilinestrings,
multipolygons,
rmm::cuda_stream_default,
mr);
}

} // namespace cuspatial
3 changes: 3 additions & 0 deletions cpp/tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,9 @@ ConfigureTest(LINESTRING_DISTANCE_TEST
ConfigureTest(POINT_POLYGON_DISTANCE_TEST
spatial/point_polygon_distance_test.cpp)

ConfigureTest(LINESTRING_POLYGON_DISTANCE_TEST
spatial/linestring_polygon_distance_test.cpp)

ConfigureTest(LINESTRING_INTERSECTION_TEST
spatial/linestring_intersection_test.cpp)

Expand Down
166 changes: 166 additions & 0 deletions cpp/tests/spatial/linestring_polygon_distance_test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
/*
* Copyright (c) 2023, 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 <cuspatial_test/column_factories.hpp>
#include <cuspatial_test/vector_equality.hpp>

#include <cuspatial/column/geometry_column_view.hpp>
#include <cuspatial/distance/linestring_polygon_distance.hpp>
#include <cuspatial/error.hpp>
#include <cuspatial/types.hpp>
#include <cuspatial/vec_2d.hpp>

#include <cudf_test/column_utilities.hpp>
#include <cudf_test/column_wrapper.hpp>

#include <cudf/utilities/default_stream.hpp>

#include <rmm/cuda_stream_view.hpp>

#include <initializer_list>
#include <memory>

using namespace cuspatial;
using namespace cuspatial::test;

using namespace cudf;
using namespace cudf::test;

template <typename T>
struct PairwiseLinestringPolygonDistanceTest : ::testing::Test {
rmm::cuda_stream_view stream() { return cudf::get_default_stream(); }
void SetUp()
{
collection_type_id _;
std::tie(_, empty_linestring_column) = make_linestring_column<T>({0}, {}, stream());
std::tie(_, empty_multilinestring_column) = make_linestring_column<T>({0}, {0}, {}, stream());
std::tie(_, empty_polygon_column) = make_polygon_column<T>({0}, {0}, {}, stream());
std::tie(_, empty_multipolygon_column) = make_polygon_column<T>({0}, {0}, {0}, {}, stream());
}

geometry_column_view empty_linestring()
{
return geometry_column_view(
empty_linestring_column->view(), collection_type_id::SINGLE, geometry_type_id::LINESTRING);
}

geometry_column_view empty_multilinestring()
{
return geometry_column_view(empty_multilinestring_column->view(),
collection_type_id::MULTI,
geometry_type_id::LINESTRING);
}

geometry_column_view empty_polygon()
{
return geometry_column_view(
empty_polygon_column->view(), collection_type_id::SINGLE, geometry_type_id::POLYGON);
}

geometry_column_view empty_multipolygon()
{
return geometry_column_view(
empty_multipolygon_column->view(), collection_type_id::MULTI, geometry_type_id::POLYGON);
}

void run_single(geometry_column_view linestrings,
geometry_column_view polygons,
std::initializer_list<T> expected)
{
auto got = pairwise_linestring_polygon_distance(linestrings, polygons);
CUDF_TEST_EXPECT_COLUMNS_EQUIVALENT(*got, fixed_width_column_wrapper<T>(expected));
}

std::unique_ptr<cudf::column> empty_linestring_column;
std::unique_ptr<cudf::column> empty_multilinestring_column;
std::unique_ptr<cudf::column> empty_polygon_column;
std::unique_ptr<cudf::column> empty_multipolygon_column;
};

struct PairwiseLinestringPolygonDistanceTestUntyped : testing::Test {
rmm::cuda_stream_view stream() { return cudf::get_default_stream(); }
};

using TestTypes = ::testing::Types<float, double>;

TYPED_TEST_CASE(PairwiseLinestringPolygonDistanceTest, TestTypes);

TYPED_TEST(PairwiseLinestringPolygonDistanceTest, SingleToSingleEmpty)
{
CUSPATIAL_RUN_TEST(this->run_single, this->empty_linestring(), this->empty_polygon(), {});
};

TYPED_TEST(PairwiseLinestringPolygonDistanceTest, SingleToMultiEmpty)
{
CUSPATIAL_RUN_TEST(this->run_single, this->empty_linestring(), this->empty_multipolygon(), {});
};

TYPED_TEST(PairwiseLinestringPolygonDistanceTest, MultiToSingleEmpty)
{
CUSPATIAL_RUN_TEST(this->run_single, this->empty_multilinestring(), this->empty_polygon(), {});
};

TYPED_TEST(PairwiseLinestringPolygonDistanceTest, MultiToMultiEmpty)
{
CUSPATIAL_RUN_TEST(
this->run_single, this->empty_multilinestring(), this->empty_multipolygon(), {});
};

TEST_F(PairwiseLinestringPolygonDistanceTestUntyped, SizeMismatch)
{
auto [ptype, linestrings] =
make_linestring_column<float>({0, 1, 2}, {0, 1, 2}, {0.0, 0.0, 1.0, 1.0}, this->stream());

auto [polytype, polygons] =
make_polygon_column<float>({0, 1}, {0, 1}, {0, 4}, {1, 1, 1, 2, 2, 2, 1, 1}, this->stream());

auto linestrings_view =
geometry_column_view(linestrings->view(), ptype, geometry_type_id::LINESTRING);
auto polygons_view = geometry_column_view(polygons->view(), polytype, geometry_type_id::POLYGON);

EXPECT_THROW(pairwise_linestring_polygon_distance(linestrings_view, polygons_view),
cuspatial::logic_error);
};

TEST_F(PairwiseLinestringPolygonDistanceTestUntyped, TypeMismatch)
{
auto [ptype, linestrings] =
make_linestring_column<double>({0, 1}, {0, 1}, {0.0, 0.0}, this->stream());

auto [polytype, polygons] =
make_polygon_column<float>({0, 1}, {0, 1}, {0, 4}, {1, 1, 1, 2, 2, 2, 1, 1}, this->stream());

auto linestrings_view =
geometry_column_view(linestrings->view(), ptype, geometry_type_id::LINESTRING);
auto polygons_view = geometry_column_view(polygons->view(), polytype, geometry_type_id::POLYGON);

EXPECT_THROW(pairwise_linestring_polygon_distance(linestrings_view, polygons_view),
cuspatial::logic_error);
};

TEST_F(PairwiseLinestringPolygonDistanceTestUntyped, WrongGeometryType)
{
auto [ptype, points] = make_point_column<double>({0, 1}, {0.0, 0.0}, this->stream());

auto [polytype, polygons] =
make_polygon_column<float>({0, 1}, {0, 1}, {0, 4}, {1, 1, 1, 2, 2, 2, 1, 1}, this->stream());

auto points_view = geometry_column_view(points->view(), ptype, geometry_type_id::POINT);
auto polygons_view = geometry_column_view(polygons->view(), polytype, geometry_type_id::POLYGON);

EXPECT_THROW(pairwise_linestring_polygon_distance(points_view, polygons_view),
cuspatial::logic_error);
};