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:

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
$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).

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
<!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:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
<?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>

Weitere Posts:

Dieser Beitrag wurde unter php, webdev veröffentlicht. Setze ein Lesezeichen auf den Permalink.

Eine Antwort auf Umkreissuche: Lat/Long und der Radius

  1. Pingback: Open Streetmap API Tutorial: Umkreissuche | davblog: webdev and stuff

Hinterlasse eine Antwort

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind markiert *

*

Du kannst folgende HTML-Tags benutzen: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>