public void ArcLength() { double radius = 50; double angle = 50; Assert.Equal(43.633231299858238, CircleHelper.ArcLength(radius, angle)); }
public void ChordLength() { double radius = 50; double angle = 50; Assert.Equal(42.26182617407, System.Math.Round(CircleHelper.ChordLength(radius, angle), 12)); }
public void ArcLengthRound12() { double radius = 50; double angle = 50; Assert.Equal(43.633231299858, System.Math.Round(CircleHelper.ArcLength(radius, angle), 12)); }
private void BuildRings() { detailCount = 40; ringClrs = new int[] { Color.Red.ToArgb(), Color.Green.ToArgb(), Color.Blue.ToArgb() }; vBuffer = new VertexBuffer(typeof(CustomVertex.PositionColored), (detailCount + 1) * 3, gDevice, Usage.WriteOnly, CustomVertex.PositionColored.Format, Pool.Managed); CustomVertex.PositionColored[] verts = (CustomVertex.PositionColored[])vBuffer.Lock(0, LockFlags.None); Vector2[] points; CircleHelper.CalcCirclePointsCCW(detailCount + 1, 1, new Vector2(), out points); BuildRingOnX(verts, (detailCount + 1) * 0, ringClrs[0], points); BuildRingOnY(verts, (detailCount + 1) * 1, ringClrs[1], points); BuildRingOnZ(verts, (detailCount + 1) * 2, ringClrs[2], points); vBuffer.Unlock(); }
/// <summary> /// Rotates the current active object. /// </summary> private void Rotate() { // only rotate if the current frame is not skipped currentPauseFrames--; if (currentPauseFrames > 0 || Vector3.Distance(lastPos, GetHandPos()) > maxMovementPerFrame) { return; } currentPauseFrames = pauseFrames; // save the current hand position lastHandPositions.Add(GetHandPos()); // get current hand velocity float velocity = GetHandVelocity(); // rotate a object around a primary axis if there are enough past hand positions if (lastHandPositions.Count > (rotationTrailSize / 3) * 3) { // ensure that the number of past hand position does not exceed the rotationTrailSize lastHandPositions.RemoveAt(0); // don't rotate if hand is to slow if (velocity < minVelocityForRotation) { return; } // calculate the average normal vector of the last triples Vector3 normal = GetAverageNormalVector(lastHandPositions); // check if the angle between the average normal vector and a primary axis is smaller than the given treshould Vector3 rotationAxis = Vector3.zero; if (Vector3.Angle(Vector3.forward, normal) <= fixAxisAngleThreshold) { rotationAxis = Vector3.forward; } else if (Vector3.Angle(Vector3.back, normal) <= fixAxisAngleThreshold) { rotationAxis = Vector3.back; } else if (Vector3.Angle(Vector3.right, normal) <= fixAxisAngleThreshold) { rotationAxis = Vector3.right; } else if (Vector3.Angle(Vector3.left, normal) <= fixAxisAngleThreshold) { rotationAxis = Vector3.left; } else if (Vector3.Angle(Vector3.up, normal) <= fixAxisAngleThreshold) { rotationAxis = Vector3.up; } else if (Vector3.Angle(Vector3.down, normal) <= fixAxisAngleThreshold) { rotationAxis = Vector3.down; } // rotate object around the detected primary axis (if there is one) if (rotationAxis != Vector3.zero) { // determine the circle described by the hand movements Vector2 v1 = lastHandPositions[lastHandPositions.Count - 3].ToVector2(rotationAxis); Vector2 v2 = lastHandPositions[lastHandPositions.Count - 2].ToVector2(rotationAxis); Vector2 v3 = lastHandPositions[lastHandPositions.Count - 1].ToVector2(rotationAxis); CircleHelper.FindCircle(v1, v2, v3, out Vector2 center, out float radius); // calculate the moved angle Vector2 c_v2 = v2 - center; Vector2 c_v3 = v3 - center; float angle = Vector2.Angle(c_v2, c_v3); if (!float.IsNaN(angle)) { float factor; // linearly increase rotation amount for the first velocity window if (velocity < midVelocityForRotation) { factor = minLoops + ((velocity - minVelocityForRotation) / (midVelocityForRotation - minVelocityForRotation)) * (midLoops - minLoops); } // exponentially increase rotation amount for the second velocity window else { float cmVelocity = (velocity - midVelocityForRotation) * 100; factor = Mathf.Max(midMaxLoops - cmVelocity * cmVelocity * 0.0005f, maxLoops); } // don't rotate if jitter is detected if (angle > maxAngle && GetTrackingConfidence() > minConfidence) { return; } angle = angle / factor; currentTakeable.transform.RotateAround(currentTakeable.transform.position, rotationAxis, angle); ManageRotationLever(rotationAxis, angle); } } } }
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 void Circumference() { double radius = 50; Assert.Equal(314.15926535897933, CircleHelper.Circumference(radius)); }
public void Area() { double radius = 50; Assert.Equal(7853.981633974483, CircleHelper.Area(radius)); }