Skip to content

Commit

Permalink
Header-only quadtree_point_to_nearest_linestring (#1005)
Browse files Browse the repository at this point in the history
Closes #986. Depends on #979.

Authors:
  - Mark Harris (https://github.com/harrism)

Approvers:
  - Michael Wang (https://github.com/isVoid)
  - Paul Taylor (https://github.com/trxcllnt)

URL: #1005
  • Loading branch information
harrism authored Mar 30, 2023
1 parent ff22dd1 commit fee47ef
Show file tree
Hide file tree
Showing 24 changed files with 1,083 additions and 583 deletions.
2 changes: 1 addition & 1 deletion cpp/benchmarks/points_in_range.cu
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@

#include <memory>

using namespace cuspatial;
using cuspatial::vec_2d;

/**
* @brief Helper to generate random points within a range
Expand Down
45 changes: 45 additions & 0 deletions cpp/include/cuspatial/detail/utility/validation.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,51 @@

#include <cuspatial/error.hpp>

/**
* @brief Macro for validating the data array sizes for linestrings.
*
* Raises an exception if any of the following are false:
* - The number of linestring offsets is greater than zero.
* - There are at least two vertices per linestring offset.
*
* Linestrings follow [GeoArrow data layout][1]. Offsets arrays have one more element than the
* number of items in the array. The last offset is always the sum of the previous offset and the
* size of that element. For example the last value in the linestring offsets array is the
* last linestring offset plus one. See [Arrow Variable-Size Binary layout](2). Note that an
* empty list still has one offset: {0}.
*
* [1]: https://github.com/geoarrow/geoarrow/blob/main/format.md
* [2]: https://arrow.apache.org/docs/format/Columnar.html#variable-size-binary-layout
*/
#define CUSPATIAL_EXPECTS_VALID_LINESTRING_SIZES(num_linestring_points, num_linestring_offsets) \
CUSPATIAL_EXPECTS(num_linestring_offsets > 0, \
"Polygon offsets must contain at least one (1) value"); \
CUSPATIAL_EXPECTS(num_linestring_points >= 2 * (num_linestring_offsets - 1), \
"Each linestring must have at least two vertices");

/**
* @brief Macro for validating the data array sizes for multilinestrings.
*
* Raises an exception if any of the following are false:
* - The number of multilinestring offsets is greater than zero.
* - The number of linestring offsets is greater than zero.
* - There are at least two vertices per linestring offset.
*
* Multilinestrings follow [GeoArrow data layout][1]. Offsets arrays have one more element than the
* number of items in the array. The last offset is always the sum of the previous offset and the
* size of that element. For example the last value in the linestring offsets array is the
* last linestring offset plus one. See [Arrow Variable-Size Binary layout](2). Note that an
* empty list still has one offset: {0}.
*
* [1]: https://github.com/geoarrow/geoarrow/blob/main/format.md
* [2]: https://arrow.apache.org/docs/format/Columnar.html#variable-size-binary-layout
*/
#define CUSPATIAL_EXPECTS_VALID_MULTILINESTRING_SIZES( \
num_linestring_points, num_multilinestring_offsets, num_linestring_offsets) \
CUSPATIAL_EXPECTS(num_multilinestring_offsets > 0, \
"Multilinestring offsets must contain at least one (1) value"); \
CUSPATIAL_EXPECTS_VALID_LINESTRING_SIZES(num_linestring_points, num_linestring_offsets);

/**
* @brief Macro for validating the data array sizes for a polygon.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ namespace cuspatial {
namespace detail {

/**
* @brief Kernel to test if a point is inside a polygon.
* @brief Test if a point is inside a polygon.
*
* Implemented based on Eric Haines's crossings-multiply algorithm:
* See "Crossings test" section of http://erich.realtimerendering.com/ptinpoly/
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
/*
* 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/experimental/geometry/linestring_ref.cuh>
#include <cuspatial/experimental/geometry/segment.cuh>
#include <cuspatial/vec_2d.hpp>

namespace cuspatial {
namespace detail {

template <typename T>
__device__ T proj2(segment<T> const& s, vec_2d<T> const& v)
{
return dot(v - s.v1, s.v2 - s.v1);
}

template <typename T, typename LinestringRef>
inline __device__ T point_linestring_distance(vec_2d<T> const& point,
LinestringRef const& linestring)
{
T distance_squared = std::numeric_limits<T>::max();

for (auto const& s : linestring) {
auto v1p = point - s.v1;
auto v2p = point - s.v2;
auto d0 = dot(v1p, v1p);
auto d1 = dot(v2p, v2p);
auto d2 = s.length2();
auto d3 = proj2(s, point);
auto const r = d3 * d3 / d2;
auto const d = (d3 <= 0 || r >= d2) ? min(d0, d1) : d0 - r;
distance_squared = min(distance_squared, d);
}

return sqrt(distance_squared);
}

} // namespace detail
} // namespace cuspatial
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,12 @@ BoundingBoxIterator linestring_bounding_boxes(LinestringOffsetIterator linestrin
T expansion_radius,
rmm::cuda_stream_view stream)
{
static_assert(is_same<T, iterator_vec_base_type<VertexIterator>>(),
"expansion_radius type must match vertex floating-point type");

static_assert(is_floating_point<T>(), "Only floating point polygon vertices supported");

static_assert(is_same<vec_2d<T>, iterator_value_type<VertexIterator>>(),
static_assert(is_vec_2d<iterator_value_type<VertexIterator>>,
"Input vertices must be cuspatial::vec_2d");

static_assert(cuspatial::is_integral<iterator_value_type<LinestringOffsetIterator>>(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,12 @@ BoundingBoxIterator polygon_bounding_boxes(PolygonOffsetIterator polygon_offsets
T expansion_radius,
rmm::cuda_stream_view stream)
{
static_assert(is_same<T, iterator_vec_base_type<VertexIterator>>(),
"expansion_radius type must match vertex floating-point type");

static_assert(is_floating_point<T>(), "Only floating point polygon vertices supported");

static_assert(is_same<vec_2d<T>, iterator_value_type<VertexIterator>>(),
static_assert(is_vec_2d<iterator_value_type<VertexIterator>>,
"Input vertices must be cuspatial::vec_2d");

static_assert(cuspatial::is_integral<iterator_value_type<PolygonOffsetIterator>,
Expand Down
Loading

0 comments on commit fee47ef

Please sign in to comment.