void CalcConvexHull_Executed(object sender, EventArgs e) { UpdateStatusLabel("calculating convex hull..."); //clear old lines var oldHull = canvas.Geometries.OfType <Segment2d> ().ToArray(); foreach (var l in oldHull) { canvas.Geometries.Remove(l); } //get all points var points = canvas.Geometries.OfType <Vector2d> ().ToArray(); watch.Start(); var convexHull = GeoAlgos.MonotoneChainConvexHull(points); watch.Stop(); //draw convex hull for (var i = 0; i < convexHull.Length; i++) { var next = (i + 1) % convexHull.Length; canvas.Geometries.Add(new Segment2d(convexHull [i], convexHull [next])); } UpdateUi(watch.Duration.TotalSeconds + " ms"); }
/// <summary> /// Calculates the minimum bounding box. /// </summary> /// <param name="points">Bounding Box.</param> public static Polygon2d Calculate(Vector2d[] points) { //calculate the convex hull var hullPoints = GeoAlgos.MonotoneChainConvexHull(points); //check if no bounding box available if (hullPoints.Length <= 1) { return new Polygon2d { Points = hullPoints.ToList() } } ; Rectangle2d minBox = null; var minAngle = 0d; //foreach edge of the convex hull for (var i = 0; i < hullPoints.Length; i++) { var nextIndex = i + 1; var current = hullPoints [i]; var next = hullPoints [nextIndex % hullPoints.Length]; var segment = new Segment2d(current, next); //min / max points var top = double.MinValue; var bottom = double.MaxValue; var left = double.MaxValue; var right = double.MinValue; //get angle of segment to x axis var angle = AngleToXAxis(segment); //rotate every point and get min and max values for each direction foreach (var p in hullPoints) { var rotatedPoint = RotateToXAxis(p, angle); top = Math.Max(top, rotatedPoint.Y); bottom = Math.Min(bottom, rotatedPoint.Y); left = Math.Min(left, rotatedPoint.X); right = Math.Max(right, rotatedPoint.X); } //create axis aligned bounding box var box = new Rectangle2d(new Vector2d(left, bottom), new Vector2d(right, top)); if (minBox == null || minBox.Area() > box.Area()) { minBox = box; minAngle = angle; } } //rotate axis algined box back var minimalBoundingBox = new Polygon2d { Points = minBox.Points.Select(p => RotateToXAxis(p, -minAngle)).ToList() }; return(minimalBoundingBox); }