#!/usr/bin/env python ############################################################################ # # MODULE: m.distance # # AUTHOR(S): Hamish Bowman, Dunedin, New Zealand # Updated for Ctypes by Martin Landa # # 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 os, sys import grass.script as grass 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: grass.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() grass.message("Location units are %s" % G_database_unit_name(True).lower()) return 0 if __name__ == "__main__": options, flags = grass.parser() sys.exit(main())