OmniSciDB  06b3bd477c
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
ExtensionFunctionsGeo.hpp
Go to the documentation of this file.
1 #include "../Shared/geo_compression_runtime.h"
2 
3 // Adjustable tolerance, determined by compression mode.
4 // The criteria is to still recognize a compressed+decompressed number.
5 // For example 1.0 longitude compressed with GEOINT32 and then decompressed
6 // comes back as 0.99999994086101651, which is still within GEOINT32
7 // tolerance val 0.0000001
8 DEVICE ALWAYS_INLINE double tol(int32_t ic) {
9  if (ic == COMPRESSION_GEOINT32) {
10  return TOLERANCE_GEOINT32;
11  }
12  return TOLERANCE_DEFAULT;
13 }
14 
15 // Combine tolerances for two-component calculations
16 DEVICE ALWAYS_INLINE double tol(int32_t ic1, int32_t ic2) {
17  return fmax(tol(ic1), tol(ic2));
18 }
19 
20 DEVICE ALWAYS_INLINE bool tol_zero(double x, double tolerance = TOLERANCE_DEFAULT) {
21  return (-tolerance <= x) && (x <= tolerance);
22 }
23 
24 DEVICE ALWAYS_INLINE bool tol_eq(double x,
25  double y,
26  double tolerance = TOLERANCE_DEFAULT) {
27  auto diff = x - y;
28  return (-tolerance <= diff) && (diff <= tolerance);
29 }
30 
31 DEVICE ALWAYS_INLINE bool tol_le(double x,
32  double y,
33  double tolerance = TOLERANCE_DEFAULT) {
34  return x <= (y + tolerance);
35 }
36 
37 DEVICE ALWAYS_INLINE bool tol_ge(double x,
38  double y,
39  double tolerance = TOLERANCE_DEFAULT) {
40  return (x + tolerance) >= y;
41 }
42 
44  int32_t index,
45  int32_t ic,
46  bool x) {
47  if (ic == COMPRESSION_GEOINT32) {
48  auto compressed_coords = reinterpret_cast<int32_t*>(data);
49  auto compressed_coord = compressed_coords[index];
50  if (x) {
52  } else {
54  }
55  }
56  auto double_coords = reinterpret_cast<double*>(data);
57  return double_coords[index];
58 }
59 
61  if (ic == COMPRESSION_GEOINT32) {
62  return 4;
63  }
64  return 8;
65 }
66 
67 DEVICE ALWAYS_INLINE double transform_coord(double coord,
68  int32_t isr,
69  int32_t osr,
70  bool x) {
71  if (isr == 4326) {
72  if (osr == 900913) {
73  // WGS 84 --> Web Mercator
74  if (x) {
75  return conv_4326_900913_x(coord);
76  } else {
77  return conv_4326_900913_y(coord);
78  }
79  }
80  }
81  return coord;
82 }
83 
84 // X coord accessor handling on-the-fly decommpression and transforms
85 DEVICE ALWAYS_INLINE double coord_x(int8_t* data,
86  int32_t index,
87  int32_t ic,
88  int32_t isr,
89  int32_t osr) {
90  auto decompressed_coord_x = decompress_coord(data, index, ic, true);
91  auto decompressed_transformed_coord_x =
92  transform_coord(decompressed_coord_x, isr, osr, true);
93  return decompressed_transformed_coord_x;
94 }
95 
96 // Y coord accessor handling on-the-fly decommpression and transforms
97 DEVICE ALWAYS_INLINE double coord_y(int8_t* data,
98  int32_t index,
99  int32_t ic,
100  int32_t isr,
101  int32_t osr) {
102  auto decompressed_coord_y = decompress_coord(data, index, ic, false);
103  auto decompressed_transformed_coord_y =
104  transform_coord(decompressed_coord_y, isr, osr, false);
105  return decompressed_transformed_coord_y;
106 }
107 
108 // Cartesian distance between points, squared
110  double p1y,
111  double p2x,
112  double p2y) {
113  auto x = p1x - p2x;
114  auto y = p1y - p2y;
115  auto x2 = x * x;
116  auto y2 = y * y;
117  auto d2 = x2 + y2;
119  return 0.0;
120  }
121  return d2;
122 }
123 
124 // Cartesian distance between points
126  double p1y,
127  double p2x,
128  double p2y) {
129  auto d2 = distance_point_point_squared(p1x, p1y, p2x, p2y);
130  return sqrt(d2);
131 }
132 
133 // Cartesian distance between a point and a line segment
134 DEVICE
135 double distance_point_line(double px,
136  double py,
137  double l1x,
138  double l1y,
139  double l2x,
140  double l2y) {
141  double length = distance_point_point(l1x, l1y, l2x, l2y);
142  if (tol_zero(length)) {
143  return distance_point_point(px, py, l1x, l1y);
144  }
145 
146  // Find projection of point P onto the line segment AB:
147  // Line containing that segment: A + k * (B - A)
148  // Projection of point P onto the line touches it at
149  // k = dot(P-A,B-A) / length^2
150  // AB segment is represented by k = [0,1]
151  // Clamping k to [0,1] will give the shortest distance from P to AB segment
152  double dotprod = (px - l1x) * (l2x - l1x) + (py - l1y) * (l2y - l1y);
153  double k = dotprod / (length * length);
154  k = fmax(0.0, fmin(1.0, k));
155  double projx = l1x + k * (l2x - l1x);
156  double projy = l1y + k * (l2y - l1y);
157  return distance_point_point(px, py, projx, projy);
158 }
159 
160 // Given three colinear points p, q, r, the function checks if
161 // point q lies on line segment 'pr'
163  double py,
164  double qx,
165  double qy,
166  double rx,
167  double ry) {
168  return (tol_le(qx, fmax(px, rx)) && tol_ge(qx, fmin(px, rx)) &&
169  tol_le(qy, fmax(py, ry)) && tol_ge(qy, fmin(py, ry)));
170 }
171 
172 DEVICE ALWAYS_INLINE int16_t
173 orientation(double px, double py, double qx, double qy, double rx, double ry) {
174  auto val = ((qy - py) * (rx - qx) - (qx - px) * (ry - qy));
175  if (tol_zero(val)) {
176  return 0; // Points p, q and r are colinear
177  }
178  if (val > 0.0) {
179  return 1; // Clockwise point orientation
180  }
181  return 2; // Counterclockwise point orientation
182 }
183 
184 // Cartesian intersection of two line segments l11-l12 and l21-l22
185 DEVICE
186 bool line_intersects_line(double l11x,
187  double l11y,
188  double l12x,
189  double l12y,
190  double l21x,
191  double l21y,
192  double l22x,
193  double l22y) {
194  auto o1 = orientation(l11x, l11y, l12x, l12y, l21x, l21y);
195  auto o2 = orientation(l11x, l11y, l12x, l12y, l22x, l22y);
196  auto o3 = orientation(l21x, l21y, l22x, l22y, l11x, l11y);
197  auto o4 = orientation(l21x, l21y, l22x, l22y, l12x, l12y);
198 
199  // General case
200  if (o1 != o2 && o3 != o4) {
201  return true;
202  }
203 
204  // Special Cases
205  // l11, l12 and l21 are colinear and l21 lies on segment l11-l12
206  if (o1 == 0 && on_segment(l11x, l11y, l21x, l21y, l12x, l12y)) {
207  return true;
208  }
209 
210  // l11, l12 and l21 are colinear and l22 lies on segment l11-l12
211  if (o2 == 0 && on_segment(l11x, l11y, l22x, l22y, l12x, l12y)) {
212  return true;
213  }
214 
215  // l21, l22 and l11 are colinear and l11 lies on segment l21-l22
216  if (o3 == 0 && on_segment(l21x, l21y, l11x, l11y, l22x, l22y)) {
217  return true;
218  }
219 
220  // l21, l22 and l12 are colinear and l12 lies on segment l21-l22
221  if (o4 == 0 && on_segment(l21x, l21y, l12x, l12y, l22x, l22y)) {
222  return true;
223  }
224 
225  return false;
226 }
227 
228 DEVICE
230  int32_t lnum_coords,
231  double l1x,
232  double l1y,
233  double l2x,
234  double l2y,
235  int32_t ic1,
236  int32_t isr1,
237  int32_t osr) {
238  double e1x = coord_x(l, 0, ic1, isr1, osr);
239  double e1y = coord_y(l, 1, ic1, isr1, osr);
240  for (int64_t i = 2; i < lnum_coords; i += 2) {
241  double e2x = coord_x(l, i, ic1, isr1, osr);
242  double e2y = coord_y(l, i + 1, ic1, isr1, osr);
243  if (line_intersects_line(e1x, e1y, e2x, e2y, l1x, l1y, l2x, l2y)) {
244  return true;
245  }
246  e1x = e2x;
247  e1y = e2y;
248  }
249  return false;
250 }
251 
252 DEVICE
253 bool ring_intersects_line(int8_t* ring,
254  int32_t ring_num_coords,
255  double l1x,
256  double l1y,
257  double l2x,
258  double l2y,
259  int32_t ic1,
260  int32_t isr1,
261  int32_t osr) {
262  double e1x = coord_x(ring, ring_num_coords - 2, ic1, isr1, osr);
263  double e1y = coord_y(ring, ring_num_coords - 1, ic1, isr1, osr);
264  double e2x = coord_x(ring, 0, ic1, isr1, osr);
265  double e2y = coord_y(ring, 1, ic1, isr1, osr);
266  if (line_intersects_line(e1x, e1y, e2x, e2y, l1x, l1y, l2x, l2y)) {
267  return true;
268  }
270  ring, ring_num_coords, l1x, l1y, l2x, l2y, ic1, isr1, osr);
271 }
272 
273 DEVICE
275  int32_t lnum_coords,
276  double l1x,
277  double l1y,
278  double l2x,
279  double l2y,
280  int32_t ic1,
281  int32_t isr1,
282  int32_t osr) {
283  double e1x = coord_x(l, 0, ic1, isr1, osr);
284  double e1y = coord_y(l, 1, ic1, isr1, osr);
285  for (int64_t i = 2; i < lnum_coords; i += 2) {
286  double e2x = coord_x(l, i, ic1, isr1, osr);
287  double e2y = coord_y(l, i + 1, ic1, isr1, osr);
288  if (line_intersects_line(e1x, e1y, e2x, e2y, l1x, l1y, l2x, l2y)) {
289  return true;
290  }
291  e1x = e2x;
292  e1y = e2y;
293  }
294  return false;
295 }
296 
297 // Cartesian distance between two line segments l11-l12 and l21-l22
298 DEVICE
299 double distance_line_line(double l11x,
300  double l11y,
301  double l12x,
302  double l12y,
303  double l21x,
304  double l21y,
305  double l22x,
306  double l22y) {
307  if (line_intersects_line(l11x, l11y, l12x, l12y, l21x, l21y, l22x, l22y)) {
308  return 0.0;
309  }
310  double dist12 = fmin(distance_point_line(l11x, l11y, l21x, l21y, l22x, l22y),
311  distance_point_line(l12x, l12y, l21x, l21y, l22x, l22y));
312  double dist21 = fmin(distance_point_line(l21x, l21y, l11x, l11y, l12x, l12y),
313  distance_point_line(l22x, l22y, l11x, l11y, l12x, l12y));
314  return fmin(dist12, dist21);
315 }
316 
317 DEVICE
318 double distance_ring_linestring(int8_t* ring,
319  int32_t ring_num_coords,
320  int8_t* l,
321  int32_t lnum_coords,
322  int32_t ic1,
323  int32_t isr1,
324  int32_t ic2,
325  int32_t isr2,
326  int32_t osr) {
327  double min_distance = 0.0;
328 
329  double re1x = coord_x(ring, ring_num_coords - 2, ic1, isr1, osr);
330  double re1y = coord_y(ring, ring_num_coords - 1, ic1, isr1, osr);
331  for (auto i = 0; i < ring_num_coords; i += 2) {
332  double re2x = coord_x(ring, i, ic1, isr1, osr);
333  double re2y = coord_y(ring, i + 1, ic1, isr1, osr);
334 
335  double le1x = coord_x(l, 0, ic2, isr2, osr);
336  double le1y = coord_y(l, 1, ic2, isr2, osr);
337  for (auto j = 2; j < lnum_coords; j += 2) {
338  double le2x = coord_x(l, j, ic2, isr2, osr);
339  double le2y = coord_y(l, j + 1, ic2, isr2, osr);
340 
341  auto distance = distance_line_line(re1x, re1y, re2x, re2y, le1x, le1y, le2x, le2y);
342  if ((i == 0 && j == 2) || min_distance > distance) {
343  min_distance = distance;
344  if (tol_zero(min_distance)) {
345  return 0.0;
346  }
347  }
348  le1x = le2x;
349  le1y = le2y;
350  }
351  re1x = re2x;
352  re1y = re2y;
353  }
354 
355  return min_distance;
356 }
357 
358 DEVICE
359 double distance_ring_ring(int8_t* ring1,
360  int32_t ring1_num_coords,
361  int8_t* ring2,
362  int32_t ring2_num_coords,
363  int32_t ic1,
364  int32_t isr1,
365  int32_t ic2,
366  int32_t isr2,
367  int32_t osr) {
368  double min_distance = 0.0;
369 
370  double e11x = coord_x(ring1, ring1_num_coords - 2, ic1, isr1, osr);
371  double e11y = coord_y(ring1, ring1_num_coords - 1, ic1, isr1, osr);
372  for (auto i = 0; i < ring1_num_coords; i += 2) {
373  double e12x = coord_x(ring1, i, ic1, isr1, osr);
374  double e12y = coord_y(ring1, i + 1, ic1, isr1, osr);
375 
376  double e21x = coord_x(ring2, ring2_num_coords - 2, ic2, isr2, osr);
377  double e21y = coord_y(ring2, ring2_num_coords - 1, ic2, isr2, osr);
378  for (auto j = 0; j < ring2_num_coords; j += 2) {
379  double e22x = coord_x(ring2, j, ic2, isr2, osr);
380  double e22y = coord_y(ring2, j + 1, ic2, isr2, osr);
381 
382  auto distance = distance_line_line(e11x, e11y, e12x, e12y, e21x, e21y, e22x, e22y);
383  if ((i == 0 && j == 0) || min_distance > distance) {
384  min_distance = distance;
385  if (tol_zero(min_distance)) {
386  return 0.0;
387  }
388  }
389  e21x = e22x;
390  e21y = e22y;
391  }
392  e11x = e12x;
393  e11y = e12y;
394  }
395 
396  return min_distance;
397 }
398 
399 // Checks if a simple polygon (no holes) contains a point.
400 //
401 // Poly coords are extracted from raw data, based on compression (ic1) and input/output
402 // SRIDs (isr1/osr).
403 //
404 // Shoot a ray from point P to the right, register intersections with any of polygon's
405 // edges. Each intersection means entrance into or exit from the polygon. Odd number of
406 // intersections means the polygon does contain P. Account for special cases: touch+cross,
407 // touch+leave, touch+overlay+cross, touch+overlay+leave, on edge, etc.
408 //
409 // Secondary ray is shot from point P down for simple redundancy, to reduce main probe's
410 // chance of error. No intersections means P is outside, irrespective of main probe's
411 // result.
412 //
413 DEVICE
414 bool polygon_contains_point(int8_t* poly,
415  int32_t poly_num_coords,
416  double px,
417  double py,
418  int32_t ic1,
419  int32_t isr1,
420  int32_t osr) {
421  bool result = false;
422  int xray_touch = 0;
423  bool horizontal_edge = false;
424  bool yray_intersects = false;
425 
426  double e1x = coord_x(poly, poly_num_coords - 2, ic1, isr1, osr);
427  double e1y = coord_y(poly, poly_num_coords - 1, ic1, isr1, osr);
428  for (int64_t i = 0; i < poly_num_coords; i += 2) {
429  double e2x = coord_x(poly, i, ic1, isr1, osr);
430  double e2y = coord_y(poly, i + 1, ic1, isr1, osr);
431 
432  // Check if point sits on an edge.
433  if (tol_zero(distance_point_line(px, py, e1x, e1y, e2x, e2y))) {
434  return true;
435  }
436 
437  // Before flipping the switch, check if xray hit a horizontal edge
438  // - If an edge lays on the xray, one of the previous edges touched it
439  // so while moving horizontally we're in 'xray_touch' state
440  // - Last edge that touched xray at (e2x,e2y) didn't register intersection
441  // - Next edge that diverges from xray at (e1,e1y) will register intersection
442  // - Can have several horizontal edges, one after the other, keep moving though
443  // in 'xray_touch' state without flipping the switch
444  horizontal_edge = (xray_touch != 0) && tol_eq(py, e1y) && tol_eq(py, e2y);
445 
446  // Main probe: xray
447  // Overshoot the xray to detect an intersection if there is one.
448  double xray = fmax(e2x, e1x) + 1.0;
449  if (px <= xray && // Only check for intersection if the edge is on the right
450  !horizontal_edge && // Keep moving through horizontal edges
451  line_intersects_line(px, // xray shooting from point p to the right
452  py,
453  xray,
454  py,
455  e1x, // polygon edge
456  e1y,
457  e2x,
458  e2y)) {
459  // Register intersection
460  result = !result;
461 
462  // Adjust for special cases
463  if (xray_touch == 0) {
464  if (tol_zero(distance_point_line(e2x, e2y, px, py, xray + 1.0, py))) {
465  // Xray goes through the edge's second vertex, unregister intersection -
466  // that vertex will be crossed again when we look at the following edge(s)
467  result = !result;
468  // Enter the xray-touch state:
469  // (1) - xray was touched by the edge from above, (-1) from below
470  xray_touch = (e1y > py) ? 1 : -1;
471  }
472  } else {
473  // Previous edge touched the xray, intersection hasn't been registered,
474  // it has to be registered now if this edge continues across the xray.
475  if (xray_touch > 0) {
476  // Previous edge touched the xray from above
477  if (e2y <= py) {
478  // Current edge crosses under xray: intersection is already registered
479  } else {
480  // Current edge just touched the xray and pulled up: unregister intersection
481  result = !result;
482  }
483  } else {
484  // Previous edge touched the xray from below
485  if (e2y > py) {
486  // Current edge crosses over xray: intersection is already registered
487  } else {
488  // Current edge just touched the xray and pulled down: unregister intersection
489  result = !result;
490  }
491  }
492  // Exit the xray-touch state
493  xray_touch = 0;
494  }
495  }
496 
497  // Redundancy: vertical yray down
498  // Main probe xray may hit multiple complex fragments which increases a chance of
499  // error. Perform a simple secondary check for edge intersections to see if point is
500  // outside.
501  if (!yray_intersects) { // Continue checking on yray until intersection is found
502  double yray = fmin(e2y, e1y) - 1.0;
503  if (yray <= py) { // Only check for yray intersection if point P is above the edge
504  yray_intersects = line_intersects_line(px, // yray shooting from point P down
505  py,
506  px,
507  yray,
508  e1x, // polygon edge
509  e1y,
510  e2x,
511  e2y);
512  }
513  }
514 
515  // Advance to the next vertex
516  e1x = e2x;
517  e1y = e2y;
518  }
519  if (!yray_intersects) {
520  // yray has zero intersections - point is outside the polygon
521  return false;
522  }
523  // Otherwise rely on the main probe
524  return result;
525 }
526 
527 // Returns true if simple polygon (no holes) contains a linestring
528 DEVICE
529 bool polygon_contains_linestring(int8_t* poly,
530  int32_t poly_num_coords,
531  int8_t* l,
532  int64_t lnum_coords,
533  int32_t ic1,
534  int32_t isr1,
535  int32_t ic2,
536  int32_t isr2,
537  int32_t osr) {
538  // Check that the first point is in the polygon
539  double l1x = coord_x(l, 0, ic2, isr2, osr);
540  double l1y = coord_y(l, 1, ic2, isr2, osr);
541  if (!polygon_contains_point(poly, poly_num_coords, l1x, l1y, ic1, isr1, osr)) {
542  return false;
543  }
544 
545  // Go through line segments and check if there are no intersections with poly edges,
546  // i.e. linestring doesn't escape
547  for (int32_t i = 2; i < lnum_coords; i += 2) {
548  double l2x = coord_x(l, i, ic2, isr2, osr);
549  double l2y = coord_y(l, i + 1, ic2, isr2, osr);
550  if (ring_intersects_line(poly, poly_num_coords, l1x, l1y, l2x, l2y, ic1, isr1, osr)) {
551  return false;
552  }
553  l1x = l2x;
554  l1y = l2y;
555  }
556  return true;
557 }
558 
560  int64_t bounds_size,
561  double px,
562  double py) {
563  return (tol_ge(px, bounds[0]) && tol_ge(py, bounds[1]) && tol_le(px, bounds[2]) &&
564  tol_le(py, bounds[3]));
565 }
566 
568  int64_t bounds_size,
569  double px,
570  double py) {
571  return box_contains_point(bounds, bounds_size, px, py);
572 }
573 
574 DEVICE ALWAYS_INLINE bool box_contains_box(double* bounds1,
575  int64_t bounds1_size,
576  double* bounds2,
577  int64_t bounds2_size) {
578  return (
580  bounds1, bounds1_size, bounds2[0], bounds2[1]) && // box1 <- box2: xmin, ymin
582  bounds1, bounds1_size, bounds2[2], bounds2[3])); // box1 <- box2: xmax, ymax
583 }
584 
586  int64_t bounds1_size,
587  double* bounds2,
588  int64_t bounds2_size) {
589  return (
591  bounds1, bounds1_size, bounds2[0], bounds2[1]) || // box1 <- box2: xmin, ymin
593  bounds1, bounds1_size, bounds2[2], bounds2[3]) || // box1 <- box2: xmax, ymax
595  bounds1, bounds1_size, bounds2[0], bounds2[3]) || // box1 <- box2: xmin, ymax
597  bounds1, bounds1_size, bounds2[2], bounds2[1])); // box1 <- box2: xmax, ymin
598 }
599 
600 DEVICE ALWAYS_INLINE bool box_overlaps_box(double* bounds1,
601  int64_t bounds1_size,
602  double* bounds2,
603  int64_t bounds2_size) {
604  // TODO: tolerance
605  if (bounds1[2] < bounds2[0] || // box1 is left of box2: box1.xmax < box2.xmin
606  bounds1[0] > bounds2[2] || // box1 is right of box2: box1.xmin > box2.xmax
607  bounds1[3] < bounds2[1] || // box1 is below box2: box1.ymax < box2.miny
608  bounds1[1] > bounds2[3]) { // box1 is above box2: box1.ymin > box1.ymax
609  return false;
610  }
611  return true;
612 }
613 
615 double ST_X_Point(int8_t* p, int64_t psize, int32_t ic, int32_t isr, int32_t osr) {
616  return coord_x(p, 0, ic, isr, osr);
617 }
618 
620 double ST_Y_Point(int8_t* p, int64_t psize, int32_t ic, int32_t isr, int32_t osr) {
621  return coord_y(p, 1, ic, isr, osr);
622 }
623 
625 double ST_X_LineString(int8_t* l,
626  int64_t lsize,
627  int32_t lindex,
628  int32_t ic,
629  int32_t isr,
630  int32_t osr) {
631  auto l_num_points = lsize / (2 * compression_unit_size(ic));
632  if (lindex < 0 || lindex > l_num_points) {
633  lindex = l_num_points; // Endpoint
634  }
635  return coord_x(l, 2 * (lindex - 1), ic, isr, osr);
636 }
637 
639 double ST_Y_LineString(int8_t* l,
640  int64_t lsize,
641  int32_t lindex,
642  int32_t ic,
643  int32_t isr,
644  int32_t osr) {
645  auto l_num_points = lsize / (2 * compression_unit_size(ic));
646  if (lindex < 0 || lindex > l_num_points) {
647  lindex = l_num_points; // Endpoint
648  }
649  return coord_y(l, 2 * (lindex - 1) + 1, ic, isr, osr);
650 }
651 
653 double ST_XMin(int8_t* coords, int64_t size, int32_t ic, int32_t isr, int32_t osr) {
654  auto num_coords = size / compression_unit_size(ic);
655  double xmin = 0.0;
656  for (int32_t i = 0; i < num_coords; i += 2) {
657  double x = coord_x(coords, i, ic, isr, osr);
658  if (i == 0 || x < xmin) {
659  xmin = x;
660  }
661  }
662  return xmin;
663 }
664 
666 double ST_YMin(int8_t* coords, int64_t size, int32_t ic, int32_t isr, int32_t osr) {
667  auto num_coords = size / compression_unit_size(ic);
668  double ymin = 0.0;
669  for (int32_t i = 1; i < num_coords; i += 2) {
670  double y = coord_y(coords, i, ic, isr, osr);
671  if (i == 1 || y < ymin) {
672  ymin = y;
673  }
674  }
675  return ymin;
676 }
677 
679 double ST_XMax(int8_t* coords, int64_t size, int32_t ic, int32_t isr, int32_t osr) {
680  auto num_coords = size / compression_unit_size(ic);
681  double xmax = 0.0;
682  for (int32_t i = 0; i < num_coords; i += 2) {
683  double x = coord_x(coords, i, ic, isr, osr);
684  if (i == 0 || x > xmax) {
685  xmax = x;
686  }
687  }
688  return xmax;
689 }
690 
692 double ST_YMax(int8_t* coords, int64_t size, int32_t ic, int32_t isr, int32_t osr) {
693  auto num_coords = size / compression_unit_size(ic);
694  double ymax = 0.0;
695  for (int32_t i = 1; i < num_coords; i += 2) {
696  double y = coord_y(coords, i, ic, isr, osr);
697  if (i == 1 || y > ymax) {
698  ymax = y;
699  }
700  }
701  return ymax;
702 }
703 
705 double ST_XMin_Bounds(double* bounds, int64_t size, int32_t isr, int32_t osr) {
706  return transform_coord(bounds[0], isr, osr, true);
707 }
708 
710 double ST_YMin_Bounds(double* bounds, int64_t size, int32_t isr, int32_t osr) {
711  return transform_coord(bounds[1], isr, osr, false);
712 }
713 
715 double ST_XMax_Bounds(double* bounds, int64_t size, int32_t isr, int32_t osr) {
716  return transform_coord(bounds[2], isr, osr, true);
717 }
718 
720 double ST_YMax_Bounds(double* bounds, int64_t size, int32_t isr, int32_t osr) {
721  return transform_coord(bounds[3], isr, osr, false);
722 }
723 
724 //
725 // ST_Length
726 //
727 
729  int64_t lsize,
730  int32_t ic,
731  int32_t isr,
732  int32_t osr,
733  bool geodesic,
734  bool check_closed) {
735  auto l_num_coords = lsize / compression_unit_size(ic);
736 
737  double length = 0.0;
738 
739  double l0x = coord_x(l, 0, ic, isr, osr);
740  double l0y = coord_y(l, 1, ic, isr, osr);
741  double l2x = l0x;
742  double l2y = l0y;
743  for (int32_t i = 2; i < l_num_coords; i += 2) {
744  double l1x = l2x;
745  double l1y = l2y;
746  l2x = coord_x(l, i, ic, isr, osr);
747  l2y = coord_y(l, i + 1, ic, isr, osr);
748  double ldist = geodesic ? distance_in_meters(l1x, l1y, l2x, l2y)
749  : distance_point_point(l1x, l1y, l2x, l2y);
750  length += ldist;
751  }
752  if (check_closed) {
753  double ldist = geodesic ? distance_in_meters(l2x, l2y, l0x, l0y)
754  : distance_point_point(l2x, l2y, l0x, l0y);
755  length += ldist;
756  }
757  return length;
758 }
759 
761 double ST_Length_LineString(int8_t* coords,
762  int64_t coords_sz,
763  int32_t ic,
764  int32_t isr,
765  int32_t osr) {
766  return length_linestring(coords, coords_sz, ic, isr, osr, false, false);
767 }
768 
770 double ST_Length_LineString_Geodesic(int8_t* coords,
771  int64_t coords_sz,
772  int32_t ic,
773  int32_t isr,
774  int32_t osr) {
775  return length_linestring(coords, coords_sz, ic, isr, osr, true, false);
776 }
777 
778 //
779 // ST_Perimeter
780 //
781 
783 double ST_Perimeter_Polygon(int8_t* poly,
784  int64_t polysize,
785  int32_t* poly_ring_sizes,
786  int64_t poly_num_rings,
787  int32_t ic,
788  int32_t isr,
789  int32_t osr) {
790  if (poly_num_rings <= 0) {
791  return 0.0;
792  }
793 
794  auto exterior_ring_num_coords = poly_ring_sizes[0] * 2;
795  auto exterior_ring_coords_size = exterior_ring_num_coords * compression_unit_size(ic);
796 
797  return length_linestring(poly, exterior_ring_coords_size, ic, isr, osr, false, true);
798 }
799 
801 double ST_Perimeter_Polygon_Geodesic(int8_t* poly,
802  int64_t polysize,
803  int32_t* poly_ring_sizes,
804  int64_t poly_num_rings,
805  int32_t ic,
806  int32_t isr,
807  int32_t osr) {
808  if (poly_num_rings <= 0) {
809  return 0.0;
810  }
811 
812  auto exterior_ring_num_coords = poly_ring_sizes[0] * 2;
813  auto exterior_ring_coords_size = exterior_ring_num_coords * compression_unit_size(ic);
814 
815  return length_linestring(poly, exterior_ring_coords_size, ic, isr, osr, true, true);
816 }
817 
818 DEVICE ALWAYS_INLINE double perimeter_multipolygon(int8_t* mpoly_coords,
819  int64_t mpoly_coords_size,
820  int32_t* mpoly_ring_sizes,
821  int64_t mpoly_num_rings,
822  int32_t* mpoly_poly_sizes,
823  int64_t mpoly_num_polys,
824  int32_t ic,
825  int32_t isr,
826  int32_t osr,
827  bool geodesic) {
828  if (mpoly_num_polys <= 0 || mpoly_num_rings <= 0) {
829  return 0.0;
830  }
831 
832  double perimeter = 0.0;
833 
834  // Set specific poly pointers as we move through the coords/ringsizes/polyrings arrays.
835  auto next_poly_coords = mpoly_coords;
836  auto next_poly_ring_sizes = mpoly_ring_sizes;
837 
838  for (auto poly = 0; poly < mpoly_num_polys; poly++) {
839  auto poly_coords = next_poly_coords;
840  auto poly_ring_sizes = next_poly_ring_sizes;
841  auto poly_num_rings = mpoly_poly_sizes[poly];
842  // Count number of coords in all of poly's rings, advance ring size pointer.
843  int32_t poly_num_coords = 0;
844  for (auto ring = 0; ring < poly_num_rings; ring++) {
845  poly_num_coords += 2 * *next_poly_ring_sizes++;
846  }
847  auto poly_coords_size = poly_num_coords * compression_unit_size(ic);
848  next_poly_coords += poly_coords_size;
849 
850  auto exterior_ring_num_coords = poly_ring_sizes[0] * 2;
851  auto exterior_ring_coords_size = exterior_ring_num_coords * compression_unit_size(ic);
852 
853  perimeter += length_linestring(
854  poly_coords, exterior_ring_coords_size, ic, isr, osr, geodesic, true);
855  }
856 
857  return perimeter;
858 }
859 
861 double ST_Perimeter_MultiPolygon(int8_t* mpoly_coords,
862  int64_t mpoly_coords_size,
863  int32_t* mpoly_ring_sizes,
864  int64_t mpoly_num_rings,
865  int32_t* mpoly_poly_sizes,
866  int64_t mpoly_num_polys,
867  int32_t ic,
868  int32_t isr,
869  int32_t osr) {
870  return perimeter_multipolygon(mpoly_coords,
871  mpoly_coords_size,
872  mpoly_ring_sizes,
873  mpoly_num_rings,
874  mpoly_poly_sizes,
875  mpoly_num_polys,
876  ic,
877  isr,
878  osr,
879  false);
880 }
881 
883 double ST_Perimeter_MultiPolygon_Geodesic(int8_t* mpoly_coords,
884  int64_t mpoly_coords_size,
885  int32_t* mpoly_ring_sizes,
886  int64_t mpoly_num_rings,
887  int32_t* mpoly_poly_sizes,
888  int64_t mpoly_num_polys,
889  int32_t ic,
890  int32_t isr,
891  int32_t osr) {
892  return perimeter_multipolygon(mpoly_coords,
893  mpoly_coords_size,
894  mpoly_ring_sizes,
895  mpoly_num_rings,
896  mpoly_poly_sizes,
897  mpoly_num_polys,
898  ic,
899  isr,
900  osr,
901  true);
902 }
903 
904 //
905 // ST_Area
906 //
907 
909  double y1,
910  double x2,
911  double y2,
912  double x3,
913  double y3) {
914  return (x1 * y2 - x2 * y1 + x3 * y1 - x1 * y3 + x2 * y3 - x3 * y2) / 2.0;
915 }
916 
917 DEVICE ALWAYS_INLINE double area_ring(int8_t* ring,
918  int64_t ringsize,
919  int32_t ic,
920  int32_t isr,
921  int32_t osr) {
922  auto ring_num_coords = ringsize / compression_unit_size(ic);
923 
924  if (ring_num_coords < 6) {
925  return 0.0;
926  }
927 
928  double area = 0.0;
929 
930  double x1 = coord_x(ring, 0, ic, isr, osr);
931  double y1 = coord_y(ring, 1, ic, isr, osr);
932  double x2 = coord_x(ring, 2, ic, isr, osr);
933  double y2 = coord_y(ring, 3, ic, isr, osr);
934  for (int32_t i = 4; i < ring_num_coords; i += 2) {
935  double x3 = coord_x(ring, i, ic, isr, osr);
936  double y3 = coord_y(ring, i + 1, ic, isr, osr);
937  area += area_triangle(x1, y1, x2, y2, x3, y3);
938  x2 = x3;
939  y2 = y3;
940  }
941  return area;
942 }
943 
944 DEVICE ALWAYS_INLINE double area_polygon(int8_t* poly_coords,
945  int64_t poly_coords_size,
946  int32_t* poly_ring_sizes,
947  int64_t poly_num_rings,
948  int32_t ic,
949  int32_t isr,
950  int32_t osr) {
951  if (poly_num_rings <= 0) {
952  return 0.0;
953  }
954 
955  double area = 0.0;
956  auto ring_coords = poly_coords;
957 
958  // Add up the areas of all rings.
959  // External ring is CCW, open - positive area.
960  // Internal rings (holes) are CW, open - negative areas.
961  for (auto r = 0; r < poly_num_rings; r++) {
962  auto ring_coords_size = poly_ring_sizes[r] * 2 * compression_unit_size(ic);
963  area += area_ring(ring_coords, ring_coords_size, ic, isr, osr);
964  // Advance to the next ring.
965  ring_coords += ring_coords_size;
966  }
967  return area;
968 }
969 
971 double ST_Area_Polygon(int8_t* poly_coords,
972  int64_t poly_coords_size,
973  int32_t* poly_ring_sizes,
974  int64_t poly_num_rings,
975  int32_t ic,
976  int32_t isr,
977  int32_t osr) {
978  return area_polygon(
979  poly_coords, poly_coords_size, poly_ring_sizes, poly_num_rings, ic, isr, osr);
980 }
981 
983 double ST_Area_Polygon_Geodesic(int8_t* poly_coords,
984  int64_t poly_coords_size,
985  int32_t* poly_ring_sizes,
986  int64_t poly_num_rings,
987  int32_t ic,
988  int32_t isr,
989  int32_t osr) {
990  return ST_Area_Polygon(
991  poly_coords, poly_coords_size, poly_ring_sizes, poly_num_rings, ic, isr, osr);
992 }
993 
995 double ST_Area_MultiPolygon(int8_t* mpoly_coords,
996  int64_t mpoly_coords_size,
997  int32_t* mpoly_ring_sizes,
998  int64_t mpoly_num_rings,
999  int32_t* mpoly_poly_sizes,
1000  int64_t mpoly_num_polys,
1001  int32_t ic,
1002  int32_t isr,
1003  int32_t osr) {
1004  if (mpoly_num_rings <= 0 || mpoly_num_polys <= 0) {
1005  return 0.0;
1006  }
1007 
1008  double area = 0.0;
1009 
1010  // Set specific poly pointers as we move through the coords/ringsizes/polyrings arrays.
1011  auto next_poly_coords = mpoly_coords;
1012  auto next_poly_ring_sizes = mpoly_ring_sizes;
1013 
1014  for (auto poly = 0; poly < mpoly_num_polys; poly++) {
1015  auto poly_coords = next_poly_coords;
1016  auto poly_ring_sizes = next_poly_ring_sizes;
1017  auto poly_num_rings = mpoly_poly_sizes[poly];
1018  // Count number of coords in all of poly's rings, advance ring size pointer.
1019  int32_t poly_num_coords = 0;
1020  for (auto ring = 0; ring < poly_num_rings; ring++) {
1021  poly_num_coords += 2 * *next_poly_ring_sizes++;
1022  }
1023  auto poly_coords_size = poly_num_coords * compression_unit_size(ic);
1024  next_poly_coords += poly_coords_size;
1025 
1026  area += area_polygon(
1027  poly_coords, poly_coords_size, poly_ring_sizes, poly_num_rings, ic, isr, osr);
1028  }
1029  return area;
1030 }
1031 
1033 double ST_Area_MultiPolygon_Geodesic(int8_t* mpoly_coords,
1034  int64_t mpoly_coords_size,
1035  int32_t* mpoly_ring_sizes,
1036  int64_t mpoly_num_rings,
1037  int32_t* mpoly_poly_sizes,
1038  int64_t mpoly_num_polys,
1039  int32_t ic,
1040  int32_t isr,
1041  int32_t osr) {
1042  return ST_Area_MultiPolygon(mpoly_coords,
1043  mpoly_coords_size,
1044  mpoly_ring_sizes,
1045  mpoly_num_rings,
1046  mpoly_poly_sizes,
1047  mpoly_num_polys,
1048  ic,
1049  isr,
1050  osr);
1051 }
1052 
1054 int32_t ST_NPoints(int8_t* coords, int64_t coords_sz, int32_t ic) {
1055  auto num_pts = coords_sz / compression_unit_size(ic);
1056  return static_cast<int32_t>(num_pts / 2);
1057 }
1058 
1060 int32_t ST_NRings(int32_t* poly_ring_sizes, int64_t poly_num_rings) {
1061  return static_cast<int32_t>(poly_num_rings);
1062 }
1063 
1064 //
1065 // ST_Distance
1066 //
1067 
1069 double ST_Distance_Point_Point(int8_t* p1,
1070  int64_t p1size,
1071  int8_t* p2,
1072  int64_t p2size,
1073  int32_t ic1,
1074  int32_t isr1,
1075  int32_t ic2,
1076  int32_t isr2,
1077  int32_t osr) {
1078  double p1x = coord_x(p1, 0, ic1, isr1, osr);
1079  double p1y = coord_y(p1, 1, ic1, isr1, osr);
1080  double p2x = coord_x(p2, 0, ic2, isr2, osr);
1081  double p2y = coord_y(p2, 1, ic2, isr2, osr);
1082  return distance_point_point(p1x, p1y, p2x, p2y);
1083 }
1084 
1087  int64_t p1size,
1088  int8_t* p2,
1089  int64_t p2size,
1090  int32_t ic1,
1091  int32_t isr1,
1092  int32_t ic2,
1093  int32_t isr2,
1094  int32_t osr) {
1095  double p1x = coord_x(p1, 0, ic1, isr1, osr);
1096  double p1y = coord_y(p1, 1, ic1, isr1, osr);
1097  double p2x = coord_x(p2, 0, ic2, isr2, osr);
1098  double p2y = coord_y(p2, 1, ic2, isr2, osr);
1099  return distance_point_point_squared(p1x, p1y, p2x, p2y);
1100 }
1101 
1104  int64_t p1size,
1105  int8_t* p2,
1106  int64_t p2size,
1107  int32_t ic1,
1108  int32_t isr1,
1109  int32_t ic2,
1110  int32_t isr2,
1111  int32_t osr) {
1112  double p1x = coord_x(p1, 0, ic1, 4326, 4326);
1113  double p1y = coord_y(p1, 1, ic1, 4326, 4326);
1114  double p2x = coord_x(p2, 0, ic2, 4326, 4326);
1115  double p2y = coord_y(p2, 1, ic2, 4326, 4326);
1116  return distance_in_meters(p1x, p1y, p2x, p2y);
1117 }
1118 
1121  int64_t psize,
1122  int8_t* l,
1123  int64_t lsize,
1124  int32_t lindex,
1125  int32_t ic1,
1126  int32_t isr1,
1127  int32_t ic2,
1128  int32_t isr2,
1129  int32_t osr) {
1130  // Currently only statically indexed LineString is supported
1131  double px = coord_x(p, 0, ic1, 4326, 4326);
1132  double py = coord_y(p, 1, ic1, 4326, 4326);
1133  auto lpoints = lsize / (2 * compression_unit_size(ic2));
1134  if (lindex < 0 || lindex > lpoints) {
1135  lindex = lpoints; // Endpoint
1136  }
1137  double lx = coord_x(l, 2 * (lindex - 1), ic2, 4326, 4326);
1138  double ly = coord_y(l, 2 * (lindex - 1) + 1, ic2, 4326, 4326);
1139  return distance_in_meters(px, py, lx, ly);
1140 }
1141 
1144  int64_t lsize,
1145  int32_t lindex,
1146  int8_t* p,
1147  int64_t psize,
1148  int32_t ic1,
1149  int32_t isr1,
1150  int32_t ic2,
1151  int32_t isr2,
1152  int32_t osr) {
1153  // Currently only statically indexed LineString is supported
1155  p, psize, l, lsize, lindex, ic2, isr2, ic1, isr1, osr);
1156 }
1157 
1160  int64_t l1size,
1161  int32_t l1index,
1162  int8_t* l2,
1163  int64_t l2size,
1164  int32_t l2index,
1165  int32_t ic1,
1166  int32_t isr1,
1167  int32_t ic2,
1168  int32_t isr2,
1169  int32_t osr) {
1170  // Currently only statically indexed LineStrings are supported
1171  auto l1points = l1size / (2 * compression_unit_size(ic1));
1172  if (l1index < 0 || l1index > l1points) {
1173  l1index = l1points; // Endpoint
1174  }
1175  double l1x = coord_x(l1, 2 * (l1index - 1), ic1, 4326, 4326);
1176  double l1y = coord_y(l1, 2 * (l1index - 1) + 1, ic1, 4326, 4326);
1177  auto l2points = l2size / (2 * compression_unit_size(ic2));
1178  if (l2index < 0 || l2index > l2points) {
1179  l2index = l2points; // Endpoint
1180  }
1181  double l2x = coord_x(l2, 2 * (l2index - 1), ic2, 4326, 4326);
1182  double l2y = coord_y(l2, 2 * (l2index - 1) + 1, ic2, 4326, 4326);
1183  return distance_in_meters(l1x, l1y, l2x, l2y);
1184 }
1185 
1187  int64_t psize,
1188  int8_t* l,
1189  int64_t lsize,
1190  int32_t lindex,
1191  int32_t ic1,
1192  int32_t isr1,
1193  int32_t ic2,
1194  int32_t isr2,
1195  int32_t osr,
1196  bool check_closed) {
1197  double px = coord_x(p, 0, ic1, isr1, osr);
1198  double py = coord_y(p, 1, ic1, isr1, osr);
1199 
1200  auto l_num_coords = lsize / compression_unit_size(ic2);
1201  auto l_num_points = l_num_coords / 2;
1202  if (lindex != 0) { // Statically indexed linestring
1203  if (lindex < 0 || lindex > l_num_points) {
1204  lindex = l_num_points; // Endpoint
1205  }
1206  double lx = coord_x(l, 2 * (lindex - 1), ic2, isr2, osr);
1207  double ly = coord_y(l, 2 * (lindex - 1) + 1, ic2, isr2, osr);
1208  return distance_point_point(px, py, lx, ly);
1209  }
1210 
1211  double l1x = coord_x(l, 0, ic2, isr2, osr);
1212  double l1y = coord_y(l, 1, ic2, isr2, osr);
1213  double l2x = coord_x(l, 2, ic2, isr2, osr);
1214  double l2y = coord_y(l, 3, ic2, isr2, osr);
1215 
1216  double dist = distance_point_line(px, py, l1x, l1y, l2x, l2y);
1217  for (int32_t i = 4; i < l_num_coords; i += 2) {
1218  l1x = l2x; // advance one point
1219  l1y = l2y;
1220  l2x = coord_x(l, i, ic2, isr2, osr);
1221  l2y = coord_y(l, i + 1, ic2, isr2, osr);
1222  double ldist = distance_point_line(px, py, l1x, l1y, l2x, l2y);
1223  if (dist > ldist) {
1224  dist = ldist;
1225  }
1226  }
1227  if (l_num_coords > 4 && check_closed) {
1228  // Also check distance to the closing edge between the first and the last points
1229  l1x = coord_x(l, 0, ic2, isr2, osr);
1230  l1y = coord_y(l, 1, ic2, isr2, osr);
1231  double ldist = distance_point_line(px, py, l1x, l1y, l2x, l2y);
1232  if (dist > ldist) {
1233  dist = ldist;
1234  }
1235  }
1236  return dist;
1237 }
1238 
1241  int64_t psize,
1242  int8_t* l,
1243  int64_t lsize,
1244  int32_t lindex,
1245  int32_t ic1,
1246  int32_t isr1,
1247  int32_t ic2,
1248  int32_t isr2,
1249  int32_t osr) {
1251  p, psize, l, lsize, lindex, ic1, isr1, ic2, isr2, osr, true);
1252 }
1253 
1256  int64_t psize,
1257  int8_t* l,
1258  int64_t lsize,
1259  int32_t lindex,
1260  int32_t ic1,
1261  int32_t isr1,
1262  int32_t ic2,
1263  int32_t isr2,
1264  int32_t osr) {
1265  if (lindex != 0) { // Statically indexed linestring
1266  auto l_num_coords = lsize / compression_unit_size(ic2);
1267  auto l_num_points = l_num_coords / 2;
1268  if (lindex < 0 || lindex > l_num_points) {
1269  lindex = l_num_points; // Endpoint
1270  }
1271  double px = coord_x(p, 0, ic1, isr1, osr);
1272  double py = coord_y(p, 1, ic1, isr1, osr);
1273  double lx = coord_x(l, 2 * (lindex - 1), ic2, isr2, osr);
1274  double ly = coord_y(l, 2 * (lindex - 1) + 1, ic2, isr2, osr);
1275  return distance_point_point(px, py, lx, ly);
1276  }
1277 
1279  p, psize, l, lsize, lindex, ic1, isr1, ic2, isr2, osr, false);
1280 }
1281 
1283 double ST_Distance_Point_Polygon(int8_t* p,
1284  int64_t psize,
1285  int8_t* poly,
1286  int64_t polysize,
1287  int32_t* poly_ring_sizes,
1288  int64_t poly_num_rings,
1289  int32_t ic1,
1290  int32_t isr1,
1291  int32_t ic2,
1292  int32_t isr2,
1293  int32_t osr) {
1294  auto exterior_ring_num_coords = polysize / compression_unit_size(ic2);
1295  if (poly_num_rings > 0) {
1296  exterior_ring_num_coords = poly_ring_sizes[0] * 2;
1297  }
1298  auto exterior_ring_coords_size = exterior_ring_num_coords * compression_unit_size(ic2);
1299 
1300  double px = coord_x(p, 0, ic1, isr1, osr);
1301  double py = coord_y(p, 1, ic1, isr1, osr);
1302  if (!polygon_contains_point(poly, exterior_ring_num_coords, px, py, ic2, isr2, osr)) {
1303  // Outside the exterior ring
1305  p, psize, poly, exterior_ring_coords_size, 0, ic1, isr1, ic2, isr2, osr);
1306  }
1307  // Inside exterior ring
1308  // Advance to first interior ring
1309  poly += exterior_ring_coords_size;
1310  // Check if one of the polygon's holes contains that point
1311  for (auto r = 1; r < poly_num_rings; r++) {
1312  auto interior_ring_num_coords = poly_ring_sizes[r] * 2;
1313  auto interior_ring_coords_size =
1314  interior_ring_num_coords * compression_unit_size(ic2);
1315  if (polygon_contains_point(poly, interior_ring_num_coords, px, py, ic2, isr2, osr)) {
1316  // Inside an interior ring
1318  p, psize, poly, interior_ring_coords_size, 0, ic1, isr1, ic2, isr2, osr);
1319  }
1320  poly += interior_ring_coords_size;
1321  }
1322  return 0.0;
1323 }
1324 
1327  int64_t psize,
1328  int8_t* mpoly_coords,
1329  int64_t mpoly_coords_size,
1330  int32_t* mpoly_ring_sizes,
1331  int64_t mpoly_num_rings,
1332  int32_t* mpoly_poly_sizes,
1333  int64_t mpoly_num_polys,
1334  int32_t ic1,
1335  int32_t isr1,
1336  int32_t ic2,
1337  int32_t isr2,
1338  int32_t osr) {
1339  if (mpoly_num_polys <= 0) {
1340  return 0.0;
1341  }
1342  double min_distance = 0.0;
1343 
1344  // Set specific poly pointers as we move through the coords/ringsizes/polyrings arrays.
1345  auto next_poly_coords = mpoly_coords;
1346  auto next_poly_ring_sizes = mpoly_ring_sizes;
1347 
1348  for (auto poly = 0; poly < mpoly_num_polys; poly++) {
1349  auto poly_coords = next_poly_coords;
1350  auto poly_ring_sizes = next_poly_ring_sizes;
1351  auto poly_num_rings = mpoly_poly_sizes[poly];
1352  // Count number of coords in all of poly's rings, advance ring size pointer.
1353  int32_t poly_num_coords = 0;
1354  for (auto ring = 0; ring < poly_num_rings; ring++) {
1355  poly_num_coords += 2 * *next_poly_ring_sizes++;
1356  }
1357  auto poly_coords_size = poly_num_coords * compression_unit_size(ic2);
1358  next_poly_coords += poly_coords_size;
1359  double distance = ST_Distance_Point_Polygon(p,
1360  psize,
1361  poly_coords,
1362  poly_coords_size,
1363  poly_ring_sizes,
1364  poly_num_rings,
1365  ic1,
1366  isr1,
1367  ic2,
1368  isr2,
1369  osr);
1370  if (poly == 0 || min_distance > distance) {
1371  min_distance = distance;
1372  if (tol_zero(min_distance)) {
1373  min_distance = 0.0;
1374  break;
1375  }
1376  }
1377  }
1378 
1379  return min_distance;
1380 }
1381 
1384  int64_t lsize,
1385  int32_t lindex,
1386  int8_t* p,
1387  int64_t psize,
1388  int32_t ic1,
1389  int32_t isr1,
1390  int32_t ic2,
1391  int32_t isr2,
1392  int32_t osr) {
1394  p, psize, l, lsize, lindex, ic2, isr2, ic1, isr1, osr);
1395 }
1396 
1399  int64_t l1size,
1400  int32_t l1index,
1401  int8_t* l2,
1402  int64_t l2size,
1403  int32_t l2index,
1404  int32_t ic1,
1405  int32_t isr1,
1406  int32_t ic2,
1407  int32_t isr2,
1408  int32_t osr) {
1409  auto l1_num_coords = l1size / compression_unit_size(ic1);
1410  if (l1index != 0) {
1411  // l1 is a statically indexed linestring
1412  auto l1_num_points = l1_num_coords / 2;
1413  if (l1index < 0 || l1index > l1_num_points) {
1414  l1index = l1_num_points;
1415  }
1416  int8_t* p = l1 + 2 * (l1index - 1) * compression_unit_size(ic1);
1417  int64_t psize = 2 * compression_unit_size(ic1);
1419  p, psize, l2, l2size, l2index, ic1, isr1, ic2, isr2, osr);
1420  }
1421 
1422  auto l2_num_coords = l2size / compression_unit_size(ic2);
1423  if (l2index != 0) {
1424  // l2 is a statically indexed linestring
1425  auto l2_num_points = l2_num_coords / 2;
1426  if (l2index < 0 || l2index > l2_num_points) {
1427  l2index = l2_num_points;
1428  }
1429  int8_t* p = l2 + 2 * (l2index - 1) * compression_unit_size(ic2);
1430  int64_t psize = 2 * compression_unit_size(ic2);
1432  p, psize, l1, l1size, l1index, ic2, isr2, ic1, isr1, osr);
1433  }
1434 
1435  double dist = 0.0;
1436  double l11x = coord_x(l1, 0, ic1, isr1, osr);
1437  double l11y = coord_y(l1, 1, ic1, isr1, osr);
1438  for (int32_t i1 = 2; i1 < l1_num_coords; i1 += 2) {
1439  double l12x = coord_x(l1, i1, ic1, isr1, osr);
1440  double l12y = coord_y(l1, i1 + 1, ic1, isr1, osr);
1441 
1442  double l21x = coord_x(l2, 0, ic2, isr2, osr);
1443  double l21y = coord_y(l2, 1, ic2, isr2, osr);
1444  for (int32_t i2 = 2; i2 < l2_num_coords; i2 += 2) {
1445  double l22x = coord_x(l2, i2, ic2, isr2, osr);
1446  double l22y = coord_y(l2, i2 + 1, ic2, isr2, osr);
1447 
1448  double ldist = distance_line_line(l11x, l11y, l12x, l12y, l21x, l21y, l22x, l22y);
1449  if (i1 == 2 && i2 == 2) {
1450  dist = ldist; // initialize dist with distance between the first two segments
1451  } else if (dist > ldist) {
1452  dist = ldist;
1453  }
1454  if (tol_zero(dist)) {
1455  return 0.0; // segments touch
1456  }
1457 
1458  l21x = l22x; // advance to the next point on l2
1459  l21y = l22y;
1460  }
1461 
1462  l11x = l12x; // advance to the next point on l1
1463  l11y = l12y;
1464  }
1465  return dist;
1466 }
1467 
1470  int64_t lsize,
1471  int32_t lindex,
1472  int8_t* poly_coords,
1473  int64_t poly_coords_size,
1474  int32_t* poly_ring_sizes,
1475  int64_t poly_num_rings,
1476  int32_t ic1,
1477  int32_t isr1,
1478  int32_t ic2,
1479  int32_t isr2,
1480  int32_t osr) {
1481  auto lnum_coords = lsize / compression_unit_size(ic1);
1482  auto lnum_points = lnum_coords / 2;
1483  if (lindex < 0 || lindex > lnum_points) {
1484  lindex = lnum_points;
1485  }
1486  auto p = l + lindex * compression_unit_size(ic1);
1487  auto psize = 2 * compression_unit_size(ic1);
1488  auto min_distance = ST_Distance_Point_Polygon(p,
1489  psize,
1490  poly_coords,
1491  poly_coords_size,
1492  poly_ring_sizes,
1493  poly_num_rings,
1494  ic1,
1495  isr1,
1496  ic2,
1497  isr2,
1498  osr);
1499  if (lindex != 0) {
1500  // Statically indexed linestring: return distance from the indexed point to poly
1501  return min_distance;
1502  }
1503  if (tol_zero(min_distance)) {
1504  // Linestring's first point is inside the poly
1505  return 0.0;
1506  }
1507 
1508  // Otherwise, linestring's first point is outside the external ring or inside
1509  // an internal ring. Measure minimum distance between linestring segments and
1510  // poly rings. Crossing a ring zeroes the distance and causes an early return.
1511  auto poly_ring_coords = poly_coords;
1512  for (auto r = 0; r < poly_num_rings; r++) {
1513  int64_t poly_ring_num_coords = poly_ring_sizes[r] * 2;
1514 
1515  auto distance = distance_ring_linestring(poly_ring_coords,
1516  poly_ring_num_coords,
1517  l,
1518  lnum_coords,
1519  ic2,
1520  isr2,
1521  ic1,
1522  isr1,
1523  osr);
1524  if (min_distance > distance) {
1525  min_distance = distance;
1526  if (tol_zero(min_distance)) {
1527  return 0.0;
1528  }
1529  }
1530 
1531  poly_ring_coords += poly_ring_num_coords * compression_unit_size(ic2);
1532  }
1533 
1534  return min_distance;
1535 }
1536 
1539  int64_t lsize,
1540  int32_t lindex,
1541  int8_t* mpoly_coords,
1542  int64_t mpoly_coords_size,
1543  int32_t* mpoly_ring_sizes,
1544  int64_t mpoly_num_rings,
1545  int32_t* mpoly_poly_sizes,
1546  int64_t mpoly_num_polys,
1547  int32_t ic1,
1548  int32_t isr1,
1549  int32_t ic2,
1550  int32_t isr2,
1551  int32_t osr) {
1552  // TODO: revisit implementation, cover all cases
1553 
1554  auto lnum_coords = lsize / compression_unit_size(ic1);
1555  auto lnum_points = lnum_coords / 2;
1556  if (lindex != 0) {
1557  // Statically indexed linestring
1558  if (lindex < 0 || lindex > lnum_points) {
1559  lindex = lnum_points;
1560  }
1561  auto p = l + lindex * compression_unit_size(ic1);
1562  auto psize = 2 * compression_unit_size(ic1);
1564  psize,
1565  mpoly_coords,
1566  mpoly_coords_size,
1567  mpoly_ring_sizes,
1568  mpoly_num_rings,
1569  mpoly_poly_sizes,
1570  mpoly_num_polys,
1571  ic1,
1572  isr1,
1573  ic2,
1574  isr2,
1575  osr);
1576  }
1577 
1578  double min_distance = 0.0;
1579 
1580  // Set specific poly pointers as we move through the coords/ringsizes/polyrings arrays.
1581  auto next_poly_coords = mpoly_coords;
1582  auto next_poly_ring_sizes = mpoly_ring_sizes;
1583 
1584  for (auto poly = 0; poly < mpoly_num_polys; poly++) {
1585  auto poly_coords = next_poly_coords;
1586  auto poly_ring_sizes = next_poly_ring_sizes;
1587  auto poly_num_rings = mpoly_poly_sizes[poly];
1588  // Count number of coords in all of poly's rings, advance ring size pointer.
1589  int32_t poly_num_coords = 0;
1590  for (auto ring = 0; ring < poly_num_rings; ring++) {
1591  poly_num_coords += 2 * *next_poly_ring_sizes++;
1592  }
1593  auto poly_coords_size = poly_num_coords * compression_unit_size(ic2);
1594  next_poly_coords += poly_coords_size;
1595  double distance = ST_Distance_LineString_Polygon(l,
1596  lsize,
1597  lindex,
1598  poly_coords,
1599  poly_coords_size,
1600  poly_ring_sizes,
1601  poly_num_rings,
1602  ic1,
1603  isr1,
1604  ic2,
1605  isr2,
1606  osr);
1607  if (poly == 0 || min_distance > distance) {
1608  min_distance = distance;
1609  if (tol_zero(min_distance)) {
1610  min_distance = 0.0;
1611  break;
1612  }
1613  }
1614  }
1615 
1616  return min_distance;
1617 }
1618 
1620 double ST_Distance_Polygon_Point(int8_t* poly_coords,
1621  int64_t poly_coords_size,
1622  int32_t* poly_ring_sizes,
1623  int64_t poly_num_rings,
1624  int8_t* p,
1625  int64_t psize,
1626  int32_t ic1,
1627  int32_t isr1,
1628  int32_t ic2,
1629  int32_t isr2,
1630  int32_t osr) {
1631  return ST_Distance_Point_Polygon(p,
1632  psize,
1633  poly_coords,
1634  poly_coords_size,
1635  poly_ring_sizes,
1636  poly_num_rings,
1637  ic2,
1638  isr2,
1639  ic1,
1640  isr1,
1641  osr);
1642 }
1643 
1645 double ST_Distance_Polygon_LineString(int8_t* poly_coords,
1646  int64_t poly_coords_size,
1647  int32_t* poly_ring_sizes,
1648  int64_t poly_num_rings,
1649  int8_t* l,
1650  int64_t lsize,
1651  int32_t li,
1652  int32_t ic1,
1653  int32_t isr1,
1654  int32_t ic2,
1655  int32_t isr2,
1656  int32_t osr) {
1658  lsize,
1659  li,
1660  poly_coords,
1661  poly_coords_size,
1662  poly_ring_sizes,
1663  poly_num_rings,
1664  ic2,
1665  isr2,
1666  ic1,
1667  isr2,
1668  osr);
1669 }
1670 
1672 double ST_Distance_Polygon_Polygon(int8_t* poly1_coords,
1673  int64_t poly1_coords_size,
1674  int32_t* poly1_ring_sizes,
1675  int64_t poly1_num_rings,
1676  int8_t* poly2_coords,
1677  int64_t poly2_coords_size,
1678  int32_t* poly2_ring_sizes,
1679  int64_t poly2_num_rings,
1680  int32_t ic1,
1681  int32_t isr1,
1682  int32_t ic2,
1683  int32_t isr2,
1684  int32_t osr) {
1685  // Check if poly1 contains the first point of poly2's shape, i.e. the external ring
1686  auto poly2_first_point_coords = poly2_coords;
1687  auto poly2_first_point_coords_size = compression_unit_size(ic2) * 2;
1688  auto min_distance = ST_Distance_Polygon_Point(poly1_coords,
1689  poly1_coords_size,
1690  poly1_ring_sizes,
1691  poly1_num_rings,
1692  poly2_first_point_coords,
1693  poly2_first_point_coords_size,
1694  ic1,
1695  isr1,
1696  ic2,
1697  isr2,
1698  osr);
1699  if (tol_zero(min_distance)) {
1700  // Polygons overlap
1701  return 0.0;
1702  }
1703 
1704  // Poly2's first point is either outside poly1's external ring or inside one of the
1705  // internal rings. Measure the smallest distance between a poly1 ring (external or
1706  // internal) and a poly2 ring (external or internal). If poly2 is completely outside
1707  // poly1, then the min distance would be between poly1's and poly2's external rings. If
1708  // poly2 is completely inside one of poly1 internal rings then the min distance would be
1709  // between that poly1 internal ring and poly2's external ring. If poly1 is completely
1710  // inside one of poly2 internal rings, min distance is between that internal ring and
1711  // poly1's external ring. In each case other rings don't get in the way. Any ring
1712  // intersection means zero distance - short-circuit and return.
1713 
1714  auto poly1_ring_coords = poly1_coords;
1715  for (auto r1 = 0; r1 < poly1_num_rings; r1++) {
1716  int64_t poly1_ring_num_coords = poly1_ring_sizes[r1] * 2;
1717 
1718  auto poly2_ring_coords = poly2_coords;
1719  for (auto r2 = 0; r2 < poly2_num_rings; r2++) {
1720  int64_t poly2_ring_num_coords = poly2_ring_sizes[r2] * 2;
1721 
1722  auto distance = distance_ring_ring(poly1_ring_coords,
1723  poly1_ring_num_coords,
1724  poly2_ring_coords,
1725  poly2_ring_num_coords,
1726  ic1,
1727  isr1,
1728  ic2,
1729  isr2,
1730  osr);
1731  if (min_distance > distance) {
1732  min_distance = distance;
1733  if (tol_zero(min_distance)) {
1734  return 0.0;
1735  }
1736  }
1737 
1738  poly2_ring_coords += poly2_ring_num_coords * compression_unit_size(ic2);
1739  }
1740 
1741  poly1_ring_coords += poly1_ring_num_coords * compression_unit_size(ic1);
1742  }
1743 
1744  return min_distance;
1745 }
1746 
1748 double ST_Distance_Polygon_MultiPolygon(int8_t* poly1_coords,
1749  int64_t poly1_coords_size,
1750  int32_t* poly1_ring_sizes,
1751  int64_t poly1_num_rings,
1752  int8_t* mpoly_coords,
1753  int64_t mpoly_coords_size,
1754  int32_t* mpoly_ring_sizes,
1755  int64_t mpoly_num_rings,
1756  int32_t* mpoly_poly_sizes,
1757  int64_t mpoly_num_polys,
1758  int32_t ic1,
1759  int32_t isr1,
1760  int32_t ic2,
1761  int32_t isr2,
1762  int32_t osr) {
1763  double min_distance = 0.0;
1764 
1765  // Set specific poly pointers as we move through the coords/ringsizes/polyrings arrays.
1766  auto next_poly_coords = mpoly_coords;
1767  auto next_poly_ring_sizes = mpoly_ring_sizes;
1768 
1769  for (auto poly = 0; poly < mpoly_num_polys; poly++) {
1770  auto poly_coords = next_poly_coords;
1771  auto poly_ring_sizes = next_poly_ring_sizes;
1772  auto poly_num_rings = mpoly_poly_sizes[poly];
1773  // Count number of coords in all of poly's rings, advance ring size pointer.
1774  int32_t poly_num_coords = 0;
1775  for (auto ring = 0; ring < poly_num_rings; ring++) {
1776  poly_num_coords += 2 * *next_poly_ring_sizes++;
1777  }
1778  auto poly_coords_size = poly_num_coords * compression_unit_size(ic2);
1779  next_poly_coords += poly_coords_size;
1780  double distance = ST_Distance_Polygon_Polygon(poly1_coords,
1781  poly1_coords_size,
1782  poly1_ring_sizes,
1783  poly1_num_rings,
1784  poly_coords,
1785  poly_coords_size,
1786  poly_ring_sizes,
1787  poly_num_rings,
1788  ic1,
1789  isr1,
1790  ic2,
1791  isr2,
1792  osr);
1793  if (poly == 0 || min_distance > distance) {
1794  min_distance = distance;
1795  if (tol_zero(min_distance)) {
1796  min_distance = 0.0;
1797  break;
1798  }
1799  }
1800  }
1801 
1802  return min_distance;
1803 }
1804 
1806 double ST_Distance_MultiPolygon_Point(int8_t* mpoly_coords,
1807  int64_t mpoly_coords_size,
1808  int32_t* mpoly_ring_sizes,
1809  int64_t mpoly_num_rings,
1810  int32_t* mpoly_poly_sizes,
1811  int64_t mpoly_num_polys,
1812  int8_t* p,
1813  int64_t psize,
1814  int32_t ic1,
1815  int32_t isr1,
1816  int32_t ic2,
1817  int32_t isr2,
1818  int32_t osr) {
1820  psize,
1821  mpoly_coords,
1822  mpoly_coords_size,
1823  mpoly_ring_sizes,
1824  mpoly_num_rings,
1825  mpoly_poly_sizes,
1826  mpoly_num_polys,
1827  ic2,
1828  isr2,
1829  ic1,
1830  isr1,
1831  osr);
1832 }
1833 
1835 double ST_Distance_MultiPolygon_LineString(int8_t* mpoly_coords,
1836  int64_t mpoly_coords_size,
1837  int32_t* mpoly_ring_sizes,
1838  int64_t mpoly_num_rings,
1839  int32_t* mpoly_poly_sizes,
1840  int64_t mpoly_num_polys,
1841  int8_t* l,
1842  int64_t lsize,
1843  int32_t lindex,
1844  int32_t ic1,
1845  int32_t isr1,
1846  int32_t ic2,
1847  int32_t isr2,
1848  int32_t osr) {
1850  lsize,
1851  lindex,
1852  mpoly_coords,
1853  mpoly_coords_size,
1854  mpoly_ring_sizes,
1855  mpoly_num_rings,
1856  mpoly_poly_sizes,
1857  mpoly_num_polys,
1858  ic2,
1859  isr2,
1860  ic1,
1861  isr1,
1862  osr);
1863 }
1864 
1866 double ST_Distance_MultiPolygon_Polygon(int8_t* mpoly_coords,
1867  int64_t mpoly_coords_size,
1868  int32_t* mpoly_ring_sizes,
1869  int64_t mpoly_num_rings,
1870  int32_t* mpoly_poly_sizes,
1871  int64_t mpoly_num_polys,
1872  int8_t* poly1_coords,
1873  int64_t poly1_coords_size,
1874  int32_t* poly1_ring_sizes,
1875  int64_t poly1_num_rings,
1876  int32_t ic1,
1877  int32_t isr1,
1878  int32_t ic2,
1879  int32_t isr2,
1880  int32_t osr) {
1881  return ST_Distance_Polygon_MultiPolygon(poly1_coords,
1882  poly1_coords_size,
1883  poly1_ring_sizes,
1884  poly1_num_rings,
1885  mpoly_coords,
1886  mpoly_coords_size,
1887  mpoly_ring_sizes,
1888  mpoly_num_rings,
1889  mpoly_poly_sizes,
1890  mpoly_num_polys,
1891  ic2,
1892  isr2,
1893  ic1,
1894  isr1,
1895  osr);
1896 }
1897 
1899 double ST_Distance_MultiPolygon_MultiPolygon(int8_t* mpoly1_coords,
1900  int64_t mpoly1_coords_size,
1901  int32_t* mpoly1_ring_sizes,
1902  int64_t mpoly1_num_rings,
1903  int32_t* mpoly1_poly_sizes,
1904  int64_t mpoly1_num_polys,
1905  int8_t* mpoly2_coords,
1906  int64_t mpoly2_coords_size,
1907  int32_t* mpoly2_ring_sizes,
1908  int64_t mpoly2_num_rings,
1909  int32_t* mpoly2_poly_sizes,
1910  int64_t mpoly2_num_polys,
1911  int32_t ic1,
1912  int32_t isr1,
1913  int32_t ic2,
1914  int32_t isr2,
1915  int32_t osr) {
1916  double min_distance = 0.0;
1917 
1918  // Set specific poly pointers as we move through mpoly1's coords/ringsizes/polyrings
1919  // arrays.
1920  auto next_poly_coords = mpoly1_coords;
1921  auto next_poly_ring_sizes = mpoly1_ring_sizes;
1922 
1923  for (auto poly = 0; poly < mpoly1_num_polys; poly++) {
1924  auto poly_coords = next_poly_coords;
1925  auto poly_ring_sizes = next_poly_ring_sizes;
1926  auto poly_num_rings = mpoly1_poly_sizes[poly];
1927  // Count number of coords in all of poly's rings, advance ring size pointer.
1928  int32_t poly_num_coords = 0;
1929  for (auto ring = 0; ring < poly_num_rings; ring++) {
1930  poly_num_coords += 2 * *next_poly_ring_sizes++;
1931  }
1932  auto poly_coords_size = poly_num_coords * compression_unit_size(ic1);
1933  next_poly_coords += poly_coords_size;
1934  double distance = ST_Distance_Polygon_MultiPolygon(poly_coords,
1935  poly_coords_size,
1936  poly_ring_sizes,
1937  poly_num_rings,
1938  mpoly2_coords,
1939  mpoly2_coords_size,
1940  mpoly2_ring_sizes,
1941  mpoly2_num_rings,
1942  mpoly2_poly_sizes,
1943  mpoly2_num_polys,
1944  ic1,
1945  isr1,
1946  ic2,
1947  isr2,
1948  osr);
1949  if (poly == 0 || min_distance > distance) {
1950  min_distance = distance;
1951  if (tol_zero(min_distance)) {
1952  min_distance = 0.0;
1953  break;
1954  }
1955  }
1956  }
1957 
1958  return min_distance;
1959 }
1960 
1961 //
1962 // ST_MaxDistance
1963 //
1964 
1965 // Max cartesian distance between a point and a line segment
1966 DEVICE
1967 double max_distance_point_line(double px,
1968  double py,
1969  double l1x,
1970  double l1y,
1971  double l2x,
1972  double l2y) {
1973  double length1 = distance_point_point(px, py, l1x, l1y);
1974  double length2 = distance_point_point(px, py, l2x, l2y);
1975  if (length1 > length2) {
1976  return length1;
1977  }
1978  return length2;
1979 }
1980 
1982  int64_t psize,
1983  int8_t* l,
1984  int64_t lsize,
1985  int32_t lindex,
1986  int32_t ic1,
1987  int32_t isr1,
1988  int32_t ic2,
1989  int32_t isr2,
1990  int32_t osr,
1991  bool check_closed) {
1992  double px = coord_x(p, 0, ic1, isr1, osr);
1993  double py = coord_y(p, 1, ic1, isr1, osr);
1994 
1995  auto l_num_coords = lsize / compression_unit_size(ic2);
1996  auto l_num_points = l_num_coords / 2;
1997  if (lindex != 0) { // Statically indexed linestring
1998  if (lindex < 0 || lindex > l_num_points) {
1999  lindex = l_num_points; // Endpoint
2000  }
2001  double lx = coord_x(l, 2 * (lindex - 1), ic2, isr2, osr);
2002  double ly = coord_y(l, 2 * (lindex - 1) + 1, ic2, isr2, osr);
2003  return distance_point_point(px, py, lx, ly);
2004  }
2005 
2006  double l1x = coord_x(l, 0, ic2, isr2, osr);
2007  double l1y = coord_y(l, 1, ic2, isr2, osr);
2008  double l2x = coord_x(l, 2, ic2, isr2, osr);
2009  double l2y = coord_y(l, 3, ic2, isr2, osr);
2010 
2011  double max_dist = max_distance_point_line(px, py, l1x, l1y, l2x, l2y);
2012  for (int32_t i = 4; i < l_num_coords; i += 2) {
2013  l1x = l2x; // advance one point
2014  l1y = l2y;
2015  l2x = coord_x(l, i, ic2, isr2, osr);
2016  l2y = coord_y(l, i + 1, ic2, isr2, osr);
2017  double ldist = max_distance_point_line(px, py, l1x, l1y, l2x, l2y);
2018  if (max_dist < ldist) {
2019  max_dist = ldist;
2020  }
2021  }
2022  if (l_num_coords > 4 && check_closed) {
2023  // Also check distance to the closing edge between the first and the last points
2024  l1x = coord_x(l, 0, ic2, isr2, osr);
2025  l1y = coord_y(l, 1, ic2, isr2, osr);
2026  double ldist = max_distance_point_line(px, py, l1x, l1y, l2x, l2y);
2027  if (max_dist < ldist) {
2028  max_dist = ldist;
2029  }
2030  }
2031  return max_dist;
2032 }
2033 
2036  int64_t psize,
2037  int8_t* l,
2038  int64_t lsize,
2039  int32_t lindex,
2040  int32_t ic1,
2041  int32_t isr1,
2042  int32_t ic2,
2043  int32_t isr2,
2044  int32_t osr) {
2046  p, psize, l, lsize, lindex, ic1, isr1, ic2, isr2, osr, false);
2047 }
2048 
2051  int64_t lsize,
2052  int32_t lindex,
2053  int8_t* p,
2054  int64_t psize,
2055  int32_t ic1,
2056  int32_t isr1,
2057  int32_t ic2,
2058  int32_t isr2,
2059  int32_t osr) {
2061  p, psize, l, lsize, lindex, ic2, isr2, ic1, isr1, osr, false);
2062 }
2063 
2064 //
2065 // ST_Contains
2066 //
2067 
2069 bool ST_Contains_Point_Point(int8_t* p1,
2070  int64_t p1size,
2071  int8_t* p2,
2072  int64_t p2size,
2073  int32_t ic1,
2074  int32_t isr1,
2075  int32_t ic2,
2076  int32_t isr2,
2077  int32_t osr) {
2078  double p1x = coord_x(p1, 0, ic1, isr1, osr);
2079  double p1y = coord_y(p1, 1, ic1, isr1, osr);
2080  double p2x = coord_x(p2, 0, ic2, isr2, osr);
2081  double p2y = coord_y(p2, 1, ic2, isr2, osr);
2082  double tolerance = tol(ic1, ic2);
2083  return tol_eq(p1x, p2x, tolerance) && tol_eq(p1y, p2y, tolerance);
2084 }
2085 
2088  int64_t psize,
2089  int8_t* l,
2090  int64_t lsize,
2091  double* lbounds,
2092  int64_t lbounds_size,
2093  int32_t li,
2094  int32_t ic1,
2095  int32_t isr1,
2096  int32_t ic2,
2097  int32_t isr2,
2098  int32_t osr) {
2099  double px = coord_x(p, 0, ic1, isr1, osr);
2100  double py = coord_y(p, 1, ic1, isr1, osr);
2101 
2102  if (lbounds) {
2103  if (tol_eq(px, lbounds[0]) && tol_eq(py, lbounds[1]) && tol_eq(px, lbounds[2]) &&
2104  tol_eq(py, lbounds[3])) {
2105  return true;
2106  }
2107  }
2108 
2109  auto l_num_coords = lsize / compression_unit_size(ic2);
2110  for (int i = 0; i < l_num_coords; i += 2) {
2111  double lx = coord_x(l, i, ic2, isr2, osr);
2112  double ly = coord_y(l, i + 1, ic2, isr2, osr);
2113  if (tol_eq(px, lx) && tol_eq(py, ly)) {
2114  continue;
2115  }
2116  return false;
2117  }
2118  return true;
2119 }
2120 
2123  int64_t psize,
2124  int8_t* poly_coords,
2125  int64_t poly_coords_size,
2126  int32_t* poly_ring_sizes,
2127  int64_t poly_num_rings,
2128  double* poly_bounds,
2129  int64_t poly_bounds_size,
2130  int32_t ic1,
2131  int32_t isr1,
2132  int32_t ic2,
2133  int32_t isr2,
2134  int32_t osr) {
2135  auto exterior_ring_num_coords = poly_coords_size / compression_unit_size(ic2);
2136  if (poly_num_rings > 0) {
2137  exterior_ring_num_coords = poly_ring_sizes[0] * 2;
2138  }
2139  auto exterior_ring_coords_size = exterior_ring_num_coords * compression_unit_size(ic2);
2140 
2142  psize,
2143  poly_coords,
2144  exterior_ring_coords_size,
2145  poly_bounds,
2146  poly_bounds_size,
2147  0,
2148  ic1,
2149  isr1,
2150  ic2,
2151  isr2,
2152  osr);
2153 }
2154 
2157  int64_t lsize,
2158  double* lbounds,
2159  int64_t lbounds_size,
2160  int32_t li,
2161  int8_t* p,
2162  int64_t psize,
2163  int32_t ic1,
2164  int32_t isr1,
2165  int32_t ic2,
2166  int32_t isr2,
2167  int32_t osr) {
2168  return tol_zero(
2169  ST_Distance_Point_LineString(p, psize, l, lsize, li, ic2, isr2, ic1, isr1, osr));
2170 }
2171 
2174  int64_t l1size,
2175  double* l1bounds,
2176  int64_t l1bounds_size,
2177  int32_t l1i,
2178  int8_t* l2,
2179  int64_t l2size,
2180  double* l2bounds,
2181  int64_t l2bounds_size,
2182  int32_t l2i,
2183  int32_t ic1,
2184  int32_t isr1,
2185  int32_t ic2,
2186  int32_t isr2,
2187  int32_t osr) {
2188  if (l1i != 0 || l2i != 0) {
2189  // At least one linestring is indexed, can rely on distance
2191  l1, l1size, l1i, l2, l2size, l2i, ic1, isr1, ic2, isr2, osr));
2192  }
2193 
2194  // TODO: sublinestring
2195  // For each line segment in l2 check if there is a segment in l1
2196  // that it's colinear with and both l2 vertices are on l1 segment.
2197  // Bail if any line segment deviates from the path.
2198  return false;
2199 }
2200 
2203  int64_t lsize,
2204  double* lbounds,
2205  int64_t lbounds_size,
2206  int32_t li,
2207  int8_t* poly_coords,
2208  int64_t poly_coords_size,
2209  int32_t* poly_ring_sizes,
2210  int64_t poly_num_rings,
2211  double* poly_bounds,
2212  int64_t poly_bounds_size,
2213  int32_t ic1,
2214  int32_t isr1,
2215  int32_t ic2,
2216  int32_t isr2,
2217  int32_t osr) {
2218  // TODO
2219  return false;
2220 }
2221 
2223 bool ST_Contains_Polygon_Point(int8_t* poly_coords,
2224  int64_t poly_coords_size,
2225  int32_t* poly_ring_sizes,
2226  int64_t poly_num_rings,
2227  double* poly_bounds,
2228  int64_t poly_bounds_size,
2229  int8_t* p,
2230  int64_t psize,
2231  int32_t ic1,
2232  int32_t isr1,
2233  int32_t ic2,
2234  int32_t isr2,
2235  int32_t osr) {
2236  double px = coord_x(p, 0, ic2, isr2, osr);
2237  double py = coord_y(p, 1, ic2, isr2, osr);
2238 
2239  if (poly_bounds) {
2240  if (!box_contains_point(poly_bounds, poly_bounds_size, px, py)) {
2241  return false;
2242  }
2243  }
2244 
2245  auto poly_num_coords = poly_coords_size / compression_unit_size(ic1);
2246  auto exterior_ring_num_coords = poly_num_coords;
2247  if (poly_num_rings > 0) {
2248  exterior_ring_num_coords = poly_ring_sizes[0] * 2;
2249  }
2250 
2251  auto poly = poly_coords;
2252  if (polygon_contains_point(poly, exterior_ring_num_coords, px, py, ic1, isr1, osr)) {
2253  // Inside exterior ring
2254  poly += exterior_ring_num_coords * compression_unit_size(ic1);
2255  // Check that none of the polygon's holes contain that point
2256  for (auto r = 1; r < poly_num_rings; r++) {
2257  int64_t interior_ring_num_coords = poly_ring_sizes[r] * 2;
2259  poly, interior_ring_num_coords, px, py, ic1, isr1, osr)) {
2260  return false;
2261  }
2262  poly += interior_ring_num_coords * compression_unit_size(ic1);
2263  }
2264  return true;
2265  }
2266  return false;
2267 }
2268 
2270 bool ST_Contains_Polygon_LineString(int8_t* poly_coords,
2271  int64_t poly_coords_size,
2272  int32_t* poly_ring_sizes,
2273  int64_t poly_num_rings,
2274  double* poly_bounds,
2275  int64_t poly_bounds_size,
2276  int8_t* l,
2277  int64_t lsize,
2278  double* lbounds,
2279  int64_t lbounds_size,
2280  int32_t li,
2281  int32_t ic1,
2282  int32_t isr1,
2283  int32_t ic2,
2284  int32_t isr2,
2285  int32_t osr) {
2286  if (poly_num_rings > 1) {
2287  return false; // TODO: support polygons with interior rings
2288  }
2289 
2290  auto poly_num_coords = poly_coords_size / compression_unit_size(ic1);
2291  auto lnum_coords = lsize / compression_unit_size(ic2);
2292  auto lnum_points = lnum_coords / 2;
2293  if (li != 0) {
2294  // Statically indexed linestring
2295  if (li < 0 || li > lnum_points) {
2296  li = lnum_points;
2297  }
2298  double lx = coord_x(l, 2 * (li - 1), ic2, isr2, osr);
2299  double ly = coord_y(l, 2 * (li - 1) + 1, ic2, isr2, osr);
2300 
2301  if (poly_bounds) {
2302  if (!box_contains_point(poly_bounds, poly_bounds_size, lx, ly)) {
2303  return false;
2304  }
2305  }
2306  return polygon_contains_point(poly_coords, poly_num_coords, lx, ly, ic1, isr1, osr);
2307  }
2308 
2309  // Bail out if poly bounding box doesn't contain linestring bounding box
2310  if (poly_bounds && lbounds) {
2311  if (!box_contains_box(poly_bounds, poly_bounds_size, lbounds, lbounds_size)) {
2312  return false;
2313  }
2314  }
2315 
2317  poly_coords, poly_num_coords, l, lnum_coords, ic1, isr1, ic2, isr2, osr);
2318 }
2319 
2321 bool ST_Contains_Polygon_Polygon(int8_t* poly1_coords,
2322  int64_t poly1_coords_size,
2323  int32_t* poly1_ring_sizes,
2324  int64_t poly1_num_rings,
2325  double* poly1_bounds,
2326  int64_t poly1_bounds_size,
2327  int8_t* poly2_coords,
2328  int64_t poly2_coords_size,
2329  int32_t* poly2_ring_sizes,
2330  int64_t poly2_num_rings,
2331  double* poly2_bounds,
2332  int64_t poly2_bounds_size,
2333  int32_t ic1,
2334  int32_t isr1,
2335  int32_t ic2,
2336  int32_t isr2,
2337  int32_t osr) {
2338  // TODO: needs to be extended, cover more cases
2339  // Right now only checking if simple poly1 (no holes) contains poly2's exterior shape
2340  if (poly1_num_rings > 1) {
2341  return false; // TODO: support polygons with interior rings
2342  }
2343 
2344  if (poly1_bounds && poly2_bounds) {
2345  if (!box_contains_box(
2346  poly1_bounds, poly1_bounds_size, poly2_bounds, poly2_bounds_size)) {
2347  return false;
2348  }
2349  }
2350 
2351  int64_t poly2_exterior_ring_coords_size = poly2_coords_size;
2352  if (poly2_num_rings > 0) {
2353  poly2_exterior_ring_coords_size =
2354  2 * poly2_ring_sizes[0] * compression_unit_size(ic2);
2355  }
2356  return ST_Contains_Polygon_LineString(poly1_coords,
2357  poly1_coords_size,
2358  poly1_ring_sizes,
2359  poly1_num_rings,
2360  poly1_bounds,
2361  poly1_bounds_size,
2362  poly2_coords,
2363  poly2_exterior_ring_coords_size,
2364  poly2_bounds,
2365  poly2_bounds_size,
2366  0,
2367  ic1,
2368  isr1,
2369  ic2,
2370  isr2,
2371  osr);
2372 }
2373 
2375 bool ST_Contains_MultiPolygon_Point(int8_t* mpoly_coords,
2376  int64_t mpoly_coords_size,
2377  int32_t* mpoly_ring_sizes,
2378  int64_t mpoly_num_rings,
2379  int32_t* mpoly_poly_sizes,
2380  int64_t mpoly_num_polys,
2381  double* mpoly_bounds,
2382  int64_t mpoly_bounds_size,
2383  int8_t* p,
2384  int64_t psize,
2385  int32_t ic1,
2386  int32_t isr1,
2387  int32_t ic2,
2388  int32_t isr2,
2389  int32_t osr) {
2390  if (mpoly_num_polys <= 0) {
2391  return false;
2392  }
2393 
2394  double px = coord_x(p, 0, ic2, isr2, osr);
2395  double py = coord_y(p, 1, ic2, isr2, osr);
2396 
2397  // TODO: mpoly_bounds could contain individual bounding boxes too:
2398  // first two points - box for the entire multipolygon, then a pair for each polygon
2399  if (mpoly_bounds) {
2400  if (!box_contains_point(mpoly_bounds, mpoly_bounds_size, px, py)) {
2401  return false;
2402  }
2403  }
2404 
2405  // Set specific poly pointers as we move through the coords/ringsizes/polyrings arrays.
2406  auto next_poly_coords = mpoly_coords;
2407  auto next_poly_ring_sizes = mpoly_ring_sizes;
2408 
2409  for (auto poly = 0; poly < mpoly_num_polys; poly++) {
2410  auto poly_coords = next_poly_coords;
2411  auto poly_ring_sizes = next_poly_ring_sizes;
2412  auto poly_num_rings = mpoly_poly_sizes[poly];
2413  // Count number of coords in all of poly's rings, advance ring size pointer.
2414  int32_t poly_num_coords = 0;
2415  for (auto ring = 0; ring < poly_num_rings; ring++) {
2416  poly_num_coords += 2 * *next_poly_ring_sizes++;
2417  }
2418  auto poly_coords_size = poly_num_coords * compression_unit_size(ic1);
2419  next_poly_coords += poly_coords_size;
2420  // TODO: pass individual bounding boxes for each polygon
2421  if (ST_Contains_Polygon_Point(poly_coords,
2422  poly_coords_size,
2423  poly_ring_sizes,
2424  poly_num_rings,
2425  nullptr,
2426  0,
2427  p,
2428  psize,
2429  ic1,
2430  isr1,
2431  ic2,
2432  isr2,
2433  osr)) {
2434  return true;
2435  }
2436  }
2437 
2438  return false;
2439 }
2440 
2442 bool ST_Contains_MultiPolygon_LineString(int8_t* mpoly_coords,
2443  int64_t mpoly_coords_size,
2444  int32_t* mpoly_ring_sizes,
2445  int64_t mpoly_num_rings,
2446  int32_t* mpoly_poly_sizes,
2447  int64_t mpoly_num_polys,
2448  double* mpoly_bounds,
2449  int64_t mpoly_bounds_size,
2450  int8_t* l,
2451  int64_t lsize,
2452  double* lbounds,
2453  int64_t lbounds_size,
2454  int32_t li,
2455  int32_t ic1,
2456  int32_t isr1,
2457  int32_t ic2,
2458  int32_t isr2,
2459  int32_t osr) {
2460  if (mpoly_num_polys <= 0) {
2461  return false;
2462  }
2463 
2464  auto lnum_coords = lsize / compression_unit_size(ic2);
2465  auto lnum_points = lnum_coords / 2;
2466  if (li != 0) {
2467  // Statically indexed linestring
2468  if (li < 0 || li > lnum_points) {
2469  li = lnum_points;
2470  }
2471  double lx = coord_x(l, 2 * (li - 1), ic2, isr2, osr);
2472  double ly = coord_y(l, 2 * (li - 1) + 1, ic2, isr2, osr);
2473 
2474  if (mpoly_bounds) {
2475  if (!box_contains_point(mpoly_bounds, mpoly_bounds_size, lx, ly)) {
2476  return false;
2477  }
2478  }
2479  auto p = l + li * compression_unit_size(ic2);
2480  auto psize = 2 * compression_unit_size(ic2);
2481  return ST_Contains_MultiPolygon_Point(mpoly_coords,
2482  mpoly_coords_size,
2483  mpoly_ring_sizes,
2484  mpoly_num_rings,
2485  mpoly_poly_sizes,
2486  mpoly_num_polys,
2487  mpoly_bounds,
2488  mpoly_bounds_size,
2489  p,
2490  psize,
2491  ic1,
2492  isr1,
2493  ic2,
2494  isr2,
2495  osr);
2496  }
2497 
2498  if (mpoly_bounds && lbounds) {
2499  if (!box_contains_box(mpoly_bounds, mpoly_bounds_size, lbounds, lbounds_size)) {
2500  return false;
2501  }
2502  }
2503 
2504  // Set specific poly pointers as we move through the coords/ringsizes/polyrings arrays.
2505  auto next_poly_coords = mpoly_coords;
2506  auto next_poly_ring_sizes = mpoly_ring_sizes;
2507 
2508  for (auto poly = 0; poly < mpoly_num_polys; poly++) {
2509  auto poly_coords = next_poly_coords;
2510  auto poly_ring_sizes = next_poly_ring_sizes;
2511  auto poly_num_rings = mpoly_poly_sizes[poly];
2512  // Count number of coords in all of poly's rings, advance ring size pointer.
2513  int32_t poly_num_coords = 0;
2514  for (auto ring = 0; ring < poly_num_rings; ring++) {
2515  poly_num_coords += 2 * *next_poly_ring_sizes++;
2516  }
2517  auto poly_coords_size = poly_num_coords * compression_unit_size(ic1);
2518  next_poly_coords += poly_coords_size;
2519 
2520  if (ST_Contains_Polygon_LineString(poly_coords,
2521  poly_coords_size,
2522  poly_ring_sizes,
2523  poly_num_rings,
2524  nullptr,
2525  0,
2526  l,
2527  lsize,
2528  nullptr,
2529  0,
2530  li,
2531  ic1,
2532  isr1,
2533  ic2,
2534  isr2,
2535  osr)) {
2536  return true;
2537  }
2538  }
2539 
2540  return false;
2541 }
2542 
2543 //
2544 // ST_Intersects
2545 //
2546 
2549  int64_t p1size,
2550  int8_t* p2,
2551  int64_t p2size,
2552  int32_t ic1,
2553  int32_t isr1,
2554  int32_t ic2,
2555  int32_t isr2,
2556  int32_t osr) {
2557  return tol_zero(
2558  ST_Distance_Point_Point(p1, p1size, p2, p2size, ic1, isr1, ic2, isr2, osr));
2559 }
2560 
2563  int64_t psize,
2564  int8_t* l,
2565  int64_t lsize,
2566  double* lbounds,
2567  int64_t lbounds_size,
2568  int32_t li,
2569  int32_t ic1,
2570  int32_t isr1,
2571  int32_t ic2,
2572  int32_t isr2,
2573  int32_t osr) {
2574  double px = coord_x(p, 0, ic1, isr1, osr);
2575  double py = coord_y(p, 1, ic1, isr1, osr);
2576 
2577  auto lnum_coords = lsize / compression_unit_size(ic2);
2578  auto lnum_points = lnum_coords / 2;
2579  if (li != 0) {
2580  // Statically indexed linestring
2581  if (li < 0 || li > lnum_points) {
2582  li = lnum_points;
2583  }
2584  auto p2 = l + li * compression_unit_size(ic2);
2585  auto p2size = 2 * compression_unit_size(ic2);
2586  return tol_zero(
2587  ST_Distance_Point_Point(p2, p2size, p, psize, ic2, isr2, ic1, isr1, osr));
2588  }
2589 
2590  if (lbounds) {
2591  if (!box_contains_point(lbounds, lbounds_size, px, py)) {
2592  return false;
2593  }
2594  }
2595  return tol_zero(
2596  ST_Distance_Point_LineString(p, psize, l, lsize, li, ic1, isr1, ic2, isr2, osr));
2597 }
2598 
2601  int64_t psize,
2602  int8_t* poly,
2603  int64_t polysize,
2604  int32_t* poly_ring_sizes,
2605  int64_t poly_num_rings,
2606  double* poly_bounds,
2607  int64_t poly_bounds_size,
2608  int32_t ic1,
2609  int32_t isr1,
2610  int32_t ic2,
2611  int32_t isr2,
2612  int32_t osr) {
2613  return ST_Contains_Polygon_Point(poly,
2614  polysize,
2615  poly_ring_sizes,
2616  poly_num_rings,
2617  poly_bounds,
2618  poly_bounds_size,
2619  p,
2620  psize,
2621  ic2,
2622  isr2,
2623  ic1,
2624  isr1,
2625  osr);
2626 }
2627 
2630  int64_t psize,
2631  int8_t* mpoly_coords,
2632  int64_t mpoly_coords_size,
2633  int32_t* mpoly_ring_sizes,
2634  int64_t mpoly_num_rings,
2635  int32_t* mpoly_poly_sizes,
2636  int64_t mpoly_num_polys,
2637  double* mpoly_bounds,
2638  int64_t mpoly_bounds_size,
2639  int32_t ic1,
2640  int32_t isr1,
2641  int32_t ic2,
2642  int32_t isr2,
2643  int32_t osr) {
2644  return ST_Contains_MultiPolygon_Point(mpoly_coords,
2645  mpoly_coords_size,
2646  mpoly_ring_sizes,
2647  mpoly_num_rings,
2648  mpoly_poly_sizes,
2649  mpoly_num_polys,
2650  mpoly_bounds,
2651  mpoly_bounds_size,
2652  p,
2653  psize,
2654  ic2,
2655  isr2,
2656  ic1,
2657  isr1,
2658  osr);
2659 }
2660 
2663  int64_t lsize,
2664  double* lbounds,
2665  int64_t lbounds_size,
2666  int32_t li,
2667  int8_t* p,
2668  int64_t psize,
2669  int32_t ic1,
2670  int32_t isr1,
2671  int32_t ic2,
2672  int32_t isr2,
2673  int32_t osr) {
2675  p, psize, l, lsize, lbounds, lbounds_size, li, ic2, isr2, ic1, isr1, osr);
2676 }
2677 
2680  int64_t l1size,
2681  double* l1bounds,
2682  int64_t l1bounds_size,
2683  int32_t l1i,
2684  int8_t* l2,
2685  int64_t l2size,
2686  double* l2bounds,
2687  int64_t l2bounds_size,
2688  int32_t l2i,
2689  int32_t ic1,
2690  int32_t isr1,
2691  int32_t ic2,
2692  int32_t isr2,
2693  int32_t osr) {
2694  auto l2num_coords = l2size / compression_unit_size(ic2);
2695  auto l2num_points = l2num_coords / 2;
2696  if (l2i != 0) {
2697  // Statically indexed linestring
2698  if (l2i < 0 || l2i > l2num_points) {
2699  l2i = l2num_points;
2700  }
2701  auto p2 = l2 + l2i * compression_unit_size(ic2);
2702  auto p2size = 2 * compression_unit_size(ic2);
2704  l1, l1size, l1bounds, l1bounds_size, l1i, p2, p2size, ic1, isr1, ic2, isr2, osr);
2705  }
2706  auto l1num_coords = l1size / compression_unit_size(ic1);
2707  auto l1num_points = l1num_coords / 2;
2708  if (l1i != 0) {
2709  // Statically indexed linestring
2710  if (l1i < 0 || l1i > l1num_points) {
2711  l1i = l1num_points;
2712  }
2713  auto p1 = l1 + l1i * compression_unit_size(ic1);
2714  auto p1size = 2 * compression_unit_size(ic1);
2716  l2, l2size, l2bounds, l2bounds_size, l2i, p1, p1size, ic2, isr2, ic1, isr1, osr);
2717  }
2718 
2719  if (l1bounds && l2bounds) {
2720  if (!box_overlaps_box(l1bounds, l1bounds_size, l2bounds, l2bounds_size)) {
2721  return false;
2722  }
2723  }
2724 
2726  l1, l1size, l1i, l2, l2size, l2i, ic1, isr1, ic2, isr2, osr));
2727 }
2728 
2731  int64_t lsize,
2732  double* lbounds,
2733  int64_t lbounds_size,
2734  int32_t li,
2735  int8_t* poly,
2736  int64_t polysize,
2737  int32_t* poly_ring_sizes,
2738  int64_t poly_num_rings,
2739  double* poly_bounds,
2740  int64_t poly_bounds_size,
2741  int32_t ic1,
2742  int32_t isr1,
2743  int32_t ic2,
2744  int32_t isr2,
2745  int32_t osr) {
2746  auto lnum_coords = lsize / compression_unit_size(ic1);
2747  auto lnum_points = lnum_coords / 2;
2748  if (li != 0) {
2749  // Statically indexed linestring
2750  if (li < 0 || li > lnum_points) {
2751  li = lnum_points;
2752  }
2753  auto p = l + li * compression_unit_size(ic1);
2754  auto psize = 2 * compression_unit_size(ic1);
2755  return ST_Contains_Polygon_Point(poly,
2756  polysize,
2757  poly_ring_sizes,
2758  poly_num_rings,
2759  poly_bounds,
2760  poly_bounds_size,
2761  p,
2762  psize,
2763  ic2,
2764  isr2,
2765  ic1,
2766  isr1,
2767  osr);
2768  }
2769 
2770  if (lbounds && poly_bounds) {
2771  if (!box_overlaps_box(lbounds, lbounds_size, poly_bounds, poly_bounds_size)) {
2772  return false;
2773  }
2774  }
2775 
2776  // Check for spatial intersection.
2777  // One way to do that would be to start with linestring's first point, if it's inside
2778  // the polygon - it means intersection. Otherwise follow the linestring, segment by
2779  // segment, checking for intersections with polygon rings, bail as soon as we cross into
2780  // the polygon.
2781 
2782  // Or, alternatively, just measure the distance:
2784  lsize,
2785  li,
2786  poly,
2787  polysize,
2788  poly_ring_sizes,
2789  poly_num_rings,
2790  ic1,
2791  isr1,
2792  ic2,
2793  isr2,
2794  osr));
2795 }
2796 
2799  int64_t lsize,
2800  double* lbounds,
2801  int64_t lbounds_size,
2802  int32_t li,
2803  int8_t* mpoly_coords,
2804  int64_t mpoly_coords_size,
2805  int32_t* mpoly_ring_sizes,
2806  int64_t mpoly_num_rings,
2807  int32_t* mpoly_poly_sizes,
2808  int64_t mpoly_num_polys,
2809  double* mpoly_bounds,
2810  int64_t mpoly_bounds_size,
2811  int32_t ic1,
2812  int32_t isr1,
2813  int32_t ic2,
2814  int32_t isr2,
2815  int32_t osr) {
2816  auto lnum_coords = lsize / compression_unit_size(ic1);
2817  auto lnum_points = lnum_coords / 2;
2818  if (li != 0) {
2819  // Statically indexed linestring
2820  if (li < 0 || li > lnum_points) {
2821  li = lnum_points;
2822  }
2823  auto p = l + li * compression_unit_size(ic1);
2824  auto psize = 2 * compression_unit_size(ic1);
2825  return ST_Contains_MultiPolygon_Point(mpoly_coords,
2826  mpoly_coords_size,
2827  mpoly_ring_sizes,
2828  mpoly_num_rings,
2829  mpoly_poly_sizes,
2830  mpoly_num_polys,
2831  mpoly_bounds,
2832  mpoly_bounds_size,
2833  p,
2834  psize,
2835  ic2,
2836  isr2,
2837  ic1,
2838  isr1,
2839  osr);
2840  }
2841 
2842  if (lbounds && mpoly_bounds) {
2843  if (!box_overlaps_box(lbounds, lbounds_size, mpoly_bounds, mpoly_bounds_size)) {
2844  return false;
2845  }
2846  }
2847 
2848  // Check for spatial intersection.
2849  // One way to do that would be to start with linestring's first point, if it's inside
2850  // any of the polygons - it means intersection. Otherwise follow the linestring, segment
2851  // by segment, checking for intersections with polygon shapes/holes, bail as soon as we
2852  // cross into a polygon.
2853 
2854  // Or, alternatively, just measure the distance:
2856  lsize,
2857  li,
2858  mpoly_coords,
2859  mpoly_coords_size,
2860  mpoly_ring_sizes,
2861  mpoly_num_rings,
2862  mpoly_poly_sizes,
2863  mpoly_num_polys,
2864  ic1,
2865  isr1,
2866  ic2,
2867  isr2,
2868  osr));
2869 }
2870 
2873  int64_t polysize,
2874  int32_t* poly_ring_sizes,
2875  int64_t poly_num_rings,
2876  double* poly_bounds,
2877  int64_t poly_bounds_size,
2878  int8_t* p,
2879  int64_t psize,
2880  int32_t ic1,
2881  int32_t isr1,
2882  int32_t ic2,
2883  int32_t isr2,
2884  int32_t osr) {
2885  return ST_Contains_Polygon_Point(poly,
2886  polysize,
2887  poly_ring_sizes,
2888  poly_num_rings,
2889  poly_bounds,
2890  poly_bounds_size,
2891  p,
2892  psize,
2893  ic1,
2894  isr1,
2895  ic2,
2896  isr2,
2897  osr);
2898 }
2899 
2902  int64_t polysize,
2903  int32_t* poly_ring_sizes,
2904  int64_t poly_num_rings,
2905  double* poly_bounds,
2906  int64_t poly_bounds_size,
2907  int8_t* l,
2908  int64_t lsize,
2909  double* lbounds,
2910  int64_t lbounds_size,
2911  int32_t li,
2912  int32_t ic1,
2913  int32_t isr1,
2914  int32_t ic2,
2915  int32_t isr2,
2916  int32_t osr) {
2918  lsize,
2919  lbounds,
2920  lbounds_size,
2921  li,
2922  poly,
2923  polysize,
2924  poly_ring_sizes,
2925  poly_num_rings,
2926  poly_bounds,
2927  poly_bounds_size,
2928  ic2,
2929  isr2,
2930  ic1,
2931  isr1,
2932  osr);
2933 }
2934 
2936 bool ST_Intersects_Polygon_Polygon(int8_t* poly1_coords,
2937  int64_t poly1_coords_size,
2938  int32_t* poly1_ring_sizes,
2939  int64_t poly1_num_rings,
2940  double* poly1_bounds,
2941  int64_t poly1_bounds_size,
2942  int8_t* poly2_coords,
2943  int64_t poly2_coords_size,
2944  int32_t* poly2_ring_sizes,
2945  int64_t poly2_num_rings,
2946  double* poly2_bounds,
2947  int64_t poly2_bounds_size,
2948  int32_t ic1,
2949  int32_t isr1,
2950  int32_t ic2,
2951  int32_t isr2,
2952  int32_t osr) {
2953  if (poly1_bounds && poly2_bounds) {
2954  if (!box_overlaps_box(
2955  poly1_bounds, poly1_bounds_size, poly2_bounds, poly2_bounds_size)) {
2956  return false;
2957  }
2958  }
2959 
2960  return tol_zero(ST_Distance_Polygon_Polygon(poly1_coords,
2961  poly1_coords_size,
2962  poly1_ring_sizes,
2963  poly1_num_rings,
2964  poly2_coords,
2965  poly2_coords_size,
2966  poly2_ring_sizes,
2967  poly2_num_rings,
2968  ic1,
2969  isr1,
2970  ic2,
2971  isr2,
2972  osr));
2973 }
2974 
2976 bool ST_Intersects_Polygon_MultiPolygon(int8_t* poly_coords,
2977  int64_t poly_coords_size,
2978  int32_t* poly_ring_sizes,
2979  int64_t poly_num_rings,
2980  double* poly_bounds,
2981  int64_t poly_bounds_size,
2982  int8_t* mpoly_coords,
2983  int64_t mpoly_coords_size,
2984  int32_t* mpoly_ring_sizes,
2985  int64_t mpoly_num_rings,
2986  int32_t* mpoly_poly_sizes,
2987  int64_t mpoly_num_polys,
2988  double* mpoly_bounds,
2989  int64_t mpoly_bounds_size,
2990  int32_t ic1,
2991  int32_t isr1,
2992  int32_t ic2,
2993  int32_t isr2,
2994  int32_t osr) {
2995  if (poly_bounds && mpoly_bounds) {
2996  if (!box_overlaps_box(
2997  poly_bounds, poly_bounds_size, mpoly_bounds, mpoly_bounds_size)) {
2998  return false;
2999  }
3000  }
3001 
3002  return tol_zero(ST_Distance_Polygon_MultiPolygon(poly_coords,
3003  poly_coords_size,
3004  poly_ring_sizes,
3005  poly_num_rings,
3006  mpoly_coords,
3007  mpoly_coords_size,
3008  mpoly_ring_sizes,
3009  mpoly_num_rings,
3010  mpoly_poly_sizes,
3011  mpoly_num_polys,
3012  ic1,
3013  isr1,
3014  ic2,
3015  isr2,
3016  osr));
3017 }
3018 
3020 bool ST_Intersects_MultiPolygon_Point(int8_t* mpoly_coords,
3021  int64_t mpoly_coords_size,
3022  int32_t* mpoly_ring_sizes,
3023  int64_t mpoly_num_rings,
3024  int32_t* mpoly_poly_sizes,
3025  int64_t mpoly_num_polys,
3026  double* mpoly_bounds,
3027  int64_t mpoly_bounds_size,
3028  int8_t* p,
3029  int64_t psize,
3030  int32_t ic1,
3031  int32_t isr1,
3032  int32_t ic2,
3033  int32_t isr2,
3034  int32_t osr) {
3035  return ST_Contains_MultiPolygon_Point(mpoly_coords,
3036  mpoly_coords_size,
3037  mpoly_ring_sizes,
3038  mpoly_num_rings,
3039  mpoly_poly_sizes,
3040  mpoly_num_polys,
3041  mpoly_bounds,
3042  mpoly_bounds_size,
3043  p,
3044  psize,
3045  ic1,
3046  isr1,
3047  ic2,
3048  isr2,
3049  osr);
3050 }
3051 
3053 bool ST_Intersects_MultiPolygon_LineString(int8_t* mpoly_coords,
3054  int64_t mpoly_coords_size,
3055  int32_t* mpoly_ring_sizes,
3056  int64_t mpoly_num_rings,
3057  int32_t* mpoly_poly_sizes,
3058  int64_t mpoly_num_polys,
3059  double* mpoly_bounds,
3060  int64_t mpoly_bounds_size,
3061  int8_t* l,
3062  int64_t lsize,
3063  double* lbounds,
3064  int64_t lbounds_size,
3065  int32_t li,
3066  int32_t ic1,
3067  int32_t isr1,
3068  int32_t ic2,
3069  int32_t isr2,
3070  int32_t osr) {
3072  lsize,
3073  lbounds,
3074  lbounds_size,
3075  li,
3076  mpoly_coords,
3077  mpoly_coords_size,
3078  mpoly_ring_sizes,
3079  mpoly_num_rings,
3080  mpoly_poly_sizes,
3081  mpoly_num_polys,
3082  mpoly_bounds,
3083  mpoly_bounds_size,
3084  ic2,
3085  isr2,
3086  ic1,
3087  isr1,
3088  osr);
3089 }
3090 
3092 bool ST_Intersects_MultiPolygon_Polygon(int8_t* mpoly_coords,
3093  int64_t mpoly_coords_size,
3094  int32_t* mpoly_ring_sizes,
3095  int64_t mpoly_num_rings,
3096  int32_t* mpoly_poly_sizes,
3097  int64_t mpoly_num_polys,
3098  double* mpoly_bounds,
3099  int64_t mpoly_bounds_size,
3100  int8_t* poly_coords,
3101  int64_t poly_coords_size,
3102  int32_t* poly_ring_sizes,
3103  int64_t poly_num_rings,
3104  double* poly_bounds,
3105  int64_t poly_bounds_size,
3106  int32_t ic1,
3107  int32_t isr1,
3108  int32_t ic2,
3109  int32_t isr2,
3110  int32_t osr) {
3111  return ST_Intersects_Polygon_MultiPolygon(poly_coords,
3112  poly_coords_size,
3113  poly_ring_sizes,
3114  poly_num_rings,
3115  poly_bounds,
3116  poly_bounds_size,
3117  mpoly_coords,
3118  mpoly_coords_size,
3119  mpoly_ring_sizes,
3120  mpoly_num_rings,
3121  mpoly_poly_sizes,
3122  mpoly_num_polys,
3123  mpoly_bounds,
3124  mpoly_bounds_size,
3125  ic2,
3126  isr2,
3127  ic1,
3128  isr1,
3129  osr);
3130 }
3131 
3133 bool ST_Intersects_MultiPolygon_MultiPolygon(int8_t* mpoly1_coords,
3134  int64_t mpoly1_coords_size,
3135  int32_t* mpoly1_ring_sizes,
3136  int64_t mpoly1_num_rings,
3137  int32_t* mpoly1_poly_sizes,
3138  int64_t mpoly1_num_polys,
3139  double* mpoly1_bounds,
3140  int64_t mpoly1_bounds_size,
3141  int8_t* mpoly2_coords,
3142  int64_t mpoly2_coords_size,
3143  int32_t* mpoly2_ring_sizes,
3144  int64_t mpoly2_num_rings,
3145  int32_t* mpoly2_poly_sizes,
3146  int64_t mpoly2_num_polys,
3147  double* mpoly2_bounds,
3148  int64_t mpoly2_bounds_size,
3149  int32_t ic1,
3150  int32_t isr1,
3151  int32_t ic2,
3152  int32_t isr2,
3153  int32_t osr) {
3154  if (mpoly1_bounds && mpoly2_bounds) {
3155  if (!box_overlaps_box(
3156  mpoly1_bounds, mpoly1_bounds_size, mpoly2_bounds, mpoly2_bounds_size)) {
3157  return false;
3158  }
3159  }
3160 
3161  return tol_zero(ST_Distance_MultiPolygon_MultiPolygon(mpoly1_coords,
3162  mpoly1_coords_size,
3163  mpoly1_ring_sizes,
3164  mpoly1_num_rings,
3165  mpoly1_poly_sizes,
3166  mpoly1_num_polys,
3167  mpoly2_coords,
3168  mpoly2_coords_size,
3169  mpoly2_ring_sizes,
3170  mpoly2_num_rings,
3171  mpoly2_poly_sizes,
3172  mpoly2_num_polys,
3173  ic1,
3174  isr1,
3175  ic2,
3176  isr2,
3177  osr));
3178 }
3179 
3180 //
3181 // Accessors for poly bounds and render group for in-situ poly render queries
3182 //
3183 // The MapD_* varieties are deprecated and renamed to "OmniSci_Geo*"
3184 // There may be some clients out there who are playing with the MapD_* so leaving
3185 // them for backwards compatibility.
3186 //
3187 
3189 int64_t OmniSci_Geo_PolyBoundsPtr(double* bounds, int64_t size) {
3190  return reinterpret_cast<int64_t>(bounds);
3191 }
3192 
3194 int32_t OmniSci_Geo_PolyRenderGroup(int32_t render_group) {
3195  return render_group;
3196 }
3197 
3199 int64_t MapD_GeoPolyBoundsPtr(double* bounds, int64_t size) {
3200  return OmniSci_Geo_PolyBoundsPtr(bounds, size);
3201 }
3202 
3204 int32_t MapD_GeoPolyRenderGroup(int32_t render_group) {
3205  return OmniSci_Geo_PolyRenderGroup(render_group);
3206 }
3207 
3209 double convert_meters_to_pixel_width(const double meters,
3210  int8_t* p,
3211  const int64_t psize,
3212  const int32_t ic,
3213  const int32_t isr,
3214  const int32_t osr,
3215  const double min_lon,
3216  const double max_lon,
3217  const int32_t img_width,
3218  const double min_width) {
3219  const double const1 = 0.017453292519943295769236907684886;
3220  const double const2 = 6372797.560856;
3221  const auto lon = decompress_coord(p, 0, ic, true);
3222  const auto lat = decompress_coord(p, 1, ic, false);
3223  double t1 = sinf(meters / (2.0 * const2));
3224  double t2 = cosf(const1 * lat);
3225  const double newlon = lon - (2.0 * asinf(t1 / t2)) / const1;
3226  t1 = transform_coord(lon, isr, osr, true);
3227  t2 = transform_coord(newlon, isr, osr, true);
3228  const double min_domain_x = transform_coord(min_lon, isr, osr, true);
3229  const double max_domain_x = transform_coord(max_lon, isr, osr, true);
3230  const double domain_diff = max_domain_x - min_domain_x;
3231  t1 = ((t1 - min_domain_x) / domain_diff) * static_cast<double>(img_width);
3232  t2 = ((t2 - min_domain_x) / domain_diff) * static_cast<double>(img_width);
3233 
3234  // TODO(croot): need to account for edge cases, such as getting close to the poles.
3235  const double sz = fabs(t1 - t2);
3236  return (sz < min_width ? min_width : sz);
3237 }
3238 
3240 double convert_meters_to_pixel_height(const double meters,
3241  int8_t* p,
3242  const int64_t psize,
3243  const int32_t ic,
3244  const int32_t isr,
3245  const int32_t osr,
3246  const double min_lat,
3247  const double max_lat,
3248  const int32_t img_height,
3249  const double min_height) {
3250  const double const1 = 0.017453292519943295769236907684886;
3251  const double const2 = 6372797.560856;
3252  const auto lat = decompress_coord(p, 1, ic, false);
3253  const double latdiff = meters / (const1 * const2);
3254  const double newlat =
3255  (lat < 0) ? lat + latdiff : lat - latdiff; // assumes a lat range of [-90, 90]
3256  double t1 = transform_coord(lat, isr, osr, false);
3257  double t2 = transform_coord(newlat, isr, osr, false);
3258  const double min_domain_y = transform_coord(min_lat, isr, osr, false);
3259  const double max_domain_y = transform_coord(max_lat, isr, osr, false);
3260  const double domain_diff = max_domain_y - min_domain_y;
3261  t1 = ((t1 - min_domain_y) / domain_diff) * static_cast<double>(img_height);
3262  t2 = ((t2 - min_domain_y) / domain_diff) * static_cast<double>(img_height);
3263 
3264  // TODO(croot): need to account for edge cases, such as getting close to the poles.
3265  const double sz = fabs(t1 - t2);
3266  return (sz < min_height ? min_height : sz);
3267 }
3268 
3270  const int64_t psize,
3271  const int32_t ic,
3272  const double min_lon,
3273  const double max_lon,
3274  const double min_lat,
3275  const double max_lat) {
3276  const auto lon = decompress_coord(p, 0, ic, true);
3277  const auto lat = decompress_coord(p, 1, ic, false);
3278  return !(lon < min_lon || lon > max_lon || lat < min_lat || lat > max_lat);
3279 }
3280 
3282  const int64_t psize,
3283  const int32_t ic,
3284  const double meters,
3285  const double min_lon,
3286  const double max_lon,
3287  const double min_lat,
3288  const double max_lat) {
3289  const double const1 = 0.017453292519943295769236907684886;
3290  const double const2 = 6372797.560856;
3291  const auto lon = decompress_coord(p, 0, ic, true);
3292  const auto lat = decompress_coord(p, 1, ic, false);
3293  const double latdiff = meters / (const1 * const2);
3294  const double t1 = sinf(meters / (2.0 * const2));
3295  const double t2 = cosf(const1 * lat);
3296  const double londiff = (2.0 * asinf(t1 / t2)) / const1;
3297  return !(lon + londiff < min_lon || lon - londiff > max_lon ||
3298  lat + latdiff < min_lat || lat - latdiff > max_lat);
3299 }
EXTENSION_NOINLINE double ST_Distance_LineString_LineString_Geodesic(int8_t *l1, int64_t l1size, int32_t l1index, int8_t *l2, int64_t l2size, int32_t l2index, int32_t ic1, int32_t isr1, int32_t ic2, int32_t isr2, int32_t osr)
EXTENSION_NOINLINE double convert_meters_to_pixel_width(const double meters, int8_t *p, const int64_t psize, const int32_t ic, const int32_t isr, const int32_t osr, const double min_lon, const double max_lon, const int32_t img_width, const double min_width)
DEVICE double distance_ring_ring(int8_t *ring1, int32_t ring1_num_coords, int8_t *ring2, int32_t ring2_num_coords, int32_t ic1, int32_t isr1, int32_t ic2, int32_t isr2, int32_t osr)
EXTENSION_INLINE bool ST_Intersects_Point_Polygon(int8_t *p, int64_t psize, int8_t *poly, int64_t polysize, int32_t *poly_ring_sizes, int64_t poly_num_rings, double *poly_bounds, int64_t poly_bounds_size, int32_t ic1, int32_t isr1, int32_t ic2, int32_t isr2, int32_t osr)
DEVICE ALWAYS_INLINE double coord_x(int8_t *data, int32_t index, int32_t ic, int32_t isr, int32_t osr)
DEVICE ALWAYS_INLINE double coord_y(int8_t *data, int32_t index, int32_t ic, int32_t isr, int32_t osr)
DEVICE ALWAYS_INLINE double length_linestring(int8_t *l, int64_t lsize, int32_t ic, int32_t isr, int32_t osr, bool geodesic, bool check_closed)
DEVICE ALWAYS_INLINE double transform_coord(double coord, int32_t isr, int32_t osr, bool x)
EXTENSION_NOINLINE double ST_Distance_Point_Point(int8_t *p1, int64_t p1size, int8_t *p2, int64_t p2size, int32_t ic1, int32_t isr1, int32_t ic2, int32_t isr2, int32_t osr)
#define TOLERANCE_GEOINT32
EXTENSION_NOINLINE double ST_X_Point(int8_t *p, int64_t psize, int32_t ic, int32_t isr, int32_t osr)
DEVICE ALWAYS_INLINE bool on_segment(double px, double py, double qx, double qy, double rx, double ry)
EXTENSION_INLINE double ST_Distance_MultiPolygon_Polygon(int8_t *mpoly_coords, int64_t mpoly_coords_size, int32_t *mpoly_ring_sizes, int64_t mpoly_num_rings, int32_t *mpoly_poly_sizes, int64_t mpoly_num_polys, int8_t *poly1_coords, int64_t poly1_coords_size, int32_t *poly1_ring_sizes, int64_t poly1_num_rings, int32_t ic1, int32_t isr1, int32_t ic2, int32_t isr2, int32_t osr)
EXTENSION_INLINE bool ST_Intersects_MultiPolygon_Polygon(int8_t *mpoly_coords, int64_t mpoly_coords_size, int32_t *mpoly_ring_sizes, int64_t mpoly_num_rings, int32_t *mpoly_poly_sizes, int64_t mpoly_num_polys, double *mpoly_bounds, int64_t mpoly_bounds_size, int8_t *poly_coords, int64_t poly_coords_size, int32_t *poly_ring_sizes, int64_t poly_num_rings, double *poly_bounds, int64_t poly_bounds_size, int32_t ic1, int32_t isr1, int32_t ic2, int32_t isr2, int32_t osr)
DEVICE ALWAYS_INLINE double area_polygon(int8_t *poly_coords, int64_t poly_coords_size, int32_t *poly_ring_sizes, int64_t poly_num_rings, int32_t ic, int32_t isr, int32_t osr)
EXTENSION_INLINE double ST_Distance_Polygon_LineString(int8_t *poly_coords, int64_t poly_coords_size, int32_t *poly_ring_sizes, int64_t poly_num_rings, int8_t *l, int64_t lsize, int32_t li, int32_t ic1, int32_t isr1, int32_t ic2, int32_t isr2, int32_t osr)
EXTENSION_NOINLINE bool ST_Contains_Point_Point(int8_t *p1, int64_t p1size, int8_t *p2, int64_t p2size, int32_t ic1, int32_t isr1, int32_t ic2, int32_t isr2, int32_t osr)
EXTENSION_NOINLINE double ST_Perimeter_Polygon(int8_t *poly, int64_t polysize, int32_t *poly_ring_sizes, int64_t poly_num_rings, int32_t ic, int32_t isr, int32_t osr)
EXTENSION_NOINLINE bool ST_Contains_LineString_Polygon(int8_t *l, int64_t lsize, double *lbounds, int64_t lbounds_size, int32_t li, int8_t *poly_coords, int64_t poly_coords_size, int32_t *poly_ring_sizes, int64_t poly_num_rings, double *poly_bounds, int64_t poly_bounds_size, int32_t ic1, int32_t isr1, int32_t ic2, int32_t isr2, int32_t osr)
EXTENSION_INLINE int32_t OmniSci_Geo_PolyRenderGroup(int32_t render_group)
EXTENSION_NOINLINE double ST_XMax(int8_t *coords, int64_t size, int32_t ic, int32_t isr, int32_t osr)
EXTENSION_NOINLINE double ST_Distance_Point_MultiPolygon(int8_t *p, int64_t psize, int8_t *mpoly_coords, int64_t mpoly_coords_size, int32_t *mpoly_ring_sizes, int64_t mpoly_num_rings, int32_t *mpoly_poly_sizes, int64_t mpoly_num_polys, int32_t ic1, int32_t isr1, int32_t ic2, int32_t isr2, int32_t osr)
EXTENSION_NOINLINE bool ST_Contains_Polygon_Point(int8_t *poly_coords, int64_t poly_coords_size, int32_t *poly_ring_sizes, int64_t poly_num_rings, double *poly_bounds, int64_t poly_bounds_size, int8_t *p, int64_t psize, int32_t ic1, int32_t isr1, int32_t ic2, int32_t isr2, int32_t osr)
EXTENSION_NOINLINE bool ST_Intersects_LineString_MultiPolygon(int8_t *l, int64_t lsize, double *lbounds, int64_t lbounds_size, int32_t li, int8_t *mpoly_coords, int64_t mpoly_coords_size, int32_t *mpoly_ring_sizes, int64_t mpoly_num_rings, int32_t *mpoly_poly_sizes, int64_t mpoly_num_polys, double *mpoly_bounds, int64_t mpoly_bounds_size, int32_t ic1, int32_t isr1, int32_t ic2, int32_t isr2, int32_t osr)
EXTENSION_NOINLINE bool ST_Intersects_Polygon_Polygon(int8_t *poly1_coords, int64_t poly1_coords_size, int32_t *poly1_ring_sizes, int64_t poly1_num_rings, double *poly1_bounds, int64_t poly1_bounds_size, int8_t *poly2_coords, int64_t poly2_coords_size, int32_t *poly2_ring_sizes, int64_t poly2_num_rings, double *poly2_bounds, int64_t poly2_bounds_size, int32_t ic1, int32_t isr1, int32_t ic2, int32_t isr2, int32_t osr)
EXTENSION_NOINLINE bool is_point_size_in_view(int8_t *p, const int64_t psize, const int32_t ic, const double meters, const double min_lon, const double max_lon, const double min_lat, const double max_lat)
DEVICE double distance_point_line(double px, double py, double l1x, double l1y, double l2x, double l2y)
EXTENSION_NOINLINE double ST_X_LineString(int8_t *l, int64_t lsize, int32_t lindex, int32_t ic, int32_t isr, int32_t osr)
EXTENSION_INLINE double ST_YMin_Bounds(double *bounds, int64_t size, int32_t isr, int32_t osr)
EXTENSION_NOINLINE double ST_YMax(int8_t *coords, int64_t size, int32_t ic, int32_t isr, int32_t osr)
DEVICE ALWAYS_INLINE bool tol_eq(double x, double y, double tolerance=TOLERANCE_DEFAULT)
EXTENSION_INLINE double ST_XMin_Bounds(double *bounds, int64_t size, int32_t isr, int32_t osr)
DEVICE ALWAYS_INLINE double perimeter_multipolygon(int8_t *mpoly_coords, int64_t mpoly_coords_size, int32_t *mpoly_ring_sizes, int64_t mpoly_num_rings, int32_t *mpoly_poly_sizes, int64_t mpoly_num_polys, int32_t ic, int32_t isr, int32_t osr, bool geodesic)
DEVICE ALWAYS_INLINE double max_distance_point_linestring(int8_t *p, int64_t psize, int8_t *l, int64_t lsize, int32_t lindex, int32_t ic1, int32_t isr1, int32_t ic2, int32_t isr2, int32_t osr, bool check_closed)
EXTENSION_NOINLINE double ST_Area_Polygon(int8_t *poly_coords, int64_t poly_coords_size, int32_t *poly_ring_sizes, int64_t poly_num_rings, int32_t ic, int32_t isr, int32_t osr)
EXTENSION_NOINLINE bool ST_Contains_MultiPolygon_LineString(int8_t *mpoly_coords, int64_t mpoly_coords_size, int32_t *mpoly_ring_sizes, int64_t mpoly_num_rings, int32_t *mpoly_poly_sizes, int64_t mpoly_num_polys, double *mpoly_bounds, int64_t mpoly_bounds_size, int8_t *l, int64_t lsize, double *lbounds, int64_t lbounds_size, int32_t li, int32_t ic1, int32_t isr1, int32_t ic2, int32_t isr2, int32_t osr)
DEVICE ALWAYS_INLINE double area_triangle(double x1, double y1, double x2, double y2, double x3, double y3)
EXTENSION_NOINLINE double ST_Distance_MultiPolygon_MultiPolygon(int8_t *mpoly1_coords, int64_t mpoly1_coords_size, int32_t *mpoly1_ring_sizes, int64_t mpoly1_num_rings, int32_t *mpoly1_poly_sizes, int64_t mpoly1_num_polys, int8_t *mpoly2_coords, int64_t mpoly2_coords_size, int32_t *mpoly2_ring_sizes, int64_t mpoly2_num_rings, int32_t *mpoly2_poly_sizes, int64_t mpoly2_num_polys, int32_t ic1, int32_t isr1, int32_t ic2, int32_t isr2, int32_t osr)
EXTENSION_NOINLINE double ST_XMin(int8_t *coords, int64_t size, int32_t ic, int32_t isr, int32_t osr)
EXTENSION_NOINLINE bool ST_Contains_Polygon_LineString(int8_t *poly_coords, int64_t poly_coords_size, int32_t *poly_ring_sizes, int64_t poly_num_rings, double *poly_bounds, int64_t poly_bounds_size, int8_t *l, int64_t lsize, double *lbounds, int64_t lbounds_size, int32_t li, int32_t ic1, int32_t isr1, int32_t ic2, int32_t isr2, int32_t osr)
EXTENSION_INLINE bool ST_Intersects_Polygon_Point(int8_t *poly, int64_t polysize, int32_t *poly_ring_sizes, int64_t poly_num_rings, double *poly_bounds, int64_t poly_bounds_size, int8_t *p, int64_t psize, int32_t ic1, int32_t isr1, int32_t ic2, int32_t isr2, int32_t osr)
EXTENSION_NOINLINE double ST_Distance_Polygon_MultiPolygon(int8_t *poly1_coords, int64_t poly1_coords_size, int32_t *poly1_ring_sizes, int64_t poly1_num_rings, int8_t *mpoly_coords, int64_t mpoly_coords_size, int32_t *mpoly_ring_sizes, int64_t mpoly_num_rings, int32_t *mpoly_poly_sizes, int64_t mpoly_num_polys, int32_t ic1, int32_t isr1, int32_t ic2, int32_t isr2, int32_t osr)
EXTENSION_NOINLINE double ST_Distance_Point_Point_Squared(int8_t *p1, int64_t p1size, int8_t *p2, int64_t p2size, int32_t ic1, int32_t isr1, int32_t ic2, int32_t isr2, int32_t osr)
EXTENSION_NOINLINE double ST_Distance_Point_LineString(int8_t *p, int64_t psize, int8_t *l, int64_t lsize, int32_t lindex, int32_t ic1, int32_t isr1, int32_t ic2, int32_t isr2, int32_t osr)
EXTENSION_NOINLINE double ST_Y_Point(int8_t *p, int64_t psize, int32_t ic, int32_t isr, int32_t osr)
DEVICE ALWAYS_INLINE bool tol_le(double x, double y, double tolerance=TOLERANCE_DEFAULT)
EXTENSION_NOINLINE double ST_Perimeter_MultiPolygon_Geodesic(int8_t *mpoly_coords, int64_t mpoly_coords_size, int32_t *mpoly_ring_sizes, int64_t mpoly_num_rings, int32_t *mpoly_poly_sizes, int64_t mpoly_num_polys, int32_t ic, int32_t isr, int32_t osr)
EXTENSION_NOINLINE double convert_meters_to_pixel_height(const double meters, int8_t *p, const int64_t psize, const int32_t ic, const int32_t isr, const int32_t osr, const double min_lat, const double max_lat, const int32_t img_height, const double min_height)
EXTENSION_NOINLINE double ST_Y_LineString(int8_t *l, int64_t lsize, int32_t lindex, int32_t ic, int32_t isr, int32_t osr)
DEVICE double max_distance_point_line(double px, double py, double l1x, double l1y, double l2x, double l2y)
EXTENSION_INLINE int32_t MapD_GeoPolyRenderGroup(int32_t render_group)
EXTENSION_NOINLINE bool Point_Overlaps_Box(double *bounds, int64_t bounds_size, double px, double py)
EXTENSION_INLINE int64_t OmniSci_Geo_PolyBoundsPtr(double *bounds, int64_t size)
DEVICE ALWAYS_INLINE int32_t compression_unit_size(int32_t ic)
#define DEVICE
EXTENSION_NOINLINE bool ST_Intersects_LineString_Linestring(int8_t *l1, int64_t l1size, double *l1bounds, int64_t l1bounds_size, int32_t l1i, int8_t *l2, int64_t l2size, double *l2bounds, int64_t l2bounds_size, int32_t l2i, int32_t ic1, int32_t isr1, int32_t ic2, int32_t isr2, int32_t osr)
#define EXTENSION_NOINLINE
Definition: OmniSciTypes.h:25
EXTENSION_INLINE double ST_Distance_LineString_Point(int8_t *l, int64_t lsize, int32_t lindex, int8_t *p, int64_t psize, int32_t ic1, int32_t isr1, int32_t ic2, int32_t isr2, int32_t osr)
EXTENSION_INLINE bool ST_Intersects_Polygon_LineString(int8_t *poly, int64_t polysize, int32_t *poly_ring_sizes, int64_t poly_num_rings, double *poly_bounds, int64_t poly_bounds_size, int8_t *l, int64_t lsize, double *lbounds, int64_t lbounds_size, int32_t li, int32_t ic1, int32_t isr1, int32_t ic2, int32_t isr2, int32_t osr)
#define TOLERANCE_DEFAULT
DEVICE ALWAYS_INLINE int16_t orientation(double px, double py, double qx, double qy, double rx, double ry)
EXTENSION_NOINLINE double ST_Distance_Polygon_Polygon(int8_t *poly1_coords, int64_t poly1_coords_size, int32_t *poly1_ring_sizes, int64_t poly1_num_rings, int8_t *poly2_coords, int64_t poly2_coords_size, int32_t *poly2_ring_sizes, int64_t poly2_num_rings, int32_t ic1, int32_t isr1, int32_t ic2, int32_t isr2, int32_t osr)
EXTENSION_NOINLINE double ST_YMin(int8_t *coords, int64_t size, int32_t ic, int32_t isr, int32_t osr)
EXTENSION_INLINE bool ST_Intersects_LineString_Point(int8_t *l, int64_t lsize, double *lbounds, int64_t lbounds_size, int32_t li, int8_t *p, int64_t psize, int32_t ic1, int32_t isr1, int32_t ic2, int32_t isr2, int32_t osr)
DEVICE ALWAYS_INLINE double area_ring(int8_t *ring, int64_t ringsize, int32_t ic, int32_t isr, int32_t osr)
DEVICE double distance_ring_linestring(int8_t *ring, int32_t ring_num_coords, int8_t *l, int32_t lnum_coords, int32_t ic1, int32_t isr1, int32_t ic2, int32_t isr2, int32_t osr)
EXTENSION_INLINE double ST_Area_Polygon_Geodesic(int8_t *poly_coords, int64_t poly_coords_size, int32_t *poly_ring_sizes, int64_t poly_num_rings, int32_t ic, int32_t isr, int32_t osr)
EXTENSION_NOINLINE bool ST_Intersects_LineString_Polygon(int8_t *l, int64_t lsize, double *lbounds, int64_t lbounds_size, int32_t li, int8_t *poly, int64_t polysize, int32_t *poly_ring_sizes, int64_t poly_num_rings, double *poly_bounds, int64_t poly_bounds_size, int32_t ic1, int32_t isr1, int32_t ic2, int32_t isr2, int32_t osr)
EXTENSION_INLINE double ST_Distance_MultiPolygon_LineString(int8_t *mpoly_coords, int64_t mpoly_coords_size, int32_t *mpoly_ring_sizes, int64_t mpoly_num_rings, int32_t *mpoly_poly_sizes, int64_t mpoly_num_polys, int8_t *l, int64_t lsize, int32_t lindex, int32_t ic1, int32_t isr1, int32_t ic2, int32_t isr2, int32_t osr)
DEVICE ALWAYS_INLINE bool box_overlaps_box(double *bounds1, int64_t bounds1_size, double *bounds2, int64_t bounds2_size)
EXTENSION_INLINE int64_t MapD_GeoPolyBoundsPtr(double *bounds, int64_t size)
EXTENSION_INLINE bool ST_Intersects_Point_MultiPolygon(int8_t *p, int64_t psize, int8_t *mpoly_coords, int64_t mpoly_coords_size, int32_t *mpoly_ring_sizes, int64_t mpoly_num_rings, int32_t *mpoly_poly_sizes, int64_t mpoly_num_polys, double *mpoly_bounds, int64_t mpoly_bounds_size, int32_t ic1, int32_t isr1, int32_t ic2, int32_t isr2, int32_t osr)
DEVICE bool linestring_intersects_line(int8_t *l, int32_t lnum_coords, double l1x, double l1y, double l2x, double l2y, int32_t ic1, int32_t isr1, int32_t osr)
EXTENSION_NOINLINE double ST_Distance_LineString_MultiPolygon(int8_t *l, int64_t lsize, int32_t lindex, int8_t *mpoly_coords, int64_t mpoly_coords_size, int32_t *mpoly_ring_sizes, int64_t mpoly_num_rings, int32_t *mpoly_poly_sizes, int64_t mpoly_num_polys, int32_t ic1, int32_t isr1, int32_t ic2, int32_t isr2, int32_t osr)
EXTENSION_INLINE double ST_Distance_LineString_Point_Geodesic(int8_t *l, int64_t lsize, int32_t lindex, int8_t *p, int64_t psize, int32_t ic1, int32_t isr1, int32_t ic2, int32_t isr2, int32_t osr)
DEVICE bool line_intersects_line(double l11x, double l11y, double l12x, double l12y, double l21x, double l21y, double l22x, double l22y)
EXTENSION_NOINLINE double ST_Area_MultiPolygon(int8_t *mpoly_coords, int64_t mpoly_coords_size, int32_t *mpoly_ring_sizes, int64_t mpoly_num_rings, int32_t *mpoly_poly_sizes, int64_t mpoly_num_polys, int32_t ic, int32_t isr, int32_t osr)
EXTENSION_NOINLINE bool ST_Intersects_Polygon_MultiPolygon(int8_t *poly_coords, int64_t poly_coords_size, int32_t *poly_ring_sizes, int64_t poly_num_rings, double *poly_bounds, int64_t poly_bounds_size, int8_t *mpoly_coords, int64_t mpoly_coords_size, int32_t *mpoly_ring_sizes, int64_t mpoly_num_rings, int32_t *mpoly_poly_sizes, int64_t mpoly_num_polys, double *mpoly_bounds, int64_t mpoly_bounds_size, int32_t ic1, int32_t isr1, int32_t ic2, int32_t isr2, int32_t osr)
DEVICE ALWAYS_INLINE bool box_contains_point(double *bounds, int64_t bounds_size, double px, double py)
DEVICE bool polygon_contains_point(int8_t *poly, int32_t poly_num_coords, double px, double py, int32_t ic1, int32_t isr1, int32_t osr)
EXTENSION_NOINLINE bool is_point_in_view(int8_t *p, const int64_t psize, const int32_t ic, const double min_lon, const double max_lon, const double min_lat, const double max_lat)
EXTENSION_INLINE double ST_Distance_MultiPolygon_Point(int8_t *mpoly_coords, int64_t mpoly_coords_size, int32_t *mpoly_ring_sizes, int64_t mpoly_num_rings, int32_t *mpoly_poly_sizes, int64_t mpoly_num_polys, int8_t *p, int64_t psize, int32_t ic1, int32_t isr1, int32_t ic2, int32_t isr2, int32_t osr)
EXTENSION_INLINE bool ST_Contains_LineString_Point(int8_t *l, int64_t lsize, double *lbounds, int64_t lbounds_size, int32_t li, int8_t *p, int64_t psize, int32_t ic1, int32_t isr1, int32_t ic2, int32_t isr2, int32_t osr)
EXTENSION_NOINLINE bool ST_Contains_LineString_LineString(int8_t *l1, int64_t l1size, double *l1bounds, int64_t l1bounds_size, int32_t l1i, int8_t *l2, int64_t l2size, double *l2bounds, int64_t l2bounds_size, int32_t l2i, int32_t ic1, int32_t isr1, int32_t ic2, int32_t isr2, int32_t osr)
DEVICE ALWAYS_INLINE bool tol_zero(double x, double tolerance=TOLERANCE_DEFAULT)
DEVICE double decompress_lattitude_coord_geoint32(const int32_t compressed)
EXTENSION_NOINLINE double ST_Distance_Point_ClosedLineString(int8_t *p, int64_t psize, int8_t *l, int64_t lsize, int32_t lindex, int32_t ic1, int32_t isr1, int32_t ic2, int32_t isr2, int32_t osr)
EXTENSION_NOINLINE double ST_Distance_Point_Polygon(int8_t *p, int64_t psize, int8_t *poly, int64_t polysize, int32_t *poly_ring_sizes, int64_t poly_num_rings, int32_t ic1, int32_t isr1, int32_t ic2, int32_t isr2, int32_t osr)
EXTENSION_NOINLINE bool ST_Contains_Point_Polygon(int8_t *p, int64_t psize, int8_t *poly_coords, int64_t poly_coords_size, int32_t *poly_ring_sizes, int64_t poly_num_rings, double *poly_bounds, int64_t poly_bounds_size, int32_t ic1, int32_t isr1, int32_t ic2, int32_t isr2, int32_t osr)
EXTENSION_NOINLINE double ST_Distance_Point_Point_Geodesic(int8_t *p1, int64_t p1size, int8_t *p2, int64_t p2size, int32_t ic1, int32_t isr1, int32_t ic2, int32_t isr2, int32_t osr)
EXTENSION_NOINLINE double ST_MaxDistance_Point_LineString(int8_t *p, int64_t psize, int8_t *l, int64_t lsize, int32_t lindex, int32_t ic1, int32_t isr1, int32_t ic2, int32_t isr2, int32_t osr)
EXTENSION_NOINLINE double ST_Length_LineString(int8_t *coords, int64_t coords_sz, int32_t ic, int32_t isr, int32_t osr)
EXTENSION_NOINLINE double ST_Perimeter_MultiPolygon(int8_t *mpoly_coords, int64_t mpoly_coords_size, int32_t *mpoly_ring_sizes, int64_t mpoly_num_rings, int32_t *mpoly_poly_sizes, int64_t mpoly_num_polys, int32_t ic, int32_t isr, int32_t osr)
EXTENSION_INLINE bool ST_Intersects_Point_Point(int8_t *p1, int64_t p1size, int8_t *p2, int64_t p2size, int32_t ic1, int32_t isr1, int32_t ic2, int32_t isr2, int32_t osr)
EXTENSION_INLINE double ST_Distance_Polygon_Point(int8_t *poly_coords, int64_t poly_coords_size, int32_t *poly_ring_sizes, int64_t poly_num_rings, int8_t *p, int64_t psize, int32_t ic1, int32_t isr1, int32_t ic2, int32_t isr2, int32_t osr)
EXTENSION_INLINE double ST_Area_MultiPolygon_Geodesic(int8_t *mpoly_coords, int64_t mpoly_coords_size, int32_t *mpoly_ring_sizes, int64_t mpoly_num_rings, int32_t *mpoly_poly_sizes, int64_t mpoly_num_polys, int32_t ic, int32_t isr, int32_t osr)
EXTENSION_INLINE int32_t ST_NRings(int32_t *poly_ring_sizes, int64_t poly_num_rings)
EXTENSION_NOINLINE double ST_Perimeter_Polygon_Geodesic(int8_t *poly, int64_t polysize, int32_t *poly_ring_sizes, int64_t poly_num_rings, int32_t ic, int32_t isr, int32_t osr)
DEVICE ALWAYS_INLINE double distance_point_point_squared(double p1x, double p1y, double p2x, double p2y)
DEVICE bool linestring_intersects_linestring(int8_t *l, int32_t lnum_coords, double l1x, double l1y, double l2x, double l2y, int32_t ic1, int32_t isr1, int32_t osr)
EXTENSION_INLINE bool ST_Intersects_MultiPolygon_MultiPolygon(int8_t *mpoly1_coords, int64_t mpoly1_coords_size, int32_t *mpoly1_ring_sizes, int64_t mpoly1_num_rings, int32_t *mpoly1_poly_sizes, int64_t mpoly1_num_polys, double *mpoly1_bounds, int64_t mpoly1_bounds_size, int8_t *mpoly2_coords, int64_t mpoly2_coords_size, int32_t *mpoly2_ring_sizes, int64_t mpoly2_num_rings, int32_t *mpoly2_poly_sizes, int64_t mpoly2_num_polys, double *mpoly2_bounds, int64_t mpoly2_bounds_size, int32_t ic1, int32_t isr1, int32_t ic2, int32_t isr2, int32_t osr)
#define COMPRESSION_GEOINT32
EXTENSION_NOINLINE double distance_in_meters(const double fromlon, const double fromlat, const double tolon, const double tolat)
Computes the distance, in meters, between two WGS-84 positions.
EXTENSION_NOINLINE double ST_Length_LineString_Geodesic(int8_t *coords, int64_t coords_sz, int32_t ic, int32_t isr, int32_t osr)
EXTENSION_NOINLINE double ST_Distance_Point_LineString_Geodesic(int8_t *p, int64_t psize, int8_t *l, int64_t lsize, int32_t lindex, int32_t ic1, int32_t isr1, int32_t ic2, int32_t isr2, int32_t osr)
#define EXTENSION_INLINE
Definition: OmniSciTypes.h:24
EXTENSION_NOINLINE bool ST_Contains_Polygon_Polygon(int8_t *poly1_coords, int64_t poly1_coords_size, int32_t *poly1_ring_sizes, int64_t poly1_num_rings, double *poly1_bounds, int64_t poly1_bounds_size, int8_t *poly2_coords, int64_t poly2_coords_size, int32_t *poly2_ring_sizes, int64_t poly2_num_rings, double *poly2_bounds, int64_t poly2_bounds_size, int32_t ic1, int32_t isr1, int32_t ic2, int32_t isr2, int32_t osr)
DEVICE ALWAYS_INLINE bool tol_ge(double x, double y, double tolerance=TOLERANCE_DEFAULT)
DEVICE double decompress_longitude_coord_geoint32(const int32_t compressed)
EXTENSION_NOINLINE double ST_Distance_LineString_Polygon(int8_t *l, int64_t lsize, int32_t lindex, int8_t *poly_coords, int64_t poly_coords_size, int32_t *poly_ring_sizes, int64_t poly_num_rings, int32_t ic1, int32_t isr1, int32_t ic2, int32_t isr2, int32_t osr)
EXTENSION_NOINLINE double ST_MaxDistance_LineString_Point(int8_t *l, int64_t lsize, int32_t lindex, int8_t *p, int64_t psize, int32_t ic1, int32_t isr1, int32_t ic2, int32_t isr2, int32_t osr)
DEVICE ALWAYS_INLINE double tol(int32_t ic)
DEVICE double distance_line_line(double l11x, double l11y, double l12x, double l12y, double l21x, double l21y, double l22x, double l22y)
DEVICE bool polygon_contains_linestring(int8_t *poly, int32_t poly_num_coords, int8_t *l, int64_t lnum_coords, int32_t ic1, int32_t isr1, int32_t ic2, int32_t isr2, int32_t osr)
EXTENSION_NOINLINE bool ST_Contains_MultiPolygon_Point(int8_t *mpoly_coords, int64_t mpoly_coords_size, int32_t *mpoly_ring_sizes, int64_t mpoly_num_rings, int32_t *mpoly_poly_sizes, int64_t mpoly_num_polys, double *mpoly_bounds, int64_t mpoly_bounds_size, int8_t *p, int64_t psize, int32_t ic1, int32_t isr1, int32_t ic2, int32_t isr2, int32_t osr)
EXTENSION_INLINE bool ST_Intersects_MultiPolygon_Point(int8_t *mpoly_coords, int64_t mpoly_coords_size, int32_t *mpoly_ring_sizes, int64_t mpoly_num_rings, int32_t *mpoly_poly_sizes, int64_t mpoly_num_polys, double *mpoly_bounds, int64_t mpoly_bounds_size, int8_t *p, int64_t psize, int32_t ic1, int32_t isr1, int32_t ic2, int32_t isr2, int32_t osr)
DEVICE bool ring_intersects_line(int8_t *ring, int32_t ring_num_coords, double l1x, double l1y, double l2x, double l2y, int32_t ic1, int32_t isr1, int32_t osr)
#define ALWAYS_INLINE
EXTENSION_INLINE bool ST_Intersects_MultiPolygon_LineString(int8_t *mpoly_coords, int64_t mpoly_coords_size, int32_t *mpoly_ring_sizes, int64_t mpoly_num_rings, int32_t *mpoly_poly_sizes, int64_t mpoly_num_polys, double *mpoly_bounds, int64_t mpoly_bounds_size, int8_t *l, int64_t lsize, double *lbounds, int64_t lbounds_size, int32_t li, int32_t ic1, int32_t isr1, int32_t ic2, int32_t isr2, int32_t osr)
EXTENSION_INLINE int32_t ST_NPoints(int8_t *coords, int64_t coords_sz, int32_t ic)
EXTENSION_NOINLINE double ST_Distance_LineString_LineString(int8_t *l1, int64_t l1size, int32_t l1index, int8_t *l2, int64_t l2size, int32_t l2index, int32_t ic1, int32_t isr1, int32_t ic2, int32_t isr2, int32_t osr)
EXTENSION_NOINLINE double conv_4326_900913_y(const double y)
DEVICE ALWAYS_INLINE double decompress_coord(int8_t *data, int32_t index, int32_t ic, bool x)
EXTENSION_NOINLINE double conv_4326_900913_x(const double x)
DEVICE ALWAYS_INLINE bool box_contains_box_vertex(double *bounds1, int64_t bounds1_size, double *bounds2, int64_t bounds2_size)
DEVICE ALWAYS_INLINE bool box_contains_box(double *bounds1, int64_t bounds1_size, double *bounds2, int64_t bounds2_size)
EXTENSION_INLINE double ST_YMax_Bounds(double *bounds, int64_t size, int32_t isr, int32_t osr)
EXTENSION_INLINE double ST_XMax_Bounds(double *bounds, int64_t size, int32_t isr, int32_t osr)
EXTENSION_NOINLINE bool ST_Contains_Point_LineString(int8_t *p, int64_t psize, int8_t *l, int64_t lsize, double *lbounds, int64_t lbounds_size, int32_t li, int32_t ic1, int32_t isr1, int32_t ic2, int32_t isr2, int32_t osr)
DEVICE ALWAYS_INLINE double distance_point_linestring(int8_t *p, int64_t psize, int8_t *l, int64_t lsize, int32_t lindex, int32_t ic1, int32_t isr1, int32_t ic2, int32_t isr2, int32_t osr, bool check_closed)
EXTENSION_NOINLINE bool ST_Intersects_Point_LineString(int8_t *p, int64_t psize, int8_t *l, int64_t lsize, double *lbounds, int64_t lbounds_size, int32_t li, int32_t ic1, int32_t isr1, int32_t ic2, int32_t isr2, int32_t osr)
DEVICE ALWAYS_INLINE double distance_point_point(double p1x, double p1y, double p2x, double p2y)