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 <ranger/ranger.hpp>
33#include <thrust/sequence.h>
34#include <thrust/tabulate.h>
41template <
typename T,
typename index_t>
43 vec_2d<T> __device__ operator()(index_t i)
45 return vec_2d<T>{cos(
static_cast<T
>(i)), sin(
static_cast<T
>(i))};
53 vec_2d<T> __device__ operator()(vec_2d<T> prev, vec_2d<T> rad)
55 return prev + segment_length * rad;
70 std::size_t num_multipolygons;
71 std::size_t num_polygons_per_multipolygon;
72 std::size_t num_holes_per_polygon;
73 std::size_t num_edges_per_ring;
77 CUSPATIAL_HOST_DEVICE std::size_t num_polygons()
79 return num_multipolygons * num_polygons_per_multipolygon;
81 CUSPATIAL_HOST_DEVICE std::size_t num_rings() {
return num_polygons() * num_rings_per_polygon(); }
82 CUSPATIAL_HOST_DEVICE std::size_t num_coords() {
return num_rings() * num_vertices_per_ring(); }
83 CUSPATIAL_HOST_DEVICE std::size_t num_vertices_per_ring() {
return num_edges_per_ring + 1; }
84 CUSPATIAL_HOST_DEVICE std::size_t num_rings_per_polygon() {
return num_holes_per_polygon + 1; }
85 CUSPATIAL_HOST_DEVICE T hole_radius() {
return radius / (num_holes_per_polygon + 1); }
102vec_2d<T> __device__ generate_ring_coordinate(std::size_t point_local_idx,
103 std::size_t num_edges,
108 if (point_local_idx == num_edges)
return vec_2d<T>{centroid.x + radius, centroid.y};
110 T angle = (2.0 * M_PI * point_local_idx) / num_edges;
112 return vec_2d<T>{centroid.x + radius * cos(angle), centroid.y + radius * sin(angle)};
128vec_2d<T> __device__ polygon_centroid_displacement(vec_2d<T> centroid,
129 std::size_t part_local_idx,
132 return centroid + vec_2d<T>{part_local_idx * radius * T{3.0}, T{0.0}};
170ring_centroid_displacement(vec_2d<T> centroid, std::size_t ring_local_idx, T radius, T hole_radius)
173 if (ring_local_idx == 0) {
return centroid; }
177 T max_hole_displacement = radius - hole_radius;
178 T displacement_x = -max_hole_displacement + ring_local_idx * hole_radius * 2;
179 T displacement_y = 0.0;
180 return centroid + vec_2d<T>{displacement_x, displacement_y};
194template <
typename T,
typename MultipolygonRange>
195void __global__ generate_multipolygon_array_coordinates(MultipolygonRange multipolygons,
196 multipolygon_generator_parameter<T> params)
198 for (
auto idx : ranger::grid_stride_range(multipolygons.num_points())) {
199 auto ring_idx = multipolygons.ring_idx_from_point_idx(idx);
200 auto part_idx = multipolygons.part_idx_from_ring_idx(ring_idx);
201 auto geometry_idx = multipolygons.geometry_idx_from_part_idx(part_idx);
203 auto point_local_idx = idx - params.num_vertices_per_ring() * ring_idx;
204 auto ring_local_idx = ring_idx - params.num_rings_per_polygon() * part_idx;
205 auto part_local_idx = part_idx - params.num_polygons_per_multipolygon * geometry_idx;
207 auto centroid = ring_centroid_displacement(
208 polygon_centroid_displacement(params.centroid, part_local_idx, params.radius),
211 params.hole_radius());
213 if (ring_local_idx == 0)
214 multipolygons.point_begin()[idx] = generate_ring_coordinate(
215 point_local_idx, params.num_edges_per_ring, centroid, params.radius);
217 multipolygons.point_begin()[idx] = generate_ring_coordinate(
218 point_local_idx, params.num_edges_per_ring, centroid, params.hole_radius());
231auto generate_multipolygon_array(multipolygon_generator_parameter<T> params,
232 rmm::cuda_stream_view stream)
234 rmm::device_uvector<std::size_t> geometry_offsets(params.num_multipolygons + 1, stream);
235 rmm::device_uvector<std::size_t> part_offsets(params.num_polygons() + 1, stream);
236 rmm::device_uvector<std::size_t> ring_offsets(params.num_rings() + 1, stream);
237 rmm::device_uvector<vec_2d<T>> coordinates(params.num_coords(), stream);
239 thrust::sequence(rmm::exec_policy(stream),
240 ring_offsets.begin(),
243 params.num_vertices_per_ring());
245 thrust::sequence(rmm::exec_policy(stream),
246 part_offsets.begin(),
249 params.num_rings_per_polygon());
251 thrust::sequence(rmm::exec_policy(stream),
252 geometry_offsets.begin(),
253 geometry_offsets.end(),
255 params.num_polygons_per_multipolygon);
257 auto multipolygons = multipolygon_range(geometry_offsets.begin(),
258 geometry_offsets.end(),
259 part_offsets.begin(),
261 ring_offsets.begin(),
266 auto [tpb, nblocks] = grid_1d(multipolygons.num_points());
268 generate_multipolygon_array_coordinates<T><<<nblocks, tpb, 0, stream>>>(multipolygons, params);
272 return make_multipolygon_array<std::size_t, vec_2d<T>>(std::move(geometry_offsets),
273 std::move(part_offsets),
274 std::move(ring_offsets),
275 std::move(coordinates));
285 std::size_t num_multilinestrings;
286 std::size_t num_linestrings_per_multilinestring;
287 std::size_t num_segments_per_linestring;
291 std::size_t num_linestrings()
293 return num_multilinestrings * num_linestrings_per_multilinestring;
296 std::size_t num_points_per_linestring() {
return num_segments_per_linestring + 1; }
298 std::size_t num_segments() {
return num_linestrings() * num_segments_per_linestring; }
299 std::size_t num_points() {
return num_linestrings() * num_points_per_linestring(); }
326auto generate_multilinestring_array(multilinestring_generator_parameter<T> params,
327 rmm::cuda_stream_view stream)
329 rmm::device_uvector<std::size_t> geometry_offset(params.num_multilinestrings + 1, stream);
330 rmm::device_uvector<std::size_t> part_offset(params.num_linestrings() + 1, stream);
331 rmm::device_uvector<vec_2d<T>> points(params.num_points(), stream);
333 thrust::sequence(rmm::exec_policy(stream),
334 geometry_offset.begin(),
335 geometry_offset.end(),
336 static_cast<std::size_t
>(0),
337 params.num_linestrings_per_multilinestring);
339 thrust::sequence(rmm::exec_policy(stream),
342 static_cast<std::size_t
>(0),
343 params.num_segments_per_linestring + 1);
345 thrust::tabulate(rmm::exec_policy(stream),
350 thrust::exclusive_scan(rmm::exec_policy(stream),
357 return make_multilinestring_array<std::size_t, T>(
358 std::move(geometry_offset), std::move(part_offset), std::move(points));
370 std::size_t num_multipoints;
371 std::size_t num_points_per_multipoints;
372 vec_2d<T> lower_left;
373 vec_2d<T> upper_right;
375 CUSPATIAL_HOST_DEVICE std::size_t num_points()
377 return num_multipoints * num_points_per_multipoints;
390auto generate_multipoint_array(multipoint_generator_parameter<T> params,
391 rmm::cuda_stream_view stream)
393 rmm::device_uvector<vec_2d<T>> coordinates(params.num_points(), stream);
394 rmm::device_uvector<std::size_t> offsets(params.num_multipoints + 1, stream);
396 thrust::sequence(rmm::exec_policy(stream),
400 params.num_points_per_multipoints);
402 auto engine_x = deterministic_engine(params.num_points());
403 auto engine_y = deterministic_engine(2 * params.num_points());
405 auto x_dist = make_uniform_dist(params.lower_left.x, params.upper_right.x);
406 auto y_dist = make_uniform_dist(params.lower_left.y, params.upper_right.y);
409 point_generator(params.lower_left, params.upper_right, engine_x, engine_y, x_dist, y_dist);
411 thrust::tabulate(rmm::exec_policy(stream), coordinates.begin(), coordinates.end(), point_gen);
413 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.