TLA Line data Source code
1 : /*-------------------------------------------------------------------------
2 : *
3 : * spgproc.c
4 : * Common supporting procedures for SP-GiST opclasses.
5 : *
6 : *
7 : * Portions Copyright (c) 1996-2023, 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 CBC 47052 : point_box_distance(Point *point, BOX *box)
32 : {
33 : double dx,
34 : dy;
35 :
36 47052 : if (isnan(point->x) || isnan(box->low.x) ||
37 47052 : isnan(point->y) || isnan(box->low.y))
38 UBC 0 : return get_float8_nan();
39 :
40 CBC 47052 : if (point->x < box->low.x)
41 42834 : dx = box->low.x - point->x;
42 4218 : else if (point->x > box->high.x)
43 3330 : dx = point->x - box->high.x;
44 : else
45 888 : dx = 0.0;
46 :
47 47052 : if (point->y < box->low.y)
48 22632 : dy = box->low.y - point->y;
49 24420 : else if (point->y > box->high.y)
50 23862 : dy = point->y - box->high.y;
51 : else
52 558 : dy = 0.0;
53 :
54 47052 : 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 186636 : spg_key_orderbys_distances(Datum key, bool isLeaf,
64 : ScanKey orderbys, int norderbys)
65 : {
66 : int sk_num;
67 186636 : double *distances = (double *) palloc(norderbys * sizeof(double)),
68 186636 : *distance = distances;
69 :
70 374226 : for (sk_num = 0; sk_num < norderbys; ++sk_num, ++orderbys, ++distance)
71 : {
72 187590 : Point *point = DatumGetPointP(orderbys->sk_argument);
73 :
74 187590 : *distance = isLeaf ? point_point_distance(point, DatumGetPointP(key))
75 187590 : : point_box_distance(point, DatumGetBoxP(key));
76 : }
77 :
78 186636 : return distances;
79 : }
80 :
81 : BOX *
82 2001 : box_copy(BOX *orig)
83 : {
84 2001 : BOX *result = palloc(sizeof(BOX));
85 :
86 2001 : *result = *orig;
87 2001 : return result;
88 : }
|