--- name: overpass_nearby_pois kind: function lang: kt domain: infra version: "1.0.0" purity: impure signature: "fun overpassNearbyPois(lat: Double, lon: Double, radiusM: Int = 500, categories: List? = null): List" description: "Consulta la Overpass API (OpenStreetMap) para obtener POIs cercanos a una coordenada. Soporta 16 categorias mapeadas a tags OSM (amenity, tourism, historic, leisure, shop). Sin dependencias externas: solo Android SDK (HttpURLConnection + org.json)." tags: [overpass, openstreetmap, osm, poi, geospatial, location, android, infra] uses_functions: [] uses_types: [] returns: [] returns_optional: false error_type: "error_go_core" imports: - "org.json.JSONObject" - "org.json.JSONArray" - "java.net.HttpURLConnection" - "java.net.URL" - "java.net.URLEncoder" tested: false tests: [] test_file_path: "" file_path: "kotlin/functions/infra/overpass_nearby_pois.kt" params: - name: lat desc: "Latitud del punto central en WGS84 (ej: 40.4168 para Madrid)" - name: lon desc: "Longitud del punto central en WGS84 (ej: -3.7038 para Madrid)" - name: radiusM desc: "Radio de busqueda en metros. Default 500. Valores grandes aumentan el tiempo de respuesta." - name: categories desc: "Lista de categorias a filtrar: restaurant, cafe, bar, museum, monument, park, library, theatre, cinema, gallery, historic, tourism, shop, hotel, pharmacy, hospital. Null devuelve todas." output: "Lista de POI con id OSM, coordenadas (lat/lon), nombre, categoria y mapa completo de tags OSM. Lanza RuntimeException si la API devuelve error HTTP o la respuesta no es JSON valido." --- ## Ejemplo ```kotlin // Restaurantes y museos en un radio de 300 metros val pois = overpassNearbyPois( lat = 40.4168, lon = -3.7038, radiusM = 300, categories = listOf("restaurant", "museum") ) pois.forEach { poi -> println("${poi.name} (${poi.category}) — lat=${poi.lat}, lon=${poi.lon}") } // Todos los POIs en 500 metros (null = todas las categorias) val all = overpassNearbyPois(lat = 48.8566, lon = 2.3522) println("Paris: ${all.size} POIs encontrados") ``` ## Categorias soportadas | Categoria | Tag OSM | |--------------|----------------------| | restaurant | amenity=restaurant | | cafe | amenity=cafe | | bar | amenity=bar | | museum | tourism=museum | | monument | historic=monument | | park | leisure=park | | library | amenity=library | | theatre | amenity=theatre | | cinema | amenity=cinema | | gallery | tourism=gallery | | historic | historic (wildcard) | | tourism | tourism (wildcard) | | shop | shop (wildcard) | | hotel | tourism=hotel | | pharmacy | amenity=pharmacy | | hospital | amenity=hospital | ## Query Overpass QL generada ``` [timeout:10][out:json]; ( node["amenity"="restaurant"](around:500,40.4168,-3.7038); node["tourism"="museum"](around:500,40.4168,-3.7038); ); out body; ``` ## Notas - Usa `java.net.HttpURLConnection` con POST y `data=`. - Timeouts: 10 segundos de conexion y lectura. La query QL tambien declara `[timeout:10]`. - El tipo `POI` se define en el mismo archivo como `data class`. - El mapa `tags` contiene todos los tags OSM del nodo, no solo el de la categoria. - Si un nodo no tiene tag `name`, el fallback es la categoria y luego "Unknown". - Las categorias wildcard (historic, tourism, shop) usan `node["key"](around:...)` sin valor. - Lanza `RuntimeException` en caso de categorias invalidas, error HTTP, o JSON malformado. - Compatible con Android SDK >= 19 (API level 19 tiene org.json integrado). ---