PostGIS  2.1.10dev-r@@SVN_REVISION@@
g_serialized.c
Go to the documentation of this file.
1 /**********************************************************************
2  * $Id: g_serialized.c 13698 2015-06-24 20:21:57Z pramsey $
3  *
4  * PostGIS - Spatial Types for PostgreSQL
5  *
6  * Copyright 2009 Paul Ramsey <pramsey@cleverelephant.ca>
7  *
8  * This is free software; you can redistribute and/or modify it under
9  * the terms of the GNU General Public Licence. See the COPYING file.
10  *
11  **********************************************************************/
12 
13 #include "liblwgeom_internal.h"
14 #include "lwgeom_log.h"
15 
16 /***********************************************************************
17 * GSERIALIZED metadata utility functions.
18 */
19 
21 {
22  return FLAGS_GET_BBOX(gser->flags);
23 }
24 
26 {
27  return FLAGS_GET_Z(gser->flags);
28 }
29 
31 {
32  return FLAGS_GET_M(gser->flags);
33 }
34 
36 {
37  return 2 * FLAGS_GET_Z(gser->flags) + FLAGS_GET_M(gser->flags);
38 }
39 
41 {
42  return FLAGS_NDIMS(gser->flags);
43 }
44 
46 {
47  return FLAGS_GET_GEODETIC(gser->flags);
48 }
49 
51 {
52  /* read GSERIALIZED size + max bbox according gbox_serialized_size (2 + Z + M) + 1 int for type */
53  return sizeof(GSERIALIZED) + 8 * sizeof(float) + sizeof(int);
54 }
55 
57 {
58  uint32_t *ptr;
59  assert(s);
60  ptr = (uint32_t*)(s->data);
61  LWDEBUG(4,"entered");
62  if ( FLAGS_GET_BBOX(s->flags) )
63  {
64  LWDEBUGF(4,"skipping forward past bbox (%d bytes)",gbox_serialized_size(s->flags));
65  ptr += (gbox_serialized_size(s->flags) / sizeof(uint32_t));
66  }
67  return *ptr;
68 }
69 
71 {
72  int32_t srid = 0;
73  srid = srid | (s->srid[0] << 16);
74  srid = srid | (s->srid[1] << 8);
75  srid = srid | s->srid[2];
76  /* Only the first 21 bits are set. Slide up and back to pull
77  the negative bits down, if we need them. */
78  srid = (srid<<11)>>11;
79 
80  /* 0 is our internal unknown value. We'll map back and forth here for now */
81  if ( srid == 0 )
82  return SRID_UNKNOWN;
83  else
84  return clamp_srid(srid);
85 }
86 
87 void gserialized_set_srid(GSERIALIZED *s, int32_t srid)
88 {
89  LWDEBUGF(3, "Called with srid = %d", srid);
90 
91  srid = clamp_srid(srid);
92 
93  /* 0 is our internal unknown value.
94  * We'll map back and forth here for now */
95  if ( srid == SRID_UNKNOWN )
96  srid = 0;
97 
98  s->srid[0] = (srid & 0x001F0000) >> 16;
99  s->srid[1] = (srid & 0x0000FF00) >> 8;
100  s->srid[2] = (srid & 0x000000FF);
101 }
102 
104 {
105  GSERIALIZED *g_out = NULL;
106  assert(g);
107  g_out = (GSERIALIZED*)lwalloc(SIZE_GET(g->size));
108  memcpy((uint8_t*)g_out,(uint8_t*)g,SIZE_GET(g->size));
109  return g_out;
110 }
111 
112 static size_t gserialized_is_empty_recurse(const uint8_t *p, int *isempty);
113 static size_t gserialized_is_empty_recurse(const uint8_t *p, int *isempty)
114 {
115  int i;
116  int32_t type, num;
117 
118  memcpy(&type, p, 4);
119  memcpy(&num, p+4, 4);
120 
121  if ( lwtype_is_collection(type) )
122  {
123  size_t lz = 8;
124  for ( i = 0; i < num; i++ )
125  {
126  lz += gserialized_is_empty_recurse(p+lz, isempty);
127  if ( ! *isempty )
128  return lz;
129  }
130  *isempty = LW_TRUE;
131  return lz;
132  }
133  else
134  {
135  *isempty = (num == 0 ? LW_TRUE : LW_FALSE);
136  return 8;
137  }
138 }
139 
141 {
142  uint8_t *p = (uint8_t*)g;
143  int isempty = 0;
144  assert(g);
145 
146  p += 8; /* Skip varhdr and srid/flags */
147  if( FLAGS_GET_BBOX(g->flags) )
148  p += gbox_serialized_size(g->flags); /* Skip the box */
149 
150  gserialized_is_empty_recurse(p, &isempty);
151  return isempty;
152 }
153 
155 {
156  return lwgeom_to_wkt(lwgeom_from_gserialized(g), WKT_ISO, 12, 0);
157 }
158 
160 {
161 
162  /* Null input! */
163  if ( ! ( g && gbox ) ) return LW_FAILURE;
164 
165  /* Initialize the flags on the box */
166  gbox->flags = g->flags;
167 
168  /* Has pre-calculated box */
169  if ( FLAGS_GET_BBOX(g->flags) )
170  {
171  int i = 0;
172  float *fbox = (float*)(g->data);
173  gbox->xmin = fbox[i++];
174  gbox->xmax = fbox[i++];
175  gbox->ymin = fbox[i++];
176  gbox->ymax = fbox[i++];
177 
178  /* Geodetic? Read next dimension (geocentric Z) and return */
179  if ( FLAGS_GET_GEODETIC(g->flags) )
180  {
181  gbox->zmin = fbox[i++];
182  gbox->zmax = fbox[i++];
183  return LW_SUCCESS;
184  }
185  /* Cartesian? Read extra dimensions (if there) and return */
186  if ( FLAGS_GET_Z(g->flags) )
187  {
188  gbox->zmin = fbox[i++];
189  gbox->zmax = fbox[i++];
190  }
191  if ( FLAGS_GET_M(g->flags) )
192  {
193  gbox->mmin = fbox[i++];
194  gbox->mmax = fbox[i++];
195  }
196  return LW_SUCCESS;
197  }
198 
199  return LW_FAILURE;
200 }
201 
202 /*
203 * Populate a bounding box *without* allocating an LWGEOM. Useful
204 * for some performance purposes.
205 */
206 static int gserialized_peek_gbox_p(const GSERIALIZED *g, GBOX *gbox)
207 {
208  uint32_t type = gserialized_get_type(g);
209 
210  /* Peeking doesn't help if you already have a box or are geodetic */
211  if ( FLAGS_GET_GEODETIC(g->flags) || FLAGS_GET_BBOX(g->flags) )
212  {
213  return LW_FAILURE;
214  }
215 
216  /* Boxes of points are easy peasy */
217  if ( type == POINTTYPE )
218  {
219  int i = 1; /* Start past <pointtype><padding> */
220  double *dptr = (double*)(g->data);
221 
222  /* Read the empty flag */
223  int *iptr = (int*)(g->data);
224  int isempty = (iptr[1] == 0);
225 
226  /* EMPTY point has no box */
227  if ( isempty ) return LW_FAILURE;
228 
229  gbox->xmin = gbox->xmax = dptr[i++];
230  gbox->ymin = gbox->ymax = dptr[i++];
231  if ( FLAGS_GET_Z(g->flags) )
232  {
233  gbox->zmin = gbox->zmax = dptr[i++];
234  }
235  if ( FLAGS_GET_M(g->flags) )
236  {
237  gbox->mmin = gbox->mmax = dptr[i++];
238  }
239  gbox_float_round(gbox);
240  return LW_SUCCESS;
241  }
242  /* We can calculate the box of a two-point cartesian line trivially */
243  else if ( type == LINETYPE )
244  {
245  int ndims = FLAGS_NDIMS(g->flags);
246  int i = 0; /* Start at <linetype><npoints> */
247  double *dptr = (double*)(g->data);
248  int *iptr = (int*)(g->data);
249  int npoints = iptr[1]; /* Read the npoints */
250 
251  /* This only works with 2-point lines */
252  if ( npoints != 2 )
253  return LW_FAILURE;
254 
255  /* Advance to X */
256  /* Past <linetype><npoints> */
257  i++;
258  gbox->xmin = FP_MIN(dptr[i], dptr[i+ndims]);
259  gbox->xmax = FP_MAX(dptr[i], dptr[i+ndims]);
260 
261  /* Advance to Y */
262  i++;
263  gbox->ymin = FP_MIN(dptr[i], dptr[i+ndims]);
264  gbox->ymax = FP_MAX(dptr[i], dptr[i+ndims]);
265 
266  if ( FLAGS_GET_Z(g->flags) )
267  {
268  /* Advance to Z */
269  i++;
270  gbox->zmin = FP_MIN(dptr[i], dptr[i+ndims]);
271  gbox->zmax = FP_MAX(dptr[i], dptr[i+ndims]);
272  }
273  if ( FLAGS_GET_M(g->flags) )
274  {
275  /* Advance to M */
276  i++;
277  gbox->mmin = FP_MIN(dptr[i], dptr[i+ndims]);
278  gbox->mmax = FP_MAX(dptr[i], dptr[i+ndims]);
279  }
280  gbox_float_round(gbox);
281  return LW_SUCCESS;
282  }
283  /* We can also do single-entry multi-points */
284  else if ( type == MULTIPOINTTYPE )
285  {
286  int i = 0; /* Start at <multipointtype><ngeoms> */
287  double *dptr = (double*)(g->data);
288  int *iptr = (int*)(g->data);
289  int ngeoms = iptr[1]; /* Read the ngeoms */
290 
291  /* This only works with single-entry multipoints */
292  if ( ngeoms != 1 )
293  return LW_FAILURE;
294 
295  /* Move forward two doubles (four ints) */
296  /* Past <multipointtype><ngeoms> */
297  /* Past <pointtype><emtpyflat> */
298  i += 2;
299 
300  /* Read the doubles from the one point */
301  gbox->xmin = gbox->xmax = dptr[i++];
302  gbox->ymin = gbox->ymax = dptr[i++];
303  if ( FLAGS_GET_Z(g->flags) )
304  {
305  gbox->zmin = gbox->zmax = dptr[i++];
306  }
307  if ( FLAGS_GET_M(g->flags) )
308  {
309  gbox->mmin = gbox->mmax = dptr[i++];
310  }
311  gbox_float_round(gbox);
312  return LW_SUCCESS;
313  }
314  /* And we can do single-entry multi-lines with two vertices (!!!) */
315  else if ( type == MULTILINETYPE )
316  {
317  int ndims = FLAGS_NDIMS(g->flags);
318  int i = 0; /* Start at <multilinetype><ngeoms> */
319  double *dptr = (double*)(g->data);
320  int *iptr = (int*)(g->data);
321  int ngeoms = iptr[1]; /* Read the ngeoms */
322  int npoints;
323 
324  /* This only works with 1-line multilines */
325  if ( ngeoms != 1 )
326  return LW_FAILURE;
327 
328  /* Npoints is at <multilinetype><ngeoms><linetype><npoints> */
329  npoints = iptr[3];
330 
331  if ( npoints != 2 )
332  return LW_FAILURE;
333 
334  /* Advance to X */
335  /* Move forward two doubles (four ints) */
336  /* Past <multilinetype><ngeoms> */
337  /* Past <linetype><npoints> */
338  i += 2;
339  gbox->xmin = FP_MIN(dptr[i], dptr[i+ndims]);
340  gbox->xmax = FP_MAX(dptr[i], dptr[i+ndims]);
341 
342  /* Advance to Y */
343  i++;
344  gbox->ymin = FP_MIN(dptr[i], dptr[i+ndims]);
345  gbox->ymax = FP_MAX(dptr[i], dptr[i+ndims]);
346 
347  if ( FLAGS_GET_Z(g->flags) )
348  {
349  /* Advance to Z */
350  i++;
351  gbox->zmin = FP_MIN(dptr[i], dptr[i+ndims]);
352  gbox->zmax = FP_MAX(dptr[i], dptr[i+ndims]);
353  }
354  if ( FLAGS_GET_M(g->flags) )
355  {
356  /* Advance to M */
357  i++;
358  gbox->mmin = FP_MIN(dptr[i], dptr[i+ndims]);
359  gbox->mmax = FP_MAX(dptr[i], dptr[i+ndims]);
360  }
361  gbox_float_round(gbox);
362  return LW_SUCCESS;
363  }
364 
365  return LW_FAILURE;
366 }
367 
368 
374 {
375  /* Try to just read the serialized box. */
376  if ( gserialized_read_gbox_p(g, box) == LW_SUCCESS )
377  {
378  return LW_SUCCESS;
379  }
380  /* No box? Try to peek into simpler geometries and */
381  /* derive a box without creating an lwgeom */
382  else if ( gserialized_peek_gbox_p(g, box) == LW_SUCCESS )
383  {
384  return LW_SUCCESS;
385  }
386  /* Damn! Nothing for it but to create an lwgeom... */
387  /* See http://trac.osgeo.org/postgis/ticket/1023 */
388  else
389  {
390  LWGEOM *lwgeom = lwgeom_from_gserialized(g);
391  int ret = lwgeom_calculate_gbox(lwgeom, box);
392  gbox_float_round(box);
393  lwgeom_free(lwgeom);
394  return ret;
395  }
396 }
397 
398 
399 /***********************************************************************
400 * Calculate the GSERIALIZED size for an LWGEOM.
401 */
402 
403 /* Private functions */
404 
405 static size_t gserialized_from_any_size(const LWGEOM *geom); /* Local prototype */
406 
407 static size_t gserialized_from_lwpoint_size(const LWPOINT *point)
408 {
409  size_t size = 4; /* Type number. */
410 
411  assert(point);
412 
413  size += 4; /* Number of points (one or zero (empty)). */
414  size += point->point->npoints * FLAGS_NDIMS(point->flags) * sizeof(double);
415 
416  LWDEBUGF(3, "point size = %d", size);
417 
418  return size;
419 }
420 
421 static size_t gserialized_from_lwline_size(const LWLINE *line)
422 {
423  size_t size = 4; /* Type number. */
424 
425  assert(line);
426 
427  size += 4; /* Number of points (zero => empty). */
428  size += line->points->npoints * FLAGS_NDIMS(line->flags) * sizeof(double);
429 
430  LWDEBUGF(3, "linestring size = %d", size);
431 
432  return size;
433 }
434 
435 static size_t gserialized_from_lwtriangle_size(const LWTRIANGLE *triangle)
436 {
437  size_t size = 4; /* Type number. */
438 
439  assert(triangle);
440 
441  size += 4; /* Number of points (zero => empty). */
442  size += triangle->points->npoints * FLAGS_NDIMS(triangle->flags) * sizeof(double);
443 
444  LWDEBUGF(3, "triangle size = %d", size);
445 
446  return size;
447 }
448 
449 static size_t gserialized_from_lwpoly_size(const LWPOLY *poly)
450 {
451  size_t size = 4; /* Type number. */
452  int i = 0;
453 
454  assert(poly);
455 
456  size += 4; /* Number of rings (zero => empty). */
457  if ( poly->nrings % 2 )
458  size += 4; /* Padding to double alignment. */
459 
460  for ( i = 0; i < poly->nrings; i++ )
461  {
462  size += 4; /* Number of points in ring. */
463  size += poly->rings[i]->npoints * FLAGS_NDIMS(poly->flags) * sizeof(double);
464  }
465 
466  LWDEBUGF(3, "polygon size = %d", size);
467 
468  return size;
469 }
470 
472 {
473  size_t size = 4; /* Type number. */
474 
475  assert(curve);
476 
477  size += 4; /* Number of points (zero => empty). */
478  size += curve->points->npoints * FLAGS_NDIMS(curve->flags) * sizeof(double);
479 
480  LWDEBUGF(3, "circstring size = %d", size);
481 
482  return size;
483 }
484 
486 {
487  size_t size = 4; /* Type number. */
488  int i = 0;
489 
490  assert(col);
491 
492  size += 4; /* Number of sub-geometries (zero => empty). */
493 
494  for ( i = 0; i < col->ngeoms; i++ )
495  {
496  size_t subsize = gserialized_from_any_size(col->geoms[i]);
497  size += subsize;
498  LWDEBUGF(3, "lwcollection subgeom(%d) size = %d", i, subsize);
499  }
500 
501  LWDEBUGF(3, "lwcollection size = %d", size);
502 
503  return size;
504 }
505 
506 static size_t gserialized_from_any_size(const LWGEOM *geom)
507 {
508  LWDEBUGF(2, "Input type: %s", lwtype_name(geom->type));
509 
510  switch (geom->type)
511  {
512  case POINTTYPE:
513  return gserialized_from_lwpoint_size((LWPOINT *)geom);
514  case LINETYPE:
515  return gserialized_from_lwline_size((LWLINE *)geom);
516  case POLYGONTYPE:
517  return gserialized_from_lwpoly_size((LWPOLY *)geom);
518  case TRIANGLETYPE:
520  case CIRCSTRINGTYPE:
522  case CURVEPOLYTYPE:
523  case COMPOUNDTYPE:
524  case MULTIPOINTTYPE:
525  case MULTILINETYPE:
526  case MULTICURVETYPE:
527  case MULTIPOLYGONTYPE:
528  case MULTISURFACETYPE:
530  case TINTYPE:
531  case COLLECTIONTYPE:
533  default:
534  lwerror("Unknown geometry type: %d - %s", geom->type, lwtype_name(geom->type));
535  return 0;
536  }
537 }
538 
539 /* Public function */
540 
542 {
543  size_t size = 8; /* Header overhead. */
544  assert(geom);
545 
546  if ( geom->bbox )
547  size += gbox_serialized_size(geom->flags);
548 
549  size += gserialized_from_any_size(geom);
550  LWDEBUGF(3, "g_serialize size = %d", size);
551 
552  return size;
553 }
554 
555 /***********************************************************************
556 * Serialize an LWGEOM into GSERIALIZED.
557 */
558 
559 /* Private functions */
560 
561 static size_t gserialized_from_lwgeom_any(const LWGEOM *geom, uint8_t *buf);
562 
563 static size_t gserialized_from_lwpoint(const LWPOINT *point, uint8_t *buf)
564 {
565  uint8_t *loc;
566  int ptsize = ptarray_point_size(point->point);
567  int type = POINTTYPE;
568 
569  assert(point);
570  assert(buf);
571 
572  if ( FLAGS_GET_ZM(point->flags) != FLAGS_GET_ZM(point->point->flags) )
573  lwerror("Dimensions mismatch in lwpoint");
574 
575  LWDEBUGF(2, "lwpoint_to_gserialized(%p, %p) called", point, buf);
576 
577  loc = buf;
578 
579  /* Write in the type. */
580  memcpy(loc, &type, sizeof(uint32_t));
581  loc += sizeof(uint32_t);
582  /* Write in the number of points (0 => empty). */
583  memcpy(loc, &(point->point->npoints), sizeof(uint32_t));
584  loc += sizeof(uint32_t);
585 
586  /* Copy in the ordinates. */
587  if ( point->point->npoints > 0 )
588  {
589  memcpy(loc, getPoint_internal(point->point, 0), ptsize);
590  loc += ptsize;
591  }
592 
593  return (size_t)(loc - buf);
594 }
595 
596 static size_t gserialized_from_lwline(const LWLINE *line, uint8_t *buf)
597 {
598  uint8_t *loc;
599  int ptsize;
600  size_t size;
601  int type = LINETYPE;
602 
603  assert(line);
604  assert(buf);
605 
606  LWDEBUGF(2, "lwline_to_gserialized(%p, %p) called", line, buf);
607 
608  if ( FLAGS_GET_Z(line->flags) != FLAGS_GET_Z(line->points->flags) )
609  lwerror("Dimensions mismatch in lwline");
610 
611  ptsize = ptarray_point_size(line->points);
612 
613  loc = buf;
614 
615  /* Write in the type. */
616  memcpy(loc, &type, sizeof(uint32_t));
617  loc += sizeof(uint32_t);
618 
619  /* Write in the npoints. */
620  memcpy(loc, &(line->points->npoints), sizeof(uint32_t));
621  loc += sizeof(uint32_t);
622 
623  LWDEBUGF(3, "lwline_to_gserialized added npoints (%d)", line->points->npoints);
624 
625  /* Copy in the ordinates. */
626  if ( line->points->npoints > 0 )
627  {
628  size = line->points->npoints * ptsize;
629  memcpy(loc, getPoint_internal(line->points, 0), size);
630  loc += size;
631  }
632  LWDEBUGF(3, "lwline_to_gserialized copied serialized_pointlist (%d bytes)", ptsize * line->points->npoints);
633 
634  return (size_t)(loc - buf);
635 }
636 
637 static size_t gserialized_from_lwpoly(const LWPOLY *poly, uint8_t *buf)
638 {
639  int i;
640  uint8_t *loc;
641  int ptsize;
642  int type = POLYGONTYPE;
643 
644  assert(poly);
645  assert(buf);
646 
647  LWDEBUG(2, "lwpoly_to_gserialized called");
648 
649  ptsize = sizeof(double) * FLAGS_NDIMS(poly->flags);
650  loc = buf;
651 
652  /* Write in the type. */
653  memcpy(loc, &type, sizeof(uint32_t));
654  loc += sizeof(uint32_t);
655 
656  /* Write in the nrings. */
657  memcpy(loc, &(poly->nrings), sizeof(uint32_t));
658  loc += sizeof(uint32_t);
659 
660  /* Write in the npoints per ring. */
661  for ( i = 0; i < poly->nrings; i++ )
662  {
663  memcpy(loc, &(poly->rings[i]->npoints), sizeof(uint32_t));
664  loc += sizeof(uint32_t);
665  }
666 
667  /* Add in padding if necessary to remain double aligned. */
668  if ( poly->nrings % 2 )
669  {
670  memset(loc, 0, sizeof(uint32_t));
671  loc += sizeof(uint32_t);
672  }
673 
674  /* Copy in the ordinates. */
675  for ( i = 0; i < poly->nrings; i++ )
676  {
677  POINTARRAY *pa = poly->rings[i];
678  size_t pasize;
679 
680  if ( FLAGS_GET_ZM(poly->flags) != FLAGS_GET_ZM(pa->flags) )
681  lwerror("Dimensions mismatch in lwpoly");
682 
683  pasize = pa->npoints * ptsize;
684  memcpy(loc, getPoint_internal(pa, 0), pasize);
685  loc += pasize;
686  }
687  return (size_t)(loc - buf);
688 }
689 
690 static size_t gserialized_from_lwtriangle(const LWTRIANGLE *triangle, uint8_t *buf)
691 {
692  uint8_t *loc;
693  int ptsize;
694  size_t size;
695  int type = TRIANGLETYPE;
696 
697  assert(triangle);
698  assert(buf);
699 
700  LWDEBUGF(2, "lwtriangle_to_gserialized(%p, %p) called", triangle, buf);
701 
702  if ( FLAGS_GET_ZM(triangle->flags) != FLAGS_GET_ZM(triangle->points->flags) )
703  lwerror("Dimensions mismatch in lwtriangle");
704 
705  ptsize = ptarray_point_size(triangle->points);
706 
707  loc = buf;
708 
709  /* Write in the type. */
710  memcpy(loc, &type, sizeof(uint32_t));
711  loc += sizeof(uint32_t);
712 
713  /* Write in the npoints. */
714  memcpy(loc, &(triangle->points->npoints), sizeof(uint32_t));
715  loc += sizeof(uint32_t);
716 
717  LWDEBUGF(3, "lwtriangle_to_gserialized added npoints (%d)", triangle->points->npoints);
718 
719  /* Copy in the ordinates. */
720  if ( triangle->points->npoints > 0 )
721  {
722  size = triangle->points->npoints * ptsize;
723  memcpy(loc, getPoint_internal(triangle->points, 0), size);
724  loc += size;
725  }
726  LWDEBUGF(3, "lwtriangle_to_gserialized copied serialized_pointlist (%d bytes)", ptsize * triangle->points->npoints);
727 
728  return (size_t)(loc - buf);
729 }
730 
731 static size_t gserialized_from_lwcircstring(const LWCIRCSTRING *curve, uint8_t *buf)
732 {
733  uint8_t *loc;
734  int ptsize;
735  size_t size;
736  int type = CIRCSTRINGTYPE;
737 
738  assert(curve);
739  assert(buf);
740 
741  if (FLAGS_GET_ZM(curve->flags) != FLAGS_GET_ZM(curve->points->flags))
742  lwerror("Dimensions mismatch in lwcircstring");
743 
744 
745  ptsize = ptarray_point_size(curve->points);
746  loc = buf;
747 
748  /* Write in the type. */
749  memcpy(loc, &type, sizeof(uint32_t));
750  loc += sizeof(uint32_t);
751 
752  /* Write in the npoints. */
753  memcpy(loc, &curve->points->npoints, sizeof(uint32_t));
754  loc += sizeof(uint32_t);
755 
756  /* Copy in the ordinates. */
757  if ( curve->points->npoints > 0 )
758  {
759  size = curve->points->npoints * ptsize;
760  memcpy(loc, getPoint_internal(curve->points, 0), size);
761  loc += size;
762  }
763 
764  return (size_t)(loc - buf);
765 }
766 
767 static size_t gserialized_from_lwcollection(const LWCOLLECTION *coll, uint8_t *buf)
768 {
769  size_t subsize = 0;
770  uint8_t *loc;
771  int i;
772  int type;
773 
774  assert(coll);
775  assert(buf);
776 
777  type = coll->type;
778  loc = buf;
779 
780  /* Write in the type. */
781  memcpy(loc, &type, sizeof(uint32_t));
782  loc += sizeof(uint32_t);
783 
784  /* Write in the number of subgeoms. */
785  memcpy(loc, &coll->ngeoms, sizeof(uint32_t));
786  loc += sizeof(uint32_t);
787 
788  /* Serialize subgeoms. */
789  for ( i=0; i<coll->ngeoms; i++ )
790  {
791  if (FLAGS_GET_ZM(coll->flags) != FLAGS_GET_ZM(coll->geoms[i]->flags))
792  lwerror("Dimensions mismatch in lwcollection");
793  subsize = gserialized_from_lwgeom_any(coll->geoms[i], loc);
794  loc += subsize;
795  }
796 
797  return (size_t)(loc - buf);
798 }
799 
800 static size_t gserialized_from_lwgeom_any(const LWGEOM *geom, uint8_t *buf)
801 {
802  assert(geom);
803  assert(buf);
804 
805  LWDEBUGF(2, "Input type (%d) %s, hasz: %d hasm: %d",
806  geom->type, lwtype_name(geom->type),
807  FLAGS_GET_Z(geom->flags), FLAGS_GET_M(geom->flags));
808  LWDEBUGF(2, "LWGEOM(%p) uint8_t(%p)", geom, buf);
809 
810  switch (geom->type)
811  {
812  case POINTTYPE:
813  return gserialized_from_lwpoint((LWPOINT *)geom, buf);
814  case LINETYPE:
815  return gserialized_from_lwline((LWLINE *)geom, buf);
816  case POLYGONTYPE:
817  return gserialized_from_lwpoly((LWPOLY *)geom, buf);
818  case TRIANGLETYPE:
819  return gserialized_from_lwtriangle((LWTRIANGLE *)geom, buf);
820  case CIRCSTRINGTYPE:
821  return gserialized_from_lwcircstring((LWCIRCSTRING *)geom, buf);
822  case CURVEPOLYTYPE:
823  case COMPOUNDTYPE:
824  case MULTIPOINTTYPE:
825  case MULTILINETYPE:
826  case MULTICURVETYPE:
827  case MULTIPOLYGONTYPE:
828  case MULTISURFACETYPE:
830  case TINTYPE:
831  case COLLECTIONTYPE:
832  return gserialized_from_lwcollection((LWCOLLECTION *)geom, buf);
833  default:
834  lwerror("Unknown geometry type: %d - %s", geom->type, lwtype_name(geom->type));
835  return 0;
836  }
837  return 0;
838 }
839 
840 static size_t gserialized_from_gbox(const GBOX *gbox, uint8_t *buf)
841 {
842  uint8_t *loc = buf;
843  float f;
844  size_t return_size;
845 
846  assert(buf);
847 
848  f = next_float_down(gbox->xmin);
849  memcpy(loc, &f, sizeof(float));
850  loc += sizeof(float);
851 
852  f = next_float_up(gbox->xmax);
853  memcpy(loc, &f, sizeof(float));
854  loc += sizeof(float);
855 
856  f = next_float_down(gbox->ymin);
857  memcpy(loc, &f, sizeof(float));
858  loc += sizeof(float);
859 
860  f = next_float_up(gbox->ymax);
861  memcpy(loc, &f, sizeof(float));
862  loc += sizeof(float);
863 
864  if ( FLAGS_GET_GEODETIC(gbox->flags) )
865  {
866  f = next_float_down(gbox->zmin);
867  memcpy(loc, &f, sizeof(float));
868  loc += sizeof(float);
869 
870  f = next_float_up(gbox->zmax);
871  memcpy(loc, &f, sizeof(float));
872  loc += sizeof(float);
873 
874  return_size = (size_t)(loc - buf);
875  LWDEBUGF(4, "returning size %d", return_size);
876  return return_size;
877  }
878 
879  if ( FLAGS_GET_Z(gbox->flags) )
880  {
881  f = next_float_down(gbox->zmin);
882  memcpy(loc, &f, sizeof(float));
883  loc += sizeof(float);
884 
885  f = next_float_up(gbox->zmax);
886  memcpy(loc, &f, sizeof(float));
887  loc += sizeof(float);
888 
889  }
890 
891  if ( FLAGS_GET_M(gbox->flags) )
892  {
893  f = next_float_down(gbox->mmin);
894  memcpy(loc, &f, sizeof(float));
895  loc += sizeof(float);
896 
897  f = next_float_up(gbox->mmax);
898  memcpy(loc, &f, sizeof(float));
899  loc += sizeof(float);
900  }
901  return_size = (size_t)(loc - buf);
902  LWDEBUGF(4, "returning size %d", return_size);
903  return return_size;
904 }
905 
906 /* Public function */
907 
908 GSERIALIZED* gserialized_from_lwgeom(LWGEOM *geom, int is_geodetic, size_t *size)
909 {
910  size_t expected_size = 0;
911  size_t return_size = 0;
912  uint8_t *serialized = NULL;
913  uint8_t *ptr = NULL;
914  GSERIALIZED *g = NULL;
915  assert(geom);
916 
917  /*
918  ** See if we need a bounding box, add one if we don't have one.
919  */
920  if ( (! geom->bbox) && lwgeom_needs_bbox(geom) && (!lwgeom_is_empty(geom)) )
921  {
922  lwgeom_add_bbox(geom);
923  }
924 
925  /*
926  ** Harmonize the flags to the state of the lwgeom
927  */
928  if ( geom->bbox )
929  FLAGS_SET_BBOX(geom->flags, 1);
930 
931  /* Set up the uint8_t buffer into which we are going to write the serialized geometry. */
932  expected_size = gserialized_from_lwgeom_size(geom);
933  serialized = lwalloc(expected_size);
934  ptr = serialized;
935 
936  /* Move past size, srid and flags. */
937  ptr += 8;
938 
939  /* Write in the serialized form of the gbox, if necessary. */
940  if ( geom->bbox )
941  ptr += gserialized_from_gbox(geom->bbox, ptr);
942 
943  /* Write in the serialized form of the geometry. */
944  ptr += gserialized_from_lwgeom_any(geom, ptr);
945 
946  /* Calculate size as returned by data processing functions. */
947  return_size = ptr - serialized;
948 
949  if ( expected_size != return_size ) /* Uh oh! */
950  {
951  lwerror("Return size (%d) not equal to expected size (%d)!", return_size, expected_size);
952  return NULL;
953  }
954 
955  if ( size ) /* Return the output size to the caller if necessary. */
956  *size = return_size;
957 
958  g = (GSERIALIZED*)serialized;
959 
960  /*
961  ** We are aping PgSQL code here, PostGIS code should use
962  ** VARSIZE to set this for real.
963  */
964  g->size = return_size << 2;
965 
966  /* Set the SRID! */
967  gserialized_set_srid(g, geom->srid);
968 
969  g->flags = geom->flags;
970 
971  return g;
972 }
973 
974 /***********************************************************************
975 * De-serialize GSERIALIZED into an LWGEOM.
976 */
977 
978 static LWGEOM* lwgeom_from_gserialized_buffer(uint8_t *data_ptr, uint8_t g_flags, size_t *g_size);
979 
980 static LWPOINT* lwpoint_from_gserialized_buffer(uint8_t *data_ptr, uint8_t g_flags, size_t *g_size)
981 {
982  uint8_t *start_ptr = data_ptr;
983  LWPOINT *point;
984  uint32_t npoints = 0;
985 
986  assert(data_ptr);
987 
988  point = (LWPOINT*)lwalloc(sizeof(LWPOINT));
989  point->srid = SRID_UNKNOWN; /* Default */
990  point->bbox = NULL;
991  point->type = POINTTYPE;
992  point->flags = g_flags;
993 
994  data_ptr += 4; /* Skip past the type. */
995  npoints = lw_get_uint32_t(data_ptr); /* Zero => empty geometry */
996  data_ptr += 4; /* Skip past the npoints. */
997 
998  if ( npoints > 0 )
999  point->point = ptarray_construct_reference_data(FLAGS_GET_Z(g_flags), FLAGS_GET_M(g_flags), 1, data_ptr);
1000  else
1001  point->point = ptarray_construct(FLAGS_GET_Z(g_flags), FLAGS_GET_M(g_flags), 0); /* Empty point */
1002 
1003  data_ptr += npoints * FLAGS_NDIMS(g_flags) * sizeof(double);
1004 
1005  if ( g_size )
1006  *g_size = data_ptr - start_ptr;
1007 
1008  return point;
1009 }
1010 
1011 static LWLINE* lwline_from_gserialized_buffer(uint8_t *data_ptr, uint8_t g_flags, size_t *g_size)
1012 {
1013  uint8_t *start_ptr = data_ptr;
1014  LWLINE *line;
1015  uint32_t npoints = 0;
1016 
1017  assert(data_ptr);
1018 
1019  line = (LWLINE*)lwalloc(sizeof(LWLINE));
1020  line->srid = SRID_UNKNOWN; /* Default */
1021  line->bbox = NULL;
1022  line->type = LINETYPE;
1023  line->flags = g_flags;
1024 
1025  data_ptr += 4; /* Skip past the type. */
1026  npoints = lw_get_uint32_t(data_ptr); /* Zero => empty geometry */
1027  data_ptr += 4; /* Skip past the npoints. */
1028 
1029  if ( npoints > 0 )
1030  line->points = ptarray_construct_reference_data(FLAGS_GET_Z(g_flags), FLAGS_GET_M(g_flags), npoints, data_ptr);
1031 
1032  else
1033  line->points = ptarray_construct(FLAGS_GET_Z(g_flags), FLAGS_GET_M(g_flags), 0); /* Empty linestring */
1034 
1035  data_ptr += FLAGS_NDIMS(g_flags) * npoints * sizeof(double);
1036 
1037  if ( g_size )
1038  *g_size = data_ptr - start_ptr;
1039 
1040  return line;
1041 }
1042 
1043 static LWPOLY* lwpoly_from_gserialized_buffer(uint8_t *data_ptr, uint8_t g_flags, size_t *g_size)
1044 {
1045  uint8_t *start_ptr = data_ptr;
1046  LWPOLY *poly;
1047  uint8_t *ordinate_ptr;
1048  uint32_t nrings = 0;
1049  int i = 0;
1050 
1051  assert(data_ptr);
1052 
1053  poly = (LWPOLY*)lwalloc(sizeof(LWPOLY));
1054  poly->srid = SRID_UNKNOWN; /* Default */
1055  poly->bbox = NULL;
1056  poly->type = POLYGONTYPE;
1057  poly->flags = g_flags;
1058 
1059  data_ptr += 4; /* Skip past the polygontype. */
1060  nrings = lw_get_uint32_t(data_ptr); /* Zero => empty geometry */
1061  poly->nrings = nrings;
1062  LWDEBUGF(4, "nrings = %d", nrings);
1063  data_ptr += 4; /* Skip past the nrings. */
1064 
1065  ordinate_ptr = data_ptr; /* Start the ordinate pointer. */
1066  if ( nrings > 0)
1067  {
1068  poly->rings = (POINTARRAY**)lwalloc( sizeof(POINTARRAY*) * nrings );
1069  ordinate_ptr += nrings * 4; /* Move past all the npoints values. */
1070  if ( nrings % 2 ) /* If there is padding, move past that too. */
1071  ordinate_ptr += 4;
1072  }
1073  else /* Empty polygon */
1074  {
1075  poly->rings = NULL;
1076  }
1077 
1078  for ( i = 0; i < nrings; i++ )
1079  {
1080  uint32_t npoints = 0;
1081 
1082  /* Read in the number of points. */
1083  npoints = lw_get_uint32_t(data_ptr);
1084  data_ptr += 4;
1085 
1086  /* Make a point array for the ring, and move the ordinate pointer past the ring ordinates. */
1087  poly->rings[i] = ptarray_construct_reference_data(FLAGS_GET_Z(g_flags), FLAGS_GET_M(g_flags), npoints, ordinate_ptr);
1088 
1089  ordinate_ptr += sizeof(double) * FLAGS_NDIMS(g_flags) * npoints;
1090  }
1091 
1092  if ( g_size )
1093  *g_size = ordinate_ptr - start_ptr;
1094 
1095  return poly;
1096 }
1097 
1098 static LWTRIANGLE* lwtriangle_from_gserialized_buffer(uint8_t *data_ptr, uint8_t g_flags, size_t *g_size)
1099 {
1100  uint8_t *start_ptr = data_ptr;
1101  LWTRIANGLE *triangle;
1102  uint32_t npoints = 0;
1103 
1104  assert(data_ptr);
1105 
1106  triangle = (LWTRIANGLE*)lwalloc(sizeof(LWTRIANGLE));
1107  triangle->srid = SRID_UNKNOWN; /* Default */
1108  triangle->bbox = NULL;
1109  triangle->type = TRIANGLETYPE;
1110  triangle->flags = g_flags;
1111 
1112  data_ptr += 4; /* Skip past the type. */
1113  npoints = lw_get_uint32_t(data_ptr); /* Zero => empty geometry */
1114  data_ptr += 4; /* Skip past the npoints. */
1115 
1116  if ( npoints > 0 )
1117  triangle->points = ptarray_construct_reference_data(FLAGS_GET_Z(g_flags), FLAGS_GET_M(g_flags), npoints, data_ptr);
1118  else
1119  triangle->points = ptarray_construct(FLAGS_GET_Z(g_flags), FLAGS_GET_M(g_flags), 0); /* Empty triangle */
1120 
1121  data_ptr += FLAGS_NDIMS(g_flags) * npoints * sizeof(double);
1122 
1123  if ( g_size )
1124  *g_size = data_ptr - start_ptr;
1125 
1126  return triangle;
1127 }
1128 
1129 static LWCIRCSTRING* lwcircstring_from_gserialized_buffer(uint8_t *data_ptr, uint8_t g_flags, size_t *g_size)
1130 {
1131  uint8_t *start_ptr = data_ptr;
1132  LWCIRCSTRING *circstring;
1133  uint32_t npoints = 0;
1134 
1135  assert(data_ptr);
1136 
1137  circstring = (LWCIRCSTRING*)lwalloc(sizeof(LWCIRCSTRING));
1138  circstring->srid = SRID_UNKNOWN; /* Default */
1139  circstring->bbox = NULL;
1140  circstring->type = CIRCSTRINGTYPE;
1141  circstring->flags = g_flags;
1142 
1143  data_ptr += 4; /* Skip past the circstringtype. */
1144  npoints = lw_get_uint32_t(data_ptr); /* Zero => empty geometry */
1145  data_ptr += 4; /* Skip past the npoints. */
1146 
1147  if ( npoints > 0 )
1148  circstring->points = ptarray_construct_reference_data(FLAGS_GET_Z(g_flags), FLAGS_GET_M(g_flags), npoints, data_ptr);
1149  else
1150  circstring->points = ptarray_construct(FLAGS_GET_Z(g_flags), FLAGS_GET_M(g_flags), 0); /* Empty circularstring */
1151 
1152  data_ptr += FLAGS_NDIMS(g_flags) * npoints * sizeof(double);
1153 
1154  if ( g_size )
1155  *g_size = data_ptr - start_ptr;
1156 
1157  return circstring;
1158 }
1159 
1160 static LWCOLLECTION* lwcollection_from_gserialized_buffer(uint8_t *data_ptr, uint8_t g_flags, size_t *g_size)
1161 {
1162  uint32_t type;
1163  uint8_t *start_ptr = data_ptr;
1164  LWCOLLECTION *collection;
1165  uint32_t ngeoms = 0;
1166  int i = 0;
1167 
1168  assert(data_ptr);
1169 
1170  type = lw_get_uint32_t(data_ptr);
1171  data_ptr += 4; /* Skip past the type. */
1172 
1173  collection = (LWCOLLECTION*)lwalloc(sizeof(LWCOLLECTION));
1174  collection->srid = SRID_UNKNOWN; /* Default */
1175  collection->bbox = NULL;
1176  collection->type = type;
1177  collection->flags = g_flags;
1178 
1179  ngeoms = lw_get_uint32_t(data_ptr);
1180  collection->ngeoms = ngeoms; /* Zero => empty geometry */
1181  data_ptr += 4; /* Skip past the ngeoms. */
1182 
1183  if ( ngeoms > 0 )
1184  collection->geoms = lwalloc(sizeof(LWGEOM*) * ngeoms);
1185  else
1186  collection->geoms = NULL;
1187 
1188  /* Sub-geometries are never de-serialized with boxes (#1254) */
1189  FLAGS_SET_BBOX(g_flags, 0);
1190 
1191  for ( i = 0; i < ngeoms; i++ )
1192  {
1193  uint32_t subtype = lw_get_uint32_t(data_ptr);
1194  size_t subsize = 0;
1195 
1196  if ( ! lwcollection_allows_subtype(type, subtype) )
1197  {
1198  lwerror("Invalid subtype (%s) for collection type (%s)", lwtype_name(subtype), lwtype_name(type));
1199  lwfree(collection);
1200  return NULL;
1201  }
1202  collection->geoms[i] = lwgeom_from_gserialized_buffer(data_ptr, g_flags, &subsize);
1203  data_ptr += subsize;
1204  }
1205 
1206  if ( g_size )
1207  *g_size = data_ptr - start_ptr;
1208 
1209  return collection;
1210 }
1211 
1212 LWGEOM* lwgeom_from_gserialized_buffer(uint8_t *data_ptr, uint8_t g_flags, size_t *g_size)
1213 {
1214  uint32_t type;
1215 
1216  assert(data_ptr);
1217 
1218  type = lw_get_uint32_t(data_ptr);
1219 
1220  LWDEBUGF(2, "Got type %d (%s), hasz=%d hasm=%d geodetic=%d hasbox=%d", type, lwtype_name(type),
1221  FLAGS_GET_Z(g_flags), FLAGS_GET_M(g_flags), FLAGS_GET_GEODETIC(g_flags), FLAGS_GET_BBOX(g_flags));
1222 
1223  switch (type)
1224  {
1225  case POINTTYPE:
1226  return (LWGEOM *)lwpoint_from_gserialized_buffer(data_ptr, g_flags, g_size);
1227  case LINETYPE:
1228  return (LWGEOM *)lwline_from_gserialized_buffer(data_ptr, g_flags, g_size);
1229  case CIRCSTRINGTYPE:
1230  return (LWGEOM *)lwcircstring_from_gserialized_buffer(data_ptr, g_flags, g_size);
1231  case POLYGONTYPE:
1232  return (LWGEOM *)lwpoly_from_gserialized_buffer(data_ptr, g_flags, g_size);
1233  case TRIANGLETYPE:
1234  return (LWGEOM *)lwtriangle_from_gserialized_buffer(data_ptr, g_flags, g_size);
1235  case MULTIPOINTTYPE:
1236  case MULTILINETYPE:
1237  case MULTIPOLYGONTYPE:
1238  case COMPOUNDTYPE:
1239  case CURVEPOLYTYPE:
1240  case MULTICURVETYPE:
1241  case MULTISURFACETYPE:
1242  case POLYHEDRALSURFACETYPE:
1243  case TINTYPE:
1244  case COLLECTIONTYPE:
1245  return (LWGEOM *)lwcollection_from_gserialized_buffer(data_ptr, g_flags, g_size);
1246  default:
1247  lwerror("Unknown geometry type: %d - %s", type, lwtype_name(type));
1248  return NULL;
1249  }
1250 }
1251 
1253 {
1254  uint8_t g_flags = 0;
1255  int32_t g_srid = 0;
1256  uint32_t g_type = 0;
1257  uint8_t *data_ptr = NULL;
1258  LWGEOM *lwgeom = NULL;
1259  GBOX bbox;
1260  size_t g_size = 0;
1261 
1262  assert(g);
1263 
1264  g_srid = gserialized_get_srid(g);
1265  g_flags = g->flags;
1266  g_type = gserialized_get_type(g);
1267  LWDEBUGF(4, "Got type %d (%s), srid=%d", g_type, lwtype_name(g_type), g_srid);
1268 
1269  data_ptr = (uint8_t*)g->data;
1270  if ( FLAGS_GET_BBOX(g_flags) )
1271  data_ptr += gbox_serialized_size(g_flags);
1272 
1273  lwgeom = lwgeom_from_gserialized_buffer(data_ptr, g_flags, &g_size);
1274 
1275  if ( ! lwgeom )
1276  lwerror("lwgeom_from_gserialized: unable create geometry"); /* Ooops! */
1277 
1278  lwgeom->type = g_type;
1279  lwgeom->flags = g_flags;
1280 
1281  if ( gserialized_read_gbox_p(g, &bbox) == LW_SUCCESS )
1282  {
1283  lwgeom->bbox = gbox_copy(&bbox);
1284  }
1285  else if ( lwgeom_needs_bbox(lwgeom) && (lwgeom_calculate_gbox(lwgeom, &bbox) == LW_SUCCESS) )
1286  {
1287  lwgeom->bbox = gbox_copy(&bbox);
1288  }
1289  else
1290  {
1291  lwgeom->bbox = NULL;
1292  }
1293 
1294  lwgeom_set_srid(lwgeom, g_srid);
1295 
1296  return lwgeom;
1297 }
1298 
int gserialized_get_gbox_p(const GSERIALIZED *g, GBOX *box)
Read the bounding box off a serialization and calculate one if it is not already there.
Definition: g_serialized.c:373
#define LINETYPE
Definition: liblwgeom.h:61
GBOX * gbox_copy(const GBOX *box)
Return a copy of the GBOX, based on dimensionality of flags.
Definition: g_box.c:362
static LWLINE * lwline_from_gserialized_buffer(uint8_t *data_ptr, uint8_t g_flags, size_t *g_size)
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:56
uint8_t type
Definition: liblwgeom.h:374
int clamp_srid(int srid)
Return a valid SRID from an arbitrary integer Raises a notice if what comes out is different from wha...
Definition: lwutil.c:326
int gserialized_read_gbox_p(const GSERIALIZED *g, GBOX *gbox)
Pull a GBOX from the header of a GSERIALIZED, if one is available.
Definition: g_serialized.c:159
POINTARRAY * ptarray_construct(char hasz, char hasm, uint32_t npoints)
Construct an empty pointarray, allocating storage and setting the npoints, but not filling in any inf...
Definition: ptarray.c:49
static LWTRIANGLE * lwtriangle_from_gserialized_buffer(uint8_t *data_ptr, uint8_t g_flags, size_t *g_size)
static LWCIRCSTRING * lwcircstring_from_gserialized_buffer(uint8_t *data_ptr, uint8_t g_flags, size_t *g_size)
GBOX * bbox
Definition: liblwgeom.h:354
uint8_t flags
Definition: liblwgeom.h:397
POINTARRAY * points
Definition: liblwgeom.h:389
uint8_t data[1]
Definition: liblwgeom.h:340
#define MULTICURVETYPE
Definition: liblwgeom.h:70
static LWCOLLECTION * lwcollection_from_gserialized_buffer(uint8_t *data_ptr, uint8_t g_flags, size_t *g_size)
GBOX * bbox
Definition: liblwgeom.h:376
uint8_t type
Definition: liblwgeom.h:363
char * lwgeom_to_wkt(const LWGEOM *geom, uint8_t variant, int precision, size_t *size_out)
WKT emitter function.
Definition: lwout_wkt.c:655
static size_t gserialized_from_lwcollection(const LWCOLLECTION *coll, uint8_t *buf)
Definition: g_serialized.c:767
void lwfree(void *mem)
Definition: lwutil.c:190
LWGEOM * lwgeom_from_gserialized(const GSERIALIZED *g)
Allocate a new LWGEOM from a GSERIALIZED.
int npoints
Definition: liblwgeom.h:327
uint8_t type
Definition: liblwgeom.h:459
int gserialized_has_m(const GSERIALIZED *gser)
Check if a GSERIALIZED has an M ordinate.
Definition: g_serialized.c:30
static LWPOLY * lwpoly_from_gserialized_buffer(uint8_t *data_ptr, uint8_t g_flags, size_t *g_size)
static size_t gserialized_from_lwcircstring_size(const LWCIRCSTRING *curve)
Definition: g_serialized.c:471
int32_t srid
Definition: liblwgeom.h:399
static int gserialized_peek_gbox_p(const GSERIALIZED *g, GBOX *gbox)
Definition: g_serialized.c:206
#define FLAGS_GET_GEODETIC(flags)
Definition: liblwgeom.h:109
static size_t gserialized_from_lwpoint_size(const LWPOINT *point)
Definition: g_serialized.c:407
#define POLYGONTYPE
Definition: liblwgeom.h:62
uint8_t flags
Definition: liblwgeom.h:353
double xmax
Definition: liblwgeom.h:249
#define CURVEPOLYTYPE
Definition: liblwgeom.h:69
void lwgeom_free(LWGEOM *geom)
Definition: lwgeom.c:1006
#define COMPOUNDTYPE
Definition: liblwgeom.h:68
#define MULTIPOINTTYPE
Definition: liblwgeom.h:63
#define LW_SUCCESS
Definition: liblwgeom.h:55
static size_t gserialized_from_gbox(const GBOX *gbox, uint8_t *buf)
Definition: g_serialized.c:840
GBOX * bbox
Definition: liblwgeom.h:461
int gserialized_ndims(const GSERIALIZED *gser)
Return the number of dimensions (2, 3, 4) in a geometry.
Definition: g_serialized.c:40
#define FLAGS_GET_ZM(flags)
Definition: liblwgeom.h:119
#define LWDEBUG(level, msg)
Definition: lwgeom_log.h:50
void gserialized_set_srid(GSERIALIZED *s, int32_t srid)
Write the SRID into the serialized form (it is packed into three bytes so this is a handy function)...
Definition: g_serialized.c:87
#define TRIANGLETYPE
Definition: liblwgeom.h:73
#define POLYHEDRALSURFACETYPE
Definition: liblwgeom.h:72
GBOX * bbox
Definition: liblwgeom.h:387
float next_float_down(double d)
Definition: lwgeom_api.c:129
GBOX * bbox
Definition: liblwgeom.h:409
GSERIALIZED * gserialized_copy(const GSERIALIZED *g)
Return a copy of the input serialized geometry.
Definition: g_serialized.c:103
int32_t srid
Definition: liblwgeom.h:377
#define FP_MIN(A, B)
int gserialized_has_bbox(const GSERIALIZED *gser)
Check if a GSERIALIZED has a bounding box without deserializing first.
Definition: g_serialized.c:20
POINTARRAY * point
Definition: liblwgeom.h:367
int gserialized_has_z(const GSERIALIZED *gser)
Check if a GSERIALIZED has a Z ordinate.
Definition: g_serialized.c:25
int32_t srid
Definition: liblwgeom.h:355
static size_t gserialized_from_lwline_size(const LWLINE *line)
Definition: g_serialized.c:421
uint8_t type
Definition: liblwgeom.h:385
int gserialized_is_empty(const GSERIALIZED *g)
Check if a GSERIALIZED is empty without deserializing first.
Definition: g_serialized.c:140
#define LW_FAILURE
Definition: liblwgeom.h:54
static size_t gserialized_from_lwtriangle(const LWTRIANGLE *triangle, uint8_t *buf)
Definition: g_serialized.c:690
float next_float_up(double d)
Definition: lwgeom_api.c:145
void lwerror(const char *fmt,...)
Write a notice out to the error handler.
Definition: lwutil.c:67
int lwgeom_calculate_gbox(const LWGEOM *lwgeom, GBOX *gbox)
Calculate bounding box of a geometry, automatically taking into account whether it is cartesian or ge...
Definition: lwgeom.c:608
uint8_t flags
Definition: liblwgeom.h:460
void gbox_float_round(GBOX *gbox)
Round given GBOX to float boundaries.
Definition: g_box.c:641
uint32_t lw_get_uint32_t(const uint8_t *loc)
Definition: lwgeom_api.c:534
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
static size_t gserialized_from_lwpoly(const LWPOLY *poly, uint8_t *buf)
Definition: g_serialized.c:637
static size_t gserialized_is_empty_recurse(const uint8_t *p, int *isempty)
Definition: g_serialized.c:113
#define WKT_ISO
Definition: liblwgeom.h:1776
static size_t gserialized_from_lwpoint(const LWPOINT *point, uint8_t *buf)
Definition: g_serialized.c:563
double xmin
Definition: liblwgeom.h:248
#define FLAGS_GET_BBOX(flags)
Definition: liblwgeom.h:108
#define LW_FALSE
Definition: liblwgeom.h:52
uint8_t type
Definition: liblwgeom.h:407
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
uint8_t type
Definition: liblwgeom.h:396
uint8_t * getPoint_internal(const POINTARRAY *pa, int n)
Definition: ptarray.c:1645
int ptarray_point_size(const POINTARRAY *pa)
Definition: ptarray.c:41
POINTARRAY * ptarray_construct_reference_data(char hasz, char hasm, uint32_t npoints, uint8_t *ptlist)
Construct a new POINTARRAY, referencing to the data from ptlist.
Definition: ptarray.c:280
GSERIALIZED * gserialized_from_lwgeom(LWGEOM *geom, int is_geodetic, size_t *size)
Allocate a new GSERIALIZED from an LWGEOM.
Definition: g_serialized.c:908
static size_t gserialized_from_any_size(const LWGEOM *geom)
Definition: g_serialized.c:506
POINTARRAY ** rings
Definition: liblwgeom.h:413
int lwtype_is_collection(uint8_t type)
Determine whether a type number is a collection or not.
Definition: lwgeom.c:955
int nrings
Definition: liblwgeom.h:411
int32_t srid
Definition: liblwgeom.h:462
double ymax
Definition: liblwgeom.h:251
char * s
Definition: cu_in_wkt.c:24
#define FLAGS_GET_Z(flags)
Macros for manipulating the 'flags' byte.
Definition: liblwgeom.h:106
int32_t srid
Definition: liblwgeom.h:366
uint8_t flags
Definition: liblwgeom.h:247
static LWGEOM * lwgeom_from_gserialized_buffer(uint8_t *data_ptr, uint8_t g_flags, size_t *g_size)
GBOX * bbox
Definition: liblwgeom.h:398
#define MULTIPOLYGONTYPE
Definition: liblwgeom.h:65
uint8_t flags
Definition: liblwgeom.h:364
int gserialized_get_zm(const GSERIALIZED *gser)
Return a number indicating presence of Z and M coordinates.
Definition: g_serialized.c:35
#define FLAGS_SET_BBOX(flags, value)
Definition: liblwgeom.h:114
GBOX * bbox
Definition: liblwgeom.h:365
#define SIZE_GET(varsize)
Macro for reading the size from the GSERIALIZED size attribute.
static size_t gserialized_from_lwcollection_size(const LWCOLLECTION *col)
Definition: g_serialized.c:485
size_t gserialized_from_lwgeom_size(const LWGEOM *geom)
Calculate required memory segment to contain a serialized form of the LWGEOM.
Definition: g_serialized.c:541
#define MULTISURFACETYPE
Definition: liblwgeom.h:71
static size_t gserialized_from_lwpoly_size(const LWPOLY *poly)
Definition: g_serialized.c:449
int32_t srid
Definition: liblwgeom.h:410
uint32_t size
Definition: liblwgeom.h:337
uint8_t srid[3]
Definition: liblwgeom.h:338
double mmin
Definition: liblwgeom.h:254
double zmin
Definition: liblwgeom.h:252
#define POINTTYPE
LWTYPE numbers, used internally by PostGIS.
Definition: liblwgeom.h:60
char * gserialized_to_string(const GSERIALIZED *g)
Return a WKT representation of the gserialized geometry.
Definition: g_serialized.c:154
void lwgeom_add_bbox(LWGEOM *lwgeom)
Compute a bbox if not already computed.
Definition: lwgeom.c:555
#define FLAGS_GET_M(flags)
Definition: liblwgeom.h:107
uint8_t type
Definition: liblwgeom.h:352
static size_t gserialized_from_lwgeom_any(const LWGEOM *geom, uint8_t *buf)
Definition: g_serialized.c:800
double mmax
Definition: liblwgeom.h:255
tuple g_size
Definition: genraster.py:42
POINTARRAY * points
Definition: liblwgeom.h:400
int gserialized_is_geodetic(const GSERIALIZED *gser)
Check if a GSERIALIZED is a geography.
Definition: g_serialized.c:45
void lwgeom_set_srid(LWGEOM *geom, int srid)
Set the SRID on an LWGEOM For collections, only the parent gets an SRID, all the children get SRID_UN...
int lwcollection_allows_subtype(int collectiontype, int subtype)
Check if subtype is allowed in collectiontype.
Definition: lwcollection.c:513
#define CIRCSTRINGTYPE
Definition: liblwgeom.h:67
uint8_t flags
Definition: liblwgeom.h:408
void * lwalloc(size_t size)
Definition: lwutil.c:175
static size_t gserialized_from_lwcircstring(const LWCIRCSTRING *curve, uint8_t *buf)
Definition: g_serialized.c:731
int lwgeom_is_empty(const LWGEOM *geom)
Return true or false depending on whether a geometry is an "empty" geometry (no vertices members) ...
Definition: lwgeom.c:1229
#define MULTILINETYPE
Definition: liblwgeom.h:64
uint8_t flags
Definition: liblwgeom.h:375
#define LWDEBUGF(level, msg,...)
Definition: lwgeom_log.h:55
#define FLAGS_NDIMS(flags)
Definition: liblwgeom.h:118
static size_t gserialized_from_lwline(const LWLINE *line, uint8_t *buf)
Definition: g_serialized.c:596
int lwgeom_needs_bbox(const LWGEOM *geom)
Check whether or not a lwgeom is big enough to warrant a bounding box.
Definition: lwgeom.c:1059
static LWPOINT * lwpoint_from_gserialized_buffer(uint8_t *data_ptr, uint8_t g_flags, size_t *g_size)
Definition: g_serialized.c:980
int32_t gserialized_get_srid(const GSERIALIZED *s)
Extract the SRID from the serialized form (it is packed into three bytes so this is a handy function)...
Definition: g_serialized.c:70
if(!(yy_init))
Definition: lwin_wkt_lex.c:860
int32_t srid
Definition: liblwgeom.h:388
static size_t gserialized_from_lwtriangle_size(const LWTRIANGLE *triangle)
Definition: g_serialized.c:435
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
#define COLLECTIONTYPE
Definition: liblwgeom.h:66
uint32_t gserialized_max_header_size(void)
Returns the size in bytes to read from toast to get the basic information from a geometry: GSERIALIZE...
Definition: g_serialized.c:50
uint8_t flags
Definition: liblwgeom.h:339
#define FP_MAX(A, B)
uint8_t flags
Definition: liblwgeom.h:386
POINTARRAY * points
Definition: liblwgeom.h:378