|
@@ -3,6 +3,7 @@ from os.path import join, exists
|
|
|
import grass.lib.gis as libgis
|
|
|
libgis.G_gisinit('')
|
|
|
import grass.lib.vector as libvect
|
|
|
+import ctypes
|
|
|
|
|
|
#
|
|
|
# import pygrass modules
|
|
@@ -576,7 +577,183 @@ class VectorTopo(Vector):
|
|
|
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
|