Created
June 11, 2021 01:04
-
-
Save Militoarg/e33a843ed4caed3a60561edb69d75f3d to your computer and use it in GitHub Desktop.
it looks to lat and lon coordinates to get maps without labels, just streets of zone around.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/python | |
# GoogleMapDownloader.py | |
# Created by Emilio Riquelme [[email protected]] | |
# | |
# A script which when given a longitude, latitude and zoom level downloads a | |
# high resolution google map | |
import urllib.request | |
from PIL import Image | |
import os | |
import math | |
from math import pi, log, tan, exp, atan, log2, floor | |
from pygeotile.tile import Tile | |
from pygeotile.point import Point | |
from PyQt5 import QtCore, QtWidgets, QtGui | |
import time | |
#C:\ProgramData\Anaconda3\Library\mingw-w64\bin | |
#C:\ProgramData\Anaconda3\Library\usr\bin | |
#C:\ProgramData\Anaconda3\Library\bin | |
class GoogleMapDownloader: | |
""" | |
A class which generates high resolution google maps images given | |
a longitude, latitude and zoom level | |
""" | |
def __init__(self, lat, lng, zoom=12): | |
""" | |
GoogleMapDownloader Constructor | |
Args: | |
lat: The latitude of the location required | |
lng: The longitude of the location required | |
zoom: The zoom level of the location required, ranges from 0 - 23 | |
defaults to 12 | |
""" | |
self._lat = float(lat) | |
self._lng = float(lng) | |
self._zoom = int(zoom) | |
my_path = os.path.abspath(os.path.dirname(__file__)) | |
self.relpath = os.path.join(my_path, "../../") | |
#self.relpath='../../' | |
self.ZOOM0_SIZE = 256 # Not 512 | |
self.proxy= {'https': 'https://177.92.20.182:46212', | |
'https': 'https://200.255.122.170:8080', | |
'https': 'https://80.187.140.26:8080' | |
} | |
#self.proxy=['socks5://Username:Password@IP1:20000', | |
# 'socks5://Username:Password@IP2:20000', | |
# 'socks5://Username:Password@IP3:20000', | |
# 'socks5://Username:Password@IP4:20000'] | |
self.kml = '''<?xml version="1.0" encoding="UTF-8"?> | |
<kml xmlns="http://www.opengis.net/kml/2.2"> | |
<Document> | |
<name>Clean Map:lat{}_lng{}</name> | |
<open>1</open> | |
<description>Google maps with no labels</description> | |
<Folder> | |
<name>Ground Overlays</name> | |
<visibility>1</visibility> | |
<description>Examples of ground overlays</description> | |
<GroundOverlay> | |
<name>Large-scale overlay on terrain</name> | |
<visibility>1</visibility> | |
<description>Overlay shows Mount Etna erupting on July 13th, 2001.</description> | |
<LookAt> | |
<longitude>{}</longitude> | |
<latitude>{}</latitude> | |
<altitude>0</altitude> | |
<heading>0</heading> | |
<tilt>0</tilt> | |
<range>1000</range> | |
</LookAt> | |
<Icon> | |
<href>{}</href> | |
</Icon> | |
<LatLonBox> | |
<north>{}</north> | |
<south>{}</south> | |
<east>{}</east> | |
<west>{}</west> | |
<rotation>0</rotation> | |
</LatLonBox> | |
</GroundOverlay> | |
</Folder> | |
</Document> | |
</kml> | |
''' | |
def getXY(self): | |
""" | |
Generates an X,Y tile coordinate based on the latitude, longitude | |
and zoom level | |
Returns: An X,Y tile coordinate | |
""" | |
tile_size = 256 | |
# Use a left shift to get the power of 2 | |
# i.e. a zoom level of 2 will have 2^2 = 4 tiles | |
numTiles = 1 << self._zoom | |
# Find the x_point given the longitude | |
point_x = (tile_size / 2 + self._lng * tile_size / 360.0) * numTiles // tile_size | |
# Convert the latitude to radians and take the sine | |
sin_y = math.sin(self._lat * (math.pi / 180.0)) | |
# Calulate the y coorindate | |
point_y = ((tile_size / 2) + 0.5 * math.log((1 + sin_y) / (1 - sin_y)) * -( | |
tile_size / (2 * math.pi))) * numTiles // tile_size | |
return int(point_x), int(point_y) | |
#obtiene lat y long a partir de punto x e y de la imagen | |
def getTileBounds(self,point_x,point_y,zoom): | |
# Use a left shift to get the power of 2 | |
# i.e. a zoom level of 2 will have 2^2 = 4 tiles | |
# get latitud longitud coordinates from tile bound | |
out = Tile.from_tms(point_x,point_y,zoom) | |
#separa en ambos puntos por latitud y longitud | |
return out.bounds | |
# Geo-coordinate in degrees => Pixel coordinate | |
def g2p(self,lat, lon, zoom): | |
return ( | |
# x | |
self.ZOOM0_SIZE * (2 ** zoom) * (1 + lon / 180) / 2, | |
# y | |
self.ZOOM0_SIZE / (2 * pi) * (2 ** zoom) * (pi - log(tan(pi / 4 * (1 + lat / 90)))) | |
) | |
# Pixel coordinate => geo-coordinate in degrees | |
def p2g(self,x, y, zoom): | |
return ( | |
# lat | |
(atan(exp(pi - y / self.ZOOM0_SIZE * (2 * pi) / (2 ** zoom))) / pi * 4 - 1) * 90, | |
# lon | |
(x / self.ZOOM0_SIZE * 2 / (2 ** zoom) - 1) * 180, | |
) | |
#crea kml archivo con coordenadas | |
def kmlPlaceMap(self,coords,filepath): | |
file='{}KML_map_lat{}_lng{}.kml'.format(self.relpath,self._lat,self._lng) | |
north,south,east,west = coords | |
with open(file,'w') as t: | |
t.write(self.kml.format(self._lat,self._lng,self._lng,self._lat,filepath,-north,-south,east,west)) | |
#genera imagen | |
def generateImage(self,mapPath,tileSize, **kwargs): | |
""" | |
Generates an image by stitching a number of google map tiles together. | |
Args: | |
start_x: The top-left x-tile coordinate | |
start_y: The top-left y-tile coordinate | |
tile_width: The number of tiles wide the image should be - | |
defaults to 5 | |
tile_height: The number of tiles high the image should be - | |
defaults to 5 | |
Returns: | |
A high-resolution Goole Map image. | |
""" | |
start_x = kwargs.get('start_x', None) | |
start_y = kwargs.get('start_y', None) | |
tile_width = kwargs.get('tile_width', tileSize) | |
tile_height = kwargs.get('tile_height', tileSize) | |
# Check that we have x and y tile coordinates | |
if start_x == None or start_y == None: | |
start_x, start_y = self.getXY() | |
# Determine the size of the image | |
width, height = 256 * tile_width, 256 * tile_height | |
# Create a new image of the size require | |
map_img = Image.new('RGB', (width, height)) | |
print(start_x,start_y,tile_width,tile_height,'x,y,wx,hy') | |
#print(self.g2p(self._lat,self._lng,self._zoom),'<-g2p') | |
#(x0,y0)=self.g2p(self._lat,self._lng,self._zoom) | |
coord = [] | |
for x in range(0, tile_width): | |
for y in range(0, tile_height): | |
xPos = start_x+x+1-(tile_width//2) | |
yPos = start_y+y+1-(tile_height//2) | |
url = 'https://mt0.google.com/vt?x=' + str(xPos) + '&y=' + str(yPos) + '&z=' + str(self._zoom)+'&apistyle=s.t%3A0%7Cs.e%3Al%7Cp.v%3Aoff' | |
#url = 'https://mt0.google.com/vt?lyrs=m&x=' + str(xPos) + '&y=' + str(yPos) + '&z=' + str(self._zoom)+'&apistyle=s.t%3A0%7Cs.e%3Al%7Cp.v%3Aoff' | |
current_tile = str(x) + '-' + str(y) | |
urllib.request.urlretrieve(url, current_tile) | |
#im = Image.open(r'D:\WIP\LEAN\001.png') | |
im = Image.open(current_tile) | |
map_img.paste(im, (x * 256, y * 256)) | |
coord.append(self.getTileBounds(xPos,yPos,17)) | |
#print(current_tile,x*256,y*256,start_x+x,start_y+y,'<-x,y tile') | |
os.remove(current_tile) | |
start_lat = [(x[0][0]) for x in coord] | |
start_lng = [(x[0][1]) for x in coord] | |
end_lat = [(x[1][0]) for x in coord] | |
end_lng = [(x[1][1]) for x in coord] | |
lat= start_lat+end_lat | |
lng= start_lng+end_lng | |
#lat Long box | |
#print(max(lat),'<-sur|', min(lat),'<-norte',max(lng),'<-este',min(lng),'<-oeste') | |
latLngBox = (min(lat),max(lat),max(lng),min(lng)) | |
#https://i.ibb.co/ZR9x7Yh/high-resolution-image01.png | |
self.kmlPlaceMap(latLngBox,mapPath) | |
return map_img | |
class MyWidget(QtWidgets.QWidget): | |
def __init__(self): | |
super(MyWidget,self).__init__() | |
my_path = os.path.abspath(os.path.dirname(__file__)) | |
self.relpath = os.path.join(my_path, "../../") | |
self.titleLabel = QtWidgets.QLabel('<font color=black>Answer these questions:</font>') | |
self.latLabel = QtWidgets.QLabel('<font color=red>What is the Latitude?</font>') | |
self.latLabel.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter) | |
self.latInput = QtWidgets.QLineEdit() | |
self.latInput.setFixedWidth(150) | |
self.latInput.setPlaceholderText('33.9956661333') | |
self.lngLabel = QtWidgets.QLabel('<font color=blue>What is the Longitude?</font>') | |
self.lngLabel.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter) | |
self.lngInput = QtWidgets.QLineEdit() | |
self.lngInput.setFixedWidth(150) | |
self.lngInput.setPlaceholderText('-120.5666661333') | |
self.zoomLabel = QtWidgets.QLabel('<font color=green>What is the map size?</font>') | |
self.zoomLabel.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter) | |
self.zoomInput = QtWidgets.QSpinBox() | |
self.zoomInput.setValue(8) | |
self.zoomInput.setMinimum(2) | |
self.zoomInput.setMaximum(16) | |
self.zoomInput.setFixedWidth(50) | |
self.tilesizeLabel = QtWidgets.QLabel('(2048x2048 pixels)') | |
self.zoomLabel.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter) | |
self.spinLayout = QtWidgets.QHBoxLayout() | |
self.spinLayout.addWidget(self.zoomInput) | |
self.spinLayout.addWidget(self.tilesizeLabel) | |
self.mapButton = QtWidgets.QPushButton('Generate clean map') | |
self.mapButton.setFixedWidth(150) | |
self.outLabel = QtWidgets.QLabel('<font color=black>Creating clean map...</font>') | |
self.outLabel.setAlignment(QtCore.Qt.AlignRight) | |
self.outLabel.hide() | |
#conexion | |
self.mapButton.clicked.connect(self.generateMap) | |
self.mapButton.clicked.connect(self.outLabel.show) | |
self.zoomInput.valueChanged.connect(self.showTile) | |
#layouts | |
self.parentLayout = QtWidgets.QGridLayout() | |
self.parentLayout.addWidget(self.titleLabel,0,1) | |
self.parentLayout.addWidget(self.latLabel,1,0) | |
self.parentLayout.addWidget(self.latInput,1,1) | |
self.parentLayout.addWidget(self.lngLabel,2,0) | |
self.parentLayout.addWidget(self.lngInput,2,1) | |
self.parentLayout.addWidget(self.zoomLabel,3,0) | |
#self.parentLayout.addWidget(self.zoomInput,3,1) | |
self.parentLayout.addLayout(self.spinLayout,3,1) | |
self.parentLayout.addWidget(self.mapButton,4,1) | |
self.parentLayout.addWidget(self.outLabel,4,0) | |
self.setLayout(self.parentLayout) | |
self.setWindowTitle('CleanMap Generator 1.5.7') | |
self.setMinimumWidth(320) | |
#muestra tilesize | |
def showTile(self): | |
val=256*self.zoomInput.value() | |
self.tilesizeLabel.setText('({}x{} pixels)'.format(val,val)) | |
#genera el mapa | |
def generateMap(self): | |
self.outLabel.setText('Creating clean map...') | |
Latitude = self.latInput.text() | |
Longitude = self.lngInput.text() | |
zoom= 17 | |
if len(Latitude) ==0 or len(Longitude)==0: | |
self.outLabel.setText('No inputs!') | |
return | |
print(Latitude,Longitude,zoom,'<- latlongzoom') | |
gmd = GoogleMapDownloader(Latitude,Longitude,zoom) | |
#33.9827179,-118.2411244,927 | |
#print("The tile coorindates are {}".format(gmd.getXY())) | |
#0,5131578947368421 | |
# Get the high resolution image | |
#img = gmd.generateImage() | |
#print(lat,lon,'<-lat y long puntual') | |
filePath="{}high_resolution_image_lat{}_lng{}.png".format(self.relpath,Latitude,Longitude) | |
try: | |
# Get the high resolution image | |
self.outLabel.setText('Creating clean map...') | |
time.sleep(0.1) | |
img = gmd.generateImage(filePath,self.zoomInput.value()) | |
print(Latitude,Longitude,'<-lat y long puntual') | |
except IOError: | |
print("Could not generate the image - try adjusting the zoom level and checking your coordinates") | |
self.outLabel.setText('Could not generate the image') | |
else: | |
# Save the image to disk | |
img.save("{}high_resolution_image_lat{}_lng{}.png".format(self.relpath,Latitude,Longitude)) | |
print("The map has successfully been created") | |
self.outLabel.setText('The map has successfully been created!') | |
def main(): | |
# Create a new instance of GoogleMap Downloader | |
#gmd = GoogleMapDownloader(51.5171, 0.1062, 13) | |
#lat=33.9827179 | |
#lon=-118.2411244 | |
lat=33.982348699999996 | |
lon=-118.24081859999998 | |
app = QtWidgets.QApplication([]) | |
form = MyWidget() | |
form.show() | |
app.exec_() | |
#sys.exit(app.exec_()) | |
if __name__ == '__main__': main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment