What Sidereal Time Is It?

It was one of those rare clear nights we sometimes get this time of year in the Pacific Northwest. My wife had been outside looking up at the night sky. Soon she came inside the house and asked, “what’s the sidereal time right now?” It was good timing because I had just added a sidereal time object to the SquareWidget.Astronomy.Core code library. While she looked over my shoulder, I started to write some code to answer the question. I looked up our local longitude (L) and in four lines of code I had the answer:

using SquareWidget.Astronomy.Core.UnitsOfMeasure;

Moment moment = new(DateTime.UtcNow);
SiderealTime st = new(moment);
SexigesimalAngle L = new(-123, 15, 43.34);
Console.WriteLine(st.ToLocalMean(L));

It returned 7 hours and some odd arcminutes and arcseconds. She nodded approvingly because she already knew the answer having been outside and saw that the constellation Orion had recently crossed our local meridian.

It’s been about four weeks since I released the first version of the code library. It took a lot out of me, so my plan was to chill out and relax for a good long while. And I did. For about 24 hours. I kept identifying and making a list of new features that I wanted to add at some point. Soon I found myself peeling them off one at a time and building releases around each one. So now the library is up to v1.5.1 and I think it’s time to do “Chill Out 2.0” for real this time. But first, let me walk through some of the new features to illustrate them. See my previous blog post on the subject as well as the README documentation on GitHub for more details.

Solar Coordinates

The first version had a solar longitude calculator. The calculator has been deprecated and the functionality is now in the Sun object. The coordinates are returned as apparent (geocentric) equatorial coordinates at a given moment. Suppose I want to know the Sun’s coordinates on 4 Jul 2028:

using SquareWidget.Astronomy.Core.UnitsOfMeasure;
using SquareWidget.Astronomy.Core.CelestialObjects.Stars;

DateTime d = new(2028, 7, 4);
Moment moment = new(d);
Sun sun = new(moment);

EquatorialCoordinates eqc = sun.GetGeocentricPosition();

Console.WriteLine($"RA {eqc.α.ToString()}");
Console.WriteLine($"Dec {eqc.δ.ToString()}.");

/* Displays:
 
RA 6h 54m 36.194953s
Dec +22° 50' 36.22891852".

*/

For a deep dive into the algorithm on solar coordinates see my earlier blog post Astronomical Calculations: Solar Coordinates.

Moon Phases

There is now a calculator to return moon phases within a given date range. Some phases fall outside the range in order to get a baseline for the previous or next phase:

using SquareWidget.Astronomy.Core.Models;
using SquareWidget.Astronomy.Core.Calculators;
using SquareWidget.Astronomy.Core.CelestialObjects.Moons;

DateOnly startDate = new(2025, 1, 1);
DateOnly endDate = new(2025, 3, 31);
DateRange dateRange = new(startDate, endDate);

List<MoonPhase> list = MoonPhaseDatesCalculator.Calculate(dateRange);

foreach (var item in list)
{
    Console.WriteLine(item.PhaseName + " on " +
        item.Moment
            .ToDateTime()
            .ToString("MM/dd/yyyy hh:mm:ss.fff tt"));
}



/* Displays:
 
NewMoon on 12/30/2024 10:26:46.440 PM
FirstQuarter on 01/06/2025 11:56:49.386 PM
LastQuarter on 01/21/2025 08:30:00.587 PM
FullMoon on 02/12/2025 01:53:20.083 PM
NewMoon on 01/29/2025 12:35:53.996 PM
FirstQuarter on 02/05/2025 08:01:06.996 AM
LastQuarter on 02/20/2025 05:31:34.392 PM
FullMoon on 03/14/2025 06:54:32.963 AM
NewMoon on 02/28/2025 12:44:39.649 AM
FirstQuarter on 03/06/2025 04:30:40.312 PM
LastQuarter on 03/22/2025 11:29:33.015 AM
FullMoon on 04/13/2025 12:22:13.127 AM

*/

Solar Eclipses

As with moon phases above you build a date range and pass that into the calculator to get a list of solar eclipses within the range. Here I’m entering the current year 2024 and I see the total eclipse this April that will swing through the U.S. Midwest.

using SquareWidget.Astronomy.Core.Calculators;
using SquareWidget.Astronomy.Core.Models;

DateOnly startDate = new(2024, 1, 1);
DateOnly endDate = new(2024, 12, 31);
DateRange dateRange = new(startDate, endDate);

IEnumerable<SolarEclipse> eclipses = SolarEclipseCalculator.Calculate(dateRange);

foreach (var eclipse in eclipses)
{
    Console.WriteLine(eclipse.ToString());
}

/* Displays:
 
04-08-2024 18:18 UTC  g:  0.3438   Total
10-02-2024 18:46 UTC  g: -0.3515   Annular

*/

Check out NASA’s Five Millennium Canon of Solar Eclipses -1999 to +3000 to see a visual diagram that you can compare with the results.

Galilean Moons of Jupiter

A few years ago, I showed how to calculate, for a given date, the apparent rectangular coordinates (X, Y) of the four Galilean moons of Jupiter (here). You can see a visual representation of the data — a sort of corkscrew diagram — that accompanies that article here. This past month, I put the feature into the code library. You use the same date range pattern as with the other calculators above:

using SquareWidget.Astronomy.Core.Calculators;
using SquareWidget.Astronomy.Core.Models;

DateTime startDate = DateTime.Today;
DateTime endDate = startDate.AddDays(1);

for (var d = startDate; d <= endDate; d = d.AddDays(1))
{
    SatellitePositions positions = JupiterSatellitePositionCalculator.Calculate(d);
    Console.WriteLine(positions.ToString());
}

/* Displays:
 
2/24/2024 12:01 AM
      Io - X:  -4.06   Y:   0.22
  Europa - X:  -0.58   Y:   0.48
Ganymede - X: -14.48   Y:   0.20
Callisto - X:  10.73   Y:  -1.24

2/25/2024 12:01 AM
      Io - X:   5.38   Y:  -0.12
  Europa - X:  -9.02   Y:  -0.12
Ganymede - X: -12.32   Y:  -0.44
Callisto - X:  18.74   Y:  -0.95

*/

The SatellitePositions object holds the date, all four moons, and their respective X, Y coordinates with respect to Jupiter.

Horizontal Coordinates

I’ve added horizontal coordinates as a third system for Alt-Az support. See the code sample for a detailed implementation. If you already have horizontal coordinates, you can convert them to equatorial:

// convert horizontal coordinates to equatorial coordinates
EquatorialCoordinates eqc = hc.ToΕquatorialCoordinates(moment, φ, L);

You need a Moment instance, and the observer’s latitude (φ) and longitude (L) for the conversion.

Sidereal Time

The code library uses sidereal time for conversion between coordinates. You can use it to find the Greenwich Mean Sidereal Time (GMST) or the Greenwich Apparent Sidereal Time (GAST) for any given moment in time. Always use UTC when initializing a SiderealTime object:

using SquareWidget.Astronomy.Core.Planets;
using SquareWidget.Astronomy.Core.UnitsOfMeasure;

DateTime datetime = new(1987, 4, 10, 19, 21, 0);
Moment moment = new Moment(datetime);
SiderealTime st = new(moment);

RightAscension gmst = new(st.GreenwichMean);
RightAscension gast = new(st.GreenwichApparent);

Console.WriteLine(gmst.ToString());
Console.WriteLine(gast.ToString());


/* Displays:
 
8h 34m 57.089579s
8h 34m 57.073455s

*/

If the observer’s longitude (L) is known, GMST can be converted to LMST:

using SquareWidget.Astronomy.Core.Planets;
using SquareWidget.Astronomy.Core.UnitsOfMeasure;

DateTime datetime = new(1987, 4, 10, 19, 21, 0);
Moment moment = new Moment(datetime);
SiderealTime st = new(moment);

RightAscension gmst = new(st.GreenwichMean);

// longitude in Corvallis, OR
SexigesimalAngle L = new(-123, 15, 43.34); 

// local mean sidereal time on the date (PST -8 offset)
RightAscension lmst = st.ToLocalMean(L);   

Console.WriteLine(gmst.ToString());
Console.WriteLine(lmst.ToString());


/* Displays:
 
8h 34m 57.089579s
0h 21m 54.200245s

*/

Finally, the hour angle (H) for an observer’s location and an object’s equatorial right ascension (α) is available by calling ToHourAngle:

using SquareWidget.Astronomy.Core.Planets;
using SquareWidget.Astronomy.Core.UnitsOfMeasure;

DateTime datetime = new(2024, 7, 4, 17, 0, 0); // UTC
Moment moment = new(datetime);
SiderealTime st = new(moment);

// longitude in Los Angeles, USA
SexigesimalAngle L = new(-118, 14, 38); 

// An object's equatorial right ascension
RightAscension α = new(5.838);

Degrees H = st.ToHourAngle(L, α);

Console.WriteLine(H.ToString());

/* Displays:
 
290°.6014494764589

*/

I’d be lying if I said I wasn’t thinking of new features and yes, I’ve started another list of enhancements. But for now, I’m going to take a break from this project for a bit and recharge my batteries. When I pick it up again it will be to do more testing. Currently, there are about 60 unit tests but there’s always room for more coverage and more tests. I also want to focus on useability. Then over time I’ll look to add more enhancements: equinoxes, solstices, equation of time, transits, conjunctions, perihelion and aphelion… the list goes on!

 

 

 

 

 

 

 

 

 

SquareWidget.Astronomy.Core: A C# Code Library

I’m happy to announce the release of SquareWidget.Astronomy.Core, a new code library targeting .NET 8.0 and written in C#, that supports common astronomical calculations and algorithms. The current version is 1.1.0. You can reference the NuGet package at the link above. It has a baseline of functionality and I have plans to add more over time.

Why a library? I’ve been writing code (and snippets of code) over several years to solve various problems in astronomy. When something looked interesting enough to share, I published some of that code on my GitHub repo and on this blog. Recently I was ploughing through the position angle of Saturn’s north pole (Jean Meeus,  Astronomical Algorithms, Chapter 49). After some long debugging sessions, I realized I was using the double data type for everything. Several times I would forget whether a value was in degrees, radians, large angles, reduced angles, or something else entirely. So, I decided I needed a basic code library to bring a little order out of the chaos. The first thing I added were the units of measure. Then planets and calculators came later. I have two design goals in mind for the library: useability and robustness. Certainly, the library should return results accurate to within a few minutes of degrees. But it should also be intuitive and easy to use.

I’ve written more detailed documentation on the GitHub README. Here I’ll just introduce a few of the features. At the heart of the library is a Moment struct. You can pass in date and time parameters, a DateTime instance, or a Julian Day (JD) value:

Moment m1 = new(2024, 1, 31, 9, 36, 0);
Moment m2 = new(2024, 1, 31.4);
Moment m3 = new(2460340.90001);

string s1 = m1.ToDateTime().ToString("yyyy MMM dd HH:mm");
string s2 = m2.ToDateTime().ToString("yyyy MMM dd HH:mm");
string s3 = m3.ToDateTime().ToString("yyyy MMM dd HH:mm");

Console.WriteLine(s1); // 2024 Jan 31 09:36
Console.WriteLine(s2); // 2024 Jan 31 09:36
Console.WriteLine(s3); // 2024 Jan 31 09:36

Once you have a Moment you can get its JD, modified JDE, Day D, or Time T (measure of Julian centuries from epoch J2000.0).

The code library also includes several units of measure with the ability to convert between them. For example, suppose I want to model the Earth’s obliquity of the ecliptic.  I can create a Degrees object by passing in decimal degrees:

Degrees d = new(23.41);
Console.WriteLine(d.ToString()); // 23°.41

Units can be converted to other units. Here I’ll convert to Radians, then a SexesimalAngle, and back to Degrees again:

Degrees d = new(23.41);
Console.WriteLine(d.ToString()); // 23°.41

Radians r = d.ToRadians();
Console.WriteLine(r.ToString()); // 0.4085816

SexigesimalAngle sa = new(d);
Console.WriteLine(sa.ToString()); // +23° 24' 36"

Degrees d1 = new(sa);
Console.WriteLine(d1.ToString()); // 23°.41

Quite often in astronomical calculations we deal with very large angles. Those can be reduced to within the range [0, 360] with the ToReducedAngle function:

Degrees d = new(13512.45);
Console.WriteLine(d.ToString()); // 13512°.45
Console.WriteLine(d.ToReducedAngle().ToString()); // 192°.45

A RightAscension can be constructed with the standard hours, minutes, and seconds (HMS) or decimal degrees:

// passing in HMS
RightAscension ra = new(12, 37, 27);
Console.WriteLine(ra.ToString());   // 12h 37m 27s

// passing decimal degrees
RightAscension ra = new(189.3625);
Console.WriteLine(ra.ToString()); // 12h 37m 27s

Two coordinate systems have been implemented, equitorial and ecliptical,  and you can convert back and forth between them. Suppose we have the equatorial coordinates (α, δ) of Pollux from a star catalog or the wiki and we know Earth’s obliquity of the ecliptic (ε):

// Pollux (β Gem)
RightAscension α = new(7, 45, 18.946);
SexigesimalAngle δ = new(28, 01, 34.26);
Degrees ε = new(23.4392911);

EquitorialCoordinates eqc = new(δ, α, ε);
Console.WriteLine(eqc.α.ToString()); // 7h 45m 18.946s
Console.WriteLine(eqc.δ.ToString()); // +28° 1' 34.26"

We can take those coordinates and convert them to ecliptical coordinates:

EquitorialCoordinates eqc = new(δ, α, ε);
EclipticalCoordinates ec = eqc.ToΕclipticCoordinates();

Console.WriteLine(ec.λ.ToDegrees().ToReducedAngle().ToString()); // 113°.21
Console.WriteLine(ec.β.ToDegrees().ToString());                  //   6°.68

You can instantiate a planet with the new operator or use the factory method. You must pass in a Moment struct either way.

DateTime datetime = new(2028, 7, 1);
Moment moment = new(datetime);

// using new operator
Earth earth = new(moment);

// using factory method for polymorphism
Planet planet = PlanetFactory.Create(PlanetName.Earth, moment);

Once you have a planet you can get its properties which include orbital elements and heliocentric spherical coordinates.

The library has six calculators right now and I plan to add at least a couple more in the next few weeks.

    • Geocentric position calculator
    • Moon phase and dates calculator
    • Nutation calculator
    • Position Angle of Saturn’s semiminor axis calculator
    • Sundial calculator
    • Solar longitude calculator

Consult the README documentation and the unit tests for details. Let me just illustrate one here. Suppose I want to know the four main phases of the moon for the month of August 2024:

DateOnly startDate = new(2024, 7, 1);
DateOnly endDate = new(2024, 9, 30);
DateRange dateRange = new(startDate, endDate);

var list = MoonPhaseDatesCalculator.Calculate(dateRange);

// use a collection expression to get just August
list = [.. list
    .Where(i => i.Moment.Month == 8)
    .OrderBy(o => o.Moment.ToDateTime())];

foreach (var item in list)
{
    Console.WriteLine(item.PhaseName + " on " + 
        item.Moment.ToDateTime().ToString("MM/dd/yyyy hh:mm:ss.fff tt"));
}

This displays:

NewMoon on 08/04/2024 11:12:56.525 AM
FirstQuarter on 08/12/2024 03:19:31.125 PM
FullMoon on 08/19/2024 06:25:37.281 PM
LastQuarter on 08/26/2024 09:27:16.726 AM

What’s next? I’ve got two enhancements open right now. One is to add a feature to calculate solar eclipses and the other is to calculate the positions of the four Galilean moons of Jupiter. Sometime after that I’ll want to address magnitude, planetary perihelion and aphelion, and probably more fun stuff with the Moon. Drop me a line if you have any requests.

Calculate New Moon Dates

In my last post (Calculate Future Solar Eclipses) I showed how to calculate the types of solar eclipses that would occur for a given date range. I took a shortcut and used a NewMoonData class that had a list of all known new moon dates that I culled from the timeanddate.com website. That worked just fine for the purposes of that blog post.

But in the real world who wants to hardcode every single new moon date into the far future? That’s not a realistic solution. I’m following up with an implementation in C# .NET, based on Jean Meeus’ algorithm he adopted from the ELP-2000/82 theory for the Moon. The results show the exact instant of the new moon phase (UTC) for any date from -1999 BCE to +3000 CE, accurate to within a few seconds.

The code is checked into my repo at FindNewMoonConsoleApp. Feel free to clone the code base and take it for a test ride. I won’t do a full walkthrough like with the solar eclipse calculations. I’ll just say that the general approach I took was to start with the first new moon in the J2000.0 epoch (6 Jan 2000) and enumerate over the mean new moon phases that follow. Starting with 6 Jan 2000 the program adds the lunar cycle of 29.5306 days to get 4 Feb 2000. Add the lunar cycle again and you get 5 Mar 2000, and so on for as many months and years as you like.

Sounds easy right? The problem is there are forces of gravity pulling on the Moon and Earth. And none of these bodies move at constant rates. So, the times of the mean phases of the moon just gets us in the ballpark of give or take a day or so. From there we have to apply an algorithm that corrects for all of the perturbations in order to get a more accurate date and time for each new moon.

Suppose I want to know the instant of the new moon in Dec 2022. I run the program and get: 12/23/2022 10:16:47 UTC. The Griffith Observatory, which uses the NASA/JPL Horizons system, rounds it up to 12/23/2022 10:17 UTC.

The program will produce results for every new moon that are accurate to within several seconds for any date range you provide.

Clear skies!

 

 

 

 

 

 

 

 

 

 

Calculate Future Solar Eclipses

According to Herodotus, who wrote The History around 430 BCE, a total solar eclipse interrupted a battle between the Lydians and the Medes:

[J]ust as the battle was growing warm, day was on a sudden changed into night. This event had been foretold by Thales, the Milesian, who forewarned the Ionians of it, fixing for it the very year in which it actually took place. The Medes and Lydians, when they observed the change, ceased fighting, and were alike anxious to have terms of peace agreed on.

(Source: Internet Classic Archives)

This “battle of the eclipse” took place in what is now Turkey, and the eclipse itself could have been the one that occurred on 28 May 585 BCE. Unfortunately, if Thales wrote anything it didn’t survive the centuries. So, we don’t know if he really did predict the eclipse or by what means he did it. All we have is Herodotus to go on. In any case, it’s the first mention in history of anyone predicting an eclipse so it’s interesting on that basis alone.

Wouldn’t it be cool if we could figure out when future solar eclipses occurred for us in the next decade or so? That’s what we’re going to do in this blog post so read on. Continue reading “Calculate Future Solar Eclipses”

Let’s Make a Sundial!

Let’s make a sundial that tells the hour of the day. I know what you’re thinking. Can’t I just go to my local garden store and buy one? Nope. Those are just for decoration only. A real sundial, one that accurately tells the time, must be built for your location (latitude). All sundials are local.

I recommend reading my previous post on building a solar calendar. Also, if you’ve never given much thought to the apparent motion of the sun across the sky, then check out my post on sidereal time. If you know all about sundials and you just want to build one, then read on!

Continue reading “Let’s Make a Sundial!”

Pretty Good Pipeline (PGP)

With apologies to Phil Zimmermann, I’ve put together a “pretty good pipeline” using Azure Pipelines, a multi-stage YAML file, and a couple of ARM templates to deploy a typical .NET Core 3.1 API to an Azure App Service. This won’t be a walkthrough or a “how to” so much as general guidance with links to relevant documentation for more information. From a high-level the pipeline will look something like this diagram:

I am not going to talk about containerization, A/B testing, the latest trends in DevOps, or continuous delivery where a dozen production releases are all in a day’s work.  This is just vanilla guidance for a typical mid-sized shop. If this still interests you then read on.

Continue reading “Pretty Good Pipeline (PGP)”

JSON Variable Substitution in Multi-Stage YAML Pipeline with Azure Key Vault

In my last post I showed how to configure JSON variable substitution with secret variables right in the pipeline. Now in this follow up post I want to expand on that to show how you could instead store your secrets in an Azure Key Vault and reference them in the pipeline. See the publicly visible TimeApi project on Azure DevOps for the source code, ARM templates, and the YAML file.

Continue reading “JSON Variable Substitution in Multi-Stage YAML Pipeline with Azure Key Vault”

JSON Variable Substitution in Multi-Stage YAML Azure Pipeline

If you made it past that long and technical article title then you are here for a purpose. Maybe you’re just getting started with the relatively new YAML experience in Azure Pipelines.  Or maybe you’ve been doing this awhile and found the variables guidance to be less than clear. In any case, in this article I’m going to show how to reference pipeline variables in an Azure Pipelines CI/CD multi-stage YAML file. See also the followup post to this one in which variables are moved into an Azure Key Vault.

Continue reading “JSON Variable Substitution in Multi-Stage YAML Azure Pipeline”

Calculate Distance Between Two Points on Earth

In two-dimensional space (a plane), the shortest distance between two points is a line. The shortest distance between two points on a sphere is the great-circle distance. The shorter arc described by the great circle running through the two points is then calculated by this well known formula below. Given the geographical longitude and latitude \(L_1, \phi_1\) of point P and \(L_2, \phi_2\) of point Q:

$$\cos d = \sin \phi_1 \space \sin \phi_2 + \cos \phi_1 \space \cos \phi_2 \space \cos (L_1 – L_2)$$

Where d is expressed in degrees:

$$d = \arccos (\sin \phi_1 \space \sin \phi_2 + \cos \phi_1 \space \cos \phi_2 \space \cos (L_1 – L_2))$$

By CheCheDaWaff – Own work, CC BY-SA 4.0, https://commons.wikimedia.org/w/index.php?curid=48187293

I once worked at a logistics company primarily as a database developer. I was asked to calculate distances between various ports in China and the U.S. in order to estimate fuel costs. I implemented the above great-circle algorithm in an Oracle PL/SQL package and it worked just fine. However, the Earth isn’t a sphere. Because of centrifugal force generated from the Earth’s rotation it bulges at the equator. It’s better to say that the Earth is a spheroid or an ellipsoid.

So while the great-circle algorithm is good enough what if we want even greater accuracy? To do that we need to take into account the Earth’s true shape as an ellipsoid. There are two variables we need. We need to know the equatorial radius of the Earth (a) and we need to know its flattening (f). Consider this ellipse that represents the Earth with an exaggerated equatorial bulge:

The equatorial radius AC (or BC) is labeled a and flattening f is the ratio of \(a – b \over a\). These values are constants accepted by the International Astronomical Union (IAU) and I can pull them from the wiki:

a = 6378.140 km

f = 0.00335281

Given these two constants we can now calculate the geodesic distance between two points on the Earth’s surface using Andoyer’s Formula. Here I’ve created the program in C# following Meeus’ Method as described in his book Astronomical Algorithms (p. 85). This method will produce an error of +/- 50 meters.

First there are two helper classes. DoubleExtensions has a method ToRadians that will be necessary for the trigonometric functions:

public static class DoubleExtensions
{
    public static double ToRadians(this double d)
    {
        return d * (Math.PI / 180); // convert degrees to radians
    }

    public static double ToDegrees(this double d)
    {
        return d * (180 / Math.PI); // convert radians to degrees
    }
}

And I created a small struct to wrap the geocoordinates of the two points between which we want to calculate the distance:

public struct GeoCoordinate
{
    public GeoCoordinate(double latitude, double longitude)
    {
        Latitude = latitude;
        Longitude = longitude;
        Name = "Unknown";
    }

    public GeoCoordinate(double latitude, double longitude, string name)
    {
        Latitude = latitude;
        Longitude = longitude;
        Name = name;
    }

    public double Latitude { get; }
    public double Longitude { get; }
    public string Name { get; }
}

With those two helpers in place the main program will calculate the distance between the Observatoire de Paris and the U.S. Naval Observatory in Washington, D.C.

class Program
{
    static void Main(string[] args)
    {
        // constants
        const double a = 6378.140;
        const double f = 0.00335281;

        var p = new GeoCoordinate(
            48.83698, -2.33652, "Observatoire de Paris"); 
        var q = new GeoCoordinate(
            38.921261, 77.06652, "U.S. Naval Observatory");

        double F = (p.Latitude + q.Latitude) / 2;
        double G = (p.Latitude - q.Latitude) / 2;
        double L = (p.Longitude - q.Longitude) / 2;

        double S = Math.Pow(Math.Sin(G.ToRadians()), 2) 
            * Math.Pow(Math.Cos(L.ToRadians()), 2) 
            + Math.Pow(Math.Cos(F.ToRadians()), 2) 
            * Math.Pow(Math.Sin(L.ToRadians()), 2);

        double C = Math.Pow(Math.Cos(G.ToRadians()), 2) 
            * Math.Pow(Math.Cos(L.ToRadians()), 2) 
            + Math.Pow(Math.Sin(F.ToRadians()), 2) 
            * Math.Pow(Math.Sin(L.ToRadians()), 2);

        double O = Math.Atan(Math.Sqrt(S / C));
        double R = Math.Sqrt(S * C) / O;
        double D = 2 * O * a;
        double H1 = (3 * R - 1) / (2 * C);
        double H2 = (3 * R + 1) / (2 * S);

        double s = D * (1 + f * H1 
            * Math.Pow(Math.Sin(F.ToRadians()), 2) 
            * Math.Pow(Math.Cos(G.ToRadians()), 2) 
            - f * H2 
            * Math.Pow(Math.Cos(F.ToRadians()), 2) 
            * Math.Pow(Math.Sin(G.ToRadians()), 2)
            );

        string d = Math.Round(s, 2).ToString();

        Console.WriteLine($"The distance between 
            {p.Name} and {q.Name} is {d} km (+/- 50 m).");
        Console.ReadLine();
    }
}

The output produces the correct result:

The distance between Observatoire de Paris and U.S. Naval Observatory is 6181.63 km (+/- 50 m).

 

 

 

Astronomical Calculations: Sidereal Time

What is Sidereal Time?

The vernal equinox for 2020 was last week (as of this writing) and I had planned on posting this on that day. But there’s a global pandemic spreading through the world right now and, like so many others in North America, I was preoccupied with other things. In any case, in honor of the vernal equinox this post is going to talk about sidereal time. If you’re an amateur astronomer interested in the algorithm for local sidereal time then skip down to the next section. If you’re coming in cold then read on!

Continue reading “Astronomical Calculations: Sidereal Time”