Exemplo n.º 1
0
        public float GetDistance(DrawablePoint p)
        {
            float dx = p.X - X;
            float dy = p.Y - Y;

            return((float)Math.Sqrt(dx * dx + dy * dy));
        }
Exemplo n.º 2
0
        // 곡선에 추가 포인트를 넣는 함수
        // 세 점을 기준으로 각도가 t_angle보다 작으면 가운데 점의 좌우 t만큼의 지점에 추가로 Point를 넣는다.
        // 급격하게 선이 꺾일 때 두께가 이상하게 나오는 현상을 감소시킬 수 있다.
        private void GetSplitPoints(List <DrawablePoint> pts, float t, float t_angle)
        {
            int count = pts.Count;

            if (count < 3)
            {
                return;
            }

            float t2 = 1.0f - t;

            int i = 1;  // 첫번째 가운데 점

            while (i < pts.Count - 1)
            {
                float angle = GetAngle(pts[i - 1], pts[i], pts[i + 1]);

                if (angle < t_angle)
                {
                    {   // 앞쪽에 추가되는 컨트롤 포인트
                        DrawablePoint point12    = GetPoint12(pts[i - 1], t2);
                        DrawablePoint point34    = GetPoint34(pts[i], t2);
                        DrawablePoint splitPoint = GetSplitPoint(pts[i - 1], pts[i], t2);
                        float         d12        = splitPoint.GetDistance(pts[i - 1]);
                        float         d23        = splitPoint.GetDistance(pts[i]);
                        float         d123       = d12 + d23;
                        float         force      = pts[i - 1].Force + (pts[i].Force - pts[i - 1].Force) * (d12 / d123);

                        splitPoint.Force = force;

                        pts[i - 1].SetOut(point12.X, point12.Y);
                        pts.Insert(i, splitPoint);
                        pts[i + 1].SetIn(point34.X, point34.Y);
                    }

                    {   // 뒤쪽에 추가되는 컨트롤 포인트
                        DrawablePoint point12    = GetPoint12(pts[i + 1], t);
                        DrawablePoint point34    = GetPoint34(pts[i + 2], t);
                        DrawablePoint splitPoint = GetSplitPoint(pts[i + 1], pts[i + 2], t);
                        float         d12        = splitPoint.GetDistance(pts[i + 1]);
                        float         d23        = splitPoint.GetDistance(pts[i + 2]);
                        float         d123       = d12 + d23;
                        float         force      = pts[i + 1].Force + (pts[i + 2].Force - pts[i + 1].Force) * (d12 / d123);

                        splitPoint.Force = force;

                        pts[i + 1].SetOut(point12.X, point12.Y);
                        pts.Insert(i + 2, splitPoint);
                        pts[i + 3].SetIn(point34.X, point34.Y);
                    }
                    i += 2;
                }
                else
                {
                    i++;
                }
            }
        }
Exemplo n.º 3
0
        private DrawablePoint GetPoint34(DrawablePoint pts2, float t)
        {
            float x3 = pts2.InX;
            float y3 = pts2.InY;
            float x4 = pts2.X;
            float y4 = pts2.Y;

            float x34 = (x4 - x3) * t + x3;
            float y34 = (y4 - y3) * t + y3;

            return(new DrawablePoint(x34, y34));
        }
Exemplo n.º 4
0
        // 이하 splitPoints를 얻기 위한 private 함수
        private DrawablePoint GetPoint12(DrawablePoint pts1, float t)
        {
            float x1 = pts1.X;
            float y1 = pts1.Y;
            float x2 = pts1.OutX;
            float y2 = pts1.OutY;

            float x12 = (x2 - x1) * t + x1;
            float y12 = (y2 - y1) * t + y1;

            return(new DrawablePoint(x12, y12));
        }
Exemplo n.º 5
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);
        }
Exemplo n.º 6
0
        // 세 점의 사이 각을 구하는 함수
        // 최적화 필요
        private float GetAngle(DrawablePoint p1, DrawablePoint p2, DrawablePoint p3)
        {
            float a, b, c;
            float angle, temp;

            a = (float)Math.Sqrt(Math.Pow(p1.X - p3.X, 2) + Math.Pow(p1.Y - p3.Y, 2));
            b = (float)Math.Sqrt(Math.Pow(p1.X - p2.X, 2) + Math.Pow(p1.Y - p2.Y, 2));
            c = (float)Math.Sqrt(Math.Pow(p2.X - p3.X, 2) + Math.Pow(p2.Y - p3.Y, 2));

            temp = (float)(Math.Pow(b, 2) + Math.Pow(c, 2) - Math.Pow(a, 2)) / (2 * b * c);

            angle  = (float)Math.Acos(temp);
            angle *= (float)(180 / Math.PI);

            return(angle);
        }
Exemplo n.º 7
0
        private DrawablePoint GetSplitPoint(DrawablePoint pts1, DrawablePoint pts2, float t)
        {
            float x1 = pts1.X;
            float y1 = pts1.Y;
            float x2 = pts1.OutX;
            float y2 = pts1.OutY;
            float x3 = pts2.InX;
            float y3 = pts2.InY;
            float x4 = pts2.X;
            float y4 = pts2.Y;

            float x12 = (x2 - x1) * t + x1;
            float y12 = (y2 - y1) * t + y1;

            float x23 = (x3 - x2) * t + x2;
            float y23 = (y3 - y2) * t + y2;

            float x34 = (x4 - x3) * t + x3;
            float y34 = (y4 - y3) * t + y3;

            float x123 = (x23 - x12) * t + x12;
            float y123 = (y23 - y12) * t + y12;

            float x234 = (x34 - x23) * t + x23;
            float y234 = (y34 - y23) * t + y23;

            float x1234 = (x234 - x123) * t + x123;
            float y1234 = (y234 - y123) * t + y123;

            DrawablePoint splitPoint = new DrawablePoint(x1234, y1234);

            splitPoint.SetIn(x123, y123);
            splitPoint.SetOut(x234, y234);

            return(splitPoint);
        }
Exemplo n.º 8
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);
                    }
                }
            }
        }
Exemplo n.º 9
0
 public void Set(DrawablePoint p)
 {
     X     = p.X;
     Y     = p.Y;
     Force = p.Force;
 }
Exemplo n.º 10
0
 public DrawablePoint(DrawablePoint p, float scale) : this(p)
 {
     SetScale(scale);
 }
Exemplo n.º 11
0
 public DrawablePoint(DrawablePoint p)
 {
     X     = p.X;
     Y     = p.Y;
     Force = p.Force;
 }