static int Intersect(AstroVector pos1, AstroVector dir1, AstroVector pos2, AstroVector dir2)
        {
            double      F     = dir1 * dir2;
            AstroVector amb   = pos1 - pos2;
            double      E     = dir1 * amb;
            double      G     = dir2 * amb;
            double      denom = 1.0 - F * F;

            if (denom == 0.0)
            {
                Console.WriteLine("ERROR: Cannot solve because directions are parallel.");
                return(1);
            }

            double u = (F * G - E) / denom;
            double v = G + F * u;

            if (u < 0.0 || v < 0.0)
            {
                Console.WriteLine("ERROR: Lines of sight do not converge.");
                return(1);
            }

            AstroVector a    = pos1 + u * dir1;
            AstroVector b    = pos2 + v * dir2;
            AstroVector c    = (a + b) / 2.0;
            AstroVector miss = a - b;

            double   dist = (Astronomy.KM_PER_AU * 1000 / 2) * miss.Length(); // error radius in meters
            Observer obs  = Astronomy.VectorObserver(c, EquatorEpoch.OfDate);

            Console.WriteLine($"Solution: lat = {obs.latitude:F6}, lon = {obs.longitude:F6}, elv = {obs.height:F3} meters; error = {dist:F3} meters.");
            return(0);
        }
        static AstroVector DirectionVector(AstroTime time, Observer observer, double altitude, double azimuth)
        {
            // Convert horizontal angles to a horizontal unit vector.
            var         hor  = new Spherical(altitude, azimuth, 1.0);
            AstroVector hvec = Astronomy.VectorFromHorizon(hor, time, Refraction.None);

            // Find the rotation matrix that converts horizontal vectors to equatorial vectors.
            RotationMatrix rot = Astronomy.Rotation_HOR_EQD(time, observer);

            // Rotate the horizontal (HOR) vector to an equator-of-date (EQD) vector.
            AstroVector evec = Astronomy.RotateVector(rot, hvec);

            return(evec);
        }
Exemple #3
0
        static int HorizontalCoords(
            out Spherical hor,
            double ecliptic_longitude,
            AstroTime time,
            RotationMatrix rot_ecl_hor)
        {
            var eclip = new Spherical(
                0.0,        /* being "on the ecliptic plane" means ecliptic latitude is zero. */
                ecliptic_longitude,
                1.0         /* any positive distance value will work fine. */
                );

            /* Convert ecliptic angular coordinates to ecliptic vector. */
            AstroVector ecl_vec = Astronomy.VectorFromSphere(eclip, time);

            /* Use the rotation matrix to convert ecliptic vector to horizontal vector. */
            AstroVector hor_vec = Astronomy.RotateVector(rot_ecl_hor, ecl_vec);

            /* Find horizontal angular coordinates, correcting for atmospheric refraction. */
            hor = Astronomy.HorizonFromVector(hor_vec, Refraction.Normal);

            return(0);   /* success */
        }
        static int Main(string[] args)
        {
            if (args.Length != 10)
            {
                Console.WriteLine(UsageText);
                return(1);
            }

            // Validate and parse command line arguments.
            double lat1 = ParseNumber("lat1", args[0]);
            double lon1 = ParseNumber("lon1", args[1]);
            double elv1 = ParseNumber("elv1", args[2]);
            double az1  = ParseNumber("az1", args[3]);
            double alt1 = ParseNumber("alt1", args[4]);
            double lat2 = ParseNumber("lat2", args[5]);
            double lon2 = ParseNumber("lon2", args[6]);
            double elv2 = ParseNumber("elv2", args[7]);
            double az2  = ParseNumber("az2", args[8]);
            double alt2 = ParseNumber("alt2", args[9]);

            var obs1 = new Observer(lat1, lon1, elv1);
            var obs2 = new Observer(lat2, lon2, elv2);

            // Use an arbitrary but consistent time for the Earth's rotation.
            AstroTime time = new AstroTime(0.0);

            // Convert geographic coordinates of the observers to vectors.
            AstroVector pos1 = Astronomy.ObserverVector(time, obs1, EquatorEpoch.OfDate);
            AstroVector pos2 = Astronomy.ObserverVector(time, obs2, EquatorEpoch.OfDate);

            // Convert horizontal coordinates into unit direction vectors.
            AstroVector dir1 = DirectionVector(time, obs1, alt1, az1);
            AstroVector dir2 = DirectionVector(time, obs2, alt2, az2);

            // Find the closest point between the skew lines.
            return(Intersect(pos1, dir1, pos2, dir2));
        }
Exemple #5
0
        static int CameraImage(Observer observer, AstroTime time)
        {
            const double tolerance = 1.0e-15;

            // Calculate the topocentric equatorial coordinates of date for the Moon.
            // Assume aberration does not matter because the Moon is so close and has such a small relative velocity.
            Equatorial moon_equ = Astronomy.Equator(Body.Moon, time, observer, EquatorEpoch.OfDate, Aberration.None);

            // Also calculate the Sun's topocentric position in the same coordinate system.
            Equatorial sun_equ = Astronomy.Equator(Body.Sun, time, observer, EquatorEpoch.OfDate, Aberration.None);

            // Get the Moon's horizontal coordinates, so we know how much to pivot azimuth and altitude.
            Topocentric moon_hor = Astronomy.Horizon(time, observer, moon_equ.ra, moon_equ.dec, Refraction.None);

            Console.WriteLine($"Moon horizontal position: azimuth = {moon_hor.azimuth:F3}, altitude = {moon_hor.altitude:F3}");

            // Get the rotation matrix that converts equatorial to horizontal coordintes for this place and time.
            RotationMatrix rot = Astronomy.Rotation_EQD_HOR(time, observer);

            // Modify the rotation matrix in two steps:
            // First, rotate the orientation so we are facing the Moon's azimuth.
            // We do this by pivoting around the zenith axis.
            // Horizontal axes are: 0 = north, 1 = west, 2 = zenith.
            // Tricky: because the pivot angle increases counterclockwise, and azimuth
            // increases clockwise, we undo the azimuth by adding the positive value.
            rot = Astronomy.Pivot(rot, 2, moon_hor.azimuth);

            // Second, pivot around the leftward axis to bring the Moon to the camera's altitude level.
            // From the point of view of the leftward axis, looking toward the camera,
            // adding the angle is the correct sense for subtracting the altitude.
            rot = Astronomy.Pivot(rot, 1, moon_hor.altitude);

            // As a sanity check, apply this rotation to the Moon's equatorial (EQD) coordinates and verify x=0, y=0.
            AstroVector vec = Astronomy.RotateVector(rot, moon_equ.vec);

            // Convert to unit vector.
            double radius = vec.Length();

            vec.x /= radius;
            vec.y /= radius;
            vec.z /= radius;
            Console.WriteLine($"Moon check: x = {vec.x}, y = {vec.y}, z = {vec.z}");
            if (!double.IsFinite(vec.x) || Math.Abs(vec.x - 1.0) > tolerance)
            {
                Console.WriteLine("Excessive error in moon check (x).");
                return(1);
            }

            if (!double.IsFinite(vec.y) || Math.Abs(vec.y) > tolerance)
            {
                Console.WriteLine("Excessive error in moon check (y).");
                return(1);
            }

            if (!double.IsFinite(vec.z) || Math.Abs(vec.z) > tolerance)
            {
                Console.WriteLine("Excessive error in moon check (z).");
                return(1);
            }

            // Apply the same rotation to the Sun's equatorial vector.
            // The x- and y-coordinates now tell us which side appears sunlit in the camera!

            vec = Astronomy.RotateVector(rot, sun_equ.vec);

            // Don't bother normalizing the Sun vector, because in AU it will be close to unit anyway.
            Console.WriteLine($"Sun vector: x = {vec.x:F6}, y = {vec.y:F6}, z = {vec.z:F6}");

            // Calculate the tilt angle of the sunlit side, as seen by the camera.
            // The x-axis is now pointing directly at the object, z is up in the camera image, y is to the left.
            double tilt = RAD2DEG * Math.Atan2(vec.z, vec.y);

            Console.WriteLine($"Tilt angle of sunlit side of the Moon = {tilt:F3} degrees counterclockwise from up.");

            IllumInfo illum = Astronomy.Illumination(Body.Moon, time);

            Console.WriteLine($"Moon magnitude = {illum.mag:F2}, phase angle = {illum.phase_angle:F2} degrees.");

            double angle = Astronomy.AngleFromSun(Body.Moon, time);

            Console.WriteLine($"Angle between Moon and Sun as seen from Earth = {angle:F2} degrees.");
            return(0);
        }