PostGIS  2.5.0dev-r@@SVN_REVISION@@
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, 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[size];
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  break;
119  }
120 
121  case LINETYPE:
122  {
123  LWLINE* line = lwgeom_as_lwline(lwgeom);
124 
125  /* reuse mline function */
126  LWMLINE* mline = lwmline_construct_empty(srid, 0, 0);
127  lwmline_add_lwline(mline, line);
128 
129  lwpoint_out = geography_centroid_from_mline(mline, &s);
130  lwmline_free(mline);
131  break;
132  }
133 
134  case MULTILINETYPE:
135  {
136  LWMLINE* mline = lwgeom_as_lwmline(lwgeom);
137  lwpoint_out = geography_centroid_from_mline(mline, &s);
138  break;
139  }
140 
141  case POLYGONTYPE:
142  {
143  LWPOLY* poly = lwgeom_as_lwpoly(lwgeom);
144 
145  /* reuse mpoly function */
146  LWMPOLY* mpoly = lwmpoly_construct_empty(srid, 0, 0);
147  lwmpoly_add_lwpoly(mpoly, poly);
148 
149  lwpoint_out = geography_centroid_from_mpoly(mpoly, use_spheroid, &s);
150  lwmpoly_free(mpoly);
151  break;
152  }
153 
154  case MULTIPOLYGONTYPE:
155  {
156  LWMPOLY* mpoly = lwgeom_as_lwmpoly(lwgeom);
157  lwpoint_out = geography_centroid_from_mpoly(mpoly, use_spheroid, &s);
158  break;
159  }
160  default:
161  elog(ERROR, "ST_Centroid(geography) unhandled geography type");
162  PG_RETURN_NULL();
163  }
164 
165  PG_FREE_IF_COPY(g, 0);
166 
167  lwgeom_out = lwpoint_as_lwgeom(lwpoint_out);
168  lwgeom_set_geodetic(lwgeom_out, true);
169  g_out = gserialized_from_lwgeom(lwgeom_out, 0);
170 
171  PG_RETURN_POINTER(g_out);
172 }
#define LINETYPE
Definition: liblwgeom.h:85
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
uint32_t ngeoms
Definition: liblwgeom.h:467
void lwmline_free(LWMLINE *mline)
Definition: lwmline.c:112
double x
Definition: liblwgeom.h:345
LWGEOM * lwgeom_from_gserialized(const GSERIALIZED *g)
Allocate a new LWGEOM from a GSERIALIZED.
#define POLYGONTYPE
Definition: liblwgeom.h:86
double b
Definition: liblwgeom.h:313
#define MULTIPOINTTYPE
Definition: liblwgeom.h:87
LWMPOLY * lwmpoly_construct_empty(int srid, char hasz, char hasm)
Definition: lwmpoly.c:40
double radius
Definition: liblwgeom.h:317
int32_t lwgeom_get_srid(const LWGEOM *geom)
Return SRID number.
Definition: lwgeom.c:909
LWPOLY * lwgeom_as_lwpoly(const LWGEOM *lwgeom)
Definition: lwgeom.c:205
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:178
LWMPOLY * lwgeom_as_lwmpoly(const LWGEOM *lwgeom)
Definition: lwgeom.c:250
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:345
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:241
LWPOINT ** geoms
Definition: liblwgeom.h:469
char * s
Definition: cu_in_wkt.c:23
double y
Definition: liblwgeom.h:345
void lwgeom_set_geodetic(LWGEOM *geom, int value)
Set the FLAGS geodetic bit on geometry an all sub-geometries and pointlists.
Definition: lwgeom.c:945
LWLINE * lwgeom_as_lwline(const LWGEOM *lwgeom)
Definition: lwgeom.c:169
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:89
double a
Definition: liblwgeom.h:312
#define POINTTYPE
LWTYPE numbers, used internally by PostGIS.
Definition: liblwgeom.h:84
LWMPOINT * lwgeom_as_lwmpoint(const LWGEOM *lwgeom)
Definition: lwgeom.c:232
double lwpoint_get_y(const LWPOINT *point)
Definition: lwpoint.c:76
LWGEOM * lwpoint_as_lwgeom(const LWPOINT *obj)
Definition: lwgeom.c:334
GSERIALIZED * gserialized_from_lwgeom(LWGEOM *geom, size_t *size)
Allocate a new GSERIALIZED from an LWGEOM.
#define MULTILINETYPE
Definition: liblwgeom.h:88
LWCOLLECTION * lwcollection_construct_empty(uint8_t type, int srid, char hasz, char hasm)
Definition: lwcollection.c:94
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:90
LWGEOM * lwcollection_as_lwgeom(const LWCOLLECTION *obj)
Definition: lwgeom.c:299

Here is the call graph for this function: