SEXP rgeos_node(SEXP env, SEXP obj) { SEXP ans, id; int pc=0; GEOSContextHandle_t GEOShandle = getContextHandle(env); SEXP p4s = GET_SLOT(obj, install("proj4string")); GEOSGeom geom = rgeos_convert_R2geos(env, obj); // int type = GEOSGeomTypeId_r(GEOShandle, geom); //Rprintf("type: %d, %s\n", type, GEOSGeomType_r(GEOShandle, geom)); GEOSGeom res = GEOSNode_r(GEOShandle, geom); // type = GEOSGeomTypeId_r(GEOShandle, res); int ng = GEOSGetNumGeometries_r(GEOShandle, res); //Rprintf("ng: %d, type: %d, %s\n", ng, type, GEOSGeomType_r(GEOShandle, res)); char buf[BUFSIZ]; PROTECT(id = NEW_CHARACTER(ng)); pc++; for (int i=0; i<ng; i++) { sprintf(buf, "%d", i); SET_STRING_ELT(id, i, COPY_TO_USER_STRING(buf)); } GEOSGeom_destroy_r(GEOShandle, geom); ans = rgeos_convert_geos2R(env, res, p4s, id); UNPROTECT(pc); return(ans); }
SEXP rgeos_polygonize(SEXP env, SEXP obj, SEXP id, SEXP p4s, SEXP cutEdges) { GEOSContextHandle_t GEOShandle = getContextHandle(env); int getCutEdges = LOGICAL_POINTER(cutEdges)[0]; int n = length(obj); GEOSGeom *geoms = (GEOSGeom *) R_alloc((size_t) n, sizeof(GEOSGeom)); for(int i=0; i<n; i++) { geoms[i] = rgeos_convert_R2geos(env, VECTOR_ELT(obj,i)); } GEOSGeom res = (getCutEdges) ? GEOSPolygonizer_getCutEdges_r(GEOShandle, (const GEOSGeometry *const *) geoms, (unsigned int) n) : GEOSPolygonize_r(GEOShandle, (const GEOSGeometry *const *) geoms, (unsigned int) n); return( rgeos_convert_geos2R(env, res, p4s, id) ); }
SEXP rgeos_delaunaytriangulation(SEXP env, SEXP obj, SEXP tol, SEXP onlyEdges) { GEOSContextHandle_t GEOShandle = getContextHandle(env); double tolerance = NUMERIC_POINTER(tol)[0]; int oE = INTEGER_POINTER(onlyEdges)[0]; int pc=0; SEXP ans, id; SEXP p4s = GET_SLOT(obj, install("proj4string")); GEOSGeom geom = rgeos_convert_R2geos(env, obj); GEOSGeom resgeom = GEOSDelaunayTriangulation_r(GEOShandle, geom, tolerance, oE); if (resgeom == NULL) error("rgeos_delaunaytriangulation: unable to compute"); GEOSGeom_destroy_r(GEOShandle, geom); // int type = GEOSGeomTypeId_r(GEOShandle, resgeom); int ng = GEOSGetNumGeometries_r(GEOShandle, resgeom); //Rprintf("ng: %d, type: %d, %s\n", ng, type, GEOSGeomType_r(GEOShandle, resgeom)); // FIXME convert type 5 to type 7 char buf[BUFSIZ]; PROTECT(id = NEW_CHARACTER(ng)); pc++; for (int i=0; i<ng; i++) { sprintf(buf, "%d", i); SET_STRING_ELT(id, i, COPY_TO_USER_STRING(buf)); } ans = rgeos_convert_geos2R(env, resgeom, p4s, id); UNPROTECT(pc); return(ans); }
SEXP rgeos_topologyfunc(SEXP env, SEXP obj, SEXP id, SEXP byid, p_topofunc topofunc) { GEOSContextHandle_t GEOShandle = getContextHandle(env); SEXP p4s = GET_SLOT(obj, install("proj4string")); GEOSGeom geom = rgeos_convert_R2geos(env, obj); int type = GEOSGeomTypeId_r(GEOShandle, geom); int n = 1; if (LOGICAL_POINTER(byid)[0] && type == GEOS_GEOMETRYCOLLECTION) n = GEOSGetNumGeometries_r(GEOShandle, geom); if (n < 1) error("rgeos_topologyfunc: invalid number of geometries"); GEOSGeom *resgeoms = (GEOSGeom *) R_alloc((size_t) n, sizeof(GEOSGeom)); for(int i=0; i<n; i++) { const GEOSGeometry *curgeom = (n > 1) ? (GEOSGeom) GEOSGetGeometryN_r(GEOShandle, geom, i) : geom; if (curgeom == NULL) error("rgeos_topologyfunc: unable to get subgeometries"); if ( topofunc == GEOSUnionCascaded_r && GEOSGeomTypeId_r(GEOShandle, curgeom) == GEOS_POLYGON) { resgeoms[i] = GEOSGeom_clone_r(GEOShandle, curgeom); } else { resgeoms[i] = topofunc(GEOShandle, curgeom); if (resgeoms[i] == NULL) error("rgeos_topologyfunc: unable to calculate"); } } GEOSGeom_destroy_r(GEOShandle, geom); GEOSGeom res = (n == 1) ? resgeoms[0] : GEOSGeom_createCollection_r(GEOShandle, GEOS_GEOMETRYCOLLECTION, resgeoms, (unsigned int) n); return( rgeos_convert_geos2R(env, res, p4s, id) ); // releases res }
SEXP rgeos_simplify(SEXP env, SEXP obj, SEXP tol, SEXP id, SEXP byid, SEXP topPres) { GEOSContextHandle_t GEOShandle = getContextHandle(env); SEXP p4s = GET_SLOT(obj, install("proj4string")); GEOSGeom geom = rgeos_convert_R2geos(env, obj); int type = GEOSGeomTypeId_r(GEOShandle, geom); int preserve = LOGICAL_POINTER(topPres)[0]; double tolerance = NUMERIC_POINTER(tol)[0]; int n = 1; if (LOGICAL_POINTER(byid)[0] && type == GEOS_GEOMETRYCOLLECTION) n = GEOSGetNumGeometries_r(GEOShandle, geom); if (n < 1) error("rgeos_simplify: invalid number of geometries"); GEOSGeom *resgeoms = (GEOSGeom *) R_alloc((size_t) n, sizeof(GEOSGeom)); for(int i=0; i<n; i++) { const GEOSGeometry *curgeom = (n > 1) ? (GEOSGeom) GEOSGetGeometryN_r(GEOShandle, geom, i) : geom; if (curgeom == NULL) error("rgeos_topologyfunc: unable to get subgeometries"); resgeoms[i] = (preserve) ? GEOSTopologyPreserveSimplify_r(GEOShandle, curgeom, tolerance) : GEOSSimplify_r(GEOShandle, curgeom, tolerance); } GEOSGeom_destroy_r(GEOShandle, geom); GEOSGeom res = (n == 1) ? resgeoms[0] : GEOSGeom_createCollection_r(GEOShandle, GEOS_GEOMETRYCOLLECTION, resgeoms, (unsigned int) n); return( rgeos_convert_geos2R(env, res, p4s, id) ); }
SEXP rgeos_convert_geos2R(SEXP env, GEOSGeom geom, SEXP p4s, SEXP id) { GEOSContextHandle_t GEOShandle = getContextHandle(env); int type = GEOSGeomTypeId_r(GEOShandle, geom); int ng = GEOSGetNumGeometries_r(GEOShandle, geom); if (ng == -1) error("rgeos_convert_geos2R: invalid number of subgeometries"); if (type == GEOS_GEOMETRYCOLLECTION && ng==0 && GEOSisEmpty_r(GEOShandle,geom)) { GEOSGeom_destroy_r(GEOShandle, geom); return(R_NilValue); } ng = ng ? ng : 1; // Empty MULTI type geometries return size 0 int pc=0; SEXP ans=NULL; switch(type) { // Determine appropriate conversion for the collection case -1: error("rgeos_convert_geos2R: unknown geometry type"); break; case GEOS_POINT: case GEOS_MULTIPOINT: PROTECT( ans = rgeos_geospoint2SpatialPoints(env, geom, p4s, id, ng) ); pc++; break; case GEOS_LINEARRING: PROTECT( ans = rgeos_geosring2SpatialRings(env, geom, p4s, id, ng)); pc++; break; case GEOS_LINESTRING: case GEOS_MULTILINESTRING: PROTECT( ans = rgeos_geosline2SpatialLines(env, geom, p4s, id, 1) ); pc++; break; case GEOS_POLYGON: case GEOS_MULTIPOLYGON: PROTECT( ans = rgeos_geospolygon2SpatialPolygons(env, geom,p4s, id, 1) ); pc++; break; case GEOS_GEOMETRYCOLLECTION: { int gctypes[] = {0,0,0,0,0,0,0,0}; int gctypen[] = {0,0,0,0,0,0,0,0}; int n=0; int *types = (int *) R_alloc((size_t) ng, sizeof(int)); for (int i=0; i<ng; i++) { const GEOSGeometry *subgeom = GEOSGetGeometryN_r(GEOShandle, geom, i); if (subgeom == NULL) error("rgeos_convert_geos2R: unable to retrieve subgeometry"); int ns = GEOSGetNumGeometries_r(GEOShandle, subgeom); if (ns == -1) error("rgeos_convert_geos2R: invalid number of geometries in subgeometry"); ns = ns ? ns : 1; n += ns; types[i] = GEOSGeomTypeId_r(GEOShandle, subgeom); if (types[i] == GEOS_GEOMETRYCOLLECTION) { Rprintf("output subgeometry %d, row.name: %s\n", i, CHAR(STRING_ELT(id, i))); for (int ii=0; ii<ns; ii++) Rprintf("subsubgeometry %d: %s\n", ii, GEOSGeomType_r(GEOShandle, GEOSGetGeometryN_r(GEOShandle, subgeom, ii))); error("Geometry collections may not contain other geometry collections"); } gctypes[ types[i] ] += 1; gctypen[ types[i] ] += ns; } int isPoint = gctypes[GEOS_POINT] + gctypes[GEOS_MULTIPOINT]; int isLine = gctypes[GEOS_LINESTRING] + gctypes[GEOS_MULTILINESTRING]; int isPoly = gctypes[GEOS_POLYGON] + gctypes[GEOS_MULTIPOLYGON]; int isRing = gctypes[GEOS_LINEARRING]; int isGC = gctypes[GEOS_GEOMETRYCOLLECTION]; if ( isPoint && !isLine && !isPoly && !isRing && !isGC ) { PROTECT( ans = rgeos_geospoint2SpatialPoints(env, geom, p4s, id, n) ); pc++; } else if ( isLine && !isPoint && !isPoly && !isRing && !isGC ) { PROTECT( ans = rgeos_geosline2SpatialLines(env, geom, p4s, id, ng) ); pc++; } else if ( isPoly && !isPoint && !isLine && !isRing && !isGC ) { PROTECT( ans = rgeos_geospolygon2SpatialPolygons(env, geom, p4s,id, ng) ); pc++; } else if ( isRing && !isPoint && !isLine && !isPoly && !isGC ) { PROTECT( ans = rgeos_geosring2SpatialRings(env, geom, p4s, id, ng) ); pc++; } else { //Rprintf("isPoint: %d isLine: %d isPoly: %d isRing: %d isGC: %d\n",isPoint, isLine, isPoly, isRing, isGC); int m = MAX(MAX(MAX(isPoint,isLine),isPoly),isRing); if (length(id) < m) { char buf[BUFSIZ]; PROTECT(id = NEW_CHARACTER(m)); pc++; for (int i=0;i<m;i++) { sprintf(buf,"%d",i); SET_STRING_ELT(id, i, COPY_TO_USER_STRING(buf)); } } GEOSGeom *GCS[4]; GCS[0] = (GEOSGeom *) R_alloc((size_t) isPoint, sizeof(GEOSGeom)); GCS[1] = (GEOSGeom *) R_alloc((size_t) isLine, sizeof(GEOSGeom)); GCS[2] = (GEOSGeom *) R_alloc((size_t) isRing, sizeof(GEOSGeom)); GCS[3] = (GEOSGeom *) R_alloc((size_t) isPoly, sizeof(GEOSGeom)); SEXP ptID, lID, rID, pID; PROTECT(ptID = NEW_CHARACTER(isPoint)); pc++; PROTECT(lID = NEW_CHARACTER(isLine)); pc++; PROTECT(rID = NEW_CHARACTER(isRing)); pc++; PROTECT(pID = NEW_CHARACTER(isPoly)); pc++; int typei[] = {0,0,0,0}; for (int i=0; i<ng; i++) { const GEOSGeometry *subgeom = GEOSGetGeometryN_r(GEOShandle, geom, i); if (subgeom == NULL) error("rgeos_convert_geos2R: unable to retrieve subgeometry"); int j = -1; SEXP cur_id=NULL; if (types[i]==GEOS_POINT || types[i]==GEOS_MULTIPOINT) { j=0; cur_id=ptID; } else if (types[i]==GEOS_LINESTRING || types[i]==GEOS_MULTILINESTRING) { j=1; cur_id=lID; } else if (types[i]==GEOS_LINEARRING) { j=2; cur_id=rID; } else if (types[i]==GEOS_POLYGON || types[i]==GEOS_MULTIPOLYGON) { j=3; cur_id=pID; } if (GCS[j] == NULL) error("rgeos_convert_geos2R: GCS element is NULL (this should never happen)."); GCS[j][ typei[j] ] = GEOSGeom_clone_r(GEOShandle, subgeom); SET_STRING_ELT(cur_id, typei[j], STRING_ELT(id,typei[j])); typei[j]++; } SEXP points = R_NilValue; SEXP lines = R_NilValue; SEXP rings = R_NilValue; SEXP polys = R_NilValue; if (isPoint) { GEOSGeom ptGC = GEOSGeom_createCollection_r(GEOShandle, GEOS_GEOMETRYCOLLECTION, GCS[0], (unsigned int) isPoint); PROTECT( points = rgeos_convert_geos2R(env, ptGC, p4s, ptID) ); pc++; } if (isLine) { GEOSGeom lGC = GEOSGeom_createCollection_r(GEOShandle, GEOS_GEOMETRYCOLLECTION, GCS[1], (unsigned int) isLine); PROTECT( lines = rgeos_convert_geos2R(env, lGC, p4s, lID) ); pc++; } if (isRing) { GEOSGeom rGC = GEOSGeom_createCollection_r(GEOShandle, GEOS_GEOMETRYCOLLECTION, GCS[2], (unsigned int) isRing); PROTECT( rings = rgeos_convert_geos2R(env, rGC, p4s, rID) ); pc++; } if (isPoly) { GEOSGeom pGC = GEOSGeom_createCollection_r(GEOShandle, GEOS_GEOMETRYCOLLECTION, GCS[3], (unsigned int) isPoly); PROTECT( polys = rgeos_convert_geos2R(env, pGC, p4s, pID) ); pc++; } PROTECT(ans = NEW_OBJECT(MAKE_CLASS("SpatialCollections"))); pc++; SET_SLOT(ans, install("proj4string"), p4s); SET_SLOT(ans, install("pointobj"), points); SET_SLOT(ans, install("lineobj"), lines); SET_SLOT(ans, install("ringobj"), rings); SET_SLOT(ans, install("polyobj"), polys); SEXP plotOrder; PROTECT(plotOrder = NEW_INTEGER(4)); pc++; INTEGER_POINTER(plotOrder)[0] = 4; INTEGER_POINTER(plotOrder)[1] = 3; INTEGER_POINTER(plotOrder)[2] = 2; INTEGER_POINTER(plotOrder)[3] = 1; SET_SLOT(ans, install("plotOrder"), plotOrder); SEXP bbox; PROTECT(bbox = rgeos_geom2bbox(env, geom)); pc++; SET_SLOT(ans, install("bbox"), bbox); } break; } default: error("rgeos_convert_geos2R: Unknown geometry type"); } GEOSGeom_destroy_r(GEOShandle, geom); UNPROTECT(pc); return(ans); }