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)); } } }