def __init__(self, parent, giface, Map, properties, tree=None, id=wx.ID_ANY, lmgr=None, style=wx.NO_FULL_REPAINT_ON_RESIZE, **kwargs): BufferedMapWindow.__init__(self, parent=parent, giface=giface, Map=Map, properties=properties, style=style, **kwargs) self.lmgr = lmgr self.tree = tree self.pdcVector = PseudoDC() self.toolbar = self.parent.GetToolbar('vdigit') self.digit = None # wxvdigit.IVDigit self._digitizingInfo = False # digitizing with info # Emitted when info about digitizing updated # Parameter text is a string with information # currently used only for coordinates of mouse cursor + segmnt and # total feature length self.digitizingInfo = Signal('VDigitWindow.digitizingInfo') # Emitted when some info about digitizing is or will be availbale self.digitizingInfoAvailable = Signal('VDigitWindow.digitizingInfo') # Emitted when some info about digitizing is or will be availbale # digitizingInfo signal is emmited only between digitizingInfoAvailable # and digitizingInfoUnavailable signals self.digitizingInfoUnavailable = Signal('VDigitWindow.digitizingInfo') self.Bind(wx.EVT_KEY_DOWN, self.OnKeyDown) self.mouseMoving.connect(self._mouseMovingToDigitizingInfo)
def __init__( self, parent, id=wx.ID_ANY, style=wx.NO_FULL_REPAINT_ON_RESIZE, Map=None, **kwargs, ): wx.Window.__init__(self, parent, id=id, style=style, **kwargs) self.parent = parent self.Map = Map self.mapname = self.parent.mapname # # Flags # self.render = True # re-render the map from GRASS or just redraw image self.resize = False # indicates whether or not a resize event has taken place self.dragimg = None # initialize variable for map panning self.pen = None # pen for drawing zoom boxes, etc. self._oldfont = self._oldencoding = None # # Event bindings # self.Bind(wx.EVT_PAINT, self.OnPaint) self.Bind(wx.EVT_SIZE, self.OnSize) self.Bind(wx.EVT_IDLE, self.OnIdle) # # Render output objects # self.mapfile = None # image file to be rendered self.img = None # wx.Image object (self.mapfile) self.imagedict = { } # images and their PseudoDC ID's for painting and dragging self.pdc = PseudoDC() # will store an off screen empty bitmap for saving to file self._buffer = EmptyBitmap(max(1, self.Map.width), max(1, self.Map.height)) # make sure that extents are updated at init self.Map.region = self.Map.GetRegion() self.Map.SetRegion() self._finishRenderingInfo = None self.Bind(wx.EVT_ERASE_BACKGROUND, lambda x: None)
def __init__(self, parent, id=wx.ID_ANY, style=wx.DEFAULT_FRAME_STYLE | wx.FULL_REPAINT_ON_RESIZE | wx.BORDER_RAISED): Debug.msg(2, "AnimationWindow.__init__()") self.bitmap = EmptyBitmap(1, 1) self.parent = parent self._pdc = PseudoDC() self._overlay = None self._tmpMousePos = None self.x = self.y = 0 self.bitmap_overlay = None BufferedWindow.__init__(self, parent=parent, id=id, style=style) self.SetBackgroundColour(wx.BLACK) self.SetBackgroundStyle(wx.BG_STYLE_CUSTOM) self.Bind(wx.EVT_SIZE, self.OnSize) self.Bind(wx.EVT_MOUSE_EVENTS, self.OnMouseEvents)
class AnimationWindow(BufferedWindow): def __init__(self, parent, id=wx.ID_ANY, style=wx.DEFAULT_FRAME_STYLE | wx.FULL_REPAINT_ON_RESIZE | wx.BORDER_RAISED): Debug.msg(2, "AnimationWindow.__init__()") self.bitmap = EmptyBitmap(1, 1) self.parent = parent self._pdc = PseudoDC() self._overlay = None self._tmpMousePos = None self.x = self.y = 0 self.bitmap_overlay = None BufferedWindow.__init__(self, parent=parent, id=id, style=style) self.SetBackgroundColour(wx.BLACK) self.SetBackgroundStyle(wx.BG_STYLE_CUSTOM) self.Bind(wx.EVT_SIZE, self.OnSize) self.Bind(wx.EVT_MOUSE_EVENTS, self.OnMouseEvents) def Draw(self, dc): """Draws bitmap.""" Debug.msg(5, "AnimationWindow.Draw()") dc.Clear() # make sure you clear the bitmap! if self.bitmap.GetWidth() > 1: dc.DrawBitmap(self.bitmap, x=self.x, y=self.y) def OnSize(self, event): Debug.msg(5, "AnimationWindow.OnSize()") BufferedWindow.OnSize(self, event) if event: event.Skip() def _rescaleIfNeeded(self, bitmap): """!If the bitmap has different size than the window, rescale it.""" bW, bH = bitmap.GetSize() wW, wH = self.GetClientSize() if abs(bW - wW) > 5 or abs(bH - wH) > 5: params = ComputeScaledRect((bW, bH), (wW, wH)) im = wx.ImageFromBitmap(bitmap) im.Rescale(params['width'], params['height']) self.x = params['x'] self.y = params['y'] bitmap = wx.BitmapFromImage(im) if self._overlay: im = wx.ImageFromBitmap(self.bitmap_overlay) im.Rescale( im.GetWidth() * params['scale'], im.GetHeight() * params['scale']) self._setOverlay( wx.BitmapFromImage(im), xperc=self.perc[0], yperc=self.perc[1]) else: self.x = 0 self.y = 0 return bitmap def DrawBitmap(self, bitmap): """Draws bitmap. Does not draw the bitmap if it is the same one as last time. """ bitmap = self._rescaleIfNeeded(bitmap) if self.bitmap == bitmap: return self.bitmap = bitmap self.UpdateDrawing() def DrawOverlay(self, x, y): self._pdc.BeginDrawing() self._pdc.SetId(1) self._pdc.DrawBitmap(bmp=self._overlay, x=x, y=y) self._pdc.SetIdBounds(1, Rect(x, y, self._overlay.GetWidth(), self._overlay.GetHeight())) self._pdc.EndDrawing() def _setOverlay(self, bitmap, xperc, yperc): if self._overlay: self._pdc.RemoveAll() self._overlay = bitmap size = self.GetClientSize() x = xperc * size[0] y = yperc * size[1] self.DrawOverlay(x, y) def SetOverlay(self, bitmap, xperc, yperc): """Sets overlay bitmap (legend) :param bitmap: instance of wx.Bitmap :param xperc: x coordinate of bitmap top left corner in % of screen :param yperc: y coordinate of bitmap top left corner in % of screen """ Debug.msg(3, "AnimationWindow.SetOverlay()") if bitmap: self._setOverlay(bitmap, xperc, yperc) self.bitmap_overlay = bitmap self.perc = (xperc, yperc) else: self._overlay = None self._pdc.RemoveAll() self.bitmap_overlay = None self.UpdateDrawing() def ClearOverlay(self): """Clear overlay (legend) """ Debug.msg(3, "AnimationWindow.ClearOverlay()") self._overlay = None self.bitmap_overlay = None self._pdc.RemoveAll() self.UpdateDrawing() def OnPaint(self, event): Debug.msg(5, "AnimationWindow.OnPaint()") # All that is needed here is to draw the buffer to screen dc = wx.BufferedPaintDC(self, self._Buffer) if self._overlay: self._pdc.DrawToDC(dc) def OnMouseEvents(self, event): """Handle mouse events.""" # If it grows larger, split it. current = event.GetPosition() if event.LeftDown(): self._dragid = None idlist = self._pdc.FindObjects(current[0], current[1], radius=10) if 1 in idlist: self._dragid = 1 self._tmpMousePos = current elif event.LeftUp(): self._dragid = None self._tmpMousePos = None elif event.Dragging(): if self._dragid is None: return dx = current[0] - self._tmpMousePos[0] dy = current[1] - self._tmpMousePos[1] self._pdc.TranslateId(self._dragid, dx, dy) self.UpdateDrawing() self._tmpMousePos = current def GetOverlayPos(self): """Returns x, y position in pixels""" rect = self._pdc.GetIdBounds(1) return rect.GetX(), rect.GetY()
class BufferedWindow(wx.Window): """A Buffered window class. When the drawing needs to change, you app needs to call the UpdateHist() method. Since the drawing is stored in a bitmap, you can also save the drawing to file by calling the SaveToFile(self,file_name,file_type) method. """ def __init__(self, parent, id=wx.ID_ANY, style=wx.NO_FULL_REPAINT_ON_RESIZE, Map=None, **kwargs): wx.Window.__init__(self, parent, id=id, style=style, **kwargs) self.parent = parent self.Map = Map self.mapname = self.parent.mapname # # Flags # self.render = True # re-render the map from GRASS or just redraw image self.resize = False # indicates whether or not a resize event has taken place self.dragimg = None # initialize variable for map panning self.pen = None # pen for drawing zoom boxes, etc. self._oldfont = self._oldencoding = None # # Event bindings # self.Bind(wx.EVT_PAINT, self.OnPaint) self.Bind(wx.EVT_SIZE, self.OnSize) self.Bind(wx.EVT_IDLE, self.OnIdle) # # Render output objects # self.mapfile = None # image file to be rendered self.img = None # wx.Image object (self.mapfile) self.imagedict = { } # images and their PseudoDC ID's for painting and dragging self.pdc = PseudoDC() # will store an off screen empty bitmap for saving to file self._buffer = EmptyBitmap(max(1, self.Map.width), max(1, self.Map.height)) # make sure that extents are updated at init self.Map.region = self.Map.GetRegion() self.Map.SetRegion() self._finishRenderingInfo = None self.Bind(wx.EVT_ERASE_BACKGROUND, lambda x: None) def Draw(self, pdc, img=None, drawid=None, pdctype='image', coords=[0, 0, 0, 0]): """Draws histogram or clears window """ if drawid is None: if pdctype == 'image': drawid = self.imagedict[img] elif pdctype == 'clear': drawid is None else: drawid = NewId() else: pdc.SetId(drawid) pdc.BeginDrawing() Debug.msg( 3, "BufferedWindow.Draw(): id=%s, pdctype=%s, coord=%s" % (drawid, pdctype, coords)) if pdctype == 'clear': # erase the display bg = wx.WHITE_BRUSH pdc.SetBackground(bg) pdc.Clear() self.Refresh() pdc.EndDrawing() return if pdctype == 'image': bg = wx.TRANSPARENT_BRUSH pdc.SetBackground(bg) bitmap = BitmapFromImage(img) w, h = bitmap.GetSize() pdc.DrawBitmap(bitmap, coords[0], coords[1], True) # draw the composite map pdc.SetIdBounds(drawid, (coords[0], coords[1], w, h)) pdc.EndDrawing() self.Refresh() def OnPaint(self, event): """Draw psuedo DC to buffer """ dc = wx.BufferedPaintDC(self, self._buffer) # use PrepareDC to set position correctly # probably does nothing, removed from wxPython 2.9 # self.PrepareDC(dc) # we need to clear the dc BEFORE calling PrepareDC bg = wx.Brush(self.GetBackgroundColour()) dc.SetBackground(bg) dc.Clear() # create a clipping rect from our position and size # and the Update Region rgn = self.GetUpdateRegion() r = rgn.GetBox() # draw to the dc using the calculated clipping rect self.pdc.DrawToDCClipped(dc, r) def OnSize(self, event): """Init image size to match window size """ # set size of the input image self.Map.width, self.Map.height = self.GetClientSize() # Make new off screen bitmap: this bitmap will always have the # current drawing in it, so it can be used to save the image to # a file, or whatever. self._buffer = EmptyBitmap(self.Map.width, self.Map.height) # get the image to be rendered self.img = self.GetImage() # update map display if self.img and self.Map.width + self.Map.height > 0: # scale image during resize self.img = self.img.Scale(self.Map.width, self.Map.height) self.render = False self.UpdateHist() # re-render image on idle self.resize = True def OnIdle(self, event): """Only re-render a histogram image from GRASS during idle time instead of multiple times during resizing. """ if self.resize: self.render = True self.UpdateHist() event.Skip() def SaveToFile(self, FileName, FileType, width, height): """This will save the contents of the buffer to the specified file. See the wx.Windows docs for wx.Bitmap::SaveFile for the details """ wx.GetApp().Yield() self._finishRenderingInfo = (FileName, FileType, width, height) self.Map.GetRenderMgr().updateMap.connect(self._finishSaveToFile) self.Map.ChangeMapSize((width, height)) self.Map.Render(force=True, windres=True) def _finishSaveToFile(self): img = self.GetImage() self.Draw(self.pdc, img, drawid=99) FileName, FileType, width, height = self._finishRenderingInfo ibuffer = EmptyBitmap(max(1, width), max(1, height)) dc = wx.BufferedDC(None, ibuffer) dc.Clear() self.pdc.DrawToDC(dc) ibuffer.SaveFile(FileName, FileType) self.Map.GetRenderMgr().updateMap.disconnect(self._finishSaveToFile) self._finishRenderingInfo = None def GetImage(self): """Converts files to wx.Image """ if self.Map.mapfile and os.path.isfile(self.Map.mapfile) and \ os.path.getsize(self.Map.mapfile): img = wx.Image(self.Map.mapfile, wx.BITMAP_TYPE_ANY) else: img = None self.imagedict[img] = 99 # set image PeudoDC ID return img def UpdateHist(self, img=None): """Update canvas if histogram options changes or window changes geometry """ Debug.msg( 2, "BufferedWindow.UpdateHist(%s): render=%s" % (img, self.render)) if not self.render: return # render new map images # set default font and encoding environmental variables if "GRASS_FONT" in os.environ: self._oldfont = os.environ["GRASS_FONT"] if self.parent.font: os.environ["GRASS_FONT"] = self.parent.font if "GRASS_ENCODING" in os.environ: self._oldencoding = os.environ["GRASS_ENCODING"] if self.parent.encoding is not None and self.parent.encoding != "ISO-8859-1": os.environ["GRASS_ENCODING"] = self.parent.encoding # using active comp region self.Map.GetRegion(update=True) self.Map.width, self.Map.height = self.GetClientSize() self.mapfile = self.Map.Render(force=self.render) self.Map.GetRenderMgr().renderDone.connect(self.UpdateHistDone) def UpdateHistDone(self): """Histogram image generated, finish rendering.""" self.img = self.GetImage() self.resize = False if not self.img: return try: id = self.imagedict[self.img] except: return # paint images to PseudoDC self.pdc.Clear() self.pdc.RemoveAll() self.Draw(self.pdc, self.img, drawid=id) # draw map image background self.resize = False # update statusbar self.Map.SetRegion() self.parent.statusbar.SetStatusText("Image/Raster map <%s>" % self.parent.mapname) # set default font and encoding environmental variables if self._oldfont: os.environ["GRASS_FONT"] = self._oldfont if self._oldencoding: os.environ["GRASS_ENCODING"] = self._oldencoding def EraseMap(self): """Erase the map display """ self.Draw(self.pdc, pdctype='clear')
def StartEditing(self, mapLayer): """Start editing selected vector map layer. :param mapLayer: MapLayer to be edited """ # check if topology is available (skip for hidden - temporary # maps, see iclass for details) if ( not mapLayer.IsHidden() and grass.vector_info(mapLayer.GetName())["level"] != 2 ): dlg = wx.MessageDialog( parent=self.MapWindow, message=_( "Topology for vector map <%s> is not available. " "Topology is required by digitizer.\nDo you want to " "rebuild topology (takes some time) and open the vector map " "for editing?" ) % mapLayer.GetName(), caption=_("Digitizer error"), style=wx.YES_NO | wx.YES_DEFAULT | wx.ICON_QUESTION | wx.CENTRE, ) if dlg.ShowModal() == wx.ID_YES: RunCommand("v.build", map=mapLayer.GetName()) else: return # deactive layer self.Map.ChangeLayerActive(mapLayer, False) # clean map canvas self.MapWindow.EraseMap() # unset background map if needed if mapLayer: if ( UserSettings.Get( group="vdigit", key="bgmap", subkey="value", settings_type="internal", ) == mapLayer.GetName() ): UserSettings.Set( group="vdigit", key="bgmap", subkey="value", value="", settings_type="internal", ) self.parent.SetStatusText( _("Please wait, " "opening vector map <%s> for editing...") % mapLayer.GetName(), 0, ) self.MapWindow.pdcVector = PseudoDC() self.digit = self.MapWindow.digit = self.digitClass(mapwindow=self.MapWindow) self.mapLayer = mapLayer # open vector map (assume that 'hidden' map layer is temporary vector # map) if self.digit.OpenMap(mapLayer.GetName(), tmp=mapLayer.IsHidden()) is None: self.mapLayer = None self.StopEditing() return False # check feature type (only for OGR layers) self.fType = self.digit.GetFeatureType() self.EnableAll() self.EnableUndo(False) self.EnableRedo(False) if self.fType == "point": for tool in ( self.addLine, self.addArea, self.moveVertex, self.addVertex, self.removeVertex, self.editLine, ): self.EnableTool(tool, False) elif self.fType == "linestring": for tool in (self.addPoint, self.addArea): self.EnableTool(tool, False) elif self.fType == "polygon": for tool in (self.addPoint, self.addLine): self.EnableTool(tool, False) elif self.fType: GError( parent=self, message=_( "Unsupported feature type '%(type)s'. Unable to edit " "OGR layer <%(layer)s>." ) % {"type": self.fType, "layer": mapLayer.GetName()}, ) self.digit.CloseMap() self.mapLayer = None self.StopEditing() return False # update toolbar if self.combo: self.combo.SetValue(mapLayer.GetName()) if "map" in self.parent.toolbars: self.parent.toolbars["map"].combo.SetValue(_("Vector digitizer")) # here was dead code to enable vdigit button in toolbar # with if to ignore iclass # some signal (DigitizerStarted) can be emitted here Debug.msg(4, "VDigitToolbar.StartEditing(): layer=%s" % mapLayer.GetName()) # change cursor if self.MapWindow.mouse["use"] == "pointer": self.MapWindow.SetNamedCursor("cross") if not self.MapWindow.resize: self.MapWindow.UpdateMap(render=True) # respect opacity opacity = mapLayer.GetOpacity() if opacity < 1.0: alpha = int(opacity * 255) self.digit.GetDisplay().UpdateSettings(alpha=alpha) # emit signal layerTree = self._giface.GetLayerTree() if layerTree: item = layerTree.FindItemByData("maplayer", self.mapLayer) else: item = None self.editingStarted.emit( vectMap=mapLayer.GetName(), digit=self.digit, layerItem=item ) return True
class VDigitWindow(BufferedMapWindow): """A Buffered window extended for vector digitizer.""" def __init__( self, parent, giface, Map, properties, tree=None, id=wx.ID_ANY, lmgr=None, style=wx.NO_FULL_REPAINT_ON_RESIZE, **kwargs, ): BufferedMapWindow.__init__( self, parent=parent, giface=giface, Map=Map, properties=properties, style=style, **kwargs, ) self.lmgr = lmgr self.tree = tree self.pdcVector = PseudoDC() self.toolbar = self.parent.GetToolbar("vdigit") self.digit = None # wxvdigit.IVDigit self._digitizingInfo = False # digitizing with info # Emitted when info about digitizing updated # Parameter text is a string with information # currently used only for coordinates of mouse cursor + segmnt and # total feature length self.digitizingInfo = Signal("VDigitWindow.digitizingInfo") # Emitted when some info about digitizing is or will be availbale self.digitizingInfoAvailable = Signal("VDigitWindow.digitizingInfo") # Emitted when some info about digitizing is or will be availbale # digitizingInfo signal is emitted only between digitizingInfoAvailable # and digitizingInfoUnavailable signals self.digitizingInfoUnavailable = Signal("VDigitWindow.digitizingInfo") self.Bind(wx.EVT_KEY_DOWN, self.OnKeyDown) self.mouseMoving.connect(self._mouseMovingToDigitizingInfo) def GetDisplay(self): if self.digit: return self.digit.GetDisplay() return None def GetDigit(self): """Get digit class""" return self.digit def SetToolbar(self, toolbar): """Set up related toolbar""" self.toolbar = toolbar def _mouseMovingToDigitizingInfo(self, x, y): e, n = x, y precision = int( UserSettings.Get(group="projection", key="format", subkey="precision") ) if ( self.toolbar.GetAction() != "addLine" or self.toolbar.GetAction("type") not in ("line", "boundary") or len(self.polycoords) == 0 ): # we cannot provide info, so find out if it is something new if self._digitizingInfo: self._digitizingInfo = False self.digitizingInfoUnavailable.emit() return # else, we can provide info, so find out if it is first time if not self._digitizingInfo: self._digitizingInfo = True self.digitizingInfoAvailable.emit() # for linear feature show segment and total length distance_seg = self.Distance(self.polycoords[-1], (e, n), screen=False)[0] distance_tot = distance_seg for idx in range(1, len(self.polycoords)): distance_tot += self.Distance( self.polycoords[idx - 1], self.polycoords[idx], screen=False )[0] text = "seg: %.*f; tot: %.*f" % ( precision, distance_seg, precision, distance_tot, ) self.digitizingInfo.emit(text=text) def OnKeyDown(self, event): """Key pressed""" shift = event.ShiftDown() kc = event.GetKeyCode() event = None if not shift: if kc == ord("P"): event = wx.CommandEvent(winid=self.toolbar.addPoint) tool = self.toolbar.OnAddPoint elif kc == ord("L"): event = wx.CommandEvent(winid=self.toolbar.addLine) tool = self.toolbar.OnAddLine if event: self.toolbar.OnTool(event) tool(event) def _updateMap(self): if not self.toolbar or not self.toolbar.GetLayer(): return # set region self.digit.GetDisplay().UpdateRegion() # re-calculate threshold for digitization tool # self.parent.digit.GetDisplay().GetThreshold() # draw map # self.pdcVector.Clear() self.pdcVector.RemoveAll() item = None if self.tree: try: item = self.tree.FindItemByData("maplayer", self.toolbar.GetLayer()) except TypeError: pass if not self.tree or (self.tree and item and self.tree.IsItemChecked(item)): self.redrawAll = True self.digit.GetDisplay().DrawMap() # translate tmp objects (pointer position) if self.toolbar.GetAction() == "moveLine" and hasattr(self, "moveInfo"): if "beginDiff" in self.moveInfo: # move line for id in self.moveInfo["id"]: self.pdcTmp.TranslateId( id, self.moveInfo["beginDiff"][0], self.moveInfo["beginDiff"][1] ) del self.moveInfo["beginDiff"] def OnLeftDownAddLine(self, event): """Left mouse button pressed - add new feature""" try: mapLayer = self.toolbar.GetLayer().GetName() except: return if self.toolbar.GetAction("type") in ["point", "centroid"]: # add new point / centroiud east, north = self.Pixel2Cell(self.mouse["begin"]) nfeat, fids = self.digit.AddFeature( self.toolbar.GetAction("type"), [(east, north)] ) if nfeat < 1: return self.UpdateMap(render=False) # redraw map # add new record into attribute table if UserSettings.Get(group="vdigit", key="addRecord", subkey="enabled"): # select attributes based on layer and category cats = { fids[0]: { UserSettings.Get(group="vdigit", key="layer", subkey="value"): ( UserSettings.Get( group="vdigit", key="category", subkey="value" ), ) } } posWindow = self.ClientToScreen( ( self.mouse["end"][0] + self.dialogOffset, self.mouse["end"][1] + self.dialogOffset, ) ) addRecordDlg = DisplayAttributesDialog( parent=self, map=mapLayer, cats=cats, pos=posWindow, action="add", ignoreError=True, ) if self.toolbar.GetAction("type") == "centroid": for fid in fids: self._geomAttrb(fid, addRecordDlg, "area") self._geomAttrb(fid, addRecordDlg, "perimeter") if addRecordDlg.IsFound(): addRecordDlg.ShowModal() addRecordDlg.Destroy() elif self.toolbar.GetAction("type") in ["line", "boundary", "area"]: # add new point to the line self.polycoords.append(self.Pixel2Cell(event.GetPosition())) self.DrawLines(pdc=self.pdcTmp) def _geomAttrb(self, fid, dialog, attrb): """Define geometry attributes""" mapLayer = self.toolbar.GetLayer() if self.tree: item = self.tree.FindItemByData("maplayer", mapLayer) vdigit = self.tree.GetLayerInfo(item, key="vdigit") else: item = vdigit = None if not vdigit or "geomAttr" not in vdigit or attrb not in vdigit["geomAttr"]: return val = -1 if attrb == "length": val = self.digit.GetLineLength(fid) type = attrb elif attrb == "area": val = self.digit.GetAreaSize(fid) type = attrb elif attrb == "perimeter": val = self.digit.GetAreaPerimeter(fid) type = "length" if val > 0: layer = int(UserSettings.Get(group="vdigit", key="layer", subkey="value")) column = vdigit["geomAttr"][attrb]["column"] val = UnitsConvertValue(val, type, vdigit["geomAttr"][attrb]["units"]) dialog.SetColumnValue(layer, column, val) dialog.OnReset() def _geomAttrbUpdate(self, fids): """Update geometry atrributes of currently selected features :param fid: list feature id """ mapLayer = self.parent.toolbars["vdigit"].GetLayer() vectorName = mapLayer.GetName() if self.tree: item = self.tree.FindItemByData("maplayer", mapLayer) vdigit = self.tree.GetLayerInfo(item, key="vdigit") else: item = vdigit = None if not vdigit or "geomAttr" not in vdigit: return dbInfo = gselect.VectorDBInfo(vectorName) sqlfile = tempfile.NamedTemporaryFile(mode="w") for fid in fids: for layer, cats in six.iteritems(self.digit.GetLineCats(fid)): table = dbInfo.GetTable(layer) for attrb, item in six.iteritems(vdigit["geomAttr"]): val = -1 if attrb == "length": val = self.digit.GetLineLength(fid) type = attrb elif attrb == "area": val = self.digit.GetAreaSize(fid) type = attrb elif attrb == "perimeter": val = self.digit.GetAreaPerimeter(fid) type = "length" if val < 0: continue val = UnitsConvertValue(val, type, item["units"]) for cat in cats: sqlfile.write( "UPDATE %s SET %s = %f WHERE %s = %d;\n" % ( table, item["column"], val, dbInfo.GetKeyColumn(layer), cat, ) ) sqlfile.file.flush() RunCommand("db.execute", parent=True, quiet=True, input=sqlfile.name) def _updateATM(self): """Update open Attribute Table Manager .. todo:: use AddDataRow() instead """ if not self.lmgr: return # update ATM digitVector = self.toolbar.GetLayer().GetName() for atm in self.lmgr.dialogs["atm"]: atmVector = atm.GetVectorName() if atmVector == digitVector: layer = UserSettings.Get(group="vdigit", key="layer", subkey="value") # TODO: use AddDataRow instead atm.LoadData(layer) def OnLeftDownEditLine(self, event): """Left mouse button pressed - edit linear feature - add new vertex. """ self.polycoords.append(self.Pixel2Cell(self.mouse["begin"])) self.moveInfo["id"].append(NewId()) self.DrawLines(pdc=self.pdcTmp) def OnLeftDownMoveLine(self, event): """Left mouse button pressed - vector digitizer move feature/vertex, edit linear feature """ self.moveInfo = dict() # geographic coordinates of initial position (left-down) self.moveInfo["begin"] = None # list of ids to modify self.moveInfo["id"] = list() # set pen if self.toolbar.GetAction() in ["moveVertex", "editLine"]: pcolor = UserSettings.Get( group="vdigit", key="symbol", subkey=["highlight", "color"] ) self.pen = self.polypen = wx.Pen( colour=pcolor, width=2, style=wx.SHORT_DASH ) self.pdcTmp.SetPen(self.polypen) def OnLeftDownDisplayCA(self, event): """Left mouse button pressed - vector digitizer display categories or attributes action """ try: mapLayer = self.toolbar.GetLayer().GetName() except: return coords = self.Pixel2Cell(self.mouse["begin"]) # unselect self.digit.GetDisplay().SetSelected([]) # select feature by point cats = {} self.digit.GetDisplay().SelectLineByPoint(coords) if not self.digit.GetDisplay().GetSelected(): for key in ("attributes", "category"): if self.parent.dialogs[key] and self.parent.dialogs[key].IsShown(): self.parent.dialogs[key].Hide() self.UpdateMap(render=False, renderVector=True) return if UserSettings.Get(group="vdigit", key="checkForDupl", subkey="enabled"): lines = self.digit.GetDisplay().GetSelected() else: lines = (self.digit.GetDisplay().GetSelected()[0],) # only first found for line in lines: cats[line] = self.digit.GetLineCats(line) posWindow = self.ClientToScreen( ( self.mouse["end"][0] + self.dialogOffset, self.mouse["end"][1] + self.dialogOffset, ) ) if self.toolbar.GetAction() == "displayAttrs": # select attributes based on coordinates (all layers) if self.parent.dialogs["attributes"] is None: self.parent.dialogs["attributes"] = DisplayAttributesDialog( parent=self, map=mapLayer, cats=cats, action="update" ) else: # upgrade dialog self.parent.dialogs["attributes"].UpdateDialog(cats=cats) if ( self.parent.dialogs["attributes"] and self.parent.dialogs["attributes"].mapDBInfo ): if len(cats.keys()) > 0: # highlight feature & re-draw map if not self.parent.dialogs["attributes"].IsShown(): self.parent.dialogs["attributes"].Show() else: if ( self.parent.dialogs["attributes"] and self.parent.dialogs["attributes"].IsShown() ): self.parent.dialogs["attributes"].Hide() else: # displayCats if self.parent.dialogs["category"] is None: # open new dialog dlg = VDigitCategoryDialog( parent=self, vectorName=mapLayer, cats=cats, pos=posWindow, title=_("Update categories"), ) self.parent.dialogs["category"] = dlg else: # update currently open dialog self.parent.dialogs["category"].UpdateDialog(cats=cats) if self.parent.dialogs["category"]: if len(cats.keys()) > 0: # highlight feature & re-draw map if not self.parent.dialogs["category"].IsShown(): self.parent.dialogs["category"].Show() else: if self.parent.dialogs["category"].IsShown(): self.parent.dialogs["category"].Hide() self.UpdateMap(render=False, renderVector=True) def OnLeftDownCopyCA(self, event): """Left mouse button pressed - vector digitizer copy categories or attributes action """ if not hasattr(self, "copyCatsList"): self.copyCatsList = [] else: self.copyCatsIds = [] self.mouse["box"] = "box" def OnLeftDownCopyLine(self, event): """Left mouse button pressed - vector digitizer copy lines action """ if not hasattr(self, "copyIds"): self.copyIds = [] self.layerTmp = None def OnLeftDownBulkLine(self, event): """Left mouse button pressed - vector digitizer label 3D vector lines """ if len(self.polycoords) > 1: # start new line self.polycoords = [] self.ClearLines(pdc=self.pdcTmp) self.polycoords.append(self.Pixel2Cell(event.GetPosition())) if len(self.polycoords) == 1: begin = self.Pixel2Cell(self.polycoords[-1]) end = self.Pixel2Cell(self.mouse["end"]) else: end = self.Pixel2Cell(self.polycoords[-1]) begin = self.Pixel2Cell(self.mouse["begin"]) self.DrawLines(self.pdcTmp, polycoords=(begin, end)) def OnLeftDownUndo(self, event): """Left mouse button pressed with control key - vector digitizer undo functionality """ if self.mouse["use"] != "pointer" or not self.toolbar: return action = self.toolbar.GetAction() if ( action == "addLine" and self.toolbar.GetAction("type") in ["line", "boundary", "area"] ) or action == "editLine": # add line or boundary -> remove last point from the line try: removed = self.polycoords.pop() Debug.msg( 4, "VDigitWindow.OnMiddleDown(): polycoords_poped=%s" % [ removed, ], ) # self.mouse['begin'] = self.Cell2Pixel(self.polycoords[-1]) except: pass if action == "editLine": # remove last vertex & line if len(self.moveInfo["id"]) > 1: self.moveInfo["id"].pop() self.UpdateMap(render=False, renderVector=False) elif action in [ "deleteLine", "deleteArea", "moveLine", "splitLine", "addVertex", "removeVertex", "moveVertex", "copyCats", "flipLine", "mergeLine", "snapLine", "connectLine", "copyLine", "queryLine", "breakLine", "typeConv", ]: # various tools -> unselected selected features self.digit.GetDisplay().SetSelected([]) if action in ["moveLine", "moveVertex", "editLine"] and hasattr( self, "moveInfo" ): del self.moveInfo elif action == "copyCats": try: del self.copyCatsList del self.copyCatsIds except AttributeError: pass elif action == "copyLine": del self.copyIds if self.layerTmp: self.Map.DeleteLayer(self.layerTmp) self.UpdateMap(render=True, renderVector=False) del self.layerTmp self.polycoords = [] self.UpdateMap(render=False) # render vector elif action == "zbulkLine": # reset polyline self.polycoords = [] self.digit.GetDisplay().SetSelected([]) self.UpdateMap(render=False) self.redrawAll = True self.UpdateMap(render=False, renderVector=False) def _onLeftDown(self, event): """Left mouse button donw - vector digitizer various actions""" try: mapLayer = self.toolbar.GetLayer().GetName() except: GMessage(parent=self, message=_("No vector map selected for editing.")) event.Skip() return action = self.toolbar.GetAction() if not action: GMessage( parent=self, message=_( "Nothing to do. " "Choose appropriate tool from digitizer toolbar." ), ) event.Skip() return if action not in ("moveVertex", "addVertex", "removeVertex", "editLine"): # set pen self.pen = wx.Pen( colour=UserSettings.Get( group="vdigit", key="symbol", subkey=["newSegment", "color"] ), width=2, style=wx.SHORT_DASH, ) self.polypen = wx.Pen( colour=UserSettings.Get( group="vdigit", key="symbol", subkey=["newLine", "color"] ), width=2, style=wx.SOLID, ) if action in ("addVertex", "removeVertex", "splitLines"): # unselect self.digit.GetDisplay().SetSelected([]) if action == "addLine": self.OnLeftDownAddLine(event) elif action == "editLine" and hasattr(self, "moveInfo"): self.OnLeftDownEditLine(event) elif action in ("moveLine", "moveVertex", "editLine") and not hasattr( self, "moveInfo" ): self.OnLeftDownMoveLine(event) elif action in ("displayAttrs" "displayCats"): self.OnLeftDownDisplayCA(event) elif action in ("copyCats", "copyAttrs"): self.OnLeftDownCopyCA(event) elif action == "copyLine": self.OnLeftDownCopyLine(event) elif action == "zbulkLine": self.OnLeftDownBulkLine(event) def OnLeftUpVarious(self, event): """Left mouse button released - vector digitizer various actions """ pos1 = self.Pixel2Cell(self.mouse["begin"]) pos2 = self.Pixel2Cell(self.mouse["end"]) nselected = 0 action = self.toolbar.GetAction() # -> delete line || move line || move vertex if action in ("moveVertex", "editLine"): if len(self.digit.GetDisplay().GetSelected()) == 0: nselected = int( self.digit.GetDisplay().SelectLineByPoint(pos1)["line"] != -1 ) if action == "editLine": try: selVertex = self.digit.GetDisplay().GetSelectedVertex(pos1)[0] except IndexError: selVertex = None if selVertex: # self.UpdateMap(render=False) ids = self.digit.GetDisplay().GetSelected(grassId=False) # move this line to tmp layer self.polycoords = [] for id in ids: if id % 2: # register only vertices e, n = self.Pixel2Cell( self.pdcVector.GetIdBounds(id)[0:2] ) self.polycoords.append((e, n)) self.digit.GetDisplay().DrawSelected(False) if selVertex < ids[-1] / 2: # choose first or last node of line self.moveInfo["id"].reverse() self.polycoords.reverse() else: # unselect self.digit.GetDisplay().SetSelected([]) if hasattr(self, "moveInfo"): del self.moveInfo self.UpdateMap(render=False) elif action in ("copyCats", "copyAttrs"): if not hasattr(self, "copyCatsIds"): # 'from' -> select by point nselected = int( self.digit.GetDisplay().SelectLineByPoint(pos1)["line"] != -1 ) if nselected: self.copyCatsList = self.digit.GetDisplay().GetSelected() else: # -> 'to' -> select by bbox self.digit.GetDisplay().SetSelected([]) # return number of selected features (by box/point) nselected = self.digit.GetDisplay().SelectLinesByBox((pos1, pos2)) if nselected == 0: nselected = int( self.digit.GetDisplay().SelectLineByPoint(pos1)["line"] != -1 ) if nselected > 0: self.copyCatsIds = self.digit.GetDisplay().GetSelected() elif action == "queryLine": selected = self.digit.SelectLinesByQuery(bbox=(pos1, pos2)) nselected = len(selected) if nselected > 0: self.digit.GetDisplay().SetSelected(selected) else: # -> moveLine || deleteLine, etc. (select by point/box) if action == "moveLine" and len(self.digit.GetDisplay().GetSelected()) > 0: nselected = 0 else: if action == "deleteArea": nselected = int( self.digit.GetDisplay().SelectAreaByPoint(pos1)["area"] != -1 ) else: if action == "moveLine": drawSeg = True else: drawSeg = False nselected = self.digit.GetDisplay().SelectLinesByBox( bbox=(pos1, pos2), drawSeg=drawSeg ) if nselected == 0: nselected = int( self.digit.GetDisplay().SelectLineByPoint(pos1)["line"] != -1 ) if nselected > 0: if action in ("moveLine", "moveVertex") and hasattr(self, "moveInfo"): # get pseudoDC id of objects which should be redrawn if action == "moveLine": # -> move line self.moveInfo["id"] = self.digit.GetDisplay().GetSelected( grassId=False ) else: # moveVertex self.moveInfo["id"] = self.digit.GetDisplay().GetSelectedVertex( pos1 ) if len(self.moveInfo["id"]) == 0: # no vertex found self.digit.GetDisplay().SetSelected([]) # # check for duplicates # if UserSettings.Get(group="vdigit", key="checkForDupl", subkey="enabled"): dupl = self.digit.GetDisplay().GetDuplicates() self.UpdateMap(render=False) if dupl: posWindow = self.ClientToScreen( ( self.mouse["end"][0] + self.dialogOffset, self.mouse["end"][1] + self.dialogOffset, ) ) dlg = VDigitDuplicatesDialog(parent=self, data=dupl, pos=posWindow) if dlg.ShowModal() == wx.ID_OK: self.digit.GetDisplay().UnSelect(dlg.GetUnSelected()) # update selected self.UpdateMap(render=False) if action != "editLine": # -> move line || move vertex self.UpdateMap(render=False) else: # no vector object found if not ( action in ("moveLine", "moveVertex") and hasattr(self, "moveInfo") and len(self.moveInfo["id"]) > 0 ): # avoid left-click when features are already selected self.UpdateMap(render=False, renderVector=False) def OnLeftUpModifyLine(self, event): """Left mouse button released - vector digitizer split line, add/remove vertex action """ pos1 = self.Pixel2Cell(self.mouse["begin"]) pointOnLine = self.digit.GetDisplay().SelectLineByPoint(pos1)["point"] if not pointOnLine: return if self.toolbar.GetAction() in ["splitLine", "addVertex"]: self.UpdateMap(render=False) # highlight object self.DrawCross( pdc=self.pdcTmp, coords=self.Cell2Pixel((pointOnLine[0], pointOnLine[1])), size=5, ) else: # removeVertex # get only id of vertex try: id = self.digit.GetDisplay().GetSelectedVertex(pos1)[0] except IndexError: id = None if id: x, y = self.pdcVector.GetIdBounds(id)[0:2] self.pdcVector.RemoveId(id) self.UpdateMap(render=False) # highlight object self.DrawCross(pdc=self.pdcTmp, coords=(x, y), size=5) else: # unselect self.digit.GetDisplay().SetSelected([]) self.UpdateMap(render=False) def OnLeftUpCopyLine(self, event): """Left mouse button released - vector digitizer copy feature action """ pos1 = self.Pixel2Cell(self.mouse["begin"]) pos2 = self.Pixel2Cell(self.mouse["end"]) if ( UserSettings.Get( group="vdigit", key="bgmap", subkey="value", settings_type="internal" ) == "" ): # no background map -> copy from current vector map layer nselected = self.digit.GetDisplay().SelectLinesByBox((pos1, pos2)) if nselected > 0: # highlight selected features self.UpdateMap(render=False) else: self.UpdateMap(render=False, renderVector=False) else: # copy features from background map self.copyIds = self.digit.SelectLinesFromBackgroundMap(bbox=(pos1, pos2)) if len(self.copyIds) > 0: color = UserSettings.Get( group="vdigit", key="symbol", subkey=["highlight", "color"] ) colorStr = str(color[0]) + ":" + str(color[1]) + ":" + str(color[2]) dVectTmp = [ "d.vect", "map=%s" % UserSettings.Get( group="vdigit", key="bgmap", subkey="value", settings_type="internal", ), "cats=%s" % ListOfCatsToRange(self.copyIds), "-i", "color=%s" % colorStr, "fill_color=%s" % colorStr, "type=point,line,boundary,centroid", "width=2", ] if not self.layerTmp: self.layerTmp = self.Map.AddLayer( ltype="vector", name=QUERYLAYER, command=dVectTmp ) else: self.layerTmp.SetCmd(dVectTmp) else: if self.layerTmp: self.Map.DeleteLayer(self.layerTmp) self.layerTmp = None self.UpdateMap(render=True, renderVector=True) def OnLeftUpBulkLine(self, event): """Left mouse button released - vector digitizer z-bulk line action """ # select lines to be labeled pos1 = self.polycoords[0] pos2 = self.polycoords[1] nselected = self.digit.GetDisplay().SelectLinesByBox((pos1, pos2)) if nselected > 0: # highlight selected features self.UpdateMap(render=False) self.DrawLines(pdc=self.pdcTmp) # redraw temp line else: self.UpdateMap(render=False, renderVector=False) def OnLeftUpConnectLine(self, event): """Left mouse button released - vector digitizer connect line action """ if len(self.digit.GetDisplay().GetSelected()) > 0: self.UpdateMap(render=False) def _onLeftUp(self, event): """Left mouse button released""" if event.ControlDown(): return if hasattr(self, "moveInfo"): if len(self.digit.GetDisplay().GetSelected()) == 0: self.moveInfo["begin"] = self.Pixel2Cell( self.mouse["begin"] ) # left down # eliminate initial mouse moving efect self.mouse["begin"] = self.mouse["end"] action = self.toolbar.GetAction() if action in ( "deleteLine", "deleteArea", "moveLine", "moveVertex", "copyCats", "copyAttrs", "editLine", "flipLine", "mergeLine", "snapLine", "queryLine", "breakLine", "typeConv", "connectLine", ): self.OnLeftUpVarious(event) elif action in ("splitLine", "addVertex", "removeVertex"): self.OnLeftUpModifyLine(event) elif action == "copyLine": self.OnLeftUpCopyLine(event) elif action == "zbulkLine" and len(self.polycoords) == 2: self.OnLeftUpBulkLine(event) elif action == "connectLine": self.OnLeftUpConnectLine(event) if len(self.digit.GetDisplay().GetSelected()) > 0: self.redrawAll = None def _onRightDown(self, event): # digitization tool (confirm action) action = self.toolbar.GetAction() if action in ("moveLine", "moveVertex") and hasattr(self, "moveInfo"): pFrom = self.moveInfo["begin"] pTo = self.Pixel2Cell(event.GetPosition()) move = (pTo[0] - pFrom[0], pTo[1] - pFrom[1]) if action == "moveLine": # move line if self.digit.MoveSelectedLines(move) < 0: return elif action == "moveVertex": # move vertex fid = self.digit.MoveSelectedVertex(pFrom, move) if fid < 0: return self._geomAttrbUpdate( [ fid, ] ) del self.moveInfo def _onRightUp(self, event): """Right mouse button released (confirm action)""" action = self.toolbar.GetAction() if action == "addLine" and self.toolbar.GetAction("type") in [ "line", "boundary", "area", ]: # -> add new line / boundary try: mapName = self.toolbar.GetLayer().GetName() except: mapName = None GError(parent=self, message=_("No vector map selected for editing.")) if mapName: if self.toolbar.GetAction("type") == "line": line = True else: line = False if len(self.polycoords) < 2: # ignore 'one-point' lines return nfeat, fids = self.digit.AddFeature( self.toolbar.GetAction("type"), self.polycoords ) if nfeat < 0: return position = self.Cell2Pixel(self.polycoords[-1]) self.polycoords = [] self.UpdateMap(render=False) self.redrawAll = True self.Refresh() # add new record into attribute table if self._addRecord() and (line is True or (not line and nfeat > 0)): posWindow = self.ClientToScreen( ( position[0] + self.dialogOffset, position[1] + self.dialogOffset, ) ) # select attributes based on layer and category cats = { fids[0]: { UserSettings.Get( group="vdigit", key="layer", subkey="value" ): ( UserSettings.Get( group="vdigit", key="category", subkey="value" ), ) } } addRecordDlg = DisplayAttributesDialog( parent=self, map=mapName, cats=cats, pos=posWindow, action="add", ignoreError=True, ) for fid in fids: self._geomAttrb(fid, addRecordDlg, "length") # auto-placing centroid self._geomAttrb(fid, addRecordDlg, "area") self._geomAttrb(fid, addRecordDlg, "perimeter") if addRecordDlg.IsFound(): addRecordDlg.ShowModal() addRecordDlg.Destroy() elif action == "deleteLine": # -> delete selected vector features if self.digit.DeleteSelectedLines() < 0: return self._updateATM() elif action == "deleteArea": # -> delete selected vector areas if self.digit.DeleteSelectedAreas() < 0: return self._updateATM() elif action == "splitLine": # split line if self.digit.SplitLine(self.Pixel2Cell(self.mouse["begin"])) < 0: return elif action == "addVertex": # add vertex fid = self.digit.AddVertex(self.Pixel2Cell(self.mouse["begin"])) if fid < 0: return elif action == "removeVertex": # remove vertex fid = self.digit.RemoveVertex(self.Pixel2Cell(self.mouse["begin"])) if fid < 0: return self._geomAttrbUpdate( [ fid, ] ) elif action in ("copyCats", "copyAttrs") and hasattr(self, "copyCatsIds"): if action == "copyCats": if ( self.digit.CopyCats( self.copyCatsList, self.copyCatsIds, copyAttrb=False ) < 0 ): return else: if ( self.digit.CopyCats( self.copyCatsList, self.copyCatsIds, copyAttrb=True ) < 0 ): return del self.copyCatsList del self.copyCatsIds self._updateATM() elif action == "editLine" and hasattr(self, "moveInfo"): line = self.digit.GetDisplay().GetSelected()[0] if self.digit.EditLine(line, self.polycoords) < 0: return del self.moveInfo elif action == "flipLine": if self.digit.FlipLine() < 0: return elif action == "mergeLine": if self.digit.MergeLine() < 0: return elif action == "breakLine": if self.digit.BreakLine() < 0: return elif action == "snapLine": if self.digit.SnapLine() < 0: return elif action == "connectLine": if len(self.digit.GetDisplay().GetSelected()) > 1: if self.digit.ConnectLine() < 0: return elif action == "copyLine": if self.digit.CopyLine(self.copyIds) < 0: return del self.copyIds if self.layerTmp: self.Map.DeleteLayer(self.layerTmp) self.UpdateMap(render=True, renderVector=False) del self.layerTmp elif action == "zbulkLine" and len(self.polycoords) == 2: pos1 = self.polycoords[0] pos2 = self.polycoords[1] selected = self.digit.GetDisplay().GetSelected() dlg = VDigitZBulkDialog( parent=self, title=_("Z bulk-labeling dialog"), nselected=len(selected) ) if dlg.ShowModal() == wx.ID_OK: if ( self.digit.ZBulkLines( pos1, pos2, dlg.value.GetValue(), dlg.step.GetValue() ) < 0 ): return self.UpdateMap(render=False) elif action == "typeConv": # -> feature type conversion # - point <-> centroid # - line <-> boundary if self.digit.TypeConvForSelectedLines() < 0: return if action != "addLine": # unselect and re-render self.digit.GetDisplay().SetSelected([]) self.polycoords = [] self.UpdateMap(render=False) def _onMouseMoving(self, event): self.mouse["end"] = event.GetPosition() Debug.msg( 5, "VDigitWindow.OnMouseMoving(): coords=%f,%f" % (self.mouse["end"][0], self.mouse["end"][1]), ) action = self.toolbar.GetAction() if action == "addLine" and self.toolbar.GetAction("type") in [ "line", "boundary", "area", ]: if len(self.polycoords) > 0: self.MouseDraw( pdc=self.pdcTmp, begin=self.Cell2Pixel(self.polycoords[-1]) ) elif action in ["moveLine", "moveVertex", "editLine"] and hasattr( self, "moveInfo" ): dx = self.mouse["end"][0] - self.mouse["begin"][0] dy = self.mouse["end"][1] - self.mouse["begin"][1] # draw lines on new position if action == "moveLine" and len(self.moveInfo["id"]) > 0: # move line for id in self.moveInfo["id"]: self.pdcTmp.TranslateId(id, dx, dy) elif action in ["moveVertex", "editLine"]: # move vertex -> # (vertex, left vertex, left line, # right vertex, right line) # do not draw static lines if action == "moveVertex" and len(self.moveInfo["id"]) > 0: self.polycoords = [] self.pdcTmp.RemoveId(self.moveInfo["id"][0]) if self.moveInfo["id"][1] > 0: # previous vertex x, y = self.Pixel2Cell( self.pdcTmp.GetIdBounds(self.moveInfo["id"][1])[0:2] ) self.pdcTmp.RemoveId(self.moveInfo["id"][1] + 1) self.polycoords.append((x, y)) self.polycoords.append(self.Pixel2Cell(self.mouse["end"])) if self.moveInfo["id"][2] > 0: # next vertex x, y = self.Pixel2Cell( self.pdcTmp.GetIdBounds(self.moveInfo["id"][2])[0:2] ) self.pdcTmp.RemoveId(self.moveInfo["id"][2] - 1) self.polycoords.append((x, y)) self.ClearLines(pdc=self.pdcTmp) self.DrawLines(pdc=self.pdcTmp) if action == "editLine": if self.polycoords: self.MouseDraw( pdc=self.pdcTmp, begin=self.Cell2Pixel(self.polycoords[-1]) ) self.Refresh() # TODO: use RefreshRect() self.mouse["begin"] = self.mouse["end"] elif action == "zbulkLine": if len(self.polycoords) == 1: # draw mouse moving self.MouseDraw(self.pdcTmp) def _zoom(self, event): tmp1 = self.mouse["end"] tmp2 = self.Cell2Pixel(self.moveInfo["begin"]) dx = tmp1[0] - tmp2[0] dy = tmp1[1] - tmp2[1] self.moveInfo["beginDiff"] = (dx, dy) for id in self.moveInfo["id"]: self.pdcTmp.RemoveId(id) def _addRecord(self): return UserSettings.Get(group="vdigit", key="addRecord", subkey="enabled")