/// <summary> /// Calculates distance/bearing between two geographic locations on Rhumb line (loxodrome) /// </summary> /// <param name="origin">origin location in geographic degrees</param> /// <param name="destination">destination location in geographic degrees</param> /// <param name="radius">radius of a geographic sphere, in kilometers</param> /// <remarks>radius defaults to Earth's mean radius</remarks> public static GeoRhumb GetRhumb(GeoPoint origin, GeoPoint destination, double radius = GeoGlobal.Earths.Radius) { origin = origin.ToRadians(); destination = destination.ToRadians(); var dLat = (destination.Latitude - origin.Latitude); var dLon = (destination.Longitude - origin.Longitude); var tDestination = Math.Tan(Math.PI / 4 + destination.Latitude / 2); var tOrigin = Math.Tan(Math.PI / 4 + origin.Latitude / 2); var dPhi = Math.Log(tDestination / tOrigin); // E-W line gives dPhi=0 var q = (IsFinite(dLat / dPhi)) ? dLat / dPhi : Math.Cos(origin.Latitude); // if dLon over 180° take shorter Rhumb across anti-meridian: if (Math.Abs(dLon) > Math.PI) { dLon = dLon > 0 ? -(2 * Math.PI - dLon) : (2 * Math.PI + dLon); } var distance = Math.Sqrt(dLat * dLat + q * q * dLon * dLon) * radius; var bearing = Math.Atan2(dLon, dPhi); return(new GeoRhumb { Distance = distance, Bearing = bearing.ToDegreesNormalized() }); }
private static void GetSphereUv(Vec3 p_point, ref HitRecord p_hitRecord) { var phi = Math.Atan2(p_point.Z, p_point.X); var theta = Math.Asin(p_point.Y); p_hitRecord.U = 1 - (phi + Math.PI) / (2 * Math.PI); p_hitRecord.V = (theta + Math.PI / 2) / Math.PI; }
/// <summary> /// Returns the counterclock angle between two vectors (between 0 and 2*pi) /// NOTE: A unique counter clockwise angle really only makes sense onces you've picked a plane normal direction. /// So as coded, this function is really only intended to be used with 2D vector inputs. /// </summary> public static double AngleToCounterClock(Vector3D v1, Vector3D v2) { double angle = Math.Atan2(v2.Y, v2.X) - Math.Atan2(v1.Y, v1.X); if (angle < 0) { return(angle + 2 * Math.PI); } return(angle); }
/// <summary> /// Calculates angle bearing from origin location towards destination location, in degrees /// <para> North = 0, East = 90, South = 180, West = 270 </para> /// </summary> /// <param name="origin">origin location in geographic degrees</param> /// <param name="destination">destination location in geographic degrees</param> public static double GetBearingAppx(IGeoLocatable origin, IGeoLocatable destination) { // from flight watcher app (not accurate) var dLat = destination.Latitude - origin.Latitude; var dLon = destination.Longitude - origin.Longitude; var angle = Math.Atan2((dLat), (dLon)) * 180.0 / Math.PI; return(-1 * angle); //return angle; }
/// <summary> /// Calculates the initial bearing from origin location in direction of destination location, in degrees from true North /// <para> North = 0, East = 90, South = 180, West = 270 </para> /// </summary> /// <param name="origin">origin location in geographic degrees</param> /// <param name="destination">destination location in geographic degrees</param> public static double GetBearing(IGeoLocatable origin, IGeoLocatable destination) { origin = origin.ToRadians(); destination = destination.ToRadians(); var dLat = (destination.Latitude - origin.Latitude); var dLon = (destination.Longitude - origin.Longitude); var y = Math.Sin(dLon) * Math.Cos(destination.Latitude); var x = Math.Cos(origin.Latitude) * Math.Sin(destination.Latitude) - Math.Sin(origin.Latitude) * Math.Cos(destination.Latitude) * Math.Cos(dLon); var angle = Math.Atan2(y, x); return(angle.ToDegreesNormalized()); }
} //NormalizeArray static void convertToAmplitudePhase(double[,] result) { int longIndexBound = result.GetUpperBound(1); for (var index = 0; index < longIndexBound; ++index) { double re = result[0, index]; double im = result[1, index]; double absValue = Math.Round(Math.Sqrt(re * re + im * im) * 100); double phase = Math.Round(Math.Atan2(re, im) * 180 / Math.PI); result[0, index] = absValue; result[1, index] = phase; } //loop } //convertToAmplitudePhase
/// <summary> /// Calculates mid point between two geographic locations on the Great Circle /// <para>Using the Spherical law of cosines </para> /// </summary> /// <param name="origin">origin location in geographic degrees</param> /// <param name="destination">destination location in geographic degrees</param> public static GeoPoint GetMidpoint(IGeoLocatable origin, IGeoLocatable destination) { origin = origin.ToRadians(); destination = destination.ToRadians(); var dLat = (destination.Latitude - origin.Latitude); var dLon = (destination.Longitude - origin.Longitude); var bx = Math.Cos(destination.Latitude) * Math.Cos(dLon); var by = Math.Cos(destination.Latitude) * Math.Sin(dLon); var lat = Math.Atan2(Math.Sin(origin.Latitude) + Math.Sin(destination.Latitude), Math.Sqrt((Math.Cos(origin.Latitude) + bx) * (Math.Cos(origin.Latitude) + bx) + by * by)); var lon = origin.Longitude + Math.Atan2(by, Math.Cos(origin.Latitude) + bx); lon = (lon + 3 * Math.PI) % (2 * Math.PI) - Math.PI; // normalize to -180..+180º return(new GeoPoint(lon.ToDegrees(), lat.ToDegrees())); }
/// <summary> /// Calculates distance between two geographic locations on the Great Circle /// <para>Using the Haversine formula</para> /// <remarks>"Virtues of the Haversine" by R. W. Sinnott, Sky and Telescope, vol 68, no 2, 1984</remarks> /// </summary> /// <param name="origin">origin location in geographic degrees</param> /// <param name="destination">destination location in geographic degrees</param> /// <param name="radius">radius of a geographic sphere, in kilometers</param> /// <remarks>radius defaults to Earth's mean radius</remarks> public static GeoDistance GetDistanceH(IGeoLocatable origin, IGeoLocatable destination, double radius = GeoGlobal.Earths.Radius) { origin = origin.ToRadians(); destination = destination.ToRadians(); var dLat = (destination.Latitude - origin.Latitude); var dLon = (destination.Longitude - origin.Longitude); var a = Math.Sin(dLat / 2) * Math.Sin(dLat / 2) + Math.Sin(dLon / 2) * Math.Sin(dLon / 2) * Math.Cos(origin.Latitude) * Math.Cos(destination.Latitude); var c = 2 * Math.Atan2(Math.Sqrt(a), Math.Sqrt(1 - a)); var distance = radius * c; return(new GeoDistance { Kilometers = distance }); }
/// <summary> /// Calculates the destination location at distance and in direction of bearing from origin location /// <para>Using the Spherical law of cosines </para> /// </summary> /// <param name="origin">location in geographic degrees </param> /// <param name="bearing">bearing in geographic degrees from origin</param> /// <param name="distance">distance in km</param> /// <param name="radius">radius in km</param> /// <remarks>radius defaults to Earth's mean radius</remarks> public static GeoPoint GetDestination(IGeoLocatable origin, double bearing, double distance, double radius = GeoGlobal.Earths.Radius) { origin = origin.ToRadians(); bearing = bearing.ToRadians(); distance = distance / radius; // angular distance in radians var latitude = Math.Asin(Math.Sin(origin.Latitude) * Math.Cos(distance) + Math.Cos(origin.Latitude) * Math.Sin(distance) * Math.Cos(bearing)); var x = Math.Sin(bearing) * Math.Sin(distance) * Math.Cos(origin.Latitude); var y = Math.Cos(distance) - Math.Sin(origin.Latitude) * Math.Sin(origin.Latitude); var longitude = origin.Longitude + Math.Atan2(x, y); longitude = (longitude + 3 * Math.PI) % (2 * Math.PI) - Math.PI; // normalize to -180..+180º var destination = new GeoPoint(longitude.ToDegrees(), latitude.ToDegrees()); return(destination); }
public static Sphere[] Mirrors(int p, int q, int r, ref Vector3D cellCenter, bool moveToBall = true, double scaling = -1) { Geometry g = Util.GetGeometry(p, q, r); if (g == Geometry.Spherical) { // These are in the ball model. Sphere[] result = SimplexCalcs.MirrorsSpherical(p, q, r); return(result); } else if (g == Geometry.Euclidean) { return(SimplexCalcs.MirrorsEuclidean()); } // This is a rotation we'll apply to the mirrors at the end. // This is to try to make our image outputs have vertical bi-lateral symmetry and the most consistent in all cases. // NOTE: + is CW, not CCW. (Because the way I did things, our images have been reflected vertically, and I'm too lazy to go change this.) double rotation = Math.PI / 2; // Some construction points we need. Vector3D p1, p2, p3; Segment seg = null; TilePoints(p, q, out p1, out p2, out p3, out seg); // // Construct in UHS // Geometry cellGeometry = Geometry2D.GetGeometry(p, q); Vector3D center = new Vector3D(); double radius = 0; if (cellGeometry == Geometry.Spherical) { // Finite or Infinite r // Spherical trig double halfSide = Geometry2D.GetTrianglePSide(q, p); double mag = Math.Sin(halfSide) / Math.Cos(Util.PiOverNSafe(r)); mag = Math.Asin(mag); // e.g. 43j //mag *= 0.95; // Move mag to p1. mag = Spherical2D.s2eNorm(mag); H3Models.Ball.DupinCyclideSphere(p1, mag, Geometry.Spherical, out center, out radius); } else if (cellGeometry == Geometry.Euclidean) { center = p1; radius = p1.Dist(p2) / Math.Cos(Util.PiOverNSafe(r)); } else if (cellGeometry == Geometry.Hyperbolic) { if (Infinite(p) && Infinite(q) && FiniteOrInfinite(r)) { //double iiiCellRadius = 2 - Math.Sqrt( 2 ); //Circle3D iiiCircle = new Circle3D() { Center = new Vector3D( 1 - iiiCellRadius, 0, 0 ), Radius = iiiCellRadius }; //radius = iiiCellRadius; // infinite r //center = new Vector3D( 1 - radius, 0, 0 ); // For finite r, it was easier to calculate cell facet in a more symmetric position, // then move into position with the other mirrors via a Mobius transformation. double rTemp = 1 / (Math.Cos(Util.PiOverNSafe(r)) + 1); Mobius m = new Mobius(); m.Isometry(Geometry.Hyperbolic, -Math.PI / 4, new Vector3D(0, Math.Sqrt(2) - 1)); Vector3D c1 = m.Apply(new Vector3D(1 - 2 * rTemp, 0, 0)); Vector3D c2 = c1; c2.Y *= -1; Vector3D c3 = new Vector3D(1, 0); Circle3D c = new Circle3D(c1, c2, c3); radius = c.Radius; center = c.Center; } else if (Infinite(p) && Finite(q) && FiniteOrInfinite(r)) { // http://www.wolframalpha.com/input/?i=r%2Bx+%3D+1%2C+sin%28pi%2Fp%29+%3D+r%2Fx%2C+solve+for+r // radius = 2 * Math.Sqrt( 3 ) - 3; // Appolonian gasket wiki page //radius = Math.Sin( Math.PI / q ) / ( Math.Sin( Math.PI / q ) + 1 ); //center = new Vector3D( 1 - radius, 0, 0 ); // For finite r, it was easier to calculate cell facet in a more symmetric position, // then move into position with the other mirrors via a Mobius transformation. double rTemp = 1 / (Math.Cos(Util.PiOverNSafe(r)) + 1); Mobius m = new Mobius(); m.Isometry(Geometry.Hyperbolic, 0, p2); Vector3D findingAngle = m.Inverse().Apply(new Vector3D(1, 0)); double angle = Math.Atan2(findingAngle.Y, findingAngle.X); m.Isometry(Geometry.Hyperbolic, angle, p2); Vector3D c1 = m.Apply(new Vector3D(1 - 2 * rTemp, 0, 0)); Vector3D c2 = c1; c2.Y *= -1; Vector3D c3 = new Vector3D(1, 0); Circle3D c = new Circle3D(c1, c2, c3); radius = c.Radius; center = c.Center; } else if (Finite(p) && Infinite(q) && FiniteOrInfinite(r)) { radius = p2.Abs(); // infinite r radius = DonHatch.asinh(Math.Sinh(DonHatch.e2hNorm(p2.Abs())) / Math.Cos(Util.PiOverNSafe(r))); // hyperbolic trig // 4j3 //m_jOffset = radius * 0.02; //radius += m_jOffset ; radius = DonHatch.h2eNorm(radius); center = new Vector3D(); rotation *= -1; } else if (/*Finite( p ) &&*/ Finite(q)) { // Infinite r //double mag = Geometry2D.GetTrianglePSide( q, p ); // Finite or Infinite r double halfSide = Geometry2D.GetTrianglePSide(q, p); double mag = DonHatch.asinh(Math.Sinh(halfSide) / Math.Cos(Util.PiOverNSafe(r))); // hyperbolic trig H3Models.Ball.DupinCyclideSphere(p1, DonHatch.h2eNorm(mag), out center, out radius); } else { throw new System.NotImplementedException(); } } Sphere cellBoundary = new Sphere() { Center = center, Radius = radius }; Sphere[] interior = InteriorMirrors(p, q); Sphere[] surfaces = new Sphere[] { cellBoundary, interior[0], interior[1], interior[2] }; // Apply rotations. bool applyRotations = true; if (applyRotations) { foreach (Sphere s in surfaces) { RotateSphere(s, rotation); } p1.RotateXY(rotation); } // Apply scaling bool applyScaling = scaling != -1; if (applyScaling) { //double scale = 1.0/0.34390660467269524; //scale = 0.58643550768408892; foreach (Sphere s in surfaces) { Sphere.ScaleSphere(s, scaling); } } bool facetCentered = false; if (facetCentered) { PrepForFacetCentering(p, q, surfaces, ref cellCenter); } // Move to ball if needed. if (moveToBall) { surfaces = MoveToBall(surfaces, ref cellCenter); } return(surfaces); }
public static float PointDirection(Vector2 p0, Vector2 p1) { return((float)SMath.Atan2(p1.Y - p0.Y, p1.X - p0.X)); }
public static double GetAngle(Point center, Point endPoint) { return(M.Atan2(endPoint.Y - center.Y, endPoint.X - center.X) + PI); }
/// <summary> /// /// </summary> /// <returns></returns> public float ToHeading() { return((float)((Maths.Atan2(X, -Y) + Maths.PI) * (180.0 / Maths.PI))); }
public static float GetAngle(this Vec2 v) { return((float)Math.Atan2(v.Y, v.X)); }
/// <summary> /// /// </summary> /// <param name="from"></param> /// <param name="to"></param> /// <returns></returns> public static float SignedAngle(Vector2 from, Vector2 to) { return((float)((Maths.Atan2(to.Y, to.X) - Maths.Atan2(from.Y, from.X)) * (180.0 / Maths.PI))); }
public static float Angle(this Vector2f value) { return((float)Math.Atan2(value.Y, value.X)); }
/// <summary> /// Calculates intersection point of paths from two geographic locations /// </summary> /// <param name="origin1">origin of first location in geographic degrees</param> /// <param name="origin2">origin of second location in geographic degrees</param> /// <param name="bearing1">bearing from first location in geographic degrees</param> /// <param name="bearing2">bearing from second location in geographic degrees</param> /// <param name="radius">radius of a geographic sphere, in kilometers</param> /// <remarks>radius defaults to Earth's mean radius</remarks> public static GeoPoint GetIntersection( IGeoLocatable origin1, double bearing1, IGeoLocatable origin2, double bearing2, double radius = GeoGlobal.Earths.Radius) { origin1 = origin1.ToRadians(); origin2 = origin2.ToRadians(); var brng13 = bearing1.ToRadians(); var brng23 = bearing2.ToRadians(); var dLat = (origin2.Latitude - origin1.Latitude); var dLon = (origin2.Longitude - origin1.Longitude); var dist12 = 2 * Math.Asin(Math.Sqrt(Math.Sin(dLat / 2) * Math.Sin(dLat / 2) + Math.Cos(origin1.Latitude) * Math.Cos(origin2.Latitude) * Math.Sin(dLon / 2) * Math.Sin(dLon / 2))); if (dist12 == 0) { return(GeoPoint.Invalid); } // initial/final bearings between points var brngA = Math.Acos((Math.Sin(origin2.Latitude) - Math.Sin(origin1.Latitude) * Math.Cos(dist12)) / (Math.Sin(dist12) * Math.Cos(origin1.Latitude))); if (double.IsNaN(brngA)) { brngA = 0; // protect against rounding } var brngB = Math.Acos((Math.Sin(origin1.Latitude) - Math.Sin(origin2.Latitude) * Math.Cos(dist12)) / (Math.Sin(dist12) * Math.Cos(origin2.Latitude))); double brng12, brng21; if (Math.Sin(dLon) > 0) { brng12 = brngA; brng21 = 2 * Math.PI - brngB; } else { brng12 = 2 * Math.PI - brngA; brng21 = brngB; } var alpha1 = (brng13 - brng12 + Math.PI) % (2 * Math.PI) - Math.PI; // angle 2-1-3 var alpha2 = (brng21 - brng23 + Math.PI) % (2 * Math.PI) - Math.PI; // angle 1-2-3 if (Math.Sin(alpha1) == 0 && Math.Sin(alpha2) == 0) { return(GeoPoint.Invalid); // infinite intersections } if (Math.Sin(alpha1) * Math.Sin(alpha2) < 0) { return(GeoPoint.Invalid); // ambiguous intersection } var alpha3 = Math.Acos(-Math.Cos(alpha1) * Math.Cos(alpha2) + Math.Sin(alpha1) * Math.Sin(alpha2) * Math.Cos(dist12)); var dist13 = Math.Atan2(Math.Sin(dist12) * Math.Sin(alpha1) * Math.Sin(alpha2), Math.Cos(alpha2) + Math.Cos(alpha1) * Math.Cos(alpha3)); var lat3 = Math.Asin(Math.Sin(origin1.Latitude) * Math.Cos(dist13) + Math.Cos(origin1.Latitude) * Math.Sin(dist13) * Math.Cos(brng13)); var dLon13 = Math.Atan2(Math.Sin(brng13) * Math.Sin(dist13) * Math.Cos(origin1.Latitude), Math.Cos(dist13) - Math.Sin(origin1.Latitude) * Math.Sin(lat3)); var lon3 = origin1.Longitude + dLon13; lon3 = (lon3 + 3 * Math.PI) % (2 * Math.PI) - Math.PI; // normalize to -180..+180º return(new GeoPoint(lat3.ToDegrees(), lon3.ToDegrees())); }
public static double Atan2(object self, double y, double x) { return(SM.Atan2(y, x)); }
public static double Atan2(object self, [DefaultProtocol] double y, [DefaultProtocol] double x) { return(SM.Atan2(y, x)); }
private static int Math_Atan2(ILuaState lua) { lua.PushNumber(Math.Atan2(lua.L_CheckNumber(1), lua.L_CheckNumber(2))); return(1); }
public static double TanAngle(Vector vector) { return(ReduceAngle(Math.Atan2(vector.Y, vector.X))); }