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

Header-only polygon_bounding_boxes and linestring_bounding_boxes, make_geometry_id_iterator utility, and box<T> class. #820

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
a23f06a
Add failing tests and empty header-only implementation
harrism Nov 23, 2022
dcc0f7f
Working header-only API
harrism Nov 23, 2022
df8d8f9
Port column-based API to call header-only API
harrism Nov 23, 2022
fe7bf68
Merge branch 'branch-23.02' into fea-header-only-polygon-bboxes
harrism Nov 24, 2022
44e2bd2
Fix tests, add expansion_radius
harrism Nov 24, 2022
5b87d80
Reinstate early out for empty
harrism Nov 24, 2022
02ad17b
tests
harrism Nov 24, 2022
2675fef
Add make_box_output_iterator and make_geometry_id_iterator factories.
harrism Nov 30, 2022
947da30
box type
harrism Nov 30, 2022
18642c1
use make_geometry_id_iterator
harrism Nov 30, 2022
2fdd802
Use box type
harrism Nov 30, 2022
bec3e95
doc
harrism Nov 30, 2022
7f85e72
Correct tparam name in doc
harrism Nov 30, 2022
1ebaea8
implementation tparam names
harrism Nov 30, 2022
a9bf663
header-only linestring_bounding_boxes refactor
harrism Nov 30, 2022
2df0fae
Merge branch 'branch-23.02' into fea-header-only-polygon-bboxes
harrism Dec 6, 2022
6f5bf15
Add deduction guides.
harrism Dec 7, 2022
de41f67
Fix index_to_geometry_id to actually return an ID and fix examples in…
harrism Dec 7, 2022
26acde0
Merge branch 'branch-23.02' into fea-header-only-polygon-bboxes
harrism Dec 13, 2022
63f770b
Merge branch 'branch-23.02' into fea-header-only-polygon-bboxes
harrism Dec 13, 2022
4b27c39
Generalize expect_segment_equivalent to expect_vec_2d_pair_equivalent…
harrism Dec 13, 2022
c86a332
Document segment and make more generic.
harrism Dec 13, 2022
79a9168
doc
harrism Dec 13, 2022
e0fc84a
doc
harrism Dec 13, 2022
fb1f2be
Missed first->v1, second -> v2
harrism Dec 13, 2022
fc2b339
Comply with GeoArrow spec for geometry and part offsets.
harrism Dec 13, 2022
fd8a67e
Add column API doc precondition about offsets for GeoArrow
harrism Dec 13, 2022
586e471
Fix python tests and column-based API offset size expectations
harrism Dec 14, 2022
53d3e0e
As above for linestring
harrism Dec 14, 2022
bce13d3
Add insufficient offsets test
harrism Dec 14, 2022
69ea0a1
include
harrism Dec 14, 2022
d0f7541
Add missing param docs
harrism Dec 14, 2022
434bf2f
Merge branch 'branch-23.02' into fea-header-only-polygon-bboxes
harrism Dec 14, 2022
b22019a
Fix quadtree bounding box tests for arrow offsets
harrism Dec 14, 2022
54f3bb0
Fix spatial join pytest
harrism Dec 14, 2022
d630cbb
Merge branch 'branch-23.02' into fea-header-only-polygon-bboxes
harrism Dec 14, 2022
7e1576a
Fix segment conflicts
harrism Dec 14, 2022
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
17 changes: 5 additions & 12 deletions cpp/include/cuspatial/experimental/detail/bounding_box.cuh
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

#pragma once

#include <cuspatial/experimental/iterator_factory.cuh>
#include <cuspatial/traits.hpp>
#include <cuspatial/vec_2d.hpp>

Expand All @@ -33,32 +34,24 @@ namespace detail {

template <typename T>
struct point_bounding_box {
using point_tuple = thrust::tuple<cuspatial::vec_2d<T>, cuspatial::vec_2d<T>>;

vec_2d<T> box_offset{};

CUSPATIAL_HOST_DEVICE point_bounding_box(T expansion_radius = T{0})
: box_offset{expansion_radius, expansion_radius}
{
}

inline __host__ __device__ point_tuple operator()(vec_2d<T> const& point)
inline CUSPATIAL_HOST_DEVICE box<T> operator()(vec_2d<T> const& point)
{
return point_tuple{point - box_offset, point + box_offset};
return box<T>{point - box_offset, point + box_offset};
}
};

template <typename T>
struct box_minmax {
using point_tuple = thrust::tuple<cuspatial::vec_2d<T>, cuspatial::vec_2d<T>>;

inline __host__ __device__ point_tuple operator()(point_tuple const& a, point_tuple const& b)
inline CUSPATIAL_HOST_DEVICE box<T> operator()(box<T> const& a, box<T> const& b)
{
// structured binding doesn't seem to work with thrust::tuple
vec_2d<T> p1, p2, p3, p4;
thrust::tie(p1, p2) = a;
thrust::tie(p3, p4) = b;
return {box_min(box_min(p1, p2), p3), box_max(box_max(p1, p2), p4)};
return {box_min(box_min(a.v1, a.v2), b.v1), box_max(box_max(a.v1, a.v2), b.v2)};
}
};

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
/*
* 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/experimental/bounding_box.cuh>
#include <cuspatial/experimental/iterator_factory.cuh>
#include <cuspatial/traits.hpp>

#include <rmm/cuda_stream_view.hpp>
#include <rmm/device_vector.hpp>
#include <rmm/exec_policy.hpp>

#include <thrust/gather.h>
#include <thrust/scan.h>
#include <thrust/scatter.h>

namespace cuspatial {

thomcom marked this conversation as resolved.
Show resolved Hide resolved
template <class LinestringOffsetIterator,
class VertexIterator,
class BoundingBoxIterator,
class T,
class IndexT>
BoundingBoxIterator linestring_bounding_boxes(LinestringOffsetIterator linestring_offsets_first,
LinestringOffsetIterator linestring_offsets_last,
VertexIterator linestring_vertices_first,
VertexIterator linestring_vertices_last,
BoundingBoxIterator bounding_boxes_first,
T expansion_radius,
rmm::cuda_stream_view stream)
{
static_assert(is_floating_point<T>(), "Only floating point polygon vertices supported");

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

static_assert(cuspatial::is_integral<iterator_value_type<LinestringOffsetIterator>>(),
"Offset iterators must have integral value type.");

// GeoArrow: Number of linestrings is number of offsets minus one.
auto const num_linestrings = std::distance(linestring_offsets_first, linestring_offsets_last) - 1;
auto const num_vertices = std::distance(linestring_vertices_first, linestring_vertices_last);

if (num_linestrings == 0 || num_vertices == 0) { return bounding_boxes_first; }

auto vertex_ids_iter =
make_geometry_id_iterator<IndexT>(linestring_offsets_first, linestring_offsets_last);

return point_bounding_boxes(vertex_ids_iter,
vertex_ids_iter + num_vertices,
linestring_vertices_first,
bounding_boxes_first,
expansion_radius,
stream);
}
} // namespace cuspatial
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
/*
* 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/experimental/bounding_box.cuh>
#include <cuspatial/experimental/iterator_factory.cuh>
#include <cuspatial/traits.hpp>

#include <rmm/cuda_stream_view.hpp>
#include <rmm/device_vector.hpp>
#include <rmm/exec_policy.hpp>

#include <thrust/gather.h>
#include <thrust/scan.h>
#include <thrust/scatter.h>

namespace cuspatial {

thomcom marked this conversation as resolved.
Show resolved Hide resolved
template <class PolygonOffsetIterator,
class RingOffsetIterator,
class VertexIterator,
class BoundingBoxIterator,
class T,
class IndexT>
BoundingBoxIterator polygon_bounding_boxes(PolygonOffsetIterator polygon_offsets_first,
PolygonOffsetIterator polygon_offsets_last,
RingOffsetIterator polygon_ring_offsets_first,
RingOffsetIterator polygon_ring_offsets_last,
VertexIterator polygon_vertices_first,
VertexIterator polygon_vertices_last,
BoundingBoxIterator bounding_boxes_first,
T expansion_radius,
rmm::cuda_stream_view stream)
{
static_assert(is_floating_point<T>(), "Only floating point polygon vertices supported");

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

static_assert(cuspatial::is_integral<iterator_value_type<PolygonOffsetIterator>,
iterator_value_type<RingOffsetIterator>>(),
"OffsetIterators must have integral value type.");

auto const num_polys = std::distance(polygon_offsets_first, polygon_offsets_last) - 1;
auto const num_rings = std::distance(polygon_ring_offsets_first, polygon_ring_offsets_last) - 1;
auto const num_vertices = std::distance(polygon_vertices_first, polygon_vertices_last);

CUSPATIAL_EXPECTS(num_rings >= num_polys, "Each polygon must have at least one ring");

CUSPATIAL_EXPECTS(num_vertices >= num_polys * 3, "Each ring must have at least three vertices");

if (num_polys == 0 || num_rings == 0 || num_vertices == 0) { return bounding_boxes_first; }

auto vertex_ids_iter = make_geometry_id_iterator<IndexT>(
polygon_offsets_first, polygon_offsets_last, polygon_ring_offsets_first);

return point_bounding_boxes(vertex_ids_iter,
vertex_ids_iter + num_vertices,
polygon_vertices_first,
bounding_boxes_first,
expansion_radius,
stream);
}
} // namespace cuspatial
50 changes: 50 additions & 0 deletions cpp/include/cuspatial/experimental/geometry/box.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/*
* 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>

namespace cuspatial {

/**
* @addtogroup types
* @{
*/

/**
* @brief A generic axis-aligned box type.
*
* @tparam T the base type for the coordinates
* @tparam Vertex the vector type to use for vertices, vec_2d<T> by default
*/
template <typename T, typename Vertex = cuspatial::vec_2d<T>>
class alignas(sizeof(Vertex)) box {
public:
using value_type = T;
Vertex v1;
harrism marked this conversation as resolved.
Show resolved Hide resolved
Vertex v2;
};

// deduction guide, enables CTAD
template <typename T>
box(vec_2d<T> a, vec_2d<T> b) -> box<T, vec_2d<T>>;

/**
* @} // end of doxygen group
*/

} // namespace cuspatial
30 changes: 23 additions & 7 deletions cpp/include/cuspatial/experimental/geometry/segment.cuh
Original file line number Diff line number Diff line change
Expand Up @@ -21,21 +21,37 @@

namespace cuspatial {

template <typename T>
class segment {
/**
* @addtogroup types
* @{
*/

/**
* @brief A generic segment type.
*
* @tparam T the base type for the coordinates
* @tparam Vertex the vector type to use for vertices, vec_2d<T> by default
*/

template <typename T, typename Vertex = cuspatial::vec_2d<T>>
class alignas(sizeof(Vertex)) segment {
public:
using value_type = T;
vec_2d<T> first;
vec_2d<T> second;
Vertex v1;
Vertex v2;

/// Return a copy of segment, translated by `v`.
segment<T> CUSPATIAL_HOST_DEVICE translate(vec_2d<T> const& v) const
segment<T> CUSPATIAL_HOST_DEVICE translate(Vertex const& v) const
{
return segment<T>{first + v, second + v};
return segment<T>{v1 + v, v2 + v};
}

/// Return the geometric center of segment.
vec_2d<T> CUSPATIAL_HOST_DEVICE center() const { return midpoint(first, second); }
Vertex CUSPATIAL_HOST_DEVICE center() const { return midpoint(v1, v2); }
};

// deduction guide, enables CTAD
template <typename T>
segment(vec_2d<T> a, vec_2d<T> b) -> segment<T, vec_2d<T>>;

} // namespace cuspatial
Loading