manager.py 112 KB

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