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);
 }
예제 #4
0
 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);
        }