namespace IStation.Curve
|
{
|
//修正曲线
|
public static class AmendCurveHelper
|
{
|
/// <summary>
|
/// 根据曲线中一个点,修改曲线,按比例调整(0点不会变,在newPt.X变化最大,大于newPt.X的点 和newPt一样变化
|
/// </summary>
|
/// <param name="originCurvePoints"></param>
|
/// <param name="newPt">在newPt.X</param>
|
/// <returns></returns>
|
public static List<CurvePoint> ByOnePointY1(List<CurvePoint> originCurvePoints, CurvePoint newPt)
|
{
|
if (originCurvePoints == null)
|
return null;
|
|
List<CurvePoint> newCurve = new List<CurvePoint>();
|
|
//计算差距
|
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<CurvePoint> newCurvePoints = new List<CurvePoint>();
|
List<CurvePoint> 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;
|
}
|
|
|
/// <summary>
|
///
|
/// </summary>
|
/// <param name="originCurve"></param>
|
/// <param name="newPt"></param>
|
/// <param name="ignoreDis">小于多少就不迭代了</param>
|
/// <param name="SplitPointNumber">分割点数</param>
|
/// <param name="iterationNum">迭代次数</param>
|
/// <returns></returns>
|
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<CurvePoint> ByTwoPointY1(List<CurvePoint> 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<CurvePoint>();
|
//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<CurvePoint> amendCurve = new List<CurvePoint>();
|
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<CurvePoint> ByThreePointY1(List<CurvePoint> 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<CurvePoint> ByZeroPointY(List<CurvePoint> originCurve, double fixPtX, double zeroPtY)
|
{
|
if (originCurve == null || originCurve.Count < 3)
|
return null;
|
|
List<CurvePoint> newCurve = new List<CurvePoint>();
|
|
|
//计算差距
|
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<CurvePoint> originCurvePoint = FitHelper.GetFitPoints(originCurve, 30);
|
return FitHelper.BuildCurveExpress(ByZeroPointY(originCurvePoint, fixPtX, zeroPtY));
|
}
|
|
}
|
}
|