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