ii2t_manager.py 112 KB

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