User:Kovposch/Overpass API/Overpass API by Example

From OpenStreetMap Wiki
Jump to navigation Jump to search

Lack of feature in areas

try it yourself in overpass-turbo
wr({{bbox}})[landuse=farmyard];
foreach
(
  wr(area)[building]->.inside;
  (._; .inside;); 
  wr._(if: count(wr) == 1); // For convenience, to output them together
  out geom meta;
);

3D rendering

try it yourself in overpass-turbo
wr({{bbox}})["building:part"][location!=underground]["building:levels"]["building:levels"!=0] -> .parts;  
.parts out geom;
(
  way.parts;
  way(r.parts); 
); 
node(w)->.partsp;
 
wr({{bbox}})[building][location!=underground];  
foreach->.each
{ 
  (.each; way(r.each);); 
  node(w); 
  node._.partsp ->.shared;
  wr(area.each)["building:part"] -> .inside;
  if (shared.count(nodes) == 0 && inside.count(wr) == 0) // Includes check for `building:part=` lying exactly on `building=` outline, which is not returned by `(area)` 
  {  
    .each out geom;
  }; 
};  

{{style:
area[building]
{ color:blue; fill-color:blue; }

area[building:part]
{ color:green; fill-color:green; }
}}

(To be refined)

Overlapping areas

try it yourself in overpass-turbo
(way({{bbox}})[natural](if: is_closed()); rel({{bbox}})[natural][type=multipolygon];);   
foreach->.this
{ 
  (way(around.this:0)[natural](if: is_closed()); rel(around.this:0)[natural][type=multipolygon];); // Any touching areas
  (._; - .this;) ->.touching; // Removes itself 
  if (touching.count(wr) > 0)
  {
    way(r.this);
    (node(w); node(w.this);) -> .thispts;  
    foreach.touching
    {
      ._ -> .thistouching;
      way(r);
      (node(w); node(w.thistouching);) -> .thistouchingpts;  
      node.thispts.thistouchingpts -> .sharedpts;    
      if (sharedpts.count(nodes) == 0) // Overlapping areas without shared points 
      { 
        (.this; .thistouching;);
        out geom meta; 
      }; 
      if (sharedpts.count(nodes) > 0) 
      { 
        node(area.this);
        (._; - .thispts;) -> .ptsinsidethis; // `node(area)` finds points lying on the area. Need to remove them. 
        node.ptsinsidethis.thistouchingpts -> .crossptsinsidethis; 
        if (crossptsinsidethis.count(nodes) > 0) // Check for points inside to discard areas with exactly shared outlines
        { 
          (.this; .thistouching;);
          out geom meta; 
        }; 
      }; 
    }; 
  };  
};

Intersection streets

Overpass_API_by_Example#Search_for_street_intersections

try it yourself in overpass-turbo
[out:json][timeout:25];

// The public street network
way({{bbox}})["highway"~"^(trunk|primary|secondary|tertiary|unclassified|residential|living_street|pedestrian)$"]->.streets;

// Get nodes that connect between three or more street segments
node(way_link.streets:3-)->.connections;

// Get intersections between distinct streets
foreach .connections->.connection
{
  // Get adjacent streets
  way(bn.connection);
  // If the names don't all match, add the node to the set of intersections
  if (u(t["name"]) == "< multiple values found >") 
  {
     make node  
      ::id = connection.u(id()), 
      _streets = set(t["name"]);  
    (._; .intersectionstreets;) -> .intersectionstreets;
    (.intersections; .connection;) -> .intersections; 
  };
}; 
for.intersections->.this(id())
{
  foreach.intersectionstreets
  {
    if (this.val == u(id()))
    {
      ._ -> .thisintersectionstreets;
    };
  };
  node.intersections(if: id() == this.val) -> ._;
  convert node 
    ::id = id(),
    ::geom = geom(),
    :: = ::,
    _intersectingstreets = thisintersectionstreets.u(t["_streets"]);
  out geom;
};

Duplicate addresses

Between buildings

try it yourself in overpass-turbo
//[out:json][timeout:55];
[out:csv(st,num,type,id)][timeout:55];
//rel(id:110826);
//map_to_area; 
wr({{bbox}})[building]["addr:housenumber"]["addr:street"]->.all; //wr(area)[building]["addr:housenumber"]["addr:street"]->.all;
for.all->.thisst(t["addr:street"])
{
  wr.all(if: t["addr:street"]==thisst.val)->.onthisst;
  for.onthisst->.thisnum(t["addr:housenumber"])
  {
    wr.onthisst(if: t["addr:housenumber"]==thisnum.val)->.matches;
    if (matches.count(wr) > 1)
    {
      //.matches out geom; 
      make dupe st=thisst.val, num=thisnum.val, type=matches.set(type()), id=matches.set(id());
      out;
    };
  };
};

Glued roads

try it yourself in overpass-turbo
[out:json][timeout:25]; 
(wr({{geocodeBbox:Brisbane}})[landuse];) -> .land;
way(r.land) -> .members; 
(way.land; .members;) -> .all;
node(w.all)->.landpts;  
way({{geocodeBbox:Brisbane}})[highway][area!=yes][highway!=services][highway!=rest_area] -> .roads;
node(w.roads) -> .roadspts;  
node.landpts.roadspts -> .intersecting;  
node.landpts.intersecting -> .landptsintersecting;
node.roadspts.intersecting -> .roadsptsintersecting; 
way.land(bn.landptsintersecting) -> .landmatchw;
way.members(bn,landptsintersecting) -> .membersmatch; 
rel.land(br.membersmatch)->.landmatchr; 
way.roads(bn.roadsptsintersecting) -> .roadsmatch; 
foreach.landmatchw->.thisland
{
  node.landptsintersecting(w.thisland)->.thisintersectingpts;
  node.thisintersectingpts.roadsptsintersecting->.thismatchpts;
  if (thismatchpts.count(nodes)>1)
  { 
    way.roadsmatch(bn.thismatchpts)->.thismatchroads;
    foreach.thismatchroads->.thisthismatchroads
    {
      node.thismatchpts(w.thisthismatchroads);
      if (count(nodes)>1)
      {
        .thisthismatchroads out geom;
        .thisland out geom;
      };
    };
  };
};
foreach.landmatchr->.thisland
{
  way.members(r.thisland) -> .thismembers;
  node.landptsintersecting(w.thismembers) -> .thisintersectingpts;
  node.thisintersectingpts.roadsptsintersecting -> .thismatchpts;
  if (thismatchpts.count(nodes)>1)
  { 
    way.roadsmatch(bn.thismatchpts)->.thismatchroads;
    foreach.thismatchroads->.thisthismatchroads
    {
      node.thismatchpts(w.thisthismatchroads);
      if (count(nodes)>1)
      {
        .thisthismatchroads out geom;
        .thisland out geom;
      };
    };
  }; 
};

Nested features

try it yourself in overpass-turbo
[out:json][timeout:25];
nwr({{bbox}})[amenity=school]->.all;
foreach.all->.this
{
  nwr.all(area.this)->.candidates;
  if (candidates.count(nodes)>0)
  {
    node.candidates;
    out geom;
    .this out geom;
  }
  (wr.candidates; - .this;)->.candidatesareas;
  if (candidatesareas.count(wr)>0)
  {
    (way.candidatesareas; way(r.candidatesareas);)->.candidatessegments;
    node(w.candidatessegments);
    node._(area.this)->.candidatessegmentspts;
    (way.this; way(r.this););
    node(w)->.thispts;
    (.candidatessegmentspts; - node.candidatessegmentspts.thispts;);
    if (count(nodes)>0)
    {
      way.candidatessegments(bn)->.matchessegments;
      (way.matchessegments.candidatesareas; rel.candidatesareas(bw.matchessegments););
      out geom;
      .this out geom;
    };
  };
};

TIGER by road section

try it yourself in overpass-turbo
[out:json][timeout:25];
way({{bbox}})[highway][name]->.all;
node(way_cnt.all:2)->.alljoints; // Find points with 2 lines intersecting 
foreach.alljoints->.this
{
  way.all(bn.this)->.thisroads;
  if (thisroads.u(t["highway"]) != "< multiple values found >" && thisroads.u(t["name"]) != "< multiple values found >") // Find same val
  {
    way.thisroads["tiger:reviewed"=no]->.unreviewed;
    if (unreviewed.count(ways) == 1)
    {
      (.thisroads; - .unreviewed;)->.reviewed;
      way.reviewed[~"^tiger:"~"."]->.tiger; // Find has tiger:*= to eliminate
      if (tiger.count(ways) == 0)
      {
        .thisroads out geom;
      };
    };
  };
};

Isolated photos

try it yourself in overpass-turbo
[out:json][timeout:25];
nwr({{bbox}})[image]->.all;
for.all->.these(t["image"]) // Loops through all unique [image=]
{
  if (these.count(nwr) > 1) // Discards unique ones
  {
    foreach.these->.this
    {
      if (findthese.count(nwr) != these.count(nwr)) // Breaks the loop when all objects of this [image=] are retrieved
      {
        nwr.these(around.this:100)->.aroundthis;
        if (aroundthis.count(nwr) == 1) // Lone object
        {
          .this out geom;
        };
        (.findthese; .aroundthis;)->.findthese; // Records what's found
      };
    };
  };
};

Bridges directly connected to junctions

https://community.openstreetmap.org/t/overpass-request-bridges-search-the-not-preferred-tagging/114549

try it yourself in overpass-turbo
[out:json][timeout:25];
way({{bbox}})[bridge][highway]->.all;
node(w.all)->.allpts;
way(bn.allpts)[highway]->.allconnected;
node.allpts(way_link.allconnected:3-);
foreach
{
  way.allconnected(bn)->.thisconnected;
  way.thisconnected[bridge]->.thisbridges;
  if ( (thisbridges.count(ways) >= 1) && (thisconnected.count(ways) - thisbridges.count(ways) >= 1) )
  {
    .thisconnected out geom;
  };
};

Continuous structure lengths

https://community.openstreetmap.org/t/how-to-find-the-longest-railway-bridge-in-mexico-with-an-overpass-query/114715

try it yourself in overpass-turbo
[out:csv(::id,allid,"name","bridge:name",length)][timeout:25];
{{geocodeArea:Mexico}}->.ar;
way(area.ar)[bridge][railway=rail]->.all;  
foreach.all->.this 
{
  if (! lrs_in(this.u(id()), visited_ids.set(t['ids'])))
  {
    .this;
    complete(10)->.thisall
    {
      node(w);
      way.all(bn);
    };
    make bdg allid=thisall.set(id()),name=thisall.set(t["name"]),"bridge:name"=thisall.set(t["bridge:name"]),length=thisall.sum(length());
    out;
    //.thisall out;
    make visited
      ids = lrs_union(thisall.set(id()), visited_ids.set(t['ids']))
      -> .visited_ids; 
  };
};

https://dev.overpass-api.de/blog/counting_roundabouts.html

https://www.reddit.com/r/openstreetmap/comments/1dsvp33/counting_bridges_with_overpassturbo/

try it yourself in overpass-turbo
[out:csv(allid,length,"bridge:name",highway,ref,network,name,"boundary:name","crossedroads:id","crossedroads:highway","crossedroads:ref","crossedroads:name","crossedrwy:id","crossedrwy:railway","crossedrwy:ref","crossedrwy:name","crossedwwy:id","crossedwwy:waterway","crossedwwy:name","crossedcoast:id","crossedcoast_count","crossedsea:id","crossedsea:natural","crossedsea:name")][timeout:55]; 
//{{geocodeArea:Mexico}}->.ar;
//way(area.ar)[bridge][highway][footway!=sidewalk]->.all;  
way({{bbox}})[bridge][highway][footway!=sidewalk]->.all;  
foreach.all->.this 
{
  if (! lrs_in(this.u(id()), visited_ids.set(t['ids'])))
  {
    .this;
    complete(10)->.thisall
    {
      node(w);
      way.all(bn);
    };
    if (thisall.sum(length()) >= 90)
    {
      way(around.thisall:0)->.thisallcrossed;
      (.thisallcrossed; rel(bw.thisallcrossed)[type=multipolygon];)->.thisallcrossed;
      (.thisallcrossed; - .thisall;)->.thisallcrossed;
      way.thisallcrossed[highway][highway!=footway][highway!=cycleway][highway!=bridleway][highway!=path][!tunnel][highway!=platform]->.thisallcrossedroads;
      way.thisallcrossed[railway][railway!=platform][!tunnel]->.thisallcrossedrwy;
      way.thisallcrossed[waterway][waterway!=dam]->.thisallcrossedwwy;
      wr.thisallcrossed[natural=water][water!=river][water!=stream][water!=canal][water!=ditch][water!=drain][!tunnel]->.thisallcrossedwaters;
      way.thisallcrossed[natural=coastline]->.thisallcrossedcoast;
      rel(bw.thisallcrossed)->.thisallcrossedparent;
      (
        way.thisallcrossed[natural=bay]; 
        way.thisallcrossed[natural=strait];  
        rel.thisallcrossedparent[natural=bay]; 
        rel.thisallcrossedparent[natural=strait];         
      )->.thisallcrossedsea;
      node(w.thisall);
      is_in;
      area._[admin_level=6]->.thisalladmins;
      make bdg allid=thisall.set(id()),
      length=thisall.sum(length()),
      "bridge:name"=thisall.set(t["bridge:name"]),
      highway=thisall.set(t["highway"]),
      ref=thisall.set(t["ref"]),
      network=thisall.set(t["network"]),
      name=thisall.set(t["name"]),
      "boundary:name"=thisalladmins.set(t["name"]),
      "crossedroads:id"=thisallcrossedroads.set(id()),
      "crossedroads:highway"=thisallcrossedroads.set(t["highway"]),
      "crossedroads:ref"=thisallcrossedroads.set(t["ref"]),
      "crossedroads:name"=thisallcrossedroads.set(t["ref"]), 
      "crossedrwy:id"=thisallcrossedrwy.set(id()),
      "crossedrwy:railway"=thisallcrossedrwy.set(t["railway"]),
      "crossedrwy:ref"=thisallcrossedrwy.set(t["ref"]),
      "crossedrwy:name"=thisallcrossedrwy.set(t["name"]),
      "crossedwwy:id"=thisallcrossedwwy.set(id()),
      "crossedwwy:waterway"=thisallcrossedwwy.set(t["waterway"]), 
      "crossedwwy:name"=thisallcrossedwwy.set(t["name"]),
      "crossedcoast:id"=thisallcrossedcoast.set(id()),
      "crossedcoast_count"=thisallcrossedcoast.count(ways),
      "crossedwater:id"=thisallcrossedwater.set(type() + id()),
      "crossedwater:water"=thisallcrossedwater.set(t["water"]),  
      "crossedsea:id"=thisallcrossedsea.set(type() + id()),
      "crossedsea:natural"=thisallcrossedsea.set(t["natural"]), 
      "crossedsea:name"=thisallcrossedsea.set(t["name"]);
      out;
    };
    //.thisall out;
    make visited
      ids = lrs_union(thisall.set(id()), visited_ids.set(t['ids']))
      -> .visited_ids; 
  };
};
try it yourself in overpass-turbo
[out:csv(allid,length,"bridge:name",highway,ref,network,name,"boundary:name","crossedroads:id","crossedroads:highway","crossedroads:ref","crossedroads:name","crossedrwy:id","crossedrwy:railway","crossedrwy:ref","crossedrwy:name","crossedwwy:id","crossedwwy:waterway","crossedwwy:name","crossedcoast:id","crossedcoast_count","crossedsea:id","crossedsea:natural","crossedsea:name")][timeout:55]; 
way({{bbox}})[bridge][highway][footway!=sidewalk]->.all;  
.all -> .allunvisited;
foreach.all->.thisstart 
{
  way.thisstart.allvisited -> .thisvisited;
  if (thisvisited.count(ways) == 0)
  {
    .thisstart->.thissome;
    complete(10).thissome->.thisall
    {
      (node(w.thissome); - .thissomeptsvisited;) -> .thissomeptsunvisited; 
      (.thissome; way.allunvisited(bn.thissomeptsunvisited);) -> .thissome;
      (.allunvisited; - .thissome;) -> .allunvisited;
      (.thissomeptsunvisited; .thissomeptsvisited;) -> .thissomeptsvisited;
    };
    if (thisall.sum(length()) >= 90)
    {
      way(around.thisall:0)->.thisallcrossed;
      (.thisallcrossed; rel(bw.thisallcrossed)[type=multipolygon];)->.thisallcrossed;
      (.thisallcrossed; - .thisall;)->.thisallcrossed;
      way.thisallcrossed[highway][highway!=footway][highway!=cycleway][highway!=bridleway][highway!=path][!tunnel][highway!=platform]->.thisallcrossedroads;
      way.thisallcrossed[railway][railway!=platform][!tunnel]->.thisallcrossedrwy;
      way.thisallcrossed[waterway][waterway!=dam]->.thisallcrossedwwy;
      wr.thisallcrossed[natural=water][water!=river][water!=stream][water!=canal][water!=ditch][water!=drain][!tunnel]->.thisallcrossedwaters;
      way.thisallcrossed[natural=coastline]->.thisallcrossedcoast;
      rel(bw.thisallcrossed)->.thisallcrossedparent;
      (
        way.thisallcrossed[natural=bay]; 
        way.thisallcrossed[natural=strait];  
        rel.thisallcrossedparent[natural=bay]; 
        rel.thisallcrossedparent[natural=strait];         
      )->.thisallcrossedsea;
      node(w.thisall);
      is_in;
      area._[admin_level=6]->.thisalladmins;
      make bdg allid=thisall.set(id()),
        length=thisall.sum(length()),
        "bridge:name"=thisall.set(t["bridge:name"]),
        highway=thisall.set(t["highway"]),
        ref=thisall.set(t["ref"]),
        network=thisall.set(t["network"]),
        name=thisall.set(t["name"]),
        "boundary:name"=thisalladmins.set(t["name"]),
        "crossedroads:id"=thisallcrossedroads.set(id()),
        "crossedroads:highway"=thisallcrossedroads.set(t["highway"]),
        "crossedroads:ref"=thisallcrossedroads.set(t["ref"]),
        "crossedroads:name"=thisallcrossedroads.set(t["ref"]), 
        "crossedrwy:id"=thisallcrossedrwy.set(id()),
        "crossedrwy:railway"=thisallcrossedrwy.set(t["railway"]),
        "crossedrwy:ref"=thisallcrossedrwy.set(t["ref"]),
        "crossedrwy:name"=thisallcrossedrwy.set(t["name"]),
        "crossedwwy:id"=thisallcrossedwwy.set(id()),
        "crossedwwy:waterway"=thisallcrossedwwy.set(t["waterway"]), 
        "crossedwwy:name"=thisallcrossedwwy.set(t["name"]),
        "crossedcoast:id"=thisallcrossedcoast.set(id()),
        "crossedcoast_count"=thisallcrossedcoast.count(ways),
        "crossedwater:id"=thisallcrossedwater.set(type() + id()),
        "crossedwater:water"=thisallcrossedwater.set(t["water"]),  
        "crossedsea:id"=thisallcrossedsea.set(type() + id()),
        "crossedsea:natural"=thisallcrossedsea.set(t["natural"]), 
        "crossedsea:name"=thisallcrossedsea.set(t["name"]);
      out;
    }; 
    (.thisall; .allvisited;)->.allvisited; 
  };
};