You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
Comrad/comrad/app/screens/map.py

295 lines
9.5 KiB
Python

4 years ago
import os,sys; sys.path.append(os.path.abspath(os.path.join(os.path.abspath(os.path.join(os.path.dirname(__file__),'..')),'..','..')))
from comrad.app.screens.dialog import MDDialog2
4 years ago
import cartopy
import cartopy.crs as ccrs
4 years ago
import matplotlib
matplotlib.use('Agg')
4 years ago
import matplotlib.pyplot as plt
from kivymd.uix.boxlayout import MDBoxLayout
from kivymd.uix.gridlayout import MDGridLayout
from kivymd.uix.button import MDFlatButton
from kivymd.uix.label import MDLabel
4 years ago
# print('\n'.join(sys.path))
from comrad.constants import *
# from comrad.app.main import rgb
4 years ago
import io
from kivy.core.image import Image as CoreImage
from kivy.uix.image import Image,AsyncImage
from kivy.core.window import Window
from kivy.app import App
import logging
logger=logging.getLogger(__name__)
def rgb(r,g,b,a=1):
return (r/255,g/255,b/255,a)
class MapImage(AsyncImage):
pass
class MapWidget(MDDialog2):
@property
def projection(self):
# return ccrs.PlateCarree()
4 years ago
# return ccrs.EckertI()
# return ccrs.EquidistantConic()
# return ccrs.LambertConformal(central_longitude=0)#,central_latitude=0)
# return ccrs.LambertConformal(central_longitude=0)#,central_latitude=0)
return ccrs.AlbersEqualArea()
4 years ago
@property
def figsize(self):
# fig = plt.figure()
# dpi=fig.dpi // 2
dpi=40
width,height=Window.size
return (width//dpi, height//dpi)
# bbox = fig.get_window_extent().transformed(fig.dpi_scale_trans.inverted())
# width, height = bbox.width*fig.dpi, bbox.height*fig.dpi
# return (width,height)
@property
4 years ago
def color_land(self): return rgb(*darksienna3,a=0) #darksienna3)
4 years ago
@property
4 years ago
def color_water(self): return rgb(*russiangreen)
4 years ago
@property
4 years ago
def color_label(self): return rgb(*COLOR_ICON)
4 years ago
@property
4 years ago
def color_marker(self): return rgb(*COLOR_ICON)
4 years ago
@property
4 years ago
def color_line(self): return rgb(*rufusred) # COLOR_ICON)
4 years ago
@property
4 years ago
def color_line_dark(self): return rgb(*COLOR_ICON)
4 years ago
def __init__(self):
self.last_lat = None
self.last_long = None
self.points = []
self.opened=False
self.label=None
4 years ago
self.intro_label=None
4 years ago
# self.fig = fig = plt.figure(figsize=(20,10))
plt.rcParams["figure.figsize"] = self.figsize
self.ax = ax = plt.axes(
projection=self.projection,
)
# ax.set_extent([-170, 165, -55, 75])
# ax.background_patch.set_facecolor(rgb(*COLOR_CARD)[:3])
# ax.outline_patch.set_facecolor(rgb(*COLOR_CARD)[:3])
# self.ax.stock_img()
# self.ax.coastlines(color=rgb(*COLOR_CARD))
ax.add_feature(cartopy.feature.OCEAN, zorder=0, color=self.color_water,edgecolor=self.color_water)
ax.add_feature(cartopy.feature.LAND, zorder=0, color=self.color_land, edgecolor=self.color_land)
ax.outline_patch.set_visible(False)
ax.background_patch.set_visible(False)
# ax.set_global()
# ax.gridlines()
self.layout=MDBoxLayout()
self.layout.orientation='vertical'
self.layout.cols=1
self.layout.size_hint=(None,None)
self.layout.size=(Window.size[0],Window.size[1]) # ('666sp','666sp')
self.layout.md_bg_color=rgb(*eerieblack) #rgb(*COLOR_BG,a=1)
# self.layout.adaptive_height=True
# self.layout.height=self.layout.minimum_height
self.layout.spacing='0sp'
self.layout.padding='0sp'
self.img=None
self.label_layout=MDGridLayout()
self.label_layout.orientation='vertical'
self.label_layout.cols=1
self.label_layout.row_default_height='25sp'
self.label_layout.row_force_default='25sp'
4 years ago
self.label_layout.rows=10
self.label_layout.pos_hint={'y':1}
4 years ago
self.label_layout.size_hint=(None,None)
self.label_layout.width=Window.size[0]
self.label_layout.height='300sp'
# self.label_layout.size=(Window.size[0],'400sp')
# self.label_layout.size=Window.size # ('666sp','666sp')
# self.layout.add_widget(self.label_layout)
# do dialog's intro
super().__init__(
type='custom',
text='',
content_cls=self.layout,
buttons=[
MDFlatButton(
text="disconnect",
text_color=rgb(*COLOR_TEXT),
md_bg_color = rgb(*eerieblack), #(0,0,0,1),
theme_text_color='Custom',
on_release=self.dismiss,
font_name=FONT_PATH
)
],
color_bg = rgb(*eerieblack), #(0,0,0,1),
overlay_color=(0,0,0,0),
background_color=(0,0,0,0)
)
self.ids.text.text_color=rgb(*COLOR_TEXT)
self.ids.text.font_name=FONT_PATH
self.size=Window.size #('666sp','666sp')
# self.
# self.adaptive_height=True
def draw(self):
from matplotlib import transforms
from PIL import Image as pImage
from PIL import ImageOps
4 years ago
# tr = transforms.Affine2D().rotate_deg(90)
4 years ago
# buf = io.BytesIO()
# plt.ion()
from comrad.constants import PATH_MAPS
odir=PATH_MAPS
4 years ago
if not os.path.exists(odir): os.makedirs(odir)
ofn=os.path.join(odir,f't_{len(self.points)}.png')
4 years ago
# plt.gca().invert_yaxis()
4 years ago
plt.savefig(ofn, format='png',transparent=True,pad_inches=0.1,bbox_inches = 'tight')
# flip?
# im = pImage.open(ofn)
# im = im.rotate(90)
# im.save(ofn)
if not self.img:
self.img= AsyncImage(source=ofn)
self.img.background_color=(0,0,0,0)
self.img.overlay_color=(0,0,0,0)
# self.img.texture.flip_horizontal()
self.img.pos_hint={'center_x':0.48,'center_y':0.5}
# self.img.size=Window.size
# self.img.texture = img
self.img.add_widget(self.label_layout,1)
self.layout.add_widget(self.img,1)
else:
self.img.source=ofn
# self.img.size_hint=(1,1)
# self.img.width=Window.size[0]
# self.img.allow_stretch=True
4 years ago
def makelabel(self,txt):
label=MDLabel(text=txt)
label.color=self.color_label #rgb(*color) #self.color_label
label.font_name=FONT_PATH
label.font_size='20sp'
# label.size_hint=(1,1)
label.width=Window.size[0]
label.height='25sp'
label.valign='top'
return label
4 years ago
def add_point(self,lat,long,desc):
logger.info(f'adding point? {desc} {lat}, {long}')
# plt.text(
# long+3,
# lat-12,
# desc,
# horizontalalignment='left',
# transform=self.projection
# )
import random
from comrad.constants import ALL_COLORS
4 years ago
color = random.choice(ALL_COLORS)
self.points+=[(lat,long,desc)]
4 years ago
# # point
4 years ago
plt.plot(
long,
lat,
'.',
markersize=25,
linewidth=10,
color=self.color_marker,#rgb(*color),
transform=ccrs.Geodetic(),
)
4 years ago
# line
if self.last_lat and self.last_long:
4 years ago
# if self.ax.lines: self.ax.lines.pop(0)
4 years ago
for line in self.ax.lines:
line.set_color(self.color_line_dark)
4 years ago
plt.plot(
[self.last_long, long],
[self.last_lat, lat],
4 years ago
color=self.color_line,#rgb(*color), #self.color_line,
linewidth=4, marker='',
4 years ago
transform=ccrs.Geodetic(),
)
4 years ago
desc = '\n'.join('--> '+desc for lat,long,desc in self.points[-1:])
4 years ago
#if self.label:
# self.img.remove_widget(self.label)
4 years ago
4 years ago
self.label=label=self.makelabel(desc)
4 years ago
# label.height='400sp'
# label.pos_hint = {'center_y':0.1+(0.1 * len(self.points))}
# label.pos = (0.5,0)
self.label_layout.add_widget(label)
self.last_lat,self.last_long = lat,long
self.ax.set_global()
# wait and show
def open(self,maxwait=666,pulse=0.1):
4 years ago
self.ax.lines=[]
4 years ago
self.draw()
4 years ago
if not self.intro_label:
4 years ago
self.intro_label = self.makelabel('Comrad @Tor: Routing you through the global maze of the deep web ...')
4 years ago
self.label_layout.add_widget(self.intro_label)
4 years ago
super().open()
self.opened=True
# await asyncio.sleep(pulse)
# waited=0
# while not self.ok_to_continue:
# await asyncio.sleep(pulse)
# waited+=pulse
# if waited>maxwait: break
# # logger.info(f'waiting for {waited} seconds... {self.ok_to_continue} {self.response}')
# return self.response
4 years ago
def dismiss(self):
super().dismiss()
4 years ago
self.intro_label=None
4 years ago
if hasattr(self.layout,'img'):
self.layout.remove_widget(self.img)
if self.layout:
self.remove_widget(self.layout)
4 years ago
default_places = {
'Cambridge':(52.205338,0.121817),
'Sydney':(-33.868820,151.209290),
'New York':(40.712776,-74.005974),
'Hong Kong':(22.278300,114.174700),
'Cape Town':(-33.9249, 18.4241),
'San Francisco':(37.774929,-122.419418),
'Honolulu':(21.306944,-157.858337),
'Tokyo':(35.689487,139.691711),
'Ushuaia':(-54.801910,-68.302948),
'Reykjavik':(64.126518,-21.817438)
}
def test_map():
map = MapWidget()
plt.show()
if __name__=='__main__':
test_map()