Geographic Information Systems Asked by dsv on December 23, 2020
I am trying to draw a polygon representing the GeoJSON on top of the image I get from a map returned by Mapbox. If I pass in the GeoJSON in the Mapbox REST API URL, I get the following image.
.
But I want to draw the polygon manually using PIL as there is a size 8kb restriction for Mapbox API (https://docs.mapbox.com/api/maps/static-images/#overlay-options).
If I just get the map and draw the image using the following code, my polygon seems to be in the correct shape but too small. Can someone point me in the right direction on how to get the polygon size correct?
def draw(self, mapbox_image, zoom, **kwargs) -> None:
geometries = get_geometries(kwargs['geojson'])
left_x = kwargs['left_x']
top_y = kwargs['top_y']
actual_x_padding = kwargs['actual_x_padding']
actual_y_padding = kwargs['actual_y_padding']
draw = ImageDraw.Draw(mapbox_image)
for geometry in geometries:
for coordinates in geometry['coordinates']:
polygon = [( actual_x_padding+ (longitude_to_x(coordinate[0], zoom ) - left_x),
(actual_y_padding +latitude_to_y(coordinate[1], zoom ) - top_y)) for coordinate in
coordinates]
draw.polygon(polygon, fill=None, outline="blue")
##This is how the parameters are calculated before passing in to the function
zoom = get_required_zoom(extent_rectangle_lat_long, IMAGE_WIDTH, IMAGE_HEIGHT, IMAGE_PADDING)
left_x = longitude_to_x(extent_rectangle_lat_long[0], zoom)
right_x = longitude_to_x(extent_rectangle_lat_long[2], zoom)
top_y = latitude_to_y(extent_rectangle_lat_long[3], zoom)
bottom_y = latitude_to_y(extent_rectangle_lat_long[1], zoom)
centre_x = left_x + ((right_x - left_x) / 2)
centre_y = top_y + ((bottom_y - top_y) / 2)
centre_longitude = x_to_longitude(centre_x, zoom)
centre_latitude = y_to_latitude(centre_y, zoom)
actual_x_padding = 2 * (longitude_to_x(extent_rectangle_lat_long[0], zoom) - image_left_x)
actual_y_padding = 2 * (latitude_to_y(extent_rectangle_lat_long[3], zoom) - image_top_y)
I use the calculations given in MapBox or Google Maps Static API: Extent or bounding box of image? to for the conversion.
def latitude_to_y(latitude_degrees, zoom):
pi_by_4 = math.pi / 4
latitude_radians = math.radians(latitude_degrees)
return (128 / math.pi) * math.pow(2, zoom) * (
math.pi - math.log(math.tan(pi_by_4 + (latitude_radians / 2)), math.e))
def longitude_to_x(longitude_degrees, zoom):
longitude_radians = math.radians(longitude_degrees)
return (128 / math.pi) * math.pow(2, zoom) * (longitude_radians + math.pi)
Okay, I managed to reproduce the same result as MapBox by introducing magnify method.. It is working for all scenarios of GeoJSON I used. Not sure why I had to magnify/zoom though.
def draw(self, mapbox_image, zoom, **kwargs) -> None:
geometries = get_geometries(kwargs['geojson'])
left_x = kwargs['left_x']
top_y = kwargs['top_y']
actual_x_padding = kwargs['actual_x_padding']
actual_y_padding = kwargs['actual_y_padding']
draw = ImageDraw.Draw(mapbox_image)
for geometry in geometries:
for coordinates in geometry['coordinates']:
polygon = [(self.magnify(longitude_to_x(coordinate[0], zoom) - left_x, 100),
self.magnify(latitude_to_y(coordinate[1], zoom) - top_y, 100)) for coordinate in
coordinates]
draw.polygon(polygon, fill=None, outline="blue")
def magnify(self, value, magnification):
return value + (value * magnification) / 100
Answered by dsv on December 23, 2020
Get help from others!
Recent Questions
Recent Answers
© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP