controller.py 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693
  1. """
  2. @package rdigit.controller
  3. @brief rdigit controller for drawing and rasterizing
  4. Classes:
  5. - controller::RDigitController
  6. (C) 2014 by the GRASS Development Team
  7. This program is free software under the GNU General Public
  8. License (>=v2). Read the file COPYING that comes with GRASS
  9. for details.
  10. @author Anna Petrasova <kratochanna gmail.com>
  11. """
  12. import os
  13. import tempfile
  14. import wx
  15. import uuid
  16. from wx.lib.newevent import NewEvent
  17. from grass.script import core as gcore
  18. from grass.script import raster as grast
  19. from grass.exceptions import CalledModuleError, ScriptError
  20. from grass.pydispatch.signal import Signal
  21. from core.gcmd import GError, GMessage
  22. from core.settings import UserSettings
  23. from core.gthread import gThread
  24. from rdigit.dialogs import NewRasterDialog
  25. updateProgress, EVT_UPDATE_PROGRESS = NewEvent()
  26. class RDigitController(wx.EvtHandler):
  27. """Controller object for raster digitizer.
  28. Inherits from EvtHandler to be able to send wx events from thraed.
  29. """
  30. def __init__(self, giface, mapWindow):
  31. """Constructs controller
  32. :param giface: grass interface object
  33. :param mapWindow: instance of BufferedMapWindow
  34. """
  35. wx.EvtHandler.__init__(self)
  36. self._giface = giface
  37. self._mapWindow = mapWindow
  38. # thread for running rasterization process
  39. self._thread = gThread()
  40. # name of raster map which is edited (also new one)
  41. self._editedRaster = None
  42. # name of optional background raster
  43. self._backgroundRaster = None
  44. # name of temporary raster used to backup original state
  45. self._backupRasterName = None
  46. # if we edit an old raster or a new one (important for setting color
  47. # table)
  48. self._editOldRaster = False
  49. # type of output raster map (CELL, FCELL, DCELL)
  50. self._mapType = None
  51. # GraphicsSet for drawing areas, lines, points
  52. self._areas = None
  53. self._lines = None
  54. self._points = None
  55. # list of all GraphicsItems in the order of drawing
  56. self._all = []
  57. # if in state of drawing lin or area
  58. self._drawing = False
  59. # if running digitizing process in thread (to block drawing)
  60. self._running = False
  61. # color used to draw (should be moved to settings)
  62. self._drawColor = wx.GREEN
  63. # transparency used to draw (should be moved to settings)
  64. self._drawTransparency = 100
  65. # current selected drawing method
  66. self._graphicsType = "area"
  67. # last edited cell value
  68. self._currentCellValue = None
  69. # last edited buffer value
  70. self._currentWidthValue = None
  71. # digit env
  72. self._env = os.environ.copy()
  73. self._oldMouseUse = None
  74. self._oldCursor = None
  75. # signal to add new raster to toolbar items
  76. self.newRasterCreated = Signal("RDigitController:newRasterCreated")
  77. # signal to add just used cell value in toolbar combo
  78. self.newFeatureCreated = Signal("RDigitController:newFeatureCreated")
  79. # signal to upload unique categories of background map into toolbar
  80. # combo
  81. self.uploadMapCategories = Signal("RDigitController:uploadMapCategories")
  82. self.quitDigitizer = Signal("RDigitController:quitDigitizer")
  83. self.showNotification = Signal("RDigitController:showNotification")
  84. def _connectAll(self):
  85. self._mapWindow.mouseLeftDown.connect(self._start)
  86. self._mapWindow.mouseLeftUp.connect(self._addPoint)
  87. self._mapWindow.mouseRightUp.connect(self._finish)
  88. self._mapWindow.Unbind(wx.EVT_CONTEXT_MENU)
  89. def _disconnectAll(self):
  90. self._mapWindow.mouseLeftDown.disconnect(self._start)
  91. self._mapWindow.mouseLeftUp.disconnect(self._addPoint)
  92. self._mapWindow.mouseRightUp.disconnect(self._finish)
  93. self._mapWindow.Bind(wx.EVT_CONTEXT_MENU, self._mapWindow.OnContextMenu)
  94. def _start(self, x, y):
  95. """Start digitizing a new object.
  96. :param x: x coordinate in map units
  97. :param y: y coordinate in map units
  98. """
  99. if self._running:
  100. return
  101. if not self._editedRaster:
  102. GMessage(
  103. parent=self._mapWindow, message=_("Please select first the raster map")
  104. )
  105. return
  106. if not self._drawing:
  107. if self._graphicsType == "area":
  108. item = self._areas.AddItem(coords=[])
  109. item.SetPropertyVal("penName", "pen1")
  110. self._all.append(item)
  111. elif self._graphicsType == "line":
  112. item = self._lines.AddItem(coords=[])
  113. item.SetPropertyVal("penName", "pen1")
  114. self._all.append(item)
  115. elif self._graphicsType == "point":
  116. item = self._points.AddItem(coords=[])
  117. item.SetPropertyVal("penName", "pen1")
  118. self._all.append(item)
  119. self._drawing = True
  120. def _addPoint(self, x, y):
  121. """Add point to an object.
  122. :param x: x coordinate in map units
  123. :param y: y coordinate in map units
  124. """
  125. if self._running:
  126. return
  127. if not self._drawing:
  128. return
  129. if self._graphicsType == "area":
  130. area = self._areas.GetItem(-1)
  131. coords = area.GetCoords() + [[x, y]]
  132. area.SetCoords(coords)
  133. self.showNotification.emit(text=_("Right click to finish area"))
  134. elif self._graphicsType == "line":
  135. line = self._lines.GetItem(-1)
  136. coords = line.GetCoords() + [[x, y]]
  137. line.SetCoords(coords)
  138. self.showNotification.emit(text=_("Right click to finish line"))
  139. elif self._graphicsType == "point":
  140. point = self._points.GetItem(-1)
  141. point.SetCoords([x, y])
  142. self._finish()
  143. # draw
  144. self._mapWindow.ClearLines()
  145. self._lines.Draw()
  146. self._areas.Draw()
  147. self._points.Draw()
  148. self._mapWindow.Refresh()
  149. def _finish(self):
  150. """Finish digitizing a new object and redraws.
  151. Saves current cell value and buffer width for that object.
  152. :param x: x coordinate in map units
  153. :param y: y coordinate in map units
  154. """
  155. if self._running:
  156. return
  157. if self._graphicsType == "point":
  158. item = self._points.GetItem(-1)
  159. elif self._graphicsType == "area":
  160. item = self._areas.GetItem(-1)
  161. elif self._graphicsType == "line":
  162. item = self._lines.GetItem(-1)
  163. else:
  164. return
  165. self._drawing = False
  166. item.SetPropertyVal("brushName", "done")
  167. item.AddProperty("cellValue")
  168. item.AddProperty("widthValue")
  169. item.SetPropertyVal("cellValue", self._currentCellValue)
  170. item.SetPropertyVal("widthValue", self._currentWidthValue)
  171. self.newFeatureCreated.emit()
  172. self._mapWindow.ClearLines()
  173. self._points.Draw()
  174. self._areas.Draw()
  175. self._lines.Draw()
  176. self._mapWindow.Refresh()
  177. def SelectType(self, drawingType):
  178. """Selects method (area/line/point) for drawing.
  179. Connects and disconnects signal to allow other tools
  180. in map toolbar to work.
  181. """
  182. if (
  183. self._graphicsType
  184. and drawingType
  185. and self._graphicsType != drawingType
  186. and self._drawing
  187. ):
  188. # if we select different drawing tool, finish the feature
  189. self._finish()
  190. if self._graphicsType and not drawingType:
  191. self._mapWindow.ClearLines(pdc=self._mapWindow.pdcTmp)
  192. self._mapWindow.mouse["end"] = self._mapWindow.mouse["begin"]
  193. # disconnect mouse events
  194. self._disconnectAll()
  195. self._mapWindow.SetNamedCursor(self._oldCursor)
  196. self._mapWindow.mouse["use"] = self._oldMouseUse
  197. elif self._graphicsType is None and drawingType:
  198. self._connectAll()
  199. # change mouse['box'] and pen to draw line during dragging
  200. # TODO: better solution for drawing this line
  201. self._mapWindow.mouse["use"] = None
  202. self._mapWindow.mouse["box"] = "line"
  203. self._mapWindow.pen = wx.Pen(colour="red", width=2, style=wx.SHORT_DASH)
  204. # change the cursor
  205. self._mapWindow.SetNamedCursor("pencil")
  206. self._graphicsType = drawingType
  207. def SetCellValue(self, value):
  208. self._currentCellValue = value
  209. def SetWidthValue(self, value):
  210. self._currentWidthValue = value
  211. def ChangeDrawColor(self, color):
  212. self._drawColor = color[:3] + (self._drawTransparency,)
  213. for each in (self._areas, self._lines, self._points):
  214. each.GetPen("pen1").SetColour(self._drawColor)
  215. each.GetBrush("done").SetColour(self._drawColor)
  216. self._mapWindow.UpdateMap(render=False)
  217. def Start(self):
  218. """Registers graphics to map window,
  219. connect required mouse signals.
  220. """
  221. self._oldMouseUse = self._mapWindow.mouse["use"]
  222. self._oldCursor = self._mapWindow.GetNamedCursor()
  223. self._connectAll()
  224. # change mouse['box'] and pen to draw line during dragging
  225. # TODO: better solution for drawing this line
  226. self._mapWindow.mouse["use"] = None
  227. self._mapWindow.mouse["box"] = "line"
  228. self._mapWindow.pen = wx.Pen(colour="red", width=2, style=wx.SHORT_DASH)
  229. color = self._drawColor[:3] + (self._drawTransparency,)
  230. self._areas = self._mapWindow.RegisterGraphicsToDraw(
  231. graphicsType="polygon", pdc=self._mapWindow.pdcTransparent, mapCoords=True
  232. )
  233. self._areas.AddPen("pen1", wx.Pen(colour=color, width=2, style=wx.SOLID))
  234. self._areas.AddBrush("done", wx.Brush(colour=color, style=wx.SOLID))
  235. self._lines = self._mapWindow.RegisterGraphicsToDraw(
  236. graphicsType="line", pdc=self._mapWindow.pdcTransparent, mapCoords=True
  237. )
  238. self._lines.AddPen("pen1", wx.Pen(colour=color, width=2, style=wx.SOLID))
  239. self._lines.AddBrush("done", wx.Brush(colour=color, style=wx.SOLID))
  240. self._points = self._mapWindow.RegisterGraphicsToDraw(
  241. graphicsType="point", pdc=self._mapWindow.pdcTransparent, mapCoords=True
  242. )
  243. self._points.AddPen("pen1", wx.Pen(colour=color, width=2, style=wx.SOLID))
  244. self._points.AddBrush("done", wx.Brush(colour=color, style=wx.SOLID))
  245. # change the cursor
  246. self._mapWindow.SetNamedCursor("pencil")
  247. def Stop(self):
  248. """Before stopping digitizer, asks to save edits"""
  249. if self._editedRaster:
  250. dlg = wx.MessageDialog(
  251. self._mapWindow,
  252. _("Do you want to save changes?"),
  253. _("Save raster map changes"),
  254. wx.YES_NO,
  255. )
  256. if dlg.ShowModal() == wx.ID_YES:
  257. if self._drawing:
  258. self._finish()
  259. self._thread.Run(
  260. callable=self._exportRaster,
  261. ondone=lambda event: self._updateAndQuit(),
  262. )
  263. else:
  264. self.quitDigitizer.emit()
  265. else:
  266. self.quitDigitizer.emit()
  267. def Save(self):
  268. """Saves current edits to a raster map"""
  269. if self._drawing:
  270. self._finish()
  271. self._thread.Run(
  272. callable=self._exportRaster, ondone=lambda event: self._update()
  273. )
  274. def Undo(self):
  275. """Undo a change, goes object back (finished or not finished)"""
  276. if len(self._all):
  277. removed = self._all.pop(-1)
  278. # try to remove from each, it fails quietly when theitem is not
  279. # there
  280. self._areas.DeleteItem(removed)
  281. self._lines.DeleteItem(removed)
  282. self._points.DeleteItem(removed)
  283. self._drawing = False
  284. self._mapWindow.UpdateMap(render=False)
  285. def CleanUp(self, restore=True):
  286. """Cleans up drawing, temporary maps.
  287. :param restore: if restore previous cursor, mouse['use']
  288. """
  289. try:
  290. if self._backupRasterName:
  291. gcore.run_command(
  292. "g.remove",
  293. type="raster",
  294. flags="f",
  295. name=self._backupRasterName,
  296. quiet=True,
  297. )
  298. except CalledModuleError:
  299. pass
  300. self._mapWindow.ClearLines(pdc=self._mapWindow.pdcTmp)
  301. self._mapWindow.mouse["end"] = self._mapWindow.mouse["begin"]
  302. # disconnect mouse events
  303. if self._graphicsType:
  304. self._disconnectAll()
  305. # unregister
  306. self._mapWindow.UnregisterGraphicsToDraw(self._areas)
  307. self._mapWindow.UnregisterGraphicsToDraw(self._lines)
  308. self._mapWindow.UnregisterGraphicsToDraw(self._points)
  309. # self._registeredGraphics = None
  310. self._mapWindow.UpdateMap(render=False)
  311. if restore:
  312. # restore mouse['use'] and cursor to the state before measuring
  313. # starts
  314. self._mapWindow.SetNamedCursor(self._oldCursor)
  315. self._mapWindow.mouse["use"] = self._oldMouseUse
  316. def _updateAndQuit(self):
  317. """Called when thread is done. Updates map and calls to quits digitizer."""
  318. self._running = False
  319. self._mapWindow.UpdateMap(render=True)
  320. self.quitDigitizer.emit()
  321. def _update(self):
  322. """Called when thread is done. Updates map."""
  323. self._running = False
  324. self._mapWindow.UpdateMap(render=True)
  325. def SelectOldMap(self, name):
  326. """After selecting old raster, creates a backup copy for editing."""
  327. try:
  328. self._backupRaster(name)
  329. except ScriptError:
  330. GError(
  331. parent=self._mapWindow,
  332. message=_("Failed to create backup copy of edited raster map."),
  333. )
  334. return False
  335. self._editedRaster = name
  336. self._mapType = grast.raster_info(map=name)["datatype"]
  337. self._editOldRaster = True
  338. return True
  339. def SelectNewMap(
  340. self,
  341. standalone=False,
  342. mapName=None,
  343. bgMap=None,
  344. mapType=None,
  345. ):
  346. """After selecting new raster, shows dialog to choose name,
  347. background map and type of the new map.
  348. :params standalone, mapName, bgMap, mapType: if digitizer is
  349. launched as standalone module
  350. :param bool standalone: if digitizer is launched as standalone
  351. module
  352. :param str mapName: edited raster map name
  353. :param str bgMap: background raster map name
  354. :param str mapType: raster map type CELL, FCELL, DCELL
  355. """
  356. if standalone:
  357. try:
  358. self._createNewMap(
  359. mapName=mapName,
  360. backgroundMap=bgMap,
  361. mapType=mapType,
  362. )
  363. except ScriptError:
  364. GError(
  365. parent=self._mapWindow,
  366. message=_("Failed to create new raster map."),
  367. )
  368. return False
  369. return True
  370. else:
  371. dlg = NewRasterDialog(parent=self._mapWindow)
  372. dlg.CenterOnParent()
  373. if dlg.ShowModal() == wx.ID_OK:
  374. try:
  375. self._createNewMap(
  376. mapName=dlg.GetMapName(),
  377. backgroundMap=dlg.GetBackgroundMapName(),
  378. mapType=dlg.GetMapType(),
  379. )
  380. except ScriptError:
  381. GError(
  382. parent=self._mapWindow,
  383. message=_("Failed to create new raster map."),
  384. )
  385. return False
  386. finally:
  387. dlg.Destroy()
  388. return True
  389. else:
  390. dlg.Destroy()
  391. return False
  392. def _createNewMap(self, mapName, backgroundMap, mapType):
  393. """Creates a new raster map based on specified background and type."""
  394. name = mapName.split("@")[0]
  395. background = backgroundMap.split("@")[0]
  396. types = {"CELL": "int", "FCELL": "float", "DCELL": "double"}
  397. if background:
  398. back = background
  399. else:
  400. back = "null()"
  401. try:
  402. grast.mapcalc(
  403. exp="{name} = {mtype}({back})".format(
  404. name=name, mtype=types[mapType], back=back
  405. ),
  406. overwrite=True,
  407. quiet=True,
  408. )
  409. if background:
  410. self._backgroundRaster = backgroundMap
  411. gcore.run_command(
  412. "r.colors", map=name, raster=self._backgroundRaster, quiet=True
  413. )
  414. if mapType == "CELL":
  415. values = gcore.read_command(
  416. "r.describe", flags="1n", map=name, quiet=True
  417. ).strip()
  418. if values:
  419. self.uploadMapCategories.emit(values=values.split("\n"))
  420. except CalledModuleError:
  421. raise ScriptError
  422. self._backupRaster(name)
  423. name = name + "@" + gcore.gisenv()["MAPSET"]
  424. self._editedRaster = name
  425. self._mapType = mapType
  426. self.newRasterCreated.emit(name=name)
  427. gisenv = gcore.gisenv()
  428. self._giface.grassdbChanged.emit(
  429. grassdb=gisenv["GISDBASE"],
  430. location=gisenv["LOCATION_NAME"],
  431. mapset=gisenv["MAPSET"],
  432. action="new",
  433. map=name.split("@")[0],
  434. element="raster",
  435. )
  436. def _backupRaster(self, name):
  437. """Creates a temporary backup raster necessary for undo behavior.
  438. :param str name: name of raster map for which we create backup
  439. """
  440. name = name.split("@")[0]
  441. backup = name + "_backupcopy_" + str(os.getpid())
  442. try:
  443. gcore.run_command("g.copy", raster=[name, backup], quiet=True)
  444. except CalledModuleError:
  445. raise ScriptError
  446. self._backupRasterName = backup
  447. def _exportRaster(self):
  448. """Rasterizes digitized features.
  449. Uses r.in.poly and r.grow for buffering features. Creates separate raster
  450. maps depending on common cell values and buffering width necessary to
  451. keep the order of editing. These rasters are then patched together.
  452. Sets default color table for the newly digitized raster.
  453. """
  454. self._setRegion()
  455. if not self._editedRaster or self._running:
  456. return
  457. self._running = True
  458. if len(self._all) < 1:
  459. new = self._editedRaster
  460. if "@" in self._editedRaster:
  461. new = self._editedRaster.split("@")[0]
  462. gcore.run_command(
  463. "g.copy",
  464. raster=[self._backupRasterName, new],
  465. overwrite=True,
  466. quiet=True,
  467. )
  468. else:
  469. tempRaster = "tmp_rdigit_rast_" + str(os.getpid())
  470. text = []
  471. rastersToPatch = []
  472. i = 0
  473. lastCellValue = lastWidthValue = None
  474. evt = updateProgress(
  475. range=len(self._all), value=0, text=_("Rasterizing...")
  476. )
  477. wx.PostEvent(self, evt)
  478. lastCellValue = self._all[0].GetPropertyVal("cellValue")
  479. lastWidthValue = self._all[0].GetPropertyVal("widthValue")
  480. for item in self._all:
  481. if item.GetPropertyVal("widthValue") and (
  482. lastCellValue != item.GetPropertyVal("cellValue")
  483. or lastWidthValue != item.GetPropertyVal("widthValue")
  484. ):
  485. if text:
  486. out = self._rasterize(
  487. text, lastWidthValue, self._mapType, tempRaster
  488. )
  489. rastersToPatch.append(out)
  490. text = []
  491. self._writeItem(item, text)
  492. out = self._rasterize(
  493. text,
  494. item.GetPropertyVal("widthValue"),
  495. self._mapType,
  496. tempRaster,
  497. )
  498. rastersToPatch.append(out)
  499. text = []
  500. else:
  501. self._writeItem(item, text)
  502. lastCellValue = item.GetPropertyVal("cellValue")
  503. lastWidthValue = item.GetPropertyVal("widthValue")
  504. i += 1
  505. evt = updateProgress(
  506. range=len(self._all), value=i, text=_("Rasterizing...")
  507. )
  508. wx.PostEvent(self, evt)
  509. if text:
  510. out = self._rasterize(
  511. text, item.GetPropertyVal("widthValue"), self._mapType, tempRaster
  512. )
  513. rastersToPatch.append(out)
  514. gcore.run_command(
  515. "r.patch",
  516. input=rastersToPatch[::-1] + [self._backupRasterName],
  517. output=self._editedRaster,
  518. overwrite=True,
  519. quiet=True,
  520. env=self._env,
  521. )
  522. gcore.run_command(
  523. "g.remove",
  524. type="raster",
  525. flags="f",
  526. name=rastersToPatch + [tempRaster],
  527. quiet=True,
  528. )
  529. try:
  530. # setting the right color table
  531. if self._editOldRaster:
  532. return
  533. if not self._backgroundRaster:
  534. table = UserSettings.Get(
  535. group="rasterLayer", key="colorTable", subkey="selection"
  536. )
  537. if not table:
  538. table = "rainbow"
  539. gcore.run_command(
  540. "r.colors", color=table, map=self._editedRaster, quiet=True
  541. )
  542. else:
  543. gcore.run_command(
  544. "r.colors",
  545. map=self._editedRaster,
  546. raster=self._backgroundRaster,
  547. quiet=True,
  548. )
  549. except CalledModuleError:
  550. self._running = False
  551. GError(
  552. parent=self._mapWindow,
  553. message=_("Failed to set default color table for edited raster map"),
  554. )
  555. def _writeFeature(self, item, vtype, text):
  556. """Writes digitized features in r.in.poly format."""
  557. coords = item.GetCoords()
  558. if vtype == "P":
  559. coords = [coords]
  560. cellValue = item.GetPropertyVal("cellValue")
  561. record = "{vtype}\n".format(vtype=vtype)
  562. for coord in coords:
  563. record += " ".join([str(c) for c in coord])
  564. record += "\n"
  565. record += "= {cellValue}\n".format(cellValue=cellValue)
  566. text.append(record)
  567. def _writeItem(self, item, text):
  568. if item in self._areas.GetAllItems():
  569. self._writeFeature(item, vtype="A", text=text)
  570. elif item in self._lines.GetAllItems():
  571. self._writeFeature(item, vtype="L", text=text)
  572. elif item in self._points.GetAllItems():
  573. self._writeFeature(item, vtype="P", text=text)
  574. def _rasterize(self, text, bufferDist, mapType, tempRaster):
  575. """Performs the actual rasterization using r.in.poly
  576. and buffering with r.grow if required.
  577. :param str text: string in r.in.poly format
  578. :param float bufferDist: buffer distance in map units
  579. :param str mapType: CELL, FCELL, DCELL
  580. :param str tempRaster: name of temporary raster used in computation
  581. :return: output raster map name as a result of digitization
  582. """
  583. output = "x" + str(uuid.uuid4())[:8]
  584. asciiFile = tempfile.NamedTemporaryFile(mode="w", delete=False)
  585. asciiFile.write("\n".join(text))
  586. asciiFile.close()
  587. if bufferDist:
  588. bufferDist /= 2.0
  589. gcore.run_command(
  590. "r.in.poly",
  591. input=asciiFile.name,
  592. output=tempRaster,
  593. type_=mapType,
  594. overwrite=True,
  595. quiet=True,
  596. )
  597. gcore.run_command(
  598. "r.grow",
  599. input=tempRaster,
  600. output=output,
  601. flags="m",
  602. radius=bufferDist,
  603. quiet=True,
  604. env=self._env,
  605. )
  606. else:
  607. gcore.run_command(
  608. "r.in.poly",
  609. input=asciiFile.name,
  610. output=output,
  611. type_=mapType,
  612. quiet=True,
  613. env=self._env,
  614. )
  615. os.unlink(asciiFile.name)
  616. return output
  617. def _setRegion(self):
  618. """Set region according input raster map"""
  619. self._env["GRASS_REGION"] = gcore.region_env(raster=self._backupRasterName)