import sys import ogr fixed_tags = { 'source': 'MassGIS OpenSpace (http://www.mass.gov/mgis/osp.htm)', 'area': 'yes', 'created_by': 'polyshp2osm' } def access(data): keys = { 'Y': 'yes', 'N': 'private', 'L': 'restricted' } if 'pub_access' in data: if data['pub_access'] in keys: return [['access', keys[data['pub_access']]]] return None def protection(data): keys = { 'P': 'perpetuity', 'T': 'temporary', 'L': 'limited', 'N': None } if 'lev_prot' in data: if data['lev_prot'] in keys: return [['protected', keys[data['lev_prot']]]] return None def owner_type(data): keys = { 'F': 'national', 'S': 'state', 'C': 'county', 'M': 'municipal', 'N': 'private_nonprofit', 'P': 'private', 'B': 'public_nonprofit', 'L': 'land_trust', 'G': 'conservation_rganization', 'I': 'inholding', } if 'owner_type' in data: if data['owner_type'] in keys: return [['ownership', keys[data['owner_type']]]] def purpose(data): keys = { 'R': [('leisure', 'recreation_ground')], 'C': [('leisure', 'nature_reserve'), ('landuse', 'conservation')], 'B': [('landuse','conservation'), ('leisure','recreation_ground')], 'H': [('historical', 'yes')], 'A': [('agricultural', 'yes'), ('landuse','farm')], 'W': [('landuse', 'resevoir')], 'S': [('scenic','yes')], 'F': [('landuse','land')], 'Q': [('landuse','conservation')], 'U': [('water','yes')] } if 'prim_purp' in data: if data['prim_purp'] in keys: return keys[data['prim_purp']] def name_tags(data): tags = [] name = data.get('site_name', None) if not name: return name = name.title() # Add regular expressions if "cemetery" in name.lower(): tags.append(['landuse', 'cemetery']) elif "forest" in name.lower(): tags.append(['landuse', 'forest']) tags.append(['name', name]) return tags def cal_date(data): date = data.get('cal_date_r', None) if not date: return try: m, d, y = map(int, date.split("/")) if m == 1 and d == 1: return [['start_date', '%4i' % y]] return [['start_date', '%04i-%02i-%02i' % (y, m, d)]] except: print "Invalid date: %s" % date return None tag_mapping = [ ('fee_owner', 'owner'), ('cal_date', cal_date), ('pub_access', access), ('lev_prot', protection), ('owner_type', owner_type), ('prim_purp', purpose), ('site_name', name_tags), ] boring_tags = [ 'AREA', 'LEN', 'GIS_ACRES' ] def close_file(): global open_file if not open_file.closed: open_file.write("") open_file.close() def start_new_file(): global open_file, file_counter file_counter += 1 if open_file: close_file() open_file = open("%s.%s.osm" % (file_name, file_counter), "w") print >>open_file, "" def clean_attr(val): val = str(val) val = val.replace("&", "&").replace("'", """).replace("<", "<").replace(">", ">").strip() return val def add_ring_nodes(ring): global open_file, id_counter ids = [] if range(ring.GetPointCount() - 1) == 0 or ring.GetPointCount() == 0: print >>sys.stderr, "Degenerate ring." return for count in range(ring.GetPointCount()-1): ids.append(id_counter) print >>open_file, "" % (id_counter, ring.GetX(count), ring.GetY(count)) #print count id_counter += 1 return ids def add_ring_way(ring): global open_file, id_counter ids = [] for count in range(ring.GetPointCount()-1): ids.append(id_counter) print >>open_file, "" % (id_counter, ring.GetX(count), ring.GetY(count)) #print count id_counter += 1 if len(ids) == 0: return None print >>open_file, "" % id_counter way_id = id_counter id_counter += 1 for i in ids: print >>open_file, "" % i print >>open_file, "" % ids[0] print >>open_file, "" return way_id open_file = None file_name = "osm/openspace" id_counter = 1 file_counter = 0 counter = 0 def run(filename, slice_count=1, obj_count=50000, output_location=None): global id_counter, file_counter, counter, file_name, open_file if output_location: file_name = output_location ds = ogr.Open(filename) l = ds.GetLayer(0) max_objs_per_file = obj_count extent = l.GetExtent() slice_width = (extent[1] - extent[0]) / slice_count seen = {} for i in range(slice_count): l.ResetReading() l.SetSpatialFilterRect(extent[0] + slice_width * i, extent[2], extent[0] + (slice_width * (i + 1)), extent[3]) start_new_file() f = l.GetNextFeature() obj_counter = 0 last_obj_split = 0 while f: start_id_counter = id_counter if f.GetFID() in seen: f = l.GetNextFeature() continue seen[f.GetFID()] = True if (obj_counter - last_obj_split) > max_objs_per_file: print "Splitting file with %s objs" % (obj_counter - last_obj_split) start_new_file() last_obj_split = obj_counter ways = [] geom = f.GetGeometryRef() ring = geom.GetGeometryRef(0) ids = add_ring_nodes(ring) if not ids or len(ids) == 0: f = l.GetNextFeature() continue print >>open_file, "" % id_counter ways.append(id_counter) id_counter += 1 for i in ids: print >>open_file, "" % i print >>open_file, "" % ids[0] field_count = f.GetFieldCount() fields = {} for field in range(field_count): value = f.GetFieldAsString(field) name = f.GetFieldDefnRef(field).GetName() if name and value and name not in boring_tags: print >>open_file, "" % (name, clean_attr(value)) fields[name.lower()] = value tags={} for tag_name, map_value in tag_mapping: if hasattr(map_value, '__call__'): tag_values = map_value(fields) if tag_values: for tag in tag_values: tags[tag[0]] = tag[1] else: if tag_name in fields: tags[map_value] = fields[tag_name].title() for key, value in tags.items(): if key and value: print >>open_file, "" % (key, clean_attr(value)) for name, value in fixed_tags.items(): print >>open_file, "" % (name, clean_attr(value)) print >>open_file, "" if geom.GetGeometryCount() > 1: for i in range(1, geom.GetGeometryCount()): ways.append(add_ring_way(geom.GetGeometryRef(i))) print >>open_file, "" % id_counter id_counter += 1 print >>open_file, '' % ways[0] for way in ways[1:]: print >>open_file, '' % way print >>open_file, "" counter += 1 f = l.GetNextFeature() obj_counter += (id_counter - start_id_counter) close_file() from optparse import OptionParser parse = OptionParser(usage="%s [args] filename.shp") parse.add_option("-s", "--slice-count", dest="slice_count", help="Number of horizontal slices of data", default=1, action="store", type="int") parse.add_option("-o", "--obj-count", dest="obj_count", help="Target Maximum number of objects in a single .osm file", default=50000) parse.add_option("-l", "--output-location", dest="output_location", help="base filepath for output files.", default="poly_output") (options, args) = parse.parse_args() kw = {} for key in ('slice_count', 'obj_count', 'output_location'): kw[key] = getattr(options, key) run(args[0], **kw)