pygrass_vector.rst 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349
  1. Introduction to Vector classes
  2. ==============================
  3. Details about the GRASS GIS vector architecture can be found in the
  4. `GRASS GIS 8 Programmer's Manual: GRASS Vector Library
  5. <https://grass.osgeo.org/programming8/vectorlib.html>`_.
  6. PyGRASS has two classes for vector maps: :ref:`Vector-label` and
  7. :ref:`VectorTopo-label`. As the names suggest, the Vector class is
  8. for vector maps, while VectorTopo opens vector maps with `GRASS GIS
  9. topology <https://grass.osgeo.org/programming8/vlibTopology.html>`_.
  10. VectorTopo is an extension of the Vector class, so supports all the
  11. Vector class methods, with additions. The classes are part of the
  12. :mod:`~pygrass.vector` module.
  13. .. _Vector-label:
  14. Vector
  15. ------
  16. The :class:`~pygrass.vector.Vector` class is based on the
  17. :class:`~pygrass.vector.abstract.Info` class, which provides methods
  18. for accessing basic information about the vector map: ::
  19. >>> from grass.pygrass.vector import Vector
  20. >>> cens = Vector('census')
  21. >>> cens.is_open()
  22. False
  23. >>> cens.mapset
  24. ''
  25. >>> cens.exist()
  26. True
  27. >>> cens.mapset
  28. 'PERMANENT'
  29. >>> cens.overwrite
  30. False
  31. .. _VectorTopo-label:
  32. VectorTopo
  33. ----------
  34. The :class:`~pygrass.vector.VectorTopo` class allows vector maps to be loaded
  35. along with an accompanying topology. The VectorTopo class interface has all the
  36. same methods as the basic Vector class, but includes many more methods dependent
  37. on the topology rules. Consult each class's documentation for a list of the
  38. methods to compare what each class can do. Using the VectorTopo class is just
  39. like the Vector class: ::
  40. >>> from grass.pygrass.vector import VectorTopo
  41. >>> municip = VectorTopo('boundary_municp_sqlite')
  42. >>> municip.is_open()
  43. False
  44. >>> municip.mapset
  45. ''
  46. >>> municip.exist() # check if exist, and if True set mapset
  47. True
  48. >>> municip.mapset
  49. 'user1'
  50. Working with Vector Maps
  51. ------------------------
  52. As the VectorTopo class is so similar to the Vector class, the following examples
  53. exclusively demonstrate the VectorTopo class.
  54. To begin using a vector map, it must first be opened: ::
  55. >>> from grass.pygrass.vector import VectorTopo
  56. >>> municip = VectorTopo('boundary_municp_sqlite')
  57. >>> municip.open(mode='r')
  58. The ``open()`` method supports a number of option arguments (see the
  59. :class:`~pygrass.vector.abstract.Info` documentation for a complete
  60. list). In particular, the mode argument can take a a value of:
  61. * 'r': read-only mode, vector features are read-only (attribute table
  62. is modifiable since are handle by a database);
  63. * 'w': write-only mode, write a new vector map in case of an old
  64. vector map all the previous features will be removed/overwritten;
  65. * 'rw': read-write mode, add new/update vector features without
  66. removing the existing ones. Add/remove vector layers.
  67. The geometry of a vector map can be read sequentially using the ``next()`` method.
  68. To return to the beginning, use the ``rewind()`` method.
  69. >>> municip.next()
  70. Boundary(v_id=1)
  71. >>> municip.next()
  72. Boundary(v_id=2)
  73. >>> municip.next()
  74. Boundary(v_id=3)
  75. >>> municip.rewind()
  76. >>> municip.next()
  77. Boundary(v_id=1)
  78. If a vector map is opened with the mode ``w`` or ``rw``, then the user can write
  79. new features to the dataset:
  80. Open a new vector map:
  81. >>> new = VectorTopo('newvect')
  82. >>> new.exist()
  83. False
  84. Define the new columns in the attribute table:
  85. >>> cols = [(u'cat', 'INTEGER PRIMARY KEY'),
  86. ... (u'name', 'TEXT')]
  87. Open the vector map in write mode:
  88. >>> new.open('w', tab_name='newvect', tab_cols=cols)
  89. Import the geometry feature class and add two points:
  90. >>> from grass.pygrass.vector.geometry import Point
  91. >>> point0 = Point(636981.336043, 256517.602235)
  92. >>> point1 = Point(637209.083058, 257970.129540)
  93. Write the two points to the map:
  94. >>> new.write(point0, cat=1, attrs=('pub',))
  95. >>> new.write(point1, cat=2, attrs=('resturant',))
  96. Commit the DB changes (attributes):
  97. >>> new.table.conn.commit()
  98. >>> new.table.execute().fetchall()
  99. [(1, u'pub'), (2, u'resturnat')]
  100. Close the vector map:
  101. >>> new.close()
  102. >>> new.exist()
  103. True
  104. Now we can play with the map:
  105. >>> new.open(mode='r')
  106. >>> new.read(1)
  107. Point(636981.336043, 256517.602235)
  108. >>> new.read(2)
  109. Point(637209.083058, 257970.129540)
  110. >>> new.read(1).attrs['name']
  111. u'pub'
  112. >>> new.read(2).attrs['name']
  113. u'resturnat'
  114. >>> new.close()
  115. >>> new.remove()
  116. Note the ``close()`` and ``remove()`` methods above. The ``close()`` method
  117. ensure that the files are properly released by the operating system, and will
  118. also build the topology (if called by the VectorTopo class). Take caution with
  119. the ``remove()`` method; it is used here because this example map was temporary.
  120. Calling this method will completely delete the map and its data from the file
  121. system.
  122. More Features of the VectorTopo Class
  123. -------------------------------------
  124. See the class documentation for a full list of methods, but here are some
  125. examples using VectorTopo methods:
  126. Get the number of primitives:
  127. >>> municip.num_primitive_of('line')
  128. 0
  129. >>> municip.num_primitive_of('centroid')
  130. 3579
  131. >>> municip.num_primitive_of('boundary')
  132. 5128
  133. Get the number of different feature types in the vector map: ::
  134. >>> municip.number_of("areas")
  135. 3579
  136. >>> municip.number_of("islands")
  137. 2629
  138. >>> municip.number_of("holes")
  139. 0
  140. >>> municip.number_of("lines")
  141. 8707
  142. >>> municip.number_of("nodes")
  143. 4178
  144. >>> municip.number_of("pizza") # doctest: +ELLIPSIS +NORMALIZE_WHITESPACE
  145. Traceback (most recent call last):
  146. ...
  147. ValueError: vtype not supported, use one of: 'areas', ..., 'volumes'
  148. Note that the method with raise a ``ValueError`` if a non-supported vtype is
  149. specified.
  150. Accessing Attribute Tables
  151. --------------------------
  152. The GRASS philosophy stipulates that vector map features are independent from
  153. their attributes, and that a vector map's attribute table(s) should not be
  154. loaded unless explicitly specified, in case they are not needed.
  155. Accessing a vector map's table(s) requires finding any links to tables, then
  156. requesting the table from each of the returned links: ::
  157. >>> from grass.pygrass.vector import VectorTopo
  158. >>> municip = VectorTopo('census')
  159. >>> municip.open(mode='r')
  160. >>> dblinks = DBlinks(municip.c_mapinfo)
  161. >>> dblinks
  162. DBlinks([Link(1, census, sqlite)])
  163. >>> link = DBlinks[0]
  164. Link(1, census, sqlite)
  165. >>> table = link.table()
  166. Here, :class:`~pygrass.vector.table.DBlinks` is a class that contains
  167. all the links of a vector map. Each link is also a class
  168. (:class:`~pygrass.vector.table.Link`) that contains a specific link's
  169. parameters. The ``table()`` method of the link class return the linked
  170. table as a table object (:class:`~pygrass.vector.table.Table`).
  171. Geometry Classes
  172. ----------------
  173. The vector package also includes a number of geometry classes,
  174. including :class:`~pygrass.vector.geometry.Area`,
  175. :class:`~pygrass.vector.geometry.Boundary`,
  176. :class:`~pygrass.vector.geometry.Centroid`,
  177. :class:`~pygrass.vector.geometry.Isle`,
  178. :class:`~pygrass.vector.geometry.Line`, and
  179. :class:`~pygrass.vector.geometry.Point` classes. Please consult the
  180. :mod:`~pygrass.vector.geometry` module for a complete list of methods
  181. for these classes, as there are many. Some basic examples are given
  182. below.
  183. Instantiate a Point object that could be 2 or 3D, default parameters are 0: ::
  184. >>> pnt = Point()
  185. >>> pnt.x
  186. 0.0
  187. >>> pnt.y
  188. 0.0
  189. >>> pnt.z
  190. >>> pnt.is2D
  191. True
  192. >>> pnt
  193. Point(0.000000, 0.000000)
  194. >>> pnt.z = 0
  195. >>> pnt.is2D
  196. False
  197. >>> pnt
  198. Point(0.000000, 0.000000, 0.000000)
  199. >>> print(pnt)
  200. POINT(0.000000 0.000000 0.000000)
  201. Create a Boundary and calculate its area: ::
  202. >>> bound = Boundary(points=[(0, 0), (0, 2), (2, 2), (2, 0),
  203. ... (0, 0)])
  204. >>> bound.area()
  205. 4.0
  206. Construct a Line feature and find its bounding box: ::
  207. >>> line = Line([(0, 0), (1, 1), (2, 0), (1, -1)])
  208. >>> line
  209. Line([Point(0.000000, 0.000000),
  210. Point(1.000000, 1.000000),
  211. Point(2.000000, 0.000000),
  212. Point(1.000000, -1.000000)])
  213. >>>bbox = line.bbox()
  214. >>> bbox
  215. Bbox(1.0, -1.0, 2.0, 0.0)
  216. Buffer a Line feature and find the buffer centroid:
  217. >>> line = Line([(0, 0), (0, 2)])
  218. >>> area = line.buffer(10)
  219. >>> area.boundary
  220. Line([Point(-10.000000, 0.000000),...Point(-10.000000, 0.000000)])
  221. >>> area.centroid
  222. Point(0.000000, 0.000000)
  223. More Examples
  224. -------------
  225. Find all areas larger than 10000m2: ::
  226. >>> big = [area for area in municip.viter('areas')
  227. ... if area.alive() and area.area >= 10000]
  228. The PyGRASS vector methods make complex operations rather easy. Notice the
  229. ``viter()`` method: this returns an iterator object of the vector features, so
  230. the user can choose on which vector features to iterate without loading all the
  231. features into memory.
  232. We can then sort the areas by size: ::
  233. >>> from operator import methodcaller as method
  234. >>> big.sort(key = method('area'), reverse = True) # sort the list
  235. >>> for area in big[:3]:
  236. ... print area, area.area()
  237. Area(3102) 697521857.848
  238. Area(2682) 320224369.66
  239. Area(2552) 298356117.948
  240. Or sort for the number of isles that are contained inside: ::
  241. >>> big.sort(key = lambda x: x.isles.__len__(), reverse = True)
  242. >>> for area in big[:3]:
  243. ... print area, area.isles.__len__()
  244. ...
  245. Area(2682) 68
  246. Area(2753) 45
  247. Area(872) 42
  248. Or can list only the areas containing isles: ::
  249. >>> area_with_isles = [area for area in big if area.isles]
  250. >>> area_with_isles # doctest: +ELLIPSIS
  251. [Area(...), ..., Area(...)]
  252. Of course is still possible work only with a specific area, with: ::
  253. >>> from grass.pygrass.vector.geometry import Area
  254. >>> area = Area(v_id=1859, c_mapinfo=municip.c_mapinfo)
  255. >>> area.area()
  256. 39486.05401495844
  257. >>> area.bbox() # north, south, east, west
  258. Bbox(175711.718494, 175393.514494, 460344.093986, 460115.281986)
  259. >>> area.isles
  260. Isles([])
  261. Now, find an area with an island inside... ::
  262. >>> area = Area(v_id=2972, c_mapinfo=municip.c_mapinfo)
  263. >>> area.isles # doctest: +ELLIPSIS
  264. Isles([Isle(1538), Isle(1542), Isle(1543), ..., Isle(2571)])
  265. >>> isle = area.isles[0]
  266. >>> isle.bbox()
  267. Bbox(199947.296494, 199280.969494, 754920.623987, 754351.812986)
  268. .. _Vector library: https://grass.osgeo.org/programming8/vectorlib.html