m.distance.py 5.7 KB

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