PostGIS  3.4.0dev-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 #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 */
45 Datum BOX2D_in(PG_FUNCTION_ARGS);
46 Datum BOX2D_out(PG_FUNCTION_ARGS);
47 Datum LWGEOM_to_BOX2D(PG_FUNCTION_ARGS);
48 Datum LWGEOM_to_BOX2DF(PG_FUNCTION_ARGS);
49 Datum BOX2D_expand(PG_FUNCTION_ARGS);
50 Datum BOX2D_to_BOX3D(PG_FUNCTION_ARGS);
51 Datum BOX2D_combine(PG_FUNCTION_ARGS);
52 Datum BOX2D_to_LWGEOM(PG_FUNCTION_ARGS);
53 Datum BOX2D_construct(PG_FUNCTION_ARGS);
54 
55 /* parser - "BOX(xmin ymin,xmax ymax)" */
57 Datum 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)" */
95 Datum 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 */
129 Datum 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 */
154 Datum 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  */
176 Datum 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  */
191 Datum 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  */
217 Datum 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  */
229 Datum 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  */
241 Datum 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  */
254 Datum 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  */
267 Datum 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  */
279 Datum 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  */
291 Datum 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  */
304 Datum 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  */
316 Datum 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  */
331 Datum 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 
344 Datum 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  */
374 Datum 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 
387 Datum 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);
396  gbox_expand(result, d);
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 
410 Datum BOX2D_to_BOX3D(PG_FUNCTION_ARGS)
411 {
412  GBOX *box = (GBOX *)PG_GETARG_POINTER(0);
413  BOX3D *result = box3d_from_gbox(box);
414  PG_RETURN_POINTER(result);
415 }
416 
418 Datum 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 
469 Datum 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;
502  ptarray_append_point(pa, &pt, LW_TRUE);
503  pt.x = box->xmax;
504  pt.y = box->ymax;
505  ptarray_append_point(pa, &pt, LW_TRUE);
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 
534 Datum 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:262
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:403
LWGEOM * lwgeom_from_gserialized(const GSERIALIZED *g)
Allocate a new LWGEOM from a GSERIALIZED.
Definition: gserialized.c:239
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 * lwline_as_lwgeom(const LWLINE *obj)
Definition: lwgeom.c:339
#define LW_FALSE
Definition: liblwgeom.h:94
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:96
LWGEOM * lwpoly_as_lwgeom(const LWPOLY *obj)
Definition: lwgeom.c:329
double lwpoint_get_x(const LWPOINT *point)
Definition: lwpoint.c:63
#define POINTTYPE
LWTYPE numbers, used internally by PostGIS.
Definition: liblwgeom.h:102
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:344
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:755
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: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
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:457
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:203
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