using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using User1.Valuation.Holworth.EngineInfrastructure;
namespace ConsoleApplication7
{
public enum PointState
{
Inner = 0,//定义域的点
Mid = 1,//未超出定义域的点
LeftOuter = 2,//超出左侧
RightOuter = 3//超出右侧
}
public class Point
{
public Point Left;
public Point Right;
public double x;
public double y;
public PointState state;
}
class Program
{
static void Main(string[] args)
{
List<double> list1 = new List<double>();
List<double> list2 = new List<double>();
for (int i = 0; i < 10; i++)
{
byte[] buffer = Guid.NewGuid().ToByteArray();
int iSeed = BitConverter.ToInt32(buffer, 0);
Random r = new Random(iSeed);
list1.Add(r.Next(1,100));
list2.Add(r.Next(1,100));
}
double[] xarr;
double[] yarr;
xarr = list1.ToArray();
yarr = list2.ToArray();
//求解的点
double[] x1arr = new double[] { 1, 2, 3, 4, 6, 8, 11, 13, 14, 16, 17 };
double[] y1arr;
Dictionary<double, Point> pointDictionary = new Dictionary<double, Point>();
int m = 1* 1;
DateTime t1 = DateTime.Now;
for (int i = 0; i < m; i++)
{
pointDictionary = LineDifferenceMethod(xarr, yarr, x1arr,out y1arr, true);
}
DateTime t2 = DateTime.Now;
Console.WriteLine("勇士:"+t2.Subtract(t1).TotalSeconds);
foreach (var item in pointDictionary)
{
Console.WriteLine(item.Key + "\t" + item.Value.y);
}
Console.Read();
}
/// <summary>
/// 线性差值法
/// </summary>
/// <param name="xarr">原始数据x轴</param>
/// <param name="yarr">原始数据y轴</param>
/// <param name="x1arr">求解的x轴的点的数组</param>
/// <param name="extension">边缘点是否使用斜率延伸</param>
/// <returns></returns>
public static Dictionary<double, Point> LineDifferenceMethod(double[] xarr, double[] yarr, double[] x1arr,out double[] y1arr, bool extension = false)
{
Dictionary<double, Point> pointDict = new Dictionary<double, Point>();
for (int i = 0; i < xarr.Length; i++)
{
Point p = new Point();
p.x = xarr[i];
p.y = yarr[i];
p.state = PointState.Inner;
pointDict[p.x] = p;
}
for (int i = 0; i < x1arr.Length; i++)
{
if (pointDict.ContainsKey(x1arr[i]))
{
continue;
}
Point p = new Point();
p.x = x1arr[i];
p.state = PointState.Mid;//默认值
pointDict[p.x] = p;
}
var orderbylist = pointDict.OrderBy(p => p.Key).ToList();
pointDict=orderbylist.ToDictionary(p=>p.Key,p=>p.Value);
var oriList = orderbylist.Where(p => p.Value.state== PointState.Inner).Select(p=>p.Value).ToArray();
Point firstPoint = oriList[0]; ;
Point lastPoint = oriList[oriList.Length-1];
if (xarr.Length== 1)
{
for (int i = 0; i < x1arr.Length; i++)
{
Point p = new Point();
p.x = x1arr[i];
p.y = yarr[0];
if (p.x != xarr[0])
{
if (p.x < xarr[0])
{
p.state = PointState.LeftOuter;
}
else if (p.x > xarr[0])
{
p.state = PointState.RightOuter;
}
}
}
y1arr = new double[x1arr.Length];
for (int i = 0; i < x1arr.Length; i++)
{
y1arr[i] = yarr[0];
pointDict[x1arr[i]].y = y1arr[i];
}
return pointDict;
}
for (int i = 0; i < x1arr.Length; i++)
{
double qx = x1arr[i];
Point p = pointDict[qx];
if (qx < firstPoint.x)
{
p.state = PointState.LeftOuter;
}
else if (qx > lastPoint.x)
{
p.state = PointState.RightOuter;
}
else if (pointDict.ContainsKey(qx))
{
//内部点不用求了
p = pointDict[qx];
continue;
}
else
{
p.state = PointState.Mid;
}
}
var points = pointDict.Values.ToArray();
for (int i = 0; i < points.Length; i++)
{
Point p = points[i];
if (i == 0)
{
p.Left = null;
if (points.Length > 1)
{
p.Right = points[i + 1];
}
else
{
p.Right = null;
}
}
else if (i == points.Length - 1)
{
p.Right = null;
if (points.Length > 1)
{
p.Left = points[i - 1];
}
else
{
p.Right = null;
}
}
else if (i > 0 && i < points.Length - 1)
{
p.Left = points[i - 1];
p.Right = points[i + 1];
}
}
//foreach (var item in points)
for(int i=0;i<points.Length;i++)
{
var item = points[i];
if (item.state == PointState.Mid)
{
var right = item.Right;
var left = item.Left;
AdjustLeftRight(ref right, ref left, item);
}
else if (item.state == PointState.LeftOuter)
{
if (!extension)
{
item.y = firstPoint.y;
}
else
{
var right = firstPoint.Right;
var left = firstPoint;
AdjustLeftRight(ref right, ref left, item);
}
}
else if (item.state == PointState.RightOuter)
{
if (!extension)
{
item.y = lastPoint.y;
}
else
{
var right = lastPoint;
var left = lastPoint.Left;
AdjustLeftRight(ref right, ref left, item);
}
}
}
y1arr = pointDict.Where(p => x1arr.Contains(p.Key)).Select(x => x.Value.y).ToArray();
return pointDict;
}
private static void AdjustLeftRight(ref Point right, ref Point left, Point item)
{
while (right.state != PointState.Inner)
{
right = right.Right;
}
while (left.state != PointState.Inner)
{
left = left.Left;
}
double k = (right.y - left.y) / (right.x - left.x);//斜率
item.y = left.y + k * (item.x - left.x);
}
}
}