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