ii2t_manager.py 112 KB

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