GRASS Programmer's Manual
6.4.2(2012)
|
00001 """! 00002 @package gcpmapdisp.py 00003 00004 @brief display to manage ground control points with two toolbars, one for 00005 various display management functions, one for manipulating GCPs. 00006 00007 Classes: 00008 - MapFrame 00009 00010 (C) 2006-2010 by the GRASS Development Team 00011 This program is free software under the GNU General Public 00012 License (>=v2). Read the file COPYING that comes with GRASS 00013 for details. 00014 00015 Derived from mapdisp.py 00016 00017 @author Markus Metz 00018 """ 00019 00020 import os 00021 import sys 00022 import glob 00023 import math 00024 import tempfile 00025 import copy 00026 import platform 00027 00028 import globalvar 00029 import wx 00030 import wx.aui 00031 00032 try: 00033 import subprocess 00034 except: 00035 CompatPath = os.path.join(globalvar.ETCWXDIR) 00036 sys.path.append(CompatPath) 00037 from compat import subprocess 00038 00039 gmpath = os.path.join(globalvar.ETCWXDIR, "icons") 00040 sys.path.append(gmpath) 00041 00042 grassPath = os.path.join(globalvar.ETCDIR, "python") 00043 sys.path.append(grassPath) 00044 00045 import render 00046 import toolbars 00047 import menuform 00048 import gselect 00049 import disp_print 00050 import gcmd 00051 import dbm 00052 import dbm_dialogs 00053 import globalvar 00054 import utils 00055 import gdialogs 00056 from grass.script import core as grass 00057 from debug import Debug 00058 from icon import Icons 00059 from preferences import globalSettings as UserSettings 00060 00061 from mapdisp_command import Command 00062 from mapdisp_window import BufferedWindow 00063 00064 # for standalone app 00065 cmdfilename = None 00066 00067 class MapFrame(wx.Frame): 00068 """!Main frame for map display window. Drawing takes place in 00069 child double buffered drawing window. 00070 """ 00071 def __init__(self, parent=None, id=wx.ID_ANY, title=_("GRASS GIS Manage Ground Control Points"), 00072 style=wx.DEFAULT_FRAME_STYLE, toolbars=["gcpdisp"], 00073 tree=None, notebook=None, lmgr=None, page=None, 00074 Map=None, auimgr=None, **kwargs): 00075 """!Main map display window with toolbars, statusbar and 00076 DrawWindow 00077 00078 @param toolbars array of activated toolbars, e.g. ['map', 'digit'] 00079 @param tree reference to layer tree 00080 @param notebook control book ID in Layer Manager 00081 @param lmgr Layer Manager 00082 @param page notebook page with layer tree 00083 @param Map instance of render.Map 00084 @param auimgs AUI manager 00085 @param kwargs wx.Frame attribures 00086 """ 00087 self._layerManager = lmgr # Layer Manager object 00088 self.Map = Map # instance of render.Map 00089 self.tree = tree # Layer Manager layer tree object 00090 self.page = page # Notebook page holding the layer tree 00091 self.layerbook = notebook # Layer Manager layer tree notebook 00092 self.parent = parent 00093 00094 if 'name' not in kwargs: 00095 kwargs['name'] = 'GCPMapWindow' 00096 wx.Frame.__init__(self, parent, id, title, style = style, **kwargs) 00097 00098 # available cursors 00099 self.cursors = { 00100 # default: cross 00101 # "default" : wx.StockCursor(wx.CURSOR_DEFAULT), 00102 "default" : wx.StockCursor(wx.CURSOR_ARROW), 00103 "cross" : wx.StockCursor(wx.CURSOR_CROSS), 00104 "hand" : wx.StockCursor(wx.CURSOR_HAND), 00105 "pencil" : wx.StockCursor(wx.CURSOR_PENCIL), 00106 "sizenwse": wx.StockCursor(wx.CURSOR_SIZENWSE) 00107 } 00108 00109 # 00110 # set the size & system icon 00111 # 00112 self.SetClientSize(self.GetSize()) 00113 self.iconsize = (16, 16) 00114 00115 self.SetIcon(wx.Icon(os.path.join(globalvar.ETCICONDIR, 'grass_map.ico'), wx.BITMAP_TYPE_ICO)) 00116 00117 # 00118 # Fancy gui 00119 # 00120 self._mgr = wx.aui.AuiManager(self) 00121 00122 # 00123 # Add toolbars 00124 # 00125 self.toolbars = { 'map' : None, 00126 'vdigit' : None, 00127 'georect' : None, 00128 'gcpdisp' : None, 00129 'gcpman' : None, 00130 'nviz' : None } 00131 00132 for toolb in toolbars: 00133 self.AddToolbar(toolb) 00134 00135 self.activemap = self.toolbars['gcpdisp'].togglemap 00136 self.activemap.SetSelection(0) 00137 self.SrcMap = self.grwiz.SrcMap # instance of render.Map 00138 self.TgtMap = self.grwiz.TgtMap # instance of render.Map 00139 self._mgr.SetDockSizeConstraint(0.5, 0.5) 00140 00141 # 00142 # Add statusbar 00143 # 00144 self.statusbar = self.CreateStatusBar(number=4, style=0) 00145 self.statusbar.SetStatusWidths([-5, -2, -1, -1]) 00146 self.statusbarWin = dict() 00147 self.statusbarWin['toggle'] = wx.Choice(self.statusbar, wx.ID_ANY, 00148 choices = [_("Coordinates"), 00149 _("Extent"), 00150 _("Comp. region"), 00151 _("Show comp. extent"), 00152 _("Display mode"), 00153 _("Display geometry"), 00154 _("Map scale"), 00155 _("Go to GCP No."), 00156 _("RMS error")]) 00157 # set StatusBar to Go to GCP No. 00158 self.statusbarWin['toggle'].SetSelection(7) 00159 00160 self.statusbar.Bind(wx.EVT_CHOICE, self.OnToggleStatus, self.statusbarWin['toggle']) 00161 # auto-rendering checkbox 00162 self.statusbarWin['render'] = wx.CheckBox(parent=self.statusbar, id=wx.ID_ANY, 00163 label=_("Render")) 00164 self.statusbar.Bind(wx.EVT_CHECKBOX, self.OnToggleRender, self.statusbarWin['render']) 00165 self.statusbarWin['render'].SetValue(UserSettings.Get(group='display', 00166 key='autoRendering', 00167 subkey='enabled')) 00168 self.statusbarWin['render'].SetToolTip(wx.ToolTip (_("Enable/disable auto-rendering"))) 00169 # show region 00170 self.statusbarWin['region'] = wx.CheckBox(parent=self.statusbar, id=wx.ID_ANY, 00171 label=_("Show computational extent")) 00172 self.statusbar.Bind(wx.EVT_CHECKBOX, self.OnToggleShowRegion, self.statusbarWin['region']) 00173 00174 self.statusbarWin['region'].SetValue(False) 00175 self.statusbarWin['region'].Hide() 00176 self.statusbarWin['region'].SetToolTip(wx.ToolTip (_("Show/hide computational " 00177 "region extent (set with g.region). " 00178 "Display region drawn as a blue box inside the " 00179 "computational region, " 00180 "computational region inside a display region " 00181 "as a red box)."))) 00182 # set resolution 00183 self.statusbarWin['resolution'] = wx.CheckBox(parent=self.statusbar, id=wx.ID_ANY, 00184 label=_("Constrain display resolution to computational settings")) 00185 self.statusbar.Bind(wx.EVT_CHECKBOX, self.OnToggleResolution, self.statusbarWin['resolution']) 00186 self.statusbarWin['resolution'].SetValue(UserSettings.Get(group='display', key='compResolution', subkey='enabled')) 00187 self.statusbarWin['resolution'].Hide() 00188 self.statusbarWin['resolution'].SetToolTip(wx.ToolTip (_("Constrain display resolution " 00189 "to computational region settings. " 00190 "Default value for new map displays can " 00191 "be set up in 'User GUI settings' dialog."))) 00192 # map scale 00193 self.statusbarWin['mapscale'] = wx.ComboBox(parent = self.statusbar, id = wx.ID_ANY, 00194 style = wx.TE_PROCESS_ENTER, 00195 size=(150, -1)) 00196 self.statusbarWin['mapscale'].SetItems(['1:1000', 00197 '1:5000', 00198 '1:10000', 00199 '1:25000', 00200 '1:50000', 00201 '1:100000', 00202 '1:1000000']) 00203 self.statusbarWin['mapscale'].Hide() 00204 self.statusbar.Bind(wx.EVT_TEXT_ENTER, self.OnChangeMapScale, self.statusbarWin['mapscale']) 00205 self.statusbar.Bind(wx.EVT_COMBOBOX, self.OnChangeMapScale, self.statusbarWin['mapscale']) 00206 00207 # go to 00208 self.statusbarWin['goto'] = wx.SpinCtrl(parent=self.statusbar, id=wx.ID_ANY, 00209 min=0) 00210 self.statusbar.Bind(wx.EVT_SPINCTRL, self.OnGoTo, self.statusbarWin['goto']) 00211 self.statusbarWin['goto'].Hide() 00212 self.statusbar.Bind(wx.EVT_TEXT_ENTER, self.OnGoTo, self.statusbarWin['goto']) 00213 00214 # projection, unused but BufferedWindow checks for it 00215 self.statusbarWin['projection'] = wx.CheckBox(parent=self.statusbar, id=wx.ID_ANY, 00216 label=_("Use defined projection")) 00217 self.statusbarWin['projection'].SetValue(False) 00218 size = self.statusbarWin['projection'].GetSize() 00219 self.statusbarWin['projection'].SetMinSize((size[0] + 150, size[1])) 00220 self.statusbarWin['projection'].SetToolTip(wx.ToolTip (_("Reproject coordinates displayed " 00221 "in the statusbar. Projection can be " 00222 "defined in GUI preferences dialog " 00223 "(tab 'Display')"))) 00224 self.statusbarWin['projection'].Hide() 00225 00226 # mask 00227 self.statusbarWin['mask'] = wx.StaticText(parent = self.statusbar, id = wx.ID_ANY, 00228 label = '') 00229 self.statusbarWin['mask'].SetForegroundColour(wx.Colour(255, 0, 0)) 00230 00231 # on-render gauge 00232 self.statusbarWin['progress'] = wx.Gauge(parent=self.statusbar, id=wx.ID_ANY, 00233 range=0, style=wx.GA_HORIZONTAL) 00234 self.statusbarWin['progress'].Hide() 00235 00236 self.StatusbarReposition() # reposition statusbar 00237 00238 # 00239 # Init map display (buffered DC & set default cursor) 00240 # 00241 self.grwiz.SwitchEnv('source') 00242 self.SrcMapWindow = BufferedWindow(self, id=wx.ID_ANY, 00243 Map=self.SrcMap, tree=self.tree, lmgr=self._layerManager) 00244 00245 self.grwiz.SwitchEnv('target') 00246 self.TgtMapWindow = BufferedWindow(self, id=wx.ID_ANY, 00247 Map=self.TgtMap, tree=self.tree, lmgr=self._layerManager) 00248 self.MapWindow = self.SrcMapWindow 00249 self.Map = self.SrcMap 00250 self.SrcMapWindow.SetCursor(self.cursors["cross"]) 00251 self.TgtMapWindow.SetCursor(self.cursors["cross"]) 00252 00253 # 00254 # initialize region values 00255 # 00256 self.__InitDisplay() 00257 00258 # 00259 # Bind various events 00260 # 00261 self.Bind(wx.EVT_ACTIVATE, self.OnFocus) 00262 self.Bind(render.EVT_UPDATE_PRGBAR, self.OnUpdateProgress) 00263 self.Bind(wx.EVT_SIZE, self.OnDispResize) 00264 self.activemap.Bind(wx.EVT_CHOICE, self.OnUpdateActive) 00265 00266 # 00267 # Update fancy gui style 00268 # 00269 # AuiManager wants a CentrePane, workaround to get two equally sized windows 00270 self.list = self.CreateGCPList() 00271 00272 #self.SrcMapWindow.SetSize((300, 300)) 00273 #self.TgtMapWindow.SetSize((300, 300)) 00274 self.list.SetSize((100, 150)) 00275 self._mgr.AddPane(self.list, wx.aui.AuiPaneInfo(). 00276 Name("gcplist").Caption(_("GCP List")).LeftDockable(False). 00277 RightDockable(False).PinButton().FloatingSize((600,200)). 00278 CloseButton(False).DestroyOnClose(True). 00279 Top().Layer(1).MinSize((200,100))) 00280 self._mgr.AddPane(self.SrcMapWindow, wx.aui.AuiPaneInfo(). 00281 Name("source").Caption(_("Source Display")).Dockable(False). 00282 CloseButton(False).DestroyOnClose(True).Floatable(False). 00283 Centre()) 00284 self._mgr.AddPane(self.TgtMapWindow, wx.aui.AuiPaneInfo(). 00285 Name("target").Caption(_("Target Display")).Dockable(False). 00286 CloseButton(False).DestroyOnClose(True).Floatable(False). 00287 Right().Layer(0)) 00288 00289 srcwidth, srcheight = self.SrcMapWindow.GetSize() 00290 tgtwidth, tgtheight = self.TgtMapWindow.GetSize() 00291 srcwidth = (srcwidth + tgtwidth) / 2 00292 self._mgr.GetPane("target").Hide() 00293 self._mgr.Update() 00294 self._mgr.GetPane("source").BestSize((srcwidth, srcheight)) 00295 self._mgr.GetPane("target").BestSize((srcwidth, srcheight)) 00296 if self.show_target: 00297 self._mgr.GetPane("target").Show() 00298 else: 00299 self.activemap.Enable(False) 00300 # needed by Mac OS, does not harm on Linux, breaks display on Windows 00301 if platform.system() != 'Windows': 00302 self._mgr.Update() 00303 00304 # 00305 # Init print module and classes 00306 # 00307 self.printopt = disp_print.PrintOptions(self, self.MapWindow) 00308 00309 # 00310 # Initialization of digitization tool 00311 # 00312 self.digit = None 00313 00314 # set active map 00315 self.MapWindow = self.SrcMapWindow 00316 self.Map = self.SrcMap 00317 00318 # do not init zoom history here, that happens when zooming to map(s) 00319 00320 # 00321 # Re-use dialogs 00322 # 00323 self.dialogs = {} 00324 self.dialogs['attributes'] = None 00325 self.dialogs['category'] = None 00326 self.dialogs['barscale'] = None 00327 self.dialogs['legend'] = None 00328 00329 self.decorationDialog = None # decoration/overlays 00330 00331 def AddToolbar(self, name): 00332 """!Add defined toolbar to the window 00333 00334 Currently known toolbars are: 00335 - 'map' - basic map toolbar 00336 - 'vdigit' - vector digitizer 00337 - 'gcpdisp' - GCP Manager, Display 00338 - 'gcpman' - GCP Manager, points management 00339 - 'georect' - georectifier 00340 - 'nviz' - 3D view mode 00341 """ 00342 # default toolbar 00343 if name == "map": 00344 self.toolbars['map'] = toolbars.MapToolbar(self, self.Map) 00345 00346 self._mgr.AddPane(self.toolbars['map'], 00347 wx.aui.AuiPaneInfo(). 00348 Name("maptoolbar").Caption(_("Map Toolbar")). 00349 ToolbarPane().Top(). 00350 LeftDockable(False).RightDockable(False). 00351 BottomDockable(False).TopDockable(True). 00352 CloseButton(False).Layer(2). 00353 BestSize((self.toolbars['map'].GetSize()))) 00354 00355 # GCP display 00356 elif name == "gcpdisp": 00357 self.toolbars['gcpdisp'] = toolbars.GCPDisplayToolbar(self) 00358 00359 self._mgr.AddPane(self.toolbars['gcpdisp'], 00360 wx.aui.AuiPaneInfo(). 00361 Name("gcpdisplaytoolbar").Caption(_("GCP Display toolbar")). 00362 ToolbarPane().Top(). 00363 LeftDockable(False).RightDockable(False). 00364 BottomDockable(False).TopDockable(True). 00365 CloseButton(False).Layer(2)) 00366 00367 if self.show_target == False: 00368 self.toolbars['gcpdisp'].Enable('zoommenu', enable = False) 00369 00370 self.toolbars['gcpman'] = toolbars.GCPManToolbar(self) 00371 00372 self._mgr.AddPane(self.toolbars['gcpman'], 00373 wx.aui.AuiPaneInfo(). 00374 Name("gcpmanagertoolbar").Caption(_("GCP Manager toolbar")). 00375 ToolbarPane().Top().Row(1). 00376 LeftDockable(False).RightDockable(False). 00377 BottomDockable(False).TopDockable(True). 00378 CloseButton(False).Layer(2)) 00379 00380 self._mgr.Update() 00381 00382 def __InitDisplay(self): 00383 """ 00384 Initialize map display, set dimensions and map region 00385 """ 00386 self.width, self.height = self.GetClientSize() 00387 00388 Debug.msg(2, "MapFrame.__InitDisplay():") 00389 self.grwiz.SwitchEnv('source') 00390 self.SrcMap.ChangeMapSize(self.GetClientSize()) 00391 self.SrcMap.region = self.SrcMap.GetRegion() # g.region -upgc 00392 self.grwiz.SwitchEnv('target') 00393 self.TgtMap.ChangeMapSize(self.GetClientSize()) 00394 self.TgtMap.region = self.TgtMap.GetRegion() # g.region -upgc 00395 # self.SrcMap.SetRegion() # adjust region to match display window 00396 # self.TgtMap.SetRegion() # adjust region to match display window 00397 00398 def OnUpdateProgress(self, event): 00399 """ 00400 Update progress bar info 00401 """ 00402 self.statusbarWin['progress'].SetValue(event.value) 00403 00404 event.Skip() 00405 00406 def OnFocus(self, event): 00407 """ 00408 Change choicebook page to match display. 00409 Or set display for georectifying 00410 """ 00411 if self._layerManager and \ 00412 self._layerManager.gcpmanagement: 00413 # in GCP Management, set focus to current MapWindow for mouse actions 00414 self.OnPointer(event) 00415 self.MapWindow.SetFocus() 00416 else: 00417 # change bookcontrol page to page associated with display 00418 # GCP Manager: use bookcontrol? 00419 if self.page: 00420 pgnum = self.layerbook.GetPageIndex(self.page) 00421 if pgnum > -1: 00422 self.layerbook.SetSelection(pgnum) 00423 00424 event.Skip() 00425 00426 def OnDraw(self, event): 00427 """!Re-display current map composition 00428 """ 00429 self.MapWindow.UpdateMap(render = False) 00430 00431 def OnRender(self, event): 00432 """!Re-render map composition (each map layer) 00433 """ 00434 # delete tmp map layers (queries) 00435 qlayer = self.Map.GetListOfLayers(l_name=globalvar.QUERYLAYER) 00436 for layer in qlayer: 00437 self.Map.DeleteLayer(layer) 00438 00439 self.SrcMapWindow.UpdateMap(render=True) 00440 if self.show_target: 00441 self.TgtMapWindow.UpdateMap(render=True) 00442 00443 # update statusbar 00444 self.StatusbarUpdate() 00445 00446 def OnPointer(self, event): 00447 """!Pointer button clicked 00448 """ 00449 # change the cursor 00450 self.SrcMapWindow.SetCursor(self.cursors["cross"]) 00451 self.SrcMapWindow.mouse['use'] = "pointer" 00452 self.SrcMapWindow.mouse['box'] = "point" 00453 self.TgtMapWindow.SetCursor(self.cursors["cross"]) 00454 self.TgtMapWindow.mouse['use'] = "pointer" 00455 self.TgtMapWindow.mouse['box'] = "point" 00456 00457 def OnZoomIn(self, event): 00458 """ 00459 Zoom in the map. 00460 Set mouse cursor, zoombox attributes, and zoom direction 00461 """ 00462 if self.toolbars['map']: 00463 self.toolbars['map'].OnTool(event) 00464 self.toolbars['map'].action['desc'] = '' 00465 00466 self.MapWindow.mouse['use'] = "zoom" 00467 self.MapWindow.mouse['box'] = "box" 00468 self.MapWindow.zoomtype = 1 00469 self.MapWindow.pen = wx.Pen(colour='Red', width=2, style=wx.SHORT_DASH) 00470 00471 # change the cursor 00472 self.MapWindow.SetCursor(self.cursors["cross"]) 00473 00474 if self.MapWindow == self.SrcMapWindow: 00475 win = self.TgtMapWindow 00476 elif self.MapWindow == self.TgtMapWindow: 00477 win = self.SrcMapWindow 00478 00479 win.mouse['use'] = "zoom" 00480 win.mouse['box'] = "box" 00481 win.zoomtype = 1 00482 win.pen = wx.Pen(colour='Red', width=2, style=wx.SHORT_DASH) 00483 00484 # change the cursor 00485 win.SetCursor(self.cursors["cross"]) 00486 00487 def OnZoomOut(self, event): 00488 """ 00489 Zoom out the map. 00490 Set mouse cursor, zoombox attributes, and zoom direction 00491 """ 00492 if self.toolbars['map']: 00493 self.toolbars['map'].OnTool(event) 00494 self.toolbars['map'].action['desc'] = '' 00495 00496 self.MapWindow.mouse['use'] = "zoom" 00497 self.MapWindow.mouse['box'] = "box" 00498 self.MapWindow.zoomtype = -1 00499 self.MapWindow.pen = wx.Pen(colour='Red', width=2, style=wx.SHORT_DASH) 00500 00501 # change the cursor 00502 self.MapWindow.SetCursor(self.cursors["cross"]) 00503 00504 if self.MapWindow == self.SrcMapWindow: 00505 win = self.TgtMapWindow 00506 elif self.MapWindow == self.TgtMapWindow: 00507 win = self.SrcMapWindow 00508 00509 win.mouse['use'] = "zoom" 00510 win.mouse['box'] = "box" 00511 win.zoomtype = -1 00512 win.pen = wx.Pen(colour='Red', width=2, style=wx.SHORT_DASH) 00513 00514 # change the cursor 00515 win.SetCursor(self.cursors["cross"]) 00516 00517 def OnZoomBack(self, event): 00518 """ 00519 Zoom last (previously stored position) 00520 """ 00521 self.MapWindow.ZoomBack() 00522 00523 def OnPan(self, event): 00524 """ 00525 Panning, set mouse to drag 00526 """ 00527 if self.toolbars['map']: 00528 self.toolbars['map'].OnTool(event) 00529 self.toolbars['map'].action['desc'] = '' 00530 00531 self.MapWindow.mouse['use'] = "pan" 00532 self.MapWindow.mouse['box'] = "pan" 00533 self.MapWindow.zoomtype = 0 00534 00535 # change the cursor 00536 self.MapWindow.SetCursor(self.cursors["hand"]) 00537 00538 if self.MapWindow == self.SrcMapWindow: 00539 win = self.TgtMapWindow 00540 elif self.MapWindow == self.TgtMapWindow: 00541 win = self.SrcMapWindow 00542 00543 win.mouse['use'] = "pan" 00544 win.mouse['box'] = "pan" 00545 win.zoomtype = 0 00546 00547 # change the cursor 00548 win.SetCursor(self.cursors["hand"]) 00549 00550 def OnErase(self, event): 00551 """ 00552 Erase the canvas 00553 """ 00554 self.MapWindow.EraseMap() 00555 00556 if self.MapWindow == self.SrcMapWindow: 00557 win = self.TgtMapWindow 00558 elif self.MapWindow == self.TgtMapWindow: 00559 win = self.SrcMapWindow 00560 00561 win.EraseMap() 00562 00563 def OnZoomRegion(self, event): 00564 """ 00565 Zoom to region 00566 """ 00567 self.Map.getRegion() 00568 self.Map.getResolution() 00569 self.UpdateMap() 00570 # event.Skip() 00571 00572 def OnAlignRegion(self, event): 00573 """ 00574 Align region 00575 """ 00576 if not self.Map.alignRegion: 00577 self.Map.alignRegion = True 00578 else: 00579 self.Map.alignRegion = False 00580 # event.Skip() 00581 00582 def OnToggleRender(self, event): 00583 """ 00584 Enable/disable auto-rendering 00585 """ 00586 if self.statusbarWin['render'].GetValue(): 00587 self.OnRender(None) 00588 00589 def OnToggleShowRegion(self, event): 00590 """ 00591 Show/Hide extent in map canvas 00592 """ 00593 if self.statusbarWin['region'].GetValue(): 00594 # show extent 00595 self.MapWindow.regionCoords = [] 00596 else: 00597 del self.MapWindow.regionCoords 00598 00599 # redraw map if auto-rendering is enabled 00600 if self.statusbarWin['render'].GetValue(): 00601 self.OnRender(None) 00602 00603 def OnToggleResolution(self, event): 00604 """ 00605 Use resolution of computation region settings 00606 for redering image instead of display resolution 00607 """ 00608 # redraw map if auto-rendering is enabled 00609 if self.statusbarWin['render'].GetValue(): 00610 self.OnRender(None) 00611 00612 def OnToggleStatus(self, event): 00613 """ 00614 Toggle status text 00615 """ 00616 self.StatusbarUpdate() 00617 00618 def OnChangeMapScale(self, event): 00619 """ 00620 Map scale changed by user 00621 """ 00622 scale = event.GetString() 00623 00624 try: 00625 if scale[:2] != '1:': 00626 raise ValueError 00627 value = int(scale[2:]) 00628 except ValueError: 00629 self.statusbarWin['mapscale'].SetValue('1:%ld' % int(self.mapScaleValue)) 00630 return 00631 00632 dEW = value * (self.Map.region['cols'] / self.ppm[0]) 00633 dNS = value * (self.Map.region['rows'] / self.ppm[1]) 00634 self.Map.region['n'] = self.Map.region['center_northing'] + dNS / 2. 00635 self.Map.region['s'] = self.Map.region['center_northing'] - dNS / 2. 00636 self.Map.region['w'] = self.Map.region['center_easting'] - dEW / 2. 00637 self.Map.region['e'] = self.Map.region['center_easting'] + dEW / 2. 00638 00639 # add to zoom history 00640 self.MapWindow.ZoomHistory(self.Map.region['n'], self.Map.region['s'], 00641 self.Map.region['e'], self.Map.region['w']) 00642 00643 # redraw a map 00644 self.MapWindow.UpdateMap() 00645 self.statusbarWin['mapscale'].SetFocus() 00646 00647 def OnGoTo(self, event): 00648 """ 00649 Go to position 00650 """ 00651 #GCPNo = int(event.GetString()) 00652 GCPNo = self.statusbarWin['goto'].GetValue() 00653 00654 if GCPNo < 0 or GCPNo > len(self.mapcoordlist): 00655 wx.MessageBox(parent=self, 00656 message="%s 1 - %s." % (_("Valid Range:"), 00657 len(self.mapcoordlist)), 00658 caption=_("Invalid GCP Number"), style=wx.OK | wx.ICON_ERROR | wx.CENTRE) 00659 return 00660 00661 if GCPNo == 0: 00662 return 00663 00664 self.list.selectedkey = GCPNo 00665 self.list.selected = self.list.FindItemData(-1, GCPNo) 00666 self.list.render = False 00667 self.list.SetItemState(self.list.selected, 00668 wx.LIST_STATE_SELECTED, 00669 wx.LIST_STATE_SELECTED) 00670 self.list.render = True 00671 00672 # Source MapWindow: 00673 begin = (self.mapcoordlist[GCPNo][1], self.mapcoordlist[GCPNo][2]) 00674 begin = self.SrcMapWindow.Cell2Pixel(begin) 00675 end = begin 00676 self.SrcMapWindow.Zoom(begin, end, 0) 00677 00678 # redraw map 00679 self.SrcMapWindow.UpdateMap() 00680 00681 if self.show_target: 00682 # Target MapWindow: 00683 begin = (self.mapcoordlist[GCPNo][3], self.mapcoordlist[GCPNo][4]) 00684 begin = self.TgtMapWindow.Cell2Pixel(begin) 00685 end = begin 00686 self.TgtMapWindow.Zoom(begin, end, 0) 00687 00688 # redraw map 00689 self.TgtMapWindow.UpdateMap() 00690 00691 self.statusbarWin['goto'].SetFocus() 00692 00693 def StatusbarUpdate(self): 00694 """!Update statusbar content""" 00695 00696 self.statusbarWin['region'].Hide() 00697 self.statusbarWin['resolution'].Hide() 00698 self.statusbarWin['mapscale'].Hide() 00699 self.statusbarWin['goto'].Hide() 00700 self.mapScaleValue = self.ppm = None 00701 00702 if self.statusbarWin['toggle'].GetSelection() == 0: # Coordinates 00703 self.statusbar.SetStatusText("", 0) 00704 # enable long help 00705 self.StatusbarEnableLongHelp() 00706 00707 elif self.statusbarWin['toggle'].GetSelection() in (1, 2): # Extent 00708 sel = self.statusbarWin['toggle'].GetSelection() 00709 if sel == 1: 00710 region = self.Map.region 00711 else: 00712 region = self.Map.GetRegion() # computation region 00713 00714 precision = int(UserSettings.Get(group = 'projection', key = 'format', 00715 subkey = 'precision')) 00716 format = UserSettings.Get(group = 'projection', key = 'format', 00717 subkey = 'll') 00718 00719 if self.Map.projinfo['proj'] == 'll' and format == 'DMS': 00720 w, s = utils.Deg2DMS(region["w"], region["s"], 00721 string = False, precision = precision) 00722 e, n = utils.Deg2DMS(region["e"], region["n"], 00723 string = False, precision = precision) 00724 if sel == 1: 00725 self.statusbar.SetStatusText("%s - %s, %s - %s" % 00726 (w, e, s, n), 0) 00727 else: 00728 ewres, nsres = utils.Deg2DMS(region['ewres'], region['nsres'], 00729 string = False, precision = precision) 00730 self.statusbar.SetStatusText("%s - %s, %s - %s (%s, %s)" % 00731 (w, e, s, n, ewres, nsres), 0) 00732 else: 00733 w, s = region["w"], region["s"] 00734 e, n = region["e"], region["n"] 00735 if sel == 1: 00736 self.statusbar.SetStatusText("%.*f - %.*f, %.*f - %.*f" % 00737 (precision, w, precision, e, 00738 precision, s, precision, n), 0) 00739 else: 00740 ewres, nsres = region['ewres'], region['nsres'] 00741 self.statusbar.SetStatusText("%.*f - %.*f, %.*f - %.*f (%.*f, %.*f)" % 00742 (precision, w, precision, e, 00743 precision, s, precision, n, 00744 precision, ewres, precision, nsres), 0) 00745 # enable long help 00746 self.StatusbarEnableLongHelp() 00747 00748 elif self.statusbarWin['toggle'].GetSelection() == 3: # Show comp. extent 00749 self.statusbar.SetStatusText("", 0) 00750 self.statusbarWin['region'].Show() 00751 # disable long help 00752 self.StatusbarEnableLongHelp(False) 00753 00754 elif self.statusbarWin['toggle'].GetSelection() == 4: # Display mode 00755 self.statusbar.SetStatusText("", 0) 00756 self.statusbarWin['resolution'].Show() 00757 # disable long help 00758 self.StatusbarEnableLongHelp(False) 00759 00760 elif self.statusbarWin['toggle'].GetSelection() == 5: # Display geometry 00761 self.statusbar.SetStatusText("rows=%d; cols=%d; nsres=%.2f; ewres=%.2f" % 00762 (self.Map.region["rows"], self.Map.region["cols"], 00763 self.Map.region["nsres"], self.Map.region["ewres"]), 0) 00764 # enable long help 00765 self.StatusbarEnableLongHelp() 00766 00767 elif self.statusbarWin['toggle'].GetSelection() == 6: # Map scale 00768 # TODO: need to be fixed... 00769 ### screen X region problem 00770 ### user should specify ppm 00771 dc = wx.ScreenDC() 00772 dpSizePx = wx.DisplaySize() # display size in pixels 00773 dpSizeMM = wx.DisplaySizeMM() # display size in mm (system) 00774 dpSizeIn = (dpSizeMM[0] / 25.4, dpSizeMM[1] / 25.4) # inches 00775 sysPpi = dc.GetPPI() 00776 comPpi = (dpSizePx[0] / dpSizeIn[0], 00777 dpSizePx[1] / dpSizeIn[1]) 00778 00779 ppi = comPpi # pixel per inch 00780 self.ppm = ((ppi[0] / 2.54) * 100, # pixel per meter 00781 (ppi[1] / 2.54) * 100) 00782 00783 Debug.msg(4, "MapFrame.StatusbarUpdate(mapscale): size: px=%d,%d mm=%f,%f " 00784 "in=%f,%f ppi: sys=%d,%d com=%d,%d; ppm=%f,%f" % \ 00785 (dpSizePx[0], dpSizePx[1], dpSizeMM[0], dpSizeMM[1], 00786 dpSizeIn[0], dpSizeIn[1], 00787 sysPpi[0], sysPpi[1], comPpi[0], comPpi[1], 00788 self.ppm[0], self.ppm[1])) 00789 00790 region = self.Map.region 00791 00792 heightCm = region['rows'] / self.ppm[1] * 100 00793 widthCm = region['cols'] / self.ppm[0] * 100 00794 00795 Debug.msg(4, "MapFrame.StatusbarUpdate(mapscale): width_cm=%f, height_cm=%f" % 00796 (widthCm, heightCm)) 00797 00798 xscale = (region['e'] - region['w']) / (region['cols'] / self.ppm[0]) 00799 yscale = (region['n'] - region['s']) / (region['rows'] / self.ppm[1]) 00800 scale = (xscale + yscale) / 2. 00801 00802 Debug.msg(3, "MapFrame.StatusbarUpdate(mapscale): xscale=%f, yscale=%f -> scale=%f" % \ 00803 (xscale, yscale, scale)) 00804 00805 self.statusbar.SetStatusText("") 00806 try: 00807 self.statusbarWin['mapscale'].SetValue("1:%ld" % (scale + 0.5)) 00808 except TypeError: 00809 pass 00810 self.mapScaleValue = scale 00811 self.statusbarWin['mapscale'].Show() 00812 00813 # disable long help 00814 self.StatusbarEnableLongHelp(False) 00815 00816 elif self.statusbarWin['toggle'].GetSelection() == 7: # go to 00817 00818 self.statusbar.SetStatusText("") 00819 max = self.list.GetItemCount() 00820 if max < 1: 00821 max = 1 00822 self.statusbarWin['goto'].SetRange(0, max) 00823 00824 self.statusbarWin['goto'].Show() 00825 00826 # disable long help 00827 self.StatusbarEnableLongHelp(False) 00828 00829 elif self.statusbarWin['toggle'].GetSelection() == 8: # RMS error 00830 self.statusbar.SetStatusText(_("Forward: %(forw)s, Backward: %(back)s") % 00831 { 'forw' : self.fwd_rmserror, 00832 'back' : self.bkw_rmserror }) 00833 # disable long help 00834 # self.StatusbarEnableLongHelp(False) 00835 00836 else: 00837 self.statusbar.SetStatusText("", 1) 00838 00839 def StatusbarEnableLongHelp(self, enable=True): 00840 """!Enable/disable toolbars long help""" 00841 for toolbar in self.toolbars.itervalues(): 00842 if toolbar: 00843 toolbar.EnableLongHelp(enable) 00844 00845 def StatusbarReposition(self): 00846 """!Reposition checkbox in statusbar""" 00847 # reposition checkbox 00848 widgets = [(0, self.statusbarWin['region']), 00849 (0, self.statusbarWin['resolution']), 00850 (0, self.statusbarWin['mapscale']), 00851 (0, self.statusbarWin['progress']), 00852 (0, self.statusbarWin['goto']), 00853 (1, self.statusbarWin['toggle']), 00854 (2, self.statusbarWin['mask']), 00855 (3, self.statusbarWin['render'])] 00856 for idx, win in widgets: 00857 rect = self.statusbar.GetFieldRect(idx) 00858 wWin, hWin = win.GetBestSize() 00859 if idx == 0: # show region / mapscale / process bar 00860 # -> size 00861 if win == self.statusbarWin['progress']: 00862 wWin = rect.width - 6 00863 # -> position 00864 # if win == self.statusbarWin['region']: 00865 # x, y = rect.x + rect.width - wWin, rect.y - 1 00866 # align left 00867 # else: 00868 x, y = rect.x + 3, rect.y - 1 00869 w, h = wWin, rect.height + 2 00870 else: # choice || auto-rendering 00871 x, y = rect.x, rect.y - 1 00872 w, h = rect.width, rect.height + 2 00873 if idx == 1: # choice 00874 h = hWin 00875 elif idx == 2: # mask 00876 x += 5 00877 y += 4 00878 elif idx == 3: # render 00879 x += 5 00880 00881 win.SetPosition((x, y)) 00882 win.SetSize((w, h)) 00883 00884 def SaveToFile(self, event): 00885 """!Save map to image 00886 """ 00887 img = self.MapWindow.img 00888 if not img: 00889 gcmd.GMessage(parent = self, 00890 message = _("Nothing to render (empty map). Operation canceled.")) 00891 return 00892 filetype, ltype = gdialogs.GetImageHandlers(img) 00893 00894 # get size 00895 dlg = gdialogs.ImageSizeDialog(self) 00896 dlg.CentreOnParent() 00897 if dlg.ShowModal() != wx.ID_OK: 00898 dlg.Destroy() 00899 return 00900 width, height = dlg.GetValues() 00901 dlg.Destroy() 00902 00903 # get filename 00904 dlg = wx.FileDialog(parent = self, 00905 message = _("Choose a file name to save the image " 00906 "(no need to add extension)"), 00907 wildcard = filetype, 00908 style=wx.SAVE | wx.FD_OVERWRITE_PROMPT) 00909 00910 if dlg.ShowModal() == wx.ID_OK: 00911 path = dlg.GetPath() 00912 if not path: 00913 dlg.Destroy() 00914 return 00915 00916 base, ext = os.path.splitext(path) 00917 fileType = ltype[dlg.GetFilterIndex()]['type'] 00918 extType = ltype[dlg.GetFilterIndex()]['ext'] 00919 if ext != extType: 00920 path = base + '.' + extType 00921 00922 self.MapWindow.SaveToFile(path, fileType, 00923 width, height) 00924 00925 dlg.Destroy() 00926 00927 def PrintMenu(self, event): 00928 """ 00929 Print options and output menu for map display 00930 """ 00931 point = wx.GetMousePosition() 00932 printmenu = wx.Menu() 00933 # Add items to the menu 00934 setup = wx.MenuItem(printmenu, wx.ID_ANY, _('Page setup')) 00935 printmenu.AppendItem(setup) 00936 self.Bind(wx.EVT_MENU, self.printopt.OnPageSetup, setup) 00937 00938 preview = wx.MenuItem(printmenu, wx.ID_ANY, _('Print preview')) 00939 printmenu.AppendItem(preview) 00940 self.Bind(wx.EVT_MENU, self.printopt.OnPrintPreview, preview) 00941 00942 doprint = wx.MenuItem(printmenu, wx.ID_ANY, _('Print display')) 00943 printmenu.AppendItem(doprint) 00944 self.Bind(wx.EVT_MENU, self.printopt.OnDoPrint, doprint) 00945 00946 # Popup the menu. If an item is selected then its handler 00947 # will be called before PopupMenu returns. 00948 self.PopupMenu(printmenu) 00949 printmenu.Destroy() 00950 00951 def GetRender(self): 00952 """!Returns current instance of render.Map() 00953 """ 00954 return self.Map 00955 00956 def GetWindow(self): 00957 """!Get map window""" 00958 return self.MapWindow 00959 00960 def FormatDist(self, dist): 00961 """!Format length numbers and units in a nice way, 00962 as a function of length. From code by Hamish Bowman 00963 Grass Development Team 2006""" 00964 00965 mapunits = self.Map.projinfo['units'] 00966 if mapunits == 'metres': mapunits = 'meters' 00967 outunits = mapunits 00968 dist = float(dist) 00969 divisor = 1.0 00970 00971 # figure out which units to use 00972 if mapunits == 'meters': 00973 if dist > 2500.0: 00974 outunits = 'km' 00975 divisor = 1000.0 00976 else: outunits = 'm' 00977 elif mapunits == 'feet': 00978 # nano-bug: we match any "feet", but US Survey feet is really 00979 # 5279.9894 per statute mile, or 10.6' per 1000 miles. As >1000 00980 # miles the tick markers are rounded to the nearest 10th of a 00981 # mile (528'), the difference in foot flavours is ignored. 00982 if dist > 5280.0: 00983 outunits = 'miles' 00984 divisor = 5280.0 00985 else: 00986 outunits = 'ft' 00987 elif 'degree' in mapunits: 00988 if dist < 1: 00989 outunits = 'min' 00990 divisor = (1/60.0) 00991 else: 00992 outunits = 'deg' 00993 00994 # format numbers in a nice way 00995 if (dist/divisor) >= 2500.0: 00996 outdist = round(dist/divisor) 00997 elif (dist/divisor) >= 1000.0: 00998 outdist = round(dist/divisor,1) 00999 elif (dist/divisor) > 0.0: 01000 outdist = round(dist/divisor,int(math.ceil(3-math.log10(dist/divisor)))) 01001 else: 01002 outdist = float(dist/divisor) 01003 01004 return (outdist, outunits) 01005 01006 def OnZoomToMap(self, event): 01007 """! 01008 Set display extents to match selected raster (including NULLs) 01009 or vector map. 01010 """ 01011 self.MapWindow.ZoomToMap(layers = self.Map.GetListOfLayers()) 01012 01013 def OnZoomToRaster(self, event): 01014 """! 01015 Set display extents to match selected raster map (ignore NULLs) 01016 """ 01017 self.MapWindow.ZoomToMap(ignoreNulls = True) 01018 01019 def OnZoomToWind(self, event): 01020 """!Set display geometry to match computational region 01021 settings (set with g.region) 01022 """ 01023 self.MapWindow.ZoomToWind() 01024 01025 def OnZoomToDefault(self, event): 01026 """!Set display geometry to match default region settings 01027 """ 01028 self.MapWindow.ZoomToDefault() 01029 01030 def OnZoomToSaved(self, event): 01031 """!Set display geometry to match extents in 01032 saved region file 01033 """ 01034 self.MapWindow.ZoomToSaved() 01035 01036 def OnDisplayToWind(self, event): 01037 """!Set computational region (WIND file) to match display 01038 extents 01039 """ 01040 self.MapWindow.DisplayToWind() 01041 01042 def SaveDisplayRegion(self, event): 01043 """!Save display extents to named region file. 01044 """ 01045 self.MapWindow.SaveDisplayRegion() 01046 01047 def OnZoomMenu(self, event): 01048 """!Popup Zoom menu 01049 """ 01050 point = wx.GetMousePosition() 01051 zoommenu = wx.Menu() 01052 # Add items to the menu 01053 01054 zoomwind = wx.MenuItem(zoommenu, wx.ID_ANY, _('Zoom to computational region (set with g.region)')) 01055 zoommenu.AppendItem(zoomwind) 01056 self.Bind(wx.EVT_MENU, self.OnZoomToWind, zoomwind) 01057 01058 zoomdefault = wx.MenuItem(zoommenu, wx.ID_ANY, _('Zoom to default region')) 01059 zoommenu.AppendItem(zoomdefault) 01060 self.Bind(wx.EVT_MENU, self.OnZoomToDefault, zoomdefault) 01061 01062 zoomsaved = wx.MenuItem(zoommenu, wx.ID_ANY, _('Zoom to saved region')) 01063 zoommenu.AppendItem(zoomsaved) 01064 self.Bind(wx.EVT_MENU, self.OnZoomToSaved, zoomsaved) 01065 01066 savewind = wx.MenuItem(zoommenu, wx.ID_ANY, _('Set computational region from display')) 01067 zoommenu.AppendItem(savewind) 01068 self.Bind(wx.EVT_MENU, self.OnDisplayToWind, savewind) 01069 01070 savezoom = wx.MenuItem(zoommenu, wx.ID_ANY, _('Save display geometry to named region')) 01071 zoommenu.AppendItem(savezoom) 01072 self.Bind(wx.EVT_MENU, self.SaveDisplayRegion, savezoom) 01073 01074 # Popup the menu. If an item is selected then its handler 01075 # will be called before PopupMenu returns. 01076 self.PopupMenu(zoommenu) 01077 zoommenu.Destroy() 01078 01079 def SetProperties(self, render=False, mode=0, showCompExtent=False, 01080 constrainRes=False, projection=False): 01081 """!Set properies of map display window""" 01082 self.statusbarWin['render'].SetValue(render) 01083 self.statusbarWin['toggle'].SetSelection(mode) 01084 self.StatusbarUpdate() 01085 self.statusbarWin['region'].SetValue(showCompExtent) 01086 self.statusbarWin['resolution'].SetValue(constrainRes) 01087 if showCompExtent: 01088 self.MapWindow.regionCoords = [] 01089 01090 def IsStandalone(self): 01091 """!Check if Map display is standalone""" 01092 if self._layerManager: 01093 return False 01094 01095 return True 01096 01097 def GetLayerManager(self): 01098 """!Get reference to Layer Manager 01099 01100 @return window reference 01101 @return None (if standalone) 01102 """ 01103 return self._layerManager 01104 01105 # end of class MapFrame