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

292 lines
9.4 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
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
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
# 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()