[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