OmniSciDB  72c90bc290
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
GeoTestTableFunctions.cpp
Go to the documentation of this file.
1 /*
2  * Copyright 2021 OmniSci, Inc.
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 #include "TableFunctionsTesting.h"
18 
19 /*
20  This file contains testing geometry-related compile-time UDTFs.
21 
22  NOTE: This file currently has no GPU UDTFs. If any GPU UDTFs are
23  added, it should be added to CUDA_TABLE_FUNCTION_FILES in CMakeLists.txt
24  */
25 
26 #ifndef __CUDACC__
27 
29  const Column<GeoPoint>& points,
30  Column<double>& xcoords,
31  Column<double>& ycoords) {
32  auto size = points.size();
33  mgr.set_output_row_size(size);
34  for (int64_t i = 0; i < size; i++) {
35  if (points.isNull(i)) {
36  xcoords.setNull(i);
37  ycoords.setNull(i);
38  } else {
39  const auto point = points[i];
40  xcoords[i] = point.x;
41  ycoords[i] = point.y;
42  }
43  }
44  return size;
45 }
46 
48  const Column<GeoPoint>& points,
49  const double x,
50  const double y,
51  Column<GeoPoint>& shifted_points) {
52  auto size = points.size();
53  mgr.set_output_row_size(size);
54  for (int64_t i = 0; i < size; i++) {
55  if (points.isNull(i)) {
56  shifted_points.setNull(i);
57  } else {
58  auto point = points[i];
59  point.x += x;
60  point.y += y;
61  shifted_points.setItem(i, point);
62  }
63  }
64  return size;
65 }
66 
67 template <typename T>
69  const Column<T>& points,
70  int64_t n,
71  Column<double>& xcoords,
72  Column<double>& ycoords) {
73  auto size = points.size();
74  mgr.set_output_row_size(size);
75  for (int64_t i = 0; i < size; i++) {
76  if (points.isNull(i)) {
77  xcoords.setNull(i);
78  ycoords.setNull(i);
79  } else {
80  const auto point = points[i][n - 1]; // n is one-based
81  xcoords[i] = point.x;
82  ycoords[i] = point.y;
83  }
84  }
85  return size;
86 }
87 
88 // explicit instantiations
89 template NEVER_INLINE HOST int32_t
91  const Column<GeoLineString>& points,
92  int64_t n,
93  Column<double>& xcoords,
94  Column<double>& ycoords);
95 
96 template NEVER_INLINE HOST int32_t
98  const Column<GeoMultiPoint>& points,
99  int64_t n,
100  Column<double>& xcoords,
101  Column<double>& ycoords);
102 
103 // explicit instantiations
104 
106  const Column<GeoPolygon>& polygons,
107  int64_t n,
108  Column<GeoLineString>& linestrings) {
109  auto size = polygons.size();
111  mgr.set_output_row_size(size);
112  for (int64_t i = 0; i < size; i++) {
113  if (polygons.isNull(i)) {
114  linestrings.setNull(i);
115  } else {
116  int64_t sz = polygons[i].size();
117  if (n < 1 || n > sz) {
118  linestrings.setNull(i);
119  } else {
120  const auto poly = polygons[i];
121  const auto ring = poly[n - 1];
122  linestrings.setItem(i, ring);
123  }
124  }
125  }
126  return size;
127 }
128 
130  const Column<GeoLineString>& rings,
131  const Column<GeoLineString>& holes1,
132  const Column<GeoLineString>& holes2,
133  Column<GeoPolygon>& polygons,
134  Column<int>& sizes) {
135  auto size = rings.size();
137  0, rings.getNofValues() + holes1.getNofValues() + holes2.getNofValues());
138  mgr.set_output_row_size(size);
139  // Initialize polygons
140  int count_nulls = 0;
141  for (int64_t i = 0; i < size; i++) {
142  if (rings.isNull(i)) {
143  polygons.setNull(i);
144  sizes.setNull(i);
145  count_nulls++;
146  } else {
147  std::vector<std::vector<double>> polygon_coords;
148 
149  polygon_coords.push_back(rings[i].toCoords());
150  if (!holes1.isNull(i)) {
151  polygon_coords.push_back(holes1[i].toCoords());
152  if (!holes2.isNull(i)) {
153  polygon_coords.push_back(holes2[i].toCoords());
154  }
155  }
156 
157  auto polygon = polygons[i];
158  auto status = polygon.fromCoords(polygon_coords);
159 
160  if (status != FlatBufferManager::Status::Success) {
161  return mgr.ERROR_MESSAGE("fromCoords failed: " + ::toString(status));
162  }
163  int nofpoints = 0;
164  for (size_t j = 0; j < polygon.size(); j++) {
165  nofpoints += polygon.size(j);
166  }
167  sizes[i] = nofpoints;
168  }
169  }
170 
171  // Check polygons content
172  if (count_nulls == 0) {
173  return mgr.ERROR_MESSAGE("counting null test failed: count_nulls=" +
174  ::toString(count_nulls) + ", expected non-zero.");
175  }
176 
177  for (int64_t i = 0; i < size; i++) {
178  if (polygons.isNull(i)) {
179  count_nulls--;
180  } else {
181  std::vector<std::vector<double>> polygon_coords;
182  polygon_coords.push_back(rings[i].toCoords());
183  if (!holes1.isNull(i)) {
184  polygon_coords.push_back(holes1[i].toCoords());
185  }
186  if (!holes2.isNull(i)) {
187  polygon_coords.push_back(holes2[i].toCoords());
188  }
189 
190  // polygons[i] is Geo::Polygon instances
191  // polygons[i][j] is Geo::LineString instances
192  // polygons[i][j][k] is Geo::Point2D instances
193 
194  auto nof_lines = polygons[i].size();
195 
196  if (nof_lines != polygon_coords.size()) {
197  return mgr.ERROR_MESSAGE(
198  "polygon size test failed: nof_lines=" + ::toString(nof_lines) +
199  ", expected " + ::toString(polygon_coords.size()) + ".");
200  }
201  std::vector<std::vector<double>> poly_coords = polygons[i].toCoords();
202  if (nof_lines != poly_coords.size()) {
203  return mgr.ERROR_MESSAGE(
204  "polygon toCoords size test failed: poly_coords.size()=" +
205  ::toString(poly_coords.size()) + ", expected " + ::toString(nof_lines) + ".");
206  }
207 
208  auto poly = polygons[i];
209 
210  for (size_t j = 0; j < poly.size(); j++) {
211  Geo::LineString line = poly[j];
212  std::vector<double> line_coords = line.toCoords();
213  auto nof_points = polygon_coords[j].size() / 2;
214  if (poly.size(j) != nof_points) {
215  return mgr.ERROR_MESSAGE("polygon linestring size test failed: poly.size(" +
216  ::toString(j) + ")=" + ::toString(poly.size(j)) +
217  ", expected " + ::toString(nof_points) + ".");
218  }
219  if (line.size() != nof_points) {
220  return mgr.ERROR_MESSAGE("polygon linestring size test failed: line.size()=" +
221  ::toString(line.size()) + ", expected " +
222  ::toString(nof_points) + ".");
223  }
224  if (poly_coords[j].size() != nof_points * 2) {
225  return mgr.ERROR_MESSAGE(
226  "polygon linestring coords size test failed: poly_coords[j].size()=" +
227  ::toString(poly_coords[j].size()) + ", expected " +
228  ::toString(nof_points * 2) + ".");
229  }
230  if (line_coords.size() != nof_points * 2) {
231  return mgr.ERROR_MESSAGE(
232  "polygon linestring coords size test failed: line_coords.size()=" +
233  ::toString(line_coords.size()) + ", expected " +
234  ::toString(nof_points * 2) + ".");
235  }
236  for (size_t k = 0; k < nof_points; k++) {
237  if (std::abs(polygon_coords[j][2 * k] - line_coords[2 * k]) > 1e-7) {
238  return mgr.ERROR_MESSAGE(
239  "polygon linestring X coord test failed: line_coords[2*k]=" +
240  ::toString(line_coords[2 * k]) + ", expected " +
241  ::toString(polygon_coords[j][2 * k]) + ".");
242  }
243  if (std::abs(polygon_coords[j][2 * k] - poly_coords[j][2 * k]) > 1e-7) {
244  return mgr.ERROR_MESSAGE("polygon X coord test failed: poly_coords[j][2*k]=" +
245  ::toString(poly_coords[j][2 * k]) + ", expected " +
246  ::toString(polygon_coords[j][2 * k]) + ".");
247  }
248  if (std::abs(polygon_coords[j][2 * k] - line[k].x) > 1e-7) {
249  return mgr.ERROR_MESSAGE(
250  "polygon linestring X coord test failed: line[k].x=" +
251  ::toString(line[k].x) + ", expected " +
252  ::toString(polygon_coords[j][2 * k]) + ".");
253  }
254  if (std::abs(polygon_coords[j][2 * k + 1] - line_coords[2 * k + 1]) > 1e-7) {
255  return mgr.ERROR_MESSAGE(
256  "polygon linestring Y coord test failed: line_coords[2*k+1]=" +
257  ::toString(line_coords[2 * k + 1]) + ", expected " +
258  ::toString(polygon_coords[j][2 * k + 1]) + ".");
259  }
260  if (std::abs(polygon_coords[j][2 * k + 1] - poly_coords[j][2 * k + 1]) > 1e-7) {
261  return mgr.ERROR_MESSAGE(
262  "polygon Y coord test failed: poly_coords[j][2*k+1]=" +
263  ::toString(poly_coords[j][2 * k + 1]) + ", expected " +
264  ::toString(polygon_coords[j][2 * k + 1]) + ".");
265  }
266  if (std::abs(polygon_coords[j][2 * k + 1] - line[k].y) > 1e-7) {
267  return mgr.ERROR_MESSAGE(
268  "polygon linestring X coord test failed: line[k].y=" +
269  ::toString(line[k].y) + ", expected " +
270  ::toString(polygon_coords[j][2 * k + 1]) + ".");
271  }
272  }
273  }
274  }
275  }
276 
277  if (count_nulls != 0) {
278  return mgr.ERROR_MESSAGE("counting null test failed: count_nulls=" +
279  ::toString(count_nulls) + ", expected 0.");
280  }
281 
282  return size;
283 }
284 
286  const Column<double>& x,
287  const Column<double>& y,
288  double dx,
289  double dy,
290  Column<GeoLineString>& linestrings) {
291  auto size = x.size();
292  mgr.set_output_item_values_total_number(0, size * 4);
293  mgr.set_output_row_size(size);
294  for (int64_t i = 0; i < size; i++) {
295  if (x.isNull(i) || y.isNull(i)) {
296  linestrings.setNull(i);
297  } else {
298  std::vector<double> line{x[i], y[i], x[i] + dx, y[i] + dy};
299  linestrings[i].fromCoords(line);
300  }
301  }
302  return size;
303 }
304 
305 EXTENSION_NOINLINE int32_t
307  const Column<GeoPolygon>& polygons,
308  Column<GeoMultiPolygon>& mpolygons) {
309  auto size = polygons.size();
311  mgr.set_output_row_size(size);
312 
313  // Initialize mpolygons
314  int count_nulls = 0;
315  for (int64_t i = 0; i < size; i++) {
316  if (polygons.isNull(i)) {
317  mpolygons.setNull(i);
318  count_nulls++;
319  } else {
320  std::vector<std::vector<std::vector<double>>> mpolygon_coords;
321  mpolygon_coords.reserve(1);
322  std::vector<std::vector<double>> polygon_coords = polygons[i].toCoords();
323  mpolygon_coords.push_back(polygon_coords);
324  auto status = mpolygons[i].fromCoords(mpolygon_coords);
325  if (status != FlatBufferManager::Status::Success) {
326  return mgr.ERROR_MESSAGE("fromCoords failed: " + ::toString(status));
327  }
328  }
329  }
330 
331  // Check mpolygons content
332  if (count_nulls == 0) {
333  return mgr.ERROR_MESSAGE("counting null test failed: count_nulls=" +
334  ::toString(count_nulls) + ", expected non-zero.");
335  }
336 
337  for (int64_t i = 0; i < size; i++) {
338  if (mpolygons.isNull(i)) {
339  count_nulls--;
340  } else {
341  std::vector<std::vector<double>> polygon_coords = polygons[i].toCoords();
342 
343  // mpolygons[i] is Geo::MultiPolygon instances
344  // mpolygons[i][j] is Geo::Polygon instances
345  // mpolygons[i][j][k] is Geo::LineString instances
346  // mpolygons[i][j][k][l] is Geo::Point2D instances
347 
348  auto nof_polygons = mpolygons[i].size();
349  if (nof_polygons != 1) {
350  return mgr.ERROR_MESSAGE("multipolygon size test failed: nof_polygons=" +
351  ::toString(nof_polygons) + ", expected 1.");
352  }
353 
354  std::vector<std::vector<std::vector<double>>> mpolygon_coords =
355  mpolygons[i].toCoords();
356  if (nof_polygons != mpolygon_coords.size()) {
357  return mgr.ERROR_MESSAGE(
358  "multipolygon toCoords size test failed: mpolygon_coords.size()=" +
359  ::toString(mpolygon_coords.size()) + ", expected " +
360  ::toString(nof_polygons) + ".");
361  }
362 
363  Geo::Polygon poly = mpolygons[i][0];
364  std::vector<std::vector<double>> poly_coords = mpolygon_coords[0];
365  if (poly.size() != polygon_coords.size()) {
366  return mgr.ERROR_MESSAGE("multipolygon polygon size test failed: poly.size()=" +
367  ::toString(poly.size()) + ", expected " +
368  ::toString(polygon_coords.size()) + ".");
369  }
370 
371  if (poly_coords.size() != polygon_coords.size()) {
372  return mgr.ERROR_MESSAGE(
373  "multipolygon polygon coords size test failed: poly_coords.size()=" +
374  ::toString(poly_coords.size()) + ", expected " +
375  ::toString(polygon_coords.size()) + ".");
376  }
377 
378  for (size_t j = 0; j < poly.size(); j++) {
379  Geo::LineString line = poly[j];
380  std::vector<double> line_coords = line.toCoords();
381  auto nof_points = polygon_coords[j].size() / 2;
382  if (poly.size(j) != nof_points) {
383  return mgr.ERROR_MESSAGE(
384  "multipolygon polygon linestring size test failed: poly.size(" +
385  ::toString(j) + ")=" + ::toString(poly.size(j)) + ", expected " +
386  ::toString(nof_points) + ".");
387  }
388  if (line.size() != nof_points) {
389  return mgr.ERROR_MESSAGE(
390  "multipolygon polygon linestring size test failed: line.size()=" +
391  ::toString(line.size()) + ", expected " + ::toString(nof_points) + ".");
392  }
393  if (poly_coords[j].size() != nof_points * 2) {
394  return mgr.ERROR_MESSAGE(
395  "multipolygon polygon linestring coords size test failed: "
396  "poly_coords[j].size()=" +
397  ::toString(poly_coords[j].size()) + ", expected " +
398  ::toString(nof_points * 2) + ".");
399  }
400  if (line_coords.size() != nof_points * 2) {
401  return mgr.ERROR_MESSAGE(
402  "multipolygon polygon linestring coords size test failed: "
403  "line_coords.size()=" +
404  ::toString(line_coords.size()) + ", expected " +
405  ::toString(nof_points * 2) + ".");
406  }
407 
408  for (size_t k = 0; k < nof_points; k++) {
409  if (std::abs(polygon_coords[j][2 * k] - line_coords[2 * k]) > 1e-7) {
410  return mgr.ERROR_MESSAGE(
411  "multipolygon polygon linestring X coord test failed: line_coords[2*k]=" +
412  ::toString(line_coords[2 * k]) + ", expected " +
413  ::toString(polygon_coords[j][2 * k]) + ".");
414  }
415  if (std::abs(polygon_coords[j][2 * k] - poly_coords[j][2 * k]) > 1e-7) {
416  return mgr.ERROR_MESSAGE(
417  "multipolygon polygon X coord test failed: poly_coords[j][2*k]=" +
418  ::toString(poly_coords[j][2 * k]) + ", expected " +
419  ::toString(polygon_coords[j][2 * k]) + ".");
420  }
421  if (std::abs(polygon_coords[j][2 * k] - line[k].x) > 1e-7) {
422  return mgr.ERROR_MESSAGE(
423  "multipolygon polygon linestring X coord test failed: line[k].x=" +
424  ::toString(line[k].x) + ", expected " +
425  ::toString(polygon_coords[j][2 * k]) + ".");
426  }
427  if (std::abs(polygon_coords[j][2 * k + 1] - line_coords[2 * k + 1]) > 1e-7) {
428  return mgr.ERROR_MESSAGE(
429  "multipolygon polygon linestring Y coord test failed: "
430  "line_coords[2*k+1]=" +
431  ::toString(line_coords[2 * k + 1]) + ", expected " +
432  ::toString(polygon_coords[j][2 * k + 1]) + ".");
433  }
434  if (std::abs(polygon_coords[j][2 * k + 1] - poly_coords[j][2 * k + 1]) > 1e-7) {
435  return mgr.ERROR_MESSAGE(
436  "multipolygon polygon Y coord test failed: poly_coords[j][2*k+1]=" +
437  ::toString(poly_coords[j][2 * k + 1]) + ", expected " +
438  ::toString(polygon_coords[j][2 * k + 1]) + ".");
439  }
440  if (std::abs(polygon_coords[j][2 * k + 1] - line[k].y) > 1e-7) {
441  return mgr.ERROR_MESSAGE(
442  "multipolygon polygon linestring X coord test failed: line[k].y=" +
443  ::toString(line[k].y) + ", expected " +
444  ::toString(polygon_coords[j][2 * k + 1]) + ".");
445  }
446  }
447  }
448  }
449  }
450 
451  if (count_nulls != 0) {
452  return mgr.ERROR_MESSAGE("counting null test failed: count_nulls=" +
453  ::toString(count_nulls) + ", expected 0.");
454  }
455 
456  return size;
457 }
458 
460  const Column<GeoMultiPolygon>& mpolygons,
461  int64_t n,
462  Column<GeoPolygon>& polygons) {
463  auto size = mpolygons.size();
465  mgr.set_output_row_size(size);
466  for (int64_t i = 0; i < size; i++) {
467  if (mpolygons.isNull(i)) {
468  polygons.setNull(i);
469  } else {
470  polygons.setItem(i, mpolygons[i][n - 1]);
471  }
472  }
473  return size;
474 }
475 
476 EXTENSION_NOINLINE int32_t
478  const Column<GeoPolygon>& polygons,
479  Column<GeoMultiLineString>& mlinestrings) {
480  auto size = polygons.size();
482  mgr.set_output_row_size(size);
483  // Initialize mlinestrings
484  int count_nulls = 0;
485  FlatBufferManager::Status status{};
486  for (int64_t i = 0; i < size; i++) {
487  if (polygons.isNull(i)) {
488  mlinestrings.setNull(i);
489  count_nulls++;
490  } else {
491  std::vector<std::vector<double>> polygon_coords = polygons[i].toCoords();
492  status = mlinestrings[i].fromCoords(polygon_coords);
493  if (status != FlatBufferManager::Status::Success) {
494  return mgr.ERROR_MESSAGE("fromCoords failed: " + ::toString(status));
495  }
496  }
497  }
498  return size;
499 }
500 
501 EXTENSION_NOINLINE int32_t
503  const Column<GeoMultiLineString>& mlinestrings,
504  Column<GeoPolygon>& polygons) {
505  auto size = mlinestrings.size();
506  mgr.set_output_item_values_total_number(0, mlinestrings.getNofValues());
507  mgr.set_output_row_size(size);
508  // Initialize polygons
509  int count_nulls = 0;
510  FlatBufferManager::Status status{};
511  for (int64_t i = 0; i < size; i++) {
512  if (mlinestrings.isNull(i)) {
513  polygons.setNull(i);
514  count_nulls++;
515  } else {
516  std::vector<std::vector<double>> polygon_coords;
517  status = mlinestrings[i].toCoords(polygon_coords);
518  if (status != FlatBufferManager::Status::Success) {
519  return mgr.ERROR_MESSAGE("toCoords failed: " + ::toString(status));
520  }
521  status = polygons[i].fromCoords(polygon_coords);
522  if (status != FlatBufferManager::Status::Success) {
523  return mgr.ERROR_MESSAGE("fromCoords failed: " + ::toString(status));
524  }
525  }
526  }
527  return size;
528 }
529 
530 #endif // #ifndef __CUDACC__
void set_output_row_size(int64_t num_rows)
Definition: heavydbTypes.h:373
#define EXTENSION_NOINLINE
Definition: heavydbTypes.h:58
DEVICE int64_t size() const
size_t size() const
std::string toString(const QueryDescriptionType &type)
Definition: Types.h:64
std::vector< CT > toCoords() const
DEVICE int64_t size() const
DEVICE void setNull(int64_t index)
EXTENSION_NOINLINE int32_t ct_to_multilinestring__cpu_(TableFunctionManager &mgr, const Column< GeoPolygon > &polygons, Column< GeoMultiLineString > &mlinestrings)
#define HOST
int64_t getNofValues() const
EXTENSION_NOINLINE int32_t ct_make_linestring2__cpu_(TableFunctionManager &mgr, const Column< double > &x, const Column< double > &y, double dx, double dy, Column< GeoLineString > &linestrings)
EXTENSION_NOINLINE int32_t ct_shift__cpu_(TableFunctionManager &mgr, const Column< GeoPoint > &points, const double x, const double y, Column< GeoPoint > &shifted_points)
EXTENSION_NOINLINE int32_t ct_coords__cpu_(TableFunctionManager &mgr, const Column< GeoPoint > &points, Column< double > &xcoords, Column< double > &ycoords)
DEVICE bool isNull(int64_t index) const
EXTENSION_NOINLINE int32_t ct_make_multipolygon__cpu_(TableFunctionManager &mgr, const Column< GeoPolygon > &polygons, Column< GeoMultiPolygon > &mpolygons)
DEVICE bool isNull(int64_t index) const
DEVICE void setNull(int64_t index)
tuple line
Definition: parse_ast.py:10
EXTENSION_NOINLINE int32_t ct_make_polygon3__cpu_(TableFunctionManager &mgr, const Column< GeoLineString > &rings, const Column< GeoLineString > &holes1, const Column< GeoLineString > &holes2, Column< GeoPolygon > &polygons, Column< int > &sizes)
void set_output_item_values_total_number(int32_t index, int64_t output_item_values_total_number)
Definition: heavydbTypes.h:367
DEVICE int64_t size() const
#define NEVER_INLINE
EXTENSION_NOINLINE int32_t ct_linestringn__cpu_(TableFunctionManager &mgr, const Column< GeoPolygon > &polygons, int64_t n, Column< GeoLineString > &linestrings)
DEVICE void setItem(int64_t index, const Geo::Point2D &other)
EXTENSION_NOINLINE int32_t ct_to_polygon__cpu_(TableFunctionManager &mgr, const Column< GeoMultiLineString > &mlinestrings, Column< GeoPolygon > &polygons)
NEVER_INLINE HOST int32_t ct_pointn__cpu_template(TableFunctionManager &mgr, const Column< T > &points, int64_t n, Column< double > &xcoords, Column< double > &ycoords)
DEVICE void setNull(int64_t index)
DEVICE bool isNull(int64_t index) const
EXTENSION_NOINLINE int32_t ct_polygonn__cpu_(TableFunctionManager &mgr, const Column< GeoMultiPolygon > &mpolygons, int64_t n, Column< GeoPolygon > &polygons)
constexpr double n
Definition: Utm.h:38
DEVICE void setItem(int64_t index, const RowType &item)