/// <summary> /// Encodes a coordinate on the sphere to the corresponding icosahedral face and /// containing 2D hex coordinates relative to that face center. /// </summary> /// <param name="g">The spherical coordinates to encode.</param> /// <param name="res">The desired H3 resolution for the encoding.</param> /// <returns> /// Tuple /// Item1: The resulting face /// Item2: The 2D hex coordinates of the cell containing the point. /// </returns> /// <!-- /// faceijk.c /// void _geoToHex2d /// --> public static (int, Vec2d) ToHex2d(this GeoCoord g, int res) { var v3d = g.ToVec3d(); var newFace = 0; // determine the icosahedron face decimal sqd = v3d.PointSquareDistance(Constants.FaceIjk.FaceCenterPoint[0]); for (var f = 1; f < Constants.H3.NUM_ICOSA_FACES; f++) { decimal sqdT = v3d.PointSquareDistance(Constants.FaceIjk.FaceCenterPoint[f]); if (!(sqdT < sqd)) { continue; } newFace = f; sqd = sqdT; } // cos(r) = 1 - 2 * sin^2(r/2) = 1 - 2 * (sqd / 4) = 1 - sqd/2 decimal r = DecimalEx.ACos(1 - sqd / 2.0m); if (r < Constants.H3.EPSILON) { return(newFace, new Vec2d()); } // now have face and r, now find CCW theta from CII i-axis decimal theta = ( Constants.FaceIjk.FaceAxesAzRadsCii[newFace, 0] - Constants.FaceIjk.FaceCenterGeo[newFace].AzimuthRadiansTo(g) .NormalizeRadians() ).NormalizeRadians(); // adjust theta for Class III (odd resolutions) if (res.IsResClassIii()) { theta = (theta - Constants.H3.M_AP7_ROT_RADS).NormalizeRadians(); } // perform gnomonic scaling of r r = DecimalEx.Tan(r); // scale for current resolution length u r /= Constants.H3.RES0_U_GNOMONIC; for (var i = 0; i < res; i++) { r *= Constants.FaceIjk.MSqrt7; } // we now have (r, theta) in hex2d with theta ccw from x-axes // convert to local x,y return(newFace, new Vec2d ( r * DecimalEx.Cos(theta), r * DecimalEx.Sin(theta) )); }
/// <summary> /// The great circle distance in radians between two spherical coordinates. /// This function uses the Haversine formula. /// For math details, see: /// https://en.wikipedia.org/wiki/Haversine_formula /// https://www.movable-type.co.uk/scripts/latlong.html /// </summary> /// <param name="a">the first lat/lng pair (in radians)</param> /// <param name="b">the second lat/lng pair (in radians)</param> /// <returns> /// the great circle distance in radians between a and b /// </returns> /// <!-- /// geoCoord.c /// double H3_EXPORT(pointDistRads) /// --> public static decimal DistanceToRadians(this GeoCoord a, GeoCoord b) { decimal sinLat = DecimalEx.Sin((b.Latitude - a.Latitude) / 2.0m); decimal sinLng = DecimalEx.Sin((b.Longitude - a.Longitude) / 2.0m); decimal p = sinLat * sinLat + DecimalEx.Cos(a.Latitude) * DecimalEx.Cos(b.Latitude) * sinLng * sinLng; return(2 * DecimalEx.ATan2(DecimalEx.Sqrt(p), DecimalEx.Sqrt(1 - p))); }
/// <summary> /// Calculate the 3D coordinate on unit sphere from the latitude and longitude. /// </summary> /// <param name="geo">The latitude and longitude of the point</param> /// <!-- /// vec3d.c /// void _geoToVec3d /// --> public static Vec3d ToVec3d(this GeoCoord geo) { decimal r = DecimalEx.Cos(geo.Latitude); return(new Vec3d ( DecimalEx.Cos(geo.Longitude) * r, DecimalEx.Sin(geo.Longitude) * r, DecimalEx.Sin(geo.Latitude) )); }
/// <summary> /// Determines the azimuth to p2 from p1 in radians /// </summary> /// <param name="p1">The first spherical coordinates</param> /// <param name="p2">The second spherical coordinates</param> /// <returns>The azimuth in radians from p1 to p2</returns> /// <!-- /// geoCoord.c /// double _geoAzimuthRads /// --> internal static decimal AzimuthRadiansTo(this GeoCoord p1, GeoCoord p2) { return (DecimalEx.ATan2 ( DecimalEx.Cos(p2.Latitude) * DecimalEx.Sin(p2.Longitude - p1.Longitude), DecimalEx.Cos(p1.Latitude) * DecimalEx.Sin(p2.Latitude) - DecimalEx.Sin(p1.Latitude) * DecimalEx.Cos(p2.Latitude) * DecimalEx.Cos(p2.Longitude - p1.Longitude) )); }
public void findCos() { Console.Write("Enter the number:\n"); string stringConversions = Console.ReadLine(); if (stringConversions.Contains("/")) { Fract.Fraction(stringConversions); FractionConverted = Fract.Fraction(stringConversions); Answer = DecimalEx.Cos(decimalConverted); Console.WriteLine($"Your answer is {Answer}.\n"); } else { decimalConverted = Decimal.Parse(stringConversions); Answer = DecimalEx.Cos(decimalConverted); Console.WriteLine($"Your answer is {Answer}.\n"); } }
/// <summary> /// Rotates about the origin. Returns a new matrix with the result. /// </summary> /// <param name="degrees">The degrees to rotate.</param> /// <param name="clockwise">If False, then + degrees rotates counter clockwise. /// If True, then + degrees rotates clockwise. Of course, if the sign of the degrees /// is -, then the rotation will be opposite whatever the + direction is.</param> public Transform2D Rotate(decimal degrees, bool clockwise = false) { var r = new Transform2D(); var theta = DecimalEx.ToRad(degrees); if (clockwise) { theta *= -1; } // 0 1 2 // 0 cos -sin 0 // 1 sin cos 0 // 2 0 0 1 r[0, 0] = DecimalEx.Cos(theta); r[0, 1] = -DecimalEx.Sin(theta); r[1, 0] = DecimalEx.Sin(theta); r[1, 1] = DecimalEx.Cos(theta); return(r.Multiply(this)); }
public void UpdateFilter() { var A = DecimalEx.Pow(10, Gain / 40m); var w = DecimalEx.TwoPi * Frequency / SampleRate; var cosw = DecimalEx.Cos(w); var sinw = DecimalEx.Sin(w); var alpha = sinw / (2 * Q); var Am1cosw = (A - 1m) * cosw; var Ap1cosw = (A + 1m) * cosw; var TwoSqrtAalpha = 2m * DecimalEx.Sqrt(A) * alpha; decimal a0 = 1m; switch (Type) { case FilterType.Disabled: b0 = 1; b1 = b2 = a1 = a2 = 0; FP_b0 = 0x00800000; FP_b1 = FP_b2 = FP_a1 = FP_a2 = 0; return; case FilterType.EQ: b0 = 1m + alpha * A; b1 = a1 = -2m * cosw; b2 = 1m - alpha * A; a0 = 1m + alpha / A; a2 = 1m - alpha / A; break; case FilterType.Lowpass: b1 = 1m - cosw; b2 = b0 = b1 / 2m; a0 = 1m + alpha; a1 = -2m * cosw; a2 = 1m - alpha; break; case FilterType.Highpass: b1 = -1m - cosw; b0 = b2 = -b1 / 2m; a0 = 1m + alpha; a1 = -2m * cosw; a2 = 1m - alpha; break; case FilterType.Bandpass: b0 = alpha; b1 = 0; b2 = -alpha; a0 = 1m + alpha; a1 = -2m * cosw; a2 = 1m - alpha; break; case FilterType.Notch: b0 = b2 = 1m; a0 = 1m + alpha; a1 = b1 = -2m * cosw; a2 = 1m - alpha; break; case FilterType.LowShelf: b0 = A * (A + 1m - Am1cosw + TwoSqrtAalpha); b1 = 2m * A * (A - 1m - Ap1cosw); b2 = A * (A + 1m - Am1cosw - TwoSqrtAalpha); a0 = A + 1m + Am1cosw + TwoSqrtAalpha; a1 = -2m * (A - 1m + Ap1cosw); a2 = A + 1m + Am1cosw - TwoSqrtAalpha; break; case FilterType.HighShelf: b0 = A * (A + 1m + Am1cosw + TwoSqrtAalpha); b1 = -2m * A * (A - 1m + Ap1cosw); b2 = A * (A + 1m + Am1cosw - TwoSqrtAalpha); a0 = A + 1m - Am1cosw + TwoSqrtAalpha; a1 = 2m * (A - 1m - Ap1cosw); a2 = A + 1m - Am1cosw - TwoSqrtAalpha; break; case FilterType.Custom: break; } b0 /= a0; b1 /= a0; b2 /= a0; a1 /= a0; a2 /= a0; if (NegateA && Type != FilterType.Custom) { a1 *= -1m; a2 *= -1m; } FP_b0 = ToFP(b0); FP_b1 = ToFP(b1); FP_b2 = ToFP(b2); FP_a1 = ToFP(a1); FP_a2 = ToFP(a2); b0 = FromFP(FP_b0); b1 = FromFP(FP_b1); b2 = FromFP(FP_b2); a1 = FromFP(FP_a1); a2 = FromFP(FP_a2); }
public void Test(decimal x, decimal expected, decimal tolerance) { tolerance = Helper.GetScaledTolerance(expected, (int)tolerance, true); Assert.That(DecimalEx.Cos(x), Is.EqualTo(expected).Within(tolerance)); }
/// <summary> /// Computes the point on the sphere a specified azimuth and distance from /// another point. /// </summary> /// <param name="p1">The first spherical coordinates.</param> /// <param name="azimuth">The desired azimuth from p1.</param> /// <param name="distance">The desired distance from p1, must be non-negative.</param> /// <returns>The spherical coordinates at the desired azimuth and distance from p1.</returns> /// <!-- /// geoCoord.c /// void _geoAzDistanceRads /// --> internal static GeoCoord GetAzimuthDistancePoint(this GeoCoord p1, decimal azimuth, decimal distance) { if (distance < Constants.H3.EPSILON) { return(p1); } azimuth = azimuth.NormalizeRadians().ConstrainToPiAccuracy(); var p2 = new GeoCoord(); // check for due north/south azimuth if (azimuth < Constants.H3.EPSILON || Math.Abs(azimuth - Constants.H3.M_PI) < Constants.H3.EPSILON) { if (azimuth < Constants.H3.EPSILON) // due north { p2 = p2.SetLatitude(p1.Latitude + distance); } else // due south { p2 = p2.SetLatitude(p1.Latitude - distance); } if (Math.Abs(p2.Latitude - Constants.H3.M_PI_2) < Constants.H3.EPSILON) // north pole { p2 = new GeoCoord(Constants.H3.M_PI_2, 0.0m); } else if (Math.Abs(p2.Latitude + Constants.H3.M_PI_2) < Constants.H3.EPSILON) // south pole { p2 = new GeoCoord(-Constants.H3.M_PI_2, 0.0m); } else { p2 = p2.SetLongitude(p1.Longitude.ConstrainLongitude()); } } else // Not due north or south { decimal sinLatitude = DecimalEx.Sin(p1.Latitude) * DecimalEx.Cos(distance) + DecimalEx.Cos(p1.Latitude) * DecimalEx.Sin(distance) * DecimalEx.Cos(azimuth); sinLatitude = sinLatitude.ConstrainToPiAccuracy(); if (sinLatitude > 1.0m) { sinLatitude = 1.0m; } if (sinLatitude < -1.0m) { sinLatitude = 1.0m; } p2 = p2.SetLatitude(DecimalEx.ASin(sinLatitude).ConstrainToPiAccuracy()); if (Math.Abs(p2.Latitude - Constants.H3.M_PI_2) < Constants.H3.EPSILON) // north pole { p2 = new GeoCoord(Constants.H3.M_PI_2, 0.0m); } else if (Math.Abs(p2.Latitude + Constants.H3.M_PI_2) < Constants.H3.EPSILON) // south pole { p2 = new GeoCoord(-Constants.H3.M_PI_2, 0.0m); } else { decimal sinLongitude = DecimalEx.Sin(azimuth) * DecimalEx.Sin(distance) / DecimalEx.Cos(p2.Latitude); decimal cosLongitude = (DecimalEx.Cos(distance) - DecimalEx.Sin(p1.Latitude) * DecimalEx.Sin(p2.Latitude)) / DecimalEx.Cos(p1.Latitude) / DecimalEx.Cos(p2.Latitude); if (sinLongitude > 1.0m) { sinLongitude = 1.0m; } if (sinLongitude < -1.0m) { sinLongitude = -1.0m; } if (cosLongitude > 1.0m) { cosLongitude = 1.0m; } if (cosLongitude < -1.0m) { cosLongitude = -1.0m; } p2 = p2.SetLongitude ( (p1.Longitude + DecimalEx.ATan2(sinLongitude, cosLongitude)) .ConstrainLongitude().ConstrainToPiAccuracy() ); } } return(p2); }