PostGIS 3.0.6dev-r@@SVN_REVISION@@
Loading...
Searching...
No Matches
lwgeom_box.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 2001-2009 Refractions Research Inc.
22 * Copyright 2009 Mark Cave-Ayland <mark.cave-ayland@siriusit.co.uk>
23 *
24 **********************************************************************/
25
26
27#include "postgres.h"
28#include "access/gist.h"
29#include "access/itup.h"
30#include "fmgr.h"
31#include "utils/elog.h"
32#include "utils/geo_decls.h"
33
34#include "../postgis_config.h"
35#include "lwgeom_pg.h"
36#include "liblwgeom.h"
37
38#include <math.h>
39#include <float.h>
40#include <string.h>
41#include <stdio.h>
42
43/* forward defs */
44Datum BOX2D_in(PG_FUNCTION_ARGS);
45Datum BOX2D_out(PG_FUNCTION_ARGS);
46Datum LWGEOM_to_BOX2D(PG_FUNCTION_ARGS);
47Datum LWGEOM_to_BOX2DF(PG_FUNCTION_ARGS);
48Datum BOX2D_expand(PG_FUNCTION_ARGS);
49Datum BOX2D_to_BOX3D(PG_FUNCTION_ARGS);
50Datum BOX2D_combine(PG_FUNCTION_ARGS);
51Datum BOX2D_to_LWGEOM(PG_FUNCTION_ARGS);
52Datum BOX2D_construct(PG_FUNCTION_ARGS);
53
54/* parser - "BOX(xmin ymin,xmax ymax)" */
56Datum BOX2D_in(PG_FUNCTION_ARGS)
57{
58 char *str = PG_GETARG_CSTRING(0);
59 int nitems;
60 double tmp;
61 GBOX box;
62 int i;
63
64 gbox_init(&box);
65
66 for(i = 0; str[i]; i++) {
67 str[i] = tolower(str[i]);
68 }
69
70 nitems = sscanf(str,"box(%lf %lf,%lf %lf)", &box.xmin, &box.ymin, &box.xmax, &box.ymax);
71 if (nitems != 4)
72 {
73 elog(ERROR,"box2d parser - couldn't parse. It should look like: BOX(xmin ymin,xmax ymax)");
74 PG_RETURN_NULL();
75 }
76
77 if (box.xmin > box.xmax)
78 {
79 tmp = box.xmin;
80 box.xmin = box.xmax;
81 box.xmax = tmp;
82 }
83 if (box.ymin > box.ymax)
84 {
85 tmp = box.ymin;
86 box.ymin = box.ymax;
87 box.ymax = tmp;
88 }
89 PG_RETURN_POINTER(gbox_copy(&box));
90}
91
92/*writer "BOX(xmin ymin,xmax ymax)" */
94Datum BOX2D_out(PG_FUNCTION_ARGS)
95{
96 char tmp[500]; /* big enough */
97 char *result;
98 int size;
99
100 GBOX *box = (GBOX *)PG_GETARG_POINTER(0);
101 /* Avoid unaligned access to the gbox struct */
102 GBOX box_aligned;
103 memcpy(&box_aligned, box, sizeof(GBOX));
104
105 size = sprintf(tmp,
106 "BOX(%.15g %.15g,%.15g %.15g)",
107 box_aligned.xmin,
108 box_aligned.ymin,
109 box_aligned.xmax,
110 box_aligned.ymax);
111
112 result= palloc(size+1); /* +1= null term */
113 memcpy(result,tmp,size+1);
114 result[size] = '\0';
115
116 PG_RETURN_CSTRING(result);
117}
118
119
120/*convert a GSERIALIZED to BOX2D */
122Datum LWGEOM_to_BOX2D(PG_FUNCTION_ARGS)
123{
124 GSERIALIZED *geom = PG_GETARG_GSERIALIZED_P(0);
125 LWGEOM *lwgeom = lwgeom_from_gserialized(geom);
126 GBOX gbox;
127
128 /* Cannot box empty! */
129 if ( lwgeom_is_empty(lwgeom) )
130 PG_RETURN_NULL();
131
132 /* Cannot calculate box? */
133 if ( lwgeom_calculate_gbox(lwgeom, &gbox) == LW_FAILURE )
134 PG_RETURN_NULL();
135
136 /* Strip out higher dimensions */
137 FLAGS_SET_Z(gbox.flags, 0);
138 FLAGS_SET_M(gbox.flags, 0);
139
140 PG_FREE_IF_COPY(geom, 0);
141 PG_RETURN_POINTER(gbox_copy(&gbox));
142}
143
144
145/*convert a GSERIALIZED to BOX2D */
147Datum LWGEOM_to_BOX2DF(PG_FUNCTION_ARGS)
148{
149 GSERIALIZED *geom = PG_GETARG_GSERIALIZED_P(0);
150 GBOX gbox;
151
152 if ( gserialized_get_gbox_p(geom, &gbox) == LW_FAILURE )
153 PG_RETURN_NULL();
154
155 /* Strip out higher dimensions */
156 FLAGS_SET_Z(gbox.flags, 0);
157 FLAGS_SET_M(gbox.flags, 0);
158
159 PG_FREE_IF_COPY(geom, 0);
160 PG_RETURN_POINTER(gbox_copy(&gbox));
161}
162
163
164/*----------------------------------------------------------
165 * Relational operators for BOXes.
166 * <, >, <=, >=, and == are based on box area.
167 *---------------------------------------------------------*/
168
169/*
170 * box_same - are two boxes identical?
171 */
173Datum BOX2D_same(PG_FUNCTION_ARGS)
174{
175 GBOX *box1 = (GBOX *) PG_GETARG_POINTER(0);
176 GBOX *box2 = (GBOX *) PG_GETARG_POINTER(1);
177
178 PG_RETURN_BOOL(FPeq(box1->xmax, box2->xmax) &&
179 FPeq(box1->xmin, box2->xmin) &&
180 FPeq(box1->ymax, box2->ymax) &&
181 FPeq(box1->ymin, box2->ymin));
182}
183
184/*
185 * box_overlap - does box1 overlap box2?
186 */
188Datum BOX2D_overlap(PG_FUNCTION_ARGS)
189{
190 GBOX *box1 = (GBOX *) PG_GETARG_POINTER(0);
191 GBOX *box2 = (GBOX *) PG_GETARG_POINTER(1);
192 bool result;
193
194
195 result = ((FPge(box1->xmax, box2->xmax) &&
196 FPle(box1->xmin, box2->xmax)) ||
197 (FPge(box2->xmax, box1->xmax) &&
198 FPle(box2->xmin, box1->xmax)))
199 &&
200 ((FPge(box1->ymax, box2->ymax) &&
201 FPle(box1->ymin, box2->ymax)) ||
202 (FPge(box2->ymax, box1->ymax) &&
203 FPle(box2->ymin, box1->ymax)));
204
205 PG_RETURN_BOOL(result);
206}
207
208
209/*
210 * box_overleft - is the right edge of box1 to the left of
211 * the right edge of box2?
212 */
214Datum BOX2D_overleft(PG_FUNCTION_ARGS)
215{
216 GBOX *box1 = (GBOX *) PG_GETARG_POINTER(0);
217 GBOX *box2 = (GBOX *) PG_GETARG_POINTER(1);
218
219 PG_RETURN_BOOL(FPle(box1->xmax, box2->xmax));
220}
221
222/*
223 * box_left - is box1 strictly left of box2?
224 */
226Datum BOX2D_left(PG_FUNCTION_ARGS)
227{
228 GBOX *box1 = (GBOX *) PG_GETARG_POINTER(0);
229 GBOX *box2 = (GBOX *) PG_GETARG_POINTER(1);
230
231 PG_RETURN_BOOL(FPlt(box1->xmax, box2->xmin));
232}
233
234/*
235 * box_right - is box1 strictly right of box2?
236 */
238Datum BOX2D_right(PG_FUNCTION_ARGS)
239{
240 GBOX *box1 = (GBOX *) PG_GETARG_POINTER(0);
241 GBOX *box2 = (GBOX *) PG_GETARG_POINTER(1);
242
243 PG_RETURN_BOOL(FPgt(box1->xmin, box2->xmax));
244}
245
246/*
247 * box_overright - is the left edge of box1 to the right of
248 * the left edge of box2?
249 */
251Datum BOX2D_overright(PG_FUNCTION_ARGS)
252{
253 GBOX *box1 = (GBOX *) PG_GETARG_POINTER(0);
254 GBOX *box2 = (GBOX *) PG_GETARG_POINTER(1);
255
256 PG_RETURN_BOOL(FPge(box1->xmin, box2->xmin));
257}
258
259/*
260 * box_overbelow - is the bottom edge of box1 below
261 * the bottom edge of box2?
262 */
264Datum BOX2D_overbelow(PG_FUNCTION_ARGS)
265{
266 GBOX *box1 = (GBOX *) PG_GETARG_POINTER(0);
267 GBOX *box2 = (GBOX *) PG_GETARG_POINTER(1);
268
269 PG_RETURN_BOOL(FPle(box1->ymax, box2->ymax));
270}
271
272/*
273 * box_below - is box1 strictly below box2?
274 */
276Datum BOX2D_below(PG_FUNCTION_ARGS)
277{
278 GBOX *box1 = (GBOX *) PG_GETARG_POINTER(0);
279 GBOX *box2 = (GBOX *) PG_GETARG_POINTER(1);
280
281 PG_RETURN_BOOL(FPlt(box1->ymax, box2->ymin));
282}
283
284/*
285 * box_above - is box1 strictly above box2?
286 */
288Datum BOX2D_above(PG_FUNCTION_ARGS)
289{
290 GBOX *box1 = (GBOX *) PG_GETARG_POINTER(0);
291 GBOX *box2 = (GBOX *) PG_GETARG_POINTER(1);
292
293 PG_RETURN_BOOL(FPgt(box1->ymin, box2->ymax));
294}
295
296/*
297 * box_overabove - the top edge of box1 above
298 * the top edge of box2?
299 */
301Datum BOX2D_overabove(PG_FUNCTION_ARGS)
302{
303 GBOX *box1 = (GBOX *) PG_GETARG_POINTER(0);
304 GBOX *box2 = (GBOX *) PG_GETARG_POINTER(1);
305
306 PG_RETURN_BOOL(FPge(box1->ymin, box2->ymin));
307}
308
309/*
310 * box_contained - is box1 contained by box2?
311 */
313Datum BOX2D_contained(PG_FUNCTION_ARGS)
314{
315 GBOX *box1 =(GBOX *) PG_GETARG_POINTER(0);
316 GBOX *box2 = (GBOX *) PG_GETARG_POINTER(1);
317
318 PG_RETURN_BOOL(FPle(box1->xmax, box2->xmax) &&
319 FPge(box1->xmin, box2->xmin) &&
320 FPle(box1->ymax, box2->ymax) &&
321 FPge(box1->ymin, box2->ymin));
322}
323
324/*
325 * box_contain - does box1 contain box2?
326 */
328Datum BOX2D_contain(PG_FUNCTION_ARGS)
329{
330 GBOX *box1 = (GBOX *) PG_GETARG_POINTER(0);
331 GBOX *box2 = (GBOX *) PG_GETARG_POINTER(1);
332
333 PG_RETURN_BOOL(FPge(box1->xmax, box2->xmax) &&
334 FPle(box1->xmin, box2->xmin) &&
335 FPge(box1->ymax, box2->ymax) &&
336 FPle(box1->ymin, box2->ymin));
337
338}
339
341Datum BOX2D_intersects(PG_FUNCTION_ARGS)
342{
343 GBOX *a = (GBOX *) PG_GETARG_POINTER(0);
344 GBOX *b = (GBOX *) PG_GETARG_POINTER(1);
345 GBOX *n;
346
347
348 n = (GBOX *) palloc(sizeof(GBOX));
349
350 n->xmax = Min(a->xmax, b->xmax);
351 n->ymax = Min(a->ymax, b->ymax);
352 n->xmin = Max(a->xmin, b->xmin);
353 n->ymin = Max(a->ymin, b->ymin);
354
355
356 if (n->xmax < n->xmin || n->ymax < n->ymin)
357 {
358 pfree(n);
359 /* Indicate "no intersection" by returning NULL pointer */
360 n = NULL;
361 }
362
363 PG_RETURN_POINTER(n);
364}
365
366
367/*
368 * union of two BOX2Ds
369 */
371Datum BOX2D_union(PG_FUNCTION_ARGS)
372{
373 GBOX *a = (GBOX*) PG_GETARG_POINTER(0);
374 GBOX *b = (GBOX*) PG_GETARG_POINTER(1);
375 GBOX *n;
376
377 n = (GBOX *) lwalloc(sizeof(GBOX));
378 if ( ! gbox_union(a,b,n) ) PG_RETURN_NULL();
379 PG_RETURN_POINTER(n);
380}
381
382
384Datum BOX2D_expand(PG_FUNCTION_ARGS)
385{
386 GBOX *box = (GBOX *)PG_GETARG_POINTER(0);
387 GBOX *result = (GBOX *)palloc(sizeof(GBOX));
388 memcpy(result, box, sizeof(GBOX));
389
390 if (PG_NARGS() == 2)
391 {
392 double d = PG_GETARG_FLOAT8(1);
393 gbox_expand(result, d);
394 }
395 else
396 {
397 double dx = PG_GETARG_FLOAT8(1);
398 double dy = PG_GETARG_FLOAT8(2);
399
400 gbox_expand_xyzm(result, dx, dy, 0, 0);
401 }
402
403 PG_RETURN_POINTER(result);
404}
405
407Datum BOX2D_to_BOX3D(PG_FUNCTION_ARGS)
408{
409 GBOX *box = (GBOX *)PG_GETARG_POINTER(0);
410 BOX3D *result = box3d_from_gbox(box);
411 PG_RETURN_POINTER(result);
412}
413
415Datum BOX2D_combine(PG_FUNCTION_ARGS)
416{
417 Pointer box2d_ptr = PG_GETARG_POINTER(0);
418 Pointer geom_ptr = PG_GETARG_POINTER(1);
419 GBOX *a,*b;
420 GSERIALIZED *lwgeom;
421 GBOX box, *result;
422
423 if ( (box2d_ptr == NULL) && (geom_ptr == NULL) )
424 {
425 PG_RETURN_NULL(); /* combine_box2d(null,null) => null */
426 }
427
428 result = (GBOX *)palloc(sizeof(GBOX));
429
430 if (box2d_ptr == NULL)
431 {
432 lwgeom = PG_GETARG_GSERIALIZED_P(1);
433 /* empty geom would make getbox2d_p return NULL */
434 if ( ! gserialized_get_gbox_p(lwgeom, &box) ) PG_RETURN_NULL();
435 memcpy(result, &box, sizeof(GBOX));
436 PG_RETURN_POINTER(result);
437 }
438
439 /* combine_bbox(BOX3D, null) => BOX3D */
440 if (geom_ptr == NULL)
441 {
442 memcpy(result, (char *)PG_GETARG_DATUM(0), sizeof(GBOX));
443 PG_RETURN_POINTER(result);
444 }
445
446 /*combine_bbox(BOX3D, geometry) => union(BOX3D, geometry->bvol) */
447
448 lwgeom = PG_GETARG_GSERIALIZED_P(1);
449 if ( ! gserialized_get_gbox_p(lwgeom, &box) )
450 {
451 /* must be the empty geom */
452 memcpy(result, (char *)PG_GETARG_DATUM(0), sizeof(GBOX));
453 PG_RETURN_POINTER(result);
454 }
455
456 a = (GBOX *)PG_GETARG_DATUM(0);
457 b = &box;
458
459 result->xmax = Max(a->xmax, b->xmax);
460 result->ymax = Max(a->ymax, b->ymax);
461 result->xmin = Min(a->xmin, b->xmin);
462 result->ymin = Min(a->ymin, b->ymin);
463
464 PG_RETURN_POINTER(result);
465}
466
468Datum BOX2D_to_LWGEOM(PG_FUNCTION_ARGS)
469{
470 GBOX *box = (GBOX *)PG_GETARG_POINTER(0);
471 POINTARRAY *pa = ptarray_construct_empty(0, 0, 5);
472 POINT4D pt;
473 GSERIALIZED *result;
474
475
476 /*
477 * Alter BOX2D cast so that a valid geometry is always
478 * returned depending upon the size of the BOX2D. The
479 * code makes the following assumptions:
480 * - If the BOX2D is a single point then return a
481 * POINT geometry
482 * - If the BOX2D represents either a horizontal or
483 * vertical line, return a LINESTRING geometry
484 * - Otherwise return a POLYGON
485 */
486
487 if ( (box->xmin == box->xmax) && (box->ymin == box->ymax) )
488 {
489 /* Construct and serialize point */
490 LWPOINT *point = lwpoint_make2d(SRID_UNKNOWN, box->xmin, box->ymin);
491 result = geometry_serialize(lwpoint_as_lwgeom(point));
492 lwpoint_free(point);
493 }
494 else if ( (box->xmin == box->xmax) || (box->ymin == box->ymax) )
495 {
496 LWLINE *line;
497
498 /* Assign coordinates to point array */
499 pt.x = box->xmin;
500 pt.y = box->ymin;
502 pt.x = box->xmax;
503 pt.y = box->ymax;
505
506 /* Construct and serialize linestring */
507 line = lwline_construct(SRID_UNKNOWN, NULL, pa);
508 result = geometry_serialize(lwline_as_lwgeom(line));
509 lwline_free(line);
510 }
511 else
512 {
513 POINT4D points[4];
514 LWPOLY *poly;
515
516 /* Initialize the 4 vertices of the polygon */
517 points[0] = (POINT4D) { box->xmin, box->ymin, 0.0, 0.0 };
518 points[1] = (POINT4D) { box->xmin, box->ymax, 0.0, 0.0 };
519 points[2] = (POINT4D) { box->xmax, box->ymax, 0.0, 0.0 };
520 points[3] = (POINT4D) { box->xmax, box->ymin, 0.0, 0.0 };
521
522 /* Construct polygon */
523 poly = lwpoly_construct_rectangle(LW_FALSE, LW_FALSE, &points[0], &points[1],
524 &points[2], &points[3]);
525 result = geometry_serialize(lwpoly_as_lwgeom(poly));
526 lwpoly_free(poly);
527 }
528
529 PG_RETURN_POINTER(result);
530}
531
533Datum BOX2D_construct(PG_FUNCTION_ARGS)
534{
535 GSERIALIZED *pgmin = PG_GETARG_GSERIALIZED_P(0);
536 GSERIALIZED *pgmax = PG_GETARG_GSERIALIZED_P(1);
537 GBOX *result;
538 LWPOINT *minpoint, *maxpoint;
539 double min, max, tmp;
540 gserialized_error_if_srid_mismatch(pgmin, pgmax, __func__);
541
542 minpoint = (LWPOINT*)lwgeom_from_gserialized(pgmin);
543 maxpoint = (LWPOINT*)lwgeom_from_gserialized(pgmax);
544
545 if ( (minpoint->type != POINTTYPE) || (maxpoint->type != POINTTYPE) )
546 {
547 elog(ERROR, "BOX2D_construct: arguments must be points");
548 PG_RETURN_NULL();
549 }
550
551 if (lwpoint_is_empty(minpoint) || lwpoint_is_empty(maxpoint) ){
552 elog(ERROR, "BOX2D_construct: args can not be empty points");
553 PG_RETURN_NULL();
554 }
555
556 result = gbox_new(lwflags(0, 0, 0));
557
558 /* Process X min/max */
559 min = lwpoint_get_x(minpoint);
560 max = lwpoint_get_x(maxpoint);
561 if ( min > max )
562 {
563 tmp = min;
564 min = max;
565 max = tmp;
566 }
567 result->xmin = min;
568 result->xmax = max;
569
570 /* Process Y min/max */
571 min = lwpoint_get_y(minpoint);
572 max = lwpoint_get_y(maxpoint);
573 if ( min > max )
574 {
575 tmp = min;
576 min = max;
577 max = tmp;
578 }
579 result->ymin = min;
580 result->ymax = max;
581
582 PG_RETURN_POINTER(result);
583}
584
int gbox_union(const GBOX *g1, const GBOX *g2, GBOX *gout)
Update the output GBOX to be large enough to include both inputs.
Definition gbox.c:135
GBOX * gbox_new(lwflags_t flags)
Create a new gbox with the dimensionality indicated by the flags.
Definition gbox.c:32
void gbox_expand(GBOX *g, double d)
Move the box minimums down and the maximums up by the distance provided.
Definition gbox.c:97
void gbox_init(GBOX *gbox)
Zero out all the entries in the GBOX.
Definition gbox.c:40
void gbox_expand_xyzm(GBOX *g, double dx, double dy, double dz, double dm)
Move the box minimums down and the maximums up by the distances provided.
Definition gbox.c:115
BOX3D * box3d_from_gbox(const GBOX *gbox)
Definition gbox.c:53
GBOX * gbox_copy(const GBOX *box)
Return a copy of the GBOX, based on dimensionality of flags.
Definition gbox.c:426
void gserialized_error_if_srid_mismatch(const GSERIALIZED *g1, const GSERIALIZED *g2, const char *funcname)
LWGEOM * lwgeom_from_gserialized(const GSERIALIZED *g)
Allocate a new LWGEOM from a GSERIALIZED.
int gserialized_get_gbox_p(const GSERIALIZED *g, GBOX *gbox)
Read the box from the GSERIALIZED or calculate it if necessary.
Definition gserialized.c:65
LWGEOM * lwpoint_as_lwgeom(const LWPOINT *obj)
Definition lwgeom.c:326
#define LW_FALSE
Definition liblwgeom.h:108
void lwpoint_free(LWPOINT *pt)
Definition lwpoint.c:213
#define LW_FAILURE
Definition liblwgeom.h:110
double lwpoint_get_x(const LWPOINT *point)
Definition lwpoint.c:63
POINTARRAY * ptarray_construct_empty(char hasz, char hasm, uint32_t maxpoints)
Create a new POINTARRAY with no points.
Definition ptarray.c:59
#define POINTTYPE
LWTYPE numbers, used internally by PostGIS.
Definition liblwgeom.h:116
void * lwalloc(size_t size)
Definition lwutil.c:227
LWLINE * lwline_construct(int32_t srid, GBOX *bbox, POINTARRAY *points)
Definition lwline.c:42
LWPOINT * lwpoint_make2d(int32_t srid, double x, double y)
Definition lwpoint.c:163
LWGEOM * lwline_as_lwgeom(const LWLINE *obj)
Definition lwgeom.c:321
LWPOLY * lwpoly_construct_rectangle(char hasz, char hasm, POINT4D *p1, POINT4D *p2, POINT4D *p3, POINT4D *p4)
Definition lwpoly.c:80
int lwgeom_calculate_gbox(const LWGEOM *lwgeom, GBOX *gbox)
Calculate bounding box of a geometry, automatically taking into account whether it is cartesian or ge...
Definition lwgeom.c:737
int ptarray_append_point(POINTARRAY *pa, const POINT4D *pt, int allow_duplicates)
Append a point to the end of an existing POINTARRAY If allow_duplicate is LW_FALSE,...
Definition ptarray.c:147
void lwpoly_free(LWPOLY *poly)
Definition lwpoly.c:175
lwflags_t lwflags(int hasz, int hasm, int geodetic)
Construct a new flags bitmask.
Definition lwutil.c:471
#define LW_TRUE
Return types for functions with status returns.
Definition liblwgeom.h:107
#define FLAGS_SET_M(flags, value)
Definition liblwgeom.h:187
#define SRID_UNKNOWN
Unknown SRID value.
Definition liblwgeom.h:229
#define FLAGS_SET_Z(flags, value)
Definition liblwgeom.h:186
LWGEOM * lwpoly_as_lwgeom(const LWPOLY *obj)
Definition lwgeom.c:311
void lwline_free(LWLINE *line)
Definition lwline.c:67
double lwpoint_get_y(const LWPOINT *point)
Definition lwpoint.c:76
This library is the generic geometry handling section of PostGIS.
int lwpoint_is_empty(const LWPOINT *point)
Datum BOX2D_below(PG_FUNCTION_ARGS)
Definition lwgeom_box.c:276
Datum BOX2D_left(PG_FUNCTION_ARGS)
Definition lwgeom_box.c:226
Datum BOX2D_overleft(PG_FUNCTION_ARGS)
Definition lwgeom_box.c:214
Datum BOX2D_contain(PG_FUNCTION_ARGS)
Definition lwgeom_box.c:328
Datum BOX2D_overright(PG_FUNCTION_ARGS)
Definition lwgeom_box.c:251
Datum BOX2D_contained(PG_FUNCTION_ARGS)
Definition lwgeom_box.c:313
Datum LWGEOM_to_BOX2DF(PG_FUNCTION_ARGS)
Definition lwgeom_box.c:147
Datum BOX2D_overabove(PG_FUNCTION_ARGS)
Definition lwgeom_box.c:301
Datum BOX2D_right(PG_FUNCTION_ARGS)
Definition lwgeom_box.c:238
Datum BOX2D_intersects(PG_FUNCTION_ARGS)
Definition lwgeom_box.c:341
Datum BOX2D_construct(PG_FUNCTION_ARGS)
Definition lwgeom_box.c:533
Datum BOX2D_overlap(PG_FUNCTION_ARGS)
Definition lwgeom_box.c:188
Datum BOX2D_above(PG_FUNCTION_ARGS)
Definition lwgeom_box.c:288
Datum BOX2D_union(PG_FUNCTION_ARGS)
Definition lwgeom_box.c:371
Datum BOX2D_in(PG_FUNCTION_ARGS)
Definition lwgeom_box.c:56
Datum LWGEOM_to_BOX2D(PG_FUNCTION_ARGS)
Definition lwgeom_box.c:122
Datum BOX2D_same(PG_FUNCTION_ARGS)
Definition lwgeom_box.c:173
Datum BOX2D_to_BOX3D(PG_FUNCTION_ARGS)
Definition lwgeom_box.c:407
Datum BOX2D_out(PG_FUNCTION_ARGS)
Definition lwgeom_box.c:94
Datum BOX2D_expand(PG_FUNCTION_ARGS)
Definition lwgeom_box.c:384
Datum BOX2D_to_LWGEOM(PG_FUNCTION_ARGS)
Definition lwgeom_box.c:468
Datum BOX2D_overbelow(PG_FUNCTION_ARGS)
Definition lwgeom_box.c:264
PG_FUNCTION_INFO_V1(BOX2D_in)
Datum BOX2D_combine(PG_FUNCTION_ARGS)
Definition lwgeom_box.c:415
#define str(s)
static int lwgeom_is_empty(const LWGEOM *geom)
Return true or false depending on whether a geometry is an "empty" geometry (no vertices members)
Definition lwinline.h:193
GSERIALIZED * geometry_serialize(LWGEOM *lwgeom)
double ymax
Definition liblwgeom.h:343
double xmax
Definition liblwgeom.h:341
double ymin
Definition liblwgeom.h:342
double xmin
Definition liblwgeom.h:340
lwflags_t flags
Definition liblwgeom.h:339
uint8_t type
Definition liblwgeom.h:460
double x
Definition liblwgeom.h:400
double y
Definition liblwgeom.h:400