""" @package iclass.digit @brief wxIClass digitizer classes Classes: - digit::IClassVDigit - digit::IClassVDigitWindow (C) 2006-2012 by the GRASS Development Team This program is free software under the GNU General Public License (>=v2). Read the file COPYING that comes with GRASS for details. @author Vaclav Petras @author Anna Kratochvilova """ import wx from vdigit.mapwindow import VDigitWindow from vdigit.wxdigit import IVDigit from vdigit.wxdisplay import DisplayDriver, TYPE_AREA from core.gcmd import GWarning try: from grass.lib.gis import G_verbose, G_set_verbose from grass.lib.vector import * from grass.lib.vedit import * except ImportError: pass import grass.script as grass class IClassVDigitWindow(VDigitWindow): """Class similar to VDigitWindow but specialized for wxIClass.""" def __init__(self, parent, giface, map, properties): """ @a parent should has toolbar providing current class (category). :param parent: gui parent :param map: map renderer instance """ VDigitWindow.__init__( self, parent=parent, giface=giface, Map=map, properties=properties ) def _onLeftDown(self, event): action = self.toolbar.GetAction() if not action: return region = grass.region() e, n = self.Pixel2Cell(event.GetPosition()) if not ( (region["s"] <= n <= region["n"]) and (region["w"] <= e <= region["e"]) ): GWarning( parent=self.parent, message=_( "You are trying to create a training area " "outside the computational region. " "Please, use g.region to set the appropriate region first." ), ) return cat = self.GetCurrentCategory() if cat is None and action == "addLine": dlg = wx.MessageDialog( parent=self.parent, message=_( "In order to create a training area, " "you have to select class first.\n\n" "There is no class yet, " "do you want to create one?" ), caption=_("No class selected"), style=wx.YES_NO, ) if dlg.ShowModal() == wx.ID_YES: self.parent.OnCategoryManager(None) dlg.Destroy() event.Skip() return super(IClassVDigitWindow, self)._onLeftDown(event) def _addRecord(self): return False def _updateATM(self): pass def _onRightUp(self, event): super(IClassVDigitWindow, self)._onRightUp(event) self.parent.UpdateChangeState(changes=True) def GetCurrentCategory(self): """Returns current category (class). Category should be assigned to new features (areas). It is taken from parent's toolbar. """ return self.parent.GetToolbar("iClass").GetSelectedCategoryIdx() def GetCategoryColor(self, cat): """Get color associated with given category""" r, g, b = [int(x) for x in self.parent.GetClassColor(cat).split(":")][:3] return wx.Colour(r, g, b) class IClassVDigit(IVDigit): """Class similar to IVDigit but specialized for wxIClass.""" def __init__(self, mapwindow): IVDigit.__init__(self, mapwindow, driver=IClassDisplayDriver) self._settings["closeBoundary"] = True # snap to the first node def _getNewFeaturesLayer(self): return 1 def _getNewFeaturesCat(self): cat = self.mapWindow.GetCurrentCategory() return cat def DeleteAreasByCat(self, cats): """Delete areas (centroid+boundaries) by categories :param cats: list of categories """ for cat in cats: Vedit_delete_areas_cat(self.poMapInfo, 1, cat) def CopyMap(self, name, tmp=False, update=False): """Make a copy of open vector map Note: Attributes are not copied :param name: name for a copy :param tmp: True for temporary map :param bool update: True if copy target vector map (poMapInfoNew) exist :return: number of copied features :return: -1 on error """ if not self.poMapInfo: # nothing to copy return -1 poMapInfoNew = pointer(Map_info()) if not tmp: if update: open_fn = Vect_open_update else: open_fn = Vect_open_new else: if update: open_fn = Vect_open_tmp_update else: open_fn = Vect_open_tmp_new if update: if open_fn(poMapInfoNew, name, "") == -1: return -1 else: is3D = bool(Vect_is_3d(self.poMapInfo)) if open_fn(poMapInfoNew, name, is3D) == -1: return -1 verbose = G_verbose() G_set_verbose(-1) # be silent if Vect_copy_map_lines(self.poMapInfo, poMapInfoNew) == 1: G_set_verbose(verbose) return -1 Vect_build(poMapInfoNew) G_set_verbose(verbose) ret = Vect_get_num_lines(poMapInfoNew) Vect_close(poMapInfoNew) return ret def GetMapInfo(self): """Returns Map_info() struct of open vector map""" return self.poMapInfo class IClassDisplayDriver(DisplayDriver): """Class similar to DisplayDriver but specialized for wxIClass .. todo:: needs refactoring (glog, gprogress) """ def __init__(self, device, deviceTmp, mapObj, window, glog, gprogress): DisplayDriver.__init__(self, device, deviceTmp, mapObj, window, glog, gprogress) self._cat = -1 def _drawObject(self, robj): """Draw given object to the device :param robj: object to draw """ if robj.type == TYPE_AREA: self._cat = Vect_get_area_cat(self.poMapInfo, robj.fid, 1) elif robj.type == TYPE_CENTROIDIN: return # skip centroids DisplayDriver._drawObject(self, robj) def _definePen(self, rtype): """Define pen/brush based on rendered object) :param rtype: type of the object :return: pen, brush """ pen, brush = DisplayDriver._definePen(self, rtype) if self._cat > 0 and rtype == TYPE_AREA: brush = wx.Brush(self.window.GetCategoryColor(self._cat), wx.SOLID) return pen, brush def CloseMap(self): """Close training areas map - be quiet""" verbosity = G_verbose() G_set_verbose(0) DisplayDriver.CloseMap(self) G_set_verbose(verbosity)