GRASS Programmer's Manual  6.4.2(2012)
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
gcpmanager.py
Go to the documentation of this file.
1 """!
2 @package gcpmanager.py
3 
4 @brief Georectification module for GRASS GIS. Includes ground control
5 point management and interactive point and click GCP creation
6 
7 Classes:
8  - GCPWizard
9  - LocationPage
10  - GroupPage
11  - DispMapPage
12  - GCP
13  - GCPList
14  - VectGroup
15  - EditGCP
16  - GrSettingsDialog
17 
18 (C) 2006-2011 by the GRASS Development Team
19 This program is free software under the GNU General Public License
20 (>=v2). Read the file COPYING that comes with GRASS for details.
21 
22 @author Michael Barton
23 @author Updated by Martin Landa <landa.martin gmail.com>
24 @author Markus Metz redesign georectfier -> GCP Manager
25 """
26 
27 import os
28 import sys
29 import tempfile
30 import shutil
31 import time
32 import cStringIO
33 
34 import wx
35 from wx.lib.mixins.listctrl import CheckListCtrlMixin, ColumnSorterMixin, ListCtrlAutoWidthMixin
36 import wx.lib.colourselect as csel
37 import wx.wizard as wiz
38 
39 import grass.script as grass
40 
41 import globalvar
42 import render
43 import toolbars
44 import menuform
45 import gselect
46 import gcmd
47 import utils
48 from debug import Debug as Debug
49 from icon import Icons as Icons
50 from location_wizard import TitledPage as TitledPage
51 from preferences import globalSettings as UserSettings
52 from gcpmapdisp import MapFrame
53 from mapdisp_window import BufferedWindow
54 
55 try:
56  import subprocess # Not needed if GRASS commands could actually be quiet
57 except:
58  CompatPath = globalvar.ETCWXDIR
59  sys.path.append(CompatPath)
60  from compat import subprocess
61 
62 sys.path.append(os.path.join(globalvar.ETCWXDIR, "icons"))
63 
64 #
65 # global variables
66 #
67 global src_map
68 global tgt_map
69 global maptype
70 
71 src_map = ''
72 tgt_map = ''
73 maptype = 'cell'
74 
76  stream = open(os.path.join(globalvar.ETCIMGDIR, 'small_up_arrow.png'), 'rb')
77  try:
78  img = wx.ImageFromStream(stream)
79  finally:
80  stream.close()
81  return img
82 
84  stream = open(os.path.join(globalvar.ETCIMGDIR, 'small_down_arrow.png'), 'rb')
85  try:
86  img = wx.ImageFromStream(stream)
87  finally:
88  stream.close()
89  stream.close()
90  return img
91 
92 class GCPWizard(object):
93  """
94  Start wizard here and finish wizard here
95  """
96 
97  def __init__(self, parent):
98  self.parent = parent # GMFrame
99 
100  #
101  # get environmental variables
102  #
103  self.grassdatabase = grass.gisenv()['GISDBASE']
104 
105  #
106  # read original environment settings
107  #
108  self.target_gisrc = os.environ['GISRC']
109  self.gisrc_dict = {}
110  try:
111  f = open(self.target_gisrc, 'r')
112  for line in f.readlines():
113  line = line.replace('\n', '').strip()
114  if len(line) < 1:
115  continue
116  key, value = line.split(':', 1)
117  self.gisrc_dict[key.strip()] = value.strip()
118  finally:
119  f.close()
120 
121  self.currentlocation = self.gisrc_dict['LOCATION_NAME']
122  self.currentmapset = self.gisrc_dict['MAPSET']
123  # location for xy map to georectify
124  self.newlocation = ''
125  # mapset for xy map to georectify
126  self.newmapset = ''
127 
128  global maptype
129  global src_map
130  global tgt_map
131 
132  src_map = ''
133  tgt_map = ''
134  maptype = 'cell'
135 
136  # GISRC file for source location/mapset of map(s) to georectify
137  self.source_gisrc = ''
138  self.src_maps = []
139 
140  #
141  # define wizard pages
142  #
143  self.wizard = wiz.Wizard(parent=parent, id=wx.ID_ANY, title=_("Setup for georectification"))
144  self.startpage = LocationPage(self.wizard, self)
145  self.grouppage = GroupPage(self.wizard, self)
146  self.mappage = DispMapPage(self.wizard, self)
147 
148  #
149  # set the initial order of the pages
150  #
151  self.startpage.SetNext(self.grouppage)
152  self.grouppage.SetPrev(self.startpage)
153  self.grouppage.SetNext(self.mappage)
154  self.mappage.SetPrev(self.grouppage)
155 
156  #
157  # do pages layout
158  #
159  self.startpage.DoLayout()
160  self.grouppage.DoLayout()
161  self.mappage.DoLayout()
162  self.wizard.FitToPage(self.startpage)
163 
164  # self.Bind(wx.EVT_CLOSE, self.Cleanup)
165  # self.parent.Bind(wx.EVT_ACTIVATE, self.OnGLMFocus)
166 
167  success = False
168 
169  #
170  # run wizard
171  #
172  if self.wizard.RunWizard(self.startpage):
173  success = self.OnWizFinished()
174  if success == False:
175  gcmd.GMessage(parent = self.parent,
176  message = _("Georectifying setup canceled."))
177  self.Cleanup()
178  else:
179  gcmd.GMessage(parent = self.parent,
180  message = _("Georectifying setup canceled."))
181  self.Cleanup()
182 
183  #
184  # start GCP display
185  #
186  if success != False:
187  # instance of render.Map to be associated with display
188  self.SwitchEnv('source')
189  self.SrcMap = render.Map(gisrc=self.source_gisrc)
190  self.SwitchEnv('target')
191  self.TgtMap = render.Map(gisrc=self.target_gisrc)
192  self.Map = self.SrcMap
193 
194  #
195  # add layer to source map
196  #
197  if maptype == 'cell':
198  rendertype = 'raster'
199  cmdlist = ['d.rast', 'map=%s' % src_map]
200  else: # -> vector layer
201  rendertype = 'vector'
202  cmdlist = ['d.vect', 'map=%s' % src_map]
203 
204  self.SwitchEnv('source')
205  name, found = utils.GetLayerNameFromCmd(cmdlist)
206  self.SrcMap.AddLayer(type=rendertype, command=cmdlist, l_active=True,
207  name=name, l_hidden=False, l_opacity=1.0, l_render=False)
208 
209  if tgt_map:
210  #
211  # add layer to target map
212  #
213  if maptype == 'cell':
214  rendertype = 'raster'
215  cmdlist = ['d.rast', 'map=%s' % tgt_map]
216  else: # -> vector layer
217  rendertype = 'vector'
218  cmdlist = ['d.vect', 'map=%s' % tgt_map]
219 
220  self.SwitchEnv('target')
221  name, found = utils.GetLayerNameFromCmd(cmdlist)
222  self.TgtMap.AddLayer(type=rendertype, command=cmdlist, l_active=True,
223  name=name, l_hidden=False, l_opacity=1.0, l_render=False)
224 
225  #
226  # start GCP Manager
227  #
228  self.gcpmgr = GCP(self.parent, grwiz=self, size=globalvar.MAP_WINDOW_SIZE,
229  toolbars=["gcpdisp"],
230  Map=self.SrcMap, lmgr=self.parent)
231 
232  # load GCPs
233  self.gcpmgr.InitMapDisplay()
234  self.gcpmgr.CenterOnScreen()
235  self.gcpmgr.Show()
236  # need to update AUI here for wingrass
237  self.gcpmgr._mgr.Update()
238  else:
239  self.Cleanup()
240 
241  def SetSrcEnv(self, location, mapset):
242  """!Create environment to use for location and mapset
243  that are the source of the file(s) to georectify
244 
245  @param location source location
246  @param mapset source mapset
247 
248  @return False on error
249  @return True on success
250  """
251 
252  self.newlocation = location
253  self.newmapset = mapset
254 
255  # check to see if we are georectifying map in current working location/mapset
256  if self.newlocation == self.currentlocation and self.newmapset == self.currentmapset:
257  return False
258 
259  self.gisrc_dict['LOCATION_NAME'] = location
260  self.gisrc_dict['MAPSET'] = mapset
261 
262  self.source_gisrc = utils.GetTempfile()
263 
264  try:
265  f = open(self.source_gisrc, mode='w')
266  for line in self.gisrc_dict.items():
267  f.write(line[0] + ": " + line[1] + "\n")
268  finally:
269  f.close()
270 
271  return True
272 
273  def SwitchEnv(self, grc):
274  """
275  Switches between original working location/mapset and
276  location/mapset that is source of file(s) to georectify
277  """
278  # check to see if we are georectifying map in current working location/mapset
279  if self.newlocation == self.currentlocation and self.newmapset == self.currentmapset:
280  return False
281 
282  if grc == 'target':
283  os.environ['GISRC'] = str(self.target_gisrc)
284  elif grc == 'source':
285  os.environ['GISRC'] = str(self.source_gisrc)
286 
287  return True
288 
289  def OnWizFinished(self):
290  # self.Cleanup()
291 
292  return True
293 
294  def OnGLMFocus(self, event):
295  """!Layer Manager focus"""
296  # self.SwitchEnv('target')
297 
298  event.Skip()
299 
300  def Cleanup(self):
301  """!Return to current location and mapset"""
302  self.SwitchEnv('target')
303  self.parent.gcpmanagement = None
304 
305  self.wizard.Destroy()
306 
307 class LocationPage(TitledPage):
308  """
309  Set map type (raster or vector) to georectify and
310  select location/mapset of map(s) to georectify.
311  """
312  def __init__(self, wizard, parent):
313  TitledPage.__init__(self, wizard, _("Select map type and location/mapset"))
314 
315  self.parent = parent
316  self.grassdatabase = self.parent.grassdatabase
317 
318  self.xylocation = ''
319  self.xymapset = ''
320 
321  #
322  # layout
323  #
324  self.sizer.AddGrowableCol(2)
325  # map type
326  self.rb_maptype = wx.RadioBox(parent=self, id=wx.ID_ANY,
327  label=' %s ' % _("Map type to georectify"),
328  choices=[_('raster'), _('vector')],
329  majorDimension=wx.RA_SPECIFY_COLS)
330  self.sizer.Add(item=self.rb_maptype,
331  flag=wx.ALIGN_CENTER | wx.ALL | wx.EXPAND, border=5,
332  pos=(1, 1), span=(1, 2))
333 
334  # location
335  self.sizer.Add(item=wx.StaticText(parent=self, id=wx.ID_ANY, label=_('Select source location:')),
336  flag=wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL | wx.ALL, border=5,
337  pos=(2, 1))
338  self.cb_location = gselect.LocationSelect(parent = self, gisdbase = self.grassdatabase)
339  self.sizer.Add(item=self.cb_location,
340  flag=wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL | wx.ALL, border=5,
341  pos=(2, 2))
342 
343  # mapset
344  self.sizer.Add(item=wx.StaticText(parent=self, id=wx.ID_ANY, label=_('Select source mapset:')),
345  flag=wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL | wx.ALL, border=5,
346  pos=(3, 1))
347  self.cb_mapset = gselect.MapsetSelect(parent = self, gisdbase = self.grassdatabase,
348  setItems = False)
349  self.sizer.Add(item=self.cb_mapset,
350  flag=wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL | wx.ALL, border=5,
351  pos=(3,2))
352 
353  #
354  # bindings
355  #
356  self.Bind(wx.EVT_RADIOBOX, self.OnMaptype, self.rb_maptype)
357  self.Bind(wx.EVT_COMBOBOX, self.OnLocation, self.cb_location)
358  self.Bind(wx.EVT_COMBOBOX, self.OnMapset, self.cb_mapset)
359  self.Bind(wiz.EVT_WIZARD_PAGE_CHANGING, self.OnPageChanging)
360  self.Bind(wiz.EVT_WIZARD_PAGE_CHANGED, self.OnEnterPage)
361  # self.Bind(wx.EVT_CLOSE, self.parent.Cleanup)
362 
363  def OnMaptype(self,event):
364  """!Change map type"""
365  global maptype
366 
367  if event.GetInt() == 0:
368  maptype = 'cell'
369  else:
370  maptype = 'vector'
371 
372  def OnLocation(self, event):
373  """!Sets source location for map(s) to georectify"""
374  self.xylocation = event.GetString()
375 
376  #create a list of valid mapsets
377  tmplist = os.listdir(os.path.join(self.grassdatabase, self.xylocation))
378  self.mapsetList = []
379  for item in tmplist:
380  if os.path.isdir(os.path.join(self.grassdatabase, self.xylocation, item)) and \
381  os.path.exists(os.path.join(self.grassdatabase, self.xylocation, item, 'WIND')):
382  if item != 'PERMANENT':
383  self.mapsetList.append(item)
384 
385  self.xymapset = 'PERMANENT'
386  utils.ListSortLower(self.mapsetList)
387  self.mapsetList.insert(0, 'PERMANENT')
388  self.cb_mapset.SetItems(self.mapsetList)
389  self.cb_mapset.SetStringSelection(self.xymapset)
390 
391  if not wx.FindWindowById(wx.ID_FORWARD).IsEnabled():
392  wx.FindWindowById(wx.ID_FORWARD).Enable(True)
393 
394  def OnMapset(self, event):
395  """!Sets source mapset for map(s) to georectify"""
396  if self.xylocation == '':
397  gcmd.GMessage(_('You must select a valid location '
398  'before selecting a mapset'),
399  parent = self)
400  return
401 
402  self.xymapset = event.GetString()
403 
404  if not wx.FindWindowById(wx.ID_FORWARD).IsEnabled():
405  wx.FindWindowById(wx.ID_FORWARD).Enable(True)
406 
407  def OnPageChanging(self, event=None):
408  if event.GetDirection() and \
409  (self.xylocation == '' or self.xymapset == ''):
410  gcmd.GMessage(_('You must select a valid location '
411  'and mapset in order to continue'),
412  parent = self)
413  event.Veto()
414  return
415 
416  self.parent.SetSrcEnv(self.xylocation, self.xymapset)
417 
418  def OnEnterPage(self, event=None):
419  if self.xylocation == '' or self.xymapset == '':
420  wx.FindWindowById(wx.ID_FORWARD).Enable(False)
421  else:
422  wx.FindWindowById(wx.ID_FORWARD).Enable(True)
423 
424 class GroupPage(TitledPage):
425  """
426  Set group to georectify. Create group if desired.
427  """
428  def __init__(self, wizard, parent):
429  TitledPage.__init__(self, wizard, _("Select image/map group to georectify"))
430 
431  self.parent = parent
432 
433  self.grassdatabase = self.parent.grassdatabase
434  self.groupList = []
435 
436  self.xylocation = ''
437  self.xymapset = ''
438  self.xygroup = ''
439 
440  # default extension
441  self.extension = '.georect' + str(os.getpid())
442 
443  #
444  # layout
445  #
446  self.sizer.AddGrowableCol(2)
447  # group
448  self.sizer.Add(item=wx.StaticText(parent=self, id=wx.ID_ANY, label=_('Select group:')),
449  flag=wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL | wx.ALL, border=5,
450  pos=(1, 1))
451  self.cb_group = wx.ComboBox(parent=self, id=wx.ID_ANY,
452  choices=self.groupList, size=(350, -1),
453  style=wx.CB_DROPDOWN | wx.CB_READONLY)
454  self.sizer.Add(item=self.cb_group,
455  flag=wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL | wx.ALL, border=5,
456  pos=(1, 2))
457 
458  # create group
459  self.sizer.Add(item=wx.StaticText(parent=self, id=wx.ID_ANY, label=_('Create group if none exists')),
460  flag=wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL | wx.ALL, border=5,
461  pos=(2, 1))
462  btnSizer = wx.BoxSizer(wx.HORIZONTAL)
463  self.btn_mkgroup = wx.Button(parent=self, id=wx.ID_ANY, label=_("Create/edit group..."))
464  self.btn_vgroup = wx.Button(parent=self, id=wx.ID_ANY, label=_("Add vector map to group..."))
465  btnSizer.Add(item=self.btn_mkgroup,
466  flag=wx.RIGHT, border=5)
467 
468  btnSizer.Add(item=self.btn_vgroup,
469  flag=wx.LEFT, border=5)
470 
471  self.sizer.Add(item=btnSizer,
472  flag=wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL | wx.ALL, border=5,
473  pos=(2, 2))
474 
475  # extension
476  self.sizer.Add(item=wx.StaticText(parent=self, id=wx.ID_ANY, label=_('Extension for output maps:')),
477  flag=wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL | wx.ALL, border=5,
478  pos=(3, 1))
479  self.ext_txt = wx.TextCtrl(parent=self, id=wx.ID_ANY, value="", size=(350,-1))
480  self.ext_txt.SetValue(self.extension)
481  self.sizer.Add(item=self.ext_txt,
482  flag=wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL | wx.ALL, border=5,
483  pos=(3, 2))
484 
485  #
486  # bindings
487  #
488  self.Bind(wx.EVT_COMBOBOX, self.OnGroup, self.cb_group)
489  self.Bind(wx.EVT_TEXT, self.OnExtension, self.ext_txt)
490  self.Bind(wiz.EVT_WIZARD_PAGE_CHANGING, self.OnPageChanging)
491  self.Bind(wiz.EVT_WIZARD_PAGE_CHANGED, self.OnEnterPage)
492  self.Bind(wx.EVT_CLOSE, self.parent.Cleanup)
493 
494  # hide vector group button by default
495  self.btn_vgroup.Hide()
496 
497  def OnGroup(self, event):
498  self.xygroup = event.GetString()
499 
500  def OnMkGroup(self, event):
501  """!Create new group in source location/mapset"""
502  menuform.GUI(parent = self.parent.parent, modal = True).ParseCommand(['i.group'],
503  completed = (self.GetOptData, None, ''))
504 
505  def OnVGroup(self, event):
506  """!Add vector maps to group"""
507  dlg = VectGroup(parent = self,
508  id = wx.ID_ANY,
509  grassdb = self.grassdatabase,
510  location = self.xylocation,
511  mapset = self.xymapset,
512  group = self.xygroup)
513 
514  if dlg.ShowModal() != wx.ID_OK:
515  return
516 
517  dlg.MakeVGroup()
518  self.OnEnterPage()
519 
520  def GetOptData(self, dcmd, layer, params, propwin):
521  """!Process i.group"""
522  # update the page
523  if dcmd:
524  gcmd.Command(dcmd)
525 
526  self.OnEnterPage()
527  self.Update()
528 
529  def OnExtension(self, event):
530  self.extension = event.GetString()
531 
532  def OnPageChanging(self, event=None):
533  if event.GetDirection() and self.xygroup == '':
534  gcmd.GMessage(_('You must select a valid image/map '
535  'group in order to continue'),
536  parent = self)
537  event.Veto()
538  return
539 
540  if event.GetDirection() and self.extension == '':
541  gcmd.GMessage(_('You must enter an map name '
542  'extension in order to continue'),
543  parent = self)
544  event.Veto()
545  return
546 
547  def OnEnterPage(self, event=None):
548  global maptype
549 
550  self.groupList = []
551 
552  self.xylocation = self.parent.gisrc_dict['LOCATION_NAME']
553  self.xymapset = self.parent.gisrc_dict['MAPSET']
554 
555  # create a list of groups in selected mapset
556  if os.path.isdir(os.path.join(self.grassdatabase,
557  self.xylocation,
558  self.xymapset,
559  'group')):
560  tmplist = os.listdir(os.path.join(self.grassdatabase,
561  self.xylocation,
562  self.xymapset,
563  'group'))
564  for item in tmplist:
565  if os.path.isdir(os.path.join(self.grassdatabase,
566  self.xylocation,
567  self.xymapset,
568  'group',
569  item)):
570  self.groupList.append(item)
571 
572  if maptype == 'cell':
573  self.btn_vgroup.Hide()
574  self.Bind(wx.EVT_BUTTON, self.OnMkGroup, self.btn_mkgroup)
575 
576  elif maptype == 'vector':
577  self.btn_vgroup.Show()
578  self.Bind(wx.EVT_BUTTON, self.OnMkGroup, self.btn_mkgroup)
579  self.Bind(wx.EVT_BUTTON, self.OnVGroup, self.btn_vgroup)
580 
581  utils.ListSortLower(self.groupList)
582  self.cb_group.SetItems(self.groupList)
583 
584  if len(self.groupList) > 0 and \
585  self.xygroup == '':
586  self.cb_group.SetSelection(0)
587  self.xygroup = self.groupList[0]
588 
589  if self.xygroup == '' or \
590  self.extension == '':
591  wx.FindWindowById(wx.ID_FORWARD).Enable(False)
592  else:
593  wx.FindWindowById(wx.ID_FORWARD).Enable(True)
594 
595  # switch to source
596  self.parent.SwitchEnv('source')
597 
598 class DispMapPage(TitledPage):
599  """
600  Select ungeoreferenced map to display for interactively
601  setting ground control points (GCPs).
602  """
603  def __init__(self, wizard, parent):
604  TitledPage.__init__(self, wizard,
605  _("Select maps to display for ground control point (GCP) creation"))
606 
607  self.parent = parent
608  global maptype
609 
610  #
611  # layout
612  #
613  self.sizer.Add(item=wx.StaticText(parent=self, id=wx.ID_ANY, label=_('Select source map to display:')),
614  flag=wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL | wx.ALL, border=5,
615  pos=(1, 1))
616 
617  self.srcselection = gselect.Select(self, id=wx.ID_ANY,
618  size=globalvar.DIALOG_GSELECT_SIZE, type=maptype, updateOnPopup = False)
619 
620  self.sizer.Add(item=self.srcselection,
621  flag=wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL | wx.ALL, border=5,
622  pos=(1, 2))
623 
624  self.sizer.Add(item=wx.StaticText(parent=self, id=wx.ID_ANY, label=_('Select target map to display:')),
625  flag=wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL | wx.ALL, border=5,
626  pos=(2, 1))
627 
628  self.tgtselection = gselect.Select(self, id=wx.ID_ANY,
629  size=globalvar.DIALOG_GSELECT_SIZE, type=maptype, updateOnPopup = False)
630 
631  self.sizer.Add(item=self.tgtselection,
632  flag=wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL | wx.ALL, border=5,
633  pos=(2, 2))
634 
635  #
636  # bindings
637  #
638  self.srcselection.Bind(wx.EVT_TEXT, self.OnSrcSelection)
639  self.tgtselection.Bind(wx.EVT_TEXT, self.OnTgtSelection)
640  self.Bind(wiz.EVT_WIZARD_PAGE_CHANGING, self.OnPageChanging)
641  self.Bind(wiz.EVT_WIZARD_PAGE_CHANGED, self.OnEnterPage)
642  self.Bind(wx.EVT_CLOSE, self.parent.Cleanup)
643 
644  def OnSrcSelection(self,event):
645  """!Source map to display selected"""
646  global src_map
647  global maptype
648 
649  src_map = event.GetString()
650 
651  if src_map == '':
652  wx.FindWindowById(wx.ID_FORWARD).Enable(False)
653  else:
654  wx.FindWindowById(wx.ID_FORWARD).Enable(True)
655 
656  try:
657  # set computational region to match selected map and zoom display to region
658  if maptype == 'cell':
659  p = gcmd.Command(['g.region', 'rast=src_map'])
660  elif maptype == 'vector':
661  p = gcmd.Command(['g.region', 'vect=src_map'])
662 
663  if p.returncode == 0:
664  print 'returncode = ', str(p.returncode)
665  self.parent.Map.region = self.parent.Map.GetRegion()
666  except:
667  pass
668 
669  def OnTgtSelection(self,event):
670  """!Source map to display selected"""
671  global tgt_map
672 
673  tgt_map = event.GetString()
674 
675  def OnPageChanging(self, event=None):
676  global src_map
677  global tgt_map
678 
679  if event.GetDirection() and (src_map == ''):
680  gcmd.GMessage(_('You must select a source map '
681  'in order to continue'),
682  parent = self)
683  event.Veto()
684  return
685 
686  self.parent.SwitchEnv('target')
687 
688  def OnEnterPage(self, event=None):
689  global maptype
690  global src_map
691  global tgt_map
692 
693  self.srcselection.SetElementList(maptype)
694  ret = gcmd.RunCommand('i.group',
695  parent = self,
696  read = True,
697  group = self.parent.grouppage.xygroup,
698  flags = 'g')
699 
700  if ret:
701  self.parent.src_maps = ret.splitlines()
702  else:
703  gcmd.GError(parent = self,
704  message = _('No maps in selected group <%s>.\n'
705  'Please edit group or select another group.') %
706  self.parent.grouppage.xygroup)
707  return
708 
709  # filter out all maps not in group
710  self.srcselection.tcp.GetElementList(elements = self.parent.src_maps)
711  src_map = self.parent.src_maps[0]
712  self.srcselection.SetValue(src_map)
713 
714  self.parent.SwitchEnv('target')
715  self.tgtselection.SetElementList(maptype)
716  self.tgtselection.GetElementList()
717  self.parent.SwitchEnv('source')
718 
719  if src_map == '':
720  wx.FindWindowById(wx.ID_FORWARD).Enable(False)
721  else:
722  wx.FindWindowById(wx.ID_FORWARD).Enable(True)
723 
724 class GCP(MapFrame, wx.Frame, ColumnSorterMixin):
725  """!
726  Manages ground control points for georectifying. Calculates RMS statics.
727  Calls i.rectify or v.transform to georectify map.
728  """
729  def __init__(self, parent, grwiz = None, id = wx.ID_ANY,
730  title = _("Manage Ground Control Points"),
731  size = (700, 300), toolbars=["gcpdisp"], Map=None, lmgr=None):
732 
733  self.grwiz = grwiz # GR Wizard
734 
735  if tgt_map == '':
736  self.show_target = False
737  else:
738  self.show_target = True
739 
740  #wx.Frame.__init__(self, parent, id, title, size = size, name = "GCPFrame")
741  MapFrame.__init__(self, parent, id, title, size = size,
742  Map=Map, toolbars=["gcpdisp"], lmgr=lmgr, name='GCPMapWindow')
743 
744  #
745  # init variables
746  #
747  self.parent = parent # GMFrame
748  self.parent.gcpmanagement = self
749 
750  self.grassdatabase = self.grwiz.grassdatabase
751 
752  self.currentlocation = self.grwiz.currentlocation
753  self.currentmapset = self.grwiz.currentmapset
754 
755  self.newlocation = self.grwiz.newlocation
756  self.newmapset = self.grwiz.newmapset
757 
758  self.xylocation = self.grwiz.gisrc_dict['LOCATION_NAME']
759  self.xymapset = self.grwiz.gisrc_dict['MAPSET']
760  self.xygroup = self.grwiz.grouppage.xygroup
761  self.src_maps = self.grwiz.src_maps
762  self.extension = self.grwiz.grouppage.extension
763  self.outname = ''
764  self.VectGRList = []
765 
766  self.file = {
767  'points' : os.path.join(self.grassdatabase,
768  self.xylocation,
769  self.xymapset,
770  'group',
771  self.xygroup,
772  'POINTS'),
773  'points_bak' : os.path.join(self.grassdatabase,
774  self.xylocation,
775  self.xymapset,
776  'group',
777  self.xygroup,
778  'POINTS_BAK'),
779  'rgrp' : os.path.join(self.grassdatabase,
780  self.xylocation,
781  self.xymapset,
782  'group',
783  self.xygroup,
784  'REF'),
785  'vgrp' : os.path.join(self.grassdatabase,
786  self.xylocation,
787  self.xymapset,
788  'group',
789  self.xygroup,
790  'VREF'),
791  'target' : os.path.join(self.grassdatabase,
792  self.xylocation,
793  self.xymapset,
794  'group',
795  self.xygroup,
796  'TARGET'),
797  }
798 
799  # make a backup of the current points file
800  if os.path.exists(self.file['points']):
801  shutil.copy(self.file['points'], self.file['points_bak'])
802 
803  # polynomial order transformation for georectification
804  self.gr_order = 1
805  # interpolation method for georectification
806  self.gr_method = 'nearest'
807  # region clipping for georectified map
808  self.clip_to_region = False
809  # number of GCPs selected to be used for georectification (checked)
810  self.GCPcount = 0
811  # forward RMS error
812  self.fwd_rmserror = 0.0
813  # backward RMS error
814  self.bkw_rmserror = 0.0
815  # list map coords and ID of map display they came from
816  self.mapcoordlist = []
817  self.mapcoordlist.append([ 0, # GCP number
818  0.0, # source east
819  0.0, # source north
820  0.0, # target east
821  0.0, # target north
822  0.0, # forward error
823  0.0 ] ) # backward error
824 
825  # init vars to highlight high RMS errors
826  self.highest_only = True
827  self.show_unused = True
828  self.highest_key = -1
829  self.rmsthresh = 0
830  self.rmsmean = 0
831  self.rmssd = 0
832 
833  self.SetTarget(self.xygroup, self.currentlocation, self.currentmapset)
834 
835  self.itemDataMap = None
836 
837  # images for column sorting
838  # CheckListCtrlMixin must set an ImageList first
839  self.il = self.list.GetImageList(wx.IMAGE_LIST_SMALL)
840 
841  SmallUpArrow = wx.BitmapFromImage(getSmallUpArrowImage())
842  SmallDnArrow = wx.BitmapFromImage(getSmallDnArrowImage())
843  self.sm_dn = self.il.Add(SmallDnArrow)
844  self.sm_up = self.il.Add(SmallUpArrow)
845 
846  # set mouse characteristics
847  self.mapwin = self.SrcMapWindow
848  self.mapwin.mouse['box'] = 'point'
849  self.mapwin.mouse["use"] == "pointer"
850  self.mapwin.zoomtype = 0
851  self.mapwin.pen = wx.Pen(colour='black', width=2, style=wx.SOLID)
852  self.mapwin.SetCursor(self.cursors["cross"])
853 
854  self.mapwin = self.TgtMapWindow
855 
856  # set mouse characteristics
857  self.mapwin.mouse['box'] = 'point'
858  self.mapwin.mouse["use"] == "pointer"
859  self.mapwin.zoomtype = 0
860  self.mapwin.pen = wx.Pen(colour='black', width=2, style=wx.SOLID)
861  self.mapwin.SetCursor(self.cursors["cross"])
862 
863  #
864  # show new display & draw map
865  #
866  if self.show_target:
867  self.MapWindow = self.TgtMapWindow
868  self.Map = self.TgtMap
869  self.OnZoomToMap(None)
870 
871  self.MapWindow = self.SrcMapWindow
872  self.Map = self.SrcMap
873  self.OnZoomToMap(None)
874 
875  #
876  # bindings
877  #
878  self.Bind(wx.EVT_ACTIVATE, self.OnFocus)
879  self.Bind(wx.EVT_CLOSE, self.OnQuit)
880 
881  def __del__(self):
882  """!Disable GCP manager mode"""
883  self.parent.gcpmanagement = None
884 
885  def CreateGCPList(self):
886  """!Create GCP List Control"""
887 
888  return GCPList(parent=self, gcp=self)
889 
890  # Used by the ColumnSorterMixin, see wx/lib/mixins/listctrl.py
891  def GetListCtrl(self):
892  return self.list
893 
894  # Used by the ColumnSorterMixin, see wx/lib/mixins/listctrl.py
895  def GetSortImages(self):
896  return (self.sm_dn, self.sm_up)
897 
898  def InitMapDisplay(self):
899  self.list.LoadData()
900 
901  # initialize column sorter
902  self.itemDataMap = self.mapcoordlist
903  ncols = self.list.GetColumnCount()
904  ColumnSorterMixin.__init__(self, ncols)
905  # init to ascending sort on first click
906  self._colSortFlag = [1] * ncols
907 
908  def SetTarget(self, tgroup, tlocation, tmapset):
909  """
910  Sets rectification target to current location and mapset
911  """
912  # check to see if we are georectifying map in current working location/mapset
913  if self.newlocation == self.currentlocation and self.newmapset == self.currentmapset:
914  gcmd.RunCommand('i.target',
915  parent = self,
916  flags = 'c',
917  group = tgroup)
918  else:
919  self.grwiz.SwitchEnv('source')
920  gcmd.RunCommand('i.target',
921  parent = self,
922  group = tgroup,
923  location = tlocation,
924  mapset = tmapset)
925  self.grwiz.SwitchEnv('target')
926 
927  def AddGCP(self, event):
928  """
929  Appends an item to GCP list
930  """
931  keyval = self.list.AddGCPItem() + 1
932  # source east, source north, target east, target north, forward error, backward error
933  self.mapcoordlist.append([ keyval, # GCP number
934  0.0, # source east
935  0.0, # source north
936  0.0, # target east
937  0.0, # target north
938  0.0, # forward error
939  0.0 ] ) # backward error
940 
941  if self.statusbarWin['toggle'].GetSelection() == 7: # go to
942  self.StatusbarUpdate()
943 
944  def DeleteGCP(self, event):
945  """
946  Deletes selected item in GCP list
947  """
948  minNumOfItems = self.OnGROrder(None)
949 
950  if self.list.GetItemCount() <= minNumOfItems:
951  gcmd.GMessage(parent = self,
952  message=_("At least %d GCPs required. Operation cancelled.") % minNumOfItems)
953  return
954 
955  key = self.list.DeleteGCPItem()
956  del self.mapcoordlist[key]
957 
958  # update key and GCP number
959  for newkey in range(key, len(self.mapcoordlist)):
960  index = self.list.FindItemData(-1, newkey + 1)
961  self.mapcoordlist[newkey][0] = newkey
962  self.list.SetStringItem(index, 0, str(newkey))
963  self.list.SetItemData(index, newkey)
964 
965  # update selected
966  if self.list.GetItemCount() > 0:
967  if self.list.selected < self.list.GetItemCount():
968  self.list.selectedkey = self.list.GetItemData(self.list.selected)
969  else:
970  self.list.selected = self.list.GetItemCount() - 1
971  self.list.selectedkey = self.list.GetItemData(self.list.selected)
972 
973  self.list.SetItemState(self.list.selected,
974  wx.LIST_STATE_SELECTED,
975  wx.LIST_STATE_SELECTED)
976  else:
977  self.list.selected = wx.NOT_FOUND
978  self.list.selectedkey = -1
979 
980  self.UpdateColours()
981 
982  if self.statusbarWin['toggle'].GetSelection() == 7: # go to
983  self.StatusbarUpdate()
984  if self.list.selectedkey > 0:
985  self.statusbarWin['goto'].SetValue(self.list.selectedkey)
986  #self.statusbarWin['goto'].SetValue(0)
987 
988  def ClearGCP(self, event):
989  """
990  Clears all values in selected item of GCP list and unchecks it
991  """
992  index = self.list.GetSelected()
993 
994  for i in range(4):
995  self.list.SetStringItem(index, i, '0.0')
996  self.list.SetStringItem(index, 4, '')
997  self.list.SetStringItem(index, 5, '')
998  self.list.CheckItem(index, False)
999  key = self.list.GetItemData(index)
1000 
1001  # GCP number, source E, source N, target E, target N, fwd error, bkwd error
1002  self.mapcoordlist[key] = [key, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]
1003 
1004  def DrawGCP(self, coordtype):
1005  """
1006  Updates GCP and map coord maps and redraws
1007  active (checked) GCP markers
1008  """
1009  self.highest_only = UserSettings.Get(group='gcpman', key='rms', subkey='highestonly')
1010 
1011  self.show_unused = UserSettings.Get(group='gcpman', key='symbol', subkey='unused')
1012  col = UserSettings.Get(group='gcpman', key='symbol', subkey='color')
1013  wxLowCol = wx.Colour(col[0], col[1], col[2], 255)
1014  col = UserSettings.Get(group='gcpman', key='symbol', subkey='hcolor')
1015  wxHiCol = wx.Colour(col[0], col[1], col[2], 255)
1016  col = UserSettings.Get(group='gcpman', key='symbol', subkey='scolor')
1017  wxSelCol = wx.Colour(col[0], col[1], col[2], 255)
1018  col = UserSettings.Get(group='gcpman', key='symbol', subkey='ucolor')
1019  wxUnCol = wx.Colour(col[0], col[1], col[2], 255)
1020  spx = UserSettings.Get(group='gcpman', key='symbol', subkey='size')
1021  wpx = UserSettings.Get(group='gcpman', key='symbol', subkey='width')
1022  font = self.GetFont()
1023  font.SetPointSize(int(spx) + 2)
1024 
1025  penOrig = polypenOrig = None
1026 
1027  mapWin = None
1028 
1029  if coordtype == 'source':
1030  mapWin = self.SrcMapWindow
1031  e_idx = 1
1032  n_idx = 2
1033  elif coordtype == 'target':
1034  mapWin = self.TgtMapWindow
1035  e_idx = 3
1036  n_idx = 4
1037 
1038  if not mapWin:
1039  gcmd.GError(parent = self,
1040  message="%s%s." % (_("mapwin not defined for "),
1041  str(idx)))
1042  return
1043 
1044  #for gcp in self.mapcoordlist:
1045  for idx in range(self.list.GetItemCount()):
1046 
1047  key = self.list.GetItemData(idx)
1048  gcp = self.mapcoordlist[key]
1049 
1050  if not self.list.IsChecked(idx):
1051  if self.show_unused:
1052  wxCol = wxUnCol
1053  else:
1054  continue
1055  else:
1056  if self.highest_only == True:
1057  if key == self.highest_key:
1058  wxCol = wxHiCol
1059  else:
1060  wxCol = wxLowCol
1061  elif self.rmsthresh > 0:
1062  if (gcp[5] > self.rmsthresh):
1063  wxCol = wxHiCol
1064  else:
1065  wxCol = wxLowCol
1066 
1067  if idx == self.list.selected:
1068  wxCol = wxSelCol
1069 
1070  if not penOrig:
1071  penOrig = mapWin.pen
1072  polypenOrig = mapWin.polypen
1073  mapWin.pen = wx.Pen(colour=wxCol, width=wpx, style=wx.SOLID)
1074  mapWin.polypen = wx.Pen(colour=wxCol, width=wpx, style=wx.SOLID) # ?
1075 
1076  mapWin.pen.SetColour(wxCol)
1077  mapWin.polypen.SetColour(wxCol)
1078 
1079  coord = mapWin.Cell2Pixel((gcp[e_idx], gcp[n_idx]))
1080  mapWin.DrawCross(pdc=mapWin.pdcTmp, coords=coord,
1081  size=spx, text={ 'text' : '%s' % str(gcp[0]),
1082  'active' : True,
1083  'font' : font,
1084  'color': wxCol,
1085  'coords': [coord[0] + 5,
1086  coord[1] + 5,
1087  5,
1088  5]})
1089 
1090  if penOrig:
1091  mapWin.pen = penOrig
1092  mapWin.polypen = polypenOrig
1093 
1094  def SetGCPData(self, coordtype, coord, mapdisp=None, confirm=False):
1095  """
1096  Inserts coordinates from file, mouse click on map, or after editing
1097  into selected item of GCP list and checks it for use
1098  """
1099 
1100  index = self.list.GetSelected()
1101  if index == wx.NOT_FOUND:
1102  return
1103 
1104  coord0 = coord[0]
1105  coord1 = coord[1]
1106 
1107  key = self.list.GetItemData(index)
1108  if confirm:
1109  if self.MapWindow == self.SrcMapWindow:
1110  currloc = _("source")
1111  else:
1112  currloc = _("target")
1113  ret = wx.MessageBox(parent=self,
1114  caption=_("Set GCP coordinates"),
1115  message=_('Set %(coor)s coordinates for GCP No. %(key)s? \n\n'
1116  'East: %(coor0)s \n'
1117  'North: %(coor1)s') % \
1118  { 'coor' : currloc,
1119  'key' : str(key),
1120  'coor0' : str(coord0),
1121  'coor1' : str(coord1) },
1122  style=wx.ICON_QUESTION | wx.YES_NO | wx.CENTRE)
1123 
1124  # for wingrass
1125  if os.name == 'nt':
1126  self.MapWindow.SetFocus()
1127  if ret == wx.NO:
1128  return
1129 
1130  if coordtype == 'source':
1131  self.list.SetStringItem(index, 1, str(coord0))
1132  self.list.SetStringItem(index, 2, str(coord1))
1133  self.mapcoordlist[key][1] = coord[0]
1134  self.mapcoordlist[key][2] = coord[1]
1135  elif coordtype == 'target':
1136  self.list.SetStringItem(index, 3, str(coord0))
1137  self.list.SetStringItem(index, 4, str(coord1))
1138  self.mapcoordlist[key][3] = coord[0]
1139  self.mapcoordlist[key][4] = coord[1]
1140 
1141  self.list.SetStringItem(index, 5, '0')
1142  self.list.SetStringItem(index, 6, '0')
1143  self.mapcoordlist[key][5] = 0.0
1144  self.mapcoordlist[key][6] = 0.0
1145 
1146  # self.list.ResizeColumns()
1147 
1148  def SaveGCPs(self, event):
1149  """
1150  Make a POINTS file or save GCP coordinates to existing POINTS file
1151  """
1152 
1153  self.GCPcount = 0
1154  try:
1155  f = open(self.file['points'], mode='w')
1156  # use os.linesep or '\n' here ???
1157  f.write('# Ground Control Points File\n')
1158  f.write("# \n")
1159  f.write("# target location: " + self.currentlocation + '\n')
1160  f.write("# target mapset: " + self.currentmapset + '\n')
1161  f.write("#\tsource\t\ttarget\t\tstatus\n")
1162  f.write("#\teast\tnorth\teast\tnorth\t(1=ok, 0=ignore)\n")
1163  f.write("#----------------------- ----------------------- ---------------\n")
1164 
1165  for index in range(self.list.GetItemCount()):
1166  if self.list.IsChecked(index) == True:
1167  check = "1"
1168  self.GCPcount += 1
1169  else:
1170  check = "0"
1171  coord0 = self.list.GetItem(index, 1).GetText()
1172  coord1 = self.list.GetItem(index, 2).GetText()
1173  coord2 = self.list.GetItem(index, 3).GetText()
1174  coord3 = self.list.GetItem(index, 4).GetText()
1175  f.write(coord0 + ' ' + coord1 + ' ' + coord2 + ' ' + coord3 + ' ' + check + '\n')
1176 
1177  except IOError, err:
1178  gcmd.GError(parent = self,
1179  message="%s <%s>. %s%s" % (_("Writing POINTS file failed"),
1180  self.file['points'], os.linesep, err))
1181  return
1182 
1183  f.close()
1184 
1185  # if event != None save also to backup file
1186  if event:
1187  shutil.copy(self.file['points'], self.file['points_bak'])
1188  self.parent.goutput.WriteLog(_('POINTS file saved for group <%s>') % self.xygroup)
1189  #self.SetStatusText(_('POINTS file saved'))
1190 
1191  def ReadGCPs(self):
1192  """
1193  Reads GCPs and georectified coordinates from POINTS file
1194  """
1195 
1196  self.GCPcount = 0
1197 
1198  sourceMapWin = self.SrcMapWindow
1199  targetMapWin = self.TgtMapWindow
1200  #targetMapWin = self.parent.curr_page.maptree.mapdisplay.MapWindow
1201 
1202  if not sourceMapWin:
1203  gcmd.GError(parent = self,
1204  message = "%s. %s%s" % (_("source mapwin not defined"),
1205  os.linesep, err))
1206 
1207  if not targetMapWin:
1208  gcmd.GError(parent = self,
1209  message="%s. %s%s" % (_("target mapwin not defined"),
1210  os.linesep, err))
1211 
1212  try:
1213  f = open(self.file['points'], 'r')
1214  GCPcnt = 0
1215 
1216  for line in f.readlines():
1217  if line[0] == '#' or line =='':
1218  continue
1219  line = line.replace('\n', '').strip()
1220  coords = map(float, line.split())
1221  if coords[4] == 1:
1222  check = True
1223  self.GCPcount +=1
1224  else:
1225  check = False
1226 
1227  self.AddGCP(event=None)
1228  self.SetGCPData('source', (coords[0], coords[1]), sourceMapWin)
1229  self.SetGCPData('target', (coords[2], coords[3]), targetMapWin)
1230  index = self.list.GetSelected()
1231  if index != wx.NOT_FOUND:
1232  self.list.CheckItem(index, check)
1233  GCPcnt += 1
1234 
1235  except IOError, err:
1236  gcmd.GError(parent = self,
1237  message = "%s <%s>. %s%s" % (_("Reading POINTS file failed"),
1238  self.file['points'], os.linesep, err))
1239  return
1240 
1241  f.close()
1242 
1243  if GCPcnt == 0:
1244  # 3 gcp is minimum
1245  for i in range(3):
1246  self.AddGCP(None)
1247 
1248  if self.CheckGCPcount():
1249  # calculate RMS
1250  self.RMSError(self.xygroup, self.gr_order)
1251 
1252  def ReloadGCPs(self, event):
1253  """!Reload data from file"""
1254 
1255  # use backup
1256  shutil.copy(self.file['points_bak'], self.file['points'])
1257 
1258  # delete all items in mapcoordlist
1259  self.mapcoordlist = []
1260  self.mapcoordlist.append([ 0, # GCP number
1261  0.0, # source east
1262  0.0, # source north
1263  0.0, # target east
1264  0.0, # target north
1265  0.0, # forward error
1266  0.0 ] ) # backward error
1267 
1268  self.list.LoadData()
1269  self.itemDataMap = self.mapcoordlist
1270 
1271  if self._col != -1:
1272  self.list.ClearColumnImage(self._col)
1273  self._colSortFlag = [1] * self.list.GetColumnCount()
1274 
1275  # draw GCPs (source and target)
1276  sourceMapWin = self.SrcMapWindow
1277  sourceMapWin.UpdateMap(render=False, renderVector=False)
1278  if self.show_target:
1279  targetMapWin = self.TgtMapWindow
1280  targetMapWin.UpdateMap(render=False, renderVector=False)
1281 
1282  def OnFocus(self, event):
1283  # self.grwiz.SwitchEnv('source')
1284  pass
1285 
1286  def OnRMS(self, event):
1287  """
1288  RMS button handler
1289  """
1290  self.RMSError(self.xygroup,self.gr_order)
1291 
1292  sourceMapWin = self.SrcMapWindow
1293  sourceMapWin.UpdateMap(render=False, renderVector=False)
1294  if self.show_target:
1295  targetMapWin = self.TgtMapWindow
1296  targetMapWin.UpdateMap(render=False, renderVector=False)
1297 
1298  def CheckGCPcount(self, msg=False):
1299  """
1300  Checks to make sure that the minimum number of GCPs have been defined and
1301  are active for the selected transformation order
1302  """
1303  if (self.GCPcount < 3 and self.gr_order == 1) or \
1304  (self.GCPcount < 6 and self.gr_order == 2) or \
1305  (self.GCPcount < 10 and self.gr_order == 3):
1306  if msg:
1307  gcmd.GWarning(parent = self,
1308  message=_('Insufficient points defined and active (checked) '
1309  'for selected rectification method.\n'
1310  '3+ points needed for 1st order,\n'
1311  '6+ points for 2nd order, and\n'
1312  '10+ points for 3rd order.'))
1313  return False
1314  else:
1315  return True
1316 
1317  def OnGeorect(self, event):
1318  """
1319  Georectifies map(s) in group using i.rectify or v.transform
1320  """
1321  global maptype
1322  self.SaveGCPs(None)
1323 
1324  if self.CheckGCPcount(msg=True) == False:
1325  return
1326 
1327  if maptype == 'cell':
1328  self.grwiz.SwitchEnv('source')
1329 
1330  if self.clip_to_region:
1331  flags = "ac"
1332  else:
1333  flags = "a"
1334 
1335  busy = wx.BusyInfo(message=_("Rectifying images, please wait..."),
1336  parent=self)
1337  wx.Yield()
1338 
1339  ret, msg = gcmd.RunCommand('i.rectify',
1340  parent = self,
1341  getErrorMsg = True,
1342  quiet = True,
1343  group = self.xygroup,
1344  extension = self.extension,
1345  order = self.gr_order,
1346  method=self.gr_method,
1347  flags = flags)
1348 
1349  busy.Destroy()
1350 
1351  # provide feedback on failure
1352  if ret != 0:
1353  print >> sys.stderr, msg
1354 
1355  elif maptype == 'vector':
1356  outmsg = ''
1357  # loop through all vectors in VREF
1358  # and move resulting vector to target location
1359 
1360  # make sure current mapset has a vector folder
1361  if not os.path.isdir(os.path.join(self.grassdatabase,
1362  self.currentlocation,
1363  self.currentmapset,
1364  'vector')):
1365  os.mkdir(os.path.join(self.grassdatabase,
1366  self.currentlocation,
1367  self.currentmapset,
1368  'vector'))
1369 
1370  self.grwiz.SwitchEnv('source')
1371 
1372  # make list of vectors to georectify from VREF
1373  f = open(self.file['vgrp'])
1374  vectlist = []
1375  try:
1376  for vect in f.readlines():
1377  vect = vect.strip('\n')
1378  if len(vect) < 1:
1379  continue
1380  vectlist.append(vect)
1381  finally:
1382  f.close()
1383 
1384  # georectify each vector in VREF using v.transform
1385  for vect in vectlist:
1386  self.outname = vect + '_' + self.extension
1387  self.parent.goutput.WriteLog(text = _('Transforming <%s>...') % vect,
1388  switchPage = True)
1389  msg = err = ''
1390 
1391  ret, out, err = gcmd.RunCommand('v.transform',
1392  overwrite = True,
1393  input = vect,
1394  output = self.outname,
1395  pointsfile = self.file['points'],
1396  getErrorMsg = True, read = True)
1397 
1398  if ret == 0:
1399  self.VectGRList.append(self.outname)
1400  # note: WriteLog doesn't handle GRASS_INFO_PERCENT well, so using a print here
1401  # self.parent.goutput.WriteLog(text = _(err), switchPage = True)
1402  self.parent.goutput.WriteLog(text = out, switchPage = True)
1403  else:
1404  self.parent.goutput.WriteError(_('Georectification of vector map <%s> failed') %
1405  self.outname)
1406  self.parent.goutput.WriteError(err)
1407 
1408  # FIXME
1409  # Copying database information not working.
1410  # Does not copy from xy location to current location
1411  # TODO: replace $GISDBASE etc with real paths
1412  # xyLayer = []
1413  # for layer in grass.vector_db(map = vect).itervalues():
1414  # xyLayer.append((layer['driver'],
1415  # layer['database'],
1416  # layer['table']))
1417 
1418 
1419  # dbConnect = grass.db_connection()
1420  # print 'db connection =', dbConnect
1421  # for layer in xyLayer:
1422  # self.parent.goutput.RunCmd(['db.copy',
1423  # '--q',
1424  # '--o',
1425  # 'from_driver=%s' % layer[0],
1426  # 'from_database=%s' % layer[1],
1427  # 'from_table=%s' % layer[2],
1428  # 'to_driver=%s' % dbConnect['driver'],
1429  # 'to_database=%s' % dbConnect['database'],
1430  # 'to_table=%s' % layer[2] + '_' + self.extension])
1431 
1432  # copy all georectified vectors from source location to current location
1433  for name in self.VectGRList:
1434  xyvpath = os.path.join(self.grassdatabase,
1435  self.xylocation,
1436  self.xymapset,
1437  'vector',
1438  name)
1439  vpath = os.path.join(self.grassdatabase,
1440  self.currentlocation,
1441  self.currentmapset,
1442  'vector',
1443  name)
1444 
1445  if os.path.isdir(vpath):
1446  self.parent.goutput.WriteWarning(_('Vector map <%s> already exists. '
1447  'Change extension name and '
1448  'georectify again.') % self.outname)
1449  break
1450  else:
1451  # use shutil.copytree() because shutil.move() deletes src dir
1452  shutil.copytree(xyvpath, vpath)
1453 
1454  # TODO: connect vectors to copied tables with v.db.connect
1455 
1456  gcmd.GMessage(_('For all vector maps georectified successfully,') + '\n' +
1457  _('you will need to copy any attribute tables') + '\n' +
1458  _('and reconnect them to the georectified vectors'),
1459  parent = self)
1460 
1461  self.grwiz.SwitchEnv('target')
1462 
1463  def OnGeorectDone(self, **kargs):
1464  """!Print final message"""
1465  global maptype
1466  if maptype == 'cell':
1467  return
1468 
1469  returncode = kargs['returncode']
1470 
1471  if returncode == 0:
1472  self.VectGRList.append(self.outname)
1473  print '*****vector list = ' + str(self.VectGRList)
1474  else:
1475  self.parent.goutput.WriteError(_('Georectification of vector map <%s> failed') %
1476  self.outname)
1477 
1478 
1479  def OnSettings(self, event):
1480  """!GCP Manager settings"""
1481  dlg = GrSettingsDialog(parent=self, id=wx.ID_ANY, title=_('GCP Manager settings'))
1482 
1483  if dlg.ShowModal() == wx.ID_OK:
1484  pass
1485 
1486  dlg.Destroy()
1487 
1488  def UpdateColours(self, srcrender=False, srcrenderVector=False,
1489  tgtrender=False, tgtrenderVector=False):
1490  """!update colours"""
1491  highest_fwd_err = 0.0
1492  self.highest_key = 0
1493  highest_idx = 0
1494 
1495  for index in range(self.list.GetItemCount()):
1496  if self.list.IsChecked(index):
1497  key = self.list.GetItemData(index)
1498  fwd_err = self.mapcoordlist[key][5]
1499 
1500  if self.highest_only == True:
1501  self.list.SetItemTextColour(index, wx.BLACK)
1502  if highest_fwd_err < fwd_err:
1503  highest_fwd_err = fwd_err
1504  self.highest_key = key
1505  highest_idx = index
1506  elif self.rmsthresh > 0:
1507  if (fwd_err > self.rmsthresh):
1508  self.list.SetItemTextColour(index, wx.RED)
1509  else:
1510  self.list.SetItemTextColour(index, wx.BLACK)
1511  else:
1512  self.list.SetItemTextColour(index, wx.BLACK)
1513 
1514  if self.highest_only and highest_fwd_err > 0.0:
1515  self.list.SetItemTextColour(highest_idx, wx.RED)
1516 
1517  sourceMapWin = self.SrcMapWindow
1518  sourceMapWin.UpdateMap(render=srcrender, renderVector=srcrenderVector)
1519  if self.show_target:
1520  targetMapWin = self.TgtMapWindow
1521  targetMapWin.UpdateMap(render=tgtrender, renderVector=tgtrenderVector)
1522 
1523  def OnQuit(self, event):
1524  """!Quit georectifier"""
1525  ret = wx.MessageBox(parent=self,
1526  caption=_("Quit GCP Manager"),
1527  message=_('Save ground control points?'),
1528  style=wx.ICON_QUESTION | wx.YES_NO | wx.CANCEL | wx.CENTRE)
1529 
1530  if ret != wx.CANCEL:
1531  if ret == wx.YES:
1532  self.SaveGCPs(None)
1533  elif ret == wx.NO:
1534  # restore POINTS file from backup
1535  if os.path.exists(self.file['points_bak']):
1536  shutil.copy(self.file['points_bak'], self.file['points'])
1537 
1538  if os.path.exists(self.file['points_bak']):
1539  os.unlink(self.file['points_bak'])
1540 
1541  self.SrcMap.Clean()
1542  self.TgtMap.Clean()
1543 
1544  self.grwiz.Cleanup()
1545 
1546  self.Destroy()
1547 
1548  #event.Skip()
1549 
1550  def OnGROrder(self, event):
1551  """
1552  sets transformation order for georectifying
1553  """
1554  if event:
1555  self.gr_order = event.GetInt() + 1
1556 
1557  numOfItems = self.list.GetItemCount()
1558  minNumOfItems = numOfItems
1559 
1560  if self.gr_order == 1:
1561  minNumOfItems = 3
1562  # self.SetStatusText(_('Insufficient points, 3+ points needed for 1st order'))
1563 
1564  elif self.gr_order == 2:
1565  minNumOfItems = 6
1566  diff = 6 - numOfItems
1567  # self.SetStatusText(_('Insufficient points, 6+ points needed for 2nd order'))
1568 
1569  elif self.gr_order == 3:
1570  minNumOfItems = 10
1571  # self.SetStatusText(_('Insufficient points, 10+ points needed for 3rd order'))
1572 
1573  for i in range(minNumOfItems - numOfItems):
1574  self.AddGCP(None)
1575 
1576  return minNumOfItems
1577 
1578  def RMSError(self, xygroup, order):
1579  """
1580  Uses g.transform to calculate forward and backward error for each used GCP
1581  in POINTS file and insert error values into GCP list.
1582  Calculates total forward and backward RMS error for all used points
1583  """
1584  # save GCPs to points file to make sure that all checked GCPs are used
1585  self.SaveGCPs(None)
1586  #self.SetStatusText('')
1587 
1588  if self.CheckGCPcount(msg=True) == False:
1589  return
1590 
1591  # get list of forward and reverse rms error values for each point
1592  self.grwiz.SwitchEnv('source')
1593 
1594  ret = gcmd.RunCommand('g.transform',
1595  parent = self,
1596  read = True,
1597  group = xygroup,
1598  order = order)
1599 
1600  self.grwiz.SwitchEnv('target')
1601 
1602  if ret:
1603  errlist = ret.splitlines()
1604  else:
1605  gcmd.GError(parent = self,
1606  message=_('Could not calculate RMS Error.\n'
1607  'Possible error with g.transform.'))
1608  return
1609 
1610  # insert error values into GCP list for checked items
1611  sdfactor = float(UserSettings.Get(group='gcpman', key='rms', subkey='sdfactor'))
1612  GCPcount = 0
1613  sumsq_fwd_err = 0.0
1614  sumsq_bkw_err = 0.0
1615  sum_fwd_err = 0.0
1616  highest_fwd_err = 0.0
1617  self.highest_key = 0
1618  highest_idx = 0
1619 
1620  for index in range(self.list.GetItemCount()):
1621  key = self.list.GetItemData(index)
1622  if self.list.IsChecked(index):
1623  fwd_err, bkw_err = errlist[GCPcount].split()
1624  self.list.SetStringItem(index, 5, fwd_err)
1625  self.list.SetStringItem(index, 6, bkw_err)
1626  self.mapcoordlist[key][5] = float(fwd_err)
1627  self.mapcoordlist[key][6] = float(bkw_err)
1628  self.list.SetItemTextColour(index, wx.BLACK)
1629  if self.highest_only:
1630  if highest_fwd_err < float(fwd_err):
1631  highest_fwd_err = float(fwd_err)
1632  self.highest_key = key
1633  highest_idx = index
1634 
1635  sumsq_fwd_err += float(fwd_err)**2
1636  sumsq_bkw_err += float(bkw_err)**2
1637  sum_fwd_err += float(fwd_err)
1638  GCPcount += 1
1639  else:
1640  self.list.SetStringItem(index, 5, '')
1641  self.list.SetStringItem(index, 6, '')
1642  self.mapcoordlist[key][5] = 0.0
1643  self.mapcoordlist[key][6] = 0.0
1644  self.list.SetItemTextColour(index, wx.BLACK)
1645 
1646  # SD
1647  if GCPcount > 0:
1648  sum_fwd_err /= GCPcount
1649  self.rmsmean = sum_fwd_err /GCPcount
1650  self.rmssd = (((sumsq_fwd_err/GCPcount) - self.rmsmean**2)**0.5)
1651  self.rmsthresh = self.rmsmean + sdfactor * self.rmssd
1652  else:
1653  self.rmsthresh = 0
1654  self.rmsmean = 0
1655  self.rmssd = 0
1656 
1657  if self.highest_only and highest_fwd_err > 0.0:
1658  self.list.SetItemTextColour(highest_idx, wx.RED)
1659  elif GCPcount > 0 and self.rmsthresh > 0 and not self.highest_only:
1660  for index in range(self.list.GetItemCount()):
1661  if self.list.IsChecked(index):
1662  key = self.list.GetItemData(index)
1663  if (self.mapcoordlist[key][5] > self.rmsthresh):
1664  self.list.SetItemTextColour(index, wx.RED)
1665 
1666  # calculate global RMS error (geometric mean)
1667  self.fwd_rmserror = round((sumsq_fwd_err/GCPcount)**0.5,4)
1668  self.bkw_rmserror = round((sumsq_bkw_err/GCPcount)**0.5,4)
1669  self.list.ResizeColumns()
1670 
1671  def GetNewExtent(self, region, map = None):
1672 
1673  coord_file = utils.GetTempfile()
1674  newreg = { 'n' : 0.0, 's' : 0.0, 'e' : 0.0, 'w' : 0.0,}
1675 
1676  try:
1677  f = open(coord_file, mode='w')
1678  # NW corner
1679  f.write(str(region['e']) + " " + str(region['n']) + "\n")
1680  # NE corner
1681  f.write(str(region['e']) + " " + str(region['s']) + "\n")
1682  # SW corner
1683  f.write(str(region['w']) + " " + str(region['n']) + "\n")
1684  # SE corner
1685  f.write(str(region['w']) + " " + str(region['s']) + "\n")
1686  finally:
1687  f.close()
1688 
1689  # save GCPs to points file to make sure that all checked GCPs are used
1690  self.SaveGCPs(None)
1691 
1692  order = self.gr_order
1693  self.gr_order = 1
1694 
1695  if self.CheckGCPcount(msg=True) == False:
1696  self.gr_order = order
1697  return
1698 
1699  self.gr_order = order
1700 
1701  # get list of forward and reverse rms error values for each point
1702  self.grwiz.SwitchEnv('source')
1703 
1704  if map == 'source':
1705  ret = gcmd.RunCommand('g.transform',
1706  parent = self,
1707  read = True,
1708  group = self.xygroup,
1709  order = 1,
1710  format = 'dst',
1711  coords = coord_file)
1712 
1713  elif map == 'target':
1714  ret = gcmd.RunCommand('g.transform',
1715  parent = self,
1716  read = True,
1717  group = self.xygroup,
1718  order = 1,
1719  flags = 'r',
1720  format = 'src',
1721  coords = coord_file)
1722 
1723  os.unlink(coord_file)
1724 
1725  self.grwiz.SwitchEnv('target')
1726 
1727  if ret:
1728  errlist = ret.splitlines()
1729  else:
1730  gcmd.GError(parent = self,
1731  message=_('Could not calculate new extends.\n'
1732  'Possible error with g.transform.'))
1733  return
1734 
1735  # fist corner
1736  e, n = errlist[0].split()
1737  fe = float(e)
1738  fn = float(n)
1739  newreg['n'] = fn
1740  newreg['s'] = fn
1741  newreg['e'] = fe
1742  newreg['w'] = fe
1743  # other three corners
1744  for i in range(1, 4):
1745  e, n = errlist[i].split()
1746  fe = float(e)
1747  fn = float(n)
1748  if fe < newreg['w']:
1749  newreg['w'] = fe
1750  if fe > newreg['e']:
1751  newreg['e'] = fe
1752  if fn < newreg['s']:
1753  newreg['s'] = fn
1754  if fn > newreg['n']:
1755  newreg['n'] = fn
1756 
1757  return newreg
1758 
1759  def OnHelp(self, event):
1760  """!Show GCP Manager manual page"""
1761  cmdlist = ['g.manual', 'entry=wxGUI.GCP_Manager']
1762  self.parent.goutput.RunCmd(cmdlist, compReg=False,
1763  switchPage=False)
1764 
1765  def OnUpdateActive(self, event):
1766 
1767  if self.activemap.GetSelection() == 0:
1768  self.MapWindow = self.SrcMapWindow
1769  self.Map = self.SrcMap
1770  else:
1771  self.MapWindow = self.TgtMapWindow
1772  self.Map = self.TgtMap
1773 
1774  self.UpdateActive(self.MapWindow)
1775  # for wingrass
1776  if os.name == 'nt':
1777  self.MapWindow.SetFocus()
1778 
1779  def UpdateActive(self, win):
1780 
1781  # optionally disable tool zoomback tool
1782  self.toolbars['gcpdisp'].Enable('zoomback', enable = (len(self.MapWindow.zoomhistory) > 1))
1783 
1784  if self.activemap.GetSelection() != (win == self.TgtMapWindow):
1785  self.activemap.SetSelection(win == self.TgtMapWindow)
1786  self.StatusbarUpdate()
1787 
1788  def AdjustMap(self, newreg):
1789  """!Adjust map window to new extents
1790  """
1791 
1792  # adjust map window
1793  self.Map.region['n'] = newreg['n']
1794  self.Map.region['s'] = newreg['s']
1795  self.Map.region['e'] = newreg['e']
1796  self.Map.region['w'] = newreg['w']
1797 
1798  self.MapWindow.ZoomHistory(self.Map.region['n'], self.Map.region['s'],
1799  self.Map.region['e'], self.Map.region['w'])
1800 
1801  # LL locations
1802  if self.Map.projinfo['proj'] == 'll':
1803  if newreg['n'] > 90.0:
1804  newreg['n'] = 90.0
1805  if newreg['s'] < -90.0:
1806  newreg['s'] = -90.0
1807 
1808  ce = newreg['w'] + (newreg['e'] - newreg['w']) / 2
1809  cn = newreg['s'] + (newreg['n'] - newreg['s']) / 2
1810 
1811  # calculate new center point and display resolution
1812  self.Map.region['center_easting'] = ce
1813  self.Map.region['center_northing'] = cn
1814  self.Map.region["ewres"] = (newreg['e'] - newreg['w']) / self.Map.width
1815  self.Map.region["nsres"] = (newreg['n'] - newreg['s']) / self.Map.height
1816  self.Map.AlignExtentFromDisplay()
1817 
1818  self.MapWindow.ZoomHistory(self.Map.region['n'], self.Map.region['s'],
1819  self.Map.region['e'], self.Map.region['w'])
1820 
1821  if self.MapWindow.redrawAll is False:
1822  self.MapWindow.redrawAll = True
1823 
1824  self.MapWindow.UpdateMap()
1825  self.StatusbarUpdate()
1826 
1827  def OnZoomToSource(self, event):
1828  """!Set target map window to match extents of source map window
1829  """
1830 
1831  if not self.MapWindow == self.TgtMapWindow:
1832  self.MapWindow = self.TgtMapWindow
1833  self.Map = self.TgtMap
1834  self.UpdateActive(self.TgtMapWindow)
1835 
1836  # get new N, S, E, W for target
1837  newreg = self.GetNewExtent(self.SrcMap.region, 'source')
1838  if newreg:
1839  self.AdjustMap(newreg)
1840 
1841  def OnZoomToTarget(self, event):
1842  """!Set source map window to match extents of target map window
1843  """
1844 
1845  if not self.MapWindow == self.SrcMapWindow:
1846  self.MapWindow = self.SrcMapWindow
1847  self.Map = self.SrcMap
1848  self.UpdateActive(self.SrcMapWindow)
1849 
1850  # get new N, S, E, W for target
1851  newreg = self.GetNewExtent(self.TgtMap.region, 'target')
1852  if newreg:
1853  self.AdjustMap(newreg)
1854 
1855  def OnZoomMenuGCP(self, event):
1856  """!Popup Zoom menu
1857  """
1858  point = wx.GetMousePosition()
1859  zoommenu = wx.Menu()
1860  # Add items to the menu
1861 
1862  zoomsource = wx.MenuItem(zoommenu, wx.ID_ANY, _('Adjust source display to target display'))
1863  zoommenu.AppendItem(zoomsource)
1864  self.Bind(wx.EVT_MENU, self.OnZoomToTarget, zoomsource)
1865 
1866  zoomtarget = wx.MenuItem(zoommenu, wx.ID_ANY, _('Adjust target display to source display'))
1867  zoommenu.AppendItem(zoomtarget)
1868  self.Bind(wx.EVT_MENU, self.OnZoomToSource, zoomtarget)
1869 
1870  # Popup the menu. If an item is selected then its handler
1871  # will be called before PopupMenu returns.
1872  self.PopupMenu(zoommenu)
1873  zoommenu.Destroy()
1874 
1875  def OnDispResize(self, event):
1876  """!GCP Map Display resized, adjust Map Windows
1877  """
1878  if self.toolbars['gcpdisp']:
1879  srcwidth, srcheight = self.SrcMapWindow.GetSize()
1880  tgtwidth, tgtheight = self.TgtMapWindow.GetSize()
1881  srcwidth = (srcwidth + tgtwidth) / 2
1882  self._mgr.GetPane("target").Hide()
1883  self._mgr.Update()
1884  self._mgr.GetPane("source").BestSize((srcwidth, srcheight))
1885  self._mgr.GetPane("target").BestSize((srcwidth, tgtheight))
1886  if self.show_target:
1887  self._mgr.GetPane("target").Show()
1888  self._mgr.Update()
1889  pass
1890 
1891 class GCPList(wx.ListCtrl,
1892  CheckListCtrlMixin,
1893  ListCtrlAutoWidthMixin):
1894 
1895  def __init__(self, parent, gcp, id=wx.ID_ANY,
1896  pos=wx.DefaultPosition, size=wx.DefaultSize,
1897  style=wx.LC_REPORT | wx.SUNKEN_BORDER | wx.LC_HRULES |
1898  wx.LC_SINGLE_SEL):
1899 
1900  wx.ListCtrl.__init__(self, parent, id, pos, size, style)
1901 
1902  self.gcp = gcp # GCP class
1903  self.render = True
1904 
1905  # Mixin settings
1906  CheckListCtrlMixin.__init__(self)
1907  ListCtrlAutoWidthMixin.__init__(self)
1908  # TextEditMixin.__init__(self)
1909 
1910  # tracks whether list items are checked or not
1911  self.CheckList = []
1912 
1913  self._Create()
1914 
1915  self.Bind(wx.EVT_LIST_ITEM_SELECTED, self.OnItemSelected)
1916  self.Bind(wx.EVT_LIST_ITEM_ACTIVATED, self.OnItemActivated)
1917  self.Bind(wx.EVT_LIST_COL_CLICK, self.OnColClick)
1918 
1919  self.selected = wx.NOT_FOUND
1920  self.selectedkey = -1
1921 
1922  def _Create(self):
1923 
1924  if 0:
1925  # normal, simple columns
1926  idx_col = 0
1927  for col in (_('use'),
1928  _('source E'),
1929  _('source N'),
1930  _('target E'),
1931  _('target N'),
1932  _('Forward error'),
1933  _('Backward error')):
1934  self.InsertColumn(idx_col, col)
1935  idx_col += 1
1936  else:
1937  # the hard way: we want images on the column header
1938  info = wx.ListItem()
1939  info.SetMask(wx.LIST_MASK_TEXT | wx.LIST_MASK_IMAGE | wx.LIST_MASK_FORMAT)
1940  info.SetImage(-1)
1941  info.m_format = wx.LIST_FORMAT_LEFT
1942 
1943  idx_col = 0
1944  for lbl in (_('use'),
1945  _('source E'),
1946  _('source N'),
1947  _('target E'),
1948  _('target N'),
1949  _('Forward error'),
1950  _('Backward error')):
1951  info.SetText(lbl)
1952  self.InsertColumnInfo(idx_col, info)
1953  idx_col += 1
1954 
1955  def LoadData(self):
1956  """!Load data into list"""
1957  self.DeleteAllItems()
1958 
1959  self.render = False
1960  if os.path.isfile(self.gcp.file['points']):
1961  self.gcp.ReadGCPs()
1962  else:
1963  # 3 gcp is minimum
1964  for i in range(3):
1965  self.gcp.AddGCP(None)
1966 
1967  # select first point by default
1968  self.selected = 0
1969  self.selectedkey = self.GetItemData(self.selected)
1970  self.SetItemState(self.selected,
1971  wx.LIST_STATE_SELECTED,
1972  wx.LIST_STATE_SELECTED)
1973 
1974  self.ResizeColumns()
1975  self.render = True
1976 
1977  def OnCheckItem(self, index, flag):
1978  """!Item is checked/unchecked"""
1979 
1980  if self.render:
1981  # redraw points
1982  sourceMapWin = self.gcp.SrcMapWindow
1983  sourceMapWin.UpdateMap(render=False, renderVector=False)
1984  if self.gcp.show_target:
1985  targetMapWin = self.gcp.TgtMapWindow
1986  targetMapWin.UpdateMap(render=False, renderVector=False)
1987 
1988  pass
1989 
1990  def AddGCPItem(self):
1991  """
1992  Appends an item to GCP list
1993  """
1994  self.selectedkey = self.GetItemCount() + 1
1995 
1996  self.Append([str(self.selectedkey), # GCP number
1997  '0.0', # source E
1998  '0.0', # source N
1999  '0.0', # target E
2000  '0.0', # target N
2001  '', # forward error
2002  '']) # backward error
2003 
2004  self.selected = self.GetItemCount() - 1
2005  self.SetItemData(self.selected, self.selectedkey)
2006 
2007  self.SetItemState(self.selected,
2008  wx.LIST_STATE_SELECTED,
2009  wx.LIST_STATE_SELECTED)
2010 
2011  self.ResizeColumns()
2012 
2013  return self.selected
2014 
2015  def DeleteGCPItem(self):
2016  """
2017  Deletes selected item in GCP list
2018  """
2019  if self.selected == wx.NOT_FOUND:
2020  return
2021 
2022  key = self.GetItemData(self.selected)
2023  self.DeleteItem(self.selected)
2024 
2025  return key
2026 
2027  def ResizeColumns(self):
2028  """!Resize columns"""
2029  minWidth = [90, 120]
2030  for i in range(self.GetColumnCount()):
2031  self.SetColumnWidth(i, wx.LIST_AUTOSIZE)
2032  # first column is checkbox, don't set to minWidth
2033  if i > 0 and self.GetColumnWidth(i) < minWidth[i > 4]:
2034  self.SetColumnWidth(i, minWidth[i > 4])
2035 
2036  self.SendSizeEvent()
2037 
2038  def GetSelected(self):
2039  """!Get index of selected item"""
2040  return self.selected
2041 
2042  def OnItemSelected(self, event):
2043  """
2044  Item selected
2045  """
2046 
2047  if self.render and self.selected != event.GetIndex():
2048  self.selected = event.GetIndex()
2049  self.selectedkey = self.GetItemData(self.selected)
2050  sourceMapWin = self.gcp.SrcMapWindow
2051  sourceMapWin.UpdateMap(render=False, renderVector=False)
2052  if self.gcp.show_target:
2053  targetMapWin = self.gcp.TgtMapWindow
2054  targetMapWin.UpdateMap(render=False, renderVector=False)
2055 
2056  event.Skip()
2057 
2058  def OnItemActivated(self, event):
2059  """
2060  When item double clicked, open editor to update coordinate values
2061  """
2062  coords = []
2063  index = event.GetIndex()
2064  key = self.GetItemData(index)
2065  changed = False
2066 
2067  for i in range(1, 5):
2068  coords.append(self.GetItem(index, i).GetText())
2069 
2070  dlg = EditGCP(parent=self, id=wx.ID_ANY, data=coords, gcpno=key)
2071 
2072  if dlg.ShowModal() == wx.ID_OK:
2073  values = dlg.GetValues() # string
2074 
2075  if len(values) == 0:
2076  gcmd.GError(parent = self,
2077  message=_("Invalid coordinate value. Operation cancelled."))
2078  else:
2079  for i in range(len(values)):
2080  if values[i] != coords[i]:
2081  self.SetStringItem(index, i + 1, values[i])
2082  changed = True
2083 
2084  if changed:
2085  # reset RMS and update mapcoordlist
2086  self.SetStringItem(index, 5, '')
2087  self.SetStringItem(index, 6, '')
2088  key = self.GetItemData(index)
2089  self.gcp.mapcoordlist[key] = [key,
2090  float(values[0]),
2091  float(values[1]),
2092  float(values[2]),
2093  float(values[3]),
2094  0.0,
2095  0.0]
2096  self.gcp.UpdateColours()
2097 
2098  def OnColClick(self, event):
2099  """!ListCtrl forgets selected item..."""
2100  self.selected = self.FindItemData(-1, self.selectedkey)
2101  self.SetItemState(self.selected,
2102  wx.LIST_STATE_SELECTED,
2103  wx.LIST_STATE_SELECTED)
2104  event.Skip()
2105 
2106 class VectGroup(wx.Dialog):
2107  """
2108  Dialog to create a vector group (VREF file) for georectifying
2109 
2110  @todo Replace by g.group
2111  """
2112  def __init__(self, parent, id, grassdb, location, mapset, group,
2113  style=wx.DEFAULT_DIALOG_STYLE):
2114 
2115  wx.Dialog.__init__(self, parent, id, style=style,
2116  title = _("Create vector map group"))
2117 
2118  self.grassdatabase = grassdb
2119  self.xylocation = location
2120  self.xymapset = mapset
2121  self.xygroup = group
2122 
2123  #
2124  # get list of valid vector directories
2125  #
2126  vectlist = os.listdir(os.path.join(self.grassdatabase,
2127  self.xylocation,
2128  self.xymapset,
2129  'vector'))
2130  for dir in vectlist:
2131  if not os.path.isfile(os.path.join(self.grassdatabase,
2132  self.xylocation,
2133  self.xymapset,
2134  'vector',
2135  dir,
2136  'coor')):
2137  vectlist.remove(dir)
2138 
2139  utils.ListSortLower(vectlist)
2140 
2141  # path to vref file
2142  self.vgrpfile = os.path.join(self.grassdatabase,
2143  self.xylocation,
2144  self.xymapset,
2145  'group',
2146  self.xygroup,
2147  'VREF')
2148 
2149  #
2150  # buttons
2151  #
2152  self.btnCancel = wx.Button(parent = self,
2153  id = wx.ID_CANCEL)
2154  self.btnOK = wx.Button(parent = self,
2155  id = wx.ID_OK)
2156  self.btnOK.SetDefault()
2157 
2158 
2159  #
2160  # list of vector maps
2161  #
2162  self.listMap = wx.CheckListBox(parent = self, id = wx.ID_ANY,
2163  choices = vectlist)
2164 
2165  if os.path.isfile(self.vgrpfile):
2166  f = open(self.vgrpfile)
2167  try:
2168  checked = []
2169  for line in f.readlines():
2170  line = line.replace('\n', '')
2171  if len(line) < 1:
2172  continue
2173  checked.append(line)
2174  self.listMap.SetCheckedStrings(checked)
2175  finally:
2176  f.close()
2177 
2178  line = wx.StaticLine(parent = self,
2179  id = wx.ID_ANY, size = (20, -1),
2180  style = wx.LI_HORIZONTAL)
2181 
2182  #
2183  # layout
2184  #
2185  sizer = wx.BoxSizer(wx.VERTICAL)
2186 
2187  box = wx.BoxSizer(wx.HORIZONTAL)
2188  box.Add(item = wx.StaticText(parent = self, id = wx.ID_ANY,
2189  label = _('Select vector map(s) to add to group:')),
2190  flag = wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT | wx.LEFT,
2191  border = 5)
2192 
2193  box.Add(item = self.listMap,
2194  flag = wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT | wx.LEFT,
2195  border = 5)
2196 
2197 
2198  sizer.Add(box, flag = wx.ALIGN_RIGHT | wx.ALL,
2199  border = 3)
2200 
2201  sizer.Add(item = line, proportion = 0,
2202  flag = wx.GROW | wx.ALIGN_CENTER_VERTICAL | wx.LEFT | wx.RIGHT,
2203  border = 5)
2204 
2205  # buttons
2206  btnSizer = wx.StdDialogButtonSizer()
2207  btnSizer.AddButton(self.btnCancel)
2208  btnSizer.AddButton(self.btnOK)
2209  btnSizer.Realize()
2210 
2211  sizer.Add(item = btnSizer, proportion = 0,
2212  flag = wx.EXPAND | wx.ALL | wx.ALIGN_CENTER,
2213  border = 5)
2214 
2215  self.SetSizer(sizer)
2216  sizer.Fit(self)
2217  self.Layout()
2218 
2219  def MakeVGroup(self):
2220  """!Create VREF file"""
2221  vgrouplist = []
2222  for item in range(self.listMap.GetCount()):
2223  if not self.listMap.IsChecked(item):
2224  continue
2225  vgrouplist.append(self.listMap.GetString(item))
2226 
2227  f = open(self.vgrpfile, mode='w')
2228  try:
2229  for vect in vgrouplist:
2230  f.write(vect + '\n')
2231  finally:
2232  f.close()
2233 
2234 class EditGCP(wx.Dialog):
2235  def __init__(self, parent, data, gcpno, id=wx.ID_ANY,
2236  title=_("Edit GCP"),
2237  style=wx.DEFAULT_DIALOG_STYLE):
2238  """!Dialog for editing GPC and map coordinates in list control"""
2239 
2240  wx.Dialog.__init__(self, parent, id, title=title, style=style)
2241 
2242  panel = wx.Panel(parent=self)
2243 
2244  sizer = wx.BoxSizer(wx.VERTICAL)
2245 
2246  box = wx.StaticBox (parent=panel, id=wx.ID_ANY,
2247  label=" %s %s " % (_("Ground Control Point No."), str(gcpno)))
2248  boxSizer = wx.StaticBoxSizer(box, wx.VERTICAL)
2249 
2250  # source coordinates
2251  gridSizer = wx.GridBagSizer(vgap=5, hgap=5)
2252 
2253  self.xcoord = wx.TextCtrl(parent=panel, id=wx.ID_ANY, size=(150, -1))
2254  self.ycoord = wx.TextCtrl(parent=panel, id=wx.ID_ANY, size=(150, -1))
2255  self.ecoord = wx.TextCtrl(parent=panel, id=wx.ID_ANY, size=(150, -1))
2256  self.ncoord = wx.TextCtrl(parent=panel, id=wx.ID_ANY, size=(150, -1))
2257 
2258  # swap source N, target E
2259  tmp_coord = data[1]
2260  data[1] = data[2]
2261  data[2] = tmp_coord
2262 
2263  row = 0
2264  col = 0
2265  idx = 0
2266  for label, win in ((_("source E:"), self.xcoord),
2267  (_("target E:"), self.ecoord),
2268  (_("source N:"), self.ycoord),
2269  (_("target N:"), self.ncoord)):
2270  label = wx.StaticText(parent=panel, id=wx.ID_ANY,
2271  label=label)
2272  gridSizer.Add(item=label,
2273  flag=wx.ALIGN_CENTER_VERTICAL,
2274  pos=(row, col))
2275 
2276  col += 1
2277  win.SetValue(str(data[idx]))
2278 
2279  gridSizer.Add(item=win,
2280  pos=(row, col))
2281 
2282  col += 1
2283  idx += 1
2284 
2285  if col > 3:
2286  row += 1
2287  col = 0
2288 
2289  boxSizer.Add(item=gridSizer, proportion=1,
2290  flag=wx.EXPAND | wx.ALL, border=5)
2291 
2292  sizer.Add(item=boxSizer, proportion=1,
2293  flag=wx.EXPAND | wx.ALL, border=5)
2294 
2295  #
2296  # buttons
2297  #
2298  self.btnCancel = wx.Button(panel, wx.ID_CANCEL)
2299  self.btnOk = wx.Button(panel, wx.ID_OK)
2300  self.btnOk.SetDefault()
2301 
2302  btnSizer = wx.StdDialogButtonSizer()
2303  btnSizer.AddButton(self.btnCancel)
2304  btnSizer.AddButton(self.btnOk)
2305  btnSizer.Realize()
2306 
2307  sizer.Add(item=btnSizer, proportion=0,
2308  flag=wx.ALIGN_RIGHT | wx.ALL, border=5)
2309 
2310  panel.SetSizer(sizer)
2311  sizer.Fit(self)
2312 
2313  def GetValues(self, columns=None):
2314  """!Return list of values (as strings).
2315  """
2316  valuelist = []
2317  try:
2318  float(self.xcoord.GetValue())
2319  float(self.ycoord.GetValue())
2320  float(self.ecoord.GetValue())
2321  float(self.ncoord.GetValue())
2322  except ValueError:
2323  return valuelist
2324 
2325  valuelist.append(self.xcoord.GetValue())
2326  valuelist.append(self.ycoord.GetValue())
2327  valuelist.append(self.ecoord.GetValue())
2328  valuelist.append(self.ncoord.GetValue())
2329 
2330  return valuelist
2331 
2332 class GrSettingsDialog(wx.Dialog):
2333  def __init__(self, parent, id, title, pos=wx.DefaultPosition, size=wx.DefaultSize,
2334  style=wx.DEFAULT_DIALOG_STYLE):
2335  wx.Dialog.__init__(self, parent, id, title, pos, size, style)
2336  """
2337  Dialog to set profile text options: font, title
2338  and font size, axis labels and font size
2339  """
2340  #
2341  # initialize variables
2342  #
2343  self.parent = parent
2344  self.new_src_map = src_map
2345  self.new_tgt_map = tgt_map
2346  self.sdfactor = 0
2347 
2348  self.symbol = {}
2349 
2350  self.methods = ["nearest",
2351  "bilinear",
2352  "bilinear_f",
2353  "cubic",
2354  "cubic_f"]
2355 
2356  # notebook
2357  notebook = wx.Notebook(parent=self, id=wx.ID_ANY, style=wx.BK_DEFAULT)
2358  self.__CreateSymbologyPage(notebook)
2359  self.__CreateRectificationPage(notebook)
2360 
2361  # buttons
2362  btnSave = wx.Button(self, wx.ID_SAVE)
2363  btnApply = wx.Button(self, wx.ID_APPLY)
2364  btnClose = wx.Button(self, wx.ID_CLOSE)
2365  btnApply.SetDefault()
2366 
2367  # bindings
2368  btnApply.Bind(wx.EVT_BUTTON, self.OnApply)
2369  btnApply.SetToolTipString(_("Apply changes for the current session"))
2370  btnSave.Bind(wx.EVT_BUTTON, self.OnSave)
2371  btnSave.SetToolTipString(_("Apply and save changes to user settings file (default for next sessions)"))
2372  btnClose.Bind(wx.EVT_BUTTON, self.OnClose)
2373  btnClose.SetToolTipString(_("Close dialog"))
2374 
2375  # sizers
2376  btnSizer = wx.BoxSizer(wx.HORIZONTAL)
2377  btnSizer.Add(btnApply, flag=wx.LEFT | wx.RIGHT, border=5)
2378  btnSizer.Add(btnSave, flag=wx.LEFT | wx.RIGHT, border=5)
2379  btnSizer.Add(btnClose, flag=wx.LEFT | wx.RIGHT, border=5)
2380 
2381  # sizers
2382  mainSizer = wx.BoxSizer(wx.VERTICAL)
2383  mainSizer.Add(item=notebook, proportion=1, flag=wx.EXPAND | wx.ALL, border=5)
2384  mainSizer.Add(item=btnSizer, proportion=0,
2385  flag=wx.ALIGN_RIGHT | wx.ALL, border=5)
2386  # flag=wx.EXPAND | wx.ALL | wx.ALIGN_CENTER, border=5)
2387 
2388  self.SetSizer(mainSizer)
2389  mainSizer.Fit(self)
2390 
2391  def __CreateSymbologyPage(self, notebook):
2392  """!Create notebook page with symbology settings"""
2393 
2394  panel = wx.Panel(parent=notebook, id=wx.ID_ANY)
2395  notebook.AddPage(page=panel, text=_("Symbology"))
2396 
2397  sizer = wx.BoxSizer(wx.VERTICAL)
2398 
2399  rmsgridSizer = wx.GridBagSizer(vgap=5, hgap=5)
2400  rmsgridSizer.AddGrowableCol(1)
2401 
2402  # highlight only highest forward RMS error
2403  self.highlighthighest = wx.CheckBox(parent=panel, id=wx.ID_ANY,
2404  label=_("Highlight highest RMS error only"))
2405  hh = UserSettings.Get(group='gcpman', key='rms', subkey='highestonly')
2406  self.highlighthighest.SetValue(hh)
2407  rmsgridSizer.Add(item=self.highlighthighest, flag=wx.ALIGN_CENTER_VERTICAL, pos=(0, 0))
2408 
2409  # RMS forward error threshold
2410  rmslabel = wx.StaticText(parent=panel, id=wx.ID_ANY, label=_("Highlight RMS error > M + SD * factor:"))
2411  rmslabel.SetToolTip(wx.ToolTip(_("Highlight GCPs with an RMS error larger than \n"
2412  "mean + standard deviation * given factor. \n"
2413  "Recommended values for this factor are between 1 and 2.")))
2414  rmsgridSizer.Add(item=rmslabel, flag=wx.ALIGN_CENTER_VERTICAL, pos=(1, 0))
2415  sdfactor = UserSettings.Get(group='gcpman', key='rms', subkey='sdfactor')
2416  self.rmsWin = wx.TextCtrl(parent=panel, id=wx.ID_ANY,
2417  size=(70,-1), style=wx.TE_NOHIDESEL)
2418  self.rmsWin.SetValue("%s" % str(sdfactor))
2419  if (self.parent.highest_only == True):
2420  self.rmsWin.Disable()
2421 
2422  self.symbol['sdfactor'] = self.rmsWin.GetId()
2423  rmsgridSizer.Add(item=self.rmsWin, flag=wx.ALIGN_RIGHT, pos=(1, 1))
2424  sizer.Add(item=rmsgridSizer, flag=wx.EXPAND | wx.ALL, border=5)
2425 
2426  box = wx.StaticBox(parent=panel, id=wx.ID_ANY,
2427  label=" %s " % _("Symbol settings"))
2428  boxSizer = wx.StaticBoxSizer(box, wx.VERTICAL)
2429  gridSizer = wx.GridBagSizer(vgap=5, hgap=5)
2430  gridSizer.AddGrowableCol(1)
2431 
2432  #
2433  # general symbol color
2434  #
2435  row = 0
2436  label = wx.StaticText(parent=panel, id=wx.ID_ANY, label=_("Color:"))
2437  gridSizer.Add(item=label, flag=wx.ALIGN_CENTER_VERTICAL, pos=(row, 0))
2438  col = UserSettings.Get(group='gcpman', key='symbol', subkey='color')
2439  colWin = csel.ColourSelect(parent=panel, id=wx.ID_ANY,
2440  colour=wx.Colour(col[0],
2441  col[1],
2442  col[2],
2443  255))
2444  self.symbol['color'] = colWin.GetId()
2445  gridSizer.Add(item=colWin,
2446  flag=wx.ALIGN_RIGHT,
2447  pos=(row, 1))
2448 
2449  #
2450  # symbol color for high forward RMS error
2451  #
2452  row += 1
2453  label = wx.StaticText(parent=panel, id=wx.ID_ANY, label=_("Color for high RMS error:"))
2454  gridSizer.Add(item=label, flag=wx.ALIGN_CENTER_VERTICAL, pos=(row, 0))
2455  hcol = UserSettings.Get(group='gcpman', key='symbol', subkey='hcolor')
2456  hcolWin = csel.ColourSelect(parent=panel, id=wx.ID_ANY,
2457  colour=wx.Colour(hcol[0],
2458  hcol[1],
2459  hcol[2],
2460  255))
2461  self.symbol['hcolor'] = hcolWin.GetId()
2462  gridSizer.Add(item=hcolWin,
2463  flag=wx.ALIGN_RIGHT,
2464  pos=(row, 1))
2465 
2466  #
2467  # symbol color for selected GCP
2468  #
2469  row += 1
2470  label = wx.StaticText(parent=panel, id=wx.ID_ANY, label=_("Color for selected GCP:"))
2471  gridSizer.Add(item=label, flag=wx.ALIGN_CENTER_VERTICAL, pos=(row, 0))
2472  scol = UserSettings.Get(group='gcpman', key='symbol', subkey='scolor')
2473  scolWin = csel.ColourSelect(parent=panel, id=wx.ID_ANY,
2474  colour=wx.Colour(scol[0],
2475  scol[1],
2476  scol[2],
2477  255))
2478  self.symbol['scolor'] = scolWin.GetId()
2479  gridSizer.Add(item=scolWin,
2480  flag=wx.ALIGN_RIGHT,
2481  pos=(row, 1))
2482 
2483  #
2484  # symbol color for unused GCP
2485  #
2486  row += 1
2487  label = wx.StaticText(parent=panel, id=wx.ID_ANY, label=_("Color for unused GCPs:"))
2488  gridSizer.Add(item=label, flag=wx.ALIGN_CENTER_VERTICAL, pos=(row, 0))
2489  ucol = UserSettings.Get(group='gcpman', key='symbol', subkey='ucolor')
2490  ucolWin = csel.ColourSelect(parent=panel, id=wx.ID_ANY,
2491  colour=wx.Colour(ucol[0],
2492  ucol[1],
2493  ucol[2],
2494  255))
2495  self.symbol['ucolor'] = ucolWin.GetId()
2496  gridSizer.Add(item=ucolWin,
2497  flag=wx.ALIGN_RIGHT,
2498  pos=(row, 1))
2499 
2500  # show unused GCPs
2501  row += 1
2502  self.showunused = wx.CheckBox(parent=panel, id=wx.ID_ANY,
2503  label=_("Show unused GCPs"))
2504  shuu = UserSettings.Get(group='gcpman', key='symbol', subkey='unused')
2505  self.showunused.SetValue(shuu)
2506  gridSizer.Add(item=self.showunused, flag=wx.ALIGN_CENTER_VERTICAL, pos=(row, 0))
2507 
2508  #
2509  # symbol size
2510  #
2511  row += 1
2512  label = wx.StaticText(parent=panel, id=wx.ID_ANY, label=_("Symbol size:"))
2513  gridSizer.Add(item=label, flag=wx.ALIGN_CENTER_VERTICAL, pos=(row, 0))
2514  symsize = int(UserSettings.Get(group='gcpman', key='symbol', subkey='size'))
2515  sizeWin = wx.SpinCtrl(parent=panel, id=wx.ID_ANY,
2516  min=1, max=20)
2517  sizeWin.SetValue(symsize)
2518  self.symbol['size'] = sizeWin.GetId()
2519  gridSizer.Add(item=sizeWin,
2520  flag=wx.ALIGN_RIGHT,
2521  pos=(row, 1))
2522 
2523  #
2524  # symbol width
2525  #
2526  row += 1
2527  label = wx.StaticText(parent=panel, id=wx.ID_ANY, label=_("Line width:"))
2528  gridSizer.Add(item=label, flag=wx.ALIGN_CENTER_VERTICAL, pos=(row, 0))
2529  width = int(UserSettings.Get(group='gcpman', key='symbol', subkey='width'))
2530  widWin = wx.SpinCtrl(parent=panel, id=wx.ID_ANY,
2531  min=1, max=10)
2532  widWin.SetValue(width)
2533  self.symbol['width'] = widWin.GetId()
2534  gridSizer.Add(item=widWin,
2535  flag=wx.ALIGN_RIGHT,
2536  pos=(row, 1))
2537 
2538  boxSizer.Add(item=gridSizer, flag=wx.EXPAND)
2539  sizer.Add(item=boxSizer, flag=wx.EXPAND | wx.ALL, border=5)
2540 
2541  #
2542  # maps to display
2543  #
2544  # source map to display
2545  self.srcselection = gselect.Select(panel, id=wx.ID_ANY,
2546  size=globalvar.DIALOG_GSELECT_SIZE, type='cell', updateOnPopup = False)
2547  self.parent.grwiz.SwitchEnv('source')
2548  self.srcselection.SetElementList(maptype)
2549  # filter out all maps not in group
2550  self.srcselection.tcp.GetElementList(elements = self.parent.src_maps)
2551 
2552  # target map to display
2553  self.tgtselection = gselect.Select(panel, id=wx.ID_ANY,
2554  size=globalvar.DIALOG_GSELECT_SIZE, type='cell', updateOnPopup = False)
2555  self.parent.grwiz.SwitchEnv('target')
2556  self.tgtselection.SetElementList(maptype)
2557  self.tgtselection.GetElementList()
2558 
2559  sizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY, label=_('Select source map to display:')),
2560  proportion=0, flag=wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL | wx.ALL, border=5)
2561  sizer.Add(item=self.srcselection, proportion=0,
2562  flag=wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL | wx.ALL, border=5)
2563  self.srcselection.SetValue(src_map)
2564  sizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY, label=_('Select target map to display:')),
2565  proportion=0, flag=wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL | wx.ALL, border=5)
2566  sizer.Add(item=self.tgtselection, proportion=0,
2567  flag=wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL | wx.ALL, border=5)
2568  self.tgtselection.SetValue(tgt_map)
2569 
2570  # bindings
2571  self.highlighthighest.Bind(wx.EVT_CHECKBOX, self.OnHighlight)
2572  self.rmsWin.Bind(wx.EVT_TEXT, self.OnSDFactor)
2573  self.srcselection.Bind(wx.EVT_TEXT, self.OnSrcSelection)
2574  self.tgtselection.Bind(wx.EVT_TEXT, self.OnTgtSelection)
2575 
2576  panel.SetSizer(sizer)
2577 
2578  return panel
2579 
2580  def __CreateRectificationPage(self, notebook):
2581  """!Create notebook page with symbology settings"""
2582 
2583  panel = wx.Panel(parent=notebook, id=wx.ID_ANY)
2584  notebook.AddPage(page=panel, text=_("Rectification"))
2585 
2586  sizer = wx.BoxSizer(wx.VERTICAL)
2587 
2588  # transformation order
2589  self.rb_grorder = wx.RadioBox(parent=panel, id=wx.ID_ANY,
2590  label=" %s " % _("Select rectification order"),
2591  choices=[_('1st order'), _('2nd order'), _('3rd order')],
2592  majorDimension=wx.RA_SPECIFY_COLS)
2593  sizer.Add(item=self.rb_grorder, proportion=0,
2594  flag=wx.EXPAND | wx.ALL, border=5)
2595  self.rb_grorder.SetSelection(self.parent.gr_order - 1)
2596 
2597  # interpolation method
2598  gridSizer = wx.GridBagSizer(vgap=5, hgap=5)
2599  gridSizer.AddGrowableCol(1)
2600  gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY, label=_('Select interpolation method:')),
2601  pos=(0,0), flag=wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL | wx.ALL, border=5)
2602  self.grmethod = wx.Choice(parent=panel, id=wx.ID_ANY,
2603  choices = self.methods)
2604  gridSizer.Add(item=self.grmethod, pos=(0,1),
2605  flag=wx.ALIGN_RIGHT, border=5)
2606  self.grmethod.SetStringSelection(self.parent.gr_method)
2607  sizer.Add(item=gridSizer, flag=wx.EXPAND | wx.ALL, border=5)
2608 
2609  # clip to region
2610  self.check = wx.CheckBox(parent=panel, id=wx.ID_ANY,
2611  label=_("clip to computational region in target location"))
2612  sizer.Add(item=self.check, proportion=0,
2613  flag=wx.EXPAND | wx.ALL, border=5)
2614  self.check.SetValue(self.parent.clip_to_region)
2615 
2616  # extension
2617  sizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY, label=_('Extension for output maps:')),
2618  proportion=0, flag=wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL | wx.ALL, border=5)
2619  self.ext_txt = wx.TextCtrl(parent=panel, id=wx.ID_ANY, value="", size=(350,-1))
2620  self.ext_txt.SetValue(self.parent.extension)
2621  sizer.Add(item=self.ext_txt,
2622  proportion=0, flag=wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL | wx.ALL, border=5)
2623 
2624  # bindings
2625  self.ext_txt.Bind(wx.EVT_TEXT, self.OnExtension)
2626  self.Bind(wx.EVT_RADIOBOX, self.parent.OnGROrder, self.rb_grorder)
2627  self.Bind(wx.EVT_CHOICE, self.OnMethod, self.grmethod)
2628  self.Bind(wx.EVT_CHECKBOX, self.OnClipRegion, self.check)
2629 
2630  panel.SetSizer(sizer)
2631 
2632  return panel
2633 
2634  def OnHighlight(self, event):
2635  """!Checkbox 'highlighthighest' checked/unchecked"""
2636  if self.highlighthighest.IsChecked():
2637  self.parent.highest_only = True
2638  self.rmsWin.Disable()
2639  else:
2640  self.parent.highest_only = False
2641  self.rmsWin.Enable()
2642 
2643  def OnSDFactor(self,event):
2644  """!New factor for RMS threshold = M + SD * factor"""
2645 
2646  self.sdfactor = float(event.GetString())
2647 
2648  if self.sdfactor <= 0:
2649  gcmd.GError(parent = self,
2650  message=_('RMS threshold factor must be > 0'))
2651  elif self.sdfactor < 1:
2652  gcmd.GError(parent = self,
2653  message=_('RMS threshold factor is < 1\n'
2654  'Too many points might be highlighted'))
2655 
2656  def OnSrcSelection(self,event):
2657  """!Source map to display selected"""
2658  global src_map
2659 
2660  tmp_map = event.GetString()
2661 
2662  if not tmp_map == '' and not tmp_map == src_map:
2663  self.new_src_map = tmp_map
2664 
2665  def OnTgtSelection(self,event):
2666  """!Target map to display selected"""
2667  global tgt_map
2668 
2669  tmp_map = event.GetString()
2670 
2671  if not tmp_map == tgt_map:
2672  self.new_tgt_map = tmp_map
2673 
2674  def OnMethod(self, event):
2675  self.parent.gr_method = self.methods[event.GetSelection()]
2676 
2677  def OnClipRegion(self, event):
2678  self.parent.clip_to_region = event.IsChecked()
2679 
2680  def OnExtension(self, event):
2681  self.parent.extension = event.GetString()
2682 
2683  def UpdateSettings(self):
2684  global src_map
2685  global tgt_map
2686 
2687  layers = None
2688 
2689  UserSettings.Set(group='gcpman', key='rms', subkey='highestonly',
2690  value=self.highlighthighest.GetValue())
2691  if self.sdfactor > 0:
2692  UserSettings.Set(group='gcpman', key='rms', subkey='sdfactor',
2693  value=self.sdfactor)
2694 
2695  self.parent.sdfactor = self.sdfactor
2696  if self.parent.rmsthresh > 0:
2697  self.parent.rmsthresh = self.parent.mean + self.parent.sdfactor * self.parent.rmssd
2698 
2699  UserSettings.Set(group='gcpman', key='symbol', subkey='color',
2700  value=tuple(wx.FindWindowById(self.symbol['color']).GetColour()))
2701  UserSettings.Set(group='gcpman', key='symbol', subkey='hcolor',
2702  value=tuple(wx.FindWindowById(self.symbol['hcolor']).GetColour()))
2703  UserSettings.Set(group='gcpman', key='symbol', subkey='scolor',
2704  value=tuple(wx.FindWindowById(self.symbol['scolor']).GetColour()))
2705  UserSettings.Set(group='gcpman', key='symbol', subkey='ucolor',
2706  value=tuple(wx.FindWindowById(self.symbol['ucolor']).GetColour()))
2707  UserSettings.Set(group='gcpman', key='symbol', subkey='unused',
2708  value=self.showunused.GetValue())
2709  UserSettings.Set(group='gcpman', key='symbol', subkey='size',
2710  value=wx.FindWindowById(self.symbol['size']).GetValue())
2711  UserSettings.Set(group='gcpman', key='symbol', subkey='width',
2712  value=wx.FindWindowById(self.symbol['width']).GetValue())
2713 
2714  srcrender = False
2715  srcrenderVector = False
2716  tgtrender = False
2717  tgtrenderVector = False
2718  if self.new_src_map != src_map:
2719  # remove old layer
2720  layers = self.parent.grwiz.SrcMap.GetListOfLayers()
2721  self.parent.grwiz.SrcMap.DeleteLayer(layers[0])
2722 
2723  src_map = self.new_src_map
2724  cmdlist = ['d.rast', 'map=%s' % src_map]
2725  self.parent.grwiz.SwitchEnv('source')
2726  name, found = utils.GetLayerNameFromCmd(cmdlist),
2727  self.parent.grwiz.SrcMap.AddLayer(type='raster', command=cmdlist, l_active=True,
2728  name=name, l_hidden=False, l_opacity=1.0, l_render=False)
2729 
2730  self.parent.grwiz.SwitchEnv('target')
2731  srcrender = True
2732 
2733  if self.new_tgt_map != tgt_map:
2734  # remove old layer
2735  layers = self.parent.grwiz.TgtMap.GetListOfLayers()
2736  if layers:
2737  self.parent.grwiz.TgtMap.DeleteLayer(layers[0])
2738  tgt_map = self.new_tgt_map
2739 
2740  if tgt_map != '':
2741  cmdlist = ['d.rast', 'map=%s' % tgt_map]
2742  name, found = utils.GetLayerNameFromCmd(cmdlist)
2743  self.parent.grwiz.TgtMap.AddLayer(type='raster', command=cmdlist, l_active=True,
2744  name=name, l_hidden=False, l_opacity=1.0, l_render=False)
2745 
2746  tgtrender = True
2747  if self.parent.show_target == False:
2748  self.parent.show_target = True
2749  self.parent._mgr.GetPane("target").Show()
2750  self.parent._mgr.Update()
2751  self.parent.toolbars['gcpdisp'].Enable('zoommenu', enable = True)
2752  self.parent.activemap.Enable()
2753  self.parent.TgtMapWindow.ZoomToMap(layers = self.parent.TgtMap.GetListOfLayers())
2754  else: # tgt_map == ''
2755  if self.parent.show_target == True:
2756  self.parent.show_target = False
2757  self.parent._mgr.GetPane("target").Hide()
2758  self.parent._mgr.Update()
2759  self.parent.activemap.SetSelection(0)
2760  self.parent.activemap.Enable(False)
2761  self.parent.toolbars['gcpdisp'].Enable('zoommenu', enable = False)
2762 
2763  self.parent.UpdateColours(srcrender, srcrenderVector, tgtrender, tgtrenderVector)
2764 
2765  def OnSave(self, event):
2766  """!Button 'Save' pressed"""
2767  self.UpdateSettings()
2768  fileSettings = {}
2769  UserSettings.ReadSettingsFile(settings=fileSettings)
2770  fileSettings['gcpman'] = UserSettings.Get(group='gcpman')
2771  file = UserSettings.SaveToFile(fileSettings)
2772  self.parent.parent.goutput.WriteLog(_('GCP Manager settings saved to file \'%s\'.') % file)
2773  #self.Close()
2774 
2775  def OnApply(self, event):
2776  """!Button 'Apply' pressed"""
2777  self.UpdateSettings()
2778  #self.Close()
2779 
2780  def OnClose(self, event):
2781  """!Button 'Cancel' pressed"""
2782  self.Close()