digit.py 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239
  1. """
  2. @package iclass.digit
  3. @brief wxIClass digitizer classes
  4. Classes:
  5. - digit::IClassVDigit
  6. - digit::IClassVDigitWindow
  7. (C) 2006-2012 by the GRASS Development Team
  8. This program is free software under the GNU General Public
  9. License (>=v2). Read the file COPYING that comes with GRASS
  10. for details.
  11. @author Vaclav Petras <wenzeslaus gmail.com>
  12. @author Anna Kratochvilova <kratochanna gmail.com>
  13. """
  14. import wx
  15. from vdigit.mapwindow import VDigitWindow
  16. from vdigit.wxdigit import IVDigit
  17. from vdigit.wxdisplay import DisplayDriver, TYPE_AREA
  18. from core.gcmd import GWarning
  19. try:
  20. from grass.lib.gis import G_verbose, G_set_verbose
  21. from grass.lib.vector import *
  22. from grass.lib.vedit import *
  23. except ImportError:
  24. pass
  25. import grass.script as grass
  26. class IClassVDigitWindow(VDigitWindow):
  27. """Class similar to VDigitWindow but specialized for wxIClass."""
  28. def __init__(self, parent, giface, map, properties):
  29. """
  30. @a parent should has toolbar providing current class (category).
  31. :param parent: gui parent
  32. :param map: map renderer instance
  33. """
  34. VDigitWindow.__init__(
  35. self, parent=parent, giface=giface, Map=map, properties=properties
  36. )
  37. def _onLeftDown(self, event):
  38. action = self.toolbar.GetAction()
  39. if not action:
  40. return
  41. region = grass.region()
  42. e, n = self.Pixel2Cell(event.GetPosition())
  43. if not (
  44. (region["s"] <= n <= region["n"]) and (region["w"] <= e <= region["e"])
  45. ):
  46. GWarning(
  47. parent=self.parent,
  48. message=_(
  49. "You are trying to create a training area "
  50. "outside the computational region. "
  51. "Please, use g.region to set the appropriate region first."
  52. ),
  53. )
  54. return
  55. cat = self.GetCurrentCategory()
  56. if cat is None and action == "addLine":
  57. dlg = wx.MessageDialog(
  58. parent=self.parent,
  59. message=_(
  60. "In order to create a training area, "
  61. "you have to select class first.\n\n"
  62. "There is no class yet, "
  63. "do you want to create one?"
  64. ),
  65. caption=_("No class selected"),
  66. style=wx.YES_NO,
  67. )
  68. if dlg.ShowModal() == wx.ID_YES:
  69. self.parent.OnCategoryManager(None)
  70. dlg.Destroy()
  71. event.Skip()
  72. return
  73. super(IClassVDigitWindow, self)._onLeftDown(event)
  74. def _addRecord(self):
  75. return False
  76. def _updateATM(self):
  77. pass
  78. def _onRightUp(self, event):
  79. super(IClassVDigitWindow, self)._onRightUp(event)
  80. self.parent.UpdateChangeState(changes=True)
  81. def GetCurrentCategory(self):
  82. """Returns current category (class).
  83. Category should be assigned to new features (areas).
  84. It is taken from parent's toolbar.
  85. """
  86. return self.parent.GetToolbar("iClass").GetSelectedCategoryIdx()
  87. def GetCategoryColor(self, cat):
  88. """Get color associated with given category"""
  89. r, g, b = [int(x) for x in self.parent.GetClassColor(cat).split(":")][:3]
  90. return wx.Colour(r, g, b)
  91. class IClassVDigit(IVDigit):
  92. """Class similar to IVDigit but specialized for wxIClass."""
  93. def __init__(self, mapwindow):
  94. IVDigit.__init__(self, mapwindow, driver=IClassDisplayDriver)
  95. self._settings["closeBoundary"] = True # snap to the first node
  96. def _getNewFeaturesLayer(self):
  97. return 1
  98. def _getNewFeaturesCat(self):
  99. cat = self.mapWindow.GetCurrentCategory()
  100. return cat
  101. def DeleteAreasByCat(self, cats):
  102. """Delete areas (centroid+boundaries) by categories
  103. :param cats: list of categories
  104. """
  105. for cat in cats:
  106. Vedit_delete_areas_cat(self.poMapInfo, 1, cat)
  107. def CopyMap(self, name, tmp=False, update=False):
  108. """Make a copy of open vector map
  109. Note: Attributes are not copied
  110. :param name: name for a copy
  111. :param tmp: True for temporary map
  112. :param bool update: True if copy target vector map (poMapInfoNew)
  113. exist
  114. :return: number of copied features
  115. :return: -1 on error
  116. """
  117. if not self.poMapInfo:
  118. # nothing to copy
  119. return -1
  120. poMapInfoNew = pointer(Map_info())
  121. if not tmp:
  122. if update:
  123. open_fn = Vect_open_update
  124. else:
  125. open_fn = Vect_open_new
  126. else:
  127. if update:
  128. open_fn = Vect_open_tmp_update
  129. else:
  130. open_fn = Vect_open_tmp_new
  131. if update:
  132. if open_fn(poMapInfoNew, name, "") == -1:
  133. return -1
  134. else:
  135. is3D = bool(Vect_is_3d(self.poMapInfo))
  136. if open_fn(poMapInfoNew, name, is3D) == -1:
  137. return -1
  138. verbose = G_verbose()
  139. G_set_verbose(-1) # be silent
  140. if Vect_copy_map_lines(self.poMapInfo, poMapInfoNew) == 1:
  141. G_set_verbose(verbose)
  142. return -1
  143. Vect_build(poMapInfoNew)
  144. G_set_verbose(verbose)
  145. ret = Vect_get_num_lines(poMapInfoNew)
  146. Vect_close(poMapInfoNew)
  147. return ret
  148. def GetMapInfo(self):
  149. """Returns Map_info() struct of open vector map"""
  150. return self.poMapInfo
  151. class IClassDisplayDriver(DisplayDriver):
  152. """Class similar to DisplayDriver but specialized for wxIClass
  153. .. todo::
  154. needs refactoring (glog, gprogress)
  155. """
  156. def __init__(self, device, deviceTmp, mapObj, window, glog, gprogress):
  157. DisplayDriver.__init__(self, device, deviceTmp, mapObj, window, glog, gprogress)
  158. self._cat = -1
  159. def _drawObject(self, robj):
  160. """Draw given object to the device
  161. :param robj: object to draw
  162. """
  163. if robj.type == TYPE_AREA:
  164. self._cat = Vect_get_area_cat(self.poMapInfo, robj.fid, 1)
  165. elif robj.type == TYPE_CENTROIDIN:
  166. return # skip centroids
  167. DisplayDriver._drawObject(self, robj)
  168. def _definePen(self, rtype):
  169. """Define pen/brush based on rendered object)
  170. :param rtype: type of the object
  171. :return: pen, brush
  172. """
  173. pen, brush = DisplayDriver._definePen(self, rtype)
  174. if self._cat > 0 and rtype == TYPE_AREA:
  175. brush = wx.Brush(self.window.GetCategoryColor(self._cat), wx.SOLID)
  176. return pen, brush
  177. def CloseMap(self):
  178. """Close training areas map - be quiet"""
  179. verbosity = G_verbose()
  180. G_set_verbose(0)
  181. DisplayDriver.CloseMap(self)
  182. G_set_verbose(verbosity)