articles
Dec 28, 2025
10 min read

One ring (road) to rule them all!

Which Belgian ring road is the most circular, and hence the best one? An excessive analysis of Belgian ring roads no one asked for.
  • Cartograpy
  • Interactive
On This Page

Introduction

Which Belgian ring road is the best ring? To answer this question, we first need to define what a ring road is:

ring road /rĭng roʊd/
noun
  1. 1.
    A circumferential highway around a town, city, or other conurbation.
  2. 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:

ring /rĭng/
noun
  1. 1.
    A circular object, form, line, or arrangement.
  2. 2.
    A small circular band, generally made of precious metal and often set with jewels, worn on the finger.
  3. 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:

  1. Data acquisition from OpenStreetMap,
  2. Rasterization of the vector-formatted roads,
  3. Circle fitting using RANSAC,
  4. 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.

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.

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.

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.

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

Brussels R0 - Ring Road

RMS: 6703 m (93.6%)
City center: 1598 m
Radius: 7158 m
100% closed

Antwerpen  R1

Antwerpen R1 - Ring Road

RMS: 922 m (32.3%)
City center: 691 m
Radius: 2857 m
100% closed

Antwerpen  R2

Antwerpen R2 - Ring Road

RMS: 401 m (5.7%)
City center: 4241 m
Radius: 6985 m
25% closed

Charleroi  R3

Charleroi R3 - Ring Road

RMS: 1246 m (22.3%)
City center: 2523 m
Radius: 5593 m
72% closed

Gent  R4

Gent R4 - Ring Road

RMS: 4194 m (73.6%)
City center: 2318 m
Radius: 5698 m
100% closed

Mons  R5

Mons R5 - Ring Road

RMS: 460 m (13.6%)
City center: 2088 m
Radius: 3387 m
35% closed

Mechelen  R6

Mechelen R6 - Ring Road

RMS: 282 m (4.1%)
City center: 4285 m
Radius: 6865 m
19% closed

Kortrijk  R8

Kortrijk R8 - Ring Road

RMS: 298 m (11.7%)
City center: 830 m
Radius: 2540 m
100% closed

Charleroi  R9

Charleroi R9 - Ring Road

RMS: 131 m (16.9%)
City center: 50 m
Radius: 772 m
100% closed

Antwerpen  R10

Antwerpen R10 - Ring Road

RMS: 148 m (6.2%)
City center: 1118 m
Radius: 2372 m
62% closed

Antwerpen  R11

Antwerpen R11 - Ring Road

RMS: 523 m (9.7%)
City center: 1172 m
Radius: 5416 m
36% closed

Mechelen  R12

Mechelen R12 - Ring Road

RMS: 53 m (7.3%)
City center: 108 m
Radius: 725 m
100% closed

Turnhout  R13

Turnhout R13 - Ring Road

RMS: 155 m (8.9%)
City center: 678 m
Radius: 1729 m
80% closed

Geel  R14

Geel R14 - Ring Road

RMS: 238 m (12.5%)
City center: 628 m
Radius: 1906 m
69% closed

Lier  R16

Lier R16 - Ring Road

RMS: 70 m (4.6%)
City center: 504 m
Radius: 1524 m
71% closed

Retie  R18

Retie R18 - Ring Road

RMS: 36 m (5.0%)
City center: 133 m
Radius: 731 m
56% closed

Brussels  R20

Brussels R20 - Ring Road

RMS: 1494 m (126.7%)
City center: 88 m
Radius: 1180 m
100% closed

Brussels  R21

Brussels R21 - Ring Road

RMS: 1112 m (40.9%)
City center: 1234 m
Radius: 2719 m
49% closed

Brussels  R22

Brussels R22 - Ring Road

RMS: 810 m (2.7%)
City center: 23392 m
Radius: 29526 m
9% closed

Leuven  R23

Leuven R23 - Ring Road

RMS: 83 m (7.2%)
City center: 122 m
Radius: 1140 m
100% closed

Nivelles  R24

Nivelles R24 - Ring Road

RMS: 298 m (13.2%)
City center: 950 m
Radius: 2263 m
50% closed

Aarschot  R25

Aarschot R25 - Ring Road

RMS: 267 m (20.5%)
City center: 838 m
Radius: 1301 m
85% closed

Diest  R26

Diest R26 - Ring Road

RMS: 171 m (21.0%)
City center: 267 m
Radius: 813 m
97% closed

Tienen  R27

Tienen R27 - Ring Road

RMS: 118 m (4.6%)
City center: 1107 m
Radius: 2574 m
38% closed

Brugge  R30

Brugge R30 - Ring Road

RMS: 216 m (19.0%)
City center: 260 m
Radius: 1133 m
100% closed

Oostende  R31

Oostende R31 - Ring Road

RMS: 74 m (2.7%)
City center: 1440 m
Radius: 2709 m
26% closed

Roeselare  R32

Roeselare R32 - Ring Road

RMS: 219 m (6.6%)
City center: 1432 m
Radius: 3343 m
58% closed

Poperinge  R33

Poperinge R33 - Ring Road

RMS: 72 m (6.0%)
City center: 157 m
Radius: 1202 m
86% closed

Torhout  R34

Torhout R34 - Ring Road

RMS: 555 m (13.8%)
City center: 3305 m
Radius: 4026 m
24% closed

Waregem  R35

Waregem R35 - Ring Road

RMS: 126 m (16.9%)
City center: 274 m
Radius: 751 m
100% closed

Kortrijk  R36

Kortrijk R36 - Ring Road

RMS: 60 m (8.6%)
City center: 252 m
Radius: 699 m
100% closed

Gent  R40

Gent R40 - Ring Road

RMS: 380 m (23.9%)
City center: 87 m
Radius: 1588 m
100% closed

Aalst  R41

Aalst R41 - Ring Road

RMS: 69 m (4.8%)
City center: 332 m
Radius: 1432 m
71% closed

Sint-Niklaas  R42

Sint-Niklaas R42 - Ring Road

RMS: 136 m (8.6%)
City center: 887 m
Radius: 1594 m
41% closed

Eeklo  R43

Eeklo R43 - Ring Road

RMS: 36 m (2.3%)
City center: 1231 m
Radius: 1560 m
26% closed

Mons  R50

Mons R50 - Ring Road

RMS: 138 m (18.9%)
City center: 173 m
Radius: 731 m
100% closed

Tournai  R52

Tournai R52 - Ring Road

RMS: 119 m (13.9%)
City center: 304 m
Radius: 859 m
100% closed

Châtelet  R53

Châtelet R53 - Ring Road

RMS: 49 m (11.2%)
City center: 103 m
Radius: 435 m
100% closed

La Louvière  R54

La Louvière R54 - Ring Road

RMS: 176 m (16.3%)
City center: 833 m
Radius: 1079 m
42% closed

Chimay  R55

Chimay R55 - Ring Road

RMS: 76 m (4.6%)
City center: 317 m
Radius: 1652 m
23% closed

Verviers  R61

Verviers R61 - Ring Road

RMS: 149 m (17.3%)
City center: 829 m
Radius: 862 m
73% closed

Hannuit  R62

Hannuit R62 - Ring Road

RMS: 462 m (29.2%)
City center: 752 m
Radius: 1579 m
65% closed

Hasselt  R70

Hasselt R70 - Ring Road

RMS: 23 m (5.7%)
City center: 39 m
Radius: 394 m
100% closed

Hasselt  R71

Hasselt R71 - Ring Road

RMS: 125 m (8.0%)
City center: 160 m
Radius: 1565 m
100% closed

Tongeren  R72

Tongeren R72 - Ring Road

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.