libcuspatial  23.12.00
Loading...
Searching...
No Matches
vector_factories.cuh
1/*
2 * Copyright (c) 2022-2023, NVIDIA CORPORATION.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#pragma once
18
19#include <cuspatial_test/test_util.cuh>
20
26#include <cuspatial/traits.hpp>
27
28#include <rmm/cuda_stream_view.hpp>
29#include <rmm/device_uvector.hpp>
30#include <rmm/device_vector.hpp>
31
32#include <thrust/device_vector.h>
33#include <thrust/host_vector.h>
34
35#include <initializer_list>
36#include <numeric>
37#include <tuple>
38#include <vector>
39
40namespace cuspatial {
41namespace test {
42
43template <typename Range>
44auto make_device_vector(Range rng)
45{
46 using T = typename Range::value_type;
47 return rmm::device_vector<T>(rng.begin(), rng.end());
48}
49
50template <typename T>
51auto make_device_vector(std::initializer_list<T> inl)
52{
53 return rmm::device_vector<T>(inl.begin(), inl.end());
54}
55
56template <typename T>
57auto make_device_uvector(std::initializer_list<T> inl,
58 rmm::cuda_stream_view stream,
59 rmm::mr::device_memory_resource* mr)
60{
61 std::vector<T> hvec(inl.begin(), inl.end());
62 auto res = rmm::device_uvector<T>(inl.size(), stream, mr);
63 cudaMemcpyAsync(res.data(),
64 hvec.data(),
65 hvec.size() * sizeof(T),
66 cudaMemcpyKind::cudaMemcpyHostToDevice,
67 stream.value());
68 return res;
69}
70
71template <typename T>
72auto make_host_vector(std::initializer_list<T> inl)
73{
74 return thrust::host_vector<T>{inl.begin(), inl.end()};
75}
76
85template <typename GeometryArray, typename PartArray, typename RingArray, typename CoordinateArray>
87 public:
88 using geometry_t = typename GeometryArray::value_type;
89 using part_t = typename PartArray::value_type;
90 using ring_t = typename RingArray::value_type;
91 using coord_t = typename CoordinateArray::value_type;
92
93 multipolygon_array(thrust::device_vector<geometry_t> geometry_offsets_array,
94 thrust::device_vector<part_t> part_offsets_array,
95 thrust::device_vector<ring_t> ring_offsets_array,
96 thrust::device_vector<coord_t> coordinates_array)
97 : _geometry_offsets_array(geometry_offsets_array),
98 _part_offsets_array(part_offsets_array),
99 _ring_offsets_array(ring_offsets_array),
100 _coordinates_array(coordinates_array)
101 {
102 }
103
104 multipolygon_array(rmm::device_vector<geometry_t>&& geometry_offsets_array,
105 rmm::device_vector<part_t>&& part_offsets_array,
106 rmm::device_vector<ring_t>&& ring_offsets_array,
107 rmm::device_vector<coord_t>&& coordinates_array)
108 : _geometry_offsets_array(std::move(geometry_offsets_array)),
109 _part_offsets_array(std::move(part_offsets_array)),
110 _ring_offsets_array(std::move(ring_offsets_array)),
111 _coordinates_array(std::move(coordinates_array))
112 {
113 }
114
115 multipolygon_array(rmm::device_uvector<geometry_t>&& geometry_offsets_array,
116 rmm::device_uvector<part_t>&& part_offsets_array,
117 rmm::device_uvector<ring_t>&& ring_offsets_array,
118 rmm::device_uvector<coord_t>&& coordinates_array)
119 : _geometry_offsets_array(std::move(geometry_offsets_array)),
120 _part_offsets_array(std::move(part_offsets_array)),
121 _ring_offsets_array(std::move(ring_offsets_array)),
122 _coordinates_array(std::move(coordinates_array))
123 {
124 }
125
127 auto size() { return _geometry_offsets_array.size() - 1; }
128
130 auto range()
131 {
132 return multipolygon_range(_geometry_offsets_array.begin(),
133 _geometry_offsets_array.end(),
134 _part_offsets_array.begin(),
135 _part_offsets_array.end(),
136 _ring_offsets_array.begin(),
137 _ring_offsets_array.end(),
138 _coordinates_array.begin(),
139 _coordinates_array.end());
140 }
141
145 auto to_host() const
146 {
147 auto geometry_offsets = cuspatial::test::to_host<geometry_t>(_geometry_offsets_array);
148 auto part_offsets = cuspatial::test::to_host<part_t>(_part_offsets_array);
149 auto ring_offsets = cuspatial::test::to_host<ring_t>(_ring_offsets_array);
150 auto coordinate_offsets = cuspatial::test::to_host<coord_t>(_coordinates_array);
151
152 return std::tuple{geometry_offsets, part_offsets, ring_offsets, coordinate_offsets};
153 }
154
155 auto release()
156 {
157 return std::tuple{std::move(_geometry_offsets_array),
158 std::move(_part_offsets_array),
159 std::move(_ring_offsets_array),
160 std::move(_coordinates_array)};
161 }
162
166 friend std::ostream& operator<<(
167 std::ostream& os,
168 multipolygon_array<GeometryArray, PartArray, RingArray, CoordinateArray> const& arr)
169 {
170 auto [geometry_offsets, part_offsets, ring_offsets, coordinates] = arr.to_host();
171
172 return os << "Geometry Offsets:\n\t{" << geometry_offsets << "}\n"
173 << "Part Offsets:\n\t{" << part_offsets << "}\n"
174 << "Ring Offsets: \n\t{" << ring_offsets << "}\n"
175 << "Coordinates: \n\t{" << coordinates << "}\n";
176 }
177
178 protected:
179 GeometryArray _geometry_offsets_array;
180 PartArray _part_offsets_array;
181 RingArray _ring_offsets_array;
182 CoordinateArray _coordinates_array;
183};
184
185template <typename IndexRange,
186 typename CoordRange,
187 typename IndexType = typename IndexRange::value_type>
188auto make_multipolygon_array(IndexRange geometry_inl,
189 IndexRange part_inl,
190 IndexRange ring_inl,
191 CoordRange coord_inl)
192{
193 using CoordType = typename CoordRange::value_type;
194 using DeviceIndexVector = thrust::device_vector<IndexType>;
195 using DeviceCoordVector = thrust::device_vector<CoordType>;
196
197 return multipolygon_array<DeviceIndexVector,
198 DeviceIndexVector,
199 DeviceIndexVector,
200 DeviceCoordVector>(make_device_vector(geometry_inl),
201 make_device_vector(part_inl),
202 make_device_vector(ring_inl),
203 make_device_vector(coord_inl));
204}
205
206template <typename T>
207auto make_multipolygon_array(std::initializer_list<std::size_t> geometry_inl,
208 std::initializer_list<std::size_t> part_inl,
209 std::initializer_list<std::size_t> ring_inl,
210 std::initializer_list<vec_2d<T>> coord_inl)
211{
212 return make_multipolygon_array(range(geometry_inl.begin(), geometry_inl.end()),
213 range(part_inl.begin(), part_inl.end()),
214 range(ring_inl.begin(), ring_inl.end()),
215 range(coord_inl.begin(), coord_inl.end()));
216}
217
218template <typename IndexType, typename CoordType>
219auto make_multipolygon_array(rmm::device_uvector<IndexType> geometry_inl,
220 rmm::device_uvector<IndexType> part_inl,
221 rmm::device_uvector<IndexType> ring_inl,
222 rmm::device_uvector<CoordType> coord_inl)
223{
224 return multipolygon_array<rmm::device_uvector<IndexType>,
225 rmm::device_uvector<IndexType>,
226 rmm::device_uvector<IndexType>,
227 rmm::device_uvector<CoordType>>(
228 std::move(geometry_inl), std::move(part_inl), std::move(ring_inl), std::move(coord_inl));
229}
230
238template <typename GeometryArray, typename PartArray, typename CoordinateArray>
240 public:
241 multilinestring_array(GeometryArray geometry_offsets_array,
242 PartArray part_offsets_array,
243 CoordinateArray coordinate_array)
244 : _geometry_offset_array(std::move(geometry_offsets_array)),
245 _part_offset_array(std::move(part_offsets_array)),
246 _coordinate_array(std::move(coordinate_array))
247 {
248 }
249
251 auto size() { return _geometry_offset_array.size() - 1; }
252
254 auto range()
255 {
256 return multilinestring_range(_geometry_offset_array.begin(),
257 _geometry_offset_array.end(),
258 _part_offset_array.begin(),
259 _part_offset_array.end(),
260 _coordinate_array.begin(),
261 _coordinate_array.end());
262 }
263
264 auto release()
265 {
266 return std::tuple{std::move(_geometry_offset_array),
267 std::move(_part_offset_array),
268 std::move(_coordinate_array)};
269 }
270
271 protected:
272 GeometryArray _geometry_offset_array;
273 PartArray _part_offset_array;
274 CoordinateArray _coordinate_array;
275};
276
285template <typename IndexType, typename T>
286auto make_multilinestring_array(rmm::device_uvector<IndexType>&& geometry_inl,
287 rmm::device_uvector<IndexType>&& part_inl,
288 rmm::device_uvector<vec_2d<T>>&& coord_inl)
289{
290 return multilinestring_array<rmm::device_uvector<IndexType>,
291 rmm::device_uvector<IndexType>,
292 rmm::device_uvector<vec_2d<T>>>(
293 std::move(geometry_inl), std::move(part_inl), std::move(coord_inl));
294}
295
304template <typename IndexType, typename T>
305auto make_multilinestring_array(rmm::device_vector<IndexType>&& geometry_inl,
306 rmm::device_vector<IndexType>&& part_inl,
307 rmm::device_vector<vec_2d<T>>&& coord_inl)
308{
309 return multilinestring_array<rmm::device_vector<IndexType>,
310 rmm::device_vector<IndexType>,
311 rmm::device_vector<vec_2d<T>>>(
312 std::move(geometry_inl), std::move(part_inl), std::move(coord_inl));
313}
314
324template <typename T>
325auto make_multilinestring_array(std::initializer_list<std::size_t> geometry_inl,
326 std::initializer_list<std::size_t> part_inl,
327 std::initializer_list<vec_2d<T>> coord_inl)
328{
329 return multilinestring_array(
330 rmm::device_vector<std::size_t>(
331 std::vector<std::size_t>(geometry_inl.begin(), geometry_inl.end())),
332 rmm::device_vector<std::size_t>(std::vector<unsigned int>(part_inl.begin(), part_inl.end())),
333 rmm::device_vector<vec_2d<T>>(std::vector<vec_2d<T>>(coord_inl.begin(), coord_inl.end())));
334}
335
342template <typename GeometryArray, typename CoordinateArray>
344 public:
345 using geometry_t = typename GeometryArray::value_type;
346 using coord_t = typename CoordinateArray::value_type;
347
348 multipoint_array(thrust::device_vector<geometry_t> geometry_offsets_array,
349 thrust::device_vector<coord_t> coordinate_array)
350 : _geometry_offsets(geometry_offsets_array), _coordinates(coordinate_array)
351 {
352 }
353
354 multipoint_array(rmm::device_uvector<geometry_t>&& geometry_offsets_array,
355 rmm::device_uvector<coord_t>&& coordinate_array)
356 : _geometry_offsets(std::move(geometry_offsets_array)),
357 _coordinates(std::move(coordinate_array))
358 {
359 }
360
362 auto size() { return _geometry_offsets.size() - 1; }
363
365 auto range()
366 {
367 return multipoint_range{
368 _geometry_offsets.begin(), _geometry_offsets.end(), _coordinates.begin(), _coordinates.end()};
369 }
370
372 auto release() { return std::pair{std::move(_geometry_offsets), std::move(_coordinates)}; }
373
374 private:
375 GeometryArray _geometry_offsets;
376 CoordinateArray _coordinates;
377};
378
383template <typename GeometryRange, typename CoordRange>
384auto make_multipoint_array(GeometryRange geometry_inl, CoordRange coordinates_inl)
385{
386 using IndexType = typename GeometryRange::value_type;
387 using CoordType = typename CoordRange::value_type;
388 using DeviceIndexVector = thrust::device_vector<IndexType>;
389 using DeviceCoordVector = thrust::device_vector<CoordType>;
390
391 return multipoint_array<DeviceIndexVector, DeviceCoordVector>{
392 make_device_vector(geometry_inl), make_device_vector(coordinates_inl)};
393}
394
409template <typename T>
410auto make_multipoint_array(std::initializer_list<std::initializer_list<vec_2d<T>>> inl)
411{
412 std::vector<std::size_t> offsets{0};
413 std::transform(inl.begin(), inl.end(), std::back_inserter(offsets), [](auto multipoint) {
414 return multipoint.size();
415 });
416 std::inclusive_scan(offsets.begin(), offsets.end(), offsets.begin());
417
418 std::vector<vec_2d<T>> coordinates = std::accumulate(
419 inl.begin(), inl.end(), std::vector<vec_2d<T>>{}, [](std::vector<vec_2d<T>>& init, auto cur) {
420 init.insert(init.end(), cur.begin(), cur.end());
421 return init;
422 });
423
424 return multipoint_array<rmm::device_vector<std::size_t>, rmm::device_vector<vec_2d<T>>>{
425 rmm::device_vector<std::size_t>(offsets), rmm::device_vector<vec_2d<T>>(coordinates)};
426}
427
432template <typename IndexType, typename T>
433auto make_multipoint_array(rmm::device_uvector<IndexType> geometry_offsets,
434 rmm::device_uvector<vec_2d<T>> coords)
435{
436 return multipoint_array<rmm::device_uvector<std::size_t>, rmm::device_uvector<vec_2d<T>>>{
437 std::move(geometry_offsets), std::move(coords)};
438}
439
444template <typename IndexType, typename T>
445auto make_multipoint_array(rmm::device_vector<IndexType> geometry_offsets,
446 rmm::device_vector<vec_2d<T>> coords)
447{
448 return multipoint_array<rmm::device_vector<std::size_t>, rmm::device_vector<vec_2d<T>>>{
449 std::move(geometry_offsets), std::move(coords)};
450}
451
452} // namespace test
453} // namespace cuspatial
Non-owning range-based interface to multilinestring data.
Non-owning range-based interface to multipoint data.
Non-owning range-based interface to multipolygon data.
Owning object of a multilinestring array following geoarrow layout.
auto size()
Return the number of multilinestrings.
auto range()
Return range object of the multilinestring array.
Owning object of a multipoint array following geoarrow format.
auto size()
Return the number of multipoints.
auto range()
Return range object of the multipoint array.
Owning object of a multipolygon array following geoarrow layout.
auto range()
Return range object of the multipolygon array.
auto to_host() const
Copy the offset arrays to host.
friend std::ostream & operator<<(std::ostream &os, multipolygon_array< GeometryArray, PartArray, RingArray, CoordinateArray > const &arr)
Output stream operator for multipolygon_array for human-readable formatting.
auto size()
Return the number of multipolygons.