PostGIS  3.7.0dev-r@@SVN_REVISION@@

◆ gserialized2_peek_gbox_p()

int gserialized2_peek_gbox_p ( const GSERIALIZED g,
GBOX gbox 
)

Definition at line 362 of file gserialized2.c.

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

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: