多谐波样条实现c#

时间:2017-08-10 14:16:41

标签: c# algorithm interpolation

我在c#中搜索“Polyharmonic spline”的实现。我只找到了这个库Altaxo。我通过nuget搜索可用的库,许可证是apache或mit。

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

  • position1(x:0 y:0温度:10°)
  • position2(x:0 y:30温度:100°)
  • 位置3(x:40 y:0温度:50°)
  • 位置4(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;
    }
}

2 个答案:

答案 0 :(得分: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使用另一个三角形。

Splines用于&#34;更顺畅&#34;确保曲率连续性的插值。

答案 1 :(得分: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);
}