Skip to content

Instantly share code, notes, and snippets.

@bemasher
Created February 17, 2011 01:07
Show Gist options
  • Save bemasher/830707 to your computer and use it in GitHub Desktop.
Save bemasher/830707 to your computer and use it in GitHub Desktop.
Converts ARC/INFO ungenerate cartographic boundary files to SVG. Currently requires tweaking for each file, not a universal system since the metadata isn't always the same format between different sets.
import sys, lxml
from lxml.builder import E
def parseMetadata(filename, select=1, records=6):
data = open(filename).read().strip().split('\n')
ids = map(lambda x: x.strip(), data[::records])
selected = map(lambda x: x.replace('"', '').strip(), data[select::records])
metaDict = {}
for x in xrange(len(ids)):
metaDict[ids[x]] = selected[x]
return metaDict
metaFilename = 'AZ - ZCTA - Meta.dat'
boundFilename = 'AZ - ZCTA - Bound.dat'
min_x = sys.float_info.max
max_x = -sys.float_info.max
min_y = sys.float_info.max
max_y = -sys.float_info.max
pathMeta = parseMetadata(metaFilename, 2, 6)
pathMeta['-99999'] = 'Unknown'
# pathMetaP1 = parseMetadata(metaFilename, 1, 7)
# pathMetaP2 = parseMetadata(metaFilename, 2, 7)
# pathMeta = {}
# for id in pathMetaP1.keys():
# pathMeta[id] = pathMetaP1[id] + pathMetaP2[id]
paths = {}
for line in open(boundFilename):
data = line.strip().split()
if len(data) == 3:
id = pathMeta[data[0]]
path = []
if len(data) == 1 and data[0] != 'END':
path = []
if len(data) == 2:
pair = tuple(map(lambda x: float(x), data))
min_x, max_x = min(min_x, pair[0]), max(max_x, pair[0])
min_y, max_y = min(min_y, pair[1]), max(max_y, pair[1])
path.append(pair)
if len(data) == 1 and data[0] == 'END':
if id not in paths:
paths[id] = []
paths[id].append(path)
else:
paths[id].append(path)
width = 800
scale = float(width) / (max_x - min_x)
height = (max_y - min_y) * scale
height = int(height + 0.5)
digits = 3
header = '''<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" version="1.0" width="{0}" height="{1}" viewbox="0 0 {0} {1}">
<g style="fill: none; stroke: black;">
'''.format(width, height)
svg = open("map.svg", "w")
svg.write(header)
for id, pathList in paths.items():
print len(pathList)
for path in pathList:
attrib = {
'id': id,
'd': 'M ' + ' '.join(map(lambda pair: str(round((pair[0] - min_x) * scale, digits)) + ',' + str(round((max_y - pair[1]) * scale, digits)), path)) + ' Z'
}
path = E.path(attrib)
svg.write(lxml.etree.tostring(path, pretty_print=True))
svg.write("</g>\n</svg>")
svg.close()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment