PostGIS  2.4.9dev-r@@SVN_REVISION@@

◆ geography_centroid()

Datum geography_centroid ( PG_FUNCTION_ARGS  )

Definition at line 49 of file geography_centroid.c.

References SPHEROID::a, SPHEROID::b, COLLECTIONTYPE, geography_centroid_from_mline(), geography_centroid_from_mpoly(), geography_centroid_from_wpoints(), LWMPOINT::geoms, gserialized_from_lwgeom(), gserialized_get_type(), gserialized_is_empty(), LINETYPE, lwcollection_as_lwgeom(), lwcollection_construct_empty(), lwgeom_as_lwline(), lwgeom_as_lwmline(), lwgeom_as_lwmpoint(), lwgeom_as_lwmpoly(), lwgeom_as_lwpoly(), lwgeom_from_gserialized(), lwgeom_get_srid(), lwgeom_set_geodetic(), lwmline_add_lwline(), lwmline_construct_empty(), lwmline_free(), lwmpoly_add_lwpoly(), lwmpoly_construct_empty(), lwmpoly_free(), lwpoint_as_lwgeom(), lwpoint_get_x(), lwpoint_get_y(), POINT3DM::m, MULTILINETYPE, MULTIPOINTTYPE, MULTIPOLYGONTYPE, LWMPOINT::ngeoms, POINTTYPE, POLYGONTYPE, SPHEROID::radius, s, ovdump::type, POINT3DM::x, and POINT3DM::y.

50 {
51  LWGEOM *lwgeom = NULL;
52  LWGEOM *lwgeom_out = NULL;
53  LWPOINT *lwpoint_out = NULL;
54  GSERIALIZED *g = NULL;
55  GSERIALIZED *g_out = NULL;
56  uint32_t srid;
57  bool use_spheroid = true;
58  SPHEROID s;
59  uint32_t type;
60 
61  /* Get our geometry object loaded into memory. */
62  g = PG_GETARG_GSERIALIZED_P(0);
63  lwgeom = lwgeom_from_gserialized(g);
64 
65  if (g == NULL)
66  {
67  PG_RETURN_NULL();
68  }
69 
70  srid = lwgeom_get_srid(lwgeom);
71 
72  /* on empty input, return empty output */
73  if (gserialized_is_empty(g))
74  {
76  lwgeom_out = lwcollection_as_lwgeom(empty);
77  lwgeom_set_geodetic(lwgeom_out, true);
78  g_out = gserialized_from_lwgeom(lwgeom_out, 0);
79  PG_RETURN_POINTER(g_out);
80  }
81 
82  /* Initialize spheroid */
83  spheroid_init_from_srid(fcinfo, srid, &s);
84 
85  /* Set to sphere if requested */
86  use_spheroid = PG_GETARG_BOOL(1);
87  if ( ! use_spheroid )
88  s.a = s.b = s.radius;
89 
90  type = gserialized_get_type(g);
91 
92  switch (type)
93  {
94 
95  case POINTTYPE:
96  {
97  /* centroid of a point is itself */
98  PG_RETURN_POINTER(g);
99  break;
100  }
101 
102  case MULTIPOINTTYPE:
103  {
104  LWMPOINT* mpoints = lwgeom_as_lwmpoint(lwgeom);
105 
106  /* average between all points */
107  uint32_t size = mpoints->ngeoms;
108  POINT3DM* points = palloc(size*sizeof(POINT3DM));
109 
110  uint32_t i;
111  for (i = 0; i < size; i++) {
112  points[i].x = lwpoint_get_x(mpoints->geoms[i]);
113  points[i].y = lwpoint_get_y(mpoints->geoms[i]);
114  points[i].m = 1;
115  }
116 
117  lwpoint_out = geography_centroid_from_wpoints(srid, points, size);
118  pfree(points);
119  break;
120  }
121 
122  case LINETYPE:
123  {
124  LWLINE* line = lwgeom_as_lwline(lwgeom);
125 
126  /* reuse mline function */
127  LWMLINE* mline = lwmline_construct_empty(srid, 0, 0);
128  lwmline_add_lwline(mline, line);
129 
130  lwpoint_out = geography_centroid_from_mline(mline, &s);
131  lwmline_free(mline);
132  break;
133  }
134 
135  case MULTILINETYPE:
136  {
137  LWMLINE* mline = lwgeom_as_lwmline(lwgeom);
138  lwpoint_out = geography_centroid_from_mline(mline, &s);
139  break;
140  }
141 
142  case POLYGONTYPE:
143  {
144  LWPOLY* poly = lwgeom_as_lwpoly(lwgeom);
145 
146  /* reuse mpoly function */
147  LWMPOLY* mpoly = lwmpoly_construct_empty(srid, 0, 0);
148  lwmpoly_add_lwpoly(mpoly, poly);
149 
150  lwpoint_out = geography_centroid_from_mpoly(mpoly, use_spheroid, &s);
151  lwmpoly_free(mpoly);
152  break;
153  }
154 
155  case MULTIPOLYGONTYPE:
156  {
157  LWMPOLY* mpoly = lwgeom_as_lwmpoly(lwgeom);
158  lwpoint_out = geography_centroid_from_mpoly(mpoly, use_spheroid, &s);
159  break;
160  }
161  default:
162  elog(ERROR, "ST_Centroid(geography) unhandled geography type");
163  PG_RETURN_NULL();
164  }
165 
166  PG_FREE_IF_COPY(g, 0);
167 
168  lwgeom_out = lwpoint_as_lwgeom(lwpoint_out);
169  lwgeom_set_geodetic(lwgeom_out, true);
170  g_out = gserialized_from_lwgeom(lwgeom_out, 0);
171 
172  PG_RETURN_POINTER(g_out);
173 }
#define LINETYPE
Definition: liblwgeom.h:86
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:86
void lwmline_free(LWMLINE *mline)
Definition: lwmline.c:112
double x
Definition: liblwgeom.h:346
LWGEOM * lwgeom_from_gserialized(const GSERIALIZED *g)
Allocate a new LWGEOM from a GSERIALIZED.
#define POLYGONTYPE
Definition: liblwgeom.h:87
double b
Definition: liblwgeom.h:314
#define MULTIPOINTTYPE
Definition: liblwgeom.h:88
LWMPOLY * lwmpoly_construct_empty(int srid, char hasz, char hasm)
Definition: lwmpoly.c:40
double radius
Definition: liblwgeom.h:318
int32_t lwgeom_get_srid(const LWGEOM *geom)
Return SRID number.
Definition: lwgeom.c:871
LWPOLY * lwgeom_as_lwpoly(const LWGEOM *lwgeom)
Definition: lwgeom.c:174
LWMLINE * lwmline_add_lwline(LWMLINE *mobj, const LWLINE *obj)
Definition: lwmline.c:46
LWMLINE * lwmline_construct_empty(int srid, char hasz, char hasm)
Definition: lwmline.c:38
int gserialized_is_empty(const GSERIALIZED *g)
Check if a GSERIALIZED is empty without deserializing first.
Definition: g_serialized.c:179
LWMPOLY * lwgeom_as_lwmpoly(const LWGEOM *lwgeom)
Definition: lwgeom.c:219
unsigned int uint32_t
Definition: uthash.h:78
double lwpoint_get_x(const LWPOINT *point)
Definition: lwpoint.c:63
void lwmpoly_free(LWMPOLY *mpoly)
Definition: lwmpoly.c:53
double m
Definition: liblwgeom.h:346
LWPOINT * geography_centroid_from_mpoly(const LWMPOLY *mpoly, bool use_spheroid, SPHEROID *s)
Split polygons into triangles and use centroid of the triangle with the triangle area as weight to ca...
LWMLINE * lwgeom_as_lwmline(const LWGEOM *lwgeom)
Definition: lwgeom.c:210
LWPOINT ** geoms
Definition: liblwgeom.h:470
char * s
Definition: cu_in_wkt.c:23
double y
Definition: liblwgeom.h:346
void lwgeom_set_geodetic(LWGEOM *geom, int value)
Set the FLAGS geodetic bit on geometry an all sub-geometries and pointlists.
Definition: lwgeom.c:907
LWLINE * lwgeom_as_lwline(const LWGEOM *lwgeom)
Definition: lwgeom.c:138
LWPOINT * geography_centroid_from_mline(const LWMLINE *mline, SPHEROID *s)
Split lines into segments and calculate with middle of segment as weighted point. ...
#define MULTIPOLYGONTYPE
Definition: liblwgeom.h:90
double a
Definition: liblwgeom.h:313
#define POINTTYPE
LWTYPE numbers, used internally by PostGIS.
Definition: liblwgeom.h:85
LWMPOINT * lwgeom_as_lwmpoint(const LWGEOM *lwgeom)
Definition: lwgeom.c:201
type
Definition: ovdump.py:41
double lwpoint_get_y(const LWPOINT *point)
Definition: lwpoint.c:76
LWGEOM * lwpoint_as_lwgeom(const LWPOINT *obj)
Definition: lwgeom.c:303
GSERIALIZED * gserialized_from_lwgeom(LWGEOM *geom, size_t *size)
Allocate a new GSERIALIZED from an LWGEOM.
#define MULTILINETYPE
Definition: liblwgeom.h:89
LWCOLLECTION * lwcollection_construct_empty(uint8_t type, int srid, char hasz, char hasm)
Definition: lwcollection.c:94
int ngeoms
Definition: liblwgeom.h:468
LWMPOLY * lwmpoly_add_lwpoly(LWMPOLY *mobj, const LWPOLY *obj)
Definition: lwmpoly.c:47
LWPOINT * geography_centroid_from_wpoints(const uint32_t srid, const POINT3DM *points, const uint32_t size)
Convert lat-lon-points to x-y-z-coordinates, calculate a weighted average point and return lat-lon-co...
#define COLLECTIONTYPE
Definition: liblwgeom.h:91
LWGEOM * lwcollection_as_lwgeom(const LWCOLLECTION *obj)
Definition: lwgeom.c:268
Here is the call graph for this function: