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 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 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() # 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() @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 def color_land(self): return rgb(*darksienna3,a=0) #darksienna3) @property def color_water(self): return rgb(*russiangreen) @property def color_label(self): return rgb(*COLOR_ICON) @property def color_marker(self): return rgb(*COLOR_ICON) @property def color_line(self): return rgb(*rufusred) # COLOR_ICON) @property def color_line_dark(self): return rgb(*COLOR_ICON) def __init__(self): self.last_lat = None self.last_long = None self.points = [] self.opened=False self.label=None self.intro_label=None # 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' self.label_layout.rows=10 self.label_layout.pos_hint={'y':1} 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 # tr = transforms.Affine2D().rotate_deg(90) # buf = io.BytesIO() # plt.ion() from comrad.constants import PATH_MAPS odir=PATH_MAPS if not os.path.exists(odir): os.makedirs(odir) ofn=os.path.join(odir,f't_{len(self.points)}.png') plt.gca().invert_yaxis() 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 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 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 color = random.choice(ALL_COLORS) self.points+=[(lat,long,desc)] # # point # plt.plot( # long, # lat, # '+', # markersize=25, # linewidth=10, # color=self.color_marker,#rgb(*color), # transform=ccrs.Geodetic(), # ) # line if self.last_lat and self.last_long: # if self.ax.lines: self.ax.lines.pop(0) for line in self.ax.lines: line.set_color(self.color_line_dark) plt.plot( [self.last_long, long], [self.last_lat, lat], color=self.color_line,#rgb(*color), #self.color_line, linewidth=4, marker='', transform=ccrs.Geodetic(), ) desc = '\n'.join('--> '+desc for lat,long,desc in self.points[-1:]) #if self.label: # self.img.remove_widget(self.label) self.label=label=self.makelabel(desc) # 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): self.ax.lines=[] self.draw() if not self.intro_label: self.intro_label = self.makelabel('Comrad @Tor: Routing you through the global maze of the deep web ...') self.label_layout.add_widget(self.intro_label) 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 def dismiss(self): super().dismiss() self.intro_label=None if hasattr(self.layout,'img'): self.layout.remove_widget(self.img) if self.layout: self.remove_widget(self.layout) 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()