namespace IStation.Curve
{
//修正曲线
public static class AmendCurveHelper
{
///
/// 根据曲线中一个点,修改曲线,按比例调整(0点不会变,在newPt.X变化最大,大于newPt.X的点 和newPt一样变化
///
///
/// 在newPt.X
///
public static List ByOnePointY1(List originCurvePoints, CurvePoint newPt)
{
if (originCurvePoints == null)
return null;
List newCurve = new List();
//计算差距
double baseX = newPt.X;
double baseDisY = originCurvePoints.GetFitPointY(baseX) - newPt.Y;
//
for (int i = 0; i < originCurvePoints.Count; i++)
{
double dis = 1;
if (originCurvePoints[i].X <= baseX)
{
dis = originCurvePoints[i].X * baseDisY / baseX;
}
else
{
dis = baseDisY;
}
newCurve.Add(new CurvePoint(originCurvePoints[i].X, originCurvePoints[i].Y - dis));
}
//
newCurve.Add(newPt);
return FitHelper.GetFitPoints(newCurve, eFitType.CubicCurve);
}
public static CurveExpress ByOnePointY1(CurveExpress originCurve, CurvePoint newPt)
{
return ByOnePointY1(originCurve, newPt, 30);
}
//insertPointNumber越多越精确
public static CurveExpress ByOnePointY1(CurveExpress originCurve, CurvePoint newPt, int insertPointNumber)
{
if (originCurve == null)
return null;
CurveExpress newCurveExpress = originCurve;
for (int i = 0; i < 3; i++)
{
newCurveExpress = ByOnePointY1内部(newCurveExpress, newPt, insertPointNumber);
}
return newCurveExpress;
}
private static CurveExpress ByOnePointY1内部(CurveExpress originCurve, CurvePoint newPt, int insertPointNumber)
{
if (originCurve == null)
return null;
List newCurvePoints = new List();
List originCurvePoints = FitHelper.GetFitPoints(originCurve, insertPointNumber);
//计算差距
double baseX = newPt.X;
double baseDisY = FitHelper.GetFitPointY(originCurve, baseX) - newPt.Y;
//
for (int i = 0; i < insertPointNumber; i++)
{
double dis = 1;
if (originCurvePoints[i].X <= baseX)
{
dis = originCurvePoints[i].X * baseDisY / baseX;
}
else
{
dis = baseDisY;
}
newCurvePoints.Add(new CurvePoint(originCurvePoints[i].X, originCurvePoints[i].Y - dis));
}
//
newCurvePoints.Add(newPt);
var newCurveExpress = FitHelper.BuildCurveExpress(newCurvePoints);
return newCurveExpress;
}
///
///
///
///
///
/// 小于多少就不迭代了
/// 分割点数
/// 迭代次数
///
public static CurveExpress ByOnePointY1(CurveExpress originCurve, CurvePoint newPt, double ignoreDis,
int SplitPointNumber = 100, int iterationNum = 6)
{
if (originCurve == null)
return null;
CurveExpress newCurve = new CurveExpress(originCurve);
for (int i = 0; i < iterationNum; i++)
{
var pointQE = FitHelper.GetFitPoints(newCurve, SplitPointNumber);
newCurve = FitHelper.BuildCurveExpress(AmendCurveHelper.ByOnePointY1(pointQE, newPt));
if (Math.Abs(FitHelper.GetFitPointY(newCurve, newPt.X) - newPt.Y) < ignoreDis)
{
return newCurve;
}
}
return newCurve;
}
//2点修补,新曲线通过minPt,maxPt
public static List ByTwoPointY1(List originCurve0, CurvePoint minPt, CurvePoint fixPt, CurvePoint maxPt)
{
if (originCurve0 == null || originCurve0.Count < 3)
return null;
//if (minPt.X > fixPt.X)
// return null;
//if (fixPt.X > maxPt.X)
// return null;
double x, y;
//先保证通过额定规定点
double ratedDis1 = originCurve0.GetFitPointY(fixPt.X) - fixPt.Y;
var originCurve1 = originCurve0;// new List();
//foreach (var pt in originCurve0)
//{
// newCurve.Add(new CurvePoint(pt.X, pt.Y - ratedDis1));
//}
double ratedPtDisY = originCurve1.GetFitPointY(fixPt.X) - fixPt.Y;
double minPtDisY = originCurve1.GetFitPointY(minPt.X) - minPt.Y;
double maxPtDisY = originCurve1.GetFitPointY(maxPt.X) - maxPt.Y;
List amendCurve = new List();
int num = 4;
double space = minPt.X / (num - 1);
for (int i = 0; i < num - 1; i++)
{
x = space * i;
y = originCurve1.GetFitPointY(x) - minPtDisY * i / (num - 1);
amendCurve.Add(new CurvePoint(x, y));
}
//插入小流量点
amendCurve.Add(minPt);
//小流量点和中间点插入2点
x = minPt.X + (fixPt.X - minPt.X) / 3;
y = originCurve1.GetFitPointY(x) - (ratedPtDisY + (ratedPtDisY - minPtDisY) / 3);
amendCurve.Add(new CurvePoint(x, y));
x = minPt.X + (fixPt.X - minPt.X) * 2 / 3;
y = originCurve1.GetFitPointY(x) - (ratedPtDisY + (ratedPtDisY - minPtDisY) * 2 / 3);
amendCurve.Add(new CurvePoint(x, y));
//插入额定点
amendCurve.Add(fixPt);
//中间插入2点
x = fixPt.X + (maxPt.X - fixPt.X) / 3;
y = originCurve1.GetFitPointY(x) - (maxPtDisY + (maxPtDisY - ratedPtDisY) / 3);
amendCurve.Add(new CurvePoint(x, y));
x = minPt.X + (fixPt.X - minPt.X) * 2 / 3;
y = originCurve1.GetFitPointY(x) - (maxPtDisY + (maxPtDisY - ratedPtDisY) * 2 / 3);
amendCurve.Add(new CurvePoint(x, y));
//插入大流量点
amendCurve.Add(maxPt);
//插入最后一个点
if (maxPt.X < originCurve1.Last().X * 0.98)
{
amendCurve.Add(new CurvePoint(originCurve1.Last().X, originCurve1.Last().Y - maxPtDisY));
}
return FitHelper.GetFitPoints(amendCurve);
}
public static List ByThreePointY1(List originCurve0, CurvePoint minPt, CurvePoint ratedPt, CurvePoint maxPt, int splitPointNum = 13)
{
if (originCurve0 == null || originCurve0.Count < 3)
return null;
if (minPt.X > ratedPt.X)
return null;
if (ratedPt.X > maxPt.X)
return null;
var originCurve1 = originCurve0.GetFitPoints(eFitType.CubicCurve, splitPointNum);
int indexMinDis = 0;
double minDis = minPt.X;
for (int i = 0; i < originCurve1.Count; i++)
{
var pt = originCurve1[i];
if (Math.Abs(pt.X - minPt.X) < minDis)
{
minDis = Math.Abs(pt.X - minPt.X);
indexMinDis = i;
}
}
originCurve1[indexMinDis].X = minPt.X;
originCurve1[indexMinDis].Y = minPt.Y;
indexMinDis = 0;
minDis = ratedPt.X;
for (int i = 0; i < originCurve1.Count; i++)
{
var pt = originCurve1[i];
if (Math.Abs(pt.X - ratedPt.X) < minDis)
{
minDis = Math.Abs(pt.X - minPt.X);
indexMinDis = i;
}
}
originCurve1[indexMinDis].X = ratedPt.X;
originCurve1[indexMinDis].Y = ratedPt.Y;
indexMinDis = 0;
minDis = maxPt.X;
for (int i = 0; i < originCurve1.Count; i++)
{
var pt = originCurve1[i];
if (Math.Abs(pt.X - maxPt.X) < minDis)
{
minDis = Math.Abs(pt.X - minPt.X);
indexMinDis = i;
}
}
originCurve1[indexMinDis].X = maxPt.X;
originCurve1[indexMinDis].Y = maxPt.Y;
// FitHelper theCurveFit = new FitHelper();
// theCurveFit.FitPointNum = originCurve.Count;
return FitHelper.GetFitPoints(originCurve1);
}
//修改曲线0点位置的值,曲线值会根据比例逐渐变化,直到fixPtX,不再变化
public static List ByZeroPointY(List originCurve, double fixPtX, double zeroPtY)
{
if (originCurve == null || originCurve.Count < 3)
return null;
List newCurve = new List();
//计算差距
double zeroDis = originCurve.First().Y - zeroPtY;
//
for (int i = 0; i < originCurve.Count; i++)
{
double dis = 0;
if (originCurve[i].X <= fixPtX)
{
dis = zeroDis * (1 - originCurve[i].X / fixPtX);
}
else
{
dis = 0;
}
newCurve.Add(new CurvePoint(originCurve[i].X, originCurve[i].Y - dis));
}
//
return newCurve.GetFitPoints(eFitType.CubicCurve, originCurve.Count);
}
public static CurveExpress ByZeroPointY(CurveExpress originCurve, double fixPtX, double zeroPtY)
{
if (originCurve == null)
return null;
List originCurvePoint = FitHelper.GetFitPoints(originCurve, 30);
return FitHelper.BuildCurveExpress(ByZeroPointY(originCurvePoint, fixPtX, zeroPtY));
}
}
}