VALUE rgeo_geos_polygons_eql(GEOSContextHandle_t context, const GEOSGeometry* geom1, const GEOSGeometry* geom2, char check_z) { VALUE result = Qnil; if (geom1 && geom2) { result = rgeo_geos_coordseqs_eql(context, GEOSGetExteriorRing_r(context, geom1), GEOSGetExteriorRing_r(context, geom2), check_z); if (RTEST(result)) { int len1 = GEOSGetNumInteriorRings_r(context, geom1); int len2 = GEOSGetNumInteriorRings_r(context, geom2); if (len1 >= 0 && len2 >= 0) { if (len1 == len2) { int i; for (i=0; i<len1; ++i) { result = rgeo_geos_coordseqs_eql(context, GEOSGetInteriorRingN_r(context, geom1, i), GEOSGetInteriorRingN_r(context, geom2, i), check_z); if (!RTEST(result)) { break; } } } else { result = Qfalse; } } else { result = Qnil; } } } return result; }
BOX3D computeBounds(GEOSContextHandle_t ctx, GEOSGeometry const *geometry) { uint32_t numInputDims; BOX3D output; GEOSGeometry const* ring = GEOSGetExteriorRing_r(ctx, geometry); GEOSCoordSequence const* coords = GEOSGeom_getCoordSeq_r(ctx, ring); GEOSCoordSeq_getDimensions_r(ctx, coords, &numInputDims); uint32_t count(0); GEOSCoordSeq_getSize_r(ctx, coords, &count); double x(0.0); double y(0.0); double z(0.0); for (unsigned i = 0; i < count; ++i) { GEOSCoordSeq_getOrdinate_r(ctx, coords, i, 0, &x); GEOSCoordSeq_getOrdinate_r(ctx, coords, i, 1, &y); if (numInputDims > 2) GEOSCoordSeq_getOrdinate_r(ctx, coords, i, 2, &z); output.grow(x, y, z); } return output; }
BOX3D Polygon::bounds() const { uint32_t numInputDims; BOX3D output; GEOSGeometry* boundary = GEOSGeom_clone_r(m_ctx, m_geom); // Smash out multi* if (GEOSGeomTypeId_r(m_ctx, m_geom) > 3) boundary = GEOSEnvelope_r(m_ctx, m_geom); GEOSGeometry const* ring = GEOSGetExteriorRing_r(m_ctx, boundary); GEOSCoordSequence const* coords = GEOSGeom_getCoordSeq_r(m_ctx, ring); GEOSCoordSeq_getDimensions_r(m_ctx, coords, &numInputDims); uint32_t count(0); GEOSCoordSeq_getSize_r(m_ctx, coords, &count); double x(0.0); double y(0.0); double z(0.0); for (unsigned i = 0; i < count; ++i) { GEOSCoordSeq_getOrdinate_r(m_ctx, coords, i, 0, &x); GEOSCoordSeq_getOrdinate_r(m_ctx, coords, i, 1, &y); if (numInputDims > 2) GEOSCoordSeq_getOrdinate_r(m_ctx, coords, i, 2, &z); output.grow(x, y, z); } GEOSGeom_destroy_r(m_ctx, boundary); return output; }
// Find holes of each face static void findFaceHoles( Face **faces, int nfaces ) { GEOSContextHandle_t handle = QgsGeos::getGEOSHandler(); // We sort by envelope area so that we know holes are only // after their shells qsort( faces, nfaces, sizeof( Face * ), compare_by_envarea ); for ( int i = 0; i < nfaces; ++i ) { Face *f = faces[i]; int nholes = GEOSGetNumInteriorRings_r( handle, f->geom ); for ( int h = 0; h < nholes; ++h ) { const GEOSGeometry *hole = GEOSGetInteriorRingN_r( handle, f->geom, h ); for ( int j = i + 1; j < nfaces; ++j ) { Face *f2 = faces[j]; if ( f2->parent ) continue; // hole already assigned /* TODO: can be optimized as the ring would have the * same vertices, possibly in different order. * maybe comparing number of points could already be * useful. */ if ( GEOSEquals_r( handle, GEOSGetExteriorRing_r( handle, f2->geom ), hole ) ) { f2->parent = f; break; } } } } }
BOX3D Crop::computeBounds(GEOSGeometry const *geometry) { uint32_t numInputDims; BOX3D output; #ifdef PDAL_HAVE_GEOS GEOSGeometry const* ring = GEOSGetExteriorRing_r(m_geosEnvironment, geometry); GEOSCoordSequence const* coords = GEOSGeom_getCoordSeq_r(m_geosEnvironment, ring); GEOSCoordSeq_getDimensions_r(m_geosEnvironment, coords, &numInputDims); log()->get(LogLevel::Debug) << "Inputted WKT had " << numInputDims << " dimensions" <<std::endl; uint32_t count(0); GEOSCoordSeq_getSize_r(m_geosEnvironment, coords, &count); double x(0.0); double y(0.0); double z(0.0); for (unsigned i = 0; i < count; ++i) { GEOSCoordSeq_getOrdinate_r(m_geosEnvironment, coords, i, 0, &x); GEOSCoordSeq_getOrdinate_r(m_geosEnvironment, coords, i, 1, &y); if (numInputDims > 2) GEOSCoordSeq_getOrdinate_r(m_geosEnvironment, coords, i, 2, &z); output.grow(x, y, z); } #else boost::ignore_unused_variable_warning(geometry); #endif return output; }
static VALUE method_polygon_exterior_ring(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_clone(self_data->factory, GEOSGetExteriorRing_r(self_data->geos_context, self_geom), RGEO_FACTORY_DATA_PTR(self_data->factory)->globals->geos_linear_ring); } return result; }
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; }
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_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); }