繁体   English   中英

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

[英]How to interpolate 2-D points between two timesteps?

我有 2 个二维坐标。 假设(x_1, y_1)是时间t = 1的点, (x_2, y_2)是时间t = 10的点。 我想在110时间步长之间进行线性插值,即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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM