Exploring Population Landscapes: 3D Maps of Egypt and Germany
Tools used: R, Adobe IllustratorThe initial spark for this project came about from my love of visualization, especially maps, which led me to discover Rayshader 3D maps. Their ability to distinctly showcase population distribution immediately caught my attention. Determined to delve into this technique, I aimed to create 3D visualizations that would straightforwardly present population densities within Egypt and Germany, both of which are important to me on a personal level.
The result was a set of interactive 3D maps that invite exploration and offer a novel way to appreciate population distribution in these two countries (an interactive version with three.js and React coming soon! đ). The project was really fun. I learned to use geospatial data and work with raster format. First, weâll take a detailed look at the Egyptian landscape, revealing the historical interplay of its people with the environment through my 3D rendering. Following that, Iâll share an insiderâs view of the coding journey that transformed raw numbers into the peaks and valleys. Finally, weâll voyage to Germany, applying the same methods to illustrate how population is spread across urban centers and rural landscapes.
Nile Reigns King
As the capital city and the largest city in Egypt, Cairoâs dense population is distinctly represented by a tall and concentrated spike in the map. The Nile Delta region, especially areas around cities like Alexandria and Port Said, show significant population density. The visualization distinctly highlights the historic concentration of the Egypt state along the Nile River, a lifeline for the nation, with most of its population residing along its banks.
Other notable spikes are observed in coastal areas like Marsa Matruh and Hurghada, which are popular cities and tourist destinations. Locations such as Siwa Oasis and Kharga Oasis, although smaller, are distinct and historical; a fun fact about Siwa is that Alexander the Great was crowned Pharaoh of Egypt there in the Temple of the Oracle. These oases have historically been vital habitats in the desert landscape. The final map uses a muted beige color as the base, reminiscent of Egyptâs vast desert landscapes, as well as the Riqâah script to reflect the most commonly used script in everyday Egyptian life.
Behind the Scenes
Initiating the project, I began by loading essential R libraries along with the Kontur Population 2022 dataset. This dataset estimates the worldwide population in 400m hexagonal geometries using a combination of âGHSL, Facebook, Microsoft Buildings, Copernicus Global Land Service Land Cover, Land Information New Zealand, and OpenStreetMap data.
A significant aspect of this process was the introduction of the stars package. This was my first time using it, and it proved instrumental for its capability to handle both raster and vector datacubes effectively. The package facilitated the transformation of geospatial data, specifically in .gpkg format (imported using the sf package), into a raster format. This conversion was a crucial step, forming the backbone of the subsequent 3D rendering.
# Load Required Libraries
library(sf) #handling spatial data
library(stars)
library(tidyverse)
library(rayshader)
library(MetBrewer)
library(colorspace)
# Load Kontur Data
data <- st_read("kontur_population_EG_20220630.gpkg")
# Data Conversion: Spatial Data to Matrix
size = 5000
rast <- st_rasterize(data, nx=floor(size*w_ratio),
ny=floor(size*h_ratio))
mat <- matrix(data=rast$population, nrow =floor(size*w_ratio),
ncol =floor(size*h_ratio))
With the data prepared, Rayshader takes the stage, turning our matrix into a 3D plot using the plot_3d()
function from the rayshader package. The following snippet of code illustrates how the matrix was transformed into a digital elevation model, which then served as the canvas for our 3D plot. Parameters such as zscale
, solid
, and shadowdepth
determine the visual characteristics of the plot, such as the elevation scaling and shadow effects. Camera angles were adjusted by render_camera()
to provide the best view.
# Create 3D Plot using Rayshader
mat |> height_shade(texture = texture) |>
plot_3d(heightmap = mat, zscale = 200/5, solid = F,
shadowdepth = 0)
# Adjust Camera Angles
render_camera(theta = -20, phi = 45, zoom = 0.8)
The final image below showcases the result of these processes. I used the render_highquality()
function from the rayshader package to output a detailed representation of Egyptâs population density. The heart of the aesthetics is the dynamic double-shadow effect achieved by using two distinct light sources. Two lightaltitude()
values, 30 and 80 degrees, are defined. The first light source at a lower altitude creates sharper and longer shadows, emphasizing the population spikes, while the higher altitude light creates softer shadows, adding depth to the visualization. With lightintensity()
parameters of 600 and 100 respectively, the primary light source is much brighter, creating dominant shadows, while the secondary source gives a diffused lighting effect.
# Adjust camera angles and Render plot
render_camera(theta = -20, phi = 45, zoom = 0.8)
render_highquality(
filename = outfile,
interactive = F,
lightdirection = 280,
lightaltitude = c(30, 80),
lightcolor = c(c1[4], 'white'),
lightintensity = c(600, 100),
samples = 450,
width = 6000,
height = 6000
)
Final Output
I chose the color pallete by Met Brewer for my love of renaissance art and Matâs ability to encapsulate all sorts of palletes from different artistic movements. For Egypt, the color âGreekâ presented a beautiful choice to reflect Egyptâs vast beige deserts and intense density reds. The colors were further enhanced by colorRampPalette
to give it more depth. The colors not only make the visualization appealing but also help in distinguishing population density variations.
# Generate Color Palette using MetBrewer
c1 <- met.brewer('Greek')
texture <- grDevices::colorRampPalette(c1, bias=2)(256)
A look at Germany
Transitioning from the Nile-focused population distribution of Egypt to Germany diverse distribution, the same 3D mapping techniques take on a different journey. This map illustrates the contrast between Germanyâs bustling urban centers and its serene rural areas. The stark spikes of Berlin, Munich, and Hamburg rise prominently, each peak representing the dense hubs of activity and culture these cities are known for. Less densely populated areas, like those surrounding Dresden and Nuremberg, create a textured landscape of valleys amidst the high urban peaks.
Taking a closer look at the map, you canât help but notice an empty semi-circle region of lands surrounding Berlin. At first glance, it might seem like a whimsical dip in the data or a playful stamp of sorts. In reality, this area is known for its sparse population, a phenomenon that is not rooted in a single cause but rather a tapestry of theories. Some suggest that Berlinâs marshy foundations, shaped by its glacial history, have influenced settlement patterns (Berlinâs name is allegedly derives from the Slavic word berl, meaning âswampâ). Others point to the transformation of the landscape by human intervention and industrialization, attracting migration from that area towards Berlin. It is most likely a result of the regionâs layers of history and geography as a whole rather for a single definitive reason.
In this project, I tried to bring together data analysis, geospatial analysis, and graphic design. One of the standout features is the meticulous care taken in aspect ratio handling and color palette generation, ensuring the final 3D plot is not only accurate but also visually compelling. Another interesting aspect is the seamless integration of spatial functions with 3D rendering capabilities, showcasing the power of R in handling diverse tasks. The full project can be found on GitHub along with other graphics and the Adobe Illustrator file.