예제 #1
0
        public static Matrix <float> CalculateRotationMatrix(Vector <float> rotationVector)
        {
            var rad            = rotationVector.Storage.AsArray().Select(x => (float)Trig.DegreeToRadian(x)).ToArray();
            var radianRotation = new DenseVector(rad);

            float cosX = (float)Math.Cos(radianRotation[0]);
            float sinX = (float)Math.Sin(radianRotation[0]);
            float cosY = (float)Math.Cos(radianRotation[1]);
            float sinY = (float)Math.Sin(radianRotation[1]);
            float cosZ = (float)Math.Cos(radianRotation[2]);
            float sinZ = (float)Math.Sin(radianRotation[2]);

            Matrix xRotationMatrix = new DenseMatrix(4, 4);

            xRotationMatrix.SetRow(0, new [] { 1f, 0f, 0f, 0f });
            xRotationMatrix.SetRow(1, new [] { 0f, cosX, -sinX, 0f });
            xRotationMatrix.SetRow(2, new [] { 0f, sinX, cosX, 0f });
            xRotationMatrix.SetRow(3, new [] { 0f, 0f, 0f, 1f });

            Matrix yRotationMatrix = new DenseMatrix(4, 4);

            yRotationMatrix.SetRow(0, new[] { cosY, 0f, sinY, 0f });
            yRotationMatrix.SetRow(1, new[] { 0f, 1f, 0f, 0f });
            yRotationMatrix.SetRow(2, new[] { -sinY, 0f, cosY, 0f });
            yRotationMatrix.SetRow(3, new[] { 0f, 0f, 0f, 1f });

            Matrix zRotationMatrix = new DenseMatrix(4, 4);

            zRotationMatrix.SetRow(0, new[] { cosZ, -sinZ, 0f, 0f });
            zRotationMatrix.SetRow(1, new[] { sinZ, cosZ, 0f, 0f });
            zRotationMatrix.SetRow(2, new[] { 0f, 0f, 1f, 0f });
            zRotationMatrix.SetRow(3, new[] { 0f, 0f, 0f, 1f });

            return(zRotationMatrix * yRotationMatrix * xRotationMatrix);
        }
예제 #2
0
        public static float[] NextPoint(float x, float y, float a, float dist)
        {
            var newx = x + (Trig.Sin(Trig.DegreeToRadian(a)) * dist);
            var newy = y + (Trig.Cos(Trig.DegreeToRadian(a)) * dist);

            return(new[] { Convert.ToSingle(newx), Convert.ToSingle(newy) });
        }
        public void Priority_OfACircleThrough0N45EAnd45N0EAnd0N45W_ShouldBeCorrect()
        {
            // Fixture setup
            var arcA = new Arc {
                Site = Utilities.SiteAt(90, 45)
            };
            var arcB = new Arc {
                Site = Utilities.SiteAt(45, 0)
            };
            var arcC = new Arc {
                Site = Utilities.SiteAt(90, -45)
            };

            var circle = new CircleEvent(arcA, arcB, arcC);

            // Exercise system
            var result = circle.Priority;

            // Verify outcome
            var expectedResult = -Trig.Cosine(Trig.DegreeToRadian(135)) - 1;

            Debug.WriteLine(expectedResult);

            var failureString = String.Format("Priority was {0}", result);

            Assert.True(Number.AlmostEqual(result, expectedResult, Tolerance), failureString);

            // Teardown
        }
예제 #4
0
        public Camera()
        {
            Eye    = DenseVector.OfArray(new[] { 1000000.0, 1000000.0, 1000000.0 });
            Target = DenseVector.OfArray(new[] { 0.0, 0.0, 0.0 });
            Up     = DenseVector.OfArray(new[] { 0.0, 1.0, 0.0 });
            Fov    = Trig.DegreeToRadian(40.0);

            SetViewMatrix();
            SetProjectionMatrix();
        }
예제 #5
0
        public XyzPoint ToXyzPoint()
        {
            //var dec = DmsAngle.FromDecimal(Declination);

            //var b = Math.Sign(Declination) *
            //        (Math.Abs(dec.Degrees) + dec.Minutes / 60.0 + dec.Seconds / 3600.0);

            var ra  = Trig.DegreeToRadian(RightAscension);
            var dec = Trig.DegreeToRadian(Declination);

            return(new XyzPoint
            {
                X = Distance * Math.Cos(dec) * Math.Cos(ra),
                Y = Distance * Math.Cos(dec) * Math.Sin(ra),
                Z = Distance * Math.Sin(dec)
            });
        }
예제 #6
0
        public void Rotate(Vector3D rotationAmount)
        {
            var rotationAroundX = new Matrix3D();

            rotationAroundX.Rotate(new Quaternion(Right, Trig.DegreeToRadian(rotationAmount.Y)));

            var rotationAroundY = new Matrix3D();

            rotationAroundY.Rotate(new Quaternion(Up, Trig.DegreeToRadian(rotationAmount.X)));

            var rotationMatrix = Matrix3D.Multiply(rotationAroundX, rotationAroundY);

            Direction = Vector3D.Multiply(Direction, rotationMatrix);
            Up        = Vector3D.Multiply(Up, rotationMatrix);

            UpdateSettings();
        }
 public void CanConvertDegreeToRadian()
 {
     AssertHelpers.AlmostEqual(Math.PI / 2, Trig.DegreeToRadian(90), 15);
 }
예제 #8
0
 /// <summary>
 /// Converts an angle to a 2d vector that points in the direction of the angle.
 /// </summary>
 /// <param name="angle">The angle in degrees</param>
 /// <returns>A 2d vector</returns>
 public static Vector <float> AngleToVector(float angle)
 {
     return(new DenseVector(new[] { (float)Math.Cos(Trig.DegreeToRadian(angle)), (float)Math.Sin(Trig.DegreeToRadian(angle)) }));
 }
예제 #9
0
파일: Basic.cs 프로젝트: janarthv/Sunrise
 public static double DegreeToRadian(double degree)
 {
     return(Trig.DegreeToRadian(degree));
 }
예제 #10
0
        /// <summary>
        /// Spawns cubes upon an arc of an ellipse.
        /// </summary>
        /// <param name="n"> The number of cubes. </param>
        /// <param name="center"> The center of the ellipse. </param>
        /// <param name="sectorChordLength"> The length of the arc's chord. </param>
        /// <param name="semiMinorAxisLength"> Half the length of the minor axis. </param>
        /// <param name="sectorAngleDeg"> The angular length of the arc in degrees. </param>
        /// <param name="cubePrefab"> The template for the cubes. </param>
        /// <param name="parent"> The parent of the cubes structure. </param>
        /// <returns> Returns the GameObject containing the cubes, whose parent is 'parent'. </returns>
        /// <remarks> This function is definitely very time-expensive. Use sparingly. </remarks>
        private static GameObject SpawnEllipseCubes(int n, Vector3 center, float sectorChordLength, float semiMinorAxisLength, float sectorAngleDeg, GameObject cubePrefab, Transform parent = null)
        {
            // TODO: Find constraints for every parameter and variable (minimum and maximum values)
            //       Problem: for some combination of input parameters, the FindRoots.OfFunction method fails with an exception:
            //                "ArithmeticException: Function does not accept floating point Not-a-Number values."
            //       Sample parameters: (16,, 12.0f, 6.0f, 90°,,)

            #region Maths

            /*
             * C: center of the ellipse
             * R: sectorChordLength, the length of the chord
             * a: half the length of the major axis of the ellipse
             * b: semiMinorAxisLength, half the length of the minor axis of the ellipse
             * α: sectorAngleDeg, the sector extension in degrees, from (90° - α/2) to (90° + α/2) counterclock-wise
             * n: number of cubes
             *
             *
             * § 1) ELLIPSE'S EQUATIONS
             *
             * ξ(ϑ): ellipse's parametric equations [-180° ≤ ϑ ≤ 180°]
             *     where ϑ is the angle of (ξˣ(ϑ), ξʸ(ϑ)) with the major axis of the ellipse itself
             *                       ___________________________
             *   ξˣ(ϑ) = a b cos(ϑ) √(a² sin²(ϑ) + b² cos²(ϑ))⁻¹
             *                       ___________________________
             *   ξʸ(ϑ) = a b sin(ϑ) √(a² sin²(ϑ) + b² cos²(ϑ))⁻¹
             *
             * A = ξ(90° + α/2)
             * B = ξ(90° - α/2)
             *
             *     __                   _______________________________
             * R = AB = 2 a b sin(α/2) √(a² cos²(α/2) + b² sin²(α/2))⁻¹
             *      _________________________________________                   _______________________
             * a = √(b² R² tan²(α/2)) / (4 b² tan²(α/2) - R²) = (b R tan(α/2)) √(4 b² tan²(α/2) - R²)⁻¹
             *
             *
             * § 2) CUBES PLACEMENT
             *      A _____________________
             * L = ∫(√D[ξˣ(ϑ)]² + D[ξʸ(ϑ)]²)dϑ: length of arc AB
             *    B
             * l = L/n: distance between each cube's center on the arc
             *
             * θᵢ: angle of the iᵗʰ arc segment; arc length to the iᵗʰ arc segment = i l
             * θᵢ = FindRoot[∫(D[ξˣ(ϑ)]² + D[ξʸ(ϑ)]²)dϑ = i l]   😭
             *
             * Pᵢ = ξ(θᵢ): position of the iᵗʰ cube
             *
             *
             * § 3) CUBES' SIDE LENGTH
             * Let Pᵢ and Pⱼ be the positions of two consecutive cubes (j = i + 1) with angles θᵢ and θⱼ.
             * Let Pₖ be a third point placed at the same arc-distance from both Pᵢ and Pⱼ; the angle of Pₖ is θₖ.
             *
             * rₖ: line from C to Pₖ
             * rᵢ: line from C to Pᵢ
             * rⱼ: line from C to Pⱼ
             *
             * M: parametric point on rₖ
             * dᵢ: segment MPᵢ
             * dⱼ: segment MPⱼ
             *
             *
             * M = (mˣ, mʸ) = (mˣ, mˣ tan(θₖ))
             *       ____________________________________
             * dᵢ = √(x(Pᵢ) - mˣ)² + (y(Pᵢ) - mˣ tan(θₖ))²
             *       ____________________________________
             * dⱼ = √(x(Pⱼ) - mˣ)² + (y(Pⱼ) - mˣ tan(θₖ))²
             *
             * ASSERTION
             * dᵢ = dⱼ = d: dᵢ and dⱼ are the semi-diagonals of the two squares
             *
             * (x(Pᵢ) - mˣ)² + (y(Pᵢ) - mˣ tan(θₖ))² = (x(Pⱼ) - mˣ)² + (y(Pⱼ) - mˣ tan(θₖ))²
             * x(Pᵢ)² + (mˣ)² - 2 x(Pᵢ) mˣ + y(Pᵢ)² + (mˣ tan(θₖ))² - 2 y(Pᵢ) mˣ tan(θₖ)  =  x(Pⱼ)² + (mˣ)² - 2 x(Pⱼ) mˣ + y(Pⱼ)² + (mˣ tan(θₖ))² - 2 y(Pⱼ) mˣ tan(θₖ)
             * x(Pᵢ)² - 2 x(Pᵢ) mˣ + y(Pᵢ)² - 2 y(Pᵢ) mˣ tan(θₖ)  =  x(Pⱼ)² - 2 x(Pⱼ) mˣ + y(Pⱼ)² - 2 y(Pⱼ) mˣ tan(θₖ)
             * 2 x(Pⱼ) mˣ + 2 y(Pⱼ) mˣ tan(θₖ) - 2 x(Pᵢ) mˣ - 2 y(Pᵢ) mˣ tan(θₖ)  =  x(Pⱼ)² + y(Pⱼ)² - x(Pᵢ)² - y(Pᵢ)²
             * 2 mˣ (x(Pⱼ) + y(Pⱼ) tan(θₖ) - x(Pᵢ) - y(Pᵢ) tan(θₖ))  =  x(Pⱼ)² + y(Pⱼ)² - x(Pᵢ)² - y(Pᵢ)²
             *
             *              x(Pⱼ)² + y(Pⱼ)² - x(Pᵢ)² - y(Pᵢ)²
             * mˣ = ——————————————————————————————————————————————————
             *       2 (x(Pⱼ) + y(Pⱼ) tan(θₖ) - x(Pᵢ) - y(Pᵢ) tan(θₖ))
             *
             * cube's side length = 2 (d/√2)
             *
             */

            #endregion Maths

            double R = sectorChordLength;
            double b = semiMinorAxisLength;

            #region § 1) ELLIPSE'S EQUATION

            double alphaRad      = Trig.DegreeToRadian(sectorAngleDeg);
            double bTanHalfAlpha = b * Trig.Tan(alphaRad / 2.0);
            double a             = (R * bTanHalfAlpha) / Math.Sqrt(4 * bTanHalfAlpha * bTanHalfAlpha - R * R);

            Func <double, double> EllipseX = t =>
            {
                double sin  = Trig.Sin(t);
                double cos  = Trig.Cos(t);
                double aSin = a * sin;
                double bCos = b * cos;
                return((a * bCos) / Math.Sqrt(aSin * aSin + bCos * bCos));
            };
            Func <double, double> EllipseY = t =>
            {
                double sin  = Trig.Sin(t);
                double cos  = Trig.Cos(t);
                double aSin = a * sin;
                double bCos = b * cos;
                return((b * aSin) / Math.Sqrt(aSin * aSin + bCos * bCos));
            };

            #endregion § 1) ELLIPSE'S EQUATION

            #region § 2) CUBES PLACEMENT

            Func <double, double> DEllipseX = Differentiate.FirstDerivativeFunc(EllipseX);
            Func <double, double> DEllipseY = Differentiate.FirstDerivativeFunc(EllipseY);

            Func <double, double> SqrtOfSumOfSquaredDerivatives = t =>
            {
                double x = DEllipseX(t);
                double y = DEllipseY(t);
                return(Math.Sqrt(x * x + y * y));
            };

            Func <double, double, double> AngleToArcLength = (fromRad, toRad) => Integrate.OnClosedInterval(SqrtOfSumOfSquaredDerivatives, fromRad, toRad);
            Func <double, double>         ArcLengthToAngle = arcLength => FindRoots.OfFunction(toRad => AngleToArcLength((Math.PI - alphaRad) / 2, toRad) - arcLength, 0, Math.PI);

            double L = AngleToArcLength((Math.PI - alphaRad) / 2, (Math.PI + alphaRad) / 2);
            double l = L / (n - 1);

            Func <int, object[]> CalculateCubePositionAndAngle = i =>
            {
                double  angle    = ArcLengthToAngle(i * l);
                Vector2 position = new Vector2((float)EllipseX(angle), (float)EllipseY(angle));
                return(new object[] { position, angle });
            };

            #endregion § 2) CUBES PLACEMENT

            #region § 3) CUBES' SIDE LENGTH

            Vector2[] positions    = new Vector2[n];
            double[]  angles       = new double[n];
            double[]  middleAngles = new double[n - 1];
            for (int i = 0; i < n; ++i)
            {
                object[] res = CalculateCubePositionAndAngle(i);
                positions[i] = (Vector2)res[0];
                angles[i]    = (double)res[1];

                if (i > 0)
                {
                    middleAngles[i - 1] = ArcLengthToAngle((2 * i - 1) * l / 2.0);
                }
            }

            double[]           sideLengths = new double[n - 1];
            Func <int, double> SideLength  = j =>
            {
                double xj   = positions[j].x;
                double yj   = positions[j].y;
                double xi   = positions[j - 1].x;
                double yi   = positions[j - 1].y;
                double tanK = Trig.Tan(middleAngles[j - 1]);
                double mx   = (xj * xj + yj * yj - (xi * xi + yi * yi)) / (2.0 * (xj + yj * tanK - (xi + yi * tanK)));
                return(Math.Sqrt((xi - mx) * (xi - mx) + (yi - mx * tanK) * (yi - mx * tanK)) * (2.0 / Math.Sqrt(2.0)));
            };
            for (int i = 1; i < n; ++i)
            {
                sideLengths[i - 1] = SideLength(i);
            }

            float squareSide = (float)sideLengths.Min();

            #endregion § 3) CUBES' SIDE LENGTH

            // Save parent's current local rotation and scale; it will be re-set later
            Quaternion parentRotation = parent?.localRotation ?? Quaternion.identity;
            Vector3    parentScale    = parent?.localScale ?? Vector3.one;
            if (parent != null)
            {
                parent.localRotation = Quaternion.identity;
                parent.localScale    = Vector3.one;
            }

            GameObject cubesContainer = parent?.gameObject ?? new GameObject();
            cubesContainer.name = $"Ellipse_{n}Cubes";
            cubesContainer.transform.localPosition = center;

            // Create the cubes
            for (int i = 0; i < n; ++i)
            {
                GameObject cube = Instantiate(cubePrefab);
                cube.name = $"Cube{i}";
                cube.SetActive(true); // Awake it now, to let it store the prefab's original scale
                cube.transform.localScale    = new Vector3(squareSide, squareSide, squareSide);
                cube.transform.position      = cubesContainer.transform.position + new Vector3(positions[i].x, 0.0f, positions[i].y);
                cube.transform.localRotation = Quaternion.Euler(0.0f, (float)(90.0 - Trig.RadianToDegree(angles[i])), 0.0f);
                cube.transform.parent        = cubesContainer.transform;
            }
            cubesContainer.transform.localRotation = Quaternion.identity;

            // Re-set parent's original local rotation
            if (parent != null)
            {
                parent.localRotation = parentRotation;
                parent.localScale    = parentScale;
            }

            return(cubesContainer);
        }
예제 #11
0
        /// <summary>
        /// Spaws cubes upon a circumference.
        /// </summary>
        /// <param name="n"> Number of cubes. </param>
        /// <param name="center"> Center of the circumference in local coordinates. </param>
        /// <param name="radius"> Radius of the circumference. </param>
        /// <param name="cubePrefab"> Cubes template. </param>
        /// <param name="parent"> Parent of the cubes structure. </param>
        /// <returns> Returns the GameObject containing the cubes, whose parent is 'parent'. </returns>
        private static GameObject SpawnCircCubes(int n, Vector3 center, float radius, GameObject cubePrefab, Transform parent = null)
        {
            #region Maths

            /*
             * C: center; R: radius; δ = 360°/n: deltaDegree
             * P, Q: first and second points on the circumference
             * t: bisectrix of angle PCQ
             * M: parametric point on t
             * p: line through M, perpendicular to PC
             * J: intersection of p and segment PC
             * d: distance from point M to point J
             * l: distance from point P to point J
             *
             * CONDITIONS:
             *  1) 0° ≤ δ ≤ 90°
             *     There should be at least 4 cubes
             *  2) d == l
             *     MJ must be half of the square's side
             *  3) length of segment MC <= R
             *     M must be inside the circumference
             *
             *
             * C = [0, 0];  P = [0, R];  Q = [-R sin(δ), R cos(δ)]
             * random point on bisectrix: B = [-R sin(δ/2), R cos(δ/2)]
             * t: y = -(R cos(δ/2) / R sin(δ/2)) x = -x cotg(δ/2)
             * M = k * B = [-k R sin(δ/2), k R cos(δ/2)]
             * p: y = k R cos(δ/2)
             * J = [0, k R cos(δ/2)]
             *
             * 1)
             * 0° ≤ δ/2 ≤ 45° => 1 ≥ cos(δ/2) ≥ √2/2
             *                   0 ≤ sin(δ/2) ≤ √2/2
             *
             * 2)     ____________________________________________________
             * { d = √(0 + k R sin(δ/2))² + (k R cos(δ/2) - k R cos(δ/2))² = | k R sin(δ/2) |
             * {      ______________________________
             * { l = √(0 - 0)² + (k R cos(δ/2) - R)² = | k R cos(δ/2) - R|
             *
             * | k R sin(δ/2) | = | k R cos(δ/2) - R |
             * k R cos(δ/2) - R = ± k R sin(δ/2)
             * k (cos(δ/2) ∓ sin(δ/2)) = 1
             * k = 1 / (cos(δ/2) ∓ sin(δ/2))
             *
             * 1+2)
             * k > 0 always ✓
             *
             * 3)
             * ‖M‖ = ‖k * B‖ < R
             *  _______________________________
             * √k²R² sin²(δ/2) + k²R² cos²(δ/2) < R
             * k R < R
             * k < 1
             *
             * 2+3)
             * k < 1  <=>  cos(δ/2) ∓ sin(δ/2) > 1
             * hence, must be  k = 1 / (cos(δ/2) + sin(δ/2))
             *
             *
             * CONCLUSION:
             *   square side = 2 * length of MJ
             *   M = [-(cos(δ/2) + sin(δ/2))⁻¹ R sin(δ/2), (cos(δ/2) + sin(δ/2))⁻¹ R cos(δ/2)]
             *   J = [0, (cos(δ/2) + sin(δ/2))⁻¹ R cos(δ/2)]
             *                   _____________________________________________
             *   length of MJ = √(0 + (cos(δ/2) + sin(δ/2))⁻¹ R sin(δ/2))² + 0 = (cos(δ/2) + sin(δ/2))⁻¹ R sin(δ/2)
             *   square side = 2 R sin(δ/2) (cos(δ/2) + sin(δ/2))⁻¹
             *
             */

            #endregion Maths

            float  deltaDegrees = 360.0f / n;
            double deltaRadians = Trig.DegreeToRadian(deltaDegrees);
            float  squareSide   = (float)(2.0 * radius * Math.Sin(deltaRadians / 2) * (1 / (Math.Cos(deltaRadians / 2) + Math.Sin(deltaRadians / 2))));

            // Save parent's current local rotation; it will be re-set later
            Quaternion parentRotation = parent?.localRotation ?? Quaternion.identity;
            if (parent != null)
            {
                parent.localRotation = Quaternion.identity;
            }

            GameObject cubesContainer = parent?.gameObject ?? new GameObject();
            cubesContainer.name = $"Circumference_{n}Cubes";
            cubesContainer.transform.localPosition = center;

            // Create the cubes
            for (int i = 0; i < n; ++i)
            {
                cubesContainer.transform.localEulerAngles = new Vector3(0.0f, -deltaDegrees * i, 0.0f);

                GameObject cube = Instantiate(cubePrefab);
                cube.name = $"Cube{i}";
                cube.SetActive(true); // Awake it now, to let it store the prefab's original scale
                cube.transform.localScale = new Vector3(squareSide, squareSide, squareSide);
                cube.transform.position   = cubesContainer.transform.position + Vector3.forward * radius;
                cube.transform.parent     = cubesContainer.transform;
            }
            cubesContainer.transform.localRotation = Quaternion.identity;

            // Re-set parent's original local rotation
            if (parent != null)
            {
                parent.localRotation = parentRotation;
            }

            return(cubesContainer);
        }
예제 #12
0
 public static Sweepline SweeplineAt(double colatitude)
 {
     return(new Sweepline {
         Colatitude = Trig.DegreeToRadian(colatitude)
     });
 }
예제 #13
0
 public static Vector3 VectorAt(double colatitude, double azimuth)
 {
     return(new SphericalCoords(Trig.DegreeToRadian(colatitude), Trig.DegreeToRadian(azimuth)).CartesianCoordinates());
 }