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