PostGIS  3.0.6dev-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  *
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 */
44 Datum BOX2D_in(PG_FUNCTION_ARGS);
45 Datum BOX2D_out(PG_FUNCTION_ARGS);
46 Datum LWGEOM_to_BOX2D(PG_FUNCTION_ARGS);
47 Datum LWGEOM_to_BOX2DF(PG_FUNCTION_ARGS);
48 Datum BOX2D_expand(PG_FUNCTION_ARGS);
49 Datum BOX2D_to_BOX3D(PG_FUNCTION_ARGS);
50 Datum BOX2D_combine(PG_FUNCTION_ARGS);
51 Datum BOX2D_to_LWGEOM(PG_FUNCTION_ARGS);
52 Datum BOX2D_construct(PG_FUNCTION_ARGS);
53 
54 /* parser - "BOX(xmin ymin,xmax ymax)" */
56 Datum 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)" */
94 Datum 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 */
122 Datum 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 */
147 Datum 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  */
173 Datum 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  */
188 Datum 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  */
214 Datum 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  */
226 Datum 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  */
238 Datum 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  */
251 Datum 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  */
264 Datum 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  */
276 Datum 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  */
288 Datum 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  */
301 Datum 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  */
313 Datum 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  */
328 Datum 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 
341 Datum 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  */
371 Datum 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 
384 Datum 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 
407 Datum 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 
415 Datum 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 
468 Datum 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;
501  ptarray_append_point(pa, &pt, LW_TRUE);
502  pt.x = box->xmax;
503  pt.y = box->ymax;
504  ptarray_append_point(pa, &pt, LW_TRUE);
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 
533 Datum 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
void gbox_expand(GBOX *g, double d)
Move the box minimums down and the maximums up by the distance provided.
Definition: gbox.c:97
BOX3D * box3d_from_gbox(const GBOX *gbox)
Definition: gbox.c:53
GBOX * gbox_new(lwflags_t flags)
Create a new gbox with the dimensionality indicated by the flags.
Definition: gbox.c:32
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
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)
Definition: gserialized.c:404
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 * lwgeom_from_gserialized(const GSERIALIZED *g)
Allocate a new LWGEOM from a GSERIALIZED.
Definition: gserialized.c:239
LWGEOM * lwline_as_lwgeom(const LWLINE *obj)
Definition: lwgeom.c:321
#define LW_FALSE
Definition: liblwgeom.h:108
LWPOINT * lwpoint_make2d(int32_t srid, double x, double y)
Definition: lwpoint.c:163
void lwpoint_free(LWPOINT *pt)
Definition: lwpoint.c:213
#define LW_FAILURE
Definition: liblwgeom.h:110
LWGEOM * lwpoly_as_lwgeom(const LWPOLY *obj)
Definition: lwgeom.c:311
double lwpoint_get_x(const LWPOINT *point)
Definition: lwpoint.c:63
#define POINTTYPE
LWTYPE numbers, used internally by PostGIS.
Definition: liblwgeom.h:116
LWLINE * lwline_construct(int32_t srid, GBOX *bbox, POINTARRAY *points)
Definition: lwline.c:42
LWPOLY * lwpoly_construct_rectangle(char hasz, char hasm, POINT4D *p1, POINT4D *p2, POINT4D *p3, POINT4D *p4)
Definition: lwpoly.c:80
LWGEOM * lwpoint_as_lwgeom(const LWPOINT *obj)
Definition: lwgeom.c:326
POINTARRAY * ptarray_construct_empty(char hasz, char hasm, uint32_t maxpoints)
Create a new POINTARRAY with no points.
Definition: ptarray.c:59
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 * lwalloc(size_t size)
Definition: lwutil.c:227
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
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