--- /dev/null
+#!/usr/bin/env python
+
+"""
+We take a Well-Known Text string and a KML file as parameters. The WKT
+string is converted into a polygon (hopefully), and the KML file is
+parsed for a linestring, which defines a path. We then drag the
+polygon along the linestring, and return the resulting polygon as KML.
+"""
+
+import pgdb
+import os
+import site
+import sys
+from optparse import OptionParser
+
+# Basically, add '../src' and '../lib/Shapely' to our path.
+# Needed for the imports that follow.
+site.addsitedir(os.path.dirname(os.path.abspath(sys.argv[0])) + '/../src')
+site.addsitedir(os.path.dirname(os.path.abspath(sys.argv[0])) + '/../lib/Shapely')
+
+import Configuration.Defaults
+import ExitCodes
+import Geometry
+import KML
+
+usage = '%prog [options] <well-known text> <kml filename>'
+
+# -h (help) Conflicts with -h HOSTNAME
+parser = OptionParser(usage=usage, add_help_option = False)
+
+# Use this module's docstring as the description.
+parser.description = __doc__.strip()
+
+parser.add_option('-h',
+ '--host',
+ help='The hostname/address where the database is located.',
+ default=Configuration.Defaults.DATABASE_HOST)
+
+parser.add_option('-d',
+ '--database',
+ help='The database in which the population data are stored.',
+ default=Configuration.Defaults.DATABASE_NAME)
+
+parser.add_option('-U',
+ '--username',
+ help='The username who has access to the database.',
+ default=Configuration.Defaults.DATABASE_USERNAME)
+
+parser.add_option('-o',
+ '--outfile',
+ help='Optional output file path. Defaults to stdout.')
+
+parser.add_option('-n',
+ '--name',
+ help='Name to give the geometry object in the KML document.',
+ default='WKT Object')
+
+parser.add_option('-s',
+ '--srid',
+ type="int",
+ help="SRID of the input geometry. Defaults to %s." % Configuration.Defaults.SRID,
+ default=Configuration.Defaults.SRID)
+
+(options, args) = parser.parse_args()
+
+if len(args) < 2:
+ print """
+ERROR: You must supply both a Well-Known Text string, and a KML file
+ containing a linestring.
+"""
+ parser.print_help()
+ print '' # Print a newline
+ raise SystemExit(ExitCodes.NOT_ENOUGH_ARGS)
+
+
+wkt_string = args[0]
+kml_filename = args[1]
+
+f = open(kml_filename, 'r')
+kml = f.read()
+f.close()
+
+coords = KML.LineString.tuples_from_kml(kml)
+p = Geometry.Polygon.from_wkt(wkt_string)
+
+death_tube = None
+
+for i in range(len(coords) - 1):
+ # For each coordinate (except the last), we want to:
+ # a) Translate our polygon to the coordinate.
+ # b) Drag the polygon to the next coordinate.
+ this_coord = Geometry.TwoVector(coords[i][0], coords[i][1])
+ next_coord = Geometry.TwoVector(coords[i+1][0], coords[i+1][1])
+ drag_vector = (next_coord - this_coord)
+ tp = p.translate(this_coord)
+
+ if (death_tube == None):
+ death_tube = tp.drag(drag_vector)
+ else:
+ death_tube = death_tube.union(tp.drag(drag_vector))
+
+
+conn = pgdb.connect(host=options.host,
+ database=options.database,
+ user=options.username)
+
+
+# We'll use this cursor for all of our queries.
+cursor = conn.cursor()
+
+
+# We use one query that basically just imports the WKT string and
+# immediately exports it as KML. The geometry must have an SRID when
+# ST_AsKml is called, so we provide one to ST_GeomFromText.
+kml_query = "SELECT ST_AsKml(ST_GeomFromText('%s', %s))" % (death_tube.wkt(), options.srid)
+
+cursor.execute(kml_query)
+rows = cursor.fetchall()
+kml_representation = rows[0][0]
+conn.close()
+
+
+doc = KML.Document()
+
+# Create a semi-transparent blue polygon style, and add it to the
+# document.
+hex_value = "b0ff0000"
+s = KML.Style(initial_id=('default'))
+poly_style = KML.PolyStyle()
+color = KML.Color(hex_value)
+poly_style.children.append(color)
+s.children.append(poly_style)
+doc.styles.append(s)
+
+# We're only going to have one placemark -- the object defined by our
+# input WKT.
+placemark = KML.Placemark()
+name = KML.Name(options.name)
+placemark.children.append(name)
+
+# This applies the red polygon style defined earlier to our placemark.
+styleurl = KML.StyleUrl('default')
+placemark.children.append(styleurl)
+
+# The database query is going to give us raw KML. For example, if our
+# input WKT represents a polygon, the output of ST_AsKml will contain
+# <Polygon>...</Polygon> and everything therein.
+rawkml = KML.RawText(kml_representation)
+placemark.children.append(rawkml)
+doc.children.append(placemark)
+
+# Default the output file to sys.stdout. If we were passed an outfile
+# as an argument, use that instead.
+output_file = sys.stdout
+if (options.outfile != None):
+ output_file = open(options.outfile, 'w')
+
+# Write the KML and get out of here.
+output_file.write(doc.to_kml())
+output_file.close()