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