PostGIS  3.4.0dev-r@@SVN_REVISION@@

◆ TWKBFromLWGEOMArray()

Datum TWKBFromLWGEOMArray ( PG_FUNCTION_ARGS  )

Definition at line 477 of file lwgeom_inout.c.

478 {
479  ArrayType *arr_geoms = NULL;
480  ArrayType *arr_ids = NULL;
481  int num_geoms, num_ids, i = 0;
482 
483  ArrayIterator iter_geoms, iter_ids;
484  bool null_geom, null_id;
485  Datum val_geom, val_id;
486 
487  int is_homogeneous = true;
488  uint32_t subtype = 0;
489  int has_z = 0;
490  int has_m = 0;
491  LWCOLLECTION *col = NULL;
492  int64_t *idlist = NULL;
493  uint8_t variant = 0;
494 
495  srs_precision sp;
496 
497  /* The first two arguments are required */
498  if ( PG_NARGS() < 2 || PG_ARGISNULL(0) || PG_ARGISNULL(1) )
499  PG_RETURN_NULL();
500 
501  arr_geoms = PG_GETARG_ARRAYTYPE_P(0);
502  arr_ids = PG_GETARG_ARRAYTYPE_P(1);
503 
504  num_geoms = ArrayGetNItems(ARR_NDIM(arr_geoms), ARR_DIMS(arr_geoms));
505  num_ids = ArrayGetNItems(ARR_NDIM(arr_ids), ARR_DIMS(arr_ids));
506 
507  if ( num_geoms != num_ids )
508  {
509  elog(ERROR, "size of geometry[] and integer[] arrays must match");
510  PG_RETURN_NULL();
511  }
512 
513  /* Loop through array and build a collection of geometry and */
514  /* a simple array of ids. If either side is NULL, skip it */
515 
516  iter_geoms = array_create_iterator(arr_geoms, 0, NULL);
517  iter_ids = array_create_iterator(arr_ids, 0, NULL);
518 
519  while( array_iterate(iter_geoms, &val_geom, &null_geom) &&
520  array_iterate(iter_ids, &val_id, &null_id) )
521  {
522  LWGEOM *geom;
523  int32_t uid;
524 
525  if ( null_geom || null_id )
526  {
527  elog(NOTICE, "ST_AsTWKB skipping NULL entry at position %d", i);
528  continue;
529  }
530 
531  geom = lwgeom_from_gserialized((GSERIALIZED*)DatumGetPointer(val_geom));
532  uid = DatumGetInt64(val_id);
533 
534  /* Construct collection/idlist first time through */
535  if ( ! col )
536  {
537  has_z = lwgeom_has_z(geom);
538  has_m = lwgeom_has_m(geom);
539  col = lwcollection_construct_empty(COLLECTIONTYPE, lwgeom_get_srid(geom), has_z, has_m);
540  }
541  if ( ! idlist )
542  idlist = palloc0(num_geoms * sizeof(int64_t));
543 
544 
545  /* Check if there is differences in dimensionality*/
546  if( lwgeom_has_z(geom)!=has_z || lwgeom_has_m(geom)!=has_m)
547  {
548  elog(ERROR, "Geometries have different dimensionality");
549  PG_FREE_IF_COPY(arr_geoms, 0);
550  PG_FREE_IF_COPY(arr_ids, 1);
551  PG_RETURN_NULL();
552  }
553  /* Store the values */
554  lwcollection_add_lwgeom(col, geom);
555  idlist[i++] = uid;
556 
557  /* Grab the geometry type and note if all geometries share it */
558  /* If so, we can make this a homogeneous collection and save some space */
559  if ( lwgeom_get_type(geom) != subtype && subtype )
560  {
561  is_homogeneous = false;
562  }
563  else
564  {
565  subtype = lwgeom_get_type(geom);
566  }
567 
568  }
569  array_free_iterator(iter_geoms);
570  array_free_iterator(iter_ids);
571 
572  if(i==0)
573  {
574  elog(NOTICE, "No valid geometry - id pairs found");
575  PG_FREE_IF_COPY(arr_geoms, 0);
576  PG_FREE_IF_COPY(arr_ids, 1);
577  PG_RETURN_NULL();
578  }
579  if ( is_homogeneous )
580  {
581  col->type = lwtype_get_collectiontype(subtype);
582  }
583 
584  /* Read sensible precision defaults (about one meter) given the srs */
585  sp = srid_axis_precision(lwgeom_get_srid(lwcollection_as_lwgeom(col)), TWKB_DEFAULT_PRECISION);
586 
587  /* If user specified XY precision, use it */
588  if ( PG_NARGS() > 2 && ! PG_ARGISNULL(2) )
589  sp.precision_xy = PG_GETARG_INT32(2);
590 
591  /* If user specified Z precision, use it */
592  if ( PG_NARGS() > 3 && ! PG_ARGISNULL(3) )
593  sp.precision_z = PG_GETARG_INT32(3);
594 
595  /* If user specified M precision, use it */
596  if ( PG_NARGS() > 4 && ! PG_ARGISNULL(4) )
597  sp.precision_m = PG_GETARG_INT32(4);
598 
599  /* We are building an ID'ed output */
600  variant = TWKB_ID;
601 
602  /* If user wants registered twkb sizes */
603  if ( PG_NARGS() > 5 && ! PG_ARGISNULL(5) && PG_GETARG_BOOL(5) )
604  variant |= TWKB_SIZE;
605 
606  /* If user wants bounding boxes */
607  if ( PG_NARGS() > 6 && ! PG_ARGISNULL(6) && PG_GETARG_BOOL(6) )
608  variant |= TWKB_BBOX;
609 
610  /* Write out the TWKB */
611  PG_RETURN_BYTEA_P(lwgeom_to_twkb_with_idlist(
612  lwcollection_as_lwgeom(col), idlist, variant, sp.precision_xy, sp.precision_z, sp.precision_m));
613 }
static uint8_t variant
Definition: cu_in_twkb.c:26
LWGEOM * lwgeom_from_gserialized(const GSERIALIZED *g)
Allocate a new LWGEOM from a GSERIALIZED.
Definition: gserialized.c:239
LWGEOM * lwcollection_as_lwgeom(const LWCOLLECTION *obj)
Definition: lwgeom.c:309
uint32_t lwtype_get_collectiontype(uint8_t type)
Given an lwtype number, what homogeneous collection can hold it?
Definition: lwgeom.c:1131
#define COLLECTIONTYPE
Definition: liblwgeom.h:108
int32_t lwgeom_get_srid(const LWGEOM *geom)
Return SRID number.
Definition: lwgeom.c:927
int lwgeom_has_z(const LWGEOM *geom)
Return LW_TRUE if geometry has Z ordinates.
Definition: lwgeom.c:934
#define TWKB_ID
Definition: liblwgeom.h:2194
LWCOLLECTION * lwcollection_construct_empty(uint8_t type, int32_t srid, char hasz, char hasm)
Definition: lwcollection.c:92
#define TWKB_DEFAULT_PRECISION
Definition: liblwgeom.h:2197
#define TWKB_SIZE
Definition: liblwgeom.h:2193
LWCOLLECTION * lwcollection_add_lwgeom(LWCOLLECTION *col, const LWGEOM *geom)
Appends geom to the collection managed by col.
Definition: lwcollection.c:188
lwvarlena_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)
Convert LWGEOM to a char* in TWKB format.
Definition: lwout_twkb.c:589
int lwgeom_has_m(const LWGEOM *geom)
Return LW_TRUE if geometry has M ordinates.
Definition: lwgeom.c:941
#define TWKB_BBOX
Definition: liblwgeom.h:2192
static uint32_t lwgeom_get_type(const LWGEOM *geom)
Return LWTYPE number.
Definition: lwinline.h:145
uint8_t type
Definition: liblwgeom.h:578

References COLLECTIONTYPE, lwcollection_add_lwgeom(), lwcollection_as_lwgeom(), lwcollection_construct_empty(), 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.

Here is the call graph for this function: