生成一组沿一条线的新点

huangapple go评论64阅读模式
英文:

Generate a new set of points along a line

问题

我有一个Python项目,在其中需要多次重绘一条线,点的位置是随机的,但保持线的形状和点的数量大致相同。最终输出将使用多边形点而不是贝塞尔路径(尽管我不反对将贝塞尔用作中间步骤)。

这个动画演示了点如何沿着线移动到不同的位置,同时保持一般的形状。

我还有一个下面的工作示例,我正在沿着线移动并在现有点之间随机选择新点(下面的红线)。它运行得还可以,但如果有更好的方法,我很乐意听听。

尽管此代码使用matplotlib来演示线条,但最终的程序将不使用它。

import numpy as np
from matplotlib import pyplot as plt
import random
from random import (randint,uniform)

def move_along_line(p1, p2, scalar):
    distX = p2[0] - p1[0]
    distY = p2[1] - p1[1]

    modX = (distX * scalar) + p1[0]
    modY = (distY * scalar) + p1[1]

    return [modX, modY]

x_coords = [213.5500031,234.3809357,255.211853,276.0427856,296.8737183,317.7046204,340.1997681,364.3751221,388.5505066,414.8896484,444.5192261,478.5549622,514.5779419,545.4779053,570.3830566,588.0241699,598.2469482,599.772583,596.758728,593.7449341,590.7310791,593.373291,610.0373535,642.1326294,677.4451904,710.0697021,737.6887817,764.4020386,791.1152954,817.8284912,844.541687,871.2550049,897.9682007,924.6813965,951.3945923,978.1078491,1009.909546,1042.689941,1068.179199,1089.543091]
y_coords = [487.3099976,456.8832703,426.4565125,396.0297852,365.6030273,335.1763,306.0349426,278.1913452,250.3477478,224.7166748,203.0908051,191.2358704,197.6810608,217.504303,244.4946136,276.7698364,312.0551453,348.6885986,385.4395447,422.1904297,458.9414063,495.5985413,527.0128479,537.1477661,527.6642456,510.959259,486.6988525,461.2799683,435.8611145,410.4422913,385.023468,359.6045532,334.18573,308.7669067,283.3480835,257.929184,239.4429474,253.6099091,280.1803284,310.158783]
plt.plot(x_coords,y_coords,color='b')
plt.scatter(x_coords,y_coords,s=2)

new_line_x = []
new_line_y = []

for tgt in range(len(x_coords)-1):
    next_pt = tgt+1
    new_pt = move_along_line([x_coords[tgt],y_coords[tgt]], [x_coords[next_pt],y_coords[next_pt]], uniform(0, 1))
    new_line_x.append(new_pt[0])
    new_line_y.append(new_pt[1])

plt.plot(new_line_x,new_line_y,color='r')
plt.scatter(new_line_x,new_line_y,s=10)
ax = plt.gca()
ax.set_aspect('equal')
plt.show()

非常感谢!

英文:

I have a Python project where I need to redraw a line many times with the points in random places but keeping the line's shape and point count roughly the same. The final output will be using polygonal points and not Bezier paths (though I wouldn't be opposed to using Bezier as an intermediary step).

This animation is demonstrating how the points could move along the line to different positions while maintaining the general shape.
生成一组沿一条线的新点

I also have a working example below where I'm moving along the line and picking random new points between existing points (the red line, below). It works okay, but I'd love to hear some other approaches I might take if someone knows of a better one?

Though this code is using matplotlib to demonstrate the line, the final program will not.

import numpy as np
from matplotlib import pyplot as plt
import random
from random import (randint,uniform)

def move_along_line(p1, p2, scalar):
    distX = p2[0] - p1[0]
    distY = p2[1] - p1[1]

    modX = (distX * scalar) + p1[0]
    modY = (distY * scalar) + p1[1]

    return [modX, modY]

x_coords = [213.5500031,234.3809357,255.211853,276.0427856,296.8737183,317.7046204,340.1997681,364.3751221,388.5505066,414.8896484,444.5192261,478.5549622,514.5779419,545.4779053,570.3830566,588.0241699,598.2469482,599.772583,596.758728,593.7449341,590.7310791,593.373291,610.0373535,642.1326294,677.4451904,710.0697021,737.6887817,764.4020386,791.1152954,817.8284912,844.541687,871.2550049,897.9682007,924.6813965,951.3945923,978.1078491,1009.909546,1042.689941,1068.179199,1089.543091]
y_coords = [487.3099976,456.8832703,426.4565125,396.0297852,365.6030273,335.1763,306.0349426,278.1913452,250.3477478,224.7166748,203.0908051,191.2358704,197.6810608,217.504303,244.4946136,276.7698364,312.0551453,348.6885986,385.4395447,422.1904297,458.9414063,495.5985413,527.0128479,537.1477661,527.6642456,510.959259,486.6988525,461.2799683,435.8611145,410.4422913,385.023468,359.6045532,334.18573,308.7669067,283.3480835,257.929184,239.4429474,253.6099091,280.1803284,310.158783]
plt.plot(x_coords,y_coords,color='b')
plt.scatter(x_coords,y_coords,s=2)

new_line_x = []
new_line_y = []

for tgt in range(len(x_coords)-1):
    #tgt = randint(0, len(x_coords)-1)
    next_pt = tgt+1
    new_pt = move_along_line([x_coords[tgt],y_coords[tgt]], [x_coords[next_pt],y_coords[next_pt]], uniform(0, 1))
    new_line_x.append(new_pt[0])
    new_line_y.append(new_pt[1])

plt.plot(new_line_x,new_line_y,color='r')
plt.scatter(new_line_x,new_line_y,s=10)
ax = plt.gca()
ax.set_aspect('equal')
plt.show()

生成一组沿一条线的新点

Thank you very much!

答案1

得分: 1

以下是代码的翻译部分:

我不确定这是否是执行此操作的最佳方式但基本上您想要按照以下步骤进行操作

1. 计算整个路径的距离以及所有点之间的距离然后对于每个点累积到该点的距离

2. 生成一组新的随机点沿着路径开始从0开始然后对于每一对点计算一个随机距离随机值介于0和1之间 * 路径的总长度

3. 将这些距离从最小到最大进行排序

4. 对于每个随机距离循环遍历距离找到随机距离大于距离 i 且小于距离 i+1 的索引从这些点中插值得到新的 x 和 y 值

这段代码使用了matplotlib、scipy.interpolate、numpy、random 和math库,以及一些坐标数据和参数,最终绘制了一个曲线图。

英文:

I'm not sure if this is the most optimal way to do this but essentially you want to follow these steps:

Calculate the distance of the entire path, and the distance between all the points. Then for each point, tally the distances to that point.

Generate a new set of random points along the path starting with 0, then for each pair of points calculate a random distance: random value between 0 and 1 * total length of the path.

Sort these distances from smallest to largest.

For each random distance loop over the distances find the index where the random distance is > than distance i, and less than distance i+1. Interpolate new x and y values from these points.

from matplotlib import pyplot as plt
from scipy.interpolate import interp1d
import numpy
import random
import math
x_coords = [195.21,212.53,237.39,270.91,314.21,368.43,434.69,514.1,607.8,692.69,746.98,773.8,776.25,757.45,720.52,668.55,604.68,545.37,505.79,487.05,490.27,516.58,567.09,642.93,745.2,851.5,939.53,1010.54,1065.8,1106.58,1134.15,1149.75,1154.68]
y_coords = [195.34,272.27,356.59,438.98,510.14,560.76,581.52,563.13,496.27,404.39,318.83,242.15,176.92,125.69,91.02,75.48,81.62,113.49,168.57,239.59,319.29,400.38,475.6,537.67,579.32,586.78,558.32,504.7,436.69,365.05,300.55,253.95,236.03]
n_points = 100
x_coords = numpy.array(x_coords)
x_min = x_coords.min()
x_max = x_coords.max()
x_range = x_max - x_min
distances = []
tallied_distances = [0]
tallied_distance = 0
for i in range(0, len(x_coords) -1):
xi = x_coords[i]
xf = x_coords[i + 1]
yi= y_coords[i]
yf = y_coords[i+1]
d = math.sqrt((xf-xi)**2 + (yf-yi)**2)
tallied_distance += d
tallied_distances.append(tallied_distance)
random_distances_along_line = [0]
for i in range(0, n_points-2):
random_distances_along_line.append(random.random()*tallied_distance)
random_distances_along_line.sort()
new_x_points = [x_coords[0]]
new_y_points = [y_coords[0]]
for i in range(0, len(random_distances_along_line)):
dt = random_distances_along_line[i]
for j in range(0, len(tallied_distances)-1):
di = tallied_distances[j]
df = tallied_distances[j+1]
if di < dt and dt < df:
difference = dt - di
xi = x_coords[j]
xf = x_coords[j+1]
yi = y_coords[j]
yf = y_coords[j+1]
xt = xi+(xf-xi)*difference/(df-di)
yt = yi+(yf-yi)*difference/(df-di)
new_x_points.append(xt)
new_y_points.append(yt)
new_x_points.append(x_coords[len(x_coords)-1])
new_y_points.append(y_coords[len(y_coords)-1])
plt.plot(new_x_points, new_y_points)
plt.scatter(new_x_points, new_y_points,s=2)
ax = plt.gca()
ax.set_aspect('equal')
plt.show()

huangapple
  • 本文由 发表于 2023年2月8日 11:24:45
  • 转载请务必保留本文链接:https://go.coder-hub.com/75381109.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定