Search code examples
openstreetmap

Calculate bounding box for OpenStreetMap


Is possible to get bounding box from coordinates (latitude, longitude), zoom level and size (screen)? I found only calculating bounding box from tile. I need it, because OpenStreetMap accept only bbox in export mode. I dont have any experience with this, so I will be glad for any advice. Thanks.

Edit:

Sorry, I was describe it wrong. I write something like this:

(pseudocode) `

x = getX(longitude, zoom); //X Tile - return 41870
y = getY(latitude, zoom); //Y Tile - return 22226
north = getXToLongitude(x, zoom); //return 49.998779 
south = getXToLongitude(x + 1, zoom); //return 50.004272
west = getYToLatitude(y, zoom); //return 49.997078 
east = getYToLatitude(y + 1, zoom); //return 50.000609

`

But this is very inaccurate and and shifts the center of the 100 m.


Solution

  • Yes, it is. I've had a similar problem, so I've written it up. Like this:

    use Math::Trig;
    
    sub getTileNumber {
        my ($lat,$lon,$zoom) = @_;
        my $xtile = int( ($lon+180)/360 * 2**$zoom ) ;
        my $ytile = int( (1 - log(tan(deg2rad($lat)) + sec(deg2rad($lat)))/pi)/2 * 2**$zoom ) ;
        return ($xtile, $ytile);
    }
    
    sub getLonLat {
        my ($xtile, $ytile, $zoom) = @_;
        my $n = 2 ** $zoom;
        my $lon_deg = $xtile / $n * 360.0 - 180.0;
        my $lat_deg = rad2deg(atan(sinh(pi * (1 - 2 * $ytile / $n))));
        return ($lon_deg, $lat_deg);
    }
    
    # convert from permalink OSM format like:
    # http://www.openstreetmap.org/?lat=43.731049999999996&lon=15.79375&zoom=13&layers=M
    # to OSM "Export" iframe embedded bbox format like:
    # http://www.openstreetmap.org/export/embed.html?bbox=15.7444,43.708,15.8431,43.7541&layer=mapnik
    
    sub LonLat_to_bbox {
        my ($lat, $lon, $zoom) = @_;
    
        my $width = 425; my $height = 350;  # note: must modify this to match your embed map width/height in pixels
        my $tile_size = 256;
    
        my ($xtile, $ytile) = getTileNumber ($lat, $lon, $zoom);
    
        my $xtile_s = ($xtile * $tile_size - $width/2) / $tile_size;
        my $ytile_s = ($ytile * $tile_size - $height/2) / $tile_size;
        my $xtile_e = ($xtile * $tile_size + $width/2) / $tile_size;
        my $ytile_e = ($ytile * $tile_size + $height/2) / $tile_size;
    
        my ($lon_s, $lat_s) = getLonLat($xtile_s, $ytile_s, $zoom);
        my ($lon_e, $lat_e) = getLonLat($xtile_e, $ytile_e, $zoom);
    
        my $bbox = "$lon_s,$lat_s,$lon_e,$lat_e";
        return $bbox;
    }
    

    I've also added this info to OSM wiki, so it will be easier to find in the future...