簡體   English   中英

C ++:復制Matlab的interp1樣條插值函數

[英]C++: replicating matlab's interp1 spline interpolation function

誰能給我一些指導,以使用樣條插值法復制MATLAB的interp1函數? 我嘗試在Wikipedia頁面上嚴格復制該算法,但結果並沒有真正匹配。

#include <stdio.h>
#include <stdint.h>

#include <iostream>
#include <vector>
//MATLAB: interp1(x,test_array,query_points,'spline')

int main(){

    int size = 10;

    std::vector<float> test_array(10);
    test_array[0] = test_array[4] = test_array[8] = 1;
    test_array[1] = test_array[3] = test_array[5] = test_array[7] = test_array[9] = 4;
    test_array[2] = test_array[6] = 7;

    std::vector<float> query_points;
    for (int i = 0; i < 10; i++)
        query_points.push_back(i +.05);

    int n = (size - 1);

    std::vector<float> a(n+1);
    std::vector<float> x(n+1);  //sample_points vector
    for (int i = 0; i < (n+1); i++){
        x[i] = i + 1.0;
        a[i] = test_array[i];
    }

    std::vector<float> b(n);
    std::vector<float> d(n);
    std::vector<float> h(n);
        for (int i = 0; i < (n); ++i)
            h[i] = x[i+1] - x[i];

    std::vector<float> alpha(n);
        for (int i = 1; i < n; ++i)
            alpha[i] = ((3 / h[i]) * (a[i+1] - a[i])) - ((3 / h[i-1]) * (a[i] - a[i-1]));

    std::vector<float> c(n+1);
    std::vector<float> l(n+1);
    std::vector<float> u(n+1);
    std::vector<float> z(n+1);

    l[0] = 1.0;
    u[0] = z[0] = 0.0;

    for (int i = 1; i < n; ++i){
        l[i] = (2 * (x[i+1] - x[i-1])) - (h[i-1] * u[i-1]);
        u[i] = h[i] / l[i];
        z[i] = (alpha[i] - (h[i-1] * z[i-1])) / l[i];
    }

    l[n] = 1.0;
    z[n] = c[n] = 0.0;

    for (int j = (n - 1); j >= 0; j--){
        c[j] = z[j] - (u[j] * c[j+1]);
        b[j] = ((a[j+1] - a[j]) / h[j]) - ((h[j] / 3) * (c[j+1] + (2 * c[j])));
        d[j] = (c[j+1] - c[j]) / (3 * h[j]);
    }


    std::vector<float> output_array(10);
    for (int i = 0; i < n-1; i++){
        float eval_point = (query_points[i] - x[i]);
        output_array[i] =   a[i] + (eval_point * b[i]) + ( eval_point * eval_point * c[i]) + (eval_point * eval_point * eval_point * d[i]); 
        std::cout << output_array[i] << std::endl;
    }

    system("pause");
    return 0;
}

事后看來,您的代碼似乎參考Wikipedia文章進行了正確編碼。 但是,您需要了解一些有關interp1 ,我認為您在使用它檢查您的答案時沒有考慮到這一點。


當指定spline標記時,MATLAB的interp1假定端點條件不是knot Wikipedia上指定的算法是自然樣條線的代碼。

因此,這可能就是您的分數不匹配的原因。 FWIW,請查閱: http : //www.cs.tau.ac.il/~turkel/notes/numeng/spline_note.pdf並查看最后一頁上的圖。 您會看到,非結樣條和自然樣條具有相同的形狀,但是當數據僅由樣條的端點組成時,它們的y值會有所不同。 但是,如果端點之間有數據點,則所有不同種類的樣條線(或多或少)都具有相同的y值。

為了完整起見,以下是我上面引用的PDF注釋中的摘錄:

在此處輸入圖片說明

如果要使用自然樣條csape ,請使用csape而不是interp1 這提供了帶有最終條件的三次樣條。 您可以這樣調用csape

pp = csape(x,y);

xy是為樣條曲線定義的控制點。 默認情況下,這將返回一個自然的樣條曲線,這是您要執行的操作,並且是ppform類型的結構。 然后,您可以使用fnval找出樣條曲線的計算fnval

yval = fnval(pp, xval);

xvalyval是輸入x坐標,並且在此特定x處針對樣條曲線評估輸出。

使用它,然后檢查代碼是否與csape提供的值匹配。


次要音符

您需要MATLAB中的Curve Fitting Toolbox才能使用csape 如果您沒有此方法,那么不幸的是該方法將無法使用。

我認為interp1受MATLAB CODER支持。
只需使用CODER生成C代碼,您便擁有了所需的東西。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM