【问题标题】:Cut a shapely polygon into N equally sized polygons将一个匀称的多边形切割成 N 个大小相等的多边形
【发布时间】:2020-09-13 22:04:27
【问题描述】:

我有一个 Shapely 多边形。我想将这些多边形切割成 n 个多边形,它们都具有或多或少相同大小的区域。大小相同是最好的,但近似值也可以。

我尝试使用described here 这两种方法,这两种方法都是朝着正确方向迈出的一步,而不是我需要的。两者都不允许目标 n

我研究了 voronoi,对此我很陌生。此分析给出的最终形状将是理想的,但它需要点而不是形状作为输入。

【问题讨论】:

    标签: python shapes


    【解决方案1】:

    这是我能做到的最好的。它不会导致每个多边形的表面积相等,但事实证明它可以满足我的需要。这会使用特定数量的点填充形状(如果参数保持不变,点数也会保持不变)。然后将这些点转换为 voronoi,然后将其转换为三角形。

    from shapely import affinity
    from shapely.geometry.multipolygon import MultiPolygon
    from scipy.spatial import Voronoi
    
    # Voronoi doesn't work properly with points below (0,0) so set lowest point to (0,0)
    shape = affinity.translate(shape, -shape_a.bounds[0], -shape_a.bounds[1])
    
    points = shape_to_points(shape)
    
    vor = points_to_voronoi(points)
    
    triangles = MultiPolygon(triangulate(MultiLineString(vor)))
    
    
    
    def shape_to_points(shape, num = 10, smaller_versions = 10):
        points = []
    
        # Take the shape, shrink it by a factor (first iteration factor=1), and then 
        # take points around the contours
        for shrink_factor in range(0,smaller_versions,1):
            # calculate the shrinking factor
            shrink_factor = smaller_versions - shrink_factor
            shrink_factor = shrink_factor / float(smaller_versions)
            # actually shrink - first iteration it remains at 1:1
            smaller_shape = affinity.scale(shape, shrink_factor, shrink_factor)
            # Interpolate numbers around the boundary of the shape
            for i in range(0,int(num*shrink_factor),1):
                i = i / int(num*shrink_factor)
                x,y =  smaller_shape.interpolate(i, normalized=True).xy
                points.append( (x[0],y[0]))
        
        # add the origin
        x,y = smaller_shape.centroid.xy
        points.append( (x[0], y[0]) ) # near, but usually not add (0,0)
        
        points = np.array(points)
        return points
    
    
    def points_to_voronoi(points):
        vor = Voronoi(points)
        vertices = [ x for x in vor.ridge_vertices if -1 not in x]
        # For some reason, some vertices were seen as super, super long. Probably also infinite lines, so take them out
        lines = [ LineString(vor.vertices[x]) for x in vertices if not vor.vertices[x].max() > 50000]
        return MultiLineString(lines)
    

    这是输入形状:

    这是shape_to_points之后的:

    这是在points_to_voronoi之后

    然后我们可以对 voronoi 进行三角测量:

    【讨论】:

    • 嗨,您在回答中使用了一些函数,这些函数看不到它们是如何导入的?你能添加进口吗?非常感谢
    • 嘿嘿。我已经添加了我的最佳猜测。我现在无法使用机器进行测试。如果它不起作用,请告诉我,我会将其从答案中删除。
    • 再次嗨,谢谢米切尔。还有一个问题:我有一种类型:多边形,代码崩溃了。形状是什么类型?我可以互相转换吗?
    • 还有,你是怎么画的?
    【解决方案2】:

    另一个开箱即用的选项是 h3 polyfill 函数。基本上任何重复结构都可以工作(三角形、正方形、十六进制),但是 Uber 的库使用十六进制,所以除非你编写一个模块来用其他形状之一做同样的事情,否则你会被困住。但是,您仍然遇到未直接指定“n”的问题(仅通过离散缩放级别选项间接指定)。

    polyfill

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-08-01
      • 2016-10-27
      • 2010-12-19
      • 2020-11-02
      • 1970-01-01
      • 2020-02-08
      • 1970-01-01
      • 2011-08-09
      相关资源
      最近更新 更多