/** * Calculate the area of an LWGEOM. Anything except POLYGON, MULTIPOLYGON * and GEOMETRYCOLLECTION return zero immediately. Multi's recurse, polygons * calculate external ring area and subtract internal ring area. A GBOX is * required to check relationship to equator an outside point. * WARNING: Does NOT WORK for polygons over equator or pole. */ double lwgeom_area_spheroid(const LWGEOM *lwgeom, const GBOX *gbox, const SPHEROID *spheroid) { int type; assert(lwgeom); /* No area in nothing */ if ( lwgeom_is_empty(lwgeom) ) return 0.0; /* Read the geometry type number */ type = TYPE_GETTYPE(lwgeom->type); /* Anything but polygons and collections returns zero */ if ( ! ( type == POLYGONTYPE || type == MULTIPOLYGONTYPE || type == COLLECTIONTYPE ) ) return 0.0; /* Actually calculate area */ if ( type == POLYGONTYPE ) { LWPOLY *poly = (LWPOLY*)lwgeom; int i; double area = 0.0; /* Just in case there's no rings */ if ( poly->nrings < 1 ) return 0.0; /* First, the area of the outer ring */ area += ptarray_area_spheroid(poly->rings[0], spheroid); /* Subtract areas of inner rings */ for ( i = 1; i < poly->nrings; i++ ) { area -= ptarray_area_spheroid(poly->rings[i], spheroid); } return area; } /* Recurse into sub-geometries to get area */ if ( type == MULTIPOLYGONTYPE || type == COLLECTIONTYPE ) { LWCOLLECTION *col = (LWCOLLECTION*)lwgeom; int i; double area = 0.0; for ( i = 0; i < col->ngeoms; i++ ) { area += lwgeom_area_spheroid(col->geoms[i], gbox, spheroid); } return area; } /* Shouldn't get here. */ return 0.0; }
static VALUE get_area_from_wkt(VALUE self, VALUE geom_wkt) { lwg = lwgeom_from_wkt(RSTRING_PTR(geom_wkt), 0); double area = lwgeom_area_spheroid(lwg, &s); return rb_float_new(area); }
double get_area_for_lwg() { double area = lwgeom_area_spheroid(lwg, &s); lwgeom_free(lwg); return area; }