123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597 |
- """
- @package gcp.manager
- @brief Georectification module for GRASS GIS. Includes ground control
- point management and interactive point and click GCP creation
- Classes:
- - manager::GCPWizard
- - manager::LocationPage
- - manager::GroupPage
- - manager::DispMapPage
- - manager::GCPPanel
- - manager::GCPDisplay
- - manager::GCPList
- - manager::VectGroup
- - manager::EditGCP
- - manager::GrSettingsDialog
- (C) 2006-2014 by the GRASS Development Team
- This program is free software under the GNU General Public License
- (>=v2). Read the file COPYING that comes with GRASS for details.
- @author Original author Michael Barton
- @author Original version improved by Martin Landa <landa.martin gmail.com>
- @author Rewritten by Markus Metz redesign georectfier -> GCP Manage
- @author Support for GraphicsSet added by Stepan Turek <stepan.turek seznam.cz> (2012)
- """
- from __future__ import print_function
- import os
- import sys
- import shutil
- import six
- from copy import copy
- import wx
- from wx.lib.mixins.listctrl import ColumnSorterMixin, ListCtrlAutoWidthMixin
- import wx.lib.colourselect as csel
- from core import globalvar
- if globalvar.wxPythonPhoenix:
- from wx import adv as wiz
- else:
- from wx import wizard as wiz
- import grass.script as grass
- from core import utils
- from core.render import Map
- from gui_core.gselect import Select, LocationSelect, MapsetSelect
- from gui_core.dialogs import GroupDialog
- from gui_core.mapdisp import FrameMixin
- from core.gcmd import RunCommand, GMessage, GError, GWarning
- from core.settings import UserSettings
- from gcp.mapdisplay import MapPanel
- from core.giface import Notification
- from gui_core.wrap import (
- SpinCtrl,
- Button,
- StaticText,
- StaticBox,
- CheckListBox,
- TextCtrl,
- Menu,
- ListCtrl,
- BitmapFromImage,
- CheckListCtrlMixin,
- )
- from location_wizard.wizard import GridBagSizerTitledPage as TitledPage
- #
- # global variables
- #
- global src_map
- global tgt_map
- global maptype
- src_map = ""
- tgt_map = {"raster": "", "vector": ""}
- maptype = "raster"
- def getSmallUpArrowImage():
- stream = open(os.path.join(globalvar.IMGDIR, "small_up_arrow.png"), "rb")
- try:
- img = wx.Image(stream)
- finally:
- stream.close()
- return img
- def getSmallDnArrowImage():
- stream = open(os.path.join(globalvar.IMGDIR, "small_down_arrow.png"), "rb")
- try:
- img = wx.Image(stream)
- finally:
- stream.close()
- stream.close()
- return img
- class GCPWizard(object):
- """
- Start wizard here and finish wizard here
- """
- def __init__(self, parent, giface):
- self.parent = parent # GMFrame
- self._giface = giface
- #
- # get environmental variables
- #
- self.grassdatabase = grass.gisenv()["GISDBASE"]
- #
- # read original environment settings
- #
- self.target_gisrc = os.environ["GISRC"]
- self.gisrc_dict = {}
- try:
- f = open(self.target_gisrc, "r")
- for line in f.readlines():
- line = line.replace("\n", "").strip()
- if len(line) < 1:
- continue
- key, value = line.split(":", 1)
- self.gisrc_dict[key.strip()] = value.strip()
- finally:
- f.close()
- self.currentlocation = self.gisrc_dict["LOCATION_NAME"]
- self.currentmapset = self.gisrc_dict["MAPSET"]
- # location for xy map to georectify
- self.newlocation = ""
- # mapset for xy map to georectify
- self.newmapset = ""
- global maptype
- global src_map
- global tgt_map
- # src_map = ''
- # tgt_map = ''
- maptype = "raster"
- # GISRC file for source location/mapset of map(s) to georectify
- self.source_gisrc = ""
- self.src_maps = []
- #
- # define wizard pages
- #
- self.wizard = wiz.Wizard(
- parent=parent, id=wx.ID_ANY, title=_("Setup for georectification")
- )
- self.startpage = LocationPage(self.wizard, self)
- self.grouppage = GroupPage(self.wizard, self)
- self.mappage = DispMapPage(self.wizard, self)
- #
- # set the initial order of the pages
- #
- self.startpage.SetNext(self.grouppage)
- self.grouppage.SetPrev(self.startpage)
- self.grouppage.SetNext(self.mappage)
- self.mappage.SetPrev(self.grouppage)
- #
- # do pages layout
- #
- self.startpage.DoLayout()
- self.grouppage.DoLayout()
- self.mappage.DoLayout()
- self.wizard.FitToPage(self.startpage)
- # self.Bind(wx.EVT_CLOSE, self.Cleanup)
- # self.parent.Bind(wx.EVT_ACTIVATE, self.OnGLMFocus)
- success = False
- #
- # run wizard
- #
- if self.wizard.RunWizard(self.startpage):
- success = self.OnWizFinished()
- if not success:
- GMessage(parent=self.parent, message=_("Georectifying setup canceled."))
- self.Cleanup()
- else:
- GMessage(parent=self.parent, message=_("Georectifying setup canceled."))
- self.Cleanup()
- #
- # start GCP display
- #
- if success:
- # instance of render.Map to be associated with display
- self.SwitchEnv("source")
- self.SrcMap = Map(gisrc=self.source_gisrc)
- self.SwitchEnv("target")
- self.TgtMap = Map(gisrc=self.target_gisrc)
- self.Map = self.SrcMap
- #
- # add layer to source map
- #
- if maptype == "raster":
- rendertype = "raster"
- cmdlist = ["d.rast", "map=%s" % src_map]
- else: # -> vector layer
- rendertype = "vector"
- cmdlist = ["d.vect", "map=%s" % src_map]
- self.SwitchEnv("source")
- name, found = utils.GetLayerNameFromCmd(cmdlist)
- self.SrcMap.AddLayer(
- ltype=rendertype,
- command=cmdlist,
- active=True,
- name=name,
- hidden=False,
- opacity=1.0,
- render=False,
- )
- self.SwitchEnv("target")
- web_service_layer = self.mappage.GetWebServiceLayers(name=tgt_map["raster"])
- if tgt_map["raster"] and web_service_layer:
- #
- # add web service layer to target map
- #
- rendertype = web_service_layer["type"]
- cmdlist = web_service_layer["cmd"]
- name = tgt_map["raster"]
- self.TgtMap.AddLayer(
- ltype=rendertype,
- command=cmdlist,
- active=True,
- name=name,
- hidden=False,
- opacity=1.0,
- render=False,
- )
- elif tgt_map["raster"]:
- #
- # add raster layer to target map
- #
- rendertype = "raster"
- cmdlist = ["d.rast", "map=%s" % tgt_map["raster"]]
- name, found = utils.GetLayerNameFromCmd(cmdlist)
- self.TgtMap.AddLayer(
- ltype=rendertype,
- command=cmdlist,
- active=True,
- name=name,
- hidden=False,
- opacity=1.0,
- render=False,
- )
- if tgt_map["vector"]:
- #
- # add raster layer to target map
- #
- rendertype = "vector"
- cmdlist = ["d.vect", "map=%s" % tgt_map["vector"]]
- name, found = utils.GetLayerNameFromCmd(cmdlist)
- self.TgtMap.AddLayer(
- ltype=rendertype,
- command=cmdlist,
- active=True,
- name=name,
- hidden=False,
- opacity=1.0,
- render=False,
- )
- #
- # start GCP Manager
- #
- # create superior Map Display frame
- mapframe = wx.Frame(
- parent=None,
- id=wx.ID_ANY,
- size=globalvar.MAP_WINDOW_SIZE,
- style=wx.DEFAULT_FRAME_STYLE,
- title=name,
- )
- # create GCP manager
- gcpmgr = GCPDisplay(
- parent=mapframe,
- giface=self._giface,
- grwiz=self,
- id=wx.ID_ANY,
- Map=self.SrcMap,
- lmgr=self.parent,
- title=name,
- )
- # load GCPs
- gcpmgr.InitMapDisplay()
- gcpmgr.CenterOnScreen()
- gcpmgr.Show()
- # need to update AUI here for wingrass
- gcpmgr._mgr.Update()
- else:
- self.Cleanup()
- def SetSrcEnv(self, location, mapset):
- """Create environment to use for location and mapset
- that are the source of the file(s) to georectify
- :param location: source location
- :param mapset: source mapset
- :return: False on error
- :return: True on success
- """
- self.newlocation = location
- self.newmapset = mapset
- # check to see if we are georectifying map in current working
- # location/mapset
- if (
- self.newlocation == self.currentlocation
- and self.newmapset == self.currentmapset
- ):
- return False
- self.gisrc_dict["LOCATION_NAME"] = location
- self.gisrc_dict["MAPSET"] = mapset
- self.source_gisrc = utils.GetTempfile()
- try:
- f = open(self.source_gisrc, mode="w")
- for line in self.gisrc_dict.items():
- f.write(line[0] + ": " + line[1] + "\n")
- finally:
- f.close()
- return True
- def SwitchEnv(self, grc):
- """
- Switches between original working location/mapset and
- location/mapset that is source of file(s) to georectify
- """
- # check to see if we are georectifying map in current working
- # location/mapset
- if (
- self.newlocation == self.currentlocation
- and self.newmapset == self.currentmapset
- ):
- return False
- if grc == "target":
- os.environ["GISRC"] = str(self.target_gisrc)
- elif grc == "source":
- os.environ["GISRC"] = str(self.source_gisrc)
- return True
- def OnWizFinished(self):
- # self.Cleanup()
- return True
- def OnGLMFocus(self, event):
- """Layer Manager focus"""
- # self.SwitchEnv('target')
- event.Skip()
- def Cleanup(self):
- """Return to current location and mapset"""
- # here was also the cleaning of gcpmanagement from layer manager
- # which is no longer needed
- self.SwitchEnv("target")
- self.wizard.Destroy()
- class LocationPage(TitledPage):
- """
- Set map type (raster or vector) to georectify and
- select location/mapset of map(s) to georectify.
- """
- def __init__(self, wizard, parent):
- TitledPage.__init__(self, wizard, _("Select map type and location/mapset"))
- self.parent = parent
- self.grassdatabase = self.parent.grassdatabase
- self.xylocation = ""
- self.xymapset = ""
- #
- # layout
- #
- # map type
- self.rb_maptype = wx.RadioBox(
- parent=self,
- id=wx.ID_ANY,
- label=" %s " % _("Map type to georectify"),
- choices=[_("raster"), _("vector")],
- majorDimension=wx.RA_SPECIFY_COLS,
- )
- self.sizer.Add(
- self.rb_maptype,
- flag=wx.ALIGN_CENTER | wx.ALL | wx.EXPAND,
- border=5,
- pos=(1, 1),
- span=(1, 2),
- )
- # location
- self.sizer.Add(
- StaticText(parent=self, id=wx.ID_ANY, label=_("Select source location:")),
- flag=wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL | wx.ALL,
- border=5,
- pos=(2, 1),
- )
- self.cb_location = LocationSelect(parent=self, gisdbase=self.grassdatabase)
- self.sizer.Add(
- self.cb_location,
- flag=wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL | wx.ALL,
- border=5,
- pos=(2, 2),
- )
- # mapset
- self.sizer.Add(
- StaticText(parent=self, id=wx.ID_ANY, label=_("Select source mapset:")),
- flag=wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL | wx.ALL,
- border=5,
- pos=(3, 1),
- )
- self.cb_mapset = MapsetSelect(
- parent=self, gisdbase=self.grassdatabase, setItems=False
- )
- self.sizer.Add(
- self.cb_mapset,
- flag=wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL | wx.ALL,
- border=5,
- pos=(3, 2),
- )
- self.sizer.AddGrowableCol(2)
- #
- # bindings
- #
- self.Bind(wx.EVT_RADIOBOX, self.OnMaptype, self.rb_maptype)
- self.Bind(wx.EVT_COMBOBOX, self.OnLocation, self.cb_location)
- self.cb_mapset.Bind(wx.EVT_TEXT, self.OnMapset)
- self.Bind(wiz.EVT_WIZARD_PAGE_CHANGING, self.OnPageChanging)
- self.Bind(wiz.EVT_WIZARD_PAGE_CHANGED, self.OnEnterPage)
- # self.Bind(wx.EVT_CLOSE, self.parent.Cleanup)
- def OnMaptype(self, event):
- """Change map type"""
- global maptype
- if event.GetInt() == 0:
- maptype = "raster"
- else:
- maptype = "vector"
- def OnLocation(self, event):
- """Sets source location for map(s) to georectify"""
- self.xylocation = event.GetString()
- # create a list of valid mapsets
- tmplist = os.listdir(os.path.join(self.grassdatabase, self.xylocation))
- self.mapsetList = []
- for item in tmplist:
- if os.path.isdir(
- os.path.join(self.grassdatabase, self.xylocation, item)
- ) and os.path.exists(
- os.path.join(self.grassdatabase, self.xylocation, item, "WIND")
- ):
- if item != "PERMANENT":
- self.mapsetList.append(item)
- self.xymapset = "PERMANENT"
- utils.ListSortLower(self.mapsetList)
- self.mapsetList.insert(0, "PERMANENT")
- self.cb_mapset.SetItems(self.mapsetList)
- self.cb_mapset.SetStringSelection(self.xymapset)
- if not wx.FindWindowById(wx.ID_FORWARD).IsEnabled():
- wx.FindWindowById(wx.ID_FORWARD).Enable(True)
- def OnMapset(self, event):
- """Sets source mapset for map(s) to georectify"""
- if self.xylocation == "":
- GMessage(
- _("You must select a valid location " "before selecting a mapset"),
- parent=self,
- )
- return
- self.xymapset = event.GetString()
- if not wx.FindWindowById(wx.ID_FORWARD).IsEnabled():
- wx.FindWindowById(wx.ID_FORWARD).Enable(True)
- def OnPageChanging(self, event=None):
- if event.GetDirection() and (self.xylocation == "" or self.xymapset == ""):
- GMessage(
- _(
- "You must select a valid location "
- "and mapset in order to continue"
- ),
- parent=self,
- )
- event.Veto()
- return
- self.parent.SetSrcEnv(self.xylocation, self.xymapset)
- def OnEnterPage(self, event=None):
- if self.xylocation == "" or self.xymapset == "":
- wx.FindWindowById(wx.ID_FORWARD).Enable(False)
- else:
- wx.FindWindowById(wx.ID_FORWARD).Enable(True)
- class GroupPage(TitledPage):
- """
- Set group to georectify. Create group if desired.
- """
- def __init__(self, wizard, parent):
- TitledPage.__init__(self, wizard, _("Select image/map group to georectify"))
- self.parent = parent
- self.grassdatabase = self.parent.grassdatabase
- self.groupList = []
- self.xylocation = ""
- self.xymapset = ""
- self.xygroup = ""
- # default extension
- self.extension = "_georect" + str(os.getpid())
- #
- # layout
- #
- # group
- self.sizer.Add(
- StaticText(parent=self, id=wx.ID_ANY, label=_("Select/create group:")),
- flag=wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL | wx.ALL,
- border=5,
- pos=(1, 1),
- )
- self.cb_group = wx.ComboBox(
- parent=self,
- id=wx.ID_ANY,
- choices=self.groupList,
- size=(350, -1),
- style=wx.CB_DROPDOWN,
- )
- self.sizer.Add(
- self.cb_group,
- flag=wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL | wx.ALL,
- border=5,
- pos=(1, 2),
- )
- # create group
- self.sizer.Add(
- StaticText(
- parent=self, id=wx.ID_ANY, label=_("Create group if none exists")
- ),
- flag=wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL | wx.ALL,
- border=5,
- pos=(2, 1),
- )
- btnSizer = wx.BoxSizer(wx.HORIZONTAL)
- self.btn_mkgroup = Button(
- parent=self, id=wx.ID_ANY, label=_("Create/edit group...")
- )
- self.btn_vgroup = Button(
- parent=self, id=wx.ID_ANY, label=_("Add vector map to group...")
- )
- btnSizer.Add(self.btn_mkgroup, flag=wx.RIGHT, border=5)
- btnSizer.Add(self.btn_vgroup, flag=wx.LEFT, border=5)
- self.sizer.Add(
- btnSizer,
- flag=wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL | wx.ALL,
- border=5,
- pos=(2, 2),
- )
- # extension
- self.sizer.Add(
- StaticText(
- parent=self, id=wx.ID_ANY, label=_("Extension for output maps:")
- ),
- flag=wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL | wx.ALL,
- border=5,
- pos=(3, 1),
- )
- self.ext_txt = TextCtrl(parent=self, id=wx.ID_ANY, value="", size=(350, -1))
- self.ext_txt.SetValue(self.extension)
- self.sizer.Add(
- self.ext_txt,
- flag=wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL | wx.ALL,
- border=5,
- pos=(3, 2),
- )
- self.sizer.AddGrowableCol(2)
- #
- # bindings
- #
- self.Bind(wx.EVT_COMBOBOX, self.OnGroup, self.cb_group)
- self.Bind(wx.EVT_TEXT, self.OnExtension, self.ext_txt)
- self.Bind(wiz.EVT_WIZARD_PAGE_CHANGING, self.OnPageChanging)
- self.Bind(wiz.EVT_WIZARD_PAGE_CHANGED, self.OnEnterPage)
- self.Bind(wx.EVT_CLOSE, self.parent.Cleanup)
- # hide vector group button by default
- self.btn_vgroup.Hide()
- def OnGroup(self, event):
- self.xygroup = event.GetString()
- def OnMkGroup(self, event):
- """Create new group in source location/mapset"""
- if self.xygroup == "":
- self.xygroup = self.cb_group.GetValue()
- dlg = GroupDialog(parent=self, defaultGroup=self.xygroup)
- dlg.DisableSubgroupEdit()
- dlg.ShowModal()
- gr, s = dlg.GetSelectedGroup()
- if gr in dlg.GetExistGroups():
- self.xygroup = gr
- else:
- gr = ""
- dlg.Destroy()
- self.OnEnterPage()
- self.Update()
- def OnVGroup(self, event):
- """Add vector maps to group"""
- if self.xygroup == "":
- self.xygroup = self.cb_group.GetValue()
- vector_dir = os.path.join(
- self.grassdatabase, self.xylocation, self.xymapset, "vector"
- )
- if os.path.exists(vector_dir):
- dlg = VectGroup(
- parent=self,
- id=wx.ID_ANY,
- grassdb=self.grassdatabase,
- location=self.xylocation,
- mapset=self.xymapset,
- group=self.xygroup,
- )
- if dlg.ShowModal() != wx.ID_OK:
- return
- dlg.MakeVGroup()
- self.OnEnterPage()
- else:
- GError(parent=self, message=_("No vector maps."))
- def OnExtension(self, event):
- self.extension = self.ext_txt.GetValue()
- def OnPageChanging(self, event=None):
- if event.GetDirection() and self.xygroup == "":
- GMessage(
- _("You must select a valid image/map " "group in order to continue"),
- parent=self,
- )
- event.Veto()
- return
- if event.GetDirection() and self.extension == "":
- GMessage(
- _("You must enter an map name " "extension in order to continue"),
- parent=self,
- )
- event.Veto()
- return
- def OnEnterPage(self, event=None):
- global maptype
- self.groupList = []
- self.xylocation = self.parent.gisrc_dict["LOCATION_NAME"]
- self.xymapset = self.parent.gisrc_dict["MAPSET"]
- # create a list of groups in selected mapset
- if os.path.isdir(
- os.path.join(self.grassdatabase, self.xylocation, self.xymapset, "group")
- ):
- tmplist = os.listdir(
- os.path.join(
- self.grassdatabase, self.xylocation, self.xymapset, "group"
- )
- )
- for item in tmplist:
- if os.path.isdir(
- os.path.join(
- self.grassdatabase,
- self.xylocation,
- self.xymapset,
- "group",
- item,
- )
- ):
- self.groupList.append(item)
- if maptype == "raster":
- self.btn_vgroup.Hide()
- self.Bind(wx.EVT_BUTTON, self.OnMkGroup, self.btn_mkgroup)
- elif maptype == "vector":
- self.btn_vgroup.Show()
- self.Bind(wx.EVT_BUTTON, self.OnMkGroup, self.btn_mkgroup)
- self.Bind(wx.EVT_BUTTON, self.OnVGroup, self.btn_vgroup)
- utils.ListSortLower(self.groupList)
- self.cb_group.SetItems(self.groupList)
- if len(self.groupList) > 0:
- if self.xygroup and self.xygroup in self.groupList:
- self.cb_group.SetStringSelection(self.xygroup)
- else:
- self.cb_group.SetSelection(0)
- self.xygroup = self.groupList[0]
- if self.xygroup == "" or self.extension == "":
- wx.FindWindowById(wx.ID_FORWARD).Enable(False)
- else:
- wx.FindWindowById(wx.ID_FORWARD).Enable(True)
- # switch to source
- self.parent.SwitchEnv("source")
- class DispMapPage(TitledPage):
- """
- Select ungeoreferenced map to display for interactively
- setting ground control points (GCPs).
- """
- def __init__(self, wizard, parent):
- TitledPage.__init__(
- self,
- wizard,
- _("Select maps to display for ground control point (GCP) creation"),
- )
- self.parent = parent
- global maptype
- self.web_servc_lyrs_root_node_name = _("Map Display Web Service Layer(s)")
- #
- # layout
- #
- self.sizer.Add(
- StaticText(
- parent=self, id=wx.ID_ANY, label=_("Select source map to display:")
- ),
- flag=wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL | wx.ALL,
- border=5,
- pos=(1, 1),
- )
- self.srcselection = Select(
- self,
- id=wx.ID_ANY,
- size=globalvar.DIALOG_GSELECT_SIZE,
- type=maptype,
- updateOnPopup=False,
- )
- self.sizer.Add(
- self.srcselection,
- flag=wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL | wx.ALL,
- border=5,
- pos=(1, 2),
- )
- self.sizer.Add(
- StaticText(
- parent=self,
- id=wx.ID_ANY,
- label=_("Select target raster map to display:"),
- ),
- flag=wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL | wx.ALL,
- border=5,
- pos=(2, 1),
- )
- self.tgtrastselection = Select(
- self,
- id=wx.ID_ANY,
- size=globalvar.DIALOG_GSELECT_SIZE,
- type="raster",
- updateOnPopup=False,
- extraItems=self.GetSelectTargetRasterExtraItems(),
- )
- self.sizer.Add(
- self.tgtrastselection,
- flag=wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL | wx.ALL,
- border=5,
- pos=(2, 2),
- )
- self.sizer.Add(
- StaticText(
- parent=self,
- id=wx.ID_ANY,
- label=_("Select target vector map to display:"),
- ),
- flag=wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL | wx.ALL,
- border=5,
- pos=(3, 1),
- )
- self.tgtvectselection = Select(
- self,
- id=wx.ID_ANY,
- size=globalvar.DIALOG_GSELECT_SIZE,
- type="vector",
- updateOnPopup=False,
- )
- self.sizer.Add(
- self.tgtvectselection,
- flag=wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL | wx.ALL,
- border=5,
- pos=(3, 2),
- )
- #
- # bindings
- #
- self.srcselection.Bind(wx.EVT_TEXT, self.OnSrcSelection)
- self.tgtrastselection.Bind(wx.EVT_TEXT, self.OnTgtRastSelection)
- self.tgtvectselection.Bind(wx.EVT_TEXT, self.OnTgtVectSelection)
- self.Bind(wiz.EVT_WIZARD_PAGE_CHANGING, self.OnPageChanging)
- self.Bind(wiz.EVT_WIZARD_PAGE_CHANGED, self.OnEnterPage)
- self.Bind(wx.EVT_CLOSE, self.parent.Cleanup)
- def OnSrcSelection(self, event):
- """Source map to display selected"""
- global src_map
- global maptype
- src_map = self.srcselection.GetValue()
- if src_map == "":
- wx.FindWindowById(wx.ID_FORWARD).Enable(False)
- else:
- wx.FindWindowById(wx.ID_FORWARD).Enable(True)
- try:
- # set computational region to match selected map and zoom display
- # to region
- if maptype == "raster":
- p = RunCommand("g.region", "raster=src_map")
- elif maptype == "vector":
- p = RunCommand("g.region", "vector=src_map")
- if p.returncode == 0:
- print("returncode = ", str(p.returncode))
- self.parent.Map.region = self.parent.Map.GetRegion()
- except:
- pass
- def OnTgtRastSelection(self, event):
- """Source map to display selected"""
- global tgt_map
- tgt_map["raster"] = self.tgtrastselection.GetValue()
- def OnTgtVectSelection(self, event):
- """Source map to display selected"""
- global tgt_map
- tgt_map["vector"] = self.tgtvectselection.GetValue()
- def OnPageChanging(self, event=None):
- global src_map
- global tgt_map
- if event.GetDirection() and (src_map == ""):
- GMessage(
- _("You must select a source map " "in order to continue"), parent=self
- )
- event.Veto()
- return
- self.parent.SwitchEnv("target")
- def OnEnterPage(self, event=None):
- global maptype
- global src_map
- global tgt_map
- self.srcselection.SetElementList(maptype)
- if maptype == "raster":
- ret = RunCommand(
- "i.group",
- parent=self,
- read=True,
- group=self.parent.grouppage.xygroup,
- flags="g",
- )
- if ret:
- self.parent.src_maps = ret.splitlines()
- else:
- GError(
- parent=self,
- message=_(
- "No maps in selected group <%s>.\n"
- "Please edit group or select another group."
- )
- % self.parent.grouppage.xygroup,
- )
- return
- elif maptype == "vector":
- grassdatabase = self.parent.grassdatabase
- xylocation = self.parent.gisrc_dict["LOCATION_NAME"]
- xymapset = self.parent.gisrc_dict["MAPSET"]
- # make list of vectors to georectify from VREF
- vgrpfile = os.path.join(
- grassdatabase,
- xylocation,
- xymapset,
- "group",
- self.parent.grouppage.xygroup,
- "VREF",
- )
- error_message = (
- _(
- "No maps in selected group <%s>.\n"
- "Please edit group or select another group."
- )
- % self.parent.grouppage.xygroup
- )
- try:
- with open(vgrpfile) as f:
- for vect in f.readlines():
- vect = vect.strip("\n")
- if len(vect) < 1:
- continue
- self.parent.src_maps.append(vect)
- except FileNotFoundError:
- GError(parent=self, message=error_message, showTraceback=False)
- return
- if len(self.parent.src_maps) < 1:
- GError(parent=self, message=error_message)
- return
- # filter out all maps not in group
- self.srcselection.tcp.GetElementList(elements=self.parent.src_maps)
- src_map = self.parent.src_maps[0]
- self.srcselection.SetValue(src_map)
- self.parent.SwitchEnv("target")
- self.tgtrastselection.SetElementList("raster")
- self.tgtrastselection.GetElementList()
- self.tgtvectselection.SetElementList("vector")
- self.tgtvectselection.GetElementList()
- self.parent.SwitchEnv("source")
- if src_map == "":
- wx.FindWindowById(wx.ID_FORWARD).Enable(False)
- else:
- wx.FindWindowById(wx.ID_FORWARD).Enable(True)
- def GetWebServiceLayers(self, ltype=("wms"), name=None):
- """Get Map Display web service layer(s).
- :param ltype: map layer type
- :param name: map layer name
- :return: web service layer(s) dict
- {
- web_service_map_layer_name: {'type': ltype, 'cmd': [cmd list]},
- ...
- }
- :return: None when web service map layer name doesn't exist
- """
- layers = {}
- for layer in self.parent._giface.GetLayerList():
- if layer.type in ltype:
- layers[str(layer)] = {"type": layer.type, "cmd": layer.cmd}
- if name:
- return layers.get(name)
- return layers
- def GetSelectTargetRasterExtraItems(self):
- """Get select target raster widget extra items."""
- return {self.web_servc_lyrs_root_node_name: self.GetWebServiceLayers().keys()}
- class GCPPanel(MapPanel, ColumnSorterMixin):
- """
- Manages ground control points for georectifying. Calculates RMS statistics.
- Calls i.rectify or v.rectify to georectify map.
- """
- def __init__(
- self,
- parent,
- giface,
- grwiz=None,
- id=wx.ID_ANY,
- title=_("Manage Ground Control Points"),
- size=(700, 300),
- toolbars=["gcpdisp"],
- Map=None,
- lmgr=None,
- ):
- self.grwiz = grwiz # GR Wizard
- self._giface = giface
- if tgt_map["raster"] == "" and tgt_map["vector"] == "":
- self.show_target = False
- else:
- self.show_target = True
- # wx.Frame.__init__(self, parent, id, title, size = size, name = "GCPFrame")
- MapPanel.__init__(
- self,
- parent=parent,
- giface=self._giface,
- title=title,
- size=size,
- Map=Map,
- toolbars=toolbars,
- name="GCPMapWindow",
- )
- # init variables
- self.parent = parent
- #
- # register data structures for drawing GCP's
- #
- self.pointsToDrawTgt = self.TgtMapWindow.RegisterGraphicsToDraw(
- graphicsType="point", setStatusFunc=self.SetGCPSatus
- )
- self.pointsToDrawSrc = self.SrcMapWindow.RegisterGraphicsToDraw(
- graphicsType="point", setStatusFunc=self.SetGCPSatus
- )
- # connect to the map windows signals
- # used to add or edit GCP
- self.SrcMapWindow.mouseLeftUpPointer.connect(
- lambda x, y: self._onMouseLeftUpPointer(self.SrcMapWindow, x, y)
- )
- self.TgtMapWindow.mouseLeftUpPointer.connect(
- lambda x, y: self._onMouseLeftUpPointer(self.TgtMapWindow, x, y)
- )
- # window resized
- self.resize = False
- self.grassdatabase = self.grwiz.grassdatabase
- self.currentlocation = self.grwiz.currentlocation
- self.currentmapset = self.grwiz.currentmapset
- self.newlocation = self.grwiz.newlocation
- self.newmapset = self.grwiz.newmapset
- self.xylocation = self.grwiz.gisrc_dict["LOCATION_NAME"]
- self.xymapset = self.grwiz.gisrc_dict["MAPSET"]
- self.xygroup = self.grwiz.grouppage.xygroup
- self.src_maps = self.grwiz.src_maps
- self.extension = self.grwiz.grouppage.extension
- self.outname = ""
- self.VectGRList = []
- self.file = {
- "points": os.path.join(
- self.grassdatabase,
- self.xylocation,
- self.xymapset,
- "group",
- self.xygroup,
- "POINTS",
- ),
- "points_bak": os.path.join(
- self.grassdatabase,
- self.xylocation,
- self.xymapset,
- "group",
- self.xygroup,
- "POINTS_BAK",
- ),
- "rgrp": os.path.join(
- self.grassdatabase,
- self.xylocation,
- self.xymapset,
- "group",
- self.xygroup,
- "REF",
- ),
- "vgrp": os.path.join(
- self.grassdatabase,
- self.xylocation,
- self.xymapset,
- "group",
- self.xygroup,
- "VREF",
- ),
- "target": os.path.join(
- self.grassdatabase,
- self.xylocation,
- self.xymapset,
- "group",
- self.xygroup,
- "TARGET",
- ),
- }
- # make a backup of the current points file
- if os.path.exists(self.file["points"]):
- shutil.copy(self.file["points"], self.file["points_bak"])
- # polynomial order transformation for georectification
- self.gr_order = 1
- # interpolation method for georectification
- self.gr_method = "nearest"
- # region clipping for georectified map
- self.clip_to_region = False
- # overwrite result map
- self.overwrite = False
- # number of GCPs selected to be used for georectification (checked)
- self.GCPcount = 0
- # forward RMS error
- self.fwd_rmserror = 0.0
- # backward RMS error
- self.bkw_rmserror = 0.0
- # list map coords and ID of map display they came from
- self.mapcoordlist = []
- self.mapcoordlist.append(
- [
- 0, # GCP number
- 0.0, # source east
- 0.0, # source north
- 0.0, # target east
- 0.0, # target north
- 0.0, # forward error
- 0.0,
- ]
- ) # backward error
- # init vars to highlight high RMS errors
- self.highest_only = True
- self.show_unused = True
- self.highest_key = -1
- self.rmsthresh = 0
- self.rmsmean = 0
- self.rmssd = 0
- self.SetTarget(self.xygroup, self.currentlocation, self.currentmapset)
- self.itemDataMap = None
- # images for column sorting
- # CheckListCtrlMixin must set an ImageList first
- self.il = self.list.GetImageList(wx.IMAGE_LIST_SMALL)
- SmallUpArrow = BitmapFromImage(getSmallUpArrowImage())
- SmallDnArrow = BitmapFromImage(getSmallDnArrowImage())
- self.sm_dn = self.il.Add(SmallDnArrow)
- self.sm_up = self.il.Add(SmallUpArrow)
- # set mouse characteristics
- self.mapwin = self.SrcMapWindow
- self.mapwin.mouse["box"] = "point"
- self.mapwin.mouse["use"] == "pointer"
- self.mapwin.zoomtype = 0
- self.mapwin.pen = wx.Pen(colour="black", width=2, style=wx.SOLID)
- self.mapwin.SetNamedCursor("cross")
- self.mapwin = self.TgtMapWindow
- # set mouse characteristics
- self.mapwin.mouse["box"] = "point"
- self.mapwin.mouse["use"] == "pointer"
- self.mapwin.zoomtype = 0
- self.mapwin.pen = wx.Pen(colour="black", width=2, style=wx.SOLID)
- self.mapwin.SetNamedCursor("cross")
- #
- # show new display & draw map
- #
- if self.show_target:
- self.MapWindow = self.TgtMapWindow
- self.Map = self.TgtMap
- self.OnZoomToMap(None)
- self.MapWindow = self.SrcMapWindow
- self.Map = self.SrcMap
- self.OnZoomToMap(None)
- #
- # bindings
- #
- self.Bind(wx.EVT_ACTIVATE, self.OnFocus)
- self.Bind(wx.EVT_SIZE, self.OnSize)
- self.Bind(wx.EVT_IDLE, self.OnIdle)
- self.SetSettings()
- def __del__(self):
- """Disable GCP manager mode"""
- # leaving the method here but was used only to delete gcpmanagement
- # from layer manager which is now not needed
- pass
- def CreateGCPList(self):
- """Create GCP List Control"""
- return GCPList(parent=self, gcp=self)
- # Used by the ColumnSorterMixin, see wx/lib/mixins/listctrl.py
- def GetListCtrl(self):
- return self.list
- def GetMapCoordList(self):
- return self.mapcoordlist
- # Used by the ColumnSorterMixin, see wx/lib/mixins/listctrl.py
- def GetSortImages(self):
- return (self.sm_dn, self.sm_up)
- def GetFwdError(self):
- return self.fwd_rmserror
- def GetBkwError(self):
- return self.bkw_rmserror
- def InitMapDisplay(self):
- self.list.LoadData()
- # initialize column sorter
- self.itemDataMap = self.mapcoordlist
- ncols = self.list.GetColumnCount()
- ColumnSorterMixin.__init__(self, ncols)
- # init to ascending sort on first click
- self._colSortFlag = [1] * ncols
- def SetTarget(self, tgroup, tlocation, tmapset):
- """
- Sets rectification target to current location and mapset
- """
- # check to see if we are georectifying map in current working
- # location/mapset
- if (
- self.newlocation == self.currentlocation
- and self.newmapset == self.currentmapset
- ):
- RunCommand("i.target", parent=self, flags="c", group=tgroup)
- else:
- self.grwiz.SwitchEnv("source")
- RunCommand(
- "i.target",
- parent=self,
- group=tgroup,
- location=tlocation,
- mapset=tmapset,
- )
- self.grwiz.SwitchEnv("target")
- def AddGCP(self, event):
- """
- Appends an item to GCP list
- """
- keyval = self.list.AddGCPItem() + 1
- # source east, source north, target east, target north, forward error,
- # backward error
- self.mapcoordlist.append(
- [
- keyval, # GCP number
- 0.0, # source east
- 0.0, # source north
- 0.0, # target east
- 0.0, # target north
- 0.0, # forward error
- 0.0,
- ]
- ) # backward error
- if self.statusbarManager.GetMode() == 8: # go to
- self.StatusbarUpdate()
- def DeleteGCP(self, event):
- """
- Deletes selected item in GCP list
- """
- minNumOfItems = self.OnGROrder(None)
- if self.list.GetItemCount() <= minNumOfItems:
- GMessage(
- parent=self,
- message=_("At least %d GCPs required. Operation canceled.")
- % minNumOfItems,
- )
- return
- key = self.list.DeleteGCPItem()
- del self.mapcoordlist[key]
- # update key and GCP number
- for newkey in range(key, len(self.mapcoordlist)):
- index = self.list.FindItem(-1, newkey + 1)
- self.mapcoordlist[newkey][0] = newkey
- self.list.SetItem(index, 0, str(newkey))
- self.list.SetItemData(index, newkey)
- # update selected
- if self.list.GetItemCount() > 0:
- if self.list.selected < self.list.GetItemCount():
- self.list.selectedkey = self.list.GetItemData(self.list.selected)
- else:
- self.list.selected = self.list.GetItemCount() - 1
- self.list.selectedkey = self.list.GetItemData(self.list.selected)
- self.list.SetItemState(
- self.list.selected, wx.LIST_STATE_SELECTED, wx.LIST_STATE_SELECTED
- )
- else:
- self.list.selected = wx.NOT_FOUND
- self.list.selectedkey = -1
- self.UpdateColours()
- if self.statusbarManager.GetMode() == 8: # go to
- self.StatusbarUpdate()
- if self.list.selectedkey > 0:
- self.statusbarManager.SetProperty("gotoGCP", self.list.selectedkey)
- def ClearGCP(self, event):
- """
- Clears all values in selected item of GCP list and unchecks it
- """
- index = self.list.GetSelected()
- key = self.list.GetItemData(index)
- for i in range(1, 5):
- self.list.SetItem(index, i, "0.0")
- self.list.SetItem(index, 5, "")
- self.list.SetItem(index, 6, "")
- self.list.CheckItem(index, False)
- # GCP number, source E, source N, target E, target N, fwd error, bkwd
- # error
- self.mapcoordlist[key] = [key, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]
- def SetSettings(self):
- """Sets settings for drawing of GCP's."""
- self.highest_only = UserSettings.Get(
- group="gcpman", key="rms", subkey="highestonly"
- )
- self.show_unused = UserSettings.Get(
- group="gcpman", key="symbol", subkey="unused"
- )
- colours = {
- "color": "default",
- "hcolor": "highest",
- "scolor": "selected",
- "ucolor": "unused",
- }
- wpx = UserSettings.Get(group="gcpman", key="symbol", subkey="width")
- for k, v in six.iteritems(colours):
- col = UserSettings.Get(group="gcpman", key="symbol", subkey=k)
- self.pointsToDrawSrc.GetPen(v).SetColour(
- wx.Colour(col[0], col[1], col[2], 255)
- ) # TODO GetPen neni to spatne?
- self.pointsToDrawTgt.GetPen(v).SetColour(
- wx.Colour(col[0], col[1], col[2], 255)
- )
- self.pointsToDrawSrc.GetPen(v).SetWidth(wpx)
- self.pointsToDrawTgt.GetPen(v).SetWidth(wpx)
- spx = UserSettings.Get(group="gcpman", key="symbol", subkey="size")
- self.pointsToDrawSrc.SetPropertyVal("size", int(spx))
- self.pointsToDrawTgt.SetPropertyVal("size", int(spx))
- font = self.GetFont()
- font.SetPointSize(int(spx) + 2)
- textProp = {}
- textProp["active"] = True
- textProp["font"] = font
- self.pointsToDrawSrc.SetPropertyVal("text", textProp)
- self.pointsToDrawTgt.SetPropertyVal("text", copy(textProp))
- # overwrite result map
- self.overwrite = UserSettings.Get(group="gcpman", key="map", subkey="overwrite")
- def SetGCPSatus(self, item, itemIndex):
- """Before GCP is drawn, decides it's colour and whether it
- will be drawed.
- """
- key = self.list.GetItemData(itemIndex)
- # incremented because of itemDataMap (has one more item) - will be
- # changed
- itemIndex += 1
- if not self.list.IsItemChecked(key - 1):
- wxPen = "unused"
- if not self.show_unused:
- item.SetPropertyVal("hide", True)
- else:
- item.SetPropertyVal("hide", False)
- else:
- item.SetPropertyVal("hide", False)
- if self.highest_only:
- if itemIndex == self.highest_key:
- wxPen = "highest"
- else:
- wxPen = "default"
- else:
- if self.mapcoordlist[key][5] > self.rmsthresh:
- wxPen = "highest"
- else:
- wxPen = "default"
- if itemIndex == self.list.selectedkey:
- wxPen = "selected"
- item.SetPropertyVal("label", str(itemIndex))
- item.SetPropertyVal("penName", wxPen)
- def SetGCPData(self, coordtype, coord, mapdisp=None, confirm=False):
- """Inserts coordinates from file, mouse click on map, or
- after editing into selected item of GCP list and checks it for
- use.
- """
- index = self.list.GetSelected()
- if index == wx.NOT_FOUND:
- return
- coord0 = coord[0]
- coord1 = coord[1]
- key = self.list.GetItemData(index)
- if confirm:
- if self.MapWindow == self.SrcMapWindow:
- currloc = _("source")
- else:
- currloc = _("target")
- ret = wx.MessageBox(
- parent=self,
- caption=_("Set GCP coordinates"),
- message=_(
- "Set %(coor)s coordinates for GCP No. %(key)s? \n\n"
- "East: %(coor0)s \n"
- "North: %(coor1)s"
- )
- % {
- "coor": currloc,
- "key": str(key),
- "coor0": str(coord0),
- "coor1": str(coord1),
- },
- style=wx.ICON_QUESTION | wx.YES_NO | wx.CENTRE,
- )
- # for wingrass
- if os.name == "nt":
- self.MapWindow.SetFocus()
- if ret == wx.NO:
- return
- if coordtype == "source":
- self.list.SetItem(index, 1, str(coord0))
- self.list.SetItem(index, 2, str(coord1))
- self.mapcoordlist[key][1] = coord[0]
- self.mapcoordlist[key][2] = coord[1]
- self.pointsToDrawSrc.GetItem(key - 1).SetCoords([coord0, coord1])
- elif coordtype == "target":
- self.list.SetItem(index, 3, str(coord0))
- self.list.SetItem(index, 4, str(coord1))
- self.mapcoordlist[key][3] = coord[0]
- self.mapcoordlist[key][4] = coord[1]
- self.pointsToDrawTgt.GetItem(key - 1).SetCoords([coord0, coord1])
- self.list.SetItem(index, 5, "0")
- self.list.SetItem(index, 6, "0")
- self.mapcoordlist[key][5] = 0.0
- self.mapcoordlist[key][6] = 0.0
- # self.list.ResizeColumns()
- def SaveGCPs(self, event):
- """Make a POINTS file or save GCP coordinates to existing
- POINTS file
- """
- self.GCPcount = 0
- try:
- f = open(self.file["points"], mode="w")
- # use os.linesep or '\n' here ???
- f.write("# Ground Control Points File\n")
- f.write("# \n")
- f.write("# target location: " + self.currentlocation + "\n")
- f.write("# target mapset: " + self.currentmapset + "\n")
- f.write("#\tsource\t\ttarget\t\tstatus\n")
- f.write("#\teast\tnorth\teast\tnorth\t(1=ok, 0=ignore)\n")
- f.write(
- "#----------------------- ----------------------- ---------------\n"
- )
- for index in range(self.list.GetItemCount()):
- if self.list.IsItemChecked(index):
- check = "1"
- self.GCPcount += 1
- else:
- check = "0"
- coord0 = self.list.GetItem(index, 1).GetText()
- coord1 = self.list.GetItem(index, 2).GetText()
- coord2 = self.list.GetItem(index, 3).GetText()
- coord3 = self.list.GetItem(index, 4).GetText()
- f.write(
- coord0
- + " "
- + coord1
- + " "
- + coord2
- + " "
- + coord3
- + " "
- + check
- + "\n"
- )
- except IOError as err:
- GError(
- parent=self,
- message="%s <%s>. %s%s"
- % (
- _("Writing POINTS file failed"),
- self.file["points"],
- os.linesep,
- err,
- ),
- )
- return
- f.close()
- # if event != None save also to backup file
- if event:
- shutil.copy(self.file["points"], self.file["points_bak"])
- self._giface.WriteLog(_("POINTS file saved for group <%s>") % self.xygroup)
- # self.SetStatusText(_('POINTS file saved'))
- def ReadGCPs(self):
- """
- Reads GCPs and georectified coordinates from POINTS file
- """
- self.GCPcount = 0
- sourceMapWin = self.SrcMapWindow
- targetMapWin = self.TgtMapWindow
- if not sourceMapWin:
- GError(parent=self, message=_("source mapwin not defined"))
- if not targetMapWin:
- GError(parent=self, message=_("target mapwin not defined"))
- try:
- f = open(self.file["points"], "r")
- GCPcnt = 0
- for line in f.readlines():
- if line[0] == "#" or line == "":
- continue
- line = line.replace("\n", "").strip()
- coords = list(map(float, line.split()))
- if coords[4] == 1:
- check = True
- self.GCPcount += 1
- else:
- check = False
- self.AddGCP(event=None)
- self.SetGCPData("source", (coords[0], coords[1]), sourceMapWin)
- self.SetGCPData("target", (coords[2], coords[3]), targetMapWin)
- index = self.list.GetSelected()
- if index != wx.NOT_FOUND:
- self.list.CheckItem(index, check)
- GCPcnt += 1
- except IOError as err:
- GError(
- parent=self,
- message="%s <%s>. %s%s"
- % (
- _("Reading POINTS file failed"),
- self.file["points"],
- os.linesep,
- err,
- ),
- )
- return
- f.close()
- if GCPcnt == 0:
- # 3 gcp is minimum
- for i in range(3):
- self.AddGCP(None)
- if self.CheckGCPcount():
- # calculate RMS
- self.RMSError(self.xygroup, self.gr_order)
- def ReloadGCPs(self, event):
- """Reload data from file"""
- # use backup
- shutil.copy(self.file["points_bak"], self.file["points"])
- # delete all items in mapcoordlist
- self.mapcoordlist = []
- self.mapcoordlist.append(
- [
- 0, # GCP number
- 0.0, # source east
- 0.0, # source north
- 0.0, # target east
- 0.0, # target north
- 0.0, # forward error
- 0.0,
- ]
- ) # backward error
- self.list.LoadData()
- self.itemDataMap = self.mapcoordlist
- if self._col != -1:
- self.list.ClearColumnImage(self._col)
- self._colSortFlag = [1] * self.list.GetColumnCount()
- # draw GCPs (source and target)
- sourceMapWin = self.SrcMapWindow
- sourceMapWin.UpdateMap(render=False, renderVector=False)
- if self.show_target:
- targetMapWin = self.TgtMapWindow
- targetMapWin.UpdateMap(render=False, renderVector=False)
- def OnFocus(self, event):
- # TODO: it is here just to remove old or obsolate beavior of base class gcp/MapPanel?
- # self.grwiz.SwitchEnv('source')
- pass
- def _onMouseLeftUpPointer(self, mapWindow, x, y):
- if mapWindow == self.SrcMapWindow:
- coordtype = "source"
- else:
- coordtype = "target"
- coord = (x, y)
- self.SetGCPData(coordtype, coord, self, confirm=True)
- mapWindow.UpdateMap(render=False, renderVector=False)
- def OnRMS(self, event):
- """
- RMS button handler
- """
- self.RMSError(self.xygroup, self.gr_order)
- sourceMapWin = self.SrcMapWindow
- sourceMapWin.UpdateMap(render=False, renderVector=False)
- if self.show_target:
- targetMapWin = self.TgtMapWindow
- targetMapWin.UpdateMap(render=False, renderVector=False)
- def CheckGCPcount(self, msg=False):
- """
- Checks to make sure that the minimum number of GCPs have been defined and
- are active for the selected transformation order
- """
- if (
- (self.GCPcount < 3 and self.gr_order == 1)
- or (self.GCPcount < 6 and self.gr_order == 2)
- or (self.GCPcount < 10 and self.gr_order == 3)
- ):
- if msg:
- GWarning(
- parent=self,
- message=_(
- "Insufficient points defined and active (checked) "
- "for selected rectification method (order: %d).\n"
- "3+ points needed for 1st order,\n"
- "6+ points for 2nd order, and\n"
- "10+ points for 3rd order."
- )
- % self.gr_order,
- )
- return False
- else:
- return True
- def _getOverWriteDialog(self, maptype, overwrite):
- """Get overwrite confirm dialog
- :param str maptype: map type
- :param bool overwrite: overwrite
- :return
- object: overwrite dialog
- None: it isn't necessary to display the overwrite dialog
- """
- if maptype == "raster":
- self.grwiz.SwitchEnv("source")
- maps = grass.read_command(
- "i.group",
- flags="gl",
- group=self.xygroup,
- quiet=True,
- ).split("\n")
- self.grwiz.SwitchEnv("target")
- found_maps = []
- if maps:
- for map in maps:
- if map:
- map_name = map.split("@")[0] + self.extension
- found = grass.find_file(
- name=map_name,
- element="cell",
- mapset=self.currentmapset,
- )
- if found["name"]:
- found_maps.append("<{}>".format(found["name"]))
- map_name = ", ".join(found_maps)
- else:
- self.grwiz.SwitchEnv("target")
- found = grass.find_file(
- name=self.outname,
- element="vector",
- mapset=self.currentmapset,
- )
- self.grwiz.SwitchEnv("source")
- map_name = "<{}>".format(found["name"])
- if found["name"] and not overwrite:
- overwrite_dlg = wx.MessageDialog(
- self.GetParent(),
- message=_(
- "The {map_type} map {map_name} exists. "
- "Do you want to overwrite?".format(
- map_type=maptype,
- map_name=map_name,
- ),
- ),
- caption=_("Overwrite?"),
- style=wx.YES_NO | wx.YES_DEFAULT | wx.ICON_QUESTION,
- )
- return overwrite_dlg
- def OnGeorect(self, event):
- """
- Georectifies map(s) in group using i.rectify or v.transform
- """
- global maptype
- self.SaveGCPs(None)
- if not self.CheckGCPcount(msg=True):
- return
- if maptype == "raster":
- overwrite_dlg = self._getOverWriteDialog(
- maptype=maptype,
- overwrite=self.overwrite,
- )
- if overwrite_dlg:
- if not overwrite_dlg.ShowModal() == wx.ID_YES:
- overwrite_dlg.Destroy()
- return
- overwrite_dlg.Destroy()
- overwrite = True
- else:
- overwrite = self.overwrite
- self.grwiz.SwitchEnv("source")
- if self.clip_to_region:
- flags = "ac"
- else:
- flags = "a"
- busy = wx.BusyInfo(_("Rectifying images, please wait..."), parent=self)
- wx.GetApp().Yield()
- ret, msg = RunCommand(
- "i.rectify",
- parent=self,
- getErrorMsg=True,
- quiet=True,
- group=self.xygroup,
- extension=self.extension,
- order=self.gr_order,
- method=self.gr_method,
- flags=flags,
- overwrite=overwrite,
- )
- del busy
- # provide feedback on failure
- if ret != 0:
- print(msg, file=sys.stderr)
- elif maptype == "vector":
- # loop through all vectors in VREF
- self.grwiz.SwitchEnv("source")
- # make list of vectors to georectify from VREF
- f = open(self.file["vgrp"])
- vectlist = []
- try:
- for vect in f.readlines():
- vect = vect.strip("\n")
- if len(vect) < 1:
- continue
- vectlist.append(vect)
- finally:
- f.close()
- # georectify each vector in VREF using v.rectify
- for vect in vectlist:
- self.outname = str(vect.split("@")[0]) + self.extension
- overwrite_dlg = self._getOverWriteDialog(
- maptype=maptype,
- overwrite=self.overwrite,
- )
- if overwrite_dlg:
- if not overwrite_dlg.ShowModal() == wx.ID_YES:
- overwrite_dlg.Destroy()
- return
- overwrite_dlg.Destroy()
- overwrite = True
- else:
- overwrite = self.overwrite
- self._giface.WriteLog(
- text=_("Transforming <%s>...") % vect,
- notification=Notification.MAKE_VISIBLE,
- )
- ret = msg = ""
- busy = wx.BusyInfo(
- _("Rectifying vector map <%s>, please wait...") % vect, parent=self
- )
- wx.GetApp().Yield()
- ret, msg = RunCommand(
- "v.rectify",
- parent=self,
- getErrorMsg=True,
- quiet=True,
- input=vect,
- output=self.outname,
- group=self.xygroup,
- order=self.gr_order,
- overwrite=overwrite,
- )
- del busy
- # provide feedback on failure
- if ret != 0:
- print(msg, file=sys.stderr)
- self.grwiz.SwitchEnv("target")
- def OnGeorectDone(self, **kargs):
- """Print final message"""
- global maptype
- if maptype == "raster":
- return
- returncode = kargs["returncode"]
- if returncode == 0:
- self.VectGRList.append(self.outname)
- print("*****vector list = " + str(self.VectGRList))
- else:
- self._giface.WriteError(
- _("Georectification of vector map <%s> failed") % self.outname
- )
- def OnSettings(self, event):
- """GCP Manager settings"""
- dlg = GrSettingsDialog(
- parent=self,
- giface=self._giface,
- id=wx.ID_ANY,
- title=_("GCP Manager settings"),
- )
- if dlg.ShowModal() == wx.ID_OK:
- pass
- dlg.Destroy()
- def UpdateColours(
- self,
- srcrender=False,
- srcrenderVector=False,
- tgtrender=False,
- tgtrenderVector=False,
- ):
- """update colours"""
- highest_fwd_err = 0.0
- self.highest_key = 0
- highest_idx = 0
- for index in range(self.list.GetItemCount()):
- if self.list.IsItemChecked(index):
- key = self.list.GetItemData(index)
- fwd_err = self.mapcoordlist[key][5]
- if self.highest_only:
- self.list.SetItemTextColour(index, wx.BLACK)
- if highest_fwd_err < fwd_err:
- highest_fwd_err = fwd_err
- self.highest_key = key
- highest_idx = index
- elif self.rmsthresh > 0:
- if fwd_err > self.rmsthresh:
- self.list.SetItemTextColour(index, wx.RED)
- else:
- self.list.SetItemTextColour(index, wx.BLACK)
- else:
- self.list.SetItemTextColour(index, wx.BLACK)
- if self.highest_only and highest_fwd_err > 0.0:
- self.list.SetItemTextColour(highest_idx, wx.RED)
- sourceMapWin = self.SrcMapWindow
- sourceMapWin.UpdateMap(render=srcrender, renderVector=srcrenderVector)
- if self.show_target:
- targetMapWin = self.TgtMapWindow
- targetMapWin.UpdateMap(render=tgtrender, renderVector=tgtrenderVector)
- def OnQuit(self, event):
- """Quit georectifier"""
- ret = wx.MessageBox(
- parent=self,
- caption=_("Quit GCP Manager"),
- message=_("Save ground control points?"),
- style=wx.ICON_QUESTION | wx.YES_NO | wx.CANCEL | wx.CENTRE,
- )
- if ret != wx.CANCEL:
- if ret == wx.YES:
- self.SaveGCPs(None)
- elif ret == wx.NO:
- # restore POINTS file from backup
- if os.path.exists(self.file["points_bak"]):
- shutil.copy(self.file["points_bak"], self.file["points"])
- if os.path.exists(self.file["points_bak"]):
- os.unlink(self.file["points_bak"])
- self.SrcMap.Clean()
- self.TgtMap.Clean()
- self.grwiz.Cleanup()
- self._mgr.UnInit()
- self.Destroy()
- # event.Skip()
- def OnGROrder(self, event):
- """
- sets transformation order for georectifying
- """
- if event:
- self.gr_order = event.GetInt() + 1
- numOfItems = self.list.GetItemCount()
- minNumOfItems = numOfItems
- if self.gr_order == 1:
- minNumOfItems = 3
- # self.SetStatusText(_('Insufficient points, 3+ points needed for 1st order'))
- elif self.gr_order == 2:
- minNumOfItems = 6
- diff = 6 - numOfItems
- # self.SetStatusText(_('Insufficient points, 6+ points needed for 2nd order'))
- elif self.gr_order == 3:
- minNumOfItems = 10
- # self.SetStatusText(_('Insufficient points, 10+ points needed for 3rd order'))
- for i in range(minNumOfItems - numOfItems):
- self.AddGCP(None)
- return minNumOfItems
- def RMSError(self, xygroup, order):
- """
- Uses m.transform to calculate forward and backward error for each used GCP
- in POINTS file and insert error values into GCP list.
- Calculates total forward and backward RMS error for all used points
- """
- # save GCPs to points file to make sure that all checked GCPs are used
- self.SaveGCPs(None)
- # self.SetStatusText('')
- if not self.CheckGCPcount(msg=True):
- return
- # get list of forward and reverse rms error values for each point
- self.grwiz.SwitchEnv("source")
- ret = RunCommand(
- "m.transform", parent=self, read=True, group=xygroup, order=order
- )
- self.grwiz.SwitchEnv("target")
- if ret:
- errlist = ret.splitlines()
- else:
- GError(
- parent=self,
- message=_(
- "Could not calculate RMS Error.\n"
- "Possible error with m.transform."
- ),
- )
- return
- # insert error values into GCP list for checked items
- sdfactor = float(UserSettings.Get(group="gcpman", key="rms", subkey="sdfactor"))
- GCPcount = 0
- sumsq_fwd_err = 0.0
- sumsq_bkw_err = 0.0
- sum_fwd_err = 0.0
- highest_fwd_err = 0.0
- self.highest_key = 0
- highest_idx = 0
- for index in range(self.list.GetItemCount()):
- key = self.list.GetItemData(index)
- if self.list.IsItemChecked(index):
- fwd_err, bkw_err = errlist[GCPcount].split()
- self.list.SetItem(index, 5, fwd_err)
- self.list.SetItem(index, 6, bkw_err)
- self.mapcoordlist[key][5] = float(fwd_err)
- self.mapcoordlist[key][6] = float(bkw_err)
- self.list.SetItemTextColour(index, wx.BLACK)
- if self.highest_only:
- if highest_fwd_err < float(fwd_err):
- highest_fwd_err = float(fwd_err)
- self.highest_key = key
- highest_idx = index
- sumsq_fwd_err += float(fwd_err) ** 2
- sumsq_bkw_err += float(bkw_err) ** 2
- sum_fwd_err += float(fwd_err)
- GCPcount += 1
- else:
- self.list.SetItem(index, 5, "")
- self.list.SetItem(index, 6, "")
- self.mapcoordlist[key][5] = 0.0
- self.mapcoordlist[key][6] = 0.0
- self.list.SetItemTextColour(index, wx.BLACK)
- # SD
- if GCPcount > 0:
- self.rmsmean = sum_fwd_err / GCPcount
- self.rmssd = (sumsq_fwd_err - self.rmsmean ** 2) ** 0.5
- self.rmsthresh = self.rmsmean + sdfactor * self.rmssd
- else:
- self.rmsthresh = 0
- self.rmsmean = 0
- self.rmssd = 0
- if self.highest_only and highest_fwd_err > 0.0:
- self.list.SetItemTextColour(highest_idx, wx.RED)
- elif GCPcount > 0 and self.rmsthresh > 0 and not self.highest_only:
- for index in range(self.list.GetItemCount()):
- if self.list.IsItemChecked(index):
- key = self.list.GetItemData(index)
- if self.mapcoordlist[key][5] > self.rmsthresh:
- self.list.SetItemTextColour(index, wx.RED)
- # calculate global RMS error (geometric mean)
- self.fwd_rmserror = round((sumsq_fwd_err / GCPcount) ** 0.5, 4)
- self.bkw_rmserror = round((sumsq_bkw_err / GCPcount) ** 0.5, 4)
- self.list.ResizeColumns()
- def GetNewExtent(self, region, map=None):
- coord_file = utils.GetTempfile()
- newreg = {
- "n": 0.0,
- "s": 0.0,
- "e": 0.0,
- "w": 0.0,
- }
- try:
- f = open(coord_file, mode="w")
- # NW corner
- f.write(str(region["e"]) + " " + str(region["n"]) + "\n")
- # NE corner
- f.write(str(region["e"]) + " " + str(region["s"]) + "\n")
- # SW corner
- f.write(str(region["w"]) + " " + str(region["n"]) + "\n")
- # SE corner
- f.write(str(region["w"]) + " " + str(region["s"]) + "\n")
- finally:
- f.close()
- # save GCPs to points file to make sure that all checked GCPs are used
- self.SaveGCPs(None)
- order = self.gr_order
- self.gr_order = 1
- if not self.CheckGCPcount(msg=True):
- self.gr_order = order
- return
- self.gr_order = order
- # get list of forward and reverse rms error values for each point
- self.grwiz.SwitchEnv("source")
- if map == "source":
- ret = RunCommand(
- "m.transform",
- parent=self,
- read=True,
- group=self.xygroup,
- order=1,
- format="dst",
- coords=coord_file,
- )
- elif map == "target":
- ret = RunCommand(
- "m.transform",
- parent=self,
- read=True,
- group=self.xygroup,
- order=1,
- flags="r",
- format="src",
- coords=coord_file,
- )
- os.unlink(coord_file)
- self.grwiz.SwitchEnv("target")
- if ret:
- errlist = ret.splitlines()
- else:
- GError(
- parent=self,
- message=_(
- "Could not calculate new extends.\n"
- "Possible error with m.transform."
- ),
- )
- return
- # fist corner
- e, n = errlist[0].split()
- fe = float(e)
- fn = float(n)
- newreg["n"] = fn
- newreg["s"] = fn
- newreg["e"] = fe
- newreg["w"] = fe
- # other three corners
- for i in range(1, 4):
- e, n = errlist[i].split()
- fe = float(e)
- fn = float(n)
- if fe < newreg["w"]:
- newreg["w"] = fe
- if fe > newreg["e"]:
- newreg["e"] = fe
- if fn < newreg["s"]:
- newreg["s"] = fn
- if fn > newreg["n"]:
- newreg["n"] = fn
- return newreg
- def OnHelp(self, event):
- """Show GCP Manager manual page"""
- self._giface.Help(entry="wxGUI.gcp")
- def OnUpdateActive(self, event):
- if self.activemap.GetSelection() == 0:
- self.MapWindow = self.SrcMapWindow
- self.Map = self.SrcMap
- else:
- self.MapWindow = self.TgtMapWindow
- self.Map = self.TgtMap
- self.UpdateActive(self.MapWindow)
- # for wingrass
- if os.name == "nt":
- self.MapWindow.SetFocus()
- def UpdateActive(self, win):
- # optionally disable tool zoomback tool
- self.GetMapToolbar().Enable(
- "zoomback", enable=(len(self.MapWindow.zoomhistory) > 1)
- )
- if self.activemap.GetSelection() != (win == self.TgtMapWindow):
- self.activemap.SetSelection(win == self.TgtMapWindow)
- self.StatusbarUpdate()
- def AdjustMap(self, newreg):
- """Adjust map window to new extents"""
- # adjust map window
- self.Map.region["n"] = newreg["n"]
- self.Map.region["s"] = newreg["s"]
- self.Map.region["e"] = newreg["e"]
- self.Map.region["w"] = newreg["w"]
- self.MapWindow.ZoomHistory(
- self.Map.region["n"],
- self.Map.region["s"],
- self.Map.region["e"],
- self.Map.region["w"],
- )
- # LL locations
- if self.Map.projinfo["proj"] == "ll":
- if newreg["n"] > 90.0:
- newreg["n"] = 90.0
- if newreg["s"] < -90.0:
- newreg["s"] = -90.0
- ce = newreg["w"] + (newreg["e"] - newreg["w"]) / 2
- cn = newreg["s"] + (newreg["n"] - newreg["s"]) / 2
- # calculate new center point and display resolution
- self.Map.region["center_easting"] = ce
- self.Map.region["center_northing"] = cn
- self.Map.region["ewres"] = (newreg["e"] - newreg["w"]) / self.Map.width
- self.Map.region["nsres"] = (newreg["n"] - newreg["s"]) / self.Map.height
- self.Map.AlignExtentFromDisplay()
- self.MapWindow.ZoomHistory(
- self.Map.region["n"],
- self.Map.region["s"],
- self.Map.region["e"],
- self.Map.region["w"],
- )
- if self.MapWindow.redrawAll is False:
- self.MapWindow.redrawAll = True
- self.MapWindow.UpdateMap()
- self.StatusbarUpdate()
- def OnZoomToSource(self, event):
- """Set target map window to match extents of source map window"""
- if not self.MapWindow == self.TgtMapWindow:
- self.MapWindow = self.TgtMapWindow
- self.Map = self.TgtMap
- self.UpdateActive(self.TgtMapWindow)
- # get new N, S, E, W for target
- newreg = self.GetNewExtent(self.SrcMap.region, "source")
- if newreg:
- self.AdjustMap(newreg)
- def OnZoomToTarget(self, event):
- """Set source map window to match extents of target map window"""
- if not self.MapWindow == self.SrcMapWindow:
- self.MapWindow = self.SrcMapWindow
- self.Map = self.SrcMap
- self.UpdateActive(self.SrcMapWindow)
- # get new N, S, E, W for target
- newreg = self.GetNewExtent(self.TgtMap.region, "target")
- if newreg:
- self.AdjustMap(newreg)
- def OnZoomMenuGCP(self, event):
- """Popup Zoom menu"""
- point = wx.GetMousePosition()
- zoommenu = Menu()
- # Add items to the menu
- zoomsource = wx.MenuItem(
- zoommenu, wx.ID_ANY, _("Adjust source display to target display")
- )
- zoommenu.AppendItem(zoomsource)
- self.Bind(wx.EVT_MENU, self.OnZoomToTarget, zoomsource)
- zoomtarget = wx.MenuItem(
- zoommenu, wx.ID_ANY, _("Adjust target display to source display")
- )
- zoommenu.AppendItem(zoomtarget)
- self.Bind(wx.EVT_MENU, self.OnZoomToSource, zoomtarget)
- # Popup the menu. If an item is selected then its handler
- # will be called before PopupMenu returns.
- self.PopupMenu(zoommenu)
- zoommenu.Destroy()
- def OnSize(self, event):
- """Adjust Map Windows after GCP Map Display has been resized"""
- # re-render image on idle
- self.resize = grass.clock()
- super(MapPanel, self).OnSize(event)
- def OnIdle(self, event):
- """GCP Map Display resized, adjust Map Windows"""
- if self.GetMapToolbar():
- if self.resize and self.resize + 0.2 < grass.clock():
- srcwidth, srcheight = self.SrcMapWindow.GetSize()
- tgtwidth, tgtheight = self.TgtMapWindow.GetSize()
- srcwidth = (srcwidth + tgtwidth) / 2
- if self.show_target:
- self._mgr.GetPane("target").Hide()
- self._mgr.Update()
- self._mgr.GetPane("source").BestSize((srcwidth, srcheight))
- self._mgr.GetPane("target").BestSize((srcwidth, tgtheight))
- if self.show_target:
- self._mgr.GetPane("target").Show()
- self._mgr.Update()
- self.resize = False
- elif self.resize:
- event.RequestMore()
- pass
- class GCPDisplay(FrameMixin, GCPPanel):
- """Map display for wrapping map panel with frame methods"""
- def __init__(self, parent, giface, grwiz, id, lmgr, Map, title, **kwargs):
- # init map panel
- GCPPanel.__init__(
- self,
- parent=parent,
- giface=giface,
- grwiz=grwiz,
- id=id,
- lmgr=lmgr,
- Map=Map,
- title=title,
- **kwargs,
- )
- # set system icon
- parent.SetIcon(
- wx.Icon(
- os.path.join(globalvar.ICONDIR, "grass_map.ico"), wx.BITMAP_TYPE_ICO
- )
- )
- # bind to frame
- parent.Bind(wx.EVT_CLOSE, self.OnQuit)
- # extend shortcuts and create frame accelerator table
- self.shortcuts_table.append((self.OnFullScreen, wx.ACCEL_NORMAL, wx.WXK_F11))
- self._initShortcuts()
- # add Map Display panel to Map Display frame
- sizer = wx.BoxSizer(wx.VERTICAL)
- sizer.Add(self, proportion=1, flag=wx.EXPAND)
- parent.SetSizer(sizer)
- parent.Layout()
- class GCPList(ListCtrl, CheckListCtrlMixin, ListCtrlAutoWidthMixin):
- def __init__(
- self,
- parent,
- gcp,
- id=wx.ID_ANY,
- pos=wx.DefaultPosition,
- size=wx.DefaultSize,
- style=wx.LC_REPORT | wx.SUNKEN_BORDER | wx.LC_HRULES | wx.LC_SINGLE_SEL,
- ):
- ListCtrl.__init__(self, parent, id, pos, size, style)
- self.gcp = gcp # GCP class
- self.render = True
- # Mixin settings
- CheckListCtrlMixin.__init__(self)
- ListCtrlAutoWidthMixin.__init__(self)
- # TextEditMixin.__init__(self)
- # tracks whether list items are checked or not
- self.CheckList = []
- self._Create()
- self.Bind(wx.EVT_LIST_ITEM_SELECTED, self.OnItemSelected)
- self.Bind(wx.EVT_LIST_ITEM_ACTIVATED, self.OnItemActivated)
- self.Bind(wx.EVT_LIST_COL_CLICK, self.OnColClick)
- self.selected = wx.NOT_FOUND
- self.selectedkey = -1
- def _Create(self):
- if 0:
- # normal, simple columns
- idx_col = 0
- for col in (
- _("use"),
- _("source E"),
- _("source N"),
- _("target E"),
- _("target N"),
- _("Forward error"),
- _("Backward error"),
- ):
- self.InsertColumn(idx_col, col)
- idx_col += 1
- else:
- # the hard way: we want images on the column header
- info = wx.ListItem()
- info.SetMask(wx.LIST_MASK_TEXT | wx.LIST_MASK_IMAGE | wx.LIST_MASK_FORMAT)
- info.SetImage(-1)
- info.m_format = wx.LIST_FORMAT_LEFT
- idx_col = 0
- for lbl in (
- _("use"),
- _("source E"),
- _("source N"),
- _("target E"),
- _("target N"),
- _("Forward error"),
- _("Backward error"),
- ):
- info.SetText(lbl)
- self.InsertColumn(idx_col, info)
- idx_col += 1
- def LoadData(self):
- """Load data into list"""
- self.DeleteAllItems()
- self.render = False
- if os.path.isfile(self.gcp.file["points"]):
- self.gcp.ReadGCPs()
- else:
- # 3 gcp is minimum
- for i in range(3):
- self.gcp.AddGCP(None)
- # select first point by default
- self.selected = 0
- self.selectedkey = self.GetItemData(self.selected)
- self.SetItemState(self.selected, wx.LIST_STATE_SELECTED, wx.LIST_STATE_SELECTED)
- self.ResizeColumns()
- self.render = True
- self.EnsureVisible(self.selected)
- def OnCheckItem(self, index, flag):
- """Item is checked/unchecked"""
- if self.render:
- # redraw points
- sourceMapWin = self.gcp.SrcMapWindow
- sourceMapWin.UpdateMap(render=False, renderVector=False)
- if self.gcp.show_target:
- targetMapWin = self.gcp.TgtMapWindow
- targetMapWin.UpdateMap(render=False, renderVector=False)
- def AddGCPItem(self):
- """
- Appends an item to GCP list
- """
- self.selectedkey = self.GetItemCount() + 1
- self.Append(
- [
- str(self.selectedkey), # GCP number
- "0.0", # source E
- "0.0", # source N
- "0.0", # target E
- "0.0", # target N
- "", # forward error
- "",
- ]
- ) # backward error
- self.selected = self.GetItemCount() - 1
- self.SetItemData(self.selected, self.selectedkey)
- self.SetItemState(self.selected, wx.LIST_STATE_SELECTED, wx.LIST_STATE_SELECTED)
- self.ResizeColumns()
- self.gcp.pointsToDrawSrc.AddItem(coords=[0, 0], label=str(self.selectedkey))
- self.gcp.pointsToDrawTgt.AddItem(coords=[0, 0], label=str(self.selectedkey))
- self.EnsureVisible(self.selected)
- return self.selected
- def DeleteGCPItem(self):
- """Deletes selected item in GCP list."""
- if self.selected == wx.NOT_FOUND:
- return
- key = self.GetItemData(self.selected)
- self.DeleteItem(self.selected)
- if self.selected != wx.NOT_FOUND:
- item = self.gcp.pointsToDrawSrc.GetItem(key - 1)
- self.gcp.pointsToDrawSrc.DeleteItem(item)
- item = self.gcp.pointsToDrawTgt.GetItem(key - 1)
- self.gcp.pointsToDrawTgt.DeleteItem(item)
- return key
- def ResizeColumns(self):
- """Resize columns"""
- minWidth = [90, 120]
- for i in range(self.GetColumnCount()):
- self.SetColumnWidth(i, wx.LIST_AUTOSIZE)
- # first column is checkbox, don't set to minWidth
- if i > 0 and self.GetColumnWidth(i) < minWidth[i > 4]:
- self.SetColumnWidth(i, minWidth[i > 4])
- self.SendSizeEvent()
- def GetSelected(self):
- """Get index of selected item"""
- return self.selected
- def OnItemSelected(self, event):
- """Item selected"""
- if self.render and self.selected != event.GetIndex():
- self.selected = event.GetIndex()
- self.selectedkey = self.GetItemData(self.selected)
- sourceMapWin = self.gcp.SrcMapWindow
- sourceMapWin.UpdateMap(render=False, renderVector=False)
- if self.gcp.show_target:
- targetMapWin = self.gcp.TgtMapWindow
- targetMapWin.UpdateMap(render=False, renderVector=False)
- event.Skip()
- def OnItemActivated(self, event):
- """
- When item double clicked, open editor to update coordinate values
- """
- coords = []
- index = event.GetIndex()
- key = self.GetItemData(index)
- changed = False
- for i in range(1, 5):
- coords.append(self.GetItem(index, i).GetText())
- dlg = EditGCP(parent=self, id=wx.ID_ANY, data=coords, gcpno=key)
- if dlg.ShowModal() == wx.ID_OK:
- values = dlg.GetValues() # string
- if len(values) == 0:
- GError(
- parent=self,
- message=_("Invalid coordinate value. Operation canceled."),
- )
- else:
- for i in range(len(values)):
- if values[i] != coords[i]:
- self.SetItem(index, i + 1, values[i])
- changed = True
- if changed:
- # reset RMS and update mapcoordlist
- self.SetItem(index, 5, "")
- self.SetItem(index, 6, "")
- key = self.GetItemData(index)
- self.gcp.mapcoordlist[key] = [
- key,
- float(values[0]),
- float(values[1]),
- float(values[2]),
- float(values[3]),
- 0.0,
- 0.0,
- ]
- self.gcp.pointsToDrawSrc.GetItem(key - 1).SetCoords(
- [float(values[0]), float(values[1])]
- )
- self.gcp.pointsToDrawTgt.GetItem(key - 1).SetCoords(
- [float(values[2]), float(values[3])]
- )
- self.gcp.UpdateColours()
- def OnColClick(self, event):
- """ListCtrl forgets selected item..."""
- self.selected = self.FindItem(-1, self.selectedkey)
- self.SetItemState(self.selected, wx.LIST_STATE_SELECTED, wx.LIST_STATE_SELECTED)
- event.Skip()
- class VectGroup(wx.Dialog):
- """Dialog to create a vector group (VREF file) for georectifying
- .. todo::
- Replace by g.group
- """
- def __init__(
- self,
- parent,
- id,
- grassdb,
- location,
- mapset,
- group,
- style=wx.DEFAULT_DIALOG_STYLE,
- ):
- wx.Dialog.__init__(
- self, parent, id, style=style, title=_("Create vector map group")
- )
- self.grassdatabase = grassdb
- self.xylocation = location
- self.xymapset = mapset
- self.xygroup = group
- #
- # get list of valid vector directories
- #
- vectlist = os.listdir(
- os.path.join(self.grassdatabase, self.xylocation, self.xymapset, "vector")
- )
- for dir in vectlist:
- if not os.path.isfile(
- os.path.join(
- self.grassdatabase,
- self.xylocation,
- self.xymapset,
- "vector",
- dir,
- "coor",
- )
- ):
- vectlist.remove(dir)
- utils.ListSortLower(vectlist)
- # path to vref file
- self.vgrpfile = os.path.join(
- self.grassdatabase,
- self.xylocation,
- self.xymapset,
- "group",
- self.xygroup,
- "VREF",
- )
- #
- # buttons
- #
- self.btnCancel = Button(parent=self, id=wx.ID_CANCEL)
- self.btnOK = Button(parent=self, id=wx.ID_OK)
- self.btnOK.SetDefault()
- #
- # list of vector maps
- #
- self.listMap = CheckListBox(parent=self, id=wx.ID_ANY, choices=vectlist)
- if os.path.isfile(self.vgrpfile):
- f = open(self.vgrpfile)
- try:
- checked = []
- for line in f.readlines():
- line = line.replace("\n", "")
- if len(line) < 1:
- continue
- checked.append(line.split("@")[0])
- self.listMap.SetCheckedStrings(checked)
- finally:
- f.close()
- line = wx.StaticLine(
- parent=self, id=wx.ID_ANY, size=(20, -1), style=wx.LI_HORIZONTAL
- )
- #
- # layout
- #
- sizer = wx.BoxSizer(wx.VERTICAL)
- box = wx.BoxSizer(wx.HORIZONTAL)
- box.Add(
- StaticText(
- parent=self,
- id=wx.ID_ANY,
- label=_("Select vector map(s) to add to group:"),
- ),
- flag=wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT | wx.LEFT,
- border=5,
- )
- box.Add(
- self.listMap,
- flag=wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT | wx.LEFT,
- border=5,
- )
- sizer.Add(box, flag=wx.ALIGN_RIGHT | wx.ALL, border=3)
- sizer.Add(
- line,
- proportion=0,
- flag=wx.GROW | wx.ALIGN_CENTER_VERTICAL | wx.LEFT | wx.RIGHT,
- border=5,
- )
- # buttons
- btnSizer = wx.StdDialogButtonSizer()
- btnSizer.AddButton(self.btnCancel)
- btnSizer.AddButton(self.btnOK)
- btnSizer.Realize()
- sizer.Add(
- btnSizer, proportion=0, flag=wx.EXPAND | wx.ALL | wx.ALIGN_CENTER, border=5
- )
- self.SetSizer(sizer)
- sizer.Fit(self)
- self.Layout()
- def MakeVGroup(self):
- """Create VREF file"""
- vgrouplist = []
- for item in range(self.listMap.GetCount()):
- if not self.listMap.IsChecked(item):
- continue
- vgrouplist.append(self.listMap.GetString(item) + "@" + self.xymapset)
- dirname = os.path.dirname(self.vgrpfile)
- if not os.path.exists(dirname):
- os.makedirs(dirname)
- f = open(self.vgrpfile, mode="w")
- try:
- for vect in vgrouplist:
- f.write(vect + "\n")
- finally:
- f.close()
- class EditGCP(wx.Dialog):
- def __init__(
- self,
- parent,
- data,
- gcpno,
- id=wx.ID_ANY,
- title=_("Edit GCP"),
- style=wx.DEFAULT_DIALOG_STYLE,
- ):
- """Dialog for editing GPC and map coordinates in list control"""
- wx.Dialog.__init__(self, parent, id, title=title, style=style)
- panel = wx.Panel(parent=self)
- sizer = wx.BoxSizer(wx.VERTICAL)
- box = StaticBox(
- parent=panel,
- id=wx.ID_ANY,
- label=" %s %s " % (_("Ground Control Point No."), str(gcpno)),
- )
- boxSizer = wx.StaticBoxSizer(box, wx.VERTICAL)
- # source coordinates
- gridSizer = wx.GridBagSizer(vgap=5, hgap=5)
- self.xcoord = TextCtrl(parent=panel, id=wx.ID_ANY, size=(150, -1))
- self.ycoord = TextCtrl(parent=panel, id=wx.ID_ANY, size=(150, -1))
- self.ecoord = TextCtrl(parent=panel, id=wx.ID_ANY, size=(150, -1))
- self.ncoord = TextCtrl(parent=panel, id=wx.ID_ANY, size=(150, -1))
- # swap source N, target E
- tmp_coord = data[1]
- data[1] = data[2]
- data[2] = tmp_coord
- row = 0
- col = 0
- idx = 0
- for label, win in (
- (_("source E:"), self.xcoord),
- (_("target E:"), self.ecoord),
- (_("source N:"), self.ycoord),
- (_("target N:"), self.ncoord),
- ):
- label = StaticText(parent=panel, id=wx.ID_ANY, label=label)
- gridSizer.Add(label, flag=wx.ALIGN_CENTER_VERTICAL, pos=(row, col))
- col += 1
- win.SetValue(str(data[idx]))
- gridSizer.Add(win, pos=(row, col))
- col += 1
- idx += 1
- if col > 3:
- row += 1
- col = 0
- boxSizer.Add(gridSizer, proportion=1, flag=wx.EXPAND | wx.ALL, border=5)
- sizer.Add(boxSizer, proportion=1, flag=wx.EXPAND | wx.ALL, border=5)
- #
- # buttons
- #
- self.btnCancel = Button(panel, wx.ID_CANCEL)
- self.btnOk = Button(panel, wx.ID_OK)
- self.btnOk.SetDefault()
- btnSizer = wx.StdDialogButtonSizer()
- btnSizer.AddButton(self.btnCancel)
- btnSizer.AddButton(self.btnOk)
- btnSizer.Realize()
- sizer.Add(btnSizer, proportion=0, flag=wx.ALIGN_RIGHT | wx.ALL, border=5)
- panel.SetSizer(sizer)
- sizer.Fit(self)
- def GetValues(self, columns=None):
- """Return list of values (as strings)."""
- valuelist = []
- try:
- float(self.xcoord.GetValue())
- float(self.ycoord.GetValue())
- float(self.ecoord.GetValue())
- float(self.ncoord.GetValue())
- except ValueError:
- return valuelist
- valuelist.append(self.xcoord.GetValue())
- valuelist.append(self.ycoord.GetValue())
- valuelist.append(self.ecoord.GetValue())
- valuelist.append(self.ncoord.GetValue())
- return valuelist
- class GrSettingsDialog(wx.Dialog):
- def __init__(
- self,
- parent,
- id,
- giface,
- title,
- pos=wx.DefaultPosition,
- size=wx.DefaultSize,
- style=wx.DEFAULT_DIALOG_STYLE,
- ):
- wx.Dialog.__init__(self, parent, id, title, pos, size, style)
- """
- Dialog to set profile text options: font, title
- and font size, axis labels and font size
- """
- #
- # initialize variables
- #
- self.parent = parent
- self.new_src_map = src_map
- self.new_tgt_map = {"raster": tgt_map["raster"], "vector": tgt_map["vector"]}
- self.sdfactor = 0
- self.symbol = {}
- self.methods = [
- "nearest",
- "linear",
- "linear_f",
- "cubic",
- "cubic_f",
- "lanczos",
- "lanczos_f",
- ]
- # notebook
- notebook = wx.Notebook(parent=self, id=wx.ID_ANY, style=wx.BK_DEFAULT)
- self.__CreateSymbologyPage(notebook)
- self.__CreateRectificationPage(notebook)
- # buttons
- btnSave = Button(self, wx.ID_SAVE)
- btnApply = Button(self, wx.ID_APPLY)
- btnClose = Button(self, wx.ID_CLOSE)
- btnApply.SetDefault()
- # bindings
- btnApply.Bind(wx.EVT_BUTTON, self.OnApply)
- btnApply.SetToolTip(_("Apply changes for the current session"))
- btnSave.Bind(wx.EVT_BUTTON, self.OnSave)
- btnSave.SetToolTip(
- _(
- "Apply and save changes to user settings file (default for next sessions)"
- )
- )
- btnClose.Bind(wx.EVT_BUTTON, self.OnClose)
- btnClose.SetToolTip(_("Close dialog"))
- # sizers
- btnSizer = wx.BoxSizer(wx.HORIZONTAL)
- btnSizer.Add(btnApply, flag=wx.LEFT | wx.RIGHT, border=5)
- btnSizer.Add(btnSave, flag=wx.LEFT | wx.RIGHT, border=5)
- btnSizer.Add(btnClose, flag=wx.LEFT | wx.RIGHT, border=5)
- # sizers
- mainSizer = wx.BoxSizer(wx.VERTICAL)
- mainSizer.Add(notebook, proportion=1, flag=wx.EXPAND | wx.ALL, border=5)
- mainSizer.Add(btnSizer, proportion=0, flag=wx.ALIGN_RIGHT | wx.ALL, border=5)
- # flag=wx.EXPAND | wx.ALL | wx.ALIGN_CENTER, border=5)
- self.SetSizer(mainSizer)
- mainSizer.Fit(self)
- def __CreateSymbologyPage(self, notebook):
- """Create notebook page with symbology settings"""
- panel = wx.Panel(parent=notebook, id=wx.ID_ANY)
- notebook.AddPage(page=panel, text=_("Symbology"))
- sizer = wx.BoxSizer(wx.VERTICAL)
- rmsgridSizer = wx.GridBagSizer(vgap=5, hgap=5)
- # highlight only highest forward RMS error
- self.highlighthighest = wx.CheckBox(
- parent=panel, id=wx.ID_ANY, label=_("Highlight highest RMS error only")
- )
- hh = UserSettings.Get(group="gcpman", key="rms", subkey="highestonly")
- self.highlighthighest.SetValue(hh)
- rmsgridSizer.Add(
- self.highlighthighest, flag=wx.ALIGN_CENTER_VERTICAL, pos=(0, 0)
- )
- # RMS forward error threshold
- rmslabel = StaticText(
- parent=panel,
- id=wx.ID_ANY,
- label=_("Highlight RMS error > M + SD * factor:"),
- )
- rmslabel.SetToolTip(
- _(
- "Highlight GCPs with an RMS error larger than \n"
- "mean + standard deviation * given factor. \n"
- "Recommended values for this factor are between 1 and 2."
- )
- )
- rmsgridSizer.Add(rmslabel, flag=wx.ALIGN_CENTER_VERTICAL, pos=(1, 0))
- sdfactor = UserSettings.Get(group="gcpman", key="rms", subkey="sdfactor")
- self.rmsWin = TextCtrl(
- parent=panel, id=wx.ID_ANY, size=(70, -1), style=wx.TE_NOHIDESEL
- )
- self.rmsWin.SetValue("%s" % str(sdfactor))
- if self.parent.highest_only:
- self.rmsWin.Disable()
- self.symbol["sdfactor"] = self.rmsWin.GetId()
- rmsgridSizer.Add(self.rmsWin, flag=wx.ALIGN_RIGHT, pos=(1, 1))
- rmsgridSizer.AddGrowableCol(1)
- sizer.Add(rmsgridSizer, flag=wx.EXPAND | wx.ALL, border=5)
- box = StaticBox(parent=panel, id=wx.ID_ANY, label=" %s " % _("Symbol settings"))
- boxSizer = wx.StaticBoxSizer(box, wx.VERTICAL)
- gridSizer = wx.GridBagSizer(vgap=5, hgap=5)
- #
- # general symbol color
- #
- row = 0
- label = StaticText(parent=panel, id=wx.ID_ANY, label=_("Color:"))
- gridSizer.Add(label, flag=wx.ALIGN_CENTER_VERTICAL, pos=(row, 0))
- col = UserSettings.Get(group="gcpman", key="symbol", subkey="color")
- colWin = csel.ColourSelect(
- parent=panel, id=wx.ID_ANY, colour=wx.Colour(col[0], col[1], col[2], 255)
- )
- self.symbol["color"] = colWin.GetId()
- gridSizer.Add(colWin, flag=wx.ALIGN_RIGHT, pos=(row, 1))
- #
- # symbol color for high forward RMS error
- #
- row += 1
- label = StaticText(
- parent=panel, id=wx.ID_ANY, label=_("Color for high RMS error:")
- )
- gridSizer.Add(label, flag=wx.ALIGN_CENTER_VERTICAL, pos=(row, 0))
- hcol = UserSettings.Get(group="gcpman", key="symbol", subkey="hcolor")
- hcolWin = csel.ColourSelect(
- parent=panel, id=wx.ID_ANY, colour=wx.Colour(hcol[0], hcol[1], hcol[2], 255)
- )
- self.symbol["hcolor"] = hcolWin.GetId()
- gridSizer.Add(hcolWin, flag=wx.ALIGN_RIGHT, pos=(row, 1))
- #
- # symbol color for selected GCP
- #
- row += 1
- label = StaticText(
- parent=panel, id=wx.ID_ANY, label=_("Color for selected GCP:")
- )
- gridSizer.Add(label, flag=wx.ALIGN_CENTER_VERTICAL, pos=(row, 0))
- scol = UserSettings.Get(group="gcpman", key="symbol", subkey="scolor")
- scolWin = csel.ColourSelect(
- parent=panel, id=wx.ID_ANY, colour=wx.Colour(scol[0], scol[1], scol[2], 255)
- )
- self.symbol["scolor"] = scolWin.GetId()
- gridSizer.Add(scolWin, flag=wx.ALIGN_RIGHT, pos=(row, 1))
- #
- # symbol color for unused GCP
- #
- row += 1
- label = StaticText(
- parent=panel, id=wx.ID_ANY, label=_("Color for unused GCPs:")
- )
- gridSizer.Add(label, flag=wx.ALIGN_CENTER_VERTICAL, pos=(row, 0))
- ucol = UserSettings.Get(group="gcpman", key="symbol", subkey="ucolor")
- ucolWin = csel.ColourSelect(
- parent=panel, id=wx.ID_ANY, colour=wx.Colour(ucol[0], ucol[1], ucol[2], 255)
- )
- self.symbol["ucolor"] = ucolWin.GetId()
- gridSizer.Add(ucolWin, flag=wx.ALIGN_RIGHT, pos=(row, 1))
- # show unused GCPs
- row += 1
- self.showunused = wx.CheckBox(
- parent=panel, id=wx.ID_ANY, label=_("Show unused GCPs")
- )
- shuu = UserSettings.Get(group="gcpman", key="symbol", subkey="unused")
- self.showunused.SetValue(shuu)
- gridSizer.Add(self.showunused, flag=wx.ALIGN_CENTER_VERTICAL, pos=(row, 0))
- #
- # symbol size
- #
- row += 1
- label = StaticText(parent=panel, id=wx.ID_ANY, label=_("Symbol size:"))
- gridSizer.Add(label, flag=wx.ALIGN_CENTER_VERTICAL, pos=(row, 0))
- symsize = int(UserSettings.Get(group="gcpman", key="symbol", subkey="size"))
- sizeWin = SpinCtrl(parent=panel, id=wx.ID_ANY, min=1, max=20)
- sizeWin.SetValue(symsize)
- self.symbol["size"] = sizeWin.GetId()
- gridSizer.Add(sizeWin, flag=wx.ALIGN_RIGHT, pos=(row, 1))
- #
- # symbol width
- #
- row += 1
- label = StaticText(parent=panel, id=wx.ID_ANY, label=_("Line width:"))
- gridSizer.Add(label, flag=wx.ALIGN_CENTER_VERTICAL, pos=(row, 0))
- width = int(UserSettings.Get(group="gcpman", key="symbol", subkey="width"))
- widWin = SpinCtrl(parent=panel, id=wx.ID_ANY, min=1, max=10)
- widWin.SetValue(width)
- self.symbol["width"] = widWin.GetId()
- gridSizer.Add(widWin, flag=wx.ALIGN_RIGHT, pos=(row, 1))
- gridSizer.AddGrowableCol(1)
- boxSizer.Add(gridSizer, flag=wx.EXPAND)
- sizer.Add(boxSizer, flag=wx.EXPAND | wx.ALL, border=5)
- #
- # maps to display
- #
- # source map to display
- self.srcselection = Select(
- panel,
- id=wx.ID_ANY,
- size=globalvar.DIALOG_GSELECT_SIZE,
- type="maptype",
- updateOnPopup=False,
- )
- self.parent.grwiz.SwitchEnv("source")
- self.srcselection.SetElementList(maptype)
- # filter out all maps not in group
- self.srcselection.tcp.GetElementList(elements=self.parent.src_maps)
- # target map(s) to display
- self.parent.grwiz.SwitchEnv("target")
- self.tgtrastselection = Select(
- panel,
- id=wx.ID_ANY,
- size=globalvar.DIALOG_GSELECT_SIZE,
- type="raster",
- updateOnPopup=False,
- extraItems=self.parent.grwiz.mappage.GetSelectTargetRasterExtraItems(),
- )
- self.tgtrastselection.SetElementList("cell")
- self.tgtrastselection.GetElementList()
- self.tgtvectselection = Select(
- panel,
- id=wx.ID_ANY,
- size=globalvar.DIALOG_GSELECT_SIZE,
- type="vector",
- updateOnPopup=False,
- )
- self.tgtvectselection.SetElementList("vector")
- self.tgtvectselection.GetElementList()
- sizer.Add(
- StaticText(
- parent=panel, id=wx.ID_ANY, label=_("Select source map to display:")
- ),
- proportion=0,
- flag=wx.ALIGN_LEFT | wx.ALL,
- border=5,
- )
- sizer.Add(
- self.srcselection, proportion=0, flag=wx.ALIGN_LEFT | wx.ALL, border=5
- )
- self.srcselection.SetValue(src_map)
- sizer.Add(
- StaticText(
- parent=panel,
- id=wx.ID_ANY,
- label=_("Select target raster map to display:"),
- ),
- proportion=0,
- flag=wx.ALIGN_LEFT | wx.ALL,
- border=5,
- )
- sizer.Add(
- self.tgtrastselection, proportion=0, flag=wx.ALIGN_LEFT | wx.ALL, border=5
- )
- self.tgtrastselection.SetValue(tgt_map["raster"])
- sizer.Add(
- StaticText(
- parent=panel,
- id=wx.ID_ANY,
- label=_("Select target vector map to display:"),
- ),
- proportion=0,
- flag=wx.ALIGN_LEFT | wx.ALL,
- border=5,
- )
- sizer.Add(
- self.tgtvectselection, proportion=0, flag=wx.ALIGN_LEFT | wx.ALL, border=5
- )
- self.tgtvectselection.SetValue(tgt_map["vector"])
- # bindings
- self.highlighthighest.Bind(wx.EVT_CHECKBOX, self.OnHighlight)
- self.rmsWin.Bind(wx.EVT_TEXT, self.OnSDFactor)
- self.srcselection.Bind(wx.EVT_TEXT, self.OnSrcSelection)
- self.tgtrastselection.Bind(wx.EVT_TEXT, self.OnTgtRastSelection)
- self.tgtvectselection.Bind(wx.EVT_TEXT, self.OnTgtVectSelection)
- panel.SetSizer(sizer)
- return panel
- def __CreateRectificationPage(self, notebook):
- """Create notebook page with symbology settings"""
- panel = wx.Panel(parent=notebook, id=wx.ID_ANY)
- notebook.AddPage(page=panel, text=_("Rectification"))
- sizer = wx.BoxSizer(wx.VERTICAL)
- # transformation order
- self.rb_grorder = wx.RadioBox(
- parent=panel,
- id=wx.ID_ANY,
- label=" %s " % _("Select rectification order"),
- choices=[_("1st order"), _("2nd order"), _("3rd order")],
- majorDimension=wx.RA_SPECIFY_COLS,
- )
- sizer.Add(self.rb_grorder, proportion=0, flag=wx.EXPAND | wx.ALL, border=5)
- self.rb_grorder.SetSelection(self.parent.gr_order - 1)
- # interpolation method
- gridSizer = wx.GridBagSizer(vgap=5, hgap=5)
- gridSizer.Add(
- StaticText(
- parent=panel, id=wx.ID_ANY, label=_("Select interpolation method:")
- ),
- pos=(0, 0),
- flag=wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL | wx.ALL,
- border=5,
- )
- self.grmethod = wx.Choice(parent=panel, id=wx.ID_ANY, choices=self.methods)
- gridSizer.Add(self.grmethod, pos=(0, 1), flag=wx.ALIGN_RIGHT, border=5)
- self.grmethod.SetStringSelection(self.parent.gr_method)
- gridSizer.AddGrowableCol(1)
- sizer.Add(gridSizer, flag=wx.EXPAND | wx.ALL, border=5)
- # clip to region
- self.check = wx.CheckBox(
- parent=panel,
- id=wx.ID_ANY,
- label=_("clip to computational region in target location"),
- )
- sizer.Add(self.check, proportion=0, flag=wx.EXPAND | wx.ALL, border=5)
- self.check.SetValue(self.parent.clip_to_region)
- # overwrite result map
- overwrite = UserSettings.Get(group="gcpman", key="map", subkey="overwrite")
- self.overwrite = wx.CheckBox(
- parent=panel, id=wx.ID_ANY, label=_("overwrite result map")
- )
- self.Bind(wx.EVT_CHECKBOX, self.OnOverwrite, self.overwrite)
- sizer.Add(self.overwrite, proportion=0, flag=wx.EXPAND | wx.ALL, border=5)
- self.overwrite.SetValue(overwrite)
- self.parent.overwrite = overwrite
- # extension
- sizer.Add(
- StaticText(
- parent=panel, id=wx.ID_ANY, label=_("Extension for output maps:")
- ),
- proportion=0,
- flag=wx.ALIGN_LEFT | wx.ALL,
- border=5,
- )
- self.ext_txt = TextCtrl(parent=panel, id=wx.ID_ANY, value="", size=(350, -1))
- self.ext_txt.SetValue(self.parent.extension)
- sizer.Add(self.ext_txt, proportion=0, flag=wx.ALIGN_LEFT | wx.ALL, border=5)
- # bindings
- self.ext_txt.Bind(wx.EVT_TEXT, self.OnExtension)
- self.Bind(wx.EVT_RADIOBOX, self.parent.OnGROrder, self.rb_grorder)
- self.Bind(wx.EVT_CHOICE, self.OnMethod, self.grmethod)
- self.Bind(wx.EVT_CHECKBOX, self.OnClipRegion, self.check)
- panel.SetSizer(sizer)
- return panel
- def OnHighlight(self, event):
- """Checkbox 'highlighthighest' checked/unchecked"""
- if self.highlighthighest.IsChecked():
- self.parent.highest_only = True
- self.rmsWin.Disable()
- else:
- self.parent.highest_only = False
- self.rmsWin.Enable()
- def OnSDFactor(self, event):
- """New factor for RMS threshold = M + SD * factor"""
- try:
- self.sdfactor = float(self.rmsWin.GetValue())
- except ValueError:
- return
- if self.sdfactor <= 0:
- GError(parent=self, message=_("RMS threshold factor must be > 0"))
- elif self.sdfactor < 1:
- GError(
- parent=self,
- message=_(
- "RMS threshold factor is < 1\n"
- "Too many points might be highlighted"
- ),
- )
- def OnSrcSelection(self, event):
- """Source map to display selected"""
- global src_map
- tmp_map = self.srcselection.GetValue()
- if not tmp_map == "" and not tmp_map == src_map:
- self.new_src_map = tmp_map
- def OnTgtRastSelection(self, event):
- """Target map to display selected"""
- global tgt_map
- self.new_tgt_map["raster"] = self.tgtrastselection.GetValue()
- def OnTgtVectSelection(self, event):
- """Target map to display selected"""
- global tgt_map
- self.new_tgt_map["vector"] = self.tgtvectselection.GetValue()
- def OnMethod(self, event):
- self.parent.gr_method = self.methods[event.GetSelection()]
- def OnClipRegion(self, event):
- self.parent.clip_to_region = event.IsChecked()
- def OnOverwrite(self, event):
- self.parent.overwrite = event.IsChecked()
- def OnExtension(self, event):
- self.parent.extension = self.ext_txt.GetValue()
- def UpdateSettings(self):
- global src_map
- global tgt_map
- global maptype
- layers = None
- UserSettings.Set(
- group="gcpman",
- key="rms",
- subkey="highestonly",
- value=self.highlighthighest.GetValue(),
- )
- if self.sdfactor > 0:
- UserSettings.Set(
- group="gcpman", key="rms", subkey="sdfactor", value=self.sdfactor
- )
- self.parent.sdfactor = self.sdfactor
- if self.parent.rmsthresh > 0:
- self.parent.rmsthresh = (
- self.parent.rmsmean + self.parent.sdfactor * self.parent.rmssd
- )
- UserSettings.Set(
- group="gcpman",
- key="symbol",
- subkey="color",
- value=tuple(wx.FindWindowById(self.symbol["color"]).GetColour()),
- )
- UserSettings.Set(
- group="gcpman",
- key="symbol",
- subkey="hcolor",
- value=tuple(wx.FindWindowById(self.symbol["hcolor"]).GetColour()),
- )
- UserSettings.Set(
- group="gcpman",
- key="symbol",
- subkey="scolor",
- value=tuple(wx.FindWindowById(self.symbol["scolor"]).GetColour()),
- )
- UserSettings.Set(
- group="gcpman",
- key="symbol",
- subkey="ucolor",
- value=tuple(wx.FindWindowById(self.symbol["ucolor"]).GetColour()),
- )
- UserSettings.Set(
- group="gcpman",
- key="symbol",
- subkey="unused",
- value=self.showunused.GetValue(),
- )
- UserSettings.Set(
- group="gcpman",
- key="symbol",
- subkey="size",
- value=wx.FindWindowById(self.symbol["size"]).GetValue(),
- )
- UserSettings.Set(
- group="gcpman",
- key="symbol",
- subkey="width",
- value=wx.FindWindowById(self.symbol["width"]).GetValue(),
- )
- UserSettings.Set(
- group="gcpman",
- key="map",
- subkey="overwrite",
- value=self.parent.overwrite,
- )
- srcrender = False
- srcrenderVector = False
- tgtrender = False
- tgtrenderVector = False
- reload_target = False
- if self.new_src_map != src_map:
- # remove old layer
- layers = self.parent.grwiz.SrcMap.GetListOfLayers()
- self.parent.grwiz.SrcMap.DeleteLayer(layers[0])
- src_map = self.new_src_map
- if maptype == "raster":
- cmdlist = ["d.rast", "map=%s" % src_map]
- srcrender = True
- else:
- cmdlist = ["d.vect", "map=%s" % src_map]
- srcrenderVector = True
- self.parent.grwiz.SwitchEnv("source")
- name, found = utils.GetLayerNameFromCmd(cmdlist)
- self.parent.grwiz.SrcMap.AddLayer(
- ltype=maptype,
- command=cmdlist,
- active=True,
- name=name,
- hidden=False,
- opacity=1.0,
- render=False,
- )
- self.parent.grwiz.SwitchEnv("target")
- if (
- self.new_tgt_map["raster"] != tgt_map["raster"]
- or self.new_tgt_map["vector"] != tgt_map["vector"]
- ):
- # remove all layers
- layers = self.parent.grwiz.TgtMap.GetListOfLayers()
- while layers:
- self.parent.grwiz.TgtMap.DeleteLayer(layers[0])
- del layers[0]
- layers = self.parent.grwiz.TgtMap.GetListOfLayers()
- # self.parent.grwiz.TgtMap.DeleteAllLayers()
- reload_target = True
- tgt_map["raster"] = self.new_tgt_map["raster"]
- tgt_map["vector"] = self.new_tgt_map["vector"]
- web_service_layer = self.parent.grwiz.mappage.GetWebServiceLayers(
- name=tgt_map["raster"]
- )
- if tgt_map["raster"] != "" and web_service_layer:
- #
- # add web service layer to target map
- #
- rendertype = web_service_layer["type"]
- cmdlist = web_service_layer["cmd"]
- name = tgt_map["raster"]
- self.parent.grwiz.TgtMap.AddLayer(
- ltype=rendertype,
- command=cmdlist,
- active=True,
- name=name,
- hidden=False,
- opacity=1.0,
- render=False,
- )
- elif tgt_map["raster"] != "":
- cmdlist = ["d.rast", "map=%s" % tgt_map["raster"]]
- name, found = utils.GetLayerNameFromCmd(cmdlist)
- self.parent.grwiz.TgtMap.AddLayer(
- ltype="raster",
- command=cmdlist,
- active=True,
- name=name,
- hidden=False,
- opacity=1.0,
- render=False,
- )
- tgtrender = True
- if tgt_map["vector"] != "":
- cmdlist = ["d.vect", "map=%s" % tgt_map["vector"]]
- name, found = utils.GetLayerNameFromCmd(cmdlist)
- self.parent.grwiz.TgtMap.AddLayer(
- ltype="vector",
- command=cmdlist,
- active=True,
- name=name,
- hidden=False,
- opacity=1.0,
- render=False,
- )
- tgtrenderVector = True
- if tgt_map["raster"] == "" and tgt_map["vector"] == "":
- if self.parent.show_target:
- self.parent.show_target = False
- self.parent._mgr.GetPane("target").Hide()
- self.parent._mgr.Update()
- self.parent.activemap.SetSelection(0)
- self.parent.activemap.Enable(False)
- self.parent.GetMapToolbar().Enable("zoommenu", enable=False)
- else:
- if not self.parent.show_target:
- self.parent.show_target = True
- self.parent._mgr.GetPane("target").Show()
- self.parent._mgr.Update()
- self.parent.activemap.SetSelection(0)
- self.parent.activemap.Enable(True)
- self.parent.GetMapToolbar().Enable("zoommenu", enable=True)
- self.parent.TgtMapWindow.ZoomToMap(
- layers=self.parent.TgtMap.GetListOfLayers()
- )
- self.parent.UpdateColours(
- srcrender, srcrenderVector, tgtrender, tgtrenderVector
- )
- self.parent.SetSettings()
- def OnSave(self, event):
- """Button 'Save' pressed"""
- self.UpdateSettings()
- fileSettings = {}
- UserSettings.ReadSettingsFile(settings=fileSettings)
- fileSettings["gcpman"] = UserSettings.Get(group="gcpman")
- file = UserSettings.SaveToFile(fileSettings)
- self.parent._giface.WriteLog(
- _("GCP Manager settings saved to file '%s'.") % file
- )
- # self.Close()
- def OnApply(self, event):
- """Button 'Apply' pressed"""
- self.UpdateSettings()
- # self.Close()
- def OnClose(self, event):
- """Button 'Cancel' pressed"""
- self.Close()
|