我在c#中搜索“Polyharmonic spline”的实现。我只找到了这个库Altaxo。我通过nuget搜索可用的库,许可证是apache或mit。
我的用例是在2d地图上找到定义点的平均温度。例如
红点是计算值。
代码示例
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;
}
}
答案 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);
}