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