[OSM-dev] Overpass-Query: Complete Relations in BBox

Roland Olbricht wrmo at gmx.net
Tue Mar 27 09:03:28 BST 2012


Hi

lets go through the questions one by one.

>   - which query-language is suited for what?

I suggest using the Overpass QL syntax. This and the XML language both offer the same semantics, but Overpass QL is more concise. Overpass QL has been created because the XML language looks cumbersome to most people.

>   - what's this .->x or .->_ about?

Overpass has an imperative execution model. In particular, the staements are executed one after another, and each statement is terminated by a semicolon. Each statement puts its results into a container in its memory named by default "_". If a statement needs input, it reads its input from "_". For example, the print statement reads from "_".

Sometimes it is useful to use more than one container during a more complex query. In this case, the output can be redirected to another container, e.g. with name "x". This is what the above syntax controls.

>   - will a print-command print all results of all unions or only the last
> one?

It prints the content of the container "_" at execution time. This comes very close to "the last one".

>   - are two queries in a union get ANDed or ORed?

They are ORed.

> I tried to fiddle an overpass-query together that would give me:
>   - all relations tagged with type=boundary or type=multipolygon
>   - their way-members
>   - nodes used by thode way-members

The query
[timeout:86400];
( rel[type=boundary];
  rel[type=multipolygon];
);
( ._;
  way(r);
  node(w);
);
out;
does that.

> but I was unable to get this result.
> 
> I'd love to see a walktrgough or a tutorial that explains the building
> blocks and how they interact in a chronological order without adding stuff
> that isn't explained.

Lets walk through the example:

[timeout:86400]; is necessary in this case because we expect a really large result. The 86400 is an amount of time in seconds and means that we expect a runtime up to a whole day. The default value is 180 seconds, which fits well to the usual timeouts of browsers or other HTTP clients.

rel[type=boundary]; collects all relations from the database that have a tag with key "type" and value "boundary". The result is stored in the memory of the query server, in the container "_", because this is the default behaviour.

If you want to see what has happened so far, you can print the content of the container at this point:
http://overpass-api.de/api/interpreter?data=rel[type=boundary];out;

Similarly, rel[type=multipolygon]; collects all relations from the database that have a tag with key "type" and value "multipolygon". Check the results with
http://overpass-api.de/api/interpreter?data=rel[type=multipolygon];out;
This is already quite a lot of data.

Now, the union statement comes into effect. It takes a copy of each output and produces as result the union of each output.
( rel[type=boundary];
  rel[type=multipolygon];
);
This means that here, first the output of rel[type=boundary]; is collected, then the output of rel[type=multipolygon]; is collected. The union of both is stored at the end of the statement into the container "_" and replaced the content of container "_" after the last substatement, "rel[type=multipolygon]". To see the conent of the container "_" at this point, run
http://overpass-api.de/api/interpreter?data=(rel[type=boundary];rel[type=multipolygon];);out;

On a semantic level, we now have in the container "_" all relations that are of type boundary or of type multipolygon. We now get to the second union block:
( ._;
  way(r);
  node(w);
);

The first substatement, "._", is only useful in a union block: It has as output in the container "_" the input from container "_". While this doesn't change container "_", it lets union copy the current content of container "_" to its own output.

Thus, we have now all relations of the interesting type in both the container "_" and the union's internal container.

The next substatement, "way(r);" reads its input from the container "_" and writes its output again to the container "_", replacing the input data. Thus, on a semantic level, "way(r);" puts all ways that are members of a relation of interesting type into the container "_". Because it is a substatement of union, this unoin block adds this output to its internal storage.

The next statement, "node(w);" again reads its input from the container "_" and writes its output to the container "_". It finds all nodes that are members of the ways in its input. Because container "_" contains at this point of time all ways that are members of a relation of interesting type into the container "_", we now have exactly the nodes that we want in the container "_". And because we are still in the union block, the internal union storage now contains the relations (from "._"), the ways (from "way(r);"), and the nodes (from "node(w);") that we want. At the end of the union statement, in the source code at ");", the statement puts this into the cotainer "_".

In a final step, we only need to print this, adding an "out;" statement. If you want meta information, you may want to use "out meta;". If you want to speed up the whole thing, try "out qt;" which orders the elements not by type and then id, but rather by type and then location, which is faster for output. Note that the "+" is cgi escaping to make the link clickable and not part of the Overpass QL syntax, but automatically converted by the server:

http://overpass-api.de/api/interpreter?data=[timeout:86400];(rel[type=boundary];rel[type=multipolygon];);(._;way(r);node(w););out+qt;
(fastest)
http://overpass-api.de/api/interpreter?data=[timeout:86400];(rel[type=boundary];rel[type=multipolygon];);(._;way(r);node(w););out;
(most common)
http://overpass-api.de/api/interpreter?data=[timeout:86400];(rel[type=boundary];rel[type=multipolygon];);(._;way(r);node(w););out+meta;
(most verbose)

Best regards,

Roland



More information about the dev mailing list