From bb8ed586e278eaa18b1861a0949afa53a743c876 Mon Sep 17 00:00:00 2001 From: Chris Pham Date: Thu, 18 Jan 2018 10:37:41 -0800 Subject: [PATCH 01/72] 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/72] 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/72] 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/72] 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/72] 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/72] 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/72] 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/72] 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/72] 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/72] 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/72] 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/72] 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/72] 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/72] 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/72] 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/72] 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/72] 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/72] 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/72] 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/72] 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/72] 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/72] 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/72] 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/72] 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/72] 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/72] 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/72] 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/72] 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 From d42ec20640a37152d13b3fa672bb6f2e0a158a8b Mon Sep 17 00:00:00 2001 From: Chris Pham Date: Thu, 18 Jan 2018 10:37:41 -0800 Subject: [PATCH 29/72] 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 619e98772adeeb6bf97a67d6a751bb30a47d08db Mon Sep 17 00:00:00 2001 From: Chris Pham Date: Thu, 18 Jan 2018 10:40:47 -0800 Subject: [PATCH 30/72] 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 d1939b5e6907f078f4f46bdd45024dcf8ae12c01 Mon Sep 17 00:00:00 2001 From: Chris Pham Date: Thu, 18 Jan 2018 10:47:56 -0800 Subject: [PATCH 31/72] 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 666f522bf5947794d802e8cbbf221ac004fc4eed Mon Sep 17 00:00:00 2001 From: Chris Pham Date: Thu, 18 Jan 2018 10:53:39 -0800 Subject: [PATCH 32/72] 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 494c76b42f31b6fe9d3f6e8660b2024d7beb4cd9 Mon Sep 17 00:00:00 2001 From: Chris Pham Date: Thu, 18 Jan 2018 10:58:24 -0800 Subject: [PATCH 33/72] fixed fp naming conventions --- ground_station/resources/core/mapping.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/ground_station/resources/core/mapping.py b/ground_station/resources/core/mapping.py index 8a9531d..a88ff67 100644 --- a/ground_station/resources/core/mapping.py +++ b/ground_station/resources/core/mapping.py @@ -12,9 +12,15 @@ import time ##################################### # Constants ##################################### +<<<<<<< 666f522bf5947794d802e8cbbf221ac004fc4eed fp = open('key', w) _KEY = fp.read().rstrip() fp.close() +======= +file_pointer = open('key', 'w') +_KEY = file_pointer.read().rstrip() +file_pointer.close() +>>>>>>> fixed fp naming conventions # Number of pixels in half the earth's circumference at zoom = 21 _EARTHPIX = 268435456 From 6a2a8c156a49aa46445391767f222198907cc0f5 Mon Sep 17 00:00:00 2001 From: Chris Pham Date: Thu, 18 Jan 2018 11:09:09 -0800 Subject: [PATCH 34/72] 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 a88ff67..5146d56 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 ##################################### @@ -31,4 +49,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 37bc8f62add1e9380e87d06d0f05d09549b20cec Mon Sep 17 00:00:00 2001 From: Chris Pham Date: Thu, 18 Jan 2018 11:21:05 -0800 Subject: [PATCH 35/72] 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 5146d56..94a147e 100644 --- a/ground_station/resources/core/mapping.py +++ b/ground_station/resources/core/mapping.py @@ -52,4 +52,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 c43517f45e728378e34acb67f2834229a5c6d36f Mon Sep 17 00:00:00 2001 From: Chris Pham Date: Thu, 18 Jan 2018 12:14:06 -0800 Subject: [PATCH 36/72] 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 94a147e..a4c5323 100644 --- a/ground_station/resources/core/mapping.py +++ b/ground_station/resources/core/mapping.py @@ -53,9 +53,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 @@ -63,5 +63,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 467614fc2a085733fb556baada93374648f3b78a Mon Sep 17 00:00:00 2001 From: Chris Pham Date: Thu, 18 Jan 2018 12:24:01 -0800 Subject: [PATCH 37/72] 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 a4c5323..695c110 100644 --- a/ground_station/resources/core/mapping.py +++ b/ground_station/resources/core/mapping.py @@ -74,6 +74,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 6e540dfe067735e0cab1f75b8ee70d48c74f4075 Mon Sep 17 00:00:00 2001 From: Chris Pham Date: Thu, 18 Jan 2018 12:43:03 -0800 Subject: [PATCH 38/72] 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 695c110..2b57143 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 @@ -74,6 +74,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 f4622bc64b3ed3b14013271b737635ac0370c12b Mon Sep 17 00:00:00 2001 From: Chris Pham Date: Thu, 18 Jan 2018 13:00:53 -0800 Subject: [PATCH 39/72] 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 2b57143..648c035 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 @@ -73,7 +76,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?' @@ -99,6 +102,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 a35691bf599688a863f4e90865a78c4e2a133f49 Mon Sep 17 00:00:00 2001 From: Chris Pham Date: Thu, 18 Jan 2018 13:07:21 -0800 Subject: [PATCH 40/72] 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 648c035..d45cf0a 100644 --- a/ground_station/resources/core/mapping.py +++ b/ground_station/resources/core/mapping.py @@ -66,6 +66,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)) @@ -109,6 +110,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 3a960d44f7d3b9356e927574586b44e218a5d57f Mon Sep 17 00:00:00 2001 From: Chris Pham Date: Thu, 18 Jan 2018 13:21:38 -0800 Subject: [PATCH 41/72] 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 d45cf0a..5deeb47 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 @@ -67,7 +65,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)) @@ -83,7 +81,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' @@ -92,7 +90,7 @@ class GMapsStitcher(object): if os.path.isfile(filename): tile_object = PIL.Image.open(filename) - + # If file on filesystem else: # make the url @@ -113,3 +111,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 475c3aebcd427648a72fee73da94bcf5a3543122 Mon Sep 17 00:00:00 2001 From: Chris Pham Date: Thu, 18 Jan 2018 13:23:48 -0800 Subject: [PATCH 42/72] 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 1f1a1d711287e42a728b6b89358091441621456a Mon Sep 17 00:00:00 2001 From: Chris Pham Date: Sat, 20 Jan 2018 13:06:28 -0800 Subject: [PATCH 43/72] 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 5deeb47..28c5f9f 100644 --- a/ground_station/resources/core/mapping.py +++ b/ground_station/resources/core/mapping.py @@ -75,6 +75,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 @@ -115,3 +118,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 81c770fed68b1b4fde00934b9cc72b6b8cfd8b0a Mon Sep 17 00:00:00 2001 From: Chris Pham Date: Sat, 20 Jan 2018 13:24:32 -0800 Subject: [PATCH 44/72] 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 28c5f9f..8bbaaac 100644 --- a/ground_station/resources/core/mapping.py +++ b/ground_station/resources/core/mapping.py @@ -75,7 +75,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): @@ -117,12 +118,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 1bd9af00f206c528febfe9b024e50b8bd4ee73fb Mon Sep 17 00:00:00 2001 From: Chris Pham Date: Sat, 20 Jan 2018 13:43:47 -0800 Subject: [PATCH 45/72] 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 8bbaaac..a1f75d7 100644 --- a/ground_station/resources/core/mapping.py +++ b/ground_station/resources/core/mapping.py @@ -66,8 +66,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 @@ -79,14 +79,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 @@ -118,8 +118,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 @@ -130,3 +130,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 a37e8946051780c4dad6a29d5915e1536ab52cc2 Mon Sep 17 00:00:00 2001 From: Chris Pham Date: Sat, 20 Jan 2018 13:57:11 -0800 Subject: [PATCH 46/72] Fixed to fit PEP --- ground_station/resources/core/mapping.py | 31 ++++++++++++------------ 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/ground_station/resources/core/mapping.py b/ground_station/resources/core/mapping.py index a1f75d7..f6e29cc 100644 --- a/ground_station/resources/core/mapping.py +++ b/ground_station/resources/core/mapping.py @@ -31,26 +31,28 @@ import PIL.Image ##################################### # Constants ##################################### +<<<<<<< 1bd9af00f206c528febfe9b024e50b8bd4ee73fb <<<<<<< 666f522bf5947794d802e8cbbf221ac004fc4eed -fp = open('key', w) -_KEY = fp.read().rstrip() -fp.close() ======= +======= +_KEYS = [] +>>>>>>> Fixed to fit PEP file_pointer = open('key', 'w') -_KEY = file_pointer.read().rstrip() +for i in file_pointer: + _KEYS.append(file_pointer.readline().rstrip()) file_pointer.close() >>>>>>> fixed fp naming conventions # 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): @@ -86,7 +88,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 @@ -113,12 +115,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,): @@ -130,20 +132,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 5fa02813f3024ad8516f83ea0a185e82d850301e Mon Sep 17 00:00:00 2001 From: Chris Pham Date: Sat, 20 Jan 2018 14:14:44 -0800 Subject: [PATCH 47/72] 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 f6e29cc..ca82fcf 100644 --- a/ground_station/resources/core/mapping.py +++ b/ground_station/resources/core/mapping.py @@ -85,11 +85,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 1961da734b5b26ff3199ccead3d0a80c40ad23ce Mon Sep 17 00:00:00 2001 From: Chris Pham Date: Sat, 20 Jan 2018 16:32:58 -0800 Subject: [PATCH 48/72] Add testing file with updated gitignore for jpgs --- .gitignore | 5 +- ground_station/resources/core/mapping.py | 33 ++++++------ ground_station/resources/core/mappingtest.py | 5 ++ ground_station/resources/core/signing.py | 53 ++++++++++++++++++++ 4 files changed, 81 insertions(+), 15 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 ca82fcf..0ea8f62 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,21 +27,17 @@ from io import StringIO, BytesIO import os import time import PIL.Image +import signing ##################################### # Constants ##################################### -<<<<<<< 1bd9af00f206c528febfe9b024e50b8bd4ee73fb -<<<<<<< 666f522bf5947794d802e8cbbf221ac004fc4eed -======= -======= _KEYS = [] ->>>>>>> Fixed to fit PEP + file_pointer = open('key', 'w') for i in file_pointer: _KEYS.append(file_pointer.readline().rstrip()) file_pointer.close() ->>>>>>> fixed fp naming conventions # Number of pixels in half the earth's circumference at zoom = 21 _EARTHPIX = 268435456 @@ -54,6 +50,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, @@ -85,11 +88,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 @@ -101,8 +104,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') @@ -123,14 +128,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 d882a936e2b20b8b73f53fb96dbd4f84e1c52dc2 Mon Sep 17 00:00:00 2001 From: Chris Pham Date: Thu, 25 Jan 2018 10:49:36 -0800 Subject: [PATCH 49/72] 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 0ea8f62..a17bbd9 100644 --- a/ground_station/resources/core/mapping.py +++ b/ground_station/resources/core/mapping.py @@ -124,9 +124,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 c7074b88d4fdaac628d88c306f46e19a9115047d Mon Sep 17 00:00:00 2001 From: Chris Pham Date: Thu, 25 Jan 2018 15:01:35 -0800 Subject: [PATCH 50/72] 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 a17bbd9..2339638 100644 --- a/ground_station/resources/core/mapping.py +++ b/ground_station/resources/core/mapping.py @@ -70,6 +70,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)) @@ -152,3 +163,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 8bdfbae4ed03b628f22fd54fbbf9eb87401400f9 Mon Sep 17 00:00:00 2001 From: Chris Pham Date: Thu, 1 Feb 2018 19:25:54 -0800 Subject: [PATCH 51/72] 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 2339638..a32ada7 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 ##################################### @@ -49,6 +50,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: @@ -64,6 +66,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 @@ -71,19 +75,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 @@ -99,11 +101,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 @@ -151,21 +153,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) @@ -174,7 +182,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() @@ -189,12 +197,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 4c19caf8bd01cfe1e0b49b7da68eeb8a94b34630 Mon Sep 17 00:00:00 2001 From: Chris Pham Date: Thu, 1 Feb 2018 19:55:57 -0800 Subject: [PATCH 52/72] starting on map updatiing --- ground_station/resources/core/mapping.py | 108 ++----------------- ground_station/resources/core/mappingtest.py | 6 +- 2 files changed, 14 insertions(+), 100 deletions(-) diff --git a/ground_station/resources/core/mapping.py b/ground_station/resources/core/mapping.py index a32ada7..b83c409 100644 --- a/ground_station/resources/core/mapping.py +++ b/ground_station/resources/core/mapping.py @@ -34,12 +34,6 @@ 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 # Number of decimal places for rounding coordinates @@ -63,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 @@ -75,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() @@ -117,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'): @@ -158,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)) @@ -179,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) @@ -202,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 @@ -290,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 @@ -310,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() @@ -326,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 07465451514e1b8e1033bc25f28383ef3712e43d Mon Sep 17 00:00:00 2001 From: Chris Pham Date: Fri, 2 Feb 2018 11:30:16 -0800 Subject: [PATCH 53/72] 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 8961b7061af818d9c49a41adf4c6cc004109800b Mon Sep 17 00:00:00 2001 From: Chris Pham Date: Fri, 2 Feb 2018 13:11:06 -0800 Subject: [PATCH 54/72] 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 From 07534f8487ba8a04d63e73c22385158479c3c6cc Mon Sep 17 00:00:00 2001 From: Chris Pham Date: Sat, 3 Feb 2018 13:45:51 -0800 Subject: [PATCH 55/72] Starting of mapping class refactor --- ground_station/resources/core/MapHelper.py | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 ground_station/resources/core/MapHelper.py diff --git a/ground_station/resources/core/MapHelper.py b/ground_station/resources/core/MapHelper.py new file mode 100644 index 0000000..d3f2cfe --- /dev/null +++ b/ground_station/resources/core/MapHelper.py @@ -0,0 +1,3 @@ +class MapHelper(object): + def __init__(self): + return From 06c605ebd5780e65f1f7ad077ef5cf7a136d2a18 Mon Sep 17 00:00:00 2001 From: Chris Pham Date: Sat, 3 Feb 2018 13:46:46 -0800 Subject: [PATCH 56/72] remove idea file --- ground_station/.idea/workspace.xml | 527 ----------------------------- 1 file changed, 527 deletions(-) delete mode 100644 ground_station/.idea/workspace.xml diff --git a/ground_station/.idea/workspace.xml b/ground_station/.idea/workspace.xml deleted file mode 100644 index 20e90b8..0000000 --- a/ground_station/.idea/workspace.xml +++ /dev/null @@ -1,527 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - true - DEFINITION_ORDER - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - project - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1510962234686 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - AAAAsNHwc2N+8Zbshoe1tr2XDVkf8aGU/l0YnN7t0gOfSXYMOeQZo2dVv+GbvgrFH5EF+uviJzRPHArF3uX1Vb0CuhmnSE0NSLdGfSjyMrpWsoZyS3WBI979X8Y/8lSe/g2O65pafrceXlU4ySEbA9w/JNU42PtXijURL7sXfaZ8kxhE5bYQlRppUyBo5g/qgzvj275mbp6uuZ5w9ssFsOzrJGsGulioJmZ9L9P6O6PVj2sPT2AEw+jC8eGiiappc0lWOA== - - \ No newline at end of file From e65d4e5067d4b3f9b1223a57f7666131e2c2cf6f Mon Sep 17 00:00:00 2001 From: Chris Pham Date: Sat, 3 Feb 2018 13:50:32 -0800 Subject: [PATCH 57/72] Move new_image function to helper --- ground_station/resources/core/MapHelper.py | 5 +++++ ground_station/resources/core/mapping.py | 10 ++++------ 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/ground_station/resources/core/MapHelper.py b/ground_station/resources/core/MapHelper.py index d3f2cfe..1d90360 100644 --- a/ground_station/resources/core/MapHelper.py +++ b/ground_station/resources/core/MapHelper.py @@ -1,3 +1,8 @@ +import PIL.Image + class MapHelper(object): def __init__(self): return + + def new_image(self, width, height): + return PIL.Image.new('RGBA', (width, height)) diff --git a/ground_station/resources/core/mapping.py b/ground_station/resources/core/mapping.py index d3708a7..d76cbff 100644 --- a/ground_station/resources/core/mapping.py +++ b/ground_station/resources/core/mapping.py @@ -26,9 +26,9 @@ import urllib2 from io import StringIO, BytesIO import os import time -import PIL.Image import PIL.ImageDraw import signing +import MapHelper ##################################### # Constants @@ -55,6 +55,7 @@ class GMapsStitcher(object): def __init__(self, width, height, latitude, longitude, zoom, maptype, radius_meters=None, num_tiles=4, debug=False): + helper = MapHelper.MapHelper() self.latitude = latitude self.longitude = longitude self.start_latitude = latitude @@ -65,7 +66,7 @@ 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.display_image = helper.new_image(width, height) self.debug = debug # Get the big image here @@ -87,9 +88,6 @@ class GMapsStitcher(object): string_builder += "LatLong of Southeast Corner: %4f, %4f\n" % (self.southeast) return string_builder - def _new_image(self, width, height): - return PIL.Image.new('RGBA', (width, height)) - def _fast_round(self, value, precision): return int(value * 10 ** precision) / 10. ** precision @@ -155,7 +153,7 @@ class GMapsStitcher(object): sin_lat = math.sin(math.radians(self.latitude)) lat_pixels = _EARTHPIX - _PIXRAD * math.log((1+sin_lat)/(1-sin_lat))/2 self.big_size = self.num_tiles * _TILESIZE - big_image = self._new_image(self.big_size, self.big_size) + big_image = self.helper.new_image(self.big_size, self.big_size) for j in range(self.num_tiles): lon = self._pixels_to_lon(j, lon_pixels) From 37303e3a95020e41aadea474e2d6e95c543f5af0 Mon Sep 17 00:00:00 2001 From: Chris Pham Date: Sat, 3 Feb 2018 13:53:21 -0800 Subject: [PATCH 58/72] Moved fast_round to helper --- ground_station/resources/core/MapHelper.py | 3 +++ ground_station/resources/core/mapping.py | 9 +++------ 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/ground_station/resources/core/MapHelper.py b/ground_station/resources/core/MapHelper.py index 1d90360..66a99fe 100644 --- a/ground_station/resources/core/MapHelper.py +++ b/ground_station/resources/core/MapHelper.py @@ -6,3 +6,6 @@ class MapHelper(object): def new_image(self, width, height): return PIL.Image.new('RGBA', (width, height)) + + def fast_round(self, value, precision): + return int(value * 10 ** precision) / 10. ** precision diff --git a/ground_station/resources/core/mapping.py b/ground_station/resources/core/mapping.py index d76cbff..9b51f9a 100644 --- a/ground_station/resources/core/mapping.py +++ b/ground_station/resources/core/mapping.py @@ -88,9 +88,6 @@ class GMapsStitcher(object): string_builder += "LatLong of Southeast Corner: %4f, %4f\n" % (self.southeast) return string_builder - 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) @@ -105,7 +102,7 @@ class GMapsStitcher(object): urlbase += 'center=%.4f,%.4f&zoom=%d&maptype=%s&size=%dx%d&format=png&key=%s' # Fill the formatting - specs = self._fast_round(latitude, 4), self._fast_round(longitude, 4), self.zoom, self.maptype, _TILESIZE, _TILESIZE, _KEYS[0] + specs = self.helper.fast_round(latitude, _DEGREE_PRECISION), self.helper.fast_round(longitude, _DEGREE_PRECISION), self.zoom, self.maptype, _TILESIZE, _TILESIZE, _KEYS[0] filename = 'Resources/Maps/' + ('%.4f_%.4f_%d_%s_%d_%d_%s' % specs) + '.png' # Tile Image object @@ -141,8 +138,8 @@ class GMapsStitcher(object): 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) + self.latitude = self.helper.fast_round(self.latitude, _DEGREE_PRECISION) + self.longitude = self.helper.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: From 0cbd593380d86ca3d479b7e40167273641c8c04d Mon Sep 17 00:00:00 2001 From: Chris Pham Date: Sat, 3 Feb 2018 13:56:15 -0800 Subject: [PATCH 59/72] Add pixels_to_degrees to helper --- ground_station/resources/core/MapHelper.py | 3 +++ ground_station/resources/core/mapping.py | 7 ++----- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/ground_station/resources/core/MapHelper.py b/ground_station/resources/core/MapHelper.py index 66a99fe..8c4218c 100644 --- a/ground_station/resources/core/MapHelper.py +++ b/ground_station/resources/core/MapHelper.py @@ -9,3 +9,6 @@ class MapHelper(object): 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) \ No newline at end of file diff --git a/ground_station/resources/core/mapping.py b/ground_station/resources/core/mapping.py index 9b51f9a..012e4bd 100644 --- a/ground_station/resources/core/mapping.py +++ b/ground_station/resources/core/mapping.py @@ -88,9 +88,6 @@ class GMapsStitcher(object): string_builder += "LatLong of Southeast Corner: %4f, %4f\n" % (self.southeast) return string_builder - def _pixels_to_degrees(self, pixels, zoom): - return pixels * 2 ** (21-zoom) - 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))) @@ -128,13 +125,13 @@ 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) + degrees = self.helper.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 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))) + math.exp(((lat_pixels + self.helper.pixels_to_degrees((iterator - self.num_tiles / 2) * _TILESIZE, self.zoom)) - _EARTHPIX) / _PIXRAD))) def fetch_tiles(self): # cap floats to precision amount From 10c9dc8451a582e67e8475e2bf161054191f1d02 Mon Sep 17 00:00:00 2001 From: Chris Pham Date: Sat, 3 Feb 2018 14:02:23 -0800 Subject: [PATCH 60/72] Make static functions and self reference for helper --- ground_station/resources/core/MapHelper.py | 11 ++++++----- ground_station/resources/core/mapping.py | 5 +++-- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/ground_station/resources/core/MapHelper.py b/ground_station/resources/core/MapHelper.py index 8c4218c..86724fc 100644 --- a/ground_station/resources/core/MapHelper.py +++ b/ground_station/resources/core/MapHelper.py @@ -1,14 +1,15 @@ import PIL.Image class MapHelper(object): - def __init__(self): - return - def new_image(self, width, height): + @staticmethod + def new_image(width, height): return PIL.Image.new('RGBA', (width, height)) - def fast_round(self, value, precision): + @staticmethod + def fast_round(value, precision): return int(value * 10 ** precision) / 10. ** precision - def pixels_to_degrees(self, pixels, zoom): + @staticmethod + def pixels_to_degrees(pixels, zoom): return pixels * 2 ** (21-zoom) \ No newline at end of file diff --git a/ground_station/resources/core/mapping.py b/ground_station/resources/core/mapping.py index 012e4bd..4c44881 100644 --- a/ground_station/resources/core/mapping.py +++ b/ground_station/resources/core/mapping.py @@ -55,7 +55,7 @@ class GMapsStitcher(object): def __init__(self, width, height, latitude, longitude, zoom, maptype, radius_meters=None, num_tiles=4, debug=False): - helper = MapHelper.MapHelper() + self.helper = MapHelper.MapHelper() self.latitude = latitude self.longitude = longitude self.start_latitude = latitude @@ -66,8 +66,9 @@ class GMapsStitcher(object): self.maptype = maptype self.radius_meters = radius_meters self.num_tiles = num_tiles - self.display_image = helper.new_image(width, height) + self.display_image = self.helper.new_image(width, height) self.debug = debug + # Get the big image here self._fetch() From 4a66dbc0b5954672d4377a1c9e07c53ccd1d7323 Mon Sep 17 00:00:00 2001 From: Chris Pham Date: Sat, 3 Feb 2018 14:06:46 -0800 Subject: [PATCH 61/72] Moved pixels_to_meters to Helper --- ground_station/resources/core/MapHelper.py | 8 +++++++- ground_station/resources/core/mapping.py | 6 +----- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/ground_station/resources/core/MapHelper.py b/ground_station/resources/core/MapHelper.py index 86724fc..e9c3d98 100644 --- a/ground_station/resources/core/MapHelper.py +++ b/ground_station/resources/core/MapHelper.py @@ -1,4 +1,5 @@ import PIL.Image +import math class MapHelper(object): @@ -12,4 +13,9 @@ class MapHelper(object): @staticmethod def pixels_to_degrees(pixels, zoom): - return pixels * 2 ** (21-zoom) \ No newline at end of file + return pixels * 2 ** (21-zoom) + + @staticmethod + def pixels_to_meters(latitude, zoom): + # https://groups.google.com/forum/#!topic/google-maps-js-api-v3/hDRO4oHVSeM + return 2 ** zoom / (156543.03392 * math.cos(math.radians(latitude))) \ No newline at end of file diff --git a/ground_station/resources/core/mapping.py b/ground_station/resources/core/mapping.py index 4c44881..8aa6fc9 100644 --- a/ground_station/resources/core/mapping.py +++ b/ground_station/resources/core/mapping.py @@ -89,10 +89,6 @@ class GMapsStitcher(object): string_builder += "LatLong of Southeast Corner: %4f, %4f\n" % (self.southeast) return string_builder - 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, longitude, latitude, sleeptime=0): # Make the url string for polling # GET request header gets appended to the string @@ -141,7 +137,7 @@ class GMapsStitcher(object): # 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.helper.pixels_to_meters(self.latitude, self.zoom) / (_TILESIZE / 2. / self.radius_meters))) lon_pixels = _EARTHPIX + self.longitude * math.radians(_PIXRAD) From d17aaf5ef8343be017032c46fa391b9b27470bc2 Mon Sep 17 00:00:00 2001 From: Chris Pham Date: Sat, 3 Feb 2018 14:37:43 -0800 Subject: [PATCH 62/72] Added Docstrings for mapping.py --- ground_station/resources/core/mapping.py | 61 +++++++++++++++++++++++- 1 file changed, 60 insertions(+), 1 deletion(-) diff --git a/ground_station/resources/core/mapping.py b/ground_station/resources/core/mapping.py index 8aa6fc9..c2fef2b 100644 --- a/ground_station/resources/core/mapping.py +++ b/ground_station/resources/core/mapping.py @@ -69,12 +69,17 @@ class GMapsStitcher(object): self.display_image = self.helper.new_image(width, height) self.debug = debug - # Get the big image here self._fetch() self.center_display(latitude, longitude) def __str__(self): + """ + This string returns when used in a print statement + Useful for debugging and to print current state + + returns STRING + """ string_builder = "" 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) @@ -90,6 +95,12 @@ class GMapsStitcher(object): return string_builder def _grab_tile(self, longitude, latitude, sleeptime=0): + """ + This will return the tile at location longitude x latitude. + Includes a sleep time to allow for free use if there is no API key + + returns PIL.IMAGE OBJECT + """ # Make the url string for polling # GET request header gets appended to the string urlbase = 'https://maps.googleapis.com/maps/api/staticmap?' @@ -121,16 +132,33 @@ class GMapsStitcher(object): return tile_object def _pixels_to_lon(self, iterator, lon_pixels): + """ + This converts pixels to degrees to be used in fetching squares and generate correct squares + + returns FLOAT(degrees) + """ # Magic Lines, no idea degrees = self.helper.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): + """ + This converts pixels to latitude using meridian projection to get the latitude to generate squares + + returns FLOAT(degrees) + """ # Magic Lines return math.degrees(math.pi / 2 - 2 * math.atan( math.exp(((lat_pixels + self.helper.pixels_to_degrees((iterator - self.num_tiles / 2) * _TILESIZE, self.zoom)) - _EARTHPIX) / _PIXRAD))) def fetch_tiles(self): + """ + Function that handles fetching of files from init'd variables + + returns PIL.IMAGE OBJECT, (WEST, NORTH), (EAST, SOUTH) + + North/East/South/West are in FLOAT(degrees) + """ # cap floats to precision amount self.latitude = self.helper.fast_round(self.latitude, _DEGREE_PRECISION) self.longitude = self.helper.fast_round(self.longitude, _DEGREE_PRECISION) @@ -161,29 +189,54 @@ class GMapsStitcher(object): return big_image, (north, west), (south, east) def move_pix(self, dx, dy): + """ + Function gets change in x and y (dx, dy) and then displaces the displayed map that amount + + NO RETURN + """ self._constrain_x(dx) self._constrain_y(dy) self.update() def _constrain_x(self, diff): + """ + Helper for move_pix + """ 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): + """ + Helper for move_pix + """ 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): + """ + Function remakes display image using top left corners + """ 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): + """ + Function generates big image + """ self.big_image, self.northwest, self.southeast = self.fetch_tiles() def move_latlon(self, lat, lon): + """ + Function to move the object/rover + """ x, y = self._get_cartesian(lat, lon) def _get_cartesian(self, lat, lon): + """ + Helper for getting the x, y given lat and lon + + returns INT, INT (x, 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 @@ -213,6 +266,9 @@ class GMapsStitcher(object): return int(x), int(y) def add_gps_location(self, lat, lon, shape, size, fill): + """ + Function adds a shape at lat x lon + """ x, y = self._get_cartesian(lat, lon) draw = PIL.ImageDraw.Draw(self.big_image) if shape is "ellipsis": @@ -223,6 +279,9 @@ class GMapsStitcher(object): def center_display(self, lat, lon): + """ + Function centers the display image + """ x, y = self._get_cartesian(lat, lon) self.center_x = x self.center_y = y From b402cd12d3ab294d280cddf85c28ac263f62ce91 Mon Sep 17 00:00:00 2001 From: Chris Pham Date: Sat, 3 Feb 2018 14:40:46 -0800 Subject: [PATCH 63/72] created docstrings for maphelper --- ground_station/resources/core/MapHelper.py | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/ground_station/resources/core/MapHelper.py b/ground_station/resources/core/MapHelper.py index e9c3d98..2f23972 100644 --- a/ground_station/resources/core/MapHelper.py +++ b/ground_station/resources/core/MapHelper.py @@ -5,17 +5,37 @@ class MapHelper(object): @staticmethod def new_image(width, height): + """ + Generates a new image using PIL.Image module + + returns PIL.IMAGE OBJECT + """ return PIL.Image.new('RGBA', (width, height)) @staticmethod def fast_round(value, precision): + """ + Function to round values instead of using python's + + return INT + """ return int(value * 10 ** precision) / 10. ** precision @staticmethod def pixels_to_degrees(pixels, zoom): + """ + Generates pixels to be expected at zoom levels + + returns INT + """ return pixels * 2 ** (21-zoom) @staticmethod def pixels_to_meters(latitude, zoom): + """ + Function generates how many pixels per meter it should be from the projecction + + returns FLOAT + """ # https://groups.google.com/forum/#!topic/google-maps-js-api-v3/hDRO4oHVSeM return 2 ** zoom / (156543.03392 * math.cos(math.radians(latitude))) \ No newline at end of file From ad51c3d7940eb1c5baa8f4ac0b72fe115c7eb776 Mon Sep 17 00:00:00 2001 From: Chris Pham Date: Sat, 3 Feb 2018 14:51:32 -0800 Subject: [PATCH 64/72] Finished move_latlon function --- ground_station/resources/core/mapping.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/ground_station/resources/core/mapping.py b/ground_station/resources/core/mapping.py index c2fef2b..240746d 100644 --- a/ground_station/resources/core/mapping.py +++ b/ground_station/resources/core/mapping.py @@ -230,6 +230,9 @@ class GMapsStitcher(object): Function to move the object/rover """ x, y = self._get_cartesian(lat, lon) + self._constrain_x(self.center_x-x) + self._constrain_y(self.center_y-y) + self.update() def _get_cartesian(self, lat, lon): """ From 31ad2185cb708d66cdb29dc23597a8c241622b4f Mon Sep 17 00:00:00 2001 From: Chris Pham Date: Sat, 3 Feb 2018 14:52:20 -0800 Subject: [PATCH 65/72] Comment out waypoints --- ground_station/resources/core/mapping.py | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/ground_station/resources/core/mapping.py b/ground_station/resources/core/mapping.py index 240746d..d23e1de 100644 --- a/ground_station/resources/core/mapping.py +++ b/ground_station/resources/core/mapping.py @@ -293,9 +293,8 @@ class GMapsStitcher(object): self.upper_y = (self.center_y - (self.height/2)) self.update() + # def update_rover_map_location(self, lat, lon): + # print "I did nothing" - def update_rover_map_location(self, lat, lon): - print "I did nothing" - - def draw_circle(self, lat, lon, radius, fill): - print "I did nothing" + # def draw_circle(self, lat, lon, radius, fill): + # print "I did nothing" From 23f3554af37f18f17b1ad9c79378f5fc185ebf1a Mon Sep 17 00:00:00 2001 From: Chris Pham Date: Sat, 3 Feb 2018 15:28:45 -0800 Subject: [PATCH 66/72] complying with PEP8 standard --- ground_station/resources/core/MapHelper.py | 8 +- ground_station/resources/core/mapping.py | 109 ++++++++++++++------- 2 files changed, 76 insertions(+), 41 deletions(-) diff --git a/ground_station/resources/core/MapHelper.py b/ground_station/resources/core/MapHelper.py index 2f23972..759209b 100644 --- a/ground_station/resources/core/MapHelper.py +++ b/ground_station/resources/core/MapHelper.py @@ -1,13 +1,14 @@ import PIL.Image import math + class MapHelper(object): @staticmethod def new_image(width, height): """ Generates a new image using PIL.Image module - + returns PIL.IMAGE OBJECT """ return PIL.Image.new('RGBA', (width, height)) @@ -33,9 +34,10 @@ class MapHelper(object): @staticmethod def pixels_to_meters(latitude, zoom): """ - Function generates how many pixels per meter it should be from the projecction + Function generates how many pixels per meter it + should be from the projecction returns FLOAT """ # https://groups.google.com/forum/#!topic/google-maps-js-api-v3/hDRO4oHVSeM - return 2 ** zoom / (156543.03392 * math.cos(math.radians(latitude))) \ No newline at end of file + return 2 ** zoom / (156543.03392 * math.cos(math.radians(latitude))) diff --git a/ground_station/resources/core/mapping.py b/ground_station/resources/core/mapping.py index d23e1de..a3c2dcd 100644 --- a/ground_station/resources/core/mapping.py +++ b/ground_station/resources/core/mapping.py @@ -6,15 +6,14 @@ 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 +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, +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 +You should have received a copy of the GNU Lesser General Public License along with this code. If not, see . - ''' ##################################### @@ -51,6 +50,7 @@ for i in file_pointer: _KEYS.append(i.rstrip()) file_pointer.close() + class GMapsStitcher(object): def __init__(self, width, height, latitude, longitude, zoom, @@ -68,11 +68,11 @@ class GMapsStitcher(object): self.num_tiles = num_tiles self.display_image = self.helper.new_image(width, height) self.debug = debug - + # Get the big image here self._fetch() self.center_display(latitude, longitude) - + def __str__(self): """ This string returns when used in a print statement @@ -81,17 +81,26 @@ class GMapsStitcher(object): returns STRING """ string_builder = "" - 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 += ("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: %4f, %4f\n" % (self.northwest) - string_builder += "LatLong of Southeast Corner: %4f, %4f\n" % (self.southeast) + 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: %4f, %4f\n" % + (self.northwest)) + string_builder += ("LatLong of Southeast Corner: %4f, %4f\n" % + (self.southeast)) return string_builder def _grab_tile(self, longitude, latitude, sleeptime=0): @@ -99,16 +108,20 @@ class GMapsStitcher(object): This will return the tile at location longitude x latitude. Includes a sleep time to allow for free use if there is no API key - returns PIL.IMAGE OBJECT + returns PIL.IMAGE 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=%.4f,%.4f&zoom=%d&maptype=%s&size=%dx%d&format=png&key=%s' + urlbase += 'center=%.4f,%.4f&zoom=%d&maptype=%s' + urlbase += '&size=%dx%d&format=png&key=%s' # Fill the formatting - specs = self.helper.fast_round(latitude, _DEGREE_PRECISION), self.helper.fast_round(longitude, _DEGREE_PRECISION), self.zoom, self.maptype, _TILESIZE, _TILESIZE, _KEYS[0] - filename = 'Resources/Maps/' + ('%.4f_%.4f_%d_%s_%d_%d_%s' % specs) + '.png' + specs = (self.helper.fast_round(latitude, _DEGREE_PRECISION), + self.helper.fast_round(longitude, _DEGREE_PRECISION), + self.zoom, self.maptype, _TILESIZE, _TILESIZE, _KEYS[0]) + filename = 'Resources/Maps/' + ('%.4f_%.4f_%d_%s_%d_%d_%s' % specs) + filename += '.png' # Tile Image object tile_object = None @@ -126,46 +139,58 @@ 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 + # Added to prevent timeouts on Google Servers time.sleep(sleeptime) return tile_object def _pixels_to_lon(self, iterator, lon_pixels): """ - This converts pixels to degrees to be used in fetching squares and generate correct squares - + This converts pixels to degrees to be used in + fetching squares and generate correct squares + returns FLOAT(degrees) """ # Magic Lines, no idea - degrees = self.helper.pixels_to_degrees(((iterator) - self.num_tiles / 2) * _TILESIZE, self.zoom) + degrees = self.helper.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): """ - This converts pixels to latitude using meridian projection to get the latitude to generate squares + This converts pixels to latitude using meridian projection + to get the latitude to generate squares returns FLOAT(degrees) """ # Magic Lines - return math.degrees(math.pi / 2 - 2 * math.atan( - math.exp(((lat_pixels + self.helper.pixels_to_degrees((iterator - self.num_tiles / 2) * _TILESIZE, self.zoom)) - _EARTHPIX) / _PIXRAD))) + return math.degrees(math.pi / 2 - 2 * math.atan(math.exp(((lat_pixels + + self.helper.pixels_to_degrees( + (iterator - self.num_tiles / 2) + * _TILESIZE, self.zoom)) + - _EARTHPIX) / _PIXRAD))) def fetch_tiles(self): """ Function that handles fetching of files from init'd variables returns PIL.IMAGE OBJECT, (WEST, NORTH), (EAST, SOUTH) - + North/East/South/West are in FLOAT(degrees) """ # cap floats to precision amount - self.latitude = self.helper.fast_round(self.latitude, _DEGREE_PRECISION) - self.longitude = self.helper.fast_round(self.longitude, _DEGREE_PRECISION) + self.latitude = self.helper.fast_round(self.latitude, + _DEGREE_PRECISION) + self.longitude = self.helper.fast_round(self.longitude, + _DEGREE_PRECISION) - # number of tiles required to go from center latitude to desired radius in meters + # 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.helper.pixels_to_meters(self.latitude, self.zoom) / (_TILESIZE / 2. / self.radius_meters))) + self.num_tiles = (int( + round(2 * self.helper.pixels_to_meters( + self.latitude, self.zoom) / + (_TILESIZE / 2. / self.radius_meters)))) lon_pixels = _EARTHPIX + self.longitude * math.radians(_PIXRAD) @@ -190,7 +215,8 @@ class GMapsStitcher(object): def move_pix(self, dx, dy): """ - Function gets change in x and y (dx, dy) and then displaces the displayed map that amount + Function gets change in x and y (dx, dy) + then displaces the displayed map that amount NO RETURN """ @@ -203,14 +229,24 @@ class GMapsStitcher(object): Helper for move_pix """ 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 + + if !(new_value > 0 and + (new_value < self.big_image.size[0] - self.width)): + return self.left_x + else: + return new_value def _constrain_y(self, diff): """ Helper for move_pix """ 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 + + if !(new_value > 0 and + new_value < self.big_image.size[0] - self.height): + return self.upper_y + else: + return new_value def update(self): """ @@ -261,8 +297,6 @@ class GMapsStitcher(object): 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 @@ -270,7 +304,7 @@ class GMapsStitcher(object): def add_gps_location(self, lat, lon, shape, size, fill): """ - Function adds a shape at lat x lon + Function adds a shape at lat x lon """ x, y = self._get_cartesian(lat, lon) draw = PIL.ImageDraw.Draw(self.big_image) @@ -280,7 +314,6 @@ class GMapsStitcher(object): draw.rectangle([x-size, y-size, x+size, y+size], fill) self.update() - def center_display(self, lat, lon): """ Function centers the display image From 89e7739f54adcf9317261f4741d1860d9c41a838 Mon Sep 17 00:00:00 2001 From: Chris Pham Date: Thu, 8 Feb 2018 12:58:45 -0800 Subject: [PATCH 67/72] Start of RoverMapCoordinator --- .../resources/core/RoverMapCoordinator.py | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 ground_station/resources/core/RoverMapCoordinator.py diff --git a/ground_station/resources/core/RoverMapCoordinator.py b/ground_station/resources/core/RoverMapCoordinator.py new file mode 100644 index 0000000..c72001e --- /dev/null +++ b/ground_station/resources/core/RoverMapCoordinator.py @@ -0,0 +1,26 @@ +##################################### +# Imports +##################################### +# Python native imports +from PyQt5 import QtCore, QtWidgets +import logging + +import rospy + +# Custom Imports +import MapHelper + +##################################### +# Global Variables +##################################### +# put some stuff here later so you can remember + + +class RoverMapCoordinator(QtCore.QThread): + pixmap_ready_signal = QtCore.pyqtSignal(str) + + def __init__(self, shared_objects): + super(RoverMapCoordinator, self).init() + + self.shared_objects = shared_objects + self.right_screen = self.shared_objects["screens"]["left_screen"] \ No newline at end of file From 33694343176eaedff94334df4083b831ce1bc006 Mon Sep 17 00:00:00 2001 From: Chris Pham Date: Thu, 8 Feb 2018 13:33:32 -0800 Subject: [PATCH 68/72] Changed file names and started initer for MapCoordinator --- .../core/{mapping.py => RoverMap.py} | 0 .../resources/core/RoverMapCoordinator.py | 32 +++++++++++++++++-- .../core/{MapHelper.py => RoverMapHelper.py} | 0 3 files changed, 30 insertions(+), 2 deletions(-) rename ground_station/resources/core/{mapping.py => RoverMap.py} (100%) rename ground_station/resources/core/{MapHelper.py => RoverMapHelper.py} (100%) diff --git a/ground_station/resources/core/mapping.py b/ground_station/resources/core/RoverMap.py similarity index 100% rename from ground_station/resources/core/mapping.py rename to ground_station/resources/core/RoverMap.py diff --git a/ground_station/resources/core/RoverMapCoordinator.py b/ground_station/resources/core/RoverMapCoordinator.py index c72001e..2543356 100644 --- a/ground_station/resources/core/RoverMapCoordinator.py +++ b/ground_station/resources/core/RoverMapCoordinator.py @@ -8,7 +8,7 @@ import logging import rospy # Custom Imports -import MapHelper +import RoverMap ##################################### # Global Variables @@ -23,4 +23,32 @@ class RoverMapCoordinator(QtCore.QThread): super(RoverMapCoordinator, self).init() self.shared_objects = shared_objects - self.right_screen = self.shared_objects["screens"]["left_screen"] \ No newline at end of file + self.right_screen = self.shared_objects["screens"]["left_screen"] + + self.setings = QtCore.QSettings() + + self.logger = logging.getLogger("groundstation") + + self.run_thread_flag = True + self.setup_map_flag = True + + # setup map + self._get_map() + self._setup_map_threads() + + def run(self): + self.logger.debug("Starting Map Coordinator Thread") + + while self.run_thread_flag: + self.msleep(10) + + self.__wait_for_map_thread() + self.logger.debug("Stopping Map Coordinator Thread") + + def __wait_for_map_thread(self): + self.map_thread.wait() + + def _setup_map_threads(self): + self.map_thread = RoverMap.GMapsStitcher(2000, + 2000, 44.567161, -123.278432, + 18, 'terrain', None, 20) diff --git a/ground_station/resources/core/MapHelper.py b/ground_station/resources/core/RoverMapHelper.py similarity index 100% rename from ground_station/resources/core/MapHelper.py rename to ground_station/resources/core/RoverMapHelper.py From f4d6835e85304f1dd43cea14ac4eb17587b14606 Mon Sep 17 00:00:00 2001 From: Chris Pham Date: Thu, 8 Feb 2018 13:50:12 -0800 Subject: [PATCH 69/72] create label for left xml for map location, and remove _get_map. --- ground_station/resources/core/RoverMapCoordinator.py | 3 ++- software/ground_station/Resources/Ui/left_screen.ui | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/ground_station/resources/core/RoverMapCoordinator.py b/ground_station/resources/core/RoverMapCoordinator.py index 2543356..b03c9d0 100644 --- a/ground_station/resources/core/RoverMapCoordinator.py +++ b/ground_station/resources/core/RoverMapCoordinator.py @@ -33,7 +33,6 @@ class RoverMapCoordinator(QtCore.QThread): self.setup_map_flag = True # setup map - self._get_map() self._setup_map_threads() def run(self): @@ -52,3 +51,5 @@ class RoverMapCoordinator(QtCore.QThread): self.map_thread = RoverMap.GMapsStitcher(2000, 2000, 44.567161, -123.278432, 18, 'terrain', None, 20) + + diff --git a/software/ground_station/Resources/Ui/left_screen.ui b/software/ground_station/Resources/Ui/left_screen.ui index bdafc73..c154798 100644 --- a/software/ground_station/Resources/Ui/left_screen.ui +++ b/software/ground_station/Resources/Ui/left_screen.ui @@ -119,7 +119,7 @@ color: #DCDCDC; 0 - + 0 From 4455e5769389aa18ea396a3981cf3a3b989c6271 Mon Sep 17 00:00:00 2001 From: Chris Pham Date: Thu, 8 Feb 2018 13:57:49 -0800 Subject: [PATCH 70/72] fixed wrong size references --- ground_station/resources/core/RoverMap.py | 2 +- ground_station/resources/core/RoverMapCoordinator.py | 11 ++++++++--- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/ground_station/resources/core/RoverMap.py b/ground_station/resources/core/RoverMap.py index a3c2dcd..e1c8671 100644 --- a/ground_station/resources/core/RoverMap.py +++ b/ground_station/resources/core/RoverMap.py @@ -243,7 +243,7 @@ class GMapsStitcher(object): new_value = self.upper_y - diff if !(new_value > 0 and - new_value < self.big_image.size[0] - self.height): + new_value < self.big_image.size[1] - self.height): return self.upper_y else: return new_value diff --git a/ground_station/resources/core/RoverMapCoordinator.py b/ground_station/resources/core/RoverMapCoordinator.py index b03c9d0..b266752 100644 --- a/ground_station/resources/core/RoverMapCoordinator.py +++ b/ground_station/resources/core/RoverMapCoordinator.py @@ -23,7 +23,8 @@ class RoverMapCoordinator(QtCore.QThread): super(RoverMapCoordinator, self).init() self.shared_objects = shared_objects - self.right_screen = self.shared_objects["screens"]["left_screen"] + self.left_screen = self.shared_objects["screens"]["left_screen"] + self.mapping_label = self.left_screen.mapping_label self.setings = QtCore.QSettings() @@ -48,8 +49,12 @@ class RoverMapCoordinator(QtCore.QThread): self.map_thread.wait() def _setup_map_threads(self): - self.map_thread = RoverMap.GMapsStitcher(2000, - 2000, 44.567161, -123.278432, + self.map_thread = RoverMap.GMapsStitcher(1280, + 720, 44.567161, -123.278432, 18, 'terrain', None, 20) + def pixmap_ready_slot(self): + self.mapping_label.setPixmap(self.map_thread.display_image) + def on_kill_threads_requested_slot(self): + self.run_thread_flag = false \ No newline at end of file From cdfc76789173155e7f6fdc8d27137149e6f41fc6 Mon Sep 17 00:00:00 2001 From: Chris Pham Date: Thu, 8 Feb 2018 14:02:43 -0800 Subject: [PATCH 71/72] Corrcted bool and created the thread for the main class --- ground_station/resources/core/RoverMapCoordinator.py | 2 +- software/ground_station/RoverGroundStation.py | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/ground_station/resources/core/RoverMapCoordinator.py b/ground_station/resources/core/RoverMapCoordinator.py index b266752..6a915ab 100644 --- a/ground_station/resources/core/RoverMapCoordinator.py +++ b/ground_station/resources/core/RoverMapCoordinator.py @@ -57,4 +57,4 @@ class RoverMapCoordinator(QtCore.QThread): self.mapping_label.setPixmap(self.map_thread.display_image) def on_kill_threads_requested_slot(self): - self.run_thread_flag = false \ No newline at end of file + self.run_thread_flag = False \ No newline at end of file diff --git a/software/ground_station/RoverGroundStation.py b/software/ground_station/RoverGroundStation.py index 74c2473..392ee5c 100755 --- a/software/ground_station/RoverGroundStation.py +++ b/software/ground_station/RoverGroundStation.py @@ -95,6 +95,7 @@ class GroundStation(QtCore.QObject): # ##### Instantiate Threaded Classes ###### self.__add_thread("Video Coordinator", RoverVideoCoordinator.RoverVideoCoordinator(self.shared_objects)) + self.__add_thread("Map Coordinator", RoverMapCoordinator.RoverMapCoordinator(self.shared_objects)) self.connect_signals_and_slots_signal.emit() self.__connect_signals_to_slots() From bb3b47977b1818ff9d45c6144d134e6a34a7d316 Mon Sep 17 00:00:00 2001 From: Chris Pham Date: Thu, 8 Feb 2018 14:06:12 -0800 Subject: [PATCH 72/72] Moved file to software/ground_station --- .../ground_station/Framework/MapSystems}/RoverMap.py | 0 .../ground_station/Framework/MapSystems}/RoverMapCoordinator.py | 0 .../ground_station/Framework/MapSystems}/RoverMapHelper.py | 0 .../ground_station/Framework/MapSystems}/signing.py | 0 4 files changed, 0 insertions(+), 0 deletions(-) rename {ground_station/resources/core => software/ground_station/Framework/MapSystems}/RoverMap.py (100%) rename {ground_station/resources/core => software/ground_station/Framework/MapSystems}/RoverMapCoordinator.py (100%) rename {ground_station/resources/core => software/ground_station/Framework/MapSystems}/RoverMapHelper.py (100%) rename {ground_station/resources/core => software/ground_station/Framework/MapSystems}/signing.py (100%) diff --git a/ground_station/resources/core/RoverMap.py b/software/ground_station/Framework/MapSystems/RoverMap.py similarity index 100% rename from ground_station/resources/core/RoverMap.py rename to software/ground_station/Framework/MapSystems/RoverMap.py diff --git a/ground_station/resources/core/RoverMapCoordinator.py b/software/ground_station/Framework/MapSystems/RoverMapCoordinator.py similarity index 100% rename from ground_station/resources/core/RoverMapCoordinator.py rename to software/ground_station/Framework/MapSystems/RoverMapCoordinator.py diff --git a/ground_station/resources/core/RoverMapHelper.py b/software/ground_station/Framework/MapSystems/RoverMapHelper.py similarity index 100% rename from ground_station/resources/core/RoverMapHelper.py rename to software/ground_station/Framework/MapSystems/RoverMapHelper.py diff --git a/ground_station/resources/core/signing.py b/software/ground_station/Framework/MapSystems/signing.py similarity index 100% rename from ground_station/resources/core/signing.py rename to software/ground_station/Framework/MapSystems/signing.py