pythonmapboxmapbox-static-maps

Convert North, South latutudes, East, West longitudes and Zoom to Center and Size in mapbox


Since my question Convert North, South, East, West and Zoom to Center and Size in mapbox was closed yesterday, and I've found the answer today. I'm creating a new question.

As stated in the previous question. I want to create an image on mapbox with which is bounded by a north latitude, east longitude, south latitude, west longitude and zoom factor. The result should be an width, height, center latitude and center longitude.


Solution

  • On the Web Mercator Wikipedia page you can find the formulas to convert latitude and longitude to pixel coordinates: https://en.wikipedia.org/wiki/Web_Mercator_projection

    To get the with: substract the pixel coordinates from the east and west longitudes, to get the height: substract pixel coordinates from the south and north latitudes.

    To get the center coordinates calculate the latitude and longitude from the center of the pixel coordinates.

    Below you find python code that generates a mapbox url

    import math
    
    def zoom_factor(zoom):
        return 256/math.pi * 2**zoom
    
    def latitude_to_pixel(latitude, zoom):
        return zoom_factor(zoom) * (math.pi - math.log(math.tan((math.pi/2 + math.radians(latitude))/2)))
    
    def longitude_to_pixel(longitude, zoom):
        return zoom_factor(zoom) * (math.radians(longitude) + math.pi)
    
    def pixel_to_latitude(y, zoom):
        #return math.degrees(2 * math.atan(math.exp(y / zoom_factor(zoom) - math.pi)) - math.pi/2)
        return math.degrees(2 * math.atan(math.exp(math.pi - y / zoom_factor(zoom))) - math.pi/2)
    
    def pixel_to_longitude(x, zoom):
        return math.degrees(x / zoom_factor(zoom) - math.pi)
    
    def mapbox_dimensions(south, north, west, east, zoom):
        top = math.floor(latitude_to_pixel(north, zoom))
        bottom = math.ceil(latitude_to_pixel(south, zoom))
        left = math.floor(longitude_to_pixel(west, zoom))
        right = math.ceil(longitude_to_pixel(east, zoom))
        return {
            'width': right - left,
            'height': bottom - top,
            'latitude': pixel_to_latitude((top+bottom)/2, zoom),
            'longitude': pixel_to_longitude((left+right)/2, zoom),
            'zoom': zoom,
    }
    
    dimensions = mapbox_dimensions(49, 54, 2, 8, 6)
    dimensions['style'] = 'streets-v11'
    dimensions['token'] = 'Your token'
    
    print('https://api.mapbox.com/styles/v1/mapbox/%(style)s/static/%(longitude)s,%(latitude)s,%(zoom)s,0,0/%(width)sx%(height)s?access_token=%(token)s' % dimensions)