Example #1
0
def vector_clean(data, tolerance=0):
    """Cleans the vector data of unnecessary clutter such as repeat
    points or closely related points within the distance specified in the
    'tolerance' parameter. Also tries to fix any broken geometries, dropping
    any unfixable ones.

    Adds the resulting cleaned data to the layers list.
    """
    # create new file
    outfile = GeoTable()
    outfile.fields = list(data.fields)

    # clean
    for feat in data:
        shapelyobj = geoj2shapely(feat.geometry)
        
        # try fixing invalid geoms
        if not shapelyobj.is_valid:
            if "Polygon" in shapelyobj.type:
                # fix bowtie polygons
                shapelyobj = shapelyobj.buffer(0.0)

        # remove repeat points (tolerance=0)
        # (and optionally smooth out complex shapes, tolerance >= 1)
        shapelyobj = shapelyobj.simplify(tolerance)
            
        # if still invalid, do not add to output
        if not shapelyobj.is_valid:
            continue

        # write to file
        geoj = shapely2geoj(shapelyobj)
        outfile.add_feature(feat.row, geoj)

    return outfile
Example #2
0
def _to_centroids(data):
    """create one centroid point for each multi geometry part"""
    
    # create new file
    outfile = GeoTable()
    outfile.fields = list(data.fields)
    
    # loop features
    for feat in data:
        if feat.geometry["type"] != "Point":
            shapelypoint = geoj2shapely(feat.geometry).centroid
            geoj = shapely2geoj(shapelypoint)
            outfile.add_feature(feat.row, geoj)
    return outfile
Example #3
0
def vector_buffer(data, dist_expression):
    # buffer and change each geojson dict in-place
    new = GeoTable()
    new.fields = list(data.fields)
    for feat in data:
        geom = geoj2shapely(feat.geometry)
        dist = eval(dist_expression)
        buffered = geom.buffer(dist)
        if not buffered.is_empty:
            geoj = shapely2geoj(buffered)
            geoj["type"] = buffered.type
            new.add_feature(feat.row, geoj)
    # change data type to polygon
    new.type = "Polygon"
    return new
Example #4
0
def vector_buffer(data, dist_expression):
    # buffer and change each geojson dict in-place
    new = GeoTable()
    new.fields = list(data.fields)
    for feat in data:
        geom = geoj2shapely(feat.geometry)
        dist = eval(dist_expression)
        buffered = geom.buffer(dist)
        if not buffered.is_empty:
            geoj = shapely2geoj(buffered)
            geoj["type"] = buffered.type
            new.add_feature(feat.row, geoj)
    # change data type to polygon
    new.type = "Polygon"
    return new
Example #5
0
def _to_multicentroids(data):
    """create multiple centroid points for each multi geometry part"""
    
    # create new file
    outfile = GeoTable()
    outfile.fields = list(data.fields)
    
    # loop features
    if "LineString" in data.type or "Polygon" in data.type:
        for feat in data:
            if "Multi" in feat.geometry["type"]:
                multishape = geoj2shapely(feat.geometry)
                for geom in multishape.geoms:
                    shapelypoint = geom.centroid
                    geoj = shapely2geoj(shapelypoint)
                    outfile.add_feature(feat.row, geoj)
            else:
                shapelypoint = geoj2shapely(feat.geometry).centroid
                geoj = shapely2geoj(shapelypoint)
                outfile.add_feature(feat.row, geoj)
        return outfile
    
    else:
        return data.copy()
Example #6
0
def vector_to_polygons(data, polytype="convex hull"):
    # create new file
    outfile = GeoTable()
    outfile.fields = list(data.fields)
        
    if polytype == "convex hull":
        for feat in data:
            shapelygeom = geoj2shapely(feat.geometry)
            convex = shapelygeom.convex_hull
            geoj = shapely2geoj(convex)
            # sometimes the convex hull is only a line or point
            # but we cannot mix shapetypes, so exclude those
            if geoj["type"] == "Polygon":
                outfile.add_feature(feat.row, geoj)
            
        return outfile

    elif polytype == "delauney triangles":
        if "Point" in data.type:
            def get_flattened_points():
                for feat in data:
                    if "Multi" in feat.geometry["type"]:
                        for point in feat.geometry["coordinates"]:
                            yield point
                    else: yield feat.geometry["coordinates"]
            triangles = pytess.triangulate(get_flattened_points())
            # triangle polygons are between multiple existing points,
            # so do not inherit any attributes
            for tri in triangles:
                geoj = {"type": "Polygon",
                        "coordinates": [tri] }
                row = ["" for field in outfile.fields]
                outfile.add_feature(row, geoj)

            return outfile

        else:
            raise Exception("Delauney triangles can only be made from point data")

    elif polytype == "voronoi polygons":
        if "Point" in data.type:
            def get_flattened_points():
                for feat in data:
                    if "Multi" in feat.geometry["type"]:
                        for point in feat.geometry["coordinates"]:
                            yield point
                    else: yield feat.geometry["coordinates"]
            results = pytess.voronoi(get_flattened_points())
            # return new file with polygon geometries
            for midpoint,polygon in results:
                geoj = {"type": "Polygon",
                        "coordinates": [polygon] }
                row = ["" for field in outfile.fields]
                outfile.add_feature(row, geoj)

            return outfile

        else:
            raise Exception("Voronoi polygons can only be made from point data")

    elif polytype == "enclose lines":
        if "LineString" in data.type:
            shapelylines = (geoj2shapely(feat.geometry) for feat in data)
            for polygon in shapely.ops.polygonize(shapelylines):
                geoj = shapely2geoj(polygon)
                row = ["" for field in outfile.fields]
                outfile.add_feature(row, geoj)

            return outfile
        
        else:
            raise Exception("Enclose lines can only be done on line data")