Closed ghost closed 7 years ago
In the meantime you could use the following workaround. Add more .a??? until no new ways appear in the result list. Could also be automated if needed.
Some example use cases:
(1) Find all streams flowing into a river (including lakes).
[timeout:120];
(way[waterway]
[name="Prims"];
complete->._
(
._; > ->.a;
(way(bn.a)["waterway"~"^stream$"];
way(bn.a)["natural"~"^water$"];
);
)
);
out geom;
And a slightly larger example:
(2) Starting with a small railway section: what is the directly connected railway network in a bbox:
[bbox:{{bbox}}]
[timeout:120];
(way(28742708);
complete->._
(
._; > ->.a;
way(bn.a)[railway];
)
);
out geom;
(3) Detect unconnected parts of a railway network
[bbox:{{bbox}}]
[timeout:120];
(way[railway]
[railway!=platform]
[railway!=abandoned]
[railway!=disused]; -
(way(28742708);
complete->._
(
._; > ->.a;
way(bn.a)[railway];
)
);
);
out geom({{bbox}});
(4) Detect unconnected parts of a waterway system:
[timeout:1200][bbox:{{bbox}}];
( (way[waterway];
way["natural"="water"];);
-
(way[waterway]
[name~"^(Nahe|Saar|Mosel|Blies)$"];
complete->._
(
._; > ->.a;
(way(bn.a)["waterway"];
way(bn.a)["natural"="water"];
);
)
););
out geom;
(5) Automatically resolve nested relations
Similar to >>;
, complete
can also be used to resolve nested relations, with a focus on the relation itself (ignoring any node/way member in each relation)
relation
["name"="Twente"]
["network"="public_transport"];
complete( rel(r) );
out ;
@drolbr : While I'm already working on this in a new branch, I'm not quite sure on the semantics for various possible inputset/outputsets for this statement:
complete .a -> .b ( statement1; statement2 -> .c; ) -> .d
Which of those names inputsets should be supported? What should be the respective logic in each case?
Also I'm fighting a bit with a check on empty sets. What would you recommend here?
Great examples! Is this branch online running?
Is it maybe possible to publish a preview at /interpreter_95 ? Regards Johannes
@mmd-osm: We have the following tasks to accomplish
The position of ".c" is not related to this statement, hence we can safely ignore it.
One can argue for or against ".a", but I would suggest to postpone parameters. It is easy to add a parameter once there is a clear use case for it, doing it right on the first attempt. But it is hard to withdraw a parameter if it turns out to be designed less than optimal.
With a closer look, one could even argue to drop either ".b" or ".d". I don't see any useful situation where both point to different variables. If you need to, then you can copy the loop variable to another variable immediately afterwards. Just use
.from ->.to;
However, consistency to "foreach" and the union statement suggests to have both.
Hmm, just got here from that diary post (http://www.openstreetmap.org/user/Chenshi/diary/35949). And I'm a bit confused with the syntax. AFAICS, complete just seems to be a foreach loop, where the input set can be added to on the fly, and that also has an output.
By requiring the line ._; > ->.a;
, it becomes apparent that you need to manually get the nodes from the elements, and use those nodes explicitly to see if other ways are connected. While that would be something I inherently expect in a complete
statement.
Modifying the foreach definition so sets can be adapted while looping over it will add about the same functionality AFAICS, while it wouldn't introduce an extra keyword. Something like this could then also give all connected ways to some selection, while being hardly more cumbersome:
area["name"="Roeselare"]["admin_level"=8]->.a;
way["highway"="primary"]["name"="Diksmuidsesteenweg"](area.a)->.ways;
foreach.ways
(
> ->.nodes;
(
.ways;
way(bn.nodes)["highway"="primary"](area.a);
)->.ways;
);
.ways out geom;
This is a common practice in at least some programming languages, so it's purely a design choice. Compare it to JavaScript, where the following will be an infinite loop (it will at least loop until it runs out of integers):
var set = new Set([1]);
for (var v of set)
set.add(v+1);
On the other hand, if foreach
is left as it currently is, and complete
is added, getting the nodes should be part of the iteration IMO, so it would become something like
[bbox:{{bbox}}]
way(28742708)->.way;
complete.way->.nodes( way(bn.nodes)[railway]; )->.result;
.result out geom;
or without sets
[bbox:{{bbox}}]
way(28742708);
complete( way(bn)[railway]; );
out geom;
Thanks for the feedback. I agree this might seem a bit confusing at first, but I believe this is really a matter of lack of documentation...
Let's take a look:
complete just seems to be a foreach loop, where the input set can be added to on the fly, and that also has an output.
From a conceptional point of view, your first foreach
based code example is somewhat similar to what is going on with complete
. Allowing self-modifying inputsets for foreach
might be an approach, but I see performance disadvantages: while foreach
processes the elements one by one, complete
provides the complete inputset to the inner statements, i.e. it always runs set-based rather than one-by-one operations. Of course, when following one large interstate across the US we will essentially be looking at a one-by-one operation. The use case in the blog post you mentioned will run one larger sets, though (which is faster).
For the inner statements you are free to do whatever you want, but at the end of the day, they have to produce some outputset (which might of course also be empty).
complete
then checks, if the iteration produced any new elements (nodes, ways, relations, area).
If there are some new elements, a new iteration will be triggered just with those new elements. Hence, the result from one iteration will be the input for the next iteration (except for those elements, which have already been processed in a previous iteration).
If the inner statements didn't produce any new elements, complete
is done and it will return the total of elements across all iterations as a resultset.
While that would be something I inherently expect in a complete statement.
It's really not only about connected ways. You might as well follow relations, which include some way. Think about it in terms of a more general iteration concept.
Another example: plan a pub trip in Dublin: you could start out with one amenity=pub and find all pubs in a distance of up to 50m. For those pubs you start out again and find any pub in 50m distance and so forth. This would also be feasible with complete
.
Here's another example using around
way(209985260);
complete{
._; way(around:200)[highway][name="Ostmerheimer Straße"];
};
out geom;
._;
could probably also be left out...
Combined with 0.7.54, we can now find a certain number of adjacent ways, controlled by a single value:
(
way(143101141);
complete(15) {
way[highway][highway!~"^(path|track|cycleway|footway)$"](around:0);
};
);
out geom;
Available by pull request integration in 409c6a5349d50b535b43d170e8fd5f9ebfac287f
The Demo is down unfortunately. How would I get all streets of Berlin as one object per street?
Currently there is no possibility to ask for a highway that belongs together with overpass-api. You can maybe ask for "Aachener Straße" in area[name=Köln] but you will receive three highways all over the city (and it gets broken at the city border).
For selecting only the desired logical highway, we can pick at first a piece of highway with than name near a known point 50.937468375711916, 6.887891440378863. Now we need a new overpass magic, which asks recursive in in every radius around all way-nodes for additional highway parts.
Roland made already a QL-proposal, thanks