g.gui.rdigit.py 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247
  1. #!/usr/bin/env python3
  2. ############################################################################
  3. #
  4. # MODULE: g.gui.rdigit
  5. # AUTHOR(S): Anna Petrasova <kratochanna gmail.com>,
  6. # Tomas Zigo <tomas.zigo slovanet.sk> (standalone module)
  7. # PURPOSE: wxGUI Raster Digitizer
  8. # COPYRIGHT: (C) 2014-2020 by Anna Petrasova, and the GRASS Development Team
  9. #
  10. # This program is free software; you can redistribute it and/or
  11. # modify it under the terms of the GNU General Public License as
  12. # published by the Free Software Foundation; either version 2 of the
  13. # License, or (at your option) any later version.
  14. #
  15. # This program is distributed in the hope that it will be useful, but
  16. # WITHOUT ANY WARRANTY; without even the implied warranty of
  17. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  18. # General Public License for more details.
  19. #
  20. ############################################################################
  21. # %module
  22. # % description: Interactive editing and digitizing of raster maps.
  23. # % keyword: general
  24. # % keyword: GUI
  25. # % keyword: raster
  26. # % keyword: editing
  27. # % keyword: digitizer
  28. # %end
  29. # %option G_OPT_R_OUTPUT
  30. # % key: create
  31. # % label: Name of new raster map to create
  32. # % required: no
  33. # % guisection: Create
  34. # %end
  35. # %option G_OPT_R_BASE
  36. # % required: no
  37. # % guisection: Create
  38. # %end
  39. # %option G_OPT_R_TYPE
  40. # % answer: CELL
  41. # % required: no
  42. # % guisection: Create
  43. # %end
  44. # %option G_OPT_R_INPUT
  45. # % key: edit
  46. # % required: no
  47. # % label: Name of existing raster map to edit
  48. # % guisection: Edit
  49. # %end
  50. # %rules
  51. # % exclusive: create, edit
  52. # % required: create, edit
  53. # % requires: base, create
  54. # %end
  55. import os
  56. import grass.script as gs
  57. def main():
  58. gs.set_raise_on_error(False)
  59. options, flags = gs.parser()
  60. # import wx only after running parser
  61. # to avoid issues with complex imports when only interface is needed
  62. import wx
  63. from grass.script.setup import set_gui_path
  64. set_gui_path()
  65. from core.render import Map
  66. from core.globalvar import ICONDIR
  67. from mapdisp.frame import MapPanel
  68. from gui_core.mapdisp import FrameMixin
  69. from mapdisp.main import DMonGrassInterface
  70. from core.settings import UserSettings
  71. # define classes which needs imports as local
  72. # for longer definitions, a separate file would be a better option
  73. class RDigitMapDisplay(FrameMixin, MapPanel):
  74. """Map display for wrapping map panel with r.digit mathods and frame methods"""
  75. def __init__(
  76. self,
  77. parent,
  78. new_map=None,
  79. base_map=None,
  80. edit_map=None,
  81. map_type=None,
  82. ):
  83. MapPanel.__init__(
  84. self, parent=parent, Map=Map(), giface=DMonGrassInterface(None)
  85. )
  86. # set system icon
  87. parent.SetIcon(
  88. wx.Icon(os.path.join(ICONDIR, "grass_map.ico"), wx.BITMAP_TYPE_ICO)
  89. )
  90. # bindings
  91. parent.Bind(wx.EVT_CLOSE, self.OnCloseWindow)
  92. # extend shortcuts and create frame accelerator table
  93. self.shortcuts_table.append(
  94. (self.OnFullScreen, wx.ACCEL_NORMAL, wx.WXK_F11)
  95. )
  96. self._initShortcuts()
  97. # this giface issue not solved yet, we must set mapframe afterwards
  98. self._giface._mapframe = self
  99. self._giface.mapCreated.connect(self.OnMapCreated)
  100. self._mapObj = self.GetMap()
  101. # load raster map
  102. self._addLayer(name=new_map if new_map else edit_map)
  103. # switch toolbar
  104. self.AddToolbar("rdigit", fixed=True)
  105. rdigit = self.toolbars["rdigit"]
  106. if new_map:
  107. rdigit._mapSelectionCombo.Unbind(wx.EVT_COMBOBOX)
  108. self.rdigit.SelectNewMap(
  109. standalone=True,
  110. mapName=new_map,
  111. bgMap=base_map,
  112. mapType=map_type,
  113. )
  114. rdigit._mapSelectionCombo.Bind(
  115. wx.EVT_COMBOBOX,
  116. rdigit.OnMapSelection,
  117. )
  118. else:
  119. rdigit._mapSelectionCombo.SetSelection(n=1)
  120. rdigit.OnMapSelection()
  121. # use Close instead of QuitRDigit for standalone tool
  122. self.rdigit.quitDigitizer.disconnect(self.QuitRDigit)
  123. self.rdigit.quitDigitizer.connect(lambda: self.Close())
  124. # add Map Display panel to Map Display frame
  125. sizer = wx.BoxSizer(wx.VERTICAL)
  126. sizer.Add(self, proportion=1, flag=wx.EXPAND)
  127. parent.SetSizer(sizer)
  128. parent.Layout()
  129. def _addLayer(self, name, ltype="raster"):
  130. """Add layer into map
  131. :param str name: map name
  132. :param str ltype: layer type
  133. """
  134. mapLayer = self._mapObj.AddLayer(
  135. ltype=ltype,
  136. name=name,
  137. command=["d.rast", "map={}".format(name)],
  138. active=True,
  139. hidden=False,
  140. opacity=1.0,
  141. render=True,
  142. )
  143. def OnMapCreated(self, name, ltype):
  144. """Add new created raster layer into map
  145. :param str name: map name
  146. :param str ltype: layer type
  147. """
  148. self._mapObj.Clean()
  149. self._addLayer(name=name, ltype=ltype)
  150. self.GetMapWindow().UpdateMap()
  151. kwargs = {
  152. "new_map": options["create"],
  153. "base_map": options["base"],
  154. "edit_map": options["edit"],
  155. "map_type": options["type"],
  156. }
  157. mapset = gs.gisenv()["MAPSET"]
  158. if kwargs["edit_map"]:
  159. edit_map = gs.find_file(
  160. name=kwargs["edit_map"],
  161. element="raster",
  162. mapset=mapset,
  163. )["fullname"]
  164. if not edit_map:
  165. gs.fatal(
  166. _(
  167. "Raster map <{}> not found in current mapset.".format(
  168. options["edit"],
  169. ),
  170. ),
  171. )
  172. else:
  173. kwargs["edit_map"] = edit_map
  174. else:
  175. if kwargs["base_map"]:
  176. base_map = gs.find_file(
  177. name=kwargs["base_map"],
  178. element="raster",
  179. mapset=mapset,
  180. )["fullname"]
  181. if not base_map:
  182. gs.fatal(
  183. _(
  184. "Base raster map <{}> not found in "
  185. "current mapset.".format(
  186. options["base"],
  187. ),
  188. ),
  189. )
  190. kwargs["base_map"] = base_map
  191. # allow immediate rendering
  192. driver = UserSettings.Get(
  193. group="display",
  194. key="driver",
  195. subkey="type",
  196. )
  197. if driver == "png":
  198. os.environ["GRASS_RENDER_IMMEDIATE"] = "png"
  199. else:
  200. os.environ["GRASS_RENDER_IMMEDIATE"] = "cairo"
  201. app = wx.App()
  202. frame = wx.Frame(
  203. None,
  204. id=wx.ID_ANY,
  205. size=(850, 600),
  206. style=wx.DEFAULT_FRAME_STYLE,
  207. title=_("Raster Digitizer - GRASS GIS"),
  208. )
  209. frame = RDigitMapDisplay(parent=frame, **kwargs)
  210. frame.Show()
  211. app.MainLoop()
  212. if __name__ == "__main__":
  213. main()