PostGIS  2.1.10dev-r@@SVN_REVISION@@
g_box.c
Go to the documentation of this file.
1 /**********************************************************************
2  * $Id: g_box.c 12901 2014-08-20 14:10:28Z pramsey $
3  *
4  * PostGIS - Spatial Types for PostgreSQL
5  * Copyright 2009 Paul Ramsey <pramsey@cleverelephant.ca>
6  *
7  * This is free software; you can redistribute and/or modify it under
8  * the terms of the GNU General Public Licence. See the COPYING file.
9  *
10  **********************************************************************/
11 
12 /* Fall back to older finite() if necessary */
13 #ifndef HAVE_ISFINITE
14 # ifdef HAVE_GNU_ISFINITE
15 # define _GNU_SOURCE
16 # else
17 # define isfinite finite
18 # endif
19 #endif
20 
21 #include "liblwgeom_internal.h"
22 #include "lwgeom_log.h"
23 #include <stdlib.h>
24 #include <math.h>
25 
26 GBOX* gbox_new(uint8_t flags)
27 {
28  GBOX *g = (GBOX*)lwalloc(sizeof(GBOX));
29  gbox_init(g);
30  g->flags = flags;
31  return g;
32 }
33 
34 void gbox_init(GBOX *gbox)
35 {
36  memset(gbox, 0, sizeof(GBOX));
37 }
38 
39 GBOX* gbox_clone(const GBOX *gbox)
40 {
41  GBOX *g = lwalloc(sizeof(GBOX));
42  memcpy(g, gbox, sizeof(GBOX));
43  return g;
44 }
45 
46 /* TODO to be removed */
47 BOX3D* box3d_from_gbox(const GBOX *gbox)
48 {
49  BOX3D *b;
50  assert(gbox);
51 
52  b = lwalloc(sizeof(BOX3D));
53 
54  b->xmin = gbox->xmin;
55  b->xmax = gbox->xmax;
56  b->ymin = gbox->ymin;
57  b->ymax = gbox->ymax;
58 
59  if ( FLAGS_GET_Z(gbox->flags) )
60  {
61  b->zmin = gbox->zmin;
62  b->zmax = gbox->zmax;
63  }
64  else
65  {
66  b->zmin = b->zmax = 0.0;
67  }
68 
69  b->srid = SRID_UNKNOWN;
70  return b;
71 }
72 
73 /* TODO to be removed */
74 GBOX* box3d_to_gbox(const BOX3D *b3d)
75 {
76  GBOX *b;
77  assert(b3d);
78 
79  b = lwalloc(sizeof(GBOX));
80 
81  b->xmin = b3d->xmin;
82  b->xmax = b3d->xmax;
83  b->ymin = b3d->ymin;
84  b->ymax = b3d->ymax;
85  b->zmin = b3d->zmin;
86  b->zmax = b3d->zmax;
87 
88  return b;
89 }
90 
91 void gbox_expand(GBOX *g, double d)
92 {
93  g->xmin -= d;
94  g->xmax += d;
95  g->ymin -= d;
96  g->ymax += d;
97  if ( FLAGS_GET_Z(g->flags) )
98  {
99  g->zmin -= d;
100  g->zmax += d;
101  }
102  if ( FLAGS_GET_M(g->flags) )
103  {
104  g->mmin -= d;
105  g->mmax += d;
106  }
107 }
108 
109 int gbox_union(const GBOX *g1, const GBOX *g2, GBOX *gout)
110 {
111  if ( ( ! g1 ) && ( ! g2 ) )
112  return LW_FALSE;
113 
114  if ( ! g1 )
115  {
116  memcpy(gout, g2, sizeof(GBOX));
117  return LW_TRUE;
118  }
119  if ( ! g2 )
120  {
121  memcpy(gout, g1, sizeof(GBOX));
122  return LW_TRUE;
123  }
124 
125  gout->flags = g1->flags;
126 
127  gout->xmin = FP_MIN(g1->xmin, g2->xmin);
128  gout->xmax = FP_MAX(g1->xmax, g2->xmax);
129 
130  gout->ymin = FP_MIN(g1->ymin, g2->ymin);
131  gout->ymax = FP_MAX(g1->ymax, g2->ymax);
132 
133  gout->zmin = FP_MIN(g1->zmin, g2->zmin);
134  gout->zmax = FP_MAX(g1->zmax, g2->zmax);
135 
136  return LW_TRUE;
137 }
138 
139 int gbox_same(const GBOX *g1, const GBOX *g2)
140 {
141  if (FLAGS_GET_ZM(g1->flags) != FLAGS_GET_ZM(g2->flags))
142  return LW_FALSE;
143 
144  if ( g1->xmin != g2->xmin || g1->ymin != g2->ymin ||
145  g1->xmax != g2->xmax || g1->ymax != g2->ymax ) return LW_FALSE;
146 
147  if (FLAGS_GET_Z(g1->flags) && (g1->zmin != g2->zmin || g1->zmax != g2->zmax))
148  return LW_FALSE;
149  if (FLAGS_GET_M(g1->flags) && (g1->mmin != g2->mmin || g1->mmax != g2->mmax))
150  return LW_FALSE;
151 
152  return LW_TRUE;
153 }
154 
155 int gbox_is_valid(const GBOX *gbox)
156 {
157  /* X */
158  if ( ! isfinite(gbox->xmin) || isnan(gbox->xmin) ||
159  ! isfinite(gbox->xmax) || isnan(gbox->xmax) )
160  return LW_FALSE;
161 
162  /* Y */
163  if ( ! isfinite(gbox->ymin) || isnan(gbox->ymin) ||
164  ! isfinite(gbox->ymax) || isnan(gbox->ymax) )
165  return LW_FALSE;
166 
167  /* Z */
168  if ( FLAGS_GET_GEODETIC(gbox->flags) || FLAGS_GET_Z(gbox->flags) )
169  {
170  if ( ! isfinite(gbox->zmin) || isnan(gbox->zmin) ||
171  ! isfinite(gbox->zmax) || isnan(gbox->zmax) )
172  return LW_FALSE;
173  }
174 
175  /* M */
176  if ( FLAGS_GET_M(gbox->flags) )
177  {
178  if ( ! isfinite(gbox->mmin) || isnan(gbox->mmin) ||
179  ! isfinite(gbox->mmax) || isnan(gbox->mmax) )
180  return LW_FALSE;
181  }
182 
183  return LW_TRUE;
184 }
185 
186 int gbox_merge_point3d(const POINT3D *p, GBOX *gbox)
187 {
188  if ( gbox->xmin > p->x ) gbox->xmin = p->x;
189  if ( gbox->ymin > p->y ) gbox->ymin = p->y;
190  if ( gbox->zmin > p->z ) gbox->zmin = p->z;
191  if ( gbox->xmax < p->x ) gbox->xmax = p->x;
192  if ( gbox->ymax < p->y ) gbox->ymax = p->y;
193  if ( gbox->zmax < p->z ) gbox->zmax = p->z;
194  return LW_SUCCESS;
195 }
196 
197 int gbox_init_point3d(const POINT3D *p, GBOX *gbox)
198 {
199  gbox->xmin = gbox->xmax = p->x;
200  gbox->ymin = gbox->ymax = p->y;
201  gbox->zmin = gbox->zmax = p->z;
202  return LW_SUCCESS;
203 }
204 
205 int gbox_contains_point3d(const GBOX *gbox, const POINT3D *pt)
206 {
207  if ( gbox->xmin > pt->x || gbox->ymin > pt->y || gbox->zmin > pt->z ||
208  gbox->xmax < pt->x || gbox->ymax < pt->y || gbox->zmax < pt->z )
209  {
210  return LW_FALSE;
211  }
212  return LW_TRUE;
213 }
214 
215 int gbox_merge(const GBOX *new_box, GBOX *merge_box)
216 {
217  assert(merge_box);
218 
219  if ( FLAGS_GET_ZM(merge_box->flags) != FLAGS_GET_ZM(new_box->flags) )
220  return LW_FAILURE;
221 
222  if ( new_box->xmin < merge_box->xmin) merge_box->xmin = new_box->xmin;
223  if ( new_box->ymin < merge_box->ymin) merge_box->ymin = new_box->ymin;
224  if ( new_box->xmax > merge_box->xmax) merge_box->xmax = new_box->xmax;
225  if ( new_box->ymax > merge_box->ymax) merge_box->ymax = new_box->ymax;
226 
227  if ( FLAGS_GET_Z(merge_box->flags) || FLAGS_GET_GEODETIC(merge_box->flags) )
228  {
229  if ( new_box->zmin < merge_box->zmin) merge_box->zmin = new_box->zmin;
230  if ( new_box->zmax > merge_box->zmax) merge_box->zmax = new_box->zmax;
231  }
232  if ( FLAGS_GET_M(merge_box->flags) )
233  {
234  if ( new_box->mmin < merge_box->mmin) merge_box->mmin = new_box->mmin;
235  if ( new_box->mmax > merge_box->mmax) merge_box->mmax = new_box->mmax;
236  }
237 
238  return LW_SUCCESS;
239 }
240 
241 int gbox_overlaps(const GBOX *g1, const GBOX *g2)
242 {
243 
244  /* Make sure our boxes are consistent */
246  lwerror("gbox_overlaps: cannot compare geodetic and non-geodetic boxes");
247 
248  /* Check X/Y first */
249  if ( g1->xmax < g2->xmin || g1->ymax < g2->ymin ||
250  g1->xmin > g2->xmax || g1->ymin > g2->ymax )
251  return LW_FALSE;
252 
253  /* Deal with the geodetic case special: we only compare the geodetic boxes (x/y/z) */
254  /* Never the M dimension */
256  {
257  if ( g1->zmax < g2->zmin || g1->zmin > g2->zmax )
258  return LW_FALSE;
259  else
260  return LW_TRUE;
261  }
262 
263  /* If both geodetic or both have Z, check Z */
264  if ( FLAGS_GET_Z(g1->flags) && FLAGS_GET_Z(g2->flags) )
265  {
266  if ( g1->zmax < g2->zmin || g1->zmin > g2->zmax )
267  return LW_FALSE;
268  }
269 
270  /* If both have M, check M */
271  if ( FLAGS_GET_M(g1->flags) && FLAGS_GET_M(g2->flags) )
272  {
273  if ( g1->mmax < g2->mmin || g1->mmin > g2->mmax )
274  return LW_FALSE;
275  }
276 
277  return LW_TRUE;
278 }
279 
280 int
281 gbox_overlaps_2d(const GBOX *g1, const GBOX *g2)
282 {
283 
284  /* Make sure our boxes are consistent */
286  lwerror("gbox_overlaps: cannot compare geodetic and non-geodetic boxes");
287 
288  /* Check X/Y first */
289  if ( g1->xmax < g2->xmin || g1->ymax < g2->ymin ||
290  g1->xmin > g2->xmax || g1->ymin > g2->ymax )
291  return LW_FALSE;
292 
293  return LW_TRUE;
294 }
295 
300 GBOX* gbox_from_string(const char *str)
301 {
302  const char *ptr = str;
303  char *nextptr;
304  char *gbox_start = strstr(str, "GBOX((");
305  GBOX *gbox = gbox_new(gflags(0,0,1));
306  if ( ! gbox_start ) return NULL; /* No header found */
307  ptr += 6;
308  gbox->xmin = strtod(ptr, &nextptr);
309  if ( ptr == nextptr ) return NULL; /* No double found */
310  ptr = nextptr + 1;
311  gbox->ymin = strtod(ptr, &nextptr);
312  if ( ptr == nextptr ) return NULL; /* No double found */
313  ptr = nextptr + 1;
314  gbox->zmin = strtod(ptr, &nextptr);
315  if ( ptr == nextptr ) return NULL; /* No double found */
316  ptr = nextptr + 3;
317  gbox->xmax = strtod(ptr, &nextptr);
318  if ( ptr == nextptr ) return NULL; /* No double found */
319  ptr = nextptr + 1;
320  gbox->ymax = strtod(ptr, &nextptr);
321  if ( ptr == nextptr ) return NULL; /* No double found */
322  ptr = nextptr + 1;
323  gbox->zmax = strtod(ptr, &nextptr);
324  if ( ptr == nextptr ) return NULL; /* No double found */
325  return gbox;
326 }
327 
328 char* gbox_to_string(const GBOX *gbox)
329 {
330  static int sz = 128;
331  char *str = NULL;
332 
333  if ( ! gbox )
334  return strdup("NULL POINTER");
335 
336  str = (char*)lwalloc(sz);
337 
338  if ( FLAGS_GET_GEODETIC(gbox->flags) )
339  {
340  snprintf(str, sz, "GBOX((%.8g,%.8g,%.8g),(%.8g,%.8g,%.8g))", gbox->xmin, gbox->ymin, gbox->zmin, gbox->xmax, gbox->ymax, gbox->zmax);
341  return str;
342  }
343  if ( FLAGS_GET_Z(gbox->flags) && FLAGS_GET_M(gbox->flags) )
344  {
345  snprintf(str, sz, "GBOX((%.8g,%.8g,%.8g,%.8g),(%.8g,%.8g,%.8g,%.8g))", gbox->xmin, gbox->ymin, gbox->zmin, gbox->mmin, gbox->xmax, gbox->ymax, gbox->zmax, gbox->mmax);
346  return str;
347  }
348  if ( FLAGS_GET_Z(gbox->flags) )
349  {
350  snprintf(str, sz, "GBOX((%.8g,%.8g,%.8g),(%.8g,%.8g,%.8g))", gbox->xmin, gbox->ymin, gbox->zmin, gbox->xmax, gbox->ymax, gbox->zmax);
351  return str;
352  }
353  if ( FLAGS_GET_M(gbox->flags) )
354  {
355  snprintf(str, sz, "GBOX((%.8g,%.8g,%.8g),(%.8g,%.8g,%.8g))", gbox->xmin, gbox->ymin, gbox->mmin, gbox->xmax, gbox->ymax, gbox->mmax);
356  return str;
357  }
358  snprintf(str, sz, "GBOX((%.8g,%.8g),(%.8g,%.8g))", gbox->xmin, gbox->ymin, gbox->xmax, gbox->ymax);
359  return str;
360 }
361 
362 GBOX* gbox_copy(const GBOX *box)
363 {
364  GBOX *copy = (GBOX*)lwalloc(sizeof(GBOX));
365  memcpy(copy, box, sizeof(GBOX));
366  return copy;
367 }
368 
369 void gbox_duplicate(const GBOX *original, GBOX *duplicate)
370 {
371  assert(duplicate);
372  memcpy(duplicate, original, sizeof(GBOX));
373 }
374 
375 size_t gbox_serialized_size(uint8_t flags)
376 {
377  if ( FLAGS_GET_GEODETIC(flags) )
378  return 6 * sizeof(float);
379  else
380  return 2 * FLAGS_NDIMS(flags) * sizeof(float);
381 }
382 
383 
384 /* ********************************************************************************
385 ** Compute cartesian bounding GBOX boxes from LWGEOM.
386 */
387 
388 int lw_arc_calculate_gbox_cartesian_2d(const POINT2D *A1, const POINT2D *A2, const POINT2D *A3, GBOX *gbox)
389 {
390  POINT2D xmin, ymin, xmax, ymax;
391  POINT2D C;
392  int A2_side;
393  double radius_A;
394 
395  LWDEBUG(2, "lw_arc_calculate_gbox_cartesian_2d called.");
396 
397  radius_A = lw_arc_center(A1, A2, A3, &C);
398 
399  /* Negative radius signals straight line, p1/p2/p3 are colinear */
400  if (radius_A < 0.0)
401  {
402  gbox->xmin = FP_MIN(A1->x, A3->x);
403  gbox->ymin = FP_MIN(A1->y, A3->y);
404  gbox->xmax = FP_MAX(A1->x, A3->x);
405  gbox->ymax = FP_MAX(A1->y, A3->y);
406  return LW_SUCCESS;
407  }
408 
409  /* Matched start/end points imply circle */
410  if ( A1->x == A3->x && A1->y == A3->y )
411  {
412  gbox->xmin = C.x - radius_A;
413  gbox->ymin = C.y - radius_A;
414  gbox->xmax = C.x + radius_A;
415  gbox->ymax = C.y + radius_A;
416  return LW_SUCCESS;
417  }
418 
419  /* First approximation, bounds of start/end points */
420  gbox->xmin = FP_MIN(A1->x, A3->x);
421  gbox->ymin = FP_MIN(A1->y, A3->y);
422  gbox->xmax = FP_MAX(A1->x, A3->x);
423  gbox->ymax = FP_MAX(A1->y, A3->y);
424 
425  /* Create points for the possible extrema */
426  xmin.x = C.x - radius_A;
427  xmin.y = C.y;
428  ymin.x = C.x;
429  ymin.y = C.y - radius_A;
430  xmax.x = C.x + radius_A;
431  xmax.y = C.y;
432  ymax.x = C.x;
433  ymax.y = C.y + radius_A;
434 
435  /* Divide the circle into two parts, one on each side of a line
436  joining p1 and p3. The circle extrema on the same side of that line
437  as p2 is on, are also the extrema of the bbox. */
438 
439  A2_side = lw_segment_side(A1, A3, A2);
440 
441  if ( A2_side == lw_segment_side(A1, A3, &xmin) )
442  gbox->xmin = xmin.x;
443 
444  if ( A2_side == lw_segment_side(A1, A3, &ymin) )
445  gbox->ymin = ymin.y;
446 
447  if ( A2_side == lw_segment_side(A1, A3, &xmax) )
448  gbox->xmax = xmax.x;
449 
450  if ( A2_side == lw_segment_side(A1, A3, &ymax) )
451  gbox->ymax = ymax.y;
452 
453  return LW_SUCCESS;
454 }
455 
456 
457 static int lw_arc_calculate_gbox_cartesian(const POINT4D *p1, const POINT4D *p2, const POINT4D *p3, GBOX *gbox)
458 {
459  int rv;
460 
461  LWDEBUG(2, "lw_arc_calculate_gbox_cartesian called.");
462 
463  rv = lw_arc_calculate_gbox_cartesian_2d((POINT2D*)p1, (POINT2D*)p2, (POINT2D*)p3, gbox);
464  gbox->zmin = FP_MIN(p1->z, p3->z);
465  gbox->mmin = FP_MIN(p1->m, p3->m);
466  gbox->zmax = FP_MAX(p1->z, p3->z);
467  gbox->mmax = FP_MAX(p1->m, p3->m);
468  return rv;
469 }
470 
472 {
473  int i;
474  POINT4D p;
475  int has_z, has_m;
476 
477  if ( ! pa ) return LW_FAILURE;
478  if ( ! gbox ) return LW_FAILURE;
479  if ( pa->npoints < 1 ) return LW_FAILURE;
480 
481  has_z = FLAGS_GET_Z(pa->flags);
482  has_m = FLAGS_GET_M(pa->flags);
483  gbox->flags = gflags(has_z, has_m, 0);
484  LWDEBUGF(4, "ptarray_calculate_gbox Z: %d M: %d", has_z, has_m);
485 
486  getPoint4d_p(pa, 0, &p);
487  gbox->xmin = gbox->xmax = p.x;
488  gbox->ymin = gbox->ymax = p.y;
489  if ( has_z )
490  gbox->zmin = gbox->zmax = p.z;
491  if ( has_m )
492  gbox->mmin = gbox->mmax = p.m;
493 
494  for ( i = 1 ; i < pa->npoints; i++ )
495  {
496  getPoint4d_p(pa, i, &p);
497  gbox->xmin = FP_MIN(gbox->xmin, p.x);
498  gbox->xmax = FP_MAX(gbox->xmax, p.x);
499  gbox->ymin = FP_MIN(gbox->ymin, p.y);
500  gbox->ymax = FP_MAX(gbox->ymax, p.y);
501  if ( has_z )
502  {
503  gbox->zmin = FP_MIN(gbox->zmin, p.z);
504  gbox->zmax = FP_MAX(gbox->zmax, p.z);
505  }
506  if ( has_m )
507  {
508  gbox->mmin = FP_MIN(gbox->mmin, p.m);
509  gbox->mmax = FP_MAX(gbox->mmax, p.m);
510  }
511  }
512  return LW_SUCCESS;
513 }
514 
516 {
517  uint8_t flags = gflags(FLAGS_GET_Z(curve->flags), FLAGS_GET_M(curve->flags), 0);
518  GBOX tmp;
519  POINT4D p1, p2, p3;
520  int i;
521 
522  if ( ! curve ) return LW_FAILURE;
523  if ( curve->points->npoints < 3 ) return LW_FAILURE;
524 
525  tmp.flags = flags;
526 
527  /* Initialize */
528  gbox->xmin = gbox->ymin = gbox->zmin = gbox->mmin = MAXFLOAT;
529  gbox->xmax = gbox->ymax = gbox->zmax = gbox->mmax = -1 * MAXFLOAT;
530 
531  for ( i = 2; i < curve->points->npoints; i += 2 )
532  {
533  getPoint4d_p(curve->points, i-2, &p1);
534  getPoint4d_p(curve->points, i-1, &p2);
535  getPoint4d_p(curve->points, i, &p3);
536 
537  if (lw_arc_calculate_gbox_cartesian(&p1, &p2, &p3, &tmp) == LW_FAILURE)
538  continue;
539 
540  gbox_merge(&tmp, gbox);
541  }
542 
543  return LW_SUCCESS;
544 }
545 
547 {
548  if ( ! point ) return LW_FAILURE;
549  return ptarray_calculate_gbox_cartesian( point->point, gbox );
550 }
551 
553 {
554  if ( ! line ) return LW_FAILURE;
555  return ptarray_calculate_gbox_cartesian( line->points, gbox );
556 }
557 
559 {
560  if ( ! triangle ) return LW_FAILURE;
561  return ptarray_calculate_gbox_cartesian( triangle->points, gbox );
562 }
563 
565 {
566  if ( ! poly ) return LW_FAILURE;
567  if ( poly->nrings == 0 ) return LW_FAILURE;
568  /* Just need to check outer ring */
569  return ptarray_calculate_gbox_cartesian( poly->rings[0], gbox );
570 }
571 
573 {
574  GBOX subbox;
575  int i;
576  int result = LW_FAILURE;
577  int first = LW_TRUE;
578  assert(coll);
579  if ( (coll->ngeoms == 0) || !gbox)
580  return LW_FAILURE;
581 
582  subbox.flags = coll->flags;
583 
584  for ( i = 0; i < coll->ngeoms; i++ )
585  {
586  if ( lwgeom_calculate_gbox_cartesian((LWGEOM*)(coll->geoms[i]), &subbox) == LW_SUCCESS )
587  {
588  /* Keep a copy of the sub-bounding box for later
589  if ( coll->geoms[i]->bbox )
590  lwfree(coll->geoms[i]->bbox);
591  coll->geoms[i]->bbox = gbox_copy(&subbox); */
592  if ( first )
593  {
594  gbox_duplicate(&subbox, gbox);
595  first = LW_FALSE;
596  }
597  else
598  {
599  gbox_merge(&subbox, gbox);
600  }
601  result = LW_SUCCESS;
602  }
603  }
604  return result;
605 }
606 
607 int lwgeom_calculate_gbox_cartesian(const LWGEOM *lwgeom, GBOX *gbox)
608 {
609  if ( ! lwgeom ) return LW_FAILURE;
610  LWDEBUGF(4, "lwgeom_calculate_gbox got type (%d) - %s", lwgeom->type, lwtype_name(lwgeom->type));
611 
612  switch (lwgeom->type)
613  {
614  case POINTTYPE:
615  return lwpoint_calculate_gbox_cartesian((LWPOINT *)lwgeom, gbox);
616  case LINETYPE:
617  return lwline_calculate_gbox_cartesian((LWLINE *)lwgeom, gbox);
618  case CIRCSTRINGTYPE:
619  return lwcircstring_calculate_gbox_cartesian((LWCIRCSTRING *)lwgeom, gbox);
620  case POLYGONTYPE:
621  return lwpoly_calculate_gbox_cartesian((LWPOLY *)lwgeom, gbox);
622  case TRIANGLETYPE:
623  return lwtriangle_calculate_gbox_cartesian((LWTRIANGLE *)lwgeom, gbox);
624  case COMPOUNDTYPE:
625  case CURVEPOLYTYPE:
626  case MULTIPOINTTYPE:
627  case MULTILINETYPE:
628  case MULTICURVETYPE:
629  case MULTIPOLYGONTYPE:
630  case MULTISURFACETYPE:
632  case TINTYPE:
633  case COLLECTIONTYPE:
634  return lwcollection_calculate_gbox_cartesian((LWCOLLECTION *)lwgeom, gbox);
635  }
636  /* Never get here, please. */
637  lwerror("unsupported type (%d) - %s", lwgeom->type, lwtype_name(lwgeom->type));
638  return LW_FAILURE;
639 }
640 
642 {
643  gbox->xmin = next_float_down(gbox->xmin);
644  gbox->xmax = next_float_up(gbox->xmax);
645 
646  gbox->ymin = next_float_down(gbox->ymin);
647  gbox->ymax = next_float_up(gbox->ymax);
648 
649  if ( FLAGS_GET_M(gbox->flags) )
650  {
651  gbox->mmin = next_float_down(gbox->mmin);
652  gbox->mmax = next_float_up(gbox->mmax);
653  }
654 
655  if ( FLAGS_GET_Z(gbox->flags) )
656  {
657  gbox->zmin = next_float_down(gbox->zmin);
658  gbox->zmax = next_float_up(gbox->zmax);
659  }
660 }
661 
double x
Definition: liblwgeom.h:308
double lw_arc_center(const POINT2D *p1, const POINT2D *p2, const POINT2D *p3, POINT2D *result)
Determines the center of the circle defined by the three given points.
Definition: lwalgorithm.c:228
#define LINETYPE
Definition: liblwgeom.h:61
int ptarray_calculate_gbox_cartesian(const POINTARRAY *pa, GBOX *gbox)
Calculate box (x/y) and add values to gbox.
Definition: g_box.c:471
GBOX * gbox_copy(const GBOX *box)
Return a copy of the GBOX, based on dimensionality of flags.
Definition: g_box.c:362
int32_t srid
Definition: liblwgeom.h:235
GBOX * gbox_new(uint8_t flags)
Create a new gbox with the dimensionality indicated by the flags.
Definition: g_box.c:26
uint8_t flags
Definition: liblwgeom.h:397
POINTARRAY * points
Definition: liblwgeom.h:389
double m
Definition: liblwgeom.h:308
#define MULTICURVETYPE
Definition: liblwgeom.h:70
void gbox_duplicate(const GBOX *original, GBOX *duplicate)
Copy the values of original GBOX into duplicate.
Definition: g_box.c:369
int gbox_is_valid(const GBOX *gbox)
Return false if any of the dimensions is NaN or infinite.
Definition: g_box.c:155
static int lwpoint_calculate_gbox_cartesian(LWPOINT *point, GBOX *gbox)
Definition: g_box.c:546
double y
Definition: liblwgeom.h:296
char * gbox_to_string(const GBOX *gbox)
Allocate a string representation of the GBOX, based on dimensionality of flags.
Definition: g_box.c:328
int lw_arc_calculate_gbox_cartesian_2d(const POINT2D *A1, const POINT2D *A2, const POINT2D *A3, GBOX *gbox)
Definition: g_box.c:388
int npoints
Definition: liblwgeom.h:327
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
static int lw_arc_calculate_gbox_cartesian(const POINT4D *p1, const POINT4D *p2, const POINT4D *p3, GBOX *gbox)
Definition: g_box.c:457
#define FLAGS_GET_GEODETIC(flags)
Definition: liblwgeom.h:109
#define POLYGONTYPE
Definition: liblwgeom.h:62
double xmax
Definition: liblwgeom.h:249
#define CURVEPOLYTYPE
Definition: liblwgeom.h:69
#define COMPOUNDTYPE
Definition: liblwgeom.h:68
#define MULTIPOINTTYPE
Definition: liblwgeom.h:63
int gbox_contains_point3d(const GBOX *gbox, const POINT3D *pt)
Return true if the point is inside the gbox.
Definition: g_box.c:205
static int lwpoly_calculate_gbox_cartesian(LWPOLY *poly, GBOX *gbox)
Definition: g_box.c:564
#define LW_SUCCESS
Definition: liblwgeom.h:55
#define FLAGS_GET_ZM(flags)
Definition: liblwgeom.h:119
#define LWDEBUG(level, msg)
Definition: lwgeom_log.h:50
#define TRIANGLETYPE
Definition: liblwgeom.h:73
double x
Definition: liblwgeom.h:296
#define POLYHEDRALSURFACETYPE
Definition: liblwgeom.h:72
double ymin
Definition: liblwgeom.h:233
int gbox_init_point3d(const POINT3D *p, GBOX *gbox)
Initialize a GBOX using the values of the point.
Definition: g_box.c:197
float next_float_down(double d)
Definition: lwgeom_api.c:129
#define FP_MIN(A, B)
static int lwcollection_calculate_gbox_cartesian(LWCOLLECTION *coll, GBOX *gbox)
Definition: g_box.c:572
POINTARRAY * point
Definition: liblwgeom.h:367
char ** result
Definition: liblwgeom.h:218
int gbox_merge(const GBOX *new_box, GBOX *merge_box)
Update the merged GBOX to be large enough to include itself and the new box.
Definition: g_box.c:215
#define LW_FAILURE
Definition: liblwgeom.h:54
float next_float_up(double d)
Definition: lwgeom_api.c:145
double z
Definition: liblwgeom.h:296
void lwerror(const char *fmt,...)
Write a notice out to the error handler.
Definition: lwutil.c:67
double x
Definition: liblwgeom.h:284
uint8_t flags
Definition: liblwgeom.h:460
void gbox_float_round(GBOX *gbox)
Round given GBOX to float boundaries.
Definition: g_box.c:641
double zmax
Definition: liblwgeom.h:253
double ymin
Definition: liblwgeom.h:250
const char * lwtype_name(uint8_t type)
Return the type name string associated with a type number (e.g.
Definition: lwutil.c:164
void gbox_init(GBOX *gbox)
Zero out all the entries in the GBOX.
Definition: g_box.c:34
double xmin
Definition: liblwgeom.h:248
#define LW_FALSE
Definition: liblwgeom.h:52
double xmin
Definition: liblwgeom.h:233
uint8_t flags
Definition: liblwgeom.h:325
#define LW_TRUE
Return types for functions with status returns.
Definition: liblwgeom.h:51
LWGEOM ** geoms
Definition: liblwgeom.h:465
#define SRID_UNKNOWN
Unknown SRID value.
Definition: liblwgeom.h:154
#define TINTYPE
Definition: liblwgeom.h:74
int gbox_merge_point3d(const POINT3D *p, GBOX *gbox)
Update the GBOX to be large enough to include itself and the new point.
Definition: g_box.c:186
POINTARRAY ** rings
Definition: liblwgeom.h:413
int nrings
Definition: liblwgeom.h:411
#define isfinite
Definition: g_box.c:17
double ymax
Definition: liblwgeom.h:251
double y
Definition: liblwgeom.h:284
#define FLAGS_GET_Z(flags)
Macros for manipulating the 'flags' byte.
Definition: liblwgeom.h:106
double z
Definition: liblwgeom.h:308
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
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
#define MULTIPOLYGONTYPE
Definition: liblwgeom.h:65
GBOX * box3d_to_gbox(const BOX3D *b3d)
Definition: g_box.c:74
static int lwcircstring_calculate_gbox_cartesian(LWCIRCSTRING *curve, GBOX *gbox)
Definition: g_box.c:515
BOX3D * box3d_from_gbox(const GBOX *gbox)
Definition: g_box.c:47
int gbox_overlaps_2d(const GBOX *g1, const GBOX *g2)
Return LW_TRUE if the GBOX overlaps on the 2d plane, LW_FALSE otherwise.
Definition: g_box.c:281
#define MULTISURFACETYPE
Definition: liblwgeom.h:71
double xmax
Definition: liblwgeom.h:234
double mmin
Definition: liblwgeom.h:254
double zmin
Definition: liblwgeom.h:252
static int lwline_calculate_gbox_cartesian(LWLINE *line, GBOX *gbox)
Definition: g_box.c:552
static int lwtriangle_calculate_gbox_cartesian(LWTRIANGLE *triangle, GBOX *gbox)
Definition: g_box.c:558
#define POINTTYPE
LWTYPE numbers, used internally by PostGIS.
Definition: liblwgeom.h:60
#define FLAGS_GET_M(flags)
Definition: liblwgeom.h:107
#define MAXFLOAT
Largest float value.
int gbox_overlaps(const GBOX *g1, const GBOX *g2)
Return LW_TRUE if the GBOX overlaps, LW_FALSE otherwise.
Definition: g_box.c:241
uint8_t type
Definition: liblwgeom.h:352
double mmax
Definition: liblwgeom.h:255
POINTARRAY * points
Definition: liblwgeom.h:400
GBOX * gbox_clone(const GBOX *gbox)
Definition: g_box.c:39
#define CIRCSTRINGTYPE
Definition: liblwgeom.h:67
void * lwalloc(size_t size)
Definition: lwutil.c:175
int lw_segment_side(const POINT2D *p1, const POINT2D *p2, const POINT2D *q)
lw_segment_side()
Definition: lwalgorithm.c:62
double y
Definition: liblwgeom.h:308
#define MULTILINETYPE
Definition: liblwgeom.h:64
double ymax
Definition: liblwgeom.h:234
GBOX * gbox_from_string(const char *str)
Warning, this function is only good for x/y/z boxes, used in unit testing of geodetic box generation...
Definition: g_box.c:300
#define LWDEBUGF(level, msg,...)
Definition: lwgeom_log.h:55
#define FLAGS_NDIMS(flags)
Definition: liblwgeom.h:118
int gbox_same(const GBOX *g1, const GBOX *g2)
Check if 2 given Gbox are the same.
Definition: g_box.c:139
size_t gbox_serialized_size(uint8_t flags)
Return the number of bytes necessary to hold a GBOX of this dimension in serialized form...
Definition: g_box.c:375
int getPoint4d_p(const POINTARRAY *pa, int n, POINT4D *point)
Definition: lwgeom_api.c:217
#define COLLECTIONTYPE
Definition: liblwgeom.h:66
#define FP_MAX(A, B)
double zmax
Definition: liblwgeom.h:234
POINTARRAY * points
Definition: liblwgeom.h:378
double zmin
Definition: liblwgeom.h:233
int lwgeom_calculate_gbox_cartesian(const LWGEOM *lwgeom, GBOX *gbox)
Calculate the 2-4D bounding box of a geometry.
Definition: g_box.c:607