123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071 |
- """!
- @package mapdisp_vdigit.py
- @brief Map display canvas extended for vector digitizer
- See also vdigit.py, wxvdriver.py and wxvdigit.py
- Classes:
- - VDigitWindow
- (C) 2011 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 Martin Landa <landa.martin gmail.com>
- """
- import wx
- import dbm_dialogs
- import gcmd
- from debug import Debug
- from mapdisp_window import BufferedWindow
- from preferences import globalSettings as UserSettings
- from utils import ListOfCatsToRange
- from globalvar import QUERYLAYER
- from vdigit import VDigitCategoryDialog
- from vdigit import VDigitZBulkDialog
- from vdigit import VDigitDuplicatesDialog
- class VDigitWindow(BufferedWindow):
- """!A Buffered window extended for vector digitizer.
- """
- def __init__(self, parent, id = wx.ID_ANY,
- Map = None, tree = None, lmgr = None,
- style = wx.NO_FULL_REPAINT_ON_RESIZE, **kwargs):
- BufferedWindow.__init__(self, parent, id, Map, tree, lmgr,
- style, **kwargs)
-
- self.pdcVector = wx.PseudoDC()
- self.toolbar = self.parent.GetToolbar('vdigit')
- self.digit = None # wxvdigit.IVDigit
-
- self.Bind(wx.EVT_KEY_DOWN, self.OnKeyDown)
-
- def SetToolbar(self, toolbar):
- """!Set up related toolbar
- """
- self.toolbar = toolbar
-
- def _onMotion(self, coord, precision):
- """!Track mouse motion and update statusbar (see self.Motion)
- @parem coord easting, northing
- @param precision formatting precision
- """
- e, n = coord
-
- if self.toolbar.GetAction() != 'addLine' or \
- self.toolbar.GetAction('type') not in ('line', 'boundary') or \
- len(self.polycoords) == 0:
- return False
-
- # 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]
- self.parent.SetStatusText("%.*f, %.*f (seg: %.*f; tot: %.*f)" % \
- (precision, e, precision, n,
- precision, distance_seg,
- precision, distance_tot), 0)
-
- return True
-
- 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()
-
- try:
- item = self.tree.FindItemByData('maplayer', self.toolbar.GetLayer())
- except TypeError:
- item = None
-
- if 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 atribute 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 = dbm_dialogs.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.mapDBInfo and \
- addRecordDlg.ShowModal() == wx.ID_OK:
- sqlfile = tempfile.NamedTemporaryFile(mode = "w")
- for sql in addRecordDlg.GetSQLString():
- sqlfile.file.write(sql + ";\n")
- sqlfile.file.flush()
-
- gcmd.RunCommand('db.execute',
- parent = self,
- quiet = True,
- input = sqlfile.name)
-
- if addRecordDlg.mapDBInfo:
- self._updateATM()
-
- elif self.toolbar.GetAction('type') in ["line", "boundary", "area"]:
- # add new point to the line
- self.polycoords.append(self.Pixel2Cell(event.GetPositionTuple()[:]))
- self.DrawLines(pdc = self.pdcTmp)
-
- def _geomAttrb(self, fid, dialog, attrb):
- """!Define geometry attributes
- """
- mapLayer = self.toolbar.GetLayer()
- item = self.tree.FindItemByData('maplayer', mapLayer)
- vdigit = self.tree.GetPyData(item)[0]['vdigit']
- 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()
- item = self.tree.FindItemByData('maplayer', mapLayer)
- vdigit = self.tree.GetPyData(item)[0]['vdigit']
-
- if vdigit is None or 'geomAttr' not in vdigit:
- return
-
- dbInfo = gselect.VectorDBInfo(vectorName)
- sqlfile = tempfile.NamedTemporaryFile(mode = "w")
- for fid in fids:
- for layer, cats in self.digit.GetLineCats(fid).iteritems():
- table = dbInfo.GetTable(layer)
- for attrb, item in vdigit['geomAttr'].iteritems():
- 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()
- gcmd.RunCommand('db.execute',
- parent = True,
- quiet = True,
- input = sqlfile.name)
-
- def _updateATM(self):
- """!Update open Attribute Table Manager
-
- @todo: use AddDataRow() instead
- """
- # 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(wx.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'] = \
- dbm_dialogs.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.GetPositionTuple()[:]))
- 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, "BufferedWindow.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", "moveLine", "splitLine",
- "addVertex", "removeVertex", "moveVertex",
- "copyCats", "flipLine", "mergeLine",
- "snapLine", "connectLine", "copyLine",
- "queryLine", "breakLine", "typeConv"]:
- # varios 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:
- gcmd.GMessage(parent = self,
- message = _("No vector map selected for editing."))
- event.Skip()
- return
-
- action = self.toolbar.GetAction()
- if not action:
- return
-
- if action not in ("moveVertex",
- "addVertex",
- "removeVertex",
- "editLine"):
- # set pen
- self.pen = wx.Pen(colour = 'Red', width = 2, style = wx.SHORT_DASH)
- self.polypen = wx.Pen(colour = 'dark green', 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 = self.digit.GetDisplay().SelectLineByPoint(pos1)['point']
-
- 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([])
- del self.moveInfo
-
- self.UpdateMap(render = False)
-
- elif action in ("copyCats",
- "copyAttrs"):
- if not hasattr(self, "copyCatsIds"):
- # 'from' -> select by point
- nselected = self.digit.GetDisplay().SelectLineByPoint(pos1)['point']
- 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:
- if self.digit.GetDisplay().SelectLineByPoint(pos1) is not None:
- nselected = 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 == 'moveLine':
- drawSeg = True
- else:
- drawSeg = False
-
- nselected = self.digit.GetDisplay().SelectLinesByBox(bbox = (pos1, pos2),
- drawSeg = drawSeg)
- if nselected == 0:
- if self.digit.GetDisplay().SelectLineByPoint(pos1) is not None:
- nselected = 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', internal = True) == '':
- # no background map -> copy from current vector map layer
- nselected = self.bdigit.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', internal = True),
- 'cats=%s' % ListOfCatsToRange(self.copyIds),
- '-i',
- 'color=%s' % colorStr,
- 'fcolor=%s' % colorStr,
- 'type=point,line,boundary,centroid',
- 'width=2']
-
- if not self.layerTmp:
- self.layerTmp = self.Map.AddLayer(type = '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 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",
- "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.GetPositionTuple())
-
- 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
- gcmd.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 atribute table
- if UserSettings.Get(group = 'vdigit', key = "addRecord", subkey = 'enabled') 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 = dbm_dialogs.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.mapDBInfo and \
- addRecordDlg.ShowModal() == wx.ID_OK:
- sqlfile = tempfile.NamedTemporaryFile(mode = "w")
- for sql in addRecordDlg.GetSQLString():
- sqlfile.file.write(sql + ";\n")
- sqlfile.file.flush()
- gcmd.RunCommand('db.execute',
- parent = True,
- quiet = True,
- input = sqlfile.name)
-
- if addRecordDlg.mapDBInfo:
- self._updateATM()
-
- elif action == "deleteLine":
- # -> delete selected vector features
- if self.digit.DeleteSelectedLines() < 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"):
- 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.GetPositionTuple()[:]
-
- Debug.msg (5, "BufferedWindow.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":
- 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)
-
|