1 | /*------------------------------------------------------------------------- |
2 | * |
3 | * spgproc.c |
4 | * Common supporting procedures for SP-GiST opclasses. |
5 | * |
6 | * |
7 | * Portions Copyright (c) 1996-2019, PostgreSQL Global Development Group |
8 | * Portions Copyright (c) 1994, Regents of the University of California |
9 | * |
10 | * IDENTIFICATION |
11 | * src/backend/access/spgist/spgproc.c |
12 | * |
13 | *------------------------------------------------------------------------- |
14 | */ |
15 | |
16 | #include "postgres.h" |
17 | |
18 | #include <math.h> |
19 | |
20 | #include "access/spgist_private.h" |
21 | #include "utils/builtins.h" |
22 | #include "utils/float.h" |
23 | #include "utils/geo_decls.h" |
24 | |
25 | #define point_point_distance(p1,p2) \ |
26 | DatumGetFloat8(DirectFunctionCall2(point_distance, \ |
27 | PointPGetDatum(p1), PointPGetDatum(p2))) |
28 | |
29 | /* Point-box distance in the assumption that box is aligned by axis */ |
30 | static double |
31 | point_box_distance(Point *point, BOX *box) |
32 | { |
33 | double dx, |
34 | dy; |
35 | |
36 | if (isnan(point->x) || isnan(box->low.x) || |
37 | isnan(point->y) || isnan(box->low.y)) |
38 | return get_float8_nan(); |
39 | |
40 | if (point->x < box->low.x) |
41 | dx = box->low.x - point->x; |
42 | else if (point->x > box->high.x) |
43 | dx = point->x - box->high.x; |
44 | else |
45 | dx = 0.0; |
46 | |
47 | if (point->y < box->low.y) |
48 | dy = box->low.y - point->y; |
49 | else if (point->y > box->high.y) |
50 | dy = point->y - box->high.y; |
51 | else |
52 | dy = 0.0; |
53 | |
54 | return HYPOT(dx, dy); |
55 | } |
56 | |
57 | /* |
58 | * Returns distances from given key to array of ordering scan keys. Leaf key |
59 | * is expected to be point, non-leaf key is expected to be box. Scan key |
60 | * arguments are expected to be points. |
61 | */ |
62 | double * |
63 | spg_key_orderbys_distances(Datum key, bool isLeaf, |
64 | ScanKey orderbys, int norderbys) |
65 | { |
66 | int sk_num; |
67 | double *distances = (double *) palloc(norderbys * sizeof(double)), |
68 | *distance = distances; |
69 | |
70 | for (sk_num = 0; sk_num < norderbys; ++sk_num, ++orderbys, ++distance) |
71 | { |
72 | Point *point = DatumGetPointP(orderbys->sk_argument); |
73 | |
74 | *distance = isLeaf ? point_point_distance(point, DatumGetPointP(key)) |
75 | : point_box_distance(point, DatumGetBoxP(key)); |
76 | } |
77 | |
78 | return distances; |
79 | } |
80 | |
81 | BOX * |
82 | box_copy(BOX *orig) |
83 | { |
84 | BOX *result = palloc(sizeof(BOX)); |
85 | |
86 | *result = *orig; |
87 | return result; |
88 | } |
89 | |