[Talk-us] MA: polyshp2osm.py diffs for other datasets

Greg Troxel gdt at ir.bbn.com
Mon Mar 29 00:35:54 BST 2010


I have the following working diff to polyshp2osm.py to enable handling
types of data other than MassGIS openspace.  There is a new --type
argument, and that controls the fixed tags that are added.  I'm trying
to deal with Assessor's parcel boundary data and town boundary data.

I realize neither of these datasets are suitable for import as is
because of duplicated nodes and overlapping ways, plus for parcel data
there are more issues.  But, I have the parcel data on my etrex and it
has been very useful.

If someone who can commit this thinks it's an improvement, that would be
great.  Feedback welcome either way.



Index: polyshp2osm.py
===================================================================
--- polyshp2osm.py	(revision 20702)
+++ polyshp2osm.py	(working copy)
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python
 
 """
 This script is designed to act as assistance in converting shapefiles
@@ -32,19 +32,42 @@
 will usually suffice. 
 """
 
+# This script can convert a number of different kinds of shapefiles,
+# and thus must be given a --type=foo argument to choose one.
+# See fixed_tags_type for permissible values and URLs.
+
 # These tags are attached to all exterior ways. You can put any key/value pairs
 # in this dictionary. 
 
 fixed_tags = {
-  'source': 'MassGIS OpenSpace (http://www.mass.gov/mgis/osp.htm)',
-  'area': 'yes',
   'created_by': 'polyshp2osm'
 }  
 
+fixed_tags_type = {
+    'massgis-openspace': {
+        'area': 'yes',
+        'source': 'MassGIS openspace (http://www.mass.gov/mgis/osp.htm)',
+        },
+    'massgis-parcels': {
+        'boundary': 'parcel',
+        'source': 'MassGIS parcels (http://www.mass.gov/mgis/parcels.htm)',
+        },
+    'massgis-townssurvey': {
+        'boundary': 'administrative',
+        'admin_level': 8,
+        'source': 'MassGIS Towns Survey (http://www.mass.gov/mgis/townssurvey.htm)',
+        }
+}
+
 # Here are a number of functions: These functions define tag mappings. The API
 # For these functions is that they are passed the attributes from a feature,
 # and they return a list of two-tuples which match to key/value pairs.
 
+# Most of these functions are for a particular kind of shapefile.  For
+# now, they all run for every kind, and having a list of converters is
+# a future enhancement.
+
+# massgis-openspace
 def access(data):
     """Access restrictions."""  
     keys = {
@@ -57,6 +80,7 @@
             return [('access', keys[data['pub_access']])]
     return None        
 
+# massgis-openspace
 def protection(data):
     keys = {
         'P': 'perpetuity',
@@ -68,6 +92,7 @@
             return [('protected', keys[data['lev_prot']])]
     return None
 
+# massgis-openspace
 def owner_type(data):
     """See wiki:Key:ownership""" 
     keys = {
@@ -86,6 +111,8 @@
         if data['owner_type'] in keys:
             return [['ownership', keys[data['owner_type']]]]
 
+# massgis-openspace
+# TODO: W in massgis "water supply protection".
 def purpose(data):
     """Based on a discussion on IRC"""
     keys = {
@@ -104,6 +131,8 @@
         if data['prim_purp'] in keys:
             return keys[data['prim_purp']]
 
+# massgis-openspace
+# Perhaps more generally applicable.
 def name_tags(data):
     """This function returns two things: a 'pretty' name to use, and
        may return a landuse of either 'cemetery' or 'forest' if the name
@@ -122,6 +151,8 @@
     tags.append(['name', name])
     return tags
 
+# massgis-openspace
+# Perhaps more generally applicable.
 def cal_date(data):
     """Return YYYY-MM-DD or YYYY formatted dates, based on 
        (m)m/(d)d/yyyy dates"""
@@ -139,7 +170,7 @@
 # The most important part of the code: define a set of key/value pairs
 # to iterate over to generate keys. This is a list of two-tuples: first
 # is a 'key', which is only used if the second value is a string. In
-# that case, it is a map of lowercased fielnames to OSM tag names: so
+# that case, it is a map of lowercased fieldnames to OSM tag names: so
 # fee_owner maps to 'owner' in the OSM output.
 
 # if the latter is callable (has a __call__; is a function), then that
@@ -148,6 +179,7 @@
 # two-tuples to be used as tags, or nothin' to skip the tags.  
 
 
+# massgis-openspace
 tag_mapping = [ 
     ('fee_owner', 'owner'),
     ('cal_date', cal_date),
@@ -161,20 +193,35 @@
 # These tags are not exported, even with the source data; this should be
 # used for tags which are usually calculated in a GIS. AREA and LEN are
 # common.
+# For now, these tags are not changed based on the input type, on the
+# hopes that boring tags are universal and it's not worth handling
+# them per type.
 
-boring_tags = [ 'AREA', 'LEN', 'GIS_ACRES' ]
+boring_tags = [
+        # massgis-openspace
+        'AREA', 'LEN', 'GIS_ACRES',
+        # massgis-parcels
+        'SHAPE_AREA', 'SHAPE_LEN', 'ACRES',
+        # massgis-townssurvey
+        'OBJECTID', 'POP1980', 'POP1990', 'POP2000', 'POPCH80_90',
+        'POPCH90_00', 'TYPE', 'ISLAND', 'COASTAL_PO', 'FOURCOLOR',
+        'FIPS_STCO', 'CCD_MCD', 'FIPS_PLACE', 'FIPS_MCD', 'FIPS_COUNT',
+        'SQUARE_MIL',
+        ]
 
 # Namespace is used to prefix existing data attributes. If 'None', or 
 # '--no-source' is set, then source attributes are not exported, only
 # attributes in tag_mapping.
 
+# For now, this script only supports massgis without editing, but
+# namespace could be settable by type.
 namespace = "massgis"
 #namespace = None 
 
 # Uncomment the "DONT_RUN = False" line to get started. 
 
 DONT_RUN = True
-#DONT_RUN = False
+DONT_RUN = False
 
 # =========== DO NOT CHANGE AFTER THIS LINE. ===========================
 # Below here is regular code, part of the file. This is not designed to
@@ -210,7 +257,7 @@
     if open_file:
         close_file()
     open_file = open("%s.%s.osm" % (file_name, file_counter), "w")
-    print >>open_file, "<osm version='0.5'>"
+    print >>open_file, "<osm version='0.6'>"
 
 def clean_attr(val):
     """Internal. Hacky way to make attribute XML safe."""
@@ -262,7 +309,7 @@
 
 class AppError(Exception): pass
 
-def run(filename, slice_count=1, obj_count=50000, output_location=None, no_source=False):
+def run(filename, slice_count=1, obj_count=50000, output_location=None, no_source=False, conv_type=False):
     """Run the converter. Requires open_file, file_name, id_counter,
     file_counter, counter to be defined in global space; not really a very good
     singleton."""
@@ -351,7 +398,7 @@
                 if key and value:
                     print >>open_file, "<tag k='%s' v='%s' />" % (key, clean_attr(value))
                     
-            for name, value in fixed_tags.items():
+            for name, value in fixed_tags.items() + fixed_tags_type[conv_type].items():
                 print >>open_file, "<tag k='%s' v='%s' />" % (name, clean_attr(value))
             print >>open_file, "</way>"   
             if geom.GetGeometryCount() > 1:
@@ -391,6 +438,9 @@
     parse.add_option("-l", "--output-location", 
                         dest="output_location", help="base filepath for output files.", 
                         default="poly_output") 
+    parse.add_option("-t", "--type", dest="conv_type",
+                     help="Specify type of shapefile to convert.",
+                     action="store", default=False)
     (options, args) = parse.parse_args()
     
     if not len(args):
@@ -399,9 +449,14 @@
         sys.exit(3)
 
     kw = {}
-    for key in  ('slice_count', 'obj_count', 'output_location', 'no_source'):
+    for key in  ('slice_count', 'obj_count', 'output_location', 'no_source',
+                 'conv_type'):
         kw[key] = getattr(options, key)
     
+    print kw;
+
+    # XXX throw an error if conv_type is invalid, and list the keys
+
     try:
         run(args[0], **kw)   
     except AppError, E:
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 194 bytes
Desc: not available
URL: <http://lists.openstreetmap.org/pipermail/talk-us/attachments/20100328/65aa65e9/attachment.pgp>


More information about the Talk-us mailing list