From bb8ed586e278eaa18b1861a0949afa53a743c876 Mon Sep 17 00:00:00 2001 From: Chris Pham Date: Thu, 18 Jan 2018 10:37:41 -0800 Subject: [PATCH 01/28] Make Mapping Core (mapping.py) --- ground_station/resources/core/mapping.py | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 ground_station/resources/core/mapping.py diff --git a/ground_station/resources/core/mapping.py b/ground_station/resources/core/mapping.py new file mode 100644 index 0000000..e69de29 From 47942ffd1dcc2b3a1e29776d00a005f5a4247ea3 Mon Sep 17 00:00:00 2001 From: Chris Pham Date: Thu, 18 Jan 2018 10:40:47 -0800 Subject: [PATCH 02/28] Added Imports --- ground_station/resources/core/mapping.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/ground_station/resources/core/mapping.py b/ground_station/resources/core/mapping.py index e69de29..d35bfbf 100644 --- a/ground_station/resources/core/mapping.py +++ b/ground_station/resources/core/mapping.py @@ -0,0 +1,10 @@ +##################################### +# Imports +##################################### +# Python native imports +import math +import urllib +import PIL.Image +from io import StringIO, BytesIO +import os +import time \ No newline at end of file From c8c8f857cd2de7d01a5c790a22ac643a6b962436 Mon Sep 17 00:00:00 2001 From: Chris Pham Date: Thu, 18 Jan 2018 10:47:56 -0800 Subject: [PATCH 03/28] Add Constants --- ground_station/resources/core/mapping.py | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/ground_station/resources/core/mapping.py b/ground_station/resources/core/mapping.py index d35bfbf..cae06d2 100644 --- a/ground_station/resources/core/mapping.py +++ b/ground_station/resources/core/mapping.py @@ -7,4 +7,20 @@ import urllib import PIL.Image from io import StringIO, BytesIO import os -import time \ No newline at end of file +import time + +##################################### +# Constants +##################################### +_KEY = + +# Number of pixels in half the earth's circumference at zoom = 21 +_EARTHPIX = 268435456 +# Number of decimal places for rounding coordinates +_DEGREE_PRECISION = 4 +# Larget tile we can grab without paying +_TILESIZE = 640 +# Fastest rate at which we can download tiles without paying +_GRABRATE = 4 +# Pixel Radius of Earth for calculations +_pixrad = _EARTHPIX / math.pi \ No newline at end of file From a9f36af40d4c3a00bb2336852d0db329f3b5905e Mon Sep 17 00:00:00 2001 From: Chris Pham Date: Thu, 18 Jan 2018 10:53:39 -0800 Subject: [PATCH 04/28] Read key from file --- ground_station/resources/core/mapping.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/ground_station/resources/core/mapping.py b/ground_station/resources/core/mapping.py index cae06d2..8a9531d 100644 --- a/ground_station/resources/core/mapping.py +++ b/ground_station/resources/core/mapping.py @@ -12,7 +12,9 @@ import time ##################################### # Constants ##################################### -_KEY = +fp = open('key', w) +_KEY = fp.read().rstrip() +fp.close() # Number of pixels in half the earth's circumference at zoom = 21 _EARTHPIX = 268435456 From 7e593097eab330b71a54b56251a1bea11e31a72c Mon Sep 17 00:00:00 2001 From: Chris Pham Date: Thu, 18 Jan 2018 10:55:42 -0800 Subject: [PATCH 05/28] Made apikey file, and fixed open error --- ground_station/resources/core/key | 1 + ground_station/resources/core/mapping.py | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) create mode 100644 ground_station/resources/core/key diff --git a/ground_station/resources/core/key b/ground_station/resources/core/key new file mode 100644 index 0000000..4e51d9a --- /dev/null +++ b/ground_station/resources/core/key @@ -0,0 +1 @@ +AIzaSyAFjAWMwQauf2Dy5KteOuT8KexfMjOCIS8 \ No newline at end of file diff --git a/ground_station/resources/core/mapping.py b/ground_station/resources/core/mapping.py index 8a9531d..48fb7a4 100644 --- a/ground_station/resources/core/mapping.py +++ b/ground_station/resources/core/mapping.py @@ -12,7 +12,7 @@ import time ##################################### # Constants ##################################### -fp = open('key', w) +fp = open('key', 'w') _KEY = fp.read().rstrip() fp.close() From b82a39d3bf666abd8ed38839d6c5730b09e6ad04 Mon Sep 17 00:00:00 2001 From: Chris Pham Date: Thu, 18 Jan 2018 10:58:24 -0800 Subject: [PATCH 06/28] fixed fp naming conventions --- ground_station/resources/core/mapping.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ground_station/resources/core/mapping.py b/ground_station/resources/core/mapping.py index 48fb7a4..3c05b90 100644 --- a/ground_station/resources/core/mapping.py +++ b/ground_station/resources/core/mapping.py @@ -12,9 +12,9 @@ import time ##################################### # Constants ##################################### -fp = open('key', 'w') -_KEY = fp.read().rstrip() -fp.close() +file_pointer = open('key', 'w') +_KEY = file_pointer.read().rstrip() +file_pointer.close() # Number of pixels in half the earth's circumference at zoom = 21 _EARTHPIX = 268435456 From 3570c4b5735bc2dbdf39bb5f52d34ccaa5bbee7e Mon Sep 17 00:00:00 2001 From: Chris Pham Date: Thu, 18 Jan 2018 11:09:09 -0800 Subject: [PATCH 07/28] write file intro --- ground_station/resources/core/mapping.py | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/ground_station/resources/core/mapping.py b/ground_station/resources/core/mapping.py index 3c05b90..7d23040 100644 --- a/ground_station/resources/core/mapping.py +++ b/ground_station/resources/core/mapping.py @@ -1,3 +1,21 @@ +''' +Mapping.py: Objected Orientated Google Maps for Python + +Copyright OSURC, orginal code from GooMPy by Alec Singer and Simon D. Levy + +This code is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as +published by the Free Software Foundation, either version 3 of the +License, or (at your option) any later version. +This code is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. +You should have received a copy of the GNU Lesser General Public License +along with this code. If not, see . + +''' + ##################################### # Imports ##################################### @@ -25,4 +43,7 @@ _TILESIZE = 640 # Fastest rate at which we can download tiles without paying _GRABRATE = 4 # Pixel Radius of Earth for calculations -_pixrad = _EARTHPIX / math.pi \ No newline at end of file +_pixrad = _EARTHPIX / math.pi + + +class Google \ No newline at end of file From a9bf793bfc0db615d7d62bef7ac1d56f81c38d6c Mon Sep 17 00:00:00 2001 From: Chris Pham Date: Thu, 18 Jan 2018 11:21:05 -0800 Subject: [PATCH 08/28] add gmaps obj and init --- ground_station/resources/core/mapping.py | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/ground_station/resources/core/mapping.py b/ground_station/resources/core/mapping.py index 7d23040..1036a14 100644 --- a/ground_station/resources/core/mapping.py +++ b/ground_station/resources/core/mapping.py @@ -46,4 +46,16 @@ _GRABRATE = 4 _pixrad = _EARTHPIX / math.pi -class Google \ No newline at end of file +class GMapsStitcher(object): + def __init__(self, width, height, latitude, + longitude, zoom, maptype, radius_meters=None, + num_tiles=4): + self.latitude = latitude + self.longitude = longitude + self.width = width + self.height = height + self.zoom = zoom + self.maptype = maptype + self.radius_meters = radius_meters + + From c2bb5f6d31e6457d59e207c5f87edeeb2ac50e11 Mon Sep 17 00:00:00 2001 From: Chris Pham Date: Thu, 18 Jan 2018 12:14:06 -0800 Subject: [PATCH 09/28] Added pixel_to_degrees helper --- ground_station/resources/core/mapping.py | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/ground_station/resources/core/mapping.py b/ground_station/resources/core/mapping.py index 1036a14..a65dded 100644 --- a/ground_station/resources/core/mapping.py +++ b/ground_station/resources/core/mapping.py @@ -47,9 +47,9 @@ _pixrad = _EARTHPIX / math.pi class GMapsStitcher(object): - def __init__(self, width, height, latitude, - longitude, zoom, maptype, radius_meters=None, - num_tiles=4): + def __init__(self, width, height, + latitude, longitude, zoom, + maptype, radius_meters=None, num_tiles=4): self.latitude = latitude self.longitude = longitude self.width = width @@ -57,5 +57,17 @@ class GMapsStitcher(object): self.zoom = zoom self.maptype = maptype self.radius_meters = radius_meters + + def _new_image(self): + return PIL.Image.new('RGB', (self.width, self.height)) + + def _fast_round(self, value, precision): + return int(value * 10 ** precision) / 10. ** precision + + def _pixels_to_degrees(self, pixels, zoom): + return pixels * 2 ** (21-zoom) + + def _grab_tile(self, sleeptime): + From f203cee53e0a60c4dc8eed40dfae0a07e4649e59 Mon Sep 17 00:00:00 2001 From: Chris Pham Date: Thu, 18 Jan 2018 12:24:01 -0800 Subject: [PATCH 10/28] rebuild Google Maps API link --- ground_station/resources/core/mapping.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ground_station/resources/core/mapping.py b/ground_station/resources/core/mapping.py index a65dded..f8a7808 100644 --- a/ground_station/resources/core/mapping.py +++ b/ground_station/resources/core/mapping.py @@ -68,6 +68,6 @@ class GMapsStitcher(object): return pixels * 2 ** (21-zoom) def _grab_tile(self, sleeptime): - - + urlbase = 'https://maps.googleapis.com/maps/api/staticmap?' + urlbase += 'center=%f%f&zoom=%d&maptype=%s&size=%dx%d&format=jpg&key=%s' From d09dbb1a02bc8883bc16e68aa8de74ee1b6ecfe6 Mon Sep 17 00:00:00 2001 From: Chris Pham Date: Thu, 18 Jan 2018 12:43:03 -0800 Subject: [PATCH 11/28] Addded _grab_tile helper --- ground_station/resources/core/mapping.py | 27 +++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/ground_station/resources/core/mapping.py b/ground_station/resources/core/mapping.py index f8a7808..64a0d67 100644 --- a/ground_station/resources/core/mapping.py +++ b/ground_station/resources/core/mapping.py @@ -21,7 +21,7 @@ along with this code. If not, see . ##################################### # Python native imports import math -import urllib +import urllib2 import PIL.Image from io import StringIO, BytesIO import os @@ -68,6 +68,31 @@ class GMapsStitcher(object): return pixels * 2 ** (21-zoom) def _grab_tile(self, sleeptime): + # Make the url string for polling + # GET request header gets appended to the string urlbase = 'https://maps.googleapis.com/maps/api/staticmap?' urlbase += 'center=%f%f&zoom=%d&maptype=%s&size=%dx%d&format=jpg&key=%s' + # Fill the formatting + specs = self.latitude, self.longitude, self.zoom, self.maptype, _TILESIZE, _KEY + filename = 'Resources/Maps/' + ('%f_%f_%d_%s_%d_%d_%s' % specs) + '.jpg' + + # Tile Image object + tile_object = None + + if os.path.isfile(filename): + tile_object = PIL.Image.open(filename) + + # If file on filesystem + else: + # make the url + url = urlbase % specs + + result = urllib2.Request(url).read() + tile_object = PIL.Image.open(BytesIO(result)) + if not os.path.exists('Resources/Maps'): + os.mkdir('Resources/Maps') + tile_object.save(filename) + + return tile_object + \ No newline at end of file From 16f76fad49699b346e15c0fdcfc2edcb814a0123 Mon Sep 17 00:00:00 2001 From: Chris Pham Date: Thu, 18 Jan 2018 13:00:53 -0800 Subject: [PATCH 12/28] added _pixels_to_lon helper --- ground_station/resources/core/mapping.py | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/ground_station/resources/core/mapping.py b/ground_station/resources/core/mapping.py index 64a0d67..a3c3698 100644 --- a/ground_station/resources/core/mapping.py +++ b/ground_station/resources/core/mapping.py @@ -1,8 +1,11 @@ ''' Mapping.py: Objected Orientated Google Maps for Python +Written by Chris Pham + Copyright OSURC, orginal code from GooMPy by Alec Singer and Simon D. Levy + This code is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the @@ -67,7 +70,7 @@ class GMapsStitcher(object): def _pixels_to_degrees(self, pixels, zoom): return pixels * 2 ** (21-zoom) - def _grab_tile(self, sleeptime): + def _grab_tile(self, sleeptime=0): # Make the url string for polling # GET request header gets appended to the string urlbase = 'https://maps.googleapis.com/maps/api/staticmap?' @@ -93,6 +96,13 @@ class GMapsStitcher(object): if not os.path.exists('Resources/Maps'): os.mkdir('Resources/Maps') tile_object.save(filename) + #Added to prevent timeouts on Google Servers + time.sleep(sleeptime) return tile_object - \ No newline at end of file + + def _pixels_to_lon(self, iterator, lon_pixels): + # Magic Lines, no idea + degrees = _pixels_to_degrees(((iterator) - self.num_tiles / 2) * _TILESIZE, self.zoom) + return math.degrees((lon_pixels + degrees - _EARTHPIX) / _pixrad) + From b7348ee897a3bbff349d2d04d7c2084bc60c46f0 Mon Sep 17 00:00:00 2001 From: Chris Pham Date: Thu, 18 Jan 2018 13:07:21 -0800 Subject: [PATCH 13/28] Fix self in pixel_to_lon helper --- ground_station/resources/core/mapping.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/ground_station/resources/core/mapping.py b/ground_station/resources/core/mapping.py index a3c3698..8e9c358 100644 --- a/ground_station/resources/core/mapping.py +++ b/ground_station/resources/core/mapping.py @@ -60,6 +60,7 @@ class GMapsStitcher(object): self.zoom = zoom self.maptype = maptype self.radius_meters = radius_meters + self.num_tiles = num_tiles def _new_image(self): return PIL.Image.new('RGB', (self.width, self.height)) @@ -103,6 +104,6 @@ class GMapsStitcher(object): def _pixels_to_lon(self, iterator, lon_pixels): # Magic Lines, no idea - degrees = _pixels_to_degrees(((iterator) - self.num_tiles / 2) * _TILESIZE, self.zoom) + degrees = self._pixels_to_degrees(((iterator) - self.num_tiles / 2) * _TILESIZE, self.zoom) return math.degrees((lon_pixels + degrees - _EARTHPIX) / _pixrad) - + From 400410cea4af92cb25fd1f686809f320c9cc102c Mon Sep 17 00:00:00 2001 From: Chris Pham Date: Thu, 18 Jan 2018 13:21:38 -0800 Subject: [PATCH 14/28] Added _pixels_to_lat --- ground_station/resources/core/mapping.py | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/ground_station/resources/core/mapping.py b/ground_station/resources/core/mapping.py index 8e9c358..1f49e83 100644 --- a/ground_station/resources/core/mapping.py +++ b/ground_station/resources/core/mapping.py @@ -1,11 +1,9 @@ ''' Mapping.py: Objected Orientated Google Maps for Python - -Written by Chris Pham +ReWritten by Chris Pham Copyright OSURC, orginal code from GooMPy by Alec Singer and Simon D. Levy - This code is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the @@ -25,10 +23,10 @@ along with this code. If not, see . # Python native imports import math import urllib2 -import PIL.Image from io import StringIO, BytesIO import os import time +import PIL.Image ##################################### # Constants @@ -61,7 +59,7 @@ class GMapsStitcher(object): self.maptype = maptype self.radius_meters = radius_meters self.num_tiles = num_tiles - + def _new_image(self): return PIL.Image.new('RGB', (self.width, self.height)) @@ -77,7 +75,7 @@ class GMapsStitcher(object): urlbase = 'https://maps.googleapis.com/maps/api/staticmap?' urlbase += 'center=%f%f&zoom=%d&maptype=%s&size=%dx%d&format=jpg&key=%s' - # Fill the formatting + # Fill the formatting specs = self.latitude, self.longitude, self.zoom, self.maptype, _TILESIZE, _KEY filename = 'Resources/Maps/' + ('%f_%f_%d_%s_%d_%d_%s' % specs) + '.jpg' @@ -86,7 +84,7 @@ class GMapsStitcher(object): if os.path.isfile(filename): tile_object = PIL.Image.open(filename) - + # If file on filesystem else: # make the url @@ -107,3 +105,7 @@ class GMapsStitcher(object): degrees = self._pixels_to_degrees(((iterator) - self.num_tiles / 2) * _TILESIZE, self.zoom) return math.degrees((lon_pixels + degrees - _EARTHPIX) / _pixrad) + def _pixels_to_lat(self, iterator, lat_pixels): + # Magic Lines + degree = self._pixels_to_degrees((iterator - self.num_tiles / 2) * _TILESIZE, self.zoom) + return math.degrees(math.pi / 2 - 2 * math.atan(math.exp(((lat_pixels + degree) - _EARTHPIX) / _pixrad))) From d2f4fc38fecf903ed35d731dafe566709707601c Mon Sep 17 00:00:00 2001 From: Chris Pham Date: Thu, 18 Jan 2018 13:23:48 -0800 Subject: [PATCH 15/28] Add gitignore for API key --- .gitignore | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index a0ad585..a6715f0 100644 --- a/.gitignore +++ b/.gitignore @@ -86,4 +86,7 @@ ENV/ .spyderproject # Rope project settings -.ropeproject \ No newline at end of file +.ropeproject + +# Google API Key +ground_station/resources/core/key \ No newline at end of file From b319118e1d32c8d655afe7a6cd084916d16f8db3 Mon Sep 17 00:00:00 2001 From: Chris Pham Date: Thu, 18 Jan 2018 13:26:03 -0800 Subject: [PATCH 16/28] remove key --- ground_station/resources/core/key | 1 - 1 file changed, 1 deletion(-) delete mode 100644 ground_station/resources/core/key diff --git a/ground_station/resources/core/key b/ground_station/resources/core/key deleted file mode 100644 index 4e51d9a..0000000 --- a/ground_station/resources/core/key +++ /dev/null @@ -1 +0,0 @@ -AIzaSyAFjAWMwQauf2Dy5KteOuT8KexfMjOCIS8 \ No newline at end of file From 995386ee89319296165900b1466b6cfc5cf060d5 Mon Sep 17 00:00:00 2001 From: Chris Pham Date: Sat, 20 Jan 2018 13:06:28 -0800 Subject: [PATCH 17/28] Made pixels_to_meters helper --- ground_station/resources/core/mapping.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/ground_station/resources/core/mapping.py b/ground_station/resources/core/mapping.py index 1f49e83..0db41a5 100644 --- a/ground_station/resources/core/mapping.py +++ b/ground_station/resources/core/mapping.py @@ -69,6 +69,9 @@ class GMapsStitcher(object): def _pixels_to_degrees(self, pixels, zoom): return pixels * 2 ** (21-zoom) + def _pixels_to_meters(self) + return 2 ** self.zoom / (156543.03392 * math.cos(math.radians(self.latitude))) + def _grab_tile(self, sleeptime=0): # Make the url string for polling # GET request header gets appended to the string @@ -109,3 +112,11 @@ class GMapsStitcher(object): # Magic Lines degree = self._pixels_to_degrees((iterator - self.num_tiles / 2) * _TILESIZE, self.zoom) return math.degrees(math.pi / 2 - 2 * math.atan(math.exp(((lat_pixels + degree) - _EARTHPIX) / _pixrad))) + + def fetch_tiles(self): + # cap floats to precision amount + self.latitude = self._fast_round(latitude, _DEGREE_PRECISION) + self.longitude = self._fast_round(longitude, _DEGREE_PRECISION) + + #grab the pixels per meter + From fee5b5537bbdb496791f7b7f323aae6995844afc Mon Sep 17 00:00:00 2001 From: Chris Pham Date: Sat, 20 Jan 2018 13:24:32 -0800 Subject: [PATCH 18/28] Added logic for num_sqares --- ground_station/resources/core/mapping.py | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/ground_station/resources/core/mapping.py b/ground_station/resources/core/mapping.py index 0db41a5..5a87778 100644 --- a/ground_station/resources/core/mapping.py +++ b/ground_station/resources/core/mapping.py @@ -69,7 +69,8 @@ class GMapsStitcher(object): def _pixels_to_degrees(self, pixels, zoom): return pixels * 2 ** (21-zoom) - def _pixels_to_meters(self) + def _pixels_to_meters(self): + # https://groups.google.com/forum/#!topic/google-maps-js-api-v3/hDRO4oHVSeM return 2 ** self.zoom / (156543.03392 * math.cos(math.radians(self.latitude))) def _grab_tile(self, sleeptime=0): @@ -111,12 +112,15 @@ class GMapsStitcher(object): def _pixels_to_lat(self, iterator, lat_pixels): # Magic Lines degree = self._pixels_to_degrees((iterator - self.num_tiles / 2) * _TILESIZE, self.zoom) - return math.degrees(math.pi / 2 - 2 * math.atan(math.exp(((lat_pixels + degree) - _EARTHPIX) / _pixrad))) - - def fetch_tiles(self): + temp = math.atan(math.exp(((lat_pixels + degree) - _EARTHPIX) + return math.degrees(math.pi / 2 - 2 * temp / _pixrad))) + + def fetch_tiles(self,): # cap floats to precision amount - self.latitude = self._fast_round(latitude, _DEGREE_PRECISION) - self.longitude = self._fast_round(longitude, _DEGREE_PRECISION) + self.latitude = self._fast_round(self.latitude, _DEGREE_PRECISION) + self.longitude = self._fast_round(self.longitude, _DEGREE_PRECISION) - #grab the pixels per meter + # number of tiles required to go from center latitude to desired radius in meters + if self.radius_meters is not None: + self.num_tiles = int(round(2*self._pixels_to_meters / (_TILESIZE / 2. / self.radius_meters))) From 3565e7b57f1f19a81b9b34b88a8c9ef527e7c7d6 Mon Sep 17 00:00:00 2001 From: Chris Pham Date: Sat, 20 Jan 2018 13:43:47 -0800 Subject: [PATCH 19/28] Rebuild grab_tile --- ground_station/resources/core/mapping.py | 29 +++++++++++++++++++----- 1 file changed, 23 insertions(+), 6 deletions(-) diff --git a/ground_station/resources/core/mapping.py b/ground_station/resources/core/mapping.py index 5a87778..81c8e40 100644 --- a/ground_station/resources/core/mapping.py +++ b/ground_station/resources/core/mapping.py @@ -60,8 +60,8 @@ class GMapsStitcher(object): self.radius_meters = radius_meters self.num_tiles = num_tiles - def _new_image(self): - return PIL.Image.new('RGB', (self.width, self.height)) + def _new_image(self, width, height): + return PIL.Image.new('RGB', (width, height)) def _fast_round(self, value, precision): return int(value * 10 ** precision) / 10. ** precision @@ -73,14 +73,14 @@ class GMapsStitcher(object): # https://groups.google.com/forum/#!topic/google-maps-js-api-v3/hDRO4oHVSeM return 2 ** self.zoom / (156543.03392 * math.cos(math.radians(self.latitude))) - def _grab_tile(self, sleeptime=0): + def _grab_tile(self, longitude, latitude, sleeptime=0): # Make the url string for polling # GET request header gets appended to the string urlbase = 'https://maps.googleapis.com/maps/api/staticmap?' urlbase += 'center=%f%f&zoom=%d&maptype=%s&size=%dx%d&format=jpg&key=%s' # Fill the formatting - specs = self.latitude, self.longitude, self.zoom, self.maptype, _TILESIZE, _KEY + specs = latitude, longitude, self.zoom, self.maptype, _TILESIZE, _KEY filename = 'Resources/Maps/' + ('%f_%f_%d_%s_%d_%d_%s' % specs) + '.jpg' # Tile Image object @@ -112,8 +112,8 @@ class GMapsStitcher(object): def _pixels_to_lat(self, iterator, lat_pixels): # Magic Lines degree = self._pixels_to_degrees((iterator - self.num_tiles / 2) * _TILESIZE, self.zoom) - temp = math.atan(math.exp(((lat_pixels + degree) - _EARTHPIX) - return math.degrees(math.pi / 2 - 2 * temp / _pixrad))) + temp = math.atan(math.exp(((lat_pixels + degree) - _EARTHPIX))/ _pixrad) + return math.degrees(math.pi / 2 - 2 * temp) def fetch_tiles(self,): # cap floats to precision amount @@ -124,3 +124,20 @@ class GMapsStitcher(object): if self.radius_meters is not None: self.num_tiles = int(round(2*self._pixels_to_meters / (_TILESIZE / 2. / self.radius_meters))) + lon_pixels = _EARTHPIX + self.longitude * math.radians(_pixrad) + + sin_lat = math.sin(math.radians(self.latitude)) + lat_pixels = _EARTHPIX - _pixrad * math.log((1+sin_lat)/(1-sin_lat))/2 + big_size = self.num_tiles * _TILESIZE + + big_image = self._new_image(big_size, big_size) + + for j in range(self.num_tiles): + lon = self._pixels_to_lon(j,lon_pixels) + for k in range(self.num_tiles): + lat = self._pixels_to_lat(k, lat_pixels) + tile = self._grab_tile(lon, lat) + big_image.paste(tile, (j * _TILESIZE, k * _TILESIZE)) + + big_image.save("buttholes.jpg") + From e955442131978ffd1d24aa6ced9ff2c9f899ed59 Mon Sep 17 00:00:00 2001 From: Chris Pham Date: Sat, 20 Jan 2018 13:57:11 -0800 Subject: [PATCH 20/28] Fixed to fit PEP --- ground_station/resources/core/mapping.py | 25 ++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/ground_station/resources/core/mapping.py b/ground_station/resources/core/mapping.py index 81c8e40..8b7755e 100644 --- a/ground_station/resources/core/mapping.py +++ b/ground_station/resources/core/mapping.py @@ -31,20 +31,22 @@ import PIL.Image ##################################### # Constants ##################################### +_KEYS = [] file_pointer = open('key', 'w') -_KEY = file_pointer.read().rstrip() +for i in file_pointer: + _KEYS.append(file_pointer.readline().rstrip()) file_pointer.close() # Number of pixels in half the earth's circumference at zoom = 21 _EARTHPIX = 268435456 # Number of decimal places for rounding coordinates -_DEGREE_PRECISION = 4 +_DEGREE_PRECISION = 4 # Larget tile we can grab without paying _TILESIZE = 640 # Fastest rate at which we can download tiles without paying _GRABRATE = 4 # Pixel Radius of Earth for calculations -_pixrad = _EARTHPIX / math.pi +_PIXRAD = _EARTHPIX / math.pi class GMapsStitcher(object): @@ -80,7 +82,7 @@ class GMapsStitcher(object): urlbase += 'center=%f%f&zoom=%d&maptype=%s&size=%dx%d&format=jpg&key=%s' # Fill the formatting - specs = latitude, longitude, self.zoom, self.maptype, _TILESIZE, _KEY + specs = latitude, longitude, self.zoom, self.maptype, _TILESIZE, _KEYS[0] filename = 'Resources/Maps/' + ('%f_%f_%d_%s_%d_%d_%s' % specs) + '.jpg' # Tile Image object @@ -107,12 +109,12 @@ class GMapsStitcher(object): def _pixels_to_lon(self, iterator, lon_pixels): # Magic Lines, no idea degrees = self._pixels_to_degrees(((iterator) - self.num_tiles / 2) * _TILESIZE, self.zoom) - return math.degrees((lon_pixels + degrees - _EARTHPIX) / _pixrad) + return math.degrees((lon_pixels + degrees - _EARTHPIX) / _PIXRAD) def _pixels_to_lat(self, iterator, lat_pixels): # Magic Lines degree = self._pixels_to_degrees((iterator - self.num_tiles / 2) * _TILESIZE, self.zoom) - temp = math.atan(math.exp(((lat_pixels + degree) - _EARTHPIX))/ _pixrad) + temp = math.atan(math.exp(((lat_pixels + degree) - _EARTHPIX))/ _PIXRAD) return math.degrees(math.pi / 2 - 2 * temp) def fetch_tiles(self,): @@ -124,20 +126,19 @@ class GMapsStitcher(object): if self.radius_meters is not None: self.num_tiles = int(round(2*self._pixels_to_meters / (_TILESIZE / 2. / self.radius_meters))) - lon_pixels = _EARTHPIX + self.longitude * math.radians(_pixrad) + lon_pixels = _EARTHPIX + self.longitude * math.radians(_PIXRAD) sin_lat = math.sin(math.radians(self.latitude)) - lat_pixels = _EARTHPIX - _pixrad * math.log((1+sin_lat)/(1-sin_lat))/2 + lat_pixels = _EARTHPIX - _PIXRAD * math.log((1+sin_lat)/(1-sin_lat))/2 big_size = self.num_tiles * _TILESIZE big_image = self._new_image(big_size, big_size) for j in range(self.num_tiles): - lon = self._pixels_to_lon(j,lon_pixels) + lon = self._pixels_to_lon(j, lon_pixels) for k in range(self.num_tiles): lat = self._pixels_to_lat(k, lat_pixels) tile = self._grab_tile(lon, lat) big_image.paste(tile, (j * _TILESIZE, k * _TILESIZE)) - - big_image.save("buttholes.jpg") - + + big_image.save("testimage.jpg") From 332c751758c837cb52b3a9008ba830c5755fbf76 Mon Sep 17 00:00:00 2001 From: Chris Pham Date: Sat, 20 Jan 2018 14:14:44 -0800 Subject: [PATCH 21/28] Append signature --- ground_station/resources/core/mapping.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ground_station/resources/core/mapping.py b/ground_station/resources/core/mapping.py index 8b7755e..fa7c6d8 100644 --- a/ground_station/resources/core/mapping.py +++ b/ground_station/resources/core/mapping.py @@ -79,11 +79,11 @@ class GMapsStitcher(object): # Make the url string for polling # GET request header gets appended to the string urlbase = 'https://maps.googleapis.com/maps/api/staticmap?' - urlbase += 'center=%f%f&zoom=%d&maptype=%s&size=%dx%d&format=jpg&key=%s' + urlbase += 'center=%f%f&zoom=%d&maptype=%s&size=%dx%d&format=jpg&key=%s&signature=%s' # Fill the formatting - specs = latitude, longitude, self.zoom, self.maptype, _TILESIZE, _KEYS[0] - filename = 'Resources/Maps/' + ('%f_%f_%d_%s_%d_%d_%s' % specs) + '.jpg' + specs = latitude, longitude, self.zoom, self.maptype, _TILESIZE, _KEYS[0], _KEYS[1] + filename = 'Resources/Maps/' + ('%f_%f_%d_%s_%d_%d_%s_%s' % specs) + '.jpg' # Tile Image object tile_object = None From a0601abb8db35bf4a7ebcdba81f702814c73fdf2 Mon Sep 17 00:00:00 2001 From: Chris Pham Date: Sat, 20 Jan 2018 16:32:58 -0800 Subject: [PATCH 22/28] Add testing file with updated gitignore for jpgs --- .gitignore | 5 +- ground_station/resources/core/mapping.py | 30 ++++++----- ground_station/resources/core/mappingtest.py | 5 ++ ground_station/resources/core/signing.py | 53 ++++++++++++++++++++ 4 files changed, 80 insertions(+), 13 deletions(-) create mode 100644 ground_station/resources/core/mappingtest.py create mode 100644 ground_station/resources/core/signing.py diff --git a/.gitignore b/.gitignore index a6715f0..8148d81 100644 --- a/.gitignore +++ b/.gitignore @@ -89,4 +89,7 @@ ENV/ .ropeproject # Google API Key -ground_station/resources/core/key \ No newline at end of file +ground_station/resources/core/key + +# Map Images +*.jpg diff --git a/ground_station/resources/core/mapping.py b/ground_station/resources/core/mapping.py index fa7c6d8..0458758 100644 --- a/ground_station/resources/core/mapping.py +++ b/ground_station/resources/core/mapping.py @@ -5,7 +5,7 @@ ReWritten by Chris Pham Copyright OSURC, orginal code from GooMPy by Alec Singer and Simon D. Levy This code is free software: you can redistribute it and/or modify -it under the terms of the GNU Lesser General Public License as +it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This code is distributed in the hope that it will be useful, @@ -27,15 +27,12 @@ from io import StringIO, BytesIO import os import time import PIL.Image +import signing ##################################### # Constants ##################################### _KEYS = [] -file_pointer = open('key', 'w') -for i in file_pointer: - _KEYS.append(file_pointer.readline().rstrip()) -file_pointer.close() # Number of pixels in half the earth's circumference at zoom = 21 _EARTHPIX = 268435456 @@ -48,6 +45,13 @@ _GRABRATE = 4 # Pixel Radius of Earth for calculations _PIXRAD = _EARTHPIX / math.pi +file_pointer = open('key', 'r') +for i in file_pointer: + _KEYS.append(i.rstrip()) +file_pointer.close() + +print _KEYS + class GMapsStitcher(object): def __init__(self, width, height, @@ -79,11 +83,11 @@ class GMapsStitcher(object): # Make the url string for polling # GET request header gets appended to the string urlbase = 'https://maps.googleapis.com/maps/api/staticmap?' - urlbase += 'center=%f%f&zoom=%d&maptype=%s&size=%dx%d&format=jpg&key=%s&signature=%s' + urlbase += 'center=%f,%f&zoom=%d&maptype=%s&size=%dx%d&format=jpg&key=%s' # Fill the formatting - specs = latitude, longitude, self.zoom, self.maptype, _TILESIZE, _KEYS[0], _KEYS[1] - filename = 'Resources/Maps/' + ('%f_%f_%d_%s_%d_%d_%s_%s' % specs) + '.jpg' + specs = latitude, longitude, self.zoom, self.maptype, _TILESIZE, _TILESIZE, _KEYS[0] + filename = 'Resources/Maps/' + ('%f_%f_%d_%s_%d_%d_%s' % specs) + '.jpg' # Tile Image object tile_object = None @@ -95,8 +99,10 @@ class GMapsStitcher(object): else: # make the url url = urlbase % specs - - result = urllib2.Request(url).read() + print url + url = signing.sign_url(url, _KEYS[1]) + print url + result = urllib2.urlopen(urllib2.Request(url)).read() tile_object = PIL.Image.open(BytesIO(result)) if not os.path.exists('Resources/Maps'): os.mkdir('Resources/Maps') @@ -117,14 +123,14 @@ class GMapsStitcher(object): temp = math.atan(math.exp(((lat_pixels + degree) - _EARTHPIX))/ _PIXRAD) return math.degrees(math.pi / 2 - 2 * temp) - def fetch_tiles(self,): + def fetch_tiles(self): # cap floats to precision amount self.latitude = self._fast_round(self.latitude, _DEGREE_PRECISION) self.longitude = self._fast_round(self.longitude, _DEGREE_PRECISION) # number of tiles required to go from center latitude to desired radius in meters if self.radius_meters is not None: - self.num_tiles = int(round(2*self._pixels_to_meters / (_TILESIZE / 2. / self.radius_meters))) + self.num_tiles = int(round(2*self._pixels_to_meters() / (_TILESIZE / 2. / self.radius_meters))) lon_pixels = _EARTHPIX + self.longitude * math.radians(_PIXRAD) diff --git a/ground_station/resources/core/mappingtest.py b/ground_station/resources/core/mappingtest.py new file mode 100644 index 0000000..12ad56c --- /dev/null +++ b/ground_station/resources/core/mappingtest.py @@ -0,0 +1,5 @@ +import mapping + +obj = mapping.GMapsStitcher(10000, 10000, 44.57078, -123.275998, 21, 'terrain', 200) + +obj.fetch_tiles() \ No newline at end of file diff --git a/ground_station/resources/core/signing.py b/ground_station/resources/core/signing.py new file mode 100644 index 0000000..d5f519a --- /dev/null +++ b/ground_station/resources/core/signing.py @@ -0,0 +1,53 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +""" Signs a URL using a URL signing secret """ + +import hashlib +import hmac +import base64 +import urlparse + +def sign_url(input_url=None, secret=None): + """ Sign a request URL with a URL signing secret. + + Usage: + from urlsigner import sign_url + + signed_url = sign_url(input_url=my_url, secret=SECRET) + + Args: + input_url - The URL to sign + secret - Your URL signing secret + + Returns: + The signed request URL + """ + + if not input_url or not secret: + raise Exception("Both input_url and secret are required") + + url = urlparse.urlparse(input_url) + + # We only need to sign the path+query part of the string + url_to_sign = url.path + "?" + url.query + + # Decode the private key into its binary format + # We need to decode the URL-encoded private key + decoded_key = base64.urlsafe_b64decode(secret) + + # Create a signature using the private key and the URL-encoded + # string using HMAC SHA1. This signature will be binary. + signature = hmac.new(decoded_key, url_to_sign, hashlib.sha1) + + # Encode the binary signature into base64 for use within a URL + encoded_signature = base64.urlsafe_b64encode(signature.digest()) + + original_url = url.scheme + "://" + url.netloc + url.path + "?" + url.query + + # Return signed URL + return original_url + "&signature=" + encoded_signature + +if __name__ == "__main__": + input_url = raw_input("URL to Sign: ") + secret = raw_input("URL signing secret: ") + print "Signed URL: " + sign_url(input_url, secret) From 1c16cb48a1faec2e8dc157748d0f870d1253fde7 Mon Sep 17 00:00:00 2001 From: Chris Pham Date: Thu, 25 Jan 2018 10:49:36 -0800 Subject: [PATCH 23/28] Creates Big Image --- ground_station/resources/core/mapping.py | 5 ++--- ground_station/resources/core/mappingtest.py | 2 +- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/ground_station/resources/core/mapping.py b/ground_station/resources/core/mapping.py index 0458758..b9a0b93 100644 --- a/ground_station/resources/core/mapping.py +++ b/ground_station/resources/core/mapping.py @@ -119,9 +119,8 @@ class GMapsStitcher(object): def _pixels_to_lat(self, iterator, lat_pixels): # Magic Lines - degree = self._pixels_to_degrees((iterator - self.num_tiles / 2) * _TILESIZE, self.zoom) - temp = math.atan(math.exp(((lat_pixels + degree) - _EARTHPIX))/ _PIXRAD) - return math.degrees(math.pi / 2 - 2 * temp) + return math.degrees(math.pi / 2 - 2 * math.atan( + math.exp(((lat_pixels + self._pixels_to_degrees((iterator - self.num_tiles / 2) * _TILESIZE, self.zoom)) - _EARTHPIX) / _PIXRAD))) def fetch_tiles(self): # cap floats to precision amount diff --git a/ground_station/resources/core/mappingtest.py b/ground_station/resources/core/mappingtest.py index 12ad56c..8d1b16e 100644 --- a/ground_station/resources/core/mappingtest.py +++ b/ground_station/resources/core/mappingtest.py @@ -1,5 +1,5 @@ import mapping -obj = mapping.GMapsStitcher(10000, 10000, 44.57078, -123.275998, 21, 'terrain', 200) +obj = mapping.GMapsStitcher(1, 1, 44.57078, -123.275998, 18, 'terrain', None, 20) obj.fetch_tiles() \ No newline at end of file From b12f8fc986912d75d018e8da9912eaa1c93b9e4b Mon Sep 17 00:00:00 2001 From: Chris Pham Date: Thu, 25 Jan 2018 15:01:35 -0800 Subject: [PATCH 24/28] Working updates and fetching, starting on zoom functionality --- ground_station/resources/core/mapping.py | 46 ++++++++++++++++++++ ground_station/resources/core/mappingtest.py | 6 ++- 2 files changed, 50 insertions(+), 2 deletions(-) diff --git a/ground_station/resources/core/mapping.py b/ground_station/resources/core/mapping.py index b9a0b93..eae7d7c 100644 --- a/ground_station/resources/core/mapping.py +++ b/ground_station/resources/core/mapping.py @@ -65,6 +65,17 @@ class GMapsStitcher(object): self.maptype = maptype self.radius_meters = radius_meters self.num_tiles = num_tiles + self.display_image = self._new_image(width, height) + self.image_zoom = 1.0 + + + # Get the big image here + self._fetch() + middle = self.big_image.size[0] // 2 + self.left_x = middle + self.upper_y = middle + + self.update() def _new_image(self, width, height): return PIL.Image.new('RGB', (width, height)) @@ -147,3 +158,38 @@ class GMapsStitcher(object): big_image.paste(tile, (j * _TILESIZE, k * _TILESIZE)) big_image.save("testimage.jpg") + + west = self._pixels_to_lon(0, lon_pixels) + east = self._pixels_to_lon(self.num_tiles - 1, lat_pixels) + + north = self._pixels_to_lat(0, lat_pixels) + south = self._pixels_to_lat(self.num_tiles - 1, lat_pixels) + return big_image, (north, west), (south, east) + + def get_image(self): + return self.display_image + + def move(self, dx, dy): + self._constrain_x(dx) + self._constrain_y(dy) + self.update() + + def _constrain_x(self, diff): + new_value = self.left_x - diff + return new_value if (new_value > 0 and (new_value < self.big_image.size[0] - self.width)) else self.left_x + + def _constrain_y(self, diff): + new_value = self.upper_y - diff + return new_value if new_value > 0 and new_value < self.big_image.size[0] - self.height else self.upper_y + + def update(self): + self.display_image.paste(self.big_image, (-self.left_x, -self.upper_y)) + self.display_image.resize((self.image_zoom, self.image_zoom)) + + def _fetch(self): + self.big_image, self.northwest, self.southeast = self.fetch_tiles() + print self.northwest + + def useZoom(self, new_zoom): + self.image_zoom = new_zoom + self.update() diff --git a/ground_station/resources/core/mappingtest.py b/ground_station/resources/core/mappingtest.py index 8d1b16e..92adb18 100644 --- a/ground_station/resources/core/mappingtest.py +++ b/ground_station/resources/core/mappingtest.py @@ -1,5 +1,7 @@ import mapping -obj = mapping.GMapsStitcher(1, 1, 44.57078, -123.275998, 18, 'terrain', None, 20) +obj = mapping.GMapsStitcher(2000, 2000, 44.57078, -123.275998, 18, 'terrain', None, 20) -obj.fetch_tiles() \ No newline at end of file +obj.useZoom(1.2) + +obj.display_image.save("display_image.jpg") From 3ed2c5977e41dc8f4baee7b10d7c3114793e29d7 Mon Sep 17 00:00:00 2001 From: Chris Pham Date: Thu, 1 Feb 2018 19:25:54 -0800 Subject: [PATCH 25/28] created and fixed centering --- .gitignore | 1 + ground_station/resources/core/mapping.py | 170 ++++++++++++++++--- ground_station/resources/core/mappingtest.py | 23 ++- 3 files changed, 170 insertions(+), 24 deletions(-) mode change 100644 => 100755 ground_station/resources/core/mappingtest.py diff --git a/.gitignore b/.gitignore index 8148d81..7f787ce 100644 --- a/.gitignore +++ b/.gitignore @@ -93,3 +93,4 @@ ground_station/resources/core/key # Map Images *.jpg +*.png diff --git a/ground_station/resources/core/mapping.py b/ground_station/resources/core/mapping.py index eae7d7c..c174cb6 100644 --- a/ground_station/resources/core/mapping.py +++ b/ground_station/resources/core/mapping.py @@ -27,6 +27,7 @@ from io import StringIO, BytesIO import os import time import PIL.Image +import PIL.ImageDraw import signing ##################################### @@ -44,6 +45,7 @@ _TILESIZE = 640 _GRABRATE = 4 # Pixel Radius of Earth for calculations _PIXRAD = _EARTHPIX / math.pi +_DISPLAYPIX = _EARTHPIX / 2000 file_pointer = open('key', 'r') for i in file_pointer: @@ -59,6 +61,8 @@ class GMapsStitcher(object): maptype, radius_meters=None, num_tiles=4): self.latitude = latitude self.longitude = longitude + self.start_latitude = latitude + self.start_longitude = longitude self.width = width self.height = height self.zoom = zoom @@ -66,19 +70,17 @@ class GMapsStitcher(object): self.radius_meters = radius_meters self.num_tiles = num_tiles self.display_image = self._new_image(width, height) - self.image_zoom = 1.0 - # Get the big image here self._fetch() - middle = self.big_image.size[0] // 2 - self.left_x = middle - self.upper_y = middle + self.center_display(latitude, longitude) - self.update() + def obj_print(self): + print("Center of the map is at "+ str(self.center_x)+"x"+str(self.center_y)) + print("The start of the box is at "+str(self.left_x)+"x"+str(self.upper_y)) def _new_image(self, width, height): - return PIL.Image.new('RGB', (width, height)) + return PIL.Image.new('RGBA', (width, height)) def _fast_round(self, value, precision): return int(value * 10 ** precision) / 10. ** precision @@ -94,11 +96,11 @@ class GMapsStitcher(object): # Make the url string for polling # GET request header gets appended to the string urlbase = 'https://maps.googleapis.com/maps/api/staticmap?' - urlbase += 'center=%f,%f&zoom=%d&maptype=%s&size=%dx%d&format=jpg&key=%s' + urlbase += 'center=%.4f,%.4f&zoom=%d&maptype=%s&size=%dx%d&format=png&key=%s' # Fill the formatting - specs = latitude, longitude, self.zoom, self.maptype, _TILESIZE, _TILESIZE, _KEYS[0] - filename = 'Resources/Maps/' + ('%f_%f_%d_%s_%d_%d_%s' % specs) + '.jpg' + specs = self._fast_round(latitude, 4), self._fast_round(longitude, 4), self.zoom, self.maptype, _TILESIZE, _TILESIZE, _KEYS[0] + filename = 'Resources/Maps/' + ('%.4f_%.4f_%d_%s_%d_%d_%s' % specs) + '.png' # Tile Image object tile_object = None @@ -146,21 +148,27 @@ class GMapsStitcher(object): sin_lat = math.sin(math.radians(self.latitude)) lat_pixels = _EARTHPIX - _PIXRAD * math.log((1+sin_lat)/(1-sin_lat))/2 - big_size = self.num_tiles * _TILESIZE - - big_image = self._new_image(big_size, big_size) + self.big_size = self.num_tiles * _TILESIZE + big_image = self._new_image(self.big_size, self.big_size) for j in range(self.num_tiles): lon = self._pixels_to_lon(j, lon_pixels) + if j is 0: + self.big_map_lon_small = lon + if j is 19: + self.big_map_lon_big = lon for k in range(self.num_tiles): lat = self._pixels_to_lat(k, lat_pixels) + #print "j, k", j, k + if k is 0: + self.big_map_lat_small = lat + if k is 19: + self.big_map_lat_big = lat tile = self._grab_tile(lon, lat) big_image.paste(tile, (j * _TILESIZE, k * _TILESIZE)) - big_image.save("testimage.jpg") - west = self._pixels_to_lon(0, lon_pixels) - east = self._pixels_to_lon(self.num_tiles - 1, lat_pixels) + east = self._pixels_to_lon(self.num_tiles - 1, lon_pixels) north = self._pixels_to_lat(0, lat_pixels) south = self._pixels_to_lat(self.num_tiles - 1, lat_pixels) @@ -169,7 +177,7 @@ class GMapsStitcher(object): def get_image(self): return self.display_image - def move(self, dx, dy): + def move_pix(self, dx, dy): self._constrain_x(dx) self._constrain_y(dy) self.update() @@ -184,12 +192,132 @@ class GMapsStitcher(object): def update(self): self.display_image.paste(self.big_image, (-self.left_x, -self.upper_y)) - self.display_image.resize((self.image_zoom, self.image_zoom)) + # self.display_image.resize((self.image_zoom, self.image_zoom)) def _fetch(self): self.big_image, self.northwest, self.southeast = self.fetch_tiles() - print self.northwest - def useZoom(self, new_zoom): - self.image_zoom = new_zoom + + def _merc_proj(self, lat): + return math.log(math.tan((lat/2.) + (math.pi/4.))) + + def move_latlon(self, lat, lon): + # print "Lat", self.big_map_lat_small, self.big_map_lat_big + # print "Lng", self.big_map_lon_small, self.big_map_lon_big + + # east = math.radians(self.big_map_lon_big) + # west = math.radians(self.big_map_lon_small) + # north = math.radians(self.big_map_lat_small) + # south = math.radians(self.big_map_lat_big) + # print north, south + # print "east-west", (east-west) + + # y_min = self._merc_proj(south) + # y_max = self._merc_proj(north) + + # x_factor = self.big_size/(east-west) + # print x_factor + # y_factor = self.big_size/(y_max - y_min) + # print y_factor + + # print "rads lon", math.radians(lon) + # x = (math.radians(lon) - east) * x_factor + # y = (y_max - self._merc_proj(math.radians(lat))) * y_factor + # print x, y + # return x*.1, y + + viewport_lat_nw, viewport_lon_nw = self.northwest + viewport_lat_se, viewport_lon_se = self.southeast + print "Lat:", viewport_lat_nw, viewport_lat_se + print "Lon:", viewport_lon_nw, viewport_lon_se + + viewport_lat_diff = viewport_lat_nw - viewport_lat_se + viewport_lon_diff = viewport_lon_se - viewport_lon_nw + + print viewport_lon_diff, viewport_lat_diff + + bigimage_width = self.big_image.size[0] + bigimage_height = self.big_image.size[1] + + pixel_per_lat = bigimage_height / viewport_lat_diff + pixel_per_lon = bigimage_width / viewport_lon_diff + print "Pixel per:", pixel_per_lat, pixel_per_lon + + new_lat_gps_range_percentage = (viewport_lat_nw - lat) + new_lon_gps_range_percentage = (lon - viewport_lon_nw) + print lon, viewport_lon_se + + print "Percentages: ", new_lat_gps_range_percentage, new_lon_gps_range_percentage + + x = new_lon_gps_range_percentage * pixel_per_lon + y = new_lat_gps_range_percentage * pixel_per_lat + + print x, y + return y, x + + # east = (self.big_map_lon_big) - (.0034) + # west = (self.big_map_lon_small) + (.0034) + # north = (self.big_map_lat_small) + (.0025) + # south = (self.big_map_lat_big) - (.0025) + # lng_diff = west - east + # lat_diff = north - south + + + # x = int(((east - lon)/lng_diff)*self.big_image.size[0]) + # y = int(((north - lat)/lat_diff)*self.big_image.size[1]) + + # print x, y + # return x, y + + def _get_cartesian(self, lat, lon): + viewport_lat_nw, viewport_lon_nw = self.northwest + viewport_lat_se, viewport_lon_se = self.southeast + print "Lat:", viewport_lat_nw, viewport_lat_se + print "Lon:", viewport_lon_nw, viewport_lon_se + + viewport_lat_diff = viewport_lat_nw - viewport_lat_se + viewport_lon_diff = viewport_lon_se - viewport_lon_nw + + print viewport_lon_diff, viewport_lat_diff + + bigimage_width = self.big_image.size[0] + bigimage_height = self.big_image.size[1] + + pixel_per_lat = bigimage_height / viewport_lat_diff + pixel_per_lon = bigimage_width / viewport_lon_diff + print "Pixel per:", pixel_per_lat, pixel_per_lon + + new_lat_gps_range_percentage = (viewport_lat_nw - lat) + new_lon_gps_range_percentage = (lon - viewport_lon_nw) + print lon, viewport_lon_se + + print "Percentages: ", new_lat_gps_range_percentage, new_lon_gps_range_percentage + + x = new_lon_gps_range_percentage * pixel_per_lon + y = new_lat_gps_range_percentage * pixel_per_lat + + return int(x), int(y) + + def add_gps_location(self, lat, lon, shape, size, fill): + x, y = self._get_cartesian(lat, lon) + draw = PIL.ImageDraw.Draw(self.big_image) + if shape is "ellipsis": + draw.ellipsis((x-size, y-size, x+size, y+size), fill) + else: + draw.rectangle([x-size, y-size, x+size, y+size], fill) + self.update() + + + def center_display(self, lat, lon): + x, y = self._get_cartesian(lat, lon) + self.center_x = x + self.center_y = y + + self.left_x = (self.center_x - (self.width/2)) + self.upper_y = (self.center_y - (self.height/2)) + self.update() + + + def update_rover_map_location(self, lat, lon): + print "I did nothing" diff --git a/ground_station/resources/core/mappingtest.py b/ground_station/resources/core/mappingtest.py old mode 100644 new mode 100755 index 92adb18..efb0880 --- a/ground_station/resources/core/mappingtest.py +++ b/ground_station/resources/core/mappingtest.py @@ -1,7 +1,24 @@ +#!/usr/bin/python + import mapping +import PIL -obj = mapping.GMapsStitcher(2000, 2000, 44.57078, -123.275998, 18, 'terrain', None, 20) +obj = mapping.GMapsStitcher(2000, 2000, 44.567161, -123.278432, 18, 'terrain', None, 20) -obj.useZoom(1.2) +obj.display_image.save("unzoomed.png") +# draw = PIL.ImageDraw.ImageDraw(obj.big_image) +# draw.rectangle([950, 950, 1050, 1050], fill=128) +# lat, lng = obj.move_latlon(44.559919, -123.280723) +# draw.rectangle([lng-300, lat-300, lng+300, lat+300], fill=328) +# obj.big_image.save("toobig.jpg") +# obj.display_image.save("zoomed.jpg") -obj.display_image.save("display_image.jpg") +obj.add_gps_location(44.559919, -123.280723, "square", 50, (225,225,225,225)) +obj.add_gps_location(44.565094, -123.276110, "square", 50, (225,225,225,225)) +obj.add_gps_location(44.565777, -123.278902, "square", 50, (225,225,225,225)) +obj.display_image.save("box.png") +obj.center_display(44.567161, -123.278432) +obj.display_image.save("centered.png") +obj.big_image.save("toobig.png") + +obj.obj_print() From 5f12d8074f8fcfb799f6ac3493cb39081bb7f7c3 Mon Sep 17 00:00:00 2001 From: Chris Pham Date: Thu, 1 Feb 2018 19:55:57 -0800 Subject: [PATCH 26/28] starting on map updatiing --- ground_station/resources/core/mapping.py | 103 ++----------------- ground_station/resources/core/mappingtest.py | 6 +- 2 files changed, 14 insertions(+), 95 deletions(-) diff --git a/ground_station/resources/core/mapping.py b/ground_station/resources/core/mapping.py index c174cb6..b83c409 100644 --- a/ground_station/resources/core/mapping.py +++ b/ground_station/resources/core/mapping.py @@ -34,7 +34,6 @@ import signing # Constants ##################################### _KEYS = [] - # Number of pixels in half the earth's circumference at zoom = 21 _EARTHPIX = 268435456 # Number of decimal places for rounding coordinates @@ -58,7 +57,7 @@ print _KEYS class GMapsStitcher(object): def __init__(self, width, height, latitude, longitude, zoom, - maptype, radius_meters=None, num_tiles=4): + maptype, radius_meters=None, num_tiles=4, debug=False): self.latitude = latitude self.longitude = longitude self.start_latitude = latitude @@ -70,6 +69,7 @@ class GMapsStitcher(object): self.radius_meters = radius_meters self.num_tiles = num_tiles self.display_image = self._new_image(width, height) + self.debug = debug # Get the big image here self._fetch() @@ -112,9 +112,7 @@ class GMapsStitcher(object): else: # make the url url = urlbase % specs - print url url = signing.sign_url(url, _KEYS[1]) - print url result = urllib2.urlopen(urllib2.Request(url)).read() tile_object = PIL.Image.open(BytesIO(result)) if not os.path.exists('Resources/Maps'): @@ -153,17 +151,8 @@ class GMapsStitcher(object): for j in range(self.num_tiles): lon = self._pixels_to_lon(j, lon_pixels) - if j is 0: - self.big_map_lon_small = lon - if j is 19: - self.big_map_lon_big = lon for k in range(self.num_tiles): lat = self._pixels_to_lat(k, lat_pixels) - #print "j, k", j, k - if k is 0: - self.big_map_lat_small = lat - if k is 19: - self.big_map_lat_big = lat tile = self._grab_tile(lon, lat) big_image.paste(tile, (j * _TILESIZE, k * _TILESIZE)) @@ -174,9 +163,6 @@ class GMapsStitcher(object): south = self._pixels_to_lat(self.num_tiles - 1, lat_pixels) return big_image, (north, west), (south, east) - def get_image(self): - return self.display_image - def move_pix(self, dx, dy): self._constrain_x(dx) self._constrain_y(dy) @@ -197,83 +183,14 @@ class GMapsStitcher(object): def _fetch(self): self.big_image, self.northwest, self.southeast = self.fetch_tiles() - - def _merc_proj(self, lat): - return math.log(math.tan((lat/2.) + (math.pi/4.))) - def move_latlon(self, lat, lon): - # print "Lat", self.big_map_lat_small, self.big_map_lat_big - # print "Lng", self.big_map_lon_small, self.big_map_lon_big - - # east = math.radians(self.big_map_lon_big) - # west = math.radians(self.big_map_lon_small) - # north = math.radians(self.big_map_lat_small) - # south = math.radians(self.big_map_lat_big) - # print north, south - # print "east-west", (east-west) - - # y_min = self._merc_proj(south) - # y_max = self._merc_proj(north) - - # x_factor = self.big_size/(east-west) - # print x_factor - # y_factor = self.big_size/(y_max - y_min) - # print y_factor - - # print "rads lon", math.radians(lon) - # x = (math.radians(lon) - east) * x_factor - # y = (y_max - self._merc_proj(math.radians(lat))) * y_factor - # print x, y - # return x*.1, y - - viewport_lat_nw, viewport_lon_nw = self.northwest - viewport_lat_se, viewport_lon_se = self.southeast - print "Lat:", viewport_lat_nw, viewport_lat_se - print "Lon:", viewport_lon_nw, viewport_lon_se - - viewport_lat_diff = viewport_lat_nw - viewport_lat_se - viewport_lon_diff = viewport_lon_se - viewport_lon_nw - - print viewport_lon_diff, viewport_lat_diff - - bigimage_width = self.big_image.size[0] - bigimage_height = self.big_image.size[1] - - pixel_per_lat = bigimage_height / viewport_lat_diff - pixel_per_lon = bigimage_width / viewport_lon_diff - print "Pixel per:", pixel_per_lat, pixel_per_lon - - new_lat_gps_range_percentage = (viewport_lat_nw - lat) - new_lon_gps_range_percentage = (lon - viewport_lon_nw) - print lon, viewport_lon_se - - print "Percentages: ", new_lat_gps_range_percentage, new_lon_gps_range_percentage - - x = new_lon_gps_range_percentage * pixel_per_lon - y = new_lat_gps_range_percentage * pixel_per_lat - - print x, y - return y, x - - # east = (self.big_map_lon_big) - (.0034) - # west = (self.big_map_lon_small) + (.0034) - # north = (self.big_map_lat_small) + (.0025) - # south = (self.big_map_lat_big) - (.0025) - # lng_diff = west - east - # lat_diff = north - south - - - # x = int(((east - lon)/lng_diff)*self.big_image.size[0]) - # y = int(((north - lat)/lat_diff)*self.big_image.size[1]) - - # print x, y - # return x, y + x, y = self._get_cartesian(lat, lon) def _get_cartesian(self, lat, lon): viewport_lat_nw, viewport_lon_nw = self.northwest viewport_lat_se, viewport_lon_se = self.southeast - print "Lat:", viewport_lat_nw, viewport_lat_se - print "Lon:", viewport_lon_nw, viewport_lon_se + # print "Lat:", viewport_lat_nw, viewport_lat_se + # print "Lon:", viewport_lon_nw, viewport_lon_se viewport_lat_diff = viewport_lat_nw - viewport_lat_se viewport_lon_diff = viewport_lon_se - viewport_lon_nw @@ -285,13 +202,13 @@ class GMapsStitcher(object): pixel_per_lat = bigimage_height / viewport_lat_diff pixel_per_lon = bigimage_width / viewport_lon_diff - print "Pixel per:", pixel_per_lat, pixel_per_lon + # print "Pixel per:", pixel_per_lat, pixel_per_lon new_lat_gps_range_percentage = (viewport_lat_nw - lat) new_lon_gps_range_percentage = (lon - viewport_lon_nw) - print lon, viewport_lon_se + # print lon, viewport_lon_se - print "Percentages: ", new_lat_gps_range_percentage, new_lon_gps_range_percentage + # print "Percentages: ", new_lat_gps_range_percentage, new_lon_gps_range_percentage x = new_lon_gps_range_percentage * pixel_per_lon y = new_lat_gps_range_percentage * pixel_per_lat @@ -305,7 +222,6 @@ class GMapsStitcher(object): draw.ellipsis((x-size, y-size, x+size, y+size), fill) else: draw.rectangle([x-size, y-size, x+size, y+size], fill) - self.update() @@ -321,3 +237,6 @@ class GMapsStitcher(object): def update_rover_map_location(self, lat, lon): print "I did nothing" + + def draw_circle(self, lat, lon, radius, fill): + print "I did nothing" diff --git a/ground_station/resources/core/mappingtest.py b/ground_station/resources/core/mappingtest.py index efb0880..2704c59 100755 --- a/ground_station/resources/core/mappingtest.py +++ b/ground_station/resources/core/mappingtest.py @@ -13,9 +13,9 @@ obj.display_image.save("unzoomed.png") # obj.big_image.save("toobig.jpg") # obj.display_image.save("zoomed.jpg") -obj.add_gps_location(44.559919, -123.280723, "square", 50, (225,225,225,225)) -obj.add_gps_location(44.565094, -123.276110, "square", 50, (225,225,225,225)) -obj.add_gps_location(44.565777, -123.278902, "square", 50, (225,225,225,225)) +obj.add_gps_location(44.559919, -123.280723, "square", 50, (00, 00, 00, 256)) +obj.add_gps_location(44.565094, -123.276110, "square", 50, (00, 00, 00, 256)) +obj.add_gps_location(44.565777, -123.278902, "square", 50, (00, 00, 00, 256)) obj.display_image.save("box.png") obj.center_display(44.567161, -123.278432) obj.display_image.save("centered.png") From 75adf70d5bfba0e4b7b48bf7cefbc88feb68f4de Mon Sep 17 00:00:00 2001 From: Chris Pham Date: Fri, 2 Feb 2018 11:30:16 -0800 Subject: [PATCH 27/28] define __str__ --- ground_station/resources/core/mapping.py | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/ground_station/resources/core/mapping.py b/ground_station/resources/core/mapping.py index b83c409..f857882 100644 --- a/ground_station/resources/core/mapping.py +++ b/ground_station/resources/core/mapping.py @@ -74,10 +74,21 @@ class GMapsStitcher(object): # Get the big image here self._fetch() self.center_display(latitude, longitude) - - def obj_print(self): - print("Center of the map is at "+ str(self.center_x)+"x"+str(self.center_y)) - print("The start of the box is at "+str(self.left_x)+"x"+str(self.upper_y)) + + def __str__(self): + string_builder = "" + string_builder += "Center of the displayed map: %dx%d\n" % (self.center_x, self.center_y) + string_builder += "Center of the big map: %dx%d\n" % (self.start_longitude, self.start_longitude) + string_builder += "Current latitude is: %4fx%4f\n" % (self.longitude, self.latitude) + string_builder += "The top-left of the box: %dx%d\n" % (self.left_x, self.upper_y) + string_builder += "Number of tiles genreated: %dx%d\n" % (self.num_tiles, self.num_tiles) + string_builder += "Map Type: %s\n" % (self.maptype) + string_builder += "Zoom Level: %s\n" % (self.zoom) + string_builder += "Dimensions of Big Image: %dx%d\n" % (self.big_image.size[0], self.big_image.size[1]) + string_builder += "Dimensions of Displayed Image: %dx%d\n" % (self.width, self.height) + string_builder += "LatLong of Northwest Corner: %4fx%4f\n" % (self.northwest) + string_builder += "LatLong of Southeast Corner: %4fx%4f\n" % (self.southeast) + return string_builder def _new_image(self, width, height): return PIL.Image.new('RGBA', (width, height)) @@ -195,7 +206,7 @@ class GMapsStitcher(object): viewport_lat_diff = viewport_lat_nw - viewport_lat_se viewport_lon_diff = viewport_lon_se - viewport_lon_nw - print viewport_lon_diff, viewport_lat_diff + # print viewport_lon_diff, viewport_lat_diff bigimage_width = self.big_image.size[0] bigimage_height = self.big_image.size[1] From d012360da50b074efb9a1cc1f7c1e0dacda207e7 Mon Sep 17 00:00:00 2001 From: Chris Pham Date: Fri, 2 Feb 2018 13:11:06 -0800 Subject: [PATCH 28/28] remove prints --- ground_station/resources/core/mapping.py | 13 +++++-------- ground_station/resources/core/mappingtest.py | 2 +- 2 files changed, 6 insertions(+), 9 deletions(-) diff --git a/ground_station/resources/core/mapping.py b/ground_station/resources/core/mapping.py index f857882..d3708a7 100644 --- a/ground_station/resources/core/mapping.py +++ b/ground_station/resources/core/mapping.py @@ -51,9 +51,6 @@ for i in file_pointer: _KEYS.append(i.rstrip()) file_pointer.close() -print _KEYS - - class GMapsStitcher(object): def __init__(self, width, height, latitude, longitude, zoom, @@ -77,17 +74,17 @@ class GMapsStitcher(object): def __str__(self): string_builder = "" - string_builder += "Center of the displayed map: %dx%d\n" % (self.center_x, self.center_y) - string_builder += "Center of the big map: %dx%d\n" % (self.start_longitude, self.start_longitude) - string_builder += "Current latitude is: %4fx%4f\n" % (self.longitude, self.latitude) + string_builder += "Center of the displayed map: %4f, %4f\n" % (self.center_x, self.center_y) + string_builder += "Center of the big map: %4fx%4f\n" % (self.start_longitude, self.start_longitude) + string_builder += "Current latitude is: %4f, %4f\n" % (self.longitude, self.latitude) string_builder += "The top-left of the box: %dx%d\n" % (self.left_x, self.upper_y) string_builder += "Number of tiles genreated: %dx%d\n" % (self.num_tiles, self.num_tiles) string_builder += "Map Type: %s\n" % (self.maptype) string_builder += "Zoom Level: %s\n" % (self.zoom) string_builder += "Dimensions of Big Image: %dx%d\n" % (self.big_image.size[0], self.big_image.size[1]) string_builder += "Dimensions of Displayed Image: %dx%d\n" % (self.width, self.height) - string_builder += "LatLong of Northwest Corner: %4fx%4f\n" % (self.northwest) - string_builder += "LatLong of Southeast Corner: %4fx%4f\n" % (self.southeast) + string_builder += "LatLong of Northwest Corner: %4f, %4f\n" % (self.northwest) + string_builder += "LatLong of Southeast Corner: %4f, %4f\n" % (self.southeast) return string_builder def _new_image(self, width, height): diff --git a/ground_station/resources/core/mappingtest.py b/ground_station/resources/core/mappingtest.py index 2704c59..4a5414a 100755 --- a/ground_station/resources/core/mappingtest.py +++ b/ground_station/resources/core/mappingtest.py @@ -21,4 +21,4 @@ obj.center_display(44.567161, -123.278432) obj.display_image.save("centered.png") obj.big_image.save("toobig.png") -obj.obj_print() +print obj