19#include <cuspatial_test/random.cuh>
20#include <cuspatial_test/vector_factories.cuh>
22#include <cuspatial/cuda_utils.hpp>
27#include <rmm/cuda_stream_view.hpp>
28#include <rmm/device_uvector.hpp>
29#include <rmm/exec_policy.hpp>
31#include <thrust/sequence.h>
32#include <thrust/tabulate.h>
34#include <ranger/ranger.hpp>
43template <
typename T,
typename index_t>
45 vec_2d<T> __device__ operator()(index_t i)
47 return vec_2d<T>{cos(
static_cast<T
>(i)), sin(
static_cast<T
>(i))};
55 vec_2d<T> __device__ operator()(vec_2d<T> prev, vec_2d<T> rad)
57 return prev + segment_length * rad;
72 std::size_t num_multipolygons;
73 std::size_t num_polygons_per_multipolygon;
74 std::size_t num_holes_per_polygon;
75 std::size_t num_edges_per_ring;
79 CUSPATIAL_HOST_DEVICE std::size_t num_polygons()
81 return num_multipolygons * num_polygons_per_multipolygon;
83 CUSPATIAL_HOST_DEVICE std::size_t num_rings() {
return num_polygons() * num_rings_per_polygon(); }
84 CUSPATIAL_HOST_DEVICE std::size_t num_coords() {
return num_rings() * num_vertices_per_ring(); }
85 CUSPATIAL_HOST_DEVICE std::size_t num_vertices_per_ring() {
return num_edges_per_ring + 1; }
86 CUSPATIAL_HOST_DEVICE std::size_t num_rings_per_polygon() {
return num_holes_per_polygon + 1; }
87 CUSPATIAL_HOST_DEVICE T hole_radius() {
return radius / (num_holes_per_polygon + 1); }
104vec_2d<T> __device__ generate_ring_coordinate(std::size_t point_local_idx,
105 std::size_t num_edges,
110 if (point_local_idx == num_edges)
return vec_2d<T>{centroid.x + radius, centroid.y};
112 T angle = (2.0 * M_PI * point_local_idx) / num_edges;
114 return vec_2d<T>{centroid.x + radius * cos(angle), centroid.y + radius * sin(angle)};
130vec_2d<T> __device__ polygon_centroid_displacement(vec_2d<T> centroid,
131 std::size_t part_local_idx,
134 return centroid + vec_2d<T>{part_local_idx * radius * T{3.0}, T{0.0}};
172ring_centroid_displacement(vec_2d<T> centroid, std::size_t ring_local_idx, T radius, T hole_radius)
175 if (ring_local_idx == 0) {
return centroid; }
179 T max_hole_displacement = radius - hole_radius;
180 T displacement_x = -max_hole_displacement + ring_local_idx * hole_radius * 2;
181 T displacement_y = 0.0;
182 return centroid + vec_2d<T>{displacement_x, displacement_y};
196template <
typename T,
typename MultipolygonRange>
197CUSPATIAL_KERNEL
void generate_multipolygon_array_coordinates(
198 MultipolygonRange multipolygons, multipolygon_generator_parameter<T> params)
200 for (
auto idx : ranger::grid_stride_range(multipolygons.num_points())) {
201 auto ring_idx = multipolygons.ring_idx_from_point_idx(idx);
202 auto part_idx = multipolygons.part_idx_from_ring_idx(ring_idx);
203 auto geometry_idx = multipolygons.geometry_idx_from_part_idx(part_idx);
205 auto point_local_idx = idx - params.num_vertices_per_ring() * ring_idx;
206 auto ring_local_idx = ring_idx - params.num_rings_per_polygon() * part_idx;
207 auto part_local_idx = part_idx - params.num_polygons_per_multipolygon * geometry_idx;
209 auto centroid = ring_centroid_displacement(
210 polygon_centroid_displacement(params.centroid, part_local_idx, params.radius),
213 params.hole_radius());
215 if (ring_local_idx == 0)
216 multipolygons.point_begin()[idx] = generate_ring_coordinate(
217 point_local_idx, params.num_edges_per_ring, centroid, params.radius);
219 multipolygons.point_begin()[idx] = generate_ring_coordinate(
220 point_local_idx, params.num_edges_per_ring, centroid, params.hole_radius());
233auto generate_multipolygon_array(multipolygon_generator_parameter<T> params,
234 rmm::cuda_stream_view stream)
236 rmm::device_uvector<std::size_t> geometry_offsets(params.num_multipolygons + 1, stream);
237 rmm::device_uvector<std::size_t> part_offsets(params.num_polygons() + 1, stream);
238 rmm::device_uvector<std::size_t> ring_offsets(params.num_rings() + 1, stream);
239 rmm::device_uvector<vec_2d<T>> coordinates(params.num_coords(), stream);
241 thrust::sequence(rmm::exec_policy(stream),
242 ring_offsets.begin(),
245 params.num_vertices_per_ring());
247 thrust::sequence(rmm::exec_policy(stream),
248 part_offsets.begin(),
251 params.num_rings_per_polygon());
253 thrust::sequence(rmm::exec_policy(stream),
254 geometry_offsets.begin(),
255 geometry_offsets.end(),
257 params.num_polygons_per_multipolygon);
259 auto multipolygons = multipolygon_range(geometry_offsets.begin(),
260 geometry_offsets.end(),
261 part_offsets.begin(),
263 ring_offsets.begin(),
268 auto [tpb, nblocks] = grid_1d(multipolygons.num_points());
270 generate_multipolygon_array_coordinates<T><<<nblocks, tpb, 0, stream>>>(multipolygons, params);
274 return make_multipolygon_array<std::size_t, vec_2d<T>>(std::move(geometry_offsets),
275 std::move(part_offsets),
276 std::move(ring_offsets),
277 std::move(coordinates));
287 std::size_t num_multilinestrings;
288 std::size_t num_linestrings_per_multilinestring;
289 std::size_t num_segments_per_linestring;
293 std::size_t num_linestrings()
295 return num_multilinestrings * num_linestrings_per_multilinestring;
298 std::size_t num_points_per_linestring() {
return num_segments_per_linestring + 1; }
300 std::size_t num_segments() {
return num_linestrings() * num_segments_per_linestring; }
301 std::size_t num_points() {
return num_linestrings() * num_points_per_linestring(); }
328auto generate_multilinestring_array(multilinestring_generator_parameter<T> params,
329 rmm::cuda_stream_view stream)
331 rmm::device_uvector<std::size_t> geometry_offset(params.num_multilinestrings + 1, stream);
332 rmm::device_uvector<std::size_t> part_offset(params.num_linestrings() + 1, stream);
333 rmm::device_uvector<vec_2d<T>> points(params.num_points(), stream);
335 thrust::sequence(rmm::exec_policy(stream),
336 geometry_offset.begin(),
337 geometry_offset.end(),
338 static_cast<std::size_t
>(0),
339 params.num_linestrings_per_multilinestring);
341 thrust::sequence(rmm::exec_policy(stream),
344 static_cast<std::size_t
>(0),
345 params.num_segments_per_linestring + 1);
347 thrust::tabulate(rmm::exec_policy(stream),
352 thrust::exclusive_scan(rmm::exec_policy(stream),
359 return make_multilinestring_array<std::size_t, T>(
360 std::move(geometry_offset), std::move(part_offset), std::move(points));
372 std::size_t num_multipoints;
373 std::size_t num_points_per_multipoints;
374 vec_2d<T> lower_left;
375 vec_2d<T> upper_right;
377 CUSPATIAL_HOST_DEVICE std::size_t num_points()
379 return num_multipoints * num_points_per_multipoints;
392auto generate_multipoint_array(multipoint_generator_parameter<T> params,
393 rmm::cuda_stream_view stream)
395 rmm::device_uvector<vec_2d<T>> coordinates(params.num_points(), stream);
396 rmm::device_uvector<std::size_t> offsets(params.num_multipoints + 1, stream);
398 thrust::sequence(rmm::exec_policy(stream),
402 params.num_points_per_multipoints);
404 auto golden_ratio = (1 + std::sqrt(T{5})) / 2;
405 auto engine_x = deterministic_engine(golden_ratio * params.num_points());
406 auto engine_y = deterministic_engine((1 / golden_ratio) * params.num_points());
408 auto x_dist = make_uniform_dist(params.lower_left.x, params.upper_right.x);
409 auto y_dist = make_uniform_dist(params.lower_left.y, params.upper_right.y);
412 point_generator(params.lower_left, params.upper_right, engine_x, engine_y, x_dist, y_dist);
414 thrust::tabulate(rmm::exec_policy(stream), coordinates.begin(), coordinates.end(), point_gen);
416 return make_multipoint_array(std::move(offsets), std::move(coordinates));
#define CUSPATIAL_CHECK_CUDA(stream)
Debug macro to check for CUDA errors.
Struct to store the parameters of the multilinestring generator.
Struct to store the parameters of the multipoint aray.
Struct to store the parameters of the multipolygon array generator.