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); } } }
public Circle(List <Point> ps) { Circle c = SmallestEnclosingCircle.MakeCircle(ps); this.c = c.c; this.r = c.r; }
/// <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 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); } } }
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); }
// Returns the smallest enclosing circle in O(n^4) time using the naive algorithm. private static Circle SmallestEnclosingCircleNaive(IList <Point> points) { // Degenerate cases if (points.Count == 0) { return(new Circle(new Point(0, 0), -1)); } else if (points.Count == 1) { return(new Circle(points[0], 0)); } // Try all unique pairs Circle result = new Circle(new Point(0, 0), -1); for (int i = 0; i < points.Count; i++) { for (int j = i + 1; j < points.Count; j++) { Circle c = SmallestEnclosingCircle.MakeDiameter(points[i], points[j]); if ((result.r < 0 || c.r < result.r) && c.Contains(points)) { result = c; } } } if (result.r >= 0) { return(result); // This optimization is not mathematically proven } // Try all unique triples for (int i = 0; i < points.Count; i++) { for (int j = i + 1; j < points.Count; j++) { for (int k = j + 1; k < points.Count; k++) { Circle c = SmallestEnclosingCircle.MakeCircumcircle(points[i], points[j], points[k]); if (c.r >= 0 && (result.r < 0 || c.r < result.r) && c.Contains(points)) { result = c; } } } } if (result.r < 0) { throw new SystemException("Assertion error"); } return(result); }
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 void MakeCircle_Get() { var points = new List <Point>() { new Point(0, 0), new Point(6, 0), new Point(3, 6), new Point(9, 6), }; var circle = SmallestEnclosingCircle.GetCircle(points); Assert.AreEqual(4.5, circle.center.x); Assert.AreEqual(3, circle.center.y); }
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); }
/// <summary> /// Processes the farm mechanics. /// </summary> private void ProcessFarmMechanics() { if (Orbwalker.Mode == OrbwalkingMode.Combo || !WSpell.Ready) { return; } var zoneCircle = Geometry.GetNewCircleAtPoint(new Point(LocalHero.Position.X, 0, LocalHero.Position.Z), LocalHeroTrueRange * 3); var enemyHeroesCountTask = Task <int> .Factory.StartNew(() => GetEnemyHeroesCountInZone(ref zoneCircle)); if (enemyHeroesCountTask.Result > 0) { return; } var minionPointSet = new PointSet(); foreach (var enemyMinion in GameObjects.EnemyMinions) { if (enemyMinion.Team != GameObjectTeam.Chaos || !IsValidTargetLocked(enemyMinion, WSpell.Range)) { continue; } minionPointSet.Add(new Point(enemyMinion.Position.X, enemyMinion.Position.Z, 0)); } if (minionPointSet.Count < 2) { return; } var smallestEnclosingCircle = new SmallestEnclosingCircle(minionPointSet); var computedCircle = smallestEnclosingCircle.ComputeCircle(); CastSpellW(new Vector2((float)computedCircle.Center.X, (float)computedCircle.Center.Y), SpellPriority.Farm); }
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); }
private AlgorithmManager() { // Color c = Colors. _algorithms.Add(new AlgorithmStandard(AlgorithmType.ConvexHull, "Graham Scan modified", "Rod Stephens", "Slowest but simple and great for comparison.", OxyPlot.OxyColors.DarkKhaki, (points, algorithmStat) => { var stopwatch = Stopwatch.StartNew(); var result = RodStephens.Geometry.MakeConvexHull(points); stopwatch.Stop(); if (algorithmStat != null) { algorithmStat.TimeSpanOriginal = stopwatch.Elapsed; } return(result.ToArray()); })); _algorithms.Add(new AlgorithmStandard(AlgorithmType.ConvexHull, "Monotone chain", "A. M. Andrew, David Piepgrass (Qwerties)", "Very slow. Got on the web.", OxyPlot.OxyColors.Chocolate, (points, algorithmStat) => { var stopwatch = Stopwatch.StartNew(); var result = MonotoneChainImplementation.ComputeConvexHull(points); stopwatch.Stop(); if (algorithmStat != null) { algorithmStat.TimeSpanOriginal = stopwatch.Elapsed; } return(result.ToArray()); })); AlgoIndexMonotoneChain = _algorithms.Count - 1; _algorithms.Add(new AlgorithmStandard(AlgorithmType.ConvexHull, "Heap", "?, Pat Morin", "Very slow. Got on the web.", OxyPlot.OxyColors.Thistle, (points, algorithmStat) => { ConvexHullHeapAndChanWrapper wrapper = new ConvexHullHeapAndChanWrapper(points); wrapper.HeapHull(); var result = wrapper.HullPoints; if (algorithmStat != null) { algorithmStat.TimeSpanOriginal = wrapper.TimeSpan; } return(result); })); AlgoIndexHeap = _algorithms.Count - 1; _algorithms.Add(new AlgorithmStandard(AlgorithmType.ConvexHull, "MI ConvexHUll (Delaunay/Voronoi)", "Delaunay and Voronoi, davecz", "Slow. From CodePlex. Could do 3D.", OxyPlot.OxyColors.Indigo, (points, algorithmStat) => { var vertices = new Vertex[points.Length]; int i = 0; foreach (var point in points) { vertices[i] = new Vertex(point.X, point.Y); i++; } var stopwatch = Stopwatch.StartNew(); var convexHull = MIConvexHull.ConvexHull.Create(vertices); stopwatch.Stop(); var hullPoints = new Point[convexHull.Points.Count()]; i = 0; if (hullPoints.Length > 0) { var firstFace = convexHull.Faces.First(); var face = firstFace; do { hullPoints[i++] = new Point(face.Vertices[0].Position[0], face.Vertices[0].Position[1]); face = face.Adjacency[0]; } while (face != firstFace); } if (algorithmStat != null) { algorithmStat.TimeSpanOriginal = stopwatch.Elapsed; } return(hullPoints); })); AlgoIndexMiConvexHull = _algorithms.Count - 1; _algorithms.Add(new AlgorithmStandard(AlgorithmType.ConvexHull, "Chan", "Chan, Pat Morin", "C code. Has a little bug (happen rarely). Got on the web.", OxyPlot.OxyColors.Red, (points, algorithmStat) => { Point[] result = null; try { ConvexHullHeapAndChanWrapper wrapper = new ConvexHullHeapAndChanWrapper(points); wrapper.ChanHull(); result = wrapper.HullPoints; if (algorithmStat != null) { algorithmStat.TimeSpanOriginal = wrapper.TimeSpan; } } catch (Exception ex) { Console.WriteLine(ex.ToString()); Debugger.Break(); } return(result); })); AlgoIndexChan = _algorithms.Count - 1; _algorithms.Add(new AlgorithmStandard(AlgorithmType.ConvexHull, "LiuAndChen", "Liu and Chen, Eric Ouellet", "The same as Ouellet without my optimization", OxyPlot.OxyColors.LightSkyBlue, (points, algorithmStat) => { LiuAndChen.ConvexHull convexHull = new LiuAndChen.ConvexHull(points); convexHull.CalcConvexHull(LiuAndChen.ConvexHullThreadUsage.OnlyOne); return(convexHull.GetResultsAsArrayOfPoint()); })); AlgoIndexLiuAndChen = _algorithms.Count - 1; _algorithms.Add(new AlgorithmStandard(AlgorithmType.ConvexHull, "Ouellet C# ST", "Eric Ouellet, Eric Ouellet", "Highly tested.", OxyPlot.OxyColors.Green, (points, algorithmStat) => { OuelletConvexHull.ConvexHull convexHull = new OuelletConvexHull.ConvexHull(points); convexHull.CalcConvexHull(ConvexHullThreadUsage.OnlyOne); return(convexHull.GetResultsAsArrayOfPoint()); })); AlgoIndexOuelletConvexHullSingleThread = _algorithms.Count - 1; _algorithms.Add(new AlgorithmStandard(AlgorithmType.ConvexHull, "Ouellet C# ST (array copy)", "Eric Ouellet, Eric Ouellet", "Array instead of a List.", OxyPlot.OxyColors.Purple, (points, algorithmStat) => { OuelletConvexHullArray.ConvexHull convexHull = new OuelletConvexHullArray.ConvexHull(OuelletConvexHullArray.PointArrayManipulationType.ArrayCopy, points); convexHull.CalcConvexHull(OuelletConvexHullArray.ConvexHullThreadUsage.OnlyOne); return(convexHull.GetResultsAsArrayOfPoint()); })); AlgoIndexOuelletConvexHullSingleThreadArray = _algorithms.Count - 1; _algorithms.Add(new AlgorithmStandard(AlgorithmType.ConvexHull, "Ouellet C# ST (array C memcpy)", "Eric Ouellet, Eric Ouellet", "Array instead of a List.", OxyPlot.OxyColors.HotPink, (points, algorithmStat) => { OuelletConvexHullArray.ConvexHull convexHull = new OuelletConvexHullArray.ConvexHull(OuelletConvexHullArray.PointArrayManipulationType.UnsafeCMemCopy, points); convexHull.CalcConvexHull(OuelletConvexHullArray.ConvexHullThreadUsage.OnlyOne); return(convexHull.GetResultsAsArrayOfPoint()); })); AlgoIndexOuelletConvexHullSingleThreadArrayMemCpy = _algorithms.Count - 1; _algorithms.Add(new AlgorithmStandard(AlgorithmType.ConvexHull, "Ouellet C# ST (array copy immu)", "Eric Ouellet, Eric Ouellet", "Array instead of a List.", OxyPlot.OxyColors.Olive, (points, algorithmStat) => { OuelletConvexHullArray.ConvexHull convexHull = new OuelletConvexHullArray.ConvexHull(OuelletConvexHullArray.PointArrayManipulationType.ArrayCopyImmutable, points); convexHull.CalcConvexHull(OuelletConvexHullArray.ConvexHullThreadUsage.OnlyOne); return(convexHull.GetResultsAsArrayOfPoint()); })); AlgoIndexOuelletConvexHullSingleThreadArrayImmu = _algorithms.Count - 1; _algorithms.Add(new AlgorithmStandard(AlgorithmType.ConvexHull, "Ouellet C# ST (array memcpy no indirect)", "Eric Ouellet, Eric Ouellet", "Array instead of a List.", OxyPlot.OxyColors.Gold, (points, algorithmStat) => { OuelletConvexHullArrayNoIndirect.ConvexHull convexHull = new OuelletConvexHullArrayNoIndirect.ConvexHull(OuelletConvexHullArrayNoIndirect.PointArrayManipulationType.ArrayCopyImmutable, points); convexHull.CalcConvexHull(OuelletConvexHullArrayNoIndirect.ConvexHullThreadUsage.OnlyOne); return(convexHull.GetResultsAsArrayOfPoint()); })); AlgoIndexOuelletConvexHullSingleThreadArrayMemCpyNoIndirect = _algorithms.Count - 1; _algorithms.Add(new AlgorithmStandard(AlgorithmType.ConvexHull, "Ouellet C# Avl", "Eric Ouellet, Eric Ouellet", "Same as ST but with Avl Tree instead of List.", OxyPlot.OxyColors.Orange, (points, algorithmStat) => { OuelletConvexHullAvl.ConvexHullAvl convexHull = new OuelletConvexHullAvl.ConvexHullAvl(points); convexHull.CalcConvexHull(OuelletConvexHullAvl.ConvexHullThreadUsageAvl.OnlyOne); return(convexHull.GetResultsAsArrayOfPoint()); })); AlgoIndexOuelletConvexHullAvl = _algorithms.Count - 1; _algorithms.Add(new AlgorithmStandard(AlgorithmType.ConvexHull, "Ouellet C# Avl v2", "Eric Ouellet, Eric Ouellet", "Same as AVL with some optimisation.", OxyPlot.OxyColors.Blue, (points, algorithmStat) => { OuelletConvexHullAvl2.ConvexHullAvl convexHull = new OuelletConvexHullAvl2.ConvexHullAvl(points); convexHull.CalcConvexHull(); return(convexHull.GetResultsAsArrayOfPoint()); })); AlgoIndexOuelletConvexHullAvl2 = _algorithms.Count - 1; // Color c = Colors. _algorithms.Add(new AlgorithmStandard(AlgorithmType.ConvexHull, "Ouellet C# Avl v3 (standard/batch)", "Eric Ouellet, Eric Ouellet", "Based on Avl v2 with little modifications and additional online methods.", OxyPlot.OxyColors.DarkCyan, (points, algorithmStat) => { OuelletConvexHullAvl3.ConvexHull convexHull = new OuelletConvexHullAvl3.ConvexHull(); convexHull.CalcConvexHull(points); return(convexHull.GetResultsAsArrayOfPoint()); })); AlgoIndexOuelletConvexHullAvl2Online = _algorithms.Count - 1; _algorithms.Add(new AlgorithmStandard(AlgorithmType.ConvexHull, "Ouellet C# Avl v3 (one by one in a loop)", "Eric Ouellet, Eric Ouellet", "Based on Avl v2 with little modifications and additional online methods.", OxyPlot.OxyColors.DarkOrchid, (points, algorithmStat) => { OuelletConvexHullAvl3.ConvexHull convexHull = new OuelletConvexHullAvl3.ConvexHull(); // TEST to ensure that IsHullPoint and DynamicallyAddAnotherPointToConvexHullIfAppropriate appears to be coherent and works fine. //foreach (Point pt in points) //{ // Point[] ptsBefore = convexHullOnline.GetResultsAsArrayOfPoint(); // int countBefore = convexHullOnline.Count; // int t = convexHullOnline.IsHullPoint(pt); // int r = convexHullOnline.DynamicallyAddAnotherPointToConvexHullIfAppropriate(pt); // Point[] ptsAfter = convexHullOnline.GetResultsAsArrayOfPoint(); // Debug.Assert(t == r); // DifferencesInPath diffs = ConvexHullUtil.GetPathDifferences("", points, ptsAfter, ptsBefore); // if (r == 1) // { // Debug.Assert(diffs.HasErrors); // } // else // { // Debug.Assert(! diffs.HasErrors); // } //} foreach (Point pt in points) { convexHull.TryAddOnePoint(pt); } return(convexHull.GetResultsAsArrayOfPoint()); })); AlgoIndexOuelletConvexHullAvl2OnlineWithOnlineUse = _algorithms.Count - 1; _algorithms.Add(new AlgorithmStandard(AlgorithmType.ConvexHull, "Ouellet C# 4T", "Eric Ouellet, Eric Ouellet", "1 thread per quadrant for part 2", OxyPlot.OxyColors.SlateBlue, (points, algorithmStat) => { OuelletConvexHull.ConvexHull convexHull = new OuelletConvexHull.ConvexHull(points); convexHull.CalcConvexHull(ConvexHullThreadUsage.FixedFour); return(convexHull.GetResultsAsArrayOfPoint()); })); AlgoIndexOuelletConvexHull4Threads = _algorithms.Count - 1; _algorithms.Add(new AlgorithmStandard(AlgorithmType.ConvexHull, "Ouellet C# MT", "Eric Ouellet, Eric Ouellet", "All thread part 1, 4 threads part 2, 1 thread part 3", OxyPlot.OxyColors.SaddleBrown, (points, algorithmStat) => { OuelletConvexHull.ConvexHull convexHull = new OuelletConvexHull.ConvexHull(points); convexHull.CalcConvexHull(ConvexHullThreadUsage.All); return(convexHull.GetResultsAsArrayOfPoint()); })); AlgoIndexOuelletConvexHullMultiThreads = _algorithms.Count - 1; _algorithms.Add(new AlgorithmStandard(AlgorithmType.ConvexHull, "Ouellet CPP ST", "Eric Ouellet, Eric Ouellet", " thread, highly optimized, very ugly code", OxyPlot.OxyColors.YellowGreen, (points, algorithmStat) => { double elapsedTime = 0; OuelletConvexHullCpp convexHull = new OuelletConvexHullCpp(); var result = convexHull.OuelletHullManagedWithElapsedTime(points, true, ref elapsedTime); if (algorithmStat != null) { algorithmStat.TimeSpanOriginal = TimeSpanHelper.MoreAccurateTimeSpanFromSeconds(elapsedTime); } return(result); })); AlgoIndexOuelletConvexHullCpp = _algorithms.Count - 1; // Color r = Colors.CornflowerBlue; _algorithms.Add(new AlgorithmOnline(AlgorithmType.ConvexHullOnline, "Ouellet C# Avl v3 (** Only for Online performance test)", "Eric Ouellet, Eric Ouellet", "Add point one by one for 'merging' performance test only.", OxyPlot.OxyColors.CornflowerBlue, () => { return(new OuelletConvexHullAvl3.ConvexHull()); }, (Object obj, Point pt, AlgorithmStat stat) => { var convexHullOnline = obj as OuelletConvexHullAvl3.ConvexHull; if (convexHullOnline == null) { throw new ArgumentException($"argument obj: '{obj}' is invalid."); } Stopwatch stopwatch = Stopwatch.StartNew(); EnumConvexHullPoint result = convexHullOnline.TryAddOnePoint(pt); stopwatch.Stop(); stat.TimeSpanCSharp = stat.TimeSpanCSharp.Add(stopwatch.Elapsed); return(result == EnumConvexHullPoint.ConvexHullPoint); }, (Object obj) => { var ch = obj as OuelletConvexHullAvl3.ConvexHull; if (ch == null) { throw new ArgumentException($"argument obj: '{obj}' is invalid."); } return(ch.GetResultsAsArrayOfPoint()); })); AlgoIndexOuelletConvexHullAvl2OnlineWithOnlineInterface = _algorithms.Count - 1; _algorithms.Add(new AlgorithmStandard(AlgorithmType.SmallestEnclosingCircle, "Smallest Enclosing Circle", "Rod Stephens, Rod Stephens", "Slow Slow Slow. Select max 500 pts.", OxyPlot.OxyColors.Red, (points, algorithmStat) => { var stopwatch = Stopwatch.StartNew(); Point center = new Point(0, 0); double radius = 0; SmallestEnclosingCircle.FindMinimalBoundingCircle(points, out center, out radius); stopwatch.Stop(); if (algorithmStat != null) { algorithmStat.TimeSpanCSharp = stopwatch.Elapsed; } Point[] result = CircleHelper.CreateCircleWithPoints(center, radius, 200); // 200 seems ok :-) return(result); })); AlgoIndexSmallestEnclosingCircle = _algorithms.Count - 1; _algorithms.Add(new AlgorithmStandard(AlgorithmType.SmallestEnclosingCircle, "Smallest Enclosing Circle from ConvexHull (Ouellet ST)", "Rod Stephens, Rod Stephens", "Same algo as previous but points are first filtered by the Convex Hull algo", OxyPlot.OxyColors.Blue, (points, algorithmStat) => { var stopwatch = Stopwatch.StartNew(); ConvexHull convexHull = new ConvexHull(points); convexHull.CalcConvexHull(ConvexHullThreadUsage.OnlyOne); Point[] hullPoints = convexHull.GetResultsAsArrayOfPoint(); Point center = new Point(0, 0); double radius = 0; SmallestEnclosingCircle.FindMinimalBoundingCircle(hullPoints, out center, out radius); stopwatch.Stop(); if (algorithmStat != null) { algorithmStat.TimeSpanCSharp = stopwatch.Elapsed; } Point[] result = CircleHelper.CreateCircleWithPoints(center, radius, 200); // 200 seems ok :-) return(result); })); AlgoIndexSmallestEnclosingCircle = _algorithms.Count - 1; }
public static void ComputeMinEnclosingCircle(ObjectId[] idArray, CoordinateSystem actualCS) { Editor editor = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument.Editor; Database workingDatabase = HostApplicationServices.WorkingDatabase; ProgressMeter progressMeter = new ProgressMeter(); MessageFilter value = new MessageFilter(); System.Windows.Forms.Application.AddMessageFilter(value); try { using (Transaction transaction = workingDatabase.TransactionManager.StartTransaction()) { progressMeter.SetLimit(idArray.Length); if ((double)idArray.Length > 10000.0) { progressMeter.Start("Computing min. enclosing circle..."); } CoordinateTransformator coordinateTransformator = new CoordinateTransformator(CoordinateSystem.Global(), actualCS); CoordinateTransformator inverseTransformation = coordinateTransformator.GetInverseTransformation(); BlockTable blockTable = (BlockTable)transaction.GetObject(workingDatabase.BlockTableId, (OpenMode)1); BlockTableRecord blockTableRecord = (BlockTableRecord)transaction.GetObject(blockTable[BlockTableRecord.ModelSpace], (OpenMode)1); ObjectId layerId = DBManager.CurrentLayerId(); DBManager.CurrentLayerName(); PointSet pointSet = new PointSet(); for (int i = 0; i < idArray.Length; i++) { progressMeter.MeterProgress(); DBPoint dBPoint = (DBPoint)transaction.GetObject(idArray[i], (OpenMode)0, true); Point point = new Point(dBPoint.Position.X, dBPoint.Position.Y, dBPoint.Position.Z); coordinateTransformator.Transform(point); pointSet.Add(point); } ConvexHull2d convexHull2d = new ConvexHull2d(); convexHull2d.InitialPoints = pointSet; convexHull2d.ComputeHull(); PointSet vertices = convexHull2d.Vertices; double z = vertices[0].Z; for (int j = 0; j < vertices.Count; j++) { vertices[j].Z = z; } SmallestEnclosingCircle smallestEnclosingCircle = new SmallestEnclosingCircle(vertices); ngeometry.VectorGeometry.Circle circle = smallestEnclosingCircle.ComputeCircle(); Point center = circle.Center; Point point2 = circle.NormalVector.ToPoint(); inverseTransformation.Transform(center); inverseTransformation.Transform(point2); Autodesk.AutoCAD.DatabaseServices.Circle circle2 = new Autodesk.AutoCAD.DatabaseServices.Circle(new Autodesk.AutoCAD.Geometry.Point3d(center.X, center.Y, center.Z), new Autodesk.AutoCAD.Geometry.Vector3d(point2.X, point2.Y, point2.Z), circle.Radius); circle2.LayerId = (layerId); blockTableRecord.AppendEntity(circle2); transaction.AddNewlyCreatedDBObject(circle2, true); editor.WriteMessage("\nMinimum enclosing circle properties:"); editor.WriteMessage("\n------------------------------------"); editor.WriteMessage("\nRadius : " + circle.Radius.ToString(DBManager.GetFormatFromLUPREC())); editor.WriteMessage("\nArea : " + circle.Area.ToString(DBManager.GetFormatFromLUPREC())); editor.WriteMessage("\nPerimeter length: " + circle.Circumference.ToString(DBManager.GetFormatFromLUPREC())); transaction.Commit(); } progressMeter.Stop(); } catch (System.Exception ex) { progressMeter.Stop(); throw; } }