Skip to content
Snippets Groups Projects
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;
}