// 가까운 점을 제거하고 곡선이 아닌 라인상 거리를 재서 점을 없앨지 판단하는 로직 // 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); }
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); } } } }