### Underpass Ruby: Step-by-step Flow Example Source: https://github.com/haiafara/underpass/blob/main/docs/usage-examples.md Demonstrates a step-by-step flow for querying OpenStreetMap data using the Underpass Ruby library. It shows how to define a bounding box from WKT, construct an Overpass QL query, perform the request, and process the API response. This example highlights inspecting intermediate objects. ```ruby require 'underpass' # Define a polygon to be used as bounding box wkt = <<-WKT POLYGON (( 23.669 47.65, 23.725 47.65, 23.725 47.674, 23.669 47.674, 23.669 47.65 )) WKT # Define the Overpass QL query op_query = 'way["heritage:operator"="lmi"]["heritage"="2"];' # We won't use the Underpass::QL::Query convenience class # Note that we pass the wkt directly to the from_wkt method op_bbox = Underpass::QL::BoundingBox.from_wkt(wkt) request = Underpass::QL::Request.new(op_query, op_bbox) api_response = Underpass::Client.perform(request) response = Underpass::QL::Response.new(api_response) matcher = Underpass::Matcher.new(response) # We'll have our matches in matcher.matches ``` -------------------------------- ### Underpass Ruby: Relation Query Example Source: https://github.com/haiafara/underpass/blob/main/docs/usage-examples.md This Ruby example demonstrates how to query for relations using the Underpass library. It defines a bounding box and an Overpass QL query specifically for relations named 'Árok'. The code shows the process of creating a request, performing it, and initializing a matcher with the response. ```ruby require 'underpass' wkt = <<-WKT POLYGON (( 23.65 47.65, 23.6995 47.65, 23.6995 47.71, 23.65 47.71, 23.65 47.65 )) WKT op_query = 'relation["name"="Árok"];' op_bbox = Underpass::QL::BoundingBox.from_wkt(wkt) request = Underpass::QL::Request.new(op_query, op_bbox) api_response = Underpass::Client.perform(request) response = Underpass::QL::Response.new(api_response) matcher = Underpass::Matcher.new(response) ``` -------------------------------- ### Install Underpass Gem Source: https://github.com/haiafara/underpass/blob/main/README.md Instructions for installing the Underpass gem, either globally using 'gem install' or by adding it to a Gemfile. ```ruby gem install underpass ``` ```ruby gem 'underpass' ``` -------------------------------- ### Use Builder DSL with Bounding Box for Cafe Queries in Underpass Source: https://github.com/haiafara/underpass/blob/main/docs/usage-examples.md A comprehensive example demonstrating the use of the Underpass gem's Builder DSL to find all nodes tagged as a cafe within a specific bounding box. It outlines the steps from defining the bounding box to processing the results. ```ruby # Example 16: Builder DSL with Bounding Box - Cafes require 'underpass' # Step 1: Define a bounding box as a WKT polygon wkt = <<-WKT POLYGON ( 26.08 44.42, 26.12 44.42, 26.12 44.45, 26.08 44.45, 26.08 44.42 ) WKT bbox = RGeo::Geographic.spherical_factory.parse_wkt(wkt) # Step 2: Use the Builder DSL to construct the query builder = Underpass::QL::Builder.new .node(amenity: 'cafe') # Step 3: Pass both bounding box and builder to Query.perform cafes = Underpass::QL::Query.perform(bbox, builder) # Step 4: Process results cafes.each do |cafe| puts "#{cafe.properties[:name]}" puts " Location: #{cafe.geometry.as_text}" puts " Type: #{cafe.type}" # => "node" end ``` -------------------------------- ### Underpass Ruby: Way Query for Parks (Polygon) Source: https://github.com/haiafara/underpass/blob/main/docs/usage-examples.md This Ruby example illustrates how to query for parks, which are represented as ways with Polygon geometries. Using the Underpass::QL::Query.perform method, it takes a bounding box and an Overpass QL query targeting parks. The output includes the park's name, geometry type, and its OpenStreetMap type. ```ruby require 'underpass' query = 'way["leisure"="park"];' parks = Underpass::QL::Query.perform(bbox, query) parks.each do |park| puts "#{park.properties[:name]}" puts " Geometry: #{park.geometry.geometry_type}" # => Polygon puts " Type: #{park.type}" # => way end ``` -------------------------------- ### Underpass Ruby: Way Query for Roads (LineString) Source: https://github.com/haiafara/underpass/blob/main/docs/usage-examples.md This Ruby example shows how to query for primary roads, which are represented as ways with LineString geometries. It uses the Underpass::QL::Query.perform method with a predefined bounding box and an Overpass QL query. The output includes the road's name and its geometry type. ```ruby require 'underpass' # Using the same Bucharest bounding box query = 'way["highway"="primary"];' roads = Underpass::QL::Query.perform(bbox, query) roads.each do |road| puts "#{road.properties[:name]}" puts " Geometry: #{road.geometry.geometry_type}" # => LineString puts " Type: #{road.type}" # => way end ``` -------------------------------- ### Query with Multiple Tag Filters using Builder DSL in Ruby Source: https://github.com/haiafara/underpass/blob/main/docs/usage-examples.md This example demonstrates how to use the Underpass Builder DSL to apply multiple tag filters to a query. It specifically searches for ways tagged with 'heritage:operator=lmi' and 'heritage=2' within a defined bounding box. Requires the 'underpass' and 'rgeo' gems. ```ruby require 'underpass' # Define bounding box (using Bucharest area from Example 1)box = RGeo::Geographic.spherical_factory.parse_wkt(<<-WKT POLYGON ((26.08 44.42, 26.12 44.42, 26.12 44.45, 26.08 44.45, 26.08 44.42)) WKT ) # Query with multiple tag filters builder = Underpass::QL::Builder.new .way('heritage:operator': 'lmi', heritage: '2') heritage = Underpass::QL::Query.perform(bbox, builder) heritage.each do |building| puts "#{building.properties[:name]}" puts " Geometry: #{building.geometry.geometry_type}" # => Polygon puts " Type: #{building.type}" # => way end ``` -------------------------------- ### Underpass Ruby: Node Query for Restaurants Source: https://github.com/haiafara/underpass/blob/main/docs/usage-examples.md This Ruby example demonstrates how to query for nodes representing restaurants in a specified bounding box. It utilizes the Underpass::QL::Query.perform method, passing a bounding box object and an Overpass QL query. The code iterates through the results, printing properties like name, cuisine, geometry type, type, and ID. ```ruby require 'underpass' # Define a bounding box for central Bucharest wkt = <<-WKT POLYGON (( 26.08 44.42, 26.12 44.42, 26.12 44.45, 26.08 44.45, 26.08 44.42 )) WKT bbox = RGeo::Geographic.spherical_factory.parse_wkt(wkt) # Query for restaurants (nodes) query = 'node["amenity"="restaurant"];' features = Underpass::QL::Query.perform(bbox, query) # Process results features.each do |f| puts "#{f.properties[:name]} - #{f.properties[:cuisine]}" puts " Geometry: #{f.geometry.geometry_type}" # => Point puts " Type: #{f.type}" # => node puts " ID: #{f.id}" end ``` -------------------------------- ### Proximity Search for Restaurants within Radius in Ruby Source: https://github.com/haiafara/underpass/blob/main/docs/usage-examples.md This example demonstrates how to find elements (restaurants in this case) within a specified radius of a given latitude and longitude. It utilizes the 'around' method of the Underpass::QL::Builder DSL and performs the query using a bounding box. Requires the 'underpass' and 'rgeo' gems. ```ruby require 'underpass' # Define bounding box (using Bucharest area from Example 1)box = RGeo::Geographic.spherical_factory.parse_wkt(<<-WKT POLYGON ((26.08 44.42, 26.12 44.42, 26.12 44.45, 26.08 44.45, 26.08 44.42)) WKT ) # Find restaurants within 500m of University Square, Bucharest lat = 44.4325 lon = 26.1025 query = Underpass::QL::Builder.new .node(amenity: 'restaurant') .around(500, lat, lon) .to_ql restaurants_nearby = Underpass::QL::Query.perform(bbox, query) restaurants_nearby.each do |restaurant| puts "#{restaurant.properties[:name]} - #{restaurant.properties[:cuisine]}" puts " Geometry: #{restaurant.geometry.geometry_type}" # => Point puts " Type: #{restaurant.type}" # => node end ``` -------------------------------- ### Query Bus Routes (Relations - MultiLineString) in Ruby Source: https://github.com/haiafara/underpass/blob/main/docs/usage-examples.md This example demonstrates how to query for bus routes (relations with MultiLineString geometries) using the Underpass gem. It shows how to iterate through the results and access properties like name, geometry type, and element type. Requires the 'underpass' gem. ```ruby require 'underpass' # Using the Bucharest bounding box query = 'relation["type"="route"]["route"="bus"];' routes = Underpass::QL::Query.perform(bbox, query) routes.each do |route| puts "#{route.properties[:name]}" puts " Geometry: #{route.geometry.geometry_type}" # => MultiLineString puts " Type: #{route.type}" # => relation end ``` -------------------------------- ### Post-Query Filtering of Amenities in Ruby Source: https://github.com/haiafara/underpass/blob/main/docs/usage-examples.md This example illustrates how to filter query results after they have been retrieved, using the Underpass::Filter class. It shows filtering for specific amenity types, multiple amenity types using an array, filtering with regular expressions, and rejecting specific amenity types. Requires the 'underpass' gem. ```ruby require 'underpass' # Query all amenities query = 'node["amenity"];' amenities = Underpass::QL::Query.perform(bbox, query) # Filter for restaurants only restaurants = Underpass::Filter.new(amenities).where(amenity: 'restaurant') puts "Restaurants: #{restaurants.size}" # Filter for multiple amenity types (OR) food_places = Underpass::Filter.new(amenities).where(amenity: %w[restaurant cafe bar]) puts "Food places: #{food_places.size}" # Filter with regex italian_places = Underpass::Filter.new(amenities).where(cuisine: /italian/i) puts "Italian places: #{italian_places.size}" # Reject banks no_banks = Underpass::Filter.new(amenities).reject(amenity: 'bank') puts "Non-bank amenities: #{no_banks.size}" ``` -------------------------------- ### Underpass Ruby: Way Query for Buildings (Polygon) Source: https://github.com/haiafara/underpass/blob/main/docs/usage-examples.md This Ruby example demonstrates querying for buildings, which are typically represented as ways with Polygon geometries. It employs the Underpass::QL::Query.perform method, specifying a bounding box and an Overpass QL query for buildings. The code prints the building's name, geometry type, and its OpenStreetMap type. ```ruby require 'underpass' query = 'way["building"="yes"];' buildings = Underpass::QL::Query.perform(bbox, query) buildings.each do |building| puts "#{building.properties[:name]}" puts " Geometry: #{building.geometry.geometry_type}" # => Polygon puts " Type: #{building.type}" # => way end ``` -------------------------------- ### Quick Start: Query Overpass API with Raw QL Source: https://github.com/haiafara/underpass/blob/main/README.md Demonstrates how to use the Underpass gem to perform a raw Overpass QL query within a specified bounding box. It shows how to define a bounding box using RGeo and process the returned features, accessing their geometry, properties, ID, and type. ```ruby require 'underpass' # Define a bounding box polygon wkt = <<-WKT POLYGON (( 23.669 47.65, 23.725 47.65, 23.725 47.674, 23.669 47.674, 23.669 47.65 )) WKT bbox = RGeo::Geographic.spherical_factory.parse_wkt(wkt) # Query using raw Overpass QL query = 'way["heritage:operator"="lmi"]["heritage"="2"];' features = Underpass::QL::Query.perform(bbox, query) # Each result is a Feature with geometry and OSM tags features.each do |f| puts f.geometry.as_text # => "POLYGON ((...))" puts f.properties[:name] # => "Biserica Romano-Catolică" puts f.id # => 186213580 puts f.type # => "way" end ``` -------------------------------- ### Convert Query Results to GeoJSON in Ruby Source: https://github.com/haiafara/underpass/blob/main/docs/usage-examples.md This example demonstrates how to convert OpenStreetMap data retrieved by Underpass into GeoJSON format. The GeoJSON output can then be easily used with web mapping libraries. It queries for restaurants and then encodes the results using Underpass::GeoJSON.encode. Requires the 'underpass' and 'json' gems. ```ruby require 'underpass' require 'json' # Query for restaurants query = 'node["amenity"="restaurant"];' restaurants = Underpass::QL::Query.perform(bbox, query) # Convert to GeoJSON geojson = Underpass::GeoJSON.encode(restaurants) # Serialize to JSON file File.write('restaurants.geojson', JSON.pretty_generate(geojson)) ``` -------------------------------- ### Query Multiple Element Types using Builder DSL in Ruby Source: https://github.com/haiafara/underpass/blob/main/docs/usage-examples.md This example showcases the Underpass Builder DSL for querying multiple element types (nodes, ways, and relations) simultaneously based on a common tag filter. It queries for all elements tagged with 'amenity=restaurant' within a defined bounding box. Requires the 'underpass' and 'rgeo' gems. ```ruby require 'underpass' # Define bounding box (using Bucharest area from Example 1)box = RGeo::Geographic.spherical_factory.parse_wkt(<<-WKT POLYGON ((26.08 44.42, 26.12 44.42, 26.12 44.45, 26.08 44.45, 26.08 44.42)) WKT ) # Using Builder DSL to query multiple types builder = Underpass::QL::Builder.new .node(amenity: 'restaurant') .way(amenity: 'restaurant') .relation(amenity: 'restaurant') all_restaurants = Underpass::QL::Query.perform(bbox, builder) all_restaurants.each do |restaurant| puts "#{restaurant.properties[:name]}" puts " Geometry: #{restaurant.geometry.geometry_type}" # Point, Polygon, or MultiPolygon puts " Type: #{restaurant.type}" # node, way, or relation end ``` -------------------------------- ### Underpass Ruby: Relation Query for Lakes (Multipolygon) Source: https://github.com/haiafara/underpass/blob/main/docs/usage-examples.md This Ruby example demonstrates querying for lakes, which are often represented as multipolygon relations. It defines a specific bounding box for Romanian mountain lakes and uses Underpass::QL::Query.perform with an appropriate Overpass QL query. The code iterates through the results, displaying the lake's name, geometry type, and OpenStreetMap type. ```ruby require 'underpass' # Define a bounding box for Romanian mountain lakes area wkt_mountains = <<-WKT POLYGON (( 25.0 45.5, 26.0 45.5, 26.0 46.0, 25.0 46.0, 25.0 45.5 )) WKT bbox_mountains = RGeo::Geographic.spherical_factory.parse_wkt(wkt_mountains) # Query for lakes as multipolygon relations query = 'relation["type"="multipolygon"]["water"="lake"];' lakes = Underpass::QL::Query.perform(bbox_mountains, query) lakes.each do |lake| puts "#{lake.properties[:name]}" puts " Geometry: #{lake.geometry.geometry_type}" # => Polygon or MultiPolygon puts " Type: #{lake.type}" # => relation end ``` -------------------------------- ### Query Cafes within a Named Area in Ruby Source: https://github.com/haiafara/underpass/blob/main/docs/usage-examples.md This example shows how to perform a query within a specified named area (e.g., 'Bucharest') instead of using a bounding box. It queries for nodes tagged with 'amenity=cafe' and iterates through the results, displaying their names, geometry types, and element types. Requires the 'underpass' gem. ```ruby require 'underpass' # Query within a named area (note: no semicolon at end) query = 'node["amenity"="cafe"]' cafes = Underpass::QL::Query.perform_in_area('Bucharest', query) cafes.each do |cafe| puts "#{cafe.properties[:name]}" puts " Geometry: #{cafe.geometry.geometry_type}" # => Point puts " Type: #{cafe.type}" # => node end ``` -------------------------------- ### Build Overpass QL Queries with Ruby DSL Source: https://github.com/haiafara/underpass/blob/main/README.md Shows how to use the Underpass Query Builder DSL to construct Overpass QL queries programmatically in Ruby. Examples include simple node queries, multiple element types, multiple tag filters, and the 'nwr' shorthand. ```ruby # Simple query query = Underpass::QL::Builder.new .node(amenity: 'restaurant') .to_ql # => 'node["amenity"="restaurant"];' # Multiple types query = Underpass::QL::Builder.new .node(amenity: 'restaurant') .way(highway: 'primary') .to_ql # => "node["amenity"="restaurant"];\nway["highway"="primary"];" # Multiple tag filters query = Underpass::QL::Builder.new .way('heritage:operator': 'lmi', heritage: '2') .to_ql # => 'way["heritage:operator"="lmi"]["heritage"="2"];' # nwr (node/way/relation) shorthand query = Underpass::QL::Builder.new .nwr(name: 'Central Park') .to_ql # => 'nwr["name"="Central Park"];' # Pass a Builder directly to Query.perform builder = Underpass::QL::Builder.new.way(building: 'yes') features = Underpass::QL::Query.perform(bbox, builder) ``` -------------------------------- ### Perform 'Around' Queries with RGeo Point in Underpass Source: https://github.com/haiafara/underpass/blob/main/docs/usage-examples.md Shows how to perform 'around' queries using an RGeo point object with the Underpass gem. This is useful for finding features within a specified radius of a geographic point. ```ruby require 'underpass' # Define bounding box (using Bucharest area from Example 1) bbox = RGeo::Geographic.spherical_factory.parse_wkt(<<-WKT POLYGON ((26.08 44.42, 26.12 44.42, 26.12 44.45, 26.08 44.45, 26.08 44.42)) WKT ) # Using RGeo point for around query point = RGeo::Geographic.spherical_factory(srid: 4326).point(26.1025, 44.4325) query = Underpass::QL::Builder.new .node(amenity: 'cafe') .around(300, point) .to_ql cafes_nearby = Underpass::QL::Query.perform(bbox, query) cafes_nearby.each do |cafe| puts "#{cafe.properties[:name]}" puts " Geometry: #{cafe.geometry.geometry_type}" # => Point puts " Type: #{cafe.type}" # => node end ``` -------------------------------- ### Query Multiple Element Types (Node, Way, Relation) with Underpass Source: https://github.com/haiafara/underpass/blob/main/docs/usage-examples.md Demonstrates how to query for nodes, ways, and relations simultaneously in a single Underpass query. This is useful for retrieving diverse data types that match specific criteria. ```ruby require 'underpass' # Query for nodes, ways, and relations in one query query = <<-QL node["amenity"="restaurant"]; way["amenity"="restaurant"]; relation["type"="route"]; QL multi_results = Underpass::QL::Query.perform(bbox, query) multi_results.each do |feature| puts "#{feature.properties[:name] || 'Unnamed'}" puts " Geometry: #{feature.geometry.geometry_type}" puts " Type: #{feature.type}" end ``` -------------------------------- ### Proximity Queries with 'around' Filter Source: https://github.com/haiafara/underpass/blob/main/README.md Explains how to perform proximity searches using the `around` filter in the Underpass Query Builder DSL. It provides examples for specifying a radius and coordinates, or a radius and an RGeo point object. ```ruby # Using coordinates query = Underpass::QL::Builder.new .node(amenity: 'restaurant') .around(500, 47.65, 23.69) .to_ql # => 'node["amenity"="restaurant"](around:500,47.65,23.69);' # Using an RGeo point point = RGeo::Geographic.spherical_factory(srid: 4326).point(23.69, 47.65) query = Underpass::QL::Builder.new .node(amenity: 'cafe') .around(1000, point) .to_ql ``` -------------------------------- ### Use NWR Shorthand for Node, Way, Relation Queries with Underpass Source: https://github.com/haiafara/underpass/blob/main/docs/usage-examples.md Illustrates the use of the 'nwr' shorthand in the Underpass gem for querying nodes, ways, and relations together. This simplifies queries when you need to find any of these element types matching a condition. ```ruby require 'underpass' # Define bounding box (using Bucharest area from Example 1) bbox = RGeo::Geographic.spherical_factory.parse_wkt(<<-WKT POLYGON ((26.08 44.42, 26.12 44.42, 26.12 44.45, 26.08 44.45, 26.08 44.42)) WKT ) # Using nwr (node/way/relation) shorthand builder = Underpass::QL::Builder.new.nwr(name: 'Universitate') results = Underpass::QL::Query.perform(bbox, builder) results.each do |feature| puts "#{feature.properties[:name]}" puts " Geometry: #{feature.geometry.geometry_type}" # Point, LineString, or Polygon puts " Type: #{feature.type}" # node, way, or relation end ``` -------------------------------- ### Overpass Query for Area Search Source: https://github.com/haiafara/underpass/blob/main/README.md An example Overpass QL query string that searches for nodes with the tag 'amenity=restaurant' within the area named 'Romania'. This is the underlying query generated by the Ruby `perform_in_area` method. ```overpassql [out:json][timeout:25]; area["name"="Romania"]->.searchArea; ( node["amenity"="restaurant"](area.searchArea); ); out body; >; out skel qt; ``` -------------------------------- ### Query with Builder DSL and Bounding Box Source: https://github.com/haiafara/underpass/blob/main/README.md Demonstrates combining the Underpass Builder DSL with a bounding box for spatial queries. It shows how to define an RGeo bounding box, build a query using the DSL, and then execute it using `Query.perform`, where the bounding box acts as a spatial constraint. ```ruby # Define a bounding box wkt = 'POLYGON ((26.08 44.42, 26.12 44.42, 26.12 44.45, 26.08 44.45, 26.08 44.42))' bbox = RGeo::Geographic.spherical_factory.parse_wkt(wkt) # Build the query builder = Underpass::QL::Builder.new.node(amenity: 'cafe') # Execute — the bounding box constrains results spatially cafes = Underpass::QL::Query.perform(bbox, builder) ``` -------------------------------- ### Perform Query with Underpass::QL::Query Source: https://context7.com/haiafara/underpass/llms.txt Shows how to execute an Underpass query directly using Underpass::QL::Query.perform. This method takes a bounding box and a builder object (or a QL string) to fetch data. It requires the RGeo gem for geometry parsing. ```ruby require 'underpass' require 'rgeo' box = RGeo::Geographic.spherical_factory.parse_wkt( 'POLYGON ((26.08 44.42, 26.12 44.42, 26.12 44.45, 26.08 44.45, 26.08 44.42))' ) builder = Underpass::QL::Builder.new.node(amenity: 'cafe') cafes = Underpass::QL::Query.perform(bbox, builder) ``` -------------------------------- ### Build NWR Query with Underpass::QL::Builder Source: https://context7.com/haiafara/underpass/llms.txt Demonstrates how to construct a basic Overpass API query for nodes, ways, and relations (NWR) using the Underpass::QL::Builder. The builder allows specifying filters like 'name' and then converting the query to the Overpass QL format. ```ruby require 'underpass' builder = Underpass::QL::Builder.new.nwr(name: 'Central Park') puts builder.to_ql # => 'nwr["name"="Central Park"];' ``` -------------------------------- ### Prepare Overpass QL Query Strings with Recurse Operator Source: https://context7.com/haiafara/underpass/llms.txt Explains how to use the `Underpass::QL::Request` class to construct Overpass QL query strings, including configuring the recurse operator. It shows the default behavior for child recursion. ```ruby require 'underpass' bbox = RGeo::Geographic.spherical_factory.parse_wkt( 'POLYGON ((26.08 44.42, 26.12 44.42, 26.12 44.45, 26.08 44.45, 26.08 44.42))' ) op_bbox = Underpass::QL::BoundingBox.from_geometry(bbox) query = 'way["building"="yes"];' # Default: child recurse (>) - fetches child elements (way nodes) request = Underpass::QL::Request.new(query, op_bbox) ``` -------------------------------- ### Underpass API Execution and Response Handling (Ruby) Source: https://context7.com/haiafara/underpass/llms.txt Illustrates how to execute an Underpass query against the Overpass API and process the response in Ruby. It covers making the API call, creating a response object, and initializing a matcher for feature extraction. ```ruby require 'underpass' query = "way[\'building\'=\'yes\']" op_bbox = "44.42,26.08,44.45,26.12" request = Underpass::QL::Request.new(query, op_bbox, recurse: '>>') # Execute manually api_response = Underpass::Client.perform(request) response = Underpass::QL::Response.new(api_response) matcher = Underpass::Matcher.new(response) features = matcher.matches puts "Number of features found: #{features.count}" ``` -------------------------------- ### Build Overpass QL Queries Programmatically (Ruby) Source: https://context7.com/haiafara/underpass/llms.txt Provides a chainable Domain Specific Language (DSL) for programmatically constructing Overpass QL queries. It supports various query types like node, way, relation, and nwr (node/way/relation) with tag filters. The generated query can be directly passed to `Underpass::QL::Query.perform` or `perform_in_area`. ```ruby require 'underpass' # Simple query for restaurants builder = Underpass::QL::Builder.new .node(amenity: 'restaurant') puts builder.to_ql # => 'node["amenity"="restaurant"];' # Multiple tag filters (AND logic) builder = Underpass::QL::Builder.new .way('heritage:operator': 'lmi', heritage: '2') puts builder.to_ql # => 'way["heritage:operator"="lmi"]["heritage"="2"];' # Multiple element types in one query builder = Underpass::QL::Builder.new .node(amenity: 'restaurant') .way(amenity: 'restaurant') .relation(amenity: 'restaurant') puts builder.to_ql # => 'node["amenity"="restaurant"]; # way["amenity"="restaurant"]; # relation["amenity"="restaurant"];' ``` -------------------------------- ### Query for Ways Only in Ruby Source: https://github.com/haiafara/underpass/blob/main/README.md Demonstrates how to query specifically for 'way' elements using Overpass QL. The Underpass library analyzes the query and returns only the requested match types (in this case, ways). ```ruby query = 'way["highway"="primary"];' features = Underpass::QL::Query.perform(bbox, query) # Returns only way matches ``` -------------------------------- ### Underpass::QL::Query.perform Source: https://context7.com/haiafara/underpass/llms.txt The primary entry point for querying OpenStreetMap data within a geographic bounding box. Accepts an RGeo polygon defining the search area and either a raw Overpass QL query string or a Builder instance. Returns an array of Feature objects with RGeo geometries and OSM metadata. ```APIDOC ## Underpass::QL::Query.perform ### Description Queries OpenStreetMap data within a geographic bounding box. ### Method `Underpass::QL::Query.perform(bbox, query)` ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Request Example ```ruby require 'underpass' # Define a bounding box as a WKT polygon wkt = """ POLYGON (( 26.08 44.42, 26.12 44.42, 26.12 44.45, 26.08 44.45, 26.08 44.42 )) WKT bbox = RGeo::Geographic.spherical_factory.parse_wkt(wkt) # Query for restaurants using raw Overpass QL query = 'node["amenity"="restaurant"];' features = Underpass::QL::Query.perform(bbox, query) # Process results features.each do |f| puts "#{f.properties[:name]} - #{f.properties[:cuisine]}" puts " Geometry: #{f.geometry.geometry_type}" # => Point puts " Type: #{f.type}" # => node puts " ID: #{f.id}" # => 286859702 puts " Coordinates: #{f.geometry.as_text}" # => POINT (26.1025 44.4325) end # Query for ways (roads) - returns LineString geometries roads = Underpass::QL::Query.perform(bbox, 'way["highway"="primary"];') roads.each do |road| puts "#{road.properties[:name]}: #{road.geometry.geometry_type}" # => LineString end # Query for ways (buildings) - returns Polygon geometries buildings = Underpass::QL::Query.perform(bbox, 'way["building"="yes"];') buildings.each do |building| puts "#{building.properties[:name]}: #{building.geometry.geometry_type}" # => Polygon end # Query for relations (multipolygons) - returns MultiPolygon geometries lakes = Underpass::QL::Query.perform(bbox, 'relation["type"="multipolygon"]["water"="lake"];') lakes.each do |lake| puts "#{lake.properties[:name]}: #{lake.geometry.geometry_type}" # => MultiPolygon end ``` ### Response #### Success Response (200) - **features** (Array) - An array of Feature objects, each containing RGeo geometries and OSM metadata. #### Response Example ```json [ { "type": "Feature", "geometry": { "type": "Point", "coordinates": [26.1025, 44.4325] }, "properties": { "id": 286859702, "name": "Example Restaurant", "cuisine": "Italian" } } ] ``` ``` -------------------------------- ### Underpass::QL::Builder Source: https://context7.com/haiafara/underpass/llms.txt A chainable DSL for constructing Overpass QL queries programmatically. Supports node, way, relation, and nwr (node/way/relation) query types with tag filters. Can be passed directly to Query.perform instead of raw query strings. ```APIDOC ## Underpass::QL::Builder ### Description A chainable DSL for constructing Overpass QL queries programmatically. ### Method `Underpass::QL::Builder.new` ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Request Example ```ruby require 'underpass' # Simple query for restaurants builder = Underpass::QL::Builder.new .node(amenity: 'restaurant') puts builder.to_ql # => 'node["amenity"="restaurant"];' # Multiple tag filters (AND logic) builder = Underpass::QL::Builder.new .way('heritage:operator': 'lmi', heritage: '2') puts builder.to_ql # => 'way["heritage:operator"="lmi"]["heritage"="2"];' # Multiple element types in one query builder = Underpass::QL::Builder.new .node(amenity: 'restaurant') .way(amenity: 'restaurant') .relation(amenity: 'restaurant') puts builder.to_ql # => 'node["amenity"="restaurant"]; # way["amenity"="restaurant"]; # relation["amenity"="restaurant"];' ``` ### Response #### Success Response (200) - **to_ql** (String) - Returns the constructed Overpass QL query string. #### Response Example ``` node["amenity"="restaurant"]; way["amenity"="restaurant"]; relation["amenity"="restaurant"]; ``` ``` -------------------------------- ### Underpass Query Construction with Recursion Options (Ruby) Source: https://context7.com/haiafara/underpass/llms.txt Demonstrates how to construct Underpass queries in Ruby, specifying different recursion options like descendant ('>>'), parent ('<'), or no recursion (nil). This allows for flexible data retrieval based on element relationships. ```ruby require 'underpass' query = "way[\'building\'=\'yes\']" op_bbox = "44.42,26.08,44.45,26.12" # Descendant recurse (>>) - fetches all descendant elements request_descendant = Underpass::QL::Request.new(query, op_bbox, recurse: '>>') # Parent recurse (<) - fetches parent elements request_parent = Underpass::QL::Request.new(query, op_bbox, recurse: '<') # No recurse - only returns tagged elements without geometry nodes request_no_recurse = Underpass::QL::Request.new(query, op_bbox, recurse: nil) puts "Descendant Query: " + request_descendant.to_query puts "Parent Query: " + request_parent.to_query puts "No Recurse Query: " + request_no_recurse.to_query ``` -------------------------------- ### Configure Underpass API Endpoint and Timeout Source: https://context7.com/haiafara/underpass/llms.txt Demonstrates how to globally configure the Underpass gem, allowing customization of the Overpass API endpoint URL and the query timeout duration. It also shows how to access and reset the configuration. ```ruby require 'underpass' # Configure custom API endpoint and timeout Underpass.configure do |config| # Use an alternative Overpass API instance config.api_endpoint = 'https://overpass.kumi.systems/api/interpreter' # Set query timeout in seconds (default: 25) config.timeout = 60 end # Access current configuration puts Underpass.configuration.api_endpoint # => "https://overpass.kumi.systems/api/interpreter" puts Underpass.configuration.timeout # => 60 # Reset to default configuration Underpass.reset_configuration! puts Underpass.configuration.api_endpoint # => "https://overpass-api.de/api/interpreter" puts Underpass.configuration.timeout # => 25 ``` -------------------------------- ### Underpass Full Query String Generation (Ruby) Source: https://context7.com/haiafara/underpass/llms.txt Shows how to generate the complete Overpass API query string from an Underpass::QL::Request object in Ruby. This includes the output format, timeout, bounding box, query body, and output commands. ```ruby require 'underpass' query = "way[\'building\'=\'yes\']" op_bbox = "44.42,26.08,44.45,26.12" request = Underpass::QL::Request.new(query, op_bbox, recurse: '>>') puts request.to_query # Expected output: # [out:json][timeout:25][bbox:44.42,26.08,44.45,26.12]; # ( # way["building"="yes"]; # ); # out body; # >; # out skel qt; ``` -------------------------------- ### Handle Underpass API Errors with Retries Source: https://context7.com/haiafara/underpass/llms.txt Illustrates error handling for the Underpass library, including automatic retries with exponential backoff for transient errors like rate limits and timeouts. It shows how to rescue specific Underpass errors. ```ruby require 'underpass' bbox = RGeo::Geographic.spherical_factory.parse_wkt( 'POLYGON ((26.08 44.42, 26.12 44.42, 26.12 44.45, 26.08 44.45, 26.08 44.42))' ) begin features = Underpass::QL::Query.perform(bbox, 'node["amenity"="restaurant"];') features.each do |f| puts f.properties[:name] end rescue Underpass::RateLimitError # HTTP 429 - rate limited after 3 retries with exponential backoff puts "Rate limited by the Overpass API, try again later" rescue Underpass::TimeoutError # HTTP 504 - gateway timeout after 3 retries puts "Query timed out, try a smaller bounding box or increase timeout" Underpass.configure { |c| c.timeout = 60 } retry rescue Underpass::ApiError => e # Other unexpected API errors (raised immediately, no retry) puts "API error: #{e.message}" rescue Underpass::Error => e # Catch any Underpass error puts "Underpass error: #{e.message}" end ``` -------------------------------- ### Serialize GeoJSON Data to File Source: https://context7.com/haiafara/underpass/llms.txt Demonstrates how to serialize a GeoJSON data structure to a file using JSON.pretty_generate. This is useful for saving API responses or prepared data for later use. ```ruby File.write('restaurants.geojson', JSON.pretty_generate(geojson)) ``` -------------------------------- ### Configure Custom API Endpoint Source: https://github.com/haiafara/underpass/blob/main/README.md Allows specifying a private Overpass API instance instead of the default public one. This is useful for self-hosted or specialized Overpass deployments. No external dependencies are required beyond the Underpass gem itself. ```ruby Underpass.configure do |c| c.api_endpoint = 'https://my-overpass.example.com/api/interpreter' end ``` -------------------------------- ### Query for Nodes and Relations in Ruby Source: https://github.com/haiafara/underpass/blob/main/README.md Shows how to query for multiple element types (nodes and relations) simultaneously. The Underpass library identifies these types from the query string and returns only matching elements. ```ruby query = 'node["amenity"="restaurant"]; relation["type"="multipolygon"];' features = Underpass::QL::Query.perform(bbox, query) # Returns node and relation matches, but no way matches ``` -------------------------------- ### Enable and Use In-Memory Cache with TTL Source: https://context7.com/haiafara/underpass/llms.txt Shows how to enable and configure Underpass's in-memory cache with a Time-To-Live (TTL) expiration. It illustrates cache hits, misses, and disabling the cache. ```ruby require 'underpass' # Enable caching with a 10-minute TTL (600 seconds) Underpass.cache = Underpass::Cache.new(ttl: 600) bbox = RGeo::Geographic.spherical_factory.parse_wkt( 'POLYGON ((26.08 44.42, 26.12 44.42, 26.12 44.45, 26.08 44.45, 26.08 44.42))' ) # First query hits the API features = Underpass::QL::Query.perform(bbox, 'node["amenity"="restaurant"];') # Subsequent identical queries return cached response features = Underpass::QL::Query.perform(bbox, 'node["amenity"="restaurant"];') # Different queries still hit the API cafes = Underpass::QL::Query.perform(bbox, 'node["amenity"="cafe"];') # Clear all cached entries Underpass.cache.clear # Disable caching Underpass.cache = nil # Cache keys are SHA-256 digests of the full query string # so different queries always produce different keys ``` -------------------------------- ### Perform Overpass Query within Bounding Box (Ruby) Source: https://context7.com/haiafara/underpass/llms.txt Executes an Overpass QL query within a specified geographic bounding box. Accepts an RGeo polygon for the bounding box and either a raw Overpass QL query string or a Builder instance. Returns an array of Feature objects containing RGeo geometries and OSM metadata. Supports querying for nodes, ways, and relations. ```ruby require 'underpass' # Define a bounding box as a WKT polygon wkt = <<-WKT POLYGON (( 26.08 44.42, 26.12 44.42, 26.12 44.45, 26.08 44.45, 26.08 44.42 )) WKT bbox = RGeo::Geographic.spherical_factory.parse_wkt(wkt) # Query for restaurants using raw Overpass QL query = 'node["amenity"="restaurant"];' features = Underpass::QL::Query.perform(bbox, query) # Process results features.each do |f| puts "#{f.properties[:name]} - #{f.properties[:cuisine]}" puts " Geometry: #{f.geometry.geometry_type}" # => Point puts " Type: #{f.type}" # => node puts " ID: #{f.id}" # => 286859702 puts " Coordinates: #{f.geometry.as_text}" # => POINT (26.1025 44.4325) end # Query for ways (roads) - returns LineString geometries roads = Underpass::QL::Query.perform(bbox, 'way["highway"="primary"];') roads.each do |road| puts "#{road.properties[:name]}: #{road.geometry.geometry_type}" # => LineString end # Query for ways (buildings) - returns Polygon geometries buildings = Underpass::QL::Query.perform(bbox, 'way["building"="yes"];') buildings.each do |building| puts "#{building.properties[:name]}: #{building.geometry.geometry_type}" # => Polygon end # Query for relations (multipolygons) - returns MultiPolygon geometries lakes = Underpass::QL::Query.perform(bbox, 'relation["type"="multipolygon"]["water"="lake"];') lakes.each do |lake| puts "#{lake.properties[:name]}: #{lake.geometry.geometry_type}" # => MultiPolygon end ``` -------------------------------- ### Filter Underpass::Feature Objects with Underpass::Filter Source: https://context7.com/haiafara/underpass/llms.txt Demonstrates post-query filtering of Underpass::Feature objects using the Underpass::Filter class. It supports exact matches, multiple conditions (AND logic), array inclusion (OR logic), regex patterns, and rejection filters. Filters can also be chained for complex criteria. ```ruby require 'underpass' require 'rgeo' box = RGeo::Geographic.spherical_factory.parse_wkt( 'POLYGON ((26.08 44.42, 26.12 44.42, 26.12 44.45, 26.08 44.45, 26.08 44.42))' ) amenities = Underpass::QL::Query.perform(bbox, 'node["amenity"];') # Exact match restaurants = Underpass::Filter.new(amenities).where(amenity: 'restaurant') # Multiple conditions (AND) chinese_restaurants = Underpass::Filter.new(amenities).where( amenity: 'restaurant', cuisine: 'chinese' ) # Array inclusion (OR) food_places = Underpass::Filter.new(amenities).where( amenity: %w[restaurant cafe bar] ) # Regex pattern matching italian_places = Underpass::Filter.new(amenities).where(cuisine: /italian/i) # Rejection filter no_banks = Underpass::Filter.new(amenities).reject(amenity: 'bank') # Chaining filters restaurants_without_fast_food = Underpass::Filter.new( Underpass::Filter.new(amenities).where(amenity: 'restaurant') ).reject(cuisine: 'fast_food') ```