Overpass API > Blog >

Bounding Boxes

Published: 2017-04-17

Table of content

Global Bounding Box
The bbox Parameter
Output with Bounding Box

Introduction

As I have announced last week, I will walk through the examples page for the next weeks. I hope that I can bring that page back up-to-date.

The use of bounding boxes are the first thing that is ot of date there. For that reason, I would like to explain which bounding boxes beyond the standard filter exist and what they are good for.

Global Bounding Box

Have you ever, like me, typed a request like this one? Do you see immediate what is the problem here?

node[amenity=restaurant];
out center;

Five seconds after sending the request I am stunned that I the request is still running. Another five seconds later I realize that I have forgotten the bounding box. There are some hundred millions of ways with this tag, thus neither the query engine nor the display engine can handle that amount of data in a sane way. And that is just because I have forgotten the bounding box:

node[amenity=restaurant]({{bbox}});
out center;

This is where the Global Bounding Box is helpful: The Global Bounding Box is set once per request. It then does automatically apply to every query statement in the request. This means that the following two requests do exactly the same:

node[amenity=restaurant]({{bbox}});
out center;

and this one:

[bbox:{{bbox}}];
node[amenity=restaurant];
out center;

I, personally, have the global bounding box always in the request and drop it only if the request is intended to be global. You may ask why the Global Bounding Box is not turned on by default? In general, Overpass API cannot know which bounding box you are looking at. It is a feature of Overpass Turbo to show a map in a viewport and to replace each occurrence of {{bbox}} by the boundaries of that viewport. In particular, the exactly boundaries depend on screen resolution, i.e. the request may have different results on different clients. For my computer, the really sent request is

node[amenity=restaurant](40.79456207284583,-73.97092580795288,40.80971663141517,-73.94957542419434);
out center;

resp.

[bbox:40.79456207284583,-73.97092580795288,40.80971663141517,-73.94957542419434];
node[amenity=restaurant];
out center;

The Global Bounding Box is even more useful when you are asking for the bounding box multiple times:

( node[amenity=restaurant]({{bbox}});
  way[amenity=restaurant]({{bbox}});
  rel[amenity=restaurant]({{bbox}}); );
out center;

This is simplified to:

[bbox:{{bbox}}];
( node[amenity=restaurant];
  way[amenity=restaurant];
  rel[amenity=restaurant]; );
out center;

The bbox Parameter

For historical reasons, there is also another mechanism to set once a bounding box everywhere. It has been designed to simplify using Overpass API from OpenLayers.

You can amend a request with bbox=west,south,east,north. Overpass API then replaces each occurence of (bbox) within the request with the proper bounding box and [bbox] in the beginning with the proper global bounding box. This means that e.g. the following two requests are equal:

https://overpass-api.de/api/interpreter?data=node[amenity=restaurant](40.79456207284583,-73.97092580795288,40.80971663141517,-73.94957542419434);out+center;

and

https://overpass-api.de/api/interpreter?data=node[amenity=restaurant](bbox);out+center;&bbox=-73.97092580795288,40.79456207284583,-73.94957542419434,40.80971663141517

Please note that the coordinates in this parameter are swapped. This is because OpenLayers violates that latitude comes first as opposed to most other software. Because I did neither want to rewrite OpenLayers nor to bother users with that, this special syntax allows to use Overpass API with coordinate order swapped.

Output with Bounding Box

Have you ever tried to keep track of recent changes in a bounding box? It turns out that relations of large extend will often clutter up the results.

This is why you can add a bounding box to the geom mode of the out statement. Just change geom to geom({{bbox}}). This restricts the add coordinates to the given bounding box.

For example, the following request loads most data outside of its viewport:

rel
  [type=route]
  [route=railway]
  ({{bbox}});
out geom;

If you add the geometry limit then only data needed to visualize the relations in the viewport is loaded:

rel
  [type=route]
  [route=railway]
  ({{bbox}});
out geom({{bbox}});

In practice, this feature is useful only for relations. Nodes are either inside oder outside the bounding box. For ways, you can drop some coordinates. But because you will get anyway the other member entries without coordinates there is not much data you can avoid. Only for relations you can drop the geometry of way members completely outside the bounding box. But in tracking changes, anyway only the large scale relations are the problem.

The global bounding box does not automatically add a limit to the geometry mode. By contrast, the bbox parameter would trigger a replacement of (bbox) by the proper bounding box if you have written geom(bbox) in the request.