Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

find a complete logical highway by name #95

Closed
ghost opened this issue Jun 3, 2014 · 11 comments
Closed

find a complete logical highway by name #95

ghost opened this issue Jun 3, 2014 · 11 comments

Comments

@ghost
Copy link

ghost commented Jun 3, 2014

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

way
  (around:200,50.937468375711916,6.887891440378863)
  [highway]
  [name="Aachener Straße"];

complete->._
(
  ._; way(around:100)[highway][name="Aachener Straße"];
);
@mmd-osm
Copy link
Contributor

mmd-osm commented Sep 14, 2014

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.

http://overpass-turbo.eu/s/527

mmd-osm added a commit to mmd-osm/Overpass-API that referenced this issue Dec 13, 2014
mmd-osm added a commit to mmd-osm/Overpass-API that referenced this issue Dec 14, 2014
@mmd-osm
Copy link
Contributor

mmd-osm commented Dec 14, 2014

Some example use cases:

(1) Find all streams flowing into a river (including lakes).

river

[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:

overpass_api

(2) Starting with a small railway section: what is the directly connected railway network in a bbox:

railway

[bbox:{{bbox}}]
[timeout:120];

(way(28742708);
complete->._
(
  ._; > ->.a; 
  way(bn.a)[railway];

)
);
out geom;

(3) Detect unconnected parts of a railway network

railway2

[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:

waterway

[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 ;

http://overpass-turbo.eu/s/cmN

@mmd-osm
Copy link
Contributor

mmd-osm commented Dec 14, 2014

@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?

@ghost
Copy link
Author

ghost commented Dec 14, 2014

Great examples! Is this branch online running?

@ghost
Copy link
Author

ghost commented Dec 21, 2014

Is it maybe possible to publish a preview at /interpreter_95 ? Regards Johannes

@drolbr
Copy link
Owner

drolbr commented Dec 21, 2014

@mmd-osm: We have the following tasks to accomplish

  • Identify the result of a single loop run: this is the result of the union of commands, no need for a special name.
  • Provide the last result as input: This job exists as well in the foreach statement. I suggest the position of ".b" for this to keep the new statement consistent.
  • Put the final result somewhere. This job doesn't exist in foreach, but it does exist in union. Being consistent means to take ".d" for this job.

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.

mmd-osm added a commit to mmd-osm/Overpass-API that referenced this issue Dec 30, 2014
mmd-osm added a commit to mmd-osm/Overpass-API that referenced this issue Dec 30, 2014
@sanderd17
Copy link

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;

@mmd-osm
Copy link
Contributor

mmd-osm commented Sep 28, 2015

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...

mmd-osm added a commit to mmd-osm/Overpass-API that referenced this issue Aug 30, 2016
mmd-osm added a commit to mmd-osm/Overpass-API that referenced this issue Aug 30, 2016
@mmd-osm
Copy link
Contributor

mmd-osm commented Mar 28, 2017

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;

@drolbr
Copy link
Owner

drolbr commented Apr 27, 2017

Available by pull request integration in 409c6a5

@drolbr drolbr closed this as completed Apr 27, 2017
@vin-ni
Copy link

vin-ni commented Oct 15, 2018

The Demo is down unfortunately.
How would I get all streets of Berlin as one object per street?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants