manager.py 108 KB

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