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);
        }
예제 #3
0
        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);
            }
        }
예제 #4
0
 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();
     }
 }
예제 #5
0
        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();
                }
            }
        }
예제 #6
0
        //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();
            }
        }
예제 #7
0
        /// <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));
        }
예제 #8
0
        public void NotEqualTest()
        {
            float test = 0f;

            Assert.IsTrue(test.AlmostEqual(0.1f, 0.11f));
        }
예제 #9
0
        public void AlmostEqualOnNegativeNumbersTest()
        {
            float test = -10f;

            Assert.IsTrue(test.AlmostEqual(-11.1f, 1.1f));
        }
예제 #10
0
        /// <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++;
            }
        }
예제 #11
0
 /// <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));
 }
예제 #13
0
 public static bool IsGreaterOrEqual(this float left, float right)
 {
     return(left.IsLarger(right, float.Epsilon) || left.AlmostEqual(right, float.Epsilon));
 }
예제 #14
0
 public static bool IsLessOrEqual(this float left, float right)
 {
     return(left.IsSmaller(right, float.Epsilon) || left.AlmostEqual(right, float.Epsilon));
 }