static int lwcollection_calculate_gbox_cartesian(LWCOLLECTION *coll, GBOX *gbox) { GBOX subbox; int i; int result = LW_FAILURE; int first = LW_TRUE; assert(coll); if ( (coll->ngeoms == 0) || !gbox) return LW_FAILURE; subbox.flags = coll->flags; for ( i = 0; i < coll->ngeoms; i++ ) { if ( lwgeom_calculate_gbox_cartesian((LWGEOM*)(coll->geoms[i]), &subbox) == LW_SUCCESS ) { /* Keep a copy of the sub-bounding box for later if ( coll->geoms[i]->bbox ) lwfree(coll->geoms[i]->bbox); coll->geoms[i]->bbox = gbox_copy(&subbox); */ if ( first ) { gbox_duplicate(&subbox, gbox); first = LW_FALSE; } else { gbox_merge(&subbox, gbox); } result = LW_SUCCESS; } } return result; }
/** * Calculate the gbox for this goemetry, a cartesian box or * geodetic box, depending on how it is flagged. */ int lwgeom_calculate_gbox(const LWGEOM *lwgeom, GBOX *gbox) { gbox->flags = lwgeom->flags; if( FLAGS_GET_GEODETIC(lwgeom->flags) ) return lwgeom_calculate_gbox_geodetic(lwgeom, gbox); else return lwgeom_calculate_gbox_cartesian(lwgeom, gbox); }
/** * Takes a GEOMETRY and returns a GeoJson representation */ char * lwgeom_to_geojson(const LWGEOM *geom, char *srs, int precision, int has_bbox) { int type = geom->type; GBOX *bbox = NULL; GBOX tmp; if ( precision > OUT_MAX_DOUBLE_PRECISION ) precision = OUT_MAX_DOUBLE_PRECISION; if (has_bbox) { /* Whether these are geography or geometry, the GeoJSON expects a cartesian bounding box */ lwgeom_calculate_gbox_cartesian(geom, &tmp); bbox = &tmp; } switch (type) { case POINTTYPE: return asgeojson_point((LWPOINT*)geom, srs, bbox, precision); case LINETYPE: return asgeojson_line((LWLINE*)geom, srs, bbox, precision); case POLYGONTYPE: return asgeojson_poly((LWPOLY*)geom, srs, bbox, precision); case MULTIPOINTTYPE: return asgeojson_multipoint((LWMPOINT*)geom, srs, bbox, precision); case MULTILINETYPE: return asgeojson_multiline((LWMLINE*)geom, srs, bbox, precision); case MULTIPOLYGONTYPE: return asgeojson_multipolygon((LWMPOLY*)geom, srs, bbox, precision); case COLLECTIONTYPE: return asgeojson_collection((LWCOLLECTION*)geom, srs, bbox, precision); default: lwerror("lwgeom_to_geojson: '%s' geometry type not supported", lwtype_name(type)); } /* Never get here */ return NULL; }
/* ** Return a geohash string for the geometry. <http://geohash.org> ** Where the precision is non-positive, calculate a precision based on the ** bounds of the feature. Big features have loose precision. ** Small features have tight precision. */ char *lwgeom_geohash(const LWGEOM *lwgeom, int precision) { GBOX gbox; GBOX gbox_bounds; double lat, lon; int result; gbox_init(&gbox); gbox_init(&gbox_bounds); result = lwgeom_calculate_gbox_cartesian(lwgeom, &gbox); if ( result == LW_FAILURE ) return NULL; /* Return error if we are being fed something outside our working bounds */ if ( gbox.xmin < -180 || gbox.ymin < -90 || gbox.xmax > 180 || gbox.ymax > 90 ) { lwerror("Geohash requires inputs in decimal degrees."); return NULL; } /* What is the center of our geometry bounds? We'll use that to ** approximate location. */ lon = gbox.xmin + (gbox.xmax - gbox.xmin) / 2; lat = gbox.ymin + (gbox.ymax - gbox.ymin) / 2; if ( precision <= 0 ) { precision = lwgeom_geohash_precision(gbox, &gbox_bounds); } /* ** Return the geohash of the center, with a precision determined by the ** extent of the bounds. ** Possible change: return the point at the center of the precision bounds? */ return geohash_point(lon, lat, precision); }