沿多边形边界生成等距点但 CW/CCW

Generating equidistance points along the boundary of a polygon but CW/CCW

假设我有一个多边形的顶点,它们都是逆时针方向。我希望沿着这个多边形的边界生成 n 个等距点。有谁知道任何现有的包可以做到这一点,如果没有,可以使用一种算法?我在 Python 工作。例如,如果所讨论的多边形是一个矩形,这就是我想要的:

enter image description here

shapely:

import shapely.geometry as sg
import shapely.affinity as sa
import matplotlib.pyplot as P
import numpy as np

n = 7
k = 11
ori = sg.Point([0,0])
p = [sg.Point([0,1])]
for j in range(1,n):
    p.append(sa.rotate(p[-1],360/n,origin=ori))
ngon = sg.Polygon(p)
P.figure()
P.plot(*ngon.exterior.xy,"-k")
P.scatter(*np.transpose([ngon.exterior.interpolate(t).xy for t in np.linspace(
    0,ngon.length,k,False)])[0])
P.axis("equal");P.box("off");P.axis("off")
P.show(block=0)

补充到可能的解决方法,等我记录一下。这个化身只是使用 numpy 来加密多边形或折线的边界。

def _pnts_on_line_(a, spacing=1, is_percent=False):  # densify by distance
"""Add points, at a fixed spacing, to an array representing a line.

**See**  `densify_by_distance` for documentation.

Parameters
----------
a : array
    A sequence of `points`, x,y pairs, representing the bounds of a polygon
    or polyline object.
spacing : number
    Spacing between the points to be added to the line.
is_percent : boolean
    Express the densification as a percent of the total length.

Notes
-----
Called by `pnt_on_poly`.
"""
N = len(a) - 1                                    # segments
dxdy = a[1:, :] - a[:-1, :]                       # coordinate differences
leng = np.sqrt(np.einsum('ij,ij->i', dxdy, dxdy))  # segment lengths
if is_percent:                                    # as percentage
    spacing = abs(spacing)
    spacing = min(spacing / 100, 1.)
    steps = (sum(leng) * spacing) / leng          # step distance
else:
    steps = leng / spacing                        # step distance
deltas = dxdy / (steps.reshape(-1, 1))            # coordinate steps
pnts = np.empty((N,), dtype='O')                  # construct an `O` array
for i in range(N):              # cycle through the segments and make
    num = np.arange(steps[i])   # the new points
    pnts[i] = np.array((num, num)).T * deltas[i] + a[i]
a0 = a[-1].reshape(1, -1)       # add the final point and concatenate
return np.concatenate((*pnts, a0), axis=0)

以 4 个单位点间距致密的六边形的结果。

h = np.array([[-8.66,  5.00], [ 0.00, 10.00], [ 8.66,  5.00], [ 8.66, -5.00],
              [ 0.00,-10.00], [-8.66, -5.00], [-8.66,  5.00]])  # ---- hexagon

附录

按照评论中的建议,我将通过因子化身添加致密化

h = np.array([[-8.66,  5.00], [-2.5, 5.0], [ 0.00, 10.00], [2.5, 5.0], [ 8.66,  5.00], [ 8.66, -5.00], [ 0.00,-10.00], [-8.66,  5.00]])  # ---- a polygon
_densify_by_factor(h, factor=3)

def _densify_by_factor(a, factor=2):
"""Densify a 2D array using np.interp.

Parameters
----------
a : array
    A 2D array of points representing a polyline/polygon boundary.
fact : number
    The factor to density the line segments by.
"""
a = np.squeeze(a)
n_fact = len(a) * factor
b = np.arange(0, n_fact, factor)
b_new = np.arange(n_fact - 1)     # Where you want to interpolate
c0 = np.interp(b_new, b, a[:, 0])
c1 = np.interp(b_new, b, a[:, 1])
n = c0.shape[0]
c = np.zeros((n, 2))
c[:, 0] = c0
c[:, 1] = c1
return c