Line data Source code
1 : /*------------------------------------------------------------------------- 2 : * 3 : * spgproc.c 4 : * Common supporting procedures for SP-GiST opclasses. 5 : * 6 : * 7 : * Portions Copyright (c) 1996-2024, 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/float.h" 22 : #include "utils/fmgrprotos.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 94152 : point_box_distance(Point *point, BOX *box) 32 : { 33 : double dx, 34 : dy; 35 : 36 94152 : if (isnan(point->x) || isnan(box->low.x) || 37 94152 : isnan(point->y) || isnan(box->low.y)) 38 0 : return get_float8_nan(); 39 : 40 94152 : if (point->x < box->low.x) 41 85700 : dx = box->low.x - point->x; 42 8452 : else if (point->x > box->high.x) 43 6660 : dx = point->x - box->high.x; 44 : else 45 1792 : dx = 0.0; 46 : 47 94152 : if (point->y < box->low.y) 48 45296 : dy = box->low.y - point->y; 49 48856 : else if (point->y > box->high.y) 50 47724 : dy = point->y - box->high.y; 51 : else 52 1132 : dy = 0.0; 53 : 54 94152 : 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 373324 : spg_key_orderbys_distances(Datum key, bool isLeaf, 64 : ScanKey orderbys, int norderbys) 65 : { 66 : int sk_num; 67 373324 : double *distances = (double *) palloc(norderbys * sizeof(double)), 68 373324 : *distance = distances; 69 : 70 748556 : for (sk_num = 0; sk_num < norderbys; ++sk_num, ++orderbys, ++distance) 71 : { 72 375232 : Point *point = DatumGetPointP(orderbys->sk_argument); 73 : 74 375232 : *distance = isLeaf ? point_point_distance(point, DatumGetPointP(key)) 75 375232 : : point_box_distance(point, DatumGetBoxP(key)); 76 : } 77 : 78 373324 : return distances; 79 : } 80 : 81 : BOX * 82 4050 : box_copy(BOX *orig) 83 : { 84 4050 : BOX *result = palloc(sizeof(BOX)); 85 : 86 4050 : *result = *orig; 87 4050 : return result; 88 : }