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