m.distance.py 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150
  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. # Requires NumPrt module from http://geosci.uchicago.edu/csc/numptr/
  25. #
  26. #%module
  27. #% label: Finds the distance between two or more points.
  28. #% description: If the projection is latitude-longitude, this distance is measured along the geodesic.
  29. #% keywords: miscellaneous, distance, measure
  30. #%end
  31. #%option
  32. #% key: coord
  33. #% type: string
  34. #% required: yes
  35. #% multiple: yes
  36. #% key_desc: easting,northing
  37. #% description: Comma separated list of coordinate pairs
  38. #%end
  39. #%flag
  40. #% key: i
  41. #% description: Read coordinate pairs from stdin
  42. #% suppress_required: yes
  43. #%end
  44. import os, sys
  45. import grass.script as grass
  46. from grass.lib.gis import *
  47. def main():
  48. G_gisinit('m.distance')
  49. # calc distance
  50. proj_type = G_begin_distance_calculations()
  51. # returns 0 if projection has no metrix (ie. imagery)
  52. # returns 1 if projection is planimetric
  53. # returns 2 if projection is latitude-longitude
  54. # parser always creates at least an empty variable, and sys.argv is
  55. # toast, so no way to check if option was given. So it hangs if
  56. # --q was the only option given and there is no data from stdin.
  57. coords = []
  58. if flags['i']:
  59. # read line by line from stdin
  60. while True:
  61. line = sys.stdin.readline().strip()
  62. if not line: # EOF
  63. break
  64. else:
  65. coords.append(line.split(','))
  66. else:
  67. # read from coord= command line option
  68. p = None
  69. for c in options['coord'].split(','):
  70. if not p:
  71. p = [c]
  72. else:
  73. p.append(c)
  74. coords.append(p)
  75. p = None
  76. if len(coords) < 2:
  77. grass.fatal("A minimum of two input coordinate pairs are needed")
  78. # init variables
  79. overall_distance = 0.0
  80. coord_array = c_double * len(coords)
  81. x = coord_array()
  82. y = coord_array()
  83. if proj_type == 2:
  84. # lat/lon scan for DDD:MM:SS.SSSS
  85. easting = c_double()
  86. northing = c_double()
  87. G_scan_easting(coords[0][0], byref(easting), PROJECTION_LL)
  88. G_scan_northing(coords[0][1], byref(northing), PROJECTION_LL)
  89. x[0] = float(easting.value)
  90. y[0] = float(northing.value)
  91. else:
  92. # plain coordinates
  93. x[0] = float(coords[0][0])
  94. y[0] = float(coords[0][1])
  95. for i in range(1, len(coords)):
  96. if proj_type == 2:
  97. easting = c_double()
  98. northing = c_double()
  99. G_scan_easting(coords[i][0], byref(easting), PROJECTION_LL)
  100. G_scan_northing(coords[i][1], byref(northing), PROJECTION_LL)
  101. x[i] = float(easting.value)
  102. y[i] = float(northing.value)
  103. else:
  104. x[i] = float(coords[i][0])
  105. y[i] = float(coords[i][1])
  106. segment_distance = G_distance(x[i-1], y[i-1], x[i], y[i])
  107. overall_distance += segment_distance
  108. print "segment %d distance is %.2f meters" % (i, segment_distance)
  109. # add to the area array
  110. print "\ntotal distance is %.2f meters\n" % overall_distance
  111. # calc area
  112. if len(coords) < 3:
  113. return 0
  114. G_begin_polygon_area_calculations()
  115. # returns 0 if the projection is not measurable (ie. imagery or xy)
  116. # returns 1 if the projection is planimetric (ie. UTM or SP)
  117. # returns 2 if the projection is non-planimetric (ie. latitude-longitude)
  118. # do not need to close polygon (but it doesn't hurt if you do)
  119. area = G_area_of_polygon(x, y, len(coords))
  120. print "area is %.2f square meters\n" % area
  121. # we don't need this, but just to have a look
  122. if proj_type == 1:
  123. G_database_units_to_meters_factor()
  124. grass.message("Location units are %s" % G_database_unit_name(True).lower())
  125. return 0
  126. if __name__ == "__main__":
  127. options, flags = grass.parser()
  128. sys.exit(main())