Skip to main content

Command Palette

Search for a command to run...

The earth may not be flat II

Updated
12 min read

This isn’t really going to be a blog about flat earth. One more thing.

My last post was about how observed daylight doesn’t work on a purported flat earth map, as the day and night make unusual shapes which cannot be explained. The way the light really works is explained here.

On the earth, the sun lights up slightly over ½ of the world at one time, leaving slightly less than ½ in darkness. Since light bends in the atmosphere, the light refracts over into the half of the world that is not directly lit by the sun, leaving somewhat more of the planet lit up than in than dark.

One could demonstrate this by determining a position that the sun was directly overhead (the noon point). Then, figure out the positions where at that time the sun was rising or setting. We’d expect that the radius between the noon point and the sunrise/sunset positions would form a circle. Furthermore, there would be an antipode of the noon point and the sunrise/sunset points would also form a circle around those points. You could show this by calculating distances between the points.

If the results show two circles, the earth could not be a flat plane. On a flat plane, the arc that circles around the noon point could not also circle the antipode of that point. Thus, we are trying to generate noon points, the antipode of that point, sunrise and sunset points and distances between them.

This isn’t really about the shape of the earth, but about generating this data with python using two packages, astral to calculate solar positions and geopy to calculate distance. Note that both of these packages rely on the earth being a globe, so it would be no surprise that they behave as expected, but the use here is to give observations about day, night and distances on the earth. If the observations the program makes match reality, the earth must be round. For the earth to be flat, some observations must be disproved.

The python script I wrote for this is in https://github.com/jamesdogrady/sunGleason, called daylightDistance.py.

To find the circles we need to calculate the point at which the sun is most over head on the earth. From there, we can determine the antipode of this point, which would be the center of darkness. The edges of the circles can be calculated by finding sunrise and sunset at various latitudes. Most of the time, some portions of the planet have 24 hour darkness or daylight, so the circle edges must account for this as well.

I’m mis-using astral here rather than a package that calculates the edges directly, so we have to find the points we require by using the astral package for a set of latitude and longitudes. This requires searching for the proper points which makes the program less direct. This will lead to errors as we may not calculate the edges of the circle with absolute precision. This make the exercise less about showing the earth is a globe and more about using astral to make observations to support a globe.

First, we have to find the noon point. We can tell where it is solar noon currently by looking on the equator and getting the time for solar noon, and calculating from that the longitude at which it’s currently noon. This looks like this.

obs_lat=0
obs_long=0
obs=Observer(obs_lat,obs_long);
noon_tm=noon(obs,tm,tzinfo=utc);
dps=15/(60*60)
# calculate the longitude where it is noon currently.
# noon has either passed or is coming, so we can tell where it is.
if ( noon_tm > tm ) :
    # noon is coming.
    noon_time=(noon_tm - tm).seconds
    noon_long=obs_long + noon_time *dps
else :
    noon_time=(tm - noon_tm).seconds
    noon_long=obs_long - noon_time * dps

The noon latitude is between the Tropic of Cancer and the Tropic of Capricorn, and we search within this range to find it.

eq_obs=Observer(0,noon_long);
eq_zenith=zenith(eq_obs,tm);
north_obs= Observer(tropic_cancer,noon_long);
south_obs= Observer(tropic_capricorn,noon_long);
north_zen=zenith(north_obs,tm);
south_zen=zenith(south_obs,tm);

done=False
first=True
north_lat=tropic_cancer
south_lat = tropic_capricorn
while not done :
    # if the zenith is the same at both endpoints the correct value is in the middle.
    if north_zen == south_zen :
        noon_lat = (north_lat + south_lat) /2
        done=True

    # are we close enough to stop?
    diff = abs(abs(north_lat) - abs(south_lat))

    if (not first and diff < precision ) :
        noon_lat = north_lat
        done=True
    first=False;
    if ( north_zen < south_zen ) :
        # between center and south.
        south_lat = ( north_lat + south_lat)/2
        south_obs= Observer(south_lat,noon_long);
        south_zen=zenith(south_obs,tm)
    else :
        north_lat = ( north_lat + south_lat)/2
        north_obs= Observer(north_lat,noon_long);
        north_zen=zenith(north_obs,tm);

We are looking for the lowest zenith and thus the point where the sun is highest in the sky. The point on the opposite side of the earth from this noon point have the opposite latitude. For longitude, we add 180 to western (negative) values and subtract 180 from eastern (positive) values.

To calculate the edges of daylight and night, we write a function to search for the points.

def find_true_value(low,high ,val,tm,fcn) :
    done=False
    while not done :
        ret_bool = False;
        t=abs(high - low)
        # for longitude, if you are more than 180 apart, you are going the long way around.  
        if t > 180 :
            t=360-t
        diff = t/2
        if ( diff < precision  ) :
            return low
        mid = low+diff
        # this could be a latitude but it won't be that big
        if mid > 180 or mid < -180 :
            mid=conv_long(mid);
        (res,v) = fcn(mid,val,tm);
        if v != None and v :
            ret_bool=True
        if res :
            high=mid
        else :
            low=mid

The point we are searching for is between low and high. fcn is a helper function for the search. If it returns True, the point we are looking for is between low and mid. if it returns False, the point we are looking for is between mid and high. This function works for both latitude and longitude searches. If low/high are latitudes, val must be a longitude and fcn must understand which value is being passed in and vice versa.

The helper function that finds the 24 hour sun is shown below.

def twenty_4_hour(lat, long,tm) :
        obs= Observer(lat,long)
        noRise=False
        light=False;
        try :
            rise=sunrise(obs,tm);
            noRise=False
        except ValueError as e :
            noRise=True
            found_24_hour=True
            if "above" in e.args[0] :
                light=True;
            else:
                light=False;
        if ( lat < 0) :
            return( not noRise,light);
        return(noRise,light);

For each trial, we see if there is a 24 hour sun at the given latitude. If there is, we know the latitude we are looking for is south of us in the northern hemisphere and north of us in the southern hemisphere, so we return a different value. For example, the southern light point is found by starting from -90 and going to just north of the antarctic circle (-65)

(south_lat)=find_true_value(-90,-65,noon_long,tm,twenty_4_hour);

We have similar helper functions for sunrise and sunset for latitudes at which the sun does rise and set to find the points where this occurs. Note that while the sun travels at 15 degrees per hour, you cannot calculate sunrise/sunset longitudes because while the earth is rotating on it’s axis, it’s also revolving around the sun, so the longitude of sunset/sunrises varies slightly due to the tilt of the earth. Unless you. account for this, the positions of sunrise/sunset are wrong.

Once we’ve calculated the points where the sun is rising or setting, we can calculate distances. geopy has a geodesic function to calculate distances using great circles accounting for the oblate spheroid shape of the earth. The program also calculates distances assuming a sphere. geodesic takes two points, so we do calculations like this

     radius =geodesic((noon_lat,noon_long),(lat,sunrise_long)).kilometers

In order to confirm the observations, there are check functions to be sure than sunrise, sunset and noon are close to where the program calculates they are. Here is check_sunset

def check_sunset(lat,long,tm) :
    s=" sun is up"
    if debug :
        print("check_sunset",lat,long);
    lat_obs = Observer(lat,long)
    set_time = sunset(lat_obs,tm) 
    if ( set_time > tm) :
        diff = set_time - tm
    else:
        s="sun has already set"
        diff = tm - set_time
    if debug :
        print("check_sunset(",lat,",",long,") ",diff.seconds," different");
    if ( diff.seconds < assert_seconds ) :
        return True;
    return False

assert_seconds and precision define how accurate the search is.

To handle 24 hour sun/darkness, we need to find where the edge is of darkness or light. If there is 24 hour daylight at say 85 ° N and the noon longitude is 120 degrees E, it will be light at the 120 E latitude up to the north pole. It won’t be dark until you get to 85 degrees N at the opposite longitude. We’ve calculated this longitude before, it’s the longitude of the antipode of the noon point. So that’s the edge of the daylight/night circles in the arctic regions.

We calculate all the radius’s for daylight and nighttime and put them in pandas data frame so we can do analysis on the results.

daylightDistance.py -g -s

Time is 09-09-2025 16:47

Noon Point is (5.05,-72.70)

Anti Noon Point is (-5.05,107.30)

value average range std dev

---------------------------- --------- ------- ---------

daylight radius (sphere) 10095.59 59.85 8.56

darkness radius (sphere) 9919.52 59.85 8.56

circumference (great circle) 40030.23 0.00 0.00

daylight_radius (actual) 10099.64 71.37 11.27

darkness radius (actual) 9923.83 71.37 11.71

Here, we see that as expected, there is a rough circle around both the noon point and the anti-noon point. While not all radius’s are the same as measured, they are within a fairly narrow range, 59.85 km of around 40075 km earth circumference . The standard deviation of these errors is also low. Note that the calculated circumference in a great circle model is based on the observed radius and not on the actual circumference so it differs from the accepted value of the circumference. On the oblate spheroid earth, we would expect less circular shapes as the flattening introduces distortion on the circles and we do see this.

With this program, there is an option to show the points which we think of the edges of the circle. We’ll show this at the 2025 winter solstice. (the -l option shows points every 20° ).

python3.13 daylightDistance.py -l 20 -g -t "12-21-2025 9:03" -v

Time is 12-21-2025 15:03

Noon Point is (-23.05,-46.19)

Anti Noon Point is (23.05,133.81)

value average range std dev

------------------------ --------- ------- ---------

daylight_radius (actual) 10108.20 131.56 40.25

darkness radius (actual) 9914.09 131.56 41.25

Radius Data Oblate Spheroid

point distance from noon (km) distance from anti-noon (km)

---------------- ------------------------- ------------------------------

(-40, 66.33) 10141.58 9876.64

(-40, -158.76) 10145.79 9872.42

(-20, 53.79) 10123.83 9904.50

(-20, -146.22) 10129.73 9898.59

(0, 44.64) 10100.77 9931.62

(0, -137.07) 10107.14 9925.24

(20, 35.63) 10074.72 9953.85

(20, -128.06) 10080.26 9948.32

(-65.78, 133.81) 10154.87 9849.06

(67.34, -46.19) 10023.31 9980.63

Note that the program does worse calculating the distances as we move closer to winter. This is because more of the sunlight and darkness is over the somewhat flattened polar regions.

Two options control the accuracy of the calculations. -p specifies how close to a point we need to look. This defaults to .05 and is in degrees. -a will cause the program to delete points for which the difference between sunrise/sunset and the current time is greater than the specified value. The default is 30. Playing with these values doesn’t really impact the results that much. You see a more consistent radius, but not by that much.

The results match our expectations. We see the circles we expect to see. While of course a point opposite the noon point has no meaning on a flat plane, the fact that we can identify a point where darkness forms a curve indicates that this point would be real and have significance. The noon point, sunrise and sunset are all observations that can be made on the earth.

I took a look at the values calculated for the circle around the antipode of the noon point for various times over the course of year. As you might expect, the calculations for a oblate spheroid are within a narrow range, but not that even.

The results for spherical model are quite narrowly defined. Here, outliers are excluded from the histogram, but the counts are not significant in this range.

It might perhaps be possible for daylight on a flat earth to form a circle around an overhead sun at the noon point. It would not be possible for the night to form a circle at the same time as we see here. The edge between daylight and night curves between two points on the earth at the same time, all the while moving over the course of a day and year. The geometry that support this is a globe earth.

The only way out would be to claim that the distances calculated here are not accurate. The problem this creates is that the same calculations are used regularly to measure distances on the planet accurately, for instance, for airline flights. There is not a way to resolve this problem. An attempt to claim distances are different than calculated will inevitably bump up against known distances on the planet.