PostGIS  2.1.10dev-r@@SVN_REVISION@@
lwgeom_btree.c
Go to the documentation of this file.
1 /**********************************************************************
2  *
3  * PostGIS - Spatial Types for PostgreSQL
4  * http://postgis.net
5  *
6  * Copyright (C) 2010 Olivier Courtin <olivier.courtin@oslandia.com>
7  * Copyright (C) 2010 Mark Cave-Ayland <mark.cave-ayland@siriusit.co.uk>
8  * Copyright (C) 2009-2011 Paul Ramsey <pramsey@cleverelephant.ca>
9  *
10  * This is free software; you can redistribute and/or modify it under
11  * the terms of the GNU General Public Licence. See the COPYING file.
12  *
13  **********************************************************************
14  *
15  * Comparision function for use in Binary Tree searches
16  * (ORDER BY, GROUP BY, DISTINCT)
17  *
18  ***********************************************************/
19 
20 #include "postgres.h"
21 #include "fmgr.h"
22 #include "utils/geo_decls.h"
23 
24 #include "../postgis_config.h"
25 #include "liblwgeom.h"
26 #include "lwgeom_pg.h"
27 
28 #include <math.h>
29 #include <float.h>
30 #include <string.h>
31 #include <stdio.h>
32 #include <errno.h>
33 
34 Datum lwgeom_lt(PG_FUNCTION_ARGS);
35 Datum lwgeom_le(PG_FUNCTION_ARGS);
36 Datum lwgeom_eq(PG_FUNCTION_ARGS);
37 Datum lwgeom_ge(PG_FUNCTION_ARGS);
38 Datum lwgeom_gt(PG_FUNCTION_ARGS);
39 Datum lwgeom_cmp(PG_FUNCTION_ARGS);
40 
41 
42 #define BTREE_SRID_MISMATCH_SEVERITY ERROR
43 
45 Datum lwgeom_lt(PG_FUNCTION_ARGS)
46 {
47  GSERIALIZED *geom1 = (GSERIALIZED *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
48  GSERIALIZED *geom2 = (GSERIALIZED *) PG_DETOAST_DATUM(PG_GETARG_DATUM(1));
49  GBOX box1;
50  GBOX box2;
51 
52  POSTGIS_DEBUG(2, "lwgeom_lt called");
53 
54  if (gserialized_get_srid(geom1) != gserialized_get_srid(geom2))
55  {
57  "Operation on two GEOMETRIES with different SRIDs\n");
58  PG_FREE_IF_COPY(geom1, 0);
59  PG_FREE_IF_COPY(geom2, 1);
60  PG_RETURN_NULL();
61  }
62 
63  POSTGIS_DEBUG(3, "lwgeom_lt passed getSRID test");
64 
65  gserialized_get_gbox_p(geom1, &box1);
66  gserialized_get_gbox_p(geom2, &box2);
67 
68  PG_FREE_IF_COPY(geom1, 0);
69  PG_FREE_IF_COPY(geom2, 1);
70 
71  POSTGIS_DEBUG(3, "lwgeom_lt getbox2d_p passed");
72 
73  if ( ! FPeq(box1.xmin , box2.xmin) )
74  {
75  if (box1.xmin < box2.xmin)
76  PG_RETURN_BOOL(TRUE);
77  }
78 
79  if ( ! FPeq(box1.ymin , box2.ymin) )
80  {
81  if (box1.ymin < box2.ymin)
82  PG_RETURN_BOOL(TRUE);
83  }
84 
85  if ( ! FPeq(box1.xmax , box2.xmax) )
86  {
87  if (box1.xmax < box2.xmax)
88  PG_RETURN_BOOL(TRUE);
89  }
90 
91  if ( ! FPeq(box1.ymax , box2.ymax) )
92  {
93  if (box1.ymax < box2.ymax)
94  PG_RETURN_BOOL(TRUE);
95  }
96 
97  PG_RETURN_BOOL(FALSE);
98 }
99 
101 Datum lwgeom_le(PG_FUNCTION_ARGS)
102 {
103  GSERIALIZED *geom1 = (GSERIALIZED *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
104  GSERIALIZED *geom2 = (GSERIALIZED *) PG_DETOAST_DATUM(PG_GETARG_DATUM(1));
105  GBOX box1;
106  GBOX box2;
107 
108  POSTGIS_DEBUG(2, "lwgeom_le called");
109 
110  if (gserialized_get_srid(geom1) != gserialized_get_srid(geom2))
111  {
113  "Operation on two GEOMETRIES with different SRIDs\n");
114  PG_FREE_IF_COPY(geom1, 0);
115  PG_FREE_IF_COPY(geom2, 1);
116  PG_RETURN_NULL();
117  }
118 
119  gserialized_get_gbox_p(geom1, &box1);
120  gserialized_get_gbox_p(geom2, &box2);
121 
122  PG_FREE_IF_COPY(geom1, 0);
123  PG_FREE_IF_COPY(geom2, 1);
124 
125  if ( ! FPeq(box1.xmin , box2.xmin) )
126  {
127  if (box1.xmin < box2.xmin)
128  {
129  PG_RETURN_BOOL(TRUE);
130  }
131  PG_RETURN_BOOL(FALSE);
132  }
133 
134  if ( ! FPeq(box1.ymin , box2.ymin) )
135  {
136  if (box1.ymin < box2.ymin)
137  {
138  PG_RETURN_BOOL(TRUE);
139  }
140  PG_RETURN_BOOL(FALSE);
141  }
142 
143  if ( ! FPeq(box1.xmax , box2.xmax) )
144  {
145  if (box1.xmax < box2.xmax)
146  {
147  PG_RETURN_BOOL(TRUE);
148  }
149  PG_RETURN_BOOL(FALSE);
150  }
151 
152  if ( ! FPeq(box1.ymax , box2.ymax) )
153  {
154  if (box1.ymax < box2.ymax)
155  {
156  PG_RETURN_BOOL(TRUE);
157  }
158  PG_RETURN_BOOL(FALSE);
159  }
160 
161  PG_RETURN_BOOL(TRUE);
162 }
163 
165 Datum lwgeom_eq(PG_FUNCTION_ARGS)
166 {
167  GSERIALIZED *geom1 = (GSERIALIZED *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
168  GSERIALIZED *geom2 = (GSERIALIZED *) PG_DETOAST_DATUM(PG_GETARG_DATUM(1));
169  GBOX box1;
170  GBOX box2;
171  bool empty1, empty2;
172  bool result;
173 
174  POSTGIS_DEBUG(2, "lwgeom_eq called");
175 
176  if (gserialized_get_srid(geom1) != gserialized_get_srid(geom2))
177  {
179  "Operation on two GEOMETRIES with different SRIDs\n");
180  PG_FREE_IF_COPY(geom1, 0);
181  PG_FREE_IF_COPY(geom2, 1);
182  PG_RETURN_NULL();
183  }
184 
185  gbox_init(&box1);
186  gbox_init(&box2);
187 
188  empty1 = ( gserialized_get_gbox_p(geom1, &box1) == LW_FAILURE );
189  empty2 = ( gserialized_get_gbox_p(geom2, &box2) == LW_FAILURE );
190  PG_FREE_IF_COPY(geom1, 0);
191  PG_FREE_IF_COPY(geom2, 1);
192 
193  if ( empty1 != empty2 )
194  {
195  result = FALSE;
196  }
197  else if ( ! (FPeq(box1.xmin, box2.xmin) && FPeq(box1.ymin, box2.ymin) &&
198  FPeq(box1.xmax, box2.xmax) && FPeq(box1.ymax, box2.ymax)) )
199  {
200  result = FALSE;
201  }
202  else
203  {
204  result = TRUE;
205  }
206 
207  PG_RETURN_BOOL(result);
208 }
209 
211 Datum lwgeom_ge(PG_FUNCTION_ARGS)
212 {
213  GSERIALIZED *geom1 = (GSERIALIZED *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
214  GSERIALIZED *geom2 = (GSERIALIZED *) PG_DETOAST_DATUM(PG_GETARG_DATUM(1));
215  GBOX box1;
216  GBOX box2;
217 
218  POSTGIS_DEBUG(2, "lwgeom_ge called");
219 
220  if (gserialized_get_srid(geom1) != gserialized_get_srid(geom2))
221  {
223  "Operation on two GEOMETRIES with different SRIDs\n");
224  PG_FREE_IF_COPY(geom1, 0);
225  PG_FREE_IF_COPY(geom2, 1);
226  PG_RETURN_NULL();
227  }
228 
229  gserialized_get_gbox_p(geom1, &box1);
230  gserialized_get_gbox_p(geom2, &box2);
231 
232  PG_FREE_IF_COPY(geom1, 0);
233  PG_FREE_IF_COPY(geom2, 1);
234 
235  if ( ! FPeq(box1.xmin , box2.xmin) )
236  {
237  if (box1.xmin > box2.xmin)
238  {
239  PG_RETURN_BOOL(TRUE);
240  }
241  PG_RETURN_BOOL(FALSE);
242  }
243 
244  if ( ! FPeq(box1.ymin , box2.ymin) )
245  {
246  if (box1.ymin > box2.ymin)
247  {
248  PG_RETURN_BOOL(TRUE);
249  }
250  PG_RETURN_BOOL(FALSE);
251  }
252 
253  if ( ! FPeq(box1.xmax , box2.xmax) )
254  {
255  if (box1.xmax > box2.xmax)
256  {
257  PG_RETURN_BOOL(TRUE);
258  }
259  PG_RETURN_BOOL(FALSE);
260  }
261 
262  if ( ! FPeq(box1.ymax , box2.ymax) )
263  {
264  if (box1.ymax > box2.ymax)
265  {
266  PG_RETURN_BOOL(TRUE);
267  }
268  PG_RETURN_BOOL(FALSE);
269  }
270 
271  PG_RETURN_BOOL(TRUE);
272 }
273 
275 Datum lwgeom_gt(PG_FUNCTION_ARGS)
276 {
277  GSERIALIZED *geom1 = (GSERIALIZED *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
278  GSERIALIZED *geom2 = (GSERIALIZED *) PG_DETOAST_DATUM(PG_GETARG_DATUM(1));
279  GBOX box1;
280  GBOX box2;
281 
282  POSTGIS_DEBUG(2, "lwgeom_gt called");
283 
284  if (gserialized_get_srid(geom1) != gserialized_get_srid(geom2))
285  {
287  "Operation on two GEOMETRIES with different SRIDs\n");
288  PG_FREE_IF_COPY(geom1, 0);
289  PG_FREE_IF_COPY(geom2, 1);
290  PG_RETURN_NULL();
291  }
292 
293  gserialized_get_gbox_p(geom1, &box1);
294  gserialized_get_gbox_p(geom2, &box2);
295 
296  PG_FREE_IF_COPY(geom1, 0);
297  PG_FREE_IF_COPY(geom2, 1);
298 
299  if ( ! FPeq(box1.xmin , box2.xmin) )
300  {
301  if (box1.xmin > box2.xmin)
302  {
303  PG_RETURN_BOOL(TRUE);
304  }
305  }
306 
307  if ( ! FPeq(box1.ymin , box2.ymin) )
308  {
309  if (box1.ymin > box2.ymin)
310  {
311  PG_RETURN_BOOL(TRUE);
312  }
313  }
314 
315  if ( ! FPeq(box1.xmax , box2.xmax) )
316  {
317  if (box1.xmax > box2.xmax)
318  {
319  PG_RETURN_BOOL(TRUE);
320  }
321  }
322 
323  if ( ! FPeq(box1.ymax , box2.ymax) )
324  {
325  if (box1.ymax > box2.ymax)
326  {
327  PG_RETURN_BOOL(TRUE);
328  }
329  }
330 
331  PG_RETURN_BOOL(FALSE);
332 }
333 
335 Datum lwgeom_cmp(PG_FUNCTION_ARGS)
336 {
337  GSERIALIZED *geom1 = (GSERIALIZED *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
338  GSERIALIZED *geom2 = (GSERIALIZED *) PG_DETOAST_DATUM(PG_GETARG_DATUM(1));
339  GBOX box1;
340  GBOX box2;
341 
342  POSTGIS_DEBUG(2, "lwgeom_cmp called");
343 
344  if (gserialized_get_srid(geom1) != gserialized_get_srid(geom2))
345  {
347  "Operation on two GEOMETRIES with different SRIDs\n");
348  PG_FREE_IF_COPY(geom1, 0);
349  PG_FREE_IF_COPY(geom2, 1);
350  PG_RETURN_NULL();
351  }
352 
353  gserialized_get_gbox_p(geom1, &box1);
354  gserialized_get_gbox_p(geom2, &box2);
355 
356  PG_FREE_IF_COPY(geom1, 0);
357  PG_FREE_IF_COPY(geom2, 1);
358 
359  if ( ! FPeq(box1.xmin , box2.xmin) )
360  {
361  if (box1.xmin < box2.xmin)
362  {
363  PG_RETURN_INT32(-1);
364  }
365  PG_RETURN_INT32(1);
366  }
367 
368  if ( ! FPeq(box1.ymin , box2.ymin) )
369  {
370  if (box1.ymin < box2.ymin)
371  {
372  PG_RETURN_INT32(-1);
373  }
374  PG_RETURN_INT32(1);
375  }
376 
377  if ( ! FPeq(box1.xmax , box2.xmax) )
378  {
379  if (box1.xmax < box2.xmax)
380  {
381  PG_RETURN_INT32(-1);
382  }
383  PG_RETURN_INT32(1);
384  }
385 
386  if ( ! FPeq(box1.ymax , box2.ymax) )
387  {
388  if (box1.ymax < box2.ymax)
389  {
390  PG_RETURN_INT32(-1);
391  }
392  PG_RETURN_INT32(1);
393  }
394 
395  PG_RETURN_INT32(0);
396 }
397 
int gserialized_get_gbox_p(const GSERIALIZED *g, GBOX *box)
Read the bounding box off a serialization and calculate one if it is not already there.
Definition: g_serialized.c:373
Datum lwgeom_eq(PG_FUNCTION_ARGS)
Definition: lwgeom_btree.c:165
double xmax
Definition: liblwgeom.h:249
Datum lwgeom_le(PG_FUNCTION_ARGS)
Definition: lwgeom_btree.c:101
Datum lwgeom_lt(PG_FUNCTION_ARGS)
Definition: lwgeom_btree.c:45
char ** result
Definition: liblwgeom.h:218
#define LW_FAILURE
Definition: liblwgeom.h:54
double ymin
Definition: liblwgeom.h:250
void gbox_init(GBOX *gbox)
Zero out all the entries in the GBOX.
Definition: g_box.c:34
double xmin
Definition: liblwgeom.h:248
#define BTREE_SRID_MISMATCH_SEVERITY
Definition: lwgeom_btree.c:42
Datum lwgeom_cmp(PG_FUNCTION_ARGS)
Definition: lwgeom_btree.c:335
double ymax
Definition: liblwgeom.h:251
Datum lwgeom_gt(PG_FUNCTION_ARGS)
Definition: lwgeom_btree.c:275
#define FALSE
Definition: dbfopen.c:169
#define FPeq(A, B)
Definition: box2d.c:11
PG_FUNCTION_INFO_V1(lwgeom_lt)
#define TRUE
Definition: dbfopen.c:170
Datum lwgeom_ge(PG_FUNCTION_ARGS)
Definition: lwgeom_btree.c:211
int32_t gserialized_get_srid(const GSERIALIZED *s)
Extract the SRID from the serialized form (it is packed into three bytes so this is a handy function)...
Definition: g_serialized.c:70
This library is the generic geometry handling section of PostGIS.