bool GEOSGeomCmp::operator () (const GEOSGeom ga, const GEOSGeom gb) const { if ( ga == 0 or gb == 0 ) return ga < gb; // true only if wa is NULL, but not wb const GEOSCoordSeq a = const_cast<GEOSCoordSeq>(GEOSGeom_getCoordSeq(ga)); const GEOSCoordSeq b = const_cast<GEOSCoordSeq>(GEOSGeom_getCoordSeq(gb)); unsigned sizeA; GEOSCoordSeq_getSize(a, & sizeA); unsigned sizeB; GEOSCoordSeq_getSize(a, & sizeB); if (sizeA != sizeB) return sizeA < sizeB; for ( unsigned i = 0; i < sizeA; ++ i) { double valA, valB; GEOSCoordSeq_getX(a, i, & valA); GEOSCoordSeq_getX(b, i, & valB); if ( valA != valB ) return valA < valB; } for ( unsigned i = 0; i < sizeA; ++ i) { double valA, valB; GEOSCoordSeq_getY(a, i, & valA); GEOSCoordSeq_getY(b, i, & valB); if ( valA != valB ) return valA < valB; } return false; }
ERL_NIF_TERM geom_to_eterm_polygon_coords(ErlNifEnv *env, const GEOSGeometry *geom) { unsigned int inner_num, i; const GEOSGeometry *outer, *inner; const GEOSCoordSequence *coords_seq; ERL_NIF_TERM coords; ERL_NIF_TERM *rings; inner_num = GEOSGetNumInteriorRings(geom); // all rings, outer + inner rings = malloc(sizeof(ERL_NIF_TERM)*inner_num+1); outer = GEOSGetExteriorRing(geom); coords_seq = GEOSGeom_getCoordSeq(outer); rings[0] = GEOSCoordSequence_to_eterm_list(env, coords_seq, GEOSGetNumCoordinates(outer)); for (i=0; i<inner_num; i++) { inner = GEOSGetInteriorRingN(geom, i); coords_seq = GEOSGeom_getCoordSeq(inner); rings[i+1] = GEOSCoordSequence_to_eterm_list(env, coords_seq, GEOSGetNumCoordinates(inner)); } coords = enif_make_list_from_array(env, rings, inner_num+1); free(rings); return coords; }
static shapeObj *msGEOSGeometry2Shape_polygon(GEOSGeom g) { shapeObj *shape=NULL; lineObj line; int numPoints, numRings; int i, j; GEOSCoordSeq coords; GEOSGeom ring; if(!g) return NULL; shape = (shapeObj *) malloc(sizeof(shapeObj)); msInitShape(shape); shape->type = MS_SHAPE_POLYGON; shape->geometry = (GEOSGeom) g; /* exterior ring */ ring = (GEOSGeom) GEOSGetExteriorRing(g); numPoints = GEOSGetNumCoordinates(ring); coords = (GEOSCoordSeq) GEOSGeom_getCoordSeq(ring); line.point = (pointObj *) malloc(sizeof(pointObj)*numPoints); line.numpoints = numPoints; for(i=0; i<numPoints; i++) { GEOSCoordSeq_getX(coords, i, &(line.point[i].x)); GEOSCoordSeq_getY(coords, i, &(line.point[i].y)); /* GEOSCoordSeq_getZ(coords, i, &(line.point[i].z)); */ } msAddLineDirectly(shape, &line); /* interior rings */ numRings = GEOSGetNumInteriorRings(g); for(j=0; j<numRings; j++) { ring = (GEOSGeom) GEOSGetInteriorRingN(g, j); if(GEOSisRing(ring) != 1) continue; /* skip it */ numPoints = GEOSGetNumCoordinates(ring); coords = (GEOSCoordSeq) GEOSGeom_getCoordSeq(ring); line.point = (pointObj *) malloc(sizeof(pointObj)*numPoints); line.numpoints = numPoints; for(i=0; i<numPoints; i++) { GEOSCoordSeq_getX(coords, i, &(line.point[i].x)); GEOSCoordSeq_getY(coords, i, &(line.point[i].y)); /* GEOSCoordSeq_getZ(coords, i, &(line.point[i].z)); */ } msAddLineDirectly(shape, &line); } msComputeBounds(shape); return shape; }
static shapeObj *msGEOSGeometry2Shape_multipoint(GEOSGeom g) { int i; int numPoints; GEOSCoordSeq coords; GEOSGeom point; shapeObj *shape=NULL; if(!g) return NULL; numPoints = GEOSGetNumGeometries(g); /* each geometry has 1 point */ shape = (shapeObj *) malloc(sizeof(shapeObj)); msInitShape(shape); shape->type = MS_SHAPE_POINT; shape->line = (lineObj *) malloc(sizeof(lineObj)); shape->numlines = 1; shape->line[0].point = (pointObj *) malloc(sizeof(pointObj)*numPoints); shape->line[0].numpoints = numPoints; shape->geometry = (GEOSGeom) g; for(i=0; i<numPoints; i++) { point = (GEOSGeom) GEOSGetGeometryN(g, i); coords = (GEOSCoordSeq) GEOSGeom_getCoordSeq(point); GEOSCoordSeq_getX(coords, 0, &(shape->line[0].point[i].x)); GEOSCoordSeq_getY(coords, 0, &(shape->line[0].point[i].y)); /* GEOSCoordSeq_getZ(coords, 0, &(shape->line[0].point[i].z)); */ } msComputeBounds(shape); return shape; }
static shapeObj *msGEOSGeometry2Shape_point(GEOSGeom g) { GEOSCoordSeq coords; shapeObj *shape=NULL; if(!g) return NULL; shape = (shapeObj *) malloc(sizeof(shapeObj)); msInitShape(shape); shape->type = MS_SHAPE_POINT; shape->line = (lineObj *) malloc(sizeof(lineObj)); shape->numlines = 1; shape->line[0].point = (pointObj *) malloc(sizeof(pointObj)); shape->line[0].numpoints = 1; shape->geometry = (GEOSGeom) g; coords = (GEOSCoordSeq) GEOSGeom_getCoordSeq(g); GEOSCoordSeq_getX(coords, 0, &(shape->line[0].point[0].x)); GEOSCoordSeq_getY(coords, 0, &(shape->line[0].point[0].y)); /* GEOSCoordSeq_getZ(coords, 0, &(shape->line[0].point[0].z)); */ shape->bounds.minx = shape->bounds.maxx = shape->line[0].point[0].x; shape->bounds.miny = shape->bounds.maxy = shape->line[0].point[0].y; return shape; }
pointObj *msGEOSGetCentroid(shapeObj *shape) { #ifdef USE_GEOS GEOSGeom g1, g2; GEOSCoordSeq coords; pointObj *point; if(!shape) return NULL; if(!shape->geometry) /* if no geometry for the shape then build one */ shape->geometry = (GEOSGeom) msGEOSShape2Geometry(shape); g1 = (GEOSGeom) shape->geometry; if(!g1) return NULL; g2 = GEOSGetCentroid(g1); point = (pointObj *) malloc(sizeof(pointObj)); coords = (GEOSCoordSeq) GEOSGeom_getCoordSeq(g2); GEOSCoordSeq_getX(coords, 0, &(point->x)); GEOSCoordSeq_getY(coords, 0, &(point->y)); /* GEOSCoordSeq_getZ(coords, 0, &(point->z)); */ GEOSCoordSeq_destroy(coords); return point; #else msSetError(MS_GEOSERR, "GEOS support is not available.", "msGEOSGetCentroid()"); return NULL; #endif }
static int ring2pts(const GEOSGeometry *geom, struct line_pnts *Points) { int i, ncoords; double x, y, z; const GEOSCoordSequence *seq = NULL; G_debug(3, "ring2pts()"); Vect_reset_line(Points); if (!geom) { G_warning(_("Invalid GEOS geometry!")); return 0; } z = 0.0; ncoords = GEOSGetNumCoordinates(geom); if (!ncoords) { G_warning(_("No coordinates in GEOS geometry (can be ok for negative distance)!")); return 0; } seq = GEOSGeom_getCoordSeq(geom); for (i = 0; i < ncoords; i++) { GEOSCoordSeq_getX(seq, i, &x); GEOSCoordSeq_getY(seq, i, &y); if (x != x || x > DBL_MAX || x < -DBL_MAX) G_fatal_error(_("Invalid x coordinate %f"), x); if (y != y || y > DBL_MAX || y < -DBL_MAX) G_fatal_error(_("Invalid y coordinate %f"), y); Vect_append_point(Points, x, y, z); } return 1; }
static shapeObj *msGEOSGeometry2Shape_line(GEOSGeom g) { shapeObj *shape=NULL; int i; int numPoints; GEOSCoordSeq coords; if(!g) return NULL; numPoints = GEOSGetNumCoordinates(g); coords = (GEOSCoordSeq) GEOSGeom_getCoordSeq(g); shape = (shapeObj *) malloc(sizeof(shapeObj)); msInitShape(shape); shape->type = MS_SHAPE_LINE; shape->line = (lineObj *) malloc(sizeof(lineObj)); shape->numlines = 1; shape->line[0].point = (pointObj *) malloc(sizeof(pointObj)*numPoints); shape->line[0].numpoints = numPoints; shape->geometry = (GEOSGeom) g; for(i=0; i<numPoints; i++) { GEOSCoordSeq_getX(coords, i, &(shape->line[0].point[i].x)); GEOSCoordSeq_getY(coords, i, &(shape->line[0].point[i].y)); /* GEOSCoordSeq_getZ(coords, i, &(shape->line[0].point[i].z)); */ } msComputeBounds(shape); return shape; }
ERL_NIF_TERM geom_to_eterm_linestring_coords(ErlNifEnv *env, const GEOSGeometry *geom) { const GEOSCoordSequence *coords_seq; coords_seq = GEOSGeom_getCoordSeq(geom); return GEOSCoordSequence_to_eterm_list(env, coords_seq, GEOSGetNumCoordinates(geom)); }
ERL_NIF_TERM geom_to_eterm_point_coords(ErlNifEnv *env, const GEOSGeometry *geom) { const GEOSCoordSequence *coords_seq; double coordx, coordy; coords_seq = GEOSGeom_getCoordSeq(geom); GEOSCoordSeq_getX(coords_seq, 0, &coordx); GEOSCoordSeq_getY(coords_seq, 0, &coordy); return enif_make_list2(env, enif_make_double(env, coordx), enif_make_double(env, coordy)); }
static YAP_Bool make_polygon_to_term (geometry_t geometry, const char * functor_name, YAP_Term *term) { int n; geometry_t ring; sequence_t sequence; YAP_Functor functor; unsigned int size; YAP_Term head; assert (term != NULL); *term = YAP_MkAtomTerm (YAP_LookupAtom ("[]")); size = GEOSGetNumInteriorRings (geometry); for (n = size - 1; n >= 0; n --) { ring = (geometry_t) GEOSGetInteriorRingN (geometry, n); sequence = (sequence_t) GEOSGeom_getCoordSeq (ring); if ((sequence == NULL) || (point_list_to_term (sequence, &head) == FALSE)) return (FALSE); *term = YAP_MkPairTerm (head, *term); } /* Exterior ring always exists. */ ring = (geometry_t) GEOSGetExteriorRing (geometry); if (ring == NULL) return (FALSE); sequence = (sequence_t) GEOSGeom_getCoordSeq (ring); if ((sequence == NULL) || (point_list_to_term (sequence, &head) == FALSE)) return (FALSE); *term = YAP_MkPairTerm (head, *term); if (functor_name != NULL) { functor = YAP_MkFunctor (YAP_LookupAtom (NAME_POLYGON), 1); *term = YAP_MkApplTerm (functor, 1, term); } return (TRUE); }
static void _get_envelope(GEOSGeometry* geometry,Rect* rect) { unsigned int num_pnt; GEOSGeometry* env; const GEOSGeometry* ring; const GEOSCoordSequence* seq; double x,y; unsigned int loop=0; assert(rect != 0); assert(geometry != 0); rect->minX = rect->minY = rect->maxX = rect->maxY = 0; if(GEOSGeomTypeId(geometry) == GEOS_POINT) { GEOSGeomGetX(geometry,&x); GEOSGeomGetY(geometry,&y); rect->minX = rect->maxX = x; rect->minY = rect->maxY = y; return; } env = GEOSEnvelope(geometry); ring = GEOSGetExteriorRing(env); seq = GEOSGeom_getCoordSeq(ring); GEOSCoordSeq_getSize(seq,&num_pnt); if(num_pnt == 0 || num_pnt > 5)return; GEOSCoordSeq_getX(seq,0,&x); GEOSCoordSeq_getY(seq,0,&y); rect->minX = rect->maxX = x; rect->minY = rect->maxY = y; for(loop=1;loop<num_pnt;loop++) { GEOSCoordSeq_getX(seq,loop,&x); GEOSCoordSeq_getY(seq,loop,&y); if(x > rect->maxX) rect->maxX = x; if(x < rect->minX) rect->minX = x; if(y > rect->maxY) rect->maxY = y; if(y < rect->minY) rect->minY = y; } GEOSGeom_destroy(env); }
static YAP_Bool make_point_to_term (geometry_t geometry, const char * functor_name, YAP_Term *term) { double x, y; sequence_t sequence; assert (term != NULL); sequence = (sequence_t) GEOSGeom_getCoordSeq (geometry); if ((sequence == NULL) || (GEOSCoordSeq_getX (sequence, 0, &x) == 0) || (GEOSCoordSeq_getY (sequence, 0, &y) == 0)) return (FALSE); if (make_point (x, y, functor_name, term) == FALSE) return (FALSE); return (TRUE); }
GEOSGeometry *Geometry::ApplyPointTransformationToSingleGeometry(PointTransformer *t, const GEOSGeometry *g) { int gtype = GEOSGeomTypeId(g); GEOSGeometry *ng = NULL; if (gtype == GEOS_POINT || gtype == GEOS_LINESTRING || gtype == GEOS_LINEARRING) { const GEOSCoordSequence *seq = GEOSGeom_getCoordSeq(g); GEOSCoordSequence *nseq = ApplyPointTransformationToCoordSequence(t, seq); // this is silly -- GEOS really needs a shortcut for this if (gtype == GEOS_POINT) { ng = GEOSGeom_createPoint(nseq); } if (gtype == GEOS_LINESTRING) { ng = GEOSGeom_createLineString(nseq); } if (gtype == GEOS_LINEARRING) { ng = GEOSGeom_createLinearRing(nseq); } } else if (gtype == GEOS_POLYGON) { int ircnt = GEOSGetNumInteriorRings(g); const GEOSGeometry *ext = GEOSGetExteriorRing(g); GEOSGeometry *next = ApplyPointTransformationToSingleGeometry(t, ext); GEOSGeometry **rings = NULL; if (ircnt > 0) { // This shares a lot in common with the code below in ApplyPointTransformation, // refactor into a single method? rings = new GEOSGeometry *[ircnt]; for (int i = 0; i < ircnt; i++) { rings[i] = ApplyPointTransformationToSingleGeometry(t, GEOSGetInteriorRingN(g, i)); } } ng = GEOSGeom_createPolygon(next, rings, ircnt); if (rings) { delete rings; } } return ng; }
static YAP_Bool make_linestring_to_term (geometry_t geometry, const char * functor_name, YAP_Term *term) { sequence_t sequence; YAP_Functor functor; assert (term != NULL); sequence = (sequence_t) GEOSGeom_getCoordSeq (geometry); if ((sequence == NULL) || (point_list_to_term (sequence, term) == FALSE)) return (FALSE); if (functor_name != NULL) { functor = YAP_MkFunctor (YAP_LookupAtom (functor_name), 1); *term = YAP_MkApplTerm (functor, 1, term); } return (TRUE); }
static shapeObj *msGEOSGeometry2Shape_multiline(GEOSGeom g) { int i, j; int numPoints, numLines; GEOSCoordSeq coords; GEOSGeom lineString; shapeObj *shape=NULL; lineObj line; if(!g) return NULL; numLines = GEOSGetNumGeometries(g); shape = (shapeObj *) malloc(sizeof(shapeObj)); msInitShape(shape); shape->type = MS_SHAPE_LINE; shape->geometry = (GEOSGeom) g; for(j=0; j<numLines; j++) { lineString = (GEOSGeom) GEOSGetGeometryN(g, j); numPoints = GEOSGetNumCoordinates(lineString); coords = (GEOSCoordSeq) GEOSGeom_getCoordSeq(lineString); line.point = (pointObj *) malloc(sizeof(pointObj)*numPoints); line.numpoints = numPoints; for(i=0; i<numPoints; i++) { GEOSCoordSeq_getX(coords, i, &(line.point[i].x)); GEOSCoordSeq_getY(coords, i, &(line.point[i].y)); /* GEOSCoordSeq_getZ(coords, i, &(line.point[i].z)); */ } msAddLineDirectly(shape, &line); } msComputeBounds(shape); return shape; }
/* Return an LWGEOM from a Geometry */ LWGEOM * GEOS2LWGEOM(const GEOSGeometry *geom, char want3d) { int type = GEOSGeomTypeId(geom) ; int hasZ; int SRID = GEOSGetSRID(geom); /* GEOS's 0 is equivalent to our unknown as for SRID values */ if ( SRID == 0 ) SRID = SRID_UNKNOWN; if ( want3d ) { hasZ = GEOSHasZ(geom); if ( ! hasZ ) { LWDEBUG(3, "Geometry has no Z, won't provide one"); want3d = 0; } } /* if ( GEOSisEmpty(geom) ) { return (LWGEOM*)lwcollection_construct_empty(COLLECTIONTYPE, SRID, want3d, 0); } */ switch (type) { const GEOSCoordSequence *cs; POINTARRAY *pa, **ppaa; const GEOSGeometry *g; LWGEOM **geoms; uint32_t i, ngeoms; case GEOS_POINT: LWDEBUG(4, "lwgeom_from_geometry: it's a Point"); cs = GEOSGeom_getCoordSeq(geom); if ( GEOSisEmpty(geom) ) return (LWGEOM*)lwpoint_construct_empty(SRID, want3d, 0); pa = ptarray_from_GEOSCoordSeq(cs, want3d); return (LWGEOM *)lwpoint_construct(SRID, NULL, pa); case GEOS_LINESTRING: case GEOS_LINEARRING: LWDEBUG(4, "lwgeom_from_geometry: it's a LineString or LinearRing"); if ( GEOSisEmpty(geom) ) return (LWGEOM*)lwline_construct_empty(SRID, want3d, 0); cs = GEOSGeom_getCoordSeq(geom); pa = ptarray_from_GEOSCoordSeq(cs, want3d); return (LWGEOM *)lwline_construct(SRID, NULL, pa); case GEOS_POLYGON: LWDEBUG(4, "lwgeom_from_geometry: it's a Polygon"); if ( GEOSisEmpty(geom) ) return (LWGEOM*)lwpoly_construct_empty(SRID, want3d, 0); ngeoms = GEOSGetNumInteriorRings(geom); ppaa = lwalloc(sizeof(POINTARRAY *)*(ngeoms+1)); g = GEOSGetExteriorRing(geom); cs = GEOSGeom_getCoordSeq(g); ppaa[0] = ptarray_from_GEOSCoordSeq(cs, want3d); for (i=0; i<ngeoms; i++) { g = GEOSGetInteriorRingN(geom, i); cs = GEOSGeom_getCoordSeq(g); ppaa[i+1] = ptarray_from_GEOSCoordSeq(cs, want3d); } return (LWGEOM *)lwpoly_construct(SRID, NULL, ngeoms+1, ppaa); case GEOS_MULTIPOINT: case GEOS_MULTILINESTRING: case GEOS_MULTIPOLYGON: case GEOS_GEOMETRYCOLLECTION: LWDEBUG(4, "lwgeom_from_geometry: it's a Collection or Multi"); ngeoms = GEOSGetNumGeometries(geom); geoms = NULL; if ( ngeoms ) { geoms = lwalloc(sizeof(LWGEOM *)*ngeoms); for (i=0; i<ngeoms; i++) { g = GEOSGetGeometryN(geom, i); geoms[i] = GEOS2LWGEOM(g, want3d); } } return (LWGEOM *)lwcollection_construct(type, SRID, NULL, ngeoms, geoms); default: lwerror("GEOS2LWGEOM: unknown geometry type: %d", type); return NULL; } }
static gaiaGeomCollPtr fromGeosGeometry (const GEOSGeometry * geos, const int dimension_model) { /* converting a GEOS Geometry into a GAIA Geometry */ int type; int itemType; unsigned int dims; int iv; int ib; int it; int sub_it; int nItems; int nSubItems; int holes; unsigned int points; double x; double y; double z; const GEOSCoordSequence *cs; const GEOSGeometry *geos_ring; const GEOSGeometry *geos_item; const GEOSGeometry *geos_sub_item; gaiaGeomCollPtr gaia = NULL; gaiaLinestringPtr ln; gaiaPolygonPtr pg; gaiaRingPtr rng; if (!geos) return NULL; type = GEOSGeomTypeId (geos); switch (type) { case GEOS_POINT: if (dimension_model == GAIA_XY_Z) gaia = gaiaAllocGeomCollXYZ (); else if (dimension_model == GAIA_XY_M) gaia = gaiaAllocGeomCollXYM (); else if (dimension_model == GAIA_XY_Z_M) gaia = gaiaAllocGeomCollXYZM (); else gaia = gaiaAllocGeomColl (); gaia->DeclaredType = GAIA_POINT; gaia->Srid = GEOSGetSRID (geos); cs = GEOSGeom_getCoordSeq (geos); GEOSCoordSeq_getDimensions (cs, &dims); if (dims == 3) { GEOSCoordSeq_getX (cs, 0, &x); GEOSCoordSeq_getY (cs, 0, &y); GEOSCoordSeq_getZ (cs, 0, &z); } else { GEOSCoordSeq_getX (cs, 0, &x); GEOSCoordSeq_getY (cs, 0, &y); z = 0.0; } if (dimension_model == GAIA_XY_Z) gaiaAddPointToGeomCollXYZ (gaia, x, y, z); else if (dimension_model == GAIA_XY_M) gaiaAddPointToGeomCollXYM (gaia, x, y, 0.0); else if (dimension_model == GAIA_XY_Z_M) gaiaAddPointToGeomCollXYZM (gaia, x, y, z, 0.0); else gaiaAddPointToGeomColl (gaia, x, y); break; case GEOS_LINESTRING: if (dimension_model == GAIA_XY_Z) gaia = gaiaAllocGeomCollXYZ (); else if (dimension_model == GAIA_XY_M) gaia = gaiaAllocGeomCollXYM (); else if (dimension_model == GAIA_XY_Z_M) gaia = gaiaAllocGeomCollXYZM (); else gaia = gaiaAllocGeomColl (); gaia->DeclaredType = GAIA_LINESTRING; gaia->Srid = GEOSGetSRID (geos); cs = GEOSGeom_getCoordSeq (geos); GEOSCoordSeq_getDimensions (cs, &dims); GEOSCoordSeq_getSize (cs, &points); ln = gaiaAddLinestringToGeomColl (gaia, points); for (iv = 0; iv < (int) points; iv++) { if (dims == 3) { GEOSCoordSeq_getX (cs, iv, &x); GEOSCoordSeq_getY (cs, iv, &y); GEOSCoordSeq_getZ (cs, iv, &z); } else { GEOSCoordSeq_getX (cs, iv, &x); GEOSCoordSeq_getY (cs, iv, &y); z = 0.0; } if (dimension_model == GAIA_XY_Z) { gaiaSetPointXYZ (ln->Coords, iv, x, y, z); } else if (dimension_model == GAIA_XY_M) { gaiaSetPointXYM (ln->Coords, iv, x, y, 0.0); } else if (dimension_model == GAIA_XY_Z_M) { gaiaSetPointXYZM (ln->Coords, iv, x, y, z, 0.0); } else { gaiaSetPoint (ln->Coords, iv, x, y); } } break; case GEOS_POLYGON: if (dimension_model == GAIA_XY_Z) gaia = gaiaAllocGeomCollXYZ (); else if (dimension_model == GAIA_XY_M) gaia = gaiaAllocGeomCollXYM (); else if (dimension_model == GAIA_XY_Z_M) gaia = gaiaAllocGeomCollXYZM (); else gaia = gaiaAllocGeomColl (); gaia->DeclaredType = GAIA_POLYGON; gaia->Srid = GEOSGetSRID (geos); /* exterior ring */ holes = GEOSGetNumInteriorRings (geos); geos_ring = GEOSGetExteriorRing (geos); cs = GEOSGeom_getCoordSeq (geos_ring); GEOSCoordSeq_getDimensions (cs, &dims); GEOSCoordSeq_getSize (cs, &points); pg = gaiaAddPolygonToGeomColl (gaia, points, holes); rng = pg->Exterior; for (iv = 0; iv < (int) points; iv++) { if (dims == 3) { GEOSCoordSeq_getX (cs, iv, &x); GEOSCoordSeq_getY (cs, iv, &y); GEOSCoordSeq_getZ (cs, iv, &z); } else { GEOSCoordSeq_getX (cs, iv, &x); GEOSCoordSeq_getY (cs, iv, &y); z = 0.0; } if (dimension_model == GAIA_XY_Z) { gaiaSetPointXYZ (rng->Coords, iv, x, y, z); } else if (dimension_model == GAIA_XY_M) { gaiaSetPointXYM (rng->Coords, iv, x, y, 0.0); } else if (dimension_model == GAIA_XY_Z_M) { gaiaSetPointXYZM (rng->Coords, iv, x, y, z, 0.0); } else { gaiaSetPoint (rng->Coords, iv, x, y); } } for (ib = 0; ib < holes; ib++) { /* interior rings */ geos_ring = GEOSGetInteriorRingN (geos, ib); cs = GEOSGeom_getCoordSeq (geos_ring); GEOSCoordSeq_getDimensions (cs, &dims); GEOSCoordSeq_getSize (cs, &points); rng = gaiaAddInteriorRing (pg, ib, points); for (iv = 0; iv < (int) points; iv++) { if (dims == 3) { GEOSCoordSeq_getX (cs, iv, &x); GEOSCoordSeq_getY (cs, iv, &y); GEOSCoordSeq_getZ (cs, iv, &z); } else { GEOSCoordSeq_getX (cs, iv, &x); GEOSCoordSeq_getY (cs, iv, &y); z = 0.0; } if (dimension_model == GAIA_XY_Z) { gaiaSetPointXYZ (rng->Coords, iv, x, y, z); } else if (dimension_model == GAIA_XY_M) { gaiaSetPointXYM (rng->Coords, iv, x, y, 0.0); } else if (dimension_model == GAIA_XY_Z_M) { gaiaSetPointXYZM (rng->Coords, iv, x, y, z, 0.0); } else { gaiaSetPoint (rng->Coords, iv, x, y); } } } break; case GEOS_MULTIPOINT: case GEOS_MULTILINESTRING: case GEOS_MULTIPOLYGON: case GEOS_GEOMETRYCOLLECTION: if (dimension_model == GAIA_XY_Z) gaia = gaiaAllocGeomCollXYZ (); else if (dimension_model == GAIA_XY_M) gaia = gaiaAllocGeomCollXYM (); else if (dimension_model == GAIA_XY_Z_M) gaia = gaiaAllocGeomCollXYZM (); else gaia = gaiaAllocGeomColl (); if (type == GEOS_MULTIPOINT) gaia->DeclaredType = GAIA_MULTIPOINT; else if (type == GEOS_MULTILINESTRING) gaia->DeclaredType = GAIA_MULTILINESTRING; else if (type == GEOS_MULTIPOLYGON) gaia->DeclaredType = GAIA_MULTIPOLYGON; else gaia->DeclaredType = GAIA_GEOMETRYCOLLECTION; gaia->Srid = GEOSGetSRID (geos); nItems = GEOSGetNumGeometries (geos); for (it = 0; it < nItems; it++) { /* looping on elementaty geometries */ geos_item = GEOSGetGeometryN (geos, it); itemType = GEOSGeomTypeId (geos_item); switch (itemType) { case GEOS_POINT: cs = GEOSGeom_getCoordSeq (geos_item); GEOSCoordSeq_getDimensions (cs, &dims); if (dims == 3) { GEOSCoordSeq_getX (cs, 0, &x); GEOSCoordSeq_getY (cs, 0, &y); GEOSCoordSeq_getZ (cs, 0, &z); } else { GEOSCoordSeq_getX (cs, 0, &x); GEOSCoordSeq_getY (cs, 0, &y); z = 0.0; } if (dimension_model == GAIA_XY_Z) gaiaAddPointToGeomCollXYZ (gaia, x, y, z); else if (dimension_model == GAIA_XY_M) gaiaAddPointToGeomCollXYM (gaia, x, y, 0.0); else if (dimension_model == GAIA_XY_Z_M) gaiaAddPointToGeomCollXYZM (gaia, x, y, z, 0.0); else gaiaAddPointToGeomColl (gaia, x, y); break; case GEOS_LINESTRING: cs = GEOSGeom_getCoordSeq (geos_item); GEOSCoordSeq_getDimensions (cs, &dims); GEOSCoordSeq_getSize (cs, &points); ln = gaiaAddLinestringToGeomColl (gaia, points); for (iv = 0; iv < (int) points; iv++) { if (dims == 3) { GEOSCoordSeq_getX (cs, iv, &x); GEOSCoordSeq_getY (cs, iv, &y); GEOSCoordSeq_getZ (cs, iv, &z); } else { GEOSCoordSeq_getX (cs, iv, &x); GEOSCoordSeq_getY (cs, iv, &y); z = 0.0; } if (dimension_model == GAIA_XY_Z) { gaiaSetPointXYZ (ln->Coords, iv, x, y, z); } else if (dimension_model == GAIA_XY_M) { gaiaSetPointXYM (ln->Coords, iv, x, y, 0.0); } else if (dimension_model == GAIA_XY_Z_M) { gaiaSetPointXYZM (ln->Coords, iv, x, y, z, 0.0); } else { gaiaSetPoint (ln->Coords, iv, x, y); } } break; case GEOS_MULTILINESTRING: nSubItems = GEOSGetNumGeometries (geos_item); for (sub_it = 0; sub_it < nSubItems; sub_it++) { /* looping on elementaty geometries */ geos_sub_item = GEOSGetGeometryN (geos_item, sub_it); cs = GEOSGeom_getCoordSeq (geos_sub_item); GEOSCoordSeq_getDimensions (cs, &dims); GEOSCoordSeq_getSize (cs, &points); ln = gaiaAddLinestringToGeomColl (gaia, points); for (iv = 0; iv < (int) points; iv++) { if (dims == 3) { GEOSCoordSeq_getX (cs, iv, &x); GEOSCoordSeq_getY (cs, iv, &y); GEOSCoordSeq_getZ (cs, iv, &z); } else { GEOSCoordSeq_getX (cs, iv, &x); GEOSCoordSeq_getY (cs, iv, &y); z = 0.0; } if (dimension_model == GAIA_XY_Z) { gaiaSetPointXYZ (ln->Coords, iv, x, y, z); } else if (dimension_model == GAIA_XY_M) { gaiaSetPointXYM (ln->Coords, iv, x, y, 0.0); } else if (dimension_model == GAIA_XY_Z_M) { gaiaSetPointXYZM (ln->Coords, iv, x, y, z, 0.0); } else { gaiaSetPoint (ln->Coords, iv, x, y); } } } break; case GEOS_POLYGON: /* exterior ring */ holes = GEOSGetNumInteriorRings (geos_item); geos_ring = GEOSGetExteriorRing (geos_item); cs = GEOSGeom_getCoordSeq (geos_ring); GEOSCoordSeq_getDimensions (cs, &dims); GEOSCoordSeq_getSize (cs, &points); pg = gaiaAddPolygonToGeomColl (gaia, points, holes); rng = pg->Exterior; for (iv = 0; iv < (int) points; iv++) { if (dims == 3) { GEOSCoordSeq_getX (cs, iv, &x); GEOSCoordSeq_getY (cs, iv, &y); GEOSCoordSeq_getZ (cs, iv, &z); } else { GEOSCoordSeq_getX (cs, iv, &x); GEOSCoordSeq_getY (cs, iv, &y); z = 0.0; } if (dimension_model == GAIA_XY_Z) { gaiaSetPointXYZ (rng->Coords, iv, x, y, z); } else if (dimension_model == GAIA_XY_M) { gaiaSetPointXYM (rng->Coords, iv, x, y, 0.0); } else if (dimension_model == GAIA_XY_Z_M) { gaiaSetPointXYZM (rng->Coords, iv, x, y, z, 0.0); } else { gaiaSetPoint (rng->Coords, iv, x, y); } } for (ib = 0; ib < holes; ib++) { /* interior rings */ geos_ring = GEOSGetInteriorRingN (geos_item, ib); cs = GEOSGeom_getCoordSeq (geos_ring); GEOSCoordSeq_getDimensions (cs, &dims); GEOSCoordSeq_getSize (cs, &points); rng = gaiaAddInteriorRing (pg, ib, points); for (iv = 0; iv < (int) points; iv++) { if (dims == 3) { GEOSCoordSeq_getX (cs, iv, &x); GEOSCoordSeq_getY (cs, iv, &y); GEOSCoordSeq_getZ (cs, iv, &z); } else { GEOSCoordSeq_getX (cs, iv, &x); GEOSCoordSeq_getY (cs, iv, &y); z = 0.0; } if (dimension_model == GAIA_XY_Z) { gaiaSetPointXYZ (rng->Coords, iv, x, y, z); } else if (dimension_model == GAIA_XY_M) { gaiaSetPointXYM (rng->Coords, iv, x, y, 0.0); } else if (dimension_model == GAIA_XY_Z_M) { gaiaSetPointXYZM (rng->Coords, iv, x, y, z, 0.0); } else { gaiaSetPoint (rng->Coords, iv, x, y); } } } break; }; } break; }; return gaia; }
void VertexSnapper::snapVertices(MyGEOSGeom *geom, GEOSCoordSequence *closeCoord) { qDebug("VertexSnapper::snapVertices: ENTERING SNAP VERTICES"); // tested geometry as coordination sequence //GEOSGeometry* points = GEOSGeom_extractUniquePoints( geom->getGEOSGeom() ); const GEOSCoordSequence *s = GEOSGeom_getCoordSeq( geom->getGEOSGeom() ); GEOSCoordSequence *coord = GEOSCoordSeq_clone( s ); qDebug("VertexSnapper::snapVertices: GEOSCoordSequence cloned from geom Geometry"); // get dimension of geometry int dim = GEOSGeom_getDimensions( geom->getGEOSGeom() ); // get number of points unsigned int cSize; GEOSCoordSeq_getSize( coord, &cSize ); unsigned int ccSize; GEOSCoordSeq_getSize( closeCoord, &ccSize ); // find closest point from closeCoord for ( unsigned int i = 0; i < cSize; i++) { // get point from coordinate sequence double x, y; GEOSCoordSeq_getX( coord, i, &x); GEOSCoordSeq_getY( coord, i, &y); GEOSCoordSequence *point = GEOSCoordSeq_create( 1, dim ); GEOSCoordSeq_setX( point, 0, x); GEOSCoordSeq_setY( point, 0, y); GEOSGeometry * pointGeom = GEOSGeom_createPoint( point ); // minimal distance double minDist = tolDistance;// = coord->getAt(i).distance( closeCoord.getAt(0) ); unsigned int indMin = 0; bool isMin = false; for ( unsigned int j = 0; j < ccSize; j++ ) { // get point from coordinate sequence double xx, yy; GEOSCoordSeq_getX( closeCoord, j, &xx); GEOSCoordSeq_getY( closeCoord, j, &yy); GEOSCoordSequence *pointj = GEOSCoordSeq_create( 1, dim ); GEOSCoordSeq_setX( pointj, 0, xx); GEOSCoordSeq_setY( pointj, 0, yy); GEOSGeometry * pointGeomj = GEOSGeom_createPoint( pointj ); // compute distance between two tested points double dist = GEOSDistance( pointGeomj, pointGeom, &minDist ); //coord->getAt(i).distance( closeCoord.getAt(j) ); if( dist <= minDist ) { minDist = dist; indMin = j; isMin = true; } GEOSGeom_destroy(pointGeomj); } // set new coordinate to the closest point if there is some if ( isMin ) { double newX, newY; GEOSCoordSeq_getX( closeCoord, indMin, &newX); GEOSCoordSeq_getY( closeCoord, indMin, &newY); GEOSCoordSeq_setX( coord, i, newX); GEOSCoordSeq_setY( coord, i, newY); //coord->setAt( closeCoord.getAt(indMin), i ); } //GEOSCoordSeq_destroy(point); GEOSGeom_destroy(pointGeom); } // edit geometry editGeometry( geom, coord); //GEOSCoordSeq_destroy(coord); //GEOSCoordSeq_destroy(point0); //GEOSGeom_destroy(pointGeom0); } // MyGEOSGeom& VertexSnapper::snapVertices(MyGEOSGeom &geom, CoordinateSequence &closeCoord)
void QgsZonalStatistics::statisticsFromMiddlePointTest_improved( void* band, QgsGeometry* poly, int pixelOffsetX, int pixelOffsetY, int nCellsX, int nCellsY, double cellSizeX, double cellSizeY, const QgsRectangle& rasterBBox, double& sum, double& count ) { double cellCenterX, cellCenterY; QgsPoint currentCellCenter; float* scanLine = ( float * ) CPLMalloc( sizeof( float ) * nCellsX ); cellCenterY = rasterBBox.yMaximum() - pixelOffsetY * cellSizeY - cellSizeY / 2; count = 0; sum = 0; for ( int i = 0; i < nCellsY; ++i ) { GDALRasterIO( band, GF_Read, pixelOffsetX, pixelOffsetY + i, nCellsX, 1, scanLine, nCellsX, 1, GDT_Float32, 0, 0 ); cellCenterX = rasterBBox.xMinimum() + pixelOffsetX * cellSizeX + cellSizeX / 2; //do intersection of scanline with geometry GEOSCoordSequence* scanLineSequence = GEOSCoordSeq_create( 2, 2 ); GEOSCoordSeq_setX( scanLineSequence, 0, cellCenterX ); GEOSCoordSeq_setY( scanLineSequence, 0, cellCenterY ); GEOSCoordSeq_setX( scanLineSequence, 1, cellCenterX + nCellsX * cellSizeX ); GEOSCoordSeq_setY( scanLineSequence, 1, cellCenterY ); GEOSGeometry* scanLineGeos = GEOSGeom_createLineString( scanLineSequence ); //todo: delete GEOSGeometry* polyGeos = poly->asGeos(); GEOSGeometry* scanLineIntersection = GEOSIntersection( scanLineGeos, polyGeos ); GEOSGeom_destroy( scanLineGeos ); if ( !scanLineIntersection ) { cellCenterY -= cellSizeY; continue; } //debug //char* scanLineIntersectionType = GEOSGeomType( scanLineIntersection ); int numGeoms = GEOSGetNumGeometries( scanLineIntersection ); if ( numGeoms < 1 ) { GEOSGeom_destroy( scanLineIntersection ); cellCenterY -= cellSizeY; continue; } QList<double> scanLineList; double currentValue; GEOSGeometry* currentGeom = 0; for ( int z = 0; z < numGeoms; ++z ) { if ( numGeoms == 1 ) { currentGeom = scanLineIntersection; } else { currentGeom = GEOSGeom_clone( GEOSGetGeometryN( scanLineIntersection, z ) ); } const GEOSCoordSequence* scanLineCoordSequence = GEOSGeom_getCoordSeq( currentGeom ); if ( !scanLineCoordSequence ) { //error } unsigned int scanLineIntersectionSize; GEOSCoordSeq_getSize( scanLineCoordSequence, &scanLineIntersectionSize ); if ( !scanLineCoordSequence || scanLineIntersectionSize < 2 || ( scanLineIntersectionSize & 1 ) ) { //error } for ( unsigned int k = 0; k < scanLineIntersectionSize; ++k ) { GEOSCoordSeq_getX( scanLineCoordSequence, k, ¤tValue ); scanLineList.push_back( currentValue ); } if ( numGeoms != 1 ) { GEOSGeom_destroy( currentGeom ); } } GEOSGeom_destroy( scanLineIntersection ); qSort( scanLineList ); if ( scanLineList.size() < 1 ) { cellCenterY -= cellSizeY; continue; } int listPlace = -1; for ( int j = 0; j < nCellsX; ++j ) { //currentCellCenter = QgsPoint( cellCenterX, cellCenterY ); //instead of doing a contained test every time, find the place of scanLineList and check if even / odd if ( listPlace >= scanLineList.size() - 1 ) { break; } if ( cellCenterX >= scanLineList.at( listPlace + 1 ) ) { ++listPlace; if ( listPlace >= scanLineList.size() ) { break; } } if ( listPlace >= 0 && listPlace < ( scanLineList.size() - 1 ) && !( listPlace & 1 ) ) { if ( scanLine[j] != mInputNodataValue ) //don't consider nodata values { sum += scanLine[j]; ++count; } } cellCenterX += cellSizeX; } cellCenterY -= cellSizeY; } CPLFree( scanLine ); }
void VertexSnapper::snap() { qDebug("VertexSnapper::snap: ENTERING SNAP"); for ( unsigned int i = 0; i < subGeometry.size(); i++ ) { // find close features from the reference layer // vectors of coordinates of close Geometries std::vector<double> closeCoordX; std::vector<double> closeCoordY; qDebug("VertexSnapper::snap: Vectors with coordinates created"); for ( unsigned int j = 0; j < refGeometry.size(); j++) { bool close = isClose( subGeometry[i].getGEOSGeom(), refGeometry[j].getGEOSGeom() ); qDebug("VertexSnapper::snap: isClose checked."); if (close) { // add close coordinates //closeCoord->add( refGeometry[j].getGEOSGeom()->getCoordinates(), false, true );//(*ref_it).getGEOSGeom()->getCoordinates(), false, true ); // get points from geometry //GEOSGeometry* points = GEOSGeom_extractUniquePoints( refGeometry[j].getGEOSGeom() ); const GEOSCoordSequence *coords = GEOSGeom_getCoordSeq( refGeometry[j].getGEOSGeom() ); // NOTE: Only linestring or points is possible //GEOSCoordSequence *coords = GEOSCoordSeq_clone( s ); qDebug("VertexSnapper::snap: GEOSCoordSequence cloned from refGeometry"); // get number of points unsigned int cSize; GEOSCoordSeq_getSize( coords, &cSize ); // add x and y coordinates to the vectors for ( unsigned int k = 0; k < cSize; k++ ) { double x, y; GEOSCoordSeq_getX( coords, k, &x ); GEOSCoordSeq_getY( coords, k, &y ); closeCoordX.push_back(x); closeCoordY.push_back(y); qDebug("VertexSnapper::snap: Close coordinates x, y added to vector"); } //GEOSCoordSeq_destroy(coords); } } // create sequence with close points int dim = GEOSGeom_getDimensions( refGeometry[0].getGEOSGeom() ); GEOSCoordSequence *closeCoord = GEOSCoordSeq_create( closeCoordX.size(), dim ); qDebug("VertexSnapper::snap: GEOSCoordSequence closeCoord created"); for( unsigned int l = 0; l < closeCoordX.size(); l++) { GEOSCoordSeq_setX(closeCoord, l, closeCoordX[l]); GEOSCoordSeq_setY(closeCoord, l, closeCoordY[l]); } // snap vertex snapVertices( &subGeometry[i], closeCoord); newGeometry.push_back( subGeometry[i] ); GEOSCoordSeq_destroy(closeCoord); } } // void VertexSnapper::snap()
PolygonReader::BoundingBox PolygonReader::getBounds( const GEOSGeom polygons ) { BoundingBox ret; int geomNumber = GEOSGetNumGeometries(polygons); for (int n=0; n<geomNumber; n++) { GEOSGeom outerRing; if (geomNumber > 1) { GEOSGeom polygon = const_cast<GEOSGeom>(GEOSGetGeometryN( polygons, n )); if (polygon == NULL) throw std::runtime_error( "Multigeometry returned is NULL" ); outerRing = const_cast<GEOSGeom>(GEOSGetExteriorRing( polygon )); } else { outerRing = const_cast<GEOSGeom>(GEOSGetExteriorRing( polygons )); } if ( outerRing == NULL ) throw std::runtime_error( "Outer ring of polygon/shape is NULL." ); GEOSCoordSeq coordSeq = const_cast<GEOSCoordSeq>(GEOSGeom_getCoordSeq( outerRing )); if ( coordSeq == NULL ) throw std::runtime_error( "Coordinate sequence of polygon/shape returned NULL" ); unsigned int size; if ( GEOSCoordSeq_getSize( coordSeq, &size ) == 0 ) throw std::runtime_error( "Error when getting size of outer ring of polygon/shape" ); // Calculate Bounds WdbProjection prj( reader_.placeSpecification().projDefinition_ ); lonlat coord; // Initialize GEOSCoordSeq_getX( coordSeq, 0, &coord.lon ); GEOSCoordSeq_getY( coordSeq, 0, &coord.lat ); if ( ! isMetric( DEFAULT_PROJECTION ) ) { coord.lon *= DEG_TO_RAD; coord.lat *= DEG_TO_RAD; } prj.transformFromDefault( 1, &coord.lon, &coord.lat ); if ( ! isMetric( reader_.placeSpecification().projDefinition_ ) ) { coord.lon *= RAD_TO_DEG; coord.lat *= RAD_TO_DEG; } if (n == 0) { ret.left_ = coord.lon; ret.top_ = coord.lat; ret.right_ = coord.lon; ret.bottom_ = coord.lat; } for ( unsigned int i = 1; i < size; i++ ) { GEOSCoordSeq_getX( coordSeq, i, &coord.lon ); GEOSCoordSeq_getY( coordSeq, i, &coord.lat ); if ( ! isMetric( DEFAULT_PROJECTION ) ) { coord.lon *= DEG_TO_RAD; coord.lat *= DEG_TO_RAD; } prj.transformFromDefault( 1, &coord.lon, &coord.lat ); if ( ! isMetric( reader_.placeSpecification().projDefinition_ ) ) { coord.lon *= RAD_TO_DEG; coord.lat *= RAD_TO_DEG; } if (coord.lon < ret.left_) ret.left_ = coord.lon; else if (coord.lon > ret.right_) ret.right_ = coord.lon; if (coord.lat < ret.bottom_) ret.bottom_ = coord.lat; else if (coord.lat > ret.top_ ) ret.top_ = coord.lat; } } return ret; }
GEOSGeometry* LWGEOM_GEOS_buildArea(const GEOSGeometry* geom_in) { GEOSGeometry *tmp; GEOSGeometry *geos_result, *shp; GEOSGeometry const *vgeoms[1]; uint32_t i, ngeoms; int srid = GEOSGetSRID(geom_in); vgeoms[0] = geom_in; geos_result = GEOSPolygonize(vgeoms, 1); LWDEBUGF(3, "GEOSpolygonize returned @ %p", geos_result); /* Null return from GEOSpolygonize (an exception) */ if ( ! geos_result ) return 0; /* * We should now have a collection */ #if PARANOIA_LEVEL > 0 if ( GEOSGeometryTypeId(geos_result) != COLLECTIONTYPE ) { GEOSGeom_destroy(geos_result); lwerror("Unexpected return from GEOSpolygonize"); return 0; } #endif ngeoms = GEOSGetNumGeometries(geos_result); LWDEBUGF(3, "GEOSpolygonize: ngeoms in polygonize output: %d", ngeoms); LWDEBUGF(3, "GEOSpolygonize: polygonized:%s", lwgeom_to_ewkt(GEOS2LWGEOM(geos_result, 0))); /* * No geometries in collection, early out */ if ( ngeoms == 0 ) { GEOSSetSRID(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(geos_result, 0); if ( ! tmp ) { GEOSGeom_destroy(geos_result); return 0; /* exception */ } shp = GEOSGeom_clone(tmp); GEOSGeom_destroy(geos_result); /* only safe after the clone above */ GEOSSetSRID(shp, srid); return shp; } /* * Iteratively invoke symdifference on outer rings * as suggested by Carl Anderson: * postgis-devel/2005-December/001805.html */ shp = NULL; for (i=0; i<ngeoms; ++i) { GEOSGeom extring; GEOSCoordSeq sq; /* * Construct a Polygon from geometry i exterior ring * We don't use GEOSGeom_clone on the ExteriorRing * due to a bug in CAPI contained in GEOS 2.2 branch * failing to properly return a LinearRing from * a LinearRing clone. */ sq=GEOSCoordSeq_clone(GEOSGeom_getCoordSeq( GEOSGetExteriorRing(GEOSGetGeometryN( geos_result, i)) )); extring = GEOSGeom_createPolygon( GEOSGeom_createLinearRing(sq), NULL, 0 ); if ( extring == NULL ) /* exception */ { lwerror("GEOSCreatePolygon threw an exception"); return 0; } if ( shp == NULL ) { shp = extring; LWDEBUGF(3, "GEOSpolygonize: shp:%s", lwgeom_to_ewkt(GEOS2LWGEOM(shp, 0))); } else { tmp = GEOSSymDifference(shp, extring); LWDEBUGF(3, "GEOSpolygonize: SymDifference(%s, %s):%s", lwgeom_to_ewkt(GEOS2LWGEOM(shp, 0)), lwgeom_to_ewkt(GEOS2LWGEOM(extring, 0)), lwgeom_to_ewkt(GEOS2LWGEOM(tmp, 0)) ); GEOSGeom_destroy(shp); GEOSGeom_destroy(extring); shp = tmp; } } GEOSGeom_destroy(geos_result); GEOSSetSRID(shp, srid); return shp; }