public static Dot2 CreateRandomDot(Random rand, Dot2 dot, double Radius, int maxWidth, int maxHeight) { Dot2 returndot; //Dot2 nulls; double radius = Radius + Radius * 1 * (rand.NextDouble() - 0.5); //Vector top = new Vector(new Dot2(maxWidth,0)); //Vector left = new Vector(new Dot2(0,maxHeight)); //Vector buttom = new Vector(new Dot2(0,maxHeight),new Dot2(maxWidth,maxHeight)); //Vector right = new Vector(new Dot2(maxWidth,0),new Dot2(maxWidth,maxHeight)); Border border = new Border(new List <Dot2>() { new Dot2(0, 0), new Dot2(maxWidth, 0), new Dot2(maxWidth, maxHeight), new Dot2(0, maxHeight) }); double theta = (rand.NextDouble() - 0.5) * 2 * System.Math.PI; returndot = dot + new Dot2(radius * System.Math.Cos(theta), radius * System.Math.Sin(theta)); while (!Math.isInside(returndot, border) //isIntersect(new Vector(dot, returndot), top, out nulls) || isIntersect(new Vector(dot, returndot), left, out nulls) || isIntersect(new Vector(dot, returndot), buttom, out nulls) || isIntersect(new Vector(dot, returndot), right, out nulls) ) { radius = Radius + Radius * 1 * (rand.NextDouble() - 0.5); theta = (rand.NextDouble() - 0.5) * 2 * System.Math.PI; returndot = dot + new Dot2(radius * System.Math.Cos(theta), radius * System.Math.Sin(theta)); } return(returndot); }
/// <summary> /// 获取离边界最近的一条边(边可以不再边界上) /// </summary> /// <param name="origin"></param> /// <param name="border"></param> /// <returns></returns> public static Vector getNearestVector(Dot2 origin, Border border) { if (border.DotCount < 2) { return(null); } int j1 = 0, j2 = 1; double lengh1 = Math.Length(origin, border.get(j1)), lengh2 = Math.Length(origin, border.get(j2)), temp; if (lengh1 > lengh2) { lengh1 = lengh1 + lengh2; lengh2 = lengh1 - lengh2; lengh1 = lengh1 - lengh2; } for (int i = 1; i < border.DotCount; i++) { temp = Math.Length(origin, border.get(i)); if (temp <= lengh1) { lengh2 = lengh1; lengh1 = temp; j2 = j1; j1 = i; } else if (temp > lengh1 && temp <= lengh2) { lengh2 = temp; j2 = i; } } return(new Vector(border.get(j1), border.get(j2))); }
/// <summary> /// 判断点是否在边界内 /// </summary> /// <param name="dot"></param> /// <param name="border"></param> /// <returns></returns> public static bool isInside(Dot2 dot, Border border) { int num = 0; //double minx, maxx; for (int i = 0; i < border.DotCount - 1; i++) { if (dot.X <= (System.Math.Max(border.get(i).X, border.get(i + 1).X)) && (border.get(i).Y - dot.Y) * (border.get(i + 1).Y - dot.Y) < 0) { if (dot.X > System.Math.Min(border.get(i).X, border.get(i + 1).X)) { if ((border.get(i).X *border.get(i + 1).Y - border.get(i).Y *border.get(i + 1).X + dot.Y * (border.get(i + 1).X - border.get(i).X)) / (border.get(i + 1).Y - border.get(i).Y) > dot.X) { num++; } } else { num++; } } } if (num % 2 == 1) { return(true); } else { return(false); } }
public void putDot(Dot2 dot) { if (Dots.Contains(dot)) { return; } Dots.Add(dot); }
public void Insert(Dot2 dot, int index) { if (index == Dots.Count) { Add(dot); } else { Operate.Add(new Operate(Type.Insert, dot, index)); Dots.Insert(index, dot.toDotx()); } }
public void Insert(Dot2 dot, int index, DrawType type) { if (index == Dots.Count) { Operate.Add(new Operate(Type.Append, dot, index)); Dots.Add(dot.toDotx(type)); } else { Operate.Add(new Operate(Type.Insert, dot, index)); Dots.Insert(index, dot.toDotx(type)); } }
/// <summary> /// 随机产生一个无交叉的边界 /// </summary> /// <param name="number">3</param> public Border(int number, int maxWidth, int maxHeight, out List <Dot2> dotss, Draw.Draw draw) { dotss = new List <Dot2>(); bool isIntersect = false; Random rand = new Random(); Dot2 indot = null; Dot2 dot = Math.CreateRandomDot(rand, maxWidth, maxHeight); int i = 0; Dot2 tempdot; while (Dots.Count < number) { tempdot = Math.CreateRandomDot(rand, dot, 100, maxWidth, maxHeight); if (i <= 2) { Add(tempdot); dot = tempdot; i++; } else { for (int j = 0; j < i - 2; j++) { if (Math.isIntersect(new Vector(tempdot, get(i - 1)), new Vector(get(j), get(j + 1)), out indot)) { if (indot != null) { //draw.Lines(new List<Dot2>() { dot, Dots[i - 1], Dots[j], Dots[j + 1] }); dotss.Add(indot); } isIntersect = true; break; } } if (isIntersect == true) { isIntersect = false; continue; } else { Add(tempdot); dot = tempdot; i++; } } } }
/// <summary> /// 返回离点集最远的点 /// </summary> /// <param name="origin"></param> /// <param name="DotSet"></param> /// <returns></returns> public static Dot2 getFastestDot(Dot2 origin, List <Dot2> DotSet) { int j = 0; double lengh = 0, temp; for (int i = 0; i < DotSet.Count; i++) { temp = Math.Length(origin, DotSet[i]); if (temp > lengh) { lengh = temp; j = i; } } return(DotSet[j]); }
private void Reflesh_Click(object sender, RoutedEventArgs e) { Random rand = new Random(); Math.Dot2 dot = Test.Math.Math.CreateRandomDot(rand, (int)this.MineCanvas.Width - 10, (int)this.MineCanvas.Height - 10); this.MineCanvas.Children.Clear(); //draw.Dots(new List<Math.Dot2>() { dot }); border.put(dot); if (IsFill.IsChecked == true) { draw.Border(border); } else { draw.Lines(border); } //draw.Lines(border); //draw.Appear(border.fetchLog().dot); }
/// <summary> /// 返回离点集最近的点 /// </summary> /// <param name="origin"></param> /// <param name="DotSet"></param> /// <returns></returns> public static Dot2 getNearestDot(Dot2 origin, List <Dot2> DotSet) { if (DotSet.Count == 0) { return(null); } int j = 0; double lengh = Math.Length(origin, DotSet[j]), temp; for (int i = 1; i < DotSet.Count; i++) { temp = Math.Length(origin, DotSet[i]); if (temp < lengh) { lengh = temp; j = i; } } return(DotSet[j]); }
/// <summary> /// 将增加长度最小的点插入 /// </summary> /// <param name="origin"></param> /// <param name="border"></param> public static void putMinLengthDotToBorder(Dot2 origin, Border border) { double temp, lengh = double.MaxValue; if (border.DotCount <= 2) { border.Add(origin); return; } int j = 0; for (int i = 0; i < border.DotCount; i++) { temp = Math.Length(origin, border.get(i)) + Math.Length(origin, border.get(i + 1)) - border.getVecter(i).Length; if (temp < lengh) { lengh = temp; j = i; } } border.Insert(origin, j + 1, DrawType.Ignore); }
/// <summary> /// 计算三角形的面积 /// </summary> /// <param name="A"></param> /// <param name="B"></param> /// <param name="C"></param> /// <returns></returns> public static double Area(Dot2 A, Dot2 B, Dot2 C) { return(0.5 * System.Math.Abs(A.X * B.Y + B.X * C.Y + A.Y * C.X - A.X * C.Y - A.Y * B.X - B.Y * C.X)); }
/// <summary> /// 将一个点转为矢径 /// </summary> /// <param name="D"></param> public Vector(Dot2 D) { From = new Dot2(0, 0); To = D; }
/// <summary> /// 创建单位向量 /// </summary> public Vector() { From = new Dot2(0, 0); To = new Dot2(1, 0); }
/// <summary> /// 判断两条边是否相交 /// </summary> /// <param name="A"></param> /// <param name="B"></param> /// /// <param name="des">双方容差距离</param> /// <returns></returns> public static bool isIntersect(Vector A, Vector B, out Dot2 interdot, double des = 10) { interdot = null; //第一步:盒子判断 double amin, amax, bmin, bmax; if (A.From.X > A.To.X) { amin = A.To.X; amax = A.From.X; } else { amin = A.From.X; amax = A.To.X; } if (B.From.X > B.To.X) { bmin = B.To.X; bmax = B.From.X; } else { bmin = B.From.X; bmax = B.To.X; } if (amax - bmin < des || amin - bmax > des) { return(false); } if (A.From.Y > A.To.Y) { amin = A.To.Y; amax = A.From.Y; } else { amin = A.From.Y; amax = A.To.Y; } if (B.From.Y > B.To.Y) { bmin = B.To.Y; bmax = B.From.Y; } else { bmin = B.From.Y; bmax = B.To.Y; } if (amax - bmin < des || amin - bmax > des) { return(false); } //第二步同向判断 if (cross(A, new Vector(A.From, B.From)) * cross(A, new Vector(A.From, B.To)) > 0) { return(false); } //第三步位置判断 interdot = new Dot2(((A.To.Y * A.From.X - A.To.X * A.From.Y) * (B.To.X - B.From.X) - (B.To.Y * B.From.X - B.To.X * B.From.Y) * (A.To.X - A.From.X)) / ((B.To.X - B.From.X) * (A.To.Y - A.From.Y) - (B.To.Y - B.From.Y) * (A.To.X - A.From.X)), -((B.To.Y * B.From.X - B.To.X * B.From.Y) * (A.To.Y - A.From.Y) - (B.To.Y - B.From.Y) * (A.To.Y * A.From.X - A.To.X * A.From.Y)) / ((B.To.X - B.From.X) * (A.To.Y - A.From.Y) - (B.To.Y - B.From.Y) * (A.To.X - A.From.X))); if (dot(new Vector(interdot, A.From), new Vector(interdot, A.To)) > 0) { if (Length(interdot, A.From) > des || Length(interdot, A.To) > des) { return(false); } } return(true); }
/// <summary> /// 将一个点插入到边界中,形成凸面体 /// </summary> /// <param name="origin"></param> /// <param name="border"></param> /// <returns></returns> public static void putDotToBorder(Dot2 origin, Border border) { Dot2 dot; int i, j = 0, count = border.DotCount, tempj; if (count <= 2) { border.Add(origin); return; } double temp, lengh = double.MaxValue; int isIntersects = 0; for (i = 0; i < count; i++) { temp = Math.Length(origin, border.get(i)); if (temp < lengh) { lengh = temp; j = i; } } //判断是否相交 tempj = count + j; for (i = 0; i < count; i++) { if (i == tempj % count || i == (tempj - 1) % count) { continue; } if (isIntersect(new Vector(origin, border.get(tempj)), border.getVecter(i), out dot)) { isIntersects = 1; break; } } if (isIntersects == 1) { isIntersects = 4; lengh = double.MaxValue; //采用面积最小方式 for (i = 0; i < border.DotCount; i++) { temp = Math.Area(origin, border.get(i), border.get((i + 1))); if (temp < lengh) { lengh = temp; j = i; } } //判断是否相交,若相交,取最近的相交的线段插入 temp = double.MaxValue; tempj = count + j; for (i = 0; i < count; i++) { if (i == tempj % count || i == (tempj - 1) % count) { continue; } if (isIntersect(new Vector(origin, border.get(tempj)), border.getVecter(i), out dot)) { temp = Math.Length(origin, dot); if (temp < lengh) { isIntersects = 5; lengh = temp; j = i; } } } //if (isIntersects == 5) //{ //} //tempj = count + i+1; //for (i = 0; i < count; i++) //{ // if (i == tempj % count || i == (tempj - 1) % count) // { // continue; // } // if (isIntersect(new Vector(origin, border.get(tempj)), border.getVecter(i), out dot)) // { // isIntersects = 5; // break; // } //} } else { tempj = count + j - 1; for (i = 0; i < count; i++) { if (i == tempj % count || i == (tempj - 1) % count) { continue; } if (isIntersect(new Vector(origin, border.get(tempj)), border.getVecter(i), out dot)) { isIntersects = 1; break; } } tempj = count + j + 1; for (i = 0; i < count; i++) { if (i == tempj % count || i == (tempj - 1) % count) { continue; } if (isIntersect(new Vector(origin, border.get(tempj)), border.getVecter(i), out dot)) { if (isIntersects == 1) { isIntersects = 2; } else { isIntersects = 3; } break; } } } switch (isIntersects) { case 0: //两线段都无交点 if (Math.Length(origin, border.get(j - 1)) + border.getVecter(j).Length > Math.Length(origin, border.get(j + 1)) + border.getVecter(j - 1).Length) { border.Insert(origin, j + 1, DrawType.normal); } else { border.Insert(origin, j, DrawType.normal); } break; case 1: //仅左线段相交 border.Insert(origin, j + 1, DrawType.Ignore); break; case 2: //左右线段都相交 break; case 3: //仅右线段相交 border.Insert(origin, j, DrawType.Ignore); break; case 4: //采用面积最小方式,无相交 border.Insert(origin, j + 1, DrawType.Ignore); break; case 5: //采用面积最小方式,有相交,插入相交线段 border.Insert(origin, j + 1, DrawType.Ignore); break; default: break; } }
public Operate(Type type, Dot2 dot, int index) { this.type = type; this.dot = dot; this.index = index; }
public Dotx(Dot2 dot, DrawType type) { this.X = dot.X; this.Y = dot.Y; this.type = type; }
public Dotx(Dot2 dot) { this.X = dot.X; this.Y = dot.Y; this.type = DrawType.normal; }
/// <summary> /// 获取两个点的长度 /// </summary> /// <returns></returns> public static double Length(Dot2 D1, Dot2 D2) { return(System.Math.Sqrt(System.Math.Pow((D1.X - D2.X), 2) + System.Math.Pow((D1.Y - D2.Y), 2))); }
/// <summary> /// 根据两个点生成向量 /// </summary> public Vector(Dot2 from, Dot2 to) { From = from; To = to; }
public void put(Dot2 dot) { Math.putMinLengthDotToBorder(dot, this); //Math.putDotToBorder(dot, this); //getNearestVector }
public void Modify(Dot2 dot, int index) { Dots[index].X = dot.X; Dots[index].Y = dot.Y; Operate.Add(new Operate(Type.Modify, dot, index)); }
public void Add(Dot2 dot) { Operate.Add(new Operate(Type.Append, dot, Dots.Count)); Dots.Add(dot.toDotx()); }