]> gitweb.michael.orlitzky.com - dead/census-tools.git/blob - bin/drag_wkt_along_kml_path
Added the first draft of drag_wkt_along_kml_path, most of which is basically cut...
[dead/census-tools.git] / bin / drag_wkt_along_kml_path
1 #!/usr/bin/env python
2
3 """
4 We take a Well-Known Text string and a KML file as parameters. The WKT
5 string is converted into a polygon (hopefully), and the KML file is
6 parsed for a linestring, which defines a path. We then drag the
7 polygon along the linestring, and return the resulting polygon as KML.
8 """
9
10 import pgdb
11 import os
12 import site
13 import sys
14 from optparse import OptionParser
15
16 # Basically, add '../src' and '../lib/Shapely' to our path.
17 # Needed for the imports that follow.
18 site.addsitedir(os.path.dirname(os.path.abspath(sys.argv[0])) + '/../src')
19 site.addsitedir(os.path.dirname(os.path.abspath(sys.argv[0])) + '/../lib/Shapely')
20
21 import Configuration.Defaults
22 import ExitCodes
23 import Geometry
24 import KML
25
26 usage = '%prog [options] <well-known text> <kml filename>'
27
28 # -h (help) Conflicts with -h HOSTNAME
29 parser = OptionParser(usage=usage, add_help_option = False)
30
31 # Use this module's docstring as the description.
32 parser.description = __doc__.strip()
33
34 parser.add_option('-h',
35 '--host',
36 help='The hostname/address where the database is located.',
37 default=Configuration.Defaults.DATABASE_HOST)
38
39 parser.add_option('-d',
40 '--database',
41 help='The database in which the population data are stored.',
42 default=Configuration.Defaults.DATABASE_NAME)
43
44 parser.add_option('-U',
45 '--username',
46 help='The username who has access to the database.',
47 default=Configuration.Defaults.DATABASE_USERNAME)
48
49 parser.add_option('-o',
50 '--outfile',
51 help='Optional output file path. Defaults to stdout.')
52
53 parser.add_option('-n',
54 '--name',
55 help='Name to give the geometry object in the KML document.',
56 default='WKT Object')
57
58 parser.add_option('-s',
59 '--srid',
60 type="int",
61 help="SRID of the input geometry. Defaults to %s." % Configuration.Defaults.SRID,
62 default=Configuration.Defaults.SRID)
63
64 (options, args) = parser.parse_args()
65
66 if len(args) < 2:
67 print """
68 ERROR: You must supply both a Well-Known Text string, and a KML file
69 containing a linestring.
70 """
71 parser.print_help()
72 print '' # Print a newline
73 raise SystemExit(ExitCodes.NOT_ENOUGH_ARGS)
74
75
76 wkt_string = args[0]
77 kml_filename = args[1]
78
79 f = open(kml_filename, 'r')
80 kml = f.read()
81 f.close()
82
83 coords = KML.LineString.tuples_from_kml(kml)
84 p = Geometry.Polygon.from_wkt(wkt_string)
85
86 death_tube = None
87
88 for i in range(len(coords) - 1):
89 # For each coordinate (except the last), we want to:
90 # a) Translate our polygon to the coordinate.
91 # b) Drag the polygon to the next coordinate.
92 this_coord = Geometry.TwoVector(coords[i][0], coords[i][1])
93 next_coord = Geometry.TwoVector(coords[i+1][0], coords[i+1][1])
94 drag_vector = (next_coord - this_coord)
95 tp = p.translate(this_coord)
96
97 if (death_tube == None):
98 death_tube = tp.drag(drag_vector)
99 else:
100 death_tube = death_tube.union(tp.drag(drag_vector))
101
102
103 conn = pgdb.connect(host=options.host,
104 database=options.database,
105 user=options.username)
106
107
108 # We'll use this cursor for all of our queries.
109 cursor = conn.cursor()
110
111
112 # We use one query that basically just imports the WKT string and
113 # immediately exports it as KML. The geometry must have an SRID when
114 # ST_AsKml is called, so we provide one to ST_GeomFromText.
115 kml_query = "SELECT ST_AsKml(ST_GeomFromText('%s', %s))" % (death_tube.wkt(), options.srid)
116
117 cursor.execute(kml_query)
118 rows = cursor.fetchall()
119 kml_representation = rows[0][0]
120 conn.close()
121
122
123 doc = KML.Document()
124
125 # Create a semi-transparent blue polygon style, and add it to the
126 # document.
127 hex_value = "b0ff0000"
128 s = KML.Style(initial_id=('default'))
129 poly_style = KML.PolyStyle()
130 color = KML.Color(hex_value)
131 poly_style.children.append(color)
132 s.children.append(poly_style)
133 doc.styles.append(s)
134
135 # We're only going to have one placemark -- the object defined by our
136 # input WKT.
137 placemark = KML.Placemark()
138 name = KML.Name(options.name)
139 placemark.children.append(name)
140
141 # This applies the red polygon style defined earlier to our placemark.
142 styleurl = KML.StyleUrl('default')
143 placemark.children.append(styleurl)
144
145 # The database query is going to give us raw KML. For example, if our
146 # input WKT represents a polygon, the output of ST_AsKml will contain
147 # <Polygon>...</Polygon> and everything therein.
148 rawkml = KML.RawText(kml_representation)
149 placemark.children.append(rawkml)
150 doc.children.append(placemark)
151
152 # Default the output file to sys.stdout. If we were passed an outfile
153 # as an argument, use that instead.
154 output_file = sys.stdout
155 if (options.outfile != None):
156 output_file = open(options.outfile, 'w')
157
158 # Write the KML and get out of here.
159 output_file.write(doc.to_kml())
160 output_file.close()