ii2t_manager.py 112 KB

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