public CubicSplineInterpolationCurve(ICurveParam curveParam) { if (canDrawCurve(curveParam)) { canDraw = true; this.curveParam = (CubicSplineInterpolationCurveParam)curveParam; } }
protected PiecewiseIntervalPolynomialCurveElement GenerateCurve(CubicSplineInterpolationCurveParam curveParam) { double[,] coefficientsArray = new double[curveParam.Count, curveParam.Count]; double[,] constantArray = new double[curveParam.Count, 1]; double uVal, dVal, val1, val2; for (int i = 1; i < curveParam.Count - 1; i++) { uVal = (curveParam[i].X.AccurateValue - curveParam[i - 1].X.AccurateValue) / (curveParam[i + 1].X.AccurateValue - curveParam[i - 1].X.AccurateValue); dVal = 6 / (curveParam[i + 1].X.AccurateValue - curveParam[i - 1].X.AccurateValue) * ( (curveParam[i + 1].Y.AccurateValue - curveParam[i].Y.AccurateValue) / (curveParam[i + 1].X.AccurateValue - curveParam[i].X.AccurateValue) - (curveParam[i].Y.AccurateValue - curveParam[i - 1].Y.AccurateValue) / (curveParam[i].X.AccurateValue - curveParam[i - 1].X.AccurateValue) ); coefficientsArray[i, i - 1] = uVal; coefficientsArray[i, i] = 2; coefficientsArray[i, i + 1] = 1 - uVal; constantArray[i, 0] = dVal; } switch (curveParam.BorderConditionType) { case CSIBorderConditionType.First_Order_Derivative: val1 = 6 / (curveParam[2].X.AccurateValue - curveParam[1].X.AccurateValue) * ( (curveParam[1].Y.AccurateValue - curveParam[0].Y.AccurateValue) / (curveParam[1].X.AccurateValue - curveParam[0].X.AccurateValue) - curveParam.LeftBorderValue.AccurateValue ); val2 = 6 / (curveParam[curveParam.Count - 1].X.AccurateValue - curveParam[curveParam.Count - 2].X.AccurateValue) * ( curveParam.RightBorderValue.AccurateValue - (curveParam[curveParam.Count - 1].Y.AccurateValue - curveParam[curveParam.Count - 2].Y.AccurateValue) / (curveParam[curveParam.Count - 1].X.AccurateValue - curveParam[curveParam.Count - 2].X.AccurateValue) ); coefficientsArray[0, 0] = 2; coefficientsArray[0, 1] = 1; coefficientsArray[curveParam.Count - 1, curveParam.Count - 2] = 1; coefficientsArray[curveParam.Count - 1, curveParam.Count - 1] = 2; constantArray[0, 0] = val1; constantArray[curveParam.Count - 1, 0] = val2; break; case CSIBorderConditionType.Second_Order_Derivative: coefficientsArray[0, 0] = 1; coefficientsArray[curveParam.Count - 1, curveParam.Count - 1] = 1; constantArray[0, 0] = curveParam.LeftBorderValue.AccurateValue; constantArray[curveParam.Count - 1, 0] = curveParam.RightBorderValue.AccurateValue; break; case CSIBorderConditionType.Cyclicity: val1 = curveParam[1].X.AccurateValue - curveParam[0].X.AccurateValue; coefficientsArray[0, 0] = val1; coefficientsArray[0, 1] = 2 * val1; val1 = curveParam[curveParam.Count - 1].X.AccurateValue - curveParam[curveParam.Count - 2].X.AccurateValue; coefficientsArray[0, curveParam.Count - 2] = val1; coefficientsArray[0, curveParam.Count - 1] = 2 * val1; coefficientsArray[curveParam.Count - 1, 0] = 1; coefficientsArray[curveParam.Count - 1, curveParam.Count - 1] = -1; val2 = 6 * ( (curveParam[1].Y.AccurateValue - curveParam[0].Y.AccurateValue) / (curveParam[1].X.AccurateValue - curveParam[0].X.AccurateValue) - (curveParam[curveParam.Count - 1].Y.AccurateValue - curveParam[curveParam.Count - 2].Y.AccurateValue) / (curveParam[curveParam.Count - 1].X.AccurateValue - curveParam[curveParam.Count - 2].X.AccurateValue) ); constantArray[0, 0] = val2; break; } LinearEquationSet equations = new LinearEquationSet(new Matrix(coefficientsArray), new Matrix(constantArray)); Matrix result = equations.AnswerMatrix; List<NormalIntervalPolynomialCurveElement> curves = new List<NormalIntervalPolynomialCurveElement>(); List<DoubleExtension> cutPoints = new List<DoubleExtension>(); cutPoints.Add(curveParam[0].X); for (int i = 1; i < curveParam.Count; i++) { curves.Add(new NormalIntervalPolynomialCurveElement(result[i - 1, 0], result[i, 0], curveParam[i - 1], curveParam[i])); cutPoints.Add(curveParam[i].X); } return new PiecewiseIntervalPolynomialCurveElement(curves, cutPoints); }
public CubicSplineInterpolationInterpolatedData(CubicSplineInterpolationCurveParam curveParam) { this.curveParam = curveParam; this.curve = GenerateCurve(curveParam); }
public void DrawCSICurve(string curveName, int borderConditionType, string leftVal, string rightVal) { BaseDataPointList pointList = this.basePoints; double left = 0, right = 0; if (borderConditionType < 3) { if (!Double.TryParse(leftVal, out left) || !Double.TryParse(rightVal, out right)) { throw new ArgumentException("The left or right border can't be recognized."); } } CubicSplineInterpolationCurveParam curveParam = new CubicSplineInterpolationCurveParam(pointList.SortedPointList, (CSIBorderConditionType)borderConditionType, new DoubleExtension(left), new DoubleExtension(right)); CubicSplineInterpolationCurve curve = new CubicSplineInterpolationCurve(curveParam); DrawLines(curveName, curve.sampleCurvePoints()); }
/// <summary> /// /// </summary> /// <param name="points">型值点</param> /// <param name="curveType">边界条件类型</param> /// <param name="val1"></param> /// <param name="val2"></param> /// <param name="val3"></param> /// <param name="val4"></param> public ParametricCubicSplineInterpolationCurveParam(List<DataPoint> points, PCSIBorderConditionType curveType, DoubleExtension val1, DoubleExtension val2, DoubleExtension val3, DoubleExtension val4) { DoubleExtension subValLeftX = DoubleExtension.ZERO, subValRightX = DoubleExtension.ZERO, subValLeftY = DoubleExtension.ZERO, subValRightY = DoubleExtension.ZERO; CSIBorderConditionType subType = CSIBorderConditionType.First_Order_Derivative; List<DataPoint> xPointList = new List<DataPoint>(); List<DataPoint> yPointList = new List<DataPoint>(); if (points.Count < 2) throw new ArgumentException("At least two points are needed for PCSI Curve drawing."); pointList = new NormalCurvePointList(points); xPointList.Add(new DataPoint(DoubleExtension.ZERO, points[0].X)); yPointList.Add(new DataPoint(DoubleExtension.ZERO, points[0].Y)); DoubleExtension accumulatedChordLength = DoubleExtension.ZERO; List<DoubleExtension> cutPoints = new List<DoubleExtension>(); cutPoints.Add(accumulatedChordLength); for (int i = 1; i < points.Count; i++) { accumulatedChordLength += DataPoint.CalculateDistance(points[i - 1], points[i]); cutPoints.Add(accumulatedChordLength); xPointList.Add(new DataPoint(accumulatedChordLength, points[i].X)); yPointList.Add(new DataPoint(accumulatedChordLength, points[i].Y)); } this.interval = new PiecewiseDataInterval(cutPoints); switch (curveType) { case PCSIBorderConditionType.First_Order_Derivative: subType = CSIBorderConditionType.First_Order_Derivative; DoubleExtension arcLeft1 = new DoubleExtension(Math.Atan(val1.AccurateValue)); DoubleExtension arcRight1 = new DoubleExtension(Math.Atan(val2.AccurateValue)); subValLeftX = new DoubleExtension(Math.Cos(arcLeft1.AccurateValue)); subValLeftY = new DoubleExtension(Math.Sin(arcLeft1.AccurateValue)); subValRightX = new DoubleExtension(Math.Cos(arcRight1.AccurateValue)); subValRightY = new DoubleExtension(Math.Sin(arcRight1.AccurateValue)); //DataVector referenceArcLeft1 = new DataVector(points[0], points[1]); //DataVector referenceArcRight1 = new DataVector(points[points.Count - 2], points[points.Count - 1]); //bool flagLeft = referenceArcLeft.GetTheFlagForCloserArc(arcLeft); //bool flagRight = referenceArcRight.GetTheFlagForCloserArc(arcRight); //if (flagLeft) //{ // subValLeftX = new DoubleExtension(Math.Cos(arcLeft.AccurateValue)); // subValLeftY = new DoubleExtension(Math.Sin(arcLeft.AccurateValue)); //} //else //{ // subValLeftX = new DoubleExtension(0 - Math.Cos(arcLeft.AccurateValue));; // subValLeftY = new DoubleExtension(0 - Math.Sin(arcLeft.AccurateValue)); //} //if (flagRight) //{ // subValRightX = new DoubleExtension(Math.Cos(arcRight.AccurateValue)); // subValRightY = new DoubleExtension(Math.Sin(arcRight.AccurateValue)); //} //else //{ // subValRightX = new DoubleExtension(Math.Cos(0 - arcRight.AccurateValue)); // subValRightY = new DoubleExtension(Math.Sin(0 - arcRight.AccurateValue)); //} break; case PCSIBorderConditionType.Zero_Curvature: subType = CSIBorderConditionType.Second_Order_Derivative; break; case PCSIBorderConditionType.Centre_of_Curvature: if (val1 == points[0].X && val3 == points[0].Y) { throw new ArgumentException("The center of the left border's curvature is the same as the left border point."); } if (val2 == points[points.Count - 1].X && val4 == points[points.Count - 1].Y) { throw new ArgumentException("The center of the right border's curvature is the same as the right border point."); } // // Second_Order_Derivative // //subType = CSIBorderConditionType.Second_Order_Derivative; //DoubleExtension denominator1 = new DoubleExtension(Math.Pow(val1.AccurateValue - points[0].X.AccurateValue, 2) + Math.Pow(val3.AccurateValue - points[0].Y.AccurateValue, 2)); //DoubleExtension denominator2 = new DoubleExtension(Math.Pow(val2.AccurateValue - points[points.Count - 1].X.AccurateValue, 2) + Math.Pow(val4.AccurateValue - points[points.Count - 1].Y.AccurateValue, 2)); //subValLeftX = (val1 - points[0].X) / denominator1; //subValLeftY = (val3 - points[0].Y) / denominator1; //subValRightX = (val2 - points[points.Count - 1].X) / denominator2; //subValRightY = (val4 - points[points.Count - 1].Y) / denominator2; // // First_Order_Derivative // subType = CSIBorderConditionType.First_Order_Derivative; DoubleExtension arcLeft2 = new DoubleExtension(Math.Atan2(val3.AccurateValue - points[0].Y.AccurateValue, val1.AccurateValue - points[0].X.AccurateValue) + Math.PI / 2.0); DoubleExtension arcRight2 = new DoubleExtension(Math.Atan2(val4.AccurateValue - points[points.Count - 1].Y.AccurateValue, val2.AccurateValue - points[points.Count - 1].X.AccurateValue) + Math.PI / 2.0); subValLeftX = new DoubleExtension(Math.Cos(arcLeft2.AccurateValue)); subValLeftY = new DoubleExtension(Math.Sin(arcLeft2.AccurateValue)); subValRightX = new DoubleExtension(Math.Cos(arcRight2.AccurateValue)); subValRightY = new DoubleExtension(Math.Sin(arcRight2.AccurateValue)); break; } xList = new CubicSplineInterpolationCurveParam(xPointList, subType, subValLeftX, subValRightX); yList = new CubicSplineInterpolationCurveParam(yPointList, subType, subValLeftY, subValRightY); }