예제 #1
0
def mappy_construct(lines: geopandas.GeoDataFrame, points: geopandas.GeoDataFrame, output: str,
                    units_field: str, layer_name="geomap",
                    auto_extend=0, overwrite=False, debug=False):
    log.info("Executing mappy construct")
    log.info(f"CRS lines: {lines.crs}")
    log.info(f"CRS points: {points.crs}")

    out_args = {}
    out_args["layers"] = []

    if lines.crs != points.crs:
        log.warning("points and lines layers has different CRS, reprojecting...")
        points = points.to_crs(lines.crs)

    if os.path.exists(output):
        log.debug(f"File {output} exists!")
        existing_layers = fiona.listlayers(output)
        if layer_name in existing_layers and overwrite is not True:
            log.error(f"output geopackage {output} already contains a layer named {layer_name}.")
            return out_args

    if auto_extend != 0:
        log.info("extend_lines enabled, lines are extended")
        lines = extend_lines(lines, auto_extend)

        if debug:
            lines.to_file(output, layer="debug_extended_lines", driver="GPKG")
            out_args["layers"].append(lines)

    if debug:
        intersections = compute_self_intersections_points(lines)
        intersections.to_file(output, layer="debug_self_intersections", driver="GPKG")
        out_args["layers"].append("debug_self_intersections")

    polygons = polygonize(lines)

    if debug:
        polygons.to_file(output, layer="debug_polygons", driver="GPKG")
        out_args["layers"].append("debug_polygons")

    out = transfer_units_to_polygons(polygons, points, units_field)

    out.crs = None  # for now, then use the same as lines

    # from mappy.dev_tests import test_geopandas_save_gpkg
    # test_geopandas_save_gpkg()

    try:

        out.to_file(output, layer=layer_name, driver="GPKG")

    except Exception as e:
        print(e)
        raise e

    out_args["layers"].append(layer_name)
    out_args["gpkg"] = output

    return out_args
예제 #2
0
def extend(p1: np.ndarray, p2: np.ndarray, distance: float):
    """
    from p1 to p2 extended by dist.
    """
    if np.linalg.norm(p2 - p1) < 1e-16:
        log.warning("two points are equal, cannot extend")
        raise ValueError("two points are equal, cannot extend")
    v = p2 - p1
    v = v / np.linalg.norm(v) * distance

    news = p2 + v
    return news
예제 #3
0
def test_modules():
    available_modules = []

    for a in OptionalModules:

        log.debug(f"testing import {a.name}")

        try:
            doimport(a.name)
            available_modules.append(a)
        except:
            log.warning("cannot import")
    return available_modules
예제 #4
0
def extend_lines(geodataframe: geopandas.GeoDataFrame, distance: float):
    """
    Extends begin and end segments of the line by the given distance.
    :param geodataframe:
    :param distance:
    :return:
    """
    from copy import deepcopy

    allg = explode_all(geodataframe.geometry)
    geodataframe = geopandas.GeoDataFrame(geometry=allg)
    outframe = deepcopy(geodataframe)

    out = []  # the collection of extended LineStrings
    for f in geodataframe.geometry:
        if f.is_closed is True:
            log.warning("shape is closed. skip - no need to extend it")
            l = LineString(np.row_stack([f.xy]).T)
            out.append(l)
            continue

        if not f.is_valid:  # if the shape is no valid for some reason we remove it.
            log.warning("a not valid shape was found")
            raise ValueError("a not valid shape was found")

        pts = np.row_stack([f.xy]).T

        pts = drop_duplicated_points(
            pts)  # be sure we dont' have duplicated points wich might
        # be a problem expecially at the end and beginning (we would not be able to extend the feature)

        start = pts[:2][::-1]
        end = pts[::-1][:2][::-1]

        news = extend(start[0], start[1], distance)
        newe = extend(end[0], end[1], distance)

        extended = np.row_stack([news, pts, newe])

        if np.isnan(extended).any():
            log.warning("Extended line containing nans, should not happen")

        l = LineString(extended)
        if not l.is_valid:
            log.warning("line not valid")
        out.append(l)

    outframe["geometry"] = out

    return outframe
예제 #5
0
def transfer_units_to_polygons(polygons: geopandas.GeoDataFrame, units: geopandas.GeoDataFrame, units_field: str):
    """
    this could be obtained with a spatial joint, but with this we have more control to perform checks and know what is going on
    e.g. geopandas.sjoin( polygons, units, how="left", op='contains').plot(column= units_field)
    :param polygons:
    :param units:
    :param units_field:
    :return: A copy of polygons with the units
    """
    outids = []
    for pol in polygons.geometry:
        ids = get_points_inside(pol, units.geometry)
        log.info(f"found {len(ids)} polygon_ids: {ids}")
        thisunit = units[units_field][ids].values
        log.info(f"thisunit {thisunit}")

        if len(ids) > 1:
            log.warning("more than two points were found in the same polygon")

            if np.all(thisunit == thisunit[0]):
                log.warning("no prob, because point to the same unit")

            else:
                log.warning("The unit contains points with mismatched indicator points. Setting to None")
                thisunit = [None]

        if len(ids) < 1:
            log.error("cannot associate some polygons to an unit, missing points in unit definition file?")
            thisunit = [None]

        myunit = thisunit[0]
        outids.append(myunit)

    from copy import deepcopy
    out_polygons = deepcopy(polygons)
    out_polygons[units_field] = outids
    return out_polygons
예제 #6
0
파일: checks.py 프로젝트: planmap-eu/mappy
def check_validity_of_geometries(data: geopandas.GeoDataFrame):
    for pol in data.geometry:
        if not pol.is_valid:
            log.warning("found invalid geometry")