m.distance.py 4.6 KB

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