2017-08-10 90 views
0

我在c#中搜索“多谐波样条”的实现。我只找到这个库Altaxo。我搜索一个库,通过nuget和许可证是可用的apache或mit。多谐波样条实现c#

我的用例是查找2D地图上定义点的平均温度。例如在

  • 位置1(X:0 Y:0温度:10°)
  • 情况2(X:0 Y:30温度:100℃)
  • POSITION3(X:40 Y:0温度:50°)
  • POSITION4(X:30 Y:30温度:20°)

红色点是计算值。

Temperature map

代码示例

using Altaxo.Calc.Interpolation; 
using Altaxo.Calc.LinearAlgebra; 
using System.Collections.Generic; 
using System.Linq; 

public class Spline 
{ 
    private PolyharmonicSpline _spline; 

    public Spline() 
    { 
     var items = new List<TemperaturePosition>() 
     { 
      new TemperaturePosition(0,0,10), 
      new TemperaturePosition(0,30,100), 
      new TemperaturePosition(40,0,50), 
      new TemperaturePosition(30,30,20), 
     }; 

     var xCoordinates = items.Select(o => o.X).ToArray(); 
     var yCoordinates = items.Select(o => o.Y).ToArray(); 
     var values = items.Select(o => o.Temperature).ToArray(); 

     this._spline = new PolyharmonicSpline(); 
     this._spline.Construct(new DoubleVector(xCoordinates), new DoubleVector(yCoordinates), new DoubleVector(values)); 
    } 

    public double Calculate(double x, double y) 
    { 
     return this._spline.GetInterpolatedValue(x, y); 
    } 
} 

public class TemperaturePosition 
{ 
    public double X { get; set; } 
    public double Y { get; set; } 
    public double Temperature { get; set; } 

    public TemperaturePosition(double x, double y, double temperature) 
    { 
     this.X = x; 
     this.Y = y; 
     this.Temperature = temperature; 
    } 
} 

回答

1

它实际上并不难使用重心插值,而不是花键的自己实现一个类似的插值。这可能有帮助practical guide to barycentric interpolation

对于一些代码,看看这个answer on gamedev.stackexchange.com

// Compute barycentric coordinates (u, v, w) for 
// point p with respect to triangle (a, b, c) 
void Barycentric(Point p, Point a, Point b, Point c, float &u, float &v, float &w) 
{ 
    Vector v0 = b - a, v1 = c - a, v2 = p - a; 
    float d00 = Dot(v0, v0); 
    float d01 = Dot(v0, v1); 
    float d11 = Dot(v1, v1); 
    float d20 = Dot(v2, v0); 
    float d21 = Dot(v2, v1); 
    float denom = d00 * d11 - d01 * d01; 
    v = (d11 * d20 - d01 * d21)/denom; 
    w = (d00 * d21 - d01 * d20)/denom; 
    u = 1.0f - v - w; 
} 

有了这个,你只需要你的三角给定的值 - 例如在您的示例中,对于数据点10,50,100使用一个三角形,对于数据点20,50,100使用另一个三角形。

样条曲线用于确保曲率连续性的“平滑”插值。

0

@schnaader我已将您的重心示例转换为C#。 该提案并没有解决我的问题,现在我需要额外的逻辑来计算温度。 3分以上并不容易。

C#实施例(Install-Package System.Numerics.Vectors

Tuple<float, float, float> Barycentric(Vector2 p, Vector2 a, Vector2 b, Vector2 c) 
{ 
    Vector2 v0 = b - a, v1 = c - a, v2 = p - a; 
    float d00 = Vector2.Dot(v0, v0); 
    float d01 = Vector2.Dot(v0, v1); 
    float d11 = Vector2.Dot(v1, v1); 
    float d20 = Vector2.Dot(v2, v0); 
    float d21 = Vector2.Dot(v2, v1); 

    float denom = d00 * d11 - d01 * d01; 
    var v = (d11 * d20 - d01 * d21)/denom; 
    var w = (d00 * d21 - d01 * d20)/denom; 
    var u = 1.0f - v - w; 
    return new Tuple<float, float, float>(v, w, u); 
}