PostGIS  2.3.7dev-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  * PostGIS is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation, either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * PostGIS is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with PostGIS. If not, see <http://www.gnu.org/licenses/>.
18  *
19  **********************************************************************
20  *
21  * Copyright (C) 2010 Olivier Courtin <olivier.courtin@oslandia.com>
22  * Copyright (C) 2010 Mark Cave-Ayland <mark.cave-ayland@siriusit.co.uk>
23  * Copyright (C) 2009-2011 Paul Ramsey <pramsey@cleverelephant.ca>
24  *
25  **********************************************************************/
26 
27 
28 #include "postgres.h"
29 #include "fmgr.h"
30 #include "utils/geo_decls.h"
31 
32 #include "../postgis_config.h"
33 #include "liblwgeom.h"
34 #include "lwgeom_pg.h"
35 
36 #include <math.h>
37 #include <float.h>
38 #include <string.h>
39 #include <stdio.h>
40 #include <errno.h>
41 
42 Datum lwgeom_lt(PG_FUNCTION_ARGS);
43 Datum lwgeom_le(PG_FUNCTION_ARGS);
44 Datum lwgeom_eq(PG_FUNCTION_ARGS);
45 Datum lwgeom_ge(PG_FUNCTION_ARGS);
46 Datum lwgeom_gt(PG_FUNCTION_ARGS);
47 Datum lwgeom_cmp(PG_FUNCTION_ARGS);
48 
50 Datum lwgeom_lt(PG_FUNCTION_ARGS)
51 {
52  GSERIALIZED *geom1 = PG_GETARG_GSERIALIZED_P(0);
53  GSERIALIZED *geom2 = PG_GETARG_GSERIALIZED_P(1);
54  GBOX box1;
55  GBOX box2;
56  bool empty1, empty2;
57 
58  POSTGIS_DEBUG(2, "lwgeom_lt called");
59 
61 
62  POSTGIS_DEBUG(3, "lwgeom_lt passed getSRID test");
63 
64  empty1 = ( gserialized_get_gbox_p(geom1, &box1) == LW_FAILURE );
65  empty2 = ( gserialized_get_gbox_p(geom2, &box2) == LW_FAILURE );
66 
67  PG_FREE_IF_COPY(geom1, 0);
68  PG_FREE_IF_COPY(geom2, 1);
69 
70  POSTGIS_DEBUG(3, "lwgeom_lt getbox2d_p passed");
71 
72  if ( empty1 != empty2 )
73  {
74  PG_RETURN_BOOL(FALSE);
75  }
76 
77  if ( ! FPeq(box1.xmin , box2.xmin) )
78  {
79  if (box1.xmin < box2.xmin)
80  PG_RETURN_BOOL(TRUE);
81  }
82 
83  if ( ! FPeq(box1.ymin , box2.ymin) )
84  {
85  if (box1.ymin < box2.ymin)
86  PG_RETURN_BOOL(TRUE);
87  }
88 
89  if ( ! FPeq(box1.xmax , box2.xmax) )
90  {
91  if (box1.xmax < box2.xmax)
92  PG_RETURN_BOOL(TRUE);
93  }
94 
95  if ( ! FPeq(box1.ymax , box2.ymax) )
96  {
97  if (box1.ymax < box2.ymax)
98  PG_RETURN_BOOL(TRUE);
99  }
100 
101  PG_RETURN_BOOL(FALSE);
102 }
103 
105 Datum lwgeom_le(PG_FUNCTION_ARGS)
106 {
107  GSERIALIZED *geom1 = PG_GETARG_GSERIALIZED_P(0);
108  GSERIALIZED *geom2 = PG_GETARG_GSERIALIZED_P(1);
109  GBOX box1;
110  GBOX box2;
111  bool empty1, empty2;
112 
113  POSTGIS_DEBUG(2, "lwgeom_le called");
114 
116 
117  empty1 = ( gserialized_get_gbox_p(geom1, &box1) == LW_FAILURE );
118  empty2 = ( gserialized_get_gbox_p(geom2, &box2) == LW_FAILURE );
119 
120  PG_FREE_IF_COPY(geom1, 0);
121  PG_FREE_IF_COPY(geom2, 1);
122 
123  if ( empty1 != empty2 )
124  {
125  PG_RETURN_BOOL(FALSE);
126  }
127 
128  if ( ! FPeq(box1.xmin , box2.xmin) )
129  {
130  if (box1.xmin < box2.xmin)
131  {
132  PG_RETURN_BOOL(TRUE);
133  }
134  PG_RETURN_BOOL(FALSE);
135  }
136 
137  if ( ! FPeq(box1.ymin , box2.ymin) )
138  {
139  if (box1.ymin < box2.ymin)
140  {
141  PG_RETURN_BOOL(TRUE);
142  }
143  PG_RETURN_BOOL(FALSE);
144  }
145 
146  if ( ! FPeq(box1.xmax , box2.xmax) )
147  {
148  if (box1.xmax < box2.xmax)
149  {
150  PG_RETURN_BOOL(TRUE);
151  }
152  PG_RETURN_BOOL(FALSE);
153  }
154 
155  if ( ! FPeq(box1.ymax , box2.ymax) )
156  {
157  if (box1.ymax < box2.ymax)
158  {
159  PG_RETURN_BOOL(TRUE);
160  }
161  PG_RETURN_BOOL(FALSE);
162  }
163 
164  PG_RETURN_BOOL(TRUE);
165 }
166 
168 Datum lwgeom_eq(PG_FUNCTION_ARGS)
169 {
170  GSERIALIZED *geom1 = PG_GETARG_GSERIALIZED_P(0);
171  GSERIALIZED *geom2 = PG_GETARG_GSERIALIZED_P(1);
172  GBOX box1;
173  GBOX box2;
174  bool empty1, empty2;
175  bool result;
176 
177  POSTGIS_DEBUG(2, "lwgeom_eq called");
178 
180 
181  gbox_init(&box1);
182  gbox_init(&box2);
183 
184  empty1 = ( gserialized_get_gbox_p(geom1, &box1) == LW_FAILURE );
185  empty2 = ( gserialized_get_gbox_p(geom2, &box2) == LW_FAILURE );
186 
187  PG_FREE_IF_COPY(geom1, 0);
188  PG_FREE_IF_COPY(geom2, 1);
189 
190  if ( empty1 != empty2 )
191  {
192  result = FALSE;
193  }
194  else if ( ! (FPeq(box1.xmin, box2.xmin) && FPeq(box1.ymin, box2.ymin) &&
195  FPeq(box1.xmax, box2.xmax) && FPeq(box1.ymax, box2.ymax)) )
196  {
197  result = FALSE;
198  }
199  else
200  {
201  result = TRUE;
202  }
203 
204  PG_RETURN_BOOL(result);
205 }
206 
208 Datum lwgeom_ge(PG_FUNCTION_ARGS)
209 {
210  GSERIALIZED *geom1 = PG_GETARG_GSERIALIZED_P(0);
211  GSERIALIZED *geom2 = PG_GETARG_GSERIALIZED_P(1);
212  GBOX box1;
213  GBOX box2;
214  bool empty1, empty2;
215 
216  POSTGIS_DEBUG(2, "lwgeom_ge called");
217 
219 
220  empty1 = ( gserialized_get_gbox_p(geom1, &box1) == LW_FAILURE );
221  empty2 = ( gserialized_get_gbox_p(geom2, &box2) == LW_FAILURE );
222 
223  PG_FREE_IF_COPY(geom1, 0);
224  PG_FREE_IF_COPY(geom2, 1);
225 
226  if ( empty1 != empty2 )
227  {
228  PG_RETURN_BOOL(FALSE);
229  }
230 
231  if ( ! FPeq(box1.xmin , box2.xmin) )
232  {
233  if (box1.xmin > box2.xmin)
234  {
235  PG_RETURN_BOOL(TRUE);
236  }
237  PG_RETURN_BOOL(FALSE);
238  }
239 
240  if ( ! FPeq(box1.ymin , box2.ymin) )
241  {
242  if (box1.ymin > box2.ymin)
243  {
244  PG_RETURN_BOOL(TRUE);
245  }
246  PG_RETURN_BOOL(FALSE);
247  }
248 
249  if ( ! FPeq(box1.xmax , box2.xmax) )
250  {
251  if (box1.xmax > box2.xmax)
252  {
253  PG_RETURN_BOOL(TRUE);
254  }
255  PG_RETURN_BOOL(FALSE);
256  }
257 
258  if ( ! FPeq(box1.ymax , box2.ymax) )
259  {
260  if (box1.ymax > box2.ymax)
261  {
262  PG_RETURN_BOOL(TRUE);
263  }
264  PG_RETURN_BOOL(FALSE);
265  }
266 
267  PG_RETURN_BOOL(TRUE);
268 }
269 
271 Datum lwgeom_gt(PG_FUNCTION_ARGS)
272 {
273  GSERIALIZED *geom1 = PG_GETARG_GSERIALIZED_P(0);
274  GSERIALIZED *geom2 = PG_GETARG_GSERIALIZED_P(1);
275  GBOX box1;
276  GBOX box2;
277  bool empty1, empty2;
278 
279  POSTGIS_DEBUG(2, "lwgeom_gt called");
280 
282 
283  empty1 = ( gserialized_get_gbox_p(geom1, &box1) == LW_FAILURE );
284  empty2 = ( gserialized_get_gbox_p(geom2, &box2) == LW_FAILURE );
285 
286  PG_FREE_IF_COPY(geom1, 0);
287  PG_FREE_IF_COPY(geom2, 1);
288 
289  if ( empty1 != empty2 )
290  {
291  PG_RETURN_BOOL(FALSE);
292  }
293 
294  if ( ! FPeq(box1.xmin , box2.xmin) )
295  {
296  if (box1.xmin > box2.xmin)
297  {
298  PG_RETURN_BOOL(TRUE);
299  }
300  }
301 
302  if ( ! FPeq(box1.ymin , box2.ymin) )
303  {
304  if (box1.ymin > box2.ymin)
305  {
306  PG_RETURN_BOOL(TRUE);
307  }
308  }
309 
310  if ( ! FPeq(box1.xmax , box2.xmax) )
311  {
312  if (box1.xmax > box2.xmax)
313  {
314  PG_RETURN_BOOL(TRUE);
315  }
316  }
317 
318  if ( ! FPeq(box1.ymax , box2.ymax) )
319  {
320  if (box1.ymax > box2.ymax)
321  {
322  PG_RETURN_BOOL(TRUE);
323  }
324  }
325 
326  PG_RETURN_BOOL(FALSE);
327 }
328 
330 Datum lwgeom_cmp(PG_FUNCTION_ARGS)
331 {
332  GSERIALIZED *geom1 = PG_GETARG_GSERIALIZED_P(0);
333  GSERIALIZED *geom2 = PG_GETARG_GSERIALIZED_P(1);
334  GBOX box1;
335  GBOX box2;
336  bool empty1, empty2;
337 
338  POSTGIS_DEBUG(2, "lwgeom_cmp called");
339 
341 
342  empty1 = ( gserialized_get_gbox_p(geom1, &box1) == LW_FAILURE );
343  empty2 = ( gserialized_get_gbox_p(geom2, &box2) == LW_FAILURE );
344 
345  PG_FREE_IF_COPY(geom1, 0);
346  PG_FREE_IF_COPY(geom2, 1);
347 
348  if ( empty1 || empty2 )
349  {
350  if ( empty1 && empty2 )
351  {
352  PG_RETURN_INT32(1);
353  }
354  else if ( empty1 )
355  {
356  PG_RETURN_INT32(-1);
357  }
358  else
359  {
360  PG_RETURN_INT32(1);
361  }
362  }
363 
364  if ( ! FPeq(box1.xmin , box2.xmin) )
365  {
366  if (box1.xmin < box2.xmin)
367  {
368  PG_RETURN_INT32(-1);
369  }
370  PG_RETURN_INT32(1);
371  }
372 
373  if ( ! FPeq(box1.ymin , box2.ymin) )
374  {
375  if (box1.ymin < box2.ymin)
376  {
377  PG_RETURN_INT32(-1);
378  }
379  PG_RETURN_INT32(1);
380  }
381 
382  if ( ! FPeq(box1.xmax , box2.xmax) )
383  {
384  if (box1.xmax < box2.xmax)
385  {
386  PG_RETURN_INT32(-1);
387  }
388  PG_RETURN_INT32(1);
389  }
390 
391  if ( ! FPeq(box1.ymax , box2.ymax) )
392  {
393  if (box1.ymax < box2.ymax)
394  {
395  PG_RETURN_INT32(-1);
396  }
397  PG_RETURN_INT32(1);
398  }
399 
400  PG_RETURN_INT32(0);
401 }
402 
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:398
Datum lwgeom_eq(PG_FUNCTION_ARGS)
Definition: lwgeom_btree.c:168
double xmax
Definition: liblwgeom.h:292
Datum lwgeom_le(PG_FUNCTION_ARGS)
Definition: lwgeom_btree.c:105
void error_if_srid_mismatch(int srid1, int srid2)
Definition: lwutil.c:369
Datum lwgeom_lt(PG_FUNCTION_ARGS)
Definition: lwgeom_btree.c:50
#define LW_FAILURE
Definition: liblwgeom.h:78
double ymin
Definition: liblwgeom.h:293
void gbox_init(GBOX *gbox)
Zero out all the entries in the GBOX.
Definition: g_box.c:51
double xmin
Definition: liblwgeom.h:291
Datum lwgeom_cmp(PG_FUNCTION_ARGS)
Definition: lwgeom_btree.c:330
double ymax
Definition: liblwgeom.h:294
Datum lwgeom_gt(PG_FUNCTION_ARGS)
Definition: lwgeom_btree.c:271
#define FALSE
Definition: dbfopen.c:168
#define FPeq(A, B)
Definition: box2d.c:37
PG_FUNCTION_INFO_V1(lwgeom_lt)
#define TRUE
Definition: dbfopen.c:169
Datum lwgeom_ge(PG_FUNCTION_ARGS)
Definition: lwgeom_btree.c:208
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:83
This library is the generic geometry handling section of PostGIS.