PostGIS  2.3.8dev-r@@SVN_REVISION@@

◆ gserialized_peek_gbox_p()

static int gserialized_peek_gbox_p ( const GSERIALIZED g,
GBOX gbox 
)
static

Definition at line 219 of file g_serialized.c.

References GSERIALIZED::data, GBOX::flags, GSERIALIZED::flags, FLAGS_GET_BBOX, FLAGS_GET_GEODETIC, FLAGS_GET_M, FLAGS_GET_Z, FLAGS_NDIMS, FP_MAX, FP_MIN, gbox_float_round(), gserialized_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 gserialized_get_gbox_p(), test_gserialized_peek_gbox_p_fails_for_unsupported_cases(), test_gserialized_peek_gbox_p_gets_correct_box(), and test_gserialized_peek_gbox_p_no_box_when_empty().

220 {
221  uint32_t type = gserialized_get_type(g);
222 
223  /* Peeking doesn't help if you already have a box or are geodetic */
224  if ( FLAGS_GET_GEODETIC(g->flags) || FLAGS_GET_BBOX(g->flags) )
225  {
226  return LW_FAILURE;
227  }
228 
229  /* Boxes of points are easy peasy */
230  if ( type == POINTTYPE )
231  {
232  int i = 1; /* Start past <pointtype><padding> */
233  double *dptr = (double*)(g->data);
234 
235  /* Read the empty flag */
236  int *iptr = (int*)(g->data);
237  int isempty = (iptr[1] == 0);
238 
239  /* EMPTY point has no box */
240  if ( isempty ) return LW_FAILURE;
241 
242  gbox->xmin = gbox->xmax = dptr[i++];
243  gbox->ymin = gbox->ymax = dptr[i++];
244  gbox->flags = g->flags;
245  if ( FLAGS_GET_Z(g->flags) )
246  {
247  gbox->zmin = gbox->zmax = dptr[i++];
248  }
249  if ( FLAGS_GET_M(g->flags) )
250  {
251  gbox->mmin = gbox->mmax = dptr[i++];
252  }
253  gbox_float_round(gbox);
254  return LW_SUCCESS;
255  }
256  /* We can calculate the box of a two-point cartesian line trivially */
257  else if ( type == LINETYPE )
258  {
259  int ndims = FLAGS_NDIMS(g->flags);
260  int i = 0; /* Start at <linetype><npoints> */
261  double *dptr = (double*)(g->data);
262  int *iptr = (int*)(g->data);
263  int npoints = iptr[1]; /* Read the npoints */
264 
265  /* This only works with 2-point lines */
266  if ( npoints != 2 )
267  return LW_FAILURE;
268 
269  /* Advance to X */
270  /* Past <linetype><npoints> */
271  i++;
272  gbox->xmin = FP_MIN(dptr[i], dptr[i+ndims]);
273  gbox->xmax = FP_MAX(dptr[i], dptr[i+ndims]);
274 
275  /* Advance to Y */
276  i++;
277  gbox->ymin = FP_MIN(dptr[i], dptr[i+ndims]);
278  gbox->ymax = FP_MAX(dptr[i], dptr[i+ndims]);
279 
280  gbox->flags = g->flags;
281  if ( FLAGS_GET_Z(g->flags) )
282  {
283  /* Advance to Z */
284  i++;
285  gbox->zmin = FP_MIN(dptr[i], dptr[i+ndims]);
286  gbox->zmax = FP_MAX(dptr[i], dptr[i+ndims]);
287  }
288  if ( FLAGS_GET_M(g->flags) )
289  {
290  /* Advance to M */
291  i++;
292  gbox->mmin = FP_MIN(dptr[i], dptr[i+ndims]);
293  gbox->mmax = FP_MAX(dptr[i], dptr[i+ndims]);
294  }
295  gbox_float_round(gbox);
296  return LW_SUCCESS;
297  }
298  /* We can also do single-entry multi-points */
299  else if ( type == MULTIPOINTTYPE )
300  {
301  int i = 0; /* Start at <multipointtype><ngeoms> */
302  double *dptr = (double*)(g->data);
303  int *iptr = (int*)(g->data);
304  int ngeoms = iptr[1]; /* Read the ngeoms */
305  int npoints;
306 
307  /* This only works with single-entry multipoints */
308  if ( ngeoms != 1 )
309  return LW_FAILURE;
310 
311  /* Npoints is at <multipointtype><ngeoms><pointtype><npoints> */
312  npoints = iptr[3];
313 
314  /* The check below is necessary because we can have a MULTIPOINT
315  * that contains a single, empty POINT (ngeoms = 1, npoints = 0) */
316  if ( npoints != 1 )
317  return LW_FAILURE;
318 
319  /* Move forward two doubles (four ints) */
320  /* Past <multipointtype><ngeoms> */
321  /* Past <pointtype><npoints> */
322  i += 2;
323 
324  /* Read the doubles from the one point */
325  gbox->xmin = gbox->xmax = dptr[i++];
326  gbox->ymin = gbox->ymax = dptr[i++];
327  gbox->flags = g->flags;
328  if ( FLAGS_GET_Z(g->flags) )
329  {
330  gbox->zmin = gbox->zmax = dptr[i++];
331  }
332  if ( FLAGS_GET_M(g->flags) )
333  {
334  gbox->mmin = gbox->mmax = dptr[i++];
335  }
336  gbox_float_round(gbox);
337  return LW_SUCCESS;
338  }
339  /* And we can do single-entry multi-lines with two vertices (!!!) */
340  else if ( type == MULTILINETYPE )
341  {
342  int ndims = FLAGS_NDIMS(g->flags);
343  int i = 0; /* Start at <multilinetype><ngeoms> */
344  double *dptr = (double*)(g->data);
345  int *iptr = (int*)(g->data);
346  int ngeoms = iptr[1]; /* Read the ngeoms */
347  int npoints;
348 
349  /* This only works with 1-line multilines */
350  if ( ngeoms != 1 )
351  return LW_FAILURE;
352 
353  /* Npoints is at <multilinetype><ngeoms><linetype><npoints> */
354  npoints = iptr[3];
355 
356  if ( npoints != 2 )
357  return LW_FAILURE;
358 
359  /* Advance to X */
360  /* Move forward two doubles (four ints) */
361  /* Past <multilinetype><ngeoms> */
362  /* Past <linetype><npoints> */
363  i += 2;
364  gbox->xmin = FP_MIN(dptr[i], dptr[i+ndims]);
365  gbox->xmax = FP_MAX(dptr[i], dptr[i+ndims]);
366 
367  /* Advance to Y */
368  i++;
369  gbox->ymin = FP_MIN(dptr[i], dptr[i+ndims]);
370  gbox->ymax = FP_MAX(dptr[i], dptr[i+ndims]);
371 
372  gbox->flags = g->flags;
373  if ( FLAGS_GET_Z(g->flags) )
374  {
375  /* Advance to Z */
376  i++;
377  gbox->zmin = FP_MIN(dptr[i], dptr[i+ndims]);
378  gbox->zmax = FP_MAX(dptr[i], dptr[i+ndims]);
379  }
380  if ( FLAGS_GET_M(g->flags) )
381  {
382  /* Advance to M */
383  i++;
384  gbox->mmin = FP_MIN(dptr[i], dptr[i+ndims]);
385  gbox->mmax = FP_MAX(dptr[i], dptr[i+ndims]);
386  }
387  gbox_float_round(gbox);
388  return LW_SUCCESS;
389  }
390 
391  return LW_FAILURE;
392 }
#define LINETYPE
Definition: liblwgeom.h:85
uint32_t gserialized_get_type(const GSERIALIZED *s)
Extract the geometry type from the serialized form (it hides in the anonymous data area...
Definition: g_serialized.c:69
uint8_t data[1]
Definition: liblwgeom.h:383
#define FLAGS_GET_GEODETIC(flags)
Definition: liblwgeom.h:142
double xmax
Definition: liblwgeom.h:292
#define MULTIPOINTTYPE
Definition: liblwgeom.h:87
#define LW_SUCCESS
Definition: liblwgeom.h:79
#define FP_MIN(A, B)
#define LW_FAILURE
Definition: liblwgeom.h:78
void gbox_float_round(GBOX *gbox)
Round given GBOX to float boundaries.
Definition: g_box.c:717
double zmax
Definition: liblwgeom.h:296
double ymin
Definition: liblwgeom.h:293
double xmin
Definition: liblwgeom.h:291
#define FLAGS_GET_BBOX(flags)
Definition: liblwgeom.h:141
double ymax
Definition: liblwgeom.h:294
#define FLAGS_GET_Z(flags)
Macros for manipulating the &#39;flags&#39; byte.
Definition: liblwgeom.h:139
uint8_t flags
Definition: liblwgeom.h:290
double mmin
Definition: liblwgeom.h:297
double zmin
Definition: liblwgeom.h:295
#define POINTTYPE
LWTYPE numbers, used internally by PostGIS.
Definition: liblwgeom.h:84
#define FLAGS_GET_M(flags)
Definition: liblwgeom.h:140
type
Definition: ovdump.py:41
double mmax
Definition: liblwgeom.h:298
#define MULTILINETYPE
Definition: liblwgeom.h:88
#define FLAGS_NDIMS(flags)
Definition: liblwgeom.h:151
uint8_t flags
Definition: liblwgeom.h:382
#define FP_MAX(A, B)
Here is the call graph for this function:
Here is the caller graph for this function: