Introduction
Which Belgian ring road is the best ring? To answer this question, we first need to define what a ring road is:
- 1. A circumferential highway around a town, city, or other conurbation.
- 2. A highway that encircles an urban area so that traffic does not have to pass through the center."The Brussels Ring Road handles over 20 vehicles daily."
In our case, let’s call all, and only, roads that are referred to with an R-number a ring road.
This excludes several national roads, such as the N712 around Pelt, which shows promising ring-like characteristics.
If a road is not deemed impressive or important enough to warrant an R-number, it is certainly not impressive enough to be called the ringiest Belgian ring road.
Some ring roads were planned but ultimately failed to come to fruition. A notable example is the R7 around Liège,
which was planned to be formed by the unfinished A604, the E42, the E25, and the planned but cancelled A605.
The ring roads are numbered in categories:
- R1-R9 around principal cities,
- R10-R19 in Antwerp,
- R20-R29 in Brabant (Flemish and Walloon),
- R30-R39 in West Flanders,
- R40-R49 in East Flanders,
- R50-R59 in Hainaut,
- R60-R69 in Liège,
- R70-R79 in Limburg.
The name “ring road” implies two properties of such roads: they are ringlike, and they are roads.
The latter property is trivially satisfied by our definition above, so let’s focus on the former:
- 1. A circular object, form, line, or arrangement.
- 2. A small circular band, generally made of precious metal and often set with jewels, worn on the finger.
- 3. A circular band used for carrying, holding, or containing something."a wedding ring."
Let’s define a ring as circular and closed. The latter of these properties is a tad more flexible than the former, as an open ring is quite common, both in road infrastructure and in other ringlike objects (e.g., a Celtic torc). The best ring road is hence the one that is the most circular while being reasonably closed.
As the problem is now clearly defined, we can focus on finding the solution. The next section will explain the method that was selected to evaluate the circularity, or you can skip straight to the interactive visualization of the results.
Method
The evaluation process consists of several steps:
- Data acquisition from OpenStreetMap,
- Rasterization of the vector-formatted roads,
- Circle fitting using RANSAC,
- Evaluation of the circularity of the ring roads.
To facilitate the interpretation of the presented method, every step is illustrated with figures taken in between important steps. The ring road R23 around Leuven is selected as an example in a chauvinistic homage to my alma mater.
Data acquisition
Getting GeoJSON road data
Road data is acquired from OpenStreetMap using the Overpass API.
The query given below is sent in the body of a POST request to the Overpass API. The response is a JSON object containing the relevant elements (including ways, traffic signals, zebra crossings, …).
For this article, only the ways are relevant, but it is nonetheless interesting to know that R23 contains 71 traffic lights and 32 zebra crossings (according to the Overpass query).
The ring road with the most traffic signals is R22 with 228 signals. The same road, R22, has the most zebra crossings, with a respectable 101 crossings.
The ring roads with the least amount of signals are those that consist of only highways, such as R0. Brussels wins across the board!
// Set output format and timeout
[out:json][timeout:60];
// Get country area for filtering
area["ISO3166-1"="BE"]->.country;
// Union '(...)' combines queries into one
(
// Search ways in Belgium where "ref" matches R23
way(area.country)["highway"]["ref"="R23"];
// Search groups of ways where "ref" matches R23
relation(area.country)["highway"]["ref"="R23"];
);
// Recursively fetch all nodes in the previous query
(._;>;);
// Output the fetched data
out body;
Transforming the fetched data
The ways in the Overpass response are in the GeoJSON format, with coordinates in WGS84 format (longitude and latitude).
They are converted to local distances to the geometric center of the road using an equirectangular approximation of the sphere, which is accurate enough for the small distances in this work.
Evaluation in local distances is necessary to avoid distortions, as the Earth is not flat.
Local distances are anyway how we normally think of the world and are how most mapping applications represent the world.
Visualization of the transformation of the WGS84 coordinates into local kilometers to more intuitively represent the roads.
Rasterization
Because the road data is in vector format, it needs to be rasterized to avoid bias towards roads with more data points.
The vector lines representing roads are rasterized using Bresenham’s line algorithm to a black and white image using a constant pixel size. Each pixel corresponds to a 5x5 m square on the map.
The image size is chosen to fit the entire road within. The black and white image is called a mask and indicates the presence (white) or absence (black) of a road.
Next, the rasterized image is dilated 32.5 m (kernel size 13 px) to ensure that the road is continuous, as every road has an initial thickness of 1 pixel.
Some roads, furthermore, have gaps due to missing data in the OpenStreetMap response (e.g., overpasses or crossings). Some roads have wider lanes, a wide median, or multiple lanes, which are all part of the same road and result in multiple parallel-ish lines.
The mask is finally eroded 22.5 m (kernel size 9 px) to give some width to the road, as the initial rasterized image is only one pixel or 5 m wide. The final road width is hence at least 20 m.
The figure below shows the intermediary road masks after every step. The algorithms that were used are quite common in computer vision and image processing and are readily available in the python-opencv library. The rasterization process is given below the figure in simplified Python code.
Visualization of the rasterization of ring road R23 (Leuven) showing the steps from vector data to rasterized image.
import numpy as np
import cv2
def rasterize_road(local_lines):
# Rasterize the list of vector lines from OpenStreetMap
mask = Bresenham(local_lines, pixel_size=5)
# Pad the mask with 20 black pixels on every side to avoid edge effects
mask = np.pad(mask, pad_width=20, mode='constant', constant_values=0)
# Dilate with kernel size 13x13 (65x65 m)
mask = cv2.dilate(mask.astype(np.float32), np.ones((13,13), np.uint8))
# Erode with kernel size 9x9 (45x45 m)
mask = cv2.erode(mask.astype(np.float32), np.ones((9,9), np.uint8))
# Remove padding
mask = mask[20:-20, 20:-20]
return mask
Circle fitting
To evaluate the circularity of the ring roads, we can now look for the circle that best conforms to the rasterized road. Since we are certain there is exactly one circle in the mask, a simple stochastic evaluation algorithm is sufficient.
The RANSAC (RANdom SAmple and Consensus) algorithm is a tried and tested method in computer vision to find shapes in images. It tries a large number of random circles, tests their match to the sample data, and takes the circle that fits the data best.
Evaluating a random circle
The RANSAC estimator evaluates the fit by looking at which points fall within a certain margin from the tried circle, but because we are not looking for perfect circles, this margin needs to be chosen quite wide (400 m) to provide plausible results.
Every point that lies further than 400 m from the tried circle is included in the cost equally. Since the margin is quite large, there are many solutions, which include all points, which can be clearly seen in the figure below.
To increase the robustness of the circle fitting algorithm, an alternative M-estimator (MSAC) is chosen as the cost function, in which the cost increases with distance to the circle squared up to a maximum of 400 m.
In contrast to the RANSAC estimator, MSAC can provide a best-fitting circle given enough iterations.
The circle with the minimum cost is deemed the best fit and is used for further processing.
The difference in cost evaluation between the RANSAC and MSAC is shown in the figure below.
Difference between the RANSAC and MSAC cost evaluation function visualized for R23.
Evaluating many circles and finding the best fit
By evaluating many random samples and comparing every circle to the previous best fit, the best-fitting circle is found given enough iterations. The next two figures visualize the sampling and evaluation process as a plot showing the reduction in cost after every iteration and visually applied on ring road R23.
A plot showing the cost of every circle fit on R23 evaluated using the MSAC estimator and the running tally of the best-fitting circle's cost. The x-axis shows the iterations where a new best fit is found.
Animation of the MSAC fitting process applied visually on R23.
Evaluation of the ring roads
To determine the ringiest ring road, we need some parameters to compare.
Root mean square (RMS) error
The root mean square error can be calculated from the distances from every point to the nearest point on the fitted circle. This distance is quite straightforward to calculate due to the properties of a circle. The line from the sample point to the center of the circle crosses the nearest point, located one radius from the center.
Where is the radius of the best-fitting circle, and and are the coordinates of its center. The RMS error can then be calculated as
A problem with the RMS error is that it favours smaller ring roads. Normalizing the RMS error to the circle radius is a better indication of the circularity.
Distance from city center
The distance to the city is calculated using the Pythagorean Theorem to the administrative center according to OpenStreetMap. The city centers are indicated with a location pin in the result section below.
Closed fraction
Not all ring roads form closed loops. To evaluate the closure of the ring roads with respect to the fitted circle, an array of uniformly spaced rays is cast outward from the city center. Every time a ray hits a white pixel (road presence in the mask), it is registered as a hit. The percentage of closure can then be calculated using
Results and conclusion
To avoid bias, the initial order is set to the R-number while showing all ring roads. Select a closure percentage to filter ring-like roads (80% seems a good cut-off) and select sorting methods to your liking.
Brussels R0
RMS: 6703 m (93.6%)
City center: 1598 m
Radius: 7158 m
100% closed
Antwerpen R1
RMS: 922 m (32.3%)
City center: 691 m
Radius: 2857 m
100% closed
Antwerpen R2
RMS: 401 m (5.7%)
City center: 4241 m
Radius: 6985 m
25% closed
Charleroi R3
RMS: 1246 m (22.3%)
City center: 2523 m
Radius: 5593 m
72% closed
Gent R4
RMS: 4194 m (73.6%)
City center: 2318 m
Radius: 5698 m
100% closed
Mons R5
RMS: 460 m (13.6%)
City center: 2088 m
Radius: 3387 m
35% closed
Mechelen R6
RMS: 282 m (4.1%)
City center: 4285 m
Radius: 6865 m
19% closed
Kortrijk R8
RMS: 298 m (11.7%)
City center: 830 m
Radius: 2540 m
100% closed
Charleroi R9
RMS: 131 m (16.9%)
City center: 50 m
Radius: 772 m
100% closed
Antwerpen R10
RMS: 148 m (6.2%)
City center: 1118 m
Radius: 2372 m
62% closed
Antwerpen R11
RMS: 523 m (9.7%)
City center: 1172 m
Radius: 5416 m
36% closed
Mechelen R12
RMS: 53 m (7.3%)
City center: 108 m
Radius: 725 m
100% closed
Turnhout R13
RMS: 155 m (8.9%)
City center: 678 m
Radius: 1729 m
80% closed
Geel R14
RMS: 238 m (12.5%)
City center: 628 m
Radius: 1906 m
69% closed
Lier R16
RMS: 70 m (4.6%)
City center: 504 m
Radius: 1524 m
71% closed
Retie R18
RMS: 36 m (5.0%)
City center: 133 m
Radius: 731 m
56% closed
Brussels R20
RMS: 1494 m (126.7%)
City center: 88 m
Radius: 1180 m
100% closed
Brussels R21
RMS: 1112 m (40.9%)
City center: 1234 m
Radius: 2719 m
49% closed
Brussels R22
RMS: 810 m (2.7%)
City center: 23392 m
Radius: 29526 m
9% closed
Leuven R23
RMS: 83 m (7.2%)
City center: 122 m
Radius: 1140 m
100% closed
Nivelles R24
RMS: 298 m (13.2%)
City center: 950 m
Radius: 2263 m
50% closed
Aarschot R25
RMS: 267 m (20.5%)
City center: 838 m
Radius: 1301 m
85% closed
Diest R26
RMS: 171 m (21.0%)
City center: 267 m
Radius: 813 m
97% closed
Tienen R27
RMS: 118 m (4.6%)
City center: 1107 m
Radius: 2574 m
38% closed
Brugge R30
RMS: 216 m (19.0%)
City center: 260 m
Radius: 1133 m
100% closed
Oostende R31
RMS: 74 m (2.7%)
City center: 1440 m
Radius: 2709 m
26% closed
Roeselare R32
RMS: 219 m (6.6%)
City center: 1432 m
Radius: 3343 m
58% closed
Poperinge R33
RMS: 72 m (6.0%)
City center: 157 m
Radius: 1202 m
86% closed
Torhout R34
RMS: 555 m (13.8%)
City center: 3305 m
Radius: 4026 m
24% closed
Waregem R35
RMS: 126 m (16.9%)
City center: 274 m
Radius: 751 m
100% closed
Kortrijk R36
RMS: 60 m (8.6%)
City center: 252 m
Radius: 699 m
100% closed
Gent R40
RMS: 380 m (23.9%)
City center: 87 m
Radius: 1588 m
100% closed
Aalst R41
RMS: 69 m (4.8%)
City center: 332 m
Radius: 1432 m
71% closed
Sint-Niklaas R42
RMS: 136 m (8.6%)
City center: 887 m
Radius: 1594 m
41% closed
Eeklo R43
RMS: 36 m (2.3%)
City center: 1231 m
Radius: 1560 m
26% closed
Mons R50
RMS: 138 m (18.9%)
City center: 173 m
Radius: 731 m
100% closed
Tournai R52
RMS: 119 m (13.9%)
City center: 304 m
Radius: 859 m
100% closed
Châtelet R53
RMS: 49 m (11.2%)
City center: 103 m
Radius: 435 m
100% closed
La Louvière R54
RMS: 176 m (16.3%)
City center: 833 m
Radius: 1079 m
42% closed
Chimay R55
RMS: 76 m (4.6%)
City center: 317 m
Radius: 1652 m
23% closed
Verviers R61
RMS: 149 m (17.3%)
City center: 829 m
Radius: 862 m
73% closed
Hannuit R62
RMS: 462 m (29.2%)
City center: 752 m
Radius: 1579 m
65% closed
Hasselt R70
RMS: 23 m (5.7%)
City center: 39 m
Radius: 394 m
100% closed
Hasselt R71
RMS: 125 m (8.0%)
City center: 160 m
Radius: 1565 m
100% closed
Tongeren R72
RMS: 76 m (11.1%)
City center: 474 m
Radius: 685 m
45% closed
Discussion
(Paragraph work in progress)
This review contains only ring roads labeled with an R-number. A possible extension is to add selected provincial roads as they sometimes act as a ring road.
N712 is a straightforward example, as it is a single road that runs around the town of Pelt.
Not all provincial ring roads are that neatly organized. N7 in Ath, for instance, is a longer road that passes Ath and acts as a ring road for a small fraction of its length. It is hence difficult to separate the ring part of the road.
Another complication is that some informal ring roads use parts of multiple roads to form a ring-like road around a city or town.
The unofficial ring road around Dendermonde, for instance, consists of parts of roads N17, N41, and N47.