[GRASS-SVN] r37975 - grass/trunk/scripts/v.out.gps

svn_grass at osgeo.org svn_grass at osgeo.org
Fri Jun 19 16:37:42 EDT 2009


Author: glynn
Date: 2009-06-19 16:37:41 -0400 (Fri, 19 Jun 2009)
New Revision: 37975

Added:
   grass/trunk/scripts/v.out.gps/v.out.gps.py
Log:
Convert v.out.gps to Python (untested)


Added: grass/trunk/scripts/v.out.gps/v.out.gps.py
===================================================================
--- grass/trunk/scripts/v.out.gps/v.out.gps.py	                        (rev 0)
+++ grass/trunk/scripts/v.out.gps/v.out.gps.py	2009-06-19 20:37:41 UTC (rev 37975)
@@ -0,0 +1,334 @@
+#!/usr/bin/env python
+#
+############################################################################
+#
+# MODULE:	v.out.gps
+#
+# PURPOSE:	Exports a GRASS vector map to a GPS receiver
+#		or data file using GpsBabel
+#
+# COPYRIGHT:	(c) 2008-2009 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.
+#
+# AUTHOR:	Hamish Bowman, Dunedin, New Zealand
+#		Converted to Python by Glynn Clements
+#
+#############################################################################
+#
+# REQUIREMENTS:
+#      -  GpsBabel from 	http://gpsbabel.sourceforge.net
+#      -  cs2cs from PROJ.4 (for m.proj)	http://proj.osgeo.org
+#
+#      - report supported GpsBabel formats:
+#	 gpsbabel -^2 | tr '\t' ';' | sort -t';' -k3
+#
+#############################################################################
+#
+# How to do it
+#   http://www.gdal.org/ogr/drv_gpx.html
+#   gpsbabel [options] -i INTYPE -f INFILE -o OUTTYPE -F OUTFILE
+#
+#############################################################################
+
+#%Module
+#%  description: Exports a vector map to a GPS receiver or file format supported by GpsBabel.
+#%  keywords: vector, export, GPS
+#%End
+#%flag
+#%  key: w
+#%  description: Export as waypoints
+#%end
+#%flag
+#%  key: r
+#%  description: Export as routes
+#%end
+#%flag
+#%  key: t
+#%  description: Export as tracks
+#%end
+############ TODO:
+##%flag
+##%  key: z
+##%  description: Export altitude from 3D vector's z-coordinate
+##%end
+############
+#%option
+#% key: input
+#% type: string
+#% description: Name of input vector map
+#% gisprompt: old,vector,vector
+#% required: yes
+#%end
+#%option
+#% key: type
+#% type: string
+#% description: Feature type(s)
+#% options: point,centroid,line,boundary
+#% multiple: yes
+#%end
+#%option
+#% key: output
+#% type: string
+#% description: Name for output file or GPS device
+#% gisprompt: new_file,file,output
+#% key_desc: name
+#% required: yes
+#%end
+#%option
+#% key: format
+#% type: string
+#% description: GpsBabel supported output format
+#% answer: gpx
+#%end
+#%option
+#% key: layer
+#% type: integer
+#% label: Layer number
+#% description: A single vector map can be connected to multiple database tables. This number determines which table to use.
+#% answer: 1
+#% required : no
+#% guisection: Subset
+#%end
+#%option
+#% key: where
+#% type: string
+#% label: WHERE conditions of SQL statement without 'where' keyword
+#% description: Example: income < 1000 and inhab >= 10000
+#% required : no
+#% guisection: Subset
+#%end
+
+import sys
+import os
+import atexit
+import string
+import grass.script as grass
+
+def cleanup():
+    grass.verbose("Cleaning up ...")
+    if tmp:
+	grass.try_remove(tmp)
+    if tmp_proj:
+	grass.try_remove(tmp_proj)
+    if tmp_gpx:
+	grass.try_remove(tmp_gpx)
+
+    # only try to remove map if it exists to avoid ugly warnings
+    if tmp_vogb:
+	if grass.find_file(tmp_vogb, element = 'vector')['name']:
+	    grass.run_command('g.remove', vect = tmp_vogb, quiet = True)
+    if tmp_extr:
+	if grass.find_file(tmp_extr, element = 'vector')['name']:
+	    grass.run_command('g.remove', vect = tmp_vogb, quiet = True)
+
+tmp = None
+tmp_proj = None
+tmp_gpx = None
+tmp_extr = None
+tmp_vogb = None
+
+def main():
+    global tmp, tmp_proj, tmp_gpx, tmp_extr, tmp_vogb
+
+    format = options['format']
+    input = options['input']
+    layer = options['layer']
+    output = options['output']
+    type = options['type']
+    where = options['where']
+    wpt = flags['w']
+    rte = flags['r']
+    trk = flags['t']
+
+    nflags = len(filter(None, [wpt, rte, trk]))
+    if nflags > 1:
+	grass.fatal("One feature at a time please.")
+    if nflags < 1:
+	grass.fatal("No features requested for export.")
+
+    # set some reasonable defaults
+    if not type:
+	if wpt:
+	    type = 'point'
+	else:
+	    type = 'line'
+
+    #### check for gpsbabel
+    ### FIXME: may need --help or similar?
+    if not grass.find_program("gpsbabel"):
+	grass.fatal("The gpsbabel program was not found, please install it first.\n" +
+		    "http://gpsbabel.sourceforge.net")
+
+    #### check for cs2cs
+    if not grass.find_program("cs2cs"):
+	grass.fatal("The cs2cs program was not found, please install it first.\n" +
+		    "http://proj.osgeo.org")
+
+    # check if we will overwrite data
+    if os.path.exists(output) and not grass.overwrite():
+	grass.fatal("Output file already exists.")
+
+    #### set temporary files
+    tmp = grass.tempfile()
+
+    # SQL extract if needed
+    if where:
+	grass.verbose("Extracting data ...")
+	tmp_extr = "tmp_vogb_extr_%d" % os.getpid()
+	ret = grass.run_command('v.extract', input = "$GIS_OPT_INPUT",
+				output = tmp_extr, type = type, layer = layer,
+				where = where, quiet = True)
+	if ret != 0:
+	    grass.fatal("Error executing SQL query")
+
+	kv = grass.vector_info_topo(tmp_extr)
+	if kv['primitives'] == 0:
+	    grass.fatal("SQL query returned an empty map (no %s features?)" % type)
+
+	inmap = tmp_extr
+    else:
+	#   g.copy "$GIS_OPT_INPUT,tmp_vogb_extr_$$"   # to get a copy of DB into local mapset
+	#   INMAP="tmp_vogb_extr_$$"
+	inmap = input
+
+    #### set up projection info
+    # TODO: check if we are already in ll/WGS84.  If so skip m.proj step.
+
+    # TODO: multi layer will probably fail badly due to sed 's/^ 1   /'
+    #   output as old GRASS 4 vector ascii and fight with dig_ascii/?
+    #   Change to s/^ \([0-9]   .*\)    /# \1/' ??? mmph.
+
+    # reproject to lat/lon WGS84
+    grass.verbose("Reprojecting data ...")
+
+    re1 = re.compile(r'^\([PLBCFKA]\)')
+    re2 = re.compile(r'^ 1     ')
+
+    re3 = re.compile(r'\t\([-\.0-9]*\) .*')
+    re4 = re.compile(r'^\([-\.0-9]\)')
+    re5 = re.compile(r'^#')
+
+    tmp_proj = tmp + ".proj"
+    tf = open(tmp_proj, 'w')
+    p1 = grass.pipe_command('v.out.ascii', input = inmap, format = 'standard')
+    p2 = grass.feed_command('m.proj', flags = 'od', quiet = True, stdout = tf)
+    tf.close()
+
+    lineno = 0
+    for line in p1.stdout:
+	lineno += 1
+	if lineno < 11:
+	    continue
+	line = re1.sub(r'#\1', line)
+	line = re2.sub(r'# 1  ', line)
+	p2.stdin.write(line)
+
+    p2.stdin.close()
+    p1.wait()
+    p2.wait()
+
+    if p1.returncode != 0 or p2.returncode != 0:
+	grass.fatal("Error reprojecting data")
+
+    tmp_vogb = "tmp_vogb_epsg4326_%d" % os.getpid()
+    p3 = grass.feed_command('v.in.ascii', out = tmp_vogb, format = 'standard', flags = 'n', quiet = True)
+    tf = open(tmp_proj, 'r')
+
+    for line in tf:
+	line = re3.sub(r' \1', line)
+	line = re4.sub(r' \1', line)
+	line = re5.sub('', line)
+	p3.stdin.write(line)
+
+    p3.stdin.close()
+    tf.close()
+    p3.wait()
+
+    if p3.returncode != 0:
+	grass.fatal("Error reprojecting data")
+
+    # don't v.db.connect directly as source table will be removed with
+    # temporary map in that case. So we make a temp copy of it to work with.
+    kv = vector_db(inmap)
+    if layer in kv:
+	db_params = kv[layer]
+
+	db_table = db_params['table']
+	db_key = db_params['key']
+	db_database = db_params['database']
+	db_driver = db_params['driver']
+
+	ret = grass.run_command('db.copy',
+				from_driver = db_driver,
+				from_database = db_database,
+				from_table = db_table,
+				to_table = tmp_vogb)
+	if ret != 0:
+	    grass.fatal("Error copying temporary DB")
+
+	ret = grass.run_command('v.db.connect', map = tmp_vogb, table = tmp_vogb, quiet = True)
+	if ret != 0:
+	    grass.fatal("Error reconnecting temporary DB")
+
+    # export as GPX using v.out.ogr
+    if trk:
+	linetype = "FORCE_GPX_TRACK=YES"
+    elif rte:
+	linetype = "FORCE_GPX_TRACK=YES"
+    else:
+	linetype = None
+
+    # BUG: cat is being reported as evelation and attribute output is skipped.
+    #   (v.out.ogr DB reading or ->OGR GPX driver bug ?)
+    #   v.out.ogr -> shapefile -> GPX works, but we try to avoid that as it's
+    #     lossy. Also that would allow ogr2ogr -a_srs $IN_PROJ -t_srs EPSG:4326
+    #     so skip m.proj pains.. if that is done ogr2ogr -s_srs MUST HAVE +wktext
+    #     with PROJ.4 terms or else the +nadgrids will be ignored! best to feed
+    #     it  IN_PROJ="`g.proj -jf` +wktext"  in that case.
+
+    grass.verbose("Exporting data ...")
+
+    tmp_gpx = tmp + ".gpx"
+    ret = grass.run_command('v.out.ogr', input = tmp_vogb, dsn = tmp_gpx,
+			    type = type, format = 'GPX', lco = linetype,
+			    dsco = "GPX_USE_EXTENSIONS=YES", quiet = True)
+    if ret != 0:
+	grass.fatal("Error exporting data")
+
+    if format == 'gpx':
+	# short circuit, we have what we came for.
+	grass.try_remove(output)
+	os.rename(tmp_gpx, output)
+	grass.verbose("Fast exit.")
+	sys.exit()
+
+    # run gpsbabel
+    if wpt:
+	gtype = '-w'
+    elif trk:
+	gtype = '-t'
+    elif rte:
+	gtype = '-r'
+    else:
+	gtype = ''
+
+    grass.verbose("Running GpsBabel ...")
+
+    ret = grass.call(['gpsbabel',
+		      gtype,
+		      '-i', 'gpx',
+		      '-f', tmp + '.gpx',
+		      '-o', format,
+		      '-F', output])
+
+    if ret != 0:
+	grass.fatal("Error running GpsBabel")
+
+    grass.verbose("Done.")
+
+if __name__ == "__main__":
+    options, flags = grass.parser()
+    atexit.register(cleanup)
+    main()


Property changes on: grass/trunk/scripts/v.out.gps/v.out.gps.py
___________________________________________________________________
Name: svn:executable
   + *



More information about the grass-commit mailing list