Esempio n. 1
0
        static int Main(string[] args)
        {
            var bodies = new Body[]
            {
                Body.Sun, Body.Moon, Body.Mercury, Body.Venus, Body.Mars,
                Body.Jupiter, Body.Saturn, Body.Uranus, Body.Neptune, Body.Pluto
            };

            Observer  observer;
            AstroTime time;

            DemoHelper.ParseArgs("positions", args, out observer, out time);
            Console.WriteLine("UTC date = {0}", time);
            Console.WriteLine();
            Console.WriteLine("BODY           RA      DEC       AZ      ALT");
            foreach (Body body in bodies)
            {
                Equatorial  equ_2000   = Astronomy.Equator(body, time, observer, EquatorEpoch.J2000, Aberration.Corrected);
                Equatorial  equ_ofdate = Astronomy.Equator(body, time, observer, EquatorEpoch.OfDate, Aberration.Corrected);
                Topocentric hor        = Astronomy.Horizon(time, observer, equ_ofdate.ra, equ_ofdate.dec, Refraction.Normal);
                Console.WriteLine("{0,-8} {1,8:0.00} {2,8:0.00} {3,8:0.00} {4,8:0.00}", body, equ_2000.ra, equ_2000.dec, hor.azimuth, hor.altitude);
            }

            return(0);
        }
Esempio n. 2
0
        public void Astronomy_HasOneSunsets_Should_ReturnCorrectSunset()
        {
            // Arrange
            var astro  = new Astronomy();
            var events = new List <AstronomyEvent> ();

            var sunrise = new AstronomyEvent
            {
                Type = AstronomyEventType.Rise,
                Time = new DateTime().AddHours(1).AddMinutes(58)
            };

            var sunset = new AstronomyEvent
            {
                Type = AstronomyEventType.Set,
                Time = new DateTime().AddHours(0).AddMinutes(3)
            };

            events.Add(sunrise);
            events.Add(sunset);

            astro.Events = events;

            // Act
            var set = astro.Sunset;

            // Assert
            Assert.AreEqual(sunset.Time.Hour, set.Value.Hour);
            Assert.AreEqual(sunset.Time.Minute, set.Value.Minute);
        }
Esempio n. 3
0
        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);
        }
Esempio n. 4
0
        static int Main(string[] args)
        {
            Observer  observer;
            AstroTime time;

            DemoHelper.ParseArgs("riseset", args, out observer, out time);
            Console.WriteLine("search   : {0}", time);
            if (0 != PrintEvent("sunrise", Astronomy.SearchRiseSet(Body.Sun, observer, Direction.Rise, time, 300.0)))
            {
                return(1);
            }
            if (0 != PrintEvent("sunset", Astronomy.SearchRiseSet(Body.Sun, observer, Direction.Set, time, 300.0)))
            {
                return(1);
            }
            if (0 != PrintEvent("moonrise", Astronomy.SearchRiseSet(Body.Moon, observer, Direction.Rise, time, 300.0)))
            {
                return(1);
            }
            if (0 != PrintEvent("moonset", Astronomy.SearchRiseSet(Body.Moon, observer, Direction.Set, time, 300.0)))
            {
                return(1);
            }
            return(0);
        }
Esempio n. 5
0
        static int Main(string[] args)
        {
            if (args.Length != 2)
            {
                Console.WriteLine("{0}", UsageText);
                return(1);
            }

            const double MAX_HEIGHT_METERS = 100000.0;

            // Force use of "." for the decimal mark, regardless of local culture settings.
            Thread.CurrentThread.CurrentCulture = CultureInfo.InvariantCulture;

            double latitude = double.Parse(args[0]);

            if (!double.IsFinite(latitude) || latitude < -90.0 || latitude > +90.0)
            {
                Console.WriteLine($"ERROR: Invalid latitude '{args[0]}'. Must be a number between -90 and +90.");
                return(1);
            }

            double height = double.Parse(args[1]);

            if (!double.IsFinite(height) || height < 0.0 || height > MAX_HEIGHT_METERS)
            {
                Console.WriteLine($"ERROR: Invalid height '{args[1]}'. Must be a number between 0 and {MAX_HEIGHT_METERS:F0}.");
                return(1);
            }

            double gravity = Astronomy.ObserverGravity(latitude, height);

            Console.WriteLine($"latitude = {latitude,8:F4},  height = {height,6:F0},  gravity = {gravity,8:F6}");
            return(0);
        }
Esempio n. 6
0
        public void CalculateSunsetTime_Test(GeoLocation location, DateTimeOffset instant, TimeSpan expectedSunsetTime)
        {
            // Act
            var sunsetTime = Astronomy.CalculateSunsetTime(location, instant);

            // Assert
            Assert.That(sunsetTime, Is.EqualTo(expectedSunsetTime).Within(TimeSpan.FromMinutes(3)));
        }
Esempio n. 7
0
 public CopernicusObservatory() : base(30)
 {
     Name         = "Copernicus' Observatory";
     RequiredTech = new Astronomy();
     ObsoleteTech = new Automobile();
     SetSmallIcon(6, 0);
     Type = Wonder.CopernicusObservatory;
 }
Esempio n. 8
0
        public override void Update()
        {
            Astronomy.Update();
            Weather.Update();

            m_PathPositions.Add(Astronomy.Orbit);

            m_UpdateInterval = 0;
            if (m_UpdateInterval > 0)
            {
                m_UpdateTimer += Time.deltaTime;
                if (m_UpdateTimer < m_UpdateInterval)
                {
                    return;
                }

                m_UpdateTimer = 0;
            }

            //UPDATE GLOABL ENVIRONMENT INFOS

            // TEMPERATURE
            TemperatureScale = Weather.TemperatureScale;
            Temperature      = Weather.Temperature;
            MinTemperature   = Weather.MinTemperature;
            MaxTemperature   = Weather.MaxTemperature;

            // DATE & TIME
            TimeHour    = (int)Astronomy.Hour;
            TimeMinutes = (int)Astronomy.Minutes;
            TimeSeconds = (int)Astronomy.Seconds;

            DateDay   = (int)Astronomy.Day;
            DateMonth = (int)Astronomy.Month;
            DateYear  = (int)Astronomy.Year;

            // ASTRO
            if (Display.UITextDateTime != null)
            {
                Display.UITextDateTime.text = CurrentDateTimeString;
            }

            if (Display.UITextDay != null)
            {
                Display.UITextDay.text = string.Format(Display.UITextDayFormat, Astronomy.DayTotal + (Display.UseFirstDay ? 1 : 0));
            }

            // WEATHER
            if (Display.UITemperatur != null)
            {
                Display.UITemperatur.text = string.Format(Display.UITemperaturFormat, Mathf.RoundToInt(Weather.Temperature));
            }

            // LIGHT
            LightIntensity = Astronomy.SunLightIntensity;
        }
Esempio n. 9
0
        public static double SunHoursToRadiations(this double sunHours, DateTime date, ILocation position)
        {
            int    dayOfYear               = Astronomy.DayOfYear(date);
            double dayAngle                = Astronomy.DayAngle(date);
            double latitude                = Astronomy.BoundedLatitude(position);
            double solarDeclination        = Astronomy.SolarDeclination(dayOfYear);
            double daylightTimeFactor      = Astronomy.DaylightTimeFactor(latitude, solarDeclination);
            double solarDistanceCorrection = Astronomy.SolarDistanceCorrection(dayAngle);
            double num = Astronomy.DayLength(daylightTimeFactor);

            return(Math.Max(0.1, Astronomy.ExtraTerrestrialRadiation(latitude, solarDistanceCorrection, solarDeclination, daylightTimeFactor) * (0.1 + 0.24 * sunHours / num + (0.78 - 0.44 * sunHours / num) * sunHours / num)));
        }
Esempio n. 10
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);
        }
Esempio n. 11
0
        static int Main(string[] args)
        {
            AstroTime time;

            switch (args.Length)
            {
            case 0:
                time = new AstroTime(DateTime.Now);
                break;

            case 1:
                time = DemoHelper.ParseTime("moonphase", args[0]);
                break;

            default:
                Console.WriteLine("USAGE: moonphase [date]");
                return(1);
            }

            /*
             *  Calculate the Moon's current phase angle,
             *  which ranges from 0 to 360 degrees.
             *
             *  0 = new moon,
             *  90 = first quarter,
             *  180 = full moon,
             *  270 = third quarter.
             */
            double phase = Astronomy.MoonPhase(time);

            Console.WriteLine("{0} : Moon's phase angle = {1:0.000000} degrees.", time, phase);

            /* Find the next 10 lunar quarter phases. */
            Console.WriteLine();
            Console.WriteLine("The next 10 lunar quarters are:");
            MoonQuarterInfo mq = Astronomy.SearchMoonQuarter(time);

            for (int i = 0; i < 10; ++i)
            {
                if (i > 0)
                {
                    mq = Astronomy.NextMoonQuarter(mq);
                }
                Console.WriteLine("{0} : {1}", mq.time, QuarterName(mq.quarter));
            }
            return(0);
        }
        /// <summary>
        /// Get sunrise, sunset.
        /// </summary>
        /// <returns></returns>
        protected IAstronomy GetSunInfo(DateTime?utcDate, CancellationToken token)
        {
            if (IfCancellationRequested(token) || !utcDate.HasValue || !Latitude.HasValue || !Longitude.HasValue)
            {
                return(null);
            }

            var sunInfo = GetSunInfo(utcDate.Value, token);

            if (sunInfo?.Validate() != true)
            {
                return(null);
            }

            var result = new Astronomy
            {
                Sunrise = sunInfo.Sunrise,
                Sunset  = sunInfo.Sunset
            };

            if (utcDate < sunInfo.Sunrise)
            {
                var sunInfoPrevious = GetSunInfo(utcDate.Value.AddDays(-1), token);
                if (sunInfoPrevious?.Validate() == true)
                {
                    result.PreviousInfo = new AstronomyInfo
                    {
                        Sunrise = sunInfoPrevious.Sunrise,
                        Sunset  = sunInfoPrevious.Sunset
                    };
                }
            }
            else if (utcDate > sunInfo.Sunset)
            {
                var sunInfoNext = GetSunInfo(utcDate.Value.AddDays(1), token);
                if (sunInfoNext?.Validate() == true)
                {
                    result.PreviousInfo = new AstronomyInfo
                    {
                        Sunrise = sunInfoNext.Sunrise,
                        Sunset  = sunInfoNext.Sunset
                    };
                }
            }

            return(result);
        }
Esempio n. 13
0
        static int Main(string[] args)
        {
            int year;

            if (args.Length != 1 || !int.TryParse(args[0], out year) || year <Astronomy.MinYear || year> Astronomy.MaxYear)
            {
                Console.WriteLine("ERROR: Must provide year {0}..{1} on command line.", Astronomy.MinYear, Astronomy.MaxYear);
                return(1);
            }
            SeasonsInfo seasons = Astronomy.Seasons(year);

            Console.WriteLine("March equinox     : {0}", seasons.mar_equinox);
            Console.WriteLine("June solstice     : {0}", seasons.jun_solstice);
            Console.WriteLine("September equinox : {0}", seasons.sep_equinox);
            Console.WriteLine("December solstice : {0}", seasons.dec_solstice);
            return(0);
        }
Esempio n. 14
0
        private void OnDrawGizmos()
        {
            if (Astronomy.SunLight == null)
            {
                return;
            }

            if (!Application.isPlaying)
            {
                Astronomy.SunLight.transform.localRotation = Astronomy.Rotation();
            }

            Gizmos.color = Color.blue;
            Gizmos.DrawLine(Astronomy.SunLight.transform.position + (Astronomy.SunLight.transform.forward * Astronomy.Radius * 0.75f), Astronomy.SunLight.transform.position + (Astronomy.SunLight.transform.forward * Astronomy.Radius));
            //Gizmos.DrawLine( Sun.transform.position - ( Sun.transform.forward * Radius * 0.75f ), Sun.transform.position - ( Sun.transform.forward * Radius ) );
            CustomGizmos.Circle(Astronomy.SunLight.transform.position, Astronomy.SunLight.transform.up, Astronomy.Radius);
            CustomGizmos.Arrow(Astronomy.SunLight.transform.position + (Astronomy.SunLight.transform.forward * Astronomy.Radius * 0.75f), Astronomy.SunLight.transform.forward * -2, 10);
            CustomGizmos.HandlesColor(Gizmos.color);
            CustomGizmos.Arrow(0, Astronomy.SunLight.transform.position - (Astronomy.SunLight.transform.forward * Astronomy.Radius), Astronomy.SunLight.transform.rotation, 50);


            if (m_PathPositions.Count > 1000)
            {
                m_PathPositions.RemoveAt(0);
            }

            Vector3 _prior_pos = Vector3.zero;

            foreach (Vector3 _pos in m_PathPositions)
            {
                if (_prior_pos != Vector3.zero)
                {
                    Gizmos.DrawLine(_prior_pos, _pos);
                }

                _prior_pos = _pos;
            }
        }
Esempio n. 15
0
        static int Main(string[] args)
        {
            Observer  observer;
            AstroTime time;

            DemoHelper.ParseArgs("culminate", args, out observer, out time);

            var bodies = new Body[]
            {
                Body.Sun, Body.Moon, Body.Mercury, Body.Venus, Body.Mars,
                Body.Jupiter, Body.Saturn, Body.Uranus, Body.Neptune, Body.Pluto
            };

            Console.WriteLine("search   : {0}", time);
            foreach (Body body in bodies)
            {
                HourAngleInfo evt = Astronomy.SearchHourAngle(body, observer, 0.0, time);
                Console.WriteLine("{0,-8} : {1}  altitude={2:##0.00}  azimuth={3:##0.00}",
                                  body, evt.time, evt.hor.altitude, evt.hor.azimuth);
            }

            return(0);
        }
Esempio n. 16
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 */
        }
Esempio n. 17
0
        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));
        }
Esempio n. 18
0
        static int Main(string[] args)
        {
            AstroTime time;

            switch (args.Length)
            {
            case 0:
                time = new AstroTime(DateTime.Now);
                break;

            case 1:
                time = DemoHelper.ParseTime("lunar_eclipse", args[0]);
                break;

            default:
                Console.WriteLine("USAGE: lunar_eclipse [date]");
                return(1);
            }

            int count = 0;
            LunarEclipseInfo eclipse = Astronomy.SearchLunarEclipse(time);

            for (;;)
            {
                if (eclipse.kind != EclipseKind.Penumbral)
                {
                    PrintEclipse(eclipse);
                    if (++count == 10)
                    {
                        break;
                    }
                }
                eclipse = Astronomy.NextLunarEclipse(eclipse.peak);
            }

            return(0);
        }
Esempio n. 19
0
 public override void Start()
 {
     Display.Init(this);
     Astronomy.Init(this);
     Weather.Init(this);
 }
Esempio n. 20
0
 public override void FixedUpdate()
 {
     Astronomy.FixedUpdate();
 }
Esempio n. 21
0
 private void BuildAstro() => this.astro       = new Astronomy();
Esempio n. 22
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);
        }
Esempio n. 23
0
        static int FindEclipticCrossings(Observer observer, AstroTime time)
        {
            int i;
            var hor = new Spherical[NUM_SAMPLES];

            /*
             *  The ecliptic is a celestial circle that describes the mean plane of
             *  the Earth's orbit around the Sun. We use J2000 ecliptic coordinates,
             *  meaning the x-axis is defined to where the plane of the Earth's
             *  equator on January 1, 2000 at noon UTC intersects the ecliptic plane.
             *  The positive x-axis points toward the March equinox.
             *  Calculate a rotation matrix that converts J2000 ecliptic vectors
             *  to horizontal vectors for this observer and time.
             */
            RotationMatrix rot = Astronomy.Rotation_ECL_HOR(time, observer);

            /*
             *  Sample several points around the ecliptic.
             *  Remember the horizontal coordinates for each sample.
             */
            for (i = 0; i < NUM_SAMPLES; ++i)
            {
                if (0 != HorizontalCoords(out hor[i], ECLIPLON(i), time, rot))
                {
                    return(1);   /* failure */
                }
            }
            for (i = 0; i < NUM_SAMPLES; ++i)
            {
                double    a1 = hor[i].lat;
                double    a2 = hor[(i + 1) % NUM_SAMPLES].lat;
                double    e1 = ECLIPLON(i);
                double    e2 = ECLIPLON(i + 1);
                double    ex;
                Spherical hx;
                int       error;

                if (a1 * a2 <= 0.0)
                {
                    /* Looks like a horizon crossing. Is altitude going up with longitude or down? */
                    if (a2 > a1)
                    {
                        /* Search for the ecliptic longitude and azimuth where altitude ascends through zero. */
                        error = Search(out ex, out hx, time, rot, e1, e2);
                    }
                    else
                    {
                        /* Search for the ecliptic longitude and azimuth where altitude descends through zero. */
                        error = Search(out ex, out hx, time, rot, e2, e1);
                    }

                    if (error != 0)
                    {
                        return(error);
                    }

                    string direction;
                    if (hx.lon > 0.0 && hx.lon < 180.0)
                    {
                        direction = "ascends ";     /* azimuth is more toward the east than the west */
                    }
                    else
                    {
                        direction = "descends";     /* azimuth is more toward the west than the east */
                    }
                    Console.WriteLine("Ecliptic longitude {0,9:0.0000} {1} through horizon az {2,9:0.0000}, alt {3,12:0.000e+00}", ex, direction, hx.lon, hx.lat);
                }
            }
            return(0);
        }