interpolation.cpp 3.79 KiB
#include "interpolation.hpp"
using namespace cgp;
/** Compute the linear interpolation p(t) between p1 at time t1 and p2 at time t2*/
vec3 linear_interpolation(float t, float t1, float t2, vec3 const& p1, vec3 const& p2);
/** Compute the cardinal spline interpolation p(t) with the polygon [p0,p1,p2,p3] at time [t0,t1,t2,t3]
* - Assume t \in [t1,t2] */
vec3 cardinal_spline_interpolation(float t, float t0, float t1, float t2, float t3, vec3 const& p0, vec3 const& p1, vec3 const& p2, vec3 const& p3, float K);
/** Find the index k such that intervals[k] < t < intervals[k+1]
* - Assume intervals is a sorted array of N time values
* - Assume t \in [ intervals[0], intervals[N-1] [ */
int find_index_of_interval(float t, numarray<float> const& intervals);
vec3 interpolation(float t, numarray<vec3> const& key_positions, numarray<float> const& key_times, float K)
{
// Find idx such that key_times[idx] < t < key_times[idx+1]
int idx = find_index_of_interval(t, key_times);
// Get parameters (time and position) used to compute the linear interpolation
// (You will need to get more parameters for the spline interpolation)
int n = key_times.size();
if (idx == 0) idx = n;
float t0 = key_times[idx - 1];
float t1 = key_times[idx%n ]; // = t_i
float t2 = key_times[(idx+1)%n]; // = t_{i+1}
float t3 = key_times[(idx+2)%n];
vec3 const& p0 = key_positions[idx - 1];
vec3 const& p1 = key_positions[idx%n ]; // = p_i
vec3 const& p2 = key_positions[(idx + 1) % n]; // = p_{i+1}
vec3 const& p3 = key_positions[(idx + 2) % n];
// Call the interpolation
vec3 p = cardinal_spline_interpolation(t, t0,t1,t2, t2,p0, p1,p2, p3, K);
return p;
}
/** Compute linear interpolation
t: current time
k: "current index" such that t_k < t < t_{k+1}, wxith t_k=key_time[k]
t1: t_k
t2: t_{k+1}
(p1,p2): positions associated to time (t1,t2) */
vec3 linear_interpolation(float t, float t1, float t2, vec3 const& p1, vec3 const& p2)
{
float const alpha = (t-t1)/(t2-t1);
vec3 const p = (1-alpha)*p1 + alpha*p2;
return p;
}
/** Compute the cardinal spline interpolation
t: current time
k: "current index" such that t_k < t < t_{k+1}, wxith t_k=key_time[k]
t0: t_{k-1}
t1: t_k
t2: t_{k+1}
t3: t_{k+2}
(p0,p1,p2,p3): positions associated to time (t0,t1,t2,t3)
K: spline tension */
vec3 cardinal_spline_interpolation(float t, float t0, float t1, float t2, float t3, vec3 const& p0, vec3 const& p1, vec3 const& p2, vec3 const& p3, float K)
{
// To do: fill the function to compute p(t) as a cardinal spline interpolation
float s = (t - t1) / (t2 - t1);
vec3 d1 = 2 * K * (p2 - p0) / (t2 - t0);
vec3 d2 = 2 * K * (p3 - p1) / (t3 - t0);
vec3 p = (2 * s * s * s-3*s*s+1) * p1 + (s * s * s - 2 * s * s + s) * d1 + (-2 * s * s * s + 3 * s * s) * p2 + (s * s * s - s * s) * d2;
return p;
}
int find_index_of_interval(float t, numarray<float> const& intervals)
{
int const N = intervals.size();
bool error = false;
if (intervals.size() < 2) {
std::cout<<"Error: Intervals should have at least two values; current size="<<intervals.size()<<std::endl;
error = true;
}
if (N>0 && t < intervals[0]) {
std::cout<<"Error: current time t is smaller than the first time of the interval"<<std::endl;
error = true;
}
if(N>0 && t > intervals[N-1]) {
std::cout<<"Error: current time t is greater than the last time of the interval"<<std::endl;
error = true;
}
if (error == true) {
std::string const error_str = "Error trying to find interval for t="+str(t)+" within values: ["+str(intervals)+"]";
error_cgp( error_str );
}
int k=0;
while( intervals[k+1]<t )
++k;
return k;
}