It's possible to measure the dip in the horizon with altitude due to the curvature of the Earth with a theodolite. At 11,580 meters or 38,000 feet the refracted dip (the angle the horizon is below the horizontal plane taking into consideration atmospheric refraction) is 3.2°. I used a theodolite app on my Pixel 2 XL phone known as "Dioptra". Dioptra displays the angle of the target object in the center of the screen, where the crosshairs are, relative to the horizontal plane. For example, 1° would mean that the target is 1° above the horizontal plane, or 91° relative to plumb.

Before trusting the values provided by Dioptra, or any theodolite app, it needs to be tested for a systematic offset which I'll refer to as the "bias". My phone reads 0.9° when level, so it has a bias of 0.9°. I'll start with the three different tests I did to find the bias, but I'll leave it as an exercise to the reader to determine which method is best. All methods are roughly in agreement.

The Geocam app has a similar bias of 1.1°, which is close to 0.9°. I've contacted tech support for my phone as well the theodolite apps, but I have not found a root cause.

For each photo it's possible to see a larger version by clicking.

Mirror Dioptra Test

Before using a mirror to test Dioptra we must first know how close the mirror is to vertical. In this case the mirror turned out to off by 0.3° with the top part of the mirror closer to the viewer:

One way of getting the phone perfectly level relative to the mirror is to place the crosshairs on a refection of the camera lens. I placed bits of pink paper above and to the side of the lens in order make it easier to see:

Dioptra indicated 1.2°, but we need to subtract 0.3° for the mirror which gives 0.9° for the bias.

I took a photo upside down to see if that would make a difference. This turns out to be tricky since the Dioptra app acts strangely when it transitions from -180° to 180°. It read 179.2°, but 179.4° would've been more consistent with the upside up measurement:

Tube Dioptra Test

I placed a long stainless steel tube on top of the laser level after putting pieces of paper under the laser level so that it was within 0.03° of level. At the end of the tube I placed a dark box with a small bit of pink paper on it that could be seen through the tube. I then attempted to take a photo straight down the tube using Dioptra:

Dioptra said 0.8°. The photo is slightly off horizontally, but vertically is what matters, and that seems to be about right.

Laser Dioptra Test

Since the level has a laser feature where the laser is horizontal when the level is horizontal I put pieces of paper under the level until it was within 0.03° of horizontal. I then turned the laser on and placed a solar filter in the beam to protect the camera. I then took a photo looking straight down the beam with the beam centered in the crosshairs:


On December 30th 2017 I took flight 3568 from Austin, TX to Nashville, TN. I took photos out the plane window in order to capturing a dip in the horizon.

On overcast days, like this one, it's important to keep in mind that the apparent horizon is caused by the cloud tops. Any calculations to find the expected refracted dip in the horizon should be done treating the cloud tops as if they are ground, and then measuring the height from there.

Here's a photo shortly after exiting the clouds while ascending at 398 meters, or 1,306 feet:

Note that Dioptra recorded 1.1° which does not make sense, which may be because the plane was turning. Consequently it's hard to know when the angle recorded by Dioptra on a plane is accurate, but it probably helps to wait until after cruising altitude is reached. Also, I would make a note if the heading as indicated by my cell phone compass seemed stable. I think I took the following two photos when the plane was stable, but it's possible there was some instability I wasn't aware of:

Here's a photo with the crosshair on what appears to be the cloud horizon (for lack of a better term) taken at 11,581 meters or 37,995 feet:

And finally here's a photo of 0.9°, which should be the horizontal plane as per Dioptra testing done above. In other words, this should be where the horizon would be at ground level, or where it would be if the Earth was flat. Taken at 11,035 meters or 36,204 feet:

Here's a photo from flight 1970 from Austin to Baltimore at 2018-12-25 6:50:45. It was early enough to capture the sunrise:

At here's a photo taken shortly after in Dioptra at 6:53 am:

From the first sunrise image we can see that the horizon is curved. The red line is straight. The green dot is the center of the image. Click to see a larger version of the image with markings, or here's the original image without the red and green markings.

From the Dioptra sunrise image it seems the altitude was 10,881 meters. Using that information the Metabunk calculator can be used to find that the "Horizon Curve Pixels" is 33.80 (which is calculated with atmospheric refraction) for the larger 4032x3024 image, which is more than the 25 pixels seen in the image. The discrepancy is due to the horizon being a relatively flat cloud layer. To estimate the distance the plane is above the cloud layer different values for the viewer height are used until it outputs 25 pixels, which is a viewer height of 5,955 meters. Subtracting from plane altitude for 10,881 meters gives a cloud height of 4,926 meters.

It's possible to come up with a better estimate taking into consideration atmospheric refraction. Using the formula from that section:

k_eff = k_sea*(54000 - 2*h_hor - h_obs)/54000
k_eff = (1/7)*(54000 - 2*4926 - 10881)/54000
k_eff = 0.088

The above can be used to find the effective radius of the Earth:

R_eff = R/(1 - k_eff)
R_eff = 1.0965*R = 6986 km

We can now plug the 6,986 meters into the calculator to come up with a better estimate for the viewer height over the clouds that produces 25 curve pixels. That viewer height is 6,530 meters, so the clouds tops are 10,881 meters - 6,530 meters = 4,351 meters above the ground.

We can also see from the calculate that the horizon dip (not the refracted one since that was taken into consideration by adjusting the radius of the Earth) is 2.476°. This is the value that matters. It impacts the sunrise time.

For the Dioptra sunrise image the crosshairs are 63 pixels above the horizon, which can be seen by rotating it 2.88° counter clockwise. Using a HFOV of 64° for the Pixel 2 the SPP (see the sun page for an explanation) is 0.0006102 which means the 63 pixels is 2.2°. Subtracting from 2.2° from the 0.7° displayed and then subtracting 0.9° for the bias results 2.4° below the horizon. This is close to the 2.476° horizon dip given by the Metabunk calculator.

Here's the original Dioptra image with white crosshairs.

From EXIF data of the first sunrise image we can see that the coordinates are 33.65 N 92.09 W which can be entered into timeanddate.com in order to see that the expected sunrise on that day for that location was 7:11 am, but the photo was taken at 6:50 am, a 21 minute discrepancy.

The discrepancy is due to the 2.476° horizon dip. The sun travels at a rate of 15°/hour around the celestial poles, but the rate relative to an observer is less by a factor of cos(suns-declination). At that time the declination of the sun was 23.416°. Also, the sun does not rise straight up from the horizon, but at an angle. The horizontal component is cos(latitude). These factors can be combined to find the rate that the sun rises up vertically:

sun_rise_rate = 15°/hour*cos(suns-declination)*cos(latitude)
sun_rise_rate = 15°/hour*cos(23.416°)*cos(33.65°)
sun_rise_rate = 11.46°/hour

For the sun to rise across the 2.476° horizon dip should take:

(2.476°)/(11.46°/hour) = 0.2160° = 12.96 minutes (approximately 13 minutes)

Subtracting 13 minutes from 7:11 am gives 6:58 am. The first photo was at 6:50 am, which may have been before sunrise. The Dioptra photo was at 6:53, which appears to be at sunrise. The sun appears 0.5° higher when on the horizon due to atmospheric refraction. Maybe some of the remaining discrepancy can be explained by looking through additional atmosphere at the sun. Maybe some of the sunlight is able to shine through the cloud layer. In any case the sunrise is significantly sooner than expected on the ground.

Atmospheric Refraction

In order to analyze images where the horizon is below eye level and curved it's helpful to understand the effect that atmospheric refraction has. At sea level the coefficient of atmospheric refraction k is 1/7, which means that the effective radius of curvature of Earth is increased by a factor of 7/6, which can be seen in the Metabunk calculator.

Atmospheric refraction is due to a gradient in the refractive index at right angles to the line of sight, which is due to a gradient in the density of air. Here's the density and pressure of the atmosphere as a function of height:

Since it's the orange "density slope" that matters it's been curve fitted with a straight magenta "density slope linear" line that will be used to estimate the effect of altitude on the refraction constant (k). The straight line has a 5% error relative to sea level for k for flight altitudes.

The graph was produced by SageMath with this file.

The line of sight is not at one altitude, but rather dips down to meet the horizon where the altitude is minimum, and then, if allowed to pass the horizon, symmetrically increases in altitude. The line of sight can be curve fit with a parabola with the apex at the horizon. If the simplifying assumption that the density slope is linear then finding the effective density slope, and therefore the effective altitude, can be found by a weighted average where the horizon altitude has twice the weight of the observer altitude (see Simpson's rule):

k_eff = (k_obs + 2*k_hor)/3

The "density slope linear" is:

dsl = 1 - h/18km.

Combining the above concepts:

k_eff = k_sea*((1 - h_obs/18km) + 2*(1 - h_hor/18km))/3
k_eff = k_sea*(54000 - 2*h_hor - h_obs)/54000

For example, set's say the horizon is at 5 km and the observer is at 10 km. The effective k would be:

k_eff = (1/7)*(54000 - 2*5000 - 10000)/54000
k_eff = 0.0899

Applying the above k_eff to find the effective radius of the Earth:

R_eff = R/(1 - k_eff)
R_eff = 1.0988*R


The P900 can be used to magnify the horizon by zooming in on it. When the magnification is done at a low altitude the horizon is close enough that details can be seen making it clear that it can't be very far away. Here's a photo I took of the Atlantic ocean in Jacksonville FL on December 26th 2018:

Notice that the waves are visible on the horizon making it bumpy.

I don't know how high my camera was above the water, but a very rough guess is 2 meters. Using that rough guess the Metabunk calculator indicates that, with refraction, the horizon is 5.45 km away. Since the photo was taken with maximum optical zoom (2000 mm focal length 35 mm equivalent) the HFOV should be 0.99° and the VFOV should be 0.74°. Calculations with that information reveal that the horizon is 94 meters long, and the photo at the same distance is 70 meters high. Like all other photos on this page click on the photo to see a larger version.

In any case it's interesting to look it. It looks like a wall of water.


It's unfortunate that theodolite apps such as Dioptra may have a bias. Perhaps there's confusion as to whether the center pixel corresponds to the horizontal plane. In any case it's important to test a theodolite app before using it. Also, I believe a dip in the horizon was demonstrated, but there are possible pitfalls, such as the plane turning, which causes roll and yaw.

That being said if we take the value of -1.9° shown for the cloud horizon and subtract from 0.9°, which is plumb, we get 2.8°. The cloud horizon is somewhere below 398 meters. So for that photo a height of 11,581 meters - 398 meters = 11,183 meters should be used. Entering 11,183 meters into Metabunk's Curve Calculator reveals a refracted horizon dip of 3.1°, which seems close. However, maybe the non-refracted value of 3.4° would be more appropriate at this altitude since refraction, which is cased by density gradient in the air, is less at higher altitudes.

For the -1.9° photo the crosshair is a bit above the cloud horizon, but only by 14 pixels. There are 28.54 pixels/° (see the this zip file for images and an explanation of how the pixels/° value was determined), so that reduces the angle by 14 / 28.54 = 0.5° which changes -1.9° to -2.4° which then changes the measured dip to 0.9° - -2.4° = 3.3°, which is between the expected non-refracted and refracted horizon dip.