public void AlmostEqualTest() { float num = 5f; Assert.That(num.AlmostEqual(5.0001f), Is.True); Assert.That(num.AlmostEqual(5.1f), Is.False); }
private void OnCompositionTargetRendering(object sender, object e) { // QUESTION 2 // What I've noticed is that I have to manually stop and // start the animation otherwise the Offset.Y is 0. Why? // _refreshIconVisual.StopAnimation("Offset.Y"); // QUESTION 3 // Why is the Translation always (0,0,0)? // //Vector3 translation; //var translationStatus = _scrollerViewerManipulation.TryGetVector3("Translation", out translation); //switch (translationStatus) //{ // case CompositionGetValueStatus.Succeeded: // Debug.WriteLine($"ScrollViewer's Translation Y: {translation.Y}"); // break; // case CompositionGetValueStatus.TypeMismatch: // case CompositionGetValueStatus.NotFound: // default: // break; //} _refreshIconOffsetY = _refreshIconVisual.Offset.Y; //Debug.WriteLine($"RefreshIcon's Offset Y: {_refreshIconOffsetY}"); // Question 4 // It's not always the case here as the user can pull it all the way down and then push it back up to // CANCEL a refresh!! Though I cannot seem to find an easy way to detect right after the finger is lifted. // DirectManipulationCompleted is called too late. // What might be really helpful is to have a DirectManipulationDelta event with velocity and other values. // // At the moment I am calculating the time difference between the list gets pulled all the way down and rolled back up. // if (!_refresh) { _refresh = _refreshIconOffsetY.AlmostEqual(IconElementMaxPulledOffsetY); } if (_refreshIconOffsetY.AlmostEqual(IconElementMaxPulledOffsetY)) { _pulledDownTime = DateTime.Now; //Debug.WriteLine($"When the list is pulled down: {_pulledDownTime}"); // Stop the Opacity animation on the RefreshIcon and the Offset.Y animation on the Border (ScrollViewer's host) _refreshIconVisual.StopAnimation("Opacity"); _borderVisual.StopAnimation("Offset.Y"); } if (_refresh && _refreshIconOffsetY <= 1) { _restoredTime = DateTime.Now; //Debug.WriteLine($"When the list is back up: {_restoredTime}"); } _refreshIconVisual.StartAnimation("Offset.Y", _offsetAnimation); }
public static void AlmostEqual(float expected, float actual, int decimalPlaces) { if (float.IsNaN(expected) && float.IsNaN(actual)) { return; } if (!expected.AlmostEqual(actual, decimalPlaces)) { Assert.Fail("Not equal within {0} places. Expected:{1}; Actual:{2}", decimalPlaces, expected, actual); } }
public void SetScale(GameObject go, float timeScale) { if (timeScale.AlmostEqual(1f, 0.001f)) { ResetScale(go); } else { timeScaleList.Add(new KeyValuePair <GameObject, float>(go, timeScale)); ApplyScale(); } }
void Update() { if (isDuckOn) { if (!_duckBattleSpeed.AlmostEqual(duckBattleSpeed)) { if (duckBattleSpeed < 0f) { duckBattleSpeed = 0f; } _duckBattleSpeed = duckBattleSpeed; speed = duckBattleSpeed; } } if (_isDuckOn != isDuckOn) { _isDuckOn = isDuckOn; if (!_isDuckOn) { SetSpeed(); } } }
//check TDB for long curves and determine each section's position/elev in the curve public SuperElevation(Simulator simulator) { if (null == simulator) { throw new ArgumentNullException(nameof(simulator)); } Curves = new List <List <TrackVectorSection> >(); Sections = new Dictionary <int, List <TrackVectorSection> >(); MaximumAllowedM = 0.07f + simulator.Settings.UseSuperElevation / 100f;//max allowed elevation controlled by user setting List <TrackVectorSection> SectionList = new List <TrackVectorSection>(); foreach (TrackNode node in simulator.TrackDatabase.TrackDB.TrackNodes) { TrackVectorNode trackVectorNode = node as TrackVectorNode; if (trackVectorNode == null) { continue; } bool StartCurve = false; int CurveDir = 0; float Len = 0.0f; SectionList.Clear(); int i = 0; int count = trackVectorNode.TrackVectorSections.Length; foreach (TrackVectorSection section in trackVectorNode.TrackVectorSections)//loop all curves { i++; TrackSection sec = simulator.TSectionDat.TrackSections.Get(section.SectionIndex); if (sec == null) { continue; } if (Math.Abs(sec.Width - (simulator.Settings.SuperElevationGauge / 1000f)) > 0.2) { continue;//the main route has a gauge different than mine } float angle = sec.Angle; if (sec.Curved && !angle.AlmostEqual(0f, 0.01f)) //a good curve { if (i == 1 || i == count) { //if (theCurve.Radius * (float)Math.Abs(theCurve.Angle * 0.0174) < 15f) continue; } //do not want the first and last piece of short curved track to be in the curve (they connected to switches) if (!StartCurve) //we are beginning a curve { StartCurve = true; CurveDir = Math.Sign(sec.Angle); Len = 0f; } else if (CurveDir != Math.Sign(sec.Angle)) //we are in curve, but bending different dir { MarkSections(simulator, SectionList, Len); //treat the sections encountered so far, then restart with other dir CurveDir = Math.Sign(sec.Angle); SectionList.Clear(); Len = 0f; //StartCurve remains true as we are still in a curve } Len += sec.Radius * (float)Math.Abs(MathHelper.ToRadians(sec.Angle)); SectionList.Add(section); } else //meet a straight line { if (StartCurve) //we are in a curve, need to finish { MarkSections(simulator, SectionList, Len); Len = 0f; SectionList.Clear(); } StartCurve = false; } } if (StartCurve) // we are in a curve after looking at every section { MarkSections(simulator, SectionList, Len); } SectionList.Clear(); } }
/// <summary> /// Builds a SuperElevation LOD to SuperElevationProfile specifications as one vertex buffer and one index buffer. /// The order in which the buffers are built reflects the nesting in the TrProfile. The nesting order is: /// (Polylines (Vertices)). All vertices and indices are built contiguously for an LOD. /// </summary> /// <param name="viewer">Viewer.</param> /// <param name="worldPosition">WorldPosition.</param> /// <param name="iLOD">Index of LOD mesh to be generated from profile.</param> /// <param name="iLODItem">Index of LOD mesh to be generated from profile.</param> public new ShapePrimitive BuildPrimitive(Viewer viewer, WorldPosition worldPosition, int iLOD, int iLODItem) { // Call for track section to initialize itself if (DTrackData.IsCurved == 0) { LinearGen(); } else { CircArcGen(); } // Count vertices and indices LOD lod = (LOD)TrProfile.LODs[iLOD]; LODItem lodItem = (LODItem)lod.LODItems[iLODItem]; NumVertices = (int)(lodItem.NumVertices * (NumSections + 1)); NumIndices = (short)(lodItem.NumSegments * NumSections * 6); // (Cells x 2 triangles/cell x 3 indices/triangle) // Allocate memory for vertices and indices VertexList = new VertexPositionNormalTexture[NumVertices]; // numVertices is now aggregate TriangleListIndices = new short[NumIndices]; // as is NumIndices // Build the mesh for lod VertexIndex = 0; IndexIndex = 0; whichCase = 0; //0: no elevation (MaxElev=0), 1: start (startE = 0, Max!=end), //2: end (end=0, max!=start), 3: middle (start>0, end>0), 4: start and finish in one if (StartElev.AlmostEqual(0f, 0.001f) && MaxElev.AlmostEqual(0f, 0.001f) && EndElv.AlmostEqual(0f, 0.001f)) { whichCase = 0; //no elev } else if (StartElev.AlmostEqual(0f, 0.001f) && EndElv.AlmostEqual(0f, 0.001f)) { whichCase = 4; //finish/start in one } else if (StartElev.AlmostEqual(0f, 0.001f) && !EndElv.AlmostEqual(0f, 0.001f)) { whichCase = 1; //start } else if (EndElv.AlmostEqual(0f, 0.001f) && !StartElev.AlmostEqual(0f, 0.001f)) { whichCase = 2; //finish } else { whichCase = 3; //in middle } Matrix PreRotation = Matrix.Identity; elevated = MaxElev; if (whichCase == 3 || whichCase == 2) { PreRotation = Matrix.CreateRotationZ(-elevated * Math.Sign(DTrackData.param1)); } //if section is in the middle of curve, will only rotate the first set of vertex, others will follow the same rotation prevRotation = 0f; Vector3 tmp; // Initial load of baseline cross section polylines for this LOD only: foreach (Polyline pl in lodItem.Polylines) { foreach (Vertex v in pl.Vertices) { tmp = new Vector3(v.Position.X, v.Position.Y, v.Position.Z); if (whichCase == 3 || whichCase == 2) { tmp = Vector3.Transform(tmp, PreRotation); prevRotation = MaxElev; } VertexList[VertexIndex].Position = tmp; VertexList[VertexIndex].Normal = v.Normal; VertexList[VertexIndex].TextureCoordinate = v.TexCoord; VertexIndex++; } } // Initial load of base cross section complete // Now generate and load subsequent cross sections OldRadius = -center; uint stride = VertexIndex; offSet = 0; for (uint i = 0; i < NumSections; i++) { currentRotation = determineRotation(DTrackData.param1); elevated = currentRotation - prevRotation; prevRotation = currentRotation; if (DTrackData.param1 > 0) { elevated *= -1; } foreach (Polyline pl in lodItem.Polylines) { uint plv = 0; // Polyline vertex index foreach (Vertex v in pl.Vertices) { if (DTrackData.IsCurved == 0) { LinearGen(stride, pl); // Generation call } else { CircArcGen(stride, pl); } if (plv > 0) { // Sense for triangles is clockwise // First triangle: TriangleListIndices[IndexIndex++] = (short)VertexIndex; TriangleListIndices[IndexIndex++] = (short)(VertexIndex - 1 - stride); TriangleListIndices[IndexIndex++] = (short)(VertexIndex - 1); // Second triangle: TriangleListIndices[IndexIndex++] = (short)VertexIndex; TriangleListIndices[IndexIndex++] = (short)(VertexIndex - stride); TriangleListIndices[IndexIndex++] = (short)(VertexIndex - 1 - stride); } VertexIndex++; plv++; } } OldRadius = radius; // Get ready for next segment offSet++; } // Create and populate a new ShapePrimitive var indexBuffer = new IndexBuffer(viewer.GraphicsDevice, typeof(short), NumIndices, BufferUsage.WriteOnly); indexBuffer.SetData(TriangleListIndices); return(new ShapePrimitive(lodItem.LODMaterial, new SharedShape.VertexBufferSet(VertexList, viewer.GraphicsDevice), indexBuffer, 0, NumVertices, NumIndices / 3, new[] { -1 }, 0)); }
public void NotEqualTest() { float test = 0f; Assert.IsTrue(test.AlmostEqual(0.1f, 0.11f)); }
public void AlmostEqualOnNegativeNumbersTest() { float test = -10f; Assert.IsTrue(test.AlmostEqual(-11.1f, 1.1f)); }
/// <summary> /// Solves the matrix equation Ax = b, where A is the coefficient matrix, b is the /// solution vector and x is the unknown vector. /// </summary> /// <param name="matrix">The coefficient <see cref="Matrix"/>, <c>A</c>.</param> /// <param name="input">The solution <see cref="Vector"/>, <c>b</c>.</param> /// <param name="result">The result <see cref="Vector"/>, <c>x</c>.</param> public void Solve(Matrix matrix, Vector input, Vector result) { // If we were stopped before, we are no longer // We're doing this at the start of the method to ensure // that we can use these fields immediately. _hasBeenStopped = false; // Parameters checks if (matrix == null) { throw new ArgumentNullException("matrix"); } if (matrix.RowCount != matrix.ColumnCount) { throw new ArgumentException(Resources.ArgumentMatrixSquare, "matrix"); } if (input == null) { throw new ArgumentNullException("input"); } if (result == null) { throw new ArgumentNullException("result"); } if (result.Count != input.Count) { throw new ArgumentException(Resources.ArgumentVectorsSameLength); } if (input.Count != matrix.RowCount) { throw new ArgumentException(Resources.ArgumentMatrixDimensions); } // Initialize the solver fields // Set the convergence monitor if (_iterator == null) { _iterator = Iterator.CreateDefault(); } if (_preconditioner == null) { _preconditioner = new UnitPreconditioner(); } _preconditioner.Initialize(matrix); // Compute r_0 = b - Ax_0 for some initial guess x_0 // In this case we take x_0 = vector // This is basically a SAXPY so it could be made a lot faster Vector residuals = new DenseVector(matrix.RowCount); CalculateTrueResidual(matrix, residuals, result, input); // Choose r~ (for example, r~ = r_0) var tempResiduals = residuals.Clone(); // create seven temporary vectors needed to hold temporary // coefficients. All vectors are mangled in each iteration. // These are defined here to prevent stressing the garbage collector Vector vecP = new DenseVector(residuals.Count); Vector vecPdash = new DenseVector(residuals.Count); Vector nu = new DenseVector(residuals.Count); Vector vecS = new DenseVector(residuals.Count); Vector vecSdash = new DenseVector(residuals.Count); Vector temp = new DenseVector(residuals.Count); Vector temp2 = new DenseVector(residuals.Count); // create some temporary float variables that are needed // to hold values in between iterations float currentRho = 0; float alpha = 0; float omega = 0; var iterationNumber = 0; while (ShouldContinue(iterationNumber, result, input, residuals)) { // rho_(i-1) = r~^T r_(i-1) // dotproduct r~ and r_(i-1) var oldRho = currentRho; currentRho = tempResiduals.DotProduct(residuals); // if (rho_(i-1) == 0) // METHOD FAILS // If rho is only 1 ULP from zero then we fail. if (currentRho.AlmostEqual(0, 1)) { // Rho-type breakdown throw new Exception("Iterative solver experience a numerical break down"); } if (iterationNumber != 0) { // beta_(i-1) = (rho_(i-1)/rho_(i-2))(alpha_(i-1)/omega(i-1)) var beta = (currentRho / oldRho) * (alpha / omega); // p_i = r_(i-1) + beta_(i-1)(p_(i-1) - omega_(i-1) * nu_(i-1)) nu.Multiply(-omega, temp); vecP.Add(temp, temp2); temp2.CopyTo(vecP); vecP.Multiply(beta, vecP); vecP.Add(residuals, temp2); temp2.CopyTo(vecP); } else { // p_i = r_(i-1) residuals.CopyTo(vecP); } // SOLVE Mp~ = p_i // M = preconditioner _preconditioner.Approximate(vecP, vecPdash); // nu_i = Ap~ matrix.Multiply(vecPdash, nu); // alpha_i = rho_(i-1)/ (r~^T nu_i) = rho / dotproduct(r~ and nu_i) alpha = currentRho * 1 / tempResiduals.DotProduct(nu); // s = r_(i-1) - alpha_i nu_i nu.Multiply(-alpha, temp); residuals.Add(temp, vecS); // Check if we're converged. If so then stop. Otherwise continue; // Calculate the temporary result. // Be careful not to change any of the temp vectors, except for // temp. Others will be used in the calculation later on. // x_i = x_(i-1) + alpha_i * p^_i + s^_i vecPdash.Multiply(alpha, temp); temp.Add(vecSdash, temp2); temp2.CopyTo(temp); temp.Add(result, temp2); temp2.CopyTo(temp); // Check convergence and stop if we are converged. if (!ShouldContinue(iterationNumber, temp, input, vecS)) { temp.CopyTo(result); // Calculate the true residual CalculateTrueResidual(matrix, residuals, result, input); // Now recheck the convergence if (!ShouldContinue(iterationNumber, result, input, residuals)) { // We're all good now. return; } // Continue the calculation iterationNumber++; continue; } // SOLVE Ms~ = s _preconditioner.Approximate(vecS, vecSdash); // temp = As~ matrix.Multiply(vecSdash, temp); // omega_i = temp^T s / temp^T temp omega = temp.DotProduct(vecS) / temp.DotProduct(temp); // x_i = x_(i-1) + alpha_i p^ + omega_i s^ temp.Multiply(-omega, residuals); residuals.Add(vecS, temp2); temp2.CopyTo(residuals); vecSdash.Multiply(omega, temp); result.Add(temp, temp2); temp2.CopyTo(result); vecPdash.Multiply(alpha, temp); result.Add(temp, temp2); temp2.CopyTo(result); // for continuation it is necessary that omega_i != 0.0 // If omega is only 1 ULP from zero then we fail. if (omega.AlmostEqual(0, 1)) { // Omega-type breakdown throw new Exception("Iterative solver experience a numerical break down"); } if (!ShouldContinue(iterationNumber, result, input, residuals)) { // Recalculate the residuals and go round again. This is done to ensure that // we have the proper residuals. // The residual calculation based on omega_i * s can be off by a factor 10. So here // we calculate the real residual (which can be expensive) but we only do it if we're // sufficiently close to the finish. CalculateTrueResidual(matrix, residuals, result, input); } iterationNumber++; } }
/// <summary>Extension method used to determine if two values are very close to equal, based on /// the Epsilon, the .NET defined potential error between equal floating point numbers.</summary> /// <param name="left">First item to be compared.</param> /// <param name="right">Second item to be compared.</param> /// <returns>Returns true if left - right is less than or equal to Epsilon, and false otherwise.</returns> public static bool AlmostEqual(this float left, float right) { return(left.AlmostEqual(right, float.Epsilon)); }
public static bool AlmostZero(this float f, float tolerance = 0.001f) { return(f.AlmostEqual(0f, tolerance)); }
public static bool IsGreaterOrEqual(this float left, float right) { return(left.IsLarger(right, float.Epsilon) || left.AlmostEqual(right, float.Epsilon)); }
public static bool IsLessOrEqual(this float left, float right) { return(left.IsSmaller(right, float.Epsilon) || left.AlmostEqual(right, float.Epsilon)); }