GRASS GIS logo

Source code for pygrass.vector

# -*- coding: utf-8 -*-
from os.path import join, exists
import grass.lib.gis as libgis
libgis.G_gisinit('')
import grass.lib.vector as libvect

#
# import pygrass modules
#
from grass.pygrass.vector.vector_type import VTYPE
from grass.pygrass.errors import GrassError, must_be_open
from grass.pygrass.gis import Location

from grass.pygrass.vector.geometry import GEOOBJ as _GEOOBJ
from grass.pygrass.vector.geometry import read_line, read_next_line
from grass.pygrass.vector.geometry import Area as _Area
from grass.pygrass.vector.abstract import Info
from grass.pygrass.vector.basic import Bbox, Cats, Ilist


_NUMOF = {"areas": libvect.Vect_get_num_areas,
          "dblinks": libvect.Vect_get_num_dblinks,
          "faces": libvect.Vect_get_num_faces,
          "holes": libvect.Vect_get_num_holes,
          "islands": libvect.Vect_get_num_islands,
          "kernels": libvect.Vect_get_num_kernels,
          "lines": libvect.Vect_get_num_lines,
          "nodes": libvect.Vect_get_num_nodes,
          "updated_lines": libvect.Vect_get_num_updated_lines,
          "updated_nodes": libvect.Vect_get_num_updated_nodes,
          "volumes": libvect.Vect_get_num_volumes}


#=============================================
# VECTOR
#=============================================

[docs]class Vector(Info): """Vector class is the grass vector format without topology >>> from grass.pygrass.vector import Vector >>> cens = Vector('census') >>> cens.is_open() False >>> cens.mapset '' >>> cens.exist() True >>> cens.mapset 'PERMANENT' >>> cens.overwrite False """ def __init__(self, name, mapset='', *args, **kwargs): # Set map name and mapset super(Vector, self).__init__(name, mapset, *args, **kwargs) self._topo_level = 1 self._class_name = 'Vector' self.overwrite = False def __repr__(self): if self.exist(): return "%s(%r, %r)" % (self._class_name, self.name, self.mapset) else: return "%s(%r)" % (self._class_name, self.name) def __iter__(self): """:: >>> cens = Vector('census') >>> cens.open(mode='r') >>> features = [feature for feature in cens] >>> features[:3] [Boundary(v_id=None), Boundary(v_id=None), Boundary(v_id=None)] >>> cens.close() .. """ #return (self.read(f_id) for f_id in xrange(self.num_of_features())) return self @must_be_open
[docs] def next(self): """:: >>> cens = Vector('census') >>> cens.open(mode='r') >>> cens.next() Boundary(v_id=None) >>> cens.next() Boundary(v_id=None) >>> cens.close() .. """ return read_next_line(self.c_mapinfo, self.table, self.writable, is2D=not self.is_3D())
@must_be_open
[docs] def rewind(self): """Rewind vector map to cause reads to start at beginning.""" if libvect.Vect_rewind(self.c_mapinfo) == -1: raise GrassError("Vect_rewind raise an error.")
@must_be_open
[docs] def write(self, geo_obj, attrs=None, set_cats=True): """Write geometry features and attributes. :param geo_obj: a geometry grass object define in grass.pygrass.vector.geometry :type geo_obj: geometry GRASS object :param attrs: a list with the values that will be insert in the attribute table. :type attrs: list :param set_cats: if True, the category of the geometry feature is set using the default layer of the vector map and a progressive category value (default), otherwise the c_cats attribute of the geometry object will be used. :type set_cats: bool Open a new vector map :: >>> new = VectorTopo('newvect') >>> new.exist() False define the new columns of the attribute table :: >>> cols = [(u'cat', 'INTEGER PRIMARY KEY'), ... (u'name', 'TEXT')] open the vector map in write mode >>> new.open('w', tab_name='newvect', tab_cols=cols) import a geometry feature :: >>> from grass.pygrass.vector.geometry import Point create two points :: >>> point0 = Point(636981.336043, 256517.602235) >>> point1 = Point(637209.083058, 257970.129540) then write the two points on the map, with :: >>> new.write(point0, ('pub', )) >>> new.write(point1, ('resturnat', )) commit the db changes :: >>> new.table.conn.commit() >>> new.table.execute().fetchall() [(1, u'pub'), (2, u'resturnat')] close the vector map :: >>> new.close() >>> new.exist() True then play with the map :: >>> new.open(mode='r') >>> new.read(1) Point(636981.336043, 256517.602235) >>> new.read(2) Point(637209.083058, 257970.129540) >>> new.read(1).attrs['name'] u'pub' >>> new.read(2).attrs['name'] u'resturnat' >>> new.close() >>> new.remove() """ self.n_lines += 1 if self.table is not None and attrs: attr = [self.n_lines, ] attr.extend(attrs) cur = self.table.conn.cursor() cur.execute(self.table.columns.insert_str, attr) cur.close() if set_cats: cats = Cats(geo_obj.c_cats) cats.reset() cats.set(self.n_lines, self.layer) if geo_obj.gtype == _Area.gtype: result = self._write_area(geo_obj) result = libvect.Vect_write_line(self.c_mapinfo, geo_obj.gtype, geo_obj.c_points, geo_obj.c_cats) if result == -1: raise GrassError("Not able to write the vector feature.") if self._topo_level == 2: # return new feature id (on level 2) geo_obj.id = result else: # return offset into file where the feature starts (on level 1) geo_obj.offset = result
@must_be_open
[docs] def has_color_table(self): """Return if vector has color table associated in file system; Color table stored in the vector's attribute table well be not checked >>> cens = Vector('census') >>> cens.open(mode='r') >>> cens.has_color_table() False >>> cens.close() >>> from grass.pygrass.utils import copy, remove >>> copy('census','mycensus','vect') >>> from grass.pygrass.modules.shortcuts import vector as v >>> v.colors(map='mycensus', color='population', column='TOTAL_POP') Module('v.colors') >>> mycens = Vector('mycensus') >>> mycens.open(mode='r') >>> mycens.has_color_table() True >>> mycens.close() >>> remove('mycensus', 'vect') """ loc = Location() path = join(loc.path(), self.mapset, 'vector', self.name, 'colr') return True if exists(path) else False #============================================= # VECTOR WITH TOPOLOGY #=============================================
[docs]class VectorTopo(Vector): """Vector class with the support of the GRASS topology. Open a vector map using the *with statement*: :: >>> with VectorTopo('schools', mode='r') as schools: ... for school in schools[:3]: ... print school.attrs['NAMESHORT'] ... SWIFT CREEK BRIARCLIFF FARMINGTON WOODS >>> schools.is_open() False .. """ def __init__(self, name, mapset='', *args, **kwargs): super(VectorTopo, self).__init__(name, mapset, *args, **kwargs) self._topo_level = 2 self._class_name = 'VectorTopo' def __len__(self): return libvect.Vect_get_num_lines(self.c_mapinfo) def __getitem__(self, key): """:: >>> cens = VectorTopo('census') >>> cens.open(mode='r') >>> cens[:3] [Boundary(v_id=1), Boundary(v_id=2), Boundary(v_id=3)] >>> cens.close() .. """ if isinstance(key, slice): return [self.read(indx) for indx in range(key.start if key.start else 1, key.stop if key.stop else len(self), key.step if key.step else 1)] elif isinstance(key, int): return self.read(key) else: raise ValueError("Invalid argument type: %r." % key) @must_be_open
[docs] def num_primitive_of(self, primitive): """Return the number of primitive :param primitive: the name of primitive to query; the supported values are: * *boundary*, * *centroid*, * *face*, * *kernel*, * *line*, * *point* * *area* * *volume* :type primitive: str :: >>> cens = VectorTopo('census') >>> cens.open(mode='r') >>> cens.num_primitive_of('point') 0 >>> cens.num_primitive_of('line') 0 >>> cens.num_primitive_of('centroid') 2537 >>> cens.num_primitive_of('boundary') 6383 >>> cens.close() .. """ return libvect.Vect_get_num_primitives(self.c_mapinfo, VTYPE[primitive])
@must_be_open
[docs] def number_of(self, vtype): """Return the number of the choosen element type :param vtype: the name of type to query; the supported values are: *areas*, *dblinks*, *faces*, *holes*, *islands*, *kernels*, *line_points*, *lines*, *nodes*, *update_lines*, *update_nodes*, *volumes* :type vtype: str >>> cens = VectorTopo('census') >>> cens.open(mode='r') >>> cens.number_of("areas") 2547 >>> cens.number_of("islands") 49 >>> cens.number_of("holes") 0 >>> cens.number_of("lines") 8920 >>> cens.number_of("nodes") 3885 >>> cens.number_of("pizza") ... # doctest: +ELLIPSIS +NORMALIZE_WHITESPACE Traceback (most recent call last): ... ValueError: vtype not supported, use one of: 'areas', ... >>> cens.close() .. """ if vtype in _NUMOF.keys(): return _NUMOF[vtype](self.c_mapinfo) else: keys = "', '".join(sorted(_NUMOF.keys())) raise ValueError("vtype not supported, use one of: '%s'" % keys)
@must_be_open
[docs] def num_primitives(self): """Return dictionary with the number of all primitives """ output = {} for prim in VTYPE.keys(): output[prim] = self.num_primitive_of(prim) return output
@must_be_open
[docs] def viter(self, vtype, idonly=False): """Return an iterator of vector features :param vtype: the name of type to query; the supported values are: *areas*, *dblinks*, *faces*, *holes*, *islands*, *kernels*, *line_points*, *lines*, *nodes*, *update_lines*, *update_nodes*, *volumes* :type vtype: str :param idonly: variable to return only the id of features instead of full features :type idonly: bool >>> cens = VectorTopo('census', mode='r') >>> cens.open(mode='r') >>> big = [area for area in cens.viter('areas') ... if area.alive() and area.area() >= 10000] >>> big[:3] [Area(5), Area(6), Area(13)] to sort the result in a efficient way, use: :: >>> from operator import methodcaller as method >>> big.sort(key=method('area'), reverse=True) # sort the list >>> for area in big[:3]: ... print area, area.area() Area(2099) 5392751.5304 Area(2171) 4799921.30863 Area(495) 4055812.49695 >>> cens.close() """ if vtype in _GEOOBJ.keys(): if _GEOOBJ[vtype] is not None: ids = (indx for indx in range(1, self.number_of(vtype) + 1)) if idonly: return ids return (_GEOOBJ[vtype](v_id=indx, c_mapinfo=self.c_mapinfo, table=self.table, writable=self.writable) for indx in ids) else: keys = "', '".join(sorted(_GEOOBJ.keys())) raise ValueError("vtype not supported, use one of: '%s'" % keys)
@must_be_open
[docs] def rewind(self): """Rewind vector map to cause reads to start at beginning. :: >>> cens = VectorTopo('census') >>> cens.open(mode='r') >>> cens.next() Boundary(v_id=1) >>> cens.next() Boundary(v_id=2) >>> cens.next() Boundary(v_id=3) >>> cens.rewind() >>> cens.next() Boundary(v_id=1) >>> cens.close() .. """ libvect.Vect_rewind(self.c_mapinfo)
@must_be_open
[docs] def cat(self, cat_id, vtype, layer=None, generator=False, geo=None): """Return the geometry features with category == cat_id. :param cat_id: the category number :type cat_id: int :param vtype: the type of geometry feature that we are looking for :type vtype: str :param layer: the layer number that will be used :type layer: int :param generator: if True return a generator otherwise it return a list of features :type generator: bool """ if geo is None and vtype not in _GEOOBJ: keys = "', '".join(sorted(_GEOOBJ.keys())) raise ValueError("vtype not supported, use one of: '%s'" % keys) Obj = _GEOOBJ[vtype] if geo is None else geo ilist = Ilist() libvect.Vect_cidx_find_all(self.c_mapinfo, layer if layer else self.layer, Obj.gtype, cat_id, ilist.c_ilist) is2D = not self.is_3D() if generator: return (read_line(feature_id=v_id, c_mapinfo=self.c_mapinfo, table=self.table, writable=self.writable, is2D=is2D) for v_id in ilist) else: return [read_line(feature_id=v_id, c_mapinfo=self.c_mapinfo, table=self.table, writable=self.writable, is2D=is2D) for v_id in ilist]
@must_be_open
[docs] def read(self, feature_id): """Return a geometry object given the feature id. :param int feature_id: the id of feature to obtain >>> cens = VectorTopo('census') >>> cens.open(mode='r') >>> feature1 = cens.read(0) #doctest: +ELLIPSIS Traceback (most recent call last): ... ValueError: The index must be >0, 0 given. >>> feature1 = cens.read(1) >>> feature1 Boundary(v_id=1) >>> feature1.length() 444.54490917696944 >>> cens.read(-1) Centoid(642963.159711, 214994.016279) >>> len(cens) 8920 >>> cens.read(8920) Centoid(642963.159711, 214994.016279) >>> cens.read(8921) #doctest: +ELLIPSIS Traceback (most recent call last): ... IndexError: Index out of range >>> cens.close() """ return read_line(feature_id, self.c_mapinfo, self.table, self.writable, is2D=not self.is_3D())
@must_be_open
[docs] def is_empty(self): """Return if a vector map is empty or not """ primitives = self.num_primitives() output = True for v in primitives.values(): if v != 0: output = False break return output
@must_be_open
[docs] def rewrite(self, line, geo_obj, attrs=None, **kargs): """Rewrite a geometry features """ if self.table is not None and attrs: attr = [line, ] attr.extend(attrs) self.table.update(key=line, values=attr) elif self.table is None and attrs: print "Table for vector {name} does not exist, attributes not" \ " loaded".format(name=self.name) libvect.Vect_cat_set(geo_obj.c_cats, self.layer, line) result = libvect.Vect_rewrite_line(self.c_mapinfo, line, geo_obj.gtype, geo_obj.c_points, geo_obj.c_cats) if result == -1: raise GrassError("Not able to write the vector feature.") # return offset into file where the feature starts geo_obj.offset = result
@must_be_open
[docs] def delete(self, feature_id): """Remove a feature by its id :param feature_id: the id of the feature :type feature_id: int """ if libvect.Vect_rewrite_line(self.c_mapinfo, feature_id) == -1: raise GrassError("C funtion: Vect_rewrite_line.")
@must_be_open
[docs] def restore(self, geo_obj): if hasattr(geo_obj, 'offset'): if libvect.Vect_restore_line(self.c_mapinfo, geo_obj.offset, geo_obj.id) == -1: raise GrassError("C funtion: Vect_restore_line.") else: raise ValueError("The value have not an offset attribute.")
@must_be_open
[docs] def bbox(self): """Return the BBox of the vecor map """ bbox = Bbox() if libvect.Vect_get_map_box(self.c_mapinfo, bbox.c_bbox) == 0: raise GrassError("I can not find the Bbox.") return bbox
@must_be_open
[docs] def select_by_bbox(self, bbox): """Return the BBox of the vector map """ # TODO replace with bbox if bbox else Bbox() ?? bbox = Bbox() if libvect.Vect_get_map_box(self.c_mapinfo, bbox.c_bbox) == 0: raise GrassError("I can not find the Bbox.") return bbox
[docs] def close(self, build=True, release=True): """Close the VectorTopo map, if release is True, the memory occupied by spatial index is released""" if release: libvect.Vect_set_release_support(self.c_mapinfo) super(VectorTopo, self).close(build=build)

Help Index | Topics Index | Keywords Index | Full Index

© 2003-2018 GRASS Development Team, GRASS GIS 7.0.7svn Reference Manual