[英]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.