简体   繁体   中英

How to interpolate 2-D points between two timesteps?

I have 2 2-dimensional coordinates. Say, (x_1, y_1) be the point at time t = 1 and (x_2, y_2) be the point at time t = 10 . I would like to linearly interpolate between 1 to 10 timesteps ie 2,3,...9 .

How do I do that in python?

You can calculate the equation of the line using those two points, and then use the equation to generate as many as points. But the relationship with time depends on the motion type you want (easeOut, easeIn, linear)

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

Here is the equation. You can use your real values and get an equation of X and Y. Then calculate Y values to given X values.

This should work. You can give seek a value in between 0 & 1 to get intermediate coordinates

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

What you want to do is called linear interpolation , which can be done with a lerp() function:

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)))

Output:

 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)

A more efficient way that does significantly fewer computations per iteration could implemented by turning lerp() into a generator function . This approach is slightly less accurate due to cumulative error in the successive additions.

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))

Object Oriented Approach

If you're going to call it often, it might be worth the trouble to optimize it so it doesn't need to recompute so many values between calls that are the same every time it's called. One way to do that in would be to make it a class with a __call__() method. That way all the preliminary computations can be done when it's first constructed, and then just reused whenever the object is called with different time arguments later. It also makes it each to have and use multiple Lerp objects at the same time or a container of them, if so desired.

Classes like this are sometimes called " functors " since they're a combination of a function and an object (although ordinary functions are already objects in Python, they're not quite as flexible and easy to customize).

Here's what I mean:

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)))

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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