manager.py 114 KB

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