# needs satellite img with equal padding in opposite directions # will use google map static api, 8k character limit of request URL # *how map is generated is, given the img size, it tries to find the right zoom to fit the points inside the size with greater than 0 padding # *one scale is for 640x640 size, 10m=1px at zoom=14; 1.1m=1px at zoom=17 # will have 10% padding in the img each side; by setting size accordingly # will call api with these parameters - key, size, maptype, format, path from PIL import Image # from haversine import haversine, Unit from geopy.distance import geodesic import requests import base64 import shutil import math # lat = 23.108696466469407 def getDistBwPoints(p1, p2): # hsDist = haversine(p1, p2, unit=Unit.METERS) gpDist = geodesic(p1, p2).m return gpDist def mPerPxByZoom(zoom, lat): return 156543.03392 * math.cos(lat * math.pi / 180) / math.pow(2, zoom) def getZoomLevel(len, lat, zoom=14): len640 = mPerPxByZoom(zoom, lat) * 640 print("len", len) if len640 > len: while len640 > len: zoom += 1 len640 = mPerPxByZoom(zoom, lat) * 640 # print(zoom, len640) return zoom - 1, len640 * 2 / 640 else: while len640 < len: zoom -= 1 len640 = mPerPxByZoom(zoom, lat) * 640 # print(zoom, len640) return zoom, len640 / 640 def getFieldMapImg(points, fieldMainLats, outPath="fieldMap.jpg", weight=0): """Downloads the field map img from google static map api ; First calculates right dimensions for the img ; Later saves it to outPath RETURNS - dimension tuple of (width, height, widthPad, heightPad)""" # returns tuple of widthPx, heightPx, widthPad, heightPad maxLat = fieldMainLats["maxLat"] minLat = fieldMainLats["minLat"] maxLng = fieldMainLats["maxLng"] minLng = fieldMainLats["minLng"] centerLat = fieldMainLats["centerLat"] centerLng = fieldMainLats["centerLng"] # w-h in meters width2 = getDistBwPoints((centerLat, minLng), (centerLat, maxLng)) height2 = getDistBwPoints((maxLat, centerLng), (minLat, centerLng)) print(width2, height2) # return # get final img size, zoom, padding % # will have padding = 10%, minPad 15m each side; aspect ratio range = 0.5 or 2 width = width2 height = height2 aspectRatio = width / height print("aspect: ", aspectRatio) if aspectRatio < 0.5: width = 0.5 * height elif aspectRatio > 2: height = 0.5 * width print("new w-h: ", width, height) # calculate seperate padding for width, height minPadDis = 15 # in m widthPadPrcnt = 0.1 # one side if width == width2: minWidthPad10 = width * widthPadPrcnt if minWidthPad10 < minPadDis: widthPadPrcnt = minPadDis / width else: extraPad = (width - width2) / 2 if extraPad < minPadDis: widthPadPrcnt = (minPadDis - extraPad) / width heightPadPrcnt = 0.1 if height == height2: minHeightPad10 = height * heightPadPrcnt if minHeightPad10 < minPadDis: heightPadPrcnt = minPadDis / height else: extraPad = (height - height2) / 2 if extraPad < minPadDis: heightPadPrcnt = (minPadDis - extraPad) / height # isHeightBigger = height>width # minPadBy10 = (width2 if isHeightBigger else height2)*padPrcnt # if minPadBy10<15: # padPrcnt = 15/(width2 if isHeightBigger else height2) # calculate zoom level; need to check at which zoom 640px don't accomodate biggerLen and use one less zoom pWidth = width * (1 + 2 * widthPadPrcnt) # with padding pHeight = height * (1 + 2 * heightPadPrcnt) biggerLen = max(pWidth, pHeight) zoom, mPerPx = getZoomLevel(biggerLen, maxLat) finalWidth = pWidth / mPerPx # the pixel values finalHeight = pHeight / mPerPx print(finalWidth, finalHeight, zoom, mPerPx, widthPadPrcnt, heightPadPrcnt) # return # isMoreThan640 = biggerLen > 640 # # preferrable size is 640x640; rough cal- with padding = 480x516; (now we need to make larger one under 640 by dividing by 2) # # for >640 values, do divide by 640, log base2 and take ceil; then divide main values by 2 power that value # # for <640 values, do divide 640 by the number, log base2 and take floor, then multiply the number by 2 power that value # factor = math.pow(2, math.ceil(math.log(biggerLen/640, 2)) if isMoreThan640 else math.floor(math.log(640/biggerLen, 2))) # finalWidth = (width/factor if isMoreThan640 else width*factor)/10*1.2 # finalHeight = (height/factor if isMoreThan640 else height*factor)/10*1.2 # print(finalWidth, finalHeight, factor) path = "color:0xff0000ff|weight:%s|" % (weight) pointsKeys = list(points.keys()) pointsKeys.sort() for pointKey in pointsKeys: pointInfo = points[pointKey] path += "%s,%s|" % (pointInfo["Latitude"], pointInfo["Longitude"]) pointInfo = points[pointsKeys[0]] path += "%s,%s" % (pointInfo["Latitude"], pointInfo["Longitude"]) # print("path: ", path) params = { "key": "AIzaSyDnM_35WfYwhJmTSPxyyiMIcYte65mPitc", "format": "jpg", "maptype": "satellite", "path": path, "zoom": zoom, "size": "%sx%s" % (round(finalWidth), round(finalHeight)), } # print(params) result = requests.get( "https://maps.googleapis.com/maps/api/staticmap", params=params, stream=True ) if result.status_code == 200: with open(outPath, "wb") as f: result.raw.decode_content = True shutil.copyfileobj(result.raw, f) return { "width": finalWidth, "height": finalHeight, "zoom": zoom, "horiPadPer": ((pWidth - width2) / 2) / width2, "verPadPer": ((pHeight - height2) / 2) / height2, } # return ( # finalWidth, # finalHeight, # ((pWidth - width2) / 2) / width2, # ((pHeight - height2) / 2) / height2, # ) else: return None def checkDownloadProcess(): read_file = open("papa.jpeg", "rb") data = read_file.read() b64 = base64.b64encode(data) print(b64[:100] + b64[-100:]) # Save file decode_b64 = base64.b64decode(b64) out_file = open("papa_again.jpeg", "wb") out_file.write(decode_b64) # checkDownloadProcess() # points = { # "a": {"Latitude": 23.108696466469407, "Longitude": 76.94931373000145}, # "P_1": {"Latitude": 23.108788361955472, "Longitude": 76.94893788546324}, # "P_2": {"Latitude": 23.107457721514155, "Longitude": 76.94890134036541}, # "P_3": {"Latitude": 23.10740036336785, "Longitude": 76.94929964840412}, # "P_4": {"Latitude": 23.108686598494, "Longitude": 76.94933719933033}, # } # points = { # "P_0": { # "Latitude": 17.0107105, # "Longitude": 81.1960322 # }, # "P_1": { # "Latitude": 17.0110342, # "Longitude": 81.1955496 # }, # "P_2": { # "Latitude": 17.0095997, # "Longitude": 81.1952624 # }, # "P_3": { # "Latitude": 17.0099828, # "Longitude": 81.1960749 # }, # "P_4": { # "Latitude": 17.0099926, # "Longitude": 81.1961406 # } # } # maxLat = 23.108788361955472 # minLat = 23.10740036336785 # centerLat = maxLat # maxLng = 76.94933719933033 # minLng = 76.94890134036541 # centerLng = maxLng # 17.01026396, 81.19581194, 17.0095997, 17.0110342, 81.1952624, 81.1961406 # maxLat = 17.0110342 # minLat = 17.0095997 # maxLng = 81.1961406 # minLng = 81.1952624 # centerLat = 17.01026396 # centerLng = 81.19581194 # fieldMainLats = { # 'maxLng': maxLng, # 'minLat': minLat, # 'minLng': minLng, # 'maxLat': maxLat, # 'centerLat': centerLat, # 'centerLng': centerLng, # } # dimens = getFieldMapImg(points, fieldMainLats, weight=3) # print(dimens) # for i in range(10): # mPerPx = mPerPxByZoom(i+10, lat) # print(i+10, mPerPx, mPerPx*200)