Browse Source

wxGUI/vdigit pythonization: add/remove vertex, display category works

git-svn-id: https://svn.osgeo.org/grass/grass/trunk@44907 15284696-431f-4ddb-bdfa-cd5b030d7da7
Martin Landa 14 years ago
parent
commit
1ef57dec09

+ 2 - 2
gui/wxpython/gui_modules/dbm_dialogs.py

@@ -271,8 +271,8 @@ class DisplayAttributesDialog(wx.Dialog):
         """!Cancel button pressed"""
         """!Cancel button pressed"""
         self.parent.parent.dialogs['attributes'] = None
         self.parent.parent.dialogs['attributes'] = None
         if self.parent.parent.digit:
         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:
         else:
             self.parent.parent.OnRender(None)
             self.parent.parent.OnRender(None)
 
 

+ 1 - 1
gui/wxpython/gui_modules/mapdisp.py

@@ -542,7 +542,7 @@ class MapFrame(wx.Frame):
         
         
         # deselect features in vdigit
         # deselect features in vdigit
         if self.toolbars['vdigit'] and self.digit:
         if self.toolbars['vdigit'] and self.digit:
-            self.digit.GetDisplay().SetSelected(None)
+            self.digit.GetDisplay().SetSelected([])
             self.MapWindow.UpdateMap(render = True, renderVector = True)
             self.MapWindow.UpdateMap(render = True, renderVector = True)
         else:
         else:
             self.MapWindow.UpdateMap(render = True)
             self.MapWindow.UpdateMap(render = True)

+ 30 - 41
gui/wxpython/gui_modules/mapdisp_window.py

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

+ 6 - 5
gui/wxpython/gui_modules/vdigit.py

@@ -69,7 +69,8 @@ class VDigitSettingsDialog(wx.Dialog):
         # notebook
         # notebook
         notebook = wx.Notebook(parent = self, id = wx.ID_ANY, style = wx.BK_DEFAULT)
         notebook = wx.Notebook(parent = self, id = wx.ID_ANY, style = wx.BK_DEFAULT)
         self.__CreateSymbologyPage(notebook)
         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.__CreateGeneralPage(notebook)
         self.__CreateAttributesPage(notebook)
         self.__CreateAttributesPage(notebook)
         self.__CreateQueryPage(notebook)
         self.__CreateQueryPage(notebook)
@@ -631,12 +632,12 @@ class VDigitSettingsDialog(wx.Dialog):
         if value < 0:
         if value < 0:
             region = self.parent.MapWindow.Map.GetRegion()
             region = self.parent.MapWindow.Map.GetRegion()
             res = (region['nsres'] + region['ewres']) / 2.
             res = (region['nsres'] + region['ewres']) / 2.
-            threshold = self.parent.digit.driver.GetThreshold(value = res)
+            threshold = self.parent.digit.GetDisplay().GetThreshold(value = res)
         else:
         else:
             if self.snappingUnit.GetStringSelection() == "map units":
             if self.snappingUnit.GetStringSelection() == "map units":
                 threshold = value
                 threshold = value
             else:
             else:
-                threshold = self.parent.digit.driver.GetThreshold(value = value)
+                threshold = self.parent.digit.GetDisplay().GetThreshold(value = value)
             
             
         if value == 0:
         if value == 0:
             self.snappingInfo.SetLabel(_("Snapping disabled"))
             self.snappingInfo.SetLabel(_("Snapping disabled"))
@@ -656,7 +657,7 @@ class VDigitSettingsDialog(wx.Dialog):
         """!Snapping units change -> update static text"""
         """!Snapping units change -> update static text"""
         value = self.snappingValue.GetValue()
         value = self.snappingValue.GetValue()
         units = self.snappingUnit.GetStringSelection()
         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":
         if units == "map units":
             self.snappingInfo.SetLabel(_("Snapping threshold is %(value).1f %(units)s") % 
             self.snappingInfo.SetLabel(_("Snapping threshold is %(value).1f %(units)s") % 
@@ -1166,7 +1167,7 @@ class VDigitCategoryDialog(wx.Dialog, listmix.ColumnSorterMixin):
         """!Cancel button pressed"""
         """!Cancel button pressed"""
         self.parent.parent.dialogs['category'] = None
         self.parent.parent.dialogs['category'] = None
         if self.parent.parent.digit:
         if self.parent.parent.digit:
-            self.parent.parent.digit.driver.SetSelected([])
+            self.parent.parent.digit.GetDisplay().SetSelected([])
             self.parent.UpdateMap(render = False)
             self.parent.UpdateMap(render = False)
         else:
         else:
             self.parent.parent.OnRender(None)
             self.parent.parent.OnRender(None)

+ 179 - 51
gui/wxpython/gui_modules/wxvdigit.py

@@ -48,6 +48,10 @@ class IVDigit:
                                       mapObj    = mapwindow.Map,
                                       mapObj    = mapwindow.Map,
                                       log       = self.log)
                                       log       = self.log)
         
         
+        # GRASS lib
+        self.poPoints = Vect_new_line_struct()
+        self.poCats   = Vect_new_cats_struct()
+        
         # self.SetCategory()
         # self.SetCategory()
         
         
         # layer / max category
         # layer / max category
@@ -69,8 +73,11 @@ class IVDigit:
             self.InitCats()
             self.InitCats()
         
         
     def __del__(self):
     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):
     def _setCategory(self):
         pass
         pass
     
     
@@ -110,17 +117,33 @@ class IVDigit:
   
   
         @return changeset id
         @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
         """!Add action to changeset
         
         
         @param changeset id of changeset
         @param changeset id of changeset
-        @param add True to add, otherwise delete
         @param line feature id
         @param line feature id
+        @param add True to add, otherwise delete
         """
         """
         if not self.poMapInfo:
         if not self.poMapInfo:
             return 
             return 
@@ -134,7 +157,9 @@ class IVDigit:
             self.changesets[changeset] = list()
             self.changesets[changeset] = list()
             self.changesetCurrent = changeset
             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",
         Debug.msg(3, "IVDigit._addActionToChangeset(): changeset=%d, type=%d, line=%d, offset=%d",
                   changeset, type, line, offset)
                   changeset, type, line, offset)
@@ -142,11 +167,25 @@ class IVDigit:
     def _applyChangeset(self):
     def _applyChangeset(self):
         pass
         pass
 
 
-    def _freeChangeset(self):
-        pass
-
     def _removeActionFromChangeset(self):
     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):
     def _listToIList(self, plist):
         """!Generate from list struct_ilist
         """!Generate from list struct_ilist
@@ -264,7 +303,7 @@ class IVDigit:
                 db_init_string(poStmt)
                 db_init_string(poStmt)
                 db_set_string(poStmt, "DELETE FROM %s WHERE" % Fi.table)
                 db_set_string(poStmt, "DELETE FROM %s WHERE" % Fi.table)
                 n_cats = 0;
                 n_cats = 0;
-                catsDel = CatsDel.contents
+                catsDel = poCatsDel.contents
                 for c in range(catsDel.n_cats):
                 for c in range(catsDel.n_cats):
                     if catsDel.field[c] == Fi.number:
                     if catsDel.field[c] == Fi.number:
                         if n_cats > 0:
                         if n_cats > 0:
@@ -345,9 +384,8 @@ class IVDigit:
         @return 0 nothing changed
         @return 0 nothing changed
         @return -1 on failure
         @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:
         if added > 0:
             self.toolbar.EnableUndo()
             self.toolbar.EnableUndo()
 
 
@@ -362,27 +400,45 @@ class IVDigit:
         @return 0 nothing changed
         @return 0 nothing changed
         @return -1 on failure
         @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:
         if deleted > 0:
             self.toolbar.EnableUndo()
             self.toolbar.EnableUndo()
 
 
         return deleted
         return deleted
 
 
 
 
-    def SplitLine(self, coords):
-        """!Split selected line/boundary on position 'coords'
-
-        @param coords coordinates to split line
+    def SplitLine(self, point):
+        """!Split/break selected line/boundary on given position
 
 
+        @param point point where to split line
+        
         @return 1 line modified
         @return 1 line modified
         @return 0 nothing changed
         @return 0 nothing changed
         @return -1 error
         @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:
         if ret > 0:
             self.toolbar.EnableUndo()
             self.toolbar.EnableUndo()
 
 
@@ -806,23 +862,20 @@ class IVDigit:
                             message = _("Unable to open background vector map <%s>") % bgmap)
                             message = _("Unable to open background vector map <%s>") % bgmap)
                 return -1
                 return -1
         
         
-        poPoints = Vect_new_line_struct()
-        poCats   = Vect_new_cats_struct() 
-        
         # set category
         # set category
         if layer > 0 and \
         if layer > 0 and \
                 (type != GV_BOUNDARY or \
                 (type != GV_BOUNDARY or \
                      (type == GV_BOUNDARY and self.settings['catBoundary'])):
                      (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))
             self.cats[layer] = max(cat, self.cats.get(layer, 0))
         
         
         # append points
         # append points
         for c in coords:
         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:
         if type & GV_BOUNDARY:
             # close boundary
             # close boundary
-            points = poPoints.contents
+            points = self.poPoints.contents
             last = points.n_points - 1
             last = points.n_points - 1
             if Vect_points_distance(points.x[0], points.x[0], points.z[0],
             if Vect_points_distance(points.x[0], points.x[0], points.z[0],
                                     points.x[last], points.x[last], points.z[last],
                                     points.x[last], points.x[last], points.z[last],
@@ -836,13 +889,13 @@ class IVDigit:
             modeSnap = not (snap == SNAP)
             modeSnap = not (snap == SNAP)
             if bgMapInfo:
             if bgMapInfo:
                 Vedit_snap_line(self.poMapInfo, byref(bgMapInfo), 1,
                 Vedit_snap_line(self.poMapInfo, byref(bgMapInfo), 1,
-                                -1, poPoints, threshold, modeSnap)
+                                -1, self.poPoints, threshold, modeSnap)
             else:
             else:
                 # Vedit_snap_line(self.poMapInfo, None, 0,
                 # Vedit_snap_line(self.poMapInfo, None, 0,
                 #                -1, poPoints, threshold, modeSnap)
                 #                -1, poPoints, threshold, modeSnap)
                 pass
                 pass
         
         
-        newline = Vect_write_line(self.poMapInfo, type, poPoints, poCats)
+        newline = Vect_write_line(self.poMapInfo, type, self.poPoints, self.poCats)
         if newline < 0:
         if newline < 0:
             self._errorWriteLine()
             self._errorWriteLine()
             return -1
             return -1
@@ -861,7 +914,7 @@ class IVDigit:
             
             
             # check if area exists and has no centroid inside
             # check if area exists and has no centroid inside
             if layer > 0 and (left > 0 or right > 0):
             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))
                 self.cats[layer] = max(cat, self.cats.get(layer, 0))
             
             
             x = c_double()
             x = c_double()
@@ -873,7 +926,7 @@ class IVDigit:
                     Vect_reset_line(bpoints)
                     Vect_reset_line(bpoints)
                     Vect_append_point(bpoints, x.value, y.value, 0.0)
                     Vect_append_point(bpoints, x.value, y.value, 0.0)
                     if Vect_write_line(self.poMapInfo, GV_CENTROID,
                     if Vect_write_line(self.poMapInfo, GV_CENTROID,
-                                       bpoints, poCats) < 0:
+                                       bpoints, self.poCats) < 0:
                         self._errorWriteLine()
                         self._errorWriteLine()
                         return -1
                         return -1
             
             
@@ -884,20 +937,17 @@ class IVDigit:
                     Vect_reset_line(bpoints)
                     Vect_reset_line(bpoints)
                     Vect_append_point(bpoints, x.value, y.value, 0.0)
                     Vect_append_point(bpoints, x.value, y.value, 0.0)
                     if Vect_write_line(byref(self.poMapInfo), GV_CENTROID,
                     if Vect_write_line(byref(self.poMapInfo), GV_CENTROID,
-                                       bpoints, poCats) < 0:
+                                       bpoints, self.poCats) < 0:
                         self._errorWriteLine()
                         self._errorWriteLine()
                         return -1
                         return -1
             Vect_destroy_line_struct(bpoints)
             Vect_destroy_line_struct(bpoints)
         
         
         # register changeset
         # register changeset
-        self._addActionToChangeset(len(self.changesets), True, newline)
+        self._addActionToChangeset(len(self.changesets), newline, add = True)
         
         
         # break at intersection
         # break at intersection
         if self.settings['breakLines']:
         if self.settings['breakLines']:
-            self._breakLineAtIntersection(newline, poPoints, changeset)
-        
-        Vect_destroy_line_struct(poPoints)
-        Vect_destroy_cats_struct(poCats)
+            self._breakLineAtIntersection(newline, self.poPoints, changeset)
         
         
         # close background map if opened
         # close background map if opened
         if bgMapInfo:
         if bgMapInfo:
@@ -913,9 +963,6 @@ class IVDigit:
     def RewriteLine(self):
     def RewriteLine(self):
         pass
         pass
     
     
-    def SplitLine(self):
-        pass
-
     def DeleteLines(self):
     def DeleteLines(self):
         pass
         pass
 
 
@@ -949,9 +996,53 @@ class IVDigit:
     def MoveVertex(self):
     def MoveVertex(self):
         pass
         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):
     def SelectLinesByQuery(self):
         pass
         pass
 
 
@@ -967,14 +1058,51 @@ class IVDigit:
     def CopyCats(self):
     def CopyCats(self):
         pass
         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):
     def SetLineCats(self):
         pass
         pass
     
     
     def GetLayers(self):
     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):
     def Undo(self):
         pass
         pass
@@ -1000,7 +1128,7 @@ class IVDigit:
         
         
         return UserSettings.Get(group = 'vdigit', key = 'category', subkey = 'value')
         return UserSettings.Get(group = 'vdigit', key = 'category', subkey = 'value')
 
 
-    def _setCategoryNextToUse(self):
+    def SetCategoryNextToUse(self):
         """!Find maximum category number for the given layer and
         """!Find maximum category number for the given layer and
         update the settings
         update the settings
         """
         """

+ 142 - 64
gui/wxpython/gui_modules/wxvdriver.py

@@ -155,7 +155,7 @@ class DisplayDriver:
         @return -1 on failure
         @return -1 on failure
         """
         """
         if not pdc or not point:
         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 - size, point.y, point.x + size, point.y)
         pdc.DrawLine(point.x, point.y - size, point.x, point.y + size)
         pdc.DrawLine(point.x, point.y - size, point.x, point.y + size)
@@ -175,53 +175,64 @@ class DisplayDriver:
         if not self.dc or not self.dcTmp:
         if not self.dc or not self.dcTmp:
             return -1
             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)
         Debug.msg(3, "_drawObject(): type=%d npoints=%d", robj.type, robj.npoints)
-        points = list()
+        brush = None
         if self._isSelected(robj.fid):
         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:
         else:
-            self._setPen(robj.type, pdc)
-        
-        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 = self.dc
+            pen, brush = self._definePen(robj.type)
+            dcId = 0
+        
+        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)
                 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:
             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
         Updates also self.topology dict
+
+        @return pen, brush
         """
         """
         if rtype == TYPE_POINT:
         if rtype == TYPE_POINT:
             key = 'point'
             key = 'point'
@@ -258,11 +269,14 @@ class DisplayDriver:
         if key in ('area', 'isle'):
         if key in ('area', 'isle'):
             pen = wx.TRANSPARENT_PEN
             pen = wx.TRANSPARENT_PEN
             if key == 'area':
             if key == 'area':
-                pdc.SetBrush(wx.Brush(self.settings[key]['color'], wx.SOLID))
+                brush = wx.Brush(self.settings[key]['color'], wx.SOLID)
             else:
             else:
-                pdc.SetBrush(wx.TRANSPARENT_BRUSH)
+                brush = wx.TRANSPARENT_BRUSH
         else:
         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):
     def _getDrawFlag(self):
         """!Get draw flag from the settings
         """!Get draw flag from the settings
@@ -370,22 +384,22 @@ class DisplayDriver:
                                  max(self.region['nsres'], self.region['ewres'])).contents
                                  max(self.region['nsres'], self.region['ewres'])).contents
         # ResetTopology()
         # ResetTopology()
         
         
-        self.dc.BeginDrawing()
-        self.dcTmp.BeginDrawing()
+        #self.dc.BeginDrawing()
+        #self.dcTmp.BeginDrawing()
         
         
         # draw objects
         # draw objects
         for i in range(rlist.nitems):
         for i in range(rlist.nitems):
             robj = rlist.item[i].contents
             robj = rlist.item[i].contents
             self._drawObject(robj)
             self._drawObject(robj)
         
         
-        self.dc.EndDrawing()
-        self.dcTmp.EndDrawing()
+        #self.dc.EndDrawing()
+        #self.dcTmp.EndDrawing()
         
         
         # reset list of selected features by cat 
         # reset list of selected features by cat 
         # list of ids - see IsSelected()
         # list of ids - see IsSelected()
-        ### selected.field = -1;
-        ### Vect_reset_list(selected.cats);
-
+        self.selected['field'] = -1
+        self.selected['cats'] = list()
+        
     def _getSelectType(self):
     def _getSelectType(self):
         """!Get type(s) to be selected
         """!Get type(s) to be selected
 
 
@@ -402,16 +416,15 @@ class DisplayDriver:
         
         
         return ftype
         return ftype
 
 
-    def SelectLinesByBox(self, bbox, drawSeg):
+    def SelectLinesByBox(self, bbox, drawSeg = False):
         """!Select vector objects by given bounding box
         """!Select vector objects by given bounding box
-   
+        
         If line id is already in the list of selected lines, then it will
         If line id is already in the list of selected lines, then it will
         be excluded from this list.
         be excluded from this list.
-
         
         
         @param bbox bounding box definition
         @param bbox bounding box definition
         @param drawSeg True to draw segments of line
         @param drawSeg True to draw segments of line
-
+        
         @return number of selected features
         @return number of selected features
         @return -1 on error
         @return -1 on error
         """
         """
@@ -420,14 +433,19 @@ class DisplayDriver:
         
         
         self.drawSegments = drawSeg
         self.drawSegments = drawSeg
         self.drawSelected = True
         self.drawSelected = True
-    
+        
         # select by ids
         # select by ids
         self.selected['cats'] = list()
         self.selected['cats'] = list()
-
+        
         poList = Vect_new_list()
         poList = Vect_new_list()
         poBbox = Vect_new_line_struct()
         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,
         Vect_select_lines_by_polygon(self.poMapInfo, poBbox,
                                      0, None, # isles
                                      0, None, # isles
@@ -519,7 +537,7 @@ class DisplayDriver:
         
         
         return (px.value, py.value, pz.value)
         return (px.value, py.value, pz.value)
     
     
-    def GetSelected(self, grassId = False):
+    def GetSelected(self, grassId = True):
         """!Get ids of selected objects
         """!Get ids of selected objects
         
         
         @param grassId if true return GRASS line ids, false to return PseudoDC ids
         @param grassId if true return GRASS line ids, false to return PseudoDC ids
@@ -527,8 +545,7 @@ class DisplayDriver:
         @return list of ids of selected vector objects
         @return list of ids of selected vector objects
         """
         """
         if grassId:
         if grassId:
-            # return ListToVector(selected.ids);
-            pass
+            return self.selected['ids']
         
         
         dc_ids = list()
         dc_ids = list()
         
         
@@ -573,8 +590,69 @@ class DisplayDriver:
             field = -1
             field = -1
             self.selected['ids'] = ids
             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):
     def DrawSelected(self):
         pass
         pass
@@ -725,7 +803,7 @@ class DisplayDriver:
         @return threshold value
         @return 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')

+ 12 - 9
lib/vector/vedit/render.c

@@ -38,13 +38,13 @@ static struct robject *draw_line(struct Map_info *, int, int);
 static struct robject *draw_line_vertices();
 static struct robject *draw_line_vertices();
 static void draw_line_nodes(struct Map_info *, int, int,
 static void draw_line_nodes(struct Map_info *, int, int,
 			    struct robject_list *);
 			    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 void list_append(struct robject_list *, struct robject *);
 static struct robject *robj_alloc(int, int);
 static struct robject *robj_alloc(int, int);
 static void robj_points(struct robject *, const struct line_pnts *);
 static void robj_points(struct robject *, const struct line_pnts *);
 static double dist_in_px(double);
 static double dist_in_px(double);
 static void en_to_xy(double, double, int *, int *);
 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 *);
 		       struct robject_list *);
 static void draw_area(struct Map_info *, int, struct robject_list *);
 static void draw_area(struct Map_info *, int, struct robject_list *);
 
 
@@ -115,6 +115,7 @@ struct robject_list *Vedit_render_map(struct Map_info *Map,
 	    /* vertices */
 	    /* vertices */
 	    if (draw_flag & DRAW_VERTEX) {
 	    if (draw_flag & DRAW_VERTEX) {
 		robj = draw_line_vertices();
 		robj = draw_line_vertices();
+		robj->fid = fid;
 		if (robj)
 		if (robj)
 		    list_append(list_obj, robj);
 		    list_append(list_obj, robj);
 	    }
 	    }
@@ -124,7 +125,7 @@ struct robject_list *Vedit_render_map(struct Map_info *Map,
 	    }
 	    }
 	    /* direction */
 	    /* direction */
 	    if (draw_flag & DRAW_DIRECTION) {
 	    if (draw_flag & DRAW_DIRECTION) {
-		draw_line_dir(list_obj);
+	      draw_line_dir(list_obj, fid);
 	    }
 	    }
 	}
 	}
     }
     }
@@ -248,7 +249,7 @@ void draw_line_nodes(struct Map_info *Map, int line, int draw_flag,
     struct robject *robj;
     struct robject *robj;
 
 
     Vect_get_line_nodes(Map, line, &(nodes[0]), &(nodes[1]));
     Vect_get_line_nodes(Map, line, &(nodes[0]), &(nodes[1]));
-
+    
     for (i = 0; i < sizeof(nodes) / sizeof(int); i++) {
     for (i = 0; i < sizeof(nodes) / sizeof(int); i++) {
 	type = 0;
 	type = 0;
 	if (Vect_get_node_n_lines(Map, nodes[i]) == 1) {
 	if (Vect_get_node_n_lines(Map, nodes[i]) == 1) {
@@ -269,6 +270,7 @@ void draw_line_nodes(struct Map_info *Map, int line, int draw_flag,
 
 
 	robj = robj_alloc(type, 1);
 	robj = robj_alloc(type, 1);
 	en_to_xy(east, north, &x, &y);
 	en_to_xy(east, north, &x, &y);
+	robj->fid = line;
 	robj->point->x = x;
 	robj->point->x = x;
 	robj->point->y = y;
 	robj->point->y = y;
 
 
@@ -329,7 +331,7 @@ struct robject *draw_line_vertices()
 /*!
 /*!
    \brief Draw line dirs
    \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 narrows;
     int size;			/* arrow length in pixels */
     int size;			/* arrow length in pixels */
@@ -363,7 +365,7 @@ int draw_line_dir(struct robject_list *list)
 
 
 	    en_to_xy(e, n, &x1, &y1);
 	    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
 	    if (narrows > 1e2)	// low resolution, break
 		break;
 		break;
@@ -385,7 +387,7 @@ int draw_line_dir(struct robject_list *list)
 
 
 		    en_to_xy(e, n, &x1, &y1);
 		    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 @@ double dist_in_px(double dist)
 /*!
 /*!
    \brief Draw arrow
    \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)
 		struct robject_list *list)
 {
 {
     double angle_symb;
     double angle_symb;
     struct robject *robj;
     struct robject *robj;
 
 
     robj = robj_alloc(TYPE_DIRECTION, 3);
     robj = robj_alloc(TYPE_DIRECTION, 3);
-
+    robj->fid = line;
+    
     angle_symb = angle - M_PI / 2.;
     angle_symb = angle - M_PI / 2.;
     robj->point[0].x = (int)x1 + size * cos(angle_symb);
     robj->point[0].x = (int)x1 + size * cos(angle_symb);
     robj->point[0].y = (int)y1 - size * sin(angle_symb);
     robj->point[0].y = (int)y1 - size * sin(angle_symb);