PostGIS  2.5.0dev-r@@SVN_REVISION@@
Datum TWKBFromLWGEOMArray ( PG_FUNCTION_ARGS  )

Definition at line 521 of file lwgeom_inout.c.

References COLLECTIONTYPE, lwcollection_add_lwgeom(), lwcollection_as_lwgeom(), lwcollection_construct_empty(), lwcollection_free(), lwgeom_from_gserialized(), lwgeom_get_srid(), lwgeom_get_type(), lwgeom_has_m(), lwgeom_has_z(), lwgeom_to_twkb_with_idlist(), lwtype_get_collectiontype(), TWKB_BBOX, TWKB_DEFAULT_PRECISION, TWKB_ID, TWKB_SIZE, LWCOLLECTION::type, and variant.

522 {
523  ArrayType *arr_geoms = NULL;
524  ArrayType *arr_ids = NULL;
525  int num_geoms, num_ids, i = 0;
526 
527  ArrayIterator iter_geoms, iter_ids;
528  bool null_geom, null_id;
529  Datum val_geom, val_id;
530 
531  int is_homogeneous = true;
532  uint32_t subtype = 0;
533  int has_z = 0;
534  int has_m = 0;
535  LWCOLLECTION *col = NULL;
536  int64_t *idlist = NULL;
537  uint8_t variant = 0;
538 
539  srs_precision sp;
540  uint8_t *twkb;
541  size_t twkb_size;
542  bytea *result;
543 
544  /* The first two arguments are required */
545  if ( PG_NARGS() < 2 || PG_ARGISNULL(0) || PG_ARGISNULL(1) )
546  PG_RETURN_NULL();
547 
548  arr_geoms = PG_GETARG_ARRAYTYPE_P(0);
549  arr_ids = PG_GETARG_ARRAYTYPE_P(1);
550 
551  num_geoms = ArrayGetNItems(ARR_NDIM(arr_geoms), ARR_DIMS(arr_geoms));
552  num_ids = ArrayGetNItems(ARR_NDIM(arr_ids), ARR_DIMS(arr_ids));
553 
554  if ( num_geoms != num_ids )
555  {
556  elog(ERROR, "size of geometry[] and integer[] arrays must match");
557  PG_RETURN_NULL();
558  }
559 
560  /* Loop through array and build a collection of geometry and */
561  /* a simple array of ids. If either side is NULL, skip it */
562 
563 #if POSTGIS_PGSQL_VERSION >= 95
564  iter_geoms = array_create_iterator(arr_geoms, 0, NULL);
565  iter_ids = array_create_iterator(arr_ids, 0, NULL);
566 #else
567  iter_geoms = array_create_iterator(arr_geoms, 0);
568  iter_ids = array_create_iterator(arr_ids, 0);
569 #endif
570 
571  while( array_iterate(iter_geoms, &val_geom, &null_geom) &&
572  array_iterate(iter_ids, &val_id, &null_id) )
573  {
574  LWGEOM *geom;
575  int32_t uid;
576 
577  if ( null_geom || null_id )
578  {
579  elog(NOTICE, "ST_AsTWKB skipping NULL entry at position %d", i);
580  continue;
581  }
582 
583  geom = lwgeom_from_gserialized((GSERIALIZED*)DatumGetPointer(val_geom));
584  uid = DatumGetInt64(val_id);
585 
586  /* Construct collection/idlist first time through */
587  if ( ! col )
588  {
589  has_z = lwgeom_has_z(geom);
590  has_m = lwgeom_has_m(geom);
591  col = lwcollection_construct_empty(COLLECTIONTYPE, lwgeom_get_srid(geom), has_z, has_m);
592  }
593  if ( ! idlist )
594  idlist = palloc0(num_geoms * sizeof(int64_t));
595 
596 
597  /*Check if there is differences in dimmenstionality*/
598  if( lwgeom_has_z(geom)!=has_z || lwgeom_has_m(geom)!=has_m)
599  {
600  elog(ERROR, "Geometries have differenct dimensionality");
601  PG_FREE_IF_COPY(arr_geoms, 0);
602  PG_FREE_IF_COPY(arr_ids, 1);
603  PG_RETURN_NULL();
604  }
605  /* Store the values */
606  lwcollection_add_lwgeom(col, geom);
607  idlist[i++] = uid;
608 
609  /* Grab the geometry type and note if all geometries share it */
610  /* If so, we can make this a homogeneous collection and save some space */
611  if ( lwgeom_get_type(geom) != subtype && subtype )
612  {
613  is_homogeneous = false;
614  }
615  else
616  {
617  subtype = lwgeom_get_type(geom);
618  }
619 
620  }
621  array_free_iterator(iter_geoms);
622  array_free_iterator(iter_ids);
623 
624  if(i==0)
625  {
626  elog(NOTICE, "No valid geometry - id pairs found");
627  PG_FREE_IF_COPY(arr_geoms, 0);
628  PG_FREE_IF_COPY(arr_ids, 1);
629  PG_RETURN_NULL();
630  }
631  if ( is_homogeneous )
632  {
633  col->type = lwtype_get_collectiontype(subtype);
634  }
635 
636  /* Read sensible precision defaults (about one meter) given the srs */
637  sp = srid_axis_precision(fcinfo, lwgeom_get_srid(lwcollection_as_lwgeom(col)), TWKB_DEFAULT_PRECISION);
638 
639  /* If user specified XY precision, use it */
640  if ( PG_NARGS() > 2 && ! PG_ARGISNULL(2) )
641  sp.precision_xy = PG_GETARG_INT32(2);
642 
643  /* If user specified Z precision, use it */
644  if ( PG_NARGS() > 3 && ! PG_ARGISNULL(3) )
645  sp.precision_z = PG_GETARG_INT32(3);
646 
647  /* If user specified M precision, use it */
648  if ( PG_NARGS() > 4 && ! PG_ARGISNULL(4) )
649  sp.precision_m = PG_GETARG_INT32(4);
650 
651  /* We are building an ID'ed output */
652  variant = TWKB_ID;
653 
654  /* If user wants registered twkb sizes */
655  if ( PG_NARGS() > 5 && ! PG_ARGISNULL(5) && PG_GETARG_BOOL(5) )
656  variant |= TWKB_SIZE;
657 
658  /* If user wants bounding boxes */
659  if ( PG_NARGS() > 6 && ! PG_ARGISNULL(6) && PG_GETARG_BOOL(6) )
660  variant |= TWKB_BBOX;
661 
662  /* Write out the TWKB */
664  idlist, variant,
665  sp.precision_xy, sp.precision_z, sp.precision_m,
666  &twkb_size);
667 
668  /* Convert to a bytea return type */
669  result = palloc(twkb_size + VARHDRSZ);
670  memcpy(VARDATA(result), twkb, twkb_size);
671  SET_VARSIZE(result, twkb_size + VARHDRSZ);
672 
673  /* Clean up */
674  pfree(twkb);
675  pfree(idlist);
676  lwcollection_free(col);
677  PG_FREE_IF_COPY(arr_geoms, 0);
678  PG_FREE_IF_COPY(arr_ids, 1);
679 
680  PG_RETURN_BYTEA_P(result);
681 }
uint8_t * lwgeom_to_twkb_with_idlist(const LWGEOM *geom, int64_t *idlist, uint8_t variant, int8_t precision_xy, int8_t precision_z, int8_t precision_m, size_t *twkb_size)
Convert LWGEOM to a char* in TWKB format.
Definition: lwout_twkb.c:567
uint8_t variant
Definition: cu_in_twkb.c:26
LWGEOM * lwgeom_from_gserialized(const GSERIALIZED *g)
Allocate a new LWGEOM from a GSERIALIZED.
uint8_t type
Definition: liblwgeom.h:502
uint32_t lwgeom_get_type(const LWGEOM *geom)
Return LWTYPE number.
Definition: lwgeom.c:916
int32_t lwgeom_get_srid(const LWGEOM *geom)
Return SRID number.
Definition: lwgeom.c:909
int lwgeom_has_z(const LWGEOM *geom)
Return LW_TRUE if geometry has Z ordinates.
Definition: lwgeom.c:923
unsigned int uint32_t
Definition: uthash.h:78
#define TWKB_ID
Definition: liblwgeom.h:2078
#define TWKB_DEFAULT_PRECISION
Definition: liblwgeom.h:2081
uint32_t lwtype_get_collectiontype(uint8_t type)
Given an lwtype number, what homogeneous collection can hold it?
Definition: lwgeom.c:1113
#define TWKB_BBOX
Definition: liblwgeom.h:2076
#define TWKB_SIZE
Definition: liblwgeom.h:2077
void lwcollection_free(LWCOLLECTION *col)
Definition: lwcollection.c:342
LWCOLLECTION * lwcollection_construct_empty(uint8_t type, int srid, char hasz, char hasm)
Definition: lwcollection.c:94
unsigned char uint8_t
Definition: uthash.h:79
int lwgeom_has_m(const LWGEOM *geom)
Return LW_TRUE if geometry has M ordinates.
Definition: lwgeom.c:930
LWCOLLECTION * lwcollection_add_lwgeom(LWCOLLECTION *col, const LWGEOM *geom)
Appends geom to the collection managed by col.
Definition: lwcollection.c:187
#define COLLECTIONTYPE
Definition: liblwgeom.h:90
LWGEOM * lwcollection_as_lwgeom(const LWCOLLECTION *obj)
Definition: lwgeom.c:299

Here is the call graph for this function: