private void Run() { if (pList.Count > 0) { /* 初始化 */ v.pList.Clear(); v.vList.Clear(); record.Clear(); stepIndex = 0; ClearPaint(); /* 初始畫布建置 */ ClearPaint(); foreach (PointF i in pList) { DrawPointF(i, Color.DarkRed); } /* 排序點 */ pList = MathEx.SortPointF(pList); /* 畫 Convex Hull */ DrawConvexHull(MathEx.GetConvexHull(pList)); /* 畫 Voronoi Diagram */ v = VoronoiMultiPoint(pList); DrawVoronoiDiagram(v.vList, Color.DarkGreen); } }
private void SaveFile() { //if(v.vList != null && v.vList.Count > 0) //{ /* 依 lexical order 排序 */ v.pList = MathEx.SortPointF(v.pList); v.vList = MathEx.SortEdge(v.vList); save_fdg.Title = "Save"; if (save_fdg.ShowDialog() == DialogResult.OK) { StreamWriter sw = new StreamWriter(save_fdg.FileName); for (int i = 0; i < v.pList.Count; i++) { sw.WriteLine("P " + v.pList[i].X + " " + v.pList[i].Y); } for (int i = 0; i < v.vList.Count; i++) { sw.WriteLine("E " + Convert.ToInt32(v.vList[i].A.X) + " " + Convert.ToInt32(v.vList[i].A.Y) + " " + Convert.ToInt32(v.vList[i].B.X) + " " + Convert.ToInt32(v.vList[i].B.Y)); } sw.Close(); } //} //else //{ // MessageBox.Show("Please draw some diagram!", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning); //} }
public Voronoi VoronoiThreePoint(PointF A, PointF B, PointF C) { Voronoi v = new Voronoi(); PointF triEx; PointF mid; v.pList.Add(A); v.pList.Add(B); v.pList.Add(C); /* 三點共線 */ if (MathEx.isCollinear(v.pList[0], v.pList[1], v.pList[2])) { /* 將點排序 */ v.pList = MathEx.SortPointF(v.pList); /* 將邊無限延伸的做法 */ mid = MathEx.GetMidPointF(v.pList[0], v.pList[1]); v.vList.Add(new Edge(mid.Add(MathEx.GetNormalVector(v.pList[0], v.pList[1]).Multi(600)), mid.Add(MathEx.GetNormalVector(v.pList[1], v.pList[0]).Multi(600)), v.pList[0], v.pList[1])); mid = MathEx.GetMidPointF(v.pList[1], v.pList[2]); v.vList.Add(new Edge(mid.Add(MathEx.GetNormalVector(v.pList[1], v.pList[2]).Multi(600)), mid.Add(MathEx.GetNormalVector(v.pList[2], v.pList[1]).Multi(600)), v.pList[1], v.pList[2])); /* 將邊畫到邊界的做法 * mid = MathEx.GetMidPointF(v.pList[0], v.pList[1]); * v.vList.Add(new Edge(GetSidePointF(mid, mid.Add(MathEx.GetNormalVector(v.pList[1], v.pList[0]))), GetSidePointF(mid, mid.Add(MathEx.GetNormalVector(v.pList[0], v.pList[1]))))); * mid = MathEx.GetMidPointF(v.pList[1], v.pList[2]); * v.vList.Add(new Edge(GetSidePointF(mid, mid.Add(MathEx.GetNormalVector(v.pList[2], v.pList[1]))), GetSidePointF(mid, mid.Add(MathEx.GetNormalVector(v.pList[1], v.pList[2]))))); */ } else { /* 計算外心 */ triEx = MathEx.GetTriangleExcenterPointF(A, B, C); /* 將點依逆時針方向排序 */ v.pList = MathEx.SortVector(v.pList); for (int i = 0; i < v.pList.Count; i++) { mid = MathEx.GetMidPointF(v.pList[i], v.pList[(i + 1) % 3]); /* 將邊無限延伸的做法 */ v.vList.Add(new Edge(triEx, mid.Add(MathEx.GetNormalVector(v.pList[i], v.pList[(i + 1) % 3]).Multi(600)), v.pList[i], v.pList[(i + 1) % 3])); /* 將邊畫到邊界的做法 * v.vList.Add(new Edge(triEx, GetSidePointF(mid, mid.Add(MathEx.GetNormalVector(v.pList[i], v.pList[(i + 1) % 3]))))); */ } } return(v); }
/// <summary> /// 取得上下切線 /// </summary> /// <param name="pListL">左半部的點集合</param> /// <param name="pListR">左半部的點集合</param> /// <returns>上下切線</returns> public List <Edge> GetTangent(List <PointF> pListL, List <PointF> pListR) { List <Edge> tangent = new List <Edge>(); List <PointF> pList = new List <PointF>(); List <PointF> chList; pList.AddRange(pListL); pList.AddRange(pListR); pList = MathEx.SortPointF(pList); chList = MathEx.GetConvexHull(pList); for (int i = 0; i < chList.Count; i++) { if ((pListL.Contains(chList[i]) && pListR.Contains(chList[(i + 1) % chList.Count])) || (pListR.Contains(chList[i]) && pListL.Contains(chList[(i + 1) % chList.Count]))) { tangent.Add(new Edge(chList[i], chList[(i + 1) % chList.Count])); } } record.Add(new Record(chList, tangent, CONVEX_HULL, true)); return(tangent); }
private void Step() { if (record.Count <= 0 || stepIndex > record.Count - 1) { /* 初始化 */ v.pList.Clear(); v.vList.Clear(); record.Clear(); stepIndex = 0; /* 排序點 */ pList = MathEx.SortPointF(pList); /* 畫 Voronoi Diagram */ v = VoronoiMultiPoint(pList); } /* 初始畫布建置 */ ClearPaint(); foreach (PointF i in pList) { DrawPointF(i, Color.DarkRed); } /* 隱藏特定紀錄 */ if (record[stepIndex].type == VORONOI) { if (record[stepIndex].clear) { record[stepIndex - 2].enable = false; int count = 0; for (int i = stepIndex - 1; i >= 0 && count < 2; i--) { if ((record[i].type == MERGE || record[i].type == VORONOI) && record[i].enable == true) { record[i].enable = false; count++; } } } } else if (record[stepIndex].type == CONVEX_HULL) { if (record[stepIndex].clear) { record[stepIndex - 1].enable = false; record[stepIndex - 2].enable = false; } } else if (record[stepIndex].type == MERGE) { if (record[stepIndex].clear) { record[stepIndex - 1].enable = false; record[stepIndex - 2].enable = false; } } /* 畫紀錄 */ for (int i = 0; i <= stepIndex; i++) { if (record[i].enable) { DrawRecord(record[i]); } else { continue; } } /* 重置步驟數 */ if (stepIndex < record.Count) { stepIndex++; } else { stepIndex = 0; } }