m.distance.py 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  1. #!/usr/bin/python
  2. ############################################################################
  3. #
  4. # MODULE: m.distance
  5. #
  6. # AUTHOR(S): Hamish Bowman, Dunedin, New Zealand
  7. #
  8. # PURPOSE: Find distance between two points
  9. # If the projection is latitude-longitude, this distance
  10. # is measured along the geodesic.
  11. # Demonstrates GRASS SWIG-Python interface
  12. #
  13. # COPYRIGHT: (c) 2008 Hamish Bowman, and The GRASS Development Team
  14. #
  15. # This program is free software under the GNU General Public
  16. # License (>=v2). Read the file COPYING that comes with GRASS
  17. # for details.
  18. #
  19. ############################################################################
  20. #
  21. # Requires GRASS SWIG-Python interface
  22. # Requires Numeric module (NumPy) from http://numpy.scipy.org/
  23. # Requires NumPrt module from http://geosci.uchicago.edu/csc/numptr/
  24. #
  25. #%Module
  26. #% label: Finds the distance between two or more points.
  27. #% description: If the projection is latitude-longitude, this distance is measured along the geodesic.
  28. #% keywords: miscellaneous, distance, measure
  29. #%End
  30. #%Option
  31. #% key: coord
  32. #% type: string
  33. #% required: no
  34. #% multiple: yes
  35. #% key_desc: x,y
  36. #% description: Comma separated list of coordinate pairs
  37. #%End
  38. #%Flag
  39. #% key: i
  40. #% description: Read coordinate pairs from stdin
  41. #%End
  42. import os, sys
  43. if not os.environ.has_key("GISBASE"):
  44. print "You must be in GRASS GIS to run this program."
  45. sys.exit(1)
  46. def main():
  47. #### add your code here ####
  48. # run this before starting python to append module search path:
  49. # export PYTHONPATH=$PYTHONPATH:/usr/local/grass-7.0.svn/etc/python
  50. # check with "import sys; sys.path"
  51. # or:
  52. sys.path.append("/usr/local/grass-7.0.svn/etc/python")
  53. from grass.lib import grass as g7lib
  54. # for passing pointers
  55. import Numeric
  56. import NumPtr
  57. g7lib.G_gisinit('m.distance')
  58. # returns 0 on success
  59. ### calc distance ###
  60. proj_type = g7lib.G_begin_distance_calculations()
  61. # returns 0 if projection has no metrix (ie. imagery)
  62. # returns 1 if projection is planimetric
  63. # returns 2 if projection is latitude-longitude
  64. # parser always creates at least an empty variable, and sys.argv is
  65. # toast, so no way to check if option was given. So it hangs if
  66. # --q was the only option given and there is no data from stdin.
  67. coord_ans = os.getenv("GIS_OPT_COORD")
  68. stdin_flag = bool(int(os.getenv("GIS_FLAG_I")))
  69. if stdin_flag is True:
  70. coords = []
  71. # read line by line from stdin
  72. while 1:
  73. line = sys.stdin.readline().strip()
  74. if not line: # EOF
  75. break
  76. else:
  77. coords += line.split(',')
  78. else:
  79. # read from coord= command line option
  80. coords = coord_ans.split(',')
  81. if len(coords) < 4:
  82. print "A minimum of two input coordinate pairs are needed"
  83. return
  84. # init variables
  85. overall_distance = 0.0
  86. if proj_type == 2:
  87. # lat/lon scan for DDD:MM:SS.SSSS
  88. easting = Numeric.array(0., Numeric.Float64)
  89. eastPtr = NumPtr.getpointer(easting)
  90. northing = Numeric.array(0., Numeric.Float64)
  91. northPtr = NumPtr.getpointer(northing)
  92. # TODO: for clarity, figure out how to replace "3" with
  93. # the defined LOCATION_LL constant from gis.i
  94. g7lib.G_scan_easting(coords[0], eastPtr, 3)
  95. g7lib.G_scan_northing(coords[1], northPtr, 3)
  96. x1 = float(easting)
  97. y1 = float(northing)
  98. else:
  99. # plain old coordinates
  100. x1 = float(coords[0])
  101. y1 = float(coords[1])
  102. x = [x1]
  103. y = [y1]
  104. for i in range(1, (len(coords) / 2)):
  105. if proj_type == 2:
  106. g7lib.G_scan_easting (coords[ i*2 + 0 ], eastPtr, 3)
  107. g7lib.G_scan_northing(coords[ i*2 + 1 ], northPtr, 3)
  108. x2 = float(easting)
  109. y2 = float(northing)
  110. else:
  111. x2 = float(coords[ i*2 + 0 ])
  112. y2 = float(coords[ i*2 + 1 ])
  113. segment_distance = g7lib.G_distance(x1, y1, x2, y2)
  114. overall_distance += segment_distance
  115. print "segment %d distance is %.2f meters" % (i, segment_distance)
  116. # add to the area array
  117. # setup for the next loop
  118. x1 = x2
  119. y1 = y2
  120. x += [x2]
  121. y += [y2]
  122. print
  123. print " total distance is %.2f meters" % overall_distance
  124. print
  125. ### calc area ###
  126. if len(coords) < 6:
  127. return
  128. g7lib.G_begin_polygon_area_calculations()
  129. # returns 0 if the projection is not measurable (ie. imagery or xy)
  130. # returns 1 if the projection is planimetric (ie. UTM or SP)
  131. # returns 2 if the projection is non-planimetric (ie. latitude-longitude)
  132. # do not need to close polygon (but it doesn't hurt if you do)
  133. npoints = len(x)
  134. # unset variables:
  135. #del [Xs, Xptr, Ys, Yptr]
  136. # or
  137. #Xs = Xptr = Ys = Yptr = None
  138. Xs = Numeric.array(x, Numeric.Float64)
  139. Xptr = NumPtr.getpointer(Xs)
  140. Ys = Numeric.array(y, Numeric.Float64)
  141. Yptr = NumPtr.getpointer(Ys)
  142. area = g7lib.G_area_of_polygon(Xptr, Yptr, npoints)
  143. print "AREA: %10.2f square meters" % area
  144. print
  145. # we don't need this, but just to have a look
  146. if False:
  147. if proj_type == 1:
  148. g7lib.G_database_units_to_meters_factor()
  149. # 1.0
  150. print "Location units are", g7lib.G_database_unit_name(True)
  151. #### end of your code ####
  152. return
  153. if __name__ == "__main__":
  154. if ( len(sys.argv) <= 1 or sys.argv[1] != "@ARGS_PARSED@" ):
  155. os.execvp("g.parser", [sys.argv[0]] + sys.argv)
  156. else:
  157. main();