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

╄→гoц情女王★ 提交于 2021-02-08 06:15:32

问题


Suppose I have the vertices of a polygon and they are all oriented CCW. I wish to generate n equidistance points along the boundary of this polygon. Does anyone know of any existing package that does this, and if not, an algorithm one can use? I am working in Python. For example, here is what I would like if the polygon in question is a rectangle:

enter image description here


回答1:


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)




回答2:


To add to the possible solutions, and so I have a record. This incarnation just uses numpy to densify the boundary of polygons or polylines.

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)

Results for a hexagon densified at 4 unit point spacing.

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

Addendum

As suggested in a comment, I will add the densify by factor incarnation

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



来源:https://stackoverflow.com/questions/64995977/generating-equidistance-points-along-the-boundary-of-a-polygon-but-cw-ccw

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!