Пример #1
0
        /// <summary>
        /// 単調増加ベジエの場合にのみ使用可。X座標からY座標を得る
        /// </summary>
        /// <param name="X"></param>
        /// <returns></returns>
        public float GetYFromX(float X)
        {
            float  ret = 0;
            PointF p1 = BCPS[0].Second, p2 = BCPS[0].Second, p3 = BCPS[1].Second, p4 = BCPS[1].Second;

            if (BCPS[0].ValidThird)
            {
                p2 = BCPS[0].Third;
            }
            if (BCPS[1].ValidFirst)
            {
                p3 = BCPS[1].First;
            }
            float s = 0, e = 1;

            for (int i = 0; i < 20; i++)
            {
                float m  = (s + e) / 2;
                var   bp = BezierCaliculate.GetBezeirPoint(ref p1, ref p2, ref p3, ref p4, ref m);
                if (bp.X < X)
                {
                    e = m;
                }
                else
                {
                    s = m;
                }
                ret = bp.Y;
            }
            return(ret);
        }
Пример #2
0
        /// <summary>
        /// 指定された割合分割されたベジエを得るメソッド
        /// </summary>
        /// <param name="num">最大、最小はMaxRatio,MinRatioから</param>
        /// <param name="bcps1">分割1</param>
        /// <param name="bcps2">分割2</param>
        public void GetDevidedBeziers(float num, out BezierControlPoint[] bcps1, out BezierControlPoint[] bcps2)
        {
            bcps1 = null;
            bcps2 = null;
            if (bcps == null || bcps.Length == 0)
            {
                return;
            }
            if (num < MinRatio)
            {
                num = MinRatio;
            }
            else if (num > MaxRatio)
            {
                num = MaxRatio;
            }
            //find where
            float sumnum = 0;
            float rest = 0;
            BezierControlPoint previous = null, next = null;
            int foundindex = -1;

            for (int i = 0; i < bcps.Length; i++)
            {
                BezierControlPoint bcp = bcps[i];
                if (previous != null)
                {
                    float ratio = eachlength[i - 1] / length * MaxRatio;
                    if (sumnum + ratio >= num || (sumnum + ratio) >= MaxRatio - 0.0009765625)
                    {
                        next       = bcp;
                        rest       = num - sumnum;
                        foundindex = i;
                        break;
                    }
                    sumnum += ratio;
                }
                previous = bcp;
            }
            if (foundindex != -1)
            {
                float targetratio = 1 - rest / MaxRatio * length / eachlength[foundindex - 1];
                BezierCaliculate.GetDevidedBeziers(previous, next, targetratio, out BezierControlPoint bcp1, out BezierControlPoint bcp2, out BezierControlPoint bcp3);
                bcps1 = new BezierControlPoint[foundindex + 1];
                bcps2 = new BezierControlPoint[BCPS.Length - foundindex + 1];
                for (int i = 0; i < foundindex - 1; i++)
                {
                    bcps1[i] = BCPS[i].Clone();
                }
                bcps1[foundindex - 1] = bcp1;
                bcps1[foundindex]     = bcp2.Clone();
                bcps2[0] = bcp2;
                bcps2[1] = bcp3;
                for (int i = foundindex + 1; i < BCPS.Length; i++)
                {
                    bcps2[i - foundindex + 1] = BCPS[i].Clone();
                }
                return;
            }
        }
Пример #3
0
        /// <summary>
        /// ベジエ曲線状に乗っているか調べる
        /// </summary>
        /// <param name="p1">頂点1</param>
        /// <param name="p2">頂点2</param>
        /// <param name="p3">頂点3</param>
        /// <param name="p4">頂点4</param>
        /// <param name="target">調べる対象</param>
        /// <param name="outt">乗っていた時の割合(0~1)</param>
        /// <returns></returns>
        public static bool OnBezeier(PointF p1, PointF p2, PointF p3, PointF p4, PointF target, out float outt)
        {
            PointF lastbezierpoint, bezierpoint;

            lastbezierpoint = p1;
            outt            = -1;
            float best  = float.MaxValue;
            var   count = BezierCaliculate.AboutBezeirCount(ref p1, ref p2, ref p3, ref p4);

            for (int i = count; i >= 0; i--)
            {
                float t = (float)i / count;
                bezierpoint = BezierCaliculate.GetBezeirPoint(ref p1, ref p2, ref p3, ref p4, ref t);
                var temp = GetLength(new PointF(bezierpoint.X - target.X, bezierpoint.Y - target.Y));
                if (temp < best)
                {
                    best = temp;
                    outt = t;
                }
                lastbezierpoint = bezierpoint;
            }
            if (best <= 2)
            {
                return(true);
            }
            return(false);
        }
Пример #4
0
        /// <summary>
        /// 4頂点からベジエ曲線上の位置を得る
        /// </summary>
        /// <param name="p1">頂点1</param>
        /// <param name="p2">頂点2</param>
        /// <param name="p3">頂点3</param>
        /// <param name="p4">頂点4</param>
        /// <returns></returns>
        public static IEnumerable <PointF> GetPoints(PointF p1, PointF p2, PointF p3, PointF p4)
        {
            var count = BezierCaliculate.AboutBezeirCount(ref p1, ref p2, ref p3, ref p4);

            for (int i = count; i >= 0; i--)
            {
                float t = (float)i / count;
                yield return(BezierCaliculate.GetBezeirPoint(ref p1, ref p2, ref p3, ref p4, ref t));
            }
        }
Пример #5
0
        private void Analyze()
        {
            eachlength = new float[bcps.Length - 1];
            BezierControlPoint previous = null;

            for (int i = 0; i < bcps.Length; i++)
            {
                BezierControlPoint bcp = bcps[i];
                if (previous != null)
                {
                    eachlength[i - 1] += BezierCaliculate.GetBezeierLength(previous, bcp);
                    length            += eachlength[i - 1];
                }
                previous = bcp;
            }
        }
Пример #6
0
        /// <summary>
        /// 連結ベジエから特定の割合の場所を得るメソッド
        /// </summary>
        /// <param name="num">最大、最小はMaxRatio,MinRatioから</param>
        /// <param name="direction">位置</param>
        /// <param name="pos">向き</param>
        /// <returns></returns>
        public void GetPoint(float num, out PointF pos, out PointF direction)
        {
            pos       = PointF.Empty;
            direction = new PointF(1, 0);
            if (bcps == null || bcps.Length == 0)
            {
                return;
            }
            if (num < MinRatio)
            {
                num = MinRatio;
            }
            else if (num > MaxRatio)
            {
                num = MaxRatio;
            }
            //find where
            float sumnum = 0;
            float rest = 0;
            BezierControlPoint previous = null, next = null;
            int foundindex = -1;

            for (int i = 0; i < bcps.Length; i++)
            {
                BezierControlPoint bcp = bcps[i];
                if (previous != null)
                {
                    float ratio = eachlength[i - 1] / length * MaxRatio;
                    if (sumnum + ratio >= num || (sumnum + ratio) >= MaxRatio - 0.0009765625)
                    {
                        next       = bcp;
                        rest       = num - sumnum;
                        foundindex = i;
                        break;
                    }
                    sumnum += ratio;
                }
                previous = bcp;
            }
            if (foundindex != -1)
            {
                float targetlength = length * rest / MaxRatio;
                BezierCaliculate.GetBezeirSplitPoint(previous, next, targetlength, out pos, out direction);
                return;
            }
        }
Пример #7
0
        private static float GetBezeierLength(PointF p1, PointF p2, PointF p3, PointF p4)
        {
            PointF lastbezierpoint, bezierpoint;

            lastbezierpoint = p1;
            float sum   = 0;
            var   count = BezierCaliculate.AboutBezeirCount(ref p1, ref p2, ref p3, ref p4);

            if (count == 0)
            {
                return(0);
            }
            for (int i = count; i >= 0; i--)
            {
                float t = (float)i / count;
                bezierpoint     = BezierCaliculate.GetBezeirPoint(ref p1, ref p2, ref p3, ref p4, ref t);
                sum            += GetLength(new PointF(bezierpoint.X - lastbezierpoint.X, bezierpoint.Y - lastbezierpoint.Y));
                lastbezierpoint = bezierpoint;
            }
            return(sum);
        }
Пример #8
0
        private static void GetBezeirSplitPoint(PointF p1, PointF p2, PointF p3, PointF p4, float length, out PointF pos, out PointF direction)
        {
            PointF lastbezierpoint, bezierpoint;

            lastbezierpoint = p1;
            pos             = p1;
            direction       = new PointF(1, 0);
            float sum   = 0;
            var   count = BezierCaliculate.AboutBezeirCount(ref p1, ref p2, ref p3, ref p4);

            for (int i = count; i >= 0; i--)
            {
                float t = (float)i / count;
                bezierpoint = BezierCaliculate.GetBezeirPoint(ref p1, ref p2, ref p3, ref p4, ref t);
                sum        += GetLength(new PointF(bezierpoint.X - lastbezierpoint.X, bezierpoint.Y - lastbezierpoint.Y));
                if (sum >= length)
                {
                    pos       = bezierpoint;
                    direction = GetNormalizePoint(new PointF(bezierpoint.X - lastbezierpoint.X, bezierpoint.Y - lastbezierpoint.Y));
                    if (direction.X == 0 && direction.Y == 0)
                    {
                        t = (float)(i - 1) / count;
                        lastbezierpoint = bezierpoint;
                        bezierpoint     = BezierCaliculate.GetBezeirPoint(ref p1, ref p2, ref p3, ref p4, ref t);
                        direction       = GetNormalizePoint(new PointF(bezierpoint.X - lastbezierpoint.X, bezierpoint.Y - lastbezierpoint.Y));
                    }
                    return;
                }
                lastbezierpoint = bezierpoint;
            }
            pos       = p4;
            direction = GetNormalizePoint(new PointF(p4.X - lastbezierpoint.X, p4.Y - lastbezierpoint.Y));
            if (direction.X == 0 && direction.Y == 0)
            {
                float t = (float)1 / count;
                bezierpoint = BezierCaliculate.GetBezeirPoint(ref p1, ref p2, ref p3, ref p4, ref t);
                direction   = GetNormalizePoint(new PointF(lastbezierpoint.X - bezierpoint.X, lastbezierpoint.Y - bezierpoint.Y));
            }
        }