Exemplo n.º 1
0
    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)
Exemplo n.º 2
0
    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)
Exemplo n.º 3
0
    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"],
            }
Exemplo n.º 4
0
    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"]}
Exemplo n.º 5
0
    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}