White areas show points of earth on land whose antipode is also on land. This is only about 8.6% of all of earth’s surface.

White areas show points of earth on land whose antipode is also on land. This is only about 8.6% of all of earth’s surface.

If you want to fly across the Pacific Ocean, you’ll have to board an airplane and fly around 12 hours. It’s pretty slow. A much faster route would be to go directly through the center of the earth. “Digging to China” was a common expression I heard growing up, with the implication that the opposite side of the globe is somewhere in Asia.

For the US, that’s actually not true. The opposite end of the earth for most of the US is actually somewhere west of Australia. For North America, there are actually very few places whose antipode (the point on the exact opposite side of the globe) is on dry land. If you could dig a hole through the center of the earth from the US, you’d pop out in the Pacific Ocean.

It is actually possible to “dig to China” though. Most of South America (excluding most of Brazil) has an antipode in east Asia. In fact, several of the world’s biggest cities have antipodes on dry land. I’ll get to this later.

Calculating Antipodes

Given the latitude and longitude of a point on earth, it’s pretty easy to calculate its antipode:

def antipode(lat, lon):
  lat = 0 - lat
  lon = 180 + lon if lon < 0 else lon - 180
  return lat, lon

Dry land?

Once I have the antipode of a particular latitude and longitude, I want to know if it’s on dry land or not. The process of figuring out what’s at a particular latitude/longitude point is called reverse geocoding, and there are a few nice tools for doing this for dry land. These tools will give fairly good information about the country a point is in.

But for now all I care about is whether a particular point is on land or water, not what country it’s in. I wasn’t able to find a great tool online that does this, so I opted for a more brute force method.

I used this picture from Wikipedia which represents almost all water as the same color of blue. Based on that, I can create a boolean mask to indicate oceans and lakes, and reverse project pixels from that image to geographic coordinates. Simple enough.

Pixels to Geocoordinates

Once you have the (x,y) coordinates they need to be converted to longitude and latitude. Latitude is how far north (or south) you are on the globe and ranges from -90 degrees at the North Pole to 90 degrees at the South Pole. On a flat map this is represented by a y coordinate.

Longitude represents how far east or west you are from the Prime Meridian (which runs through Greenwich, UK) and ranges from -180 to 180, both of which represent the same meridian.

How a latitude/longitude point is projected onto the globe depends on the map projection. In this case we’re using Equirectangular projection, so we just need to reverse that operation to get the x/y coordinates. The formula for doing so is:

#height is the height of the image
def lat2y(lat):
    return int((90 - lat) * (height / 180))

# width is the width of the image
def lon2x(lon):
    return int((lon + 180) * (width / 360))

# the reverse operations of the above
def y2lat(y):
    return 90 - 180 * y / height

def x2lon(x):
    return 360 * x / width - 180

Pixel Antipodes

Now we can calculate the antipodes of a pixel.

def pixel_antipode(y, x):
    lat, lon = antipode(y2lat(y), x2lon(x))
    return lat2y(lat), lon2x(lon)

Antipodal Cities

If we look at a list of the world’s largest cities, which of them have antipodes on land? In the top 20, only four cities do.

city population (millions) lat, lon antipode country
Shanghai🇨🇳 25.5 31.2, 121.5 Argentina🇦🇷
Beijing🇨🇳 19.6 39.9, 116.4 Argentina🇦🇷
Manila🇵🇭 13.5 14.6, 121.0 Brazil🇧🇷
Tianjin🇨🇳 13.2 39.1, 117.2 Argentina🇦🇷