[GRASS-SVN] r66092 - grass/trunk/lib/python/pygrass/vector

svn_grass at osgeo.org svn_grass at osgeo.org
Thu Sep 3 14:16:31 PDT 2015


Author: huhabla
Date: 2015-09-03 14:16:30 -0700 (Thu, 03 Sep 2015)
New Revision: 66092

Modified:
   grass/trunk/lib/python/pygrass/vector/__init__.py
   grass/trunk/lib/python/pygrass/vector/find.py
   grass/trunk/lib/python/pygrass/vector/table.py
Log:
pygrass vector: Re-establishing of the generator functionality in finder classes, 
added convenient functions to convert a vector map layer into WKB representation 
and to read the whole attribute table as dictionary. Plenty of doctests implemented. 


Modified: grass/trunk/lib/python/pygrass/vector/__init__.py
===================================================================
--- grass/trunk/lib/python/pygrass/vector/__init__.py	2015-09-03 21:12:13 UTC (rev 66091)
+++ grass/trunk/lib/python/pygrass/vector/__init__.py	2015-09-03 21:16:30 UTC (rev 66092)
@@ -3,6 +3,7 @@
 import grass.lib.gis as libgis
 libgis.G_gisinit('')
 import grass.lib.vector as libvect
+import ctypes
 
 #
 # import pygrass modules
@@ -576,8 +577,184 @@
         if release:
             libvect.Vect_set_release_support(self.c_mapinfo)
         super(VectorTopo, self).close(build=build)
+        
+    @must_be_open
+    def table_to_dict(self, where=None):
+        """Return the attribute table as a dictionary with the category as keys
+        
+            The columns have the order of the self.table.columns.names() list.
+           
+            Examples
+           
+            >>> from grass.pygrass.vector import VectorTopo
+            >>> from grass.pygrass.vector.basic import Bbox
+            >>> test_vect = VectorTopo(test_vector_name)
+            >>> test_vect.open('r')
+            
+            >>> test_vect.table_to_dict()
+            {1: [1, u'point', 1.0], 2: [2, u'line', 2.0], 3: [3, u'centroid', 3.0]}
+            
+            >>> test_vect.table_to_dict(where="value > 2")
+            {3: [3, u'centroid', 3.0]}
 
+            >>> test_vect.table_to_dict(where="value > 0")
+            {1: [1, u'point', 1.0], 2: [2, u'line', 2.0], 3: [3, u'centroid', 3.0]}
+            
+            >>> test_vect.table.filters.get_sql()
+            u'SELECT cat,name,value FROM vector_doctest_map WHERE value > 0 ORDER BY cat;'
 
+        """
+        
+        if self.table is not None:
+            table_dict = {}
+            # Get the category index
+            cat_index = self.table.columns.names().index("cat")
+            # Prepare a filter
+            if where is not None:
+                self.table.filters.where(where)
+
+            self.table.filters.order_by("cat")
+
+            self.table.filters.select(",".join(self.table.columns.names()))
+            # Execute the query and fetch the result
+            cur = self.table.execute()
+            l = cur.fetchall()
+            # Generate the dictionary
+            for entry in l:
+                table_dict[entry[cat_index]] = list(entry)
+                
+            return(table_dict)
+            
+        return None
+        
+    @must_be_open
+    def features_to_wkb_list(self, bbox=None, feature_type="point", field=1):
+        """Return all features of type point, line, boundary or centroid 
+           as a list of Well Known Binary representations (WKB)
+           (id, cat, wkb) triplets located in a specific 
+           bounding box.
+           
+           :param bbox: The boundingbox to search for features, 
+                       if bbox=None the boundingbox of the whole
+                       vector map layer is used
+                        
+           :type bbox: grass.pygrass.vector.basic.Bbox
+           
+           :param feature_type: The type of feature that should be converted to
+                                the Well Known Binary (WKB) format. Supported are:
+                               'point'    -> libvect.GV_POINT     1
+                               'line'     -> libvect.GV_LINE      2
+                               'boundary' -> libvect.GV_BOUNDARY  3
+                               'centroid' -> libvect.GV_CENTROID  4
+           :type type: string
+            
+           :param field: The category field
+           :type field: integer
+            
+           :return: A list of triplets, or None if nothing was found 
+           
+           The well known binary are stored in byte arrays.
+           
+            Examples:
+           
+            >>> from grass.pygrass.vector import VectorTopo
+            >>> from grass.pygrass.vector.basic import Bbox
+            >>> test_vect = VectorTopo(test_vector_name)
+            >>> test_vect.open('r')
+
+            >>> bbox = Bbox(north=20, south=-1, east=203, west=-1)
+            >>> result = test_vect.features_to_wkb_list(bbox=bbox, 
+            ...                                         feature_type="point")
+            >>> len(result)
+            3
+            >>> for entry in result:
+            ...     f_id, cat, wkb = entry
+            ...     print(f_id, cat, len(wkb))
+            (1, 1, 21)
+            (2, 1, 21)
+            (3, 1, 21)
+
+            >>> result = test_vect.features_to_wkb_list(bbox=None, 
+            ...                                         feature_type="line")
+            >>> len(result)
+            3
+            >>> for entry in result:
+            ...     f_id, cat, wkb = entry
+            ...     print(f_id, cat, len(wkb))
+            (4, 2, 57)
+            (5, 2, 57)
+            (6, 2, 57)
+
+            >>> result = test_vect.features_to_wkb_list(bbox=bbox, 
+            ...                                         feature_type="boundary")
+            >>> len(result)
+            11
+            
+            >>> result = test_vect.features_to_wkb_list(bbox=None, 
+            ...                                         feature_type="centroid")
+            >>> len(result)
+            4
+            
+            >>> for entry in result:
+            ...     f_id, cat, wkb = entry
+            ...     print(f_id, cat, len(wkb))
+            (19, 3, 21)
+            (18, 3, 21)
+            (20, 3, 21)
+            (21, 3, 21)
+
+            >>> result = test_vect.features_to_wkb_list(bbox=bbox, 
+            ...                                         feature_type="blub")
+            Traceback (most recent call last):
+            ...
+            GrassError: Unsupported feature type <blub>, supported are <point,line,boundary,centroid>
+
+            >>> test_vect.close()
+            
+            
+        """
+        
+        supported = ['point', 'line', 'boundary', 'centroid']
+        
+        if feature_type not in supported:
+            raise GrassError("Unsupported feature type <%s>, "\
+                             "supported are <%s>"%(feature_type, 
+                                                   ",".join(supported)))
+        
+        if bbox is None:
+            bbox = self.bbox()
+        
+        bboxlist = self.find_by_bbox.geos(bbox, type=feature_type, 
+                                          bboxlist_only = True)
+        
+        if bboxlist is not None:
+            
+            l = []
+            line_p = libvect.line_pnts()
+            line_c = libvect.line_cats()
+            size = ctypes.c_size_t()
+            cat = ctypes.c_int()
+
+            for f_id in bboxlist.ids:
+                barray = libvect.Vect_read_line_to_wkb(self.c_mapinfo,
+                                                       ctypes.byref(line_p),
+                                                       ctypes.byref(line_c),
+                                                       f_id, ctypes.byref(size))
+                if not barray:
+                    raise GrassError(_("Unable to read line of feature %i"%(f_id)))
+
+                ok = libvect.Vect_cat_get(ctypes.byref(line_c), field, 
+                                          ctypes.byref(cat))
+                if ok < 1:
+                    pcat = None
+                else:
+                    pcat = cat.value
+
+                l.append((f_id, pcat, ctypes.string_at(barray, size.value)))
+
+            return l
+        return None
+
 if __name__ == "__main__":
     import doctest
     from grass.pygrass import utils

Modified: grass/trunk/lib/python/pygrass/vector/find.py
===================================================================
--- grass/trunk/lib/python/pygrass/vector/find.py	2015-09-03 21:12:13 UTC (rev 66091)
+++ grass/trunk/lib/python/pygrass/vector/find.py	2015-09-03 21:16:30 UTC (rev 66092)
@@ -412,7 +412,7 @@
 
             >>> bbox = Bbox(north=5, south=-1, east=3, west=-1)
             >>> result = test_vect.find_by_bbox.geos(bbox=bbox)
-            >>> result                   #doctest: +NORMALIZE_WHITESPACE
+            >>> [bbox for bbox in result] #doctest: +NORMALIZE_WHITESPACE
             [Boundary([Point(4.000000, 0.000000), Point(0.000000, 0.000000)]),
              Boundary([Point(0.000000, 0.000000), Point(0.000000, 4.000000)]),
              Boundary([Point(0.000000, 4.000000), Point(4.000000, 4.000000)]),
@@ -433,7 +433,7 @@
 
             >>> bbox = Bbox(north=7, south=-1, east=15, west=9)
             >>> result = test_vect.find_by_bbox.geos(bbox=bbox)
-            >>> result                   #doctest: +NORMALIZE_WHITESPACE
+            >>> [bbox for bbox in result] #doctest: +NORMALIZE_WHITESPACE
             [Line([Point(10.000000, 4.000000), Point(10.000000, 2.000000),
                    Point(10.000000, 0.000000)]),
              Point(10.000000, 6.000000),
@@ -458,8 +458,8 @@
             if bboxlist_only:
                 return found
             else:
-                return [read_line(f_id, self.c_mapinfo, self.table,
-                                  self.writeable) for f_id in found.ids]
+                return (read_line(f_id, self.c_mapinfo, self.table,
+                                  self.writeable) for f_id in found.ids)
 
     @must_be_open
     def nodes(self, bbox):
@@ -482,7 +482,7 @@
             # Find nodes in box
             >>> bbox = Bbox(north=5, south=-1, east=15, west=9)
             >>> result = test_vect.find_by_bbox.nodes(bbox=bbox)
-            >>> result
+            >>> [node for node in result]
             [Node(2), Node(1), Node(4), Node(3), Node(5), Node(6)]
 
             >>> bbox = Bbox(north=20, south=18, east=20, west=18)
@@ -494,9 +494,9 @@
         if libvect.Vect_select_nodes_by_box(self.c_mapinfo, bbox.c_bbox,
                                             found.c_ilist):
             if len(found) > 0:
-                return [Node(v_id=n_id, c_mapinfo=self.c_mapinfo,
+                return (Node(v_id=n_id, c_mapinfo=self.c_mapinfo,
                              table=self.table, writeable=self.writeable)
-                        for n_id in found]
+                        for n_id in found)
 
     @must_be_open
     def areas(self, bbox, boxlist=None, bboxlist_only=False):
@@ -526,7 +526,7 @@
             # Find areas in box
             >>> bbox = Bbox(north=5, south=-1, east=9, west=-1)
             >>> result = test_vect.find_by_bbox.areas(bbox=bbox)
-            >>> result
+            >>> [area for area in result]
             [Area(1), Area(2), Area(3), Area(4)]
 
             >>> bbox = Bbox(north=5, south=-1, east=9, west=-1)
@@ -552,9 +552,9 @@
             if bboxlist_only:
                 return boxlist
             else:
-                return [Area(v_id=a_id, c_mapinfo=self.c_mapinfo,
+                return (Area(v_id=a_id, c_mapinfo=self.c_mapinfo,
                              table=self.table, writeable=self.writeable)
-                        for a_id in boxlist.ids]
+                        for a_id in boxlist.ids)
 
     @must_be_open
     def islands(self, bbox, bboxlist_only=False):
@@ -581,7 +581,7 @@
             # Find isles in box
             >>> bbox = Bbox(north=5, south=-1, east=9, west=-1)
             >>> result = test_vect.find_by_bbox.islands(bbox=bbox)
-            >>> result
+            >>> [isle for isle in result]
             [Isle(1), Isle(2)]
 
             >>> bbox = Bbox(north=5, south=-1, east=9, west=-1)
@@ -605,9 +605,9 @@
             if bboxlist_only:
                 return found
             else:
-                return [Isle(v_id=i_id, c_mapinfo=self.c_mapinfo,
+                return (Isle(v_id=i_id, c_mapinfo=self.c_mapinfo,
                              table=self.table, writeable=self.writeable)
-                        for i_id in found.ids]
+                        for i_id in found.ids)
 
 
 class PolygonFinder(AbstractFinder):

Modified: grass/trunk/lib/python/pygrass/vector/table.py
===================================================================
--- grass/trunk/lib/python/pygrass/vector/table.py	2015-09-03 21:12:13 UTC (rev 66091)
+++ grass/trunk/lib/python/pygrass/vector/table.py	2015-09-03 21:16:30 UTC (rev 66092)
@@ -1166,6 +1166,6 @@
     """Remove the generated vector map, if exist"""
     from grass.pygrass.utils import get_mapset_vector
     from grass.script.core import run_command
-    #mset = get_mapset_vector(test_vector_name, mapset='')
-    #if mset:
-    #    run_command("g.remove", flags='f', type='vector', name=test_vector_name)
+    mset = get_mapset_vector(test_vector_name, mapset='')
+    if mset:
+        run_command("g.remove", flags='f', type='vector', name=test_vector_name)



More information about the grass-commit mailing list