4 @brief Map display with toolbar for various display management
5 functions, and additional toolbars (vector digitizer, 3d view).
7 Can be used either from Layer Manager or as d.mon backend.
12 (C) 2006-2011 by the GRASS Development Team
14 This program is free software under the GNU General Public License
15 (>=v2). Read the file COPYING that comes with GRASS for details.
17 @author Michael Barton
18 @author Jachym Cepicky
19 @author Martin Landa <landa.martin gmail.com>
20 @author Vaclav Petras <wenzeslaus gmail.com> (MapFrameBase)
21 @author Anna Kratochvilova <kratochanna gmail.com> (MapFrameBase)
29 from core
import globalvar
33 sys.path.append(os.path.join(globalvar.ETCWXDIR,
"icons"))
34 sys.path.append(os.path.join(globalvar.ETCDIR,
"python"))
36 from core
import globalvar
41 from core.gcmd import GError, GMessage, RunCommand
43 from core.utils import ListOfCatsToRange, GetLayerNameFromCmd, GetAllVectorLayers
44 from gui_core.dialogs import GetImageHandlers, ImageSizeDialog, DecorationDialog, TextLayerDialog, \
45 DECOR_DIALOG_LEGEND, DECOR_DIALOG_BARSCALE
54 from mapdisp
import statusbar
as sb
61 """!Main frame for map display window. Drawing takes place in
62 child double buffered drawing window.
64 def __init__(self, parent = None, title = _(
"GRASS GIS - Map display"),
65 toolbars = [
"map"], tree =
None, notebook =
None, lmgr =
None,
66 page =
None, Map =
None, auimgr =
None, name =
'MapWindow', **kwargs):
67 """!Main map display window with toolbars, statusbar and
68 BufferedWindow (map canvas)
70 @param toolbars array of activated toolbars, e.g. ['map', 'digit']
71 @param tree reference to layer tree
72 @param notebook control book ID in Layer Manager
73 @param lmgr Layer Manager
74 @param page notebook page with layer tree
75 @param Map instance of render.Map
76 @param auimgs AUI manager
77 @param name frame name
78 @param kwargs wx.Frame attributes
80 MapFrameBase.__init__(self, parent = parent, title = title, toolbars = toolbars,
81 Map = Map, auimgr = auimgr, name = name, **kwargs)
90 for toolb
in toolbars:
100 sb.SbCompRegionExtent,
104 sb.SbDisplayGeometry,
110 sb.SbDisplayGeometry,
116 statusbar = self.CreateStatusBar(number = 4, style = 0)
117 statusbar.SetStatusWidths([-5, -2, -1, -1])
121 self.statusbarManager.AddStatusbarItemsByClass(self.
statusbarItems, mapframe = self, statusbar = statusbar)
122 self.statusbarManager.AddStatusbarItem(sb.SbMask(self, statusbar = statusbar, position = 2))
123 self.statusbarManager.AddStatusbarItem(sb.SbRender(self, statusbar = statusbar, position = 3))
125 self.statusbarManager.Update()
141 self.MapWindow.SetCursor(self.cursors[
"default"])
150 self._initMap(map = self.Map)
155 self.Bind(wx.EVT_ACTIVATE, self.
OnFocus)
162 self._mgr.AddPane(self.
MapWindow, wx.aui.AuiPaneInfo().CentrePane().
163 Dockable(
False).BestSize((-1,-1)).Name(
'2d').
164 CloseButton(
False).DestroyOnClose(
True).
176 self.MapWindow.ZoomHistory(self.Map.region[
'n'],
177 self.Map.region[
's'],
178 self.Map.region[
'e'],
179 self.Map.region[
'w'])
185 self.
dialogs[
'attributes'] =
None
186 self.
dialogs[
'category'] =
None
187 self.
dialogs[
'barscale'] =
None
195 def _addToolbarVDigit(self):
196 """!Add vector digitizer toolbar
201 from vdigit
import errorMsg
202 msg = _(
"Unable to start wxGUI vector digitizer.\nDo you want to start "
203 "TCL/TK digitizer (v.digit) instead?\n\n"
204 "Details: %s" % errorMsg)
206 self.toolbars[
'map'].combo.SetValue(_(
"2D view"))
207 dlg = wx.MessageDialog(parent = self,
209 caption=_(
"Vector digitizer failed"),
210 style = wx.YES_NO | wx.CENTRE)
211 if dlg.ShowModal() == wx.ID_YES:
212 mapName = self.tree.GetPyData(self.tree.layer_selected)[0][
'maplayer'].GetName()
213 self._layerManager.goutput.RunCmd([
'v.digit',
'map=%s' % mapName],
217 self.toolbars[
'map'].combo.SetValue(_(
"2D view"))
221 log = self._layerManager.goutput
228 Map = self.Map, tree = self.
tree,
230 self.MapWindowVDigit.Show()
231 self._mgr.AddPane(self.
MapWindowVDigit, wx.aui.AuiPaneInfo().CentrePane().
232 Dockable(
False).BestSize((-1,-1)).Name(
'vdigit').
233 CloseButton(
False).DestroyOnClose(
True).
238 if self._mgr.GetPane(
'2d').IsShown():
239 self._mgr.GetPane(
'2d').Hide()
240 elif self._mgr.GetPane(
'3d').IsShown():
241 self._mgr.GetPane(
'3d').Hide()
242 self._mgr.GetPane(
'vdigit').Show()
243 self.toolbars[
'vdigit'] = VDigitToolbar(parent = self, mapcontent = self.Map,
244 layerTree = self.
tree,
246 self.MapWindowVDigit.SetToolbar(self.toolbars[
'vdigit'])
248 self._mgr.AddPane(self.toolbars[
'vdigit'],
249 wx.aui.AuiPaneInfo().
250 Name(
"vdigittoolbar").Caption(_(
"Vector Digitizer Toolbar")).
251 ToolbarPane().Top().Row(1).
252 LeftDockable(
False).RightDockable(
False).
253 BottomDockable(
False).TopDockable(
True).
254 CloseButton(
False).Layer(2).
255 BestSize((self.toolbars[
'vdigit'].GetBestSize())))
257 self.MapWindow.mouse[
'box'] =
"point"
258 self.MapWindow.zoomtype = 0
259 self.MapWindow.pen = wx.Pen(colour =
'red', width = 2, style = wx.SOLID)
260 self.MapWindow.polypen = wx.Pen(colour =
'green', width = 2, style = wx.SOLID)
263 """!Add 3D view mode window
269 self.toolbars[
'map'].combo.SetValue(_(
"2D view"))
270 GError(parent = self,
271 message = _(
"Unable to switch to 3D display mode.\nThe Nviz python extension "
272 "was not found or loaded properly.\n"
273 "Switching back to 2D display mode.\n\nDetails: %s" % nviz.errorMsg))
277 for page
in range(0, self._layerManager.gm_cb.GetPageCount()):
278 if self._layerManager.gm_cb.GetPage(page) != self._layerManager.curr_page:
279 if '3D' in self._layerManager.gm_cb.GetPage(page).maptree.mapdisplay.toolbars[
'map'].combo.GetString(1):
280 self._layerManager.gm_cb.GetPage(page).maptree.mapdisplay.toolbars[
'map'].combo.Delete(1)
281 self.toolbars[
'map'].Enable2D(
False)
283 self.toolbars[
'map'].InsertTool(((
'rotate', NvizIcons[
'rotate'],
285 self.toolbars[
'map'].InsertTool(((
'flyThrough', NvizIcons[
'flyThrough'],
287 self.toolbars[
'map'].ChangeToolsDesc(mode2d =
False)
291 self.statusbarManager.SetMode(0)
294 self.MapWindow.EraseMap()
296 self._layerManager.goutput.WriteCmdLog(_(
"Starting 3D view mode..."),
298 self.SetStatusText(_(
"Please wait, loading data..."), 0)
305 self.MapWindow.SetCursor(self.cursors[
"default"])
308 self._layerManager.AddNvizTools()
311 self._mgr.GetPane(
'2d').Hide()
312 self._mgr.AddPane(self.
MapWindow3D, wx.aui.AuiPaneInfo().CentrePane().
313 Dockable(
False).BestSize((-1,-1)).Name(
'3d').
314 CloseButton(
False).DestroyOnClose(
True).
317 self.MapWindow3D.Show()
318 self.MapWindow3D.ResetViewHistory()
319 self.MapWindow3D.UpdateView(
None)
322 os.environ[
'GRASS_REGION'] = self.Map.SetRegion(windres =
True)
323 self.MapWindow3D.GetDisplay().Init()
324 del os.environ[
'GRASS_REGION']
327 self._mgr.GetPane(
'2d').Hide()
328 self._mgr.GetPane(
'3d').Show()
331 self._layerManager.AddNvizTools()
332 self.MapWindow3D.ResetViewHistory()
333 for page
in (
'view',
'light',
'fringe',
'constant',
'cplane',
'animation'):
334 self._layerManager.nviz.UpdatePage(page)
336 self.MapWindow3D.overlays = self.MapWindow2D.overlays
337 self.MapWindow3D.textdict = self.MapWindow2D.textdict
340 wx.CallAfter(self.MapWindow3D.UpdateOverlays)
342 self.SetStatusText(
"", 0)
346 """!Restore 2D view"""
347 self.toolbars[
'map'].RemoveTool(self.toolbars[
'map'].rotate)
348 self.toolbars[
'map'].RemoveTool(self.toolbars[
'map'].flyThrough)
351 self.statusbarManager.SetMode(UserSettings.Get(group =
'display',
352 key =
'statusbarMode',
353 subkey =
'selection'))
354 self.SetStatusText(_(
"Please wait, unloading data..."), 0)
355 self._layerManager.goutput.WriteCmdLog(_(
"Switching back to 2D view mode..."),
357 self.MapWindow3D.OnClose(event =
None)
359 self._mgr.GetPane(
'2d').Show()
360 self._mgr.GetPane(
'3d').Hide()
364 self._layerManager.RemoveNvizTools()
366 self.MapWindow2D.overlays = self.MapWindow3D.overlays
367 self.MapWindow2D.textdict = self.MapWindow3D.textdict
368 self.MapWindow.UpdateMap()
372 """!Add defined toolbar to the window
374 Currently known toolbars are:
375 - 'map' - basic map toolbar
376 - 'vdigit' - vector digitizer
377 - 'gcpdisp' - GCP Manager Display
381 self.toolbars[
'map'] = MapToolbar(self, self.Map)
383 self._mgr.AddPane(self.toolbars[
'map'],
384 wx.aui.AuiPaneInfo().
385 Name(
"maptoolbar").Caption(_(
"Map Toolbar")).
386 ToolbarPane().Top().Name(
'mapToolbar').
387 LeftDockable(
False).RightDockable(
False).
388 BottomDockable(
False).TopDockable(
True).
389 CloseButton(
False).Layer(2).
390 BestSize((self.toolbars[
'map'].GetBestSize())))
393 elif name ==
"vdigit":
399 """!Removes defined toolbar from the window
401 @todo Only hide, activate by calling AddToolbar()
407 self._mgr.DetachPane(self.toolbars[name])
408 self.toolbars[name].Destroy()
409 self.toolbars.pop(name)
412 self._mgr.GetPane(
'vdigit').Hide()
413 self._mgr.GetPane(
'2d').Show()
416 self.toolbars[
'map'].combo.SetValue(_(
"2D view"))
417 self.toolbars[
'map'].Enable2D(
True)
422 """!Check if pane (toolbar, mapWindow ...) of given name is currently shown"""
423 if self._mgr.GetPane(name).IsOk():
424 return self._mgr.GetPane(name).IsShown()
428 """!Update progress bar info
430 self.GetProgressBar().
SetValue(event.value)
435 """!Change choicebook page to match display.
439 pgnum = self.layerbook.GetPageIndex(self.
page)
441 self.layerbook.SetSelection(pgnum)
442 self._layerManager.curr_page = self.layerbook.GetCurrentPage()
447 """!Removes temporary map layers (queries)"""
448 qlayer = self.GetMap().GetListOfLayers(l_name = globalvar.QUERYLAYER)
450 self.GetMap().DeleteLayer(layer)
453 """!Re-render map composition (each map layer)
458 if self.MapWindow.mouse[
"use"]
in (
"measure",
460 self.MapWindow.polycoords = []
461 self.MapWindow.ClearLines()
464 if self.GetToolbar(
'vdigit'):
465 if self.MapWindow.digit:
466 self.MapWindow.digit.GetDisplay().SetSelected([])
467 self.MapWindow.UpdateMap(render =
True, renderVector =
True)
469 self.MapWindow.UpdateMap(render =
True)
472 self.StatusbarUpdate()
475 """!Pointer button clicked
479 self.toolbars[
'map'].OnTool(event)
480 self.toolbars[
'map'].action[
'desc'] =
''
482 self.MapWindow.mouse[
'use'] =
"pointer"
483 self.MapWindow.mouse[
'box'] =
"point"
486 if self.GetToolbar(
'vdigit'):
488 self.MapWindow.SetCursor(self.cursors[
"cross"])
491 if self.toolbars[
'vdigit'].GetAction()
in [
'addLine']:
492 if self.toolbars[
'vdigit'].GetAction(
'type')
in [
'point',
'centroid']:
493 self.MapWindow.mouse[
'box'] =
'point'
495 self.MapWindow.mouse[
'box'] =
'line'
496 elif self.toolbars[
'vdigit'].GetAction()
in [
'addVertex',
'removeVertex',
'splitLine',
497 'editLine',
'displayCats',
'queryMap',
499 self.MapWindow.mouse[
'box'] =
'point'
501 self.MapWindow.mouse[
'box'] =
'box'
504 self.MapWindow.SetCursor(self.cursors[
"default"])
510 self.toolbars[
'map'].OnTool(event)
511 self.toolbars[
'map'].action[
'desc'] =
''
513 self.MapWindow.mouse[
'use'] =
"rotate"
516 self.MapWindow.SetCursor(self.cursors[
"hand"])
521 if self.toolbars[
'map']:
522 self.toolbars[
'map'].OnTool(event)
523 self.toolbars[
'map'].action[
'desc'] =
''
525 self.MapWindow.mouse[
'use'] =
"fly"
528 self.MapWindow.SetCursor(self.cursors[
"hand"])
529 self.MapWindow.SetFocus()
536 self.Map.getResolution()
544 if not self.Map.alignRegion:
545 self.Map.alignRegion =
True
547 self.Map.alignRegion =
False
551 """!Save map to image
554 filetype =
"TIF file (*.tif)|*.tif|PPM file (*.ppm)|*.ppm"
555 ltype = [{
'ext' :
'tif',
'type' :
'tif' },
556 {
'ext' :
'ppm',
'type' :
'ppm' }]
558 img = self.MapWindow.img
560 GMessage(parent = self,
561 message = _(
"Nothing to render (empty map). Operation canceled."))
566 dlg = ImageSizeDialog(self)
568 if dlg.ShowModal() != wx.ID_OK:
571 width, height = dlg.GetValues()
575 dlg = wx.FileDialog(parent = self,
576 message = _(
"Choose a file name to save the image "
577 "(no need to add extension)"),
579 style = wx.FD_SAVE | wx.FD_OVERWRITE_PROMPT)
581 if dlg.ShowModal() == wx.ID_OK:
587 base, ext = os.path.splitext(path)
588 fileType = ltype[dlg.GetFilterIndex()][
'type']
589 extType = ltype[dlg.GetFilterIndex()][
'ext']
591 path = base +
'.' + extType
593 self.MapWindow.SaveToFile(path, fileType,
600 Print options and output menu for map display
602 point = wx.GetMousePosition()
603 printmenu = wx.Menu()
605 setup = wx.MenuItem(printmenu, wx.ID_ANY, _(
'Page setup'))
606 printmenu.AppendItem(setup)
607 self.Bind(wx.EVT_MENU, self.printopt.OnPageSetup, setup)
609 preview = wx.MenuItem(printmenu, wx.ID_ANY, _(
'Print preview'))
610 printmenu.AppendItem(preview)
611 self.Bind(wx.EVT_MENU, self.printopt.OnPrintPreview, preview)
613 doprint = wx.MenuItem(printmenu, wx.ID_ANY, _(
'Print display'))
614 printmenu.AppendItem(doprint)
615 self.Bind(wx.EVT_MENU, self.printopt.OnDoPrint, doprint)
619 self.PopupMenu(printmenu)
624 Also close associated layer tree page
630 if self.GetToolbar(
'vdigit'):
631 maplayer = self.toolbars[
'vdigit'].GetLayer()
633 self.toolbars[
'vdigit'].OnExit()
640 pgnum = self.layerbook.GetPageIndex(self.
page)
642 self.layerbook.DeletePage(pgnum)
645 """!Query selected layers.
647 Calls QueryMap in case of raster or more vectors,
648 or QueryVector in case of one vector with db connection.
650 @param x,y coordinates
651 @param layers selected tree item layers
656 ltype = self.tree.GetPyData(layer)[0][
'maplayer'].GetType()
657 if ltype
in (
'raster',
'rgb',
'his',
658 'vector',
'thememap',
'themechart'):
659 filteredLayers.append(layer)
661 if not filteredLayers:
662 GMessage(parent = self,
663 message = _(
'No raster or vector map layer selected for querying.'))
666 layers = filteredLayers
668 qdist = 10.0 * ((self.Map.region[
'e'] - self.Map.region[
'w']) / self.Map.width)
669 east, north = self.MapWindow.Pixel2Cell((x, y))
671 posWindow = self.ClientToScreen((x + self.MapWindow.dialogOffset,
672 y + self.MapWindow.dialogOffset))
676 isDbConnection =
False
677 allLayersConnected =
None
679 maplayer = self.tree.GetPyData(l)[0][
'maplayer']
680 if maplayer.GetType() ==
'raster':
683 if maplayer.GetType() ==
'vector':
685 isDbConnection = grass.vector_db(maplayer.GetName())
690 allLayersConnected =
True
691 vLayersDb = sorted(isDbConnection.keys())
693 if vLayersAll != vLayersDb:
694 allLayersConnected =
False
697 if isRaster
or nVectors > 1
or not allLayersConnected:
698 self.
QueryMap(east, north, qdist, layers)
700 self.
QueryVector(east, north, qdist, posWindow, layers[0])
703 self.MapWindow.QuerySurface(x, y)
704 if nVectors > 1
or not isDbConnection:
705 self.
QueryMap(east, north, qdist, layers)
707 self.
QueryVector(east, north, qdist, posWindow, layers[0])
710 """!Query raster or vector map layers by r/v.what
712 @param east,north coordinates
713 @param qdist query distance
714 @param layers selected tree items
718 rcmd = [
'r.what',
'--v']
719 vcmd = [
'v.what',
'--v']
722 ltype = self.tree.GetPyData(layer)[0][
'maplayer'].GetType()
723 dcmd = self.tree.GetPyData(layer)[0][
'cmd']
728 if ltype ==
'raster':
730 elif ltype
in (
'rgb',
'his'):
731 for iname
in name.split(
'\n'):
733 elif ltype
in (
'vector',
'thememap',
'themechart'):
738 os.environ[
"GRASS_REGION"] = self.Map.SetRegion(windres =
False)
744 rcmd.append(
'input=%s' %
','.join(rast))
745 rcmd.append(
'east_north=%f,%f' % (float(east), float(north)))
749 digitToolbar = self.GetToolbar(
'vdigit')
751 lmap = digitToolbar.GetLayer().GetName()
754 self._layerManager.goutput.WriteWarning(_(
"Vector map <%s> "
755 "opened for editing - skipped.") % map)
759 self._layerManager.goutput.WriteCmdLog(_(
"Nothing to query."))
763 vcmd.append(
'map=%s' %
','.join(vect))
764 vcmd.append(
'east_north=%f,%f' % (float(east), float(north)))
765 vcmd.append(
'distance=%f' % float(qdist))
767 Debug.msg(1,
"QueryMap(): raster=%s vector=%s" % (
','.join(rast),
772 self._layerManager.goutput.RunCmd(rcmd,
776 self._layerManager.goutput.RunCmd(vcmd,
779 def _QueryMapDone(self, cmd, returncode):
780 """!Restore settings after querying (restore GRASS_REGION)
782 @param returncode command return code
784 if hasattr(self,
"tmpreg"):
786 os.environ[
"GRASS_REGION"] = self.
tmpreg
787 elif 'GRASS_REGION' in os.environ:
788 del os.environ[
"GRASS_REGION"]
789 elif 'GRASS_REGION' in os.environ:
790 del os.environ[
"GRASS_REGION"]
792 if hasattr(self,
"tmpreg"):
796 """!Query vector map layer features
798 Attribute data of selected vector object are displayed in GUI dialog.
799 Data can be modified (On Submit)
801 mapName = self.tree.GetPyData(layer)[0][
'maplayer'].name
803 if self.tree.GetPyData(layer)[0][
'maplayer'].GetMapset() != \
804 grass.gisenv()[
'MAPSET']:
809 if self.
dialogs[
'attributes']
is None:
810 dlg = DisplayAttributesDialog(parent = self.
MapWindow,
812 query = ((east, north), qdist),
815 self.
dialogs[
'attributes'] = dlg
819 if not self.
dialogs[
'attributes'].mapDBInfo
or \
820 self.
dialogs[
'attributes'].mapDBInfo.map != mapName:
826 if not self.
dialogs[
'attributes'].IsFound():
827 self._layerManager.goutput.WriteLog(_(
'Nothing found.'))
829 cats = self.
dialogs[
'attributes'].GetCats()
832 if not self.
IsPaneShown(
'3d')
and self.IsAutoRendered():
834 qlayer = self.Map.GetListOfLayers(l_name = globalvar.QUERYLAYER)[0]
838 if self.
dialogs[
'attributes'].mapDBInfo
and cats:
839 if not self.
IsPaneShown(
'3d')
and self.IsAutoRendered():
849 opacity = self.tree.GetPyData(layer)[0][
'maplayer'].GetOpacity(float =
True)
850 qlayer.SetOpacity(opacity)
852 self.MapWindow.UpdateMap(render =
False, renderVector =
False)
853 if not self.
dialogs[
'attributes'].IsShown():
854 self.
dialogs[
'attributes'].Show()
857 self.Map.DeleteLayer(qlayer)
858 self.MapWindow.UpdateMap(render =
False, renderVector =
False)
859 if self.
dialogs[
'attributes'].IsShown():
860 self.
dialogs[
'attributes'].Hide()
863 """!Query tools menu"""
865 self.toolbars[
'map'].OnTool(event)
866 action = self.toolbars[
'map'].GetAction()
868 self.toolbars[
'map'].action[
'desc'] =
'queryMap'
869 self.MapWindow.mouse[
'use'] =
"query"
873 self._layerManager.notebook.SetSelectionByName(
'output')
875 self.MapWindow.mouse[
'box'] =
"point"
876 self.MapWindow.zoomtype = 0
879 self.MapWindow.SetCursor(self.cursors[
"cross"])
882 """!Add temporal vector map layer to map composition
884 @param name name of map layer
885 @param useId use feature id instead of category
888 color = UserSettings.Get(group =
'atm', key =
'highlight', subkey =
'color')
889 colorStr = str(color[0]) +
":" + \
890 str(color[1]) +
":" + \
896 vparam = self.tree.GetPyData(self.tree.layer_selected)[0][
'cmd']
899 parg,pval = p.split(
'=', 1)
900 if parg ==
'icon': icon = pval
901 elif parg ==
'size': size = float(pval)
905 "color=%s" % colorStr,
906 "fcolor=%s" % colorStr,
907 "width=%d" % UserSettings.Get(group =
'atm', key =
'highlight', subkey =
'width')]
909 pattern.append(
'icon=%s' % icon)
911 pattern.append(
'size=%i' % size)
916 cmd.append(
'cats=%s' % str(cats))
919 for layer
in cats.keys():
920 cmd.append(copy.copy(pattern))
922 cmd[-1].append(
"layer=%d" % layer)
927 return self.Map.AddLayer(type =
'vector', name = globalvar.QUERYLAYER, command = cmd,
928 l_active =
True, l_hidden =
True, l_opacity = 1.0)
930 return self.Map.AddLayer(type =
'command', name = globalvar.QUERYLAYER, command = cmd,
931 l_active =
True, l_hidden =
True, l_opacity = 1.0)
936 """!Init measurement routine that calculates map distance
937 along transect drawn on map display
942 self._layerManager.notebook.SetSelectionByName(
'output')
945 self.MapWindow.mouse[
'use'] =
"measure"
946 self.MapWindow.mouse[
'box'] =
"line"
947 self.MapWindow.zoomtype = 0
948 self.MapWindow.pen = wx.Pen(colour =
'red', width = 2, style = wx.SHORT_DASH)
949 self.MapWindow.polypen = wx.Pen(colour =
'green', width = 2, style = wx.SHORT_DASH)
952 self.MapWindow.SetCursor(self.cursors[
"pencil"])
955 self._layerManager.goutput.WriteWarning(_(
'Click and drag with left mouse button '
957 'Double click with left button to clear.'))
959 if self.Map.projinfo[
'proj'] !=
'xy':
960 units = self.Map.projinfo[
'units']
961 self._layerManager.goutput.WriteCmdLog(_(
'Measuring distance') +
' ('
964 self._layerManager.goutput.WriteCmdLog(_(
'Measuring distance:'))
966 if self.Map.projinfo[
'proj'] ==
'll':
972 gislib.G_begin_distance_calculations()
973 except ImportError, e:
974 self._layerManager.goutput.WriteWarning(_(
'Geodesic distance is not yet '
975 'supported by this tool.\n'
979 """!Calculate map distance from screen distance
980 and print to output window
982 self._layerManager.notebook.SetSelectionByName(
'output')
984 dist, (north, east) = self.MapWindow.Distance(beginpt, endpt)
986 dist =
round(dist, 3)
995 if self.Map.projinfo[
'proj'] ==
'xy' or 'degree' not in self.Map.projinfo[
'unit']:
996 angle = int(math.degrees(math.atan2(north,east)) + 0.5)
1003 mstring =
'%s = %s %s\n%s = %s %s\n%s = %d %s\n%s' \
1004 % (_(
'segment'), strdist, dunits,
1005 _(
'total distance'), strtotdist, tdunits,
1006 _(
'bearing'), angle, _(
'degrees (clockwise from grid-north)'),
1009 mstring =
'%s = %s %s\n%s = %s %s\n%s' \
1010 % (_(
'segment'), strdist, dunits,
1011 _(
'total distance'), strtotdist, tdunits,
1014 self._layerManager.goutput.WriteLog(mstring)
1019 """!Launch profile tool
1022 if self.tree.layer_selected
and \
1023 self.tree.GetPyData(self.tree.layer_selected)[0][
'type'] ==
'raster':
1024 raster.append(self.tree.GetPyData(self.tree.layer_selected)[0][
'maplayer'].name)
1026 win = ProfileFrame(parent = self, rasterList = raster)
1028 win.CentreOnParent()
1032 win.OnSelectRaster(
None)
1035 """!Format length numbers and units in a nice way,
1036 as a function of length. From code by Hamish Bowman
1037 Grass Development Team 2006"""
1039 mapunits = self.Map.projinfo[
'units']
1040 if mapunits ==
'metres':
1047 if mapunits ==
'meters':
1051 else: outunits =
'm'
1052 elif mapunits ==
'feet':
1062 elif 'degree' in mapunits
and \
1073 if (dist/divisor) >= 2500.0:
1074 outdist =
round(dist/divisor)
1075 elif (dist/divisor) >= 1000.0:
1076 outdist =
round(dist/divisor,1)
1077 elif (dist/divisor) > 0.0:
1078 outdist =
round(dist/divisor,int(math.ceil(3-math.log10(dist/divisor))))
1080 outdist = float(dist/divisor)
1082 return (outdist, outunits)
1085 """!Init histogram display canvas and tools
1087 win = HistogramFrame(self)
1089 win.CentreOnParent()
1095 """!Handler for scale/arrow map decoration menu selection.
1098 self.barscale.cmd = cmd
1101 self.barscale.Show()
1102 self.MapWindow.UpdateMap()
1107 if self.
dialogs[
'barscale'].IsShown():
1108 self.
dialogs[
'barscale'].SetFocus()
1110 self.
dialogs[
'barscale'].Show()
1121 DecorationDialog(parent = self, title = _(
'Scale and North arrow'),
1123 ddstyle = DECOR_DIALOG_BARSCALE,
1125 style = wx.DEFAULT_DIALOG_STYLE | wx.CENTRE)
1127 self.
dialogs[
'barscale'].CentreOnParent()
1130 self.
dialogs[
'barscale'].Show()
1131 self.MapWindow.mouse[
'use'] =
'pointer'
1134 """!Handler for legend map decoration menu selection.
1137 self.legend.cmd = cmd
1139 if self.tree.layer_selected
and \
1140 self.tree.GetPyData(self.tree.layer_selected)[0][
'type'] ==
'raster':
1141 self.legend.cmd.append(
'map=%s' % self.tree.GetPyData(self.tree.layer_selected)[0][
'maplayer'].name)
1145 self.MapWindow.UpdateMap()
1150 if self.
dialogs[
'legend'].IsShown():
1151 self.
dialogs[
'legend'].SetFocus()
1157 DecorationDialog(parent = self, title = (
'Legend'),
1158 overlayController = self.
legend,
1159 ddstyle = DECOR_DIALOG_LEGEND,
1161 style = wx.DEFAULT_DIALOG_STYLE | wx.CENTRE)
1163 self.
dialogs[
'legend'].CentreOnParent()
1167 self.MapWindow.mouse[
'use'] =
'pointer'
1170 """!Handler for text decoration menu selection.
1172 if self.MapWindow.dragid > -1:
1173 id = self.MapWindow.dragid
1174 self.MapWindow.dragid = -1
1177 if len(self.MapWindow.textdict.keys()) > 0:
1178 id =
max(self.MapWindow.textdict.keys()) + 1
1182 self.
dialogs[
'text'] = TextLayerDialog(parent = self, ovlId = id,
1183 title = _(
'Add text layer'),
1185 self.
dialogs[
'text'].CenterOnParent()
1188 if self.
dialogs[
'text'].ShowModal() == wx.ID_OK:
1189 text = self.
dialogs[
'text'].GetValues()[
'text']
1190 active = self.
dialogs[
'text'].GetValues()[
'active']
1193 if text ==
'' or active ==
False:
1195 self.MapWindow2D.pdc.ClearId(id)
1196 self.MapWindow2D.pdc.RemoveId(id)
1197 del self.MapWindow.textdict[id]
1199 self.MapWindow3D.UpdateOverlays()
1200 self.MapWindow.UpdateMap()
1202 self.MapWindow2D.UpdateMap(render =
False, renderVector =
False)
1208 self.MapWindow.textdict[id] = self.
dialogs[
'text'].GetValues()
1211 self.MapWindow3D.UpdateOverlays()
1212 self.MapWindow3D.UpdateMap()
1214 self.MapWindow2D.pdc.ClearId(id)
1215 self.MapWindow2D.pdc.SetId(id)
1216 self.MapWindow2D.UpdateMap(render =
False, renderVector =
False)
1218 self.MapWindow.mouse[
'use'] =
'pointer'
1221 """!Handler for north arrow menu selection.
1222 Opens Appearance page of nviz notebook.
1225 self._layerManager.nviz.SetPage(
'decoration')
1226 self.MapWindow3D.SetDrawArrow((70, 70))
1229 """!Callback method for decoration overlay command generated by
1230 dialog created in menuform.py
1234 self.Map.ChangeOverlay(ovltype = type, type =
'overlay', name =
'', command = dcmd,
1235 l_active =
True, l_render =
False)
1236 self.params[type] = params
1237 self.propwin[type] = propwin
1240 """!Set display extents to match selected raster (including
1241 NULLs) or vector map.
1243 self.MapWindow.ZoomToMap()
1246 """!Set display extents to match selected raster map (ignore NULLs)
1248 self.MapWindow.ZoomToMap(ignoreNulls =
True)
1251 """!Set display geometry to match extents in
1254 self.MapWindow.ZoomToSaved()
1257 """!Set computational region (WIND file) to match display
1260 self.MapWindow.DisplayToWind()
1263 """!Save display extents to named region file.
1265 self.MapWindow.SaveDisplayRegion()
1270 point = wx.GetMousePosition()
1271 zoommenu = wx.Menu()
1274 zoomwind = wx.MenuItem(zoommenu, wx.ID_ANY, _(
'Zoom to computational region (set with g.region)'))
1275 zoommenu.AppendItem(zoomwind)
1276 self.Bind(wx.EVT_MENU, self.OnZoomToWind, zoomwind)
1278 zoomdefault = wx.MenuItem(zoommenu, wx.ID_ANY, _(
'Zoom to default region'))
1279 zoommenu.AppendItem(zoomdefault)
1280 self.Bind(wx.EVT_MENU, self.OnZoomToDefault, zoomdefault)
1282 zoomsaved = wx.MenuItem(zoommenu, wx.ID_ANY, _(
'Zoom to saved region'))
1283 zoommenu.AppendItem(zoomsaved)
1286 savewind = wx.MenuItem(zoommenu, wx.ID_ANY, _(
'Set computational region from display extent'))
1287 zoommenu.AppendItem(savewind)
1290 savezoom = wx.MenuItem(zoommenu, wx.ID_ANY, _(
'Save display geometry to named region'))
1291 zoommenu.AppendItem(savezoom)
1296 self.PopupMenu(zoommenu)
1299 def SetProperties(self, render = False, mode = 0, showCompExtent = False,
1300 constrainRes =
False, projection =
False, alignExtent =
True):
1301 """!Set properies of map display window"""
1302 self.SetProperty(
'render', render)
1303 self.statusbarManager.SetMode(mode)
1304 self.StatusbarUpdate()
1305 self.SetProperty(
'region', showCompExtent)
1306 self.SetProperty(
'alignExtent', alignExtent)
1307 self.SetProperty(
'resolution', constrainRes)
1308 self.SetProperty(
'projection', projection)
1311 """!Check if Map display is standalone"""
1318 """!Get reference to Layer Manager
1320 @return window reference
1321 @return None (if standalone)
1326 """!Returns toolbar with zooming tools"""
1327 return self.toolbars[
'map']
def SaveToFile(self, event)
Save map to image.
def OnDisplayToWind(self, event)
Set computational region (WIND file) to match display extents.
def OnFlyThrough(self, event)
Fly-through mode.
def SaveDisplayRegion(self, event)
Save display extents to named region file.
def OnFocus(self, event)
Change choicebook page to match display.
def PrintMenu(self, event)
def IsPaneShown(self, name)
Check if pane (toolbar, mapWindow ...) of given name is currently shown.
def OnProfile(self, event)
Launch profile tool.
def OnUpdateProgress(self, event)
Update progress bar info.
def AddToolbar(self, name)
Add defined toolbar to the window.
def _addToolbarVDigit(self)
Add vector digitizer toolbar.
def OnAlignRegion(self, event)
def MeasureDist(self, beginpt, endpt)
Calculate map distance from screen distance and print to output window.
def GetImageHandlers(image)
Get list of supported image handlers.
def SetProperties
Set properies of map display window.
def RemoveNviz(self)
Restore 2D view.
def OnZoomToMap(self, event)
Set display extents to match selected raster (including NULLs) or vector map.
def __init__(self, parent=None, title=_("GRASS GIS - Map display"), toolbars=["map"], tree=None, notebook=None, lmgr=None, page=None, Map=None, auimgr=None, name='MapWindow', kwargs)
Main map display window with toolbars, statusbar and BufferedWindow (map canvas)
def AddNviz(self)
Add 3D view mode window.
def AddLegend
Handler for legend map decoration menu selection.
Various dialogs used in wxGUI.
def _QueryMapDone(self, cmd, returncode)
Restore settings after querying (restore GRASS_REGION)
Print context and utility functions for printing contents of map display window.
Rendering map layers and overlays into map composition image.
def GetAllVectorLayers(vector)
Returns list of all vector layers as strings.
Base classes for Map display window.
def OnCloseWindow(self, event)
Window closed.
def IsStandalone(self)
Check if Map display is standalone.
def RemoveQueryLayer(self)
Removes temporary map layers (queries)
def GetMapToolbar(self)
Returns toolbar with zooming tools.
def OnHistogram(self, event)
Init histogram display canvas and tools.
def GetLayerNameFromCmd
Get map name from GRASS command.
Plotting histogram based on d.histogram.
def GetLayerManager(self)
Get reference to Layer Manager.
def QueryMap(self, east, north, qdist, layers)
Query raster or vector map layers by r/v.what.
def AddTmpVectorMapLayer
Add temporal vector map layer to map composition.
def RemoveToolbar(self, name)
Removes defined toolbar from the window.
def FormatDist(self, dist)
Format length numbers and units in a nice way, as a function of length.
def OnZoomToRaster(self, event)
Set display extents to match selected raster map (ignore NULLs)
def OnMeasure(self, event)
Init measurement routine that calculates map distance along transect drawn on map display...
def OnAddArrow(self, event)
Handler for north arrow menu selection.
Main frame for map display window.
statusbarItemsHiddenInNviz
def ListOfCatsToRange(cats)
Convert list of category number to range(s)
Misc utilities for wxGUI.
def OnPointer(self, event)
Pointer button clicked.
def OnAddText(self, event)
Handler for text decoration menu selection.
Map display canvas for wxGUI vector digitizer.
def QueryVector(self, east, north, qdist, posWindow, layer)
Query vector map layer features.
def AddBarscale
Handler for scale/arrow map decoration menu selection.
Map display canvas - buffered window.
def GetOptData(self, dcmd, type, params, propwin)
Callback method for decoration overlay command generated by dialog created in menuform.py.
def Query(self, x, y, layers)
Query selected layers.
def OnZoomMenu(self, event)
Popup Zoom menu.
def OnRotate(self, event)
Rotate 3D view.
def OnZoomToSaved(self, event)
Set display geometry to match extents in saved region file.
def OnQuery(self, event)
Query tools menu.
Map display overlays - barscale and legend.
def OnZoomRegion(self, event)
def OnRender(self, event)
Re-render map composition (each map layer)