static VALUE method_polygon_centroid(VALUE self) { VALUE result = Qnil; RGeo_GeometryData* self_data = RGEO_GEOMETRY_DATA_PTR(self); const GEOSGeometry* self_geom = self_data->geom; if (self_geom) { result = rgeo_wrap_geos_geometry(self_data->factory, GEOSGetCentroid_r(self_data->geos_context, self_geom), RGEO_FACTORY_DATA_PTR(self_data->factory)->globals->geos_point); } return result; }
SEXP rgeos_geosring2Polygon(SEXP env, GEOSGeom lr, int hole) { GEOSContextHandle_t GEOShandle = getContextHandle(env); int pc=0; GEOSCoordSeq s = (GEOSCoordSequence *) GEOSGeom_getCoordSeq_r(GEOShandle, lr); if (s == NULL) error("rgeos_geosring2Polygon: CoordSeq failure"); unsigned int n; if (GEOSCoordSeq_getSize_r(GEOShandle, s, &n) == 0) error("rgeos_geosring2Polygon: CoordSeq failure"); // Get coordinates SEXP crd; PROTECT(crd = rgeos_crdMatFixDir(PROTECT(rgeos_CoordSeq2crdMat(env, s, FALSE, hole)), hole)); pc += 2; // Calculate area GEOSGeom p = GEOSGeom_createPolygon_r(GEOShandle,GEOSGeom_clone_r(GEOShandle,lr),NULL,0); if (p == NULL) error("rgeos_geosring2Polygon: unable to create polygon"); SEXP area; PROTECT(area = NEW_NUMERIC(1)); pc++; NUMERIC_POINTER(area)[0] = 0.0; if (!GEOSArea_r(GEOShandle, p, NUMERIC_POINTER(area))) error("rgeos_geosring2Polygon: area calculation failure"); // Calculate label position SEXP labpt; PROTECT(labpt = NEW_NUMERIC(2)); pc++; GEOSGeom centroid = GEOSGetCentroid_r(GEOShandle, p); double xc, yc; rgeos_Pt2xy(env, centroid, &xc, &yc); if (!R_FINITE(xc) || !R_FINITE(yc)) { xc = 0.0; yc = 0.0; for(int i=0; i != n; i++) { xc += NUMERIC_POINTER(crd)[i]; yc += NUMERIC_POINTER(crd)[(int) (n) +i]; } xc /= n; yc /= n; } NUMERIC_POINTER(labpt)[0] = xc; NUMERIC_POINTER(labpt)[1] = yc; GEOSGeom_destroy_r(GEOShandle, centroid); GEOSGeom_destroy_r(GEOShandle, p); // Get ring direction SEXP ringDir; PROTECT(ringDir = NEW_INTEGER(1)); pc++; INTEGER_POINTER(ringDir)[0] = hole ? -1 : 1; // Get hole status SEXP Hole; PROTECT(Hole = NEW_LOGICAL(1)); pc++; LOGICAL_POINTER(Hole)[0] = hole; SEXP ans; PROTECT(ans = NEW_OBJECT(MAKE_CLASS("Polygon"))); pc++; SET_SLOT(ans, install("ringDir"), ringDir); SET_SLOT(ans, install("labpt"), labpt); SET_SLOT(ans, install("area"), area); SET_SLOT(ans, install("hole"), Hole); SET_SLOT(ans, install("coords"), crd); SEXP valid; PROTECT(valid = SP_PREFIX(Polygon_validate_c)(ans)); pc++; if (!isLogical(valid)) { UNPROTECT(pc); if (isString(valid)) error(CHAR(STRING_ELT(valid, 0))); else error("invalid Polygon object"); } UNPROTECT(pc); return(ans); }