SEXP rgeos_miscfunc(SEXP env, SEXP obj, SEXP byid, p_miscfunc miscfunc) { SEXP ans; GEOSContextHandle_t GEOShandle = getContextHandle(env); GEOSGeom geom = rgeos_convert_R2geos(env, obj); int type = GEOSGeomTypeId_r(GEOShandle, geom); int n = (LOGICAL_POINTER(byid)[0] && type == GEOS_GEOMETRYCOLLECTION) ? GEOSGetNumGeometries_r(GEOShandle, geom) : 1; int pc=0; PROTECT(ans = NEW_NUMERIC(n)); pc++; GEOSGeom curgeom = geom; for(int i=0; i<n; i++) { if ( n > 1) { curgeom = (GEOSGeom) GEOSGetGeometryN_r(GEOShandle, geom, i); if (curgeom == NULL) error("rgeos_miscfunc: unable to get subgeometries"); } double val; if (!miscfunc(GEOShandle, curgeom, &val)) error("rgeos_miscfunc: unable to calculate"); NUMERIC_POINTER(ans)[i] = val; } GEOSGeom_destroy_r(GEOShandle, geom); UNPROTECT(pc); return(ans); }
RGEO_BEGIN_C /**** INTERNAL UTILITY FUNCTIONS ****/ // Determine the dimension of the given geometry. Empty collections have dimension -1. // Recursively checks collection elemenets. static int compute_dimension(GEOSContextHandle_t context, const GEOSGeometry* geom) { int result; int size; int i; int dim; result = -1; if (geom) { switch (GEOSGeomTypeId_r(context, geom)) { case GEOS_POINT: result = 0; break; case GEOS_MULTIPOINT: if (!GEOSisEmpty_r(context, geom)) { result = 0; } break; case GEOS_LINESTRING: case GEOS_LINEARRING: result = 1; break; case GEOS_MULTILINESTRING: if (!GEOSisEmpty_r(context, geom)) { result = 1; } break; case GEOS_POLYGON: result = 2; break; case GEOS_MULTIPOLYGON: if (!GEOSisEmpty_r(context, geom)) { result = 2; } break; case GEOS_GEOMETRYCOLLECTION: size = GEOSGetNumGeometries_r(context, geom); for (i=0; i<size; ++i) { dim = compute_dimension(context, GEOSGetGeometryN_r(context, geom, i)); if (dim > result) { result = dim; } } break; } } return result; }
QLinkedList<const GEOSGeometry *>* pal::Util::unmulti( const GEOSGeometry *the_geom ) { QLinkedList<const GEOSGeometry*> *queue = new QLinkedList<const GEOSGeometry*>; QLinkedList<const GEOSGeometry*> *final_queue = new QLinkedList<const GEOSGeometry*>; const GEOSGeometry *geom; queue->append( the_geom ); int nGeom; int i; GEOSContextHandle_t geosctxt = geosContext(); while ( !queue->isEmpty() ) { geom = queue->takeFirst(); int type = GEOSGeomTypeId_r( geosctxt, geom ); switch ( type ) { case GEOS_MULTIPOINT: case GEOS_MULTILINESTRING: case GEOS_MULTIPOLYGON: nGeom = GEOSGetNumGeometries_r( geosctxt, geom ); for ( i = 0; i < nGeom; i++ ) { queue->append( GEOSGetGeometryN_r( geosctxt, geom, i ) ); } break; case GEOS_POINT: case GEOS_LINESTRING: case GEOS_POLYGON: final_queue->append( geom ); break; default: QgsDebugMsg( QString( "unexpected geometry type:%1" ).arg( type ) ); delete final_queue; delete queue; return nullptr; } } delete queue; return final_queue; }
QLinkedList<const GEOSGeometry *> *unmulti( const GEOSGeometry *the_geom ) { QLinkedList<const GEOSGeometry*> *queue = new QLinkedList<const GEOSGeometry*>; QLinkedList<const GEOSGeometry*> *final_queue = new QLinkedList<const GEOSGeometry*>; const GEOSGeometry *geom; queue->append( the_geom ); int nGeom; int i; while ( !queue->isEmpty() ) { geom = queue->takeFirst(); GEOSContextHandle_t geosctxt = geosContext(); switch ( GEOSGeomTypeId_r( geosctxt, geom ) ) { case GEOS_MULTIPOINT: case GEOS_MULTILINESTRING: case GEOS_MULTIPOLYGON: nGeom = GEOSGetNumGeometries_r( geosctxt, geom ); for ( i = 0; i < nGeom; i++ ) { queue->append( GEOSGetGeometryN_r( geosctxt, geom, i ) ); } break; case GEOS_POINT: case GEOS_LINESTRING: case GEOS_POLYGON: final_queue->append( geom ); break; default: delete final_queue; delete queue; return NULL; } } delete queue; return final_queue; }
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 }
// Will return NULL on error (expect error handler being called by then) static GEOSGeometry *LWGEOM_GEOS_makeValidCollection( const GEOSGeometry *gin, QString &errorMessage ) { GEOSContextHandle_t handle = QgsGeos::getGEOSHandler(); int nvgeoms = GEOSGetNumGeometries_r( handle, gin ); if ( nvgeoms == -1 ) { errorMessage = QStringLiteral( "GEOSGetNumGeometries: %1" ).arg( QStringLiteral( "?" ) ); return nullptr; } QVector<GEOSGeometry *> vgeoms( nvgeoms ); for ( int i = 0; i < nvgeoms; ++i ) { vgeoms[i] = LWGEOM_GEOS_makeValid( GEOSGetGeometryN_r( handle, gin, i ), errorMessage ); if ( ! vgeoms[i] ) { while ( i-- ) GEOSGeom_destroy_r( handle, vgeoms[i] ); // we expect lwerror being called already by makeValid return nullptr; } } // Collect areas and lines (if any line) try { return GEOSGeom_createCollection_r( handle, GEOS_GEOMETRYCOLLECTION, vgeoms.data(), nvgeoms ); } catch ( GEOSException &e ) { // cleanup and throw for ( int i = 0; i < nvgeoms; ++i ) GEOSGeom_destroy_r( handle, vgeoms[i] ); errorMessage = QStringLiteral( "GEOSGeom_createCollection() threw an error: %1" ).arg( e.what() ); return nullptr; } }
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) ); }
void Point::update(const std::string& wkt_or_json, SpatialReference ref) { Geometry::update(wkt_or_json, ref); int t = GEOSGeomTypeId_r(m_geoserr.ctx(), m_geom.get()); if (t == -1) throw pdal_error("Unable to fetch geometry point type"); if (t > 0) throw pdal_error("Geometry type is not point!"); int nGeometries = GEOSGetNumGeometries_r(m_geoserr.ctx(), m_geom.get()); if (nGeometries > 1) throw pdal_error("Geometry count is > 1!"); const GEOSGeometry* g = GEOSGetGeometryN_r(m_geoserr.ctx(), m_geom.get(), 0); GEOSCoordSequence const* coords = GEOSGeom_getCoordSeq_r(m_geoserr.ctx(), g); uint32_t numInputDims; GEOSCoordSeq_getDimensions_r(m_geoserr.ctx(), coords, &numInputDims); uint32_t count(0); GEOSCoordSeq_getSize_r(m_geoserr.ctx(), coords, &count); if (count == 0) throw pdal_error("No coordinates in geometry!"); for (unsigned i = 0; i < count; ++i) { GEOSCoordSeq_getOrdinate_r(m_geoserr.ctx(), coords, i, 0, &x); GEOSCoordSeq_getOrdinate_r(m_geoserr.ctx(), coords, i, 1, &y); if (numInputDims > 2) GEOSCoordSeq_getOrdinate_r(m_geoserr.ctx(), coords, i, 2, &z); } }
Polygon Polygon::simplify(double distance_tolerance, double area_tolerance) const { GEOSGeometry *smoothed = GEOSTopologyPreserveSimplify_r(m_ctx, m_geom, distance_tolerance); if (!smoothed) throw pdal_error("Unable to simplify input geometry!"); std::vector<GEOSGeometry*> geometries; int numGeom = GEOSGetNumGeometries_r(m_ctx, smoothed); for (int n = 0; n < numGeom; ++n) { const GEOSGeometry* m = GEOSGetGeometryN_r(m_ctx, smoothed, n); if (!m) throw pdal::pdal_error("Unable to Get GeometryN"); const GEOSGeometry* ering = GEOSGetExteriorRing_r(m_ctx, m); if (!ering) throw pdal::pdal_error("Unable to Get Exterior Ring"); GEOSGeometry* exterior = GEOSGeom_clone_r(m_ctx, GEOSGetExteriorRing_r(m_ctx, m)); if (!exterior) throw pdal::pdal_error("Unable to clone exterior ring!"); std::vector<GEOSGeometry*> keep_rings; int numRings = GEOSGetNumInteriorRings_r(m_ctx, m); for (int i = 0; i < numRings; ++i) { double area(0.0); const GEOSGeometry* iring = GEOSGetInteriorRingN_r(m_ctx, m, i); if (!iring) throw pdal::pdal_error("Unable to Get Interior Ring"); GEOSGeometry* cring = GEOSGeom_clone_r(m_ctx, iring); if (!cring) throw pdal::pdal_error("Unable to clone interior ring!"); GEOSGeometry* aring = GEOSGeom_createPolygon_r(m_ctx, cring, NULL, 0); int errored = GEOSArea_r(m_ctx, aring, &area); if (errored == 0) throw pdal::pdal_error("Unable to get area of ring!"); if (area > area_tolerance) { keep_rings.push_back(cring); } } GEOSGeometry* p = GEOSGeom_createPolygon_r(m_ctx, exterior, keep_rings.data(), keep_rings.size()); if (p == NULL) throw pdal::pdal_error("smooth polygon could not be created!" ); geometries.push_back(p); } GEOSGeometry* o = GEOSGeom_createCollection_r(m_ctx, GEOS_MULTIPOLYGON, geometries.data(), geometries.size()); Polygon p(o, m_srs, m_ctx); GEOSGeom_destroy_r(m_ctx, smoothed); GEOSGeom_destroy_r(m_ctx, o); return p; }
static GEOSGeometry *LWGEOM_GEOS_makeValidMultiLine( const GEOSGeometry *gin, QString &errorMessage ) { GEOSContextHandle_t handle = QgsGeos::getGEOSHandler(); int ngeoms = GEOSGetNumGeometries_r( handle, gin ); uint32_t nlines_alloc = ngeoms; QVector<GEOSGeometry *> lines; QVector<GEOSGeometry *> points; lines.reserve( nlines_alloc ); points.reserve( ngeoms ); for ( int i = 0; i < ngeoms; ++i ) { const GEOSGeometry *g = GEOSGetGeometryN_r( handle, gin, i ); GEOSGeometry *vg = LWGEOM_GEOS_makeValidLine( g, errorMessage ); if ( GEOSisEmpty_r( handle, vg ) ) { // we don't care about this one GEOSGeom_destroy_r( handle, vg ); } if ( GEOSGeomTypeId_r( handle, vg ) == GEOS_POINT ) { points.append( vg ); } else if ( GEOSGeomTypeId_r( handle, vg ) == GEOS_LINESTRING ) { lines.append( vg ); } else if ( GEOSGeomTypeId_r( handle, vg ) == GEOS_MULTILINESTRING ) { int nsubgeoms = GEOSGetNumGeometries_r( handle, vg ); nlines_alloc += nsubgeoms; lines.reserve( nlines_alloc ); for ( int j = 0; j < nsubgeoms; ++j ) { // NOTE: ownership of the cloned geoms will be taken by final collection lines.append( GEOSGeom_clone_r( handle, GEOSGetGeometryN_r( handle, vg, j ) ) ); } } else { // NOTE: return from GEOSGeomType will leak but we really don't expect this to happen errorMessage = QStringLiteral( "unexpected geom type returned by LWGEOM_GEOS_makeValid: %1" ).arg( GEOSGeomTypeId_r( handle, vg ) ); } } GEOSGeometry *mpoint_out = nullptr; if ( points.count() ) { if ( points.count() > 1 ) { mpoint_out = GEOSGeom_createCollection_r( handle, GEOS_MULTIPOINT, points.data(), points.count() ); } else { mpoint_out = points[0]; } } GEOSGeometry *mline_out = nullptr; if ( lines.count() ) { if ( lines.count() > 1 ) { mline_out = GEOSGeom_createCollection_r( handle, GEOS_MULTILINESTRING, lines.data(), lines.count() ); } else { mline_out = lines[0]; } } if ( mline_out && mpoint_out ) { GEOSGeometry *collection[2]; collection[0] = mline_out; collection[1] = mpoint_out; return GEOSGeom_createCollection_r( handle, GEOS_GEOMETRYCOLLECTION, collection, 2 ); } else if ( mline_out ) { return mline_out; } else if ( mpoint_out ) { return mpoint_out; } else { return nullptr; } }
Q_NOWARN_UNREACHABLE_POP // Return Nth vertex in GEOSGeometry as a POINT. // May return NULL if the geometry has NO vertexex. static GEOSGeometry *LWGEOM_GEOS_getPointN( const GEOSGeometry *g_in, uint32_t n ) { GEOSContextHandle_t handle = QgsGeos::getGEOSHandler(); uint32_t dims; const GEOSCoordSequence *seq_in = nullptr; GEOSCoordSeq seq_out; double val; uint32_t sz; int gn; GEOSGeometry *ret = nullptr; switch ( GEOSGeomTypeId_r( handle, g_in ) ) { case GEOS_MULTIPOINT: case GEOS_MULTILINESTRING: case GEOS_MULTIPOLYGON: case GEOS_GEOMETRYCOLLECTION: { for ( gn = 0; gn < GEOSGetNumGeometries_r( handle, g_in ); ++gn ) { const GEOSGeometry *g = GEOSGetGeometryN_r( handle, g_in, gn ); ret = LWGEOM_GEOS_getPointN( g, n ); if ( ret ) return ret; } break; } case GEOS_POLYGON: { ret = LWGEOM_GEOS_getPointN( GEOSGetExteriorRing_r( handle, g_in ), n ); if ( ret ) return ret; for ( gn = 0; gn < GEOSGetNumInteriorRings_r( handle, g_in ); ++gn ) { const GEOSGeometry *g = GEOSGetInteriorRingN_r( handle, g_in, gn ); ret = LWGEOM_GEOS_getPointN( g, n ); if ( ret ) return ret; } break; } case GEOS_POINT: case GEOS_LINESTRING: case GEOS_LINEARRING: break; } seq_in = GEOSGeom_getCoordSeq_r( handle, g_in ); if ( ! seq_in ) return nullptr; if ( ! GEOSCoordSeq_getSize_r( handle, seq_in, &sz ) ) return nullptr; if ( ! sz ) return nullptr; if ( ! GEOSCoordSeq_getDimensions_r( handle, seq_in, &dims ) ) return nullptr; seq_out = GEOSCoordSeq_create_r( handle, 1, dims ); if ( ! seq_out ) return nullptr; if ( ! GEOSCoordSeq_getX_r( handle, seq_in, n, &val ) ) return nullptr; if ( ! GEOSCoordSeq_setX_r( handle, seq_out, n, val ) ) return nullptr; if ( ! GEOSCoordSeq_getY_r( handle, seq_in, n, &val ) ) return nullptr; if ( ! GEOSCoordSeq_setY_r( handle, seq_out, n, val ) ) return nullptr; if ( dims > 2 ) { if ( ! GEOSCoordSeq_getZ_r( handle, seq_in, n, &val ) ) return nullptr; if ( ! GEOSCoordSeq_setZ_r( handle, seq_out, n, val ) ) return nullptr; } return GEOSGeom_createPoint_r( handle, seq_out ); }
SEXP rgeos_geospolygon2SpatialPolygons(SEXP env, GEOSGeom geom, SEXP p4s, SEXP IDs, int ng) { GEOSContextHandle_t GEOShandle = getContextHandle(env); int pc=0; SEXP bbox, comment; PROTECT(bbox = rgeos_geom2bbox(env, geom)); pc++; int type = GEOSGeomTypeId_r(GEOShandle, geom); int empty = GEOSisEmpty_r(GEOShandle, geom); if (ng < 1) error("rgeos_geospolygon2SpatialPolygons: invalid number of geometries"); if (ng > length(IDs)) error("rgeos_geospolygon2SpatialPolygons: ng > length(IDs)"); SEXP pls; PROTECT(pls = NEW_LIST(ng)); pc++; double *areas = (double *) R_alloc((size_t) ng, sizeof(double)); int *po = (int *) R_alloc((size_t) ng, sizeof(int)); for (int i=0; i<ng; i++) { GEOSGeom GC = (type == GEOS_GEOMETRYCOLLECTION && !empty) ? (GEOSGeometry *) GEOSGetGeometryN_r(GEOShandle, geom, i) : geom; if (GC == NULL) error("rgeos_geospolygon2SpatialPolygons: unable to get subgeometry"); SEXP poly, ID; PROTECT( ID = NEW_CHARACTER(1)); SET_STRING_ELT(ID,0,STRING_ELT(IDs, i)); PROTECT( poly = rgeos_geospolygon2Polygons(env, GC, ID) ); areas[i] = NUMERIC_POINTER(GET_SLOT(poly, install("area")))[0]; SET_VECTOR_ELT(pls, i, poly); po[i] = i + R_OFFSET; UNPROTECT(2); } revsort(areas, po, ng); SEXP plotOrder; PROTECT(plotOrder = NEW_INTEGER(ng)); pc++; for (int i=0; i<ng; i++) INTEGER_POINTER(plotOrder)[i] = po[i]; SEXP ans; PROTECT(ans = NEW_OBJECT(MAKE_CLASS("SpatialPolygons"))); pc++; SET_SLOT(ans, install("polygons"), pls); SET_SLOT(ans, install("proj4string"), p4s); SET_SLOT(ans, install("plotOrder"), plotOrder); SET_SLOT(ans, install("bbox"), bbox); // RSB 120417 add top-level comment that all member Polygons // objects have comment set PROTECT(comment = NEW_CHARACTER(1)); pc++; SET_STRING_ELT(comment, 0, mkChar("TRUE")); setAttrib(ans, install("comment"), comment); UNPROTECT(pc); return(ans); }
SEXP rgeos_geosring2SpatialRings(SEXP env, GEOSGeom geom, SEXP p4s, SEXP idlist, int nrings) { GEOSContextHandle_t GEOShandle = getContextHandle(env); int type = GEOSGeomTypeId_r(GEOShandle, geom); if (type != GEOS_LINEARRING && type != GEOS_GEOMETRYCOLLECTION ) error("rgeos_geosring2SpatialRings: invalid type"); if (nrings < 1) error("rgeos_geosring2SpatialRings: invalid number of geometries"); int pc=0; SEXP bbox, rings_list; PROTECT(bbox = rgeos_geom2bbox(env, geom)); pc++; PROTECT(rings_list = NEW_LIST(nrings)); pc++; for(int j = 0; j < nrings; j++) { GEOSGeom curgeom = (type == GEOS_GEOMETRYCOLLECTION) ? (GEOSGeom) GEOSGetGeometryN_r(GEOShandle, geom, j) : geom; if (curgeom == NULL) error("rgeos_geosring2SpatialRings: unable to get geometry collection geometry"); SEXP crdmat; if (GEOSisEmpty_r(GEOShandle, curgeom) == 0) { GEOSCoordSeq s = (GEOSCoordSeq) GEOSGeom_getCoordSeq_r(GEOShandle, curgeom); if (s == NULL) error("rgeos_geosring2SpatialRings: unable to generate coordinate sequence"); PROTECT(crdmat = rgeos_crdMatFixDir(PROTECT(rgeos_CoordSeq2crdMat(env, s, FALSE, FALSE)), FALSE)); pc += 2; } else { PROTECT( crdmat = R_NilValue); pc++; } SEXP ring; PROTECT(ring = NEW_OBJECT(MAKE_CLASS("Ring"))); pc++; SET_SLOT(ring, install("coords"), crdmat); SEXP id; PROTECT( id = NEW_CHARACTER(1) ); pc++; char idbuf[BUFSIZ]; strcpy(idbuf, CHAR( STRING_ELT(idlist, j) )); SET_STRING_ELT(id, 0, COPY_TO_USER_STRING(idbuf)); SET_SLOT(ring, install("ID"), id); SET_VECTOR_ELT(rings_list, j, ring ); UNPROTECT(pc); } SEXP ans; PROTECT(ans = NEW_OBJECT(MAKE_CLASS("SpatialRings"))); pc++; SET_SLOT(ans, install("rings"), rings_list); SET_SLOT(ans, install("bbox"), bbox); SET_SLOT(ans, install("proj4string"), p4s); UNPROTECT(pc); return(ans); }
SEXP rgeos_geosline2SpatialLines(SEXP env, GEOSGeom geom, SEXP p4s, SEXP idlist, int nlines) { GEOSContextHandle_t GEOShandle = getContextHandle(env); GEOSGeom curgeom; GEOSGeom subgeom; GEOSCoordSeq s; int type = GEOSGeomTypeId_r(GEOShandle, geom); if (type != GEOS_LINESTRING && type != GEOS_MULTILINESTRING && type != GEOS_LINEARRING && type != GEOS_GEOMETRYCOLLECTION ) { error("rgeos_geosline2SpatialLines: invalid type"); } if (nlines < 1) error("rgeos_geosline2SpatialLines: invalid number of geometries"); int pc=0; if (nlines > length(idlist)) error("rgeos_geosline2SpatialLines: nlines > length(idlist)"); SEXP bbox, lines_list; PROTECT(bbox = rgeos_geom2bbox(env, geom)); pc++; PROTECT(lines_list = NEW_LIST(nlines)); pc++; for(int j = 0; j < nlines; j++) { curgeom = (type == GEOS_GEOMETRYCOLLECTION) ? (GEOSGeom) GEOSGetGeometryN_r(GEOShandle, geom, j) : geom; if (curgeom == NULL) error("rgeos_geosline2SpatialLines: unable to get geometry collection geometry"); int curtype = GEOSGeomTypeId_r(GEOShandle, curgeom); int n = GEOSGetNumGeometries_r(GEOShandle, curgeom); if (n == -1) error("rgeos_geosline2SpatialLines: invalid number of geometries in current geometry"); n = n ? n : 1; SEXP line_list; PROTECT(line_list = NEW_LIST(n)); for(int i = 0; i < n; i++) { subgeom = (curtype == GEOS_MULTILINESTRING && !GEOSisEmpty_r(GEOShandle, curgeom)) ? (GEOSGeom) GEOSGetGeometryN_r(GEOShandle, curgeom, i) : curgeom; if(subgeom == NULL) error("rgeos_geosline2SpatialLines: unable to get subgeometry"); SEXP crdmat; if (GEOSisEmpty_r(GEOShandle, subgeom) == 0) { s = (GEOSCoordSeq) GEOSGeom_getCoordSeq_r(GEOShandle, subgeom); if (s == NULL) error("rgeos_geosline2SpatialLines: unable to generate coordinate sequence"); PROTECT( crdmat = rgeos_CoordSeq2crdMat(env, s, FALSE, FALSE)); } else { error("rgeos_geosline2SpatialLines: empty line found"); // PROTECT( crdmat = R_NilValue); } SEXP line; PROTECT(line = NEW_OBJECT(MAKE_CLASS("Line"))); SET_SLOT(line, install("coords"), crdmat); SET_VECTOR_ELT(line_list, i, line ); UNPROTECT(2); } SEXP lines; PROTECT( lines = NEW_OBJECT(MAKE_CLASS("Lines")) ); SET_SLOT(lines, install("Lines"), line_list); char idbuf[BUFSIZ]; strcpy(idbuf, CHAR( STRING_ELT(idlist, j) )); SEXP id; PROTECT( id = NEW_CHARACTER(1) ); SET_STRING_ELT(id, 0, COPY_TO_USER_STRING(idbuf)); SET_SLOT(lines, install("ID"), id); SET_VECTOR_ELT( lines_list, j, lines ); UNPROTECT(3); } SEXP ans; PROTECT(ans = NEW_OBJECT(MAKE_CLASS("SpatialLines"))); pc++; SET_SLOT(ans, install("lines"), lines_list); SET_SLOT(ans, install("bbox"), bbox); SET_SLOT(ans, install("proj4string"), p4s); UNPROTECT(pc); return(ans); }
SEXP rgeos_geospolygon2Polygons(SEXP env, GEOSGeom geom, SEXP ID) { GEOSContextHandle_t GEOShandle = getContextHandle(env); int pc=0; int type = GEOSGeomTypeId_r(GEOShandle, geom); int empty = GEOSisEmpty_r(GEOShandle, geom); int ngeom = GEOSGetNumGeometries_r(GEOShandle, geom); ngeom = ngeom ? ngeom : 1; int npoly = 0; for (int i=0; i<ngeom; i++) { GEOSGeom GC = (type == GEOS_MULTIPOLYGON && !empty) ? (GEOSGeometry *) GEOSGetGeometryN_r(GEOShandle, geom, i) : geom; int GCempty = GEOSisEmpty_r(GEOShandle, GC); int GCpolys = (GCempty) ? 1 : GEOSGetNumInteriorRings_r(GEOShandle, GC) + 1; npoly += GCpolys; } SEXP polys; PROTECT(polys = NEW_LIST(npoly)); pc++; int *comm = (int *) R_alloc((size_t) npoly, sizeof(int)); int *po = (int *) R_alloc((size_t) npoly, sizeof(int)); double *areas = (double *) R_alloc((size_t) npoly, sizeof(double)); double totalarea = 0.0; int k = 0; for (int i=0; i<ngeom; i++) { GEOSGeom GC = (type == GEOS_MULTIPOLYGON && !empty) ? (GEOSGeometry *) GEOSGetGeometryN_r(GEOShandle, geom, i) : geom; if (GEOSisEmpty_r(GEOShandle, GC)) { SEXP ringDir,area,labpt,hole; PROTECT(ringDir = NEW_INTEGER(1)); INTEGER_POINTER(ringDir)[0] = 1; PROTECT(labpt = NEW_NUMERIC(2)); NUMERIC_POINTER(labpt)[0] = NA_REAL; NUMERIC_POINTER(labpt)[1] = NA_REAL; PROTECT(area = NEW_NUMERIC(1)); NUMERIC_POINTER(area)[0] = 0.0; PROTECT(hole = NEW_LOGICAL(1)); LOGICAL_POINTER(hole)[0] = TRUE; SEXP poly; PROTECT(poly = NEW_OBJECT(MAKE_CLASS("Polygon"))); SET_SLOT(poly, install("ringDir"), ringDir); SET_SLOT(poly, install("labpt"), labpt); SET_SLOT(poly, install("area"), area); SET_SLOT(poly, install("hole"), hole); SET_SLOT(poly, install("coords"), R_NilValue); SET_VECTOR_ELT(polys, k, poly); UNPROTECT(5); comm[k] = 0; areas[k] = 0; po[k] = k + R_OFFSET; // modified 131004 RSB // https://stat.ethz.ch/pipermail/r-sig-geo/2013-October/019470.html // warning("rgeos_geospolygon2Polygons: empty Polygons object"); error("rgeos_geospolygon2Polygons: empty Polygons object"); k++; } else { GEOSGeom lr = (GEOSGeometry *) GEOSGetExteriorRing_r(GEOShandle, GC); if (lr == NULL) error("rgeos_geospolygon2Polygons: exterior ring failure"); SET_VECTOR_ELT(polys, k, rgeos_geosring2Polygon(env, lr, FALSE)); comm[k] = 0; areas[k] = NUMERIC_POINTER( GET_SLOT(VECTOR_ELT(polys,k), install("area")) )[0]; totalarea += areas[k]; po[k] = k + R_OFFSET; int ownerk = k + R_OFFSET; k++; int nirs = GEOSGetNumInteriorRings_r(GEOShandle, GC); for (int j=0; j<nirs; j++) { lr = (GEOSGeometry *) GEOSGetInteriorRingN_r(GEOShandle, GC, j); if (lr == NULL) error("rgeos_geospolygon2Polygons: interior ring failure"); SET_VECTOR_ELT(polys, k, rgeos_geosring2Polygon(env, lr, TRUE)); comm[k] = ownerk; areas[k] = NUMERIC_POINTER( GET_SLOT(VECTOR_ELT(polys,k), install("area")) )[0]; po[k] = k + R_OFFSET; k++; } } } SEXP plotOrder; PROTECT(plotOrder = NEW_INTEGER(npoly)); pc++; revsort(areas, po, npoly); for (int i=0; i<npoly; i++) INTEGER_POINTER(plotOrder)[i] = po[i]; SEXP labpt = GET_SLOT(VECTOR_ELT(polys,po[0]-1), install("labpt")); SEXP area; PROTECT(area = NEW_NUMERIC(1)); pc++; NUMERIC_POINTER(area)[0] = totalarea; SEXP comment; PROTECT(comment = NEW_CHARACTER(1)); pc++; char *buf; int nc; nc = (int) (ceil(log10(npoly)+1.0))+1; buf = (char *) R_alloc((size_t) (npoly*nc)+1, sizeof(char)); SP_PREFIX(comm2comment)(buf, (npoly*nc)+1, comm, npoly); SET_STRING_ELT(comment, 0, mkChar((const char*) buf)); SEXP ans; PROTECT(ans = NEW_OBJECT(MAKE_CLASS("Polygons"))); pc++; SET_SLOT(ans, install("Polygons"), polys); SET_SLOT(ans, install("plotOrder"), plotOrder); SET_SLOT(ans, install("labpt"), labpt); SET_SLOT(ans, install("ID"), ID); SET_SLOT(ans, install("area"), area); setAttrib(ans, install("comment"), comment); UNPROTECT(pc); return(ans); }
SEXP rgeos_binary_STRtree_query(SEXP env, SEXP obj1, SEXP obj2) { GEOSGeom *bbs2; int nobj1, nobj2, i, j, pc=0, isPts=FALSE; GEOSGeom GC, GCpts=NULL, bb; SEXP pl, bblist; GEOSSTRtree *str; int *icard, *ids, *oids; char classbuf1[BUFSIZ], classbuf2[BUFSIZ]; GEOSGeom (*rgeos_xx2MP)(SEXP, SEXP); strcpy(classbuf1, CHAR(STRING_ELT(GET_CLASS(VECTOR_ELT(obj1, 0)), 0))); if (!strncmp(classbuf1, "Polygons", 8)) rgeos_xx2MP = rgeos_Polygons2MP; else if (!strncmp(classbuf1, "Lines", 5)) rgeos_xx2MP = rgeos_Lines2MP; else error("rgeos_binary_STRtree_query: object class %s unknown", classbuf1); GEOSContextHandle_t GEOShandle = getContextHandle(env); str = (GEOSSTRtree *) GEOSSTRtree_create_r(GEOShandle, (size_t) 10); nobj1 = length(obj1); SEXP cl2 = GET_CLASS(obj2); if (cl2 == R_NilValue) strcpy(classbuf2, "\0"); else strcpy(classbuf2, CHAR(STRING_ELT(cl2, 0))); if ( !strcmp( classbuf2, "SpatialPoints") || !strcmp(classbuf2, "SpatialPointsDataFrame")) { isPts = TRUE; SEXP crds = GET_SLOT(obj2, install("coords")); SEXP dim = getAttrib(crds, install("dim")); nobj2 = INTEGER_POINTER(dim)[0]; } else { nobj2 = length(obj2); } bbs2 = (GEOSGeom *) R_alloc((size_t) nobj2, sizeof(GEOSGeom)); ids = (int *) R_alloc((size_t) nobj1, sizeof(int)); UD.ids = (int *) R_alloc((size_t) nobj1, sizeof(int)); oids = (int *) R_alloc((size_t) nobj1, sizeof(int)); for (i=0; i<nobj1; i++) { ids[i] = i; pl = VECTOR_ELT(obj1, i); GC = rgeos_xx2MP(env, pl); if (GC == NULL) { error("rgeos_binary_STRtree_query: MP GC[%d] not created", i); } if ((bb = GEOSEnvelope_r(GEOShandle, GC)) == NULL) { error("rgeos_binary_STRtree_query: envelope [%d] not created", i); } GEOSGeom_destroy_r(GEOShandle, GC); GEOSSTRtree_insert_r(GEOShandle, str, bb, &(ids[i])); } if (isPts) { GCpts = rgeos_SpatialPoints2geospoint(env, obj2); } else { strcpy(classbuf2, CHAR(STRING_ELT(GET_CLASS(VECTOR_ELT(obj2, 0)), 0))); if (!strncmp(classbuf2, "Polygons", 8)) rgeos_xx2MP = rgeos_Polygons2MP; else if (!strncmp(classbuf2, "Lines", 5)) rgeos_xx2MP = rgeos_Lines2MP; else error("rgeos_binary_STRtree_query: object class %s unknown", classbuf2); } for (i=0; i<nobj2; i++) { if (isPts) { GC = (GEOSGeom) GEOSGetGeometryN_r(GEOShandle, GCpts, i); } else { pl = VECTOR_ELT(obj2, i); GC = rgeos_xx2MP(env, pl); } if (GC == NULL) { error("rgeos_binary_STRtree_query: GC[%d] not created", i); } if ((bb = GEOSEnvelope_r(GEOShandle, GC)) == NULL) { error("rgeos_binary_STRtree_query: envelope [%d] not created", i); } GEOSGeom_destroy_r(GEOShandle, GC); // Rprintf("i: %d, bb %s\n", i, GEOSGeomType_r(GEOShandle, bb)); bbs2[i] = bb; } // 110904 EJP icard = (int *) R_alloc((size_t) nobj2, sizeof(int)); PROTECT(bblist = NEW_LIST(nobj2)); pc++; for (i=0; i<nobj2; i++) { UD.count = 0; GEOSSTRtree_query_r(GEOShandle, str, bbs2[i], (GEOSQueryCallback) cb, &UD); icard[i] = UD.count; if (icard[i] > 0) { SET_VECTOR_ELT(bblist, i, NEW_INTEGER(icard[i])); for (j=0; j<UD.count; j++) { oids[j] = UD.ids[j] + R_OFFSET; } R_isort(oids, UD.count); for (j=0; j<UD.count; j++) { INTEGER_POINTER(VECTOR_ELT(bblist, i))[j] = oids[j]; } } } GEOSSTRtree_destroy_r(GEOShandle, str); for (i=0; i<nobj2; i++) { GEOSGeom_destroy_r(GEOShandle, bbs2[i]); } UNPROTECT(pc); return(bblist); }
SEXP rgeos_distancefunc(SEXP env, SEXP spgeom1, SEXP spgeom2, SEXP byid, p_distfunc distfunc) { GEOSContextHandle_t GEOShandle = getContextHandle(env); GEOSGeom geom1 = rgeos_convert_R2geos(env, spgeom1); int type1 = GEOSGeomTypeId_r(GEOShandle, geom1); GEOSGeom geom2; int type2; int sym_ans = FALSE; if (spgeom2 == R_NilValue) { sym_ans = TRUE; geom2 = geom1; type2 = GEOSGeomTypeId_r(GEOShandle, geom2); } else { geom2 = rgeos_convert_R2geos(env, spgeom2); type2 = GEOSGeomTypeId_r(GEOShandle, geom2); } int m = (LOGICAL_POINTER(byid)[0] && type1 == GEOS_GEOMETRYCOLLECTION) ? GEOSGetNumGeometries_r(GEOShandle, geom1) : 1; int n = (LOGICAL_POINTER(byid)[1] && type2 == GEOS_GEOMETRYCOLLECTION) ? GEOSGetNumGeometries_r(GEOShandle, geom2) : 1; if (m == -1) error("rgeos_distancefunc: invalid number of subgeometries in geometry 1"); if (n == -1) error("rgeos_distancefunc: invalid number of subgeometries in geometry 2"); int pc=0; SEXP ans; PROTECT(ans = NEW_NUMERIC(m*n)); pc++; GEOSGeom curgeom1 = geom1; GEOSGeom curgeom2 = geom2; for(int i=0; i<m; i++) { if ( m > 1) { curgeom1 = (GEOSGeom) GEOSGetGeometryN_r(GEOShandle, geom1, i); if (curgeom1 == NULL) error("rgeos_binpredfunc: unable to get subgeometries from geometry 1"); } for(int j=0; j<n; j++) { if(sym_ans && j > i) break; if ( n > 1) { curgeom2 = (GEOSGeom) GEOSGetGeometryN_r(GEOShandle, geom2, j); if (curgeom2 == NULL) error("rgeos_binpredfunc: unable to get subgeometries from geometry 2"); } double dist; if (!distfunc(GEOShandle, curgeom1, curgeom2, &dist)) error("rgeos_distancefunc: unable to calculate distance"); NUMERIC_POINTER(ans)[n*i+j] = dist; if (sym_ans) NUMERIC_POINTER(ans)[n*j+i] = dist; } } if (LOGICAL_POINTER(byid)[0] || LOGICAL_POINTER(byid)[1]) { SEXP dims; PROTECT(dims = NEW_INTEGER(2)); pc++; INTEGER_POINTER(dims)[0] = n; INTEGER_POINTER(dims)[1] = m; setAttrib(ans, R_DimSymbol, dims); } GEOSGeom_destroy_r(GEOShandle, geom1); if (!sym_ans) GEOSGeom_destroy_r(GEOShandle, geom2); UNPROTECT(pc); return(ans); }
Q_NOWARN_UNREACHABLE_PUSH static GEOSGeometry *LWGEOM_GEOS_buildArea( const GEOSGeometry *geom_in, QString &errorMessage ) { GEOSContextHandle_t handle = QgsGeos::getGEOSHandler(); GEOSGeometry *tmp = nullptr; GEOSGeometry *shp = nullptr; GEOSGeometry *geos_result = nullptr; int srid = GEOSGetSRID_r( handle, geom_in ); GEOSGeometry const *vgeoms[1]; vgeoms[0] = geom_in; try { geos_result = GEOSPolygonize_r( handle, vgeoms, 1 ); } catch ( GEOSException &e ) { errorMessage = QStringLiteral( "GEOSPolygonize(): %1" ).arg( e.what() ); return nullptr; } // We should now have a collection #if PARANOIA_LEVEL > 0 if ( GEOSGeometryTypeId_r( handle, geos_result ) != COLLECTIONTYPE ) { GEOSGeom_destroy_r( handle, geos_result ); errorMessage = "Unexpected return from GEOSpolygonize"; return nullptr; } #endif int ngeoms = GEOSGetNumGeometries_r( handle, geos_result ); // No geometries in collection, early out if ( ngeoms == 0 ) { GEOSSetSRID_r( handle, geos_result, srid ); return geos_result; } // Return first geometry if we only have one in collection, // to avoid the unnecessary Geometry clone below. if ( ngeoms == 1 ) { tmp = ( GEOSGeometry * )GEOSGetGeometryN_r( handle, geos_result, 0 ); if ( ! tmp ) { GEOSGeom_destroy_r( handle, geos_result ); return nullptr; } shp = GEOSGeom_clone_r( handle, tmp ); GEOSGeom_destroy_r( handle, geos_result ); // only safe after the clone above GEOSSetSRID_r( handle, shp, srid ); return shp; } /* * Polygonizer returns a polygon for each face in the built topology. * * This means that for any face with holes we'll have other faces * representing each hole. We can imagine a parent-child relationship * between these faces. * * In order to maximize the number of visible rings in output we * only use those faces which have an even number of parents. * * Example: * * +---------------+ * | L0 | L0 has no parents * | +---------+ | * | | L1 | | L1 is an hole of L0 * | | +---+ | | * | | |L2 | | | L2 is an hole of L1 (which is an hole of L0) * | | | | | | * | | +---+ | | * | +---------+ | * | | * +---------------+ * * See http://trac.osgeo.org/postgis/ticket/1806 * */ // Prepare face structures for later analysis Face **geoms = new Face*[ngeoms]; for ( int i = 0; i < ngeoms; ++i ) geoms[i] = newFace( GEOSGetGeometryN_r( handle, geos_result, i ) ); // Find faces representing other faces holes findFaceHoles( geoms, ngeoms ); // Build a MultiPolygon composed only by faces with an // even number of ancestors tmp = collectFacesWithEvenAncestors( geoms, ngeoms ); // Cleanup face structures for ( int i = 0; i < ngeoms; ++i ) delFace( geoms[i] ); delete [] geoms; // Faces referenced memory owned by geos_result. // It is safe to destroy geos_result after deleting them. GEOSGeom_destroy_r( handle, geos_result ); // Run a single overlay operation to dissolve shared edges shp = GEOSUnionCascaded_r( handle, tmp ); if ( !shp ) { GEOSGeom_destroy_r( handle, tmp ); return nullptr; } GEOSGeom_destroy_r( handle, tmp ); GEOSSetSRID_r( handle, shp, srid ); return shp; }
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); }