示例#1
0
        /// <summary>
        /// 指定された頂点列の指定範囲にベジェ曲線をフィットさせる
        /// </summary>
        /// <param name="d">フィット元頂点列</param>
        /// <param name="first"><see cref="d"/>内の範囲開始インデックス</param>
        /// <param name="last"><see cref="d"/>内の範囲終了インデックス</param>
        /// <param name="tHat1">指定範囲開始点の長さ1の順方向ベクトル</param>
        /// <param name="tHat2">指定範囲終了点の長さ1の逆方向ベクトル</param>
        /// <param name="error">フィット時許容誤差の二乗</param>
        /// <param name="result">ここにベジェ曲線列が追加される</param>
        static void FitCubic(vector[] d, int first, int last, vector tHat1, vector tHat2, element error, List <cubicbezier> result)
        {
            cubicbezier bezCurve;                /*Control points of fitted Bezier curve*/
            var         nPts = last - first + 1; /*  Number of points in subset  */

            /*  Use heuristic if region only has two points in it */
            if (nPts == 2)
            {
                bezCurve    = new cubicbezier();
                bezCurve.P0 = d[first];
                bezCurve.P3 = d[last];

                var dist = (d[last] - d[first]).Length / 3;
                bezCurve.P1 = bezCurve.P0 + tHat1.Relength(dist);
                bezCurve.P2 = bezCurve.P3 + tHat2.Relength(dist);
                result.Add(bezCurve);
                return;
            }

            /*  Parameterize points, and attempt to fit curve */
            var u = ChordLengthParameterize(d, first, last);

            bezCurve = GenerateBezier(d, first, last, u, tHat1, tHat2);

            /*  Find max deviation of points to fitted curve */
            int splitPoint;             /*  Point to split point set at	 */
            var maxError = ComputeMaxError(d, first, last, bezCurve, u, out splitPoint);

            if (maxError < error)
            {
                result.Add(bezCurve);
                return;
            }


            /*  If error not too large, try some reparameterization  */
            /*  and iteration */
            var iterationError = error * error;             /*Error below which you try iterating  */

            if (maxError < iterationError)
            {
                var maxIterations = 4;                 /*  Max times to try iterating  */
                for (var i = 0; i < maxIterations; i++)
                {
                    var uPrime = Reparameterize(d, first, last, u, bezCurve);
                    bezCurve = GenerateBezier(d, first, last, uPrime, tHat1, tHat2);
                    maxError = ComputeMaxError(d, first, last, bezCurve, uPrime, out splitPoint);
                    if (maxError < error)
                    {
                        result.Add(bezCurve);
                        return;
                    }
                    u = uPrime;
                }
            }

            /* Fitting failed -- split at max error point and fit recursively */
            var tHatCenter = ((d[splitPoint - 1] - d[splitPoint + 1]) * (element)0.5).Normalize();

            FitCubic(d, first, splitPoint, tHat1, tHatCenter, error, result);

            tHatCenter = -tHatCenter;

            FitCubic(d, splitPoint, last, tHatCenter, tHat2, error, result);
        }