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