-
Notifications
You must be signed in to change notification settings - Fork 156
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Header-only refactoring of
points_in_spatial_window
(#579)
Fixes #564 A couple of notes: 1. For clarity and generality, this name for the header-only version of the function is now `copy_points_in_range()` rather than `points_in_spatial_window()`. This is the reflect that it is a range filter, and we may want to enable constraining the dimensions of the range in the future. 2. I have renamed the parameters for the range delimiters and clarified their documentation. This API is not limited to Cartesian coordinates and the documents make that clear by specifying that the input points and the range limits are specified using points in the same coordinate system. It also uses "quadrilateral" rather than "rectangle", since in lon/lat (spherical) coordinates the range is not a rectangle, but it is a quadrilateral. 3. Note that the change to the iterator-based API means that the user is responsible for allocating the output (as they are with STL and Thrust). Therefore, they need a way to know how much to allocate. In addition to the header-only `copy_points_in_range()`, this PR also adds a new function, `cuspatial::count_points_in_range()`. Previously, the cuDF-based API used `cudf::copy_if`, which does the equivalent of both of the above functions and returns a properly sized pair of columns. The new column-based implementation calls `count_points_in_range`, then allocates the result columns, and then calls `cuspatial::copy_points_in_range()`. Authors: - Mark Harris (https://github.com/harrism) Approvers: - Michael Wang (https://github.com/isVoid) - H. Thomson Comer (https://github.com/thomcom) URL: #579
- Loading branch information
Showing
11 changed files
with
484 additions
and
123 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
92 changes: 92 additions & 0 deletions
92
cpp/include/cuspatial/experimental/detail/points_in_range.cuh
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,92 @@ | ||
/* | ||
* 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 <cuspatial/detail/utility/traits.hpp> | ||
#include <cuspatial/error.hpp> | ||
#include <cuspatial/vec_2d.hpp> | ||
|
||
#include <rmm/cuda_stream_view.hpp> | ||
#include <rmm/exec_policy.hpp> | ||
|
||
#include <type_traits> | ||
|
||
namespace cuspatial { | ||
namespace detail { | ||
|
||
// Functor to filter out points that are not inside the query range. Passed to thrust::copy_if | ||
template <typename T> | ||
struct range_filter { | ||
range_filter(vec_2d<T> vertex_1, vec_2d<T> vertex_2) | ||
: v1{std::min(vertex_1.x, vertex_2.x), std::min(vertex_1.y, vertex_2.y)}, | ||
v2{std::max(vertex_1.x, vertex_2.x), std::max(vertex_1.y, vertex_2.y)} | ||
{ | ||
} | ||
|
||
__device__ inline bool operator()(vec_2d<T> point) | ||
{ | ||
return point.x > v1.x && point.x < v2.x && point.y > v1.y && point.y < v2.y; | ||
} | ||
|
||
protected: | ||
vec_2d<T> v1; | ||
vec_2d<T> v2; | ||
}; | ||
|
||
} // namespace detail | ||
|
||
template <class InputIt, class T> | ||
typename thrust::iterator_traits<InputIt>::difference_type count_points_in_range( | ||
vec_2d<T> vertex_1, | ||
vec_2d<T> vertex_2, | ||
InputIt points_first, | ||
InputIt points_last, | ||
rmm::cuda_stream_view stream) | ||
{ | ||
using Point = typename std::iterator_traits<InputIt>::value_type; | ||
|
||
static_assert(detail::is_convertible_to<cuspatial::vec_2d<T>, Point>(), | ||
"Input points must be convertible to cuspatial::vec_2d"); | ||
|
||
return thrust::count_if( | ||
rmm::exec_policy(stream), points_first, points_last, detail::range_filter{vertex_1, vertex_2}); | ||
} | ||
|
||
template <class InputIt, class OutputIt, class T> | ||
OutputIt copy_points_in_range(vec_2d<T> vertex_1, | ||
vec_2d<T> vertex_2, | ||
InputIt points_first, | ||
InputIt points_last, | ||
OutputIt output_points_first, | ||
rmm::cuda_stream_view stream) | ||
{ | ||
using Point = typename std::iterator_traits<InputIt>::value_type; | ||
|
||
static_assert(detail::is_convertible_to<cuspatial::vec_2d<T>, Point>(), | ||
"Input points must be convertible to cuspatial::vec_2d"); | ||
|
||
static_assert(detail::is_same_floating_point<T, typename Point::value_type>(), | ||
"Inputs and Range coordinates must have the same value type."); | ||
|
||
return thrust::copy_if(rmm::exec_policy(stream), | ||
points_first, | ||
points_last, | ||
output_points_first, | ||
detail::range_filter{vertex_1, vertex_2}); | ||
} | ||
|
||
} // namespace cuspatial |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,118 @@ | ||
/* | ||
* 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 <cuspatial/vec_2d.hpp> | ||
|
||
#include <rmm/cuda_stream_view.hpp> | ||
|
||
#include <thrust/iterator/iterator_traits.h> | ||
|
||
namespace cuspatial { | ||
|
||
/** | ||
* @brief Count of points (x,y) that fall within a query range. | ||
* | ||
* @ingroup spatial_relationship | ||
* | ||
* The query range is defined by a pair of opposite vertices within the coordinate system of the | ||
* input points, `v1` and `v2`. A point (x, y) is in the range if `x` lies between `v1.x` and `v2.x` | ||
* and `y` lies between `v1.y` and `v2.y`. A point is only counted if it is strictly within the | ||
* interior of the query range. Points exactly on an edge or vertex of the range are not counted. | ||
* | ||
* The query range vertices and the input points are assumed to be defined in the same coordinate | ||
* system. | ||
* | ||
* @param[in] vertex_1 Vertex of the query range quadrilateral | ||
* @param[in] vertex_2 Vertex of the query range quadrilateral opposite `vertex_1` | ||
* @param[in] points_first beginning of sequence of (x, y) coordinates of points to be queried | ||
* @param[in] points_last end of sequence of (x, y) coordinates of points to be queried | ||
* @param[in] stream The CUDA stream on which to perform computations | ||
* | ||
* @tparam InputIt Iterator to input points. Must meet the requirements of | ||
* [LegacyRandomAccessIterator][LinkLRAI] and be device-accessible. | ||
* @tparam T The underlying coordinate type. Must be a floating-point type. | ||
* | ||
* @pre All iterators must have the same `value_type`, with the same underlying floating-point | ||
* coordinate type (e.g. `cuspatial::vec_2d<float>`). | ||
* | ||
* @returns The number of input points that fall within the specified query range. | ||
* | ||
* [LinkLRAI]: https://en.cppreference.com/w/cpp/named_req/RandomAccessIterator | ||
* "LegacyRandomAccessIterator" | ||
*/ | ||
template <class InputIt, class T> | ||
typename thrust::iterator_traits<InputIt>::difference_type count_points_in_range( | ||
vec_2d<T> vertex_1, | ||
vec_2d<T> vertex_2, | ||
InputIt points_first, | ||
InputIt points_last, | ||
rmm::cuda_stream_view stream = rmm::cuda_stream_default); | ||
|
||
/** | ||
* @brief Copies points (x,y) that fall within a query range. | ||
* | ||
* @ingroup spatial_relationship | ||
* | ||
* The query range is defined by a pair of opposite vertices of a quadrilateral within the | ||
* coordinate system of the input points, `v1` and `v2`. A point (x, y) is in the range if `x` lies | ||
* between `v1.x` and `v2.x` and `y` lies between `v1.y` and `v2.y`. A point is only counted if it | ||
* is strictly within the interior of the query range. Points exactly on an edge or vertex of the | ||
* range are not copied. | ||
* | ||
* The query range vertices and the input points are assumed to be defined in the same coordinate | ||
* system. | ||
* | ||
* `output_points_first` must be an iterator to storage of sufficient size for the points that will | ||
* be copied. cuspatial::count_points_in_range may be used to determine the size required. | ||
* | ||
* @param[in] vertex_1 Vertex of the query range quadrilateral | ||
* @param[in] vertex_2 Vertex of the query range quadrilateral opposite `vertex_1` | ||
* @param[in] points_first beginning of sequence of (x, y) coordinates of points to be queried | ||
* @param[in] points_last end of sequence of (x, y) coordinates of points to be queried | ||
* @param[out] output_points_first beginning of output range of (x, y) coordinates within the | ||
* query range | ||
* @param[in] stream The CUDA stream on which to perform computations and allocate memory. | ||
* | ||
* @tparam InputIt Iterator to input points. Must meet the requirements of | ||
* [LegacyRandomAccessIterator][LinkLRAI] and be device-accessible. | ||
* @tparam OutputIt Output iterator. Must meet the requirements of | ||
* [LegacyRandomAccessIterator][LinkLRAI] and be device-accessible and mutable. | ||
* @tparam T The underlying coordinate type. Must be a floating-point type. | ||
* | ||
* @pre The range `[points_first, points_last)` may equal the range `[output_points_first, | ||
* output_points_first + std::distance(points_first, points_last)), but the ranges may not | ||
* partially overlap. | ||
* @pre All iterators must have the same `value_type`, with the same underlying floating-point | ||
* coordinate type (e.g. `cuspatial::vec_2d<float>`). | ||
* | ||
* @returns Output iterator to the element past the last output point. | ||
* | ||
* [LinkLRAI]: https://en.cppreference.com/w/cpp/named_req/RandomAccessIterator | ||
* "LegacyRandomAccessIterator" | ||
*/ | ||
template <class InputIt, class OutputIt, class T> | ||
OutputIt copy_points_in_range(vec_2d<T> vertex_1, | ||
vec_2d<T> vertex_2, | ||
InputIt points_first, | ||
InputIt points_last, | ||
OutputIt output_points_first, | ||
rmm::cuda_stream_view stream = rmm::cuda_stream_default); | ||
|
||
} // namespace cuspatial | ||
|
||
#include <cuspatial/experimental/detail/points_in_range.cuh> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.