[GRASS-SVN] r44907 - in grass/trunk: gui/wxpython/gui_modules lib/vector/vedit

svn_grass at osgeo.org svn_grass at osgeo.org
Sat Jan 8 12:51:31 EST 2011


Author: martinl
Date: 2011-01-08 09:51:31 -0800 (Sat, 08 Jan 2011)
New Revision: 44907

Modified:
   grass/trunk/gui/wxpython/gui_modules/dbm_dialogs.py
   grass/trunk/gui/wxpython/gui_modules/mapdisp.py
   grass/trunk/gui/wxpython/gui_modules/mapdisp_window.py
   grass/trunk/gui/wxpython/gui_modules/vdigit.py
   grass/trunk/gui/wxpython/gui_modules/wxvdigit.py
   grass/trunk/gui/wxpython/gui_modules/wxvdriver.py
   grass/trunk/lib/vector/vedit/render.c
Log:
wxGUI/vdigit pythonization: add/remove vertex, display category works


Modified: grass/trunk/gui/wxpython/gui_modules/dbm_dialogs.py
===================================================================
--- grass/trunk/gui/wxpython/gui_modules/dbm_dialogs.py	2011-01-08 09:44:31 UTC (rev 44906)
+++ grass/trunk/gui/wxpython/gui_modules/dbm_dialogs.py	2011-01-08 17:51:31 UTC (rev 44907)
@@ -271,8 +271,8 @@
         """!Cancel button pressed"""
         self.parent.parent.dialogs['attributes'] = None
         if self.parent.parent.digit:
-            self.parent.parent.digit.driver.SetSelected([])
-            self.parent.UpdateMap(render=False)
+            self.parent.parent.digit.GetDisplay().SetSelected([])
+            self.parent.UpdateMap(render = False)
         else:
             self.parent.parent.OnRender(None)
 

Modified: grass/trunk/gui/wxpython/gui_modules/mapdisp.py
===================================================================
--- grass/trunk/gui/wxpython/gui_modules/mapdisp.py	2011-01-08 09:44:31 UTC (rev 44906)
+++ grass/trunk/gui/wxpython/gui_modules/mapdisp.py	2011-01-08 17:51:31 UTC (rev 44907)
@@ -542,7 +542,7 @@
         
         # deselect features in vdigit
         if self.toolbars['vdigit'] and self.digit:
-            self.digit.GetDisplay().SetSelected(None)
+            self.digit.GetDisplay().SetSelected([])
             self.MapWindow.UpdateMap(render = True, renderVector = True)
         else:
             self.MapWindow.UpdateMap(render = True)

Modified: grass/trunk/gui/wxpython/gui_modules/mapdisp_window.py
===================================================================
--- grass/trunk/gui/wxpython/gui_modules/mapdisp_window.py	2011-01-08 09:44:31 UTC (rev 44906)
+++ grass/trunk/gui/wxpython/gui_modules/mapdisp_window.py	2011-01-08 17:51:31 UTC (rev 44907)
@@ -503,8 +503,7 @@
                 tool(event)
         
     def OnPaint(self, event):
-        """!
-        Draw PseudoDC's to buffered paint DC
+        """!Draw PseudoDC's to buffered paint DC
 
         self.pdc for background and decorations
         self.pdcVector for vector map which is edited
@@ -714,7 +713,7 @@
         #
         # initialize process bar (only on 'render')
         #
-        if render is True or renderVector is True:
+        if render or renderVector:
             self.parent.statusbarWin['progress'].Show()
             if self.parent.statusbarWin['progress'].GetRange() > 0:
                 self.parent.statusbarWin['progress'].SetValue(1)
@@ -722,9 +721,8 @@
         #
         # render background image if needed
         #
-        
         # update layer dictionary if there has been a change in layers
-        if self.tree and self.tree.reorder == True:
+        if self.tree and self.tree.reorder:
             self.tree.ReorderLayers()
         
         # reset flag for auto-rendering
@@ -749,7 +747,7 @@
             self.mapfile = None
         
         self.img = self.GetImage() # id=99
-            
+        
         #
         # clear pseudoDcs
         #
@@ -769,7 +767,7 @@
                 id = self.imagedict[self.img]['id']
             except:
                 return False
-
+            
             self.Draw(self.pdc, self.img, drawid = id)
         
         #
@@ -784,16 +782,18 @@
             # self.parent.digit.GetDisplay().GetThreshold()
             # draw map
             if self.pdcVector:
-                self.pdcVector.Clear()
+                # self.pdcVector.Clear()
                 self.pdcVector.RemoveAll()
+            
             try:
                 item = self.tree.FindItemByData('maplayer', digitToolbar.GetLayer())
             except TypeError:
                 item = None
             
             if item and self.tree.IsItemChecked(item):
+                self.redrawAll = True
                 self.parent.digit.GetDisplay().DrawMap()
-
+            
             # translate tmp objects (pointer position)
             if digitToolbar.GetAction() == 'moveLine':
                 if  hasattr(self, "vdigitMove") and \
@@ -814,7 +814,7 @@
                 id = self.imagedict[img]['id']
                 self.Draw(self.pdc, img = img, drawid = id,
                           pdctype = self.overlays[id]['pdcType'], coords = self.overlays[id]['coords'])
-
+        
         for id in self.textdict.keys():
             self.Draw(self.pdc, img = self.textdict[id], drawid = id,
                       pdctype = 'text', coords = [10, 10, 10, 10])
@@ -1425,8 +1425,7 @@
             self.pdcTmp.SetPen(self.polypen)
 
     def OnLeftDownVDigitDisplayCA(self, event):
-        """!
-        Left mouse button down - vector digitizer display categories
+        """!Left mouse button down - vector digitizer display categories
         or attributes action
         """
         digitToolbar = self.parent.toolbars['vdigit']
@@ -1444,10 +1443,9 @@
         
         # select feature by point
         cats = {}
-        if digitClass.GetDisplay().SelectLineByPoint(coords,
-                                               digitClass.GetSelectType()) is None:
+        if digitClass.GetDisplay().SelectLineByPoint(coords) is None:
             return
-
+        
         if UserSettings.Get(group = 'vdigit', key = 'checkForDupl',
                             subkey = 'enabled'):
             lines = digitClass.GetDisplay().GetSelected()
@@ -1470,7 +1468,7 @@
             else:
                 # upgrade dialog
                 self.parent.dialogs['attributes'].UpdateDialog(cats = cats)
-
+           
             if self.parent.dialogs['attributes']:
                 if len(cats.keys()) > 0:
                     # highlight feature & re-draw map
@@ -1493,7 +1491,7 @@
             else:
                 # update currently open dialog
                 self.parent.dialogs['category'].UpdateDialog(cats = cats)
-                            
+                
             if self.parent.dialogs['category']:
                 if len(cats.keys()) > 0:
                     # highlight feature & re-draw map
@@ -1502,8 +1500,8 @@
                 else:
                     if self.parent.dialogs['category'].IsShown():
                         self.parent.dialogs['category'].Hide()
-                
-        self.UpdateMap(render = False)
+        
+        self.UpdateMap(render = False, renderVector = True)
  
     def OnLeftDownVDigitCopyCA(self, event):
         """!
@@ -1551,8 +1549,7 @@
             self.DrawLines(self.pdcTmp, polycoords = (begin, end))
         
     def OnLeftDown(self, event):
-        """!
-        Left mouse button pressed
+        """!Left mouse button pressed
         """
         Debug.msg (5, "BufferedWindow.OnLeftDown(): use=%s" % \
                    self.mouse["use"])
@@ -1646,8 +1643,7 @@
         event.Skip()
 
     def OnLeftUpVDigitVarious(self, event):
-        """!
-        Left mouse button up - vector digitizer various actions
+        """!Left mouse button up - vector digitizer various actions
         """
         digitToolbar = self.parent.toolbars['vdigit']
         digitClass   = self.parent.digit
@@ -1660,7 +1656,7 @@
         if digitToolbar.GetAction() in ("moveVertex",
                                         "editLine"):
             if len(digitClass.GetDisplay().GetSelected()) == 0:
-                nselected = digitClass.GetDisplay().SelectLineByPoint(pos1, type = VDigit_Lines_Type)
+                nselected = digitClass.GetDisplay().SelectLineByPoint(pos1)
                 
                 if digitToolbar.GetAction() == "editLine":
                     try:
@@ -1694,18 +1690,16 @@
                                           "copyAttrs"):
             if not hasattr(self, "copyCatsIds"):
                 # 'from' -> select by point
-                nselected = digitClass.GetDisplay().SelectLineByPoint(pos1, digitClass.GetSelectType())
+                nselected = digitClass.GetDisplay().SelectLineByPoint(pos1)
                 if nselected:
                     self.copyCatsList = digitClass.GetDisplay().GetSelected()
             else:
                 # -> 'to' -> select by bbox
                 digitClass.GetDisplay().SetSelected([])
                 # return number of selected features (by box/point)
-                nselected = digitClass.GetDisplay().SelectLinesByBox(pos1, pos2,
-                                                               digitClass.GetSelectType())
+                nselected = digitClass.GetDisplay().SelectLinesByBox((pos1, pos2))
                 if nselected == 0:
-                    if digitClass.GetDisplay().SelectLineByPoint(pos1,
-                                                           digitClass.GetSelectType()) is not None:
+                    if digitClass.GetDisplay().SelectLineByPoint(pos1) is not None:
                         nselected = 1
                         
                 if nselected > 0:
@@ -1777,8 +1771,7 @@
                 self.UpdateMap(render = False, renderVector = False)
         
     def OnLeftUpVDigitModifyLine(self, event):
-        """!
-        Left mouse button up - vector digitizer split line, add/remove
+        """!Left mouse button up - vector digitizer split line, add/remove
         vertex action
         """
         digitToolbar = self.parent.toolbars['vdigit']
@@ -1786,15 +1779,13 @@
         
         pos1 = self.Pixel2Cell(self.mouse['begin'])
         
-        pointOnLine = digitClass.GetDisplay().SelectLineByPoint(pos1,
-                                                          type = VDigit_Lines_Type)
-
+        pointOnLine = digitClass.GetDisplay().SelectLineByPoint(pos1)
         if not pointOnLine:
             return
 
         if digitToolbar.GetAction() in ["splitLine", "addVertex"]:
             self.UpdateMap(render = False) # highlight object
-            self.DrawCross(pdc = self.pdcTmp, coords = self.Cell2Pixel(pointOnLine),
+            self.DrawCross(pdc = self.pdcTmp, coords = self.Cell2Pixel((pointOnLine[0], pointOnLine[1])),
                            size = 5)
         else: # removeVertex
             # get only id of vertex
@@ -1827,8 +1818,7 @@
         if UserSettings.Get(group = 'vdigit', key = 'bgmap',
                             subkey = 'value', internal = True) == '':
             # no background map -> copy from current vector map layer
-            nselected = digitClass.GetDisplay().SelectLinesByBox(pos1, pos2,
-                                                           digitClass.GetSelectType())
+            nselected = digitClass.GetDisplay().SelectLinesByBox((pos1, pos2))
 
             if nselected > 0:
                 # highlight selected features
@@ -1877,9 +1867,8 @@
         # select lines to be labeled
         pos1 = self.polycoords[0]
         pos2 = self.polycoords[1]
-        nselected = digitClass.GetDisplay().SelectLinesByBox(pos1, pos2,
-                                                       digitClass.GetSelectType())
-
+        nselected = digitClass.GetDisplay().SelectLinesByBox((pos1, pos2))
+        
         if nselected > 0:
             # highlight selected features
             self.UpdateMap(render = False)
@@ -2365,7 +2354,7 @@
         
         # set region in zoom or pan
         begin = self.mouse['begin']
-        end = self.mouse['end']
+        end   = self.mouse['end']
         
         self.Zoom(begin, end, 0) # no zoom
         

Modified: grass/trunk/gui/wxpython/gui_modules/vdigit.py
===================================================================
--- grass/trunk/gui/wxpython/gui_modules/vdigit.py	2011-01-08 09:44:31 UTC (rev 44906)
+++ grass/trunk/gui/wxpython/gui_modules/vdigit.py	2011-01-08 17:51:31 UTC (rev 44907)
@@ -69,7 +69,8 @@
         # notebook
         notebook = wx.Notebook(parent = self, id = wx.ID_ANY, style = wx.BK_DEFAULT)
         self.__CreateSymbologyPage(notebook)
-        parent.digit.SetCategory() # update category number (next to use)
+        if not UserSettings.Get(group = 'vdigit', key = 'categoryMode', subkey = 'selection'):
+            self.parent.digit.SetCategoryNextToUse()
         self.__CreateGeneralPage(notebook)
         self.__CreateAttributesPage(notebook)
         self.__CreateQueryPage(notebook)
@@ -631,12 +632,12 @@
         if value < 0:
             region = self.parent.MapWindow.Map.GetRegion()
             res = (region['nsres'] + region['ewres']) / 2.
-            threshold = self.parent.digit.driver.GetThreshold(value = res)
+            threshold = self.parent.digit.GetDisplay().GetThreshold(value = res)
         else:
             if self.snappingUnit.GetStringSelection() == "map units":
                 threshold = value
             else:
-                threshold = self.parent.digit.driver.GetThreshold(value = value)
+                threshold = self.parent.digit.GetDisplay().GetThreshold(value = value)
             
         if value == 0:
             self.snappingInfo.SetLabel(_("Snapping disabled"))
@@ -656,7 +657,7 @@
         """!Snapping units change -> update static text"""
         value = self.snappingValue.GetValue()
         units = self.snappingUnit.GetStringSelection()
-        threshold = self.parent.digit.driver.GetThreshold(value = value, units = units)
+        threshold = self.parent.digit.GetDisplay().GetThreshold(value = value, units = units)
 
         if units == "map units":
             self.snappingInfo.SetLabel(_("Snapping threshold is %(value).1f %(units)s") % 
@@ -1166,7 +1167,7 @@
         """!Cancel button pressed"""
         self.parent.parent.dialogs['category'] = None
         if self.parent.parent.digit:
-            self.parent.parent.digit.driver.SetSelected([])
+            self.parent.parent.digit.GetDisplay().SetSelected([])
             self.parent.UpdateMap(render = False)
         else:
             self.parent.parent.OnRender(None)

Modified: grass/trunk/gui/wxpython/gui_modules/wxvdigit.py
===================================================================
--- grass/trunk/gui/wxpython/gui_modules/wxvdigit.py	2011-01-08 09:44:31 UTC (rev 44906)
+++ grass/trunk/gui/wxpython/gui_modules/wxvdigit.py	2011-01-08 17:51:31 UTC (rev 44907)
@@ -48,6 +48,10 @@
                                       mapObj    = mapwindow.Map,
                                       log       = self.log)
         
+        # GRASS lib
+        self.poPoints = Vect_new_line_struct()
+        self.poCats   = Vect_new_cats_struct()
+        
         # self.SetCategory()
         
         # layer / max category
@@ -69,8 +73,11 @@
             self.InitCats()
         
     def __del__(self):
-        pass # free changesets ?
-
+        Vect_destroy_line_struct(self.poPoints)
+        self.poPoints = None
+        Vect_destroy_cats_struct(self.poCats)
+        self.poCats = None
+        
     def _setCategory(self):
         pass
     
@@ -110,17 +117,33 @@
   
         @return changeset id
         """
-        pass
+        changeset = len(self.changesets)
+        for line in self._display.selected['ids']:
+            if Vect_line_alive(self.poMapInfo, line):
+                self._addActionToChangeset(changeset, line, add = False)
+        
+        return changeset
     
-    def _addActionsAfter(self):
-        pass
+    def _addActionsAfter(self, changeset, nlines):
+        """!Register action after operation
 
-    def _addActionToChangeset(self, changeset, add, line):
+        @param changeset changeset id
+        @param nline number of lines
+        """
+        for line in self._display.selected['ids']:
+            if Vect_line_alive(self.poMapInfo, line):
+                self._removeActionFromChangeset(changeset, line, add = False)
+        
+        for line in range(nlines + 1, Vect_get_num_lines(self.poMapInfo)):
+            if Vect_line_alive(self.poMapInfo, line):
+                self._addActionToChangeset(changeset, line, add = True)
+        
+    def _addActionToChangeset(self, changeset, line, add):
         """!Add action to changeset
         
         @param changeset id of changeset
+        @param line feature id
         @param add True to add, otherwise delete
-        @param line feature id
         """
         if not self.poMapInfo:
             return 
@@ -134,7 +157,9 @@
             self.changesets[changeset] = list()
             self.changesetCurrent = changeset
         
-        self.changesets[changeset].append((type, line, offset))
+        self.changesets[changeset].append({ 'type'   : type,
+                                            'line'   : line,
+                                            'offset' : offset })
         
         Debug.msg(3, "IVDigit._addActionToChangeset(): changeset=%d, type=%d, line=%d, offset=%d",
                   changeset, type, line, offset)
@@ -142,11 +167,25 @@
     def _applyChangeset(self):
         pass
 
-    def _freeChangeset(self):
-        pass
-
     def _removeActionFromChangeset(self):
-        pass
+        """!Remove action from changeset
+        
+        @param changeset changeset id
+        @param line line id
+        @param add True for add, False for delete
+        
+        @return number of actions in changeset
+        @return -1 on error
+        """
+        if changeset not in self.changesets.keys():
+            return -1
+        
+        alist = self.changesets[changeset] 
+        for action in alist:
+            if action['type'] == type and action['line'] == line:
+                alist.remove(action)
+        
+        return len(alist)
 
     def _listToIList(self, plist):
         """!Generate from list struct_ilist
@@ -264,7 +303,7 @@
                 db_init_string(poStmt)
                 db_set_string(poStmt, "DELETE FROM %s WHERE" % Fi.table)
                 n_cats = 0;
-                catsDel = CatsDel.contents
+                catsDel = poCatsDel.contents
                 for c in range(catsDel.n_cats):
                     if catsDel.field[c] == Fi.number:
                         if n_cats > 0:
@@ -345,9 +384,8 @@
         @return 0 nothing changed
         @return -1 on failure
         """
-        added = self.digit.ModifyLineVertex(1, coords[0], coords[1], 0.0, # TODO 3D
-                                            self.driver.GetThreshold(type='selectThresh'))
-
+        added = self._ModifyLineVertex(coords, add = True)
+        
         if added > 0:
             self.toolbar.EnableUndo()
 
@@ -362,27 +400,45 @@
         @return 0 nothing changed
         @return -1 on failure
         """
-        deleted = self.digit.ModifyLineVertex(0, coords[0], coords[1], 0.0, # TODO 3D
-                                              self.driver.GetThreshold(type='selectThresh'))
-
+        deleted = self._ModifyLineVertex(coords, add = False)
+        
         if deleted > 0:
             self.toolbar.EnableUndo()
 
         return deleted
 
 
-    def SplitLine(self, coords):
-        """!Split selected line/boundary on position 'coords'
+    def SplitLine(self, point):
+        """!Split/break selected line/boundary on given position
 
-        @param coords coordinates to split line
-
+        @param point point where to split line
+        
         @return 1 line modified
         @return 0 nothing changed
         @return -1 error
         """
-        ret = self.digit.SplitLine(coords[0], coords[1], 0.0, # TODO 3D
-                                   self.driver.GetThreshold('selectThresh'))
+        thresh = self._display.GetThreshold('selectThresh')
+        if not self.poMapInfo:
+            return -1
+        
+        poList  = self._listToIList(self._display.selected['ids'])
+        
+        Vect_append_point(self.poPoints, point[0], point[1], 0.0)
+        
+        nlines = Vect_get_num_lines(self.poMapInfo)
+        
+        changeset = self._addActionsBefore()
+        
+        ret = Vedit_split_lines(self.poMapInfo, poList,
+                                self.poPoints, thresh, poList)
+        
+        if ret > 0:
+            self._addActionsAfter(changeset, nlines)
+        else:
+            self.changesets.remove(changeset);
 
+        Vect_destroy_list(poList)
+        
         if ret > 0:
             self.toolbar.EnableUndo()
 
@@ -806,23 +862,20 @@
                             message = _("Unable to open background vector map <%s>") % bgmap)
                 return -1
         
-        poPoints = Vect_new_line_struct()
-        poCats   = Vect_new_cats_struct() 
-        
         # set category
         if layer > 0 and \
                 (type != GV_BOUNDARY or \
                      (type == GV_BOUNDARY and self.settings['catBoundary'])):
-            Vect_cat_set(poCats, layer, cat)
+            Vect_cat_set(self.poCats, layer, cat)
             self.cats[layer] = max(cat, self.cats.get(layer, 0))
         
         # append points
         for c in coords:
-            Vect_append_point(poPoints, c[0], c[1], 0.0)
+            Vect_append_point(self.poPoints, c[0], c[1], 0.0)
         
         if type & GV_BOUNDARY:
             # close boundary
-            points = poPoints.contents
+            points = self.poPoints.contents
             last = points.n_points - 1
             if Vect_points_distance(points.x[0], points.x[0], points.z[0],
                                     points.x[last], points.x[last], points.z[last],
@@ -836,13 +889,13 @@
             modeSnap = not (snap == SNAP)
             if bgMapInfo:
                 Vedit_snap_line(self.poMapInfo, byref(bgMapInfo), 1,
-                                -1, poPoints, threshold, modeSnap)
+                                -1, self.poPoints, threshold, modeSnap)
             else:
                 # Vedit_snap_line(self.poMapInfo, None, 0,
                 #                -1, poPoints, threshold, modeSnap)
                 pass
         
-        newline = Vect_write_line(self.poMapInfo, type, poPoints, poCats)
+        newline = Vect_write_line(self.poMapInfo, type, self.poPoints, self.poCats)
         if newline < 0:
             self._errorWriteLine()
             return -1
@@ -861,7 +914,7 @@
             
             # check if area exists and has no centroid inside
             if layer > 0 and (left > 0 or right > 0):
-                Vect_cat_set(poCats, layer, cat)
+                Vect_cat_set(self.poCats, layer, cat)
                 self.cats[layer] = max(cat, self.cats.get(layer, 0))
             
             x = c_double()
@@ -873,7 +926,7 @@
                     Vect_reset_line(bpoints)
                     Vect_append_point(bpoints, x.value, y.value, 0.0)
                     if Vect_write_line(self.poMapInfo, GV_CENTROID,
-                                       bpoints, poCats) < 0:
+                                       bpoints, self.poCats) < 0:
                         self._errorWriteLine()
                         return -1
             
@@ -884,21 +937,18 @@
                     Vect_reset_line(bpoints)
                     Vect_append_point(bpoints, x.value, y.value, 0.0)
                     if Vect_write_line(byref(self.poMapInfo), GV_CENTROID,
-                                       bpoints, poCats) < 0:
+                                       bpoints, self.poCats) < 0:
                         self._errorWriteLine()
                         return -1
             Vect_destroy_line_struct(bpoints)
         
         # register changeset
-        self._addActionToChangeset(len(self.changesets), True, newline)
+        self._addActionToChangeset(len(self.changesets), newline, add = True)
         
         # break at intersection
         if self.settings['breakLines']:
-            self._breakLineAtIntersection(newline, poPoints, changeset)
+            self._breakLineAtIntersection(newline, self.poPoints, changeset)
         
-        Vect_destroy_line_struct(poPoints)
-        Vect_destroy_cats_struct(poCats)
-        
         # close background map if opened
         if bgMapInfo:
             Vect_close(byref(bgMapInfo))
@@ -913,9 +963,6 @@
     def RewriteLine(self):
         pass
     
-    def SplitLine(self):
-        pass
-
     def DeleteLines(self):
         pass
 
@@ -949,9 +996,53 @@
     def MoveVertex(self):
         pass
 
-    def ModifyLineVertex(self):
-        pass
-
+    def _ModifyLineVertex(self, coords, add = True):
+        """!Add or remove vertex
+        
+        Shape of line/boundary is not changed when adding new vertex.
+        
+        @param coords coordinates of point
+        @param add True to add, False to remove
+        
+        @return id id of the new feature
+        @return 0 nothing changed
+        @return -1 error
+        """
+        if not self.poMapInfo:
+            return -1
+        
+        selected = self._display.selected
+        if len(selected['ids']) != 1:
+            return 0
+        
+        poList  = self._listToIList(selected['ids'])
+        Vect_append_point(self.poPoints, coords[0], coords[1], 0.0)
+        
+        nlines = Vect_get_num_lines(self.poMapInfo)
+        thresh = self._display.GetThreshold(type = 'selectThresh')
+        
+        changeset = self._addActionsBefore()
+        
+        if add:
+            ret = Vedit_add_vertex(self.poMapInfo, poList,
+                                   self.poPoints, thresh)
+        else:
+            ret = Vedit_remove_vertex(self.poMapInfo, poList,
+                                      self.poPoints, thresh)
+        
+        if ret > 0:
+            self._addActionsAfter(changeset, nlines)
+        else:
+            self.changesets.remove(changeset)
+        
+        if not add and ret > 0 and self.settings['breakLines']:
+            self._breakLineAtIntersection(Vect_get_num_lines(self.poMapInfo),
+                                          None, changeset)
+        
+        Vect_destroy_list(poList)
+        
+        return nlines + 1 # feature is write at the end of the file
+    
     def SelectLinesByQuery(self):
         pass
 
@@ -967,14 +1058,51 @@
     def CopyCats(self):
         pass
     
-    def GetLineCats(self):
-        pass
+    def GetLineCats(self, line):
+        """!Get list of layer/category(ies) for selected feature.
 
+        @param line feature id (-1 for first selected feature)
+
+        @return list of layer/cats
+        """
+        ret = dict()
+        if not self.poMapInfo:
+            return ret
+        
+        if line == -1 and len(self._display.selected['ids']) < 1:
+            return ret
+        
+        if line == -1:
+            line = self._display.selected['ids'][0]
+            
+        if not Vect_line_alive(self.poMapInfo, line):
+            self._errorDeadLine(line)
+            return ret
+        
+        if Vect_read_line(self.poMapInfo, None, self.poCats, line) < 0:
+            self._errorReadLineMsg(line)
+            return ret
+        
+        cats = self.poCats.contents
+        for i in range(cats.n_cats):
+            field = cats.field[i]
+            if field not in ret:
+                ret[field] = list()
+            ret[field].append(cats.cat[i])
+        
+        return ret
+
     def SetLineCats(self):
         pass
     
     def GetLayers(self):
-        pass
+        """!Get list of layers
+        
+        Requires self.InitCats() to be called.
+
+        @return list of layers
+        """
+        return self.cats.keys()
     
     def Undo(self):
         pass
@@ -1000,7 +1128,7 @@
         
         return UserSettings.Get(group = 'vdigit', key = 'category', subkey = 'value')
 
-    def _setCategoryNextToUse(self):
+    def SetCategoryNextToUse(self):
         """!Find maximum category number for the given layer and
         update the settings
         """

Modified: grass/trunk/gui/wxpython/gui_modules/wxvdriver.py
===================================================================
--- grass/trunk/gui/wxpython/gui_modules/wxvdriver.py	2011-01-08 09:44:31 UTC (rev 44906)
+++ grass/trunk/gui/wxpython/gui_modules/wxvdriver.py	2011-01-08 17:51:31 UTC (rev 44907)
@@ -155,7 +155,7 @@
         @return -1 on failure
         """
         if not pdc or not point:
-            return -1;
+            return -1
         
         pdc.DrawLine(point.x - size, point.y, point.x + size, point.y)
         pdc.DrawLine(point.x, point.y - size, point.x, point.y + size)
@@ -175,53 +175,64 @@
         if not self.dc or not self.dcTmp:
             return -1
         
-        dcId = 0
-        pdc = self.dc
-        # draw object to the device
-        pdc.SetId(dcId) # 0 | 1 (selected)
-        
         Debug.msg(3, "_drawObject(): type=%d npoints=%d", robj.type, robj.npoints)
-        points = list()
+        brush = None
         if self._isSelected(robj.fid):
-            pdc.SetPen(wx.Pen(self.settings['highlight'], self.settings['lineWidth'], wx.SOLID))
+            pdc = self.dcTmp
+            if self.settings['highlightDupl']['enabled'] and self._isDuplicated(robj.fid):
+                pen = wx.Pen(self.settings['highlightDupl'], self.settings['lineWidth'], wx.SOLID)
+            else:            
+                pen = wx.Pen(self.settings['highlight'], self.settings['lineWidth'], wx.SOLID)
+            
+            dcId = 1
+            self.topology['highlight'] += 1
         else:
-            self._setPen(robj.type, pdc)
+            pdc = self.dc
+            pen, brush = self._definePen(robj.type)
+            dcId = 0
         
-        for i in range(robj.npoints):
-            p = robj.point[i]
-
-            if robj.type & (TYPE_POINT | TYPE_CENTROIDIN | TYPE_CENTROIDOUT | TYPE_CENTROIDDUP |
-                            TYPE_NODEONE | TYPE_NODETWO | TYPE_VERTEX): # -> point
+        pdc.SetPen(pen)        
+        if brush:
+            pdc.SetBrush(brush)
+        
+        if robj.type & (TYPE_POINT | TYPE_CENTROIDIN | TYPE_CENTROIDOUT | TYPE_CENTROIDDUP |
+                        TYPE_NODEONE | TYPE_NODETWO | TYPE_VERTEX): # -> point
+            for i in range(robj.npoints):
+                p = robj.point[i]
                 self._drawCross(pdc, p)
-            else: # -> line
-                # if dcId > 0 and self.drawSegments:
-                #     dcId = 2 # first segment
-                #     i = 0
-                #     while (i < len(self.pointsScreen) - 2):
-                #         point_beg = wx.Point(self.pointsScreen[i])
-                #         point_end = wx.Point(self.pointsScreen[i + 1])
-                        
-                #         pdc.SetId(dcId) # set unique id & set bbox for each segment
-                #         pdc.SetPen(pen)
-                #         rect = wx.Rect(point_beg, point_end)
-                #         pdc.SetIdBounds(dcId, rect)
-                #         pdc.DrawLine(point_beg.x, point_beg.y,
-                #                      point_end.x, point_end.y)
-                #         i    += 2
-                #         dcId += 2
-                # else:
-                points.append(wx.Point(p.x, p.y))
-        
-        if points:
-            if robj.type == TYPE_AREA:
-                pdc.DrawPolygon(points)
+        else:
+            if dcId > 0 and self.drawSegments:
+                dcId = 2 # first segment
+                i = 0
+                while i < robj.npoints - 1:
+                    point_beg = wx.Point(robj.point[i].x, robj.point[i].y)
+                    point_end = wx.Point(robj.point[i+1].x, robj.point[i+1].y)
+                    
+                    pdc.SetId(dcId) # set unique id & set bbox for each segment
+                    pdc.SetPen(pen)
+                    rect = wx.RectPP(point_beg, point_end)
+                    pdc.SetIdBounds(dcId, rect)
+                    pdc.DrawLine(point_beg.x, point_beg.y,
+                                 point_end.x, point_end.y)
+                    i    += 1
+                    dcId += 2
             else:
-                pdc.DrawLines(points)
+                points = list()
+                for i in range(robj.npoints):
+                    p = robj.point[i]
+                    points.append(wx.Point(p.x, p.y))
+                    
+                if robj.type == TYPE_AREA:
+                    pdc.DrawPolygon(points)
+                else:
+                    pdc.DrawLines(points)
         
-    def _setPen(self, rtype, pdc):
-        """!Set pen/brush based on rendered object)
+    def _definePen(self, rtype):
+        """!Define pen/brush based on rendered object)
         
         Updates also self.topology dict
+
+        @return pen, brush
         """
         if rtype == TYPE_POINT:
             key = 'point'
@@ -258,12 +269,15 @@
         if key in ('area', 'isle'):
             pen = wx.TRANSPARENT_PEN
             if key == 'area':
-                pdc.SetBrush(wx.Brush(self.settings[key]['color'], wx.SOLID))
+                brush = wx.Brush(self.settings[key]['color'], wx.SOLID)
             else:
-                pdc.SetBrush(wx.TRANSPARENT_BRUSH)
+                brush = wx.TRANSPARENT_BRUSH
         else:
-            pdc.SetPen(wx.Pen(self.settings[key]['color'], self.settings['lineWidth'], wx.SOLID))
+            pen = wx.Pen(self.settings[key]['color'], self.settings['lineWidth'], wx.SOLID)
+            brush = None
         
+        return pen, brush
+        
     def _getDrawFlag(self):
         """!Get draw flag from the settings
 
@@ -370,22 +384,22 @@
                                  max(self.region['nsres'], self.region['ewres'])).contents
         # ResetTopology()
         
-        self.dc.BeginDrawing()
-        self.dcTmp.BeginDrawing()
+        #self.dc.BeginDrawing()
+        #self.dcTmp.BeginDrawing()
         
         # draw objects
         for i in range(rlist.nitems):
             robj = rlist.item[i].contents
             self._drawObject(robj)
         
-        self.dc.EndDrawing()
-        self.dcTmp.EndDrawing()
+        #self.dc.EndDrawing()
+        #self.dcTmp.EndDrawing()
         
         # reset list of selected features by cat 
         # list of ids - see IsSelected()
-        ### selected.field = -1;
-        ### Vect_reset_list(selected.cats);
-
+        self.selected['field'] = -1
+        self.selected['cats'] = list()
+        
     def _getSelectType(self):
         """!Get type(s) to be selected
 
@@ -402,16 +416,15 @@
         
         return ftype
 
-    def SelectLinesByBox(self, bbox, drawSeg):
+    def SelectLinesByBox(self, bbox, drawSeg = False):
         """!Select vector objects by given bounding box
-   
+        
         If line id is already in the list of selected lines, then it will
         be excluded from this list.
-
         
         @param bbox bounding box definition
         @param drawSeg True to draw segments of line
-
+        
         @return number of selected features
         @return -1 on error
         """
@@ -420,14 +433,19 @@
         
         self.drawSegments = drawSeg
         self.drawSelected = True
-    
+        
         # select by ids
         self.selected['cats'] = list()
-
+        
         poList = Vect_new_list()
         poBbox = Vect_new_line_struct()
-        for p in bbox:
-            Vect_append_point(poBbox, p[0], p[1], 0.0)
+        x1, y1 = bbox[0]
+        x2, y2 = bbox[1]
+        Vect_append_point(poBbox, x1, y1, 0.0)
+        Vect_append_point(poBbox, x2, y1, 0.0)
+        Vect_append_point(poBbox, x2, y2, 0.0)
+        Vect_append_point(poBbox, x1, y2, 0.0)
+        Vect_append_point(poBbox, x1, y1, 0.0)
         
         Vect_select_lines_by_polygon(self.poMapInfo, poBbox,
                                      0, None, # isles
@@ -519,7 +537,7 @@
         
         return (px.value, py.value, pz.value)
     
-    def GetSelected(self, grassId = False):
+    def GetSelected(self, grassId = True):
         """!Get ids of selected objects
         
         @param grassId if true return GRASS line ids, false to return PseudoDC ids
@@ -527,8 +545,7 @@
         @return list of ids of selected vector objects
         """
         if grassId:
-            # return ListToVector(selected.ids);
-            pass
+            return self.selected['ids']
         
         dc_ids = list()
         
@@ -573,9 +590,70 @@
             field = -1
             self.selected['ids'] = ids
     
-    def GetSelectedVertex(self):
-        pass
+    def GetSelectedVertex(self, pos):
+        """Get PseudoDC vertex id of selected line
 
+        Set bounding box for vertices of line.
+        
+        \param pos position
+        
+        \return id of center, left and right vertex
+        \return 0 no line found
+        \return -1 on error
+        """
+        returnId = list()
+        # only one object can be selected
+        if len(self.selected['ids']) != 1 or not self.drawSegments:
+            return returnId
+        
+        startId = 1
+        line = self.selected['ids'][0]
+        
+        ftype = Vect_read_line(self.poMapInfo, self.poPoints, self.poCats, line)
+        
+        minDist = 0.0
+        Gid = -1
+        # find the closest vertex (x, y)
+        DCid = 1
+        points = self.poPoints.contents
+        for idx in range(points.n_points):
+            dist = Vect_points_distance(pos[0], pos[1], 0.0,
+                                        points.x[idx], points.y[idx], points.z[idx], 0)
+            
+            if idx == 0:
+                minDist = dist
+                Gid     = idx
+            else:
+                if minDist > dist:
+                    minDist = dist
+                    Gid = idx
+            
+            vx, vy = self._cell2Pixel(points.x[idx], points.y[idx], points.z[idx])
+            rect = wx.Rect(vx, vy, 0, 0)
+            self.dc.SetIdBounds(DCid, rect)
+            DCid += 2
+        
+        if minDist > self.GetThreshold():
+            return returnId
+        
+        # translate id
+        DCid = Gid * 2 + 1
+        
+        # add selected vertex
+        returnId.append(DCid)
+        # left vertex
+        if DCid == startId:
+            returnId.append(-1)
+        else:
+            returnId.append(DCid - 2)
+        # right vertex
+        if DCid == (points.n_points - 1) * 2 + startId:
+            returnId.append(-1)
+        else:
+            returnId.append(DCid + 2)
+        
+        return returnId
+
     def DrawSelected(self):
         pass
     
@@ -725,7 +803,7 @@
         @return threshold value
         """
         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:
             units = UserSettings.Get(group = 'vdigit', key = type, subkey = 'units')

Modified: grass/trunk/lib/vector/vedit/render.c
===================================================================
--- grass/trunk/lib/vector/vedit/render.c	2011-01-08 09:44:31 UTC (rev 44906)
+++ grass/trunk/lib/vector/vedit/render.c	2011-01-08 17:51:31 UTC (rev 44907)
@@ -38,13 +38,13 @@
 static struct robject *draw_line_vertices();
 static void draw_line_nodes(struct Map_info *, int, int,
 			    struct robject_list *);
-static int draw_line_dir(struct robject_list *);
+static int draw_line_dir(struct robject_list *, int);
 static void list_append(struct robject_list *, struct robject *);
 static struct robject *robj_alloc(int, int);
 static void robj_points(struct robject *, const struct line_pnts *);
 static double dist_in_px(double);
 static void en_to_xy(double, double, int *, int *);
-static void draw_arrow(int, int, int, int, double, int,
+static void draw_arrow(int, int, int, int, double, int, int,
 		       struct robject_list *);
 static void draw_area(struct Map_info *, int, struct robject_list *);
 
@@ -115,6 +115,7 @@
 	    /* vertices */
 	    if (draw_flag & DRAW_VERTEX) {
 		robj = draw_line_vertices();
+		robj->fid = fid;
 		if (robj)
 		    list_append(list_obj, robj);
 	    }
@@ -124,7 +125,7 @@
 	    }
 	    /* direction */
 	    if (draw_flag & DRAW_DIRECTION) {
-		draw_line_dir(list_obj);
+	      draw_line_dir(list_obj, fid);
 	    }
 	}
     }
@@ -248,7 +249,7 @@
     struct robject *robj;
 
     Vect_get_line_nodes(Map, line, &(nodes[0]), &(nodes[1]));
-
+    
     for (i = 0; i < sizeof(nodes) / sizeof(int); i++) {
 	type = 0;
 	if (Vect_get_node_n_lines(Map, nodes[i]) == 1) {
@@ -269,6 +270,7 @@
 
 	robj = robj_alloc(type, 1);
 	en_to_xy(east, north, &x, &y);
+	robj->fid = line;
 	robj->point->x = x;
 	robj->point->y = y;
 
@@ -329,7 +331,7 @@
 /*!
    \brief Draw line dirs
  */
-int draw_line_dir(struct robject_list *list)
+int draw_line_dir(struct robject_list *list, int line)
 {
     int narrows;
     int size;			/* arrow length in pixels */
@@ -363,7 +365,7 @@
 
 	    en_to_xy(e, n, &x1, &y1);
 
-	    draw_arrow(x0, y0, x1, y1, angle, size, list);
+	    draw_arrow(x0, y0, x1, y1, angle, size, line, list);
 
 	    if (narrows > 1e2)	// low resolution, break
 		break;
@@ -385,7 +387,7 @@
 
 		    en_to_xy(e, n, &x1, &y1);
 
-		    draw_arrow(x0, y0, x1, y1, angle, size, list);
+		    draw_arrow(x0, y0, x1, y1, angle, size, line, list);
 		}
 	    }
 	}
@@ -409,14 +411,15 @@
 /*!
    \brief Draw arrow
  */
-void draw_arrow(int x0, int y0, int x1, int y1, double angle, int size,
+void draw_arrow(int x0, int y0, int x1, int y1, double angle, int size, int line,
 		struct robject_list *list)
 {
     double angle_symb;
     struct robject *robj;
 
     robj = robj_alloc(TYPE_DIRECTION, 3);
-
+    robj->fid = line;
+    
     angle_symb = angle - M_PI / 2.;
     robj->point[0].x = (int)x1 + size * cos(angle_symb);
     robj->point[0].y = (int)y1 - size * sin(angle_symb);



More information about the grass-commit mailing list