PostGIS  3.0.6dev-r@@SVN_REVISION@@

◆ gserialized2_peek_gbox_p()

int gserialized2_peek_gbox_p ( const GSERIALIZED g,
GBOX gbox 
)

Definition at line 360 of file gserialized2.c.

361 {
362  uint32_t type = gserialized2_get_type(g);
363  uint8_t *geometry_start = gserialized2_get_geometry_p(g);
364  double *dptr = (double *)(geometry_start);
365  int32_t *iptr = (int32_t *)(geometry_start);
366 
367  /* Peeking doesn't help if you already have a box or are geodetic */
369  {
370  return LW_FAILURE;
371  }
372 
373  /* Boxes of points are easy peasy */
374  if (type == POINTTYPE)
375  {
376  int i = 1; /* Start past <pointtype><padding> */
377 
378  /* Read the npoints flag */
379  int isempty = (iptr[1] == 0);
380 
381  /* EMPTY point has no box */
382  if (isempty) return LW_FAILURE;
383 
384  gbox->xmin = gbox->xmax = dptr[i++];
385  gbox->ymin = gbox->ymax = dptr[i++];
386  gbox->flags = gserialized2_get_lwflags(g);
387  if (G2FLAGS_GET_Z(g->gflags))
388  {
389  gbox->zmin = gbox->zmax = dptr[i++];
390  }
391  if (G2FLAGS_GET_M(g->gflags))
392  {
393  gbox->mmin = gbox->mmax = dptr[i++];
394  }
395  gbox_float_round(gbox);
396  return LW_SUCCESS;
397  }
398  /* We can calculate the box of a two-point cartesian line trivially */
399  else if (type == LINETYPE)
400  {
401  int ndims = G2FLAGS_NDIMS(g->gflags);
402  int i = 0; /* Start at <linetype><npoints> */
403  int npoints = iptr[1]; /* Read the npoints */
404 
405  /* This only works with 2-point lines */
406  if (npoints != 2)
407  return LW_FAILURE;
408 
409  /* Advance to X */
410  /* Past <linetype><npoints> */
411  i++;
412  gbox->xmin = FP_MIN(dptr[i], dptr[i+ndims]);
413  gbox->xmax = FP_MAX(dptr[i], dptr[i+ndims]);
414 
415  /* Advance to Y */
416  i++;
417  gbox->ymin = FP_MIN(dptr[i], dptr[i+ndims]);
418  gbox->ymax = FP_MAX(dptr[i], dptr[i+ndims]);
419 
420  gbox->flags = gserialized2_get_lwflags(g);
421  if (G2FLAGS_GET_Z(g->gflags))
422  {
423  /* Advance to Z */
424  i++;
425  gbox->zmin = FP_MIN(dptr[i], dptr[i+ndims]);
426  gbox->zmax = FP_MAX(dptr[i], dptr[i+ndims]);
427  }
428  if (G2FLAGS_GET_M(g->gflags))
429  {
430  /* Advance to M */
431  i++;
432  gbox->mmin = FP_MIN(dptr[i], dptr[i+ndims]);
433  gbox->mmax = FP_MAX(dptr[i], dptr[i+ndims]);
434  }
435  gbox_float_round(gbox);
436  return LW_SUCCESS;
437  }
438  /* We can also do single-entry multi-points */
439  else if (type == MULTIPOINTTYPE)
440  {
441  int i = 0; /* Start at <multipointtype><ngeoms> */
442  int ngeoms = iptr[1]; /* Read the ngeoms */
443  int npoints;
444 
445  /* This only works with single-entry multipoints */
446  if (ngeoms != 1)
447  return LW_FAILURE;
448 
449  /* Npoints is at <multipointtype><ngeoms><pointtype><npoints> */
450  npoints = iptr[3];
451 
452  /* The check below is necessary because we can have a MULTIPOINT
453  * that contains a single, empty POINT (ngeoms = 1, npoints = 0) */
454  if (npoints != 1)
455  return LW_FAILURE;
456 
457  /* Move forward two doubles (four ints) */
458  /* Past <multipointtype><ngeoms> */
459  /* Past <pointtype><npoints> */
460  i += 2;
461 
462  /* Read the doubles from the one point */
463  gbox->xmin = gbox->xmax = dptr[i++];
464  gbox->ymin = gbox->ymax = dptr[i++];
465  gbox->flags = gserialized2_get_lwflags(g);
466  if (G2FLAGS_GET_Z(g->gflags))
467  {
468  gbox->zmin = gbox->zmax = dptr[i++];
469  }
470  if (G2FLAGS_GET_M(g->gflags))
471  {
472  gbox->mmin = gbox->mmax = dptr[i++];
473  }
474  gbox_float_round(gbox);
475  return LW_SUCCESS;
476  }
477  /* And we can do single-entry multi-lines with two vertices (!!!) */
478  else if (type == MULTILINETYPE)
479  {
480  int ndims = G2FLAGS_NDIMS(g->gflags);
481  int i = 0; /* Start at <multilinetype><ngeoms> */
482  int ngeoms = iptr[1]; /* Read the ngeoms */
483  int npoints;
484 
485  /* This only works with 1-line multilines */
486  if (ngeoms != 1)
487  return LW_FAILURE;
488 
489  /* Npoints is at <multilinetype><ngeoms><linetype><npoints> */
490  npoints = iptr[3];
491 
492  if (npoints != 2)
493  return LW_FAILURE;
494 
495  /* Advance to X */
496  /* Move forward two doubles (four ints) */
497  /* Past <multilinetype><ngeoms> */
498  /* Past <linetype><npoints> */
499  i += 2;
500  gbox->xmin = FP_MIN(dptr[i], dptr[i+ndims]);
501  gbox->xmax = FP_MAX(dptr[i], dptr[i+ndims]);
502 
503  /* Advance to Y */
504  i++;
505  gbox->ymin = FP_MIN(dptr[i], dptr[i+ndims]);
506  gbox->ymax = FP_MAX(dptr[i], dptr[i+ndims]);
507 
508  gbox->flags = gserialized2_get_lwflags(g);
509  if (G2FLAGS_GET_Z(g->gflags))
510  {
511  /* Advance to Z */
512  i++;
513  gbox->zmin = FP_MIN(dptr[i], dptr[i+ndims]);
514  gbox->zmax = FP_MAX(dptr[i], dptr[i+ndims]);
515  }
516  if (G2FLAGS_GET_M(g->gflags))
517  {
518  /* Advance to M */
519  i++;
520  gbox->mmin = FP_MIN(dptr[i], dptr[i+ndims]);
521  gbox->mmax = FP_MAX(dptr[i], dptr[i+ndims]);
522  }
523  gbox_float_round(gbox);
524  return LW_SUCCESS;
525  }
526 
527  return LW_FAILURE;
528 }
void gbox_float_round(GBOX *gbox)
Round given GBOX to float boundaries.
Definition: gbox.c:774
uint32_t gserialized2_get_type(const GSERIALIZED *g)
Extract the geometry type from the serialized form (it hides in the anonymous data area,...
Definition: gserialized2.c:184
static uint8_t * gserialized2_get_geometry_p(const GSERIALIZED *g)
Definition: gserialized2.c:104
lwflags_t gserialized2_get_lwflags(const GSERIALIZED *g)
Read the flags from a GSERIALIZED and return a standard lwflag integer.
Definition: gserialized2.c:57
#define G2FLAGS_GET_BBOX(gflags)
Definition: gserialized2.h:24
#define G2FLAGS_GET_GEODETIC(gflags)
Definition: gserialized2.h:25
#define G2FLAGS_GET_Z(gflags)
Definition: gserialized2.h:22
#define G2FLAGS_GET_M(gflags)
Definition: gserialized2.h:23
#define G2FLAGS_NDIMS(gflags)
Definition: gserialized2.h:36
#define LW_FAILURE
Definition: liblwgeom.h:110
#define MULTILINETYPE
Definition: liblwgeom.h:120
#define LINETYPE
Definition: liblwgeom.h:117
#define LW_SUCCESS
Definition: liblwgeom.h:111
#define MULTIPOINTTYPE
Definition: liblwgeom.h:119
#define POINTTYPE
LWTYPE numbers, used internally by PostGIS.
Definition: liblwgeom.h:116
#define FP_MAX(A, B)
#define FP_MIN(A, B)
type
Definition: ovdump.py:42
double ymax
Definition: liblwgeom.h:343
double zmax
Definition: liblwgeom.h:345
double xmax
Definition: liblwgeom.h:341
double zmin
Definition: liblwgeom.h:344
double mmax
Definition: liblwgeom.h:347
double ymin
Definition: liblwgeom.h:342
double xmin
Definition: liblwgeom.h:340
double mmin
Definition: liblwgeom.h:346
lwflags_t flags
Definition: liblwgeom.h:339
uint8_t gflags
Definition: liblwgeom.h:432

References GBOX::flags, FP_MAX, FP_MIN, G2FLAGS_GET_BBOX, G2FLAGS_GET_GEODETIC, G2FLAGS_GET_M, G2FLAGS_GET_Z, G2FLAGS_NDIMS, gbox_float_round(), GSERIALIZED::gflags, gserialized2_get_geometry_p(), gserialized2_get_lwflags(), gserialized2_get_type(), LINETYPE, LW_FAILURE, LW_SUCCESS, GBOX::mmax, GBOX::mmin, MULTILINETYPE, MULTIPOINTTYPE, POINTTYPE, ovdump::type, GBOX::xmax, GBOX::xmin, GBOX::ymax, GBOX::ymin, GBOX::zmax, and GBOX::zmin.

Referenced by gserialized2_fast_gbox_p(), gserialized2_get_gbox_p(), test_gserialized2_peek_gbox_p_fails_for_unsupported_cases(), test_gserialized2_peek_gbox_p_gets_correct_box(), and test_gserialized2_peek_gbox_p_no_box_when_empty().

Here is the call graph for this function:
Here is the caller graph for this function: