|
GRASS Programmer's Manual
6.5.svn(2012)-r51648
|
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()