find.py 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220
  1. # -*- coding: utf-8 -*-
  2. """
  3. Created on Tue Mar 19 11:09:30 2013
  4. @author: pietro
  5. """
  6. import grass.lib.vector as libvect
  7. from grass.pygrass.errors import must_be_open
  8. from grass.pygrass.vector.basic import Ilist, BoxList
  9. from grass.pygrass.vector.geometry import read_line, Isle, Area, Point, Node
  10. # For test purposes
  11. test_vector_name = "find_doctest_map"
  12. class AbstractFinder(object):
  13. def __init__(self, c_mapinfo, table=None, writeable=False):
  14. """AbstractFinder
  15. -----------------
  16. Find geometry feature around a point.
  17. """
  18. self.c_mapinfo = c_mapinfo
  19. self.table = table
  20. self.writeable = writeable
  21. self.vtype = {'point': libvect.GV_POINT, # 1
  22. 'line': libvect.GV_LINE, # 2
  23. 'boundary': libvect.GV_BOUNDARY, # 3
  24. 'centroid': libvect.GV_CENTROID, # 4
  25. 'all': -1}
  26. def is_open(self):
  27. """Check if the vector map is open or not"""
  28. from . import abstract
  29. return abstract.is_open(self.c_mapinfo)
  30. class PointFinder(AbstractFinder):
  31. """PointFinder
  32. Find the geometry features of a vector map that are close to a point.
  33. >>> from grass.pygrass.vector import VectorTopo
  34. >>> zipcodes = VectorTopo('zipcodes', 'PERMANENT')
  35. >>> schools = VectorTopo('schools', 'PERMANENT')
  36. >>> zipcodes.open('r')
  37. >>> schools.open('r')
  38. >>> result = []
  39. >>> for school in schools:
  40. ... zipcode = zipcodes.find['by_point'].area(school)
  41. ... result.append((school.attrs['NAMESHORT'],
  42. ... zipcode.attrs['ZIPCODE']))
  43. ...
  44. >>> result[0]
  45. (u'SWIFT CREEK', u'RALEIGH 27606')
  46. >>> result[1]
  47. (u'BRIARCLIFF', u'CARY 27511')
  48. >>> result[2]
  49. (u'FARMINGTON WOODS', u'CARY 27511')
  50. >>> from grass.pygrass.vector.geometry import Point
  51. >>> pnt = Point(631213.349291, 224684.900084)
  52. >>> school = schools.find['by_point'].geo(pnt, maxdist=300.)
  53. >>> school.attrs['NAMELONG']
  54. u'ADAMS ELEMENTARY'
  55. >>> for school in schools.find['by_point'].geos(pnt, maxdist=1000.):
  56. ... print school.attrs['NAMELONG']
  57. ...
  58. CARY HIGH
  59. EAST CARY MIDDLE SITE
  60. ADAMS ELEMENTARY
  61. >>> schools.close()
  62. >>> zipcodes.close()
  63. """
  64. def __init__(self, c_mapinfo, table=None, writeable=False):
  65. """Find geometry feature around a point.
  66. """
  67. super(PointFinder, self).__init__(c_mapinfo, table, writeable)
  68. # TODO: add the Node class and enable this method
  69. # def node(self, point, maxdist):
  70. # """Find the nearest node. Vect_find_node"""
  71. # i = libvect.Vect_find_node(self.c_mapinfo, point.x, point.y, point.z,
  72. # float(maxdist), int(not point.is2D))
  73. # return geometry.Node(self.c_mapinfo.contents.plus.contents.Node[i])
  74. @must_be_open
  75. def geo(self, point, maxdist, type='all', exclude=0):
  76. """Find the nearest line. Vect_find_line
  77. Valid type are all the keys in find.vtype dictionary
  78. """
  79. feature_id = libvect.Vect_find_line(self.c_mapinfo,
  80. point.x, point.y,
  81. point.z if point.z else 0,
  82. self.vtype[type], float(maxdist),
  83. int(not point.is2D), exclude)
  84. if feature_id:
  85. return read_line(feature_id, self.c_mapinfo,
  86. self.table, self.writeable)
  87. @must_be_open
  88. def geos(self, point, maxdist, type='all', exclude=None):
  89. """Find the nearest line. Vect_find_line_list
  90. Valid type are all the keys in find.vtype dictionary
  91. """
  92. excl = Ilist(exclude) if exclude else Ilist([])
  93. found = Ilist()
  94. if libvect.Vect_find_line_list(self.c_mapinfo,
  95. point.x, point.y,
  96. point.z if point.z else 0,
  97. self.vtype[type], float(maxdist),
  98. int(not point.is2D),
  99. excl.c_ilist, found.c_ilist):
  100. return [read_line(f_id, self.c_mapinfo, self.table, self.writeable)
  101. for f_id in found]
  102. else:
  103. return []
  104. @must_be_open
  105. def area(self, point):
  106. """Find the nearest area. Vect_find_area"""
  107. area_id = libvect.Vect_find_area(self.c_mapinfo, point.x, point.y)
  108. if area_id:
  109. return Area(v_id=area_id, c_mapinfo=self.c_mapinfo,
  110. table=self.table, writeable=self.writeable)
  111. @must_be_open
  112. def island(self, point):
  113. """Find the nearest island. Vect_find_island"""
  114. isle_id = libvect.Vect_find_island(self.c_mapinfo, point.x, point.y)
  115. if isle_id:
  116. return Isle(v_id=isle_id, c_mapinfo=self.c_mapinfo,
  117. table=self.table, writeable=self.writeable)
  118. class BboxFinder(AbstractFinder):
  119. def __init__(self, c_mapinfo, table=None, writeable=False):
  120. super(BboxFinder, self).__init__(c_mapinfo, table, writeable)
  121. @must_be_open
  122. def geos(self, bbox, type='all', bbox_list=False):
  123. """Find the geometry features contained in the bbox.
  124. Vect_select_lines_by_box
  125. Valid type are all the keys in find.vtype dictionary
  126. """
  127. found = BoxList()
  128. if libvect.Vect_select_lines_by_box(self.c_mapinfo, bbox.c_bbox,
  129. self.vtype[type], found.c_boxlist):
  130. if bbox_list:
  131. return found
  132. else:
  133. return (read_line(f_id, self.c_mapinfo, self.table,
  134. self.writeable) for f_id in found.ids)
  135. @must_be_open
  136. def nodes(self, bbox):
  137. """Find the nearest area. Vect_find_area"""
  138. found = Ilist()
  139. if libvect.Vect_select_nodes_by_box(self.c_mapinfo, bbox.c_bbox,
  140. found.c_ilist):
  141. for n_id in found:
  142. yield Node(v_id=n_id, c_mapinfo=self.c_mapinfo,
  143. table=self.table, writeable=self.writeable)
  144. @must_be_open
  145. def areas(self, bbox, boxlist=None, bboxlist_only=False):
  146. """Find the nearest area. Vect_find_area"""
  147. boxlist = boxlist if boxlist else BoxList()
  148. if libvect.Vect_select_areas_by_box(self.c_mapinfo, bbox.c_bbox,
  149. boxlist.c_boxlist):
  150. if bboxlist_only:
  151. return boxlist
  152. else:
  153. return (Area(v_id=a_id, c_mapinfo=self.c_mapinfo,
  154. table=self.table, writeable=self.writeable)
  155. for a_id in boxlist.ids)
  156. return []
  157. @must_be_open
  158. def islands(self, bbox, bbox_list=False):
  159. """Find the nearest island. Vect_find_island"""
  160. found = BoxList()
  161. if libvect.Vect_select_isles_by_box(self.c_mapinfo, bbox.c_bbox,
  162. found.c_boxlist):
  163. if bbox_list:
  164. return found
  165. else:
  166. return (Isle(v_id=i_id, c_mapinfo=self.c_mapinfo,
  167. table=self.table, writeable=self.writeable)
  168. for i_id in found.ids)
  169. return []
  170. class PolygonFinder(AbstractFinder):
  171. def __init__(self, c_mapinfo, table=None, writeable=False):
  172. super(PolygonFinder, self).__init__(c_mapinfo, table, writeable)
  173. def lines(self, polygon, isles=None):
  174. pass
  175. def areas(self, polygon, isles=None):
  176. pass
  177. if __name__ == "__main__":
  178. import doctest
  179. from grass.pygrass import utils
  180. utils.create_test_vector_map(test_vector_name)
  181. doctest.testmod()
  182. """Remove the generated vector map, if exist"""
  183. from grass.pygrass.utils import get_mapset_vector
  184. from grass.script.core import run_command
  185. mset = get_mapset_vector(test_vector_name, mapset='')
  186. if mset:
  187. run_command("g.remove", flags='f', type='vector', name=test_vector_name)