GRASS Programmer's Manual  6.4.2(2012)
gcpmanager.py
Go to the documentation of this file.
00001 """!
00002 @package gcpmanager.py
00003 
00004 @brief Georectification module for GRASS GIS. Includes ground control
00005 point management and interactive point and click GCP creation
00006 
00007 Classes:
00008  - GCPWizard
00009  - LocationPage
00010  - GroupPage
00011  - DispMapPage
00012  - GCP
00013  - GCPList
00014  - VectGroup
00015  - EditGCP
00016  - GrSettingsDialog
00017 
00018 (C) 2006-2011 by the GRASS Development Team
00019 This program is free software under the GNU General Public License
00020 (>=v2). Read the file COPYING that comes with GRASS for details.
00021 
00022 @author Michael Barton
00023 @author Updated by Martin Landa <landa.martin gmail.com>
00024 @author Markus Metz redesign georectfier -> GCP Manager
00025 """
00026 
00027 import os
00028 import sys
00029 import tempfile
00030 import shutil
00031 import time
00032 import cStringIO
00033 
00034 import wx
00035 from wx.lib.mixins.listctrl import CheckListCtrlMixin, ColumnSorterMixin, ListCtrlAutoWidthMixin
00036 import wx.lib.colourselect as  csel
00037 import wx.wizard as wiz
00038 
00039 import grass.script as grass
00040 
00041 import globalvar
00042 import render
00043 import toolbars
00044 import menuform
00045 import gselect
00046 import gcmd
00047 import utils
00048 from debug import Debug as Debug
00049 from icon import Icons as Icons
00050 from location_wizard import TitledPage as TitledPage
00051 from preferences import globalSettings as UserSettings
00052 from gcpmapdisp import MapFrame
00053 from mapdisp_window import BufferedWindow
00054 
00055 try:
00056     import subprocess # Not needed if GRASS commands could actually be quiet
00057 except:
00058     CompatPath = globalvar.ETCWXDIR
00059     sys.path.append(CompatPath)
00060     from compat import subprocess
00061 
00062 sys.path.append(os.path.join(globalvar.ETCWXDIR, "icons"))
00063 
00064 #
00065 # global variables
00066 #
00067 global src_map
00068 global tgt_map
00069 global maptype
00070 
00071 src_map = ''
00072 tgt_map = ''
00073 maptype = 'cell'
00074 
00075 def getSmallUpArrowImage():
00076     stream = open(os.path.join(globalvar.ETCIMGDIR, 'small_up_arrow.png'), 'rb')
00077     try:
00078         img = wx.ImageFromStream(stream)
00079     finally:
00080         stream.close()
00081     return img
00082 
00083 def getSmallDnArrowImage():
00084     stream = open(os.path.join(globalvar.ETCIMGDIR, 'small_down_arrow.png'), 'rb')
00085     try:
00086         img = wx.ImageFromStream(stream)
00087     finally:
00088         stream.close()
00089     stream.close()
00090     return img
00091 
00092 class GCPWizard(object):
00093     """
00094     Start wizard here and finish wizard here
00095     """
00096 
00097     def __init__(self, parent):
00098         self.parent = parent # GMFrame
00099 
00100         #
00101         # get environmental variables
00102         #
00103         self.grassdatabase = grass.gisenv()['GISDBASE']
00104         
00105         #
00106         # read original environment settings
00107         #
00108         self.target_gisrc = os.environ['GISRC']
00109         self.gisrc_dict = {}
00110         try:
00111             f = open(self.target_gisrc, 'r')
00112             for line in f.readlines():
00113                 line = line.replace('\n', '').strip()
00114                 if len(line) < 1:
00115                     continue
00116                 key, value = line.split(':', 1)
00117                 self.gisrc_dict[key.strip()] = value.strip()
00118         finally:
00119             f.close()
00120             
00121         self.currentlocation = self.gisrc_dict['LOCATION_NAME']
00122         self.currentmapset = self.gisrc_dict['MAPSET']
00123         # location for xy map to georectify
00124         self.newlocation = ''
00125         # mapset for xy map to georectify
00126         self.newmapset = '' 
00127 
00128         global maptype
00129         global src_map
00130         global tgt_map
00131 
00132         src_map = ''
00133         tgt_map = ''
00134         maptype = 'cell'
00135 
00136         # GISRC file for source location/mapset of map(s) to georectify
00137         self.source_gisrc = ''
00138         self.src_maps = []
00139 
00140         #
00141         # define wizard pages
00142         #
00143         self.wizard = wiz.Wizard(parent=parent, id=wx.ID_ANY, title=_("Setup for georectification"))
00144         self.startpage = LocationPage(self.wizard, self)
00145         self.grouppage = GroupPage(self.wizard, self)
00146         self.mappage = DispMapPage(self.wizard, self)
00147 
00148         #
00149         # set the initial order of the pages
00150         #
00151         self.startpage.SetNext(self.grouppage)
00152         self.grouppage.SetPrev(self.startpage)
00153         self.grouppage.SetNext(self.mappage)
00154         self.mappage.SetPrev(self.grouppage)
00155 
00156         #
00157         # do pages layout
00158         #
00159         self.startpage.DoLayout()
00160         self.grouppage.DoLayout()
00161         self.mappage.DoLayout()
00162         self.wizard.FitToPage(self.startpage)
00163 
00164         # self.Bind(wx.EVT_CLOSE,    self.Cleanup)
00165         # self.parent.Bind(wx.EVT_ACTIVATE, self.OnGLMFocus)
00166 
00167         success = False
00168 
00169         #
00170         # run wizard
00171         #
00172         if self.wizard.RunWizard(self.startpage):
00173             success = self.OnWizFinished()
00174             if success == False:
00175                 gcmd.GMessage(parent = self.parent,
00176                               message = _("Georectifying setup canceled."))
00177                 self.Cleanup()
00178         else:
00179             gcmd.GMessage(parent = self.parent,
00180                           message = _("Georectifying setup canceled."))
00181             self.Cleanup()
00182 
00183         #
00184         # start GCP display
00185         #
00186         if success != False:
00187             # instance of render.Map to be associated with display
00188             self.SwitchEnv('source')
00189             self.SrcMap = render.Map(gisrc=self.source_gisrc) 
00190             self.SwitchEnv('target')
00191             self.TgtMap = render.Map(gisrc=self.target_gisrc)
00192             self.Map = self.SrcMap
00193             
00194             #
00195             # add layer to source map
00196             #
00197             if maptype == 'cell':
00198                 rendertype = 'raster'
00199                 cmdlist = ['d.rast', 'map=%s' % src_map]
00200             else: # -> vector layer
00201                 rendertype = 'vector'
00202                 cmdlist = ['d.vect', 'map=%s' % src_map]
00203             
00204             self.SwitchEnv('source')
00205             name, found = utils.GetLayerNameFromCmd(cmdlist)
00206             self.SrcMap.AddLayer(type=rendertype, command=cmdlist, l_active=True,
00207                                  name=name, l_hidden=False, l_opacity=1.0, l_render=False)
00208 
00209             if tgt_map:
00210                 #
00211                 # add layer to target map
00212                 #
00213                 if maptype == 'cell':
00214                     rendertype = 'raster'
00215                     cmdlist = ['d.rast', 'map=%s' % tgt_map]
00216                 else: # -> vector layer
00217                     rendertype = 'vector'
00218                     cmdlist = ['d.vect', 'map=%s' % tgt_map]
00219                 
00220                 self.SwitchEnv('target')
00221                 name, found = utils.GetLayerNameFromCmd(cmdlist)
00222                 self.TgtMap.AddLayer(type=rendertype, command=cmdlist, l_active=True,
00223                                      name=name, l_hidden=False, l_opacity=1.0, l_render=False)
00224             
00225             #
00226             # start GCP Manager
00227             #
00228             self.gcpmgr = GCP(self.parent, grwiz=self, size=globalvar.MAP_WINDOW_SIZE,
00229                                                toolbars=["gcpdisp"],
00230                                                Map=self.SrcMap, lmgr=self.parent)
00231 
00232             # load GCPs
00233             self.gcpmgr.InitMapDisplay()
00234             self.gcpmgr.CenterOnScreen()
00235             self.gcpmgr.Show()
00236             # need to update AUI here for wingrass
00237             self.gcpmgr._mgr.Update()
00238         else:
00239             self.Cleanup()
00240                             
00241     def SetSrcEnv(self, location, mapset):
00242         """!Create environment to use for location and mapset
00243         that are the source of the file(s) to georectify
00244 
00245         @param location source location
00246         @param mapset source mapset
00247 
00248         @return False on error
00249         @return True on success
00250         """
00251         
00252         self.newlocation = location
00253         self.newmapset = mapset
00254         
00255         # check to see if we are georectifying map in current working location/mapset
00256         if self.newlocation == self.currentlocation and self.newmapset == self.currentmapset:
00257             return False
00258         
00259         self.gisrc_dict['LOCATION_NAME'] = location
00260         self.gisrc_dict['MAPSET'] = mapset
00261         
00262         self.source_gisrc = utils.GetTempfile()
00263 
00264         try:
00265             f = open(self.source_gisrc, mode='w')        
00266             for line in self.gisrc_dict.items():
00267                 f.write(line[0] + ": " + line[1] + "\n")
00268         finally:
00269             f.close()
00270 
00271         return True
00272 
00273     def SwitchEnv(self, grc):
00274         """
00275         Switches between original working location/mapset and
00276         location/mapset that is source of file(s) to georectify
00277         """
00278         # check to see if we are georectifying map in current working location/mapset
00279         if self.newlocation == self.currentlocation and self.newmapset == self.currentmapset:
00280             return False
00281 
00282         if grc == 'target':
00283             os.environ['GISRC'] = str(self.target_gisrc)
00284         elif grc == 'source':
00285             os.environ['GISRC'] = str(self.source_gisrc)
00286 
00287         return True
00288     
00289     def OnWizFinished(self):
00290         # self.Cleanup()
00291 
00292         return True
00293         
00294     def OnGLMFocus(self, event):
00295         """!Layer Manager focus"""
00296         # self.SwitchEnv('target')
00297         
00298         event.Skip()
00299 
00300     def Cleanup(self):
00301         """!Return to current location and mapset"""
00302         self.SwitchEnv('target')
00303         self.parent.gcpmanagement = None
00304 
00305         self.wizard.Destroy()
00306 
00307 class LocationPage(TitledPage):
00308     """
00309     Set map type (raster or vector) to georectify and
00310     select location/mapset of map(s) to georectify.
00311     """
00312     def __init__(self, wizard, parent):
00313         TitledPage.__init__(self, wizard, _("Select map type and location/mapset"))
00314 
00315         self.parent = parent
00316         self.grassdatabase = self.parent.grassdatabase
00317         
00318         self.xylocation = ''
00319         self.xymapset = ''
00320         
00321         #
00322         # layout
00323         #
00324         self.sizer.AddGrowableCol(2)
00325         # map type
00326         self.rb_maptype = wx.RadioBox(parent=self, id=wx.ID_ANY,
00327                                       label=' %s ' % _("Map type to georectify"),
00328                                       choices=[_('raster'), _('vector')],
00329                                       majorDimension=wx.RA_SPECIFY_COLS)
00330         self.sizer.Add(item=self.rb_maptype,
00331                        flag=wx.ALIGN_CENTER | wx.ALL | wx.EXPAND, border=5,
00332                        pos=(1, 1), span=(1, 2))
00333 
00334         # location
00335         self.sizer.Add(item=wx.StaticText(parent=self, id=wx.ID_ANY, label=_('Select source location:')),
00336                        flag=wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL | wx.ALL, border=5,
00337                        pos=(2, 1))
00338         self.cb_location = gselect.LocationSelect(parent = self, gisdbase = self.grassdatabase)
00339         self.sizer.Add(item=self.cb_location,
00340                        flag=wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL | wx.ALL, border=5,
00341                        pos=(2, 2))
00342 
00343         # mapset
00344         self.sizer.Add(item=wx.StaticText(parent=self, id=wx.ID_ANY, label=_('Select source mapset:')),
00345                        flag=wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL | wx.ALL, border=5,
00346                        pos=(3, 1))
00347         self.cb_mapset = gselect.MapsetSelect(parent = self, gisdbase = self.grassdatabase,
00348                                               setItems = False)
00349         self.sizer.Add(item=self.cb_mapset,
00350                        flag=wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL | wx.ALL, border=5,
00351                        pos=(3,2))
00352 
00353         #
00354         # bindings
00355         #
00356         self.Bind(wx.EVT_RADIOBOX, self.OnMaptype, self.rb_maptype)
00357         self.Bind(wx.EVT_COMBOBOX, self.OnLocation, self.cb_location)
00358         self.Bind(wx.EVT_COMBOBOX, self.OnMapset, self.cb_mapset)
00359         self.Bind(wiz.EVT_WIZARD_PAGE_CHANGING, self.OnPageChanging)
00360         self.Bind(wiz.EVT_WIZARD_PAGE_CHANGED, self.OnEnterPage)
00361         # self.Bind(wx.EVT_CLOSE, self.parent.Cleanup)
00362 
00363     def OnMaptype(self,event):
00364         """!Change map type"""
00365         global maptype
00366 
00367         if event.GetInt() == 0:
00368             maptype = 'cell'
00369         else:
00370             maptype = 'vector'
00371         
00372     def OnLocation(self, event):
00373         """!Sets source location for map(s) to georectify"""
00374         self.xylocation = event.GetString()
00375         
00376         #create a list of valid mapsets
00377         tmplist = os.listdir(os.path.join(self.grassdatabase, self.xylocation))
00378         self.mapsetList = []
00379         for item in tmplist:
00380             if os.path.isdir(os.path.join(self.grassdatabase, self.xylocation, item)) and \
00381                 os.path.exists(os.path.join(self.grassdatabase, self.xylocation, item, 'WIND')):
00382                 if item != 'PERMANENT':
00383                     self.mapsetList.append(item)
00384 
00385         self.xymapset = 'PERMANENT'
00386         utils.ListSortLower(self.mapsetList)
00387         self.mapsetList.insert(0, 'PERMANENT')
00388         self.cb_mapset.SetItems(self.mapsetList)
00389         self.cb_mapset.SetStringSelection(self.xymapset)
00390         
00391         if not wx.FindWindowById(wx.ID_FORWARD).IsEnabled():
00392             wx.FindWindowById(wx.ID_FORWARD).Enable(True)
00393 
00394     def OnMapset(self, event):
00395         """!Sets source mapset for map(s) to georectify"""
00396         if self.xylocation == '':
00397             gcmd.GMessage(_('You must select a valid location '
00398                             'before selecting a mapset'),
00399                           parent = self)
00400             return
00401 
00402         self.xymapset = event.GetString()
00403         
00404         if not wx.FindWindowById(wx.ID_FORWARD).IsEnabled():
00405             wx.FindWindowById(wx.ID_FORWARD).Enable(True)
00406 
00407     def OnPageChanging(self, event=None):
00408         if event.GetDirection() and \
00409                (self.xylocation == '' or self.xymapset == ''):
00410             gcmd.GMessage(_('You must select a valid location '
00411                             'and mapset in order to continue'),
00412                           parent = self)
00413             event.Veto()
00414             return
00415         
00416         self.parent.SetSrcEnv(self.xylocation, self.xymapset)
00417         
00418     def OnEnterPage(self, event=None):
00419         if self.xylocation == '' or self.xymapset == '':
00420             wx.FindWindowById(wx.ID_FORWARD).Enable(False)
00421         else:
00422             wx.FindWindowById(wx.ID_FORWARD).Enable(True)
00423 
00424 class GroupPage(TitledPage):
00425     """
00426     Set group to georectify. Create group if desired.
00427     """
00428     def __init__(self, wizard, parent):
00429         TitledPage.__init__(self, wizard, _("Select image/map group to georectify"))
00430 
00431         self.parent = parent
00432         
00433         self.grassdatabase = self.parent.grassdatabase
00434         self.groupList = []
00435         
00436         self.xylocation = ''
00437         self.xymapset = ''
00438         self.xygroup = ''
00439 
00440         # default extension
00441         self.extension = '.georect' + str(os.getpid())
00442 
00443         #
00444         # layout
00445         #
00446         self.sizer.AddGrowableCol(2)
00447         # group
00448         self.sizer.Add(item=wx.StaticText(parent=self, id=wx.ID_ANY, label=_('Select group:')),
00449                        flag=wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL | wx.ALL, border=5,
00450                        pos=(1, 1))
00451         self.cb_group = wx.ComboBox(parent=self, id=wx.ID_ANY,
00452                                     choices=self.groupList, size=(350, -1),
00453                                     style=wx.CB_DROPDOWN | wx.CB_READONLY)
00454         self.sizer.Add(item=self.cb_group,
00455                        flag=wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL | wx.ALL, border=5,
00456                        pos=(1, 2))
00457         
00458         # create group               
00459         self.sizer.Add(item=wx.StaticText(parent=self, id=wx.ID_ANY, label=_('Create group if none exists')),
00460                        flag=wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL | wx.ALL, border=5,
00461                        pos=(2, 1))
00462         btnSizer = wx.BoxSizer(wx.HORIZONTAL)
00463         self.btn_mkgroup = wx.Button(parent=self, id=wx.ID_ANY, label=_("Create/edit group..."))
00464         self.btn_vgroup = wx.Button(parent=self, id=wx.ID_ANY, label=_("Add vector map to group..."))
00465         btnSizer.Add(item=self.btn_mkgroup,
00466                      flag=wx.RIGHT, border=5)
00467 
00468         btnSizer.Add(item=self.btn_vgroup,
00469                      flag=wx.LEFT, border=5)
00470         
00471         self.sizer.Add(item=btnSizer,
00472                        flag=wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL | wx.ALL, border=5,
00473                        pos=(2, 2))
00474         
00475         # extension
00476         self.sizer.Add(item=wx.StaticText(parent=self, id=wx.ID_ANY, label=_('Extension for output maps:')),
00477                        flag=wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL | wx.ALL, border=5,
00478                        pos=(3, 1))
00479         self.ext_txt = wx.TextCtrl(parent=self, id=wx.ID_ANY, value="", size=(350,-1))
00480         self.ext_txt.SetValue(self.extension)
00481         self.sizer.Add(item=self.ext_txt,
00482                        flag=wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL | wx.ALL, border=5,
00483                        pos=(3, 2))
00484 
00485         #
00486         # bindings
00487         #
00488         self.Bind(wx.EVT_COMBOBOX, self.OnGroup, self.cb_group)
00489         self.Bind(wx.EVT_TEXT, self.OnExtension, self.ext_txt)
00490         self.Bind(wiz.EVT_WIZARD_PAGE_CHANGING, self.OnPageChanging)
00491         self.Bind(wiz.EVT_WIZARD_PAGE_CHANGED, self.OnEnterPage)
00492         self.Bind(wx.EVT_CLOSE, self.parent.Cleanup)
00493 
00494         # hide vector group button by default
00495         self.btn_vgroup.Hide()
00496 
00497     def OnGroup(self, event):        
00498         self.xygroup = event.GetString()
00499         
00500     def OnMkGroup(self, event):
00501         """!Create new group in source location/mapset"""
00502         menuform.GUI(parent = self.parent.parent, modal = True).ParseCommand(['i.group'],
00503                                                                              completed = (self.GetOptData, None, ''))
00504         
00505     def OnVGroup(self, event):
00506         """!Add vector maps to group"""
00507         dlg = VectGroup(parent = self,
00508                         id = wx.ID_ANY,
00509                         grassdb = self.grassdatabase,
00510                         location = self.xylocation,
00511                         mapset = self.xymapset,
00512                         group = self.xygroup)
00513 
00514         if dlg.ShowModal() != wx.ID_OK:
00515             return
00516 
00517         dlg.MakeVGroup()
00518         self.OnEnterPage()
00519         
00520     def GetOptData(self, dcmd, layer, params, propwin):
00521         """!Process i.group"""
00522         # update the page
00523         if dcmd:
00524             gcmd.Command(dcmd)
00525 
00526         self.OnEnterPage()
00527         self.Update()
00528         
00529     def OnExtension(self, event):
00530         self.extension = event.GetString()
00531 
00532     def OnPageChanging(self, event=None):
00533         if event.GetDirection() and self.xygroup == '':
00534             gcmd.GMessage(_('You must select a valid image/map '
00535                             'group in order to continue'),
00536                           parent = self)
00537             event.Veto()
00538             return
00539 
00540         if event.GetDirection() and self.extension == '':
00541             gcmd.GMessage(_('You must enter an map name '
00542                             'extension in order to continue'),
00543                           parent = self)
00544             event.Veto()
00545             return
00546 
00547     def OnEnterPage(self, event=None):
00548         global maptype
00549         
00550         self.groupList = []
00551 
00552         self.xylocation = self.parent.gisrc_dict['LOCATION_NAME']
00553         self.xymapset = self.parent.gisrc_dict['MAPSET']
00554 
00555         # create a list of groups in selected mapset
00556         if os.path.isdir(os.path.join(self.grassdatabase,
00557                                       self.xylocation,
00558                                       self.xymapset,
00559                                       'group')):
00560             tmplist = os.listdir(os.path.join(self.grassdatabase,
00561                                               self.xylocation,
00562                                               self.xymapset,
00563                                               'group'))
00564             for item in tmplist:
00565                 if os.path.isdir(os.path.join(self.grassdatabase,
00566                                               self.xylocation,
00567                                               self.xymapset,
00568                                               'group',
00569                                               item)):
00570                     self.groupList.append(item)
00571         
00572         if maptype == 'cell':
00573             self.btn_vgroup.Hide()
00574             self.Bind(wx.EVT_BUTTON, self.OnMkGroup, self.btn_mkgroup)
00575 
00576         elif maptype == 'vector':
00577             self.btn_vgroup.Show()
00578             self.Bind(wx.EVT_BUTTON, self.OnMkGroup, self.btn_mkgroup)
00579             self.Bind(wx.EVT_BUTTON, self.OnVGroup, self.btn_vgroup)
00580         
00581         utils.ListSortLower(self.groupList)
00582         self.cb_group.SetItems(self.groupList)
00583         
00584         if len(self.groupList) > 0 and \
00585                 self.xygroup == '':
00586             self.cb_group.SetSelection(0)
00587             self.xygroup = self.groupList[0]
00588         
00589         if self.xygroup == '' or \
00590                 self.extension == '':
00591             wx.FindWindowById(wx.ID_FORWARD).Enable(False)
00592         else:
00593             wx.FindWindowById(wx.ID_FORWARD).Enable(True)
00594         
00595         # switch to source
00596         self.parent.SwitchEnv('source')
00597     
00598 class DispMapPage(TitledPage):
00599     """
00600     Select ungeoreferenced map to display for interactively
00601     setting ground control points (GCPs).
00602     """
00603     def __init__(self, wizard, parent):
00604         TitledPage.__init__(self, wizard,
00605                             _("Select maps to display for ground control point (GCP) creation"))
00606 
00607         self.parent = parent
00608         global maptype
00609 
00610         #
00611         # layout
00612         #
00613         self.sizer.Add(item=wx.StaticText(parent=self, id=wx.ID_ANY, label=_('Select source map to display:')),
00614                        flag=wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL | wx.ALL, border=5,
00615                        pos=(1, 1))
00616         
00617         self.srcselection = gselect.Select(self, id=wx.ID_ANY,
00618                                     size=globalvar.DIALOG_GSELECT_SIZE, type=maptype, updateOnPopup = False)
00619         
00620         self.sizer.Add(item=self.srcselection,
00621                        flag=wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL | wx.ALL, border=5,
00622                        pos=(1, 2))
00623 
00624         self.sizer.Add(item=wx.StaticText(parent=self, id=wx.ID_ANY, label=_('Select target map to display:')),
00625                        flag=wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL | wx.ALL, border=5,
00626                        pos=(2, 1))
00627 
00628         self.tgtselection = gselect.Select(self, id=wx.ID_ANY,
00629                                         size=globalvar.DIALOG_GSELECT_SIZE, type=maptype, updateOnPopup = False)
00630         
00631         self.sizer.Add(item=self.tgtselection,
00632                        flag=wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL | wx.ALL, border=5,
00633                        pos=(2, 2))
00634 
00635         #
00636         # bindings
00637         #
00638         self.srcselection.Bind(wx.EVT_TEXT, self.OnSrcSelection)
00639         self.tgtselection.Bind(wx.EVT_TEXT, self.OnTgtSelection)
00640         self.Bind(wiz.EVT_WIZARD_PAGE_CHANGING, self.OnPageChanging)
00641         self.Bind(wiz.EVT_WIZARD_PAGE_CHANGED, self.OnEnterPage)
00642         self.Bind(wx.EVT_CLOSE, self.parent.Cleanup)
00643 
00644     def OnSrcSelection(self,event):
00645         """!Source map to display selected"""
00646         global src_map
00647         global maptype
00648 
00649         src_map = event.GetString()
00650 
00651         if src_map == '':
00652             wx.FindWindowById(wx.ID_FORWARD).Enable(False)
00653         else:
00654             wx.FindWindowById(wx.ID_FORWARD).Enable(True)
00655 
00656         try:
00657         # set computational region to match selected map and zoom display to region
00658             if maptype == 'cell':
00659                 p = gcmd.Command(['g.region', 'rast=src_map'])
00660             elif maptype == 'vector':
00661                 p = gcmd.Command(['g.region', 'vect=src_map'])
00662             
00663             if p.returncode == 0:
00664                 print 'returncode = ', str(p.returncode)
00665                 self.parent.Map.region = self.parent.Map.GetRegion()
00666         except:
00667             pass
00668 
00669     def OnTgtSelection(self,event):
00670         """!Source map to display selected"""
00671         global tgt_map
00672 
00673         tgt_map = event.GetString()
00674 
00675     def OnPageChanging(self, event=None):
00676         global src_map
00677         global tgt_map
00678 
00679         if event.GetDirection() and (src_map == ''):
00680             gcmd.GMessage(_('You must select a source map '
00681                             'in order to continue'),
00682                           parent = self)
00683             event.Veto()
00684             return
00685 
00686         self.parent.SwitchEnv('target')
00687         
00688     def OnEnterPage(self, event=None):
00689         global maptype
00690         global src_map
00691         global tgt_map
00692 
00693         self.srcselection.SetElementList(maptype)
00694         ret = gcmd.RunCommand('i.group',
00695                               parent = self,
00696                               read = True,
00697                               group = self.parent.grouppage.xygroup,
00698                               flags = 'g')            
00699 
00700         if ret:
00701             self.parent.src_maps = ret.splitlines()
00702         else:
00703             gcmd.GError(parent = self,
00704                         message = _('No maps in selected group <%s>.\n'
00705                                     'Please edit group or select another group.') %
00706                         self.parent.grouppage.xygroup)
00707             return
00708 
00709         # filter out all maps not in group
00710         self.srcselection.tcp.GetElementList(elements = self.parent.src_maps)
00711         src_map = self.parent.src_maps[0]
00712         self.srcselection.SetValue(src_map)
00713 
00714         self.parent.SwitchEnv('target')
00715         self.tgtselection.SetElementList(maptype)
00716         self.tgtselection.GetElementList()
00717         self.parent.SwitchEnv('source')
00718 
00719         if src_map == '':
00720             wx.FindWindowById(wx.ID_FORWARD).Enable(False)
00721         else:
00722             wx.FindWindowById(wx.ID_FORWARD).Enable(True)
00723 
00724 class GCP(MapFrame, wx.Frame, ColumnSorterMixin):
00725     """!
00726     Manages ground control points for georectifying. Calculates RMS statics.
00727     Calls i.rectify or v.transform to georectify map.
00728     """
00729     def __init__(self, parent, grwiz = None, id = wx.ID_ANY,
00730                  title = _("Manage Ground Control Points"),
00731                  size = (700, 300), toolbars=["gcpdisp"], Map=None, lmgr=None):
00732 
00733         self.grwiz = grwiz # GR Wizard
00734 
00735         if tgt_map == '':
00736             self.show_target = False
00737         else:
00738             self.show_target = True
00739         
00740         #wx.Frame.__init__(self, parent, id, title, size = size, name = "GCPFrame")
00741         MapFrame.__init__(self, parent, id, title, size = size,
00742                             Map=Map, toolbars=["gcpdisp"], lmgr=lmgr, name='GCPMapWindow')
00743 
00744         #
00745         # init variables
00746         #
00747         self.parent = parent # GMFrame
00748         self.parent.gcpmanagement = self
00749 
00750         self.grassdatabase = self.grwiz.grassdatabase
00751 
00752         self.currentlocation = self.grwiz.currentlocation
00753         self.currentmapset = self.grwiz.currentmapset
00754 
00755         self.newlocation = self.grwiz.newlocation
00756         self.newmapset = self.grwiz.newmapset
00757 
00758         self.xylocation = self.grwiz.gisrc_dict['LOCATION_NAME']
00759         self.xymapset = self.grwiz.gisrc_dict['MAPSET']
00760         self.xygroup = self.grwiz.grouppage.xygroup
00761         self.src_maps = self.grwiz.src_maps
00762         self.extension = self.grwiz.grouppage.extension
00763         self.outname = ''
00764         self.VectGRList = []
00765 
00766         self.file = {
00767             'points' : os.path.join(self.grassdatabase,
00768                                     self.xylocation,
00769                                     self.xymapset,
00770                                     'group',
00771                                     self.xygroup,
00772                                     'POINTS'),
00773             'points_bak' : os.path.join(self.grassdatabase,
00774                                     self.xylocation,
00775                                     self.xymapset,
00776                                     'group',
00777                                     self.xygroup,
00778                                     'POINTS_BAK'),
00779             'rgrp' : os.path.join(self.grassdatabase,
00780                                   self.xylocation,
00781                                   self.xymapset,
00782                                   'group',
00783                                   self.xygroup,
00784                                   'REF'),
00785             'vgrp' : os.path.join(self.grassdatabase,
00786                                   self.xylocation,
00787                                   self.xymapset,
00788                                   'group',
00789                                   self.xygroup,
00790                                   'VREF'),
00791             'target' : os.path.join(self.grassdatabase,
00792                                     self.xylocation,
00793                                     self.xymapset,
00794                                     'group',
00795                                     self.xygroup,
00796                                     'TARGET'),
00797             }
00798 
00799         # make a backup of the current points file
00800         if os.path.exists(self.file['points']):
00801             shutil.copy(self.file['points'], self.file['points_bak'])
00802 
00803         # polynomial order transformation for georectification
00804         self.gr_order = 1 
00805         # interpolation method for georectification
00806         self.gr_method = 'nearest'
00807         # region clipping for georectified map
00808         self.clip_to_region = False
00809         # number of GCPs selected to be used for georectification (checked)
00810         self.GCPcount = 0
00811         # forward RMS error
00812         self.fwd_rmserror = 0.0
00813         # backward RMS error
00814         self.bkw_rmserror = 0.0
00815         # list map coords and ID of map display they came from
00816         self.mapcoordlist = []
00817         self.mapcoordlist.append([ 0,        # GCP number
00818                                    0.0,      # source east
00819                                    0.0,      # source north
00820                                    0.0,      # target east
00821                                    0.0,      # target north
00822                                    0.0,      # forward error
00823                                    0.0 ] )   # backward error
00824 
00825         # init vars to highlight high RMS errors
00826         self.highest_only = True
00827         self.show_unused =  True
00828         self.highest_key = -1
00829         self.rmsthresh = 0
00830         self.rmsmean = 0
00831         self.rmssd = 0
00832 
00833         self.SetTarget(self.xygroup, self.currentlocation, self.currentmapset)
00834 
00835         self.itemDataMap = None
00836 
00837         # images for column sorting
00838         # CheckListCtrlMixin must set an ImageList first
00839         self.il = self.list.GetImageList(wx.IMAGE_LIST_SMALL)
00840 
00841         SmallUpArrow = wx.BitmapFromImage(getSmallUpArrowImage())            
00842         SmallDnArrow = wx.BitmapFromImage(getSmallDnArrowImage())            
00843         self.sm_dn = self.il.Add(SmallDnArrow)
00844         self.sm_up = self.il.Add(SmallUpArrow)
00845 
00846         # set mouse characteristics
00847         self.mapwin = self.SrcMapWindow
00848         self.mapwin.mouse['box'] = 'point'
00849         self.mapwin.mouse["use"] == "pointer"
00850         self.mapwin.zoomtype = 0
00851         self.mapwin.pen = wx.Pen(colour='black', width=2, style=wx.SOLID)
00852         self.mapwin.SetCursor(self.cursors["cross"])
00853 
00854         self.mapwin = self.TgtMapWindow
00855         
00856         # set mouse characteristics
00857         self.mapwin.mouse['box'] = 'point'
00858         self.mapwin.mouse["use"] == "pointer"
00859         self.mapwin.zoomtype = 0
00860         self.mapwin.pen = wx.Pen(colour='black', width=2, style=wx.SOLID)
00861         self.mapwin.SetCursor(self.cursors["cross"])
00862 
00863         #
00864         # show new display & draw map
00865         #
00866         if self.show_target:
00867             self.MapWindow = self.TgtMapWindow
00868             self.Map = self.TgtMap
00869             self.OnZoomToMap(None)
00870 
00871         self.MapWindow = self.SrcMapWindow
00872         self.Map = self.SrcMap
00873         self.OnZoomToMap(None)
00874 
00875         #
00876         # bindings
00877         #
00878         self.Bind(wx.EVT_ACTIVATE, self.OnFocus)
00879         self.Bind(wx.EVT_CLOSE, self.OnQuit)
00880 
00881     def __del__(self):
00882         """!Disable GCP manager mode"""
00883         self.parent.gcpmanagement = None
00884         
00885     def CreateGCPList(self):
00886         """!Create GCP List Control"""
00887 
00888         return GCPList(parent=self, gcp=self)
00889 
00890     # Used by the ColumnSorterMixin, see wx/lib/mixins/listctrl.py
00891     def GetListCtrl(self):
00892         return self.list
00893 
00894     # Used by the ColumnSorterMixin, see wx/lib/mixins/listctrl.py
00895     def GetSortImages(self):
00896         return (self.sm_dn, self.sm_up)
00897 
00898     def InitMapDisplay(self):
00899         self.list.LoadData()
00900         
00901         # initialize column sorter
00902         self.itemDataMap = self.mapcoordlist
00903         ncols = self.list.GetColumnCount()
00904         ColumnSorterMixin.__init__(self, ncols)
00905         # init to ascending sort on first click
00906         self._colSortFlag = [1] * ncols
00907 
00908     def SetTarget(self, tgroup, tlocation, tmapset):
00909         """
00910         Sets rectification target to current location and mapset
00911         """
00912         # check to see if we are georectifying map in current working location/mapset
00913         if self.newlocation == self.currentlocation and self.newmapset == self.currentmapset:
00914             gcmd.RunCommand('i.target',
00915                             parent = self,
00916                             flags = 'c',
00917                             group = tgroup)
00918         else:
00919             self.grwiz.SwitchEnv('source')
00920             gcmd.RunCommand('i.target',
00921                             parent = self,
00922                             group = tgroup,
00923                             location = tlocation,
00924                             mapset = tmapset)
00925             self.grwiz.SwitchEnv('target')
00926 
00927     def AddGCP(self, event):
00928         """
00929         Appends an item to GCP list
00930         """
00931         keyval = self.list.AddGCPItem() + 1
00932         # source east, source north, target east, target north, forward error, backward error
00933         self.mapcoordlist.append([ keyval,             # GCP number
00934                                    0.0,                # source east
00935                                    0.0,                # source north
00936                                    0.0,                # target east
00937                                    0.0,                # target north
00938                                    0.0,                # forward error
00939                                    0.0 ] )             # backward error
00940 
00941         if self.statusbarWin['toggle'].GetSelection() == 7: # go to
00942             self.StatusbarUpdate()
00943 
00944     def DeleteGCP(self, event):
00945         """
00946         Deletes selected item in GCP list
00947         """
00948         minNumOfItems = self.OnGROrder(None)
00949 
00950         if self.list.GetItemCount() <= minNumOfItems:
00951             gcmd.GMessage(parent = self,
00952                           message=_("At least %d GCPs required. Operation cancelled.") % minNumOfItems)
00953             return
00954 
00955         key = self.list.DeleteGCPItem()
00956         del self.mapcoordlist[key]
00957 
00958         # update key and GCP number
00959         for newkey in range(key, len(self.mapcoordlist)):
00960             index = self.list.FindItemData(-1, newkey + 1)
00961             self.mapcoordlist[newkey][0] = newkey
00962             self.list.SetStringItem(index, 0, str(newkey))
00963             self.list.SetItemData(index, newkey)
00964 
00965         # update selected
00966         if self.list.GetItemCount() > 0:
00967             if self.list.selected < self.list.GetItemCount():
00968                 self.list.selectedkey = self.list.GetItemData(self.list.selected)
00969             else:
00970                 self.list.selected = self.list.GetItemCount() - 1
00971                 self.list.selectedkey = self.list.GetItemData(self.list.selected)
00972                 
00973             self.list.SetItemState(self.list.selected,
00974                               wx.LIST_STATE_SELECTED,
00975                               wx.LIST_STATE_SELECTED)
00976         else:
00977             self.list.selected = wx.NOT_FOUND
00978             self.list.selectedkey = -1
00979 
00980         self.UpdateColours()
00981 
00982         if self.statusbarWin['toggle'].GetSelection() == 7: # go to
00983             self.StatusbarUpdate()
00984             if self.list.selectedkey > 0:
00985                 self.statusbarWin['goto'].SetValue(self.list.selectedkey)
00986             #self.statusbarWin['goto'].SetValue(0)
00987 
00988     def ClearGCP(self, event):
00989         """
00990         Clears all values in selected item of GCP list and unchecks it
00991         """
00992         index = self.list.GetSelected()
00993 
00994         for i in range(4):
00995             self.list.SetStringItem(index, i, '0.0')
00996         self.list.SetStringItem(index, 4, '')
00997         self.list.SetStringItem(index, 5, '')
00998         self.list.CheckItem(index, False)
00999         key = self.list.GetItemData(index)
01000 
01001         # GCP number, source E, source N, target E, target N, fwd error, bkwd error
01002         self.mapcoordlist[key] = [key, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]
01003 
01004     def DrawGCP(self, coordtype):
01005         """
01006         Updates GCP and map coord maps and redraws
01007         active (checked) GCP markers
01008         """
01009         self.highest_only = UserSettings.Get(group='gcpman', key='rms', subkey='highestonly')
01010 
01011         self.show_unused =  UserSettings.Get(group='gcpman', key='symbol', subkey='unused')
01012         col = UserSettings.Get(group='gcpman', key='symbol', subkey='color')
01013         wxLowCol = wx.Colour(col[0], col[1], col[2], 255)
01014         col = UserSettings.Get(group='gcpman', key='symbol', subkey='hcolor')
01015         wxHiCol = wx.Colour(col[0], col[1], col[2], 255)
01016         col = UserSettings.Get(group='gcpman', key='symbol', subkey='scolor')
01017         wxSelCol = wx.Colour(col[0], col[1], col[2], 255)
01018         col = UserSettings.Get(group='gcpman', key='symbol', subkey='ucolor')
01019         wxUnCol = wx.Colour(col[0], col[1], col[2], 255)
01020         spx = UserSettings.Get(group='gcpman', key='symbol', subkey='size')
01021         wpx = UserSettings.Get(group='gcpman', key='symbol', subkey='width')
01022         font = self.GetFont()
01023         font.SetPointSize(int(spx) + 2)
01024 
01025         penOrig = polypenOrig = None
01026 
01027         mapWin = None
01028         
01029         if coordtype == 'source':
01030             mapWin = self.SrcMapWindow
01031             e_idx = 1
01032             n_idx = 2
01033         elif coordtype == 'target':
01034             mapWin = self.TgtMapWindow
01035             e_idx = 3
01036             n_idx = 4
01037 
01038         if not mapWin:
01039             gcmd.GError(parent = self,
01040                         message="%s%s." % (_("mapwin not defined for "),
01041                                            str(idx)))
01042             return
01043 
01044         #for gcp in self.mapcoordlist:
01045         for idx in range(self.list.GetItemCount()):
01046 
01047             key = self.list.GetItemData(idx)
01048             gcp = self.mapcoordlist[key]
01049 
01050             if not self.list.IsChecked(idx):
01051                 if self.show_unused:
01052                     wxCol = wxUnCol
01053                 else:
01054                     continue
01055             else:
01056                 if self.highest_only == True:
01057                     if key == self.highest_key:
01058                         wxCol = wxHiCol
01059                     else:
01060                         wxCol = wxLowCol
01061                 elif self.rmsthresh > 0:
01062                     if (gcp[5] > self.rmsthresh):
01063                         wxCol = wxHiCol
01064                     else:
01065                         wxCol = wxLowCol
01066 
01067             if idx == self.list.selected:
01068                 wxCol = wxSelCol
01069 
01070             if not penOrig:
01071                 penOrig = mapWin.pen
01072                 polypenOrig = mapWin.polypen
01073                 mapWin.pen = wx.Pen(colour=wxCol, width=wpx, style=wx.SOLID)
01074                 mapWin.polypen = wx.Pen(colour=wxCol, width=wpx, style=wx.SOLID) # ?
01075 
01076             mapWin.pen.SetColour(wxCol)
01077             mapWin.polypen.SetColour(wxCol)
01078 
01079             coord = mapWin.Cell2Pixel((gcp[e_idx], gcp[n_idx]))
01080             mapWin.DrawCross(pdc=mapWin.pdcTmp, coords=coord,
01081                              size=spx, text={ 'text' : '%s' % str(gcp[0]),
01082                                             'active' : True,
01083                                             'font' : font,
01084                                             'color': wxCol,
01085                                             'coords': [coord[0] + 5,
01086                                                        coord[1] + 5,
01087                                                        5,
01088                                                        5]})
01089             
01090         if penOrig:
01091             mapWin.pen = penOrig
01092             mapWin.polypen = polypenOrig
01093         
01094     def SetGCPData(self, coordtype, coord, mapdisp=None, confirm=False):
01095         """
01096         Inserts coordinates from file, mouse click on map, or after editing
01097         into selected item of GCP list and checks it for use
01098         """
01099         
01100         index = self.list.GetSelected()
01101         if index == wx.NOT_FOUND:
01102             return
01103 
01104         coord0 = coord[0]
01105         coord1 = coord[1]
01106 
01107         key = self.list.GetItemData(index)
01108         if confirm:
01109             if self.MapWindow == self.SrcMapWindow:
01110                 currloc = _("source")
01111             else:
01112                 currloc = _("target")
01113             ret = wx.MessageBox(parent=self,
01114                                 caption=_("Set GCP coordinates"),
01115                                 message=_('Set %(coor)s coordinates for GCP No. %(key)s? \n\n'
01116                                           'East: %(coor0)s \n'
01117                                           'North: %(coor1)s') % \
01118                                     { 'coor' : currloc,
01119                                       'key' : str(key),
01120                                       'coor0' : str(coord0),
01121                                       'coor1' : str(coord1) },
01122                                 style=wx.ICON_QUESTION | wx.YES_NO | wx.CENTRE)
01123 
01124             # for wingrass
01125             if os.name == 'nt':
01126                 self.MapWindow.SetFocus()
01127             if ret == wx.NO:
01128                 return
01129             
01130         if coordtype == 'source':
01131             self.list.SetStringItem(index, 1, str(coord0))
01132             self.list.SetStringItem(index, 2, str(coord1))
01133             self.mapcoordlist[key][1] = coord[0]
01134             self.mapcoordlist[key][2] = coord[1]
01135         elif coordtype == 'target':
01136             self.list.SetStringItem(index, 3, str(coord0))
01137             self.list.SetStringItem(index, 4, str(coord1))
01138             self.mapcoordlist[key][3] = coord[0]
01139             self.mapcoordlist[key][4] = coord[1]
01140             
01141         self.list.SetStringItem(index, 5, '0')
01142         self.list.SetStringItem(index, 6, '0')
01143         self.mapcoordlist[key][5] = 0.0
01144         self.mapcoordlist[key][6] = 0.0
01145 
01146         # self.list.ResizeColumns()
01147 
01148     def SaveGCPs(self, event):
01149         """
01150         Make a POINTS file or save GCP coordinates to existing POINTS file
01151         """
01152 
01153         self.GCPcount = 0
01154         try:
01155             f = open(self.file['points'], mode='w')
01156             # use os.linesep or '\n' here ???
01157             f.write('# Ground Control Points File\n')
01158             f.write("# \n")
01159             f.write("# target location: " + self.currentlocation + '\n')
01160             f.write("# target mapset: " + self.currentmapset + '\n')
01161             f.write("#\tsource\t\ttarget\t\tstatus\n")
01162             f.write("#\teast\tnorth\teast\tnorth\t(1=ok, 0=ignore)\n")
01163             f.write("#-----------------------     -----------------------     ---------------\n")
01164 
01165             for index in range(self.list.GetItemCount()):
01166                 if self.list.IsChecked(index) == True:
01167                     check = "1"
01168                     self.GCPcount += 1
01169                 else:
01170                     check = "0"
01171                 coord0 = self.list.GetItem(index, 1).GetText()
01172                 coord1 = self.list.GetItem(index, 2).GetText()
01173                 coord2 = self.list.GetItem(index, 3).GetText()
01174                 coord3 = self.list.GetItem(index, 4).GetText()
01175                 f.write(coord0 + ' ' + coord1 + '     ' + coord2 + ' ' + coord3 + '     ' + check + '\n')
01176 
01177         except IOError, err:
01178             gcmd.GError(parent = self,
01179                         message="%s <%s>. %s%s" % (_("Writing POINTS file failed"),
01180                                                    self.file['points'], os.linesep, err))
01181             return
01182 
01183         f.close()
01184 
01185         # if event != None save also to backup file
01186         if event:
01187             shutil.copy(self.file['points'], self.file['points_bak'])
01188             self.parent.goutput.WriteLog(_('POINTS file saved for group <%s>') % self.xygroup)
01189             #self.SetStatusText(_('POINTS file saved'))
01190 
01191     def ReadGCPs(self):
01192         """
01193         Reads GCPs and georectified coordinates from POINTS file
01194         """
01195         
01196         self.GCPcount = 0
01197 
01198         sourceMapWin = self.SrcMapWindow
01199         targetMapWin = self.TgtMapWindow
01200         #targetMapWin = self.parent.curr_page.maptree.mapdisplay.MapWindow
01201 
01202         if not sourceMapWin:
01203             gcmd.GError(parent = self,
01204                         message = "%s. %s%s" % (_("source mapwin not defined"),
01205                                                 os.linesep, err))
01206         
01207         if not targetMapWin:
01208             gcmd.GError(parent = self,
01209                         message="%s. %s%s" % (_("target mapwin not defined"),
01210                                               os.linesep, err))
01211         
01212         try:
01213             f = open(self.file['points'], 'r')
01214             GCPcnt = 0
01215             
01216             for line in f.readlines():
01217                 if line[0] == '#' or line =='':
01218                     continue
01219                 line = line.replace('\n', '').strip()
01220                 coords = map(float, line.split())
01221                 if coords[4] == 1:
01222                     check = True
01223                     self.GCPcount +=1
01224                 else:
01225                     check = False
01226 
01227                 self.AddGCP(event=None)
01228                 self.SetGCPData('source', (coords[0], coords[1]), sourceMapWin)
01229                 self.SetGCPData('target', (coords[2], coords[3]), targetMapWin)
01230                 index = self.list.GetSelected()
01231                 if index != wx.NOT_FOUND:
01232                     self.list.CheckItem(index, check)
01233                 GCPcnt += 1
01234 
01235         except IOError, err:
01236             gcmd.GError(parent = self,
01237                         message = "%s <%s>. %s%s" % (_("Reading POINTS file failed"),
01238                                                      self.file['points'], os.linesep, err))
01239             return
01240 
01241         f.close()
01242 
01243         if GCPcnt == 0:
01244             # 3 gcp is minimum
01245             for i in range(3):
01246                 self.AddGCP(None)
01247 
01248         if self.CheckGCPcount():
01249             # calculate RMS
01250             self.RMSError(self.xygroup, self.gr_order)
01251 
01252     def ReloadGCPs(self, event):
01253         """!Reload data from file"""
01254 
01255         # use backup
01256         shutil.copy(self.file['points_bak'], self.file['points'])
01257 
01258         # delete all items in mapcoordlist
01259         self.mapcoordlist = []
01260         self.mapcoordlist.append([ 0,        # GCP number
01261                                    0.0,      # source east
01262                                    0.0,      # source north
01263                                    0.0,      # target east
01264                                    0.0,      # target north
01265                                    0.0,      # forward error
01266                                    0.0 ] )   # backward error
01267 
01268         self.list.LoadData()
01269         self.itemDataMap = self.mapcoordlist
01270 
01271         if self._col != -1:
01272             self.list.ClearColumnImage(self._col)
01273         self._colSortFlag = [1] * self.list.GetColumnCount()
01274 
01275         # draw GCPs (source and target)
01276         sourceMapWin = self.SrcMapWindow
01277         sourceMapWin.UpdateMap(render=False, renderVector=False)
01278         if self.show_target:
01279             targetMapWin = self.TgtMapWindow
01280             targetMapWin.UpdateMap(render=False, renderVector=False)
01281     
01282     def OnFocus(self, event):
01283         # self.grwiz.SwitchEnv('source')
01284         pass
01285         
01286     def OnRMS(self, event):
01287         """
01288         RMS button handler
01289         """
01290         self.RMSError(self.xygroup,self.gr_order)
01291 
01292         sourceMapWin = self.SrcMapWindow
01293         sourceMapWin.UpdateMap(render=False, renderVector=False)
01294         if self.show_target:
01295             targetMapWin = self.TgtMapWindow
01296             targetMapWin.UpdateMap(render=False, renderVector=False)
01297         
01298     def CheckGCPcount(self, msg=False):
01299         """
01300         Checks to make sure that the minimum number of GCPs have been defined and
01301         are active for the selected transformation order
01302         """
01303         if (self.GCPcount < 3 and self.gr_order == 1) or \
01304             (self.GCPcount < 6 and self.gr_order == 2) or \
01305             (self.GCPcount < 10 and self.gr_order == 3):
01306             if msg:
01307                 gcmd.GWarning(parent = self,
01308                               message=_('Insufficient points defined and active (checked) '
01309                                         'for selected rectification method.\n'
01310                                         '3+ points needed for 1st order,\n'
01311                                         '6+ points for 2nd order, and\n'
01312                                         '10+ points for 3rd order.'))
01313                 return False
01314         else:
01315             return True
01316 
01317     def OnGeorect(self, event):
01318         """
01319         Georectifies map(s) in group using i.rectify or v.transform
01320         """
01321         global maptype
01322         self.SaveGCPs(None)
01323         
01324         if self.CheckGCPcount(msg=True) == False:
01325             return
01326 
01327         if maptype == 'cell':
01328             self.grwiz.SwitchEnv('source')
01329 
01330             if self.clip_to_region:
01331                 flags = "ac"
01332             else:
01333                 flags = "a"
01334 
01335             busy = wx.BusyInfo(message=_("Rectifying images, please wait..."),
01336                                parent=self)
01337             wx.Yield()
01338 
01339             ret, msg = gcmd.RunCommand('i.rectify',
01340                                   parent = self,
01341                                   getErrorMsg = True,
01342                                   quiet = True,
01343                                   group = self.xygroup,
01344                                   extension = self.extension,
01345                                   order = self.gr_order,
01346                                   method=self.gr_method,
01347                                   flags = flags)
01348 
01349             busy.Destroy()
01350 
01351             # provide feedback on failure
01352             if ret != 0:
01353                 print >> sys.stderr, msg
01354                 
01355         elif maptype == 'vector':
01356             outmsg = ''
01357             # loop through all vectors in VREF
01358             # and move resulting vector to target location
01359             
01360             # make sure current mapset has a vector folder
01361             if not os.path.isdir(os.path.join(self.grassdatabase,
01362                                               self.currentlocation,
01363                                               self.currentmapset,
01364                                               'vector')):
01365                 os.mkdir(os.path.join(self.grassdatabase,
01366                                       self.currentlocation,
01367                                       self.currentmapset,
01368                                       'vector'))
01369 
01370             self.grwiz.SwitchEnv('source')
01371             
01372             # make list of vectors to georectify from VREF
01373             f = open(self.file['vgrp'])
01374             vectlist = []
01375             try:
01376                 for vect in f.readlines():
01377                     vect = vect.strip('\n')
01378                     if len(vect) < 1:
01379                         continue
01380                     vectlist.append(vect)
01381             finally:
01382                 f.close()
01383                                
01384             # georectify each vector in VREF using v.transform
01385             for vect in vectlist:
01386                 self.outname = vect + '_' + self.extension
01387                 self.parent.goutput.WriteLog(text = _('Transforming <%s>...') % vect,
01388                                              switchPage = True)
01389                 msg = err = ''
01390                 
01391                 ret, out, err = gcmd.RunCommand('v.transform',
01392                                                 overwrite = True,
01393                                                 input = vect,
01394                                                 output = self.outname,
01395                                                 pointsfile = self.file['points'],
01396                                                 getErrorMsg = True, read = True) 
01397                 
01398                 if ret == 0:
01399                     self.VectGRList.append(self.outname)
01400                     # note: WriteLog doesn't handle GRASS_INFO_PERCENT well, so using a print here
01401                     # self.parent.goutput.WriteLog(text = _(err), switchPage = True)
01402                     self.parent.goutput.WriteLog(text = out, switchPage = True)
01403                 else:
01404                     self.parent.goutput.WriteError(_('Georectification of vector map <%s> failed') %
01405                                                    self.outname)
01406                     self.parent.goutput.WriteError(err)
01407                 
01408                 # FIXME
01409                 # Copying database information not working. 
01410                 # Does not copy from xy location to current location
01411                 # TODO: replace $GISDBASE etc with real paths
01412                 #                xyLayer = []
01413                 #                for layer in grass.vector_db(map = vect).itervalues():
01414                 #                    xyLayer.append((layer['driver'],
01415                 #                                    layer['database'],
01416                 #                                    layer['table']))
01417                     
01418                     
01419                     #                dbConnect = grass.db_connection()
01420                     #                print 'db connection =', dbConnect
01421                     #                for layer in xyLayer:     
01422                     #                    self.parent.goutput.RunCmd(['db.copy',
01423                     #                                                '--q',
01424                     #                                                '--o',
01425                     #                                                'from_driver=%s' % layer[0],
01426                     #                                                'from_database=%s' % layer[1],
01427                     #                                                'from_table=%s' % layer[2],
01428                     #                                                'to_driver=%s' % dbConnect['driver'],
01429                     #                                                'to_database=%s' % dbConnect['database'],
01430                     #                                                'to_table=%s' % layer[2] + '_' + self.extension])
01431 
01432             # copy all georectified vectors from source location to current location
01433             for name in self.VectGRList:
01434                 xyvpath = os.path.join(self.grassdatabase,
01435                                        self.xylocation,
01436                                        self.xymapset,
01437                                        'vector',
01438                                        name)
01439                 vpath = os.path.join(self.grassdatabase,
01440                                      self.currentlocation,
01441                                      self.currentmapset,
01442                                      'vector',
01443                                      name)
01444                                     
01445                 if os.path.isdir(vpath):
01446                     self.parent.goutput.WriteWarning(_('Vector map <%s> already exists. '
01447                                                        'Change extension name and '
01448                                                        'georectify again.') % self.outname)
01449                     break
01450                 else:
01451                     # use shutil.copytree() because shutil.move() deletes src dir
01452                     shutil.copytree(xyvpath, vpath)
01453 
01454                 # TODO: connect vectors to copied tables with v.db.connect
01455                                                    
01456             gcmd.GMessage(_('For all vector maps georectified successfully,') + '\n' +
01457                           _('you will need to copy any attribute tables') + '\n' +
01458                           _('and reconnect them to the georectified vectors'),
01459                           parent = self)
01460         
01461         self.grwiz.SwitchEnv('target')
01462 
01463     def OnGeorectDone(self, **kargs):
01464         """!Print final message"""
01465         global maptype
01466         if maptype == 'cell':
01467             return
01468         
01469         returncode = kargs['returncode']
01470         
01471         if returncode == 0:
01472             self.VectGRList.append(self.outname)
01473             print '*****vector list = ' + str(self.VectGRList)
01474         else:
01475             self.parent.goutput.WriteError(_('Georectification of vector map <%s> failed') %
01476                                                    self.outname)
01477 
01478          
01479     def OnSettings(self, event):
01480         """!GCP Manager settings"""
01481         dlg = GrSettingsDialog(parent=self, id=wx.ID_ANY, title=_('GCP Manager settings'))
01482         
01483         if dlg.ShowModal() == wx.ID_OK:
01484             pass
01485         
01486         dlg.Destroy()
01487 
01488     def UpdateColours(self, srcrender=False, srcrenderVector=False,
01489                             tgtrender=False, tgtrenderVector=False):
01490         """!update colours"""
01491         highest_fwd_err = 0.0
01492         self.highest_key = 0
01493         highest_idx = 0
01494 
01495         for index in range(self.list.GetItemCount()):
01496             if self.list.IsChecked(index):
01497                 key = self.list.GetItemData(index)
01498                 fwd_err = self.mapcoordlist[key][5]
01499 
01500                 if self.highest_only == True:
01501                     self.list.SetItemTextColour(index, wx.BLACK)
01502                     if highest_fwd_err < fwd_err:
01503                         highest_fwd_err = fwd_err
01504                         self.highest_key = key
01505                         highest_idx = index
01506                 elif self.rmsthresh > 0:
01507                     if (fwd_err > self.rmsthresh):
01508                         self.list.SetItemTextColour(index, wx.RED)
01509                     else:
01510                         self.list.SetItemTextColour(index, wx.BLACK)
01511             else:
01512                 self.list.SetItemTextColour(index, wx.BLACK)
01513         
01514         if self.highest_only and highest_fwd_err > 0.0:
01515             self.list.SetItemTextColour(highest_idx, wx.RED)
01516 
01517         sourceMapWin = self.SrcMapWindow
01518         sourceMapWin.UpdateMap(render=srcrender, renderVector=srcrenderVector)
01519         if self.show_target:
01520             targetMapWin = self.TgtMapWindow
01521             targetMapWin.UpdateMap(render=tgtrender, renderVector=tgtrenderVector)
01522 
01523     def OnQuit(self, event):
01524         """!Quit georectifier"""
01525         ret = wx.MessageBox(parent=self,
01526                       caption=_("Quit GCP Manager"),
01527                       message=_('Save ground control points?'),
01528                       style=wx.ICON_QUESTION | wx.YES_NO | wx.CANCEL | wx.CENTRE)
01529 
01530         if ret != wx.CANCEL:
01531             if ret == wx.YES:
01532                 self.SaveGCPs(None)
01533             elif ret == wx.NO:
01534                 # restore POINTS file from backup
01535                 if os.path.exists(self.file['points_bak']):
01536                     shutil.copy(self.file['points_bak'], self.file['points'])
01537 
01538             if os.path.exists(self.file['points_bak']):
01539                 os.unlink(self.file['points_bak'])
01540 
01541             self.SrcMap.Clean()
01542             self.TgtMap.Clean()
01543 
01544             self.grwiz.Cleanup()
01545 
01546             self.Destroy()
01547 
01548         #event.Skip()
01549 
01550     def OnGROrder(self, event):
01551         """
01552         sets transformation order for georectifying
01553         """
01554         if event:
01555             self.gr_order = event.GetInt() + 1
01556 
01557         numOfItems = self.list.GetItemCount()
01558         minNumOfItems = numOfItems
01559         
01560         if self.gr_order == 1:
01561             minNumOfItems = 3
01562             # self.SetStatusText(_('Insufficient points, 3+ points needed for 1st order'))
01563 
01564         elif self.gr_order == 2:
01565             minNumOfItems = 6
01566             diff = 6 - numOfItems
01567             # self.SetStatusText(_('Insufficient points, 6+ points needed for 2nd order'))
01568 
01569         elif self.gr_order == 3:
01570             minNumOfItems = 10
01571             # self.SetStatusText(_('Insufficient points, 10+ points needed for 3rd order'))
01572 
01573         for i in range(minNumOfItems - numOfItems):
01574             self.AddGCP(None)
01575 
01576         return minNumOfItems
01577     
01578     def RMSError(self, xygroup, order):
01579         """
01580         Uses g.transform to calculate forward and backward error for each used GCP
01581         in POINTS file and insert error values into GCP list.
01582         Calculates total forward and backward RMS error for all used points
01583         """
01584         # save GCPs to points file to make sure that all checked GCPs are used
01585         self.SaveGCPs(None)
01586         #self.SetStatusText('')
01587         
01588         if self.CheckGCPcount(msg=True) == False:
01589             return
01590         
01591         # get list of forward and reverse rms error values for each point
01592         self.grwiz.SwitchEnv('source')
01593         
01594         ret = gcmd.RunCommand('g.transform',
01595                               parent = self,
01596                               read = True,
01597                               group = xygroup,
01598                               order = order)
01599         
01600         self.grwiz.SwitchEnv('target')
01601 
01602         if ret:
01603             errlist = ret.splitlines()
01604         else:
01605             gcmd.GError(parent = self,
01606                         message=_('Could not calculate RMS Error.\n'
01607                                   'Possible error with g.transform.'))
01608             return
01609         
01610         # insert error values into GCP list for checked items
01611         sdfactor = float(UserSettings.Get(group='gcpman', key='rms', subkey='sdfactor'))
01612         GCPcount = 0
01613         sumsq_fwd_err = 0.0
01614         sumsq_bkw_err = 0.0
01615         sum_fwd_err = 0.0
01616         highest_fwd_err = 0.0
01617         self.highest_key = 0
01618         highest_idx = 0
01619         
01620         for index in range(self.list.GetItemCount()):
01621             key = self.list.GetItemData(index)
01622             if self.list.IsChecked(index):
01623                 fwd_err, bkw_err = errlist[GCPcount].split()
01624                 self.list.SetStringItem(index, 5, fwd_err)
01625                 self.list.SetStringItem(index, 6, bkw_err)
01626                 self.mapcoordlist[key][5] = float(fwd_err)
01627                 self.mapcoordlist[key][6] = float(bkw_err)
01628                 self.list.SetItemTextColour(index, wx.BLACK)
01629                 if self.highest_only:
01630                     if highest_fwd_err < float(fwd_err):
01631                         highest_fwd_err = float(fwd_err)
01632                         self.highest_key = key
01633                         highest_idx = index
01634                         
01635                 sumsq_fwd_err += float(fwd_err)**2
01636                 sumsq_bkw_err += float(bkw_err)**2
01637                 sum_fwd_err += float(fwd_err)
01638                 GCPcount += 1
01639             else:
01640                 self.list.SetStringItem(index, 5, '')
01641                 self.list.SetStringItem(index, 6, '')
01642                 self.mapcoordlist[key][5] = 0.0
01643                 self.mapcoordlist[key][6] = 0.0
01644                 self.list.SetItemTextColour(index, wx.BLACK)
01645 
01646         # SD
01647         if GCPcount > 0:
01648             sum_fwd_err /= GCPcount
01649             self.rmsmean = sum_fwd_err /GCPcount
01650             self.rmssd = (((sumsq_fwd_err/GCPcount) - self.rmsmean**2)**0.5)
01651             self.rmsthresh = self.rmsmean + sdfactor * self.rmssd
01652         else:
01653             self.rmsthresh = 0
01654             self.rmsmean = 0
01655             self.rmssd = 0
01656 
01657         if self.highest_only and highest_fwd_err > 0.0:
01658             self.list.SetItemTextColour(highest_idx, wx.RED)
01659         elif GCPcount > 0 and self.rmsthresh > 0 and not self.highest_only:
01660             for index in range(self.list.GetItemCount()):
01661                 if self.list.IsChecked(index):
01662                     key = self.list.GetItemData(index)
01663                     if (self.mapcoordlist[key][5] > self.rmsthresh):
01664                         self.list.SetItemTextColour(index, wx.RED)
01665             
01666         # calculate global RMS error (geometric mean)
01667         self.fwd_rmserror = round((sumsq_fwd_err/GCPcount)**0.5,4)
01668         self.bkw_rmserror = round((sumsq_bkw_err/GCPcount)**0.5,4)
01669         self.list.ResizeColumns()
01670 
01671     def GetNewExtent(self, region, map = None):
01672 
01673         coord_file = utils.GetTempfile()
01674         newreg = { 'n' : 0.0, 's' : 0.0, 'e' : 0.0, 'w' : 0.0,}
01675 
01676         try:
01677             f = open(coord_file, mode='w')
01678             # NW corner        
01679             f.write(str(region['e']) + " " + str(region['n']) + "\n")
01680             # NE corner        
01681             f.write(str(region['e']) + " " + str(region['s']) + "\n")
01682             # SW corner        
01683             f.write(str(region['w']) + " " + str(region['n']) + "\n")
01684             # SE corner        
01685             f.write(str(region['w']) + " " + str(region['s']) + "\n")
01686         finally:
01687             f.close()
01688 
01689         # save GCPs to points file to make sure that all checked GCPs are used
01690         self.SaveGCPs(None)
01691 
01692         order = self.gr_order
01693         self.gr_order = 1
01694 
01695         if self.CheckGCPcount(msg=True) == False:
01696             self.gr_order = order
01697             return
01698         
01699         self.gr_order = order
01700 
01701         # get list of forward and reverse rms error values for each point
01702         self.grwiz.SwitchEnv('source')
01703         
01704         if map == 'source':
01705             ret = gcmd.RunCommand('g.transform',
01706                                   parent = self,
01707                                   read = True,
01708                                   group = self.xygroup,
01709                                   order = 1,
01710                                   format = 'dst',
01711                                   coords = coord_file)
01712 
01713         elif map == 'target':
01714             ret = gcmd.RunCommand('g.transform',
01715                                   parent = self,
01716                                   read = True,
01717                                   group = self.xygroup,
01718                                   order = 1,
01719                                   flags = 'r',
01720                                   format = 'src',
01721                                   coords = coord_file)
01722 
01723         os.unlink(coord_file)
01724         
01725         self.grwiz.SwitchEnv('target')
01726 
01727         if ret:
01728             errlist = ret.splitlines()
01729         else:
01730             gcmd.GError(parent = self,
01731                         message=_('Could not calculate new extends.\n'
01732                                   'Possible error with g.transform.'))
01733             return
01734 
01735         # fist corner
01736         e, n = errlist[0].split()
01737         fe = float(e)
01738         fn = float(n)
01739         newreg['n'] = fn
01740         newreg['s'] = fn
01741         newreg['e'] = fe
01742         newreg['w'] = fe
01743         # other three corners
01744         for i in range(1, 4):
01745             e, n = errlist[i].split()
01746             fe = float(e)
01747             fn = float(n)
01748             if fe < newreg['w']:
01749                 newreg['w'] = fe
01750             if fe > newreg['e']:
01751                 newreg['e'] = fe
01752             if fn < newreg['s']:
01753                 newreg['s'] = fn
01754             if fn > newreg['n']:
01755                 newreg['n'] = fn
01756 
01757         return newreg
01758 
01759     def OnHelp(self, event):
01760         """!Show GCP Manager manual page"""
01761         cmdlist = ['g.manual', 'entry=wxGUI.GCP_Manager']
01762         self.parent.goutput.RunCmd(cmdlist, compReg=False,
01763                                        switchPage=False)
01764 
01765     def OnUpdateActive(self, event):
01766 
01767         if self.activemap.GetSelection() == 0:
01768             self.MapWindow = self.SrcMapWindow
01769             self.Map = self.SrcMap
01770         else:
01771             self.MapWindow = self.TgtMapWindow
01772             self.Map = self.TgtMap
01773 
01774         self.UpdateActive(self.MapWindow)
01775         # for wingrass
01776         if os.name == 'nt':
01777             self.MapWindow.SetFocus()
01778 
01779     def UpdateActive(self, win):
01780 
01781         # optionally disable tool zoomback tool
01782         self.toolbars['gcpdisp'].Enable('zoomback', enable = (len(self.MapWindow.zoomhistory) > 1))
01783 
01784         if self.activemap.GetSelection() != (win == self.TgtMapWindow):
01785             self.activemap.SetSelection(win == self.TgtMapWindow)
01786         self.StatusbarUpdate()
01787 
01788     def AdjustMap(self, newreg):
01789         """!Adjust map window to new extents
01790         """
01791 
01792         # adjust map window
01793         self.Map.region['n'] = newreg['n']
01794         self.Map.region['s'] = newreg['s']
01795         self.Map.region['e'] = newreg['e']
01796         self.Map.region['w'] = newreg['w']
01797 
01798         self.MapWindow.ZoomHistory(self.Map.region['n'], self.Map.region['s'],
01799                  self.Map.region['e'], self.Map.region['w'])
01800 
01801         # LL locations
01802         if self.Map.projinfo['proj'] == 'll':
01803             if newreg['n'] > 90.0:
01804                 newreg['n'] = 90.0
01805             if newreg['s'] < -90.0:
01806                 newreg['s'] = -90.0
01807         
01808         ce = newreg['w'] + (newreg['e'] - newreg['w']) / 2
01809         cn = newreg['s'] + (newreg['n'] - newreg['s']) / 2
01810         
01811         # calculate new center point and display resolution
01812         self.Map.region['center_easting'] = ce
01813         self.Map.region['center_northing'] = cn
01814         self.Map.region["ewres"] = (newreg['e'] - newreg['w']) / self.Map.width
01815         self.Map.region["nsres"] = (newreg['n'] - newreg['s']) / self.Map.height
01816         self.Map.AlignExtentFromDisplay()
01817 
01818         self.MapWindow.ZoomHistory(self.Map.region['n'], self.Map.region['s'],
01819                  self.Map.region['e'], self.Map.region['w'])
01820 
01821         if self.MapWindow.redrawAll is False:
01822             self.MapWindow.redrawAll = True
01823 
01824         self.MapWindow.UpdateMap()
01825         self.StatusbarUpdate()
01826 
01827     def OnZoomToSource(self, event):
01828         """!Set target map window to match extents of source map window
01829         """
01830 
01831         if not self.MapWindow == self.TgtMapWindow:
01832             self.MapWindow = self.TgtMapWindow
01833             self.Map = self.TgtMap
01834             self.UpdateActive(self.TgtMapWindow)
01835 
01836         # get new N, S, E, W for target
01837         newreg = self.GetNewExtent(self.SrcMap.region, 'source')
01838         if newreg:
01839             self.AdjustMap(newreg)
01840 
01841     def OnZoomToTarget(self, event):
01842         """!Set source map window to match extents of target map window
01843         """
01844 
01845         if not self.MapWindow == self.SrcMapWindow:
01846             self.MapWindow = self.SrcMapWindow
01847             self.Map = self.SrcMap
01848             self.UpdateActive(self.SrcMapWindow)
01849 
01850         # get new N, S, E, W for target
01851         newreg = self.GetNewExtent(self.TgtMap.region, 'target')
01852         if newreg:
01853             self.AdjustMap(newreg)
01854 
01855     def OnZoomMenuGCP(self, event):
01856         """!Popup Zoom menu
01857         """
01858         point = wx.GetMousePosition()
01859         zoommenu = wx.Menu()
01860         # Add items to the menu
01861 
01862         zoomsource = wx.MenuItem(zoommenu, wx.ID_ANY, _('Adjust source display to target display'))
01863         zoommenu.AppendItem(zoomsource)
01864         self.Bind(wx.EVT_MENU, self.OnZoomToTarget, zoomsource)
01865 
01866         zoomtarget = wx.MenuItem(zoommenu, wx.ID_ANY, _('Adjust target display to source display'))
01867         zoommenu.AppendItem(zoomtarget)
01868         self.Bind(wx.EVT_MENU, self.OnZoomToSource, zoomtarget)
01869 
01870         # Popup the menu. If an item is selected then its handler
01871         # will be called before PopupMenu returns.
01872         self.PopupMenu(zoommenu)
01873         zoommenu.Destroy()
01874         
01875     def OnDispResize(self, event):
01876         """!GCP Map Display resized, adjust Map Windows
01877         """
01878         if self.toolbars['gcpdisp']:
01879             srcwidth, srcheight = self.SrcMapWindow.GetSize()
01880             tgtwidth, tgtheight = self.TgtMapWindow.GetSize()
01881             srcwidth = (srcwidth + tgtwidth) / 2
01882             self._mgr.GetPane("target").Hide()
01883             self._mgr.Update()
01884             self._mgr.GetPane("source").BestSize((srcwidth, srcheight))
01885             self._mgr.GetPane("target").BestSize((srcwidth, tgtheight))
01886             if self.show_target:
01887                 self._mgr.GetPane("target").Show()
01888             self._mgr.Update()
01889         pass
01890 
01891 class GCPList(wx.ListCtrl,
01892               CheckListCtrlMixin,
01893               ListCtrlAutoWidthMixin):
01894               
01895     def __init__(self, parent, gcp, id=wx.ID_ANY,
01896                  pos=wx.DefaultPosition, size=wx.DefaultSize,
01897                  style=wx.LC_REPORT | wx.SUNKEN_BORDER | wx.LC_HRULES |
01898                  wx.LC_SINGLE_SEL):
01899 
01900         wx.ListCtrl.__init__(self, parent, id, pos, size, style)
01901 
01902         self.gcp = gcp # GCP class
01903         self.render = True
01904 
01905         # Mixin settings
01906         CheckListCtrlMixin.__init__(self)
01907         ListCtrlAutoWidthMixin.__init__(self)
01908         # TextEditMixin.__init__(self)
01909 
01910         # tracks whether list items are checked or not
01911         self.CheckList = [] 
01912 
01913         self._Create()
01914 
01915         self.Bind(wx.EVT_LIST_ITEM_SELECTED, self.OnItemSelected)
01916         self.Bind(wx.EVT_LIST_ITEM_ACTIVATED, self.OnItemActivated)
01917         self.Bind(wx.EVT_LIST_COL_CLICK, self.OnColClick)
01918 
01919         self.selected = wx.NOT_FOUND
01920         self.selectedkey = -1
01921 
01922     def _Create(self):
01923 
01924         if 0:
01925             # normal, simple columns
01926             idx_col = 0
01927             for col in (_('use'),
01928                 _('source E'),
01929                 _('source N'),
01930                 _('target E'),
01931                 _('target N'),
01932                 _('Forward error'),
01933                 _('Backward error')):
01934                 self.InsertColumn(idx_col, col)
01935                 idx_col += 1
01936         else:
01937             # the hard way: we want images on the column header
01938             info = wx.ListItem()
01939             info.SetMask(wx.LIST_MASK_TEXT | wx.LIST_MASK_IMAGE | wx.LIST_MASK_FORMAT)
01940             info.SetImage(-1)
01941             info.m_format = wx.LIST_FORMAT_LEFT
01942 
01943             idx_col = 0
01944             for lbl in (_('use'),
01945                 _('source E'),
01946                 _('source N'),
01947                 _('target E'),
01948                 _('target N'),
01949                 _('Forward error'),
01950                 _('Backward error')):
01951                 info.SetText(lbl)
01952                 self.InsertColumnInfo(idx_col, info)
01953                 idx_col += 1
01954 
01955     def LoadData(self):
01956         """!Load data into list"""
01957         self.DeleteAllItems()
01958 
01959         self.render = False
01960         if os.path.isfile(self.gcp.file['points']):
01961             self.gcp.ReadGCPs()
01962         else:
01963             # 3 gcp is minimum
01964             for i in range(3):
01965                 self.gcp.AddGCP(None)
01966 
01967         # select first point by default
01968         self.selected = 0
01969         self.selectedkey = self.GetItemData(self.selected)
01970         self.SetItemState(self.selected,
01971                           wx.LIST_STATE_SELECTED,
01972                           wx.LIST_STATE_SELECTED)
01973 
01974         self.ResizeColumns()
01975         self.render = True
01976 
01977     def OnCheckItem(self, index, flag):
01978         """!Item is checked/unchecked"""
01979 
01980         if self.render:
01981             # redraw points
01982             sourceMapWin = self.gcp.SrcMapWindow
01983             sourceMapWin.UpdateMap(render=False, renderVector=False)
01984             if self.gcp.show_target:
01985                 targetMapWin = self.gcp.TgtMapWindow
01986                 targetMapWin.UpdateMap(render=False, renderVector=False)
01987 
01988         pass
01989     
01990     def AddGCPItem(self):
01991         """
01992         Appends an item to GCP list
01993         """
01994         self.selectedkey = self.GetItemCount() + 1
01995 
01996         self.Append([str(self.selectedkey),    # GCP number
01997                      '0.0',                # source E
01998                      '0.0',                # source N
01999                      '0.0',                # target E
02000                      '0.0',                # target N
02001                      '',                   # forward error
02002                      ''])                  # backward error
02003 
02004         self.selected = self.GetItemCount() - 1
02005         self.SetItemData(self.selected, self.selectedkey)
02006 
02007         self.SetItemState(self.selected,
02008                           wx.LIST_STATE_SELECTED,
02009                           wx.LIST_STATE_SELECTED)
02010 
02011         self.ResizeColumns()
02012 
02013         return self.selected
02014 
02015     def DeleteGCPItem(self):
02016         """
02017         Deletes selected item in GCP list
02018         """
02019         if self.selected == wx.NOT_FOUND:
02020             return
02021 
02022         key = self.GetItemData(self.selected)
02023         self.DeleteItem(self.selected)
02024 
02025         return key
02026         
02027     def ResizeColumns(self):
02028         """!Resize columns"""
02029         minWidth = [90, 120]
02030         for i in range(self.GetColumnCount()):
02031             self.SetColumnWidth(i, wx.LIST_AUTOSIZE)
02032             # first column is checkbox, don't set to minWidth
02033             if i > 0 and self.GetColumnWidth(i) < minWidth[i > 4]:
02034                 self.SetColumnWidth(i, minWidth[i > 4])
02035 
02036         self.SendSizeEvent()
02037 
02038     def GetSelected(self):
02039         """!Get index of selected item"""
02040         return self.selected
02041 
02042     def OnItemSelected(self, event):
02043         """
02044         Item selected
02045         """
02046 
02047         if self.render and self.selected != event.GetIndex():
02048             self.selected = event.GetIndex()
02049             self.selectedkey = self.GetItemData(self.selected)
02050             sourceMapWin = self.gcp.SrcMapWindow
02051             sourceMapWin.UpdateMap(render=False, renderVector=False)
02052             if self.gcp.show_target:
02053                 targetMapWin = self.gcp.TgtMapWindow
02054                 targetMapWin.UpdateMap(render=False, renderVector=False)
02055 
02056         event.Skip()
02057 
02058     def OnItemActivated(self, event):
02059         """
02060         When item double clicked, open editor to update coordinate values
02061         """
02062         coords = []
02063         index = event.GetIndex()
02064         key = self.GetItemData(index)
02065         changed = False
02066 
02067         for i in range(1, 5):
02068             coords.append(self.GetItem(index, i).GetText())
02069 
02070         dlg = EditGCP(parent=self, id=wx.ID_ANY, data=coords, gcpno=key)
02071 
02072         if dlg.ShowModal() == wx.ID_OK:
02073             values = dlg.GetValues() # string
02074             
02075             if len(values) == 0:
02076                 gcmd.GError(parent = self,
02077                             message=_("Invalid coordinate value. Operation cancelled."))
02078             else:
02079                 for i in range(len(values)):
02080                     if values[i] != coords[i]:
02081                         self.SetStringItem(index, i + 1, values[i])
02082                         changed = True
02083 
02084                 if changed:
02085                     # reset RMS and update mapcoordlist
02086                     self.SetStringItem(index, 5, '')
02087                     self.SetStringItem(index, 6, '')
02088                     key = self.GetItemData(index)
02089                     self.gcp.mapcoordlist[key] = [key,
02090                                                   float(values[0]),
02091                                                   float(values[1]),
02092                                                   float(values[2]),
02093                                                   float(values[3]),
02094                                                   0.0,
02095                                                   0.0]
02096                     self.gcp.UpdateColours()
02097         
02098     def OnColClick(self, event):
02099         """!ListCtrl forgets selected item..."""
02100         self.selected = self.FindItemData(-1, self.selectedkey)
02101         self.SetItemState(self.selected,
02102                           wx.LIST_STATE_SELECTED,
02103                           wx.LIST_STATE_SELECTED)
02104         event.Skip()
02105 
02106 class VectGroup(wx.Dialog):
02107     """
02108     Dialog to create a vector group (VREF file) for georectifying
02109 
02110     @todo Replace by g.group
02111     """
02112     def __init__(self, parent, id, grassdb, location, mapset, group,
02113                  style=wx.DEFAULT_DIALOG_STYLE):
02114         
02115         wx.Dialog.__init__(self, parent, id, style=style,
02116                            title = _("Create vector map group"))
02117         
02118         self.grassdatabase = grassdb
02119         self.xylocation = location
02120         self.xymapset = mapset
02121         self.xygroup = group
02122         
02123         #
02124         # get list of valid vector directories
02125         #
02126         vectlist = os.listdir(os.path.join(self.grassdatabase,
02127                                            self.xylocation,
02128                                            self.xymapset,
02129                                            'vector'))
02130         for dir in vectlist:
02131             if not os.path.isfile(os.path.join(self.grassdatabase,
02132                                            self.xylocation,
02133                                            self.xymapset,
02134                                            'vector',
02135                                            dir,
02136                                            'coor')):
02137                 vectlist.remove(dir)
02138         
02139         utils.ListSortLower(vectlist)
02140         
02141         # path to vref file
02142         self.vgrpfile = os.path.join(self.grassdatabase,
02143                                      self.xylocation,
02144                                      self.xymapset,
02145                                      'group',
02146                                      self.xygroup,
02147                                      'VREF')
02148         
02149         #
02150         # buttons
02151         #
02152         self.btnCancel = wx.Button(parent = self,
02153                                    id = wx.ID_CANCEL)
02154         self.btnOK = wx.Button(parent = self,
02155                                    id = wx.ID_OK)
02156         self.btnOK.SetDefault()
02157 
02158 
02159         #
02160         # list of vector maps
02161         #
02162         self.listMap = wx.CheckListBox(parent = self, id = wx.ID_ANY,
02163                                       choices = vectlist)
02164         
02165         if os.path.isfile(self.vgrpfile):
02166             f = open(self.vgrpfile)
02167             try:
02168                 checked = []
02169                 for line in f.readlines():
02170                     line = line.replace('\n', '')
02171                     if len(line) < 1:
02172                         continue
02173                     checked.append(line)
02174                 self.listMap.SetCheckedStrings(checked)
02175             finally:
02176                 f.close()
02177                 
02178         line = wx.StaticLine(parent = self,
02179                              id = wx.ID_ANY, size = (20, -1),
02180                              style = wx.LI_HORIZONTAL)
02181 
02182         #
02183         # layout
02184         #
02185         sizer = wx.BoxSizer(wx.VERTICAL)
02186         
02187         box = wx.BoxSizer(wx.HORIZONTAL)
02188         box.Add(item = wx.StaticText(parent = self, id = wx.ID_ANY,
02189                                      label = _('Select vector map(s) to add to group:')),
02190                 flag = wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT | wx.LEFT,
02191                 border = 5)
02192 
02193         box.Add(item = self.listMap,
02194                 flag = wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT | wx.LEFT,
02195                 border = 5)
02196 
02197         
02198         sizer.Add(box, flag = wx.ALIGN_RIGHT | wx.ALL,
02199                   border = 3)
02200         
02201         sizer.Add(item = line, proportion = 0,
02202                   flag = wx.GROW | wx.ALIGN_CENTER_VERTICAL | wx.LEFT | wx.RIGHT,
02203                   border = 5)
02204         
02205         # buttons
02206         btnSizer = wx.StdDialogButtonSizer()
02207         btnSizer.AddButton(self.btnCancel)
02208         btnSizer.AddButton(self.btnOK)
02209         btnSizer.Realize()
02210 
02211         sizer.Add(item = btnSizer, proportion = 0,
02212                   flag = wx.EXPAND | wx.ALL | wx.ALIGN_CENTER,
02213                   border = 5)
02214         
02215         self.SetSizer(sizer)
02216         sizer.Fit(self)
02217         self.Layout()
02218         
02219     def MakeVGroup(self):
02220         """!Create VREF file"""
02221         vgrouplist = []
02222         for item in range(self.listMap.GetCount()):
02223             if not self.listMap.IsChecked(item):
02224                 continue
02225             vgrouplist.append(self.listMap.GetString(item))
02226         
02227         f = open(self.vgrpfile, mode='w')
02228         try:
02229             for vect in vgrouplist:
02230                 f.write(vect + '\n')
02231         finally:
02232             f.close()
02233         
02234 class EditGCP(wx.Dialog):
02235     def __init__(self, parent, data, gcpno, id=wx.ID_ANY,
02236                  title=_("Edit GCP"),
02237                  style=wx.DEFAULT_DIALOG_STYLE):
02238         """!Dialog for editing GPC and map coordinates in list control"""
02239 
02240         wx.Dialog.__init__(self, parent, id, title=title, style=style)
02241 
02242         panel = wx.Panel(parent=self)
02243 
02244         sizer = wx.BoxSizer(wx.VERTICAL)
02245 
02246         box = wx.StaticBox (parent=panel, id=wx.ID_ANY,
02247                             label=" %s %s " % (_("Ground Control Point No."), str(gcpno)))
02248         boxSizer = wx.StaticBoxSizer(box, wx.VERTICAL)
02249 
02250         # source coordinates
02251         gridSizer = wx.GridBagSizer(vgap=5, hgap=5)
02252        
02253         self.xcoord = wx.TextCtrl(parent=panel, id=wx.ID_ANY, size=(150, -1))
02254         self.ycoord = wx.TextCtrl(parent=panel, id=wx.ID_ANY, size=(150, -1))
02255         self.ecoord = wx.TextCtrl(parent=panel, id=wx.ID_ANY, size=(150, -1))
02256         self.ncoord = wx.TextCtrl(parent=panel, id=wx.ID_ANY, size=(150, -1))
02257 
02258         # swap source N, target E
02259         tmp_coord = data[1]
02260         data[1] = data[2]
02261         data[2] = tmp_coord
02262         
02263         row = 0
02264         col = 0
02265         idx = 0
02266         for label, win in ((_("source E:"), self.xcoord),
02267                            (_("target E:"), self.ecoord),
02268                            (_("source N:"), self.ycoord),
02269                            (_("target N:"), self.ncoord)):
02270             label = wx.StaticText(parent=panel, id=wx.ID_ANY,
02271                                   label=label)
02272             gridSizer.Add(item=label,
02273                           flag=wx.ALIGN_CENTER_VERTICAL,
02274                           pos=(row, col))
02275 
02276             col += 1
02277             win.SetValue(str(data[idx]))
02278 
02279             gridSizer.Add(item=win,
02280                           pos=(row, col))
02281 
02282             col += 1
02283             idx += 1
02284 
02285             if col > 3:
02286                 row += 1
02287                 col = 0
02288 
02289         boxSizer.Add(item=gridSizer, proportion=1,
02290                   flag=wx.EXPAND | wx.ALL, border=5)
02291 
02292         sizer.Add(item=boxSizer, proportion=1,
02293                   flag=wx.EXPAND | wx.ALL, border=5)
02294 
02295         #
02296         # buttons
02297         #
02298         self.btnCancel = wx.Button(panel, wx.ID_CANCEL)
02299         self.btnOk = wx.Button(panel, wx.ID_OK)
02300         self.btnOk.SetDefault()
02301 
02302         btnSizer = wx.StdDialogButtonSizer()
02303         btnSizer.AddButton(self.btnCancel)
02304         btnSizer.AddButton(self.btnOk)
02305         btnSizer.Realize()
02306 
02307         sizer.Add(item=btnSizer, proportion=0,
02308                   flag=wx.ALIGN_RIGHT | wx.ALL, border=5)
02309 
02310         panel.SetSizer(sizer)
02311         sizer.Fit(self)
02312 
02313     def GetValues(self, columns=None):
02314         """!Return list of values (as strings).
02315         """
02316         valuelist = []
02317         try:
02318             float(self.xcoord.GetValue())
02319             float(self.ycoord.GetValue())
02320             float(self.ecoord.GetValue())
02321             float(self.ncoord.GetValue())
02322         except ValueError:
02323             return valuelist
02324 
02325         valuelist.append(self.xcoord.GetValue())
02326         valuelist.append(self.ycoord.GetValue())
02327         valuelist.append(self.ecoord.GetValue())
02328         valuelist.append(self.ncoord.GetValue())
02329 
02330         return valuelist
02331 
02332 class GrSettingsDialog(wx.Dialog):
02333     def __init__(self, parent, id, title, pos=wx.DefaultPosition, size=wx.DefaultSize,
02334                  style=wx.DEFAULT_DIALOG_STYLE):
02335         wx.Dialog.__init__(self, parent, id, title, pos, size, style)
02336         """
02337         Dialog to set profile text options: font, title
02338         and font size, axis labels and font size
02339         """
02340         #
02341         # initialize variables
02342         #
02343         self.parent = parent
02344         self.new_src_map = src_map
02345         self.new_tgt_map = tgt_map
02346         self.sdfactor = 0
02347 
02348         self.symbol = {}
02349         
02350         self.methods = ["nearest",
02351                         "bilinear",
02352                         "bilinear_f",
02353                         "cubic", 
02354                         "cubic_f"]
02355 
02356         # notebook
02357         notebook = wx.Notebook(parent=self, id=wx.ID_ANY, style=wx.BK_DEFAULT)
02358         self.__CreateSymbologyPage(notebook)
02359         self.__CreateRectificationPage(notebook)
02360 
02361         # buttons
02362         btnSave = wx.Button(self, wx.ID_SAVE)
02363         btnApply = wx.Button(self, wx.ID_APPLY)
02364         btnClose = wx.Button(self, wx.ID_CLOSE)
02365         btnApply.SetDefault()
02366 
02367         # bindings
02368         btnApply.Bind(wx.EVT_BUTTON, self.OnApply)
02369         btnApply.SetToolTipString(_("Apply changes for the current session"))
02370         btnSave.Bind(wx.EVT_BUTTON, self.OnSave)
02371         btnSave.SetToolTipString(_("Apply and save changes to user settings file (default for next sessions)"))
02372         btnClose.Bind(wx.EVT_BUTTON, self.OnClose)
02373         btnClose.SetToolTipString(_("Close dialog"))
02374 
02375         # sizers
02376         btnSizer = wx.BoxSizer(wx.HORIZONTAL)
02377         btnSizer.Add(btnApply, flag=wx.LEFT | wx.RIGHT, border=5)
02378         btnSizer.Add(btnSave, flag=wx.LEFT | wx.RIGHT, border=5)
02379         btnSizer.Add(btnClose, flag=wx.LEFT | wx.RIGHT, border=5)
02380         
02381         # sizers
02382         mainSizer = wx.BoxSizer(wx.VERTICAL)
02383         mainSizer.Add(item=notebook, proportion=1, flag=wx.EXPAND | wx.ALL, border=5)
02384         mainSizer.Add(item=btnSizer, proportion=0,
02385                        flag=wx.ALIGN_RIGHT | wx.ALL, border=5)
02386         #              flag=wx.EXPAND | wx.ALL | wx.ALIGN_CENTER, border=5)
02387 
02388         self.SetSizer(mainSizer)
02389         mainSizer.Fit(self)
02390         
02391     def __CreateSymbologyPage(self, notebook):
02392         """!Create notebook page with symbology settings"""
02393 
02394         panel = wx.Panel(parent=notebook, id=wx.ID_ANY)
02395         notebook.AddPage(page=panel, text=_("Symbology"))
02396 
02397         sizer = wx.BoxSizer(wx.VERTICAL)
02398 
02399         rmsgridSizer = wx.GridBagSizer(vgap=5, hgap=5)
02400         rmsgridSizer.AddGrowableCol(1)
02401 
02402         # highlight only highest forward RMS error
02403         self.highlighthighest = wx.CheckBox(parent=panel, id=wx.ID_ANY,
02404                                 label=_("Highlight highest RMS error only"))
02405         hh = UserSettings.Get(group='gcpman', key='rms', subkey='highestonly')
02406         self.highlighthighest.SetValue(hh)
02407         rmsgridSizer.Add(item=self.highlighthighest, flag=wx.ALIGN_CENTER_VERTICAL, pos=(0, 0))
02408 
02409         # RMS forward error threshold
02410         rmslabel = wx.StaticText(parent=panel, id=wx.ID_ANY, label=_("Highlight RMS error > M + SD * factor:"))
02411         rmslabel.SetToolTip(wx.ToolTip(_("Highlight GCPs with an RMS error larger than \n"
02412                               "mean + standard deviation * given factor. \n"
02413                               "Recommended values for this factor are between 1 and 2.")))
02414         rmsgridSizer.Add(item=rmslabel, flag=wx.ALIGN_CENTER_VERTICAL, pos=(1, 0))
02415         sdfactor = UserSettings.Get(group='gcpman', key='rms', subkey='sdfactor')
02416         self.rmsWin = wx.TextCtrl(parent=panel, id=wx.ID_ANY,
02417                        size=(70,-1), style=wx.TE_NOHIDESEL)
02418         self.rmsWin.SetValue("%s" % str(sdfactor))
02419         if (self.parent.highest_only == True):
02420            self.rmsWin.Disable()
02421 
02422         self.symbol['sdfactor'] = self.rmsWin.GetId()
02423         rmsgridSizer.Add(item=self.rmsWin, flag=wx.ALIGN_RIGHT, pos=(1, 1))
02424         sizer.Add(item=rmsgridSizer, flag=wx.EXPAND | wx.ALL, border=5)
02425 
02426         box = wx.StaticBox(parent=panel, id=wx.ID_ANY,
02427                            label=" %s " % _("Symbol settings"))
02428         boxSizer = wx.StaticBoxSizer(box, wx.VERTICAL)
02429         gridSizer = wx.GridBagSizer(vgap=5, hgap=5)
02430         gridSizer.AddGrowableCol(1)
02431 
02432         #
02433         # general symbol color
02434         #
02435         row = 0
02436         label = wx.StaticText(parent=panel, id=wx.ID_ANY, label=_("Color:"))
02437         gridSizer.Add(item=label, flag=wx.ALIGN_CENTER_VERTICAL, pos=(row, 0))
02438         col = UserSettings.Get(group='gcpman', key='symbol', subkey='color')
02439         colWin = csel.ColourSelect(parent=panel, id=wx.ID_ANY,
02440                                    colour=wx.Colour(col[0],
02441                                                     col[1],
02442                                                     col[2],
02443                                                     255))
02444         self.symbol['color'] = colWin.GetId()
02445         gridSizer.Add(item=colWin,
02446                       flag=wx.ALIGN_RIGHT,
02447                       pos=(row, 1))
02448 
02449         #
02450         # symbol color for high forward RMS error
02451         #
02452         row += 1
02453         label = wx.StaticText(parent=panel, id=wx.ID_ANY, label=_("Color for high RMS error:"))
02454         gridSizer.Add(item=label, flag=wx.ALIGN_CENTER_VERTICAL, pos=(row, 0))
02455         hcol = UserSettings.Get(group='gcpman', key='symbol', subkey='hcolor')
02456         hcolWin = csel.ColourSelect(parent=panel, id=wx.ID_ANY,
02457                                    colour=wx.Colour(hcol[0],
02458                                                     hcol[1],
02459                                                     hcol[2],
02460                                                     255))
02461         self.symbol['hcolor'] = hcolWin.GetId()
02462         gridSizer.Add(item=hcolWin,
02463                       flag=wx.ALIGN_RIGHT,
02464                       pos=(row, 1))
02465 
02466         #
02467         # symbol color for selected GCP
02468         #
02469         row += 1
02470         label = wx.StaticText(parent=panel, id=wx.ID_ANY, label=_("Color for selected GCP:"))
02471         gridSizer.Add(item=label, flag=wx.ALIGN_CENTER_VERTICAL, pos=(row, 0))
02472         scol = UserSettings.Get(group='gcpman', key='symbol', subkey='scolor')
02473         scolWin = csel.ColourSelect(parent=panel, id=wx.ID_ANY,
02474                                    colour=wx.Colour(scol[0],
02475                                                     scol[1],
02476                                                     scol[2],
02477                                                     255))
02478         self.symbol['scolor'] = scolWin.GetId()
02479         gridSizer.Add(item=scolWin,
02480                       flag=wx.ALIGN_RIGHT,
02481                       pos=(row, 1))
02482 
02483         #
02484         # symbol color for unused GCP
02485         #
02486         row += 1
02487         label = wx.StaticText(parent=panel, id=wx.ID_ANY, label=_("Color for unused GCPs:"))
02488         gridSizer.Add(item=label, flag=wx.ALIGN_CENTER_VERTICAL, pos=(row, 0))
02489         ucol = UserSettings.Get(group='gcpman', key='symbol', subkey='ucolor')
02490         ucolWin = csel.ColourSelect(parent=panel, id=wx.ID_ANY,
02491                                    colour=wx.Colour(ucol[0],
02492                                                     ucol[1],
02493                                                     ucol[2],
02494                                                     255))
02495         self.symbol['ucolor'] = ucolWin.GetId()
02496         gridSizer.Add(item=ucolWin,
02497                       flag=wx.ALIGN_RIGHT,
02498                       pos=(row, 1))
02499 
02500         # show unused GCPs
02501         row += 1
02502         self.showunused = wx.CheckBox(parent=panel, id=wx.ID_ANY,
02503                                 label=_("Show unused GCPs"))
02504         shuu = UserSettings.Get(group='gcpman', key='symbol', subkey='unused')
02505         self.showunused.SetValue(shuu)
02506         gridSizer.Add(item=self.showunused, flag=wx.ALIGN_CENTER_VERTICAL, pos=(row, 0))
02507 
02508         #
02509         # symbol size
02510         #
02511         row += 1
02512         label = wx.StaticText(parent=panel, id=wx.ID_ANY, label=_("Symbol size:"))
02513         gridSizer.Add(item=label, flag=wx.ALIGN_CENTER_VERTICAL, pos=(row, 0))
02514         symsize = int(UserSettings.Get(group='gcpman', key='symbol', subkey='size'))
02515         sizeWin = wx.SpinCtrl(parent=panel, id=wx.ID_ANY,
02516                              min=1, max=20)
02517         sizeWin.SetValue(symsize)
02518         self.symbol['size'] = sizeWin.GetId()
02519         gridSizer.Add(item=sizeWin,
02520                       flag=wx.ALIGN_RIGHT,
02521                       pos=(row, 1))
02522         
02523         #
02524         # symbol width
02525         #
02526         row += 1
02527         label = wx.StaticText(parent=panel, id=wx.ID_ANY, label=_("Line width:"))
02528         gridSizer.Add(item=label, flag=wx.ALIGN_CENTER_VERTICAL, pos=(row, 0))
02529         width = int(UserSettings.Get(group='gcpman', key='symbol', subkey='width'))
02530         widWin = wx.SpinCtrl(parent=panel, id=wx.ID_ANY,
02531                              min=1, max=10)
02532         widWin.SetValue(width)
02533         self.symbol['width'] = widWin.GetId()
02534         gridSizer.Add(item=widWin,
02535                       flag=wx.ALIGN_RIGHT,
02536                       pos=(row, 1))
02537         
02538         boxSizer.Add(item=gridSizer, flag=wx.EXPAND)
02539         sizer.Add(item=boxSizer, flag=wx.EXPAND | wx.ALL, border=5)
02540 
02541         #
02542         # maps to display
02543         #
02544         # source map to display
02545         self.srcselection = gselect.Select(panel, id=wx.ID_ANY,
02546                     size=globalvar.DIALOG_GSELECT_SIZE, type='cell', updateOnPopup = False)
02547         self.parent.grwiz.SwitchEnv('source')
02548         self.srcselection.SetElementList(maptype)
02549         # filter out all maps not in group
02550         self.srcselection.tcp.GetElementList(elements = self.parent.src_maps)
02551 
02552         # target map to display
02553         self.tgtselection = gselect.Select(panel, id=wx.ID_ANY,
02554                     size=globalvar.DIALOG_GSELECT_SIZE, type='cell', updateOnPopup = False)
02555         self.parent.grwiz.SwitchEnv('target')
02556         self.tgtselection.SetElementList(maptype)
02557         self.tgtselection.GetElementList()
02558 
02559         sizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY, label=_('Select source map to display:')),
02560                        proportion=0, flag=wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL | wx.ALL, border=5)
02561         sizer.Add(item=self.srcselection, proportion=0, 
02562                        flag=wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL | wx.ALL, border=5)
02563         self.srcselection.SetValue(src_map)
02564         sizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY, label=_('Select target map to display:')),
02565                        proportion=0, flag=wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL | wx.ALL, border=5)
02566         sizer.Add(item=self.tgtselection, proportion=0, 
02567                        flag=wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL | wx.ALL, border=5)
02568         self.tgtselection.SetValue(tgt_map)
02569 
02570         # bindings
02571         self.highlighthighest.Bind(wx.EVT_CHECKBOX, self.OnHighlight)
02572         self.rmsWin.Bind(wx.EVT_TEXT, self.OnSDFactor)
02573         self.srcselection.Bind(wx.EVT_TEXT, self.OnSrcSelection)
02574         self.tgtselection.Bind(wx.EVT_TEXT, self.OnTgtSelection)
02575 
02576         panel.SetSizer(sizer)
02577         
02578         return panel
02579 
02580     def __CreateRectificationPage(self, notebook):
02581         """!Create notebook page with symbology settings"""
02582 
02583         panel = wx.Panel(parent=notebook, id=wx.ID_ANY)
02584         notebook.AddPage(page=panel, text=_("Rectification"))
02585 
02586         sizer = wx.BoxSizer(wx.VERTICAL)
02587 
02588         # transformation order
02589         self.rb_grorder = wx.RadioBox(parent=panel, id=wx.ID_ANY,
02590                                        label=" %s " % _("Select rectification order"),
02591                                        choices=[_('1st order'), _('2nd order'), _('3rd order')],
02592                                        majorDimension=wx.RA_SPECIFY_COLS)
02593         sizer.Add(item=self.rb_grorder, proportion=0,
02594                        flag=wx.EXPAND | wx.ALL, border=5)
02595         self.rb_grorder.SetSelection(self.parent.gr_order - 1)
02596 
02597         # interpolation method
02598         gridSizer = wx.GridBagSizer(vgap=5, hgap=5)
02599         gridSizer.AddGrowableCol(1)
02600         gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY, label=_('Select interpolation method:')),
02601                        pos=(0,0), flag=wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL | wx.ALL, border=5)
02602         self.grmethod = wx.Choice(parent=panel, id=wx.ID_ANY,
02603                                   choices = self.methods)
02604         gridSizer.Add(item=self.grmethod, pos=(0,1),
02605                        flag=wx.ALIGN_RIGHT, border=5)
02606         self.grmethod.SetStringSelection(self.parent.gr_method)
02607         sizer.Add(item=gridSizer, flag=wx.EXPAND | wx.ALL, border=5)
02608 
02609         # clip to region
02610         self.check = wx.CheckBox(parent=panel, id=wx.ID_ANY,
02611                                 label=_("clip to computational region in target location"))
02612         sizer.Add(item=self.check, proportion=0,
02613                        flag=wx.EXPAND | wx.ALL, border=5)
02614         self.check.SetValue(self.parent.clip_to_region)
02615 
02616         # extension
02617         sizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY, label=_('Extension for output maps:')),
02618                        proportion=0, flag=wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL | wx.ALL, border=5)
02619         self.ext_txt = wx.TextCtrl(parent=panel, id=wx.ID_ANY, value="", size=(350,-1))
02620         self.ext_txt.SetValue(self.parent.extension)
02621         sizer.Add(item=self.ext_txt,
02622                        proportion=0, flag=wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL | wx.ALL, border=5)
02623 
02624         # bindings
02625         self.ext_txt.Bind(wx.EVT_TEXT, self.OnExtension)
02626         self.Bind(wx.EVT_RADIOBOX, self.parent.OnGROrder, self.rb_grorder)
02627         self.Bind(wx.EVT_CHOICE, self.OnMethod, self.grmethod)
02628         self.Bind(wx.EVT_CHECKBOX, self.OnClipRegion, self.check)
02629 
02630         panel.SetSizer(sizer)
02631         
02632         return panel
02633 
02634     def OnHighlight(self, event):
02635         """!Checkbox 'highlighthighest' checked/unchecked"""
02636         if self.highlighthighest.IsChecked():
02637             self.parent.highest_only = True
02638             self.rmsWin.Disable()
02639         else:
02640             self.parent.highest_only = False
02641             self.rmsWin.Enable()
02642 
02643     def OnSDFactor(self,event):
02644         """!New factor for RMS threshold = M + SD * factor"""
02645 
02646         self.sdfactor = float(event.GetString())
02647 
02648         if self.sdfactor <= 0:
02649             gcmd.GError(parent = self,
02650                         message=_('RMS threshold factor must be > 0'))
02651         elif self.sdfactor < 1:
02652             gcmd.GError(parent = self,
02653                         message=_('RMS threshold factor is < 1\n'
02654                                   'Too many points might be highlighted'))
02655         
02656     def OnSrcSelection(self,event):
02657         """!Source map to display selected"""
02658         global src_map
02659 
02660         tmp_map = event.GetString()
02661 
02662         if not tmp_map == '' and not tmp_map == src_map:
02663             self.new_src_map = tmp_map
02664 
02665     def OnTgtSelection(self,event):
02666         """!Target map to display selected"""
02667         global tgt_map
02668 
02669         tmp_map = event.GetString()
02670 
02671         if not tmp_map == tgt_map:
02672             self.new_tgt_map = tmp_map
02673 
02674     def OnMethod(self, event):
02675         self.parent.gr_method = self.methods[event.GetSelection()]
02676 
02677     def OnClipRegion(self, event):
02678         self.parent.clip_to_region = event.IsChecked()
02679         
02680     def OnExtension(self, event):
02681         self.parent.extension = event.GetString()
02682 
02683     def UpdateSettings(self):
02684         global src_map
02685         global tgt_map
02686 
02687         layers = None
02688 
02689         UserSettings.Set(group='gcpman', key='rms', subkey='highestonly',
02690                          value=self.highlighthighest.GetValue())
02691         if self.sdfactor > 0:
02692             UserSettings.Set(group='gcpman', key='rms', subkey='sdfactor',
02693                              value=self.sdfactor)
02694 
02695             self.parent.sdfactor = self.sdfactor
02696             if self.parent.rmsthresh > 0:
02697                 self.parent.rmsthresh = self.parent.mean + self.parent.sdfactor * self.parent.rmssd
02698 
02699         UserSettings.Set(group='gcpman', key='symbol', subkey='color',
02700                          value=tuple(wx.FindWindowById(self.symbol['color']).GetColour()))
02701         UserSettings.Set(group='gcpman', key='symbol', subkey='hcolor',
02702                          value=tuple(wx.FindWindowById(self.symbol['hcolor']).GetColour()))
02703         UserSettings.Set(group='gcpman', key='symbol', subkey='scolor',
02704                          value=tuple(wx.FindWindowById(self.symbol['scolor']).GetColour()))
02705         UserSettings.Set(group='gcpman', key='symbol', subkey='ucolor',
02706                          value=tuple(wx.FindWindowById(self.symbol['ucolor']).GetColour()))
02707         UserSettings.Set(group='gcpman', key='symbol', subkey='unused',
02708                          value=self.showunused.GetValue())
02709         UserSettings.Set(group='gcpman', key='symbol', subkey='size',
02710                          value=wx.FindWindowById(self.symbol['size']).GetValue())
02711         UserSettings.Set(group='gcpman', key='symbol', subkey='width',
02712                          value=wx.FindWindowById(self.symbol['width']).GetValue())
02713 
02714         srcrender = False
02715         srcrenderVector = False
02716         tgtrender = False
02717         tgtrenderVector = False
02718         if self.new_src_map != src_map:
02719             # remove old layer
02720             layers = self.parent.grwiz.SrcMap.GetListOfLayers()
02721             self.parent.grwiz.SrcMap.DeleteLayer(layers[0])
02722             
02723             src_map = self.new_src_map
02724             cmdlist = ['d.rast', 'map=%s' % src_map]
02725             self.parent.grwiz.SwitchEnv('source')
02726             name, found = utils.GetLayerNameFromCmd(cmdlist),
02727             self.parent.grwiz.SrcMap.AddLayer(type='raster', command=cmdlist, l_active=True,
02728                               name=name, l_hidden=False, l_opacity=1.0, l_render=False)
02729 
02730             self.parent.grwiz.SwitchEnv('target')
02731             srcrender = True
02732 
02733         if self.new_tgt_map != tgt_map:
02734             # remove old layer
02735             layers = self.parent.grwiz.TgtMap.GetListOfLayers()
02736             if layers:
02737                 self.parent.grwiz.TgtMap.DeleteLayer(layers[0])
02738             tgt_map = self.new_tgt_map
02739 
02740             if tgt_map != '':
02741                 cmdlist = ['d.rast', 'map=%s' % tgt_map]
02742                 name, found = utils.GetLayerNameFromCmd(cmdlist)
02743                 self.parent.grwiz.TgtMap.AddLayer(type='raster', command=cmdlist, l_active=True,
02744                                   name=name, l_hidden=False, l_opacity=1.0, l_render=False)
02745 
02746                 tgtrender = True
02747                 if self.parent.show_target == False:
02748                     self.parent.show_target = True
02749                     self.parent._mgr.GetPane("target").Show()
02750                     self.parent._mgr.Update()
02751                     self.parent.toolbars['gcpdisp'].Enable('zoommenu', enable = True)
02752                     self.parent.activemap.Enable()
02753                     self.parent.TgtMapWindow.ZoomToMap(layers = self.parent.TgtMap.GetListOfLayers())
02754             else: # tgt_map == ''
02755                 if self.parent.show_target == True:
02756                     self.parent.show_target = False
02757                     self.parent._mgr.GetPane("target").Hide()
02758                     self.parent._mgr.Update()
02759                     self.parent.activemap.SetSelection(0)
02760                     self.parent.activemap.Enable(False)
02761                     self.parent.toolbars['gcpdisp'].Enable('zoommenu', enable = False)
02762 
02763         self.parent.UpdateColours(srcrender, srcrenderVector, tgtrender, tgtrenderVector)
02764 
02765     def OnSave(self, event):
02766         """!Button 'Save' pressed"""
02767         self.UpdateSettings()
02768         fileSettings = {}
02769         UserSettings.ReadSettingsFile(settings=fileSettings)
02770         fileSettings['gcpman'] = UserSettings.Get(group='gcpman')
02771         file = UserSettings.SaveToFile(fileSettings)
02772         self.parent.parent.goutput.WriteLog(_('GCP Manager settings saved to file \'%s\'.') % file)
02773         #self.Close()
02774 
02775     def OnApply(self, event):
02776         """!Button 'Apply' pressed"""
02777         self.UpdateSettings()
02778         #self.Close()
02779 
02780     def OnClose(self, event):
02781         """!Button 'Cancel' pressed"""
02782         self.Close()
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines