2015-04-23 75 views
0

我嘗試使用特徵庫來創建樣條曲線。但是,一旦我創建一個樣條,我不知道如何獲得在給定點x處的值。特徵樣條插值 - 如何在任意點x處獲取樣條y值?

參見下面的例子與我的意圖的解釋:

#include <Eigen/Core> 
#include <unsupported/Eigen/Splines> 

int main(int argc, char const* argv[]) 
{ 
    // points at (0,0) (15,12) and (30,17) 
    Eigen::MatrixXd points(2, 3); 
    points << 0, 15, 30, 
       0, 12, 17; 

    typedef Eigen::Spline<double, 2> spline2d; 
    spline2d s = Eigen::SplineFitting<spline2d>::Interpolate(points, 2); 

    // I now have a spline called s. 
    // I want to do something like: 
    double x = 12.34; 
    double new_y = s(x)[1]; // However this s() function uses a chord value. What is a chord value? 

    // Is there a: 
    double new_y2 = s.eval(x) 
} 

回答

5

我怎麼看,可能會造成混亂。 Eigen樣條曲線擬合模塊在您使用它時不會爲R - > R函數建模。例如,您可以用它構建螺旋。這意味着您不能期望從X值獲得Y值,而是通過樣條曲線上的距離(因此爲弦長)在樣條曲線上選取點。

有可能使用該模塊建模功能,雖然不是非常直觀:考慮你的Y值點中的R ,而不是讓本徵計算弦長,提供自己的一套結參數像X值一樣間隔(縮小到[0,1],因此算法可以應付)。它可以被包裝是這樣的:

#include <Eigen/Core> 
#include <unsupported/Eigen/Splines> 

#include <iostream> 

class SplineFunction { 
public: 
    SplineFunction(Eigen::VectorXd const &x_vec, 
       Eigen::VectorXd const &y_vec) 
    : x_min(x_vec.minCoeff()), 
     x_max(x_vec.maxCoeff()), 
     // Spline fitting here. X values are scaled down to [0, 1] for this. 
     spline_(Eigen::SplineFitting<Eigen::Spline<double, 1>>::Interpolate(
       y_vec.transpose(), 
       // No more than cubic spline, but accept short vectors. 

       std::min<int>(x_vec.rows() - 1, 3), 
       scaled_values(x_vec))) 
    { } 

    double operator()(double x) const { 
    // x values need to be scaled down in extraction as well. 
    return spline_(scaled_value(x))(0); 
    } 

private: 
    // Helpers to scale X values down to [0, 1] 
    double scaled_value(double x) const { 
    return (x - x_min)/(x_max - x_min); 
    } 

    Eigen::RowVectorXd scaled_values(Eigen::VectorXd const &x_vec) const { 
    return x_vec.unaryExpr([this](double x) { return scaled_value(x); }).transpose(); 
    } 

    double x_min; 
    double x_max; 

    // Spline of one-dimensional "points." 
    Eigen::Spline<double, 1> spline_; 
}; 

int main(int argc, char const* argv[]) 
{ 
    Eigen::VectorXd xvals(3); 
    Eigen::VectorXd yvals(xvals.rows()); 

    xvals << 0, 15, 30; 
    yvals << 0, 12, 17; 

    SplineFunction s(xvals, yvals); 

    std::cout << s(12.34) << std::endl; 
} 
+0

看起來不錯,感謝 – windenergy

+0

@Wintermute感謝這個答案,我發現谷歌搜索時花鍵支持本徵的。然而,我不明白爲什麼Eigen的樣條插值不會給出與C中普通的Vanilla自然樣條代碼相同的結果。另外,我不明白爲什麼值縮放是必要的:我嘗試使用未縮放的值並且插值似乎可行,但仍與普通香草數字接收器不同C代碼 – volatile

+0

@volatile Eigen Splines模塊使用B樣條(鏈接到[documentation](http://eigen.tuxfamily.org/dox/unsupported/classEigen_1_1Spline.html))。所需的數值縮放可能是這樣的僞影;我不得不去挖掘細節。在任何情況下,如果沒有插入僞造值。例如,你會發現,如果你用上面的代碼中的scaled_value替換了return x;,s(30)變成了-496.714而不是'17'。 – Wintermute