dialogs.py 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255
  1. """
  2. @package datacatalog.dialogs
  3. @brief Dialogs used in data catalog
  4. Classes:
  5. - dialogs::CatalogReprojectionDialog
  6. (C) 2017 by the GRASS Development Team
  7. This program is free software under the GNU General Public License
  8. (>=v2). Read the file COPYING that comes with GRASS for details.
  9. @author Anna Petrasova <kratochanna gmail.com>
  10. """
  11. import wx
  12. from gui_core.widgets import FloatValidator, IntegerValidator
  13. from core.giface import Notification
  14. from core.gcmd import RunCommand
  15. from gui_core.wrap import Button, StaticText, TextCtrl
  16. from grass.script import parse_key_val, region_env
  17. class CatalogReprojectionDialog(wx.Dialog):
  18. def __init__(
  19. self,
  20. parent,
  21. giface,
  22. inputGisdbase,
  23. inputLocation,
  24. inputMapset,
  25. inputLayer,
  26. inputEnv,
  27. outputGisdbase,
  28. outputLocation,
  29. outputMapset,
  30. outputLayer,
  31. etype,
  32. outputEnv,
  33. callback,
  34. id=wx.ID_ANY,
  35. title=_("Reprojection"),
  36. style=wx.DEFAULT_DIALOG_STYLE | wx.RESIZE_BORDER,
  37. ):
  38. self.parent = parent
  39. self._giface = giface
  40. wx.Dialog.__init__(
  41. self, parent, id, title, style=style, name="ReprojectionDialog"
  42. )
  43. self.panel = wx.Panel(parent=self)
  44. self.iGisdbase = inputGisdbase
  45. self.iLocation = inputLocation
  46. self.iMapset = inputMapset
  47. self.iLayer = inputLayer
  48. self.iEnv = inputEnv
  49. self.oGisdbase = outputGisdbase
  50. self.oLocation = outputLocation
  51. self.oMapset = outputMapset
  52. self.oLayer = outputLayer
  53. self.etype = etype
  54. self.oEnv = outputEnv
  55. self.callback = callback
  56. self._widgets()
  57. self._doLayout()
  58. if self.etype == "raster":
  59. self._estimateResampling()
  60. self._estimateResolution()
  61. def _widgets(self):
  62. if self.etype == "raster":
  63. self.resolution = TextCtrl(self.panel, validator=FloatValidator())
  64. self.resampling = wx.Choice(
  65. self.panel,
  66. size=(200, -1),
  67. choices=[
  68. "nearest",
  69. "bilinear",
  70. "bicubic",
  71. "lanczos",
  72. "bilinear_f",
  73. "bicubic_f",
  74. "lanczos_f",
  75. ],
  76. )
  77. else:
  78. self.vsplit = TextCtrl(self.panel, validator=IntegerValidator())
  79. self.vsplit.SetValue("10000")
  80. #
  81. # buttons
  82. #
  83. self.btn_close = Button(parent=self.panel, id=wx.ID_CLOSE)
  84. self.SetEscapeId(self.btn_close.GetId())
  85. # run
  86. self.btn_run = Button(parent=self.panel, id=wx.ID_OK, label=_("Reproject"))
  87. if self.etype == "raster":
  88. self.btn_run.SetToolTip(_("Reproject raster"))
  89. elif self.etype == "vector":
  90. self.btn_run.SetToolTip(_("Reproject vector"))
  91. self.btn_run.SetDefault()
  92. self.btn_run.Bind(wx.EVT_BUTTON, self.OnReproject)
  93. def _doLayout(self):
  94. """Do layout"""
  95. dialogSizer = wx.BoxSizer(wx.VERTICAL)
  96. optionsSizer = wx.GridBagSizer(5, 5)
  97. label = _(
  98. "Map layer <{ml}> needs to be reprojected.\n"
  99. "Please review and modify reprojection parameters:"
  100. ).format(ml=self.iLayer)
  101. dialogSizer.Add(
  102. StaticText(self.panel, label=label), flag=wx.ALL | wx.EXPAND, border=10
  103. )
  104. if self.etype == "raster":
  105. optionsSizer.Add(
  106. StaticText(self.panel, label=_("Estimated resolution:")),
  107. pos=(0, 0),
  108. flag=wx.EXPAND | wx.ALIGN_CENTER_VERTICAL,
  109. )
  110. optionsSizer.Add(self.resolution, pos=(0, 1), flag=wx.EXPAND)
  111. optionsSizer.Add(
  112. StaticText(self.panel, label=_("Resampling method:")),
  113. pos=(1, 0),
  114. flag=wx.EXPAND | wx.ALIGN_CENTER_VERTICAL,
  115. )
  116. optionsSizer.Add(self.resampling, pos=(1, 1), flag=wx.EXPAND)
  117. else:
  118. optionsSizer.Add(
  119. StaticText(self.panel, label=_("Maximum segment length:")),
  120. pos=(1, 0),
  121. flag=wx.EXPAND | wx.ALIGN_CENTER_VERTICAL,
  122. )
  123. optionsSizer.Add(self.vsplit, pos=(1, 1), flag=wx.EXPAND)
  124. optionsSizer.AddGrowableCol(1)
  125. dialogSizer.Add(optionsSizer, proportion=1, flag=wx.ALL | wx.EXPAND, border=10)
  126. helptext = StaticText(
  127. self.panel,
  128. label="For more reprojection options,"
  129. " please see {module}".format(
  130. module="r.proj" if self.etype == "raster" else "v.proj"
  131. ),
  132. )
  133. dialogSizer.Add(helptext, proportion=0, flag=wx.ALL | wx.EXPAND, border=10)
  134. #
  135. # buttons
  136. #
  137. btnStdSizer = wx.StdDialogButtonSizer()
  138. btnStdSizer.AddButton(self.btn_run)
  139. btnStdSizer.AddButton(self.btn_close)
  140. btnStdSizer.Realize()
  141. dialogSizer.Add(btnStdSizer, proportion=0, flag=wx.ALL | wx.EXPAND, border=5)
  142. self.panel.SetSizer(dialogSizer)
  143. dialogSizer.Fit(self.panel)
  144. self.Layout()
  145. self.SetSize(self.GetBestSize())
  146. def _estimateResolution(self):
  147. output = RunCommand(
  148. "r.proj",
  149. flags="g",
  150. quiet=False,
  151. read=True,
  152. input=self.iLayer,
  153. dbase=self.iGisdbase,
  154. location=self.iLocation,
  155. mapset=self.iMapset,
  156. env=self.oEnv,
  157. ).strip()
  158. params = parse_key_val(output, vsep=" ")
  159. output = RunCommand(
  160. "g.region",
  161. flags="ug",
  162. quiet=False,
  163. read=True,
  164. env=self.oEnv,
  165. parse=lambda x: parse_key_val(x, val_type=float),
  166. **params,
  167. )
  168. cell_ns = (output["n"] - output["s"]) / output["rows"]
  169. cell_ew = (output["e"] - output["w"]) / output["cols"]
  170. estimate = (cell_ew + cell_ns) / 2.0
  171. self.resolution.SetValue(str(estimate))
  172. self.params = params
  173. def _estimateResampling(self):
  174. output = RunCommand(
  175. "r.info",
  176. flags="g",
  177. quiet=False,
  178. read=True,
  179. map=self.iLayer,
  180. env=self.iEnv,
  181. parse=parse_key_val,
  182. )
  183. if output["datatype"] == "CELL":
  184. self.resampling.SetStringSelection("nearest")
  185. else:
  186. self.resampling.SetStringSelection("bilinear")
  187. def OnReproject(self, event):
  188. cmd = []
  189. if self.etype == "raster":
  190. cmd.append("r.proj")
  191. cmd.append("dbase=" + self.iGisdbase)
  192. cmd.append("location=" + self.iLocation)
  193. cmd.append("mapset=" + self.iMapset)
  194. cmd.append("input=" + self.iLayer)
  195. cmd.append("output=" + self.oLayer)
  196. cmd.append("method=" + self.resampling.GetStringSelection())
  197. self.oEnv["GRASS_REGION"] = region_env(
  198. n=self.params["n"],
  199. s=self.params["s"],
  200. e=self.params["e"],
  201. w=self.params["w"],
  202. flags="a",
  203. res=float(self.resolution.GetValue()),
  204. env=self.oEnv,
  205. )
  206. else:
  207. cmd.append("v.proj")
  208. cmd.append("dbase=" + self.iGisdbase)
  209. cmd.append("location=" + self.iLocation)
  210. cmd.append("mapset=" + self.iMapset)
  211. cmd.append("input=" + self.iLayer)
  212. cmd.append("output=" + self.oLayer)
  213. cmd.append("smax=" + self.vsplit.GetValue())
  214. self._giface.RunCmd(
  215. cmd,
  216. env=self.oEnv,
  217. compReg=False,
  218. addLayer=False,
  219. onDone=self._onDone,
  220. userData=None,
  221. notification=Notification.MAKE_VISIBLE,
  222. )
  223. event.Skip()
  224. def _onDone(self, event):
  225. self.callback()