[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