PostGIS  3.0.6dev-r@@SVN_REVISION@@

◆ geography_centroid_from_mpoly()

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 calculate the centroid of a (multi)polygon.

Definition at line 316 of file geography_centroid.c.

317 {
318  uint32_t size = 0;
319  uint32_t i, ir, ip, j = 0;
320  POINT3DM* points;
321  POINT4D* reference_point = NULL;
322  LWPOINT* result = NULL;
323 
324  for (ip = 0; ip < mpoly->ngeoms; ip++) {
325  for (ir = 0; ir < mpoly->geoms[ip]->nrings; ir++) {
326  size += mpoly->geoms[ip]->rings[ir]->npoints - 1;
327  }
328  }
329 
330  points = palloc(size*sizeof(POINT3DM));
331 
332 
333  /* use first point as reference to create triangles */
334  reference_point = (POINT4D*) getPoint2d_cp(mpoly->geoms[0]->rings[0], 0);
335 
336  for (ip = 0; ip < mpoly->ngeoms; ip++) {
337  LWPOLY* poly = mpoly->geoms[ip];
338 
339  for (ir = 0; ir < poly->nrings; ir++) {
340  POINTARRAY* ring = poly->rings[ir];
341 
342  /* split into triangles (two points + reference point) */
343  for (i = 0; i < ring->npoints - 1; i++) {
344  const POINT4D* p1 = (const POINT4D*) getPoint2d_cp(ring, i);
345  const POINT4D* p2 = (const POINT4D*) getPoint2d_cp(ring, i+1);
346  LWPOLY* poly_tri;
347  LWGEOM* geom_tri;
348  double_t weight;
349  POINT3DM triangle[3];
350  LWPOINT* tri_centroid;
351 
352  POINTARRAY* pa = ptarray_construct_empty(0, 0, 4);
353  ptarray_insert_point(pa, p1, 0);
354  ptarray_insert_point(pa, p2, 1);
355  ptarray_insert_point(pa, reference_point, 2);
356  ptarray_insert_point(pa, p1, 3);
357 
358  poly_tri = lwpoly_construct_empty(mpoly->srid, 0, 0);
359  lwpoly_add_ring(poly_tri, pa);
360 
361  geom_tri = lwpoly_as_lwgeom(poly_tri);
362  lwgeom_set_geodetic(geom_tri, LW_TRUE);
363 
364  /* Calculate the weight of the triangle. If counter clockwise,
365  * the weight is negative (e.g. for holes in polygons)
366  */
367 
368  if ( use_spheroid )
369  weight = lwgeom_area_spheroid(geom_tri, s);
370  else
371  weight = lwgeom_area_sphere(geom_tri, s);
372 
373 
374  triangle[0].x = p1->x;
375  triangle[0].y = p1->y;
376  triangle[0].m = 1;
377 
378  triangle[1].x = p2->x;
379  triangle[1].y = p2->y;
380  triangle[1].m = 1;
381 
382  triangle[2].x = reference_point->x;
383  triangle[2].y = reference_point->y;
384  triangle[2].m = 1;
385 
386  /* get center of triangle */
387  tri_centroid = geography_centroid_from_wpoints(mpoly->srid, triangle, 3);
388 
389  points[j].x = lwpoint_get_x(tri_centroid);
390  points[j].y = lwpoint_get_y(tri_centroid);
391  points[j].m = weight;
392  j++;
393 
394  lwpoint_free(tri_centroid);
395  lwgeom_free(geom_tri);
396  }
397  }
398  }
399  result = geography_centroid_from_wpoints(mpoly->srid, points, size);
400  pfree(points);
401  return result;
402 }
char * s
Definition: cu_in_wkt.c:23
LWPOINT * geography_centroid_from_wpoints(const int32_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...
void lwgeom_set_geodetic(LWGEOM *geom, int value)
Set the FLAGS geodetic bit on geometry an all sub-geometries and pointlists.
Definition: lwgeom.c:946
void lwpoint_free(LWPOINT *pt)
Definition: lwpoint.c:213
void lwgeom_free(LWGEOM *geom)
Definition: lwgeom.c:1138
LWGEOM * lwpoly_as_lwgeom(const LWPOLY *obj)
Definition: lwgeom.c:311
double lwgeom_area_spheroid(const LWGEOM *lwgeom, const SPHEROID *spheroid)
Calculate the geodetic area of a lwgeom on the spheroid.
Definition: lwspheroid.c:647
double lwpoint_get_x(const LWPOINT *point)
Definition: lwpoint.c:63
int lwpoly_add_ring(LWPOLY *poly, POINTARRAY *pa)
Add a ring, allocating extra space if necessary.
Definition: lwpoly.c:247
int ptarray_insert_point(POINTARRAY *pa, const POINT4D *p, uint32_t where)
Insert a point into an existing POINTARRAY.
Definition: ptarray.c:85
POINTARRAY * ptarray_construct_empty(char hasz, char hasm, uint32_t maxpoints)
Create a new POINTARRAY with no points.
Definition: ptarray.c:59
#define LW_TRUE
Return types for functions with status returns.
Definition: liblwgeom.h:107
LWPOLY * lwpoly_construct_empty(int32_t srid, char hasz, char hasm)
Definition: lwpoly.c:161
double lwpoint_get_y(const LWPOINT *point)
Definition: lwpoint.c:76
double lwgeom_area_sphere(const LWGEOM *lwgeom, const SPHEROID *spheroid)
Calculate the geodetic area of a lwgeom on the sphere.
Definition: lwgeodetic.c:2031
static const POINT2D * getPoint2d_cp(const POINTARRAY *pa, uint32_t n)
Returns a POINT2D pointer into the POINTARRAY serialized_ptlist, suitable for reading from.
Definition: lwinline.h:91
uint32_t ngeoms
Definition: liblwgeom.h:552
LWPOLY ** geoms
Definition: liblwgeom.h:547
int32_t srid
Definition: liblwgeom.h:548
POINTARRAY ** rings
Definition: liblwgeom.h:505
uint32_t nrings
Definition: liblwgeom.h:510
double m
Definition: liblwgeom.h:394
double x
Definition: liblwgeom.h:394
double y
Definition: liblwgeom.h:394
double x
Definition: liblwgeom.h:400
double y
Definition: liblwgeom.h:400
uint32_t npoints
Definition: liblwgeom.h:413

References geography_centroid_from_wpoints(), LWMPOLY::geoms, getPoint2d_cp(), LW_TRUE, lwgeom_area_sphere(), lwgeom_area_spheroid(), lwgeom_free(), lwgeom_set_geodetic(), lwpoint_free(), lwpoint_get_x(), lwpoint_get_y(), lwpoly_add_ring(), lwpoly_as_lwgeom(), lwpoly_construct_empty(), POINT3DM::m, LWMPOLY::ngeoms, POINTARRAY::npoints, LWPOLY::nrings, ptarray_construct_empty(), ptarray_insert_point(), LWPOLY::rings, s, LWMPOLY::srid, POINT3DM::x, POINT4D::x, POINT3DM::y, and POINT4D::y.

Referenced by geography_centroid().

Here is the call graph for this function:
Here is the caller graph for this function: