如何在两个时间步之间插值二维点?



我有 2 个二维坐标。比如说,(x_1, y_1)是时间t = 1的点,(x_2, y_2)是时间t = 10的点。我想在110时间步之间线性插值,即2,3,...9.

如何在python中做到这一点?

您可以使用这两个点计算直线的方程,然后使用该方程生成尽可能多的点。但是与时间的关系取决于您想要的运动类型(缓出、缓和、线性)

(Y - y2)/(X - x2) = (y2 - y1)(x2 - x1)

这是等式。您可以使用实际值并得到 X 和 Y 的方程。 然后将 Y 值计算为给定的 X 值。

这应该有效。您可以给seek一个介于 0 和 1 之间的值以获得中间坐标

def interpolate(x1, y1, x2, y2, seek):
X = x1 + x2*seek
Y = y2 + (y2 - y1)(X - x2)/(x2 - x1)
return (X,Y)

你想要做的称为线性插值,这可以通过lerp()函数来完成:

from __future__ import division  # For Python 2
def lerp(t, times, points):
dx = points[1][0] - points[0][0]
dy = points[1][1] - points[0][1]
dt = (t-times[0]) / (times[1]-times[0])
return dt*dx + points[0][0], dt*dy + points[0][1]
x_1, y_1 = 1, 2
x_2, y_2 = -3, 4
times = [1, 10]
points = [(x_1, y_1), (x_2, y_2)]
for v in range(1, 11):
print('{:2d} -> ({:6.3f}, {:6.3f})'.format(v, *lerp(v, times, points)))

输出:

1 -> ( 1.000,  2.000)
2 -> ( 0.556,  2.222)
3 -> ( 0.111,  2.444)
4 -> (-0.333,  2.667)
5 -> (-0.778,  2.889)
6 -> (-1.222,  3.111)
7 -> (-1.667,  3.333)
8 -> (-2.111,  3.556)
9 -> (-2.556,  3.778)
10 -> (-3.000,  4.000)

一种更有效的方法,每次迭代的计算次数要少得多,可以通过将lerp()转换为生成器函数来实现。由于连续添加中的累积误差,此方法的准确性略低。

from __future__ import division  # For Python 2
def lerp(times, points, steps):
divisor = steps-1
dt =     (times[1] - times[0]) / divisor
dx = (points[1][0] - points[0][0]) / divisor
dy = (points[1][1] - points[0][1]) / divisor
t, x, y = (times[0],) + points[0]
for _ in range(steps):
yield t, x, y
t += dt
x += dx
y += dy
x_1, y_1 = 1, 2
x_2, y_2 = -3, 4
times = [1, 10]
points = [(x_1, y_1), (x_2, y_2)]
steps= times[1] - times[0] + 1
for t, x, y in lerp(times, points, steps):
print('{:6.2f} -> ({:6.3f}, {:6.3f})'.format(t, x, y))

面向对象的方法

如果要经常调用它,则可能需要麻烦对其进行优化,这样它就不需要在每次调用时都相同的调用之间重新计算这么多值。一种方法是使用__call__()方法使其成为class。这样,所有初步计算都可以在首次构造时完成,然后在以后使用不同的时间参数调用对象时重用。如果需要,它还使每个对象同时拥有和使用多个Lerp对象或它们的容器。

像这样的类有时被称为"函子",因为它们是函数和对象的组合(尽管普通函数已经是 Python 中的对象,但它们并不那么灵活且易于定制)。

我的意思是:

from __future__ import division  # For Python 2
class Lerp(object):
def __init__(self, times, points):
self.t0 = times[0]
self.p0 = points[0]
self.dt = times[1] - times[0]
self.dx = points[1][0] - points[0][0]
self.dy = points[1][1] - points[0][1]
def __call__(self, t):
dt = (t-self.t0) / self.dt
return dt*self.dx + self.p0[0], dt*self.dy + self.p0[1]
x_1, y_1 = 1, 2
x_2, y_2 = -3, 4
times = [1, 10]
points = [(x_1, y_1), (x_2, y_2)]
lerp = Lerp(times, points)
for v in range(1, 11):
print('{:2d} -> ({:6.3f}, {:6.3f})'.format(v, *lerp(v)))

最新更新