GRASS Programmer's Manual  6.4.2(2012)
mapdisp_vdigit.py
Go to the documentation of this file.
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         
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines