[GRASS-SVN] r54331 - in grass-addons/grass7/gui/wxpython: . wx.rdigit wx.rdigit/rdigit
svn_grass at osgeo.org
svn_grass at osgeo.org
Tue Dec 18 05:26:26 PST 2012
Author: rashadkm
Date: 2012-12-18 05:26:25 -0800 (Tue, 18 Dec 2012)
New Revision: 54331
Added:
grass-addons/grass7/gui/wxpython/wx.rdigit/
grass-addons/grass7/gui/wxpython/wx.rdigit/frame.py
grass-addons/grass7/gui/wxpython/wx.rdigit/rdigit/
grass-addons/grass7/gui/wxpython/wx.rdigit/rdigit/__init__.py
grass-addons/grass7/gui/wxpython/wx.rdigit/rdigit/dialogs_core.py
grass-addons/grass7/gui/wxpython/wx.rdigit/rdigit/main.py
grass-addons/grass7/gui/wxpython/wx.rdigit/rdigit/mapwindow.py
grass-addons/grass7/gui/wxpython/wx.rdigit/rdigit/toolbars.py
grass-addons/grass7/gui/wxpython/wx.rdigit/rdigit/wxdigit.py
grass-addons/grass7/gui/wxpython/wx.rdigit/toolbars.py
Log:
Added wxGUI Raster Digitizer
Added: grass-addons/grass7/gui/wxpython/wx.rdigit/frame.py
===================================================================
--- grass-addons/grass7/gui/wxpython/wx.rdigit/frame.py (rev 0)
+++ grass-addons/grass7/gui/wxpython/wx.rdigit/frame.py 2012-12-18 13:26:25 UTC (rev 54331)
@@ -0,0 +1,392 @@
+"""!
+ at package frame.py
+
+ at brief wxIClass frame with toolbar for digitizing training areas and
+for spectral signature analysis.
+
+Classes:
+ - frame::RDigitMapFrame
+ - frame::MapManager
+
+(C) 2006-2011 by the GRASS Development Team
+This program is free software under the GNU General Public
+License (>=v2). Read the file COPYING that comes with GRASS
+for details.
+
+ at author Mohammed Rashad <rashadkm gmail.com>
+"""
+
+import os
+import sys
+import copy
+import tempfile
+
+if __name__ == "__main__":
+ sys.path.append(os.path.join(os.environ['GISBASE'], "etc", "gui", "wxpython"))
+
+import wx
+
+from ctypes import *
+import grass.script as grass
+from core import globalvar
+from core.gcmd import GError, GMessage
+from mapdisp import statusbar as sb
+from mapdisp.mapwindow import BufferedWindow
+from gui_core.mapdisp import SingleMapFrame
+from core.render import Map, MapLayer
+from core.gcmd import RunCommand, GMessage
+
+from toolbars import RDigitMapToolbar, RDigitMapManagerToolbar
+
+from rdigit.mapwindow import RDigitWindow
+from rdigit.toolbars import RDigitToolbar
+from rdigit.main import haveRDigit, RDigit
+
+class RDigitMapFrame(SingleMapFrame):
+ """! RDigitMapFrame main frame
+ This is the raster digitizer main window. It holds a minimal layer manager from wxIClass
+ """
+ def __init__(self, parent = None, giface = None, title = _("Raster Digitizer"),
+ toolbars = ["digitMap","rdigit"],
+ size = (875, 600), name = 'RDigitWindow', **kwargs):
+ """!
+ @param parent (no parent is expected)
+ @param title window title
+ @param toolbars dictionary of active toolbars (defalult value represents all toolbars)
+ @param size default size
+ """
+ SingleMapFrame.__init__(self, parent = parent, title = title, name = name, Map = Map(), **kwargs)
+ self._giface = giface
+
+ self.MapWindow = BufferedWindow(parent = self,giface = self._giface, Map = self.Map, frame = self)
+ self.outMapName = None
+
+ self.mapManager = MapManager(self, mapWindow = self.GetWindow(),
+ Map = self.GetMap())
+ self.SetSize(size)
+
+ self.MapWindowRDigit = RDigitWindow(parent = self, giface = self._giface,
+ id = wx.ID_ANY, frame = self,
+ Map = self.Map)
+
+ # Add toolbars
+
+ toolbarsCopy = toolbars[:]
+ if sys.platform == 'win32':
+ self.AddToolbar(toolbarsCopy.pop(1))
+ toolbarsCopy.reverse()
+ else:
+ self.AddToolbar(toolbarsCopy.pop(0))
+ for toolb in toolbarsCopy:
+ self.AddToolbar(toolb)
+
+ self.GetMapToolbar().Bind(wx.EVT_CHOICE, self.OnUpdateActive)
+
+ #
+ # Add statusbar
+ #
+
+ # items for choice
+ self.statusbarItems = [sb.SbCoordinates,
+ sb.SbRegionExtent,
+ sb.SbCompRegionExtent,
+ sb.SbShowRegion,
+ sb.SbAlignExtent,
+ sb.SbResolution,
+ sb.SbDisplayGeometry,
+ sb.SbMapScale,
+ sb.SbGoTo,
+ sb.SbProjection]
+
+ # create statusbar and its manager
+ statusbar = self.CreateStatusBar(number = 4, style = 0)
+ statusbar.SetStatusWidths([-5, -2, -1, -1])
+ self.statusbarManager = sb.SbManager(mapframe = self, statusbar = statusbar)
+
+ # fill statusbar manager
+ self.statusbarManager.AddStatusbarItemsByClass(self.statusbarItems, mapframe = self, statusbar = statusbar)
+ self.statusbarManager.AddStatusbarItem(sb.SbMask(self, statusbar = statusbar, position = 2))
+ self.statusbarManager.AddStatusbarItem(sb.SbRender(self, statusbar = statusbar, position = 3))
+
+ self.statusbarManager.Update()
+
+ self.changes = False
+ self.exportVector = None
+ self.MapWindowCopy = None
+
+
+ self._addPanes()
+ self._mgr.Update()
+
+ self.mapManager.SetToolbar(self.toolbars['digitMap'])
+
+ # default action
+ self.OnPan(event = None)
+
+ self.Bind(wx.EVT_CLOSE, self.OnCloseWindow)
+
+ def OnCloseWindow(self, event):
+ self.Destroy()
+
+ def GetWindow(self):
+ return self.MapWindow
+
+ def GetMap(self):
+ return self.Map
+
+
+ def OnHelp(self, event):
+ """!Show help page"""
+ helpInProgress = True
+
+ def GetToolbar(self,name):
+ if name in self.toolbars:
+ return self.toolbars[name]
+
+ return None
+
+ def AddToolbar(self, name):
+ """!Add toolbars to the frame
+ """
+ if name == "digitMap":
+ self.toolbars[name] = RDigitMapToolbar(self)
+
+ self._mgr.AddPane(self.toolbars[name],
+ wx.aui.AuiPaneInfo().
+ Name(name).Caption(_("Map Toolbar")).
+ ToolbarPane().Top().
+ LeftDockable(False).RightDockable(False).
+ BottomDockable(False).TopDockable(True).
+ CloseButton(False).Layer(2).Row(1).
+ BestSize((self.toolbars[name].GetBestSize())))
+
+ elif name == "rdigit":
+ self.toolbars[name] = RDigitToolbar(parent = self, MapWindow = self.MapWindowRDigit,
+ digitClass = RDigit, layerTree = self.mapManager)
+
+ self._mgr.AddPane(self.toolbars[name],
+ wx.aui.AuiPaneInfo().
+ Name("rdigittoolbar").Caption(_("Raster Digitizer Toolbar")).
+ ToolbarPane().Top().Row(1).
+ LeftDockable(False).RightDockable(False).
+ BottomDockable(False).TopDockable(True).
+ CloseButton(False).Layer(0).
+ BestSize((self.toolbars['rdigit'].GetBestSize())))
+ self.MapWindowRDigit.SetToolbar(self.toolbars[name])
+ self._mgr.GetPane('rdigittoolbar').Hide()
+
+
+
+ def _addPanes(self):
+ """!Add mapwindows and toolbars to aui manager"""
+
+ self._addPaneMapWindow()
+ self._addPaneToolbar(name = 'digitMap')
+
+
+
+ def _addPaneToolbar(self, name):
+
+ self.toolbars[name] = RDigitMapManagerToolbar(self, self.mapManager)
+ self._mgr.AddPane(self.toolbars[name],
+ wx.aui.AuiPaneInfo().ToolbarPane().Movable().
+ Name(name).
+ CloseButton(False).Center().Layer(0).
+ BestSize((self.toolbars[name].GetBestSize())))
+
+ def _addPaneMapWindow(self):
+
+ self._mgr.AddPane(self.MapWindow, wx.aui.AuiPaneInfo().CentrePane().
+ Dockable(False).BestSize((-1,-1)).Name('window').
+ CloseButton(False).DestroyOnClose(True).
+ Layer(0))
+
+ self._mgr.AddPane(self.MapWindowRDigit, wx.aui.AuiPaneInfo().CentrePane().
+ Dockable(True).BestSize((-1,-1)).Name('rdigit').
+ CloseButton(False).DestroyOnClose(True).
+ Layer(0))
+
+
+
+ self._mgr.GetPane('window').Show()
+ self._mgr.GetPane('rdigit').Hide()
+
+
+
+ def IsStandalone(self):
+ """!Check if Map display is standalone"""
+ return True
+
+ def OnUpdateActive(self, event):
+ """!
+ @todo move to DoubleMapFrame?
+ """
+ self.StatusbarUpdate()
+
+
+ def GetMapToolbar(self):
+ """!Returns toolbar with zooming tools"""
+ return self.toolbars['digitMap']
+
+ def AddRasterMap(self, name, firstMap = True, secondMap = True):
+ """!Add raster map to Map"""
+ cmdlist = ['d.rast', 'map=%s' % name]
+ if firstMap:
+ self.GetFirstMap().AddLayer(type='raster', command=cmdlist, l_active=True,
+ name=name, l_hidden=False, l_opacity=1.0, l_render=False)
+ self.GetWindow().UpdateMap(render = True, renderVector = False)
+
+ def OnZoomMenu(self, event):
+ """!Popup Zoom menu """
+ zoommenu = wx.Menu()
+ zoommenu.Destroy()
+
+ def OnZoomIn(self, event):
+ super(RDigitMapFrame, self).OnZoomIn(event)
+
+ def OnZoomOut(self, event):
+ super(RDigitMapFrame, self).OnZoomOut(event)
+
+ def OnPan(self, event):
+ super(RDigitMapFrame, self).OnPan(event)
+
+ def GetOutputMap(self):
+ return self.outMapName
+
+ def RemoveToolbar(self, name):
+
+ self.outMapName = self.toolbars['rdigit'].GetMapName()
+ self.mapManager.AddLayer(name = self.outMapName)
+ self._mgr.GetPane('window').Show()
+ self._mgr.GetPane('rdigit').Hide()
+ self._mgr.GetPane('rdigittoolbar').Hide()
+ self.MapWindow = self.MapWindowCopy
+ self._mgr.Update()
+
+ def OnDrawArea(self, event):
+
+ if not self._mgr.GetPane('rdigit').IsShown():
+ self._mgr.GetPane('window').Hide()
+ self._mgr.GetPane('rdigit').Show()
+ self._mgr.GetPane('rdigittoolbar').Show()
+ self._mgr.Update()
+ self.MapWindowCopy = self.MapWindow
+ self.MapWindow = self.MapWindowRDigit
+ self.MapWindow.mouse['box'] = "point"
+ self.MapWindow.zoomtype = 0
+ self.MapWindow.pen = wx.Pen(colour = 'red', width = 2, style = wx.SOLID)
+ self.MapWindow.polypen = wx.Pen(colour = 'green', width = 2, style = wx.SOLID)
+ else:
+ self.MapWindow = self.MapWindowCopy
+ self._mgr.GetPane('window').Show()
+ self._mgr.GetPane('rdigit').Hide()
+
+
+
+
+class MapManager:
+ """! Class for managing map renderer.
+
+ It is connected with iClassMapManagerToolbar.
+ """
+ def __init__(self, frame, mapWindow, Map):
+ """!
+
+ It is expected that \a mapWindow is conected with \a Map.
+
+ @param frame application main window
+ @param mapWindow map window instance
+ @param Map map renderer instance
+ """
+ self.map = Map
+ self.frame = frame
+ self.mapWindow = mapWindow
+ self.toolbar = None
+
+ self.layerName = {}
+
+
+ def SetToolbar(self, toolbar):
+ self.toolbar = toolbar
+
+ def AddLayer(self, name, alias = None, resultsLayer = False):
+ """!Adds layer to Map and update toolbar
+
+ @param name layer (raster) name
+ @param resultsLayer True if layer is temp. raster showing the results of computation
+ """
+ if (resultsLayer and
+ name in [l.GetName() for l in self.map.GetListOfLayers(l_name = name)]):
+ self.frame.Render(self.mapWindow)
+ return
+
+ cmdlist = ['d.rast', 'map=%s' % name]
+ self.map.AddLayer(type = 'raster', command = cmdlist, l_active = True,
+ name = name, l_hidden = False, l_opacity = 1.0, l_render = True)
+ #self.frame.Render(self.GetWindow().Render())
+ self.frame.GetWindow().UpdateMap(render = True, renderVector = False)
+
+
+ if alias is not None:
+ alias = self._addSuffix(alias)
+ self.layerName[alias] = name
+ name = alias
+ else:
+ self.layerName[name] = name
+
+ self.toolbar.choice.Insert(name, 0)
+ self.toolbar.choice.SetSelection(0)
+
+
+
+ def RemoveLayer(self, name, idx):
+ """!Removes layer from Map and update toolbar"""
+ name = self.layerName[name]
+ self.map.RemoveLayer(name = name)
+ del self.layerName[name]
+ self.toolbar.choice.Delete(idx)
+ if not self.toolbar.choice.IsEmpty():
+ self.toolbar.choice.SetSelection(0)
+
+ self.frame.GetWindow().UpdateMap(render = True, renderVector = False)
+ #self.frame.Render(self.mapWindow)
+
+ def SelectLayer(self, name):
+ """!Moves selected layer to top"""
+ layers = self.map.GetListOfLayers(l_type = 'raster')
+ idx = None
+ for i, layer in enumerate(layers):
+ if self.layerName[name] == layer.GetName():
+ idx = i
+ break
+
+ if idx is not None: # should not happen
+ layers.append(layers.pop(idx))
+
+ choice = self.toolbar.choice
+ idx = choice.FindString(name)
+ choice.Delete(idx)
+ choice.Insert(name, 0)
+ choice.SetSelection(0)
+
+ #layers.reverse()
+ self.map.ReorderLayers(layers)
+ self.frame.GetWindow().UpdateMap(render = True, renderVector = False)
+
+
+def test():
+ import gettext
+ import core.render as render
+
+ gettext.install('grasswxpy', os.path.join(os.getenv("GISBASE"), 'locale'), unicode = True)
+
+ app = wx.PySimpleApp()
+ wx.InitAllImageHandlers()
+
+ frame = RDigitMapFrame()
+ frame.Show()
+ app.MainLoop()
+
+if __name__ == "__main__":
+ test()
+
Added: grass-addons/grass7/gui/wxpython/wx.rdigit/rdigit/__init__.py
===================================================================
--- grass-addons/grass7/gui/wxpython/wx.rdigit/rdigit/__init__.py (rev 0)
+++ grass-addons/grass7/gui/wxpython/wx.rdigit/rdigit/__init__.py 2012-12-18 13:26:25 UTC (rev 54331)
@@ -0,0 +1,6 @@
+all = [
+ 'mapwindow',
+ 'main',
+ 'toolbars',
+ 'wxdigit',
+ ]
Added: grass-addons/grass7/gui/wxpython/wx.rdigit/rdigit/dialogs_core.py
===================================================================
--- grass-addons/grass7/gui/wxpython/wx.rdigit/rdigit/dialogs_core.py (rev 0)
+++ grass-addons/grass7/gui/wxpython/wx.rdigit/rdigit/dialogs_core.py 2012-12-18 13:26:25 UTC (rev 54331)
@@ -0,0 +1,233 @@
+
+import os
+import sys
+import re
+from bisect import bisect
+
+import wx
+#import wx.lib.filebrowsebutton as filebrowse
+#import wx.lib.mixins.listctrl as listmix
+#from wx.lib.newevent import NewEvent
+
+from gui_core.dialogs import ElementDialog
+
+from grass.script import core as grass
+from grass.lib import gis as gis
+from grass.lib import raster as grast
+
+from core import globalvar
+from core.gcmd import GError, RunCommand, GMessage
+from gui_core.gselect import ElementSelect, LocationSelect, MapsetSelect, Select, OgrTypeSelect, GdalSelect, MapsetSelect
+from gui_core.forms import GUI
+from gui_core.widgets import SingleSymbolPanel, EVT_SYMBOL_SELECTION_CHANGED, GListCtrl
+from core.utils import GetLayerNameFromCmd, GetValidLayerName
+from core.settings import UserSettings, GetDisplayVectSettings
+from core.debug import Debug
+import ctypes
+
+
+class NewRasterDialog(ElementDialog):
+ def __init__(self, parent, id = wx.ID_ANY, title = _('Create new vector map'),
+ disableAdd = False, showType = False,
+ style = wx.DEFAULT_DIALOG_STYLE | wx.RESIZE_BORDER, *kwargs):
+ """!Dialog for creating new vector map
+
+ @param parent parent window
+ @param id window id
+ @param title window title
+ @param disableAdd disable 'add layer' checkbox
+ @param showType True to show feature type selector (used for creating new empty OGR layers)
+ @param style window style
+ @param kwargs other argumentes for ElementDialog
+
+ @return dialog instance
+ """
+ ElementDialog.__init__(self, parent, title, label = _("Name for new raster map:"))
+
+ self.element = Select(parent = self.panel, id = wx.ID_ANY, size = globalvar.DIALOG_GSELECT_SIZE,
+ type = 'raster', mapsets = [grass.gisenv()['MAPSET'],])
+
+ # determine output format
+ if showType:
+ self.ftype = GdalSelect(parent = self, panel = self.panel)
+ else:
+ self.ftype = None
+
+
+ self.addbox = wx.CheckBox(parent = self.panel,
+ label = _('Add created map into layer tree'), style = wx.NO_BORDER)
+ if disableAdd:
+ self.addbox.SetValue(True)
+ self.addbox.Enable(False)
+ else:
+ self.addbox.SetValue(UserSettings.Get(group = 'cmd', key = 'addNewLayer', subkey = 'enabled'))
+
+
+
+ self.PostInit()
+
+ self._layout()
+ self.SetMinSize(self.GetSize())
+
+ def OnMapName(self, event):
+ """!Name for vector map layer given"""
+ self.OnElement(event)
+
+
+
+ def _layout(self):
+ """!Do layout"""
+ self.dataSizer.Add(item = self.element, proportion = 0,
+ flag = wx.EXPAND | wx.ALL, border = 1)
+ if self.ftype:
+ self.dataSizer.AddSpacer(1)
+ self.dataSizer.Add(item = self.ftype, proportion = 0,
+ flag = wx.EXPAND | wx.ALL, border = 1)
+
+
+
+ self.dataSizer.AddSpacer(5)
+
+ self.dataSizer.Add(item = self.addbox, proportion = 0,
+ flag = wx.EXPAND | wx.ALL, border = 1)
+
+ self.panel.SetSizer(self.sizer)
+ self.sizer.Fit(self)
+
+ def GetName(self, full = False):
+ """!Get name of vector map to be created
+
+ @param full True to get fully qualified name
+ """
+ name = self.GetElement()
+ if full:
+ if '@' in name:
+ return name
+ else:
+ return name + '@' + grass.gisenv()['MAPSET']
+
+ return name.split('@', 1)[0]
+
+ def GetKey(self):
+ """!Get key column name"""
+
+
+ def IsChecked(self, key):
+ """!Get dialog properties
+
+ @param key window key ('add', 'table')
+
+ @return True/False
+ @return None on error
+ """
+ if key == 'add':
+ return self.addbox.IsChecked()
+
+
+ return None
+
+ def GetFeatureType(self):
+ """!Get feature type for OGR
+
+ @return feature type as string
+ @return None for native format
+ """
+ if self.ftype:
+ return self.ftype.GetType()
+
+ return None
+
+def CreateNewRaster(parent, title = _('Create new vector map'),
+ exceptMap = None,
+ disableAdd = False):
+ """!Create new vector map layer
+
+ @param cmd (prog, **kwargs)
+ @param title window title
+ @param exceptMap list of maps to be excepted
+ @param disableAdd disable 'add layer' checkbox
+
+ @return dialog instance
+ @return None on error
+ """
+ vExternalOut = grass.parse_command('r.external.out', flags = 'p', delimiter = ':')
+
+
+ UsingGDAL = vExternalOut.has_key('Not using GDAL') == False
+
+
+ if not UsingGDAL:
+ showType = False
+ else:
+ showType = True
+
+ dlg = NewRasterDialog(parent, title = title,
+ disableAdd = disableAdd, showType = showType)
+
+ if dlg.ShowModal() != wx.ID_OK:
+ dlg.Destroy()
+ return None
+
+ outmap = dlg.GetName()
+ #key = dlg.GetKey()
+ if outmap == exceptMap:
+ GError(parent = parent,
+ message = _("Unable to create raster map <%s>.") % outmap)
+ dlg.Destroy()
+ return None
+
+
+ if outmap == '': # should not happen
+ dlg.Destroy()
+ return None
+
+
+
+ if not UsingGDAL:
+ listOfRasters = grass.list_grouped('rast')[grass.gisenv()['MAPSET']]
+ else:
+ listOfRasters = RunCommand('r.external',
+ quiet = True,
+ parent = parent,
+ read = True,
+ flags = 'l',
+ out = outmap,
+ source = vExternalOut['directory']).splitlines()
+
+ if not UserSettings.Get(group = 'cmd', key = 'overwrite', subkey = 'enabled') and \
+ outmap in listOfRasters:
+ dlgOw = wx.MessageDialog(parent, message = _("Raster map <%s> already exists "
+ "in the current mapset. "
+ "Do you want to overwrite it?") % outmap,
+ caption = _("Overwrite?"),
+ style = wx.YES_NO | wx.YES_DEFAULT | wx.ICON_QUESTION)
+ if dlgOw.ShowModal() == wx.ID_YES:
+ overwrite = True
+ else:
+ dlgOw.Destroy()
+ dlg.Destroy()
+ return None
+
+ if UserSettings.Get(group = 'cmd', key = 'overwrite', subkey = 'enabled'):
+ overwrite = True
+
+
+
+
+ if UsingGDAL:
+ # create link for OGR layers
+ RunCommand('r.external',
+ overwrite = overwrite,
+ parent = parent,
+ directory = vExternalOut['directory'],
+ layer = outmap)
+
+
+ # return fully qualified map name
+ if '@' not in outmap:
+ outmap += '@' + grass.gisenv()['MAPSET']
+
+ #if log:
+ # log.WriteLog(_("New raster map <%s> created") % outmap)
+ return dlg
+
Added: grass-addons/grass7/gui/wxpython/wx.rdigit/rdigit/main.py
===================================================================
--- grass-addons/grass7/gui/wxpython/wx.rdigit/rdigit/main.py (rev 0)
+++ grass-addons/grass7/gui/wxpython/wx.rdigit/rdigit/main.py 2012-12-18 13:26:25 UTC (rev 54331)
@@ -0,0 +1,36 @@
+"""!
+ at package vdigit.main
+
+ at brief wxGUI vector digitizer
+
+Classes:
+ - main::VDigit
+
+(C) 2007-2011 by the GRASS Development Team
+
+This program is free software under the GNU General Public License
+(>=v2). Read the file COPYING that comes with GRASS for details.
+
+ at author Martin Landa <landa.martin gmail.com>
+"""
+
+try:
+ from rdigit.wxdigit import IRDigit, GV_LINES, CFUNCTYPE
+ haveRDigit = True
+ errorMsg = ''
+except (ImportError, NameError), err:
+ haveRDigit = False
+ errorMsg = err
+ print errorMsg
+ GV_LINES = -1
+ class IRDigit:
+ def __init__(self):
+ pass
+
+class RDigit(IRDigit):
+ def __init__(self, mapwindow):
+ """!Base class of vector digitizer
+
+ @param mapwindow reference to mapwindow (mapdisp_window.BufferedWindow) instance
+ """
+ IRDigit.__init__(self, mapwindow)
Added: grass-addons/grass7/gui/wxpython/wx.rdigit/rdigit/mapwindow.py
===================================================================
--- grass-addons/grass7/gui/wxpython/wx.rdigit/rdigit/mapwindow.py (rev 0)
+++ grass-addons/grass7/gui/wxpython/wx.rdigit/rdigit/mapwindow.py 2012-12-18 13:26:25 UTC (rev 54331)
@@ -0,0 +1,448 @@
+"""!
+ at package vdigit.mapwindow
+
+ at brief Map display canvas for wxGUI vector digitizer
+
+Classes:
+ - mapwindow::RDigitWindow
+
+(C) 2011 by the GRASS Development Team
+
+This program is free software under the GNU General Public License
+(>=v2). Read the file COPYING that comes with GRASS for details.
+
+ at author Mohammed Rashad <rashadkm gmail.com>
+"""
+
+import wx
+
+from core.gcmd import RunCommand, GMessage, GError
+from core.debug import Debug
+from mapdisp.mapwindow import BufferedWindow
+from core.settings import UserSettings
+from core.utils import ListOfCatsToRange
+from core.globalvar import QUERYLAYER
+
+
+class Circle:
+ def __init__(self, pt, r):
+ self.point = pt
+ self.radius = r
+
+class RDigitWindow(BufferedWindow):
+ """!A Buffered window extended for raster digitizer.
+ """
+ def __init__(self, parent, giface, Map, frame,
+ id = wx.ID_ANY, tree = None, lmgr = None,
+ style = wx.NO_FULL_REPAINT_ON_RESIZE, **kwargs):
+ BufferedWindow.__init__(self, parent = parent, giface = giface, id = id, Map = Map,
+ frame = frame, tree = tree, style = style, **kwargs)
+ self.lmgr = lmgr
+ self.pdcVector = wx.PseudoDC()
+ self.toolbar = self.parent.GetToolbar('rdigit')
+ self.digit = None # wxvdigit.IVDigit
+ self.existingCoords = list()
+ self.polygons = list()
+ self.circles = list()
+ self.idx = wx.ID_NEW + 1
+ self.selectid = None
+ self.selectid_circle = None
+ self.idxCats = dict()
+ self.Bind(wx.EVT_KEY_DOWN, self.OnKeyDown)
+
+
+ def SetToolbar(self, toolbar):
+ """!Set up related toolbar
+ """
+ self.toolbar = toolbar
+
+ def _onMotion(self, coord, precision):
+ """!Track mouse motion and update statusbar (see self.Motion)
+
+ @parem coord easting, northing
+ @param precision formatting precision
+ """
+ e, n = coord
+
+ if self.toolbar.GetAction() != 'addLine' or \
+ self.toolbar.GetAction('type') not in ('line', 'boundary') or \
+ len(self.polycoords) == 0:
+ return False
+
+ # for linear feature show segment and total length
+ distance_seg = self.Distance(self.polycoords[-1],
+ (e, n), screen = False)[0]
+ distance_tot = distance_seg
+ for idx in range(1, len(self.polycoords)):
+ distance_tot += self.Distance(self.polycoords[idx-1],
+ self.polycoords[idx],
+ screen = False)[0]
+ self.parent.SetStatusText("%.*f, %.*f (seg: %.*f; tot: %.*f)" % \
+ (precision, e, precision, n,
+ precision, distance_seg,
+ precision, distance_tot), 0)
+
+ return True
+
+ def OnKeyDown(self, event):
+ """!Key pressed"""
+ shift = event.ShiftDown()
+ kc = event.GetKeyCode()
+
+ event = None
+ if not shift:
+ if kc == ord('P'):
+ event = wx.CommandEvent(winid = self.toolbar.addPoint)
+ tool = self.toolbar.OnAddPoint
+ elif kc == ord('L'):
+ event = wx.CommandEvent(winid = self.toolbar.addLine)
+ tool = self.toolbar.OnAddLine
+ if event:
+ self.toolbar.OnTool(event)
+ self.selectid = None
+ tool(event)
+
+
+ def DrawLines2(self, plineid, pdc = None, polycoords = None):
+ """!Draw polyline in PseudoDC
+
+ Set self.pline to wx.NEW_ID + 1
+
+ polycoords - list of polyline vertices, geographical coordinates
+ (if not given, self.polycoords is used)
+ """
+ if not pdc:
+ pdc = self.pdcTmp
+
+ if not polycoords:
+ polycoords = self.polycoords
+
+ if len(polycoords) > 0:
+ coords = []
+ for p in polycoords:
+ coords.append(self.Cell2Pixel(p))
+
+ self.Draw(pdc, drawid = plineid, pdctype = 'polyline', coords = coords)
+
+ Debug.msg (2, "BufferedWindow.DrawLines2(): coords=%s, id=%s" % \
+ (coords, plineid))
+
+ return plineid
+
+ return -1
+
+ def _updateMap(self):
+ if not self.toolbar or \
+ not self.toolbar.GetMapName():
+ return
+
+ self.pdcVector.RemoveAll()
+
+ for poly in self.polygons:
+ idx = poly.keys()[0]
+ #print idx
+ self.pdcVector.SetId(idx)
+ #if self.selectid:
+ #if poly.has_key(self.selectid):
+ #print poly[self.selectid]
+ if idx != self.selectid:
+ self.pen = self.polypen = wx.Pen(colour = wx.GREEN, width = 2)
+ else:
+ self.pen = self.polypen = wx.Pen(colour = wx.RED, width = 2)
+
+ self.DrawLines2(idx, pdc = self.pdcVector, polycoords = poly[idx])
+
+ #print self.circles
+ for circle in self.circles:
+ idx = circle.keys()[0]
+ C = circle[idx]
+
+ if idx != self.selectid_circle:
+ self.pen = self.polypen = wx.Pen(colour = wx.GREEN, width = 2)
+ else:
+ self.pen = self.polypen = wx.Pen(colour = wx.RED, width = 2)
+
+ self.pdcVector.BeginDrawing()
+ self.pdcVector.SetBrush(wx.Brush(wx.CYAN, wx.TRANSPARENT))
+ self.pdcVector.SetPen(self.pen)
+ self.pdcVector.SetId(idx)
+ self.pdcVector.DrawCircle(C.point[0],C.point[1],C.radius)
+ self.pdcVector.EndDrawing()
+ self.Refresh()
+
+ item = None
+ if self.tree:
+ try:
+ item = self.tree.FindItemByData('maplayer', self.toolbar.GetMapName())
+ except TypeError:
+ pass
+
+ # translate tmp objects (pointer position)
+ if self.toolbar.GetAction() == 'moveLine' and \
+ hasattr(self, "moveInfo"):
+ if 'beginDiff' in self.moveInfo:
+ # move line
+ for id in self.moveInfo['id']:
+ self.pdcTmp.TranslateId(id,
+ self.moveInfo['beginDiff'][0],
+ self.moveInfo['beginDiff'][1])
+ del self.moveInfo['beginDiff']
+
+ def OnLeftDownAddLine(self, event):
+ """!Left mouse button pressed - add new feature
+ """
+ try:
+ mapLayer = self.toolbar.GetMapName()
+ except:
+ return
+
+ if self.toolbar.GetAction('type') in ['point', 'centroid']:
+ # add new point / centroiud
+ east, north = self.Pixel2Cell(self.mouse['begin'])
+ nfeat, fids = self.digit.AddFeature(self.toolbar.GetAction('type'), [(east, north)])
+ #if nfeat < 1:
+ #return
+
+ self.UpdateMap(render = False) # redraw map
+
+ elif self.toolbar.GetAction('type') in ["line", "boundary", "area"]:
+ # add new point to the line
+ self.polycoords.append(self.Pixel2Cell(event.GetPositionTuple()[:]))
+ self.DrawLines(pdc = self.pdcTmp)
+
+
+ def _onLeftDown(self, event):
+ """!Left mouse button donw - vector digitizer various actions
+ """
+ try:
+ mapLayer = self.toolbar.GetMapName()
+ except:
+ GMessage(parent = self,
+ message = _("No vector map selected for editing.1"))
+ event.Skip()
+ return
+
+ action = self.toolbar.GetAction()
+ #print action
+ if not action:
+ GMessage(parent = self,
+ message = _("Nothing to do. "
+ "Choose appropriate tool from digitizer toolbar."))
+ event.Skip()
+ return
+
+ if action not in ("moveVertex",
+ "addVertex",
+ "removeVertex",
+ "editLine"):
+ # set pen
+ self.pen = wx.Pen(colour = UserSettings.Get(group = 'vdigit', key = 'symbol',
+ subkey = ['newSegment', 'color']),
+ width = 2, style = wx.SHORT_DASH)
+ self.polypen = wx.Pen(colour = UserSettings.Get(group = 'vdigit', key = 'symbol',
+ subkey = ['newLine', 'color']),
+ width = 2, style = wx.SOLID)
+
+ if action in ("addVertex",
+ "removeVertex",
+ "splitLines"):
+ # unselect
+ self.digit.GetDisplay().SetSelected([])
+
+ if action == "addLine":
+ self.OnLeftDownAddLine(event)
+
+ elif action == "deleteCircle":
+ #print "delete:Circle"
+ x,y = event.GetPositionTuple()
+ ids = self.pdcVector.FindObjects(x,y)
+ #print ids
+ if len(ids) > 0:
+ self.selectid_circle = ids[0]
+ else:
+ self.selectid_circle = None
+
+ ids = []
+ self.polycoords = []
+
+ elif action == "addCircle":
+ if len(self.polycoords) < 1: # ignore 'one-point' lines
+ self.polycoords.append(event.GetPositionTuple()[:])
+
+
+ def OnLeftUpVarious(self, event):
+ """!Left mouse button released - vector digitizer various
+ actions
+ """
+ pos1 = self.Pixel2Cell(self.mouse['begin'])
+ pos2 = self.Pixel2Cell(self.mouse['end'])
+
+ nselected = 0
+ action = self.toolbar.GetAction()
+
+ if action in ("deleteLine", "deleteCircle",
+ "deleteArea"):
+
+ if action in ["deleteArea", "deleteLine"]:
+
+ x,y = event.GetPositionTuple()
+ ids = self.pdcVector.FindObjectsByBBox(x,y)
+ if len(ids) > 0:
+ self.selectid = ids[0]
+ else:
+ self.selectid = None
+
+ ids = []
+ self.polycoords = []
+ self.UpdateMap(render = False)
+
+ def _onLeftUp(self, event):
+ """!Left mouse button released"""
+
+ # eliminate initial mouse moving efect
+ self.mouse['begin'] = self.mouse['end']
+
+ action = self.toolbar.GetAction()
+
+ if action in ("deleteLine",
+ "deleteArea",
+ "deleteCircle"):
+ self.OnLeftUpVarious(event)
+
+ elif action == "addCircle":
+ if len(self.polycoords) > 0: # ignore 'one-point' lines
+
+ beginpt =self.polycoords[0]
+ endpt = event.GetPositionTuple()[:]
+ dist, (north, east) = self.Distance(beginpt, endpt,False)
+ #print dist
+ circle = dict()
+ c = Circle(beginpt, dist)
+ circle[self.idx] = c
+ self.idx = self.idx + 1
+ self.circles.append(circle)
+
+ self._updateMap()
+ self.polycoords = []
+
+ def _onRightDown(self, event):
+ # digitization tool (confirm action)
+ action = self.toolbar.GetAction()
+
+
+ def _onRightUp(self, event):
+ """!Right mouse button released (confirm action)
+ """
+ action = self.toolbar.GetAction()
+
+ if action == "addLine" and \
+ self.toolbar.GetAction('type') in ["line", "boundary", "area"]:
+ # -> add new line / boundary
+ try:
+ mapName = self.toolbar.GetMapName()
+ except:
+ mapName = None
+ GError(parent = self,
+ message = _("No vector map selected for editing.2"))
+
+ if mapName:
+ if len(self.polycoords) < 2: # ignore 'one-point' lines
+ return
+
+ self.idxCats[self.idx] = self.digit.AddFeature(self.toolbar.GetAction('type'), self.polycoords)
+ if self.toolbar.GetAction('type') == 'boundary':
+ x0,y0 = self.polycoords[0]
+ for coord in self.polycoords:
+ x,y = coord #self.Cell2Pixel(coord)
+ c = wx.Point(x,y)
+ self.existingCoords.append(c)
+
+ self.existingCoords.append(wx.Point(x0,y0))
+
+ coordIdx = dict()
+ coordIdx[self.idx] = self.existingCoords
+ self.polygons.append(coordIdx)
+ self.idx = self.idx+1
+ self.existingCoords = []
+
+
+ if self.toolbar.GetAction('type') == 'line':
+ for coord in self.polycoords:
+ x,y = coord #self.Cell2Pixel(coord)
+ c = wx.Point(x,y)
+ self.existingCoords.append(c)
+
+ coordIdx = dict()
+ coordIdx[self.idx] = self.existingCoords
+ self.polygons.append(coordIdx)
+ self.idx = self.idx+1
+ self.existingCoords = []
+
+
+ #Update Map
+ self.polycoords = []
+ self.UpdateMap(render = False)
+ self.redrawAll = True
+ self.Refresh()
+
+ elif action in ["deleteArea", "deleteLine"]:
+ # -> delete selected vector features
+ x,y = event.GetPositionTuple()
+ ids = self.pdcVector.FindObjectsByBBox(x,y)
+ idx = ids[0]
+ cat = None
+ if self.idxCats.has_key(idx):
+ cat = self.idxCats[idx]
+ self.digit.DeleteArea(cat)
+
+ polygonsCopy = self.polygons
+ self.polygons = []
+ for poly in polygonsCopy:
+ id = poly.keys()[0]
+ if idx != id:
+ self.polygons.append(poly)
+
+
+ elif action == "deleteCircle":
+ x,y = event.GetPositionTuple()
+ ids = self.pdcVector.FindObjectsByBBox(x,y)
+ idx = ids[0]
+ cat = None
+ #print self.idxCats
+ #print self.idxCats.has_key(idx) , idx
+ if self.idxCats.has_key(idx):
+ cat = self.idxCats[idx]
+ #print cat
+ #self.digit.DeleteCircle(cat)
+
+ circlesCopy = self.circles
+ self.circles = []
+ for circle in circlesCopy:
+ id = circle.keys()[0]
+ if idx != id:
+ self.circles.append(circle)
+
+
+ def _onMouseMoving(self, event):
+ self.mouse['end'] = event.GetPositionTuple()[:]
+
+ Debug.msg (5, "BufferedWindow.OnMouseMoving(): coords=%f,%f" % \
+ (self.mouse['end'][0], self.mouse['end'][1]))
+
+ action = self.toolbar.GetAction()
+ if action == "addLine" and \
+ self.toolbar.GetAction('type') in ["line", "boundary", "area"]:
+ if len(self.polycoords) > 0:
+ self.MouseDraw(pdc = self.pdcTmp, begin = self.Cell2Pixel(self.polycoords[-1]))
+
+
+ self.Refresh() # TODO: use RefreshRect()
+ self.mouse['begin'] = self.mouse['end']
+
+ def _zoom(self, event):
+ tmp1 = self.mouse['end']
+ tmp2 = self.Cell2Pixel(self.moveInfo['begin'])
+ dx = tmp1[0] - tmp2[0]
+ dy = tmp1[1] - tmp2[1]
+
+
Added: grass-addons/grass7/gui/wxpython/wx.rdigit/rdigit/toolbars.py
===================================================================
--- grass-addons/grass7/gui/wxpython/wx.rdigit/rdigit/toolbars.py (rev 0)
+++ grass-addons/grass7/gui/wxpython/wx.rdigit/rdigit/toolbars.py 2012-12-18 13:26:25 UTC (rev 54331)
@@ -0,0 +1,561 @@
+"""!
+ at package rdigit.toolbars
+
+ at brief wxGUI raster digitizer toolbars
+
+List of classes:
+ - toolbars::RDigitToolbar
+
+(C) 2007-2012 by the GRASS Development Team
+
+This program is free software under the GNU General Public License
+(>=v2). Read the file COPYING that comes with GRASS for details.
+
+ at author Mohammed Rashad <rashadkm gmail.com>
+"""
+import wx
+
+from grass.script import core as grass
+
+from gui_core.toolbars import BaseToolbar, BaseIcons
+from gui_core.dialogs import CreateNewVector
+from dialogs_core import CreateNewRaster
+from vdigit.preferences import VDigitSettingsDialog
+from core.debug import Debug
+from core.settings import UserSettings
+from core.gcmd import GError
+from icons.icon import MetaIcon
+from iclass.digit import IClassVDigit
+
+class RDigitToolbar(BaseToolbar):
+ """!Toolbar for digitization
+ """
+ def __init__(self, parent, MapWindow, digitClass, tools = [], layerTree = None, log = None):
+ self.MapWindow = MapWindow
+ self.Map = MapWindow.GetMap() # Map class instance
+ self.layerTree = layerTree # reference to layer tree associated to map display
+ self.log = log # log area
+ self.tools = tools
+ self.digitClass = digitClass
+ BaseToolbar.__init__(self, parent)
+ self.digit = None
+
+ # currently selected map layer for editing (reference to MapLayer instance)
+ self.mapLayer = None
+ self.mapName = None
+ # list of vector layers from Layer Manager (only in the current mapset)
+ #self.laayers = []
+
+ self.comboid = self.combo = None
+ self.undo = -1
+ self.redo = -1
+
+ # only one dialog can be open
+ self.settingsDialog = None
+
+ # create toolbars (two rows optionally)
+ self.InitToolbar(self._toolbarData())
+ self.Bind(wx.EVT_TOOL, self._toolChosen)
+
+ # default action (digitize new point, line, etc.)
+ self.action = { 'desc' : '',
+ 'type' : '',
+ 'id' : -1 }
+
+ # list of available vector maps
+ self.UpdateListOfLayers(updateTool = True)
+
+ self.layerNameList = []
+ layers = self.Map.GetListOfLayers(l_type = "raster",
+ l_mapset = grass.gisenv()['MAPSET'])
+
+ for layer in layers:
+ if not layer.name in self.layerNameList: # do not duplicate layer
+ self.layerNameList.append (layer.GetName())
+
+ # realize toolbar
+ self.Realize()
+ # workaround for Mac bug. May be fixed by 2.8.8, but not before then.
+ if self.combo:
+ self.combo.Hide()
+ self.combo.Show()
+
+ # disable undo/redo
+ if self.undo > 0:
+ self.EnableTool(self.undo, False)
+ if self.redo > 0:
+ self.EnableTool(self.redo, False)
+
+ # toogle to pointer by default
+ self.OnTool(None)
+
+ self.FixSize(width = 105)
+
+ def _toolbarData(self):
+ """!Toolbar data
+ """
+ data = []
+
+ icons = {
+
+ 'addLine' : MetaIcon(img = 'line-create',
+ label = _('Digitize new line'),
+ desc = _('Left: new point; Ctrl+Left: undo last point; Right: close line')),
+ 'addBoundary' : MetaIcon(img = 'polygon-create',
+ label = _('Digitize new boundary'),
+ desc = _('Left: new point; Ctrl+Left: undo last point; Right: close line')),
+ 'addCircle' : MetaIcon(img = 'draw-circle',
+ label = _('Digitize new Cirlce'),
+ desc = _('Left: new point; Ctrl+Left: undo last point; Right: close line')),
+
+
+ 'deleteLine' : MetaIcon(img = 'line-delete',
+ label = _('Delete feature(s)'),
+ desc = _('Left: Select; Ctrl+Left: Unselect; Right: Confirm')),
+ 'deleteArea' : MetaIcon(img = 'polygon-delete',
+ label = _('Delete area(s)'),
+ desc = _('Left: Select; Ctrl+Left: Unselect; Right: Confirm')),
+ 'deleteCircle' : MetaIcon(img = 'delete-circle',
+ label = _('Digitize new Cirlce'),
+ desc = _('Left: new point; Ctrl+Left: undo last point; Right: close line')),
+
+ 'settings' : BaseIcons['settings'].SetLabel(_('Digitization settings')),
+ 'quit' : BaseIcons['quit'].SetLabel(label = _('Quit digitizer'),
+ desc = _('Quit digitizer and save changes')),
+ 'help' : BaseIcons['help'].SetLabel(label = _('Vector Digitizer manual'),
+ desc = _('Show Vector Digitizer manual')),
+ 'undo' : MetaIcon(img = 'undo',
+ label = _('Undo'),
+ desc = _('Undo previous changes')),
+ 'redo' : MetaIcon(img = 'redo',
+ label = _('Redo'),
+ desc = _('Redo previous changes')),
+ }
+
+ if not self.tools or 'selector' in self.tools:
+ data.append((None, ))
+
+ if not self.tools or 'addLine' in self.tools:
+ data.append(("addLine", icons["addLine"],
+ self.OnAddLine,
+ wx.ITEM_CHECK))
+
+ if not self.tools or 'addBoundary' in self.tools:
+ data.append(("addBoundary", icons["addBoundary"],
+ self.OnAddBoundary,
+ wx.ITEM_CHECK))
+
+# if not self.tools or 'addCircle' in self.tools:
+# data.append(("addCircle", icons["addCircle"],
+# self.OnAddCircle,
+# wx.ITEM_CHECK))
+
+ data.append((None, ))
+
+ if not self.tools or 'deleteLine' in self.tools:
+ data.append(("deleteLine", icons["deleteLine"],
+ self.OnDeleteLine,
+ wx.ITEM_CHECK))
+ if not self.tools or 'deleteArea' in self.tools:
+ data.append(("deleteArea", icons["deleteArea"],
+ self.OnDeleteArea,
+ wx.ITEM_CHECK))
+# if not self.tools or 'deleteCircle' in self.tools:
+# data.append(("deleteCircle", icons["deleteCircle"],
+# self.OnDeleteCircle,
+# wx.ITEM_CHECK))
+
+# if not self.tools or 'undo' in self.tools or \
+# 'redo' in self.tools:
+# data.append((None, ))
+# if not self.tools or 'undo' in self.tools:
+# data.append(("undo", icons["undo"],
+# self.OnUndo))
+# if not self.tools or 'redo' in self.tools:
+# data.append(("redo", icons["redo"],
+# self.OnRedo))
+# if not self.tools or 'settings' in self.tools or \
+# 'help' in self.tools or \
+# 'quit' in self.tools:
+# data.append((None, ))
+
+ if not self.tools or 'help' in self.tools:
+ data.append(("help", icons["help"],
+ self.OnHelp))
+ if not self.tools or 'quit' in self.tools:
+ data.append(("quit", icons["quit"],
+ self.OnExit))
+
+ return self._getToolbarData(data)
+
+ def _toolChosen(self, event):
+ """!Tool selected -> untoggles selected tools in other
+ toolbars
+
+ @todo implement iclass front-end
+ """
+ self.parent.MapWindow.UnregisterAllHandlers()
+
+ if hasattr(self.parent, "UpdateTools"):
+ self.parent.UpdateTools(event)
+ self.OnTool(event)
+
+ def OnTool(self, event):
+ """!Tool selected -> untoggles previusly selected tool in
+ toolbar"""
+ # set cursor
+ cursor = self.parent.cursors["cross"]
+ self.MapWindow.SetCursor(cursor)
+
+ # pointer
+ self.parent.OnPointer(None)
+
+ aId = self.action.get('id', -1)
+ BaseToolbar.OnTool(self, event)
+
+ # clear tmp canvas
+ if self.action['id'] != aId or aId == -1:
+ self.MapWindow.polycoords = []
+ self.MapWindow.ClearLines(pdc = self.MapWindow.pdcTmp)
+# if self.digit and \
+# len(self.MapWindow.digit.GetDisplay().GetSelected()) > 0:
+# # cancel action
+# self.MapWindow.OnMiddleDown(None)
+#
+ # set no action
+ if self.action['id'] == -1:
+ self.action = { 'desc' : '',
+ 'type' : '',
+ 'id' : -1 }
+
+ # set focus
+ self.MapWindow.SetFocus()
+
+
+
+ def OnAddLine(self, event):
+ """!Add line to the vector map layer"""
+
+ Debug.msg (2, "RDigitToolbar.OnAddLine()")
+
+ self.action = { 'desc' : "addLine",
+ 'type' : "line",
+ 'id' : self.addLine }
+ self.MapWindow.mouse['box'] = 'line'
+
+
+ def OnAddBoundary(self, event):
+ """!Add boundary to the vector map layer"""
+
+ Debug.msg (2, "RDigitToolbar.OnAddBoundary()")
+
+ if self.action['desc'] != 'addLine' or \
+ self.action['type'] != 'boundary':
+ self.MapWindow.polycoords = [] # reset temp line
+ self.action = { 'desc' : "addLine",
+ 'type' : "boundary",
+ 'id' : self.addBoundary }
+ self.MapWindow.mouse['box'] = 'line'
+
+ def OnAddCircle(self, event):
+ """!Add cirlce to the vector map layer"""
+
+ Debug.msg (2, "RDigitToolbar.OnAddCircle()")
+
+ if self.action['desc'] != 'addCircle':
+ self.MapWindow.polycoords = [] # reset temp line
+ self.action = { 'desc' : "addCircle",
+ 'type' : "circle",
+ 'id' : self.addCircle }
+ self.MapWindow.mouse['box'] = 'line'
+
+ def OnExit (self, event=None):
+ """!Quit digitization tool"""
+
+ # stop editing of the currently selected map layer
+ if self.mapLayer:
+ self.StopEditing()
+
+ # close dialogs if still open
+ if self.settingsDialog:
+ self.settingsDialog.OnCancel(None)
+
+ # set default mouse settings
+ self.MapWindow.mouse['use'] = "pointer"
+ self.MapWindow.mouse['box'] = "point"
+ self.MapWindow.polycoords = []
+
+ # disable the toolbar
+ self.parent.RemoveToolbar("rdigit")
+
+
+
+ def OnDeleteLine(self, event):
+ """!Delete line"""
+
+ Debug.msg(2, "RDigittoolbar.OnDeleteLine():")
+
+ self.action = { 'desc' : "deleteLine",
+ 'id' : self.deleteLine }
+ self.MapWindow.mouse['box'] = 'box'
+
+ def OnDeleteArea(self, event):
+ """!Delete Area"""
+
+ Debug.msg(2, "RDigittoolbar.OnDeleteArea():")
+
+ self.action = { 'desc' : "deleteArea",
+ 'id' : self.deleteArea }
+ self.MapWindow.mouse['box'] = 'line'
+
+ def OnDeleteCircle(self, event):
+ """!Delete Circle"""
+
+ Debug.msg(2, "RDigittoolbar.OnDeleteCircle():")
+
+ self.action = { 'desc' : "deleteCircle",
+ 'id' : self.deleteCircle }
+ self.MapWindow.mouse['box'] = 'line'
+
+
+ def OnUndo(self, event):
+ """!Undo previous changes"""
+ self.digit.Undo()
+
+ event.Skip()
+
+ def OnRedo(self, event):
+ """!Undo previous changes"""
+ self.digit.Undo(level = 1)
+
+ event.Skip()
+
+ def EnableUndo(self, enable = True):
+ """!Enable 'Undo' in toolbar
+
+ @param enable False for disable
+ """
+ self._enableTool(self.undo, enable)
+
+ def EnableRedo(self, enable = True):
+ """!Enable 'Redo' in toolbar
+
+ @param enable False for disable
+ """
+ self._enableTool(self.redo, enable)
+
+ def _enableTool(self, tool, enable):
+ if not self.FindById(tool):
+ return
+
+ if enable:
+ if self.GetToolEnabled(tool) is False:
+ self.EnableTool(tool, True)
+ else:
+ if self.GetToolEnabled(tool) is True:
+ self.EnableTool(tool, False)
+
+
+ def OnHelp(self, event):
+ """!Show digitizer help page in web browser"""
+ helpInProgress = True
+ #log = self.parent.GetLayerManager().GetLogWindow()
+ #log.RunCmd(['g.manual', 'entry=wxGUI.Vector_Digitizer'])
+
+ def GetListOfLayers(self):
+ return self.layerNameList
+
+
+ def GetMapName(self):
+ return self.mapName
+
+
+ def OnSelectMap (self, event):
+ """!Select raster map layer for editing
+ If there is a raster map layer already edited, this action is
+ firstly terminated. The map layer is closed. After this the
+ selected map layer activated for editing.
+ """
+
+ selectedMapName = None
+ selection = -1
+ if event.GetSelection() == 0: # create new raster map layer
+ if self.mapLayer:
+ openVectorMap = self.mapLayer.GetName(fullyQualified = False)['name']
+ else:
+ openVectorMap = None
+ dlg = CreateNewRaster(self.parent, exceptMap = openVectorMap,disableAdd = True)
+
+
+
+ if dlg and dlg.GetName():
+ # add layer to map layer tree(layer tree is map manager)
+
+ mapName = str(dlg.GetName() + '@' + grass.gisenv()['MAPSET'])
+ self.combo.Append(mapName)
+ self.mapName = selectedMapName = mapName
+ self.layerNameList.append(mapName)
+ vectLayers = self.GetListOfLayers()
+ selection = vectLayers.index(mapName)
+ else:
+ self.combo.SetValue(_('Select raster map'))
+ if dlg:
+ dlg.Destroy()
+ return
+ else:
+ selection = event.GetSelection() - 1 # first option is 'New raster map'
+ selectedMapName = self.combo.GetValue()
+
+ # skip currently selected map FIXME
+ #if self.layers[selection] == self.mapLayer:
+ #return
+
+ if selection == -1: #FIXME
+ # deactive map layer for editing
+ self.StopEditing()
+
+
+ # select the given map layer for editing FIXME
+ if selectedMapName:
+ self.combo.SetValue(selectedMapName)
+
+ self.StartEditing(selectedMapName)
+ self.digit.setOutputName(selectedMapName)
+
+ event.Skip()
+
+ def StartEditing (self, mapLayer):
+ """!Start editing selected vector map layer.
+
+ @param mapLayer MapLayer to be edited
+ """
+ # deactive layer FIXME
+ #self.Map.ChangeLayerActive(mapLayer, False)
+
+ # clean map canvas
+ self.MapWindow.EraseMap()
+
+# # unset background map if needed
+# if mapLayer:
+# if UserSettings.Get(group = 'vdigit', key = 'bgmap',
+# subkey = 'value', internal = True) == mapLayer:
+# UserSettings.Set(group = 'vdigit', key = 'bgmap',
+# subkey = 'value', value = '', internal = True)
+#
+# self.parent.SetStatusText(_("Please wait, "
+# "opening vector map <%s> for editing...") % mapLayer,
+# 0)
+#
+ self.MapWindow.pdcVector = wx.PseudoDC()
+ self.digit = self.MapWindow.digit = self.digitClass(mapwindow = self.MapWindow)
+
+ self.mapLayer = mapLayer
+
+ self.EnableAll()
+ self.EnableUndo(False)
+ self.EnableRedo(False)
+
+ Debug.msg (4, "RDigitToolbar.StartEditing(): layer=%s" % mapLayer)
+
+ # change cursor
+ if self.MapWindow.mouse['use'] == 'pointer':
+ self.MapWindow.SetCursor(self.parent.cursors["cross"])
+
+ if not self.MapWindow.resize:
+ self.MapWindow.UpdateMap(render = True)
+
+ # respect opacity
+ opacity = 100 # FIXME mapLayer.GetOpacity(float = True)
+
+ if opacity < 1.0:
+ alpha = int(opacity * 255)
+ self.digit.GetDisplay().UpdateSettings(alpha = alpha)
+
+ return True
+
+ def StopEditing(self):
+ """!Stop editing of selected vector map layer.
+
+ @return True on success
+ @return False on failure
+ """
+ if self.combo:
+ self.combo.SetValue (_('Select vector map'))
+
+ # save changes
+ if self.mapLayer:
+ Debug.msg (4, "RDigitToolbar.StopEditing(): layer=%s" % self.mapLayer)
+
+ dlg = wx.MessageDialog(parent = self.parent,
+ message = _("Do you want to save changes "
+ "in vector map <%s>?") % self.mapLayer,
+ caption = _("Save changes?"),
+ style = wx.YES_NO | wx.YES_DEFAULT | wx.ICON_QUESTION)
+ if dlg.ShowModal() == wx.ID_NO:
+ # revert changes
+ self.digit.saveMap = False
+ dlg.Destroy()
+
+ #FIXME self.digit.CloseMap()
+
+ #FIXME self.Map.ChangeLayerActive(self.mapLayer, True)
+
+ # change cursor
+ self.MapWindow.SetCursor(self.parent.cursors["default"])
+ self.MapWindow.pdcVector = None
+
+ del self.digit
+ del self.MapWindow.digit
+
+ self.mapLayer = None
+
+ self.MapWindow.redrawAll = True
+
+ return True
+
+ def UpdateListOfLayers (self, updateTool = False):
+ """!Update list of available vector map layers.
+ This list consists only editable layers (in the current mapset)
+
+ @param updateTool True to update also toolbar
+ """
+ Debug.msg (4, "RDigitToolbar.UpdateListOfLayers(): updateTool=%d" % updateTool)
+
+ layerNameSelected = None
+ # name of currently selected layer
+ if self.mapLayer:
+ layerNameSelected = self.mapLayer
+
+ # select vector map layer in the current mapset
+ layerNameList = []
+ self.layers = self.Map.GetListOfLayers(l_type = "raster",
+ l_mapset = grass.gisenv()['MAPSET'])
+
+ for layer in self.layers:
+ if not layer.name in layerNameList: # do not duplicate layer
+ layerNameList.append (layer.GetName())
+
+ if updateTool: # update toolbar
+ if not self.mapLayer:
+ value = _('Select vector map')
+ else:
+ value = layerNameSelected
+
+ if not self.comboid:
+ if not self.tools or 'selector' in self.tools:
+ self.combo = wx.ComboBox(self, id = wx.ID_ANY, value = value,
+ choices = [_('New raster map'), ] + layerNameList, size = (80, -1),
+ style = wx.CB_READONLY)
+ self.comboid = self.InsertControl(0, self.combo)
+ self.parent.Bind(wx.EVT_COMBOBOX, self.OnSelectMap, self.comboid)
+ else:
+ self.combo.SetItems([_('New raster map'), ] + layerNameList)
+
+ self.Realize()
+
+ return layerNameList
+
+ def GetLayer(self):
+ """!Get selected layer for editing -- MapLayer instance"""
+ return self.mapLayer
+
Added: grass-addons/grass7/gui/wxpython/wx.rdigit/rdigit/wxdigit.py
===================================================================
--- grass-addons/grass7/gui/wxpython/wx.rdigit/rdigit/wxdigit.py (rev 0)
+++ grass-addons/grass7/gui/wxpython/wx.rdigit/rdigit/wxdigit.py 2012-12-18 13:26:25 UTC (rev 54331)
@@ -0,0 +1,201 @@
+"""!
+ at package vdigit.wxdigit
+
+ at brief wxGUI raster digitizer (base class)
+
+List of classes:
+
+ - wxvdigit::IRDigit
+
+(C) 2007-2011 by the GRASS Development Team
+
+This program is free software under the GNU General Public License
+(>=v2). Read the file COPYING that comes with GRASS for details.
+
+ at author Mohammed Rashad <rashadkm gmail.com>
+ at author Martin Landa <landa.martin gmail.com>(original wxvdigit)
+"""
+
+import grass.script.core as grass
+#from pygrass.modules import Module
+from core.gconsole import GConsole
+from core.gcmd import GError, RunCommand, CommandThread
+from core.debug import Debug
+from core.settings import UserSettings
+
+import sys
+import os
+import tempfile
+
+try:
+ from grass.lib.gis import *
+ from grass.lib.vector import *
+ from grass.lib.raster import *
+except ImportError:
+ pass
+
+
+class RasterObject:
+ def __init__(self,cat,coords,ft):
+ self.catId = cat
+ self.coords = coords
+ self.ftype = ft
+
+
+class IRDigit:
+ def __init__(self, mapwindow):
+ """!Base class for vector digitizer (ctypes interface)
+
+ @param mapwindow reference for map window (BufferedWindow)
+ """
+ self.mapWindow = mapwindow
+
+ self.objects = list()
+
+ self.toolbar = mapwindow.parent.toolbars['rdigit']
+
+ self.polyfile = tempfile.NamedTemporaryFile(delete=False)
+
+ Debug.msg(2, "IRDigit.__init__() %s ", self.polyfile.name)
+
+ self.cat = 1
+ self.saveMap = True
+
+ self.outputName = None
+
+
+
+ def __del__(self):
+ Debug.msg(1, "IVDigit.__del__()")
+
+ if self.saveMap == True:
+
+ for obj in self.objects:
+ if obj.ftype == GV_BOUNDARY:
+ self.polyfile.write("AREA\n");
+ for coor in obj.coords:
+ east, north = coor
+ locbuf = " %s %s\n" % (east,north)
+ self.polyfile.write(locbuf);
+
+ elif obj.ftype == GV_LINE:
+ self.polyfile.write("LINE\n");
+ for coor in obj.coords:
+ east, north = coor
+ locbuf = " %s %s\n" % (east,north)
+ self.polyfile.write(locbuf);
+
+ catbuf = "=%d a\n" % (obj.catId)
+ self.polyfile.write(catbuf);
+
+ self.polyfile.close()
+
+ region_settings = grass.parse_command('g.region', flags = 'p', delimiter = ':')
+ RunCommand('r.in.poly', input=self.polyfile.name,
+ rows=region_settings['rows'], output=self.getOutputName(),overwrite=True)
+
+ os.unlink(self.polyfile.name)
+
+
+ def setOutputName(self, name):
+ if name:
+ self.outputName = name
+
+ def getOutputName(self):
+ return self.outputName
+
+ def DeleteArea(self, cat):
+ self.objectsCopy = self.objects
+ self.objects = []
+ for obj in self.objectsCopy:
+ if obj.catId != cat:
+ self.objects.append(obj)
+
+ def AddFeature(self, ftype, points):
+ """!Add new feature
+
+ @param ftype feature type (point, line, centroid, boundary)
+ @param points tuple of points ((x, y), (x, y), ...)
+
+ @return tuple (number of added features, feature ids)
+ """
+
+ #layer = self._getNewFeaturesLayer()
+ #cat = self._getNewFeaturesCat()
+
+ if ftype == 'point':
+ vtype = GV_POINT
+ elif ftype == 'line':
+ vtype = GV_LINE
+ elif ftype == 'centroid':
+ vtype = GV_CENTROID
+ elif ftype == 'boundary':
+ vtype = GV_BOUNDARY
+ elif ftype == 'area':
+ vtype = GV_AREA
+ elif ftype == 'circle':
+ vtype = 'circle'
+ else:
+ GError(parent = self.mapWindow,
+ message = _("Unknown feature type '%s'") % ftype)
+ return (-1, None)
+
+ Debug.msg(2, "IRRDigit1()")
+
+ if vtype & GV_LINES and len(points) < 2:
+ GError(parent = self.mapWindow,
+ message = _("Not enough points for line"))
+ return (-1, None)
+
+ self.toolbar.EnableUndo()
+
+
+ return self._addFeature(vtype, points)
+
+ def _checkMap(self):
+ """!Check if map is open
+ """
+ if not self.polyfile.name:
+ self._NoMap()
+ return False
+
+ return True
+
+ def NoMap(self, name = None):
+ """!No map for editing"""
+ if name:
+ message = _('Unable to open vector map <%s>.') % name
+ else:
+ message = _('No vector map open for editing.3')
+ GError(message + ' ' + _('Operation canceled.'),
+ parent = self.parent,
+ caption = self.caption)
+
+ def _addFeature(self, ftype, coords):
+ """!Add new feature(s) to the vector map
+
+ @param ftype feature type (GV_POINT, GV_LINE, GV_BOUNDARY, ...)
+ @coords tuple of coordinates ((x, y), (x, y), ...)
+ @param layer layer number (-1 for no cat)
+ @param cat category number
+ @param snap snap to node/vertex
+ @param threshold threshold for snapping
+
+ @return tuple (number of added features, list of fids)
+ @return number of features -1 on error
+ """
+
+ if not self._checkMap():
+ return (-1, None)
+
+ #is3D = bool(Vect_is_3d(self.poMapInfo))
+
+ Debug.msg(2, "IVDigit._addFeature(): npoints=%d, ftype=%d",
+ len(coords), ftype)
+
+ obj = RasterObject(self.cat, coords,ftype)
+ self.objects.append(obj)
+ self.cat = self.cat + 1
+ return self.cat - 1
+
+
Added: grass-addons/grass7/gui/wxpython/wx.rdigit/toolbars.py
===================================================================
--- grass-addons/grass7/gui/wxpython/wx.rdigit/toolbars.py (rev 0)
+++ grass-addons/grass7/gui/wxpython/wx.rdigit/toolbars.py 2012-12-18 13:26:25 UTC (rev 54331)
@@ -0,0 +1,152 @@
+"""!
+ at package iclass.toolbars
+
+ at brief wxIClass toolbars and icons.
+
+Classes:
+ - toolbars::IClassMapToolbar
+ - toolbars::IClassToolbar
+ - toolbars::IClassMapManagerToolbar
+
+(C) 2006-2011 by the GRASS Development Team
+This program is free software under the GNU General Public
+License (>=v2). Read the file COPYING that comes with GRASS
+for details.
+
+ at author Vaclav Petras <wenzeslaus gmail.com>
+ at author Anna Kratochvilova <kratochanna gmail.com>
+"""
+
+import wx
+
+from gui_core.toolbars import BaseToolbar, BaseIcons
+from icons.icon import MetaIcon
+
+import grass.script as grass
+
+iClassIcons = {
+ 'opacity' : MetaIcon(img = 'layer-opacity',
+ label = _('Set opacity level')),
+ 'tools' : MetaIcon(img = 'tools',
+ label = _('Load Digitizer tools')),
+ 'selectGroup' : MetaIcon(img = 'layer-group-add',
+ label = _('Select imagery group')),
+ 'run' : MetaIcon(img = 'execute',
+ label = _('Run analysis')),
+ 'sigFile' : MetaIcon(img = 'script-save',
+ label = _('Save signature file')),
+ 'delCmd' : MetaIcon(img = 'layer-remove',
+ label = _('Delete selected map layer')),
+ 'exportAreas' : MetaIcon(img = 'layer-export',
+ label = _('Export training areas')),
+ 'importAreas' : MetaIcon(img = 'layer-import',
+ label = _('Import training areas')),
+ }
+
+class RDigitMapToolbar(BaseToolbar):
+ """!IClass Map toolbar
+ """
+ def __init__(self, parent):
+ """!IClass Map toolbar constructor
+ """
+ BaseToolbar.__init__(self, parent)
+
+ self.InitToolbar(self._toolbarData())
+
+
+
+ # realize the toolbar
+ self.Realize()
+
+ self.action = { 'id' : self.pan }
+ self.defaultAction = { 'id' : self.pan,
+ 'bind' : self.parent.OnPan }
+
+ self.OnTool(None)
+
+ self.EnableTool(self.zoomBack, False)
+
+
+
+ def _toolbarData(self):
+ """!Toolbar data"""
+ icons = BaseIcons
+ return self._getToolbarData((("displaymap", icons["display"],
+ self.parent.OnDraw),
+ ("rendermap", icons["render"],
+ self.parent.OnRender),
+ ("erase", icons["erase"],
+ self.parent.OnErase),
+ (None, ),
+ ("pan", icons["pan"],
+ self.parent.OnPan,
+ wx.ITEM_CHECK),
+ ("zoomIn", icons["zoomIn"],
+ self.parent.OnZoomIn,
+ wx.ITEM_CHECK),
+ ("zoomOut", icons["zoomOut"],
+ self.parent.OnZoomOut,
+ wx.ITEM_CHECK),
+ ("zoomMenu", icons["zoomMenu"],
+ self.parent.OnZoomMenu),
+ (None, ),
+ ("zoomBack", icons["zoomBack"],
+ self.parent.OnZoomBack),
+ ("zoomToMap", icons["zoomExtent"],
+ self.parent.OnZoomToMap),
+
+ ("drawArea", iClassIcons["tools"],
+ self.parent.OnDrawArea),
+ ))
+
+
+
+
+
+class RDigitMapManagerToolbar(BaseToolbar):
+ """!IClass toolbar
+ """
+ def __init__(self, parent, mapManager):
+ """!IClass toolbar constructor
+ """
+ BaseToolbar.__init__(self, parent)
+
+ self.InitToolbar(self._toolbarData())
+ self.choice = wx.Choice(parent = self, id = wx.ID_ANY, size = (300, -1))
+
+ self.choiceid = self.AddControl(self.choice)
+
+ self.choice.Bind(wx.EVT_CHOICE, self.OnSelectLayer)
+
+ self.mapManager = mapManager
+ # realize the toolbar
+ self.Realize()
+
+ def _toolbarData(self):
+ """!Toolbar data"""
+ return self._getToolbarData((("addRast", BaseIcons['addRast'],
+ self.OnAddRast),
+ ("delRast", iClassIcons['delCmd'],
+ self.OnDelRast),
+
+ ))
+
+ def OnSelectLayer(self, event):
+ layer = self.choice.GetStringSelection()
+ self.mapManager.SelectLayer(name = layer)
+
+ def OnAddRast(self, event):
+ dlg = IClassMapDialog(self, title = _("Add raster map"), element = 'raster')
+ if dlg.ShowModal() == wx.ID_OK:
+ raster = grass.find_file(name = dlg.GetMap(), element = 'cell')
+ if raster['fullname']:
+ self.mapManager.AddLayer(name = raster['fullname'])
+
+ dlg.Destroy()
+
+ def OnDelRast(self, event):
+ layer = self.choice.GetStringSelection()
+ idx = self.choice.GetSelection()
+ if layer:
+ self.mapManager.RemoveLayer(name = layer, idx = idx)
+
More information about the grass-commit
mailing list