d.rast.edit.py 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734
  1. #!/usr/bin/env python3
  2. ############################################################################
  3. #
  4. # MODULE: d.rast.edit
  5. # AUTHOR(S): Glynn Clements <glynn@gclements.plus.com>
  6. # COPYRIGHT: (C) 2007,2008,2009 Glynn Clements
  7. #
  8. # This program is free software; you can redistribute it and/or modify
  9. # it under the terms of the GNU General Public License as published by
  10. # the Free Software Foundation; either version 2 of the License, or
  11. # (at your option) any later version.
  12. #
  13. # This program is distributed in the hope that it will be useful,
  14. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. # GNU General Public License for more details.
  17. #
  18. # /
  19. # %module
  20. # % description: Edits cell values in a raster map.
  21. # % keyword: display
  22. # % keyword: editing
  23. # % keyword: raster
  24. # %end
  25. # %option G_OPT_R_INPUT
  26. # %end
  27. # %option G_OPT_R_OUTPUT
  28. # %end
  29. # %option G_OPT_R_INPUT
  30. # % key: aspect
  31. # % required: no
  32. # % description: Name of input aspect raster map
  33. # %end
  34. # %option
  35. # % key: width
  36. # % type: integer
  37. # % required: no
  38. # % multiple: no
  39. # % description: Width of display canvas
  40. # % answer: 640
  41. # %end
  42. # %option
  43. # % key: height
  44. # % type: integer
  45. # % required: no
  46. # % multiple: no
  47. # % description: Height of display canvas
  48. # % answer: 480
  49. # %end
  50. # %option
  51. # % key: size
  52. # % type: integer
  53. # % required: no
  54. # % multiple: no
  55. # % description: Minimum size of each cell
  56. # % answer: 12
  57. # %end
  58. # %option
  59. # % key: rows
  60. # % type: integer
  61. # % required: no
  62. # % multiple: no
  63. # % description: Maximum number of rows to load
  64. # % answer: 100
  65. # %end
  66. # %option
  67. # % key: cols
  68. # % type: integer
  69. # % required: no
  70. # % multiple: no
  71. # % description: Maximum number of columns to load
  72. # % answer: 100
  73. # %end
  74. import sys
  75. import math
  76. import atexit
  77. import grass.script as grass
  78. from grass.script.setup import set_gui_path
  79. set_gui_path()
  80. try:
  81. import wx
  82. except ImportError:
  83. # ensure that --help, --interface-description etc work even without wx
  84. if __name__ == "__main__":
  85. if len(sys.argv) == 2:
  86. arg = sys.argv[1]
  87. if arg[0:2] == "--" or arg in ["help", "-help"]:
  88. grass.parser()
  89. # Either we didn't call g.parser, or it returned
  90. # At this point, there's nothing to be done except re-raise the exception
  91. raise
  92. wind_keys = {
  93. "north": ("n", float),
  94. "south": ("s", float),
  95. "east": ("e", float),
  96. "west": ("w", float),
  97. "nsres": ("nsres", float),
  98. "ewres": ("ewres", float),
  99. "rows": ("rows", int),
  100. "cols": ("cols", int),
  101. }
  102. gray12_bits = b"\x00\x00\x22\x22\x00\x00\x88\x88\x00\x00\x22\x22\x00\x00\x88\x88\x00\x00\x22\x22\x00\x00\x88\x88\x00\x00\x22\x22\x00\x00\x88\x88"
  103. def run(cmd, **kwargs):
  104. grass.run_command(cmd, quiet=True, **kwargs)
  105. def wxGUI():
  106. class OverviewCanvas(wx.ScrolledWindow):
  107. def __init__(self, app, parent):
  108. wx.ScrolledWindow.__init__(self, parent)
  109. self.app = app
  110. self.width = app.total["cols"]
  111. self.height = app.total["rows"]
  112. self.SetVirtualSize((self.width, self.height))
  113. self.SetScrollRate(1, 1)
  114. self.Bind(wx.EVT_LEFT_DOWN, self.OnMouse)
  115. self.Bind(wx.EVT_MOTION, self.OnMouse)
  116. self.Bind(wx.EVT_LEFT_UP, self.OnMouse)
  117. self.Bind(wx.EVT_PAINT, self.OnPaint)
  118. run("r.out.ppm", input=app.inmap, output=app.tempfile)
  119. self.image = wx.Bitmap(wx.Image(app.tempfile))
  120. grass.try_remove(app.tempfile)
  121. app.force_window()
  122. def OnPaint(self, ev):
  123. x0 = self.app.origin_x
  124. y0 = self.app.origin_y
  125. dx = self.app.cols
  126. dy = self.app.rows
  127. dc = wx.PaintDC(self)
  128. self.DoPrepareDC(dc)
  129. src = wx.MemoryDC()
  130. src.SelectObjectAsSource(self.image)
  131. dc.Blit(0, 0, self.width, self.height, src, 0, 0)
  132. src.SelectObjectAsSource(wx.NullBitmap)
  133. dc.SetPen(wx.Pen("red", style=wx.LONG_DASH))
  134. dc.SetBrush(wx.Brush("black", style=wx.TRANSPARENT))
  135. dc.DrawRectangle(x0, y0, dx, dy)
  136. dc.SetBrush(wx.NullBrush)
  137. dc.SetPen(wx.NullPen)
  138. def OnMouse(self, ev):
  139. if ev.Moving():
  140. return
  141. x = ev.GetX()
  142. y = ev.GetY()
  143. (x, y) = self.CalcUnscrolledPosition(x, y)
  144. self.set_window(x, y)
  145. if ev.ButtonUp():
  146. self.app.change_window()
  147. def set_window(self, x, y):
  148. self.app.origin_x = x - app.cols / 2
  149. self.app.origin_y = y - app.rows / 2
  150. self.app.force_window()
  151. self.Refresh()
  152. class OverviewWindow(wx.Frame):
  153. def __init__(self, app):
  154. wx.Frame.__init__(self, None, title="d.rast.edit overview (%s)" % app.inmap)
  155. self.app = app
  156. self.canvas = OverviewCanvas(app, parent=self)
  157. self.Bind(wx.EVT_CLOSE, self.OnClose)
  158. def OnClose(self, ev):
  159. self.app.finalize()
  160. class Canvas(wx.ScrolledWindow):
  161. def __init__(self, app, parent):
  162. wx.ScrolledWindow.__init__(self, parent)
  163. self.app = app
  164. self.size = app.size
  165. w = app.cols * self.size
  166. h = app.rows * self.size
  167. self.SetVirtualSize((w, h))
  168. self.SetScrollRate(1, 1)
  169. self.Bind(wx.EVT_LEFT_DOWN, self.OnMouse)
  170. self.Bind(wx.EVT_RIGHT_DOWN, self.OnMouse)
  171. self.Bind(wx.EVT_MOTION, self.OnMouse)
  172. self.Bind(wx.EVT_PAINT, self.OnPaint2)
  173. self.row = 0
  174. self.col = 0
  175. self.gray12 = wx.Bitmap(bits=gray12_bits, width=16, height=16)
  176. def OnMouse(self, ev):
  177. oldrow = self.row
  178. oldcol = self.col
  179. x = ev.GetX()
  180. y = ev.GetY()
  181. (x, y) = self.CalcUnscrolledPosition(x, y)
  182. col = x / self.size
  183. row = y / self.size
  184. self.row = int(row)
  185. self.col = int(col)
  186. if ev.Moving():
  187. self.refresh_cell(oldrow, oldcol)
  188. self.refresh_cell(row, col)
  189. elif ev.ButtonDown(wx.MOUSE_BTN_LEFT):
  190. self.cell_set()
  191. elif ev.ButtonDown(wx.MOUSE_BTN_RIGHT):
  192. self.cell_get()
  193. def paint_cell(self, dc, r, c):
  194. if r < 0 or r >= self.app.rows or c < 0 or c >= self.app.cols:
  195. return
  196. val = self.app.values[r][c]
  197. if val is None:
  198. fill = "black"
  199. stipple = self.gray12
  200. else:
  201. fill = self.app.get_color(val)
  202. stipple = None
  203. if r == self.row and c == self.col:
  204. outline = "red"
  205. elif self.app.changed[r][c]:
  206. outline = "white"
  207. else:
  208. outline = "black"
  209. dc.SetPen(wx.Pen(outline))
  210. if stipple:
  211. brush = wx.Brush(fill, style=wx.STIPPLE)
  212. brush.SetStipple(stipple)
  213. else:
  214. brush = wx.Brush(fill, style=wx.SOLID)
  215. x0 = c * self.size + 1
  216. x1 = x0 + self.size - 1
  217. y0 = r * self.size + 1
  218. y1 = y0 + self.size - 1
  219. dc.SetBrush(brush)
  220. dc.DrawRectangle(x0, y0, x1 - x0, y1 - y0)
  221. dc.SetPen(wx.NullPen)
  222. dc.SetBrush(wx.NullBrush)
  223. if not self.app.angles:
  224. return
  225. if self.app.angles[r][c] == "*":
  226. return
  227. cx = (x0 + x1) / 2
  228. cy = (y0 + y1) / 2
  229. a = math.radians(float(self.app.angles[r][c]))
  230. dx = math.cos(a) * self.size / 2
  231. dy = -math.sin(a) * self.size / 2
  232. x0 = cx - dx
  233. y0 = cy - dy
  234. x1 = cx + dx
  235. y1 = cy + dy
  236. dx, dy = x1 - x0, y1 - y0
  237. px, py = -dy, dx
  238. r, g, b, a = wx.Colour(fill).Get()
  239. if r + g + b > 384:
  240. line = "black"
  241. else:
  242. line = "white"
  243. dc.SetPen(wx.Pen(line))
  244. dc.DrawLine(x0, y0, x1, y1)
  245. dc.DrawLine(x1, y1, x1 + px / 6 - dx / 3, y1 + py / 6 - dy / 3)
  246. dc.DrawLine(x1, y1, x1 - px / 6 - dx / 3, y1 - py / 6 - dy / 3)
  247. dc.SetPen(wx.NullPen)
  248. def paint_rect(self, dc, x, y, w, h):
  249. c0 = int((x + 0) / self.size)
  250. c1 = int((x + w + 1) / self.size)
  251. r0 = int((y + 0) / self.size)
  252. r1 = int((y + h + 1) / self.size)
  253. for r in range(r0, r1 + 1):
  254. for c in range(c0, c1 + 1):
  255. self.paint_cell(dc, r, c)
  256. def OnPaint(self, ev):
  257. dc = wx.PaintDC(self)
  258. self.DoPrepareDC(dc)
  259. for r in range(self.app.rows):
  260. for c in range(self.app.cols):
  261. self.paint_cell(dc, r, c)
  262. def OnPaint2(self, ev):
  263. dc = wx.PaintDC(self)
  264. self.DoPrepareDC(dc)
  265. it = wx.RegionIterator(self.GetUpdateRegion())
  266. while it.HaveRects():
  267. x = it.GetX()
  268. y = it.GetY()
  269. w = it.GetW()
  270. h = it.GetH()
  271. (x, y) = self.CalcUnscrolledPosition(x, y)
  272. self.paint_rect(dc, x, y, w, h)
  273. it.Next()
  274. def cell_enter(self):
  275. if not self.row or not self.col:
  276. return
  277. self.app.update_status(self.row, self.col)
  278. def cell_leave(self):
  279. self.app.clear_status()
  280. def cell_get(self):
  281. self.app.brush = self.app.values[self.row][self.col]
  282. self.app.frame.brush_update()
  283. def cell_set(self):
  284. self.app.values[self.row][self.col] = self.app.brush
  285. self.app.changed[self.row][self.col] = True
  286. self.refresh_cell(self.row, self.col)
  287. def refresh_cell(self, row, col):
  288. x = col * self.size
  289. y = row * self.size
  290. (x, y) = self.CalcScrolledPosition(x, y)
  291. self.RefreshRect((x, y, self.size, self.size))
  292. class ColorPanel(Panel):
  293. def __init__(self, **kwargs):
  294. Panel.__init__(self, **kwargs)
  295. self.stipple = wx.Bitmap(bits=gray12_bits, width=16, height=16)
  296. self.null_bg = True
  297. self.Bind(wx.EVT_ERASE_BACKGROUND, self.OnErase)
  298. def OnErase(self, ev):
  299. self.ClearBackground()
  300. if not self.null_bg:
  301. return
  302. dc = ev.GetDC()
  303. if not dc:
  304. dc = ClientDC(self)
  305. brush = wx.Brush("black", style=wx.STIPPLE)
  306. brush.SetStipple(self.stipple)
  307. dc.SetBackground(brush)
  308. dc.Clear()
  309. dc.SetBackground(wx.NullBrush)
  310. def SetNullBackgroundColour(self):
  311. Panel.SetBackgroundColour(self, "gray")
  312. self.null_bg = True
  313. def SetBackgroundColour(self, color):
  314. Panel.SetBackgroundColour(self, color)
  315. self.null_bg = False
  316. class MainWindow(wx.Frame):
  317. def __init__(self, app):
  318. wx.Frame.__init__(self, None, title="d.rast.edit (%s)" % app.inmap)
  319. self.app = app
  320. self.Bind(wx.EVT_CLOSE, self.OnClose)
  321. filemenu = Menu()
  322. filemenu.Append(wx.ID_SAVE, "&Save", "Save changes")
  323. filemenu.Append(wx.ID_EXIT, "E&xit", "Terminate the program")
  324. menubar = wx.MenuBar()
  325. menubar.Append(filemenu, "&File")
  326. self.SetMenuBar(menubar)
  327. self.Bind(wx.EVT_MENU, self.OnSave)
  328. self.Bind(wx.EVT_MENU, self.OnExit)
  329. sizer = wx.BoxSizer(orient=wx.VERTICAL)
  330. self.canvas = Canvas(app, parent=self)
  331. sizer.Add(self.canvas, proportion=1, flag=wx.EXPAND)
  332. tools = wx.BoxSizer(wx.HORIZONTAL)
  333. label = wx.StaticText(parent=self, label="New Value:")
  334. tools.Add(label, flag=wx.ALIGN_CENTER_VERTICAL)
  335. tools.AddSpacer(5)
  336. self.newval = wx.TextCtrl(parent=self, style=wx.TE_PROCESS_ENTER)
  337. tools.Add(self.newval, flag=wx.ALIGN_CENTER_VERTICAL)
  338. label = wx.StaticText(parent=self, label="Color:")
  339. tools.Add(label, flag=wx.ALIGN_CENTER_VERTICAL)
  340. tools.AddSpacer(5)
  341. self.color = ColorPanel(parent=self, size=(30, 5))
  342. tools.Add(self.color, flag=wx.ALIGN_CENTER_VERTICAL | wx.EXPAND)
  343. self.Bind(wx.EVT_TEXT_ENTER, self.OnReturn, source=self.newval)
  344. sizer.Add(tools, proportion=0, flag=wx.EXPAND)
  345. self.SetSizerAndFit(sizer)
  346. self.SetSize((app.width, app.height))
  347. self.status = self.CreateStatusBar(6)
  348. self.brush_update()
  349. def OnSave(self, ev):
  350. self.app.save_map()
  351. def OnExit(self, ev):
  352. self.Close(True)
  353. def OnClose(self, ev):
  354. self.app.finalize()
  355. def OnReturn(self, ev):
  356. self.app.brush = self.newval.GetValue()
  357. if self.app.brush != "*" and self.app.brush.strip("0123456789") != "":
  358. self.app.brush = "*"
  359. self.brush_update()
  360. def update_status(self):
  361. for i, key in enumerate(["row", "col", "x", "y", "value", "aspect"]):
  362. s = "%s%s: %s" % (key[0].upper(), key[1:], self.app.status[key])
  363. self.status.SetStatusText(s, i)
  364. def clear_status(self):
  365. for key in self.status:
  366. self.status[key] = ""
  367. def brush_update(self):
  368. self.newval.ChangeValue(self.app.brush)
  369. if self.app.brush == "*":
  370. self.color.SetNullBackgroundColour()
  371. else:
  372. self.color.SetBackgroundColour(self.app.get_color(self.app.brush))
  373. self.color.Refresh()
  374. class Application(wx.App):
  375. def __init__(self, options):
  376. self.options = options
  377. wx.App.__init__(self)
  378. def initialize(self):
  379. grass.use_temp_region()
  380. run("g.region", raster=self.inmap)
  381. reg = grass.region()
  382. for k, f in wind_keys.values():
  383. self.total[k] = (f)(reg[k])
  384. if self.cols > self.total["cols"]:
  385. self.cols = self.total["cols"]
  386. if self.rows > self.total["rows"]:
  387. self.rows = self.total["rows"]
  388. tempbase = grass.tempfile()
  389. grass.try_remove(tempbase)
  390. self.tempfile = tempbase + ".ppm"
  391. self.tempmap = "tmp.d.rast.edit"
  392. atexit.register(self.cleanup)
  393. run("g.copy", raster=(self.inmap, self.outmap), overwrite=True)
  394. run("r.colors", map=self.outmap, rast=self.inmap)
  395. def cleanup(self):
  396. grass.try_remove(self.tempfile)
  397. run("g.remove", flags="f", type="raster", name=self.tempmap)
  398. def finalize(self):
  399. self.save_map()
  400. sys.exit(0)
  401. def save_map(self):
  402. p = grass.feed_command(
  403. "r.in.ascii", input="-", output=self.tempmap, quiet=True, overwrite=True
  404. )
  405. outf = p.stdin
  406. outf.write(grass.encode("north: %f\n" % self.wind["n"]))
  407. outf.write(grass.encode("south: %f\n" % self.wind["s"]))
  408. outf.write(grass.encode("east: %f\n" % self.wind["e"]))
  409. outf.write(grass.encode("west: %f\n" % self.wind["w"]))
  410. outf.write(grass.encode("rows: %d\n" % self.wind["rows"]))
  411. outf.write(grass.encode("cols: %d\n" % self.wind["cols"]))
  412. outf.write(grass.encode("null: *\n"))
  413. for row in range(self.wind["rows"]):
  414. for col in range(self.wind["cols"]):
  415. if col > 0:
  416. outf.write(grass.encode(" "))
  417. val = self.values[row][col]
  418. if val and self.changed[row][col]:
  419. outf.write(grass.encode("%s" % val))
  420. else:
  421. outf.write(grass.encode("*"))
  422. outf.write(grass.encode("\n"))
  423. outf.close()
  424. p.wait()
  425. run("g.region", raster=self.inmap)
  426. run(
  427. "r.patch",
  428. input=(self.tempmap, self.outmap),
  429. output=self.outmap,
  430. overwrite=True,
  431. )
  432. run("r.colors", map=self.outmap, rast=self.inmap)
  433. run("g.remove", flags="f", type="raster", name=self.tempmap)
  434. def read_header(self, infile):
  435. wind = {}
  436. for i in range(6):
  437. line = grass.decode(infile.readline()).rstrip("\r\n")
  438. f = line.split(":")
  439. key = f[0]
  440. val = f[1].strip()
  441. (k, f) = wind_keys[key]
  442. wind[k] = (f)(val)
  443. return wind
  444. def read_data(self, infile):
  445. values = []
  446. for row in range(self.wind["rows"]):
  447. line = grass.decode(infile.readline()).rstrip("\r\n")
  448. values.append(line.split())
  449. return values
  450. def load_map(self):
  451. run("g.region", **self.wind)
  452. p = grass.pipe_command("r.out.ascii", input=self.inmap, quiet=True)
  453. self.wind = self.read_header(p.stdout)
  454. self.values = self.read_data(p.stdout)
  455. self.changed = [[False for c in row] for row in self.values]
  456. p.wait()
  457. self.clear_changes()
  458. run("r.out.ppm", input=self.inmap, output=self.tempfile)
  459. colorimg = wx.Image(self.tempfile)
  460. grass.try_remove(self.tempfile)
  461. for row in range(self.wind["rows"]):
  462. for col in range(self.wind["cols"]):
  463. val = self.values[row][col]
  464. if val in self.colors:
  465. continue
  466. r = colorimg.GetRed(col, row)
  467. g = colorimg.GetGreen(col, row)
  468. b = colorimg.GetBlue(col, row)
  469. color = "#%02x%02x%02x" % (r, g, b)
  470. self.colors[val] = color
  471. colorimg.Destroy()
  472. def load_aspect(self):
  473. if not self.aspect:
  474. return
  475. p = grass.pipe_command("r.out.ascii", input=self.aspect, quiet=True)
  476. self.read_header(p.stdout)
  477. self.angles = self.read_data(p.stdout)
  478. p.wait()
  479. def clear_changes(self):
  480. for row in range(self.wind["rows"]):
  481. for col in range(self.wind["cols"]):
  482. self.changed[row][col] = 0
  483. def update_window(self):
  484. x0 = self.origin_x
  485. y0 = self.origin_y
  486. x1 = x0 + self.cols
  487. y1 = y0 + self.rows
  488. self.wind["n"] = self.total["n"] - y0 * self.total["nsres"]
  489. self.wind["s"] = self.total["n"] - y1 * self.total["nsres"]
  490. self.wind["w"] = self.total["w"] + x0 * self.total["ewres"]
  491. self.wind["e"] = self.total["w"] + x1 * self.total["ewres"]
  492. self.wind["rows"] = self.rows
  493. self.wind["cols"] = self.cols
  494. def change_window(self):
  495. wait = wx.BusyCursor()
  496. self.save_map()
  497. self.update_window()
  498. self.load_map()
  499. self.load_aspect()
  500. self.refresh_canvas()
  501. del wait
  502. def force_window(self):
  503. if self.origin_x < 0:
  504. self.origin_x = 0
  505. if self.origin_x > self.total["cols"] - self.cols:
  506. self.origin_x = self.total["cols"] - self.cols
  507. if self.origin_y < 0:
  508. self.origin_y = 0
  509. if self.origin_y > self.total["rows"] - self.rows:
  510. self.origin_y = self.total["rows"] - self.rows
  511. def update_status(self, row, col):
  512. self.status["row"] = row
  513. self.status["col"] = col
  514. self.status["x"] = (
  515. self.wind["e"]
  516. + (col + 0.5) * (self.wind["e"] - self.wind["w"]) / self.wind["cols"]
  517. )
  518. self.status["y"] = (
  519. self.wind["n"]
  520. - (row + 0.5) * (self.wind["n"] - self.wind["s"]) / self.wind["rows"]
  521. )
  522. self.status["value"] = self.values[row][col]
  523. if self.angles:
  524. self.status["aspect"] = self.angles[row][col]
  525. def force_color(self, val):
  526. run("g.region", rows=1, cols=1)
  527. run("r.mapcalc", expression="%s = %d" % (self.tempmap, val))
  528. run("r.colors", map=self.tempmap, rast=self.inmap)
  529. run("r.out.ppm", input=self.tempmap, out=self.tempfile)
  530. run("g.remove", flags="f", type="raster", name=self.tempmap)
  531. tempimg = wx.Image(self.tempfile)
  532. grass.try_remove(self.tempfile)
  533. rgb = tempimg.get(0, 0)
  534. color = "#%02x%02x%02x" % rgb
  535. self.colors[val] = color
  536. tempimg.delete()
  537. def get_color(self, val):
  538. if val not in self.colors:
  539. try:
  540. self.force_color(val)
  541. except:
  542. self.colors[val] = "#ffffff"
  543. return self.colors[val]
  544. def refresh_canvas(self):
  545. self.frame.canvas.Refresh()
  546. def make_ui(self):
  547. self.frame = MainWindow(self)
  548. self.SetTopWindow(self.frame)
  549. self.frame.Show()
  550. self.overview = OverviewWindow(self)
  551. self.overview.Show()
  552. def OnInit(self):
  553. self.outmap = self.options["output"]
  554. self.inmap = self.options["input"]
  555. self.aspect = self.options["aspect"]
  556. self.width = int(self.options["width"])
  557. self.height = int(self.options["height"])
  558. self.size = int(self.options["size"])
  559. self.rows = int(self.options["rows"])
  560. self.cols = int(self.options["cols"])
  561. self.status = {
  562. "row": "",
  563. "col": "",
  564. "x": "",
  565. "y": "",
  566. "value": "",
  567. "aspect": "",
  568. }
  569. self.values = None
  570. self.changed = None
  571. self.angles = None
  572. self.colors = {}
  573. self.brush = "*"
  574. self.origin_x = 0
  575. self.origin_y = 0
  576. self.wind = {}
  577. self.total = {}
  578. self.initialize()
  579. self.update_window()
  580. self.make_ui()
  581. self.load_map()
  582. self.load_aspect()
  583. self.refresh_canvas()
  584. return True
  585. return Application
  586. if __name__ == "__main__":
  587. options, flags = grass.parser()
  588. from gui_core.wrap import ClientDC, Menu, Panel
  589. Application = wxGUI()
  590. app = Application(options)
  591. app.MainLoop()