英文:
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()
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论