public Bounds(Vertex TL, Vertex TR, Vertex BL, Vertex BR) { TopLeft = TL; TopRight = TR; BottomLeft = BL; BottomRight = BR; }
private static double EuclideanDistance(Vertex v1, Vertex v2) { return Math.Sqrt(Math.Pow((v1.X - v2.X), 2) + Math.Pow((v1.Y - v2.Y), 2)); }
private static double angle(Vertex v1, Vertex v2) { // TODO fix Vertex v3 = new Vertex(v1.X, 0); if (Orientation(v3, v1, v2) == 0) return 180; double b = EuclideanDistance(v3, v1); double a = EuclideanDistance(v1, v2); double c = EuclideanDistance(v3, v2); double angle = Math.Acos((Math.Pow(a, 2) + Math.Pow(b, 2) - Math.Pow(c, 2)) / (2 * a * b)); if (Orientation(v3, v1, v2) < 0) angle = 360 - angle; return angle; }
private static Vertex[] Add(Vertex[] vs, Vertex v) { List<Vertex> n = new List<Vertex>(vs); n.Add(v); return n.ToArray(); }
public static int Compare(Vertex u, Vertex a, Vertex b) { if (a.X == b.X && a.Y == b.Y) return 0; Vertex upper = new Vertex(); Vertex p1 = new Vertex(); Vertex p2 = new Vertex(); upper.X = (u.X + 180) * 360; upper.Y = (u.Y + 90) * 180; p1.X = (a.X + 180) * 360; p1.Y = (a.Y + 90) * 180; p2.X = (b.X + 180) * 360; p2.Y = (b.Y + 90) * 180; if (p1 == upper) return -1; if (p2 == upper) return 1; double m1 = upper.slope(p1); double m2 = upper.slope(p2); if (m1 == m2) { return p1.distance(upper) < p2.distance(upper) ? -1 : 1; } if (m1 <= 0 && m2 > 0) return -1; if (m1 > 0 && m2 <= 0) return -1; return m1 > m2 ? -1 : 1; }
public Edge(double ax, double ay, double bx, double by) { A = new Vertex(ax, ay); B = new Vertex(bx, by); }
private static Vertex[] sortByAngle(Vertex[] vs, Vertex v, double angle) { return new Vertex[] { }; }
private static Vertex[] RemoveDuplicates(Vertex[] vs) { List<Vertex> clean = new List<Vertex>(); /* foreach (Vertex v in vs) { if (!clean.Contains(v, vc)) clean.Add(v); } return clean.ToArray();*/ return null; }
public double distance(Vertex b) { double dX = b.X - this.X; double dY = b.Y - this.Y; return Math.Sqrt((dX * dX) + (dY * dY)); }
public static Vertex UpperLeft(Vertex[] vs) { Vertex top = vs[0]; for (int i = 1; i < vs.Length; i++) { Vertex temp = vs[i]; if (temp.Y > top.Y || (temp.Y == top.Y && temp.X < top.X)) { top = temp; } } return top; }
public static string ToString(Vertex[] array) { string res = "["; foreach (Vertex v in array) res += v.ToString() + ","; return res.Remove(res.Length - 1) + "]"; }
public static string Stringify(Vertex[] vs) { string res = "["; foreach (Vertex v in vs) { res += v.ToString(); res += ";"; } res = res.Remove(res.Length - 1); res += "]"; return res; }
/* //When x < y return -1 //When x == y return 0 //When x > y return 1 public static int Compare(Vertex x, Vertex y) { //To find lowest if (x.X < y.X) { return -1; } else if (x.X == y.X) { if (x.Y < y.Y) { return -1; } else if (x.Y == y.Y) { return 0; } else { return 1; } } else { return 1; } } */ public static int CompareY(Vertex a, Vertex b) { if (a.Y < b.Y) return -1; if (a.Y == b.Y) return 0; return 1; }
public static int CompareX(Vertex a, Vertex b) { if (a.X < b.X) return -1; if (a.X == b.X) return 0; return 1; }
private static bool intersectsQ(Vertex v1, Vertex v2, Vertex v3, Vertex v4) { return intersectsQ(new Edge(v1, v2), new Edge(v3, v4)); }
private static Vertex[] nearestPoints(Vertex[] vs, Vertex v, int k) { Dictionary<double, Vertex> lengths = new Dictionary<double, Vertex>(); List<Vertex> n = new List<Vertex>(); double[] sorted = lengths.Keys.OrderBy(d => d).ToArray(); for (int i = 0; i < k; i++) { n.Add(lengths[sorted[i]]); } return n.ToArray(); }
public double slope(Vertex b) { double dX = b.X - this.X; double dY = b.Y - this.Y; return dY / dX; }
private static Vertex[] RemoveIndex(Vertex[] vs, int index) { List<Vertex> removed = new List<Vertex>(); for (int i = 0; i < vs.Length; i++) if (i != index) removed.Add(vs[i]); return removed.ToArray(); }
public static Vertex[] ConcaveHull(Vertex[] points, int k = 3) { if (k < 3) throw new ArgumentException("K is required to be 3 or more", "k"); List<Vertex> hull = new List<Vertex>(); //Clean first, may have lots of duplicates Vertex[] clean = RemoveDuplicates(points); if (clean.Length < 3) throw new ArgumentException("At least 3 dissimilar points reqired", "points"); if (clean.Length == 3)//This is the hull, its already as small as it can be. return clean; if (clean.Length < k) throw new ArgumentException("K must be equal to or smaller then the amount of dissimilar points", "points"); Vertex firstPoint = clean[0]; //TODO find mid point hull.Add(firstPoint); Vertex currentPoint = firstPoint; Vertex[] dataset = RemoveIndex(clean, 0); double previousAngle = 0; int step = 2; int i; while (((currentPoint != firstPoint) || (step == 2)) && (dataset.Length > 0)) { if (step == 5) dataset = Add(dataset, firstPoint); Vertex[] kNearestPoints = nearestPoints(dataset, currentPoint, k); Vertex[] cPoints = sortByAngle(kNearestPoints, currentPoint, previousAngle); bool its = true; i = 0; while ((its) && (i < cPoints.Length)) { i++; int lastPoint = 0; if (cPoints[0] == firstPoint) lastPoint = 1; int j = 2; its = false; while ((!its) && (j < hull.Count - lastPoint)) { its = intersectsQ(hull[step - 1 - 1], cPoints[0], hull[step - i - j - 1], hull[step - j - 1]); j++; } } if (its) { return ConcaveHull(points, k + 1); } currentPoint = cPoints[0]; hull.Add(currentPoint); previousAngle = angle(hull[step - 1], hull[step - 2]); dataset = RemoveIndex(dataset, 0); step++; } bool allInside = true; i = dataset.Length; while (allInside && i > 0) { allInside = new Polygon(dataset).Contains(currentPoint); //TODO havent finished ray casting yet. i--; } if (!allInside) return ConcaveHull(points, k + 1); return hull.ToArray(); }
public Edge(Vertex a, Vertex b) { A = a; B = b; }
public static double Orientation(Vertex p1, Vertex p2, Vertex p) { double Orin = (p2.X - p1.X) * (p.Y - p1.Y) - (p.X - p1.X) * (p2.Y - p1.Y); if (Orin > 0) return -1;//Left if (Orin < 0) return 1;//Right return 0;//Colinier }
public Polygon(Vertex[] Vertexes) { vs = Vertexes; }
public bool Contains(Vertex v) { return false; }