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