[GRASS-SVN] r43715 - in
grass/branches/releasebranch_6_4/gui/wxpython: . docs
gui_modules xml
svn_grass at osgeo.org
svn_grass at osgeo.org
Mon Sep 27 15:32:44 EDT 2010
Author: mmetz
Date: 2010-09-27 19:32:44 +0000 (Mon, 27 Sep 2010)
New Revision: 43715
Added:
grass/branches/releasebranch_6_4/gui/wxpython/docs/wxGUI.GCP_Manager.html
grass/branches/releasebranch_6_4/gui/wxpython/docs/wxGUI_GCP_Manager.jpg
grass/branches/releasebranch_6_4/gui/wxpython/gui_modules/gcpmanager.py
grass/branches/releasebranch_6_4/gui/wxpython/gui_modules/gcpmapdisp.py
Modified:
grass/branches/releasebranch_6_4/gui/wxpython/docs/Makefile
grass/branches/releasebranch_6_4/gui/wxpython/docs/wxGUI.html
grass/branches/releasebranch_6_4/gui/wxpython/gui_modules/__init__.py
grass/branches/releasebranch_6_4/gui/wxpython/gui_modules/gselect.py
grass/branches/releasebranch_6_4/gui/wxpython/gui_modules/mapdisp.py
grass/branches/releasebranch_6_4/gui/wxpython/gui_modules/preferences.py
grass/branches/releasebranch_6_4/gui/wxpython/gui_modules/toolbars.py
grass/branches/releasebranch_6_4/gui/wxpython/gui_modules/wxgui_utils.py
grass/branches/releasebranch_6_4/gui/wxpython/wxgui.py
grass/branches/releasebranch_6_4/gui/wxpython/xml/menudata.xml
Log:
add wxGUI version of i.points
Modified: grass/branches/releasebranch_6_4/gui/wxpython/docs/Makefile
===================================================================
--- grass/branches/releasebranch_6_4/gui/wxpython/docs/Makefile 2010-09-27 19:28:50 UTC (rev 43714)
+++ grass/branches/releasebranch_6_4/gui/wxpython/docs/Makefile 2010-09-27 19:32:44 UTC (rev 43715)
@@ -4,7 +4,8 @@
wxGUI.Vector_Digitizing_Tool \
wxGUI.Attribute_Table_Manager \
wxGUI.Nviz \
- wxGUI.Icons
+ wxGUI.Icons \
+ wxGUI.GCP_Manager
include $(MODULE_TOPDIR)/include/Make/Platform.make
include $(MODULE_TOPDIR)/include/Make/Grass.make
Added: grass/branches/releasebranch_6_4/gui/wxpython/docs/wxGUI.GCP_Manager.html
===================================================================
--- grass/branches/releasebranch_6_4/gui/wxpython/docs/wxGUI.GCP_Manager.html (rev 0)
+++ grass/branches/releasebranch_6_4/gui/wxpython/docs/wxGUI.GCP_Manager.html 2010-09-27 19:32:44 UTC (rev 43715)
@@ -0,0 +1,308 @@
+<h2>DESCRIPTION</h2>
+
+<p>
+The <b>GCP Manager</b> is a <em><a href="wxGUI.html">wxGUI</a></em>
+extension which allows the user to create, edit, and manage
+Ground Control Points. It is available from the menu
+"File | Manage Ground Control Points".
+
+<p>
+The <b>GCP Manager</b> provides an interactive graphical interface to
+manage and analyze Ground Control Points. A backup copy of the initial
+POINTS file is always maintained and updated only on request (Save GCPs
+to POINTS file). This guarantees that accidential changes are not
+permanent and can be undone by reloading the Ground Control Points.
+
+<p>
+The GCP Manager must be started in the target location, not in the
+source location.
+
+<p>
+The GCP Manager is structured into three panels:
+
+<ul>
+ <li>The topmost panel shows a list of Ground Control Points. Tools to
+ manipulate and analyze GCPs are provided in the toolbar. This panel can
+ be moved out of the GCP manager window by either dragging with the
+ caption or by clicking on the pin button on the right in the caption.
+ This panel can also be placed below the map displays by dragging.
+ <li>The two panels in the lower part are used for map and GCP display,
+ the left pane showing a map from the source location and the right
+ pane showing a reference map from the target location. Numbered Ground
+ Control Points are shown on both map displays.
+</ul>
+
+
+
+<h3>Components of the GCP Manager</h3>
+
+<center>
+ <br><img src="wxGUI_GCP_Manager.jpg" border="0" alt="GCP Manager"><br><br>
+</center>
+
+<p>
+<em>Toolbars</em>
+<p>
+Two toolbars are provided with the GCP Manager, one for managing the map
+displays and one for managing the GCP list.
+
+<p>
+<em>List of ground control points</em>
+<p>
+The list of Ground Control Points can be sorted by clicking on a column
+header. Clicking on a cloumn header will sort the GCPs ascending, a
+second click on the same column will sort the GCPs descending. Overall
+RMS error and individual RMS errors of all points are often improved if
+the GCP with the highest RMS error is adjusted. Individual coordinates
+can be edited by double-clicking on a row.
+<p>
+The first column holds a checkbox and displays the point number. A GCP
+is only used for RMS error calculation and georectification if its
+checkbox on the left is checked. Uncheck to deactivate a GCP (mark as
+unused GCP).
+
+<p>
+<em>Two panels for map display</em>
+<p>
+The left panel is used to display a map from the source location, the
+right panel to display a map from the target loaction. Zooming in and
+out is always possible with the mouse wheel and done for each map canvas
+separately.
+<p>
+GCPs are displayed in different colors, depending on whether a GCP has
+a high RMS error, is currently unused or is currently selected. Optionally,
+currently unused GCPs are not shown on the map display.
+
+<p>
+<em>Statusbar</em>
+<p>
+At the bottom of the GCP Manager is a statusbar providing several
+functions. The default is set to <em>Go to GCP No.</em> (see also below).
+Typing a number or using the up/down arrows will center the maps on the
+given GCP, useful with a high zoom.
+
+<h4>GCP Map Display Toolbar</h4>
+
+<dl>
+
+<dt><img src="icons/grass2/show.png">
+ <em>Display map</em></dt>
+<dd>Displays maps for source and target canvas and re-renders any layers
+that have changed since the last time the display was updated.</dd>
+
+<dt><img src="icons/grass2/layer-redraw.png">
+ <em>Re-render map</em></dt>
+<dd>Re-renders both source and target canvas regardless of whether they
+have changed or not.</dd>
+
+<dt><img src="icons/grass2/erase.png">
+ <em>Erase display</em></dt>
+<dd>Erases both source and target canvas to a white background.</dd>
+
+<dt><img src="icons/grass2/gcp-create.png">
+ <em>Define GCP (Ground Control Points)</em></dt>
+<dd>On left mouse click, coordinates are defined for the currently
+selected GCP.</dd>
+
+<dt><img src="icons/grass2/pan.png">
+ <em>Pan</em></dt>
+<dd>Interactive selection of a new center of view in the active
+display monitor. Drag the pan cursor while pressing the left mouse
+button to pan. Alternatively left-click on the new center. Panning
+changes the location of the region displayed but not the size of the
+area displayed or the resolution.</dd>
+
+<dt><img src="icons/grass2/zoom-in.png">
+ <em>Zoom in</em></dt>
+<dd>Interactive zooming with the mouse in the active map canvas (source
+or target). Drawing a box or just a left click with the mouse and zoom-in
+cursor causes the display to zoom in so that the area defined by the box
+fills the display. The map resolution is not changed. Clicking with the
+zoom-in cursor causes the display to zoom in by 30%, centered on the
+point where the mouse is clicked. Zooming changes the display region
+extents (both size and location of area displayed).</dd>
+
+<dt><img src="icons/grass2/zoom-out.png">
+ <em>Zoom out</em></dt>
+<dd>Interactive zooming with the mouse in the active map canvas (source
+or target). Drawing a box or just a left click with the mouse and zoom-out
+cursor causes the display to zoom out so that the area displayed
+shrinks to fill the area defined by the box. The map resolution is not
+changed. Clicking with the zoom-out cursor causes the display to zoom
+out by 30%, centered on the point where the mouse is clicked. Zooming
+changes the display region extents (both size and location of area
+displayed).</dd>
+
+<dt><img src="icons/grass2/zoom-more.png">
+ <em>Adjust display zoom</em></dt>
+<dd>Source and target display are adjusted by using the current GCPs for
+coordinate transformation:
+<br><br>
+ <dl>
+ <dt><em>Adjust source display to target display</em>
+ <dd>The extents of the source display are adjusted to the current
+ extents of the target display.
+ <dt><em>Adjust target display to source display</em>
+ <dd>The extents of the source display are adjusted to the current
+ extents of the target display.
+ </dl>
+
+<dt><em>Set active map canvas</em></dt>
+<dd>Sets the currently active map canvas (source or target). Click
+to set active map canvas for <em>Return to previous zoom</em> or
+<em>Zoom to extent of currently displayed map</em>. Alternatively, move
+the mouse over the map canvas to be used as active canvas.</dd>
+
+<dt><img src="icons/grass2/zoom-last.png">
+ <em>Return to previous zoom</em></dt>
+<dd>Returns to the previous zoom extent. Up to 10 levels of zoom back are
+maintained.</dd>
+
+<dt><img src="icons/grass2/zoom-extent.png">
+<em>Zoom to extent of currently displayed map</em></dt>
+<dd>Zoom to the extent of the currently displayed map in the active map
+canvas (source or target).</dd>
+
+<dt><img src="icons/grass2/settings.png">
+<em>Settings</em></dt>
+<dd>Shows a settings dialog for GCP management and display:<br><br>
+
+ <dl>
+ <dt><em>Symbology</em></dt>
+ <dd>Settings for map and GCP display:<br><br>
+
+ <dl>
+ <dt><em>Highlight highest RMS error only</em></dt>
+ <dd>Only the GCP with the highest RMS error will be displayed in
+ a different colour, both in the list of GCPs and the GCP Map Display.
+ <dt><em>Factor for RMS error threshold = M + SD * factor:</em></dt>
+ <dd>All GCPs with an RMS error larger than mean RMS + RMS standard
+ deviation * this factor will be displayed in a different colour,
+ both in the list of GCPs and the GCP Map Display. As a rule of
+ thumb, GCPs with an RMS error larger than <em>M + SD * 2</em> are
+ most probably wrong. GCPs with an RMS error larger than
+ <em>M + SD * 1</em> are worth closer inspection. This option is
+ only available if <em>Highlight highest RMS error only</em> is
+ unchecked.</dd>
+ <dt><em>Color</em></dt>
+ <dd>Set the color for GCPs on the GCP Map Display.</dd>
+ <dt><em>Color for high RMS error</em></dt>
+ <dd>Set the color for GCPs with a high RMS error on the GCP Map
+ Display.</dd>
+ <dt><em>Color for selected GCP</em></dt>
+ <dd>Set the color for the currently selected GCP on the GCP Map
+ Display.</dd>
+ <dt><em>Show unused GCPs</em></dt>
+ <dd>If unchecked, unused GCPs will not be shown on the GCP Map
+ Display.</dd>
+ <dt><em>Color for unused GCPs</em></dt>
+ <dd>Set the color for unused GCPs on the GCP Map Display.</dd>
+ <dt><em>Symbol size</em></dt>
+ <dd>Set the symbol size for GCPs on the GCP Map Display.</dd>
+ <dt><em>Line width</em></dt>
+ <dd>Set the line width for GCPs on the GCP Map Display.</dd>
+ <dt><em>Select source map to display</em></dt>
+ <dd>Select a source map for the left pane of the GCP Map Display.</dd>
+ <dt><em>Select target map to display</em></dt>
+ <dd>Select a target map for the right pane of the GCP Map Display.</dd>
+ </dl>
+ </dd>
+
+ <dt><br><em>Rectification</em></dt>
+ <dd>Settings for georectification:<br><br>
+ <dl>
+ <dt><em>Select rectification method</em></dt>
+ <dd>Set the polynomial order for georectification. This order will
+ also be used for RMS error calculation.</dd>
+ <dt><em>Clip to computational region in target location</em></dt>
+ <dd>Clip raster maps to the current computational region in the
+ target location when georectifying.</dd>
+ <dt><em>Extension for output maps</em></dt>
+ <dd>Change the extension for output map names when doing the actual
+ georectification.</dd>
+ </dl>
+ </dd>
+ </dl><br>
+</dd>
+
+<dt>
+<em>Show Help</em></dt>
+<dd>Show help page for the GCP Manager.
+
+<dt><img src="icons/grass2/quit.png">
+<em>Quit</em></dt>
+<dd>Quit the GCP Manager.
+
+</dl>
+
+<h4>Toolbar for the GCP list</h4>
+
+<dl>
+
+<dt><img src="icons/grass2/gcp-save.png">
+<em>Save GCPs to POINTS file</em></dt>
+<dd>The current list of GCPs is saved to the imagery group's POINTS file
+and to a backup copy.</dd>
+
+<dt><img src="icons/grass2/gcp-add.png">
+<em>Add new GCP</em></dt>
+<dd>Adds a new Ground Control Point to the list and selects it for editing.</dd>
+
+<dt><img src="icons/grass2/gcp-delete.png">
+<em>Delete selected GCP</em></dt>
+<dd>Deletes the currently selected GCP from the list.</dd>
+
+<dt><img src="icons/grass2/gcp-remove.png">
+<em>Clear selected GCP</em></dt>
+<dd>Resets all coordinates of the currently selected GCP to 0 (zero).</dd>
+
+<dt><img src="icons/grass2/reload.png">
+<em>Reload GCPs from POINTS file</em></dt>
+<dd>Reloads GCPs from the imagery group's POINTS file.</dd>
+
+<dt><img src="icons/grass2/gcp-rms.png">
+<em>Recalculate RMS error</em></dt>
+<dd>Recalculates forward and backward RMS error for all GCP marked for
+use (activated checkbox in first row).
+</dd>
+
+<dt><img src="icons/grass2/georectify.png">
+<em>Georectify</em></dt>
+<dd>Uses <em><a href="i.rectify.html">i.rectify</a></em> to georectify
+all images in the source imagery group.
+</dd>
+
+</dl>
+
+<h4>GCP Map Display Statusbar</h4>
+
+The GCP map display statusbar is similar to the statusbar in the regular
+GRASS GIS map display with two differences, <em>Go to</em> has been
+replaced with <em>Go to GCP No.</em> and <em>Projection</em> has been
+replaced with <em>RMS error</em>.
+<p>
+If <em>Go to GCP No.</em> is selected, a GCP number can be given in the
+left side of the statusbar and the source and target map canvas will be
+centered on the given GCP. Clicking on the map canvas will update
+coordinates for this GCP.
+<p>
+If <em>RMS error</em> is selected, the overall forward and backward RMS
+error is displayed.
+
+<h2>SEE ALSO</h2>
+
+<em>
+ <a href="wxGUI.html">wxGUI</a><br>
+ <a href="i.rectify.html">i.rectify</a><br>
+ <a href="g.transform.html">g.transform</a>
+</em>
+
+<h2>AUTHORS</h2>
+
+Markus Metz<br><br>
+<em>Based on the Georectifier by</em><br>
+Michael Barton<br>
+Martin Landa<br>
+
+<p>
+<i>$Date$</i>
Property changes on: grass/branches/releasebranch_6_4/gui/wxpython/docs/wxGUI.GCP_Manager.html
___________________________________________________________________
Added: svn:mime-type
+ text/html
Added: svn:keywords
+ Author Date Id
Added: svn:eol-style
+ native
Modified: grass/branches/releasebranch_6_4/gui/wxpython/docs/wxGUI.html
===================================================================
--- grass/branches/releasebranch_6_4/gui/wxpython/docs/wxGUI.html 2010-09-27 19:28:50 UTC (rev 43714)
+++ grass/branches/releasebranch_6_4/gui/wxpython/docs/wxGUI.html 2010-09-27 19:32:44 UTC (rev 43715)
@@ -363,7 +363,7 @@
see <em><a href="g.region.html">g.region</a></em>.</dd>
<dt><img src="icons/grass2/zoom-last.png">
- <em>Return to pervious zoom</em></dt>
+ <em>Return to previous zoom</em></dt>
<dd>Returns to the previous zoom extent. Up to 10 levels of zoom back are
maintained, see <em><a href="g.region.html">g.region</a></em>.</dd>
@@ -478,9 +478,10 @@
<h2>SEE ALSO</h2>
<em>
- <a href="wxGUI.Vector_Digitizing_Tool.html">Vector Digitizer</a>,
- <a href="wxGUI.Attribute_Table_Manager.html">Attribute Table Manager</a>,
- <a href="wxGUI.Nviz.html">3D Viewer</a>,
+ <a href="wxGUI.Vector_Digitizing_Tool.html">Vector Digitizer</a><br>
+ <a href="wxGUI.Attribute_Table_Manager.html">Attribute Table Manager</a><br>
+ <a href="wxGUI.Nviz.html">3D Viewer</a><br>
+ <a href="wxGUI.GCP_Manager.html">Manage Ground Control Points</a><br>
<a href="wxGUI.Icons.html">Icon themes</a>
</em>
Added: grass/branches/releasebranch_6_4/gui/wxpython/docs/wxGUI_GCP_Manager.jpg
===================================================================
(Binary files differ)
Property changes on: grass/branches/releasebranch_6_4/gui/wxpython/docs/wxGUI_GCP_Manager.jpg
___________________________________________________________________
Added: svn:mime-type
+ image/jpeg
Modified: grass/branches/releasebranch_6_4/gui/wxpython/gui_modules/__init__.py
===================================================================
--- grass/branches/releasebranch_6_4/gui/wxpython/gui_modules/__init__.py 2010-09-27 19:28:50 UTC (rev 43714)
+++ grass/branches/releasebranch_6_4/gui/wxpython/gui_modules/__init__.py 2010-09-27 19:32:44 UTC (rev 43715)
@@ -3,6 +3,8 @@
"disp_print",
"gcmd",
"georect",
+ "gcpmanager",
+ "gcpmapdisp",
"globalvar",
"grassenv",
"gselect",
Added: grass/branches/releasebranch_6_4/gui/wxpython/gui_modules/gcpmanager.py
===================================================================
--- grass/branches/releasebranch_6_4/gui/wxpython/gui_modules/gcpmanager.py (rev 0)
+++ grass/branches/releasebranch_6_4/gui/wxpython/gui_modules/gcpmanager.py 2010-09-27 19:32:44 UTC (rev 43715)
@@ -0,0 +1,2938 @@
+"""!
+ at package gcpmanager.py
+
+ at brief Georectification module for GRASS GIS. Includes ground control
+point management and interactive point and click GCP creation
+
+Classes:
+ - GCPWizard
+ - LocationPage
+ - GroupPage
+ - DispMapPage
+ - GCP
+ - GCPList
+ - VectGroup
+ - EditGCP
+ - GrSettingsDialog
+
+(C) 2006-2010 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 Markus Metz
+ at author Michael Barton
+ at author Updated by Martin Landa <landa.martin gmail.com>
+"""
+
+import os
+import sys
+import tempfile
+import shutil
+import time
+import cStringIO
+
+import wx
+from wx.lib.mixins.listctrl import CheckListCtrlMixin, ColumnSorterMixin, ListCtrlAutoWidthMixin
+import wx.lib.colourselect as csel
+import wx.wizard as wiz
+
+import grass.script as grass
+
+import globalvar
+import render
+import toolbars
+import menuform
+import gselect
+import gcmd
+import utils
+from debug import Debug as Debug
+from icon import Icons as Icons
+from location_wizard import TitledPage as TitledPage
+from preferences import globalSettings as UserSettings
+from gcpmapdisp import MapFrame
+from mapdisp import BufferedWindow
+
+try:
+ import subprocess # Not needed if GRASS commands could actually be quiet
+except:
+ CompatPath = globalvar.ETCWXDIR
+ sys.path.append(CompatPath)
+ from compat import subprocess
+
+gmpath = os.path.join(globalvar.ETCWXDIR, "icons")
+sys.path.append(gmpath)
+
+#
+# global variables
+#
+global src_map
+global tgt_map
+global maptype
+
+src_map = ''
+tgt_map = ''
+maptype = 'cell'
+
+def getSmallUpArrowData():
+ return \
+'\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\
+\x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\
+\x00\x00<IDAT8\x8dcddbf\xa0\x040Q\xa4{h\x18\xf0\xff\xdf\xdf\xffd\x1b\x00\xd3\
+\x8c\xcf\x10\x9c\x06\xa0k\xc2e\x08m\xc2\x00\x97m\xd8\xc41\x0c \x14h\xe8\xf2\
+\x8c\xa3)q\x10\x18\x00\x00R\xd8#\xec\xb2\xcd\xc1Y\x00\x00\x00\x00IEND\xaeB`\
+\x82'
+
+def getSmallUpArrowImage():
+ stream = cStringIO.StringIO(getSmallUpArrowData())
+ return wx.ImageFromStream(stream)
+
+def getSmallDnArrowData():
+ return \
+"\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\
+\x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\
+\x00\x00HIDAT8\x8dcddbf\xa0\x040Q\xa4{\xd4\x00\x06\x06\x06\x06\x06\x16t\x81\
+\xff\xff\xfe\xfe'\xa4\x89\x91\x89\x99\x11\xa7\x0b\x90%\ti\xc6j\x00>C\xb0\x89\
+\xd3.\x10\xd1m\xc3\xe5*\xbc.\x80i\xc2\x17.\x8c\xa3y\x81\x01\x00\xa1\x0e\x04e\
+?\x84B\xef\x00\x00\x00\x00IEND\xaeB`\x82"
+
+def getSmallDnArrowImage():
+ stream = cStringIO.StringIO(getSmallDnArrowData())
+ return wx.ImageFromStream(stream)
+
+class GCPWizard(object):
+ """
+ Start wizard here and finish wizard here
+ """
+
+ def __init__(self, parent):
+ self.parent = parent # GMFrame
+
+ #
+ # get environmental variables
+ #
+ self.grassdatabase = grass.gisenv()['GISDBASE']
+
+ #
+ # read original environment settings
+ #
+ self.target_gisrc = os.environ['GISRC']
+ self.gisrc_dict = {}
+ try:
+ f = open(self.target_gisrc, 'r')
+ for line in f.readlines():
+ line = line.replace('\n', '').strip()
+ if len(line) < 1:
+ continue
+ key, value = line.split(':', 1)
+ self.gisrc_dict[key.strip()] = value.strip()
+ finally:
+ f.close()
+
+ self.currentlocation = self.gisrc_dict['LOCATION_NAME']
+ self.currentmapset = self.gisrc_dict['MAPSET']
+ # location for xy map to georectify
+ self.newlocation = ''
+ # mapset for xy map to georectify
+ self.newmapset = ''
+
+ global maptype
+ global src_map
+ global tgt_map
+
+ src_map = ''
+ tgt_map = ''
+ maptype = 'cell'
+
+ # GISRC file for source location/mapset of map(s) to georectify
+ self.source_gisrc = ''
+ self.src_maps = []
+
+ #
+ # define wizard pages
+ #
+ self.wizard = wiz.Wizard(parent=parent, id=wx.ID_ANY, title=_("Setup for georectification"))
+ self.startpage = LocationPage(self.wizard, self)
+ self.grouppage = GroupPage(self.wizard, self)
+ self.mappage = DispMapPage(self.wizard, self)
+
+ #
+ # set the initial order of the pages
+ #
+ self.startpage.SetNext(self.grouppage)
+ self.grouppage.SetPrev(self.startpage)
+ self.grouppage.SetNext(self.mappage)
+ self.mappage.SetPrev(self.grouppage)
+
+ #
+ # do pages layout
+ #
+ self.startpage.DoLayout()
+ self.grouppage.DoLayout()
+ self.mappage.DoLayout()
+ self.wizard.FitToPage(self.startpage)
+
+ # self.Bind(wx.EVT_CLOSE, self.Cleanup)
+ # self.parent.Bind(wx.EVT_ACTIVATE, self.OnGLMFocus)
+
+ success = False
+
+ #
+ # run wizard
+ #
+ if self.wizard.RunWizard(self.startpage):
+ success = self.OnWizFinished()
+ if success == False:
+ wx.MessageBox(parent=self.parent,
+ message=_("Georectifying setup canceled."),
+ caption=_("Georectify"),
+ style=wx.OK | wx.ICON_INFORMATION | wx.CENTRE)
+ self.Cleanup()
+ else:
+ wx.MessageBox(parent=self.parent,
+ message=_("Georectifying setup canceled."),
+ caption=_("Georectify"),
+ style=wx.OK | wx.ICON_INFORMATION | wx.CENTRE)
+ self.Cleanup()
+
+ #
+ # start GCP display
+ #
+ if success != False:
+ # instance of render.Map to be associated with display
+ self.SwitchEnv('source')
+ self.SrcMap = render.Map(gisrc=self.source_gisrc)
+ self.SwitchEnv('target')
+ self.TgtMap = render.Map(gisrc=self.target_gisrc)
+ self.Map = self.SrcMap
+
+ #
+ # add layer to source map
+ #
+ if maptype == 'cell':
+ rendertype = 'raster'
+ cmdlist = ['d.rast', 'map=%s' % src_map]
+ else: # -> vector layer
+ rendertype = 'vector'
+ cmdlist = ['d.vect', 'map=%s' % src_map]
+
+ self.SwitchEnv('source')
+ self.SrcMap.AddLayer(type=rendertype, command=cmdlist, l_active=True,
+ name=utils.GetLayerNameFromCmd(cmdlist),
+ l_hidden=False, l_opacity=1.0, l_render=False)
+
+ if tgt_map:
+ #
+ # add layer to target map
+ #
+ if maptype == 'cell':
+ rendertype = 'raster'
+ cmdlist = ['d.rast', 'map=%s' % tgt_map]
+ else: # -> vector layer
+ rendertype = 'vector'
+ cmdlist = ['d.vect', 'map=%s' % tgt_map]
+
+ self.SwitchEnv('target')
+ self.TgtMap.AddLayer(type=rendertype, command=cmdlist, l_active=True,
+ name=utils.GetLayerNameFromCmd(cmdlist),
+ l_hidden=False, l_opacity=1.0, l_render=False)
+
+ #
+ # start GCP Manager
+ #
+ self.gcpmgr = GCP(self.parent, grwiz=self, size=globalvar.MAP_WINDOW_SIZE,
+ toolbars=["gcpdisp"],
+ Map=self.SrcMap, lmgr=self.parent)
+
+ # load GCPs
+ self.gcpmgr.InitMapDisplay()
+ self.gcpmgr.CenterOnScreen()
+ self.gcpmgr.Show()
+ # need to update AUI here for wingrass
+ self.gcpmgr._mgr.Update()
+ else:
+ self.Cleanup()
+
+ def SetSrcEnv(self, location, mapset):
+ """!Create environment to use for location and mapset
+ that are the source of the file(s) to georectify
+
+ @param location source location
+ @param mapset source mapset
+
+ @return False on error
+ @return True on success
+ """
+
+ self.newlocation = location
+ self.newmapset = mapset
+
+ # check to see if we are georectifying map in current working location/mapset
+ if self.newlocation == self.currentlocation and self.newmapset == self.currentmapset:
+ return False
+
+ self.gisrc_dict['LOCATION_NAME'] = location
+ self.gisrc_dict['MAPSET'] = mapset
+
+ self.source_gisrc = utils.GetTempfile()
+
+ try:
+ f = open(self.source_gisrc, mode='w')
+ for line in self.gisrc_dict.items():
+ f.write(line[0] + ": " + line[1] + "\n")
+ finally:
+ f.close()
+
+ return True
+
+ def SwitchEnv(self, grc):
+ """
+ Switches between original working location/mapset and
+ location/mapset that is source of file(s) to georectify
+ """
+ # check to see if we are georectifying map in current working location/mapset
+ if self.newlocation == self.currentlocation and self.newmapset == self.currentmapset:
+ return False
+
+ if grc == 'target':
+ os.environ["GISRC"] = str(self.target_gisrc)
+ gisrcfile = str(self.target_gisrc)
+ elif grc == 'source':
+ os.environ["GISRC"] = str(self.source_gisrc)
+ gisrcfile = str(self.source_gisrc)
+
+ # do it the hard way
+ gisrc_dict = {}
+ try:
+ f = open(gisrcfile, 'r')
+ for line in f.readlines():
+ line = line.replace('\n', '').strip()
+ if len(line) < 1:
+ continue
+ key, value = line.split(':', 1)
+ gisrc_dict[key.strip()] = value.strip()
+ finally:
+ f.close()
+
+ gcmd.RunCommand('g.gisenv', 'set=LOCATION_NAME=%s' % gisrc_dict['LOCATION_NAME'])
+ gcmd.RunCommand('g.gisenv', 'set=MAPSET=%s' % gisrc_dict['MAPSET'])
+
+ return True
+
+ def OnWizFinished(self):
+ # self.Cleanup()
+
+ return True
+
+ def OnGLMFocus(self, event):
+ """!Layer Manager focus"""
+ # self.SwitchEnv('target')
+
+ event.Skip()
+
+ def Cleanup(self):
+ """!Return to current location and mapset"""
+ self.SwitchEnv('target')
+ self.parent.gcpmanagement = None
+
+ self.wizard.Destroy()
+
+class LocationPage(TitledPage):
+ """
+ Set map type (raster or vector) to georectify and
+ select location/mapset of map(s) to georectify.
+ """
+ def __init__(self, wizard, parent):
+ TitledPage.__init__(self, wizard, _("Select map type and location/mapset"))
+
+ self.parent = parent
+ self.grassdatabase = self.parent.grassdatabase
+
+ self.xylocation = ''
+ self.xymapset = ''
+
+ tmplist = os.listdir(self.grassdatabase)
+ self.locList = []
+ self.mapsetList = []
+
+ #
+ # create a list of valid locations
+ #
+ for item in tmplist:
+ if os.path.isdir(os.path.join(self.grassdatabase, item)) and \
+ os.path.exists(os.path.join(self.grassdatabase, item, 'PERMANENT')):
+ self.locList.append(item)
+
+ utils.ListSortLower(self.locList)
+
+ #
+ # layout
+ #
+ self.sizer.AddGrowableCol(2)
+ # map type
+ self.rb_maptype = wx.RadioBox(parent=self, id=wx.ID_ANY,
+ label=' %s ' % _("Map type to georectify"),
+ choices=[_('raster'), _('vector')],
+ majorDimension=wx.RA_SPECIFY_COLS)
+ self.sizer.Add(item=self.rb_maptype,
+ flag=wx.ALIGN_CENTER | wx.ALL | wx.EXPAND, border=5,
+ pos=(1, 1), span=(1, 2))
+
+ # location
+ self.sizer.Add(item=wx.StaticText(parent=self, id=wx.ID_ANY, label=_('Select source location:')),
+ flag=wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL | wx.ALL, border=5,
+ pos=(2, 1))
+ self.cb_location = wx.ComboBox(parent=self, id=wx.ID_ANY,
+ choices = self.locList, size=(300, -1),
+ style=wx.CB_DROPDOWN | wx.CB_READONLY)
+ self.sizer.Add(item=self.cb_location,
+ flag=wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL | wx.ALL, border=5,
+ pos=(2, 2))
+
+ # mapset
+ self.sizer.Add(item=wx.StaticText(parent=self, id=wx.ID_ANY, label=_('Select source mapset:')),
+ flag=wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL | wx.ALL, border=5,
+ pos=(3, 1))
+ self.cb_mapset = wx.ComboBox(parent=self, id=wx.ID_ANY,
+ choices = self.mapsetList, size=(300, -1),
+ style=wx.CB_DROPDOWN | wx.CB_READONLY)
+ self.sizer.Add(item=self.cb_mapset,
+ flag=wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL | wx.ALL, border=5,
+ pos=(3,2))
+
+ #
+ # bindings
+ #
+ self.Bind(wx.EVT_RADIOBOX, self.OnMaptype, self.rb_maptype)
+ self.Bind(wx.EVT_COMBOBOX, self.OnLocation, self.cb_location)
+ self.Bind(wx.EVT_COMBOBOX, self.OnMapset, self.cb_mapset)
+ self.Bind(wiz.EVT_WIZARD_PAGE_CHANGING, self.OnPageChanging)
+ self.Bind(wiz.EVT_WIZARD_PAGE_CHANGED, self.OnEnterPage)
+ # self.Bind(wx.EVT_CLOSE, self.parent.Cleanup)
+
+ def OnMaptype(self,event):
+ """!Change map type"""
+ global maptype
+
+ if event.GetInt() == 0:
+ maptype = 'cell'
+ else:
+ maptype = 'vector'
+
+ def OnLocation(self, event):
+ """!Sets source location for map(s) to georectify"""
+ self.xylocation = event.GetString()
+
+ #create a list of valid mapsets
+ tmplist = os.listdir(os.path.join(self.grassdatabase, self.xylocation))
+ self.mapsetList = []
+ for item in tmplist:
+ if os.path.isdir(os.path.join(self.grassdatabase, self.xylocation, item)) and \
+ os.path.exists(os.path.join(self.grassdatabase, self.xylocation, item, 'WIND')):
+ if item != 'PERMANENT':
+ self.mapsetList.append(item)
+
+ self.xymapset = 'PERMANENT'
+ utils.ListSortLower(self.mapsetList)
+ self.mapsetList.insert(0, 'PERMANENT')
+ self.cb_mapset.SetItems(self.mapsetList)
+ self.cb_mapset.SetStringSelection(self.xymapset)
+
+ if not wx.FindWindowById(wx.ID_FORWARD).IsEnabled():
+ wx.FindWindowById(wx.ID_FORWARD).Enable(True)
+
+ def OnMapset(self, event):
+ """!Sets source mapset for map(s) to georectify"""
+ if self.xylocation == '':
+ wx.MessageBox(_('You must select a valid location before selecting a mapset'))
+ return
+
+ self.xymapset = event.GetString()
+
+ if not wx.FindWindowById(wx.ID_FORWARD).IsEnabled():
+ wx.FindWindowById(wx.ID_FORWARD).Enable(True)
+
+ def OnPageChanging(self, event=None):
+ if event.GetDirection() and \
+ (self.xylocation == '' or self.xymapset == ''):
+ wx.MessageBox(_('You must select a valid location and mapset in order to continue'))
+ event.Veto()
+ return
+
+ self.parent.SetSrcEnv(self.xylocation, self.xymapset)
+
+ def OnEnterPage(self, event=None):
+ if self.xylocation == '' or self.xymapset == '':
+ wx.FindWindowById(wx.ID_FORWARD).Enable(False)
+ else:
+ wx.FindWindowById(wx.ID_FORWARD).Enable(True)
+
+class GroupPage(TitledPage):
+ """
+ Set group to georectify. Create group if desired.
+ """
+ def __init__(self, wizard, parent):
+ TitledPage.__init__(self, wizard, _("Select image/map group to georectify"))
+
+ self.parent = parent
+
+ self.grassdatabase = self.parent.grassdatabase
+ self.groupList = []
+
+ self.xylocation = ''
+ self.xymapset = ''
+ self.xygroup = ''
+
+ # default extension
+ self.extension = 'georect' + str(os.getpid())
+
+ #
+ # layout
+ #
+ self.sizer.AddGrowableCol(2)
+ # group
+ self.sizer.Add(item=wx.StaticText(parent=self, id=wx.ID_ANY, label=_('Select group:')),
+ flag=wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL | wx.ALL, border=5,
+ pos=(1, 1))
+ self.cb_group = wx.ComboBox(parent=self, id=wx.ID_ANY,
+ choices=self.groupList, size=(350, -1),
+ style=wx.CB_DROPDOWN | wx.CB_READONLY)
+ self.sizer.Add(item=self.cb_group,
+ flag=wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL | wx.ALL, border=5,
+ pos=(1, 2))
+
+ # create group
+ self.sizer.Add(item=wx.StaticText(parent=self, id=wx.ID_ANY, label=_('Create group if none exists')),
+ flag=wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL | wx.ALL, border=5,
+ pos=(2, 1))
+ btnSizer = wx.BoxSizer(wx.HORIZONTAL)
+ self.btn_mkgroup = wx.Button(parent=self, id=wx.ID_ANY, label=_("Create/edit group..."))
+ self.btn_vgroup = wx.Button(parent=self, id=wx.ID_ANY, label=_("Add vector map to group..."))
+ btnSizer.Add(item=self.btn_mkgroup,
+ flag=wx.RIGHT, border=5)
+
+ btnSizer.Add(item=self.btn_vgroup,
+ flag=wx.LEFT, border=5)
+
+ self.sizer.Add(item=btnSizer,
+ flag=wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL | wx.ALL, border=5,
+ pos=(2, 2))
+
+ # extension
+ self.sizer.Add(item=wx.StaticText(parent=self, id=wx.ID_ANY, label=_('Extension for output maps:')),
+ flag=wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL | wx.ALL, border=5,
+ pos=(3, 1))
+ self.ext_txt = wx.TextCtrl(parent=self, id=wx.ID_ANY, value="", size=(350,-1))
+ self.ext_txt.SetValue(self.extension)
+ self.sizer.Add(item=self.ext_txt,
+ flag=wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL | wx.ALL, border=5,
+ pos=(3, 2))
+
+ #
+ # bindings
+ #
+ self.Bind(wx.EVT_COMBOBOX, self.OnGroup, self.cb_group)
+ self.Bind(wx.EVT_TEXT, self.OnExtension, self.ext_txt)
+ self.Bind(wiz.EVT_WIZARD_PAGE_CHANGING, self.OnPageChanging)
+ self.Bind(wiz.EVT_WIZARD_PAGE_CHANGED, self.OnEnterPage)
+ self.Bind(wx.EVT_CLOSE, self.parent.Cleanup)
+
+ # hide vector group button by default
+ self.btn_vgroup.Hide()
+
+ def OnGroup(self, event):
+ self.xygroup = event.GetString()
+
+ def OnMkGroup(self, event):
+ """!Create new group in source location/mapset"""
+ menuform.GUI().ParseCommand(['i.group'],
+ completed=(self.GetOptData, None, ''),
+ parentframe=self.parent.parent, modal=True)
+
+ def OnVGroup(self, event):
+ """!Add vector maps to group"""
+ dlg = VectGroup(parent = self,
+ id = wx.ID_ANY,
+ grassdb = self.grassdatabase,
+ location = self.xylocation,
+ mapset = self.xymapset,
+ group = self.xygroup)
+
+ if dlg.ShowModal() != wx.ID_OK:
+ return
+
+ dlg.MakeVGroup()
+ self.OnEnterPage()
+
+ def GetOptData(self, dcmd, layer, params, propwin):
+ """!Process i.group"""
+ # update the page
+ if dcmd:
+ gcmd.Command(dcmd)
+
+ self.OnEnterPage()
+ self.Update()
+
+ def OnExtension(self, event):
+ self.extension = event.GetString()
+
+ def OnPageChanging(self, event=None):
+ if event.GetDirection() and self.xygroup == '':
+ wx.MessageBox(_('You must select a valid image/map group in order to continue'))
+ event.Veto()
+ return
+
+ if event.GetDirection() and self.extension == '':
+ wx.MessageBox(_('You must enter an map name extension in order to continue'))
+ event.Veto()
+ return
+
+ def OnEnterPage(self, event=None):
+ global maptype
+
+ self.groupList = []
+
+ self.xylocation = self.parent.gisrc_dict['LOCATION_NAME']
+ self.xymapset = self.parent.gisrc_dict['MAPSET']
+
+ # create a list of groups in selected mapset
+ if os.path.isdir(os.path.join(self.grassdatabase,
+ self.xylocation,
+ self.xymapset,
+ 'group')):
+ tmplist = os.listdir(os.path.join(self.grassdatabase,
+ self.xylocation,
+ self.xymapset,
+ 'group'))
+ for item in tmplist:
+ if os.path.isdir(os.path.join(self.grassdatabase,
+ self.xylocation,
+ self.xymapset,
+ 'group',
+ item)):
+ self.groupList.append(item)
+
+ if maptype == 'cell':
+ self.btn_vgroup.Hide()
+ self.Bind(wx.EVT_BUTTON, self.OnMkGroup, self.btn_mkgroup)
+
+ elif maptype == 'vector':
+ self.btn_vgroup.Show()
+ self.Bind(wx.EVT_BUTTON, self.OnMkGroup, self.btn_mkgroup)
+ self.Bind(wx.EVT_BUTTON, self.OnVGroup, self.btn_vgroup)
+
+ utils.ListSortLower(self.groupList)
+ self.cb_group.SetItems(self.groupList)
+
+ if len(self.groupList) > 0 and \
+ self.xygroup == '':
+ self.cb_group.SetSelection(0)
+ self.xygroup = self.groupList[0]
+
+ if self.xygroup == '' or \
+ self.extension == '':
+ wx.FindWindowById(wx.ID_FORWARD).Enable(False)
+ else:
+ wx.FindWindowById(wx.ID_FORWARD).Enable(True)
+
+ # switch to source
+ self.parent.SwitchEnv('source')
+
+class DispMapPage(TitledPage):
+ """
+ Select ungeoreferenced map to display for interactively
+ setting ground control points (GCPs).
+ """
+ def __init__(self, wizard, parent):
+ TitledPage.__init__(self, wizard,
+ _("Select maps to display for ground control point (GCP) creation"))
+
+ self.parent = parent
+ global maptype
+
+ #
+ # layout
+ #
+ self.sizer.Add(item=wx.StaticText(parent=self, id=wx.ID_ANY, label=_('Select source map to display:')),
+ flag=wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL | wx.ALL, border=5,
+ pos=(1, 1))
+
+ self.srcselection = gselect.Select(self, id=wx.ID_ANY,
+ size=globalvar.DIALOG_GSELECT_SIZE, type=maptype, updateOnPopup = False)
+
+ self.sizer.Add(item=self.srcselection,
+ flag=wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL | wx.ALL, border=5,
+ pos=(1, 2))
+
+ self.sizer.Add(item=wx.StaticText(parent=self, id=wx.ID_ANY, label=_('Select target map to display:')),
+ flag=wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL | wx.ALL, border=5,
+ pos=(2, 1))
+
+ self.tgtselection = gselect.Select(self, id=wx.ID_ANY,
+ size=globalvar.DIALOG_GSELECT_SIZE, type=maptype, updateOnPopup = False)
+
+ self.sizer.Add(item=self.tgtselection,
+ flag=wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL | wx.ALL, border=5,
+ pos=(2, 2))
+
+ #
+ # bindings
+ #
+ self.srcselection.Bind(wx.EVT_TEXT, self.OnSrcSelection)
+ self.tgtselection.Bind(wx.EVT_TEXT, self.OnTgtSelection)
+ self.Bind(wiz.EVT_WIZARD_PAGE_CHANGING, self.OnPageChanging)
+ self.Bind(wiz.EVT_WIZARD_PAGE_CHANGED, self.OnEnterPage)
+ self.Bind(wx.EVT_CLOSE, self.parent.Cleanup)
+
+ def OnSrcSelection(self,event):
+ """!Source map to display selected"""
+ global src_map
+ global maptype
+
+ src_map = event.GetString()
+
+ if src_map == '':
+ wx.FindWindowById(wx.ID_FORWARD).Enable(False)
+ else:
+ wx.FindWindowById(wx.ID_FORWARD).Enable(True)
+
+ try:
+ # set computational region to match selected map and zoom display to region
+ if maptype == 'cell':
+ p = gcmd.Command(['g.region', 'rast=src_map'])
+ elif maptype == 'vector':
+ p = gcmd.Command(['g.region', 'vect=src_map'])
+
+ if p.returncode == 0:
+ print 'returncode = ', str(p.returncode)
+ self.parent.Map.region = self.parent.Map.GetRegion()
+ except:
+ pass
+
+ def OnTgtSelection(self,event):
+ """!Source map to display selected"""
+ global tgt_map
+
+ tgt_map = event.GetString()
+
+ def OnPageChanging(self, event=None):
+ global src_map
+ global tgt_map
+
+ if event.GetDirection() and (src_map == ''):
+ wx.MessageBox(_('You must select a source map in order to continue'))
+ event.Veto()
+ return
+
+ self.parent.SwitchEnv('target')
+
+ def OnEnterPage(self, event=None):
+ global maptype
+ global src_map
+ global tgt_map
+
+ self.srcselection.SetElementList(maptype)
+ ret = gcmd.RunCommand('i.group',
+ parent = self,
+ read = True,
+ group = self.parent.grouppage.xygroup,
+ flags = 'g')
+
+ if ret:
+ self.parent.src_maps = ret.splitlines()
+ else:
+ wx.MessageBox(parent=self,
+ caption=_("Select maps to display"),
+ message=_('No maps in selected group <%s>. \n'
+ 'Please edit group or select another group.') %
+ self.parent.grouppage.xygroup,
+ style=wx.ICON_ERROR | wx.ID_OK | wx.CENTRE)
+ return
+
+ # filter out all maps not in group
+ # not available in 64
+ #self.srcselection.tcp.GetElementList(elements = self.parent.src_maps)
+ # modified from gselect
+ self.srcselection.tcp.seltree.DeleteAllItems()
+ # get current mapset
+ curr_mapset = grass.gisenv()['MAPSET']
+ mapsets = utils.ListOfMapsets()
+ for i in range(len(mapsets)):
+ if i > 0 and mapsets[i] == curr_mapset:
+ mapsets[i] = mapsets[0]
+ mapsets[0] = curr_mapset
+
+ elementdict = {'cell':'rast',
+ 'raster':'rast',
+ 'rast':'rast',
+ 'raster files':'rast',
+ 'vector':'vect',
+ 'vect':'vect'
+ }
+ if globalvar.have_mlist:
+ filesdict = grass.mlist_grouped(elementdict[maptype])
+ else:
+ filesdict = grass.list_grouped(elementdict[maptype])
+
+ first_dir = None
+ for dir in mapsets:
+ dir_node = self.srcselection.tcp.AddItem('Mapset: ' + dir)
+ if not first_dir:
+ first_dir = dir_node
+
+ self.srcselection.tcp.seltree.SetItemTextColour(dir_node, wx.Colour(50, 50, 200))
+ try:
+ elem_list = filesdict[dir]
+ elem_list.sort(key=str.lower)
+ for elem in elem_list:
+ if elem != '':
+ fullqElem = elem + '@' + dir
+ if fullqElem in self.parent.src_maps:
+ self.srcselection.tcp.AddItem(fullqElem, parent=dir_node)
+ except:
+ continue
+
+ if self.srcselection.tcp.seltree.ItemHasChildren(dir_node):
+ sel = UserSettings.Get(group='general', key='elementListExpand',
+ subkey='selection')
+ collapse = True
+
+ if sel == 0: # collapse all except PERMANENT and current
+ if dir in ('PERMANENT', curr_mapset):
+ collapse = False
+ elif sel == 1: # collapse all except PERMANENT
+ if dir == 'PERMANENT':
+ collapse = False
+ elif sel == 2: # collapse all except current
+ if dir == curr_mapset:
+ collapse = False
+ elif sel == 3: # collapse all
+ pass
+ elif sel == 4: # expand all
+ collapse = False
+
+ if collapse:
+ self.srcselection.tcp.seltree.Collapse(dir_node)
+ else:
+ self.srcselection.tcp.seltree.Expand(dir_node)
+
+ if first_dir:
+ # select first mapset (MSW hack)
+ self.srcselection.tcp.seltree.SelectItem(first_dir)
+
+ # end copy from gselect
+ src_map = self.parent.src_maps[0]
+ self.srcselection.SetValue(src_map)
+
+ self.parent.SwitchEnv('target')
+ self.tgtselection.SetElementList(maptype)
+ #self.tgtselection.GetElementList()
+ self.parent.SwitchEnv('source')
+
+ if src_map == '':
+ wx.FindWindowById(wx.ID_FORWARD).Enable(False)
+ else:
+ wx.FindWindowById(wx.ID_FORWARD).Enable(True)
+
+class GCP(MapFrame, wx.Frame, ColumnSorterMixin):
+ """!
+ Manages ground control points for georectifying. Calculates RMS statics.
+ Calls i.rectify or v.transform to georectify map.
+ """
+ def __init__(self, parent, grwiz = None, id = wx.ID_ANY,
+ title = _("Manage Ground Control Points"),
+ size = (700, 300), toolbars=["gcpdisp"], Map=None, lmgr=None):
+
+ self.grwiz = grwiz # GR Wizard
+
+ if tgt_map == '':
+ self.show_target = False
+ else:
+ self.show_target = True
+
+ #wx.Frame.__init__(self, parent, id, title, size = size, name = "GCPFrame")
+ MapFrame.__init__(self, parent, id, title, size = size,
+ Map=Map, toolbars=["gcpdisp"], lmgr=lmgr, name='GCPMapWindow')
+
+ #
+ # init variables
+ #
+ self.parent = parent # GMFrame
+ self.parent.gcpmanagement = self
+
+ self.grassdatabase = self.grwiz.grassdatabase
+
+ self.currentlocation = self.grwiz.currentlocation
+ self.currentmapset = self.grwiz.currentmapset
+
+ self.newlocation = self.grwiz.newlocation
+ self.newmapset = self.grwiz.newmapset
+
+ self.xylocation = self.grwiz.gisrc_dict['LOCATION_NAME']
+ self.xymapset = self.grwiz.gisrc_dict['MAPSET']
+ self.xygroup = self.grwiz.grouppage.xygroup
+ self.src_maps = self.grwiz.src_maps
+ self.extension = self.grwiz.grouppage.extension
+ self.outname = ''
+ self.VectGRList = []
+
+ self.file = {
+ 'points' : os.path.join(self.grassdatabase,
+ self.xylocation,
+ self.xymapset,
+ 'group',
+ self.xygroup,
+ 'POINTS'),
+ 'points_bak' : os.path.join(self.grassdatabase,
+ self.xylocation,
+ self.xymapset,
+ 'group',
+ self.xygroup,
+ 'POINTS_BAK'),
+ 'rgrp' : os.path.join(self.grassdatabase,
+ self.xylocation,
+ self.xymapset,
+ 'group',
+ self.xygroup,
+ 'REF'),
+ 'vgrp' : os.path.join(self.grassdatabase,
+ self.xylocation,
+ self.xymapset,
+ 'group',
+ self.xygroup,
+ 'VREF'),
+ 'target' : os.path.join(self.grassdatabase,
+ self.xylocation,
+ self.xymapset,
+ 'group',
+ self.xygroup,
+ 'TARGET'),
+ }
+
+ # make a backup of the current points file
+ if os.path.exists(self.file['points']):
+ shutil.copy(self.file['points'], self.file['points_bak'])
+
+ # polynomial order transformation for georectification
+ self.gr_order = 1
+ # region clipping for georectified map
+ self.clip_to_region = False
+ # number of GCPs selected to be used for georectification (checked)
+ self.GCPcount = 0
+ # forward RMS error
+ self.fwd_rmserror = 0.0
+ # backward RMS error
+ self.bkw_rmserror = 0.0
+ # list map coords and ID of map display they came from
+ self.mapcoordlist = []
+ self.mapcoordlist.append([ 0, # GCP number
+ 0.0, # source east
+ 0.0, # source north
+ 0.0, # target east
+ 0.0, # target north
+ 0.0, # forward error
+ 0.0 ] ) # backward error
+
+ # init vars to highlight high RMS errors
+ self.highest_only = True
+ self.show_unused = True
+ self.highest_key = -1
+ self.rmsthresh = 0
+ self.rmsmean = 0
+ self.rmssd = 0
+
+ self.SetTarget(self.xygroup, self.currentlocation, self.currentmapset)
+
+ self.itemDataMap = None
+
+ # images for column sorting
+ # CheckListCtrlMixin must set an ImageList first
+ self.il = self.list.GetImageList(wx.IMAGE_LIST_SMALL)
+
+ use_art_provider = False
+ if use_art_provider:
+ i_size = wx.Size(12, 12)
+ SmallUpArrow = wx.ArtProvider.GetBitmap(id=wx.ART_GO_UP,
+ client=wx.ART_FRAME_ICON, size=i_size)
+ SmallDnArrow = wx.ArtProvider.GetBitmap(id=wx.ART_GO_DOWN,
+ client=wx.ART_FRAME_ICON, size=i_size)
+ else:
+ SmallUpArrow = wx.BitmapFromImage(getSmallUpArrowImage())
+ SmallDnArrow = wx.BitmapFromImage(getSmallDnArrowImage())
+ self.sm_dn = self.il.Add(SmallDnArrow)
+ self.sm_up = self.il.Add(SmallUpArrow)
+
+ # set mouse characteristics
+ self.mapwin = self.SrcMapWindow
+ self.mapwin.mouse['box'] = 'point'
+ self.mapwin.mouse["use"] == "pointer"
+ self.mapwin.zoomtype = 0
+ self.mapwin.pen = wx.Pen(colour='black', width=2, style=wx.SOLID)
+ self.mapwin.SetCursor(self.cursors["cross"])
+
+ self.mapwin = self.TgtMapWindow
+
+ # set mouse characteristics
+ self.mapwin.mouse['box'] = 'point'
+ self.mapwin.mouse["use"] == "pointer"
+ self.mapwin.zoomtype = 0
+ self.mapwin.pen = wx.Pen(colour='black', width=2, style=wx.SOLID)
+ self.mapwin.SetCursor(self.cursors["cross"])
+
+ #
+ # show new display & draw map
+ #
+ self.MapWindow = self.TgtMapWindow
+ self.Map = self.TgtMap
+ self.OnZoomToMap(None)
+ self.MapWindow = self.SrcMapWindow
+ self.Map = self.SrcMap
+ self.OnZoomToMap(None)
+
+ #
+ # bindings
+ #
+ self.Bind(wx.EVT_ACTIVATE, self.OnFocus)
+ self.Bind(wx.EVT_CLOSE, self.OnQuit)
+
+ def __del__(self):
+ """!Disable GCP manager mode"""
+ self.parent.gcpmanagement = None
+
+ def CreateGCPList(self):
+ """!Create GCP List Control"""
+
+ return GCPList(parent=self, gcp=self)
+
+ # Used by the ColumnSorterMixin, see wx/lib/mixins/listctrl.py
+ def GetListCtrl(self):
+ return self.list
+
+ # Used by the ColumnSorterMixin, see wx/lib/mixins/listctrl.py
+ def GetSortImages(self):
+ return (self.sm_dn, self.sm_up)
+
+ def InitMapDisplay(self):
+ self.list.LoadData()
+
+ # initialize column sorter
+ self.itemDataMap = self.mapcoordlist
+ ncols = self.list.GetColumnCount()
+ ColumnSorterMixin.__init__(self, ncols)
+ # init to ascending sort on first click
+ self._colSortFlag = [1] * ncols
+
+ def SetTarget(self, tgroup, tlocation, tmapset):
+ """
+ Sets rectification target to current location and mapset
+ """
+ # check to see if we are georectifying map in current working location/mapset
+ if self.newlocation == self.currentlocation and self.newmapset == self.currentmapset:
+ gcmd.RunCommand('i.target',
+ parent = self,
+ flags = 'c',
+ group = tgroup)
+ else:
+ self.grwiz.SwitchEnv('source')
+ gcmd.RunCommand('i.target',
+ parent = self,
+ group = tgroup,
+ location = tlocation,
+ mapset = tmapset)
+ self.grwiz.SwitchEnv('target')
+
+ def AddGCP(self, event):
+ """
+ Appends an item to GCP list
+ """
+ keyval = self.list.AddGCPItem() + 1
+ # source east, source north, target east, target north, forward error, backward error
+ self.mapcoordlist.append([ keyval, # GCP number
+ 0.0, # source east
+ 0.0, # source north
+ 0.0, # target east
+ 0.0, # target north
+ 0.0, # forward error
+ 0.0 ] ) # backward error
+
+ if self.toggleStatus.GetSelection() == 7: # go to
+ self.StatusbarUpdate()
+
+ def DeleteGCP(self, event):
+ """
+ Deletes selected item in GCP list
+ """
+ minNumOfItems = self.OnGROrder(None)
+
+ if self.list.GetItemCount() <= minNumOfItems:
+ wx.MessageBox(parent=self, message=_("At least %d GCPs required. Operation cancelled.") % minNumOfItems,
+ caption=_("Delete GCP"), style=wx.OK | wx.ICON_INFORMATION)
+ return
+
+ key = self.list.DeleteGCPItem()
+ del self.mapcoordlist[key]
+
+ # update key and GCP number
+ for newkey in range(key, len(self.mapcoordlist)):
+ index = self.list.FindItemData(-1, newkey + 1)
+ self.mapcoordlist[newkey][0] = newkey
+ self.list.SetStringItem(index, 0, str(newkey))
+ self.list.SetItemData(index, newkey)
+
+ # update selected
+ if self.list.GetItemCount() > 0:
+ if self.list.selected < self.list.GetItemCount():
+ self.list.selectedkey = self.list.GetItemData(self.list.selected)
+ else:
+ self.list.selected = self.list.GetItemCount() - 1
+ self.list.selectedkey = self.list.GetItemData(self.list.selected)
+
+ self.list.SetItemState(self.list.selected,
+ wx.LIST_STATE_SELECTED,
+ wx.LIST_STATE_SELECTED)
+ else:
+ self.list.selected = wx.NOT_FOUND
+ self.list.selectedkey = -1
+
+ self.UpdateColours()
+
+ if self.toggleStatus.GetSelection() == 7: # go to
+ self.StatusbarUpdate()
+ if self.list.selectedkey > 0:
+ self.gotogcp.SetValue(self.list.selectedkey)
+ #self.gotogcp.SetValue(0)
+
+ def ClearGCP(self, event):
+ """
+ Clears all values in selected item of GCP list and unchecks it
+ """
+ index = self.list.GetSelected()
+
+ for i in range(4):
+ self.list.SetStringItem(index, i, '0.0')
+ self.list.SetStringItem(index, 4, '')
+ self.list.SetStringItem(index, 5, '')
+ self.list.CheckItem(index, False)
+ key = self.list.GetItemData(index)
+
+ # GCP number, source E, source N, target E, target N, fwd error, bkwd error
+ self.mapcoordlist[key] = [key, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]
+
+ def DrawGCP(self, coordtype):
+ """
+ Updates GCP and map coord maps and redraws
+ active (checked) GCP markers
+ """
+ self.highest_only = UserSettings.Get(group='gcpman', key='rms', subkey='highestonly')
+
+ self.show_unused = UserSettings.Get(group='gcpman', key='symbol', subkey='unused')
+ col = UserSettings.Get(group='gcpman', key='symbol', subkey='color')
+ wxLowCol = wx.Colour(col[0], col[1], col[2], 255)
+ col = UserSettings.Get(group='gcpman', key='symbol', subkey='hcolor')
+ wxHiCol = wx.Colour(col[0], col[1], col[2], 255)
+ col = UserSettings.Get(group='gcpman', key='symbol', subkey='scolor')
+ wxSelCol = wx.Colour(col[0], col[1], col[2], 255)
+ col = UserSettings.Get(group='gcpman', key='symbol', subkey='ucolor')
+ wxUnCol = wx.Colour(col[0], col[1], col[2], 255)
+ spx = UserSettings.Get(group='gcpman', key='symbol', subkey='size')
+ wpx = UserSettings.Get(group='gcpman', key='symbol', subkey='width')
+ font = self.GetFont()
+ font.SetPointSize(int(spx) + 2)
+
+ penOrig = polypenOrig = None
+
+ mapWin = None
+
+ if coordtype == 'source':
+ mapWin = self.SrcMapWindow
+ e_idx = 1
+ n_idx = 2
+ elif coordtype == 'target':
+ mapWin = self.TgtMapWindow
+ e_idx = 3
+ n_idx = 4
+
+ if not mapWin:
+ wx.MessageBox(parent=self,
+ message="%s%s." % (_("mapwin not defined for "),
+ str(idx)),
+ caption=_("Error"), style=wx.OK | wx.ICON_ERROR | wx.CENTRE)
+ return
+
+ #for gcp in self.mapcoordlist:
+ for idx in range(self.list.GetItemCount()):
+
+ key = self.list.GetItemData(idx)
+ gcp = self.mapcoordlist[key]
+
+ if not self.list.IsChecked(idx):
+ if self.show_unused:
+ wxCol = wxUnCol
+ else:
+ continue
+ else:
+ if self.highest_only == True:
+ if key == self.highest_key:
+ wxCol = wxHiCol
+ else:
+ wxCol = wxLowCol
+ elif self.rmsthresh > 0:
+ if (gcp[5] > self.rmsthresh):
+ wxCol = wxHiCol
+ else:
+ wxCol = wxLowCol
+
+ if idx == self.list.selected:
+ wxCol = wxSelCol
+
+ if not penOrig:
+ penOrig = mapWin.pen
+ polypenOrig = mapWin.polypen
+ mapWin.pen = wx.Pen(colour=wxCol, width=wpx, style=wx.SOLID)
+ mapWin.polypen = wx.Pen(colour=wxCol, width=wpx, style=wx.SOLID) # ?
+
+ mapWin.pen.SetColour(wxCol)
+ mapWin.polypen.SetColour(wxCol)
+
+ coord = mapWin.Cell2Pixel((gcp[e_idx], gcp[n_idx]))
+ mapWin.DrawCross(pdc=mapWin.pdcTmp, coords=coord,
+ size=spx, text={ 'text' : '%s' % str(gcp[0]),
+ 'active' : True,
+ 'font' : font,
+ 'color': wxCol,
+ 'coords': [coord[0] + 5,
+ coord[1] + 5,
+ 5,
+ 5]})
+
+ if penOrig:
+ mapWin.pen = penOrig
+ mapWin.polypen = polypenOrig
+
+ def SetGCPData(self, coordtype, coord, mapdisp=None, confirm=False):
+ """
+ Inserts coordinates from file, mouse click on map, or after editing
+ into selected item of GCP list and checks it for use
+ """
+
+ index = self.list.GetSelected()
+ if index == wx.NOT_FOUND:
+ return
+
+ coord0 = coord[0]
+ coord1 = coord[1]
+
+ key = self.list.GetItemData(index)
+ if confirm:
+ if self.MapWindow == self.SrcMapWindow:
+ currloc = _("source")
+ else:
+ currloc = _("target")
+ ret = wx.MessageBox(parent=self,
+ caption=_("Set GCP coordinates"),
+ message=_('Set %s coordinates for GCP No. %s? \n\n'
+ 'East: %s \n'
+ 'North: %s') % (currloc, str(key), str(coord0), str(coord1)),
+ style=wx.ICON_QUESTION | wx.YES_NO | wx.CENTRE)
+
+ # for wingrass
+ if os.name == 'nt':
+ self.MapWindow.SetFocus()
+ if ret == wx.NO:
+ return
+
+ if coordtype == 'source':
+ self.list.SetStringItem(index, 1, str(coord0))
+ self.list.SetStringItem(index, 2, str(coord1))
+ self.mapcoordlist[key][1] = coord[0]
+ self.mapcoordlist[key][2] = coord[1]
+ elif coordtype == 'target':
+ self.list.SetStringItem(index, 3, str(coord0))
+ self.list.SetStringItem(index, 4, str(coord1))
+ self.mapcoordlist[key][3] = coord[0]
+ self.mapcoordlist[key][4] = coord[1]
+
+ self.list.SetStringItem(index, 5, '0')
+ self.list.SetStringItem(index, 6, '0')
+ self.mapcoordlist[key][5] = 0.0
+ self.mapcoordlist[key][6] = 0.0
+
+ # self.list.ResizeColumns()
+
+ def SaveGCPs(self, event):
+ """
+ Make a POINTS file or save GCP coordinates to existing POINTS file
+ """
+
+ self.GCPcount = 0
+ try:
+ f = open(self.file['points'], mode='w')
+ # use os.linesep or '\n' here ???
+ f.write('# Ground Control Points File\n')
+ f.write("# \n")
+ f.write("# target location: " + self.currentlocation + '\n')
+ f.write("# target mapset: " + self.currentmapset + '\n')
+ f.write("#\tsource\t\ttarget\t\tstatus\n")
+ f.write("#\teast\tnorth\teast\tnorth\t(1=ok, 0=ignore)\n")
+ f.write("#----------------------- ----------------------- ---------------\n")
+
+ for index in range(self.list.GetItemCount()):
+ if self.list.IsChecked(index) == True:
+ check = "1"
+ self.GCPcount += 1
+ else:
+ check = "0"
+ coord0 = self.list.GetItem(index, 1).GetText()
+ coord1 = self.list.GetItem(index, 2).GetText()
+ coord2 = self.list.GetItem(index, 3).GetText()
+ coord3 = self.list.GetItem(index, 4).GetText()
+ f.write(coord0 + ' ' + coord1 + ' ' + coord2 + ' ' + coord3 + ' ' + check + '\n')
+
+ except IOError, err:
+ wx.MessageBox(parent=self,
+ message="%s <%s>. %s%s" % (_("Writing POINTS file failed"),
+ self.file['points'], os.linesep, err),
+ caption=_("Error"), style=wx.OK | wx.ICON_ERROR | wx.CENTRE)
+ return
+
+ f.close()
+
+ # if event != None save also to backup file
+ if event:
+ shutil.copy(self.file['points'], self.file['points_bak'])
+ self.parent.goutput.WriteLog(_('POINTS file saved for group <%s>') % self.xygroup)
+ #self.SetStatusText(_('POINTS file saved'))
+
+ def ReadGCPs(self):
+ """
+ Reads GCPs and georectified coordinates from POINTS file
+ """
+
+ self.GCPcount = 0
+
+ sourceMapWin = self.SrcMapWindow
+ targetMapWin = self.TgtMapWindow
+ #targetMapWin = self.parent.curr_page.maptree.mapdisplay.MapWindow
+
+ if not sourceMapWin:
+ wx.MessageBox(parent=self,
+ message="%s. %s%s" % (_("source mapwin not defined"),
+ os.linesep, err),
+ caption=_("Error"), style=wx.OK | wx.ICON_ERROR | wx.CENTRE)
+
+ if not targetMapWin:
+ wx.MessageBox(parent=self,
+ message="%s. %s%s" % (_("target mapwin not defined"),
+ os.linesep, err),
+ caption=_("Error"), style=wx.OK | wx.ICON_ERROR | wx.CENTRE)
+
+ try:
+ f = open(self.file['points'], 'r')
+ GCPcnt = 0
+
+ for line in f.readlines():
+ if line[0] == '#' or line =='':
+ continue
+ line = line.replace('\n', '').strip()
+ coords = map(float, line.split())
+ if coords[4] == 1:
+ check = True
+ self.GCPcount +=1
+ else:
+ check = False
+
+ self.AddGCP(event=None)
+ self.SetGCPData('source', (coords[0], coords[1]), sourceMapWin)
+ self.SetGCPData('target', (coords[2], coords[3]), targetMapWin)
+ index = self.list.GetSelected()
+ if index != wx.NOT_FOUND:
+ self.list.CheckItem(index, check)
+ GCPcnt += 1
+
+ except IOError, err:
+ wx.MessageBox(parent=self,
+ message="%s <%s>. %s%s" % (_("Reading POINTS file failed"),
+ self.file['points'], os.linesep, err),
+ caption=_("Error"), style=wx.OK | wx.ICON_ERROR | wx.CENTRE)
+ return
+
+ f.close()
+
+ if GCPcnt == 0:
+ # 3 gcp is minimum
+ for i in range(3):
+ self.AddGCP(None)
+
+ if self.CheckGCPcount():
+ # calculate RMS
+ self.RMSError(self.xygroup, self.gr_order)
+ else:
+ # draw GCPs (source and target)
+ sourceMapWin.UpdateMap(render=False, renderVector=False)
+ targetMapWin.UpdateMap(render=False, renderVector=False)
+
+ def ReloadGCPs(self, event):
+ """!Reload data from file"""
+
+ # use backup
+ shutil.copy(self.file['points_bak'], self.file['points'])
+
+ # delete all items in mapcoordlist
+ self.mapcoordlist = []
+ self.mapcoordlist.append([ 0, # GCP number
+ 0.0, # source east
+ 0.0, # source north
+ 0.0, # target east
+ 0.0, # target north
+ 0.0, # forward error
+ 0.0 ] ) # backward error
+
+ self.list.LoadData()
+ self.itemDataMap = self.mapcoordlist
+
+ def OnFocus(self, event):
+ # self.grwiz.SwitchEnv('source')
+ pass
+
+ def OnRMS(self, event):
+ """
+ RMS button handler
+ """
+ self.RMSError(self.xygroup,self.gr_order)
+
+ def CheckGCPcount(self, msg=False):
+ """
+ Checks to make sure that the minimum number of GCPs have been defined and
+ are active for the selected transformation order
+ """
+ if (self.GCPcount < 3 and self.gr_order == 1) or \
+ (self.GCPcount < 6 and self.gr_order == 2) or \
+ (self.GCPcount < 10 and self.gr_order == 3):
+ if msg:
+ wx.MessageBox(parent=self,
+ caption=_("RMS Error"),
+ message=_('Insufficient points defined and active (checked) '
+ 'for selected rectification method.\n'
+ '3+ points needed for 1st order,\n'
+ '6+ points for 2nd order, and\n'
+ '10+ points for 3rd order.'),
+ style=wx.ICON_INFORMATION | wx.ID_OK | wx.CENTRE)
+ return False
+ else:
+ return True
+
+ def OnGeorect(self, event):
+ """
+ Georectifies map(s) in group using i.rectify or v.transform
+ """
+ global maptype
+ self.SaveGCPs(None)
+
+ if self.CheckGCPcount(msg=True) == False:
+ return
+
+ if maptype == 'cell':
+ self.grwiz.SwitchEnv('source')
+ cmdlist = ['i.rectify','-a','group=%s' % self.xygroup,
+ 'extension=%s' % self.extension,'order=%s' % self.gr_order]
+ if self.clip_to_region:
+ cmdlist.append('-c')
+
+ self.parent.goutput.RunCmd(cmdlist, compReg=False,
+ switchPage=True)
+
+ time.sleep(.1)
+
+ elif maptype == 'vector':
+ outmsg = ''
+ # loop through all vectors in VREF
+ # and move resulting vector to target location
+
+ # make sure current mapset has a vector folder
+ if not os.path.isdir(os.path.join(self.grassdatabase,
+ self.currentlocation,
+ self.currentmapset,
+ 'vector')):
+ os.mkdir(os.path.join(self.grassdatabase,
+ self.currentlocation,
+ self.currentmapset,
+ 'vector'))
+
+ self.grwiz.SwitchEnv('source')
+
+ # make list of vectors to georectify from VREF
+ f = open(self.file['vgrp'])
+ vectlist = []
+ try:
+ for vect in f.readlines():
+ vect = vect.strip('\n')
+ if len(vect) < 1:
+ continue
+ vectlist.append(vect)
+ finally:
+ f.close()
+
+ # georectify each vector in VREF using v.transform
+ for vect in vectlist:
+ self.outname = vect + '_' + self.extension
+ self.parent.goutput.WriteLog(text = _('Transforming <%s>...') % vect,
+ switchPage = True)
+ msg = err = ''
+
+ ret, out, err = gcmd.RunCommand('v.transform',
+ flags = '-o',
+ input=vect,
+ output=self.outname,
+ pointsfile=self.file['points'],
+ getErrorMsg=True, read=True)
+
+
+ if ret == 0:
+ self.VectGRList.append(self.outname)
+ print err
+ # note: WriteLog doesn't handle GRASS_INFO_PERCENT well, so using a print here
+# self.parent.goutput.WriteLog(text = _(err), switchPage = True)
+ self.parent.goutput.WriteLog(text = _(out), switchPage = True)
+ else:
+ self.parent.goutput.WriteError(_('Georectification of vector map <%s> failed') %
+ self.outname)
+ self.parent.goutput.WriteError(_(err))
+
+ # FIXME
+ # Copying database information not working.
+ # Does not copy from xy location to current location
+ # TODO: replace $GISDBASE etc with real paths
+# xyLayer = []
+# for layer in grass.vector_db(map = vect).itervalues():
+# xyLayer.append((layer['driver'],
+# layer['database'],
+# layer['table']))
+
+
+# dbConnect = grass.db_connection()
+# print 'db connection =', dbConnect
+# for layer in xyLayer:
+# self.parent.goutput.RunCmd(['db.copy',
+# '--q',
+# '--o',
+# 'from_driver=%s' % layer[0],
+# 'from_database=%s' % layer[1],
+# 'from_table=%s' % layer[2],
+# 'to_driver=%s' % dbConnect['driver'],
+# 'to_database=%s' % dbConnect['database'],
+# 'to_table=%s' % layer[2] + '_' + self.extension])
+
+ # copy all georectified vectors from source location to current location
+ for name in self.VectGRList:
+ xyvpath = os.path.join(self.grassdatabase,
+ self.xylocation,
+ self.xymapset,
+ 'vector',
+ name)
+ vpath = os.path.join(self.grassdatabase,
+ self.currentlocation,
+ self.currentmapset,
+ 'vector',
+ name)
+
+ if os.path.isdir(vpath):
+ self.parent.goutput.WriteWarning(_('Vector map <%s> already exists. '
+ 'Change extension name and '
+ 'georectify again.') % self.outname)
+ break
+ else:
+ # use shutil.copytree() because shutil.move() deletes src dir
+ shutil.copytree(xyvpath, vpath)
+
+ # TODO: connect vectors to copied tables with v.db.connect
+
+ wx.MessageBox('For all vector maps georectified successfully, ' + '\n' +
+ 'you will need to copy any attribute tables' + '\n' +
+ 'and reconnect them to the georectified vectors')
+
+ self.grwiz.SwitchEnv('target')
+
+ def OnGeorectDone(self, **kargs):
+ """!Print final message"""
+ global maptype
+ if maptype == 'cell':
+ return
+
+ returncode = kargs['returncode']
+
+ if returncode == 0:
+ self.VectGRList.append(self.outname)
+ print '*****vector list = ' + str(self.VectGRList)
+ else:
+ self.parent.goutput.WriteError(_('Georectification of vector map <%s> failed') %
+ self.outname)
+
+
+ def OnSettings(self, event):
+ """!GCP Manager settings"""
+ dlg = GrSettingsDialog(parent=self, id=wx.ID_ANY, title=_('GCP Manager settings'))
+
+ if dlg.ShowModal() == wx.ID_OK:
+ pass
+
+ dlg.Destroy()
+
+ def UpdateColours(self, srcrender=False, srcrenderVector=False,
+ tgtrender=False, tgtrenderVector=False):
+ """!update colours"""
+ highest_fwd_err = 0.0
+ self.highest_key = 0
+ highest_idx = 0
+
+ for index in range(self.list.GetItemCount()):
+ if self.list.IsChecked(index):
+ key = self.list.GetItemData(index)
+ fwd_err = self.mapcoordlist[key][5]
+
+ if self.highest_only == True:
+ self.list.SetItemTextColour(index, wx.BLACK)
+ if highest_fwd_err < fwd_err:
+ highest_fwd_err = fwd_err
+ self.highest_key = key
+ highest_idx = index
+ elif self.rmsthresh > 0:
+ if (fwd_err > self.rmsthresh):
+ self.list.SetItemTextColour(index, wx.RED)
+ else:
+ self.list.SetItemTextColour(index, wx.BLACK)
+ else:
+ self.list.SetItemTextColour(index, wx.BLACK)
+
+ if self.highest_only and highest_fwd_err > 0.0:
+ self.list.SetItemTextColour(highest_idx, wx.RED)
+
+ sourceMapWin = self.SrcMapWindow
+ sourceMapWin.UpdateMap(render=srcrender, renderVector=srcrenderVector)
+ if self.show_target:
+ targetMapWin = self.TgtMapWindow
+ targetMapWin.UpdateMap(render=tgtrender, renderVector=tgtrenderVector)
+
+ def OnQuit(self, event):
+ """!Quit georectifier"""
+
+ ret = wx.MessageBox(parent=self,
+ caption=_("Quit GCP Manager"),
+ message=_('Save ground control points?'),
+ style=wx.ICON_QUESTION | wx.YES_NO | wx.CANCEL | wx.CENTRE)
+
+ if ret != wx.CANCEL:
+ if ret == wx.YES:
+ self.SaveGCPs(None)
+ elif ret == wx.NO:
+ # restore POINTS file from backup
+ if os.path.exists(self.file['points_bak']):
+ shutil.copy(self.file['points_bak'], self.file['points'])
+
+ if os.path.exists(self.file['points_bak']):
+ os.unlink(self.file['points_bak'])
+
+ self.SrcMap.Clean()
+ self.TgtMap.Clean()
+ self.grwiz.Cleanup()
+
+ self.Destroy()
+
+ #event.Skip()
+
+ def OnGROrder(self, event):
+ """
+ sets transformation order for georectifying
+ """
+ if event:
+ self.gr_order = event.GetInt() + 1
+
+ numOfItems = self.list.GetItemCount()
+ minNumOfItems = numOfItems
+
+ if self.gr_order == 1:
+ minNumOfItems = 3
+ # self.SetStatusText(_('Insufficient points, 3+ points needed for 1st order'))
+
+ elif self.gr_order == 2:
+ minNumOfItems = 6
+ diff = 6 - numOfItems
+ # self.SetStatusText(_('Insufficient points, 6+ points needed for 2nd order'))
+
+ elif self.gr_order == 3:
+ minNumOfItems = 10
+ # self.SetStatusText(_('Insufficient points, 10+ points needed for 3rd order'))
+
+ for i in range(minNumOfItems - numOfItems):
+ self.AddGCP(None)
+
+ return minNumOfItems
+
+ def RMSError(self, xygroup, order):
+ """
+ Uses g.transform to calculate forward and backward error for each used GCP
+ in POINTS file and insert error values into GCP list.
+ Calculates total forward and backward RMS error for all used points
+ """
+ # save GCPs to points file to make sure that all checked GCPs are used
+ self.SaveGCPs(None)
+ #self.SetStatusText('')
+
+ if self.CheckGCPcount(msg=True) == False:
+ return
+
+ # get list of forward and reverse rms error values for each point
+ self.grwiz.SwitchEnv('source')
+
+ ret = gcmd.RunCommand('g.transform',
+ parent = self,
+ read = True,
+ group = xygroup,
+ order = order)
+
+ self.grwiz.SwitchEnv('target')
+
+ if ret:
+ errlist = ret.splitlines()
+ else:
+ wx.MessageBox(parent=self,
+ caption=_("RMS Error"),
+ message=_('Could not calculate RMS Error. \n'
+ 'Possible error with g.transform.'),
+ style=wx.ICON_ERROR | wx.ID_OK | wx.CENTRE)
+ return
+
+ # insert error values into GCP list for checked items
+ sdfactor = float(UserSettings.Get(group='gcpman', key='rms', subkey='sdfactor'))
+ GCPcount = 0
+ sumsq_fwd_err = 0.0
+ sumsq_bkw_err = 0.0
+ sum_fwd_err = 0.0
+ highest_fwd_err = 0.0
+ self.highest_key = 0
+ highest_idx = 0
+
+ for index in range(self.list.GetItemCount()):
+ key = self.list.GetItemData(index)
+ if self.list.IsChecked(index):
+ fwd_err, bkw_err = errlist[GCPcount].split()
+ self.list.SetStringItem(index, 5, fwd_err)
+ self.list.SetStringItem(index, 6, bkw_err)
+ self.mapcoordlist[key][5] = float(fwd_err)
+ self.mapcoordlist[key][6] = float(bkw_err)
+ self.list.SetItemTextColour(index, wx.BLACK)
+ if self.highest_only:
+ if highest_fwd_err < float(fwd_err):
+ highest_fwd_err = float(fwd_err)
+ self.highest_key = key
+ highest_idx = index
+
+ sumsq_fwd_err += float(fwd_err)**2
+ sumsq_bkw_err += float(bkw_err)**2
+ sum_fwd_err += float(fwd_err)
+ GCPcount += 1
+ else:
+ self.list.SetStringItem(index, 5, '')
+ self.list.SetStringItem(index, 6, '')
+ self.mapcoordlist[key][5] = 0.0
+ self.mapcoordlist[key][6] = 0.0
+ self.list.SetItemTextColour(index, wx.BLACK)
+
+ # SD
+ if GCPcount > 0:
+ sum_fwd_err /= GCPcount
+ self.rmsmean = sum_fwd_err /GCPcount
+ self.rmssd = (((sumsq_fwd_err/GCPcount) - self.rmsmean**2)**0.5)
+ self.rmsthresh = self.rmsmean + sdfactor * self.rmssd
+ else:
+ self.rmsthresh = 0
+ self.rmsmean = 0
+ self.rmssd = 0
+
+ if self.highest_only and highest_fwd_err > 0.0:
+ self.list.SetItemTextColour(highest_idx, wx.RED)
+ elif GCPcount > 0 and self.rmsthresh > 0 and not self.highest_only:
+ for index in range(self.list.GetItemCount()):
+ if self.list.IsChecked(index):
+ key = self.list.GetItemData(index)
+ if (self.mapcoordlist[key][5] > self.rmsthresh):
+ self.list.SetItemTextColour(index, wx.RED)
+
+ # calculate global RMS error (geometric mean)
+ self.fwd_rmserror = round((sumsq_fwd_err/GCPcount)**0.5,4)
+ self.bkw_rmserror = round((sumsq_bkw_err/GCPcount)**0.5,4)
+ self.list.ResizeColumns()
+
+ sourceMapWin = self.SrcMapWindow
+ sourceMapWin.UpdateMap(render=False, renderVector=False)
+ if self.show_target:
+ targetMapWin = self.TgtMapWindow
+ targetMapWin.UpdateMap(render=False, renderVector=False)
+
+ def GetNewExtend(self, region, map = None):
+
+ coord_file = utils.GetTempfile()
+ newreg = { 'n' : 0.0, 's' : 0.0, 'e' : 0.0, 'w' : 0.0,}
+
+ try:
+ f = open(coord_file, mode='w')
+ # NW corner
+ f.write(str(region['e']) + " " + str(region['n']) + "\n")
+ # NE corner
+ f.write(str(region['e']) + " " + str(region['s']) + "\n")
+ # SW corner
+ f.write(str(region['w']) + " " + str(region['n']) + "\n")
+ # SE corner
+ f.write(str(region['w']) + " " + str(region['s']) + "\n")
+ finally:
+ f.close()
+
+ # save GCPs to points file to make sure that all checked GCPs are used
+ self.SaveGCPs(None)
+
+ order = self.gr_order
+ self.gr_order = 1
+
+ if self.CheckGCPcount(msg=True) == False:
+ self.gr_order = order
+ return
+
+ self.gr_order = order
+
+ # get list of forward and reverse rms error values for each point
+ self.grwiz.SwitchEnv('source')
+
+ if map == 'source':
+ ret = gcmd.RunCommand('g.transform',
+ parent = self,
+ read = True,
+ group = self.xygroup,
+ order = 1,
+ format = 'dst',
+ coords = coord_file)
+
+ elif map == 'target':
+ ret = gcmd.RunCommand('g.transform',
+ parent = self,
+ read = True,
+ group = self.xygroup,
+ order = 1,
+ flags = 'r',
+ format = 'src',
+ coords = coord_file)
+
+ os.unlink(coord_file)
+
+ self.grwiz.SwitchEnv('target')
+
+ if ret:
+ errlist = ret.splitlines()
+ else:
+ wx.MessageBox(parent=self,
+ caption=_("Adjust GCP Displays "),
+ message=_('Could not calculate new extends. \n'
+ 'Possible error with g.transform.'),
+ style=wx.ICON_ERROR | wx.ID_OK | wx.CENTRE)
+ return
+
+ # fist corner
+ e, n = errlist[0].split()
+ fe = float(e)
+ fn = float(n)
+ newreg['n'] = fn
+ newreg['s'] = fn
+ newreg['e'] = fe
+ newreg['w'] = fe
+ # other three corners
+ for i in range(1, 4):
+ e, n = errlist[i].split()
+ fe = float(e)
+ fn = float(n)
+ if fe < newreg['w']:
+ newreg['w'] = fe
+ if fe > newreg['e']:
+ newreg['e'] = fe
+ if fn < newreg['s']:
+ newreg['s'] = fn
+ if fn > newreg['n']:
+ newreg['n'] = fn
+
+ return newreg
+
+ def OnHelp(self, event):
+ """!Show GCP Manager manual page"""
+
+ cmdlist = ['g.manual','entry=wxGUI.GCP_Manager']
+ self.parent.goutput.RunCmd(cmdlist, compReg=False,
+ switchPage=False)
+
+ def OnUpdateActive(self, event):
+
+ if self.activemap.GetSelection() == 0:
+ self.MapWindow = self.SrcMapWindow
+ self.Map = self.SrcMap
+ else:
+ self.MapWindow = self.TgtMapWindow
+ self.Map = self.TgtMap
+
+ self.UpdateActive(self.MapWindow)
+ # for wingrass
+ if os.name == 'nt':
+ self.MapWindow.SetFocus()
+
+ def UpdateActive(self, win):
+
+ # optionally disable tool zoomback tool
+ self.toolbars['gcpdisp'].toolbar.EnableTool(self.toolbars['gcpdisp'].zoomback,
+ enable = (len(self.MapWindow.zoomhistory) > 1))
+
+ if self.activemap.GetSelection() != (win == self.TgtMapWindow):
+ self.activemap.SetSelection(win == self.TgtMapWindow)
+ self.StatusbarUpdate()
+
+ def AdjustMap(self, newreg):
+ """!Adjust map window to new extents
+ """
+
+ # adjust map window
+ self.Map.region['n'] = newreg['n']
+ self.Map.region['s'] = newreg['s']
+ self.Map.region['e'] = newreg['e']
+ self.Map.region['w'] = newreg['w']
+
+ self.MapWindow.ZoomHistory(self.Map.region['n'], self.Map.region['s'],
+ self.Map.region['e'], self.Map.region['w'])
+
+ # LL locations
+ if self.Map.projinfo['proj'] == 'll':
+ if newreg['n'] > 90.0:
+ newreg['n'] = 90.0
+ if newreg['s'] < -90.0:
+ newreg['s'] = -90.0
+
+ ce = newreg['w'] + (newreg['e'] - newreg['w']) / 2
+ cn = newreg['s'] + (newreg['n'] - newreg['s']) / 2
+
+ # calculate new center point and display resolution
+ self.Map.region['center_easting'] = ce
+ self.Map.region['center_northing'] = cn
+ self.Map.region["ewres"] = (newreg['e'] - newreg['w']) / self.Map.width
+ self.Map.region["nsres"] = (newreg['n'] - newreg['s']) / self.Map.height
+ self.Map.AlignExtentFromDisplay()
+
+ self.MapWindow.ZoomHistory(self.Map.region['n'], self.Map.region['s'],
+ self.Map.region['e'], self.Map.region['w'])
+
+ if self.MapWindow.redrawAll is False:
+ self.MapWindow.redrawAll = True
+
+ self.MapWindow.UpdateMap()
+ self.StatusbarUpdate()
+
+ def OnZoomToSource(self, event):
+ """!Set target map window to match extents of source map window
+ """
+
+ if not self.MapWindow == self.TgtMapWindow:
+ self.MapWindow = self.TgtMapWindow
+ self.Map = self.TgtMap
+ self.UpdateActive(self.TgtMapWindow)
+
+ # get new N, S, E, W for target
+ newreg = self.GetNewExtend(self.SrcMap.region, 'source')
+ self.AdjustMap(newreg)
+
+ def OnZoomToTarget(self, event):
+ """!Set source map window to match extents of target map window
+ """
+
+ if not self.MapWindow == self.SrcMapWindow:
+ self.MapWindow = self.SrcMapWindow
+ self.Map = self.SrcMap
+ self.UpdateActive(self.SrcMapWindow)
+
+ # get new N, S, E, W for target
+ newreg = self.GetNewExtend(self.TgtMap.region, 'target')
+ self.AdjustMap(newreg)
+
+ def OnZoomMenuGCP(self, event):
+ """!Popup Zoom menu
+ """
+ point = wx.GetMousePosition()
+ zoommenu = wx.Menu()
+ # Add items to the menu
+
+ zoomsource = wx.MenuItem(zoommenu, wx.ID_ANY, _('Adjust source display to target display'))
+ zoommenu.AppendItem(zoomsource)
+ self.Bind(wx.EVT_MENU, self.OnZoomToTarget, zoomsource)
+
+ zoomtarget = wx.MenuItem(zoommenu, wx.ID_ANY, _('Adjust target display to source display'))
+ zoommenu.AppendItem(zoomtarget)
+ self.Bind(wx.EVT_MENU, self.OnZoomToSource, zoomtarget)
+
+ # Popup the menu. If an item is selected then its handler
+ # will be called before PopupMenu returns.
+ self.PopupMenu(zoommenu)
+ zoommenu.Destroy()
+
+ def OnDispResize(self, event):
+ """!GCP Map Display resized, adjust Map Windows
+ """
+ if self.toolbars['gcpdisp']:
+ time.sleep(0.5)
+ srcwidth, srcheight = self.SrcMapWindow.GetSize()
+ tgtwidth, tgtheight = self.TgtMapWindow.GetSize()
+ tgtwidth = (srcwidth + tgtwidth) / 2
+ self._mgr.GetPane("target").Hide()
+ self._mgr.Update()
+ self._mgr.GetPane("source").BestSize((tgtwidth, srcheight))
+ self._mgr.GetPane("target").BestSize((tgtwidth, tgtheight))
+ if self.show_target:
+ self._mgr.GetPane("target").Show()
+ self._mgr.Update()
+ pass
+
+class GCPList(wx.ListCtrl,
+ CheckListCtrlMixin,
+ ListCtrlAutoWidthMixin):
+
+ def __init__(self, parent, gcp, id=wx.ID_ANY,
+ pos=wx.DefaultPosition, size=wx.DefaultSize,
+ style=wx.LC_REPORT | wx.SUNKEN_BORDER | wx.LC_HRULES |
+ wx.LC_SINGLE_SEL):
+
+ wx.ListCtrl.__init__(self, parent, id, pos, size, style)
+
+ self.gcp = gcp # GCP class
+ self.render = True
+
+ # Mixin settings
+ CheckListCtrlMixin.__init__(self)
+ ListCtrlAutoWidthMixin.__init__(self)
+ # TextEditMixin.__init__(self)
+
+ # tracks whether list items are checked or not
+ self.CheckList = []
+
+ self._Create()
+
+ self.Bind(wx.EVT_LIST_ITEM_SELECTED, self.OnItemSelected)
+ self.Bind(wx.EVT_LIST_ITEM_ACTIVATED, self.OnItemActivated)
+ self.Bind(wx.EVT_LIST_COL_CLICK, self.OnColClick)
+
+ self.selected = wx.NOT_FOUND
+ self.selectedkey = -1
+
+ def _Create(self):
+
+ if 0:
+ # normal, simple columns
+ idx_col = 0
+ for col in (_('use'),
+ _('source E'),
+ _('source N'),
+ _('target E'),
+ _('target N'),
+ _('Forward error'),
+ _('Backward error')):
+ self.InsertColumn(idx_col, col)
+ idx_col += 1
+ else:
+ # the hard way: we want images on the column header
+ info = wx.ListItem()
+ info.SetMask(wx.LIST_MASK_TEXT | wx.LIST_MASK_IMAGE | wx.LIST_MASK_FORMAT)
+ info.SetImage(-1)
+ info.m_format = wx.LIST_FORMAT_LEFT
+
+ idx_col = 0
+ for lbl in (_('use'),
+ _('source E'),
+ _('source N'),
+ _('target E'),
+ _('target N'),
+ _('Forward error'),
+ _('Backward error')):
+ info.SetText(lbl)
+ self.InsertColumnInfo(idx_col, info)
+ idx_col += 1
+
+ def LoadData(self):
+ """!Load data into list"""
+ self.DeleteAllItems()
+
+ self.render = False
+ if os.path.isfile(self.gcp.file['points']):
+ self.gcp.ReadGCPs()
+ else:
+ # 3 gcp is minimum
+ for i in range(3):
+ self.gcp.AddGCP(None)
+
+ # select first point by default
+ self.selected = 0
+ self.selectedkey = self.GetItemData(self.selected)
+ self.SetItemState(self.selected,
+ wx.LIST_STATE_SELECTED,
+ wx.LIST_STATE_SELECTED)
+
+ self.ResizeColumns()
+ self.render = True
+
+ def OnCheckItem(self, index, flag):
+ """!Item is checked/unchecked"""
+
+ if self.render:
+ # redraw points
+ sourceMapWin = self.gcp.SrcMapWindow
+ sourceMapWin.UpdateMap(render=False, renderVector=False)
+ if self.gcp.show_target:
+ targetMapWin = self.gcp.TgtMapWindow
+ targetMapWin.UpdateMap(render=False, renderVector=False)
+
+ pass
+
+ def AddGCPItem(self):
+ """
+ Appends an item to GCP list
+ """
+ self.selectedkey = self.GetItemCount() + 1
+
+ self.Append([str(self.selectedkey), # GCP number
+ '0.0', # source E
+ '0.0', # source N
+ '0.0', # target E
+ '0.0', # target N
+ '', # forward error
+ '']) # backward error
+
+ self.selected = self.GetItemCount() - 1
+ self.SetItemData(self.selected, self.selectedkey)
+
+ self.SetItemState(self.selected,
+ wx.LIST_STATE_SELECTED,
+ wx.LIST_STATE_SELECTED)
+
+ self.ResizeColumns()
+
+ return self.selected
+
+ def DeleteGCPItem(self):
+ """
+ Deletes selected item in GCP list
+ """
+ if self.selected == wx.NOT_FOUND:
+ return
+
+ key = self.GetItemData(self.selected)
+ self.DeleteItem(self.selected)
+
+ return key
+
+ def ResizeColumns(self):
+ """!Resize columns"""
+ minWidth = [90, 120]
+ for i in range(self.GetColumnCount()):
+ self.SetColumnWidth(i, wx.LIST_AUTOSIZE)
+ # first column is checkbox, don't set to minWidth
+ if i > 0 and self.GetColumnWidth(i) < minWidth[i > 4]:
+ self.SetColumnWidth(i, minWidth[i > 4])
+
+ self.SendSizeEvent()
+
+ def GetSelected(self):
+ """!Get index of selected item"""
+ return self.selected
+
+ def OnItemSelected(self, event):
+ """
+ Item selected
+ """
+
+ if self.render and self.selected != event.GetIndex():
+ self.selected = event.GetIndex()
+ self.selectedkey = self.GetItemData(self.selected)
+ sourceMapWin = self.gcp.SrcMapWindow
+ sourceMapWin.UpdateMap(render=False, renderVector=False)
+ if self.gcp.show_target:
+ targetMapWin = self.gcp.TgtMapWindow
+ targetMapWin.UpdateMap(render=False, renderVector=False)
+
+ event.Skip()
+
+ def OnItemActivated(self, event):
+ """
+ When item double clicked, open editor to update coordinate values
+ """
+ coords = []
+ index = event.GetIndex()
+ key = self.GetItemData(index)
+ changed = False
+
+ for i in range(1, 5):
+ coords.append(self.GetItem(index, i).GetText())
+
+ dlg = EditGCP(parent=self, id=wx.ID_ANY, data=coords, gcpno=key)
+
+ if dlg.ShowModal() == wx.ID_OK:
+ values = dlg.GetValues() # string
+
+ if len(values) == 0:
+ wx.MessageBox(parent=self,
+ caption=_("Edit GCP"),
+ message=_("Invalid coordinate value. Operation cancelled."),
+ style=wx.CENTRE | wx.ICON_ERROR | wx.ID_OK)
+ else:
+ for i in range(len(values)):
+ if values[i] != coords[i]:
+ self.SetStringItem(index, i + 1, values[i])
+ changed = True
+
+ if changed:
+ # reset RMS and update mapcoordlist
+ self.SetStringItem(index, 5, '')
+ self.SetStringItem(index, 6, '')
+ key = self.GetItemData(index)
+ self.gcp.mapcoordlist[key] = [key,
+ float(values[0]),
+ float(values[1]),
+ float(values[2]),
+ float(values[3]),
+ 0.0,
+ 0.0]
+ self.gcp.UpdateColours()
+
+ def OnColClick(self, event):
+ """!ListCtrl forgets selected item..."""
+ self.selected = self.FindItemData(-1, self.selectedkey)
+ self.SetItemState(self.selected,
+ wx.LIST_STATE_SELECTED,
+ wx.LIST_STATE_SELECTED)
+ event.Skip()
+
+class VectGroup(wx.Dialog):
+ """
+ Dialog to create a vector group (VREF file) for georectifying
+
+ @todo Replace by g.group
+ """
+ def __init__(self, parent, id, grassdb, location, mapset, group,
+ style=wx.DEFAULT_DIALOG_STYLE):
+
+ wx.Dialog.__init__(self, parent, id, style=style,
+ title = _("Create vector map group"))
+
+ self.grassdatabase = grassdb
+ self.xylocation = location
+ self.xymapset = mapset
+ self.xygroup = group
+
+ #
+ # get list of valid vector directories
+ #
+ vectlist = os.listdir(os.path.join(self.grassdatabase,
+ self.xylocation,
+ self.xymapset,
+ 'vector'))
+ for dir in vectlist:
+ if not os.path.isfile(os.path.join(self.grassdatabase,
+ self.xylocation,
+ self.xymapset,
+ 'vector',
+ dir,
+ 'coor')):
+ vectlist.remove(dir)
+
+ utils.ListSortLower(vectlist)
+
+ # path to vref file
+ self.vgrpfile = os.path.join(self.grassdatabase,
+ self.xylocation,
+ self.xymapset,
+ 'group',
+ self.xygroup,
+ 'VREF')
+
+ #
+ # buttons
+ #
+ self.btnCancel = wx.Button(parent = self,
+ id = wx.ID_CANCEL)
+ self.btnOK = wx.Button(parent = self,
+ id = wx.ID_OK)
+ self.btnOK.SetDefault()
+
+
+ #
+ # list of vector maps
+ #
+ self.listMap = wx.CheckListBox(parent = self, id = wx.ID_ANY,
+ choices = vectlist)
+
+ if os.path.isfile(self.vgrpfile):
+ f = open(self.vgrpfile)
+ try:
+ checked = []
+ for line in f.readlines():
+ line = line.replace('\n', '')
+ if len(line) < 1:
+ continue
+ checked.append(line)
+ self.listMap.SetCheckedStrings(checked)
+ finally:
+ f.close()
+
+ line = wx.StaticLine(parent = self,
+ id = wx.ID_ANY, size = (20, -1),
+ style = wx.LI_HORIZONTAL)
+
+ #
+ # layout
+ #
+ sizer = wx.BoxSizer(wx.VERTICAL)
+
+ box = wx.BoxSizer(wx.HORIZONTAL)
+ box.Add(item = wx.StaticText(parent = self, id = wx.ID_ANY,
+ label = _('Select vector map(s) to add to group:')),
+ flag = wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT | wx.LEFT,
+ border = 5)
+
+ box.Add(item = self.listMap,
+ flag = wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT | wx.LEFT,
+ border = 5)
+
+
+ sizer.Add(box, flag = wx.ALIGN_RIGHT | wx.ALL,
+ border = 3)
+
+ sizer.Add(item = line, proportion = 0,
+ flag = wx.GROW | wx.ALIGN_CENTER_VERTICAL | wx.LEFT | wx.RIGHT,
+ border = 5)
+
+ # buttons
+ btnSizer = wx.StdDialogButtonSizer()
+ btnSizer.AddButton(self.btnCancel)
+ btnSizer.AddButton(self.btnOK)
+ btnSizer.Realize()
+
+ sizer.Add(item = btnSizer, proportion = 0,
+ flag = wx.EXPAND | wx.ALL | wx.ALIGN_CENTER,
+ border = 5)
+
+ self.SetSizer(sizer)
+ sizer.Fit(self)
+ self.Layout()
+
+ def MakeVGroup(self):
+ """!Create VREF file"""
+ vgrouplist = []
+ for item in range(self.listMap.GetCount()):
+ if not self.listMap.IsChecked(item):
+ continue
+ vgrouplist.append(self.listMap.GetString(item))
+
+ f = open(self.vgrpfile, mode='w')
+ try:
+ for vect in vgrouplist:
+ f.write(vect + '\n')
+ finally:
+ f.close()
+
+class EditGCP(wx.Dialog):
+ def __init__(self, parent, data, gcpno, id=wx.ID_ANY,
+ title=_("Edit GCP"),
+ style=wx.DEFAULT_DIALOG_STYLE):
+ """!Dialog for editing GPC and map coordinates in list control"""
+
+ wx.Dialog.__init__(self, parent, id, title=title, style=style)
+
+ panel = wx.Panel(parent=self)
+
+ sizer = wx.BoxSizer(wx.VERTICAL)
+
+ box = wx.StaticBox (parent=panel, id=wx.ID_ANY,
+ label=" %s %s " % (_("Ground Control Point No."), str(gcpno)))
+ boxSizer = wx.StaticBoxSizer(box, wx.VERTICAL)
+
+ # source coordinates
+ gridSizer = wx.GridBagSizer(vgap=5, hgap=5)
+
+ self.xcoord = wx.TextCtrl(parent=panel, id=wx.ID_ANY, size=(150, -1))
+ self.ycoord = wx.TextCtrl(parent=panel, id=wx.ID_ANY, size=(150, -1))
+ self.ecoord = wx.TextCtrl(parent=panel, id=wx.ID_ANY, size=(150, -1))
+ self.ncoord = wx.TextCtrl(parent=panel, id=wx.ID_ANY, size=(150, -1))
+
+ # swap source N, target E
+ tmp_coord = data[1]
+ data[1] = data[2]
+ data[2] = tmp_coord
+
+ row = 0
+ col = 0
+ idx = 0
+ for label, win in ((_("source E:"), self.xcoord),
+ (_("target E:"), self.ecoord),
+ (_("source N:"), self.ycoord),
+ (_("target N:"), self.ncoord)):
+ label = wx.StaticText(parent=panel, id=wx.ID_ANY,
+ label=label)
+ gridSizer.Add(item=label,
+ flag=wx.ALIGN_CENTER_VERTICAL,
+ pos=(row, col))
+
+ col += 1
+ win.SetValue(str(data[idx]))
+
+ gridSizer.Add(item=win,
+ pos=(row, col))
+
+ col += 1
+ idx += 1
+
+ if col > 3:
+ row += 1
+ col = 0
+
+ boxSizer.Add(item=gridSizer, proportion=1,
+ flag=wx.EXPAND | wx.ALL, border=5)
+
+ sizer.Add(item=boxSizer, proportion=1,
+ flag=wx.EXPAND | wx.ALL, border=5)
+
+ #
+ # buttons
+ #
+ self.btnCancel = wx.Button(panel, wx.ID_CANCEL)
+ self.btnOk = wx.Button(panel, wx.ID_OK)
+ self.btnOk.SetDefault()
+
+ btnSizer = wx.StdDialogButtonSizer()
+ btnSizer.AddButton(self.btnCancel)
+ btnSizer.AddButton(self.btnOk)
+ btnSizer.Realize()
+
+ sizer.Add(item=btnSizer, proportion=0,
+ flag=wx.ALIGN_RIGHT | wx.ALL, border=5)
+
+ panel.SetSizer(sizer)
+ sizer.Fit(self)
+
+ def GetValues(self, columns=None):
+ """!Return list of values (as strings).
+ """
+ valuelist = []
+ try:
+ float(self.xcoord.GetValue())
+ float(self.ycoord.GetValue())
+ float(self.ecoord.GetValue())
+ float(self.ncoord.GetValue())
+ except ValueError:
+ return valuelist
+
+ valuelist.append(self.xcoord.GetValue())
+ valuelist.append(self.ycoord.GetValue())
+ valuelist.append(self.ecoord.GetValue())
+ valuelist.append(self.ncoord.GetValue())
+
+ return valuelist
+
+class GrSettingsDialog(wx.Dialog):
+ def __init__(self, parent, id, title, pos=wx.DefaultPosition, size=wx.DefaultSize,
+ style=wx.DEFAULT_DIALOG_STYLE):
+ wx.Dialog.__init__(self, parent, id, title, pos, size, style)
+ """
+ Dialog to set profile text options: font, title
+ and font size, axis labels and font size
+ """
+ #
+ # initialize variables
+ #
+ self.parent = parent
+ self.new_src_map = src_map
+ self.new_tgt_map = tgt_map
+ self.sdfactor = 0
+
+ self.symbol = {}
+
+ # notebook
+ notebook = wx.Notebook(parent=self, id=wx.ID_ANY, style=wx.BK_DEFAULT)
+ self.__CreateSymbologyPage(notebook)
+ self.__CreateRectificationPage(notebook)
+
+ # buttons
+ btnSave = wx.Button(self, wx.ID_SAVE)
+ btnApply = wx.Button(self, wx.ID_APPLY)
+ btnClose = wx.Button(self, wx.ID_CLOSE)
+ btnApply.SetDefault()
+
+ # bindings
+ btnApply.Bind(wx.EVT_BUTTON, self.OnApply)
+ btnApply.SetToolTipString(_("Apply changes for the current session"))
+ btnSave.Bind(wx.EVT_BUTTON, self.OnSave)
+ btnSave.SetToolTipString(_("Apply and save changes to user settings file (default for next sessions)"))
+ btnClose.Bind(wx.EVT_BUTTON, self.OnClose)
+ btnClose.SetToolTipString(_("Close dialog"))
+
+ # sizers
+ btnSizer = wx.BoxSizer(wx.HORIZONTAL)
+ btnSizer.Add(btnApply, flag=wx.LEFT | wx.RIGHT, border=5)
+ btnSizer.Add(btnSave, flag=wx.LEFT | wx.RIGHT, border=5)
+ btnSizer.Add(btnClose, flag=wx.LEFT | wx.RIGHT, border=5)
+
+ # sizers
+ mainSizer = wx.BoxSizer(wx.VERTICAL)
+ mainSizer.Add(item=notebook, proportion=1, flag=wx.EXPAND | wx.ALL, border=5)
+ mainSizer.Add(item=btnSizer, proportion=0,
+ flag=wx.ALIGN_RIGHT | wx.ALL, border=5)
+ # flag=wx.EXPAND | wx.ALL | wx.ALIGN_CENTER, border=5)
+
+ self.SetSizer(mainSizer)
+ mainSizer.Fit(self)
+
+ def __CreateSymbologyPage(self, notebook):
+ """!Create notebook page with symbology settings"""
+
+ panel = wx.Panel(parent=notebook, id=wx.ID_ANY)
+ notebook.AddPage(page=panel, text=_("Symbology"))
+
+ sizer = wx.BoxSizer(wx.VERTICAL)
+
+ rmsgridSizer = wx.GridBagSizer(vgap=5, hgap=5)
+ rmsgridSizer.AddGrowableCol(1)
+
+ # highlight only highest forward RMS error
+ self.highlighthighest = wx.CheckBox(parent=panel, id=wx.ID_ANY,
+ label=_("Highlight highest RMS error only"))
+ hh = UserSettings.Get(group='gcpman', key='rms', subkey='highestonly')
+ self.highlighthighest.SetValue(hh)
+ rmsgridSizer.Add(item=self.highlighthighest, flag=wx.ALIGN_CENTER_VERTICAL, pos=(0, 0))
+
+ # RMS forward error threshold
+ rmslabel = wx.StaticText(parent=panel, id=wx.ID_ANY, label=_("Highlight RMS error > M + SD * factor:"))
+ rmslabel.SetToolTip(wx.ToolTip(_("Highlight GCPs with an RMS error larger than \n"
+ "mean + standard deviation * given factor. \n"
+ "Recommended values for this factor are between 1 and 2.")))
+ rmsgridSizer.Add(item=rmslabel, flag=wx.ALIGN_CENTER_VERTICAL, pos=(1, 0))
+ sdfactor = UserSettings.Get(group='gcpman', key='rms', subkey='sdfactor')
+ self.rmsWin = wx.TextCtrl(parent=panel, id=wx.ID_ANY,
+ size=(70,-1), style=wx.TE_NOHIDESEL)
+ self.rmsWin.SetValue("%s" % str(sdfactor))
+ if (self.parent.highest_only == True):
+ self.rmsWin.Disable()
+
+ self.symbol['sdfactor'] = self.rmsWin.GetId()
+ rmsgridSizer.Add(item=self.rmsWin, flag=wx.ALIGN_RIGHT, pos=(1, 1))
+ sizer.Add(item=rmsgridSizer, flag=wx.EXPAND | wx.ALL, border=5)
+
+ box = wx.StaticBox(parent=panel, id=wx.ID_ANY,
+ label=" %s " % _("Symbol settings"))
+ boxSizer = wx.StaticBoxSizer(box, wx.VERTICAL)
+ gridSizer = wx.GridBagSizer(vgap=5, hgap=5)
+ gridSizer.AddGrowableCol(1)
+
+ #
+ # general symbol color
+ #
+ row = 0
+ label = wx.StaticText(parent=panel, id=wx.ID_ANY, label=_("Color:"))
+ gridSizer.Add(item=label, flag=wx.ALIGN_CENTER_VERTICAL, pos=(row, 0))
+ col = UserSettings.Get(group='gcpman', key='symbol', subkey='color')
+ colWin = csel.ColourSelect(parent=panel, id=wx.ID_ANY,
+ colour=wx.Colour(col[0],
+ col[1],
+ col[2],
+ 255))
+ self.symbol['color'] = colWin.GetId()
+ gridSizer.Add(item=colWin,
+ flag=wx.ALIGN_RIGHT,
+ pos=(row, 1))
+
+ #
+ # symbol color for high forward RMS error
+ #
+ row += 1
+ label = wx.StaticText(parent=panel, id=wx.ID_ANY, label=_("Color for high RMS error:"))
+ gridSizer.Add(item=label, flag=wx.ALIGN_CENTER_VERTICAL, pos=(row, 0))
+ hcol = UserSettings.Get(group='gcpman', key='symbol', subkey='hcolor')
+ hcolWin = csel.ColourSelect(parent=panel, id=wx.ID_ANY,
+ colour=wx.Colour(hcol[0],
+ hcol[1],
+ hcol[2],
+ 255))
+ self.symbol['hcolor'] = hcolWin.GetId()
+ gridSizer.Add(item=hcolWin,
+ flag=wx.ALIGN_RIGHT,
+ pos=(row, 1))
+
+ #
+ # symbol color for selected GCP
+ #
+ row += 1
+ label = wx.StaticText(parent=panel, id=wx.ID_ANY, label=_("Color for selected GCP:"))
+ gridSizer.Add(item=label, flag=wx.ALIGN_CENTER_VERTICAL, pos=(row, 0))
+ scol = UserSettings.Get(group='gcpman', key='symbol', subkey='scolor')
+ scolWin = csel.ColourSelect(parent=panel, id=wx.ID_ANY,
+ colour=wx.Colour(scol[0],
+ scol[1],
+ scol[2],
+ 255))
+ self.symbol['scolor'] = scolWin.GetId()
+ gridSizer.Add(item=scolWin,
+ flag=wx.ALIGN_RIGHT,
+ pos=(row, 1))
+
+ #
+ # symbol color for unused GCP
+ #
+ row += 1
+ label = wx.StaticText(parent=panel, id=wx.ID_ANY, label=_("Color for unused GCPs:"))
+ gridSizer.Add(item=label, flag=wx.ALIGN_CENTER_VERTICAL, pos=(row, 0))
+ ucol = UserSettings.Get(group='gcpman', key='symbol', subkey='ucolor')
+ ucolWin = csel.ColourSelect(parent=panel, id=wx.ID_ANY,
+ colour=wx.Colour(ucol[0],
+ ucol[1],
+ ucol[2],
+ 255))
+ self.symbol['ucolor'] = ucolWin.GetId()
+ gridSizer.Add(item=ucolWin,
+ flag=wx.ALIGN_RIGHT,
+ pos=(row, 1))
+
+ # show unused GCPs
+ row += 1
+ self.showunused = wx.CheckBox(parent=panel, id=wx.ID_ANY,
+ label=_("Show unused GCPs"))
+ shuu = UserSettings.Get(group='gcpman', key='symbol', subkey='unused')
+ self.showunused.SetValue(shuu)
+ gridSizer.Add(item=self.showunused, flag=wx.ALIGN_CENTER_VERTICAL, pos=(row, 0))
+
+ #
+ # symbol size
+ #
+ row += 1
+ label = wx.StaticText(parent=panel, id=wx.ID_ANY, label=_("Symbol size:"))
+ gridSizer.Add(item=label, flag=wx.ALIGN_CENTER_VERTICAL, pos=(row, 0))
+ symsize = int(UserSettings.Get(group='gcpman', key='symbol', subkey='size'))
+ sizeWin = wx.SpinCtrl(parent=panel, id=wx.ID_ANY,
+ min=1, max=20)
+ sizeWin.SetValue(symsize)
+ self.symbol['size'] = sizeWin.GetId()
+ gridSizer.Add(item=sizeWin,
+ flag=wx.ALIGN_RIGHT,
+ pos=(row, 1))
+
+ #
+ # symbol width
+ #
+ row += 1
+ label = wx.StaticText(parent=panel, id=wx.ID_ANY, label=_("Line width:"))
+ gridSizer.Add(item=label, flag=wx.ALIGN_CENTER_VERTICAL, pos=(row, 0))
+ width = int(UserSettings.Get(group='gcpman', key='symbol', subkey='width'))
+ widWin = wx.SpinCtrl(parent=panel, id=wx.ID_ANY,
+ min=1, max=10)
+ widWin.SetValue(width)
+ self.symbol['width'] = widWin.GetId()
+ gridSizer.Add(item=widWin,
+ flag=wx.ALIGN_RIGHT,
+ pos=(row, 1))
+
+ boxSizer.Add(item=gridSizer, flag=wx.EXPAND)
+ sizer.Add(item=boxSizer, flag=wx.EXPAND | wx.ALL, border=5)
+
+ #
+ # maps to display
+ #
+ # source map to display
+ self.srcselection = gselect.Select(panel, id=wx.ID_ANY,
+ size=globalvar.DIALOG_GSELECT_SIZE, type='cell', updateOnPopup = False)
+ self.parent.grwiz.SwitchEnv('source')
+ self.srcselection.SetElementList(maptype)
+ # filter out all maps not in group
+ # not available in 64
+ #self.srcselection.tcp.GetElementList(elements = self.parent.src_maps)
+ # modified from gselect
+ self.srcselection.tcp.seltree.DeleteAllItems()
+ # get current mapset
+ curr_mapset = grass.gisenv()['MAPSET']
+ mapsets = utils.ListOfMapsets()
+ for i in range(len(mapsets)):
+ if i > 0 and mapsets[i] == curr_mapset:
+ mapsets[i] = mapsets[0]
+ mapsets[0] = curr_mapset
+
+ elementdict = {'cell':'rast',
+ 'raster':'rast',
+ 'rast':'rast',
+ 'raster files':'rast',
+ 'vector':'vect',
+ 'vect':'vect'
+ }
+ if globalvar.have_mlist:
+ filesdict = grass.mlist_grouped(elementdict[maptype])
+ else:
+ filesdict = grass.list_grouped(elementdict[maptype])
+
+ first_dir = None
+ for dir in mapsets:
+ dir_node = self.srcselection.tcp.AddItem('Mapset: ' + dir)
+ if not first_dir:
+ first_dir = dir_node
+
+ self.srcselection.tcp.seltree.SetItemTextColour(dir_node, wx.Colour(50, 50, 200))
+ try:
+ elem_list = filesdict[dir]
+ elem_list.sort(key=str.lower)
+ for elem in elem_list:
+ if elem != '':
+ fullqElem = elem + '@' + dir
+ if fullqElem in self.parent.src_maps:
+ self.srcselection.tcp.AddItem(fullqElem, parent=dir_node)
+ except:
+ continue
+
+ if self.srcselection.tcp.seltree.ItemHasChildren(dir_node):
+ sel = UserSettings.Get(group='general', key='elementListExpand',
+ subkey='selection')
+ collapse = True
+
+ if sel == 0: # collapse all except PERMANENT and current
+ if dir in ('PERMANENT', curr_mapset):
+ collapse = False
+ elif sel == 1: # collapse all except PERMANENT
+ if dir == 'PERMANENT':
+ collapse = False
+ elif sel == 2: # collapse all except current
+ if dir == curr_mapset:
+ collapse = False
+ elif sel == 3: # collapse all
+ pass
+ elif sel == 4: # expand all
+ collapse = False
+
+ if collapse:
+ self.srcselection.tcp.seltree.Collapse(dir_node)
+ else:
+ self.srcselection.tcp.seltree.Expand(dir_node)
+
+ if first_dir:
+ # select first mapset (MSW hack)
+ self.srcselection.tcp.seltree.SelectItem(first_dir)
+
+ # end copy from gselect
+
+ # target map to display
+ self.tgtselection = gselect.Select(panel, id=wx.ID_ANY,
+ size=globalvar.DIALOG_GSELECT_SIZE, type='cell', updateOnPopup = False)
+ self.parent.grwiz.SwitchEnv('target')
+ self.tgtselection.SetElementList(maptype)
+ #self.tgtselection.GetElementList()
+
+ sizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY, label=_('Select source map to display:')),
+ proportion=0, flag=wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL | wx.ALL, border=5)
+ sizer.Add(item=self.srcselection, proportion=0,
+ flag=wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL | wx.ALL, border=5)
+ self.srcselection.SetValue(src_map)
+ sizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY, label=_('Select target map to display:')),
+ proportion=0, flag=wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL | wx.ALL, border=5)
+ sizer.Add(item=self.tgtselection, proportion=0,
+ flag=wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL | wx.ALL, border=5)
+ self.tgtselection.SetValue(tgt_map)
+
+ # bindings
+ self.highlighthighest.Bind(wx.EVT_CHECKBOX, self.OnHighlight)
+ self.rmsWin.Bind(wx.EVT_TEXT, self.OnSDFactor)
+ self.srcselection.Bind(wx.EVT_TEXT, self.OnSrcSelection)
+ self.tgtselection.Bind(wx.EVT_TEXT, self.OnTgtSelection)
+
+ panel.SetSizer(sizer)
+
+ return panel
+
+ def __CreateRectificationPage(self, notebook):
+ """!Create notebook page with symbology settings"""
+
+ panel = wx.Panel(parent=notebook, id=wx.ID_ANY)
+ notebook.AddPage(page=panel, text=_("Rectification"))
+
+ sizer = wx.BoxSizer(wx.VERTICAL)
+
+ # transformation order
+ self.rb_grmethod = wx.RadioBox(parent=panel, id=wx.ID_ANY,
+ label=" %s " % _("Select rectification method for rasters"),
+ choices=[_('1st order'), _('2nd order'), _('3rd order')],
+ majorDimension=wx.RA_SPECIFY_COLS)
+ sizer.Add(item=self.rb_grmethod, proportion=0,
+ flag=wx.EXPAND | wx.ALL, border=5)
+ self.rb_grmethod.SetSelection(self.parent.gr_order - 1)
+
+ # clip to region
+ self.check = wx.CheckBox(parent=panel, id=wx.ID_ANY,
+ label=_("clip to computational region in target location"))
+ sizer.Add(item=self.check, proportion=0,
+ flag=wx.EXPAND | wx.ALL, border=5)
+ self.check.SetValue(self.parent.clip_to_region)
+
+ # extension
+ sizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY, label=_('Extension for output maps:')),
+ proportion=0, flag=wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL | wx.ALL, border=5)
+ self.ext_txt = wx.TextCtrl(parent=panel, id=wx.ID_ANY, value="", size=(350,-1))
+ self.ext_txt.SetValue(self.parent.extension)
+ sizer.Add(item=self.ext_txt,
+ proportion=0, flag=wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL | wx.ALL, border=5)
+
+ # bindings
+ self.ext_txt.Bind(wx.EVT_TEXT, self.OnExtension)
+ self.Bind(wx.EVT_RADIOBOX, self.parent.OnGROrder, self.rb_grmethod)
+ self.Bind(wx.EVT_CHECKBOX, self.OnClipRegion, self.check)
+
+ panel.SetSizer(sizer)
+
+ return panel
+
+ def OnHighlight(self, event):
+ """!Checkbox 'highlighthighest' checked/unchecked"""
+ if self.highlighthighest.IsChecked():
+ self.parent.highest_only = True
+ self.rmsWin.Disable()
+ else:
+ self.parent.highest_only = False
+ self.rmsWin.Enable()
+
+ def OnSDFactor(self,event):
+ """!New factor for RMS threshold = M + SD * factor"""
+
+ self.sdfactor = float(event.GetString())
+
+ if self.sdfactor <= 0:
+ wx.MessageBox(parent=self,
+ caption=_("Update settings"),
+ message=_('RMS threshold factor must be > 0'),
+ style=wx.ICON_ERROR | wx.ID_OK | wx.CENTRE)
+ elif self.sdfactor < 1:
+ wx.MessageBox(parent=self,
+ caption=_("Update settings"),
+ message=_('RMS threshold factor is < 1\n'
+ 'Too many points might be highlighted'),
+ style=wx.ICON_EXCLAMATION | wx.ID_OK | wx.CENTRE)
+
+ def OnSrcSelection(self,event):
+ """!Source map to display selected"""
+ global src_map
+
+ tmp_map = event.GetString()
+
+ if not tmp_map == '' and not tmp_map == src_map:
+ self.new_src_map = tmp_map
+
+ def OnTgtSelection(self,event):
+ """!Target map to display selected"""
+ global tgt_map
+
+ tmp_map = event.GetString()
+
+ if not tmp_map == tgt_map:
+ self.new_tgt_map = tmp_map
+
+ def OnClipRegion(self, event):
+ self.parent.clip_to_region = event.IsChecked()
+
+ def OnExtension(self, event):
+ self.parent.extension = event.GetString()
+
+ def UpdateSettings(self):
+ global src_map
+ global tgt_map
+
+ layers = None
+
+ UserSettings.Set(group='gcpman', key='rms', subkey='highestonly',
+ value=self.highlighthighest.GetValue())
+ if self.sdfactor > 0:
+ UserSettings.Set(group='gcpman', key='rms', subkey='sdfactor',
+ value=self.sdfactor)
+
+ self.parent.sdfactor = self.sdfactor
+ if self.parent.rmsthresh > 0:
+ self.parent.rmsthresh = self.parent.mean + self.parent.sdfactor * self.parent.rmssd
+
+ UserSettings.Set(group='gcpman', key='symbol', subkey='color',
+ value=tuple(wx.FindWindowById(self.symbol['color']).GetColour()))
+ UserSettings.Set(group='gcpman', key='symbol', subkey='hcolor',
+ value=tuple(wx.FindWindowById(self.symbol['hcolor']).GetColour()))
+ UserSettings.Set(group='gcpman', key='symbol', subkey='scolor',
+ value=tuple(wx.FindWindowById(self.symbol['scolor']).GetColour()))
+ UserSettings.Set(group='gcpman', key='symbol', subkey='ucolor',
+ value=tuple(wx.FindWindowById(self.symbol['ucolor']).GetColour()))
+ UserSettings.Set(group='gcpman', key='symbol', subkey='unused',
+ value=self.showunused.GetValue())
+ UserSettings.Set(group='gcpman', key='symbol', subkey='size',
+ value=wx.FindWindowById(self.symbol['size']).GetValue())
+ UserSettings.Set(group='gcpman', key='symbol', subkey='width',
+ value=wx.FindWindowById(self.symbol['width']).GetValue())
+
+ srcrender = False
+ srcrenderVector = False
+ tgtrender = False
+ tgtrenderVector = False
+ if self.new_src_map != src_map:
+ # remove old layer
+ layers = self.parent.grwiz.SrcMap.GetListOfLayers()
+ self.parent.grwiz.SrcMap.DeleteLayer(layers[0])
+
+ src_map = self.new_src_map
+ cmdlist = ['d.rast', 'map=%s' % src_map]
+ self.parent.grwiz.SwitchEnv('source')
+ self.parent.grwiz.SrcMap.AddLayer(type='raster', command=cmdlist, l_active=True,
+ name=utils.GetLayerNameFromCmd(cmdlist),
+ l_hidden=False, l_opacity=1.0, l_render=False)
+
+ self.parent.grwiz.SwitchEnv('target')
+ srcrender = True
+
+ if self.new_tgt_map != tgt_map:
+ # remove old layer
+ layers = self.parent.grwiz.TgtMap.GetListOfLayers()
+ if layers:
+ self.parent.grwiz.TgtMap.DeleteLayer(layers[0])
+ tgt_map = self.new_tgt_map
+
+ if tgt_map != '':
+ cmdlist = ['d.rast', 'map=%s' % tgt_map]
+ self.parent.grwiz.TgtMap.AddLayer(type='raster', command=cmdlist, l_active=True,
+ name=utils.GetLayerNameFromCmd(cmdlist),
+ l_hidden=False, l_opacity=1.0, l_render=False)
+
+ tgtrender = True
+ if self.parent.show_target == False:
+ self.parent.show_target = True
+ self.parent._mgr.GetPane("target").Show()
+ self.parent.toolbars['gcpdisp'].toolbar.EnableTool(self.parent.toolbars['gcpdisp'].zoommenu, enable = True)
+ self.parent.activemap.Enable()
+ self.parent.TgtMapWindow.ZoomToMap(layer = self.parent.TgtMap.GetListOfLayers())
+ self.parent._mgr.Update()
+ else: # tgt_map == ''
+ if self.parent.show_target == True:
+ self.parent.show_target = False
+ self.parent._mgr.GetPane("target").Hide()
+ self.parent.activemap.SetSelection(0)
+ self.parent.activemap.Enable(False)
+ self.parent.toolbars['gcpdisp'].toolbar.EnableTool(self.parent.toolbars['gcpdisp'].zoommenu, enable = False)
+ self.parent._mgr.Update()
+
+ self.parent.UpdateColours(srcrender, srcrenderVector, tgtrender, tgtrenderVector)
+
+ def OnSave(self, event):
+ """!Button 'Save' pressed"""
+ self.UpdateSettings()
+ fileSettings = {}
+ UserSettings.ReadSettingsFile(settings=fileSettings)
+ fileSettings['gcpman'] = UserSettings.Get(group='gcpman')
+ file = UserSettings.SaveToFile(fileSettings)
+ self.parent.parent.goutput.WriteLog(_('GCP Manager settings saved to file \'%s\'.') % file)
+ #self.Close()
+
+ def OnApply(self, event):
+ """!Button 'Apply' pressed"""
+ self.UpdateSettings()
+ #self.Close()
+
+ def OnClose(self, event):
+ """!Button 'Cancel' pressed"""
+ self.Close()
Property changes on: grass/branches/releasebranch_6_4/gui/wxpython/gui_modules/gcpmanager.py
___________________________________________________________________
Added: svn:mime-type
+ text/x-python
Added: svn:eol-style
+ native
Added: grass/branches/releasebranch_6_4/gui/wxpython/gui_modules/gcpmapdisp.py
===================================================================
--- grass/branches/releasebranch_6_4/gui/wxpython/gui_modules/gcpmapdisp.py (rev 0)
+++ grass/branches/releasebranch_6_4/gui/wxpython/gui_modules/gcpmapdisp.py 2010-09-27 19:32:44 UTC (rev 43715)
@@ -0,0 +1,1744 @@
+"""!
+ at package gcpmapdisp.py
+
+ at brief GIS map display canvas, with toolbar for various display
+management functions, and additional toolbars (vector digitizer, 3d
+view).
+
+Classes:
+- MapFrame
+
+
+(C) 2006-2010 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 Markus Metz
+based on mapdisp.py by
+ at author Michael Barton
+ at author Jachym Cepicky
+ at author Martin Landa <landa.martin gmail.com>
+"""
+
+import os
+import sys
+import glob
+import math
+import tempfile
+import copy
+
+import globalvar
+if not os.getenv("GRASS_WXBUNDLED"):
+ globalvar.CheckForWx()
+import wx
+import wx.aui
+
+try:
+ import subprocess
+except:
+ CompatPath = os.path.join(globalvar.ETCWXDIR)
+ sys.path.append(CompatPath)
+ from compat import subprocess
+
+gmpath = os.path.join(globalvar.ETCWXDIR, "icons")
+sys.path.append(gmpath)
+
+grassPath = os.path.join(globalvar.ETCDIR, "python")
+sys.path.append(grassPath)
+
+import render
+import toolbars
+import menuform
+import gselect
+import disp_print
+import gcmd
+import dbm
+import histogram
+import profile
+import globalvar
+import utils
+import gdialogs
+from grass.script import core as grass
+from debug import Debug
+from icon import Icons
+from preferences import globalSettings as UserSettings
+
+from gcmd import Command
+from mapdisp import BufferedWindow
+
+import images
+imagepath = images.__path__[0]
+sys.path.append(imagepath)
+
+class MapFrame(wx.Frame):
+ """!Main frame for map display window. Drawing takes place in
+ child double buffered drawing window.
+ """
+ def __init__(self, parent=None, id=wx.ID_ANY, title=_("GRASS GIS - Map display"),
+ style=wx.DEFAULT_FRAME_STYLE, toolbars=["gcpdisp"],
+ tree=None, notebook=None, lmgr=None, page=None,
+ Map=None, auimgr=None, **kwargs):
+ """!Main map display window with toolbars, statusbar and
+ DrawWindow
+
+ @param toolbars array of activated toolbars, here 'gcpdisp'
+ @param tree reference to layer tree
+ @param notebook control book ID in Layer Manager
+ @param lmgr Layer Manager
+ @param page notebook page with layer tree
+ @param Map instance of render.Map
+ @param auimgs AUI manager
+ @param kwargs wx.Frame attribures
+ """
+ self._layerManager = lmgr # Layer Manager object
+ self.gismanager = lmgr # GIS Manager object
+ self.Map = Map # instance of render.Map
+ self.tree = tree # Layer Manager layer tree object
+ self.page = page # Notebook page holding the layer tree
+ self.layerbook = notebook # Layer Manager layer tree notebook
+ self.parent = parent
+
+ if not kwargs.has_key('name'):
+ kwargs['name'] = 'GCPDisplay'
+ wx.Frame.__init__(self, parent, id, title, style = style, **kwargs)
+
+ # available cursors
+ self.cursors = {
+ # default: cross
+ # "default" : wx.StockCursor(wx.CURSOR_DEFAULT),
+ "default" : wx.StockCursor(wx.CURSOR_ARROW),
+ "cross" : wx.StockCursor(wx.CURSOR_CROSS),
+ "hand" : wx.StockCursor(wx.CURSOR_HAND),
+ "pencil" : wx.StockCursor(wx.CURSOR_PENCIL),
+ "sizenwse": wx.StockCursor(wx.CURSOR_SIZENWSE)
+ }
+
+ #
+ # set the size & system icon
+ #
+ self.SetClientSize(self.GetSize())
+ self.iconsize = (16, 16)
+
+ self.SetIcon(wx.Icon(os.path.join(globalvar.ETCICONDIR, 'grass_map.ico'), wx.BITMAP_TYPE_ICO))
+
+ #
+ # Fancy gui
+ #
+ self._mgr = wx.aui.AuiManager(self)
+
+ #
+ # Add toolbars
+ #
+ self.toolbars = { 'map' : None,
+ 'vdigit' : None,
+ 'georect' : None,
+ 'gcpdisp' : None,
+ 'gcpman' : None,
+ 'nviz' : None }
+
+ for toolb in toolbars:
+ self.AddToolbar(toolb)
+
+ self.activemap = self.toolbars['gcpdisp'].togglemap
+ self.activemap.SetSelection(0)
+ self.SrcMap = self.grwiz.SrcMap # instance of render.Map
+ self.TgtMap = self.grwiz.TgtMap # instance of render.Map
+ self._mgr.SetDockSizeConstraint(0.5, 0.5)
+
+ #
+ # Add statusbar
+ #
+ self.statusbar = self.CreateStatusBar(number=4, style=0)
+ self.statusbar.SetStatusWidths([-5, -2, -1, -1])
+ self.toggleStatus = wx.Choice(self.statusbar, wx.ID_ANY,
+ choices = [_("Coordinates"),
+ _("Extent"),
+ _("Comp. region"),
+ _("Show comp. extent"),
+ _("Display mode"),
+ _("Display geometry"),
+ _("Map scale"),
+ _("Go to GCP No."),
+ _("RMS error")])
+ # set StatusBar to Go to GCP No.
+ self.toggleStatus.SetSelection(7)
+
+ self.statusbar.Bind(wx.EVT_CHOICE, self.OnToggleStatus, self.toggleStatus)
+ # auto-rendering checkbox
+ self.autoRender = wx.CheckBox(parent=self.statusbar, id=wx.ID_ANY,
+ label=_("Render"))
+ self.statusbar.Bind(wx.EVT_CHECKBOX, self.OnToggleRender, self.autoRender)
+ self.autoRender.SetValue(UserSettings.Get(group='display',
+ key='autoRendering',
+ subkey='enabled'))
+ self.autoRender.SetToolTip(wx.ToolTip (_("Enable/disable auto-rendering")))
+ # show region
+ self.showRegion = wx.CheckBox(parent=self.statusbar, id=wx.ID_ANY,
+ label=_("Show computational extent"))
+ self.statusbar.Bind(wx.EVT_CHECKBOX, self.OnToggleShowRegion, self.showRegion)
+
+ self.showRegion.SetValue(False)
+ self.showRegion.Hide()
+ self.showRegion.SetToolTip(wx.ToolTip (_("Show/hide computational "
+ "region extent (set with g.region). "
+ "Display region drawn as a blue box inside the "
+ "computational region, "
+ "computational region inside a display region "
+ "as a red box).")))
+ # set resolution
+ self.compResolution = wx.CheckBox(parent=self.statusbar, id=wx.ID_ANY,
+ label=_("Constrain display resolution to computational settings"))
+ self.statusbar.Bind(wx.EVT_CHECKBOX, self.OnToggleResolution, self.compResolution)
+ self.compResolution.SetValue(UserSettings.Get(group='display', key='compResolution', subkey='enabled'))
+ self.compResolution.Hide()
+ self.compResolution.SetToolTip(wx.ToolTip (_("Constrain display resolution "
+ "to computational region settings. "
+ "Default value for new map displays can "
+ "be set up in 'User GUI settings' dialog.")))
+ # map scale
+ self.mapScale = wx.ComboBox(parent = self.statusbar, id = wx.ID_ANY,
+ style = wx.TE_PROCESS_ENTER,
+ size=(150, -1))
+ self.mapScale.SetItems(['1:1000',
+ '1:5000',
+ '1:10000',
+ '1:25000',
+ '1:50000',
+ '1:100000',
+ '1:1000000'])
+ self.mapScale.Hide()
+ self.statusbar.Bind(wx.EVT_TEXT_ENTER, self.OnChangeMapScale, self.mapScale)
+ self.statusbar.Bind(wx.EVT_COMBOBOX, self.OnChangeMapScale, self.mapScale)
+
+ # go to GCP
+ self.gotogcp = wx.SpinCtrl(parent=self.statusbar, id=wx.ID_ANY,
+ min=0)
+ self.statusbar.Bind(wx.EVT_SPINCTRL, self.OnGoTo, self.gotogcp)
+ self.gotogcp.Hide()
+ self.statusbar.Bind(wx.EVT_TEXT_ENTER, self.OnGoTo, self.gotogcp)
+
+ # mask
+ self.maskInfo = wx.StaticText(parent = self.statusbar, id = wx.ID_ANY,
+ label = '')
+ self.maskInfo.SetForegroundColour(wx.Colour(255, 0, 0))
+
+ # on-render gauge
+ self.onRenderGauge = wx.Gauge(parent=self.statusbar, id=wx.ID_ANY,
+ range=0, style=wx.GA_HORIZONTAL)
+ self.onRenderGauge.Hide()
+
+ self.StatusbarReposition() # reposition statusbar
+
+ #
+ # Init map display (buffered DC & set default cursor)
+ #
+ self.grwiz.SwitchEnv('source')
+ self.SrcMapWindow = BufferedWindow(self, id=wx.ID_ANY,
+ Map=self.SrcMap, tree=self.tree, gismgr=self._layerManager)
+
+ self.grwiz.SwitchEnv('target')
+ self.TgtMapWindow = BufferedWindow(self, id=wx.ID_ANY,
+ Map=self.TgtMap, tree=self.tree, gismgr=self._layerManager)
+ self.MapWindow = self.SrcMapWindow
+ self.Map = self.SrcMap
+ self.SrcMapWindow.Bind(wx.EVT_MOTION, self.OnMotion)
+ self.TgtMapWindow.Bind(wx.EVT_MOTION, self.OnMotion)
+ self.SrcMapWindow.SetCursor(self.cursors["cross"])
+ self.TgtMapWindow.SetCursor(self.cursors["cross"])
+
+ #
+ # initialize region values
+ #
+ self.__InitDisplay()
+
+ #
+ # Bind various events
+ #
+ self.Bind(wx.EVT_ACTIVATE, self.OnFocus)
+ self.Bind(render.EVT_UPDATE_PRGBAR, self.OnUpdateProgress)
+ self.Bind(wx.EVT_SIZE, self.OnDispResize)
+ self.activemap.Bind(wx.EVT_CHOICE, self.OnUpdateActive)
+
+ #
+ # Update fancy gui style
+ #
+ # AuiManager wants a CentrePane , workaround to get two equally sized windows
+ self.list = self.CreateGCPList()
+
+ #self.SrcMapWindow.SetSize((300, 300))
+ #self.TgtMapWindow.SetSize((300, 300))
+ self.list.SetSize((100, 150))
+ self._mgr.AddPane(self.list, wx.aui.AuiPaneInfo().
+ Name("gcplist").Caption(_("GCP List")).LeftDockable(False).
+ RightDockable(False).PinButton().FloatingSize((600,200)).
+ CloseButton(False).DestroyOnClose(True).
+ Top().Layer(1).MinSize((200,100)))
+ self._mgr.AddPane(self.SrcMapWindow, wx.aui.AuiPaneInfo().
+ Name("source").Caption(_("Source Display")).Dockable(False).
+ CloseButton(False).DestroyOnClose(True).Floatable(False).
+ Centre())
+ self._mgr.AddPane(self.TgtMapWindow, wx.aui.AuiPaneInfo().
+ Name("target").Caption(_("Target Display")).Dockable(False).
+ CloseButton(False).DestroyOnClose(True).Floatable(False).
+ Right().Layer(0))
+
+ srcwidth, srcheight = self.SrcMapWindow.GetSize()
+ tgtwidth, tgtheight = self.TgtMapWindow.GetSize()
+ tgtwidth = (srcwidth + tgtwidth) / 2
+ self._mgr.GetPane("target").Hide()
+ self._mgr.Update()
+ self._mgr.GetPane("source").BestSize((tgtwidth, tgtheight))
+ self._mgr.GetPane("target").BestSize((tgtwidth, tgtheight))
+ if self.show_target:
+ self._mgr.GetPane("target").Show()
+ else:
+ self.activemap.Enable(False)
+
+ # called by GCPWizard
+ #self._mgr.Update()
+
+ #
+ # Init print module and classes
+ #
+ self.printopt = disp_print.PrintOptions(self, self.MapWindow)
+
+ # set active map
+ self.MapWindow = self.SrcMapWindow
+ self.Map = self.SrcMap
+ #
+ # Init zoom history
+ #
+ self.TgtMapWindow.ZoomHistory(self.Map.region['n'],
+ self.Map.region['s'],
+ self.Map.region['e'],
+ self.Map.region['w'])
+ self.MapWindow.ZoomHistory(self.Map.region['n'],
+ self.Map.region['s'],
+ self.Map.region['e'],
+ self.Map.region['w'])
+
+ #
+ # Re-use dialogs
+ #
+ self.dialogs = {}
+ self.dialogs['attributes'] = None
+ self.dialogs['category'] = None
+ self.dialogs['barscale'] = None
+ self.dialogs['legend'] = None
+
+ self.decorationDialog = None # decoration/overlays
+
+ def AddToolbar(self, name):
+ """!Add defined toolbar to the window
+
+ Currently known toolbars are:
+ - 'map' - basic map toolbar
+ - 'vdigit' - vector digitizer
+ - 'gcpdisp' - GCP Manager, Display
+ - 'gcpman' - GCP Manager, points management
+ - 'georect' - georectifier
+ - 'nviz' - 3D view mode
+ """
+ # default toolbars for GCP display
+ if name == "gcpdisp":
+ self.toolbars['gcpdisp'] = toolbars.GCPDisplayToolbar(self)
+
+ self._mgr.AddPane(self.toolbars['gcpdisp'].toolbar,
+ wx.aui.AuiPaneInfo().
+ Name("gcpdisplaytoolbar").Caption(_("GCP Display toolbar")).
+ ToolbarPane().Top().
+ LeftDockable(False).RightDockable(False).
+ BottomDockable(False).TopDockable(True).
+ CloseButton(False).Layer(2))
+
+ if self.show_target == False:
+ self.toolbars['gcpdisp'].toolbar.EnableTool(self.toolbars['gcpdisp'].zoommenu, enable = False)
+
+ self.toolbars['gcpman'] = toolbars.GCPManToolbar(self)
+
+ self._mgr.AddPane(self.toolbars['gcpman'].toolbar,
+ wx.aui.AuiPaneInfo().
+ Name("gcpmanagertoolbar").Caption(_("GCP Manager toolbar")).
+ ToolbarPane().Top().Row(1).
+ LeftDockable(False).RightDockable(False).
+ BottomDockable(False).TopDockable(True).
+ CloseButton(False).Layer(2))
+
+ # georectifier
+ elif name == "georect":
+ self.toolbars['georect'] = toolbars.GRToolbar(self, self.Map)
+
+ self._mgr.AddPane(self.toolbars['georect'].toolbar,
+ wx.aui.AuiPaneInfo().
+ Name("georecttoolbar").Caption(_("Georectification toolbar")).
+ ToolbarPane().Top().
+ LeftDockable(False).RightDockable(False).
+ BottomDockable(False).TopDockable(True).
+ CloseButton(False).Layer(2))
+
+ self._mgr.Update()
+
+ def __InitDisplay(self):
+ """
+ Initialize map display, set dimensions and map region
+ """
+ self.width, self.height = self.GetClientSize()
+
+ Debug.msg(2, "MapFrame.__InitDisplay():")
+ self.grwiz.SwitchEnv('source')
+ self.SrcMap.ChangeMapSize(self.GetClientSize())
+ self.SrcMap.region = self.SrcMap.GetRegion() # g.region -upgc
+ self.grwiz.SwitchEnv('target')
+ self.TgtMap.ChangeMapSize(self.GetClientSize())
+ self.TgtMap.region = self.TgtMap.GetRegion() # g.region -upgc
+ # self.SrcMap.SetRegion() # adjust region to match display window
+ # self.TgtMap.SetRegion() # adjust region to match display window
+
+ def OnUpdateProgress(self, event):
+ """
+ Update progress bar info
+ """
+ self.onRenderGauge.SetValue(event.value)
+
+ event.Skip()
+
+ def OnFocus(self, event):
+ """
+ Change choicebook page to match display.
+ Or set display for georectifying
+ """
+ if self._layerManager and \
+ self._layerManager.georectifying:
+ # in georectifying session; display used to get geographic
+ # coordinates for GCPs
+ self.OnPointer(event)
+ elif self._layerManager and \
+ self._layerManager.gcpmanagement:
+ # in georectifying session; display used to get geographic
+ # coordinates for GCPs
+ self.OnPointer(event)
+ self.MapWindow.SetFocus()
+
+ event.Skip()
+
+ def OnMotion(self, event):
+ """
+ Mouse moved
+ Track mouse motion and update status bar
+ """
+ # update statusbar if required
+ if self.toggleStatus.GetSelection() == 0: # Coordinates
+ e, n = self.MapWindow.Pixel2Cell(event.GetPositionTuple())
+ if self.toolbars['vdigit'] and \
+ self.toolbars['vdigit'].GetAction() == 'addLine' and \
+ self.toolbars['vdigit'].GetAction('type') in ('line', 'boundary') and \
+ len(self.MapWindow.polycoords) > 0:
+ # for linear feature show segment and total length
+ distance_seg = self.MapWindow.Distance(self.MapWindow.polycoords[-1],
+ (e, n), screen=False)[0]
+ distance_tot = distance_seg
+ for idx in range(1, len(self.MapWindow.polycoords)):
+ distance_tot += self.MapWindow.Distance(self.MapWindow.polycoords[idx-1],
+ self.MapWindow.polycoords[idx],
+ screen=False )[0]
+ self.statusbar.SetStatusText("%.2f, %.2f (seg: %.2f; tot: %.2f)" % \
+ (e, n, distance_seg, distance_tot), 0)
+ else:
+ if self.Map.projinfo['proj'] == 'll':
+ self.statusbar.SetStatusText("%s" % utils.Deg2DMS(e, n), 0)
+ else:
+ self.statusbar.SetStatusText("%.2f, %.2f" % (e, n), 0)
+
+ event.Skip()
+
+ def OnDraw(self, event):
+ """!Re-display current map composition
+ """
+ self.MapWindow.UpdateMap(render = False)
+
+ def OnRender(self, event):
+ """!Re-render map composition (each map layer)
+ """
+ # delete tmp map layers (queries)
+ qlayer = self.Map.GetListOfLayers(l_name=globalvar.QUERYLAYER)
+ for layer in qlayer:
+ self.Map.DeleteLayer(layer)
+
+ # delete tmp lines
+ if self.MapWindow.mouse["use"] in ("measure",
+ "profile"):
+ self.MapWindow.polycoords = []
+ self.MapWindow.ClearLines()
+
+ if self.toolbars['gcpdisp']:
+ self.SrcMapWindow.UpdateMap(render=True)
+ self.TgtMapWindow.UpdateMap(render=True)
+ self._mgr.Update()
+ else:
+ self.MapWindow.UpdateMap(render=True)
+
+ # update statusbar
+ self.StatusbarUpdate()
+
+ def OnPointer(self, event):
+ """!Pointer button clicked
+ """
+ if self.toolbars['map']:
+ if event:
+ self.toolbars['map'].OnTool(event)
+ self.toolbars['map'].action['desc'] = ''
+
+ self.MapWindow.mouse['use'] = "pointer"
+ self.MapWindow.mouse['box'] = "point"
+
+ # change the cursor
+ if self._layerManager.gcpmanagement:
+ self.SrcMapWindow.SetCursor(self.cursors["cross"])
+ self.SrcMapWindow.mouse['use'] = "pointer"
+ self.SrcMapWindow.mouse['box'] = "point"
+ self.TgtMapWindow.SetCursor(self.cursors["cross"])
+ self.TgtMapWindow.mouse['use'] = "pointer"
+ self.TgtMapWindow.mouse['box'] = "point"
+
+ elif self._layerManager and self._layerManager.georectifying:
+ self.MapWindow.SetCursor(self.cursors["cross"])
+
+ else:
+ self.MapWindow.SetCursor(self.cursors["default"])
+
+ def OnZoomIn(self, event):
+ """
+ Zoom in the map.
+ Set mouse cursor, zoombox attributes, and zoom direction
+ """
+ if self.toolbars['map']:
+ self.toolbars['map'].OnTool(event)
+ self.toolbars['map'].action['desc'] = ''
+
+ self.MapWindow.mouse['use'] = "zoom"
+ self.MapWindow.mouse['box'] = "box"
+ self.MapWindow.zoomtype = 1
+ self.MapWindow.pen = wx.Pen(colour='Red', width=2, style=wx.SHORT_DASH)
+
+ # change the cursor
+ self.MapWindow.SetCursor(self.cursors["cross"])
+
+ if self._layerManager and self._layerManager.gcpmanagement:
+ if self.MapWindow == self.SrcMapWindow:
+ win = self.TgtMapWindow
+ elif self.MapWindow == self.TgtMapWindow:
+ win = self.SrcMapWindow
+
+ win.mouse['use'] = "zoom"
+ win.mouse['box'] = "box"
+ win.zoomtype = 1
+ win.pen = wx.Pen(colour='Red', width=2, style=wx.SHORT_DASH)
+
+ # change the cursor
+ win.SetCursor(self.cursors["cross"])
+
+ def OnZoomOut(self, event):
+ """
+ Zoom out the map.
+ Set mouse cursor, zoombox attributes, and zoom direction
+ """
+ if self.toolbars['map']:
+ self.toolbars['map'].OnTool(event)
+ self.toolbars['map'].action['desc'] = ''
+
+ self.MapWindow.mouse['use'] = "zoom"
+ self.MapWindow.mouse['box'] = "box"
+ self.MapWindow.zoomtype = -1
+ self.MapWindow.pen = wx.Pen(colour='Red', width=2, style=wx.SHORT_DASH)
+
+ # change the cursor
+ self.MapWindow.SetCursor(self.cursors["cross"])
+
+ if self._layerManager and self._layerManager.gcpmanagement:
+ if self.MapWindow == self.SrcMapWindow:
+ win = self.TgtMapWindow
+ elif self.MapWindow == self.TgtMapWindow:
+ win = self.SrcMapWindow
+
+ win.mouse['use'] = "zoom"
+ win.mouse['box'] = "box"
+ win.zoomtype = -1
+ win.pen = wx.Pen(colour='Red', width=2, style=wx.SHORT_DASH)
+
+ # change the cursor
+ win.SetCursor(self.cursors["cross"])
+
+ def OnZoomBack(self, event):
+ """
+ Zoom last (previously stored position)
+ """
+ self.MapWindow.ZoomBack()
+
+ def OnPan(self, event):
+ """
+ Panning, set mouse to drag
+ """
+ if self.toolbars['map']:
+ self.toolbars['map'].OnTool(event)
+ self.toolbars['map'].action['desc'] = ''
+
+ self.MapWindow.mouse['use'] = "pan"
+ self.MapWindow.mouse['box'] = "pan"
+ self.MapWindow.zoomtype = 0
+
+ # change the cursor
+ self.MapWindow.SetCursor(self.cursors["hand"])
+
+ if self._layerManager and self._layerManager.gcpmanagement:
+ if self.MapWindow == self.SrcMapWindow:
+ win = self.TgtMapWindow
+ elif self.MapWindow == self.TgtMapWindow:
+ win = self.SrcMapWindow
+
+ win.mouse['use'] = "pan"
+ win.mouse['box'] = "pan"
+ win.zoomtype = 0
+
+ # change the cursor
+ win.SetCursor(self.cursors["hand"])
+
+ def OnErase(self, event):
+ """
+ Erase the canvas
+ """
+ self.MapWindow.EraseMap()
+
+ if self._layerManager and self._layerManager.gcpmanagement:
+ if self.MapWindow == self.SrcMapWindow:
+ win = self.TgtMapWindow
+ elif self.MapWindow == self.TgtMapWindow:
+ win = self.SrcMapWindow
+
+ win.EraseMap()
+
+ def OnZoomRegion(self, event):
+ """
+ Zoom to region
+ """
+ self.Map.getRegion()
+ self.Map.getResolution()
+ self.UpdateMap()
+ # event.Skip()
+
+ def OnAlignRegion(self, event):
+ """
+ Align region
+ """
+ if not self.Map.alignRegion:
+ self.Map.alignRegion = True
+ else:
+ self.Map.alignRegion = False
+ # event.Skip()
+
+ def OnToggleRender(self, event):
+ """
+ Enable/disable auto-rendering
+ """
+ if self.autoRender.GetValue():
+ self.OnRender(None)
+
+ def OnToggleShowRegion(self, event):
+ """
+ Show/Hide extent in map canvas
+ """
+ if self.showRegion.GetValue():
+ # show extent
+ self.MapWindow.regionCoords = []
+ else:
+ del self.MapWindow.regionCoords
+
+ # redraw map if auto-rendering is enabled
+ if self.autoRender.GetValue():
+ self.OnRender(None)
+
+ def OnToggleResolution(self, event):
+ """
+ Use resolution of computation region settings
+ for redering image instead of display resolution
+ """
+ # redraw map if auto-rendering is enabled
+ if self.autoRender.GetValue():
+ self.OnRender(None)
+
+ def OnToggleStatus(self, event):
+ """
+ Toggle status text
+ """
+ self.StatusbarUpdate()
+
+ def OnChangeMapScale(self, event):
+ """
+ Map scale changed by user
+ """
+ scale = event.GetString()
+
+ try:
+ if scale[:2] != '1:':
+ raise ValueError
+ value = int(scale[2:])
+ except ValueError:
+ self.mapScale.SetValue('1:%ld' % int(self.mapScaleValue))
+ return
+
+ dEW = value * (self.Map.region['cols'] / self.ppm[0])
+ dNS = value * (self.Map.region['rows'] / self.ppm[1])
+ self.Map.region['n'] = self.Map.region['center_northing'] + dNS / 2.
+ self.Map.region['s'] = self.Map.region['center_northing'] - dNS / 2.
+ self.Map.region['w'] = self.Map.region['center_easting'] - dEW / 2.
+ self.Map.region['e'] = self.Map.region['center_easting'] + dEW / 2.
+
+ # add to zoom history
+ self.MapWindow.ZoomHistory(self.Map.region['n'], self.Map.region['s'],
+ self.Map.region['e'], self.Map.region['w'])
+
+ # redraw a map
+ self.MapWindow.UpdateMap()
+ self.mapScale.SetFocus()
+
+ def OnGoTo(self, event):
+ """
+ Go to GCP No
+ """
+ #GCPNo = int(event.GetString())
+ GCPNo = self.gotogcp.GetValue()
+
+ if GCPNo < 0 or GCPNo > len(self.mapcoordlist):
+ wx.MessageBox(parent=self,
+ message="%s 1 - %s." % (_("Valid Range:"),
+ len(self.mapcoordlist)),
+ caption=_("Invalid GCP Number"), style=wx.OK | wx.ICON_ERROR | wx.CENTRE)
+ return
+
+ if GCPNo == 0:
+ return
+
+ self.list.selectedkey = GCPNo
+ self.list.selected = self.list.FindItemData(-1, GCPNo)
+ self.list.render = False
+ self.list.SetItemState(self.list.selected,
+ wx.LIST_STATE_SELECTED,
+ wx.LIST_STATE_SELECTED)
+ self.list.render = True
+
+ # Source MapWindow:
+ begin = (self.mapcoordlist[GCPNo][1], self.mapcoordlist[GCPNo][2])
+ begin = self.SrcMapWindow.Cell2Pixel(begin)
+ end = begin
+ self.SrcMapWindow.Zoom(begin, end, 0)
+
+ # redraw map
+ self.SrcMapWindow.UpdateMap()
+
+ if self.show_target:
+ # Target MapWindow:
+ begin = (self.mapcoordlist[GCPNo][3], self.mapcoordlist[GCPNo][4])
+ begin = self.TgtMapWindow.Cell2Pixel(begin)
+ end = begin
+ self.TgtMapWindow.Zoom(begin, end, 0)
+
+ # redraw map
+ self.TgtMapWindow.UpdateMap()
+
+ self.gotogcp.SetFocus()
+
+ def StatusbarUpdate(self):
+ """!Update statusbar content"""
+
+ self.showRegion.Hide()
+ self.compResolution.Hide()
+ self.mapScale.Hide()
+ self.gotogcp.Hide()
+ self.mapScaleValue = self.ppm = None
+
+ if self.toggleStatus.GetSelection() == 0: # Coordinates
+ self.statusbar.SetStatusText("", 0)
+ # enable long help
+ self.StatusbarEnableLongHelp()
+
+ elif self.toggleStatus.GetSelection() == 1: # Extent
+ self.statusbar.SetStatusText("%.2f - %.2f, %.2f - %.2f" %
+ (self.Map.region["w"], self.Map.region["e"],
+ self.Map.region["s"], self.Map.region["n"]), 0)
+ # enable long help
+ self.StatusbarEnableLongHelp()
+
+ elif self.toggleStatus.GetSelection() == 2: # Comp. region
+ compregion = self.Map.GetRegion()
+ self.statusbar.SetStatusText("%.2f - %.2f, %.2f - %.2f (%.2f, %.2f)" %
+ (compregion["w"], compregion["e"],
+ compregion["s"], compregion["n"],
+ compregion["ewres"], compregion["nsres"]), 0)
+ # enable long help
+ self.StatusbarEnableLongHelp()
+
+ elif self.toggleStatus.GetSelection() == 3: # Show comp. extent
+ self.statusbar.SetStatusText("", 0)
+ self.showRegion.Show()
+ # disable long help
+ self.StatusbarEnableLongHelp(False)
+
+ elif self.toggleStatus.GetSelection() == 4: # Display mode
+ self.statusbar.SetStatusText("", 0)
+ self.compResolution.Show()
+ # disable long help
+ self.StatusbarEnableLongHelp(False)
+
+ elif self.toggleStatus.GetSelection() == 5: # Display geometry
+ self.statusbar.SetStatusText("rows=%d; cols=%d; nsres=%.2f; ewres=%.2f" %
+ (self.Map.region["rows"], self.Map.region["cols"],
+ self.Map.region["nsres"], self.Map.region["ewres"]), 0)
+ # enable long help
+ self.StatusbarEnableLongHelp()
+
+ elif self.toggleStatus.GetSelection() == 6: # Map scale
+ # TODO: need to be fixed...
+ ### screen X region problem
+ ### user should specify ppm
+ dc = wx.ScreenDC()
+ dpSizePx = wx.DisplaySize() # display size in pixels
+ dpSizeMM = wx.DisplaySizeMM() # display size in mm (system)
+ dpSizeIn = (dpSizeMM[0] / 25.4, dpSizeMM[1] / 25.4) # inches
+ sysPpi = dc.GetPPI()
+ comPpi = (dpSizePx[0] / dpSizeIn[0],
+ dpSizePx[1] / dpSizeIn[1])
+
+ ppi = comPpi # pixel per inch
+ self.ppm = ((ppi[0] / 2.54) * 100, # pixel per meter
+ (ppi[1] / 2.54) * 100)
+
+ Debug.msg(4, "MapFrame.StatusbarUpdate(mapscale): size: px=%d,%d mm=%f,%f "
+ "in=%f,%f ppi: sys=%d,%d com=%d,%d; ppm=%f,%f" % \
+ (dpSizePx[0], dpSizePx[1], dpSizeMM[0], dpSizeMM[1],
+ dpSizeIn[0], dpSizeIn[1],
+ sysPpi[0], sysPpi[1], comPpi[0], comPpi[1],
+ self.ppm[0], self.ppm[1]))
+
+ region = self.Map.region
+
+ heightCm = region['rows'] / self.ppm[1] * 100
+ widthCm = region['cols'] / self.ppm[0] * 100
+
+ Debug.msg(4, "MapFrame.StatusbarUpdate(mapscale): width_cm=%f, height_cm=%f" %
+ (widthCm, heightCm))
+
+ xscale = (region['e'] - region['w']) / (region['cols'] / self.ppm[0])
+ yscale = (region['n'] - region['s']) / (region['rows'] / self.ppm[1])
+ scale = (xscale + yscale) / 2.
+
+ Debug.msg(3, "MapFrame.StatusbarUpdate(mapscale): xscale=%f, yscale=%f -> scale=%f" % \
+ (xscale, yscale, scale))
+
+ self.statusbar.SetStatusText("")
+ try:
+ self.mapScale.SetValue("1:%ld" % (scale + 0.5))
+ except TypeError:
+ pass
+ self.mapScaleValue = scale
+ self.mapScale.Show()
+
+ # disable long help
+ self.StatusbarEnableLongHelp(False)
+
+ elif self.toggleStatus.GetSelection() == 7: # go to
+
+ self.statusbar.SetStatusText("")
+ max = self.list.GetItemCount()
+ if max < 1:
+ max = 1
+ self.gotogcp.SetRange(0, max)
+ self.gotogcp.Show()
+
+ # disable long help
+ self.StatusbarEnableLongHelp(False)
+
+ elif self.toggleStatus.GetSelection() == 8: # RMS error
+ self.statusbar.SetStatusText(_("Forward: %s, Backward: %s") %
+ (self.fwd_rmserror, self.bkw_rmserror))
+
+ else:
+ self.statusbar.SetStatusText("", 1)
+
+ def StatusbarEnableLongHelp(self, enable=True):
+ """!Enable/disable toolbars long help"""
+ for toolbar in self.toolbars.itervalues():
+ if toolbar:
+ toolbar.EnableLongHelp(enable)
+
+ def StatusbarReposition(self):
+ """!Reposition checkbox in statusbar"""
+ # reposition checkbox
+ widgets = [(0, self.showRegion),
+ (0, self.compResolution),
+ (0, self.mapScale),
+ (0, self.onRenderGauge),
+ (0, self.gotogcp),
+ (1, self.toggleStatus),
+ (2, self.maskInfo),
+ (3, self.autoRender)]
+ for idx, win in widgets:
+ rect = self.statusbar.GetFieldRect(idx)
+ wWin, hWin = win.GetBestSize()
+ if idx == 0: # show region / mapscale / process bar
+ # -> size
+ if win == self.onRenderGauge:
+ wWin = rect.width - 6
+ # -> position
+ # if win == self.showRegion:
+ # x, y = rect.x + rect.width - wWin, rect.y - 1
+ # align left
+ # else:
+ x, y = rect.x + 3, rect.y - 1
+ w, h = wWin, rect.height + 2
+ else: # choice || auto-rendering
+ x, y = rect.x, rect.y - 1
+ w, h = rect.width, rect.height + 2
+ if idx == 1: # choice
+ h = hWin
+ elif idx == 2: # mask
+ x += 5
+ y += 4
+ elif idx == 3: # render
+ x += 5
+
+ win.SetPosition((x, y))
+ win.SetSize((w, h))
+
+ def SaveToFile(self, event):
+ """!Save map to image
+ """
+ img = self.MapWindow.img
+ if not img:
+ gcmd.GMessage(parent = self,
+ message = _("Nothing to render (empty map). Operation canceled."),
+ msgType = 'info')
+ return
+ filetype, ltype = gdialogs.GetImageHandlers(img)
+
+ # get size
+ dlg = gdialogs.ImageSizeDialog(self)
+ dlg.CentreOnParent()
+ if dlg.ShowModal() != wx.ID_OK:
+ dlg.Destroy()
+ return
+ width, height = dlg.GetValues()
+ dlg.Destroy()
+
+ # get filename
+ dlg = wx.FileDialog(parent = self,
+ message = _("Choose a file name to save the image "
+ "(no need to add extension)"),
+ wildcard = filetype,
+ style=wx.SAVE | wx.FD_OVERWRITE_PROMPT)
+
+ if dlg.ShowModal() == wx.ID_OK:
+ path = dlg.GetPath()
+ if not path:
+ dlg.Destroy()
+ return
+
+ base, ext = os.path.splitext(path)
+ fileType = ltype[dlg.GetFilterIndex()]['type']
+ extType = ltype[dlg.GetFilterIndex()]['ext']
+ if ext != extType:
+ path = base + '.' + extType
+
+ self.MapWindow.SaveToFile(path, fileType,
+ width, height)
+
+ dlg.Destroy()
+
+ def PrintMenu(self, event):
+ """
+ Print options and output menu for map display
+ """
+ point = wx.GetMousePosition()
+ printmenu = wx.Menu()
+ # Add items to the menu
+ setup = wx.MenuItem(printmenu, wx.ID_ANY, _('Page setup'))
+ printmenu.AppendItem(setup)
+ self.Bind(wx.EVT_MENU, self.printopt.OnPageSetup, setup)
+
+ preview = wx.MenuItem(printmenu, wx.ID_ANY, _('Print preview'))
+ printmenu.AppendItem(preview)
+ self.Bind(wx.EVT_MENU, self.printopt.OnPrintPreview, preview)
+
+ doprint = wx.MenuItem(printmenu, wx.ID_ANY, _('Print display'))
+ printmenu.AppendItem(doprint)
+ self.Bind(wx.EVT_MENU, self.printopt.OnDoPrint, doprint)
+
+ # Popup the menu. If an item is selected then its handler
+ # will be called before PopupMenu returns.
+ self.PopupMenu(printmenu)
+ printmenu.Destroy()
+
+ def GetRender(self):
+ """!Returns current instance of render.Map()
+ """
+ return self.Map
+
+ def GetWindow(self):
+ """!Get map window"""
+ return self.MapWindow
+
+ def OnQueryDisplay(self, event):
+ """!Query currrent raster/vector map layers (display mode)
+ """
+ if self.toolbars['map'].GetAction() == 'displayAttrb': # select previous action
+ self.toolbars['map'].SelectDefault(event)
+ return
+
+ self.toolbars['map'].action['desc'] = 'displayAttrb'
+
+ # switch GIS Manager to output console to show query results
+ self._layerManager.notebook.SetSelection(1)
+
+ self.MapWindow.mouse['use'] = "query"
+ self.MapWindow.mouse['box'] = "point"
+ self.MapWindow.zoomtype = 0
+
+ # change the cursor
+ self.MapWindow.SetCursor(self.cursors["cross"])
+
+ def OnQueryModify(self, event):
+ """
+ Query vector map layer (edit mode)
+ """
+ if self.toolbars['map'].GetAction() == 'modifyAttrb': # select previous action
+ self.toolbars['map'].SelectDefault(event)
+ return
+
+ self.toolbars['map'].action['desc'] = 'modifyAttrb'
+
+ self.MapWindow.mouse['use'] = "queryVector"
+ self.MapWindow.mouse['box'] = "point"
+ self.MapWindow.pen = wx.Pen(colour='Red', width=2, style=wx.SHORT_DASH)
+ self.MapWindow.zoomtype = 0
+
+ # change the cursor
+ self.MapWindow.SetCursor(self.cursors["cross"])
+
+ def QueryMap(self, x, y):
+ """!Query map layer features
+
+ Currently only raster and vector map layers are supported.
+
+ @param x,y coordinates
+ """
+ #set query snap distance for v.what at mapunit equivalent of 10 pixels
+ qdist = 10.0 * ((self.Map.region['e'] - self.Map.region['w']) / self.Map.width)
+ east, north = self.MapWindow.Pixel2Cell((x, y))
+
+ num = 0
+ for layer in self.tree.GetSelections():
+ type = self.tree.GetPyData(layer)[0]['maplayer'].GetType()
+ if type in ('raster', 'rgb', 'his',
+ 'vector', 'thememap', 'themechart'):
+ num += 1
+
+ if num < 1:
+ dlg = wx.MessageDialog(parent = self,
+ message = _('No raster or vector map layer selected for querying.'),
+ caption = _('No map layer selected'),
+ style = wx.OK | wx.ICON_INFORMATION | wx.CENTRE)
+ dlg.ShowModal()
+ dlg.Destroy()
+ return
+
+ mapname = None
+ raststr = ''
+ vectstr = ''
+ rcmd = ['r.what', '--q']
+ vcmd = ['v.what', '--q']
+ for layer in self.tree.GetSelections():
+ type = self.tree.GetPyData(layer)[0]['maplayer'].GetType()
+ dcmd = self.tree.GetPyData(layer)[0]['cmd']
+ name = utils.GetLayerNameFromCmd(dcmd)
+ if name == '':
+ continue
+ if type in ('raster', 'rgb', 'his'):
+ raststr += "%s," % name
+ elif type in ('vector', 'thememap', 'themechart'):
+ vectstr += "%s," % name
+
+ # use display region settings instead of computation region settings
+ self.tmpreg = os.getenv("GRASS_REGION")
+ os.environ["GRASS_REGION"] = self.Map.SetRegion(windres=False)
+
+ # build query commands for any selected rasters and vectors
+ if raststr != '':
+ rcmd.append('-f')
+ rcmd.append('input=%s' % raststr.rstrip(','))
+ rcmd.append('east_north=%f,%f' % (float(east), float(north)))
+
+ if vectstr != '':
+ # check for vector maps open to be edited
+ digitToolbar = self.toolbars['vdigit']
+ if digitToolbar:
+ map = digitToolbar.GetLayer().GetName()
+ vect = []
+ for vector in vectstr.split(','):
+ if map == vector:
+ self._layerManager.goutput.WriteWarning("Vector map <%s> "
+ "opened for editing - skipped." % map)
+ continue
+ vect.append(vector)
+ vectstr = ','.join(vect)
+
+ if len(vectstr) <= 1:
+ self._layerManager.goutput.WriteCmdLog("Nothing to query.")
+ return
+
+ vcmd.append('-a')
+ vcmd.append('map=%s' % vectstr.rstrip(','))
+ vcmd.append('east_north=%f,%f' % (float(east), float(north)))
+ vcmd.append('distance=%f' % float(qdist))
+
+ # parse query command(s)
+ if self._layerManager:
+ if raststr:
+ self._layerManager.goutput.RunCmd(rcmd,
+ compReg=False,
+ onDone = self._QueryMapDone)
+ if vectstr:
+ self._layerManager.goutput.RunCmd(vcmd,
+ onDone = self._QueryMapDone)
+ else:
+ if raststr:
+ gcmd.RunCommand(rcmd)
+ if vectstr:
+ gcmd.RunCommand(vcmd)
+
+ def _QueryMapDone(self, returncode):
+ """!Restore settings after querying (restore GRASS_REGION)
+
+ @param returncode command return code
+ """
+ if hasattr(self, "tmpreg"):
+ if self.tmpreg:
+ os.environ["GRASS_REGION"] = self.tmpreg
+ elif os.environ.has_key('GRASS_REGION'):
+ del os.environ["GRASS_REGION"]
+ elif os.environ.has_key('GRASS_REGION'):
+ del os.environ["GRASS_REGION"]
+
+ if hasattr(self, "tmpreg"):
+ del self.tmpreg
+
+ def QueryVector(self, x, y):
+ """
+ Query vector map layer features
+
+ Attribute data of selected vector object are displayed in GUI dialog.
+ Data can be modified (On Submit)
+ """
+ if not self.tree.layer_selected or \
+ self.tree.GetPyData(self.tree.layer_selected)[0]['type'] != 'vector':
+ wx.MessageBox(parent=self,
+ message=_("No vector map selected for querying."),
+ caption=_("Vector querying"),
+ style=wx.OK | wx.ICON_INFORMATION | wx.CENTRE)
+ return
+
+ if self.tree.GetPyData(self.tree.layer_selected)[0]['maplayer'].GetMapset() != \
+ grass.gisenv()['MAPSET']:
+ wx.MessageBox(parent=self,
+ message=_("Only vector map from the current mapset can be modified."),
+ caption=_("Vector querying"),
+ style=wx.OK | wx.ICON_INFORMATION | wx.CENTRE)
+ return
+
+ posWindow = self.ClientToScreen((x + self.MapWindow.dialogOffset,
+ y + self.MapWindow.dialogOffset))
+
+ qdist = 10.0 * ((self.Map.region['e'] - self.Map.region['w']) /
+ self.Map.width)
+
+ east, north = self.MapWindow.Pixel2Cell((x, y))
+
+ mapName = self.tree.GetPyData(self.tree.layer_selected)[0]['maplayer'].name
+
+ if self.dialogs['attributes'] is None:
+ self.dialogs['attributes'] = \
+ dbm_dialogs.DisplayAttributesDialog(parent=self.MapWindow,
+ map=mapName,
+ query=((east, north), qdist),
+ pos=posWindow,
+ action="update")
+ else:
+ # selection changed?
+ if not self.dialogs['attributes'].mapDBInfo or \
+ self.dialogs['attributes'].mapDBInfo.map != mapName:
+ self.dialogs['attributes'].UpdateDialog(map=mapName, query=((east, north), qdist))
+ else:
+ self.dialogs['attributes'].UpdateDialog(query=((east, north), qdist))
+
+ cats = self.dialogs['attributes'].GetCats()
+
+ try:
+ qlayer = self.Map.GetListOfLayers(l_name=globalvar.QUERYLAYER)[0]
+ except IndexError:
+ qlayer = None
+
+ if self.dialogs['attributes'].mapDBInfo and cats:
+ # highlight feature & re-draw map
+ if qlayer:
+ qlayer.SetCmd(self.AddTmpVectorMapLayer(mapName, cats,
+ useId=False,
+ addLayer=False))
+ else:
+ qlayer = self.AddTmpVectorMapLayer(mapName, cats, useId=False)
+
+ # set opacity based on queried layer
+ opacity = self.tree.GetPyData(self.tree.layer_selected)[0]['maplayer'].GetOpacity(float=True)
+ qlayer.SetOpacity(opacity)
+
+ self.MapWindow.UpdateMap(render=False, renderVector=False)
+ if not self.dialogs['attributes'].IsShown():
+ self.dialogs['attributes'].Show()
+ else:
+ if qlayer:
+ self.Map.DeleteLayer(qlayer)
+ self.MapWindow.UpdateMap(render=False, renderVector=False)
+ if self.dialogs['attributes'].IsShown():
+ self.dialogs['attributes'].Hide()
+
+ def OnQuery(self, event):
+ """!Query tools menu"""
+ if self.toolbars['map']:
+ self.toolbars['map'].OnTool(event)
+ action = self.toolbars['map'].GetAction()
+
+ point = wx.GetMousePosition()
+ toolsmenu = wx.Menu()
+ # Add items to the menu
+ display = wx.MenuItem(parentMenu=toolsmenu, id=wx.ID_ANY,
+ text=_("Query raster/vector map(s) (display mode)"),
+ kind=wx.ITEM_CHECK)
+ toolsmenu.AppendItem(display)
+ self.Bind(wx.EVT_MENU, self.OnQueryDisplay, display)
+ numLayers = 0
+ for layer in self.tree.GetSelections():
+ type = self.tree.GetPyData(layer)[0]['maplayer'].GetType()
+ if type in ('raster', 'rgb', 'his',
+ 'vector', 'thememap', 'themechart'):
+ numLayers += 1
+ if numLayers < 1:
+ display.Enable(False)
+
+ if action == "displayAttrb":
+ display.Check(True)
+
+ modify = wx.MenuItem(parentMenu=toolsmenu, id=wx.ID_ANY,
+ text=_("Query vector map (edit mode)"),
+ kind=wx.ITEM_CHECK)
+ toolsmenu.AppendItem(modify)
+ self.Bind(wx.EVT_MENU, self.OnQueryModify, modify)
+ digitToolbar = self.toolbars['vdigit']
+ if self.tree.layer_selected:
+ layer_selected = self.tree.GetPyData(self.tree.layer_selected)[0]['maplayer']
+ if layer_selected.GetType() != 'vector' or \
+ (digitToolbar and \
+ digitToolbar.GetLayer() == layer_selected):
+ modify.Enable(False)
+ else:
+ if action == "modifyAttrb":
+ modify.Check(True)
+
+ self.PopupMenu(toolsmenu)
+ toolsmenu.Destroy()
+
+ def AddTmpVectorMapLayer(self, name, cats, useId=False, addLayer=True):
+ """
+ Add temporal vector map layer to map composition
+
+ @param name name of map layer
+ @param useId use feature id instead of category
+ """
+ # color settings from ATM
+ color = UserSettings.Get(group='atm', key='highlight', subkey='color')
+ colorStr = str(color[0]) + ":" + \
+ str(color[1]) + ":" + \
+ str(color[2])
+
+ # icon used in vector display and its size
+ icon = ''
+ size = 0
+ vparam = self.tree.GetPyData(self.tree.layer_selected)[0]['cmd']
+ for p in vparam:
+ if '=' in p:
+ parg,pval = p.split('=')
+ if parg == 'icon': icon = pval
+ elif parg == 'size': size = int(pval)
+
+ pattern = ["d.vect",
+ "map=%s" % name,
+ "color=%s" % colorStr,
+ "fcolor=%s" % colorStr,
+ "width=%d" % UserSettings.Get(group='atm', key='highlight', subkey='width')]
+ if icon != '':
+ pattern.append('icon=%s' % icon)
+ if size > 0:
+ pattern.append('size=%i' % size)
+
+ if useId:
+ cmd = pattern
+ cmd.append('-i')
+ cmd.append('cats=%s' % str(cats))
+ else:
+ cmd = []
+ for layer in cats.keys():
+ cmd.append(copy.copy(pattern))
+ lcats = cats[layer]
+ cmd[-1].append("layer=%d" % layer)
+ cmd[-1].append("cats=%s" % utils.ListOfCatsToRange(lcats))
+
+ # if self.icon:
+ # cmd.append("icon=%s" % (self.icon))
+ # if self.pointsize:
+ # cmd.append("size=%s" % (self.pointsize))
+
+ if addLayer:
+ if useId:
+ return self.Map.AddLayer(type='vector', name=globalvar.QUERYLAYER, command=cmd,
+ l_active=True, l_hidden=True, l_opacity=1.0)
+ else:
+ return self.Map.AddLayer(type='command', name=globalvar.QUERYLAYER, command=cmd,
+ l_active=True, l_hidden=True, l_opacity=1.0)
+ else:
+ return cmd
+
+ def OnAnalyze(self, event):
+ """
+ Analysis tools menu
+ """
+ point = wx.GetMousePosition()
+ toolsmenu = wx.Menu()
+ # Add items to the menu
+ measure = wx.MenuItem(toolsmenu, wx.ID_ANY, Icons["measure"].GetLabel())
+ measure.SetBitmap(Icons["measure"].GetBitmap(self.iconsize))
+ toolsmenu.AppendItem(measure)
+ self.Bind(wx.EVT_MENU, self.OnMeasure, measure)
+
+ profile = wx.MenuItem(toolsmenu, wx.ID_ANY, Icons["profile"].GetLabel())
+ profile.SetBitmap(Icons["profile"].GetBitmap(self.iconsize))
+ toolsmenu.AppendItem(profile)
+ self.Bind(wx.EVT_MENU, self.Profile, profile)
+
+ histogram = wx.MenuItem(toolsmenu, wx.ID_ANY, Icons["histogram"].GetLabel())
+ histogram.SetBitmap(Icons["histogram"].GetBitmap(self.iconsize))
+ toolsmenu.AppendItem(histogram)
+ self.Bind(wx.EVT_MENU, self.Histogram, histogram)
+
+ # Popup the menu. If an item is selected then its handler
+ # will be called before PopupMenu returns.
+ self.PopupMenu(toolsmenu)
+ toolsmenu.Destroy()
+
+ def OnMeasure(self, event):
+ """
+ Init measurement routine that calculates
+ map distance along transect drawn on
+ map display
+ """
+
+ self.totaldist = 0.0 # total measured distance
+
+ # switch GIS Manager to output console to show measure results
+ self._layerManager.notebook.SetSelection(1)
+
+ # change mouse to draw line for measurement
+ self.MapWindow.mouse['use'] = "measure"
+ self.MapWindow.mouse['box'] = "line"
+ self.MapWindow.zoomtype = 0
+ self.MapWindow.pen = wx.Pen(colour='red', width=2, style=wx.SHORT_DASH)
+ self.MapWindow.polypen = wx.Pen(colour='green', width=2, style=wx.SHORT_DASH)
+
+ # change the cursor
+ self.MapWindow.SetCursor(self.cursors["pencil"])
+
+ # initiating output
+ style = self._layerManager.goutput.cmd_output.StyleWarning
+ self._layerManager.goutput.WriteLog(_('Click and drag with left mouse button '
+ 'to measure.%s'
+ 'Double click with left button to clear.') % \
+ (os.linesep), style)
+ if self.Map.projinfo['proj'] != 'xy':
+ units = self.Map.projinfo['units']
+ style = self._layerManager.goutput.cmd_output.StyleCommand
+ self._layerManager.goutput.WriteLog(_('Measuring distance') + ' ('
+ + units + '):',
+ style)
+ else:
+ self._layerManager.goutput.WriteLog(_('Measuring distance:'),
+ style)
+
+ def MeasureDist(self, beginpt, endpt):
+ """!Calculate map distance from screen distance
+ and print to output window
+ """
+ if self._layerManager.notebook.GetSelection() != 1:
+ self._layerManager.notebook.SetSelection(1)
+
+ dist, (north, east) = self.MapWindow.Distance(beginpt, endpt)
+
+ dist = round(dist, 3)
+ d, dunits = self.FormatDist(dist)
+
+ self.totaldist += dist
+ td, tdunits = self.FormatDist(self.totaldist)
+
+ strdist = str(d)
+ strtotdist = str(td)
+
+ if self.Map.projinfo['proj'] == 'xy' or 'degree' not in self.Map.projinfo['unit']:
+ angle = int(math.degrees(math.atan2(north,east)) + 0.5)
+ angle = 180 - angle
+ if angle < 0:
+ angle = 360+angle
+
+ mstring = 'segment = %s %s\ttotal distance = %s %s\tbearing = %d deg' \
+ % (strdist,dunits,strtotdist,tdunits,angle)
+ else:
+ mstring = 'segment = %s %s\ttotal distance = %s %s' \
+ % (strdist,dunits,strtotdist,tdunits)
+
+ self._layerManager.goutput.WriteLog(mstring)
+
+ return dist
+
+ def Profile(self, event):
+ """
+ Init profile canvas and tools
+ """
+ raster = []
+ if self.tree.layer_selected and \
+ self.tree.GetPyData(self.tree.layer_selected)[0]['type'] == 'raster':
+ raster.append(self.tree.GetPyData(self.tree.layer_selected)[0]['maplayer'].name)
+
+ self.profile = profile.ProfileFrame(self,
+ id=wx.ID_ANY, pos=wx.DefaultPosition, size=(700,300),
+ style=wx.DEFAULT_FRAME_STYLE, rasterList=raster)
+ self.profile.Show()
+ # Open raster select dialog to make sure that a raster (and the desired raster)
+ # is selected to be profiled
+ self.profile.OnSelectRaster(None)
+
+ def FormatDist(self, dist):
+ """!Format length numbers and units in a nice way,
+ as a function of length. From code by Hamish Bowman
+ Grass Development Team 2006"""
+
+ mapunits = self.Map.projinfo['units']
+ if mapunits == 'metres': mapunits = 'meters'
+ outunits = mapunits
+ dist = float(dist)
+ divisor = 1.0
+
+ # figure out which units to use
+ if mapunits == 'meters':
+ if dist > 2500.0:
+ outunits = 'km'
+ divisor = 1000.0
+ else: outunits = 'm'
+ elif mapunits == 'feet':
+ # nano-bug: we match any "feet", but US Survey feet is really
+ # 5279.9894 per statute mile, or 10.6' per 1000 miles. As >1000
+ # miles the tick markers are rounded to the nearest 10th of a
+ # mile (528'), the difference in foot flavours is ignored.
+ if dist > 5280.0:
+ outunits = 'miles'
+ divisor = 5280.0
+ else:
+ outunits = 'ft'
+ elif 'degree' in mapunits:
+ if dist < 1:
+ outunits = 'min'
+ divisor = (1/60.0)
+ else:
+ outunits = 'deg'
+
+ # format numbers in a nice way
+ if (dist/divisor) >= 2500.0:
+ outdist = round(dist/divisor)
+ elif (dist/divisor) >= 1000.0:
+ outdist = round(dist/divisor,1)
+ elif (dist/divisor) > 0.0:
+ outdist = round(dist/divisor,int(math.ceil(3-math.log10(dist/divisor))))
+ else:
+ outdist = float(dist/divisor)
+
+ return (outdist, outunits)
+
+
+ def Histogram(self, event):
+ """
+ Init histogram display canvas and tools
+ """
+ self.histogram = histogram.HistFrame(self,
+ id=wx.ID_ANY, size=globalvar.HIST_WINDOW_SIZE,
+ style=wx.DEFAULT_FRAME_STYLE)
+
+ #show new display
+ self.histogram.Show()
+ self.histogram.Refresh()
+ self.histogram.Update()
+
+
+ def OnDecoration(self, event):
+ """
+ Decorations overlay menu
+ """
+ point = wx.GetMousePosition()
+ decmenu = wx.Menu()
+ # Add items to the menu
+ AddScale = wx.MenuItem(decmenu, wx.ID_ANY, Icons["addbarscale"].GetLabel())
+ AddScale.SetBitmap(Icons["addbarscale"].GetBitmap(self.iconsize))
+ decmenu.AppendItem(AddScale)
+ self.Bind(wx.EVT_MENU, self.OnAddBarscale, AddScale)
+
+ AddLegend = wx.MenuItem(decmenu, wx.ID_ANY, Icons["addlegend"].GetLabel())
+ AddLegend.SetBitmap(Icons["addlegend"].GetBitmap(self.iconsize))
+ decmenu.AppendItem(AddLegend)
+ self.Bind(wx.EVT_MENU, self.OnAddLegend, AddLegend)
+
+ AddText = wx.MenuItem(decmenu, wx.ID_ANY, Icons["addtext"].GetLabel())
+ AddText.SetBitmap(Icons["addtext"].GetBitmap(self.iconsize))
+ decmenu.AppendItem(AddText)
+ self.Bind(wx.EVT_MENU, self.OnAddText, AddText)
+
+ # Popup the menu. If an item is selected then its handler
+ # will be called before PopupMenu returns.
+ self.PopupMenu(decmenu)
+ decmenu.Destroy()
+
+ def OnAddBarscale(self, event):
+ """
+ Handler for scale/arrow map decoration menu selection.
+ """
+ if self.dialogs['barscale']:
+ return
+
+ id = 0 # unique index for overlay layer
+
+ # If location is latlon, only display north arrow (scale won't work)
+ # proj = self.Map.projinfo['proj']
+ # if proj == 'll':
+ # barcmd = 'd.barscale -n'
+ # else:
+ # barcmd = 'd.barscale'
+
+ # decoration overlay control dialog
+ self.dialogs['barscale'] = \
+ gdialogs.DecorationDialog(parent=self, title=_('Scale and North arrow'),
+ size=(350, 200),
+ style=wx.DEFAULT_DIALOG_STYLE | wx.CENTRE,
+ cmd=['d.barscale', 'at=0,5'],
+ ovlId=id,
+ name='barscale',
+ checktxt = _("Show/hide scale and North arrow"),
+ ctrltxt = _("scale object"))
+
+ self.dialogs['barscale'].CentreOnParent()
+ ### dialog cannot be show as modal - in the result d.barscale is not selectable
+ ### self.dialogs['barscale'].ShowModal()
+ self.dialogs['barscale'].Show()
+ self.MapWindow.mouse['use'] = 'pointer'
+
+ def OnAddLegend(self, event):
+ """
+ Handler for legend map decoration menu selection.
+ """
+ if self.dialogs['legend']:
+ return
+
+ id = 1 # index for overlay layer in render
+
+ cmd = ['d.legend', 'at=5,50,2,5']
+ if self.tree.layer_selected and \
+ self.tree.GetPyData(self.tree.layer_selected)[0]['type'] == 'raster':
+ cmd.append('map=%s' % self.tree.GetPyData(self.tree.layer_selected)[0]['maplayer'].name)
+
+ # Decoration overlay control dialog
+ self.dialogs['legend'] = \
+ gdialogs.DecorationDialog(parent=self, title=('Legend'),
+ size=(350, 200),
+ style=wx.DEFAULT_DIALOG_STYLE | wx.CENTRE,
+ cmd=cmd,
+ ovlId=id,
+ name='legend',
+ checktxt = _("Show/hide legend"),
+ ctrltxt = _("legend object"))
+
+ self.dialogs['legend'].CentreOnParent()
+ ### dialog cannot be show as modal - in the result d.legend is not selectable
+ ### self.dialogs['legend'].ShowModal()
+ self.dialogs['legend'].Show()
+ self.MapWindow.mouse['use'] = 'pointer'
+
+ def OnAddText(self, event):
+ """
+ Handler for text decoration menu selection.
+ """
+ if self.MapWindow.dragid > -1:
+ id = self.MapWindow.dragid
+ else:
+ # index for overlay layer in render
+ if len(self.MapWindow.textdict.keys()) > 0:
+ id = self.MapWindow.textdict.keys()[-1] + 1
+ else:
+ id = 101
+
+ self.dialogs['text'] = gdialogs.TextLayerDialog(parent=self, ovlId=id,
+ title=_('Add text layer'),
+ size=(400, 200))
+ self.dialogs['text'].CenterOnParent()
+
+ # If OK button pressed in decoration control dialog
+ if self.dialogs['text'].ShowModal() == wx.ID_OK:
+ text = self.dialogs['text'].GetValues()['text']
+ active = self.dialogs['text'].GetValues()['active']
+ coords, w, h = self.MapWindow.TextBounds(self.dialogs['text'].GetValues())
+
+ # delete object if it has no text or is not active
+ if text == '' or active == False:
+ try:
+ self.MapWindow.pdc.ClearId(id)
+ self.MapWindow.pdc.RemoveId(id)
+ del self.MapWindow.textdict[id]
+ except:
+ pass
+ return
+
+ self.MapWindow.pdc.ClearId(id)
+ self.MapWindow.pdc.SetId(id)
+ self.MapWindow.textdict[id] = self.dialogs['text'].GetValues()
+
+ self.MapWindow.Draw(self.MapWindow.pdcDec, img=self.MapWindow.textdict[id],
+ drawid=id, pdctype='text', coords=coords)
+
+ self.MapWindow.UpdateMap(render=False, renderVector=False)
+
+ self.MapWindow.mouse['use'] = 'pointer'
+
+ def GetOptData(self, dcmd, type, params, propwin):
+ """
+ Callback method for decoration overlay command generated by
+ dialog created in menuform.py
+ """
+ # Reset comand and rendering options in render.Map. Always render decoration.
+ # Showing/hiding handled by PseudoDC
+ self.Map.ChangeOverlay(ovltype=type, type='overlay', name='', command=dcmd,
+ l_active=True, l_render=False)
+ self.params[type] = params
+ self.propwin[type] = propwin
+
+ def OnZoomToMap(self, event):
+ """!
+ Set display extents to match selected raster (including NULLs)
+ or vector map.
+ """
+ if self.toolbars['gcpdisp']:
+ self.MapWindow.ZoomToMap(layer = self.Map.GetListOfLayers())
+ else:
+ self.MapWindow.ZoomToMap()
+
+ def OnZoomToRaster(self, event):
+ """!
+ Set display extents to match selected raster map (ignore NULLs)
+ """
+ self.MapWindow.ZoomToMap(ignoreNulls = True)
+
+ def OnZoomToWind(self, event):
+ """!Set display geometry to match computational region
+ settings (set with g.region)
+ """
+ self.MapWindow.ZoomToWind()
+
+ def OnZoomToDefault(self, event):
+ """!Set display geometry to match default region settings
+ """
+ self.MapWindow.ZoomToDefault()
+
+ def OnZoomToSaved(self, event):
+ """!Set display geometry to match extents in
+ saved region file
+ """
+ self.MapWindow.ZoomToSaved()
+
+ def OnDisplayToWind(self, event):
+ """!Set computational region (WIND file) to match display
+ extents
+ """
+ self.MapWindow.DisplayToWind()
+
+ def SaveDisplayRegion(self, event):
+ """!Save display extents to named region file.
+ """
+ self.MapWindow.SaveDisplayRegion()
+
+ def OnZoomMenu(self, event):
+ """!Popup Zoom menu
+ """
+ point = wx.GetMousePosition()
+ zoommenu = wx.Menu()
+ # Add items to the menu
+
+ zoomwind = wx.MenuItem(zoommenu, wx.ID_ANY, _('Zoom to computational region (set with g.region)'))
+ zoommenu.AppendItem(zoomwind)
+ self.Bind(wx.EVT_MENU, self.OnZoomToWind, zoomwind)
+
+ zoomdefault = wx.MenuItem(zoommenu, wx.ID_ANY, _('Zoom to default region'))
+ zoommenu.AppendItem(zoomdefault)
+ self.Bind(wx.EVT_MENU, self.OnZoomToDefault, zoomdefault)
+
+ zoomsaved = wx.MenuItem(zoommenu, wx.ID_ANY, _('Zoom to saved region'))
+ zoommenu.AppendItem(zoomsaved)
+ self.Bind(wx.EVT_MENU, self.OnZoomToSaved, zoomsaved)
+
+ savewind = wx.MenuItem(zoommenu, wx.ID_ANY, _('Set computational region from display'))
+ zoommenu.AppendItem(savewind)
+ self.Bind(wx.EVT_MENU, self.OnDisplayToWind, savewind)
+
+ savezoom = wx.MenuItem(zoommenu, wx.ID_ANY, _('Save display geometry to named region'))
+ zoommenu.AppendItem(savezoom)
+ self.Bind(wx.EVT_MENU, self.SaveDisplayRegion, savezoom)
+
+ # Popup the menu. If an item is selected then its handler
+ # will be called before PopupMenu returns.
+ self.PopupMenu(zoommenu)
+ zoommenu.Destroy()
+
+ def SetProperties(self, render=False, mode=0, showCompExtent=False,
+ constrainRes=False, projection=False):
+ """!Set properies of map display window"""
+ self.autoRender.SetValue(render)
+ self.toggleStatus.SetSelection(mode)
+ self.StatusbarUpdate()
+ self.showRegion.SetValue(showCompExtent)
+ self.compResolution.SetValue(constrainRes)
+ self.projInfo.SetValue(projection)
+ if showCompExtent:
+ self.MapWindow.regionCoords = []
+
+ def IsStandalone(self):
+ """!Check if Map display is standalone"""
+ if self._layerManager:
+ return False
+
+ return True
+
+ def GetLayerManager(self):
+ """!Get reference to Layer Manager
+
+ @return window reference
+ @return None (if standalone)
+ """
+ return self._layerManager
+
+# end of class MapFrame
Property changes on: grass/branches/releasebranch_6_4/gui/wxpython/gui_modules/gcpmapdisp.py
___________________________________________________________________
Added: svn:mime-type
+ text/x-python
Added: svn:eol-style
+ native
Modified: grass/branches/releasebranch_6_4/gui/wxpython/gui_modules/gselect.py
===================================================================
--- grass/branches/releasebranch_6_4/gui/wxpython/gui_modules/gselect.py 2010-09-27 19:28:50 UTC (rev 43714)
+++ grass/branches/releasebranch_6_4/gui/wxpython/gui_modules/gselect.py 2010-09-27 19:32:44 UTC (rev 43715)
@@ -37,7 +37,8 @@
class Select(wx.combo.ComboCtrl):
def __init__(self, parent, id = wx.ID_ANY, size = globalvar.DIALOG_GSELECT_SIZE,
- type = None, multiple = False, mapsets = None, exceptOf = []):
+ type = None, multiple = False, mapsets = None, exceptOf = [],
+ updateOnPopup = True):
"""
Custom control to create a ComboBox with a tree control
to display and select GIS elements within acessible mapsets.
@@ -55,7 +56,8 @@
if type:
self.tcp.GetElementList(type, mapsets, exceptOf)
self.tcp.SetData(type = type, mapsets = mapsets,
- exceptOf = exceptOf, multiple = multiple)
+ exceptOf = exceptOf, multiple = multiple,
+ updateOnPopup = updateOnPopup)
def SetElementList(self, type, mapsets = None, exceptOf = []):
self.tcp.seltree.DeleteAllItems()
@@ -101,6 +103,7 @@
self.curitem = None
self.multiple = False
self.type = None
+ self.updateOnPopup = True
self.mapsets = []
self.exceptOf = []
@@ -154,6 +157,8 @@
def OnPopup(self):
"""Limited only for first selected"""
# update list
+ if not self.updateOnPopup:
+ return
self.seltree.DeleteAllItems()
self.GetElementList(self.type, self.mapsets, self.exceptOf)
@@ -361,6 +366,8 @@
self.exceptOf = kargs['exceptOf']
if kargs.has_key('multiple'):
self.multiple = kargs['multiple']
+ if kargs.has_key('updateOnPopup'):
+ self.updateOnPopup = kargs['updateOnPopup']
class VectorDBInfo:
"""Class providing information about attribute tables
Modified: grass/branches/releasebranch_6_4/gui/wxpython/gui_modules/mapdisp.py
===================================================================
--- grass/branches/releasebranch_6_4/gui/wxpython/gui_modules/mapdisp.py 2010-09-27 19:28:50 UTC (rev 43714)
+++ grass/branches/releasebranch_6_4/gui/wxpython/gui_modules/mapdisp.py 2010-09-27 19:32:44 UTC (rev 43715)
@@ -802,6 +802,15 @@
if len(self.polycoords) > 0:
self.DrawLines(self.pdcTmp)
+ if self.parent.gismanager.gcpmanagement:
+ # -> GCP Manager (redraw GCPs)
+ if self.parent.toolbars['gcpdisp']:
+ if self == self.parent.TgtMapWindow:
+ coordtype = 'target'
+ else:
+ coordtype = 'source'
+ self.parent.gismanager.gcpmanagement.DrawGCP(coordtype)
+
if self.parent.gismanager.georectifying:
# -> georectifier (redraw GCPs)
if self.parent.toolbars['georect']:
@@ -809,7 +818,7 @@
else:
coordtype = 'mapcoord'
self.parent.gismanager.georectifying.DrawGCP(coordtype)
-
+
#
# clear measurement
#
@@ -1111,6 +1120,9 @@
elif event.RightUp():
self.OnRightUp(event)
+ elif event.Entering():
+ self.OnMouseEnter(event)
+
elif event.Moving():
self.OnMouseMoving(event)
@@ -1485,6 +1497,18 @@
self.ClearLines(pdc=self.pdcTmp)
self.DrawLines(pdc=self.pdcTmp)
+ elif self.mouse["use"] == "pointer" and self.parent.gismanager.gcpmanagement:
+ # -> GCP Manager
+ coord = self.Pixel2Cell(self.mouse['end'])
+ if self.parent.toolbars['gcpdisp']:
+ if self.parent.MapWindow == self.parent.SrcMapWindow:
+ coordtype = 'source'
+ else:
+ coordtype = 'target'
+
+ self.parent.gismanager.gcpmanagement.SetGCPData(coordtype, coord, self, confirm=True)
+ self.UpdateMap(render = False, renderVector = False)
+
elif self.mouse["use"] == "pointer" and self.parent.gismanager.georectifying:
# -> georectifying
coord = self.Pixel2Cell(self.mouse['end'])
@@ -2056,6 +2080,20 @@
self.redrawAll = True
+ def OnMouseEnter(self, event):
+ """!
+ Mouse entered window and no mouse buttons were pressed
+ """
+ if self.parent.gismanager.gcpmanagement:
+ if self.parent.toolbars['gcpdisp']:
+ if not self.parent.MapWindow == self:
+ self.parent.MapWindow = self
+ self.parent.Map = self.Map
+ self.parent.UpdateActive(self)
+ self.SetFocus()
+ else:
+ event.Skip()
+
def OnMouseMoving(self, event):
"""
Motion event and no mouse buttons were pressed
@@ -2239,6 +2277,9 @@
elif zoomtype == 0:
dx = x1 - x2
dy = y1 - y2
+ if dx == 0 and dy == 0:
+ dx = x1 - self.Map.width / 2
+ dy = y1 - self.Map.height / 2
newreg['w'], newreg['n'] = self.Pixel2Cell((dx, dy))
newreg['e'], newreg['s'] = self.Pixel2Cell((self.Map.width + dx,
self.Map.height + dy))
@@ -2614,6 +2655,7 @@
#
self.toolbars = { 'map' : None,
'vdigit' : None,
+ 'gcpdisp' : None,
'georect' : None,
'nviz' : None }
for toolb in toolbars:
Modified: grass/branches/releasebranch_6_4/gui/wxpython/gui_modules/preferences.py
===================================================================
--- grass/branches/releasebranch_6_4/gui/wxpython/gui_modules/preferences.py 2010-09-27 19:28:50 UTC (rev 43714)
+++ grass/branches/releasebranch_6_4/gui/wxpython/gui_modules/preferences.py 2010-09-27 19:32:44 UTC (rev 43715)
@@ -392,6 +392,21 @@
'enabled' : True
},
},
+ 'gcpman' : {
+ 'rms' : {
+ 'highestonly' : True,
+ 'sdfactor' : 1,
+ },
+ 'symbol' : {
+ 'color' : (0, 0, 255, 255),
+ 'hcolor' : (255, 0, 0, 255),
+ 'scolor' : (0, 255, 0, 255),
+ 'ucolor' : (255, 165, 0, 255),
+ 'unused' : True,
+ 'size' : 8,
+ 'width' : 2,
+ },
+ },
'georect' : {
'symbol' : {
'color' : (0, 0, 255, 255),
Modified: grass/branches/releasebranch_6_4/gui/wxpython/gui_modules/toolbars.py
===================================================================
--- grass/branches/releasebranch_6_4/gui/wxpython/gui_modules/toolbars.py 2010-09-27 19:28:50 UTC (rev 43714)
+++ grass/branches/releasebranch_6_4/gui/wxpython/gui_modules/toolbars.py 2010-09-27 19:32:44 UTC (rev 43715)
@@ -326,6 +326,162 @@
self.printmap):
self.toolbar.EnableTool(tool, enabled)
+class GCPManToolbar(AbstractToolbar):
+ """!
+ Toolbar for managing ground control points
+
+ @param parent reference to GCP widget
+ """
+ def __init__(self, parent):
+ AbstractToolbar.__init__(self)
+ self.parent = parent
+
+ self.toolbar = wx.ToolBar(parent=self.parent, id=wx.ID_ANY)
+ self.toolbar.SetToolBitmapSize(globalvar.toolbarSize)
+
+ self.InitToolbar(self.parent, self.toolbar, self.ToolbarData())
+
+ # realize the toolbar
+ self.toolbar.Realize()
+
+ def ToolbarData(self):
+ self.gcpSave = wx.NewId()
+ self.gcpReload = wx.NewId()
+ self.gcpAdd = wx.NewId()
+ self.gcpDelete = wx.NewId()
+ self.gcpClear = wx.NewId()
+ self.rms = wx.NewId()
+ self.georect = wx.NewId()
+
+ return (
+ (self.gcpSave, 'grGcpSave', Icons["grGcpSave"].GetBitmap(),
+ wx.ITEM_NORMAL, Icons["grGcpSave"].GetLabel(), Icons["grGcpSave"].GetDesc(),
+ self.parent.SaveGCPs),
+ (self.gcpReload, 'grGcpReload', Icons["grGcpReload"].GetBitmap(),
+ wx.ITEM_NORMAL, Icons["grGcpReload"].GetLabel(), Icons["grGcpReload"].GetDesc(),
+ self.parent.ReloadGCPs),
+ ("", "", "", "", "", "", ""),
+ (self.gcpAdd, 'grGrGcpAdd', Icons["grGcpAdd"].GetBitmap(),
+ wx.ITEM_NORMAL, Icons["grGcpAdd"].GetLabel(), Icons["grGcpAdd"].GetDesc(),
+ self.parent.AddGCP),
+ (self.gcpDelete, 'grGrGcpDelete', Icons["grGcpDelete"].GetBitmap(),
+ wx.ITEM_NORMAL, Icons["grGcpDelete"].GetLabel(), Icons["grGcpDelete"].GetDesc(),
+ self.parent.DeleteGCP),
+ (self.gcpClear, 'grGcpClear', Icons["grGcpClear"].GetBitmap(),
+ wx.ITEM_NORMAL, Icons["grGcpClear"].GetLabel(), Icons["grGcpClear"].GetDesc(),
+ self.parent.ClearGCP),
+ ("", "", "", "", "", "", ""),
+ (self.rms, 'grGcpRms', Icons["grGcpRms"].GetBitmap(),
+ wx.ITEM_NORMAL, Icons["grGcpRms"].GetLabel(), Icons["grGcpRms"].GetDesc(),
+ self.parent.OnRMS),
+ (self.georect, 'grGeorect', Icons["grGeorect"].GetBitmap(),
+ wx.ITEM_NORMAL, Icons["grGeorect"].GetLabel(), Icons["grGeorect"].GetDesc(),
+ self.parent.OnGeorect),
+ )
+
+class GCPDisplayToolbar(AbstractToolbar):
+ """
+ GCP Display toolbar
+ """
+ def __init__(self, mapdisplay):
+ """!
+ GCP Display toolbar constructor
+ """
+ AbstractToolbar.__init__(self)
+
+ self.parent = mapdisplay
+
+ self.toolbar = wx.ToolBar(parent=self.parent, id=wx.ID_ANY)
+ self.toolbar.SetToolBitmapSize(globalvar.toolbarSize)
+
+ self.InitToolbar(self.parent, self.toolbar, self.ToolbarData())
+
+ # add tool to toggle active map window
+ self.togglemapid = wx.NewId()
+ self.togglemap = wx.Choice(parent=self.toolbar, id=self.togglemapid,
+ choices = [_('source'), _('target')],
+ style=wx.CB_READONLY)
+
+ self.toolbar.InsertControl(10, self.togglemap)
+
+ self.toolbar.SetToolShortHelp(self.togglemapid, '%s %s %s' % (_('Set map canvas for '),
+ Icons["zoom_back"].GetLabel(),
+ _(' / Zoom to map')))
+
+ # realize the toolbar
+ self.toolbar.Realize()
+
+ self.action = { 'id' : self.gcpset }
+ self.defaultAction = { 'id' : self.gcpset,
+ 'bind' : self.parent.OnPointer }
+
+ self.OnTool(None)
+
+ self.toolbar.EnableTool(self.zoomback, False)
+
+ def ToolbarData(self):
+ """!Toolbar data"""
+ self.displaymap = wx.NewId()
+ self.rendermap = wx.NewId()
+ self.erase = wx.NewId()
+ self.gcpset = wx.NewId()
+ self.pan = wx.NewId()
+ self.zoomin = wx.NewId()
+ self.zoomout = wx.NewId()
+ self.zoomback = wx.NewId()
+ self.zoomtomap = wx.NewId()
+ self.zoommenu = wx.NewId()
+ self.settings = wx.NewId()
+ self.helpid = wx.NewId()
+ self.quit = wx.NewId()
+
+ # tool, label, bitmap, kind, shortHelp, longHelp, handler
+ return (
+ (self.displaymap, "displaymap", Icons["displaymap"].GetBitmap(),
+ wx.ITEM_NORMAL, Icons["displaymap"].GetLabel(), Icons["displaymap"].GetDesc(),
+ self.parent.OnDraw),
+ (self.rendermap, "rendermap", Icons["rendermap"].GetBitmap(),
+ wx.ITEM_NORMAL, Icons["rendermap"].GetLabel(), Icons["rendermap"].GetDesc(),
+ self.parent.OnRender),
+ (self.erase, "erase", Icons["erase"].GetBitmap(),
+ wx.ITEM_NORMAL, Icons["erase"].GetLabel(), Icons["erase"].GetDesc(),
+ self.parent.OnErase),
+ ("", "", "", "", "", "", ""),
+ (self.gcpset, "grGcpSet", Icons["grGcpSet"].GetBitmap(),
+ wx.ITEM_RADIO, Icons["grGcpSet"].GetLabel(), Icons["grGcpSet"].GetDesc(),
+ self.parent.OnPointer),
+ (self.pan, "pan", Icons["pan"].GetBitmap(),
+ wx.ITEM_RADIO, Icons["pan"].GetLabel(), Icons["pan"].GetDesc(),
+ self.parent.OnPan),
+ (self.zoomin, "zoom_in", Icons["zoom_in"].GetBitmap(),
+ wx.ITEM_RADIO, Icons["zoom_in"].GetLabel(), Icons["zoom_in"].GetDesc(),
+ self.parent.OnZoomIn),
+ (self.zoomout, "zoom_out", Icons["zoom_out"].GetBitmap(),
+ wx.ITEM_RADIO, Icons["zoom_out"].GetLabel(), Icons["zoom_out"].GetDesc(),
+ self.parent.OnZoomOut),
+ (self.zoommenu, "zoommenu", Icons["zoommenu"].GetBitmap(),
+ wx.ITEM_NORMAL, _("Adjust display zoom"), Icons["zoommenu"].GetDesc(),
+ self.parent.OnZoomMenuGCP),
+ ("", "", "", "", "", "", ""),
+ (self.zoomback, "zoom_back", Icons["zoom_back"].GetBitmap(),
+ wx.ITEM_NORMAL, Icons["zoom_back"].GetLabel(), Icons["zoom_back"].GetDesc(),
+ self.parent.OnZoomBack),
+ (self.zoomtomap, "zoomtomap", Icons["zoom_extent"].GetBitmap(),
+ wx.ITEM_NORMAL, _("Zoom to map"), _("Zoom to displayed map"),
+ self.parent.OnZoomToMap),
+ ("", "", "", "", "", "", ""),
+ (self.settings, 'grSettings', Icons["grSettings"].GetBitmap(),
+ wx.ITEM_NORMAL, Icons["grSettings"].GetLabel(), Icons["grSettings"].GetDesc(),
+ self.parent.OnSettings),
+ (self.helpid, 'grHelp', wx.ArtProvider.GetBitmap(id=wx.ART_HELP, client=wx.ART_TOOLBAR, size=globalvar.toolbarSize),
+ wx.ITEM_NORMAL, _('Show Help'), _('Show Help for GCP Manager'),
+ self.parent.OnHelp),
+ ("", "", "", "", "", "", ""),
+ (self.quit, 'grGcpQuit', Icons["grGcpQuit"].GetBitmap(),
+ wx.ITEM_NORMAL, Icons["grGcpQuit"].GetLabel(), Icons["grGcpQuit"].GetDesc(),
+ self.parent.OnQuit)
+ )
+
class GRToolbar(AbstractToolbar):
"""
Georectification Display toolbar
Modified: grass/branches/releasebranch_6_4/gui/wxpython/gui_modules/wxgui_utils.py
===================================================================
--- grass/branches/releasebranch_6_4/gui/wxpython/gui_modules/wxgui_utils.py 2010-09-27 19:28:50 UTC (rev 43714)
+++ grass/branches/releasebranch_6_4/gui/wxpython/gui_modules/wxgui_utils.py 2010-09-27 19:32:44 UTC (rev 43715)
@@ -74,6 +74,7 @@
CT.TR_MULTIPLE,**kargs):
self.items = []
self.itemCounter = 0
+ ctstyle |= style
if 'style' in kargs:
ctstyle |= kargs['style']
del kargs['style']
@@ -81,7 +82,7 @@
if globalvar.hasAgw:
super(LayerTree, self).__init__(parent, id, pos, size, agwStyle = ctstyle)
else:
- super(LayerTree, self).__init__(parent, id, pos, size, style = ctstyle)
+ super(LayerTree, self).__init__(parent, id, pos, size, style = ctstyle, ctstyle = ctstyle)
self.SetName("LayerTree")
### SetAutoLayout() causes that no vertical scrollbar is displayed
Modified: grass/branches/releasebranch_6_4/gui/wxpython/wxgui.py
===================================================================
--- grass/branches/releasebranch_6_4/gui/wxpython/wxgui.py 2010-09-27 19:28:50 UTC (rev 43714)
+++ grass/branches/releasebranch_6_4/gui/wxpython/wxgui.py 2010-09-27 19:32:44 UTC (rev 43715)
@@ -134,6 +134,7 @@
self.workspaceFile = workspace # workspace file
self.menucmd = {} # menuId / cmd
self.georectifying = None # reference to GCP class or None
+ self.gcpmanagement = None # reference to GCP class or None
# creating widgets
# -> self.notebook, self.goutput, self.outpage
@@ -374,6 +375,14 @@
# but in this case just call Skip so the default is done
event.Skip()
+ def OnGCPManager(self, event):
+ """
+ Launch GCP Manager module
+ """
+ import gui_modules.gcpmanager as gcpmanager
+
+ gcpmanager.GCPWizard(self)
+
def OnGeorectify(self, event):
"""
Launch georectifier module
Modified: grass/branches/releasebranch_6_4/gui/wxpython/xml/menudata.xml
===================================================================
--- grass/branches/releasebranch_6_4/gui/wxpython/xml/menudata.xml 2010-09-27 19:28:50 UTC (rev 43714)
+++ grass/branches/releasebranch_6_4/gui/wxpython/xml/menudata.xml 2010-09-27 19:32:44 UTC (rev 43715)
@@ -547,6 +547,11 @@
</menu>
<separator />
<menuitem>
+ <label>Manage Ground Control Points</label>
+ <help>Manage Ground Control Points for Georectification</help>
+ <handler>self.OnGCPManager</handler>
+ </menuitem>
+ <menuitem>
<label>Georectify</label>
<help>Georectify raster and vector maps</help>
<handler>self.OnGeorectify</handler>
More information about the grass-commit
mailing list