m.distance.py 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  1. #!/usr/bin/env python
  2. ############################################################################
  3. #
  4. # MODULE: m.distance
  5. #
  6. # AUTHOR(S): Hamish Bowman, Dunedin, New Zealand
  7. # Updated for Ctypes by Martin Landa <landa.martin gmail.com>
  8. #
  9. # PURPOSE: Find distance between two points
  10. # If the projection is latitude-longitude, this distance
  11. # is measured along the geodesic.
  12. # Demonstrates GRASS Python Ctypes interface
  13. #
  14. # COPYRIGHT: (c) 2008-2011 Hamish Bowman, and the GRASS Development Team
  15. #
  16. # This program is free software under the GNU General
  17. # Public License (>=v2). Read the file COPYING that
  18. # comes with GRASS for details.
  19. #
  20. ############################################################################
  21. #
  22. # Requires GRASS Python Ctypes interface
  23. # Requires Numeric module (NumPy) from http://numpy.scipy.org/
  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: yes
  34. #% multiple: yes
  35. #% key_desc: easting,northing
  36. #% description: Comma separated list of coordinate pairs
  37. #%end
  38. #%flag
  39. #% key: i
  40. #% description: Read coordinate pairs from stdin
  41. #% suppress_required: yes
  42. #%end
  43. import os, sys
  44. import grass.script as grass
  45. from grass.lib.gis import *
  46. def main():
  47. G_gisinit('m.distance')
  48. # calc distance
  49. proj_type = G_begin_distance_calculations()
  50. # returns 0 if projection has no metrix (ie. imagery)
  51. # returns 1 if projection is planimetric
  52. # returns 2 if projection is latitude-longitude
  53. # parser always creates at least an empty variable, and sys.argv is
  54. # toast, so no way to check if option was given. So it hangs if
  55. # --q was the only option given and there is no data from stdin.
  56. coords = []
  57. if flags['i']:
  58. # read line by line from stdin
  59. while True:
  60. line = sys.stdin.readline().strip()
  61. if not line: # EOF
  62. break
  63. else:
  64. coords.append(line.split(','))
  65. else:
  66. # read from coord= command line option
  67. p = None
  68. for c in options['coord'].split(','):
  69. if not p:
  70. p = [c]
  71. else:
  72. p.append(c)
  73. coords.append(p)
  74. p = None
  75. if len(coords) < 2:
  76. grass.fatal("A minimum of two input coordinate pairs are needed")
  77. # init variables
  78. overall_distance = 0.0
  79. coord_array = c_double * len(coords)
  80. x = coord_array()
  81. y = coord_array()
  82. if proj_type == 2:
  83. # lat/lon scan for DDD:MM:SS.SSSS
  84. easting = c_double()
  85. northing = c_double()
  86. G_scan_easting(coords[0][0], byref(easting), PROJECTION_LL)
  87. G_scan_northing(coords[0][1], byref(northing), PROJECTION_LL)
  88. x[0] = float(easting.value)
  89. y[0] = float(northing.value)
  90. else:
  91. # plain coordinates
  92. x[0] = float(coords[0][0])
  93. y[0] = float(coords[0][1])
  94. for i in range(1, len(coords)):
  95. if proj_type == 2:
  96. easting = c_double()
  97. northing = c_double()
  98. G_scan_easting(coords[i][0], byref(easting), PROJECTION_LL)
  99. G_scan_northing(coords[i][1], byref(northing), PROJECTION_LL)
  100. x[i] = float(easting.value)
  101. y[i] = float(northing.value)
  102. else:
  103. x[i] = float(coords[i][0])
  104. y[i] = float(coords[i][1])
  105. segment_distance = G_distance(x[i-1], y[i-1], x[i], y[i])
  106. overall_distance += segment_distance
  107. print "segment %d distance is %.2f meters" % (i, segment_distance)
  108. # add to the area array
  109. print "\ntotal distance is %.2f meters\n" % overall_distance
  110. # calc area
  111. if len(coords) < 3:
  112. return 0
  113. G_begin_polygon_area_calculations()
  114. # returns 0 if the projection is not measurable (ie. imagery or xy)
  115. # returns 1 if the projection is planimetric (ie. UTM or SP)
  116. # returns 2 if the projection is non-planimetric (ie. latitude-longitude)
  117. # do not need to close polygon (but it doesn't hurt if you do)
  118. area = G_area_of_polygon(x, y, len(coords))
  119. print "area is %.2f square meters\n" % area
  120. # we don't need this, but just to have a look
  121. if proj_type == 1:
  122. G_database_units_to_meters_factor()
  123. grass.message("Location units are %s" % G_database_unit_name(True).lower())
  124. return 0
  125. if __name__ == "__main__":
  126. options, flags = grass.parser()
  127. sys.exit(main())