GRASS Programmer's Manual
6.4.2(2012)
|
00001 """! 00002 @package mapdisp_vdigit.py 00003 00004 @brief Map display canvas extended for vector digitizer 00005 00006 See also vdigit.py, wxvdriver.py and wxvdigit.py 00007 00008 Classes: 00009 - VDigitWindow 00010 00011 (C) 2011 by the GRASS Development Team 00012 This program is free software under the GNU General Public 00013 License (>=v2). Read the file COPYING that comes with GRASS 00014 for details. 00015 00016 @author Martin Landa <landa.martin gmail.com> 00017 """ 00018 00019 import wx 00020 00021 import dbm_dialogs 00022 00023 import gcmd 00024 from debug import Debug 00025 from mapdisp_window import BufferedWindow 00026 from preferences import globalSettings as UserSettings 00027 from utils import ListOfCatsToRange 00028 from globalvar import QUERYLAYER 00029 from vdigit import VDigitCategoryDialog 00030 from vdigit import VDigitZBulkDialog 00031 from vdigit import VDigitDuplicatesDialog 00032 00033 class VDigitWindow(BufferedWindow): 00034 """!A Buffered window extended for vector digitizer. 00035 """ 00036 def __init__(self, parent, id = wx.ID_ANY, 00037 Map = None, tree = None, lmgr = None, 00038 style = wx.NO_FULL_REPAINT_ON_RESIZE, **kwargs): 00039 BufferedWindow.__init__(self, parent, id, Map, tree, lmgr, 00040 style, **kwargs) 00041 00042 self.pdcVector = wx.PseudoDC() 00043 self.toolbar = self.parent.toolbars['vdigit'] 00044 self.digit = None # wxvdigit.IVDigit 00045 00046 self.Bind(wx.EVT_KEY_DOWN, self.OnKeyDown) 00047 00048 def SetToolbar(self, toolbar): 00049 """!Set up related toolbar 00050 """ 00051 self.toolbar = toolbar 00052 00053 def _onMotion(self, coord, precision): 00054 """!Track mouse motion and update statusbar (see self.Motion) 00055 00056 @parem coord easting, northing 00057 @param precision formatting precision 00058 """ 00059 e, n = coord 00060 00061 if self.toolbar.GetAction() != 'addLine' or \ 00062 self.toolbar.GetAction('type') not in ('line', 'boundary') or \ 00063 len(self.polycoords) == 0: 00064 return False 00065 00066 # for linear feature show segment and total length 00067 distance_seg = self.Distance(self.polycoords[-1], 00068 (e, n), screen = False)[0] 00069 distance_tot = distance_seg 00070 for idx in range(1, len(self.polycoords)): 00071 distance_tot += self.Distance(self.polycoords[idx-1], 00072 self.polycoords[idx], 00073 screen = False)[0] 00074 self.parent.statusbar.SetStatusText("%.*f, %.*f (seg: %.*f; tot: %.*f)" % \ 00075 (precision, e, precision, n, 00076 precision, distance_seg, 00077 precision, distance_tot), 0) 00078 00079 return True 00080 00081 def OnKeyDown(self, event): 00082 """!Key pressed""" 00083 shift = event.ShiftDown() 00084 kc = event.GetKeyCode() 00085 00086 event = None 00087 if not shift: 00088 if kc == ord('P'): 00089 event = wx.CommandEvent(winid = self.toolbar.addPoint) 00090 tool = self.toolbar.OnAddPoint 00091 elif kc == ord('L'): 00092 event = wx.CommandEvent(winid = self.toolbar.addLine) 00093 tool = self.toolbar.OnAddLine 00094 if event: 00095 self.toolbar.OnTool(event) 00096 tool(event) 00097 00098 def _updateMap(self): 00099 if not self.toolbar or \ 00100 not self.toolbar.GetLayer(): 00101 return 00102 00103 # set region 00104 self.digit.GetDisplay().UpdateRegion() 00105 # re-calculate threshold for digitization tool 00106 # self.parent.digit.GetDisplay().GetThreshold() 00107 # draw map 00108 # self.pdcVector.Clear() 00109 self.pdcVector.RemoveAll() 00110 00111 try: 00112 item = self.tree.FindItemByData('maplayer', self.toolbar.GetLayer()) 00113 except TypeError: 00114 item = None 00115 00116 if item and self.tree.IsItemChecked(item): 00117 self.redrawAll = True 00118 self.digit.GetDisplay().DrawMap() 00119 00120 # translate tmp objects (pointer position) 00121 if self.toolbar.GetAction() == 'moveLine' and \ 00122 hasattr(self, "moveInfo"): 00123 if 'beginDiff' in self.moveInfo: 00124 # move line 00125 for id in self.moveInfo['id']: 00126 self.pdcTmp.TranslateId(id, 00127 self.moveInfo['beginDiff'][0], 00128 self.moveInfo['beginDiff'][1]) 00129 del self.moveInfo['beginDiff'] 00130 00131 def OnLeftDownAddLine(self, event): 00132 """!Left mouse button pressed - add new feature 00133 """ 00134 try: 00135 mapLayer = self.toolbar.GetLayer().GetName() 00136 except: 00137 return 00138 00139 if self.toolbar.GetAction('type') in ['point', 'centroid']: 00140 # add new point / centroiud 00141 east, north = self.Pixel2Cell(self.mouse['begin']) 00142 nfeat, fids = self.digit.AddFeature(self.toolbar.GetAction('type'), [(east, north)]) 00143 if nfeat < 1: 00144 return 00145 00146 self.UpdateMap(render = False) # redraw map 00147 00148 # add new record into atribute table 00149 if UserSettings.Get(group = 'vdigit', key = "addRecord", subkey = 'enabled'): 00150 # select attributes based on layer and category 00151 cats = { fids[0] : { 00152 UserSettings.Get(group = 'vdigit', key = "layer", subkey = 'value') : 00153 (UserSettings.Get(group = 'vdigit', key = "category", subkey = 'value'), ) 00154 }} 00155 00156 posWindow = self.ClientToScreen((self.mouse['end'][0] + self.dialogOffset, 00157 self.mouse['end'][1] + self.dialogOffset)) 00158 00159 addRecordDlg = dbm_dialogs.DisplayAttributesDialog(parent = self, map = mapLayer, 00160 cats = cats, 00161 pos = posWindow, 00162 action = "add") 00163 00164 if self.toolbar.GetAction('type') == 'centroid': 00165 for fid in fids: 00166 self._geomAttrb(fid, addRecordDlg, 'area') 00167 self._geomAttrb(fid, addRecordDlg, 'perimeter') 00168 00169 if addRecordDlg.mapDBInfo and \ 00170 addRecordDlg.ShowModal() == wx.ID_OK: 00171 sqlfile = tempfile.NamedTemporaryFile(mode = "w") 00172 for sql in addRecordDlg.GetSQLString(): 00173 sqlfile.file.write(sql + ";\n") 00174 sqlfile.file.flush() 00175 00176 gcmd.RunCommand('db.execute', 00177 parent = self, 00178 quiet = True, 00179 input = sqlfile.name) 00180 00181 if addRecordDlg.mapDBInfo: 00182 self._updateATM() 00183 00184 elif self.toolbar.GetAction('type') in ["line", "boundary", "area"]: 00185 # add new point to the line 00186 self.polycoords.append(self.Pixel2Cell(event.GetPositionTuple()[:])) 00187 self.DrawLines(pdc = self.pdcTmp) 00188 00189 def _geomAttrb(self, fid, dialog, attrb): 00190 """!Define geometry attributes 00191 """ 00192 mapLayer = self.toolbar.GetLayer() 00193 item = self.tree.FindItemByData('maplayer', mapLayer) 00194 vdigit = self.tree.GetPyData(item)[0]['vdigit'] 00195 if not vdigit or \ 00196 'geomAttr' not in vdigit or \ 00197 attrb not in vdigit['geomAttr']: 00198 return 00199 00200 val = -1 00201 if attrb == 'length': 00202 val = self.digit.GetLineLength(fid) 00203 type = attrb 00204 elif attrb == 'area': 00205 val = self.digit.GetAreaSize(fid) 00206 type = attrb 00207 elif attrb == 'perimeter': 00208 val = self.digit.GetAreaPerimeter(fid) 00209 type = 'length' 00210 00211 if val > 0: 00212 layer = int(UserSettings.Get(group = 'vdigit', key = "layer", subkey = 'value')) 00213 column = vdigit['geomAttr'][attrb]['column'] 00214 val = UnitsConvertValue(val, type, vdigit['geomAttr'][attrb]['units']) 00215 dialog.SetColumnValue(layer, column, val) 00216 dialog.OnReset() 00217 00218 def _geomAttrbUpdate(self, fids): 00219 """!Update geometry atrributes of currently selected features 00220 00221 @param fid list feature id 00222 """ 00223 mapLayer = self.parent.toolbars['vdigit'].GetLayer() 00224 vectorName = mapLayer.GetName() 00225 item = self.tree.FindItemByData('maplayer', mapLayer) 00226 vdigit = self.tree.GetPyData(item)[0]['vdigit'] 00227 00228 if vdigit is None or 'geomAttr' not in vdigit: 00229 return 00230 00231 dbInfo = gselect.VectorDBInfo(vectorName) 00232 sqlfile = tempfile.NamedTemporaryFile(mode = "w") 00233 for fid in fids: 00234 for layer, cats in self.digit.GetLineCats(fid).iteritems(): 00235 table = dbInfo.GetTable(layer) 00236 for attrb, item in vdigit['geomAttr'].iteritems(): 00237 val = -1 00238 if attrb == 'length': 00239 val = self.digit.GetLineLength(fid) 00240 type = attrb 00241 elif attrb == 'area': 00242 val = self.digit.GetAreaSize(fid) 00243 type = attrb 00244 elif attrb == 'perimeter': 00245 val = self.digit.GetAreaPerimeter(fid) 00246 type = 'length' 00247 00248 if val < 0: 00249 continue 00250 val = UnitsConvertValue(val, type, item['units']) 00251 00252 for cat in cats: 00253 sqlfile.write('UPDATE %s SET %s = %f WHERE %s = %d;\n' % \ 00254 (table, item['column'], val, 00255 dbInfo.GetKeyColumn(layer), cat)) 00256 00257 sqlfile.file.flush() 00258 gcmd.RunCommand('db.execute', 00259 parent = True, 00260 quiet = True, 00261 input = sqlfile.name) 00262 00263 def _updateATM(self): 00264 """!Update open Attribute Table Manager 00265 00266 @todo: use AddDataRow() instead 00267 """ 00268 # update ATM 00269 digitVector = self.toolbar.GetLayer().GetName() 00270 00271 for atm in self.lmgr.dialogs['atm']: 00272 atmVector = atm.GetVectorName() 00273 if atmVector == digitVector: 00274 layer = UserSettings.Get(group = 'vdigit', key = "layer", subkey = 'value') 00275 # TODO: use AddDataRow instead 00276 atm.LoadData(layer) 00277 00278 def OnLeftDownEditLine(self, event): 00279 """!Left mouse button pressed - edit linear feature - add new 00280 vertex. 00281 """ 00282 self.polycoords.append(self.Pixel2Cell(self.mouse['begin'])) 00283 self.moveInfo['id'].append(wx.NewId()) 00284 self.DrawLines(pdc = self.pdcTmp) 00285 00286 def OnLeftDownMoveLine(self, event): 00287 """!Left mouse button pressed - vector digitizer move 00288 feature/vertex, edit linear feature 00289 """ 00290 self.moveInfo = dict() 00291 # geographic coordinates of initial position (left-down) 00292 self.moveInfo['begin'] = None 00293 # list of ids to modify 00294 self.moveInfo['id'] = list() 00295 00296 # set pen 00297 if self.toolbar.GetAction() in ["moveVertex", "editLine"]: 00298 pcolor = UserSettings.Get(group = 'vdigit', key = "symbol", 00299 subkey = ["highlight", "color"]) 00300 self.pen = self.polypen = wx.Pen(colour = pcolor, 00301 width = 2, style = wx.SHORT_DASH) 00302 self.pdcTmp.SetPen(self.polypen) 00303 00304 def OnLeftDownDisplayCA(self, event): 00305 """!Left mouse button pressed - vector digitizer display categories 00306 or attributes action 00307 """ 00308 try: 00309 mapLayer = self.toolbar.GetLayer().GetName() 00310 except: 00311 return 00312 00313 coords = self.Pixel2Cell(self.mouse['begin']) 00314 00315 # unselect 00316 self.digit.GetDisplay().SetSelected([]) 00317 00318 # select feature by point 00319 cats = {} 00320 self.digit.GetDisplay().SelectLineByPoint(coords) 00321 00322 if not self.digit.GetDisplay().GetSelected(): 00323 for key in ('attributes', 'category'): 00324 if self.parent.dialogs[key] and \ 00325 self.parent.dialogs[key].IsShown(): 00326 self.parent.dialogs[key].Hide() 00327 self.UpdateMap(render = False, renderVector = True) 00328 return 00329 00330 if UserSettings.Get(group = 'vdigit', key = 'checkForDupl', 00331 subkey = 'enabled'): 00332 lines = self.digit.GetDisplay().GetSelected() 00333 else: 00334 lines = (self.digit.GetDisplay().GetSelected()[0],) # only first found 00335 00336 for line in lines: 00337 cats[line] = self.digit.GetLineCats(line) 00338 00339 posWindow = self.ClientToScreen((self.mouse['end'][0] + self.dialogOffset, 00340 self.mouse['end'][1] + self.dialogOffset)) 00341 00342 if self.toolbar.GetAction() == "displayAttrs": 00343 # select attributes based on coordinates (all layers) 00344 if self.parent.dialogs['attributes'] is None: 00345 self.parent.dialogs['attributes'] = \ 00346 dbm_dialogs.DisplayAttributesDialog(parent = self, map = mapLayer, 00347 cats = cats, 00348 action = "update") 00349 else: 00350 # upgrade dialog 00351 self.parent.dialogs['attributes'].UpdateDialog(cats = cats) 00352 00353 if self.parent.dialogs['attributes']: 00354 if len(cats.keys()) > 0: 00355 # highlight feature & re-draw map 00356 if not self.parent.dialogs['attributes'].IsShown(): 00357 self.parent.dialogs['attributes'].Show() 00358 else: 00359 if self.parent.dialogs['attributes'] and \ 00360 self.parent.dialogs['attributes'].IsShown(): 00361 self.parent.dialogs['attributes'].Hide() 00362 00363 else: # displayCats 00364 if self.parent.dialogs['category'] is None: 00365 # open new dialog 00366 dlg = VDigitCategoryDialog(parent = self, 00367 vectorName = mapLayer, 00368 cats = cats, 00369 pos = posWindow, 00370 title = _("Update categories")) 00371 self.parent.dialogs['category'] = dlg 00372 else: 00373 # update currently open dialog 00374 self.parent.dialogs['category'].UpdateDialog(cats = cats) 00375 00376 if self.parent.dialogs['category']: 00377 if len(cats.keys()) > 0: 00378 # highlight feature & re-draw map 00379 if not self.parent.dialogs['category'].IsShown(): 00380 self.parent.dialogs['category'].Show() 00381 else: 00382 if self.parent.dialogs['category'].IsShown(): 00383 self.parent.dialogs['category'].Hide() 00384 00385 self.UpdateMap(render = False, renderVector = True) 00386 00387 def OnLeftDownCopyCA(self, event): 00388 """!Left mouse button pressed - vector digitizer copy 00389 categories or attributes action 00390 """ 00391 if not hasattr(self, "copyCatsList"): 00392 self.copyCatsList = [] 00393 else: 00394 self.copyCatsIds = [] 00395 self.mouse['box'] = 'box' 00396 00397 def OnLeftDownCopyLine(self, event): 00398 """!Left mouse button pressed - vector digitizer copy lines 00399 action 00400 """ 00401 if not hasattr(self, "copyIds"): 00402 self.copyIds = [] 00403 self.layerTmp = None 00404 00405 def OnLeftDownBulkLine(self, event): 00406 """!Left mouse button pressed - vector digitizer label 3D 00407 vector lines 00408 """ 00409 if len(self.polycoords) > 1: # start new line 00410 self.polycoords = [] 00411 self.ClearLines(pdc = self.pdcTmp) 00412 self.polycoords.append(self.Pixel2Cell(event.GetPositionTuple()[:])) 00413 if len(self.polycoords) == 1: 00414 begin = self.Pixel2Cell(self.polycoords[-1]) 00415 end = self.Pixel2Cell(self.mouse['end']) 00416 else: 00417 end = self.Pixel2Cell(self.polycoords[-1]) 00418 begin = self.Pixel2Cell(self.mouse['begin']) 00419 00420 self.DrawLines(self.pdcTmp, polycoords = (begin, end)) 00421 00422 def OnLeftDownUndo(self, event): 00423 """!Left mouse button pressed with control key - vector 00424 digitizer undo functionality 00425 """ 00426 if self.mouse["use"] != "pointer" or not self.toolbar: 00427 return 00428 00429 action = self.toolbar.GetAction() 00430 if (action == "addLine" and \ 00431 self.toolbar.GetAction('type') in ["line", "boundary", "area"]) or \ 00432 action == "editLine": 00433 # add line or boundary -> remove last point from the line 00434 try: 00435 removed = self.polycoords.pop() 00436 Debug.msg(4, "BufferedWindow.OnMiddleDown(): polycoords_poped=%s" % \ 00437 [removed,]) 00438 # self.mouse['begin'] = self.Cell2Pixel(self.polycoords[-1]) 00439 except: 00440 pass 00441 00442 if action == "editLine": 00443 # remove last vertex & line 00444 if len(self.moveInfo['id']) > 1: 00445 self.moveInfo['id'].pop() 00446 00447 self.UpdateMap(render = False, renderVector = False) 00448 00449 elif action in ["deleteLine", "moveLine", "splitLine", 00450 "addVertex", "removeVertex", "moveVertex", 00451 "copyCats", "flipLine", "mergeLine", 00452 "snapLine", "connectLine", "copyLine", 00453 "queryLine", "breakLine", "typeConv"]: 00454 # varios tools -> unselected selected features 00455 self.digit.GetDisplay().SetSelected([]) 00456 if action in ["moveLine", "moveVertex", "editLine"] and \ 00457 hasattr(self, "moveInfo"): 00458 del self.moveInfo 00459 00460 elif action == "copyCats": 00461 try: 00462 del self.copyCatsList 00463 del self.copyCatsIds 00464 except AttributeError: 00465 pass 00466 00467 elif action == "copyLine": 00468 del self.copyIds 00469 if self.layerTmp: 00470 self.Map.DeleteLayer(self.layerTmp) 00471 self.UpdateMap(render = True, renderVector = False) 00472 del self.layerTmp 00473 00474 self.polycoords = [] 00475 self.UpdateMap(render = False) # render vector 00476 00477 elif action == "zbulkLine": 00478 # reset polyline 00479 self.polycoords = [] 00480 self.digit.GetDisplay().SetSelected([]) 00481 self.UpdateMap(render = False) 00482 00483 self.redrawAll = True 00484 self.UpdateMap(render = False, renderVector = False) 00485 00486 def _onLeftDown(self, event): 00487 """!Left mouse button donw - vector digitizer various actions 00488 """ 00489 try: 00490 mapLayer = self.toolbar.GetLayer().GetName() 00491 except: 00492 gcmd.GMessage(parent = self, 00493 message = _("No vector map selected for editing.")) 00494 event.Skip() 00495 return 00496 00497 action = self.toolbar.GetAction() 00498 if not action: 00499 return 00500 00501 if action not in ("moveVertex", 00502 "addVertex", 00503 "removeVertex", 00504 "editLine"): 00505 # set pen 00506 self.pen = wx.Pen(colour = 'Red', width = 2, style = wx.SHORT_DASH) 00507 self.polypen = wx.Pen(colour = 'dark green', width = 2, style = wx.SOLID) 00508 00509 if action in ("addVertex", 00510 "removeVertex", 00511 "splitLines"): 00512 # unselect 00513 self.digit.GetDisplay().SetSelected([]) 00514 00515 if action == "addLine": 00516 self.OnLeftDownAddLine(event) 00517 00518 elif action == "editLine" and \ 00519 hasattr(self, "moveInfo"): 00520 self.OnLeftDownEditLine(event) 00521 00522 elif action in ("moveLine", "moveVertex", "editLine") and \ 00523 not hasattr(self, "moveInfo"): 00524 self.OnLeftDownMoveLine(event) 00525 00526 elif action in ("displayAttrs" 00527 "displayCats"): 00528 self.OnLeftDownDisplayCA(event) 00529 00530 elif action in ("copyCats", 00531 "copyAttrs"): 00532 self.OnLeftDownCopyCA(event) 00533 00534 elif action == "copyLine": 00535 self.OnLeftDownCopyLine(event) 00536 00537 elif action == "zbulkLine": 00538 self.OnLeftDownBulkLine(event) 00539 00540 def OnLeftUpVarious(self, event): 00541 """!Left mouse button released - vector digitizer various 00542 actions 00543 """ 00544 pos1 = self.Pixel2Cell(self.mouse['begin']) 00545 pos2 = self.Pixel2Cell(self.mouse['end']) 00546 00547 nselected = 0 00548 action = self.toolbar.GetAction() 00549 # -> delete line || move line || move vertex 00550 if action in ("moveVertex", 00551 "editLine"): 00552 if len(self.digit.GetDisplay().GetSelected()) == 0: 00553 nselected = self.digit.GetDisplay().SelectLineByPoint(pos1)['point'] 00554 00555 if action == "editLine": 00556 try: 00557 selVertex = self.digit.GetDisplay().GetSelectedVertex(pos1)[0] 00558 except IndexError: 00559 selVertex = None 00560 00561 if selVertex: 00562 # self.UpdateMap(render=False) 00563 ids = self.digit.GetDisplay().GetSelected(grassId = False) 00564 # move this line to tmp layer 00565 self.polycoords = [] 00566 for id in ids: 00567 if id % 2: # register only vertices 00568 e, n = self.Pixel2Cell(self.pdcVector.GetIdBounds(id)[0:2]) 00569 self.polycoords.append((e, n)) 00570 self.digit.GetDisplay().DrawSelected(False) 00571 00572 if selVertex < ids[-1] / 2: 00573 # choose first or last node of line 00574 self.moveInfo['id'].reverse() 00575 self.polycoords.reverse() 00576 else: 00577 # unselect 00578 self.digit.GetDisplay().SetSelected([]) 00579 del self.moveInfo 00580 00581 self.UpdateMap(render = False) 00582 00583 elif action in ("copyCats", 00584 "copyAttrs"): 00585 if not hasattr(self, "copyCatsIds"): 00586 # 'from' -> select by point 00587 nselected = self.digit.GetDisplay().SelectLineByPoint(pos1)['point'] 00588 if nselected: 00589 self.copyCatsList = self.digit.GetDisplay().GetSelected() 00590 else: 00591 # -> 'to' -> select by bbox 00592 self.digit.GetDisplay().SetSelected([]) 00593 # return number of selected features (by box/point) 00594 nselected = self.digit.GetDisplay().SelectLinesByBox((pos1, pos2)) 00595 if nselected == 0: 00596 if self.digit.GetDisplay().SelectLineByPoint(pos1) is not None: 00597 nselected = 1 00598 00599 if nselected > 0: 00600 self.copyCatsIds = self.digit.GetDisplay().GetSelected() 00601 00602 elif action == "queryLine": 00603 selected = self.digit.SelectLinesByQuery(bbox = (pos1, pos2)) 00604 nselected = len(selected) 00605 if nselected > 0: 00606 self.digit.GetDisplay().SetSelected(selected) 00607 00608 else: 00609 # -> moveLine || deleteLine, etc. (select by point/box) 00610 if action == 'moveLine' and \ 00611 len(self.digit.GetDisplay().GetSelected()) > 0: 00612 nselected = 0 00613 else: 00614 if action == 'moveLine': 00615 drawSeg = True 00616 else: 00617 drawSeg = False 00618 00619 nselected = self.digit.GetDisplay().SelectLinesByBox(bbox = (pos1, pos2), 00620 drawSeg = drawSeg) 00621 if nselected == 0: 00622 if self.digit.GetDisplay().SelectLineByPoint(pos1) is not None: 00623 nselected = 1 00624 00625 if nselected > 0: 00626 if action in ("moveLine", "moveVertex") and \ 00627 hasattr(self, "moveInfo"): 00628 # get pseudoDC id of objects which should be redrawn 00629 if action == "moveLine": 00630 # -> move line 00631 self.moveInfo['id'] = self.digit.GetDisplay().GetSelected(grassId = False) 00632 else: # moveVertex 00633 self.moveInfo['id'] = self.digit.GetDisplay().GetSelectedVertex(pos1) 00634 if len(self.moveInfo['id']) == 0: # no vertex found 00635 self.digit.GetDisplay().SetSelected([]) 00636 00637 # 00638 # check for duplicates 00639 # 00640 if UserSettings.Get(group = 'vdigit', key = 'checkForDupl', subkey = 'enabled'): 00641 dupl = self.digit.GetDisplay().GetDuplicates() 00642 self.UpdateMap(render = False) 00643 00644 if dupl: 00645 posWindow = self.ClientToScreen((self.mouse['end'][0] + self.dialogOffset, 00646 self.mouse['end'][1] + self.dialogOffset)) 00647 00648 dlg = VDigitDuplicatesDialog(parent = self, data = dupl, pos = posWindow) 00649 00650 if dlg.ShowModal() == wx.ID_OK: 00651 self.digit.GetDisplay().UnSelect(dlg.GetUnSelected()) 00652 # update selected 00653 self.UpdateMap(render = False) 00654 00655 if action != "editLine": 00656 # -> move line || move vertex 00657 self.UpdateMap(render = False) 00658 00659 else: # no vector object found 00660 if not (action in ("moveLine", 00661 "moveVertex") and \ 00662 hasattr(self, "moveInfo") and \ 00663 len(self.moveInfo['id']) > 0): 00664 # avoid left-click when features are already selected 00665 self.UpdateMap(render = False, renderVector = False) 00666 00667 def OnLeftUpModifyLine(self, event): 00668 """!Left mouse button released - vector digitizer split line, 00669 add/remove vertex action 00670 """ 00671 pos1 = self.Pixel2Cell(self.mouse['begin']) 00672 00673 pointOnLine = self.digit.GetDisplay().SelectLineByPoint(pos1)['point'] 00674 if not pointOnLine: 00675 return 00676 00677 if self.toolbar.GetAction() in ["splitLine", "addVertex"]: 00678 self.UpdateMap(render = False) # highlight object 00679 self.DrawCross(pdc = self.pdcTmp, coords = self.Cell2Pixel((pointOnLine[0], pointOnLine[1])), 00680 size = 5) 00681 else: # removeVertex 00682 # get only id of vertex 00683 try: 00684 id = self.digit.GetDisplay().GetSelectedVertex(pos1)[0] 00685 except IndexError: 00686 id = None 00687 00688 if id: 00689 x, y = self.pdcVector.GetIdBounds(id)[0:2] 00690 self.pdcVector.RemoveId(id) 00691 self.UpdateMap(render = False) # highlight object 00692 self.DrawCross(pdc = self.pdcTmp, coords = (x, y), 00693 size = 5) 00694 else: 00695 # unselect 00696 self.digit.GetDisplay().SetSelected([]) 00697 self.UpdateMap(render = False) 00698 00699 def OnLeftUpCopyLine(self, event): 00700 """!Left mouse button released - vector digitizer copy feature 00701 action 00702 """ 00703 pos1 = self.Pixel2Cell(self.mouse['begin']) 00704 pos2 = self.Pixel2Cell(self.mouse['end']) 00705 00706 if UserSettings.Get(group = 'vdigit', key = 'bgmap', 00707 subkey = 'value', internal = True) == '': 00708 # no background map -> copy from current vector map layer 00709 nselected = self.bdigit.GetDisplay().SelectLinesByBox((pos1, pos2)) 00710 00711 if nselected > 0: 00712 # highlight selected features 00713 self.UpdateMap(render = False) 00714 else: 00715 self.UpdateMap(render = False, renderVector = False) 00716 else: 00717 # copy features from background map 00718 self.copyIds = self.digit.SelectLinesFromBackgroundMap(bbox = (pos1, pos2)) 00719 if len(self.copyIds) > 0: 00720 color = UserSettings.Get(group = 'vdigit', key = 'symbol', 00721 subkey = ['highlight', 'color']) 00722 colorStr = str(color[0]) + ":" + str(color[1]) + ":" + str(color[2]) 00723 dVectTmp = ['d.vect', 00724 'map=%s' % UserSettings.Get(group = 'vdigit', key = 'bgmap', 00725 subkey = 'value', internal = True), 00726 'cats=%s' % ListOfCatsToRange(self.copyIds), 00727 '-i', 00728 'color=%s' % colorStr, 00729 'fcolor=%s' % colorStr, 00730 'type=point,line,boundary,centroid', 00731 'width=2'] 00732 00733 if not self.layerTmp: 00734 self.layerTmp = self.Map.AddLayer(type = 'vector', 00735 name = QUERYLAYER, 00736 command = dVectTmp) 00737 else: 00738 self.layerTmp.SetCmd(dVectTmp) 00739 else: 00740 if self.layerTmp: 00741 self.Map.DeleteLayer(self.layerTmp) 00742 self.layerTmp = None 00743 00744 self.UpdateMap(render = True, renderVector = True) 00745 00746 def OnLeftUpBulkLine(self, event): 00747 """!Left mouse button released - vector digitizer z-bulk line 00748 action 00749 """ 00750 # select lines to be labeled 00751 pos1 = self.polycoords[0] 00752 pos2 = self.polycoords[1] 00753 nselected = self.digit.GetDisplay().SelectLinesByBox((pos1, pos2)) 00754 00755 if nselected > 0: 00756 # highlight selected features 00757 self.UpdateMap(render = False) 00758 self.DrawLines(pdc = self.pdcTmp) # redraw temp line 00759 else: 00760 self.UpdateMap(render = False, renderVector = False) 00761 00762 def OnLeftUpConnectLine(self, event): 00763 """!Left mouse button released - vector digitizer connect line 00764 action 00765 """ 00766 if len(self.digit.GetDisplay().GetSelected()) > 0: 00767 self.UpdateMap(render = False) 00768 00769 def _onLeftUp(self, event): 00770 """!Left mouse button released""" 00771 if hasattr(self, "moveInfo"): 00772 if len(self.digit.GetDisplay().GetSelected()) == 0: 00773 self.moveInfo['begin'] = self.Pixel2Cell(self.mouse['begin']) # left down 00774 00775 # eliminate initial mouse moving efect 00776 self.mouse['begin'] = self.mouse['end'] 00777 00778 action = self.toolbar.GetAction() 00779 if action in ("deleteLine", 00780 "moveLine", 00781 "moveVertex", 00782 "copyCats", 00783 "copyAttrs", 00784 "editLine", 00785 "flipLine", 00786 "mergeLine", 00787 "snapLine", 00788 "queryLine", 00789 "breakLine", 00790 "typeConv", 00791 "connectLine"): 00792 self.OnLeftUpVarious(event) 00793 00794 elif action in ("splitLine", 00795 "addVertex", 00796 "removeVertex"): 00797 self.OnLeftUpModifyLine(event) 00798 00799 elif action == "copyLine": 00800 self.OnLeftUpCopyLine(event) 00801 00802 elif action == "zbulkLine" and \ 00803 len(self.polycoords) == 2: 00804 self.OnLeftUpBulkLine(event) 00805 00806 elif action == "connectLine": 00807 self.OnLeftUpConnectLine(event) 00808 00809 if len(self.digit.GetDisplay().GetSelected()) > 0: 00810 self.redrawAll = None 00811 00812 def _onRightDown(self, event): 00813 # digitization tool (confirm action) 00814 action = self.toolbar.GetAction() 00815 if action in ("moveLine", "moveVertex") and \ 00816 hasattr(self, "moveInfo"): 00817 pFrom = self.moveInfo['begin'] 00818 pTo = self.Pixel2Cell(event.GetPositionTuple()) 00819 00820 move = (pTo[0] - pFrom[0], 00821 pTo[1] - pFrom[1]) 00822 00823 if action == "moveLine": 00824 # move line 00825 if self.digit.MoveSelectedLines(move) < 0: 00826 return 00827 elif action == "moveVertex": 00828 # move vertex 00829 fid = self.digit.MoveSelectedVertex(pFrom, move) 00830 if fid < 0: 00831 return 00832 00833 self._geomAttrbUpdate([fid,]) 00834 00835 del self.moveInfo 00836 00837 def _onRightUp(self, event): 00838 """!Right mouse button released (confirm action) 00839 """ 00840 action = self.toolbar.GetAction() 00841 if action == "addLine" and \ 00842 self.toolbar.GetAction('type') in ["line", "boundary", "area"]: 00843 # -> add new line / boundary 00844 try: 00845 mapName = self.toolbar.GetLayer().GetName() 00846 except: 00847 mapName = None 00848 gcmd.GError(parent = self, 00849 message = _("No vector map selected for editing.")) 00850 00851 if mapName: 00852 if self.toolbar.GetAction('type') == 'line': 00853 line = True 00854 else: 00855 line = False 00856 00857 if len(self.polycoords) < 2: # ignore 'one-point' lines 00858 return 00859 00860 nfeat, fids = self.digit.AddFeature(self.toolbar.GetAction('type'), self.polycoords) 00861 if nfeat < 0: 00862 return 00863 00864 position = self.Cell2Pixel(self.polycoords[-1]) 00865 self.polycoords = [] 00866 self.UpdateMap(render = False) 00867 self.redrawAll = True 00868 self.Refresh() 00869 00870 # add new record into atribute table 00871 if UserSettings.Get(group = 'vdigit', key = "addRecord", subkey = 'enabled') and \ 00872 (line is True or \ 00873 (not line and nfeat > 0)): 00874 posWindow = self.ClientToScreen((position[0] + self.dialogOffset, 00875 position[1] + self.dialogOffset)) 00876 00877 # select attributes based on layer and category 00878 cats = { fids[0] : { 00879 UserSettings.Get(group = 'vdigit', key = "layer", subkey = 'value') : 00880 (UserSettings.Get(group = 'vdigit', key = "category", subkey = 'value'), ) 00881 }} 00882 00883 addRecordDlg = dbm_dialogs.DisplayAttributesDialog(parent = self, map = mapName, 00884 cats = cats, 00885 pos = posWindow, 00886 action = "add") 00887 00888 for fid in fids: 00889 self._geomAttrb(fid, addRecordDlg, 'length') 00890 # auto-placing centroid 00891 self._geomAttrb(fid, addRecordDlg, 'area') 00892 self._geomAttrb(fid, addRecordDlg, 'perimeter') 00893 00894 00895 if addRecordDlg.mapDBInfo and \ 00896 addRecordDlg.ShowModal() == wx.ID_OK: 00897 sqlfile = tempfile.NamedTemporaryFile(mode = "w") 00898 for sql in addRecordDlg.GetSQLString(): 00899 sqlfile.file.write(sql + ";\n") 00900 sqlfile.file.flush() 00901 gcmd.RunCommand('db.execute', 00902 parent = True, 00903 quiet = True, 00904 input = sqlfile.name) 00905 00906 if addRecordDlg.mapDBInfo: 00907 self._updateATM() 00908 00909 elif action == "deleteLine": 00910 # -> delete selected vector features 00911 if self.digit.DeleteSelectedLines() < 0: 00912 return 00913 self._updateATM() 00914 elif action == "splitLine": 00915 # split line 00916 if self.digit.SplitLine(self.Pixel2Cell(self.mouse['begin'])) < 0: 00917 return 00918 elif action == "addVertex": 00919 # add vertex 00920 fid = self.digit.AddVertex(self.Pixel2Cell(self.mouse['begin'])) 00921 if fid < 0: 00922 return 00923 elif action == "removeVertex": 00924 # remove vertex 00925 fid = self.digit.RemoveVertex(self.Pixel2Cell(self.mouse['begin'])) 00926 if fid < 0: 00927 return 00928 self._geomAttrbUpdate([fid,]) 00929 elif action in ("copyCats", "copyAttrs"): 00930 if action == 'copyCats': 00931 if self.digit.CopyCats(self.copyCatsList, 00932 self.copyCatsIds, copyAttrb = False) < 0: 00933 return 00934 else: 00935 if self.digit.CopyCats(self.copyCatsList, 00936 self.copyCatsIds, copyAttrb = True) < 0: 00937 return 00938 00939 del self.copyCatsList 00940 del self.copyCatsIds 00941 00942 self._updateATM() 00943 00944 elif action == "editLine" and \ 00945 hasattr(self, "moveInfo"): 00946 line = self.digit.GetDisplay().GetSelected()[0] 00947 if self.digit.EditLine(line, self.polycoords) < 0: 00948 return 00949 00950 del self.moveInfo 00951 00952 elif action == "flipLine": 00953 if self.digit.FlipLine() < 0: 00954 return 00955 elif action == "mergeLine": 00956 if self.digit.MergeLine() < 0: 00957 return 00958 elif action == "breakLine": 00959 if self.digit.BreakLine() < 0: 00960 return 00961 elif action == "snapLine": 00962 if self.digit.SnapLine() < 0: 00963 return 00964 elif action == "connectLine": 00965 if len(self.digit.GetDisplay().GetSelected()) > 1: 00966 if self.digit.ConnectLine() < 0: 00967 return 00968 elif action == "copyLine": 00969 if self.digit.CopyLine(self.copyIds) < 0: 00970 return 00971 del self.copyIds 00972 if self.layerTmp: 00973 self.Map.DeleteLayer(self.layerTmp) 00974 self.UpdateMap(render = True, renderVector = False) 00975 del self.layerTmp 00976 00977 elif action == "zbulkLine" and len(self.polycoords) == 2: 00978 pos1 = self.polycoords[0] 00979 pos2 = self.polycoords[1] 00980 00981 selected = self.digit.GetDisplay().GetSelected() 00982 dlg = VDigitZBulkDialog(parent = self, title = _("Z bulk-labeling dialog"), 00983 nselected = len(selected)) 00984 if dlg.ShowModal() == wx.ID_OK: 00985 if self.digit.ZBulkLines(pos1, pos2, dlg.value.GetValue(), 00986 dlg.step.GetValue()) < 0: 00987 return 00988 self.UpdateMap(render = False) 00989 elif action == "typeConv": 00990 # -> feature type conversion 00991 # - point <-> centroid 00992 # - line <-> boundary 00993 if self.digit.TypeConvForSelectedLines() < 0: 00994 return 00995 00996 if action != "addLine": 00997 # unselect and re-render 00998 self.digit.GetDisplay().SetSelected([]) 00999 self.polycoords = [] 01000 self.UpdateMap(render = False) 01001 01002 def _onMouseMoving(self, event): 01003 self.mouse['end'] = event.GetPositionTuple()[:] 01004 01005 Debug.msg (5, "BufferedWindow.OnMouseMoving(): coords=%f,%f" % \ 01006 (self.mouse['end'][0], self.mouse['end'][1])) 01007 01008 action = self.toolbar.GetAction() 01009 if action == "addLine" and \ 01010 self.toolbar.GetAction('type') in ["line", "boundary", "area"]: 01011 if len(self.polycoords) > 0: 01012 self.MouseDraw(pdc = self.pdcTmp, begin = self.Cell2Pixel(self.polycoords[-1])) 01013 01014 elif action in ["moveLine", "moveVertex", "editLine"] \ 01015 and hasattr(self, "moveInfo"): 01016 dx = self.mouse['end'][0] - self.mouse['begin'][0] 01017 dy = self.mouse['end'][1] - self.mouse['begin'][1] 01018 01019 # draw lines on new position 01020 if action == "moveLine" and \ 01021 len(self.moveInfo['id']) > 0: 01022 # move line 01023 for id in self.moveInfo['id']: 01024 self.pdcTmp.TranslateId(id, dx, dy) 01025 elif action in ["moveVertex", "editLine"]: 01026 # move vertex -> 01027 # (vertex, left vertex, left line, 01028 # right vertex, right line) 01029 01030 # do not draw static lines 01031 if action == "moveVertex" and \ 01032 len(self.moveInfo['id']) > 0: 01033 self.polycoords = [] 01034 self.pdcTmp.RemoveId(self.moveInfo['id'][0]) 01035 if self.moveInfo['id'][1] > 0: # previous vertex 01036 x, y = self.Pixel2Cell(self.pdcTmp.GetIdBounds(self.moveInfo['id'][1])[0:2]) 01037 self.pdcTmp.RemoveId(self.moveInfo['id'][1] + 1) 01038 self.polycoords.append((x, y)) 01039 self.polycoords.append(self.Pixel2Cell(self.mouse['end'])) 01040 01041 if self.moveInfo['id'][2] > 0: # next vertex 01042 x, y = self.Pixel2Cell(self.pdcTmp.GetIdBounds(self.moveInfo['id'][2])[0:2]) 01043 self.pdcTmp.RemoveId(self.moveInfo['id'][2]-1) 01044 self.polycoords.append((x, y)) 01045 01046 self.ClearLines(pdc = self.pdcTmp) 01047 self.DrawLines(pdc = self.pdcTmp) 01048 01049 if action == "editLine": 01050 self.MouseDraw(pdc = self.pdcTmp, 01051 begin = self.Cell2Pixel(self.polycoords[-1])) 01052 01053 self.Refresh() # TODO: use RefreshRect() 01054 self.mouse['begin'] = self.mouse['end'] 01055 01056 elif action == "zbulkLine": 01057 if len(self.polycoords) == 1: 01058 # draw mouse moving 01059 self.MouseDraw(self.pdcTmp) 01060 01061 def _zoom(self, event): 01062 tmp1 = self.mouse['end'] 01063 tmp2 = self.Cell2Pixel(self.moveInfo['begin']) 01064 dx = tmp1[0] - tmp2[0] 01065 dy = tmp1[1] - tmp2[1] 01066 self.moveInfo['beginDiff'] = (dx, dy) 01067 for id in self.moveInfo['id']: 01068 self.pdcTmp.RemoveId(id) 01069