def test_get_crs(self): # from EPSG epsg = "EPSG:28992" crs = utils.get_crs(epsg) self.assertIsInstance(crs, CRS) # from proj4 proj4 = """ +proj=sterea +lat_0=52.15616055555555 +lon_0=5.38763888888889 +k=0.9999079 +x_0=155000 +y_0=463000 +ellps=bessel +towgs84=565.2369,50.0087,465.658,-0.406857,0.350733,-1.87035,4.0812 +units=m +no_defs """ crs = utils.get_crs(proj4) self.assertIsInstance(crs, CRS)
def test_get_crs(self): if utils.GEOPANDAS_GTE_0_7_0: from pyproj import CRS expected_type = CRS else: expected_type = dict # from EPSG epsg = "EPSG:28992" crs = utils.get_crs(epsg) self.assertIsInstance(crs, expected_type) # from proj4 proj4 = """ +proj=sterea +lat_0=52.15616055555555 +lon_0=5.38763888888889 +k=0.9999079 +x_0=155000 +y_0=463000 +ellps=bessel +towgs84=565.2369,50.0087,465.658,-0.406857,0.350733,-1.87035,4.0812 +units=m +no_defs """ crs = utils.get_crs(proj4) self.assertIsInstance(crs, expected_type)
def process(data, request): mode = request["mode"] if mode not in ("extent", "intersects", "centroid"): raise ValueError("Unknown mode '{}'".format(mode)) # load the geometry and transform it into the requested projection geometry = load_wkt(data["wkt"]) if data["projection"] != request["projection"]: geometry = utils.shapely_transform(geometry, data["projection"], request["projection"]) f = gpd.GeoDataFrame(geometry=[geometry], crs=utils.get_crs(request["projection"])) # compute the bounds of each geometry and filter on min_size min_size = request.get("min_size") if min_size: minx, miny, maxx, maxy = geometry.bounds if (maxy - miny) < min_size or (maxx - minx) < min_size: return { "projection": request["projection"], "features": gpd.GeoDataFrame([]), } if mode == "intersects": if not geometry.intersects(request["geometry"]): return { "projection": request["projection"], "features": gpd.GeoDataFrame([]), } return {"features": f, "projection": request["projection"]} elif mode == "centroid": with warnings.catch_warnings(): # geopandas warns if in WGS84 warnings.simplefilter("ignore") centroid = geometry.centroid if not centroid.intersects(request["geometry"]): return { "projection": request["projection"], "features": gpd.GeoDataFrame([]), } return {"features": f, "projection": request["projection"]} elif mode == "extent": if not geometry.intersects(request["geometry"]): return {"projection": request["projection"], "extent": None} return { "extent": tuple(geometry.bounds), "projection": request["projection"], }
def process(polygons, properties, projection, request): if request.get("limit") is not None: polygons = polygons[: request["limit"]] if properties is not None: properties = properties[: request["limit"]] mode = request.get("mode", "intersects") geoseries = gpd.GeoSeries( [Polygon(x) for x in polygons], crs=get_crs(projection) ) if get_epsg_or_wkt(projection) != get_epsg_or_wkt(request["projection"]): geoseries = geoseries.apply( shapely_transform, args=(projection, request["projection"]) ) if mode == "extent": if len(geoseries) > 0: extent = tuple(geoseries.total_bounds) else: extent = None return {"extent": extent, "projection": request["projection"]} if len(geoseries) == 0: return { "features": gpd.GeoDataFrame([]), "projection": request["projection"], } if properties is not None: df = gpd.GeoDataFrame.from_records(properties) df.set_geometry(geoseries, inplace=True) if "id" in df.columns: df.set_index("id", inplace=True, drop=True) else: df = gpd.GeoDataFrame(geometry=geoseries) df.index.name = "id" if mode == "centroid": df = df[df["geometry"].centroid.within(request["geometry"])] elif mode == "intersects": df = df[df["geometry"].intersects(request["geometry"])] return {"features": df, "projection": request["projection"]}
def process(url, request): path = utils.safe_abspath(url) # convert the requested projection to a geopandas CRS crs = utils.get_crs(request["projection"]) # convert the requested shapely geometry object to a GeoSeries filt_geom = gpd.GeoSeries([request["geometry"]], crs=crs) # acquire the data, filtering on the filt_geom bbox f = gpd.GeoDataFrame.from_file(path, bbox=filt_geom, layer=request["layer"]) if len(f) == 0: # return directly if there is no data if request.get("mode") == "extent": return {"projection": request["projection"], "extent": None} else: # this takes modes 'centroid' and 'intersects' return { "projection": request["projection"], "features": gpd.GeoDataFrame([]), } f.set_index(request["id_field"], inplace=True) # apply the non-geometry field filters first mask = None for field, value in request["filters"].items(): if field not in f.columns: continue _mask = f[field] == value if mask is None: mask = _mask else: mask &= _mask if mask is not None: f = f[mask] # convert the data to the requested crs utils.geodataframe_transform(f, utils.crs_to_srs(f.crs), request["projection"]) # compute the bounds of each geometry and filter on min_size min_size = request.get("min_size") if min_size: bounds = f["geometry"].bounds widths = bounds["maxx"] - bounds["minx"] heights = bounds["maxy"] - bounds["miny"] f = f[(widths > min_size) | (heights > min_size)] # only return geometries that truly intersect the requested geometry if request["mode"] == "centroid": with warnings.catch_warnings(): # geopandas warns if in WGS84 warnings.simplefilter("ignore") f = f[f["geometry"].centroid.within(filt_geom.iloc[0])] else: f = f[f["geometry"].intersects(filt_geom.iloc[0])] if request.get("mode") == "extent": return { "projection": request["projection"], "extent": tuple(f.total_bounds), } else: # this takes modes 'centroid' and 'intersects' # truncate the number of geometries if necessary if request.get("limit") and len(f) > request["limit"]: f = f.iloc[:request["limit"]] elif request.get("limit") is None: global_limit = config.get("geomodeling.geometry-limit") if len(f) > global_limit: raise RuntimeError( "The amount of returned geometries exceeded " "the maximum of {} geometries.".format(global_limit)) return {"projection": request["projection"], "features": f}