[英]How to interpolate 2-D points between two timesteps?
我有 2 个二维坐标。 假设(x_1, y_1)
是时间t = 1
的点, (x_2, y_2)
是时间t = 10
的点。 我想在1
到10
时间步长之间进行线性插值,即2,3,...9
。
我如何在 python 中做到这一点?
您可以使用这两个点计算直线的方程,然后使用该方程生成尽可能多的点。 但与时间的关系取决于你想要的运动类型(easeOut、easeIn、linear)
(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)))
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.