找到两个坐标之间的等距点

2024-04-18 20:24:33 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个函数,需要在屏幕上的两点之间(2d)取出等距点。
像这样-

|--------------|

距离已经决定了。例如,在这里,我把它看作2,然后我需要-

|--.--.--.--.--|

点可以是2d平面上的任何地方,这意味着如果我在两点之间画一条线,它可以是2d平面上可能的任何方向,即对角线、水平方向等。
我不知道用python怎么做。

我不知道用谷歌搜索什么。。。我14岁了,所以我不知道这方面的数学知识。
我知道如何计算直线的距离和坡度,但不知道如何继续。
提前谢谢!


Tags: 函数距离屏幕地方水平方向平面直线
3条回答

你需要做的是在两点之间interpolate

例如,假设您的两个端点有坐标(x1, y1)(x2, y2),并且您希望将它们之间的距离分割为n相等的部分,然后您可以计算它们之间的n-1新点,如下所示:

points = []
for i in range(1, n):
    a = float(i) / n             # rescale 0 < i < n --> 0 < a < 1
    x = (1 - a) * x1 + a * x2    # interpolate x coordinate
    y = (1 - a) * y1 + a * y2    # interpolate y coordinate
    points.append( (x,y) )

这里,a是原始点之间直线上插值点的位置,缩放后的值a = 0a = 1对应于原始点本身。


或者,如果希望插值点相距固定距离d,则可以使用Pythagorean theorem计算原始点之间的距离d_full,除以d得到s = d / d_full,然后按s从0到1的步骤递增a

d_full = ( (x2 - x1)**2 + (y2 - y1)**2 )**0.5
s = d / d_full

points = []
a = s                           # start at s so we don't duplicate (x1, y1)
while a < 1:
    x = (1 - a) * x1 + a * x2
    y = (1 - a) * y1 + a * y2
    points.append( (x,y) )
    a += s

请注意,这可能会导致在(x2, y2)处放置一个新点,或将其放置得非常近,这取决于d如何精确地划分点之间的距离。如果要避免这种情况,可以将条件a < 1替换为a < 1 - s/2

编辑:上面的代码以d的间隔放置点,开始于(x1, x2)。这就是说,如果d = 2原始点位于(0,0)(0,5),那么将在(0,2)(0,4)获得新点。 如果您希望新点在原始点之间居中(即在示例中位于(0,1)(0,3)),则可以通过将起点a = s替换为a = (1 % s) / 2来修改代码。

%modulo或余数运算符,因此1 % s在将0到1的距离分割成长度为s的片段后,给出剩余距离“剩余”。

给定这两个端点,可以用“参数”形式表示直线的方程式

x = x1 + (x2-x1) * t
y = y1 + (y2-y1) * t

正如您可以验证的,当t == 0(x,y) == (x1,y1)t == 1(x,y) == (x2,y2)时。通过更多的研究,您可以看到当t在0和1之间时,(x,y)在连接线段上,并且要获得点之间距离的某个分数,请将t设置为该分数。

例如,要获得距离为10的直线上间隔为2的点,请在t=0.2、0.4、0.6和0.8处计算xy

这是最容易解决的使用参数表示的线,其中涉及一个字母矢量数学。但别担心,会很容易的。

假设您的行由以下公式很好地指定:

y=ax+b

其中a是斜率,b是y截距。

然后你的线有一个向量<1,a>给出的方向,这意味着线在水平方向上每运行一个1单位就会上升m单位。

我们可以通过除以向量的大小来规范化这个向量。

向量的大小由

m=sqrt(a**2+b**2)

规范化向量由v=<1/m,a/m>给出。

现在,我们可以画出你的线如下:

for t in range(50):
  xp=0+t*v[0]
  yp=b+t*v[1]
  plot_point(xp,yp,'-')

你知道我在那里做了什么吗?我将循环的变量从x更改为t。这允许我们分别处理方程的xy部分。

如果我的线是由它的端点指定的,那么我可以写出如下公式:

for t in range(0,1,0.01):
  xp=x1+t*(x2-x1)
  yp=y1+t*(y2-y1)
  plot_point(xp,yp,'-')

由于x1是直线x部分的起点,而x2-x1是直线x点之间的距离,当t0走到1时,它通过了直线的所有x点。y的工作原理类似。

现在,我们可以抽象我们的画线函数,使其看起来像这样:

def draw_line(a,b,len,skip,sym):
  m=sqrt(a**2+b**2)
  v=(1/m,a/m)
  for t in range(0,len,skip):
    xp=0+t*v[0]
    yp=b+t*v[1]
    plot_point(xp,yp,sym)

现在,我们通过键入以下内容来绘制您的线条:

draw_line(a,b,50,1,'-')

并用

draw_line(a,b,50,3,'.')

其中,50是直线的长度,3是间隙之间的距离。

如果我们改用直线的起点和终点,我们的函数将如下所示:

def draw_line(x1,y1,x2,y2,skip,sym):
  dist=sqrt((x1-x2)**2)+(y1-y2)**2)
  skip=skip/dist
  for t in range(0,1,skip):
    xp=x1+t*(x2-x1)
    yp=y1+t*(y2-y1)
    plot_point(xp,yp,sym)

这会将要跳过的距离转换为直线总长度的一部分。您可能需要使用小于或等于1的跳过值来绘制直线,使用较大的跳过值来提取等距点。

您可能需要考虑使用Bresenham's Line Algorithm来为您绘制图形—这是一种很好的方法,可以在有字符像素网格的情况下找到最佳的近似线的方法。

而且,如果您在屏幕上绘制字符,您可能会对ANSI escape codes感兴趣,它可以用于移动光标、显示颜色和清除屏幕。

相关问题 更多 >