#!/usr/bin/python3 from pyproj import Proj, transform from xml.sax.saxutils import quoteattr import csv, argparse, sys, locale, re parser = argparse.ArgumentParser(description="Convert csv spreadsheets to osm format.") parser.add_argument('infile', help="Input csv file", nargs='?', type=argparse.FileType('r'), default=sys.stdin) parser.add_argument('outfile', help="Output osm file", nargs='?', type=argparse.FileType('w'), default=sys.stdout) parser.add_argument("-x", "--lon", help="Name of the longitude/easting field", metavar="FIELD_NAME") parser.add_argument("-y", "--lat", help="Name of the latitude/northing field", metavar="FIELD_NAME") parser.add_argument("-l", "--locale", help="Locale used to convert coordinate fields to float") parser.add_argument("--proj4", help="Input coordinate system, given as a proj4 string", metavar="PROJ4_STRING") parser.add_argument("--sirgas2000", metavar="ZONE", help="Set input coordinate system to SIRGAS2000 in the given UTM zone") parser.add_argument("--sad69", metavar="ZONE", help="Set input coordinate system to SAD69 in the given UTM zone. Use the special value 'll' for longitude/latitude coordinates.") parser.add_argument('--way', action='store_true', help="Create a way joining all nodes") args = parser.parse_args() proj_out = Proj('+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs +towgs84=0,0,0') if args.locale: locale.setlocale(locale.LC_NUMERIC, args.locale) # Projection conversions according to http://wiki.osgeo.org/wiki/Brazilian_Coordinate_Reference_Systems if args.proj4: proj_in = Proj(args.proj4) elif args.sirgas2000: proj_in = Proj('+proj=utm +zone={} +south +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs'.format(args.sirgas2000)) elif args.sad69 == 'll': proj_in = Proj('+proj=longlat +ellps=aust_SA +towgs84=-67.35,3.88,-38.22,0,0,0,0 +no_defs') elif args.sad69: proj_in = Proj('+proj=utm +zone={} +south +ellps=aust_SA +towgs84=-67.35,3.88,-38.22,0,0,0,0 +units=m +no_defs'.format(args.sad69)) else: proj_in = proj_out parse_dms = re.compile(r'''(?P
[NSWE+-]?)\s?(?P\d+)(?:°|º|\s?deg)\s?(?P \d+)(?:'|’| )\s?(?P [\d,.]+)(?:"|”)?\s?(?P [NSWE]?)''') def parse_coord(c): try: return locale.atof(c) except: m = parse_dms.match(c) if m.group('post') and m.group('pre'): h = None elif m.group('post') in ['S', 'W'] or m.group('pre') in ['-', 'S', 'W']: h = -1 elif m.group('post') in ['N', 'E'] or m.group('pre') in ['+', 'N', 'E']\ or not (m.group('post') and m.group('pre')): h = 1 return h * (locale.atof(m.group('deg')) + locale.atof(m.group('min'))/60 + locale.atof(m.group('sec'))/3600) if args.infile.seekable(): dialect = csv.Sniffer().sniff(args.infile.read(1024)) args.infile.seek(0) else: dialect = csv.excel reader = csv.DictReader(args.infile, dialect=dialect) try: xkey = args.lon or [i for i in ["LONGITUDE", "longitude", "lon", "x", "e"] if i in reader.fieldnames][0] ykey = args.lat or [i for i in ["LATITUDE", "latitude", "lat", "y", "n"] if i in reader.fieldnames][0] except: sys.exit('Error: Coordinate fields not found in the csv file header.') print(' ', file=args.outfile) i=0 for row in reader: i = i-1 try: (lon, lat) = transform(proj_in, proj_out, parse_coord(row.pop(xkey)), parse_coord(row.pop(ykey))) except: print("Skipping node {}: couldn't parse coordinates".format(i), file=sys.stderr) continue print(' ', file=args.outfile)'.format(i,lat, lon), file=args.outfile) for key in row: if row[key]: print(' ', file=args.outfile) if args.way: print(''.format(key, quoteattr(row[key])), file=args.outfile) print(' '.format(i-1), file=args.outfile) for j in range(-1,i-1,-1): print(' ', file=args.outfile) print(''.format(j), file=args.outfile) print('