public Circle(List <Point> ps) { Circle c = SmallestEnclosingCircle.MakeCircle(ps); this.c = c.c; this.r = c.r; }
public void OnExecute() { IList <Point> points = null; DateTime start = DateTime.Now; if (JsonPointsPath == null) { points = GenerateRandomPoints(NumberOfPoints == 0 ? 2 : NumberOfPoints); } else { // deserialize JSON directly from a file using (StreamReader file = File.OpenText(JsonPointsPath)) { JsonSerializer serializer = new JsonSerializer(); points = (Point[])serializer.Deserialize(file, typeof(Point[])); } } DateTime end = DateTime.Now; Console.WriteLine(end - start); start = end; Circle result = SmallestEnclosingCircle.MakeCircle(points); Console.WriteLine(JsonConvert.SerializeObject(result)); end = DateTime.Now; Console.WriteLine(end - start); }
private Matrix4X4 GetCenteringTransformExpandedToRadius(IEnumerable <IObject3D> items, double radius) { IEnumerable <Vector2> GetTranslatedXY() { foreach (var item in items) { foreach (var mesh in item.VisibleMeshes()) { var worldMatrix = mesh.WorldMatrix(this); foreach (var vertex in mesh.Mesh.Vertices) { yield return(new Vector2(vertex.Transform(worldMatrix))); } } } } var circle = SmallestEnclosingCircle.MakeCircle(GetTranslatedXY()); // move the circle center to the origin var centering = Matrix4X4.CreateTranslation(-circle.Center.X, -circle.Center.Y, 0); // scale to the fit size in x y double scale = radius / circle.Radius; var scalling = Matrix4X4.CreateScale(scale, scale, 1); return(centering * scalling); }
private static void TestScaling() { int TRIALS = 100; int CHECKS = 10; for (int i = 0; i < TRIALS; i++) { IList <Point> points = MakeRandomPoints(rand.Next(300) + 1); Circle reference = SmallestEnclosingCircle.MakeCircle(points); for (int j = 0; j < CHECKS; j++) { double scale = NextGaussian(); IList <Point> newPoints = new List <Point>(); foreach (Point p in points) { newPoints.Add(new Point(p.x * scale, p.y * scale)); } Circle scaled = SmallestEnclosingCircle.MakeCircle(newPoints); AssertApproxEqual(reference.c.x * scale, scaled.c.x, EPSILON); AssertApproxEqual(reference.c.y * scale, scaled.c.y, EPSILON); AssertApproxEqual(reference.r * Math.Abs(scale), scaled.r, EPSILON); } } }
private static void TestTranslation() { int TRIALS = 100; int CHECKS = 10; for (int i = 0; i < TRIALS; i++) { IList <Point> points = MakeRandomPoints(rand.Next(300) + 1); Circle reference = SmallestEnclosingCircle.MakeCircle(points); for (int j = 0; j < CHECKS; j++) { double dx = NextGaussian(); double dy = NextGaussian(); IList <Point> newPoints = new List <Point>(); foreach (Point p in points) { newPoints.Add(new Point(p.x + dx, p.y + dy)); } Circle translated = SmallestEnclosingCircle.MakeCircle(newPoints); AssertApproxEqual(reference.c.x + dx, translated.c.x, EPSILON); AssertApproxEqual(reference.c.y + dy, translated.c.y, EPSILON); AssertApproxEqual(reference.r, translated.r, EPSILON); } } }
/// <summary> /// Calculate a marina's location based on the locations that its spots have, if it has any. /// </summary> /// <remarks> /// Uses a algorithm in order to determine the smallest enclosing circle of a number of points. /// </remarks> /// <param name="marina"></param> public static void CalculateMarinaLocation(Marina marina) { if (marina is not null) { if (MarinaSpotsHaveLocations(marina)) { var locations = new List <Point>(); // Verify for spots with locations once again // (When the method gets called it is made sure that the spots inside have a valid location, but let's verify again) marina.Spots .FindAll(spot => spot.LocationId.IsValidId()) .ForEach(spot => locations.Add(new Point(spot.Location.Latitude, spot.Location.Longitude))); Circle circle = SmallestEnclosingCircle.MakeCircle(locations); if (circle.r * 8000 < 10000) { circle.r = 10; } Location marinaLocation = new Location { Latitude = circle.c.x, Longitude = circle.c.y, Radius = circle.r, }; marina.Location = marinaLocation; } } }
private static Affine GetCenteringTransformExpandedToRadius(IVertexSource vertexSource, double radius) { var circle = SmallestEnclosingCircle.MakeCircle(vertexSource.Vertices().Select((v) => new Vector2(v.position.X, v.position.Y))); // move the circle center to the origin var centering = Affine.NewTranslation(-circle.Center); // scale to the fit size in x y double scale = radius / circle.Radius; var scalling = Affine.NewScaling(scale); return(centering * scalling); }
public CylinderParams GetBoundingCylinder(IBody2 body, double[] dir) { double[] xAxis = new double[] { 1, 0, 0 }; double[] yAxis = new double[] { 0, 1, 0 }; double[] zAxis = new double[] { 0, 0, 1 }; bool isAligned = m_MathHelper.ArrayEqual(dir, yAxis); IMathTransform alignTransform = null; if (!isAligned) { alignTransform = m_MathHelper.GetTransformBetweenVectorsAroundPoint( dir, yAxis, new double[] { 0, 0, 0 }); IBody2 bodyCopy = body.ICopy(); bodyCopy.ApplyTransform(alignTransform as MathTransform); body = bodyCopy; } double[] rootPt; double[] endPt; GetExtremePoints(body, yAxis, out rootPt, out endPt); double height = Math.Abs(endPt[1] - rootPt[1]); dir = new double[] { 0, endPt[1] - rootPt[1], 0 }; List <double[]> perPoints = GetPerimeterPoints(body, xAxis, zAxis); List <Point> points = new List <Point>(); foreach (double[] pt in perPoints) { points.Add(new Point(pt[0], pt[2])); } Circle cir = SmallestEnclosingCircle.MakeCircle(points); double[] circCenter = new double[] { cir.c.x, rootPt[1], cir.c.y }; if (!isAligned) { circCenter = m_MathHelper.TransformPoint(circCenter, alignTransform.IInverse()); dir = m_MathHelper.TransformVector(dir, alignTransform.IInverse()); } double radius = cir.r; return(new CylinderParams(height, circCenter, dir, radius)); }
/*---- Test suite functions ----*/ private static void TestMatchingNaiveAlgorithm() { int TRIALS = 1000; for (int i = 0; i < TRIALS; i++) { IList <Point> points = MakeRandomPoints(rand.Next(30) + 1); Circle reference = SmallestEnclosingCircleNaive(points); Circle actual = SmallestEnclosingCircle.MakeCircle(points); AssertApproxEqual(reference.c.x, actual.c.x, EPSILON); AssertApproxEqual(reference.c.y, actual.c.y, EPSILON); AssertApproxEqual(reference.r, actual.r, EPSILON); } }
public static Circle GetSmallestEnclosingCircleAlongZ(this IObject3D object3D) { var visibleMeshes = object3D.VisibleMeshes().Select(vm => (source: vm, convexHull: vm.Mesh.GetConvexHull(false))).ToList(); IEnumerable <Vector2> GetVertices() { foreach (var visibleMesh in visibleMeshes) { var matrix = visibleMesh.source.WorldMatrix(object3D); foreach (var positon in visibleMesh.convexHull.Vertices) { var transformed = positon.Transform(matrix); yield return(new Vector2(transformed.X, transformed.Y)); } } } var circle = SmallestEnclosingCircle.MakeCircle(GetVertices()); return(circle); }
private Polygon GetBoundingCircle(Polygons basePolygons) { IntPoint center; double radius; if (Centering == CenteringTypes.Bounds) { IEnumerable <Vector2> GetVertices() { foreach (var polygon in basePolygons) { foreach (var positon in polygon) { yield return(new Vector2(positon.X, positon.Y)); } } } var circle = SmallestEnclosingCircle.MakeCircle(GetVertices()); center = new IntPoint(circle.Center.X, circle.Center.Y); radius = (long)circle.Radius; } else { var outsidePolygons = new List <List <IntPoint> >(); // remove all holes from the polygons so we only center the major outlines var polygons = VertexSource.CreatePolygons(); foreach (var polygon in polygons) { if (polygon.GetWindingDirection() == 1) { outsidePolygons.Add(polygon); } } IVertexSource outsideSource = outsidePolygons.CreateVertexStorage(); var polyCenter = outsideSource.GetWeightedCenter(); center = new IntPoint(polyCenter.X * 1000, polyCenter.Y * 1000); radius = 0; foreach (Polygon polygon in basePolygons) { foreach (IntPoint point in polygon) { long length = (point - center).Length(); if (length > radius) { radius = length; } } } } var boundingCircle = new Polygon(); int numPoints = 100; for (int i = 0; i < numPoints; i++) { double angle = i / 100.0 * Math.PI * 2.0; IntPoint newPointOnCircle = new IntPoint(Math.Cos(angle) * radius, Math.Sin(angle) * radius) + center; boundingCircle.Add(newPointOnCircle); } return(boundingCircle); }