[GRASS-SVN] r44893 - grass/trunk/gui/wxpython/gui_modules

svn_grass at osgeo.org svn_grass at osgeo.org
Wed Jan 5 18:10:14 EST 2011


Author: martinl
Date: 2011-01-05 15:10:14 -0800 (Wed, 05 Jan 2011)
New Revision: 44893

Modified:
   grass/trunk/gui/wxpython/gui_modules/mapdisp_window.py
   grass/trunk/gui/wxpython/gui_modules/wxvdigit.py
   grass/trunk/gui/wxpython/gui_modules/wxvdriver.py
Log:
wxGUI/vdigit pythonized: add new feature works


Modified: grass/trunk/gui/wxpython/gui_modules/mapdisp_window.py
===================================================================
--- grass/trunk/gui/wxpython/gui_modules/mapdisp_window.py	2011-01-05 23:08:58 UTC (rev 44892)
+++ grass/trunk/gui/wxpython/gui_modules/mapdisp_window.py	2011-01-05 23:10:14 UTC (rev 44893)
@@ -565,9 +565,8 @@
                 # self.bufferLast = wx.BitmapFromImage(self.buffer.ConvertToImage())
                 self.bufferLast = dc.GetAsBitmap(wx.Rect(0, 0, self.Map.width, self.Map.height))
             
-            pdcLast = self.PseudoDC(vdigit = False)
-            pdcLast.DrawBitmap(self.bufferLast, 0, 0, False)
-            pdcLast.DrawToDC(dc)
+            self.pdc.DrawBitmap(self.bufferLast, 0, 0, False)
+            self.pdc.DrawToDC(dc)
         
         # draw decorations (e.g. region box)
         try:
@@ -782,7 +781,7 @@
             # set region
             self.parent.digit.GetDisplay().UpdateRegion()
             # re-calculate threshold for digitization tool
-            # self.parent.digit.driver.GetThreshold()
+            # self.parent.digit.GetDisplay().GetThreshold()
             # draw map
             if self.pdcVector:
                 self.pdcVector.Clear()
@@ -1234,7 +1233,7 @@
             if (event.LeftIsDown() and 
                 not (digitToolbar and 
                     digitToolbar.GetAction() in ("moveLine",) and 
-                    digitClass.driver.GetSelected() > 0)):
+                    digitClass.GetDisplay().GetSelected() > 0)):
                 # draw box only when left mouse button is pressed
                 self.MouseDraw(pdc = self.pdcTmp)
         
@@ -1252,22 +1251,17 @@
         except:
             return
         
-        if digitToolbar.GetAction('type') in ["point", "centroid"]:
-            # add new point
-            if digitToolbar.GetAction('type') == 'point':
-                point = True
-            else:
-                point = False
-
+        if digitToolbar.GetAction('type') in ['point', 'centroid']:
+            # add new point / centroiud
             east, north = self.Pixel2Cell(self.mouse['begin'])
-            fid = digitClass.AddPoint(mapLayer, point, east, north)
+            fid = digitClass.AddFeature(digitToolbar.GetAction('type'), [(east, north)])
             if fid < 0:
                 return
-
+            
             self.UpdateMap(render = False) # redraw map
             
             # add new record into atribute table
-            if UserSettings.Get(group = 'vdigit', key = "addRecord", subkey = 'enabled')  is True:
+            if UserSettings.Get(group = 'vdigit', key = "addRecord", subkey = 'enabled'):
                 # select attributes based on layer and category
                 cats = { fid : {
                         UserSettings.Get(group = 'vdigit', key = "layer", subkey = 'value') :
@@ -1446,19 +1440,19 @@
         coords = self.Pixel2Cell(self.mouse['begin'])
         
         # unselect
-        digitClass.driver.SetSelected([])
+        digitClass.GetDisplay().SetSelected([])
         
         # select feature by point
         cats = {}
-        if digitClass.driver.SelectLineByPoint(coords,
+        if digitClass.GetDisplay().SelectLineByPoint(coords,
                                                digitClass.GetSelectType()) is None:
             return
 
         if UserSettings.Get(group = 'vdigit', key = 'checkForDupl',
                             subkey = 'enabled'):
-            lines = digitClass.driver.GetSelected()
+            lines = digitClass.GetDisplay().GetSelected()
         else:
-            lines = (digitClass.driver.GetSelected()[0],) # only first found
+            lines = (digitClass.GetDisplay().GetSelected()[0],) # only first found
                         
         for line in lines:
             cats[line] = digitClass.GetLineCats(line)
@@ -1606,7 +1600,7 @@
                                             "removeVertex",
                                             "splitLines"):
                 # unselect
-                digitClass.driver.SetSelected([])
+                digitClass.GetDisplay().SetSelected([])
 
             if digitToolbar.GetAction() == "addLine":
                 self.OnLeftDownVDigitAddLine(event)
@@ -1665,25 +1659,25 @@
         # -> delete line || move line || move vertex
         if digitToolbar.GetAction() in ("moveVertex",
                                         "editLine"):
-            if len(digitClass.driver.GetSelected()) == 0:
-                nselected = digitClass.driver.SelectLineByPoint(pos1, type = VDigit_Lines_Type)
+            if len(digitClass.GetDisplay().GetSelected()) == 0:
+                nselected = digitClass.GetDisplay().SelectLineByPoint(pos1, type = VDigit_Lines_Type)
                 
                 if digitToolbar.GetAction() == "editLine":
                     try:
-                        selVertex = digitClass.driver.GetSelectedVertex(pos1)[0]
+                        selVertex = digitClass.GetDisplay().GetSelectedVertex(pos1)[0]
                     except IndexError:
                         selVertex = None
                         
                     if selVertex:
                         # self.UpdateMap(render=False)
-                        ids = digitClass.driver.GetSelected(grassId = False)
+                        ids = digitClass.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))
-                        digitClass.driver.DrawSelected(False) 
+                        digitClass.GetDisplay().DrawSelected(False) 
                                 
                         if selVertex < ids[-1] / 2:
                             # choose first or last node of line
@@ -1691,7 +1685,7 @@
                             self.polycoords.reverse()
                     else:
                         # unselect
-                        digitClass.driver.SetSelected([])
+                        digitClass.GetDisplay().SetSelected([])
                         del self.vdigitMove
                 
                     self.UpdateMap(render = False)
@@ -1700,33 +1694,33 @@
                                           "copyAttrs"):
             if not hasattr(self, "copyCatsIds"):
                 # 'from' -> select by point
-                nselected = digitClass.driver.SelectLineByPoint(pos1, digitClass.GetSelectType())
+                nselected = digitClass.GetDisplay().SelectLineByPoint(pos1, digitClass.GetSelectType())
                 if nselected:
-                    self.copyCatsList = digitClass.driver.GetSelected()
+                    self.copyCatsList = digitClass.GetDisplay().GetSelected()
             else:
                 # -> 'to' -> select by bbox
-                digitClass.driver.SetSelected([])
+                digitClass.GetDisplay().SetSelected([])
                 # return number of selected features (by box/point)
-                nselected = digitClass.driver.SelectLinesByBox(pos1, pos2,
+                nselected = digitClass.GetDisplay().SelectLinesByBox(pos1, pos2,
                                                                digitClass.GetSelectType())
                 if nselected == 0:
-                    if digitClass.driver.SelectLineByPoint(pos1,
+                    if digitClass.GetDisplay().SelectLineByPoint(pos1,
                                                            digitClass.GetSelectType()) is not None:
                         nselected = 1
                         
                 if nselected > 0:
-                    self.copyCatsIds = digitClass.driver.GetSelected()
+                    self.copyCatsIds = digitClass.GetDisplay().GetSelected()
 
         elif digitToolbar.GetAction() == "queryLine":
             selected = digitClass.SelectLinesByQuery(pos1, pos2)
             nselected = len(selected)
             if nselected > 0:
-                digitClass.driver.SetSelected(selected)
+                digitClass.GetDisplay().SetSelected(selected)
 
         else:
             # -> moveLine || deleteLine, etc. (select by point/box)
             if digitToolbar.GetAction() == 'moveLine' and \
-                    len(digitClass.driver.GetSelected()) > 0:
+                    len(digitClass.GetDisplay().GetSelected()) > 0:
                 nselected = 0
             else:
                 if digitToolbar.GetAction() == 'moveLine':
@@ -1734,12 +1728,12 @@
                 else:
                     drawSeg = False
 
-                nselected = digitClass.driver.SelectLinesByBox(pos1, pos2,
+                nselected = digitClass.GetDisplay().SelectLinesByBox(pos1, pos2,
                                                                digitClass.GetSelectType(),
                                                                drawSeg)
                     
                 if nselected == 0:
-                    if digitClass.driver.SelectLineByPoint(pos1,
+                    if digitClass.GetDisplay().SelectLineByPoint(pos1,
                                                            digitClass.GetSelectType()) is not None:
                         nselected = 1
         
@@ -1749,18 +1743,18 @@
                 # get pseudoDC id of objects which should be redrawn
                 if digitToolbar.GetAction() == "moveLine":
                     # -> move line
-                    self.vdigitMove['id'] = digitClass.driver.GetSelected(grassId = False)
-                    self.vdigitMove['coord'] = digitClass.driver.GetSelectedCoord()
+                    self.vdigitMove['id'] = digitClass.GetDisplay().GetSelected(grassId = False)
+                    self.vdigitMove['coord'] = digitClass.GetDisplay().GetSelectedCoord()
                 else: # moveVertex
-                    self.vdigitMove['id'] = digitClass.driver.GetSelectedVertex(pos1)
+                    self.vdigitMove['id'] = digitClass.GetDisplay().GetSelectedVertex(pos1)
                     if len(self.vdigitMove['id']) == 0: # no vertex found
-                        digitClass.driver.SetSelected([])
+                        digitClass.GetDisplay().SetSelected([])
                 
             #
             # check for duplicates
             #
             if UserSettings.Get(group = 'vdigit', key = 'checkForDupl', subkey = 'enabled') is True:
-                dupl = digitClass.driver.GetDuplicates()
+                dupl = digitClass.GetDisplay().GetDuplicates()
                 self.UpdateMap(render = False)
                     
                 if dupl:
@@ -1770,7 +1764,7 @@
                     dlg = VDigitDuplicatesDialog(parent = self, data = dupl, pos = posWindow)
                     
                     if dlg.ShowModal() == wx.ID_OK:
-                        digitClass.driver.UnSelect(dlg.GetUnSelected())
+                        digitClass.GetDisplay().UnSelect(dlg.GetUnSelected())
                         # update selected
                         self.UpdateMap(render = False)
                 
@@ -1795,7 +1789,7 @@
         
         pos1 = self.Pixel2Cell(self.mouse['begin'])
         
-        pointOnLine = digitClass.driver.SelectLineByPoint(pos1,
+        pointOnLine = digitClass.GetDisplay().SelectLineByPoint(pos1,
                                                           type = VDigit_Lines_Type)
 
         if not pointOnLine:
@@ -1808,7 +1802,7 @@
         else: # removeVertex
             # get only id of vertex
             try:
-                id = digitClass.driver.GetSelectedVertex(pos1)[0]
+                id = digitClass.GetDisplay().GetSelectedVertex(pos1)[0]
             except IndexError:
                 id = None
 
@@ -1820,7 +1814,7 @@
                                size = 5)
             else:
                 # unselect
-                digitClass.driver.SetSelected([])
+                digitClass.GetDisplay().SetSelected([])
                 self.UpdateMap(render = False)
 
     def OnLeftUpVDigitCopyLine(self, event):
@@ -1836,7 +1830,7 @@
         if UserSettings.Get(group = 'vdigit', key = 'bgmap',
                             subkey = 'value', internal = True) == '':
             # no background map -> copy from current vector map layer
-            nselected = digitClass.driver.SelectLinesByBox(pos1, pos2,
+            nselected = digitClass.GetDisplay().SelectLinesByBox(pos1, pos2,
                                                            digitClass.GetSelectType())
 
             if nselected > 0:
@@ -1886,7 +1880,7 @@
         # select lines to be labeled
         pos1 = self.polycoords[0]
         pos2 = self.polycoords[1]
-        nselected = digitClass.driver.SelectLinesByBox(pos1, pos2,
+        nselected = digitClass.GetDisplay().SelectLinesByBox(pos1, pos2,
                                                        digitClass.GetSelectType())
 
         if nselected > 0:
@@ -1903,7 +1897,7 @@
         digitToolbar = self.parent.toolbars['vdigit']
         digitClass   = self.parent.digit
         
-        if len(digitClass.driver.GetSelected()) > 0:
+        if len(digitClass.GetDisplay().GetSelected()) > 0:
             self.UpdateMap(render = False)
         
     def OnLeftUp(self, event):
@@ -1988,7 +1982,7 @@
             digitClass   = self.parent.digit
             
             if hasattr(self, "vdigitMove"):
-                if len(digitClass.driver.GetSelected()) == 0:
+                if len(digitClass.GetDisplay().GetSelected()) == 0:
                     self.vdigitMove['begin'] = self.Pixel2Cell(self.mouse['begin']) # left down
                 
                 # eliminate initial mouse moving efect
@@ -2024,7 +2018,7 @@
             elif digitToolbar.GetAction() == "connectLine":
                 self.OnLeftUpConnectLine(event)
             
-            if len(digitClass.driver.GetSelected()) > 0:
+            if len(digitClass.GetDisplay().GetSelected()) > 0:
                 self.redrawAll = None
             
         elif (self.mouse['use'] == 'pointer' and 
@@ -2142,19 +2136,10 @@
                                   caption = _("Error"), style = wx.OK | wx.ICON_ERROR | wx.CENTRE)
                     
                 if map:
-                    # mapcoords = []
-                    # xy -> EN
-                    # for coord in self.polycoords:
-                    #    mapcoords.append(self.Pixel2Cell(coord))
-                    if digitToolbar.GetAction('type') == 'line':
-                        line = True
-                    else:
-                        line = False
-
                     if len(self.polycoords) < 2: # ignore 'one-point' lines
                         return
                     
-                    fid = digitClass.AddLine(map, line, self.polycoords)
+                    fid = digitClass.AddFeature(digitToolbar.GetAction('type'), self.polycoords)
                     if fid < 0:
                         return
                     
@@ -2244,7 +2229,7 @@
                 
             elif digitToolbar.GetAction() == "editLine" and \
                     hasattr(self, "vdigitMove"):
-                line = digitClass.driver.GetSelected()
+                line = digitClass.GetDisplay().GetSelected()
                 if digitClass.EditLine(line, self.polycoords) < 0:
                     return
                 
@@ -2263,7 +2248,7 @@
                 if digitClass.SnapLine() < 0:
                     return
             elif digitToolbar.GetAction() == "connectLine":
-                if len(digitClass.driver.GetSelected()) > 1:
+                if len(digitClass.GetDisplay().GetSelected()) > 1:
                     if digitClass.ConnectLine() < 0:
                         return
             elif digitToolbar.GetAction() == "copyLine":
@@ -2279,7 +2264,7 @@
                 pos1 = self.polycoords[0]
                 pos2 = self.polycoords[1]
 
-                selected = digitClass.driver.GetSelected()
+                selected = digitClass.GetDisplay().GetSelected()
                 dlg = VDigitZBulkDialog(parent = self, title = _("Z bulk-labeling dialog"),
                                         nselected = len(selected))
                 if dlg.ShowModal() == wx.ID_OK:
@@ -2296,7 +2281,7 @@
 
             if digitToolbar.GetAction() != "addLine":
                 # unselect and re-render
-                digitClass.driver.SetSelected([])
+                digitClass.GetDisplay().SetSelected([])
                 self.polycoords = []
                 self.UpdateMap(render = False)
 
@@ -2341,7 +2326,7 @@
                                               "snapLine", "connectLine", "copyLine",
                                               "queryLine", "breakLine", "typeConv"]:
                 # varios tools -> unselected selected features
-                digitClass.driver.SetSelected([])
+                digitClass.GetDisplay().SetSelected([])
                 if digitToolbar.GetAction() in ["moveLine", "moveVertex", "editLine"] and \
                         hasattr(self, "vdigitMove"):
 
@@ -2367,7 +2352,7 @@
             elif digitToolbar.GetAction() == "zbulkLine":
                 # reset polyline
                 self.polycoords = []
-                digitClass.driver.SetSelected([])
+                digitClass.GetDisplay().SetSelected([])
                 self.UpdateMap(render = False)
             
             self.redrawAll = True

Modified: grass/trunk/gui/wxpython/gui_modules/wxvdigit.py
===================================================================
--- grass/trunk/gui/wxpython/gui_modules/wxvdigit.py	2011-01-05 23:08:58 UTC (rev 44892)
+++ grass/trunk/gui/wxpython/gui_modules/wxvdigit.py	2011-01-05 23:10:14 UTC (rev 44893)
@@ -3,8 +3,8 @@
 
 @brief wxGUI vector digitizer (base class)
 
-Code based on wxVdigit C++ component from GRASS 6.4.0. Converted to
-Python in 2010/12-2011/01.
+Code based on wxVdigit C++ component from GRASS 6.4.0
+(gui/wxpython/vdigit). Converted to Python in 2010/12-2011/01.
 
 List of classes:
  - IVDigit
@@ -20,14 +20,19 @@
 from debug       import Debug
 from preferences import globalSettings as UserSettings
 
-from wxvdriver import DisplayDriver
+from wxvdriver   import DisplayDriver
 
 from grass.lib.grass  import *
 from grass.lib.vector import *
+from grass.lib.vedit  import *
 
 class IVDigit:
     def __init__(self, mapwindow):
-        self.map       = None
+        """!Base class for vector digitizer (ctypes interface)
+        
+        @parem mapwindow reference for map window (BufferedWindow)
+        """
+        self.mapInfo   = None      # pointer to Map_info
         self.mapWindow = mapwindow
         
         if not mapwindow.parent.IsStandalone():
@@ -46,32 +51,56 @@
         
         # layer / max category
         self.cats = dict()
+
         # settings
-        self._settings = {
-            'breakLines'  : None,
-            'addCentroid' : None,
-            'catBoundary' : None
+        self.settings = {
+            'breakLines'  : False,
+            'addCentroid' : False,
+            'catBoundary' : True,
             }
+        
         # undo/redo
         self.changesets = dict()
-        self.changesetCurrent = None # first changeset to apply
-        self.changesetEnd     = None # last changeset to be applied
+        self.changesetCurrent = -1 # first changeset to apply
+        self.changesetEnd     = -1 # last changeset to be applied
         
-        if self._display.mapInfo:
+        if self.mapInfo:
             self.InitCats()
         
-        # initial value for undo/redo
-        self.changesetEnd = self.changesetCurrent = -1
-        
     def __del__(self):
         pass # free changesets ?
 
     def _setCategory(self):
         pass
     
-    def _openBackgroundVectorMap(self):
-        pass
+    def _openBackgroundMap(self, bgmap):
+        """!Open background vector map
 
+        @todo support more background maps then only one
+        
+        @param bgmap name of vector map to be opened
+
+        @return map_info
+        @return None on error
+        """
+        name = c_char()
+        mapset = c_char()
+        if not G__name_is_fully_qualified(bgmap, byref(name), byref(mapset)):
+            name = bgmap
+            mapset = G_find_vector2(bgmap, '')
+        else:
+            name = name.value
+            mapset = mapset.value
+
+        if (name == Vect_get_name(self.mapInfo) and \
+                mapset == Vect_get_mapset(self.mapInfo)):
+            return None
+
+        bgMapInfo = map_info()
+	if Vect_open_old(byref(bgMapInfo), name, mapset) == -1:
+            return None
+        return bgMapInfo
+    
     def _breakLineAtIntersection(self):
         pass
     
@@ -85,9 +114,30 @@
     def _addActionsAfter(self):
         pass
 
-    def _addActionToChangeset(self):
-        pass
-
+    def _addActionToChangeset(self, changeset, add, line):
+        """!Add action to changeset
+        
+        @param changeset id of changeset
+        @param add True to add, otherwise delete
+        @param line feature id
+        """
+        if not self.mapInfo:
+            return 
+        
+        if not Vect_line_alive(self.mapInfo, line):
+            return
+        
+        offset = Vect_get_line_offset(self.mapInfo, line)
+        
+        if not self.changesets.has_key(changeset):
+            self.changesets[changeset] = list()
+            self.changesetCurrent = changeset
+        
+        self.changesets[changeset].append((type, line, offset))
+        
+        Debug.msg(3, "IVDigit._addActionToChangeset(): changeset=%d, type=%d, line=%d, offset=%d",
+                  changeset, type, line, offset)
+        
     def _applyChangeset(self):
         pass
 
@@ -97,77 +147,48 @@
     def _removeActionFromChangeset(self):
         pass
 
-    def AddPoint (self, map, point, x, y, z=None):
-        """!Add new point/centroid
-
-        @param map   map name (unused, for compatability with VEdit)
-        @param point feature type (if true point otherwise centroid)
-        @param x,y,z coordinates
+    def AddFeature(self, ftype, points):
+        """!Add new feature
+        
+        @param ftype feature type (point, line, centroid, boundary)
+        @param points tuple of points ((x, y), (x, y), ...)
+        
+        @return new feature id
         """
-        if UserSettings.Get(group='vdigit', key="categoryMode", subkey='selection') == 2:
+        if UserSettings.Get(group = 'vdigit', key = "categoryMode", subkey = 'selection') == 2:
             layer = -1 # -> no category
             cat   = -1
         else:
-            layer = UserSettings.Get(group='vdigit', key="layer", subkey='value')
-            cat   = self.SetCategory()
-            
-        if point:
-            type = wxvdigit.GV_POINT 
-        else:
-            type = wxvdigit.GV_CENTROID 
-
-        snap, thresh = self.__getSnapThreshold()
-
-        bgmap = str(UserSettings.Get(group='vdigit', key="bgmap",
-                                     subkey='value', internal=True))
-        if z:
-            ret = self.digit.AddLine(type, [x, y, z], layer, cat,
-                                     bgmap, snap, thresh)
-        else:
-            ret = self.digit.AddLine(type, [x, y], layer, cat,
-                                     bgmap, snap, thresh)
-        self.toolbar.EnableUndo()
-
-        return ret
+            layer = UserSettings.Get(group = 'vdigit', key = "layer", subkey = 'value')
+            cat   = self.cats.get(layer, 1)
         
-    def AddLine (self, map, line, coords):
-        """!Add line/boundary
-
-        @param map    map name (unused, for compatability with VEdit)
-        @param line   feature type (if True line, otherwise boundary)
-        @param coords list of coordinates
-        """
-        if len(coords) < 2:
-            return
+        snap, thresh = self._display.GetThreshold()
         
-        if UserSettings.Get(group='vdigit', key="categoryMode", subkey='selection') == 2:
-            layer = -1 # -> no category
-            cat   = -1
-        else:
-            layer = UserSettings.Get(group='vdigit', key="layer", subkey='value')
-            cat   = self.SetCategory()
+        bgmap = str(UserSettings.Get(group = 'vdigit', key = 'bgmap',
+                                     subkey = 'value', internal = True))
         
-        if line:
-            type = wxvdigit.GV_LINE
+        if ftype == 'point':
+            vtype = GV_POINT
+        elif ftype == 'line':
+            vtype = GV_LINE
+        elif ftype == 'centroid':
+            vtype = GV_CENTROID
+        elif ftype == 'boundary':
+            vtype = GV_BOUNDARY
         else:
-            type = wxvdigit.GV_BOUNDARY
+            gcmd.GError(parent = self.mapwindow,
+                        message = _("Unknown feature type '%s'") % ftype)
+            return
         
-        listCoords = []
-        for c in coords:
-            for x in c:
-                listCoords.append(x)
+        if vtype & GV_LINES and len(points) < 2:
+            gcmd.GError(parent = self.mapwindow,
+                        message = _("Not enough points for line"))
+            return
         
-        snap, thresh = self.__getSnapThreshold()
-        
-        bgmap = str(UserSettings.Get(group='vdigit', key="bgmap",
-                                     subkey='value', internal=True))
-        
-        ret = self.digit.AddLine(type, listCoords, layer, cat,
-                                 bgmap, snap, thresh)
-
         self.toolbar.EnableUndo()
         
-        return ret
+        return self._addFeature(vtype, points, layer, cat,
+                                bgmap, snap, thresh)
     
     def DeleteSelectedLines(self):
         """!Delete selected features
@@ -567,23 +588,6 @@
         
         return ret
     
-    def __getSnapThreshold(self):
-        """!Get snap mode and threshold value
-
-        @return (snap, thresh)
-        """
-        thresh = self.driver.GetThreshold()
-
-        if thresh > 0.0:
-            if UserSettings.Get(group='vdigit', key='snapToVertex', subkey='enabled') is True:
-                snap = wxvdigit.SNAPVERTEX
-            else:
-                snap = wxvdigit.SNAP
-        else:
-            snap = wxvdigit.NO_SNAP
-
-        return (snap, thresh)
-
     def GetDisplay(self):
         """!Get display driver instance"""
         return self._display
@@ -594,13 +598,12 @@
         @param map name of vector map to be set up
         """
         Debug.msg (3, "AbstractDigit.SetMapName map=%s" % name)
-        self.map = name
         
         name, mapset = name.split('@')
         try:
-            ret = self._display.OpenMap(str(name), str(mapset), True)
+            self.mapInfo = self._display.OpenMap(str(name), str(mapset), True)
         except SystemExit:
-                ret = -1
+            pass
         
         # except StandardError, e:
         #     raise gcmd.GException(_("Unable to initialize display driver of vector "
@@ -625,7 +628,7 @@
     def CloseMap(self):
         """!Close currently open vector map
         """
-        if not self.map:
+        if not self.mapInfo:
             return
         
         self._display.CloseMap()
@@ -637,30 +640,29 @@
         @return -1 on error
         """
         self.cats.clear()
-        mapInfo = self._display.mapInfo
-        if not mapInfo:
+        if not self.mapInfo:
             return -1
         
-        ndblinks = Vect_get_num_dblinks(byref(mapInfo))
+        ndblinks = Vect_get_num_dblinks(self.mapInfo)
         for i in range(ndblinks):
-            fi = Vect_get_dblink(byref(mapInfo), i).contents
+            fi = Vect_get_dblink(self.mapInfo, i).contents
             if fi:
                 self.cats[fi.number] = None
         
         # find max category
-        nfields = Vect_cidx_get_num_fields(byref(mapInfo))
+        nfields = Vect_cidx_get_num_fields(self.mapInfo)
         Debug.msg(2, "wxDigit.InitCats(): nfields=%d", nfields)
         
         for i in range(nfields):
-            field = Vect_cidx_get_field_number(byref(mapInfo), i)
-            ncats = Vect_cidx_get_num_cats_by_index(byref(mapInfo), i)
+            field = Vect_cidx_get_field_number(self.mapInfo, i)
+            ncats = Vect_cidx_get_num_cats_by_index(self.mapInfo, i)
             if field <= 0:
                 continue
             for j in range(ncats):
                 cat = c_int()
                 type = c_int()
                 id = c_int()
-                Vect_cidx_get_cat_by_index(byref(mapInfo), i, j,
+                Vect_cidx_get_cat_by_index(self.mapInfo, i, j,
                                            byref(cat), byref(type), byref(id))
                 if self.cats.has_key(field):
                     if cat > self.cats[field]:
@@ -675,9 +677,150 @@
                 self.cats[field] = 0 # first category 1
 	    Debug.msg(3, "wxDigit.InitCats(): layer=%d, cat=%d", field, self.cats[field])
         
-    def AddLine(self):
-        pass
+    def _errorWriteLine(self):
+        """!Show error dialog
+        """
+        gcmd.GError(parent = self.mapwindow,
+                    message = _("Writing new feature failed"))
+        
+    def _addFeature(self, type, coords, layer, cat, bgmap, snap, threshold):
+        """!Add new feature to the vector map
 
+        @param type feature type (GV_POINT, GV_LINE, GV_BOUNDARY, ...)
+        @coords tuple of coordinates ((x, y), (x, y), ...)
+        @param layer layer number (-1 for no cat)
+        @param cat category number
+        @param bgmap name of background vector map (None for no background) to be used for snapping
+        @param snap snap to node/vertex
+        @param threshold threshold for snapping
+        
+        @return -1 on error
+        @return feature id of new feature
+        """
+        if not self.mapInfo:
+            return -1
+        
+        is3D = bool(Vect_is_3d(self.mapInfo))
+        
+        Debug.msg(2, "IVDigit._addFeature(): npoints=%d, layer=%d, cat=%d, snap=%d",
+                  len(coords), layer, cat, snap)
+        
+        if not (type & (GV_POINTS | GV_LINES)): # TODO: 3D
+            return -1
+        
+        # try to open background map if asked
+        bgMapInfo = None
+        if bgmap:
+            bgMapInfo = self._openBackgroundMap(bgmap)
+            if not bgMapInfo:
+                gcmd.GError(parent = self.mapwindow,
+                            message = _("Unable to open background vector map <%s>") % bgmap)
+                return -1
+        
+        Points = Vect_new_line_struct()
+        Cats   = Vect_new_cats_struct() 
+        
+        # set category
+        if layer > 0 and \
+                (type != GV_BOUNDARY or \
+                     (type == GV_BOUNDARY and self.settings['catBoundary'])):
+            Vect_cat_set(Cats, layer, cat)
+            self.cats[layer] = max(cat, self.cats.get(layer, 0))
+        
+        # append points
+        for c in coords:
+            Vect_append_point(Points, c[0], c[1], 0.0)
+        
+        if type & GV_BOUNDARY:
+            # close boundary
+            cPoints = Points.contents
+            last = cPoints.n_points - 1
+            if Vect_points_distance(cPoints.x[0], cPoints.x[0], cPoints.z[0],
+                                    cPoints.x[last], cPoints.x[last], cPoints.z[last],
+                                    is3D) <= threshold:
+                cPoints.x[last] = cPoints.x[0]
+                cPoints.y[last] = cPoints.y[0]
+                cPoints.z[last] = cPoints.z[0]
+        
+        if snap != NO_SNAP and (type & (GV_POINT | GV_LINES)):
+            # apply snapping (node or vertex)
+            modeSnap = not (snap == SNAP)
+            if bgMapInfo:
+                Vedit_snap_line(self.mapInfo, byref(bgMapInfo), 1,
+                                -1, Points, threshold, modeSnap)
+            else:
+                # Vedit_snap_line(self.mapInfo, None, 0,
+                #                -1, Points, threshold, modeSnap)
+                pass
+        
+        newline = Vect_write_line(self.mapInfo, type, Points, Cats)
+        if newline < 0:
+            self._errorWriteLine()
+            return -1
+        
+        left = right = -1
+        if type & GV_BOUNDARY and self.settings['addCentroid']:
+            # add centroids for left/right area
+            bpoints = Vect_new_line_struct()
+            cleft = c_int()
+            cright = c_int()
+            
+            Vect_get_line_areas(self.mapInfo, newline,
+                                byref(cleft), byref(cright))
+            left = cleft.value
+            right = cright.value
+            
+            # check if area exists and has no centroid inside
+            if layer > 0 and (left > 0 or right > 0):
+                Vect_cat_set(Cats, layer, cat)
+                self.cats[layer] = max(cat, self.cats.get(layer, 0))
+            
+            x = c_double()
+            y = c_double()
+            if left > 0 and \
+                    Vect_get_area_centroid(self.mapInfo, left) == 0:
+                if Vect_get_area_points(self.mapInfo, left, bpoints) > 0 and \
+                        Vect_find_poly_centroid(bpoints, byref(x), byref(y)) == 0:
+                    Vect_reset_line(bpoints)
+                    Vect_append_point(bpoints, x.value, y.value, 0.0)
+                    if Vect_write_line(self.mapInfo, GV_CENTROID,
+                                       bpoints, Cats) < 0:
+                        self._errorWriteLine()
+                        return -1
+            
+            if right > 0 and \
+                    Vect_get_area_centroid(self.mapInfo, right) == 0:
+                if Vect_get_area_points(byref(self.mapInfo), right, bpoints) > 0 and \
+                        Vect_find_poly_centroid(bpoints, byref(x), byref(y)) == 0:
+                    Vect_reset_line(bpoints)
+                    Vect_append_point(bpoints, x.value, y.value, 0.0)
+                    if Vect_write_line(byref(self.mapInfo), GV_CENTROID,
+                                       bpoints, Cats) < 0:
+                        self._errorWriteLine()
+                        return -1
+            Vect_destroy_line_struct(bpoints)
+        
+        # register changeset
+        self._addActionToChangeset(len(self.changesets), True, newline)
+        
+        # break at intersection
+        if self.settings['breakLines']:
+            self._breakLineAtIntersection(newline, Points, changeset)
+        
+        Vect_destroy_line_struct(Points)
+        Vect_destroy_cats_struct(Cats)
+        
+        # close background map if opened
+        if bgMapInfo:
+            Vect_close(byref(bgMapInfo))
+        
+        if type & GV_BOUNDARY and \
+                not self.settings['catBoundary'] and \
+        	left < 1 and right < 1:
+            newline = None # ?
+        
+        return newline
+
     def RewriteLine(self):
         pass
     
@@ -734,20 +877,6 @@
 
     def CopyCats(self):
         pass
-
-    def GetCategory(self, layer):
-        """!Get max category number for layer
-        
-        @param layer layer number
-        
-        @return category number (0 if no category found)
-        @return -1 on error
-        """
-        if cats.find(layer) != cats.end():
-            Debug.msg(3, "vdigit.GetCategory(): layer=%d, cat=%d", layer, cats[layer])
-            return cats[layer]
-        
-        return 0
     
     def GetLineCats(self):
         pass
@@ -775,24 +904,23 @@
         self._settings['addCentroid'] = addCentroid
         self._settings['catBoundary'] = None # !catBoundary # do not attach
 
-    def SetCategory(self):
-        """!Return category number to use (according Settings)"""
+    def _getCategory(self):
+        """!Get current category number to be use"""
         if not UserSettings.Get(group = 'vdigit', key = 'categoryMode', subkey = 'selection'):
             self.SetCategoryNextToUse()
         
         return UserSettings.Get(group = 'vdigit', key = 'category', subkey = 'value')
 
-    def SetCategoryNextToUse(self):
-        """!Find maximum category number in the map layer
-        and update Digit.settings['category']
-
-        @return 'True' on success, 'False' on failure
+    def _setCategoryNextToUse(self):
+        """!Find maximum category number for the given layer and
+        update the settings
         """
-        # vector map layer without categories, reset to '1'
+        # reset 'category' to '1' (for maps with no attributes)
         UserSettings.Set(group = 'vdigit', key = 'category', subkey = 'value', value = 1)
         
-        if self.map:
-            cat = self.GetCategory(UserSettings.Get(group = 'vdigit', key = 'layer', subkey = 'value'))
-            cat += 1
-            UserSettings.Set(group = 'vdigit', key = 'category', subkey = 'value',
-                             value = cat)
+        # get max category number for given layer and update the settings
+        cat = self.cats.get(UserSettings.Get(group = 'vdigit', key = 'layer', subkey = 'value'), 0)
+        cat += 1
+        UserSettings.Set(group = 'vdigit', key = 'category', subkey = 'value',
+                         value = cat)
+        

Modified: grass/trunk/gui/wxpython/gui_modules/wxvdriver.py
===================================================================
--- grass/trunk/gui/wxpython/gui_modules/wxvdriver.py	2011-01-05 23:08:58 UTC (rev 44892)
+++ grass/trunk/gui/wxpython/gui_modules/wxvdriver.py	2011-01-05 23:10:14 UTC (rev 44893)
@@ -3,8 +3,8 @@
 
 @brief wxGUI vector digitizer (display driver)
 
-Code based on wxVdigit C++ component from GRASS 6.4.0. Converted to
-Python in 2010/12-2011/01.
+Code based on wxVdigit C++ component from GRASS 6.4.0
+(gui/wxpython/vdigit). Converted to Python in 2010/12-2011/01.
 
 List of classes:
  - DisplayDriver
@@ -35,9 +35,11 @@
         @param device    wx.PseudoDC device where to draw vector objects
         @param deviceTmp wx.PseudoDC device where to draw temporary vector objects
         """
-        G_gisinit("")             # initialize GRASS libs
+        G_gisinit('')             # initialize GRASS libs
         
-        self.mapInfo = None       # open vector map (Map_Info structure)
+        self.mapInfoObj = None    # open vector map (Map_Info structure)
+        self.mapInfo    = None    # pointer to self.mapInfoObj
+        
         self.dc      = device     # PseudoDC devices
         self.dcTmp   = deviceTmp
         self.mapObj  = mapObj
@@ -111,6 +113,8 @@
         self.drawSegments = False
 
         self.UpdateSettings()
+
+        Vect_set_fatal_error(GV_FATAL_PRINT)
         
     # def __del__(self):
     #     """!Close currently open vector map"""
@@ -329,7 +333,7 @@
         if not self.mapInfo or not self.dc or not self.dcTmp:
             return -1
         
-        rlist = Vedit_render_map(byref(self.mapInfo), byref(self._getRegionBox()), self._getDrawFlag(),
+        rlist = Vedit_render_map(self.mapInfo, byref(self._getRegionBox()), self._getDrawFlag(),
                                  self.region['center_easting'], self.region['center_northing'],
                                  self.mapObj.width, self.mapObj.height,
                                  max(self.region['nsres'], self.region['ewres'])).contents
@@ -374,7 +378,7 @@
             dc_ids.append(1)
         else:
             # only first selected feature
-            # Vect_read_line(byref(self.mapInfo), byref(self.points), None,
+            # Vect_read_line(self.mapInfo, byref(self.points), None,
             # self.selected.ids->value[0]);
             npoints = self.points.n_points
             # node - segment - vertex - segment - node
@@ -431,15 +435,15 @@
         """
         ret = 0
         if self.mapInfo:
-            if self.mapInfo.mode == GV_MODE_RW:
+            if self.mapInfoObj.mode == GV_MODE_RW:
                 # rebuild topology
-                Vect_build_partial(byref(self.mapInfo), GV_BUILD_NONE)
-                Vect_build(byref(self.mapInfo))
+                Vect_build_partial(self.mapInfo, GV_BUILD_NONE)
+                Vect_build(self.mapInfo)
 
             # close map and store topo/cidx
-            ret = Vect_close(byref(self.mapInfo))
-            del self.mapInfo
-            self.mapInfo = None
+            ret = Vect_close(self.mapInfo)
+            del self.mapInfoObj
+            self.mapInfo = self.mapInfoObj = None
         
         return ret
     
@@ -449,13 +453,14 @@
         @param name name of vector map to be open
         @param mapset name of mapset where the vector map lives
    
-        @return topo level on success
-        @return -1 on error
+        @return map_info
+        @return None on error
         """
         Debug.msg("DisplayDriver.OpenMap(): name=%s mapset=%s updated=%d",
                   name, mapset, update)
-        if not self.mapInfo:
-            self.mapInfo = Map_info()
+        if not self.mapInfoObj:
+            self.mapInfoObj = Map_info()
+            self.mapInfo = pointer(self.mapInfoObj)
         
         # define open level (level 2: topology)
         Vect_set_open_level(2)
@@ -465,15 +470,15 @@
         
         # open existing map
         if update:
-            ret = Vect_open_update(byref(self.mapInfo), name, mapset)
+            ret = Vect_open_update(self.mapInfo, name, mapset)
         else:
-            ret = Vect_open_old(byref(self.mapInfo), name, mapset)
-        
+            ret = Vect_open_old(self.mapInfo, name, mapset)
+
         if ret == -1: # error
-            del self.mapInfo
-            self.mapInfo = None
+            del self.mapInfoObj
+            self.mapInfo = self.mapInfoObj = None
         
-        return ret
+        return self.mapInfo
     
     def ReloadMap(self):
         pass
@@ -490,7 +495,7 @@
             return None
         
         bbox = bound_box()
-        Vect_get_map_box(byref(self.mapInfo), byref(bbox))
+        Vect_get_map_box(self.mapInfo, byref(bbox))
 
         return bbox.W, bbox.S, bbox.B, \
             bbox.E, bbox.N, bbox.T
@@ -541,14 +546,17 @@
         self.region = self.mapObj.GetCurrentRegion()
         
     def GetThreshold(self, type = 'snapping', value = None, units = None):
-        """!Return threshold in map units
+        """!Return threshold value in map units
         
+        @param type snapping mode (node, vertex)
         @param value threshold to be set up
         @param units units (map, screen)
+
+        @return (snap mode id, threshold value)
         """
         if value is None:
             value = UserSettings.Get(group = 'vdigit', key = type, subkey =' value')
-
+        
         if units is None:
             units = UserSettings.Get(group = 'vdigit', key = type, subkey = 'units')
         
@@ -562,6 +570,12 @@
         else:
             threshold = value
         
-        Debug.msg(4, "DisplayDriver.GetThreshold(): type=%s, thresh=%f" % (type, threshold))
-        
-        return threshold
+        if threshold > 0.0:
+            if UserSettings.Get(group = 'vdigit', key = 'snapToVertex', subkey = 'enabled'):
+                snap = SNAPVERTEX
+            else:
+                snap = SNAP
+        else:
+            snap = NO_SNAP
+
+        return (snap, threshold)



More information about the grass-commit mailing list