Umkreissuche: Lat/Long und der Radius

Aufgabenstellung: Ich weiß, wo ich mich befinde (Lat / Long, ist ja aus den Smartphones easy herauszubekommen) und habe einen Radius in km, in dem ich POI’s mit der Open Streemap API suchen möchte.

Problem: Die OSM API bietet keine (mir bekannte) Möglichkeit, um meinen aktuellen Standort herum eine Radius-Suche in km auszuführen, sondern hätte gern eine Bounding Box angegeben, die die Ecken der Box als Geo-Koordinaten angibt – siehe hier:
http://www.overpass-api.de/api/xapi?node[bbox=8.62,49.85,8.68,49.89][amenity=fast_food|pub][@meta]

Dabei spezifiziert der Parameter bbox die Lat/Long-Koordinaten in der Reihenfolge links, oben, rechts, unten.

Dazu erstmal zum Verständnis:

  • Der Breitengrad (Latitude) gibt die Nord-Südachse an, „50“ ist nördlicher als „49“
  • Der Längengrad (Longitude) gibt die Ost-Westachse an, „5“ ist westlicher als „6“

Berechnung

Nun haben wir also den eigenen Standort, wissen über Lat/Long Bescheid und wollen die Eckpunkte für die oben angesprochene Bounding Box errechnen. Aufbauend auf diesem Artikel habe ich folgende PHP-Funktion gebaut:

$lat = 49.869059; $lon = 8.645318; $radius = 1.5;  /**  * lat (breitengrad = nord -> sued): 50 ist noerdlicher als 49  * lon (längengrad = west -> ost): 5 ist westlicher als 6    */ function getBoundingBox($lat, $lon, $radius) { 	$earth_radius = 6371; 	$maxLat = $lat + rad2deg($radius/$earth_radius); 	$minLat = $lat - rad2deg($radius/$earth_radius); 	$maxLon = $lon + rad2deg($radius/$earth_radius/cos(deg2rad($lat))); 	$minLon = $lon - rad2deg($radius/$earth_radius/cos(deg2rad($lat))); 	 	return array 	( 		"center" => array("lat" => $lat, "lon" => $lon), 		"nw" => array("lat" => $maxLat, "lon" => $minLon),  		"ne" => array("lat" => $maxLat, "lon" => $maxLon),  		"sw" => array("lat" => $minLat, "lon" => $minLon), 		"se" => array("lat" => $minLat, "lon" => $maxLon) 	); }  $coords = getBoundingBox($lat, $lon, $radius);  print_r($coords); /*  Array (     [center] => Array         (             [lat] => 49.869059             [lon] => 8.645318         )      [nw] => Array         (             [lat] => 49.882548824089             [lon] => 8.6243885076019         )      [ne] => Array         (             [lat] => 49.882548824089             [lon] => 8.6662474923981         )      [sw] => Array         (             [lat] => 49.855569175911             [lon] => 8.6243885076019         )      [se] => Array         (             [lat] => 49.855569175911             [lon] => 8.6662474923981         )  ) */ 

Somit haben wir schonmal die Eckpunkte für den Radius 1,5km um unseren Mittelpunkt ausgerechnet.

Darstellen der Eckpunkte auf einer Google Map

Zur Verifikation der errechneten Eckpunkte muss Quick&Dirty eine googlemap herhalten (inspiriert von hier).

<!DOCTYPE html> <html> <head> <link rel="stylesheet" href="http://code.google.com/apis/maps/documentation/javascript/examples/default.css" /> <script src="http://maps.googleapis.com/maps/api/js?sensor=false"></script> <script> 	function init()  	{ 		var markers = [];  		<?php 		foreach ($coords as $desc => $latlong) 		{ 		?> 			markers.push({ 				'lat' : <?php echo $latlong['lat']; ?>,  				'lon' : <?php echo $latlong['lon']; ?>, 				'desc' : "<?php echo $desc; ?>" 			}); 		<?php 		} 		?>  		var map = new google.maps.Map(document.getElementById("map_canvas"), { 			zoom: 11, 			center: new google.maps.LatLng(<?php echo $coords['center']['lat'] . "," . $coords['center']['lon']; ?>), 			mapTypeId: google.maps.MapTypeId.ROADMAP 		});  		for (var i = 0; i < markers.length; i++) { 			new google.maps.Marker({ 				position: new google.maps.LatLng(markers[i].lat, markers[i].lon),  				map: map, 				title: markers[i].desc 			});    		} 	}      window.onload = init; </script> </head> <body> 	<div id="map_canvas"></div> </body> </html> 

radius

radius

Sieht doch gut aus. Somit haben wir unsere Bounding Box Koordinaten auch visuell dargestellt und können die OSM API damit füttern.

Und hier nochmal der komplette Code:

<?php $lat = 49.869059; $lon = 8.645318; $radius = 1.5;  /**  * lat (breitengrad = nord -> sued): 50 ist noerdlicher als 49  * lon (längengrad = west -> ost): 5 ist westlicher als 6    */ function getBoundingBox($lat, $lon, $radius) { 	$earth_radius = 6371; 	$maxLat = $lat + rad2deg($radius/$earth_radius); 	$minLat = $lat - rad2deg($radius/$earth_radius); 	$maxLon = $lon + rad2deg($radius/$earth_radius/cos(deg2rad($lat))); 	$minLon = $lon - rad2deg($radius/$earth_radius/cos(deg2rad($lat))); 	 	return array 	( 		"center" => array("lat" => $lat, "lon" => $lon), 		"nw" => array("lat" => $maxLat, "lon" => $minLon),  		"ne" => array("lat" => $maxLat, "lon" => $maxLon),  		"sw" => array("lat" => $minLat, "lon" => $minLon), 		"se" => array("lat" => $minLat, "lon" => $maxLon) 	); }  $coords = getBoundingBox($lat, $lon, $radius); ?>  <!DOCTYPE html> <html> <head> <link rel="stylesheet" href="http://code.google.com/apis/maps/documentation/javascript/examples/default.css" /> <script src="http://maps.googleapis.com/maps/api/js?sensor=false"></script> <script> 	function init()  	{ 		var markers = [];  		<?php 		foreach ($coords as $desc => $latlong) 		{ 		?> 			markers.push({ 				'lat' : <?php echo $latlong['lat']; ?>,  				'lon' : <?php echo $latlong['lon']; ?>, 				'desc' : "<?php echo $desc; ?>" 			}); 		<?php 		} 		?>  		var map = new google.maps.Map(document.getElementById("map_canvas"), { 			zoom: 11, 			center: new google.maps.LatLng(<?php echo $coords['center']['lat'] . "," . $coords['center']['lon']; ?>), 			mapTypeId: google.maps.MapTypeId.ROADMAP 		});  		for (var i = 0; i < markers.length; i++) { 			new google.maps.Marker({ 				position: new google.maps.LatLng(markers[i].lat, markers[i].lon),  				map: map, 				title: markers[i].desc 			});    		} 	}      window.onload = init; </script> </head> <body> 	<div id="map_canvas"></div> </body> </html>