Преглед на файлове

wxGUI/vdigit pythonized: add new feature works

git-svn-id: https://svn.osgeo.org/grass/grass/trunk@44893 15284696-431f-4ddb-bdfa-cd5b030d7da7
Martin Landa преди 14 години
родител
ревизия
df466e18d8
променени са 3 файла, в които са добавени 359 реда и са изтрити 232 реда
  1. 51 66
      gui/wxpython/gui_modules/mapdisp_window.py
  2. 266 138
      gui/wxpython/gui_modules/wxvdigit.py
  3. 42 28
      gui/wxpython/gui_modules/wxvdriver.py

+ 51 - 66
gui/wxpython/gui_modules/mapdisp_window.py

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

+ 266 - 138
gui/wxpython/gui_modules/wxvdigit.py

@@ -3,8 +3,8 @@
 
 
 @brief wxGUI vector digitizer (base class)
 @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:
 List of classes:
  - IVDigit
  - IVDigit
@@ -20,14 +20,19 @@ This program is free software under the GNU General Public License
 from debug       import Debug
 from debug       import Debug
 from preferences import globalSettings as UserSettings
 from preferences import globalSettings as UserSettings
 
 
-from wxvdriver import DisplayDriver
+from wxvdriver   import DisplayDriver
 
 
 from grass.lib.grass  import *
 from grass.lib.grass  import *
 from grass.lib.vector import *
 from grass.lib.vector import *
+from grass.lib.vedit  import *
 
 
 class IVDigit:
 class IVDigit:
     def __init__(self, mapwindow):
     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
         self.mapWindow = mapwindow
         
         
         if not mapwindow.parent.IsStandalone():
         if not mapwindow.parent.IsStandalone():
@@ -46,32 +51,56 @@ class IVDigit:
         
         
         # layer / max category
         # layer / max category
         self.cats = dict()
         self.cats = dict()
+
         # settings
         # settings
-        self._settings = {
-            'breakLines'  : None,
-            'addCentroid' : None,
-            'catBoundary' : None
+        self.settings = {
+            'breakLines'  : False,
+            'addCentroid' : False,
+            'catBoundary' : True,
             }
             }
+        
         # undo/redo
         # undo/redo
         self.changesets = dict()
         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()
             self.InitCats()
         
         
-        # initial value for undo/redo
-        self.changesetEnd = self.changesetCurrent = -1
-        
     def __del__(self):
     def __del__(self):
         pass # free changesets ?
         pass # free changesets ?
 
 
     def _setCategory(self):
     def _setCategory(self):
         pass
         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):
     def _breakLineAtIntersection(self):
         pass
         pass
     
     
@@ -85,9 +114,30 @@ class IVDigit:
     def _addActionsAfter(self):
     def _addActionsAfter(self):
         pass
         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):
     def _applyChangeset(self):
         pass
         pass
 
 
@@ -97,77 +147,48 @@ class IVDigit:
     def _removeActionFromChangeset(self):
     def _removeActionFromChangeset(self):
         pass
         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
-        """
-        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
+    def AddFeature(self, ftype, points):
+        """!Add new feature
         
         
-    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
+        @param ftype feature type (point, line, centroid, boundary)
+        @param points tuple of points ((x, y), (x, y), ...)
         
         
-        if UserSettings.Get(group='vdigit', key="categoryMode", subkey='selection') == 2:
+        @return new feature id
+        """
+        if UserSettings.Get(group = 'vdigit', key = "categoryMode", subkey = 'selection') == 2:
             layer = -1 # -> no category
             layer = -1 # -> no category
             cat   = -1
             cat   = -1
         else:
         else:
-            layer = UserSettings.Get(group='vdigit', key="layer", subkey='value')
-            cat   = self.SetCategory()
-        
-        if line:
-            type = wxvdigit.GV_LINE
+            layer = UserSettings.Get(group = 'vdigit', key = "layer", subkey = 'value')
+            cat   = self.cats.get(layer, 1)
+        
+        snap, thresh = self._display.GetThreshold()
+        
+        bgmap = str(UserSettings.Get(group = 'vdigit', key = 'bgmap',
+                                     subkey = 'value', internal = True))
+        
+        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:
         else:
-            type = wxvdigit.GV_BOUNDARY
-        
-        listCoords = []
-        for c in coords:
-            for x in c:
-                listCoords.append(x)
-        
-        snap, thresh = self.__getSnapThreshold()
+            gcmd.GError(parent = self.mapwindow,
+                        message = _("Unknown feature type '%s'") % ftype)
+            return
         
         
-        bgmap = str(UserSettings.Get(group='vdigit', key="bgmap",
-                                     subkey='value', internal=True))
+        if vtype & GV_LINES and len(points) < 2:
+            gcmd.GError(parent = self.mapwindow,
+                        message = _("Not enough points for line"))
+            return
         
         
-        ret = self.digit.AddLine(type, listCoords, layer, cat,
-                                 bgmap, snap, thresh)
-
         self.toolbar.EnableUndo()
         self.toolbar.EnableUndo()
         
         
-        return ret
+        return self._addFeature(vtype, points, layer, cat,
+                                bgmap, snap, thresh)
     
     
     def DeleteSelectedLines(self):
     def DeleteSelectedLines(self):
         """!Delete selected features
         """!Delete selected features
@@ -567,23 +588,6 @@ class IVDigit:
         
         
         return ret
         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):
     def GetDisplay(self):
         """!Get display driver instance"""
         """!Get display driver instance"""
         return self._display
         return self._display
@@ -594,13 +598,12 @@ class IVDigit:
         @param map name of vector map to be set up
         @param map name of vector map to be set up
         """
         """
         Debug.msg (3, "AbstractDigit.SetMapName map=%s" % name)
         Debug.msg (3, "AbstractDigit.SetMapName map=%s" % name)
-        self.map = name
         
         
         name, mapset = name.split('@')
         name, mapset = name.split('@')
         try:
         try:
-            ret = self._display.OpenMap(str(name), str(mapset), True)
+            self.mapInfo = self._display.OpenMap(str(name), str(mapset), True)
         except SystemExit:
         except SystemExit:
-                ret = -1
+            pass
         
         
         # except StandardError, e:
         # except StandardError, e:
         #     raise gcmd.GException(_("Unable to initialize display driver of vector "
         #     raise gcmd.GException(_("Unable to initialize display driver of vector "
@@ -625,7 +628,7 @@ class IVDigit:
     def CloseMap(self):
     def CloseMap(self):
         """!Close currently open vector map
         """!Close currently open vector map
         """
         """
-        if not self.map:
+        if not self.mapInfo:
             return
             return
         
         
         self._display.CloseMap()
         self._display.CloseMap()
@@ -637,30 +640,29 @@ class IVDigit:
         @return -1 on error
         @return -1 on error
         """
         """
         self.cats.clear()
         self.cats.clear()
-        mapInfo = self._display.mapInfo
-        if not mapInfo:
+        if not self.mapInfo:
             return -1
             return -1
         
         
-        ndblinks = Vect_get_num_dblinks(byref(mapInfo))
+        ndblinks = Vect_get_num_dblinks(self.mapInfo)
         for i in range(ndblinks):
         for i in range(ndblinks):
-            fi = Vect_get_dblink(byref(mapInfo), i).contents
+            fi = Vect_get_dblink(self.mapInfo, i).contents
             if fi:
             if fi:
                 self.cats[fi.number] = None
                 self.cats[fi.number] = None
         
         
         # find max category
         # 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)
         Debug.msg(2, "wxDigit.InitCats(): nfields=%d", nfields)
         
         
         for i in range(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:
             if field <= 0:
                 continue
                 continue
             for j in range(ncats):
             for j in range(ncats):
                 cat = c_int()
                 cat = c_int()
                 type = c_int()
                 type = c_int()
                 id = 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))
                                            byref(cat), byref(type), byref(id))
                 if self.cats.has_key(field):
                 if self.cats.has_key(field):
                     if cat > self.cats[field]:
                     if cat > self.cats[field]:
@@ -675,8 +677,149 @@ class IVDigit:
                 self.cats[field] = 0 # first category 1
                 self.cats[field] = 0 # first category 1
 	    Debug.msg(3, "wxDigit.InitCats(): layer=%d, cat=%d", field, self.cats[field])
 	    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):
     def RewriteLine(self):
         pass
         pass
@@ -734,20 +877,6 @@ class IVDigit:
 
 
     def CopyCats(self):
     def CopyCats(self):
         pass
         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):
     def GetLineCats(self):
         pass
         pass
@@ -775,24 +904,23 @@ class IVDigit:
         self._settings['addCentroid'] = addCentroid
         self._settings['addCentroid'] = addCentroid
         self._settings['catBoundary'] = None # !catBoundary # do not attach
         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'):
         if not UserSettings.Get(group = 'vdigit', key = 'categoryMode', subkey = 'selection'):
             self.SetCategoryNextToUse()
             self.SetCategoryNextToUse()
         
         
         return UserSettings.Get(group = 'vdigit', key = 'category', subkey = 'value')
         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)
         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)
+        

+ 42 - 28
gui/wxpython/gui_modules/wxvdriver.py

@@ -3,8 +3,8 @@
 
 
 @brief wxGUI vector digitizer (display driver)
 @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:
 List of classes:
  - DisplayDriver
  - DisplayDriver
@@ -35,9 +35,11 @@ class DisplayDriver:
         @param device    wx.PseudoDC device where to draw vector objects
         @param device    wx.PseudoDC device where to draw vector objects
         @param deviceTmp wx.PseudoDC device where to draw temporary vector objects
         @param deviceTmp wx.PseudoDC device where to draw temporary vector objects
         """
         """
-        G_gisinit("")             # initialize GRASS libs
+        G_gisinit('')             # initialize GRASS libs
+        
+        self.mapInfoObj = None    # open vector map (Map_Info structure)
+        self.mapInfo    = None    # pointer to self.mapInfoObj
         
         
-        self.mapInfo = None       # open vector map (Map_Info structure)
         self.dc      = device     # PseudoDC devices
         self.dc      = device     # PseudoDC devices
         self.dcTmp   = deviceTmp
         self.dcTmp   = deviceTmp
         self.mapObj  = mapObj
         self.mapObj  = mapObj
@@ -111,6 +113,8 @@ class DisplayDriver:
         self.drawSegments = False
         self.drawSegments = False
 
 
         self.UpdateSettings()
         self.UpdateSettings()
+
+        Vect_set_fatal_error(GV_FATAL_PRINT)
         
         
     # def __del__(self):
     # def __del__(self):
     #     """!Close currently open vector map"""
     #     """!Close currently open vector map"""
@@ -329,7 +333,7 @@ class DisplayDriver:
         if not self.mapInfo or not self.dc or not self.dcTmp:
         if not self.mapInfo or not self.dc or not self.dcTmp:
             return -1
             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.region['center_easting'], self.region['center_northing'],
                                  self.mapObj.width, self.mapObj.height,
                                  self.mapObj.width, self.mapObj.height,
                                  max(self.region['nsres'], self.region['ewres'])).contents
                                  max(self.region['nsres'], self.region['ewres'])).contents
@@ -374,7 +378,7 @@ class DisplayDriver:
             dc_ids.append(1)
             dc_ids.append(1)
         else:
         else:
             # only first selected feature
             # 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]);
             # self.selected.ids->value[0]);
             npoints = self.points.n_points
             npoints = self.points.n_points
             # node - segment - vertex - segment - node
             # node - segment - vertex - segment - node
@@ -431,15 +435,15 @@ class DisplayDriver:
         """
         """
         ret = 0
         ret = 0
         if self.mapInfo:
         if self.mapInfo:
-            if self.mapInfo.mode == GV_MODE_RW:
+            if self.mapInfoObj.mode == GV_MODE_RW:
                 # rebuild topology
                 # 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
             # 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
         return ret
     
     
@@ -449,13 +453,14 @@ class DisplayDriver:
         @param name name of vector map to be open
         @param name name of vector map to be open
         @param mapset name of mapset where the vector map lives
         @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",
         Debug.msg("DisplayDriver.OpenMap(): name=%s mapset=%s updated=%d",
                   name, mapset, update)
                   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)
         # define open level (level 2: topology)
         Vect_set_open_level(2)
         Vect_set_open_level(2)
@@ -465,15 +470,15 @@ class DisplayDriver:
         
         
         # open existing map
         # open existing map
         if update:
         if update:
-            ret = Vect_open_update(byref(self.mapInfo), name, mapset)
+            ret = Vect_open_update(self.mapInfo, name, mapset)
         else:
         else:
-            ret = Vect_open_old(byref(self.mapInfo), name, mapset)
-        
+            ret = Vect_open_old(self.mapInfo, name, mapset)
+
         if ret == -1: # error
         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):
     def ReloadMap(self):
         pass
         pass
@@ -490,7 +495,7 @@ class DisplayDriver:
             return None
             return None
         
         
         bbox = bound_box()
         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, \
         return bbox.W, bbox.S, bbox.B, \
             bbox.E, bbox.N, bbox.T
             bbox.E, bbox.N, bbox.T
@@ -541,14 +546,17 @@ class DisplayDriver:
         self.region = self.mapObj.GetCurrentRegion()
         self.region = self.mapObj.GetCurrentRegion()
         
         
     def GetThreshold(self, type = 'snapping', value = None, units = None):
     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 value threshold to be set up
         @param units units (map, screen)
         @param units units (map, screen)
+
+        @return (snap mode id, threshold value)
         """
         """
         if value is None:
         if value is None:
             value = UserSettings.Get(group = 'vdigit', key = type, subkey =' value')
             value = UserSettings.Get(group = 'vdigit', key = type, subkey =' value')
-
+        
         if units is None:
         if units is None:
             units = UserSettings.Get(group = 'vdigit', key = type, subkey = 'units')
             units = UserSettings.Get(group = 'vdigit', key = type, subkey = 'units')
         
         
@@ -562,6 +570,12 @@ class DisplayDriver:
         else:
         else:
             threshold = value
             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)