[GRASS-SVN] r66016 - in grass/trunk/lib/python/pygrass: . vector
svn_grass at osgeo.org
svn_grass at osgeo.org
Tue Aug 25 08:20:23 PDT 2015
Author: huhabla
Date: 2015-08-25 08:20:23 -0700 (Tue, 25 Aug 2015)
New Revision: 66016
Modified:
grass/trunk/lib/python/pygrass/utils.py
grass/trunk/lib/python/pygrass/vector/__init__.py
grass/trunk/lib/python/pygrass/vector/abstract.py
grass/trunk/lib/python/pygrass/vector/find.py
grass/trunk/lib/python/pygrass/vector/geometry.py
Log:
pygrass vector: API changes: removed "get_" prefix from several functions to harmonize method names,
added vector map layer generator that is used in several doc tests. Modified many doctests in __init__.py and geometry.py
to use generated vector maps.
Modified: grass/trunk/lib/python/pygrass/utils.py
===================================================================
--- grass/trunk/lib/python/pygrass/utils.py 2015-08-25 13:41:44 UTC (rev 66015)
+++ grass/trunk/lib/python/pygrass/utils.py 2015-08-25 15:20:23 UTC (rev 66016)
@@ -347,3 +347,66 @@
return False
one = cursor.fetchone() if cursor else None
return True if one and one[0] else False
+
+
+def create_test_vector_map(map_name="test_vector"):
+ """This functions creates a vector map layer with points, lines, boundaries,
+ centroids, areas, isles and attributes for testing purposes
+
+ This should be used in doc and unit tests to create location/mapset
+ independent vector map layer. This map includes 3 points, 3 lines,
+ 11 boundaries and 4 centroids. The attribute table contains cat and name
+ columns.
+
+ param map_name: The vector map name that should be used
+ """
+
+ from grass.pygrass.vector import VectorTopo
+ from grass.pygrass.vector.geometry import Point, Line, Centroid, Boundary, Area
+
+ cols = [(u'cat', 'INTEGER PRIMARY KEY'),
+ (u'name','varchar(50)'),
+ (u'value', 'double precision')]
+ with VectorTopo(map_name, mode='w', tab_name=map_name,
+ tab_cols=cols) as vect:
+
+ # Write 3 points, 3 lines and 11 boundaries with one nested isle and 4 centroids
+ #
+ #
+ # ______ ___ ___ * * *
+ # |1 __ *|3 *|4 *| | | |
+ # | |2*| | | | | | |
+ # | |__| | | | | | |
+ # |______|___|___| | | |
+ #
+ # Write 3 points
+ vect.write(Point(10, 6), cat=1, attrs=("point", 1))
+ vect.write(Point(12, 6), cat=1)
+ vect.write(Point(14, 6), cat=1)
+ # Write 3 lines
+ vect.write(Line([(10, 4), (10, 2), (10,0)]), cat=2, attrs=("line", 2))
+ vect.write(Line([(12, 4), (12, 2), (12,0)]), cat=2)
+ vect.write(Line([(14, 4), (14, 2), (14,0)]), cat=2)
+ # boundaries 1 - 4
+ vect.write(Boundary(points=[(0, 0), (0,4)]))
+ vect.write(Boundary(points=[(0, 4), (4,4)]))
+ vect.write(Boundary(points=[(4, 4), (4,0)]))
+ vect.write(Boundary(points=[(4, 0), (0,0)]))
+ # 5. boundary (Isle)
+ vect.write(Boundary(points=[(1, 1), (1,3), (3, 3), (3,1), (1,1)]))
+ # boundaries 6 - 8
+ vect.write(Boundary(points=[(4, 4), (6,4)]))
+ vect.write(Boundary(points=[(6, 4), (6,0)]))
+ vect.write(Boundary(points=[(6, 0), (4,0)]))
+ # boundaries 9 - 11
+ vect.write(Boundary(points=[(6, 4), (8,4)]))
+ vect.write(Boundary(points=[(8, 4), (8,0)]))
+ vect.write(Boundary(points=[(8, 0), (6,0)]))
+ # Centroids, all have the same cat and attribute
+ vect.write(Centroid(x=3.5, y=3.5), cat=3, attrs=("centroid", 3))
+ vect.write(Centroid(x=2.5, y=2.5), cat=3)
+ vect.write(Centroid(x=5.5, y=3.5), cat=3)
+ vect.write(Centroid(x=7.5, y=3.5), cat=3)
+
+ vect.table.conn.commit()
+ vect.close()
Modified: grass/trunk/lib/python/pygrass/vector/__init__.py
===================================================================
--- grass/trunk/lib/python/pygrass/vector/__init__.py 2015-08-25 13:41:44 UTC (rev 66015)
+++ grass/trunk/lib/python/pygrass/vector/__init__.py 2015-08-25 15:20:23 UTC (rev 66016)
@@ -31,6 +31,8 @@
"updated_nodes": libvect.Vect_get_num_updated_nodes,
"volumes": libvect.Vect_get_num_volumes}
+# For test purposes
+test_vector_name = "vector_doctest_map"
#=============================================
# VECTOR
@@ -40,16 +42,14 @@
"""Vector class is the grass vector format without topology
>>> from grass.pygrass.vector import Vector
- >>> cens = Vector('census')
- >>> cens.is_open()
+ >>> test_vect = Vector(test_vector_name)
+ >>> test_vect.is_open()
False
- >>> cens.mapset
+ >>> test_vect.mapset
''
- >>> cens.exist()
+ >>> test_vect.exist()
True
- >>> cens.mapset
- 'PERMANENT'
- >>> cens.overwrite
+ >>> test_vect.overwrite
False
"""
@@ -59,6 +59,7 @@
self._topo_level = 1
self._class_name = 'Vector'
self.overwrite = False
+ self._cats = []
def __repr__(self):
if self.exist():
@@ -69,12 +70,12 @@
def __iter__(self):
"""::
- >>> cens = Vector('census')
- >>> cens.open(mode='r')
- >>> features = [feature for feature in cens]
+ >>> test_vect = Vector(test_vector_name)
+ >>> test_vect.open(mode='r')
+ >>> features = [feature for feature in test_vect]
>>> features[:3]
- [Boundary(v_id=None), Boundary(v_id=None), Boundary(v_id=None)]
- >>> cens.close()
+ [Point(10.000000, 6.000000), Point(12.000000, 6.000000), Point(14.000000, 6.000000)]
+ >>> test_vect.close()
..
"""
@@ -85,17 +86,17 @@
def next(self):
"""::
- >>> cens = Vector('census')
- >>> cens.open(mode='r')
- >>> cens.next()
- Boundary(v_id=None)
- >>> cens.next()
- Boundary(v_id=None)
- >>> cens.close()
+ >>> test_vect = Vector(test_vector_name)
+ >>> test_vect.open(mode='r')
+ >>> test_vect.next()
+ Point(10.000000, 6.000000)
+ >>> test_vect.next()
+ Point(12.000000, 6.000000)
+ >>> test_vect.close()
..
"""
- return read_next_line(self.c_mapinfo, self.table, self.writable,
+ return read_next_line(self.c_mapinfo, self.table, self.writeable,
is2D=not self.is_3D())
@must_be_open
@@ -105,7 +106,7 @@
raise GrassError("Vect_rewind raise an error.")
@must_be_open
- def write(self, geo_obj, attrs=None, set_cats=True):
+ def write(self, geo_obj, cat=None, attrs=None):
"""Write geometry features and attributes.
:param geo_obj: a geometry grass object define in
@@ -114,11 +115,9 @@
: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
+ :param cat: The category of the geometry feature, otherwise the
c_cats attribute of the geometry object will be used.
- :type set_cats: bool
+ :type cat: integer
Open a new vector map ::
@@ -141,19 +140,19 @@
create two points ::
- >>> point0 = Point(636981.336043, 256517.602235)
- >>> point1 = Point(637209.083058, 257970.129540)
+ >>> point0 = Point(0, 0)
+ >>> point1 = Point(1, 1)
then write the two points on the map, with ::
- >>> new.write(point0, ('pub', ))
- >>> new.write(point1, ('resturnat', ))
+ >>> new.write(point0, cat=1, attrs=('pub',))
+ >>> new.write(point1, cat=2, attrs=('resturant',))
commit the db changes ::
>>> new.table.conn.commit()
>>> new.table.execute().fetchall()
- [(1, u'pub'), (2, u'resturnat')]
+ [(1, u'pub'), (2, u'resturant')]
close the vector map ::
@@ -165,29 +164,31 @@
>>> new.open(mode='r')
>>> new.read(1)
- Point(636981.336043, 256517.602235)
+ Point(0.000000, 0.000000)
>>> new.read(2)
- Point(637209.083058, 257970.129540)
+ Point(1.000000, 1.000000)
>>> new.read(1).attrs['name']
u'pub'
>>> new.read(2).attrs['name']
- u'resturnat'
+ u'resturant'
>>> 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 self.table is not None and attrs and cat is not None:
+ if cat not in self._cats:
+ self._cats.append(cat)
+ attr = [cat, ]
+ attr.extend(attrs)
+ cur = self.table.conn.cursor()
+ cur.execute(self.table.columns.insert_str, attr)
+ cur.close()
- if set_cats:
+ if cat is not None:
cats = Cats(geo_obj.c_cats)
cats.reset()
- cats.set(self.n_lines, self.layer)
+ cats.set(cat, self.layer)
if geo_obj.gtype == _Area.gtype:
result = self._write_area(geo_obj)
@@ -207,23 +208,23 @@
"""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()
+ >>> test_vect = Vector(test_vector_name)
+ >>> test_vect.open(mode='r')
+ >>> test_vect.has_color_table()
False
- >>> cens.close()
+ >>> test_vect.close()
>>> from grass.pygrass.utils import copy, remove
- >>> copy('census','mycensus','vect')
+ >>> copy(test_vector_name,'mytest_vect','vect')
>>> from grass.pygrass.modules.shortcuts import vector as v
- >>> v.colors(map='mycensus', color='population', column='TOTAL_POP')
+ >>> v.colors(map='mytest_vect', color='population', column='value')
Module('v.colors')
- >>> mycens = Vector('mycensus')
- >>> mycens.open(mode='r')
- >>> mycens.has_color_table()
+ >>> mytest_vect = Vector('mytest_vect')
+ >>> mytest_vect.open(mode='r')
+ >>> mytest_vect.has_color_table()
True
- >>> mycens.close()
- >>> remove('mycensus', 'vect')
+ >>> mytest_vect.close()
+ >>> remove('mytest_vect', 'vect')
"""
loc = Location()
path = join(loc.path(), self.mapset, 'vector', self.name, 'colr')
@@ -239,14 +240,17 @@
Open a vector map using the *with statement*: ::
- >>> with VectorTopo('schools', mode='r') as schools:
- ... for school in schools[:4]:
- ... print school.attrs['NAMESHORT']
+ >>> with VectorTopo(test_vector_name, mode='r') as test_vect:
+ ... for feature in test_vect[:7]:
+ ... print feature.attrs['name']
...
- SWIFT CREEK
- BRIARCLIFF
- FARMINGTON WOODS
- >>> schools.is_open()
+ point
+ point
+ point
+ line
+ line
+ line
+ >>> test_vect.is_open()
False
..
@@ -262,11 +266,11 @@
def __getitem__(self, key):
"""::
- >>> cens = VectorTopo('census')
- >>> cens.open(mode='r')
- >>> cens[:4]
- [Boundary(v_id=1), Boundary(v_id=2), Boundary(v_id=3)]
- >>> cens.close()
+ >>> test_vect = VectorTopo(test_vector_name)
+ >>> test_vect.open(mode='r')
+ >>> test_vect[:4]
+ [Point(10.000000, 6.000000), Point(12.000000, 6.000000), Point(14.000000, 6.000000)]
+ >>> test_vect.close()
..
"""
@@ -299,17 +303,17 @@
::
- >>> 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()
+ >>> test_vect = VectorTopo(test_vector_name)
+ >>> test_vect.open(mode='r')
+ >>> test_vect.num_primitive_of('point')
+ 3
+ >>> test_vect.num_primitive_of('line')
+ 3
+ >>> test_vect.num_primitive_of('centroid')
+ 4
+ >>> test_vect.num_primitive_of('boundary')
+ 11
+ >>> test_vect.close()
..
"""
@@ -326,24 +330,24 @@
*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")
+ >>> test_vect = VectorTopo(test_vector_name)
+ >>> test_vect.open(mode='r')
+ >>> test_vect.number_of("areas")
+ 4
+ >>> test_vect.number_of("islands")
+ 2
+ >>> test_vect.number_of("holes")
0
- >>> cens.number_of("lines")
- 8920
- >>> cens.number_of("nodes")
- 3885
- >>> cens.number_of("pizza")
+ >>> test_vect.number_of("lines")
+ 21
+ >>> test_vect.number_of("nodes")
+ 15
+ >>> test_vect.number_of("pizza")
... # doctest: +ELLIPSIS +NORMALIZE_WHITESPACE
Traceback (most recent call last):
...
ValueError: vtype not supported, use one of: 'areas', ...
- >>> cens.close()
+ >>> test_vect.close()
..
@@ -376,24 +380,23 @@
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)]
+ >>> test_vect = VectorTopo(test_vector_name, mode='r')
+ >>> test_vect.open(mode='r')
+ >>> areas = [area for area in test_vect.viter('areas')]
+ >>> areas[:3]
+ [Area(1), Area(2), Area(3)]
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]:
+ >>> areas.sort(key=method('area'), reverse=True) # sort the list
+ >>> for area in areas[:3]:
... print area, area.area()
- Area(2099) 5392751.5304
- Area(2171) 4799921.30863
- Area(495) 4055812.49695
- >>> cens.close()
+ Area(1) 12.0
+ Area(2) 8.0
+ Area(4) 8.0
+ >>> test_vect.close()
"""
if vtype in _GEOOBJ.keys():
@@ -403,7 +406,7 @@
return ids
return (_GEOOBJ[vtype](v_id=indx, c_mapinfo=self.c_mapinfo,
table=self.table,
- writable=self.writable)
+ writeable=self.writeable)
for indx in ids)
else:
keys = "', '".join(sorted(_GEOOBJ.keys()))
@@ -413,18 +416,18 @@
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()
+ >>> test_vect = VectorTopo(test_vector_name)
+ >>> test_vect.open(mode='r')
+ >>> test_vect.next()
+ Point(10.000000, 6.000000)
+ >>> test_vect.next()
+ Point(12.000000, 6.000000)
+ >>> test_vect.next()
+ Point(14.000000, 6.000000)
+ >>> test_vect.rewind()
+ >>> test_vect.next()
+ Point(10.000000, 6.000000)
+ >>> test_vect.close()
..
"""
@@ -455,12 +458,12 @@
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,
+ table=self.table, writeable=self.writeable,
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,
+ table=self.table, writeable=self.writeable,
is2D=is2D)
for v_id in ilist]
@@ -470,31 +473,31 @@
:param int feature_id: the id of feature to obtain
- >>> cens = VectorTopo('census')
- >>> cens.open(mode='r')
- >>> feature1 = cens.read(0) #doctest: +ELLIPSIS
+ >>> test_vect = VectorTopo(test_vector_name)
+ >>> test_vect.open(mode='r')
+ >>> feature1 = test_vect.read(0) #doctest: +ELLIPSIS
Traceback (most recent call last):
...
ValueError: The index must be >0, 0 given.
- >>> feature1 = cens.read(1)
+ >>> feature1 = test_vect.read(5)
>>> feature1
- Boundary(v_id=1)
+ Line([Point(12.000000, 4.000000), Point(12.000000, 2.000000), Point(12.000000, 0.000000)])
>>> 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
+ 4.0
+ >>> test_vect.read(-1)
+ Centoid(7.500000, 3.500000)
+ >>> len(test_vect)
+ 21
+ >>> test_vect.read(21)
+ Centoid(7.500000, 3.500000)
+ >>> test_vect.read(22) #doctest: +ELLIPSIS
Traceback (most recent call last):
...
IndexError: Index out of range
- >>> cens.close()
+ >>> test_vect.close()
"""
- return read_line(feature_id, self.c_mapinfo, self.table, self.writable,
+ return read_line(feature_id, self.c_mapinfo, self.table, self.writeable,
is2D=not self.is_3D())
@must_be_open
@@ -575,3 +578,9 @@
if release:
libvect.Vect_set_release_support(self.c_mapinfo)
super(VectorTopo, self).close(build=build)
+
+if __name__ == "__main__":
+ import doctest
+ from grass.pygrass import utils
+ utils.create_test_vector_map(test_vector_name)
+ doctest.testmod()
Modified: grass/trunk/lib/python/pygrass/vector/abstract.py
===================================================================
--- grass/trunk/lib/python/pygrass/vector/abstract.py 2015-08-25 13:41:44 UTC (rev 66015)
+++ grass/trunk/lib/python/pygrass/vector/abstract.py 2015-08-25 15:20:23 UTC (rev 66016)
@@ -388,13 +388,13 @@
self.layer = self.dblinks.by_layer(layer).layer
self.table = self.dblinks.by_layer(layer).table()
self.n_lines = self.table.n_rows()
- self.writable = self.mapset == utils.getenv("MAPSET")
+ self.writeable = self.mapset == utils.getenv("MAPSET")
self.find = {'by_point': PointFinder(self.c_mapinfo, self.table,
- self.writable),
+ self.writeable),
'by_box': BboxFinder(self.c_mapinfo, self.table,
- self.writable),
+ self.writeable),
'by_polygon': PolygonFinder(self.c_mapinfo, self.table,
- self.writable), }
+ self.writeable), }
def close(self, build=False):
"""Method to close the Vector
Modified: grass/trunk/lib/python/pygrass/vector/find.py
===================================================================
--- grass/trunk/lib/python/pygrass/vector/find.py 2015-08-25 13:41:44 UTC (rev 66015)
+++ grass/trunk/lib/python/pygrass/vector/find.py 2015-08-25 15:20:23 UTC (rev 66016)
@@ -13,7 +13,7 @@
class AbstractFinder(object):
- def __init__(self, c_mapinfo, table=None, writable=False):
+ def __init__(self, c_mapinfo, table=None, writeable=False):
"""AbstractFinder
-----------------
@@ -21,7 +21,7 @@
"""
self.c_mapinfo = c_mapinfo
self.table = table
- self.writable = writable
+ self.writeable = writeable
self.vtype = {'point': libvect.GV_POINT, # 1
'line': libvect.GV_LINE, # 2
'boundary': libvect.GV_BOUNDARY, # 3
@@ -70,10 +70,10 @@
>>> schools.close()
>>> zipcodes.close()
"""
- def __init__(self, c_mapinfo, table=None, writable=False):
+ def __init__(self, c_mapinfo, table=None, writeable=False):
"""Find geometry feature around a point.
"""
- super(PointFinder, self).__init__(c_mapinfo, table, writable)
+ super(PointFinder, self).__init__(c_mapinfo, table, writeable)
# TODO: add the Node class and enable this method
# def node(self, point, maxdist):
@@ -95,7 +95,7 @@
int(not point.is2D), exclude)
if feature_id:
return read_line(feature_id, self.c_mapinfo,
- self.table, self.writable)
+ self.table, self.writeable)
@must_be_open
def geos(self, point, maxdist, type='all', exclude=None):
@@ -111,7 +111,7 @@
self.vtype[type], float(maxdist),
int(not point.is2D),
excl.c_ilist, found.c_ilist):
- return [read_line(f_id, self.c_mapinfo, self.table, self.writable)
+ return [read_line(f_id, self.c_mapinfo, self.table, self.writeable)
for f_id in found]
else:
return []
@@ -122,7 +122,7 @@
area_id = libvect.Vect_find_area(self.c_mapinfo, point.x, point.y)
if area_id:
return Area(v_id=area_id, c_mapinfo=self.c_mapinfo,
- table=self.table, writable=self.writable)
+ table=self.table, writeable=self.writeable)
@must_be_open
def island(self, point):
@@ -130,12 +130,12 @@
isle_id = libvect.Vect_find_island(self.c_mapinfo, point.x, point.y)
if isle_id:
return Isle(v_id=isle_id, c_mapinfo=self.c_mapinfo,
- table=self.table, writable=self.writable)
+ table=self.table, writeable=self.writeable)
class BboxFinder(AbstractFinder):
- def __init__(self, c_mapinfo, table=None, writable=False):
- super(BboxFinder, self).__init__(c_mapinfo, table, writable)
+ def __init__(self, c_mapinfo, table=None, writeable=False):
+ super(BboxFinder, self).__init__(c_mapinfo, table, writeable)
@must_be_open
def geos(self, bbox, type='all', bbox_list=False):
@@ -151,7 +151,7 @@
return found
else:
return (read_line(f_id, self.c_mapinfo, self.table,
- self.writable) for f_id in found.ids)
+ self.writeable) for f_id in found.ids)
@must_be_open
def nodes(self, bbox):
@@ -161,7 +161,7 @@
found.c_ilist):
for n_id in found:
yield Node(v_id=n_id, c_mapinfo=self.c_mapinfo,
- table=self.table, writable=self.writable)
+ table=self.table, writeable=self.writeable)
@must_be_open
def areas(self, bbox, boxlist=None, bboxlist_only=False):
@@ -173,7 +173,7 @@
return boxlist
else:
return (Area(v_id=a_id, c_mapinfo=self.c_mapinfo,
- table=self.table, writable=self.writable)
+ table=self.table, writeable=self.writeable)
for a_id in boxlist.ids)
return []
@@ -187,14 +187,14 @@
return found
else:
return (Isle(v_id=i_id, c_mapinfo=self.c_mapinfo,
- table=self.table, writable=self.writable)
+ table=self.table, writeable=self.writeable)
for i_id in found.ids)
return []
class PolygonFinder(AbstractFinder):
- def __init__(self, c_mapinfo, table=None, writable=False):
- super(PolygonFinder, self).__init__(c_mapinfo, table, writable)
+ def __init__(self, c_mapinfo, table=None, writeable=False):
+ super(PolygonFinder, self).__init__(c_mapinfo, table, writeable)
def lines(self, polygon, isles=None):
pass
Modified: grass/trunk/lib/python/pygrass/vector/geometry.py
===================================================================
--- grass/trunk/lib/python/pygrass/vector/geometry.py 2015-08-25 13:41:44 UTC (rev 66015)
+++ grass/trunk/lib/python/pygrass/vector/geometry.py 2015-08-25 15:20:23 UTC (rev 66016)
@@ -19,6 +19,8 @@
from grass.pygrass.vector.basic import Ilist, Bbox, Cats
from grass.pygrass.vector import sql
+# For test purposes
+test_vector_name = "geometry_doctest_map"
LineDist = namedtuple('LineDist', 'point dist spdist sldist')
@@ -133,12 +135,12 @@
class Attrs(object):
- def __init__(self, cat, table, writable=False):
+ def __init__(self, cat, table, writeable=False):
self._cat = None
self.cond = ''
self.table = table
self.cat = cat
- self.writable = writable
+ self.writeable = writeable
def _get_cat(self):
return self._cat
@@ -156,12 +158,12 @@
"""Return the value stored in the attribute table.
>>> from grass.pygrass.vector import VectorTopo
- >>> schools = VectorTopo('schools')
- >>> schools.open('r')
- >>> school = schools[1]
- >>> attrs = Attrs(school.cat, schools.table)
- >>> attrs['TAG']
- u'568'
+ >>> test_vect = VectorTopo(test_vector_name)
+ >>> test_vect.open('r')
+ >>> v1 = test_vect[1]
+ >>> v1.attrs['name']
+ u'point'
+ >>> test_vect.close()
"""
#SELECT {cols} FROM {tname} WHERE {condition};
@@ -179,19 +181,23 @@
"""Set value of a given column of a table attribute.
>>> from grass.pygrass.vector import VectorTopo
- >>> from grass.pygrass.utils import copy, remove
- >>> copy('schools', 'myschools', 'vect')
- >>> schools = VectorTopo('myschools')
- >>> schools.open('r')
- >>> school = schools[1]
- >>> attrs = Attrs(school.cat, schools.table, True)
- >>> attrs['TAG'] = 'New Label'
- >>> attrs['TAG']
- u'New Label'
- >>> attrs.table.conn.close()
- >>> remove('myschools','vect')
+ >>> test_vect = VectorTopo(test_vector_name)
+ >>> test_vect.open('r')
+ >>> v1 = test_vect[1]
+ >>> v1.attrs['name']
+ u'point'
+
+ #>>> v1.attrs['name'] = "new_point"
+ #>>> v1.attrs['name']
+ #u'new_point'
+ #>>> v1.attrs['name'] = "point"
+ #>>> v1.attrs['name']
+ #u'point'
+ #>>> v.table.conn.commit()
+ >>> test_vect.close()
+
"""
- if self.writable:
+ if self.writeable:
#UPDATE {tname} SET {new_col} = {old_col} WHERE {condition}
values = '%s=%r' % (key, value)
self.table.execute(sql.UPDATE_WHERE.format(tname=self.table.name,
@@ -211,15 +217,14 @@
def values(self):
"""Return the values of the attribute table row.
+
>>> from grass.pygrass.vector import VectorTopo
- >>> schools = VectorTopo('schools')
- >>> schools.open('r')
- >>> school = schools[1]
- >>> attrs = Attrs(school.cat, schools.table)
- >>> attrs.values() # doctest: +ELLIPSIS +NORMALIZE_WHITESPACE
- (1,
- ...
- None)
+ >>> test_vect = VectorTopo(test_vector_name)
+ >>> test_vect.open('r')
+ >>> v1 = test_vect[1]
+ >>> v1.attrs.values()
+ (1, u'point', 1.0)
+ >>> test_vect.close()
"""
#SELECT {cols} FROM {tname} WHERE {condition}
@@ -230,15 +235,15 @@
def keys(self):
"""Return the column name of the attribute table.
+
>>> from grass.pygrass.vector import VectorTopo
- >>> schools = VectorTopo('schools')
- >>> schools.open('r')
- >>> school = schools[1]
- >>> attrs = Attrs(school.cat, schools.table)
- >>> attrs.keys() # doctest: +ELLIPSIS +NORMALIZE_WHITESPACE
- [u'cat',
- ...
- u'NOTES']
+ >>> test_vect = VectorTopo(test_vector_name)
+ >>> test_vect.open('r')
+ >>> v1 = test_vect[1]
+ >>> v1.attrs.keys()
+ [u'cat', u'name', u'value']
+ >>> test_vect.close()
+
"""
return self.table.columns.names()
@@ -249,15 +254,12 @@
class Geo(object):
"""
- >>> geo0 = Geo()
- >>> points = ctypes.pointer(libvect.line_pnts())
- >>> cats = ctypes.pointer(libvect.line_cats())
- >>> geo1 = Geo(c_points=points, c_cats=cats)
+ Base object for different feature types
"""
gtype = None
def __init__(self, v_id=0, c_mapinfo=None, c_points=None, c_cats=None,
- table=None, writable=False, is2D=True):
+ table=None, writeable=False, is2D=True):
self.id = v_id # vector id
self.c_mapinfo = c_mapinfo
self.is2D = (is2D if is2D is not None else
@@ -284,14 +286,14 @@
# set the attributes as last thing to do
self.attrs = None
if table is not None and self.cat is not None:
- self.attrs = Attrs(self.cat, table, writable)
+ self.attrs = Attrs(self.cat, table, writeable)
@property
def cat(self):
if self.c_cats.contents.cat:
return self.c_cats.contents.cat.contents.value
- def is_with_topology(self):
+ def has_topology(self):
if self.c_mapinfo is not None:
return self.c_mapinfo.contents.level == 2
else:
@@ -379,7 +381,7 @@
doc="Set and obtain z coordinate")
def __str__(self):
- return self.get_wkt()
+ return self.to_wkt()
def __repr__(self):
return "Point(%s)" % ', '.join(['%f' % coor for coor in self.coords()])
@@ -428,11 +430,11 @@
else:
return self.x, self.y, self.z
- def get_wkt(self):
+ def to_wkt(self):
"""Return a "well know text" (WKT) geometry string. ::
>>> pnt = Point(10, 100)
- >>> pnt.get_wkt()
+ >>> pnt.to_wkt()
'POINT(10.000000 100.000000)'
.. warning::
@@ -443,7 +445,7 @@
return "POINT(%s)" % ' '.join(['%f' % coord
for coord in self.coords()])
- def get_wkb(self):
+ def to_wkb(self):
"""Return a "well know binary" (WKB) geometry buffer
.. warning::
@@ -604,23 +606,23 @@
return self.c_points.contents.n_points
def __str__(self):
- return self.get_wkt()
+ return self.to_wkt()
def __repr__(self):
return "Line([%s])" % ', '.join([repr(pnt) for pnt in self.__iter__()])
- def get_pnt(self, distance, angle=0, slope=0):
+ def point_on_line(self, distance, angle=0, slope=0):
"""Return a Point object on line in the specified distance, using the
`Vect_point_on_line` C function.
Raise a ValueError If the distance exceed the Line length. ::
>>> line = Line([(0, 0), (1, 1)])
- >>> line.get_pnt(5) #doctest: +ELLIPSIS +NORMALIZE_WHITESPACE
+ >>> line.point_on_line(5) #doctest: +ELLIPSIS +NORMALIZE_WHITESPACE
Traceback (most recent call last):
...
ValueError: The distance exceed the length of the line,
that is: 1.414214
- >>> line.get_pnt(1)
+ >>> line.point_on_line(1)
Point(0.707107, 0.707107)
..
@@ -811,7 +813,7 @@
return LineDist(point, dist.value, sp_dist.value, lp_dist.value)
@mapinfo_must_be_set
- def get_first_cat(self):
+ def first_cat(self):
"""Fetches FIRST category number for given vector line and field, using
the ``Vect_get_line_cat`` C function.
@@ -831,9 +833,9 @@
>>> line = Line([(0, 0), (1, 1), (2, 2)])
>>> midle_pnt = line.pop(1)
- >>> midle_pnt
+ >>> midle_pnt #doctest: +NORMALIZE_WHITESPACE
Point(1.000000, 1.000000)
- >>> line
+ >>> line #doctest: +NORMALIZE_WHITESPACE
Line([Point(0.000000, 0.000000), Point(2.000000, 2.000000)])
"""
@@ -852,7 +854,7 @@
>>> line = Line([(0, 0), (1, 1), (2, 2)])
>>> line.delete(-1)
- >>> line
+ >>> line #doctest: +NORMALIZE_WHITESPACE
Line([Point(0.000000, 0.000000), Point(1.000000, 1.000000)])
"""
@@ -906,7 +908,7 @@
>>> line = Line([(0, 0), (1, 1), (2, 2)])
>>> line.remove((2, 2))
- >>> line[-1]
+ >>> line[-1] #doctest: +NORMALIZE_WHITESPACE
Point(1.000000, 1.000000)
..
@@ -960,22 +962,22 @@
libvect.Vect_line_segment(self.c_points, start, end, line.c_points)
return line
- def tolist(self):
+ def to_list(self):
"""Return a list of tuple. ::
>>> line = Line([(0, 0), (1, 1), (2, 0), (1, -1)])
- >>> line.tolist()
+ >>> line.to_list()
[(0.0, 0.0), (1.0, 1.0), (2.0, 0.0), (1.0, -1.0)]
..
"""
return [pnt.coords() for pnt in self.__iter__()]
- def toarray(self):
+ def to_array(self):
"""Return an array of coordinates. ::
>>> line = Line([(0, 0), (1, 1), (2, 0), (1, -1)])
- >>> line.toarray() #doctest: +NORMALIZE_WHITESPACE
+ >>> line.to_array() #doctest: +NORMALIZE_WHITESPACE
array([[ 0., 0.],
[ 1., 1.],
[ 2., 0.],
@@ -983,13 +985,13 @@
..
"""
- return np.array(self.tolist())
+ return np.array(self.to_list())
- def get_wkt(self):
+ def to_wkt(self):
"""Return a Well Known Text string of the line. ::
>>> line = Line([(0, 0), (1, 1), (1, 2)])
- >>> line.get_wkt() #doctest: +ELLIPSIS
+ >>> line.to_wkt() #doctest: +ELLIPSIS
'LINESTRING(0.000000 0.000000, ..., 1.000000 2.000000)'
..
@@ -1054,7 +1056,7 @@
>>> area = line.buffer(10)
>>> area.boundary #doctest: +ELLIPSIS
Line([Point(-10.000000, 0.000000),...Point(-10.000000, 0.000000)])
- >>> area.centroid
+ >>> area.centroid #doctest: +NORMALIZE_WHITESPACE
Point(0.000000, 0.000000)
>>> area.isles
[]
@@ -1104,7 +1106,7 @@
return: A tuple of Node objects that represent the
start and end point of this line.
"""
- if self.is_with_topology():
+ if self.has_topology():
n1 = ctypes.c_int()
n2 = ctypes.c_int()
libvect.Vect_get_line_nodes(self.c_mapinfo, self.id,
@@ -1208,14 +1210,13 @@
# geometry type
gtype = libvect.GV_BOUNDARY
- def __init__(self, lines=None, left=None, right=None,
- **kargs):
+ def __init__(self, **kargs):
+ super(Boundary, self).__init__(**kargs)
+
v_id = kargs.get('v_id', 0)
self.dir = libvect.GV_FORWARD if v_id > 0 else libvect.GV_BACKWARD
- super(Boundary, self).__init__(**kargs)
self.c_left = ctypes.pointer(ctypes.c_int())
self.c_right = ctypes.pointer(ctypes.c_int())
- #self.get_left_right()
@property
def left_id(self):
@@ -1226,10 +1227,10 @@
return self.c_right.contents.value
def __repr__(self):
- return "Boundary(v_id=%r)" % self.id
+ return "Boundary([%s])" % ', '.join([repr(pnt) for pnt in self.__iter__()])
@mapinfo_must_be_set
- def _get_centroid(self, side, idonly=False):
+ def _centroid(self, side, idonly=False):
if side > 0:
v_id = libvect.Vect_get_area_centroid(self.c_mapinfo, side)
v_id = v_id if v_id else None
@@ -1239,21 +1240,21 @@
cntr = Centroid(v_id=v_id, c_mapinfo=self.c_mapinfo)
return cntr
- def get_left_centroid(self, idonly=False):
- """Return left value
+ def left_centroid(self, idonly=False):
+ """Return left centroid
:param idonly: True to return only the cat of feature
:type idonly: bool
"""
- return self._get_centroid(self.left_id, idonly)
+ return self._centroid(self.left_id, idonly)
- def get_right_centroid(self, idonly=False):
- """Return right value
+ def right_centroid(self, idonly=False):
+ """Return right centroid
:param idonly: True to return only the cat of feature
:type idonly: bool
"""
- return self._get_centroid(self.left_id, idonly)
+ return self._centroid(self.left_id, idonly)
@mapinfo_must_be_set
def get_left_right(self):
@@ -1287,11 +1288,12 @@
>>> centroid
Centoid(0.000000, 10.000000)
>>> from grass.pygrass.vector import VectorTopo
- >>> geo = VectorTopo('geology')
- >>> geo.open(mode='r')
- >>> centroid = Centroid(v_id=1, c_mapinfo=geo.c_mapinfo)
+ >>> test_vect = VectorTopo(test_vector_name)
+ >>> test_vect.open(mode='r')
+ >>> centroid = Centroid(v_id=1, c_mapinfo=test_vect.c_mapinfo)
>>> centroid
- Centoid(893202.874416, 297339.312795)
+ Centoid(10.000000, 6.000000)
+ >>> test_vect.close()
..
"""
@@ -1304,7 +1306,7 @@
if self.id and self.c_mapinfo and self.area_id is None:
self.area_id = self.get_area_id()
elif self.c_mapinfo and self.area_id and self.id is None:
- self.id = self.get_centroid_id()
+ self.id = self.centroid_id()
if self.area_id is not None:
self.read()
@@ -1314,7 +1316,7 @@
return "Centoid(%s)" % ', '.join(['%f' % co for co in self.coords()])
@mapinfo_must_be_set
- def get_centroid_id(self):
+ def centroid_id(self):
"""Return the centroid_id, using the c_mapinfo and an area_id
attributes of the class, and calling the Vect_get_area_centroid
C function, if no centroid_id were found return None"""
@@ -1325,7 +1327,7 @@
@mapinfo_must_be_set
def get_area_id(self):
"""Return the area_id, using the c_mapinfo and an centroid_id
- attributes of the class, and calling the Vect_get_centroid_area
+ attributes of the class, and calling the Vect_centroid_area
C function, if no area_id were found return None"""
area_id = libvect.Vect_get_centroid_area(self.c_mapinfo,
self.id)
@@ -1413,8 +1415,8 @@
self._isles_id = None
self._isles = None
if area_id:
- self._isles_id = self.get_isles_id()
- self._isles = self.get_isles()
+ self._isles_id = self.isles_ids()
+ self._isles = self.isles()
@mapinfo_must_be_set
def __len__(self):
@@ -1425,39 +1427,29 @@
def __getitem__(self, key):
if self._isles is None:
- self.get_isles()
+ self.isles()
return self._isles[key]
@mapinfo_must_be_set
- def get_isles_id(self):
+ def isles_ids(self):
"""Return the id of isles"""
return [libvect.Vect_get_area_isle(self.c_mapinfo, self.area_id, i)
for i in range(self.__len__())]
@mapinfo_must_be_set
- def get_isles(self):
+ def isles(self):
"""Return isles"""
return [Isle(v_id=isle_id, c_mapinfo=self.c_mapinfo)
for isle_id in self._isles_id]
- def select_by_bbox(self, bbox):
- """Vect_select_isles_by_box
- .. warning::
-
- Not implemented yet.
-
- """
- pass
-
-
class Area(Geo):
"""
Vect_build_line_area,
Vect_find_area,
Vect_get_area_box,
Vect_get_area_points_geos,
- Vect_get_centroid_area,
+ Vect_centroid_area,
Vect_get_isle_area,
Vect_get_line_areas,
@@ -1498,12 +1490,12 @@
raise ValueError("You need to give or set the area_id")
self.id = area_id if area_id is not None else self.id
# get boundary
- self.get_points()
+ self.points()
# get isles
- self.get_isles()
+ self.isles()
@mapinfo_must_be_set
- def get_points(self, line=None):
+ def points(self, line=None):
"""Return a Line object with the outer ring
:param line: a Line object to fill with info from points of area
@@ -1514,7 +1506,7 @@
return line
@mapinfo_must_be_set
- def get_centroid(self, centroid=None):
+ def centroid(self, centroid=None):
"""Return the centroid
:param centroid: a Centroid object to fill with info from centroid of area
@@ -1534,7 +1526,7 @@
return libvect.Vect_get_area_num_isles(self.c_mapinfo, self.id)
@mapinfo_must_be_set
- def get_isles(self, isles=None):
+ def isles(self, isles=None):
"""Instantiate the boundary attribute reading area_id"""
if isles is not None:
isles.area_id = self.id
@@ -1620,18 +1612,18 @@
return [Boundary(v_id=abs(v_id), c_mapinfo=self.c_mapinfo) for v_id in ilst]
- def get_wkt(self):
+ def to_wkt(self):
"""Return a Well Known Text string of the Area. ::
For now the outer ring is returned
TODO: Implement inner rings detected from isles
"""
- line = self.get_points()
+ line = self.points()
return "Polygon((%s))" % ', '.join([
' '.join(['%f' % coord for coord in pnt])
- for pnt in line.tolist()])
+ for pnt in line.to_list()])
@mapinfo_must_be_set
def cats(self, cats=None):
@@ -1674,13 +1666,13 @@
:return: double Vect_area_perimeter (const struct line_pnts \*Points)
"""
- border = self.get_points()
+ border = self.points()
return libvect.Vect_line_geodesic_length(border.c_points)
def read(self, line=None, centroid=None, isles=None):
- self.boundary = self.get_points(line)
- self.centroid = self.get_centroid(centroid)
- #self.isles = self.get_isles(isles)
+ self.boundary = self.points(line)
+ self.centroid = self.centroid(centroid)
+ #self.isles = self.isles(isles)
if self.centroid:
libvect.Vect_read_line(self.c_mapinfo, None, self.c_cats,
self.centroid.id)
@@ -1723,7 +1715,7 @@
return ftype, v_id, c_points, c_cats
-def read_next_line(c_mapinfo, table=None, writable=False,
+def read_next_line(c_mapinfo, table=None, writeable=False,
c_points=None, c_cats=None, is2D=True):
"""Return the next geometry feature of a vector map."""
c_points = c_points if c_points else ctypes.pointer(libvect.line_pnts())
@@ -1732,7 +1724,7 @@
c_cats)
return GV_TYPE[ftype]['obj'](v_id=v_id, c_mapinfo=c_mapinfo,
c_points=c_points, c_cats=c_cats,
- table=table, writable=writable, is2D=is2D)
+ table=table, writeable=writeable, is2D=is2D)
def c_read_line(feature_id, c_mapinfo, c_points, c_cats):
@@ -1748,7 +1740,7 @@
raise ValueError('The index must be >0, %r given.' % feature_id)
-def read_line(feature_id, c_mapinfo, table=None, writable=False,
+def read_line(feature_id, c_mapinfo, table=None, writeable=False,
c_points=None, c_cats=None, is2D=True):
"""Return a geometry object given the feature id and the c_mapinfo.
"""
@@ -1759,7 +1751,12 @@
if GV_TYPE[ftype]['obj'] is not None:
return GV_TYPE[ftype]['obj'](v_id=feature_id, c_mapinfo=c_mapinfo,
c_points=c_points, c_cats=c_cats,
- table=table, writable=writable, is2D=is2D)
+ table=table, writeable=writeable, is2D=is2D)
+if __name__ == "__main__":
+ import doctest
+ from grass.pygrass import utils
+ utils.create_test_vector_map(test_vector_name)
+ doctest.testmod()
More information about the grass-commit
mailing list