PostGIS  2.2.8dev-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 
42 Datum lwgeom_lt(PG_FUNCTION_ARGS)
43 {
44  GSERIALIZED *geom1 = PG_GETARG_GSERIALIZED_P(0);
45  GSERIALIZED *geom2 = PG_GETARG_GSERIALIZED_P(1);
46  GBOX box1;
47  GBOX box2;
48 
49  POSTGIS_DEBUG(2, "lwgeom_lt called");
50 
52 
53  POSTGIS_DEBUG(3, "lwgeom_lt passed getSRID test");
54 
55  gserialized_get_gbox_p(geom1, &box1);
56  gserialized_get_gbox_p(geom2, &box2);
57 
58  PG_FREE_IF_COPY(geom1, 0);
59  PG_FREE_IF_COPY(geom2, 1);
60 
61  POSTGIS_DEBUG(3, "lwgeom_lt getbox2d_p passed");
62 
63  if ( ! FPeq(box1.xmin , box2.xmin) )
64  {
65  if (box1.xmin < box2.xmin)
66  PG_RETURN_BOOL(TRUE);
67  }
68 
69  if ( ! FPeq(box1.ymin , box2.ymin) )
70  {
71  if (box1.ymin < box2.ymin)
72  PG_RETURN_BOOL(TRUE);
73  }
74 
75  if ( ! FPeq(box1.xmax , box2.xmax) )
76  {
77  if (box1.xmax < box2.xmax)
78  PG_RETURN_BOOL(TRUE);
79  }
80 
81  if ( ! FPeq(box1.ymax , box2.ymax) )
82  {
83  if (box1.ymax < box2.ymax)
84  PG_RETURN_BOOL(TRUE);
85  }
86 
87  PG_RETURN_BOOL(FALSE);
88 }
89 
91 Datum lwgeom_le(PG_FUNCTION_ARGS)
92 {
93  GSERIALIZED *geom1 = PG_GETARG_GSERIALIZED_P(0);
94  GSERIALIZED *geom2 = PG_GETARG_GSERIALIZED_P(1);
95  GBOX box1;
96  GBOX box2;
97 
98  POSTGIS_DEBUG(2, "lwgeom_le called");
99 
101 
102  gserialized_get_gbox_p(geom1, &box1);
103  gserialized_get_gbox_p(geom2, &box2);
104 
105  PG_FREE_IF_COPY(geom1, 0);
106  PG_FREE_IF_COPY(geom2, 1);
107 
108  if ( ! FPeq(box1.xmin , box2.xmin) )
109  {
110  if (box1.xmin < box2.xmin)
111  {
112  PG_RETURN_BOOL(TRUE);
113  }
114  PG_RETURN_BOOL(FALSE);
115  }
116 
117  if ( ! FPeq(box1.ymin , box2.ymin) )
118  {
119  if (box1.ymin < box2.ymin)
120  {
121  PG_RETURN_BOOL(TRUE);
122  }
123  PG_RETURN_BOOL(FALSE);
124  }
125 
126  if ( ! FPeq(box1.xmax , box2.xmax) )
127  {
128  if (box1.xmax < box2.xmax)
129  {
130  PG_RETURN_BOOL(TRUE);
131  }
132  PG_RETURN_BOOL(FALSE);
133  }
134 
135  if ( ! FPeq(box1.ymax , box2.ymax) )
136  {
137  if (box1.ymax < box2.ymax)
138  {
139  PG_RETURN_BOOL(TRUE);
140  }
141  PG_RETURN_BOOL(FALSE);
142  }
143 
144  PG_RETURN_BOOL(TRUE);
145 }
146 
148 Datum lwgeom_eq(PG_FUNCTION_ARGS)
149 {
150  GSERIALIZED *geom1 = PG_GETARG_GSERIALIZED_P(0);
151  GSERIALIZED *geom2 = PG_GETARG_GSERIALIZED_P(1);
152  GBOX box1;
153  GBOX box2;
154  bool empty1, empty2;
155  bool result;
156 
157  POSTGIS_DEBUG(2, "lwgeom_eq called");
158 
160 
161  gbox_init(&box1);
162  gbox_init(&box2);
163 
164  empty1 = ( gserialized_get_gbox_p(geom1, &box1) == LW_FAILURE );
165  empty2 = ( gserialized_get_gbox_p(geom2, &box2) == LW_FAILURE );
166  PG_FREE_IF_COPY(geom1, 0);
167  PG_FREE_IF_COPY(geom2, 1);
168 
169  if ( empty1 != empty2 )
170  {
171  result = FALSE;
172  }
173  else if ( ! (FPeq(box1.xmin, box2.xmin) && FPeq(box1.ymin, box2.ymin) &&
174  FPeq(box1.xmax, box2.xmax) && FPeq(box1.ymax, box2.ymax)) )
175  {
176  result = FALSE;
177  }
178  else
179  {
180  result = TRUE;
181  }
182 
183  PG_RETURN_BOOL(result);
184 }
185 
187 Datum lwgeom_ge(PG_FUNCTION_ARGS)
188 {
189  GSERIALIZED *geom1 = PG_GETARG_GSERIALIZED_P(0);
190  GSERIALIZED *geom2 = PG_GETARG_GSERIALIZED_P(1);
191  GBOX box1;
192  GBOX box2;
193 
194  POSTGIS_DEBUG(2, "lwgeom_ge called");
195 
197 
198  gserialized_get_gbox_p(geom1, &box1);
199  gserialized_get_gbox_p(geom2, &box2);
200 
201  PG_FREE_IF_COPY(geom1, 0);
202  PG_FREE_IF_COPY(geom2, 1);
203 
204  if ( ! FPeq(box1.xmin , box2.xmin) )
205  {
206  if (box1.xmin > box2.xmin)
207  {
208  PG_RETURN_BOOL(TRUE);
209  }
210  PG_RETURN_BOOL(FALSE);
211  }
212 
213  if ( ! FPeq(box1.ymin , box2.ymin) )
214  {
215  if (box1.ymin > box2.ymin)
216  {
217  PG_RETURN_BOOL(TRUE);
218  }
219  PG_RETURN_BOOL(FALSE);
220  }
221 
222  if ( ! FPeq(box1.xmax , box2.xmax) )
223  {
224  if (box1.xmax > box2.xmax)
225  {
226  PG_RETURN_BOOL(TRUE);
227  }
228  PG_RETURN_BOOL(FALSE);
229  }
230 
231  if ( ! FPeq(box1.ymax , box2.ymax) )
232  {
233  if (box1.ymax > box2.ymax)
234  {
235  PG_RETURN_BOOL(TRUE);
236  }
237  PG_RETURN_BOOL(FALSE);
238  }
239 
240  PG_RETURN_BOOL(TRUE);
241 }
242 
244 Datum lwgeom_gt(PG_FUNCTION_ARGS)
245 {
246  GSERIALIZED *geom1 = PG_GETARG_GSERIALIZED_P(0);
247  GSERIALIZED *geom2 = PG_GETARG_GSERIALIZED_P(1);
248  GBOX box1;
249  GBOX box2;
250 
251  POSTGIS_DEBUG(2, "lwgeom_gt called");
252 
254 
255  gserialized_get_gbox_p(geom1, &box1);
256  gserialized_get_gbox_p(geom2, &box2);
257 
258  PG_FREE_IF_COPY(geom1, 0);
259  PG_FREE_IF_COPY(geom2, 1);
260 
261  if ( ! FPeq(box1.xmin , box2.xmin) )
262  {
263  if (box1.xmin > box2.xmin)
264  {
265  PG_RETURN_BOOL(TRUE);
266  }
267  }
268 
269  if ( ! FPeq(box1.ymin , box2.ymin) )
270  {
271  if (box1.ymin > box2.ymin)
272  {
273  PG_RETURN_BOOL(TRUE);
274  }
275  }
276 
277  if ( ! FPeq(box1.xmax , box2.xmax) )
278  {
279  if (box1.xmax > box2.xmax)
280  {
281  PG_RETURN_BOOL(TRUE);
282  }
283  }
284 
285  if ( ! FPeq(box1.ymax , box2.ymax) )
286  {
287  if (box1.ymax > box2.ymax)
288  {
289  PG_RETURN_BOOL(TRUE);
290  }
291  }
292 
293  PG_RETURN_BOOL(FALSE);
294 }
295 
297 Datum lwgeom_cmp(PG_FUNCTION_ARGS)
298 {
299  GSERIALIZED *geom1 = PG_GETARG_GSERIALIZED_P(0);
300  GSERIALIZED *geom2 = PG_GETARG_GSERIALIZED_P(1);
301  GBOX box1;
302  GBOX box2;
303 
304  POSTGIS_DEBUG(2, "lwgeom_cmp called");
305 
307 
308  gserialized_get_gbox_p(geom1, &box1);
309  gserialized_get_gbox_p(geom2, &box2);
310 
311  PG_FREE_IF_COPY(geom1, 0);
312  PG_FREE_IF_COPY(geom2, 1);
313 
314  if ( ! FPeq(box1.xmin , box2.xmin) )
315  {
316  if (box1.xmin < box2.xmin)
317  {
318  PG_RETURN_INT32(-1);
319  }
320  PG_RETURN_INT32(1);
321  }
322 
323  if ( ! FPeq(box1.ymin , box2.ymin) )
324  {
325  if (box1.ymin < box2.ymin)
326  {
327  PG_RETURN_INT32(-1);
328  }
329  PG_RETURN_INT32(1);
330  }
331 
332  if ( ! FPeq(box1.xmax , box2.xmax) )
333  {
334  if (box1.xmax < box2.xmax)
335  {
336  PG_RETURN_INT32(-1);
337  }
338  PG_RETURN_INT32(1);
339  }
340 
341  if ( ! FPeq(box1.ymax , box2.ymax) )
342  {
343  if (box1.ymax < box2.ymax)
344  {
345  PG_RETURN_INT32(-1);
346  }
347  PG_RETURN_INT32(1);
348  }
349 
350  PG_RETURN_INT32(0);
351 }
352 
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:371
Datum lwgeom_eq(PG_FUNCTION_ARGS)
Definition: lwgeom_btree.c:148
double xmax
Definition: liblwgeom.h:277
Datum lwgeom_le(PG_FUNCTION_ARGS)
Definition: lwgeom_btree.c:91
void error_if_srid_mismatch(int srid1, int srid2)
Definition: lwutil.c:341
Datum lwgeom_lt(PG_FUNCTION_ARGS)
Definition: lwgeom_btree.c:42
#define LW_FAILURE
Definition: liblwgeom.h:64
double ymin
Definition: liblwgeom.h:278
void gbox_init(GBOX *gbox)
Zero out all the entries in the GBOX.
Definition: g_box.c:36
double xmin
Definition: liblwgeom.h:276
Datum lwgeom_cmp(PG_FUNCTION_ARGS)
Definition: lwgeom_btree.c:297
double ymax
Definition: liblwgeom.h:279
Datum lwgeom_gt(PG_FUNCTION_ARGS)
Definition: lwgeom_btree.c:244
#define FALSE
Definition: dbfopen.c:168
#define FPeq(A, B)
Definition: box2d.c:11
PG_FUNCTION_INFO_V1(lwgeom_lt)
#define TRUE
Definition: dbfopen.c:169
Datum lwgeom_ge(PG_FUNCTION_ARGS)
Definition: lwgeom_btree.c:187
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:69
This library is the generic geometry handling section of PostGIS.