Uluru, Ayers Rock or simply “the Rock” is a large sandstone monolith located in central Australia. It is thought to have formed 550 million years ago and stands 348 metres above the surrounding plain. It is listed as a United Nations Educational, Scientific and Cultural Organisation (UNESCO) World Heritage Site.
Uluru, and the surrounding area, is of great spiritual and cultural significance to the local Pitjantjatjara and Yankunyjatjara Aboriginal people. They believe Uluru was formed by ancestral beings during the Dreamtime and they have been its custodians for thousands of years.
Despite there being an abundance of information on Uluru no where does it detail how far it is from the sea. In this vignette will use R to determine far it is to the sea from Uluru? And where the closest point on the coast is?
To start the following libraries are loaded.
library(tmaptools)
library(rgeos)
library(geosphere)
library(rgdal)
library(ggplot2)
Data relating to the surface of the Earth, or geospatial data, can be a little confusing for the uninitiated so we’ll start with some basics.
The basic geospatial objects are:
In the 1950’s the United States Department of Defence, together with scientists from around the world, commenced efforts to establish a system to which geodetic data (measurements of the Earth) could be referred. This collaboration established a common latitude, longitude and elevation co-ordinate reference system (CRS) which was called World Geodetic System 1960 (WGS60).
Since 1960 the World Geodetic System (WGS) has been updated a number of times to account for new information and data that effects measurements of the Earth’s surface. The last such updated was in 1984 and formed the WGS84 used today as the standard reference system for modern technologies based on the Global Positioning Service (GPS).
The use of WGS84 to place objects on the earths surface is a common practice but there are other methods available. In this instance WGS84 will be used as the CRS and is set below using the get_proj4 function within the tmaptools package. The get_proj4 function requires a projection and, optionally, an output can be defined to determine how the projection is output, in this case we want the projection as a string.
As an aside WGS84 is being used but it’s not really a projection and more a plot of co-ordinates. A projection is the method by which a three dimensional CRS is displayed on a flat surface; WGS84 is the CRS rather than the projection but it can be used in this instance. A list of the various map projections can be found at http://en.wikipedia.org/wiki/List_of_map_projections, or for a more light-hearted version https://xkcd.com/977/.
wgs84 <- get_proj4("WGS84", output = "character")
wgs84
## [1] "+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs +towgs84=0,0,0"
The value of the wgs84 variable contains a few parts.
The International Association of Oil and Gas Producers has a collection of projections based on best practices for surveying and applied geodesy. These are often identified with an EPSG code. A registry of these projections can be found at http://www.epsg-registry.org/.
The first step is to identify the point on the Earth’s surface where Uluru is located. There are a number of packages and services that provide the ability to obtain the co-ordinates, or latitude and longitude, of an address or significant place. In this example the geocode_OSM function in the tmaptools package will be used. This function uses the Open Street Maps (OSM) Nominatim (http://nominatim.openstreetmap.org/) to identify the latitude and longitude for Uluru.
The first parameter passed to the geocode_OSM function is the search term, the second is the CRS or projection to be used, in this instance WGS84. The geocode_OSM accepts other parameters that control what information is returned and in what format. The server to use can also be set if a local OSM Nominatim server is available. Further details an be found in R using ?geocode_OSM.
loc <- geocode_OSM("Uluru", projection = wgs84)
longitude <- loc$coords["x"]
latitude <- loc$coords["y"]
Now that the latitude and longitude co-ordinates for Uluru have been obtained the point needs to be converted to a geometry object. This conversion is required for subsequent calculations of distance between Uluru and the sea.
To perform this conversion the readWKT function from the rgeos package is used. The readWKT function reads the Well Known Text (WKT), created by concatenating the latitude and longitude into the format POINT(longitude latitude), and outputs a spatial object in the specified WGS84.
loc_txt <- paste("POINT(",longitude,latitude,")")
loc_wkt <- readWKT(loc_txt, p4s = CRS(wgs84))
The coastline is a geographic boundary between land and sea. Fortunately to help find a point on this boundary there is a publicly available shape (.shp) file that contains the coastline as a linestring (i.e. a collection of connected points). The shape file is available on the http://www.naturalearthdata.com website.
The coastline shape file is downloaded and unzipped. It is then loaded into a spatial object using the readOGR function from the rgdal package.
download.file("http://www.naturalearthdata.com/http//www.naturalearthdata.com/download/10m/physical/ne_10m_coastline.zip",
destfile = 'coastlines.zip')
unzip(zipfile = "coastlines.zip",
exdir = 'ne-coastlines-10m')
coast <- readOGR("ne-coastlines-10m/ne_10m_coastline.shp", p4s = wgs84)
The output from the readOGR function is an object of class spatial data frame.
coast
## class : SpatialLinesDataFrame
## features : 4133
## extent : -180, 180, -85.22194, 83.6341 (xmin, xmax, ymin, ymax)
## coord. ref. : +proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs +towgs84=0,0,0
## variables : 3
## names : featurecla, scalerank, min_zoom
## min values : Coastline, 0, 0.0
## max values : Null island, 6, 7.0
Now that the location of Uluru and the coastlines of the world are known and loaded the minimum “as the crow flies” distance from Uluru to the sea can be calculated. This operation can be performed using the dist2Line function in the geosphere package. The dist2Line function returns a matrix with the distance, longitude and latitude of the nearest point on the line. The distance returned is measured in metres; the value is divided by 1000 to obtain the distance in kilometres.
dist_line <- dist2Line(loc_wkt, coast)
closest_longitude <- dist_line[2]
closest_latitude <- dist_line[3]
The distance from Uluru to the sea is 679.350808 kilometres. The location of the closest point on the coast to Uluru is at 131.1354273 -31.4747861 which is located on the South Australian coast at the head of the Great Australian Bight.
To get a better sense of where Uluru is located, and the closest point on the coast, a map can be created using ggplot.
As the map will be based on latitude and longitude the first step is to identify the distance between Uluru and the closest point to the sea in degrees of latitude and longitude rather than in kilometres. This is performed through the use of the gDistance function in the rgeos function.
Like the dist2Line function described earlier the gDistance function finds the minimum distance between two spatial objects. The difference is that gDistance will return the distance in the units of the projections of the spatial objects passed in. As we are using the WGS84 the distance will be returned in degress of latitude and longitude. The gDistance function could have been used to calculate the distance in kilometres but the projection of the location of Uluru and the coast would need to have been changed to one that output kilometres (or metres).
# Distance in degrees
dist_degrees <- gDistance(loc_wkt,coast)
After the distance in degrees has been calculated the circumference of the circle around Uluru can be determined. 1000 points on the circumference of the circle are calculated using the standard equation \(2\pi r\) and then added to the latitude and longitude of Uluru so as to be correctly centred on the map.
# Circumfrence of the circle 2pir
th <- seq(0, 2 * pi, len = 1000)
circle <- cbind(1.00001 * dist_degrees * cos(th) + loc_wkt$x,
1.00001 * dist_degrees * sin(th) + loc_wkt$y)
# Plot on map
ggplot() +
geom_path(data = coast, aes(x = long, y = lat, group = group)) +
geom_path(data = data.frame(circle), aes(x = X1, y = X2), colour = "blue") +
geom_point(data = data.frame(loc_wkt), aes(x = x, y = y), colour = "red") +
scale_x_continuous(limits = c(110, 155)) +
scale_y_continuous(limits = c(-45, -5)) +
coord_fixed()
Through the use of a number of R packages we’ve ben able to answer the initial question and visualise the data on a map. This technique can be applied to any point on the Earth’s surface to detemine the nearest coastline, regardless of whether that point is located on a land mass or in the sea.