PostGIS 3.7.0dev-r@@SVN_REVISION@@
Loading...
Searching...
No Matches

◆ pgis_union_geometry_array()

Datum pgis_union_geometry_array ( PG_FUNCTION_ARGS  )

Definition at line 527 of file postgis/lwgeom_geos.c.

528{
529 ArrayType *array;
530
531 ArrayIterator iterator;
532 Datum value;
533 bool isnull;
534
535 int is3d = LW_FALSE, gotsrid = LW_FALSE;
536 int nelems = 0, geoms_size = 0, curgeom = 0, count = 0;
537
538 GSERIALIZED *gser_out = NULL;
539
540 GEOSGeometry *g = NULL;
541 GEOSGeometry *g_union = NULL;
542 GEOSGeometry **geoms = NULL;
543
544 int32_t srid = SRID_UNKNOWN;
545
546 int empty_type = 0;
547
548 /* Null array, null geometry (should be empty?) */
549 if ( PG_ARGISNULL(0) )
550 PG_RETURN_NULL();
551
552 array = PG_GETARG_ARRAYTYPE_P(0);
553 nelems = ArrayGetNItems(ARR_NDIM(array), ARR_DIMS(array));
554
555 /* Empty array? Null return */
556 if ( nelems == 0 ) PG_RETURN_NULL();
557
558 /* Quick scan for nulls */
559 iterator = array_create_iterator(array, 0, NULL);
560 while (array_iterate(iterator, &value, &isnull))
561 {
562 /* Skip null array items */
563 if (isnull) continue;
564 count++;
565 }
566 array_free_iterator(iterator);
567
568
569 /* All-nulls? Return null */
570 if ( count == 0 )
571 PG_RETURN_NULL();
572
573 /* Ok, we really need GEOS now ;) */
574 initGEOS(lwpgnotice, lwgeom_geos_error);
575
576 /* One geom, good geom? Return it */
577 if ( count == 1 && nelems == 1 )
578 {
579#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)
580#pragma GCC diagnostic push
581#pragma GCC diagnostic ignored "-Wsign-compare"
582#endif
583 g = POSTGIS2GEOS((GSERIALIZED *)(ARR_DATA_PTR(array)));
584#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)
585#pragma GCC diagnostic pop
586#endif
587 srid = GEOSGetSRID(g);
588 g_union = GEOSUnaryUnion(g);
589 GEOSGeom_destroy(g);
590 if (!g_union) HANDLE_GEOS_ERROR("GEOSUnaryUnion");
591 GEOSSetSRID(g_union, srid);
592 gser_out = GEOS2POSTGIS(g_union, is3d);
593 GEOSGeom_destroy(g_union);
594 PG_RETURN_POINTER(gser_out);
595 }
596
597 /*
598 ** Collect the non-empty inputs and stuff them into a GEOS collection
599 */
600 geoms_size = nelems;
601 geoms = palloc(sizeof(GEOSGeometry*) * geoms_size);
602
603 /*
604 ** We need to convert the array of GSERIALIZED into a GEOS collection.
605 ** First make an array of GEOS geometries.
606 */
607 iterator = array_create_iterator(array, 0, NULL);
608 while (array_iterate(iterator, &value, &isnull))
609 {
610 GSERIALIZED *gser_in;
611
612 /* Skip null array items */
613 if (isnull) continue;
614 gser_in = (GSERIALIZED *)DatumGetPointer(value);
615
616 /* Check for SRID mismatch in array elements */
617 if ( gotsrid )
618 gserialized_error_if_srid_mismatch_reference(gser_in, srid, __func__);
619 else
620 {
621 /* Initialize SRID/dimensions info */
622 srid = gserialized_get_srid(gser_in);
623 is3d = gserialized_has_z(gser_in);
624 gotsrid = 1;
625 }
626
627 /* Don't include empties in the union */
628 if ( gserialized_is_empty(gser_in) )
629 {
630 int gser_type = gserialized_get_type(gser_in);
631 if (gser_type > empty_type)
632 {
633 empty_type = gser_type;
634 POSTGIS_DEBUGF(4, "empty_type = %d gser_type = %d", empty_type, gser_type);
635 }
636 }
637 else
638 {
639 g = POSTGIS2GEOS(gser_in);
640
641 /* Uh oh! Exception thrown at construction... */
642 if ( ! g )
643 {
645 "One of the geometries in the set "
646 "could not be converted to GEOS");
647 }
648
649 /* Ensure we have enough space in our storage array */
650 if ( curgeom == geoms_size )
651 {
652 geoms_size *= 2;
653 geoms = repalloc( geoms, sizeof(GEOSGeometry*) * geoms_size );
654 }
655
656 geoms[curgeom] = g;
657 curgeom++;
658 }
659
660 }
661 array_free_iterator(iterator);
662
663 /*
664 ** Take our GEOS geometries and turn them into a GEOS collection,
665 ** then pass that into cascaded union.
666 */
667 if (curgeom > 0)
668 {
669 g = GEOSGeom_createCollection(GEOS_GEOMETRYCOLLECTION, geoms, curgeom);
670 if (!g) HANDLE_GEOS_ERROR("Could not create GEOS COLLECTION from geometry array");
671
672 g_union = GEOSUnaryUnion(g);
673 GEOSGeom_destroy(g);
674 if (!g_union) HANDLE_GEOS_ERROR("GEOSUnaryUnion");
675
676 GEOSSetSRID(g_union, srid);
677 gser_out = GEOS2POSTGIS(g_union, is3d);
678 GEOSGeom_destroy(g_union);
679 }
680 /* No real geometries in our array, any empties? */
681 else
682 {
683 /* If it was only empties, we'll return the largest type number */
684 if ( empty_type > 0 )
685 {
686 PG_RETURN_POINTER(geometry_serialize(lwgeom_construct_empty(empty_type, srid, is3d, 0)));
687 }
688 /* Nothing but NULL, returns NULL */
689 else
690 {
691 PG_RETURN_NULL();
692 }
693 }
694
695 if ( ! gser_out )
696 {
697 /* Union returned a NULL geometry */
698 PG_RETURN_NULL();
699 }
700
701 PG_RETURN_POINTER(gser_out);
702}
void gserialized_error_if_srid_mismatch_reference(const GSERIALIZED *g1, const int32_t srid2, const char *funcname)
int32_t gserialized_get_srid(const GSERIALIZED *g)
Extract the SRID from the serialized form (it is packed into three bytes so this is a handy function)...
int gserialized_is_empty(const GSERIALIZED *g)
Check if a GSERIALIZED is empty without deserializing first.
int gserialized_has_z(const GSERIALIZED *g)
Check if a GSERIALIZED has a Z ordinate.
uint32_t gserialized_get_type(const GSERIALIZED *g)
Extract the geometry type from the serialized form (it hides in the anonymous data area,...
void lwgeom_geos_error(const char *fmt,...)
#define LW_FALSE
Definition liblwgeom.h:94
LWGEOM * lwgeom_construct_empty(uint8_t type, int32_t srid, char hasz, char hasm)
Definition lwgeom.c:2219
#define SRID_UNKNOWN
Unknown SRID value.
Definition liblwgeom.h:215
int value
Definition genraster.py:62
int count
Definition genraster.py:57
GSERIALIZED * GEOS2POSTGIS(GEOSGeom geom, char want3d)
GEOSGeometry * POSTGIS2GEOS(const GSERIALIZED *pglwgeom)
#define HANDLE_GEOS_ERROR(label)

References GEOS2POSTGIS(), gserialized_error_if_srid_mismatch_reference(), gserialized_get_srid(), gserialized_get_type(), gserialized_has_z(), gserialized_is_empty(), HANDLE_GEOS_ERROR, LW_FALSE, lwgeom_construct_empty(), lwgeom_geos_error(), POSTGIS2GEOS(), and SRID_UNKNOWN.

Here is the call graph for this function: