zoukankan      html  css  js  c++  java
  • 生成凹包

    import time
    from struct import *
    import subprocess
    import fiona
    import math
    import numpy as np
    import pylab as pl
    from osgeo import ogr, gdal
    import shapely.geometry as geometry
    from shapely.geometry import polygon, multipolygon
    from geojson import Feature, Point, FeatureCollection, dumps
    from descartes import PolygonPatch
    from shapely.ops import cascaded_union, polygonize
    from scipy.spatial import Delaunay
    
    #
    input_shapefile = 'E:/test/pointNoRepeat.shp'
    shapefile = fiona.open(input_shapefile)
    points = [geometry.shape(point['geometry']) for point in shapefile]
    x = [p.coords.xy[0] for p in points]
    y = [p.coords.xy[1] for p in points]
    
    
    '''
    point_collection = geometry.MultiPoint(list(points))
    point_collection.envelope
    
    def plot_polygon(polygon):
        fig = pl.figure(figsize=(10,10))
        ax = fig.add_subplot(111)
        margin = .3
        x_min, y_min, x_max, y_max = polygon.bounds
        ax.set_xlim([x_min-margin, x_max+margin])
        ax.set_ylim([y_min-margin, y_max+margin])
        #print(str(x_min) + "  " + str(y_min) + "  " + str(x_max) + "  " + str(y_max))
        #print(polygon)
        patch = PolygonPatch(polygon, fc='#999999', ec='#000000', fill=True, zorder=-1)
        ax.add_patch(patch)
        return fig
    
    plot_polygon(point_collection.envelope)
    pl.plot(x,y,'o', color='#f16824')
    '''
    
    
    #
    def alpha_shape(points, alpha):
        """
        Compute the alpha shape (concave hull) of a set of points.
        @param points: Iterable container of points.
        @param alpha: alpha value to influence the gooeyness of the border. Smaller numbers don't fall inward as much as larger numbers.
            Too large, and you lose everything!
        """
        if len(points) < 4:
            # When you have a triangle, there is no sense in computing an alpha shape.
            return geometry.MultiPoint(list(points)).convex_hull
        def add_edge(edges, edge_points, coords, i, j):
            """
            Add a line between the i-th and j-th points, if not in the list already
            """
            if (i, j) in edges or (j, i) in edges:
                # already added
                return
            edges.add( (i, j) )
            edge_points.append(coords[ [i, j] ])
        coords = np.array([point.coords[0] for point in points])
        #print(coords)
        tri = Delaunay(coords)
        edges = set()
        edge_points = []
        # loop over triangles:
        # ia, ib, ic = indices of corner points of the triangle
        for ia, ib, ic in tri.vertices:
            pa = coords[ia]
            pb = coords[ib]
            pc = coords[ic]
            # Lengths of sides of triangle
            a = math.sqrt((pa[0]-pb[0])**2 + (pa[1]-pb[1])**2)
            b = math.sqrt((pb[0]-pc[0])**2 + (pb[1]-pc[1])**2)
            c = math.sqrt((pc[0]-pa[0])**2 + (pc[1]-pa[1])**2)
            # Semiperimeter of triangle
            s = (a + b + c)/2.0
            # Area of triangle by Heron's formula
            area = math.sqrt(s*(s-a)*(s-b)*(s-c))
            if area <= 0:
                continue;
            circum_r = a*b*c/(4.0*area)
            # Here's the radius filter.
            #print circum_r
            if circum_r < 1.0/alpha:
                add_edge(edges, edge_points, coords, ia, ib)
                add_edge(edges, edge_points, coords, ib, ic)
                add_edge(edges, edge_points, coords, ic, ia)
        m = geometry.MultiLineString(edge_points)
        triangles = list(polygonize(m))
        #
        return cascaded_union(triangles), edge_points
    
    #
    concave_hull, edge_points = alpha_shape(points, alpha=0.38)
    #
    featCollection = FeatureCollection([])
    featCollection["crs"] = {"type":"name","properties":{"name":"EPSG:2385"}}
    if hasattr(concave_hull, "geoms"):
        polys = concave_hull.geoms
        fig = pl.figure(figsize=(10,10))
        ax = fig.add_subplot(111)
        margin = .3
        if len(concave_hull.bounds)>0:
            #
            x_min, y_min, x_max, y_max = concave_hull.bounds
            ax.set_xlim([x_min-margin, x_max+margin])
            ax.set_ylim([y_min-margin, y_max+margin])
            for poly in polys:
                patch = PolygonPatch(poly, fc='#999999', ec='#000000', fill=True, zorder=-1)
                ax.add_patch(patch)
                #
                geojs_geom = poly.__geo_interface__
                hull_poly = dict(type='Feature', properties=dict(id=1))
                hull_poly['geometry'] = geojs_geom
                #print(hull_poly)
                my_feature = Feature(geometry=geojs_geom)
                featCollection["features"].append(my_feature)
            print(featCollection)
            pl.plot(x,y,'o', color='#f16824')
        #
        #print(concave_hull.geoms)
    else:
        fig = pl.figure(figsize=(10,10))
        ax = fig.add_subplot(111)
        margin = .3
        x_min, y_min, x_max, y_max = concave_hull.bounds
        ax.set_xlim([x_min-margin, x_max+margin])
        ax.set_ylim([y_min-margin, y_max+margin])
        patch = PolygonPatch(concave_hull, fc='#999999', ec='#000000', fill=True, zorder=-1)
        ax.add_patch(patch)
        pl.plot(x, y, 'o', color='#f16824')
        geojs_geom = concave_hull.__geo_interface__
        my_feature = Feature(geometry=geojs_geom)
        featCollection["features"].append(my_feature)
    #
    file_object = open('e:\test\result\result.json', 'w')
    file_object.write(dumps(featCollection))
    file_object.close()
    subprocess.call(["ogr2ogr", "-t_srs", "EPSG:2385", "-f", "ESRI Shapefile", "e:\test\result\ConcaveEnvelope.shp", "e:\test\result\result.json"])
    pl.show()

    image

    image

  • 相关阅读:
    冲刺周期第一天
    05构建之法阅读笔记之三
    第十周进度表
    问题账户需求分析
    2016年秋季个人阅读计划
    课后作业--1:《软件需求与分析》博文读后感
    《人月神话》阅读笔记--3
    《人月神话》阅读笔记--02
    《人月神话》阅读笔记--01
    个人总结
  • 原文地址:https://www.cnblogs.com/gispathfinder/p/5826236.html
Copyright © 2011-2022 走看看