簡體   English   中英

將一個勻稱的多邊形切割成 N 個大小相等的多邊形

[英]Cut a shapely polygon into N equally sized polygons

我有一個勻稱的多邊形。 我想將這些多邊形切割成n 個多邊形,它們都具有或多或少相同大小的區域。 大小相同是最好的,但近似值也可以。

我嘗試使用這里描述的兩種方法,這兩種方法都是朝着正確方向邁出的一步,而不是我需要的。 兩者都不允許目標n

我調查了voronoi ,對此我很陌生。 此分析給出的最終形狀將是理想的,但它需要點,而不是形狀作為輸入。

這是我能做到的最好的。 它不會導致每個多邊形的表面積相等,但事實證明它可以滿足我的需要。 這會使用特定數量的點填充形狀(如果參數保持不變,點數也會保持不變)。 然后將這些點轉換為 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 進行三角測量:

在此處輸入圖像描述

另一個開箱即用的選項是 h3 polyfill 函數。 基本上任何重復結構都可以工作(三角形、正方形、十六進制),但 Uber 的庫使用十六進制,所以除非你編寫一個模塊來對其他形狀之一做同樣的事情,否則你會被困住。 但是,您仍然存在未直接指定“n”的問題(僅通過離散縮放級別選項間接指定)。

填充物

只需結合 @user3496060 提供的響應和基本 polyfill 文檔(對我很有幫助,謝謝),這是一個簡單的功能。

這是來自 h3 repo 的一個很棒的筆記本 查看“人口普查多邊形到十六進制”部分,了解他們如何使用polyfill()

    def h3_fill_shapely_poly(poly = shape, res = 10):
        """
        inputs:
               - poly: must be a shapely Polygon, cannot be any other shapely object
               - res: resolution (higher means more specific zoom)
        output:
               - h3_fill: a Python set() object, generated by polypill
        """
        coordinates = [[i[0], i[1]] for i in poly.exterior.coords]
        geo_json = {
                "type": "Polygon",
                "coordinates": [coordinates]
        }
        h3_fill = h3.polyfill(geo_json, res, geo_json_conformant=False)
        print(f'h3_fill =\n{type(h3_fill), h3_fill}')
        return h3_fill

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM