PostGIS 3.7.0dev-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#include "liblwgeom_internal.h"
38
39#include <math.h>
40#include <float.h>
41#include <string.h>
42#include <stdio.h>
43
44/* forward defs */
45Datum BOX2D_in(PG_FUNCTION_ARGS);
46Datum BOX2D_out(PG_FUNCTION_ARGS);
47Datum LWGEOM_to_BOX2D(PG_FUNCTION_ARGS);
48Datum LWGEOM_to_BOX2DF(PG_FUNCTION_ARGS);
49Datum BOX2D_expand(PG_FUNCTION_ARGS);
50Datum BOX2D_to_BOX3D(PG_FUNCTION_ARGS);
51Datum BOX2D_combine(PG_FUNCTION_ARGS);
52Datum BOX2D_to_LWGEOM(PG_FUNCTION_ARGS);
53Datum BOX2D_construct(PG_FUNCTION_ARGS);
54
55/* parser - "BOX(xmin ymin,xmax ymax)" */
57Datum BOX2D_in(PG_FUNCTION_ARGS)
58{
59 char *str = PG_GETARG_CSTRING(0);
60 int nitems;
61 double tmp;
62 GBOX box;
63 int i;
64
65 gbox_init(&box);
66
67 for(i = 0; str[i]; i++) {
68 str[i] = tolower(str[i]);
69 }
70
71 nitems = sscanf(str,"box(%lf %lf,%lf %lf)", &box.xmin, &box.ymin, &box.xmax, &box.ymax);
72 if (nitems != 4)
73 {
74 elog(ERROR,"box2d parser - couldn't parse. It should look like: BOX(xmin ymin,xmax ymax)");
75 PG_RETURN_NULL();
76 }
77
78 if (box.xmin > box.xmax)
79 {
80 tmp = box.xmin;
81 box.xmin = box.xmax;
82 box.xmax = tmp;
83 }
84 if (box.ymin > box.ymax)
85 {
86 tmp = box.ymin;
87 box.ymin = box.ymax;
88 box.ymax = tmp;
89 }
90 PG_RETURN_POINTER(gbox_copy(&box));
91}
92
93/*writer "BOX(xmin ymin,xmax ymax)" */
95Datum BOX2D_out(PG_FUNCTION_ARGS)
96{
97 char tmp[500] = {'B', 'O', 'X', '(', 0}; /* big enough */
98 static const int precision = 15;
99 char *result;
100 int size = 0;
101
102 GBOX *box = (GBOX *)PG_GETARG_POINTER(0);
103 /* Avoid unaligned access to the gbox struct */
104 GBOX box_aligned;
105 memcpy(&box_aligned, box, sizeof(GBOX));
106
107 size = 4;
108 size += lwprint_double(box_aligned.xmin, precision, &tmp[size]);
109 tmp[size++] = ' ';
110 size += lwprint_double(box_aligned.ymin, precision, &tmp[size]);
111 tmp[size++] = ',';
112 size += lwprint_double(box_aligned.xmax, precision, &tmp[size]);
113 tmp[size++] = ' ';
114 size += lwprint_double(box_aligned.ymax, precision, &tmp[size]);
115
116 tmp[size++] = ')';
117 size += 1;
118
119 result = palloc(size + 1); /* +1= null term */
120 memcpy(result, tmp, size + 1);
121 result[size] = '\0';
122
123 PG_RETURN_CSTRING(result);
124}
125
126
127/*convert a GSERIALIZED to BOX2D */
129Datum LWGEOM_to_BOX2D(PG_FUNCTION_ARGS)
130{
131 GSERIALIZED *geom = PG_GETARG_GSERIALIZED_P(0);
132 LWGEOM *lwgeom = lwgeom_from_gserialized(geom);
133 GBOX gbox;
134
135 /* Cannot box empty! */
136 if ( lwgeom_is_empty(lwgeom) )
137 PG_RETURN_NULL();
138
139 /* Cannot calculate box? */
140 if ( lwgeom_calculate_gbox(lwgeom, &gbox) == LW_FAILURE )
141 PG_RETURN_NULL();
142
143 /* Strip out higher dimensions */
144 FLAGS_SET_Z(gbox.flags, 0);
145 FLAGS_SET_M(gbox.flags, 0);
146
147 PG_FREE_IF_COPY(geom, 0);
148 PG_RETURN_POINTER(gbox_copy(&gbox));
149}
150
151
152/*convert a GSERIALIZED to BOX2D */
154Datum LWGEOM_to_BOX2DF(PG_FUNCTION_ARGS)
155{
156 GBOX gbox;
157 if (gserialized_datum_get_gbox_p(PG_GETARG_DATUM(0), &gbox) == LW_FAILURE)
158 PG_RETURN_NULL();
159
160 /* Strip out higher dimensions */
161 FLAGS_SET_Z(gbox.flags, 0);
162 FLAGS_SET_M(gbox.flags, 0);
163 PG_RETURN_POINTER(gbox_copy(&gbox));
164}
165
166
167/*----------------------------------------------------------
168 * Relational operators for BOXes.
169 * <, >, <=, >=, and == are based on box area.
170 *---------------------------------------------------------*/
171
172/*
173 * box_same - are two boxes identical?
174 */
176Datum BOX2D_same(PG_FUNCTION_ARGS)
177{
178 GBOX *box1 = (GBOX *) PG_GETARG_POINTER(0);
179 GBOX *box2 = (GBOX *) PG_GETARG_POINTER(1);
180
181 PG_RETURN_BOOL(FPeq(box1->xmax, box2->xmax) &&
182 FPeq(box1->xmin, box2->xmin) &&
183 FPeq(box1->ymax, box2->ymax) &&
184 FPeq(box1->ymin, box2->ymin));
185}
186
187/*
188 * box_overlap - does box1 overlap box2?
189 */
191Datum BOX2D_overlap(PG_FUNCTION_ARGS)
192{
193 GBOX *box1 = (GBOX *) PG_GETARG_POINTER(0);
194 GBOX *box2 = (GBOX *) PG_GETARG_POINTER(1);
195 bool result;
196
197
198 result = ((FPge(box1->xmax, box2->xmax) &&
199 FPle(box1->xmin, box2->xmax)) ||
200 (FPge(box2->xmax, box1->xmax) &&
201 FPle(box2->xmin, box1->xmax)))
202 &&
203 ((FPge(box1->ymax, box2->ymax) &&
204 FPle(box1->ymin, box2->ymax)) ||
205 (FPge(box2->ymax, box1->ymax) &&
206 FPle(box2->ymin, box1->ymax)));
207
208 PG_RETURN_BOOL(result);
209}
210
211
212/*
213 * box_overleft - is the right edge of box1 to the left of
214 * the right edge of box2?
215 */
217Datum BOX2D_overleft(PG_FUNCTION_ARGS)
218{
219 GBOX *box1 = (GBOX *) PG_GETARG_POINTER(0);
220 GBOX *box2 = (GBOX *) PG_GETARG_POINTER(1);
221
222 PG_RETURN_BOOL(FPle(box1->xmax, box2->xmax));
223}
224
225/*
226 * box_left - is box1 strictly left of box2?
227 */
229Datum BOX2D_left(PG_FUNCTION_ARGS)
230{
231 GBOX *box1 = (GBOX *) PG_GETARG_POINTER(0);
232 GBOX *box2 = (GBOX *) PG_GETARG_POINTER(1);
233
234 PG_RETURN_BOOL(FPlt(box1->xmax, box2->xmin));
235}
236
237/*
238 * box_right - is box1 strictly right of box2?
239 */
241Datum BOX2D_right(PG_FUNCTION_ARGS)
242{
243 GBOX *box1 = (GBOX *) PG_GETARG_POINTER(0);
244 GBOX *box2 = (GBOX *) PG_GETARG_POINTER(1);
245
246 PG_RETURN_BOOL(FPgt(box1->xmin, box2->xmax));
247}
248
249/*
250 * box_overright - is the left edge of box1 to the right of
251 * the left edge of box2?
252 */
254Datum BOX2D_overright(PG_FUNCTION_ARGS)
255{
256 GBOX *box1 = (GBOX *) PG_GETARG_POINTER(0);
257 GBOX *box2 = (GBOX *) PG_GETARG_POINTER(1);
258
259 PG_RETURN_BOOL(FPge(box1->xmin, box2->xmin));
260}
261
262/*
263 * box_overbelow - is the bottom edge of box1 below
264 * the bottom edge of box2?
265 */
267Datum BOX2D_overbelow(PG_FUNCTION_ARGS)
268{
269 GBOX *box1 = (GBOX *) PG_GETARG_POINTER(0);
270 GBOX *box2 = (GBOX *) PG_GETARG_POINTER(1);
271
272 PG_RETURN_BOOL(FPle(box1->ymax, box2->ymax));
273}
274
275/*
276 * box_below - is box1 strictly below box2?
277 */
279Datum BOX2D_below(PG_FUNCTION_ARGS)
280{
281 GBOX *box1 = (GBOX *) PG_GETARG_POINTER(0);
282 GBOX *box2 = (GBOX *) PG_GETARG_POINTER(1);
283
284 PG_RETURN_BOOL(FPlt(box1->ymax, box2->ymin));
285}
286
287/*
288 * box_above - is box1 strictly above box2?
289 */
291Datum BOX2D_above(PG_FUNCTION_ARGS)
292{
293 GBOX *box1 = (GBOX *) PG_GETARG_POINTER(0);
294 GBOX *box2 = (GBOX *) PG_GETARG_POINTER(1);
295
296 PG_RETURN_BOOL(FPgt(box1->ymin, box2->ymax));
297}
298
299/*
300 * box_overabove - the top edge of box1 above
301 * the top edge of box2?
302 */
304Datum BOX2D_overabove(PG_FUNCTION_ARGS)
305{
306 GBOX *box1 = (GBOX *) PG_GETARG_POINTER(0);
307 GBOX *box2 = (GBOX *) PG_GETARG_POINTER(1);
308
309 PG_RETURN_BOOL(FPge(box1->ymin, box2->ymin));
310}
311
312/*
313 * box_contained - is box1 contained by box2?
314 */
316Datum BOX2D_contained(PG_FUNCTION_ARGS)
317{
318 GBOX *box1 =(GBOX *) PG_GETARG_POINTER(0);
319 GBOX *box2 = (GBOX *) PG_GETARG_POINTER(1);
320
321 PG_RETURN_BOOL(FPle(box1->xmax, box2->xmax) &&
322 FPge(box1->xmin, box2->xmin) &&
323 FPle(box1->ymax, box2->ymax) &&
324 FPge(box1->ymin, box2->ymin));
325}
326
327/*
328 * box_contain - does box1 contain box2?
329 */
331Datum BOX2D_contain(PG_FUNCTION_ARGS)
332{
333 GBOX *box1 = (GBOX *) PG_GETARG_POINTER(0);
334 GBOX *box2 = (GBOX *) PG_GETARG_POINTER(1);
335
336 PG_RETURN_BOOL(FPge(box1->xmax, box2->xmax) &&
337 FPle(box1->xmin, box2->xmin) &&
338 FPge(box1->ymax, box2->ymax) &&
339 FPle(box1->ymin, box2->ymin));
340
341}
342
344Datum BOX2D_intersects(PG_FUNCTION_ARGS)
345{
346 GBOX *a = (GBOX *) PG_GETARG_POINTER(0);
347 GBOX *b = (GBOX *) PG_GETARG_POINTER(1);
348 GBOX *n;
349
350
351 n = (GBOX *) palloc(sizeof(GBOX));
352
353 n->xmax = Min(a->xmax, b->xmax);
354 n->ymax = Min(a->ymax, b->ymax);
355 n->xmin = Max(a->xmin, b->xmin);
356 n->ymin = Max(a->ymin, b->ymin);
357
358
359 if (n->xmax < n->xmin || n->ymax < n->ymin)
360 {
361 pfree(n);
362 /* Indicate "no intersection" by returning NULL pointer */
363 n = NULL;
364 }
365
366 PG_RETURN_POINTER(n);
367}
368
369
370/*
371 * union of two BOX2Ds
372 */
374Datum BOX2D_union(PG_FUNCTION_ARGS)
375{
376 GBOX *a = (GBOX*) PG_GETARG_POINTER(0);
377 GBOX *b = (GBOX*) PG_GETARG_POINTER(1);
378 GBOX *n;
379
380 n = (GBOX *) lwalloc(sizeof(GBOX));
381 if ( ! gbox_union(a,b,n) ) PG_RETURN_NULL();
382 PG_RETURN_POINTER(n);
383}
384
385
387Datum BOX2D_expand(PG_FUNCTION_ARGS)
388{
389 GBOX *box = (GBOX *)PG_GETARG_POINTER(0);
390 GBOX *result = (GBOX *)palloc(sizeof(GBOX));
391 memcpy(result, box, sizeof(GBOX));
392
393 if (PG_NARGS() == 2)
394 {
395 double d = PG_GETARG_FLOAT8(1);
397 }
398 else
399 {
400 double dx = PG_GETARG_FLOAT8(1);
401 double dy = PG_GETARG_FLOAT8(2);
402
403 gbox_expand_xyzm(result, dx, dy, 0, 0);
404 }
405
406 PG_RETURN_POINTER(result);
407}
408
410Datum BOX2D_to_BOX3D(PG_FUNCTION_ARGS)
411{
412 GBOX *box = (GBOX *)PG_GETARG_POINTER(0);
414 PG_RETURN_POINTER(result);
415}
416
418Datum BOX2D_combine(PG_FUNCTION_ARGS)
419{
420 static const uint32_t box2d_idx = 0;
421 static const uint32_t geom_idx = 1;
422 GBOX *a,*b;
423 GBOX box, *result;
424
425 if (PG_ARGISNULL(box2d_idx) && PG_ARGISNULL(geom_idx))
426 {
427 PG_RETURN_NULL(); /* combine_box2d(null,null) => null */
428 }
429
430 result = (GBOX *)palloc(sizeof(GBOX));
431
432 if (PG_ARGISNULL(box2d_idx))
433 {
434 /* empty geom would make getbox2d_p return NULL */
435 if (!gserialized_datum_get_gbox_p(PG_GETARG_DATUM(geom_idx), &box))
436 PG_RETURN_NULL();
437 memcpy(result, &box, sizeof(GBOX));
438 PG_RETURN_POINTER(result);
439 }
440
441 /* combine_bbox(BOX3D, null) => BOX3D */
442 if (PG_ARGISNULL(geom_idx))
443 {
444 memcpy(result, (char *)PG_GETARG_DATUM(box2d_idx), sizeof(GBOX));
445 PG_RETURN_POINTER(result);
446 }
447
448 /*combine_bbox(BOX3D, geometry) => union(BOX3D, geometry->bvol) */
449
450 if (!gserialized_datum_get_gbox_p(PG_GETARG_DATUM(geom_idx), &box))
451 {
452 /* must be the empty geom */
453 memcpy(result, (char *)PG_GETARG_DATUM(box2d_idx), sizeof(GBOX));
454 PG_RETURN_POINTER(result);
455 }
456
457 a = (GBOX *)PG_GETARG_DATUM(box2d_idx);
458 b = &box;
459
460 result->xmax = Max(a->xmax, b->xmax);
461 result->ymax = Max(a->ymax, b->ymax);
462 result->xmin = Min(a->xmin, b->xmin);
463 result->ymin = Min(a->ymin, b->ymin);
464
465 PG_RETURN_POINTER(result);
466}
467
469Datum BOX2D_to_LWGEOM(PG_FUNCTION_ARGS)
470{
471 GBOX *box = (GBOX *)PG_GETARG_POINTER(0);
472 POINTARRAY *pa = ptarray_construct_empty(0, 0, 5);
473 POINT4D pt;
475
476
477 /*
478 * Alter BOX2D cast so that a valid geometry is always
479 * returned depending upon the size of the BOX2D. The
480 * code makes the following assumptions:
481 * - If the BOX2D is a single point then return a
482 * POINT geometry
483 * - If the BOX2D represents either a horizontal or
484 * vertical line, return a LINESTRING geometry
485 * - Otherwise return a POLYGON
486 */
487
488 if ( (box->xmin == box->xmax) && (box->ymin == box->ymax) )
489 {
490 /* Construct and serialize point */
491 LWPOINT *point = lwpoint_make2d(SRID_UNKNOWN, box->xmin, box->ymin);
492 result = geometry_serialize(lwpoint_as_lwgeom(point));
493 lwpoint_free(point);
494 }
495 else if ( (box->xmin == box->xmax) || (box->ymin == box->ymax) )
496 {
497 LWLINE *line;
498
499 /* Assign coordinates to point array */
500 pt.x = box->xmin;
501 pt.y = box->ymin;
503 pt.x = box->xmax;
504 pt.y = box->ymax;
506
507 /* Construct and serialize linestring */
508 line = lwline_construct(SRID_UNKNOWN, NULL, pa);
509 result = geometry_serialize(lwline_as_lwgeom(line));
510 lwline_free(line);
511 }
512 else
513 {
514 POINT4D points[4];
515 LWPOLY *poly;
516
517 /* Initialize the 4 vertices of the polygon */
518 points[0] = (POINT4D) { box->xmin, box->ymin, 0.0, 0.0 };
519 points[1] = (POINT4D) { box->xmin, box->ymax, 0.0, 0.0 };
520 points[2] = (POINT4D) { box->xmax, box->ymax, 0.0, 0.0 };
521 points[3] = (POINT4D) { box->xmax, box->ymin, 0.0, 0.0 };
522
523 /* Construct polygon */
524 poly = lwpoly_construct_rectangle(LW_FALSE, LW_FALSE, &points[0], &points[1],
525 &points[2], &points[3]);
526 result = geometry_serialize(lwpoly_as_lwgeom(poly));
527 lwpoly_free(poly);
528 }
529
530 PG_RETURN_POINTER(result);
531}
532
534Datum BOX2D_construct(PG_FUNCTION_ARGS)
535{
536 GSERIALIZED *pgmin = PG_GETARG_GSERIALIZED_P(0);
537 GSERIALIZED *pgmax = PG_GETARG_GSERIALIZED_P(1);
538 GBOX *result;
539 LWPOINT *minpoint, *maxpoint;
540 double min, max, tmp;
541 gserialized_error_if_srid_mismatch(pgmin, pgmax, __func__);
542
543 minpoint = (LWPOINT*)lwgeom_from_gserialized(pgmin);
544 maxpoint = (LWPOINT*)lwgeom_from_gserialized(pgmax);
545
546 if ( (minpoint->type != POINTTYPE) || (maxpoint->type != POINTTYPE) )
547 {
548 elog(ERROR, "BOX2D_construct: arguments must be points");
549 PG_RETURN_NULL();
550 }
551
552 if (lwpoint_is_empty(minpoint) || lwpoint_is_empty(maxpoint) ){
553 elog(ERROR, "BOX2D_construct: args can not be empty points");
554 PG_RETURN_NULL();
555 }
556
557 result = gbox_new(lwflags(0, 0, 0));
558
559 /* Process X min/max */
560 min = lwpoint_get_x(minpoint);
561 max = lwpoint_get_x(maxpoint);
562 if ( min > max )
563 {
564 tmp = min;
565 min = max;
566 max = tmp;
567 }
568 result->xmin = min;
569 result->xmax = max;
570
571 /* Process Y min/max */
572 min = lwpoint_get_y(minpoint);
573 max = lwpoint_get_y(maxpoint);
574 if ( min > max )
575 {
576 tmp = min;
577 min = max;
578 max = tmp;
579 }
580 result->ymin = min;
581 result->ymax = max;
582
583 PG_RETURN_POINTER(result);
584}
585
static uint8_t precision
Definition cu_in_twkb.c:25
char result[OUT_DOUBLE_BUFFER_SIZE]
Definition cu_print.c:267
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:438
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_datum_get_gbox_p(Datum gsdatum, GBOX *gbox)
Given a GSERIALIZED datum, as quickly as possible (peaking into the top of the memory) return the gbo...
LWGEOM * lwpoint_as_lwgeom(const LWPOINT *obj)
Definition lwgeom.c:372
#define LW_FALSE
Definition liblwgeom.h:94
void lwpoint_free(LWPOINT *pt)
Definition lwpoint.c:213
#define LW_FAILURE
Definition liblwgeom.h:96
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:102
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:367
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:783
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:477
#define LW_TRUE
Return types for functions with status returns.
Definition liblwgeom.h:93
#define FLAGS_SET_M(flags, value)
Definition liblwgeom.h:173
#define SRID_UNKNOWN
Unknown SRID value.
Definition liblwgeom.h:215
#define FLAGS_SET_Z(flags, value)
Definition liblwgeom.h:172
LWGEOM * lwpoly_as_lwgeom(const LWPOLY *obj)
Definition lwgeom.c:357
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)
int lwprint_double(double d, int maxdd, char *buf)
Definition lwprint.c:463
Datum BOX2D_below(PG_FUNCTION_ARGS)
Definition lwgeom_box.c:279
Datum BOX2D_left(PG_FUNCTION_ARGS)
Definition lwgeom_box.c:229
Datum BOX2D_overleft(PG_FUNCTION_ARGS)
Definition lwgeom_box.c:217
Datum BOX2D_contain(PG_FUNCTION_ARGS)
Definition lwgeom_box.c:331
Datum BOX2D_overright(PG_FUNCTION_ARGS)
Definition lwgeom_box.c:254
Datum BOX2D_contained(PG_FUNCTION_ARGS)
Definition lwgeom_box.c:316
Datum LWGEOM_to_BOX2DF(PG_FUNCTION_ARGS)
Definition lwgeom_box.c:154
Datum BOX2D_overabove(PG_FUNCTION_ARGS)
Definition lwgeom_box.c:304
Datum BOX2D_right(PG_FUNCTION_ARGS)
Definition lwgeom_box.c:241
Datum BOX2D_intersects(PG_FUNCTION_ARGS)
Definition lwgeom_box.c:344
Datum BOX2D_construct(PG_FUNCTION_ARGS)
Definition lwgeom_box.c:534
Datum BOX2D_overlap(PG_FUNCTION_ARGS)
Definition lwgeom_box.c:191
Datum BOX2D_above(PG_FUNCTION_ARGS)
Definition lwgeom_box.c:291
Datum BOX2D_union(PG_FUNCTION_ARGS)
Definition lwgeom_box.c:374
Datum BOX2D_in(PG_FUNCTION_ARGS)
Definition lwgeom_box.c:57
Datum LWGEOM_to_BOX2D(PG_FUNCTION_ARGS)
Definition lwgeom_box.c:129
Datum BOX2D_same(PG_FUNCTION_ARGS)
Definition lwgeom_box.c:176
Datum BOX2D_to_BOX3D(PG_FUNCTION_ARGS)
Definition lwgeom_box.c:410
Datum BOX2D_out(PG_FUNCTION_ARGS)
Definition lwgeom_box.c:95
Datum BOX2D_expand(PG_FUNCTION_ARGS)
Definition lwgeom_box.c:387
Datum BOX2D_to_LWGEOM(PG_FUNCTION_ARGS)
Definition lwgeom_box.c:469
Datum BOX2D_overbelow(PG_FUNCTION_ARGS)
Definition lwgeom_box.c:267
PG_FUNCTION_INFO_V1(BOX2D_in)
Datum BOX2D_combine(PG_FUNCTION_ARGS)
Definition lwgeom_box.c:418
#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:199
double ymax
Definition liblwgeom.h:357
double xmax
Definition liblwgeom.h:355
double ymin
Definition liblwgeom.h:356
double xmin
Definition liblwgeom.h:354
lwflags_t flags
Definition liblwgeom.h:353
uint8_t type
Definition liblwgeom.h:474
double x
Definition liblwgeom.h:414
double y
Definition liblwgeom.h:414