/// <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()
            });
        }
Beispiel #2
0
        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;
        }
Beispiel #3
0
        /// <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);
        }
Beispiel #10
0
        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);
        }
Beispiel #11
0
 public static float PointDirection(Vector2 p0, Vector2 p1)
 {
     return((float)SMath.Atan2(p1.Y - p0.Y, p1.X - p0.X));
 }
Beispiel #12
0
 public static double GetAngle(Point center, Point endPoint)
 {
     return(M.Atan2(endPoint.Y - center.Y, endPoint.X - center.X) + PI);
 }
Beispiel #13
0
 /// <summary>
 ///
 /// </summary>
 /// <returns></returns>
 public float ToHeading()
 {
     return((float)((Maths.Atan2(X, -Y) + Maths.PI) * (180.0 / Maths.PI)));
 }
Beispiel #14
0
 public static float GetAngle(this Vec2 v)
 {
     return((float)Math.Atan2(v.Y, v.X));
 }
Beispiel #15
0
 /// <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));
 }
Beispiel #17
0
        /// <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()));
        }
Beispiel #18
0
 public static double Atan2(object self, double y, double x)
 {
     return(SM.Atan2(y, x));
 }
Beispiel #19
0
 public static double Atan2(object self, [DefaultProtocol] double y, [DefaultProtocol] double x)
 {
     return(SM.Atan2(y, x));
 }
Beispiel #20
0
 private static int Math_Atan2(ILuaState lua)
 {
     lua.PushNumber(Math.Atan2(lua.L_CheckNumber(1),
                               lua.L_CheckNumber(2)));
     return(1);
 }
Beispiel #21
0
 public static double TanAngle(Vector vector)
 {
     return(ReduceAngle(Math.Atan2(vector.Y, vector.X)));
 }