예제 #1
0
        // 가까운 점을 제거하고 곡선이 아닌 라인상 거리를 재서 점을 없앨지 판단하는 로직
        // O(n)으로 처리하기 위해 복잡한 계산을 피하고 그 대신 결과물이 완벽하지 않을 때도 있다.
        private int IsNear(DrawablePoint p1, DrawablePoint p2, DrawablePoint p3, float tp, float tl)
        {
            float l12 = p1.GetDistance(p2);
            float l13 = p1.GetDistance(p3);
            float l23 = p2.GetDistance(p3);

            if (l12 < tp)
            {
                return(2);
            }

            if (l13 < tp)
            {
                return(3);
            }

            if (l23 < tp)
            {
                return(2);
            }

            float prj = ((p3.X - p1.X) * (p2.X - p1.X) + (p3.Y - p1.Y) * (p2.Y - p1.Y)) / l12;
            float d   = 0;

            if (prj < 0)
            {
                d = p1.GetDistance(p3);
                if (d < tp)
                {
                    return(1); // remove p1
                }
            }
            else if (prj > l12)
            {
                d = p2.GetDistance(p3);
                if (d < tp)
                {
                    return(2); // remove p2
                }
            }
            else
            {
                float area = Math.Abs((p1.X - p3.X) * (p2.Y - p3.Y) - (p1.Y - p3.Y) * (p2.X - p3.X));
                d = area / l12;
                if (p1.GetDistance(p3) < tl || p2.GetDistance(p3) < tl || d < tl / 2)
                {
                    return(3); // remove p3
                }
            }

            return(0);
        }
예제 #2
0
        private void GetControlPoint(List <DrawablePoint> p, int count, bool closePath, float factor, InterpolationType type = InterpolationType.Catmullrom)
        {
            DrawablePoint p0 = new DrawablePoint();   // prev point
            DrawablePoint p1 = new DrawablePoint();   // current point
            DrawablePoint p2 = new DrawablePoint();   // next point

            for (int i = 0; i < count; i++)
            {
                p1.Set(p[i]);

                if (i == 0)
                {
                    if (closePath)
                    {
                        p0.Set(p[count - 1]);
                    }
                    else
                    {
                        p0.Set(p1);
                    }
                }
                else
                {
                    p0.Set(p[i - 1]);
                }

                if (i == count - 1)
                {
                    if (closePath)
                    {
                        p2.Set(p[0]);
                    }
                    else
                    {
                        p2.Set(p1);
                    }
                }
                else
                {
                    p2.Set(p[i + 1]);
                }

                float d1 = p0.GetDistance(p1);
                float d2 = p1.GetDistance(p2);

                if (type == InterpolationType.Catmullrom)
                {
                    float d1_a  = (float)Math.Pow(d1, factor); // factor 기본 값 : 0.5
                    float d1_2a = d1_a * d1_a;
                    float d2_a  = (float)Math.Pow(d2, factor);
                    float d2_2a = d2_a * d2_a;

                    if (i != 0 || closePath)
                    {
                        float A = 2 * d2_2a + 3 * d2_a * d1_a + d1_2a;
                        float N = 3 * d2_a * (d2_a + d1_a);

                        if (N != 0)
                        {
                            p[i].SetIn((d2_2a * p0.X + A * p1.X - d1_2a * p2.X) / N, (d2_2a * p0.Y + A * p1.Y - d1_2a * p2.Y) / N);
                        }
                        else
                        {
                            p[i].SetIn(p1.X, p1.Y);
                        }
                    }
                    else
                    {
                        p[i].SetIn(p1.X, p1.Y);
                    }

                    if (i != count - 1 || closePath)
                    {
                        float A = 2 * d1_2a + 3 * d1_a * d2_a + d2_2a;
                        float N = 3 * d1_a * (d1_a + d2_a);

                        if (N != 0)
                        {
                            p[i].SetOut((d1_2a * p2.X + A * p1.X - d2_2a * p0.X) / N, (d1_2a * p2.Y + A * p1.Y - d2_2a * p0.Y) / N);
                        }
                        else
                        {
                            p[i].SetOut(p1.X, p1.Y);
                        }
                    }
                    else
                    {
                        p[i].SetOut(p1.X, p1.Y);
                    }
                }
                else
                {
                    float vx = p0.X - p2.X;
                    float vy = p0.Y - p2.Y;
                    float t  = factor; // factor 기본값 : 0.4
                    float k  = t * d1 / (d1 + d2);

                    if (i != 0 || closePath)
                    {
                        p[i].SetIn(p1.X + vx * k, p1.Y + vy * k);
                    }
                    else
                    {
                        p[i].SetIn(p1.X, p1.Y);
                    }

                    if (i != count - 1 || closePath)
                    {
                        p[i].SetOut(p1.X + vx * (k - t), p1.Y + vy * (k - t));
                    }
                    else
                    {
                        p[i].SetOut(p1.X, p1.Y);
                    }
                }
            }
        }