manager.py 114 KB

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