PostGIS  2.2.7dev-r@@SVN_REVISION@@
geography_btree.c
Go to the documentation of this file.
1 /**********************************************************************
2  *
3  * PostGIS - Spatial Types for PostgreSQL
4  * Copyright 2009 Paul Ramsey <pramsey@cleverelephant.ca>
5  *
6  * This is free software; you can redistribute and/or modify it under
7  * the terms of the GNU General Public Licence. See the COPYING file.
8  *
9  **********************************************************************/
10 
11 #include "postgres.h"
12 #include "access/hash.h"
13 
14 #include "../postgis_config.h"
15 
16 #include "liblwgeom.h" /* For standard geometry types. */
17 #include "liblwgeom_internal.h" /* For FP comparators. */
18 #include "lwgeom_pg.h" /* For debugging macros. */
19 #include "gserialized_gist.h"
20 #include "geography.h" /* For utility functions. */
21 
22 Datum geography_lt(PG_FUNCTION_ARGS);
23 Datum geography_le(PG_FUNCTION_ARGS);
24 Datum geography_eq(PG_FUNCTION_ARGS);
25 Datum geography_ge(PG_FUNCTION_ARGS);
26 Datum geography_gt(PG_FUNCTION_ARGS);
27 Datum geography_cmp(PG_FUNCTION_ARGS);
28 
29 
30 /*
31 ** Utility function to return the center point of a
32 ** geocentric bounding box. We don't divide by two
33 ** because we're only using the values for comparison.
34 */
35 static void geography_gidx_center(GIDX *gidx, POINT3D *p)
36 {
37  p->x = GIDX_GET_MIN(gidx, 0) + GIDX_GET_MAX(gidx, 0);
38  p->y = GIDX_GET_MIN(gidx, 1) + GIDX_GET_MAX(gidx, 1);
39  p->z = GIDX_GET_MIN(gidx, 2) + GIDX_GET_MAX(gidx, 2);
40 }
41 
42 /*
43 ** BTree support function. Based on two geographies return true if
44 ** they are "less than" and false otherwise.
45 */
47 Datum geography_lt(PG_FUNCTION_ARGS)
48 {
49  /* Put aside some stack memory and use it for GIDX pointers. */
50  char gboxmem1[GIDX_MAX_SIZE];
51  char gboxmem2[GIDX_MAX_SIZE];
52  GIDX *gbox1 = (GIDX*)gboxmem1;
53  GIDX *gbox2 = (GIDX*)gboxmem2;
54  POINT3D p1, p2;
55 
56  /* Must be able to build box for each argument (ie, not empty geometry) */
57  if ( ! gserialized_datum_get_gidx_p(PG_GETARG_DATUM(0), gbox1) ||
58  ! gserialized_datum_get_gidx_p(PG_GETARG_DATUM(1), gbox2) )
59  {
60  PG_RETURN_BOOL(FALSE);
61  }
62 
63  geography_gidx_center(gbox1, &p1);
64  geography_gidx_center(gbox2, &p2);
65 
66  if ( p1.x < p2.x || p1.y < p2.y || p1.z < p2.z )
67  PG_RETURN_BOOL(TRUE);
68 
69  PG_RETURN_BOOL(FALSE);
70 }
71 
72 /*
73 ** BTree support function. Based on two geographies return true if
74 ** they are "less than or equal" and false otherwise.
75 */
77 Datum geography_le(PG_FUNCTION_ARGS)
78 {
79  /* Put aside some stack memory and use it for GIDX pointers. */
80  char gboxmem1[GIDX_MAX_SIZE];
81  char gboxmem2[GIDX_MAX_SIZE];
82  GIDX *gbox1 = (GIDX*)gboxmem1;
83  GIDX *gbox2 = (GIDX*)gboxmem2;
84  POINT3D p1, p2;
85 
86  /* Must be able to build box for each argument (ie, not empty geometry) */
87  if ( ! gserialized_datum_get_gidx_p(PG_GETARG_DATUM(0), gbox1) ||
88  ! gserialized_datum_get_gidx_p(PG_GETARG_DATUM(1), gbox2) )
89  {
90  PG_RETURN_BOOL(FALSE);
91  }
92 
93  geography_gidx_center(gbox1, &p1);
94  geography_gidx_center(gbox2, &p2);
95 
96  if ( p1.x <= p2.x || p1.y <= p2.y || p1.z <= p2.z )
97  PG_RETURN_BOOL(TRUE);
98 
99  PG_RETURN_BOOL(FALSE);
100 }
101 
102 /*
103 ** BTree support function. Based on two geographies return true if
104 ** they are "greater than" and false otherwise.
105 */
107 Datum geography_gt(PG_FUNCTION_ARGS)
108 {
109  /* Put aside some stack memory and use it for GIDX pointers. */
110  char gboxmem1[GIDX_MAX_SIZE];
111  char gboxmem2[GIDX_MAX_SIZE];
112  GIDX *gbox1 = (GIDX*)gboxmem1;
113  GIDX *gbox2 = (GIDX*)gboxmem2;
114  POINT3D p1, p2;
115 
116  /* Must be able to build box for each argument (ie, not empty geometry) */
117  if ( ! gserialized_datum_get_gidx_p(PG_GETARG_DATUM(0), gbox1) ||
118  ! gserialized_datum_get_gidx_p(PG_GETARG_DATUM(1), gbox2) )
119  {
120  PG_RETURN_BOOL(FALSE);
121  }
122 
123  geography_gidx_center(gbox1, &p1);
124  geography_gidx_center(gbox2, &p2);
125 
126  if ( p1.x > p2.x && p1.y > p2.y && p1.z > p2.z )
127  PG_RETURN_BOOL(TRUE);
128 
129  PG_RETURN_BOOL(FALSE);
130 }
131 
132 /*
133 ** BTree support function. Based on two geographies return true if
134 ** they are "greater than or equal" and false otherwise.
135 */
137 Datum geography_ge(PG_FUNCTION_ARGS)
138 {
139  /* Put aside some stack memory and use it for GIDX pointers. */
140  char gboxmem1[GIDX_MAX_SIZE];
141  char gboxmem2[GIDX_MAX_SIZE];
142  GIDX *gbox1 = (GIDX*)gboxmem1;
143  GIDX *gbox2 = (GIDX*)gboxmem2;
144  POINT3D p1, p2;
145 
146  /* Must be able to build box for each argument (ie, not empty geometry) */
147  if ( ! gserialized_datum_get_gidx_p(PG_GETARG_DATUM(0), gbox1) ||
148  ! gserialized_datum_get_gidx_p(PG_GETARG_DATUM(1), gbox2) )
149  {
150  PG_RETURN_BOOL(FALSE);
151  }
152 
153  geography_gidx_center(gbox1, &p1);
154  geography_gidx_center(gbox2, &p2);
155 
156  if ( p1.x >= p2.x && p1.y >= p2.y && p1.z >= p2.z )
157  PG_RETURN_BOOL(TRUE);
158 
159  PG_RETURN_BOOL(FALSE);
160 }
161 
162 
163 #if 0
164 /*
165 ** Calculate a hash code based on the geometry data alone
166 */
167 static uint32 geography_hash(GSERIALIZED *g)
168 {
169  return DatumGetUInt32(hash_any((void*)g, VARSIZE(g)));
170 }
171 /*
172 ** BTree support function. Based on two geographies return true if
173 ** they are "equal" and false otherwise. This version uses a hash
174 ** function to try and shoot for a more exact equality test.
175 */
177 Datum geography_eq(PG_FUNCTION_ARGS)
178 {
179  /* Perfect equals test based on hash */
180  GSERIALIZED *g1 = PG_GETARG_GSERIALIZED_P(0);
181  GSERIALIZED *g2 = PG_GETARG_GSERIALIZED_P(1);
182 
183  uint32 h1 = geography_hash(g1);
184  uint32 h2 = geography_hash(g2);
185 
186  PG_FREE_IF_COPY(g1,0);
187  PG_FREE_IF_COPY(g2,0);
188 
189  if ( h1 == h2 )
190  PG_RETURN_BOOL(TRUE);
191 
192  PG_RETURN_BOOL(FALSE);
193 }
194 #endif
195 
196 /*
197 ** BTree support function. Based on two geographies return true if
198 ** they are "equal" and false otherwise.
199 */
201 Datum geography_eq(PG_FUNCTION_ARGS)
202 {
203  /* Put aside some stack memory and use it for GIDX pointers. */
204  char gboxmem1[GIDX_MAX_SIZE];
205  char gboxmem2[GIDX_MAX_SIZE];
206  GIDX *gbox1 = (GIDX*)gboxmem1;
207  GIDX *gbox2 = (GIDX*)gboxmem2;
208  POINT3D p1, p2;
209 
210  /* Must be able to build box for each argument (ie, not empty geometry) */
211  if ( ! gserialized_datum_get_gidx_p(PG_GETARG_DATUM(0), gbox1) ||
212  ! gserialized_datum_get_gidx_p(PG_GETARG_DATUM(1), gbox2) )
213  {
214  PG_RETURN_BOOL(FALSE);
215  }
216 
217  geography_gidx_center(gbox1, &p1);
218  geography_gidx_center(gbox2, &p2);
219 
220  if ( FP_EQUALS(p1.x, p2.x) && FP_EQUALS(p1.y, p2.y) && FP_EQUALS(p1.z, p2.z) )
221  PG_RETURN_BOOL(TRUE);
222 
223  PG_RETURN_BOOL(FALSE);
224 
225 }
226 
227 /*
228 ** BTree support function. Based on two geographies return true if
229 ** they are "equal" and false otherwise.
230 */
232 Datum geography_cmp(PG_FUNCTION_ARGS)
233 {
234  /* Put aside some stack memory and use it for GIDX pointers. */
235  char gboxmem1[GIDX_MAX_SIZE];
236  char gboxmem2[GIDX_MAX_SIZE];
237  GIDX *gbox1 = (GIDX*)gboxmem1;
238  GIDX *gbox2 = (GIDX*)gboxmem2;
239  POINT3D p1, p2;
240 
241  /* Must be able to build box for each argument (ie, not empty geometry) */
242  if ( ! gserialized_datum_get_gidx_p(PG_GETARG_DATUM(0), gbox1) ||
243  ! gserialized_datum_get_gidx_p(PG_GETARG_DATUM(1), gbox2) )
244  {
245  PG_RETURN_BOOL(FALSE);
246  }
247 
248  geography_gidx_center(gbox1, &p1);
249  geography_gidx_center(gbox2, &p2);
250 
251  if ( ! FP_EQUALS(p1.x, p2.x) )
252  {
253  if (p1.x < p2.x)
254  {
255  PG_RETURN_INT32(-1);
256  }
257  PG_RETURN_INT32(1);
258  }
259 
260  if ( ! FP_EQUALS(p1.y, p2.y) )
261  {
262  if (p1.y < p2.y)
263  {
264  PG_RETURN_INT32(-1);
265  }
266  PG_RETURN_INT32(1);
267  }
268 
269  if ( ! FP_EQUALS(p1.z, p2.z) )
270  {
271  if (p1.z < p2.z)
272  {
273  PG_RETURN_INT32(-1);
274  }
275  PG_RETURN_INT32(1);
276  }
277 
278  PG_RETURN_INT32(0);
279 }
280 
double y
Definition: liblwgeom.h:324
Datum geography_eq(PG_FUNCTION_ARGS)
Datum geography_gt(PG_FUNCTION_ARGS)
double x
Definition: liblwgeom.h:324
Datum geography_le(PG_FUNCTION_ARGS)
double z
Definition: liblwgeom.h:324
Datum geography_ge(PG_FUNCTION_ARGS)
PG_FUNCTION_INFO_V1(geography_lt)
Datum geography_lt(PG_FUNCTION_ARGS)
static void geography_gidx_center(GIDX *gidx, POINT3D *p)
Datum geography_cmp(PG_FUNCTION_ARGS)
#define FALSE
Definition: dbfopen.c:168
#define FP_EQUALS(A, B)
#define TRUE
Definition: dbfopen.c:169
This library is the generic geometry handling section of PostGIS.