After trying some of the TopoJSON examples I could not resist the temptation of learning more about it. As a Catalan citizen, I decided to focus on Catalonia (or Catalunya in Catalan). Before starting I did a quick search to see if somebody else had already used TopoJSON in my region. I found some nice examples from a couple of authors: martgnz and rveciana. However in these examples little information is given on how maps are generated. Particularly topics like map simplification or projection are not discussed. So I decided to write this post where I explain in some detail the process of generating the TopoJSON maps for Catalonia.
Together with this post I have created the cat-topojson utility which will allow you to easily generate the maps.
In this post we will also use some tools part of GDAL, useful
to convert from one coordinate system to another or simply to retrieve
information from map files. It can also be installed using
Before we proceed further, we need to obtain the source maps. They are freely
available from ICGC (registration is required). The
maps of interest are called Base Municipal and are offered in multiple scales
(1:50, 1:250 and 1:1000) and formats (DXF, DGN and SHP). In the examples found
in this post we will use the scale 1:50 and the format SHP (shapefile), which is
the only one of the list supported by
topojson. The specification for these
maps can be found
A summary of the relevant information is given below.
The shapefiles of interest contained in the downloaded file are the following:
eeee is the scale (i.e.,
m is the
frame coordinate reference (only
1 is available, meaning EPSG:25831 - ETRS89
/ UTM zone 31N),
aaaammdd is the maps reference date (e.g.
c is the distribution revision (e.g.
0). Other files are provided, e.g.
the location of municipality capital cities, but they will not be analyzed in
We can easily get detailed information of each file using the
utility provided by GDAL, e.g.
Generation of the TopoJSON maps
In the following sections the process of generating the TopoJSON maps from the ICGC shapefiles is discussed.
There are two types of coordinate systems used in maps: projected (X, Y) or geographic (, ). As we have just seen in the previous section, the maps provided by ICGC are projected in UTM. Advantages of using projected coordinates include better simplification results as well as reduced overhead on the rendering process as stated in this example. You can use either one or the other with D3.js, so choose what best fits your application. In this post examples for both cases are provided.
In order to change from one coordinate system to another, you can use the
ogr2ogr utility provided by GDAL. Actually,
ogr2ogr offers many more
possibilities (e.g. filtering), but it is left to the reader to explore them. As
a quick example, if you want to convert the counties shapefile to the World
Provided that your input maps are in geographical coordinates, you could also
topojson --projection option to apply one of the D3.js
Finally, when using projected coordinates, we can specify
--margin to fit a viewport of the specified size. This will
simplify the map usage if we know in advance where we are going to display the
map, as we will not need to translate or scale it (see the examples).
Simplification and quantization
An important thing to care about when distributing maps is its complexity and size, both intrinsically related. Two techniques can be used to reduce both: geometry simplification and quantization.
As illustrated, in this article geometry
simplification reduces the number of points given an area threshold. This area
threshold is specified through the
-s argument. It is given in
steradians in geographical coordinates. In
case of projected coordinates it is given as squared base units, e.g. if we use
--height it will be in px2.
Quantization is about numeric precision. TopoJSON uses fixed
point coordinates, and allows you to
specify the number of differentiable values. It is controlled by the
--post-quantization to specify
input and output quantizations, respectively. A value of 10.000 differentiable
values is used by default, which in most cases will be fine. Roughly speaking,
the more values, the larger the size of the map.
In any case, the simplest way to choose the right simplification and quantization parameters is to try and see how map looks. Three illustrative examples are shown below, exaggerating the effects of simplification and quantization in the second and third maps, respectively.
The ICGC shapefiles contain some properties which are useful to retain (e.g. province names, area, etc.). They are detailed in the specification file.
topojson does not copy the properties contained in the input
-p argument can be used to copy all properties, or
target=source to only keep the
source property while renaming it to
target. More than one property can be copied by passing multiple
arguments or by appending multiple properties, e.g.
name=NAME,surname=SURN. Furthermore, prepending a
+ sign to a property
name will force the property to be a number, e.g.
Another important argument is
--id-property. It is used to assign any of the
properties to the ID of the geometry.
Finally to conclude this post a couple of minimal examples are provided. Note that not many details are given on how to use D3.js/TopoJSON, as it is not the aim of this post. If you want to learn more about the topic, you can find great tutorials online like this.
In order to run the examples you will need an HTTP server, e.g.
In this example we will use the counties (comarques) map and fit it to a
viewport of 500x500 px. As the source map is already projected, we can just feed
Then, we can quickly visualize the results creating an html file with the following code:
In this second example we will use the municipalities (municipis) map but the
projection will be done on the browser. We first use
ogr2ogr to convert our
map to the WGS-84 geographical
Then, we use
topojson to generate the map:
Note that an area threshold of 10-8 sr has proved to deliver a good compromise after a few tries.
When using a projected map already adjusted to a viewport we do not need to care about centering or scaling it, but now we do. Finding the right values is a tedious task, as you need to go through a trial and error process until you find an acceptable result. However, there is an easy way to automatically center and scale a map described in this great example, which could even be used to calculate the right static values. Summarizing, the example code looks like this: