public void Duplicate(ref Point3[] Points, int i) { Circular node = this; do { Points[i++] = node.Point; node = node.Next; } while (node != this); }
public Circular(Point3 point) { Point = point; Next = this; Last = this; }
public bool Equals(Point3 point) { if (x == point.x && y == point.y) return true; else return false; }
public bool Smaller(Point3 point) { if ((x < point.x) || (x == point.x && y < point.y)) return true; else return false; }
public static double check(Point3 point1, Point3 point2, Point3 point3) { return point1.x * (point2.y - point3.y) + point2.x * (point3.y - point1.y) + point3.x * (point1.y - point2.y); }
private static void sort(ref Point3[] Points, int start, int end) { if (start < end) { int i = start; int j = end; Point3 x = Points[(i + j) / 2]; do { while (Points[i].Smaller(x)) i++; while (x.Smaller(Points[j])) j--; if (i <= j) { Point3 temp = Points[i]; Points[i] = Points[j]; Points[j] = temp; i++; j--; } } while (i <= j); sort(ref Points, start, j); sort(ref Points, i, end); } }
private static void increase1pc(ref Point3[] points) { Point3 cent = new Point3(0, 0); for (int i = 0; i < points.Length; i++) { cent.x += points[i].x; cent.y += points[i].y; } cent.x = cent.x / points.Length; cent.y = cent.y / points.Length; for (int i = 0; i < points.Length; i++) { points[i].x += (points[i].x - cent.x) * .01; points[i].y += (points[i].y - cent.y) * .01; } }
public static Point3[] getConvexPolygon(Point3[] points) { int num = points.Length; sort(ref points,0,points.Length-1); Point3 left = points[0]; Point3 right = points[num - 1]; Circular lower = new Circular(left); Circular upper = new Circular(left); for (int i = 0; i < num; i++) { double result = Point3.check(left, right, points[i]); if (result > 0) upper = upper.Append(new Circular(points[i])); else if (result < 0) lower = lower.Prepend(new Circular(points[i])); } lower = lower.Prepend(new Circular(right)); upper = upper.Append(new Circular(right)).Next; minimize(lower); minimize(upper); if (lower.Last.Point.Equals(upper.Point)) lower.Last.Remove(); if (upper.Last.Point.Equals(lower.Point)) upper.Last.Remove(); Point3[] final = new Point3[lower.Length() + upper.Length() + 1]; lower.Duplicate(ref final, 0); upper.Duplicate(ref final, lower.Length()); final[lower.Length() + upper.Length()] = final[0]; increase1pc(ref final); return final; }
public void Execute(params object[] args) { string statusMessage = "Clustering orders."; App.Current.Messenger.AddInfo(statusMessage); ///////////////////////////////// // Find Current Schedule, Routes and Orders ///////////////////////////////// ESRI.ArcLogistics.DomainObjects.Schedule schedule = new ESRI.ArcLogistics.DomainObjects.Schedule(); int numSchedules = App.Current.Project.Schedules.Count; foreach (ESRI.ArcLogistics.DomainObjects.Schedule s in App.Current.Project.Schedules.Search(App.Current.CurrentDate)) { if (s.Name == "Current") { schedule = s; break; } } //Get number of Routes on current Schedule int numRoutes = schedule.Routes.Count; //Get number of Orders for current Date int numOrders = App.Current.Project.Orders.GetCount(App.Current.CurrentDate); if (numRoutes > 0 && numOrders > numRoutes) { ///////////////////////////////// // Create Dataset ///////////////////////////////// Point2[] data = new Point2[numOrders]; Point2[] centres = new Point2[numRoutes]; List<ESRI.ArcLogistics.DomainObjects.Order> oList = App.Current.Project.Orders.Search(App.Current.CurrentDate).ToList(); for (int i = 0; i < numOrders; i++) { ESRI.ArcLogistics.DomainObjects.Order o = oList.ElementAt(i); Point2 p2 = new Point2(0, o.GeoLocation.Value.X, o.GeoLocation.Value.Y); data[i] = p2; } ///////////////////////////////// // Perform Clustering ///////////////////////////////// int iterations = cluster(ref data, ref centres); ///////////////////////////////// // Delete all previous zones from the project ///////////////////////////////// for (int c = App.Current.Project.Zones.Count - 1; c >= 0; c--) { ESRI.ArcLogistics.DomainObjects.Zone z = App.Current.Project.Zones.ElementAt(c); App.Current.Project.Zones.Remove(z); } ///////////////////////////////// // Delete all previous zones from the current day's routes ///////////////////////////////// for (int j = 0; j < numRoutes; j++) { for (int c = schedule.Routes[j].Zones.Count - 1; c >= 0; c--) { ESRI.ArcLogistics.DomainObjects.Zone z = schedule.Routes[j].Zones.ElementAt(c); schedule.Routes[j].Zones.Remove(z); } } ///////////////////////////////// // Find Convex Hull, create Soft Zones and assign them to routes ///////////////////////////////// List<Point3>[] DataList = new List<Point3>[numRoutes]; for (int j = 0; j < numRoutes; j++) DataList[j] = new List<Point3>(); for (int i = 0; i < numOrders; i++) { Point3 p3 = new Point3(data[i].X, data[i].Y); DataList[data[i].cluster].Add(p3); } for (int j = 0; j < numRoutes; j++) { // Dont create zones for less than 3 orders if (DataList[j].Count <= 2) continue; // Get Convex Hull Point3[] chpts = ConvexPolygon.getConvexPolygon(DataList[j].ToArray()); // Convert Point3 array to Geometry Point array ESRI.ArcLogistics.Geometry.Point[] polyPoints = new ESRI.ArcLogistics.Geometry.Point[chpts.Length]; for (int k = 0; k < chpts.Length; k++) { Point3 p3 = chpts[k]; ESRI.ArcLogistics.Geometry.Point geoP = new ESRI.ArcLogistics.Geometry.Point(); geoP.X = p3.x; geoP.Y = p3.y; polyPoints[k] = geoP; } // Create soft zone, and add to Project and to a Route ESRI.ArcLogistics.Geometry.Polygon p = new ESRI.ArcLogistics.Geometry.Polygon(polyPoints); ESRI.ArcLogistics.DomainObjects.Zone z = new ESRI.ArcLogistics.DomainObjects.Zone(); z.CreationTime = DateTime.Now.Ticks; z.Geometry = p; z.Name = String.Format("Zone {0}", j+1); App.Current.Project.Zones.Add(z); schedule.Routes[j].Zones.Add(z); schedule.Routes[j].HardZones = false; } App.Current.Project.Save(); statusMessage = "Finished clustering orders."; App.Current.Messenger.AddInfo(statusMessage); } else { statusMessage=""; if(numOrders==0) statusMessage = "No Orders found."; else if(numRoutes==0) statusMessage = "No Routes found."; else if (numRoutes > numOrders) statusMessage = "Insufficient number of orders."; App.Current.Messenger.AddError(statusMessage); } }