ii2t_manager.py 112 KB

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