manager.py 106 KB

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