wiki:BluePrint/GIS/ShapefileLayers

Version 32 (modified by Fran Boon, 12 years ago) ( diff )

--

Shapefile Layers

Upload a Shapefile to display on the map.

We can include TM_WORLD_BORDERS-0.3.zip as a useful base/sample

Import to display as an Overlay

This is available as gis_layer_shapefile in Trunk

ToDo

  • Needs styling
    • Point layers should be possible to just use a marker
      • ok currently
    • Polygon layers (& optionally Point layers) can use a JSON Style object, as per Feature & Theme layers
      • Python side is done
      • Need to work in static/scripts/S3/s3.gis.layers.js
    • S3SQLCustomForm to include Style field from layer_config into main form
    • Graphical UI to adjust style
      • accessible from map
        • update map in real-time to see effect of sliders
      • accessible from catalogue (less important)
  • Handle different projections
    • Currently this is supported by manually setting the projection (untested)
    • Can we read it from the Shapefile?
  • onaccept to write any modified data back to the attached shapefile
  • Don't parse the Shapefile repeatedly if the file doesn't change
    • update_onaccept to check this & call main onaccept if it has

Import into native Tables

See below for code to convert SHP to an lxml.etree for import using XSLT

Paul Porthouse [2013-04-27 at the MapAction Hackathon]:

Our idea is to use a basic web form with a file upload (similar to the Import from OpenStreetMap) where you can select which Shapefile to use. You should also be able to set basic information including database connection details. This will then upload the shape and use OGR2OGR to convert the Shapefile to geometry and import it into the specified database.

A basic OGR2OGR which should accomplish the import is: OGR2OGR -overwrite -f "PostgreSQL" PG:dbname=databaseconnection shapefile.sh

This could be called directly from Python by running it as a sub process.

Alternatively, to use Python bindings, you could perform the import using GDAL which would allow more control over the import directly within Python, but should still handle the import into Postgres.

'''
    Dump the contents of a shapefile to an lxml etree object
    Assumes the shapefile is encoded in UTF-8 format
    Tested with TM_WORLD_BORDERS-0.3.shp
'''

import sys
import ogr
import os

from lxml import etree

if len(sys.argv) != 2:
    print "Usage: importshape.py filename"
    sys.exit(0)
    
shapefilename = sys.argv[1]

layername = os.path.splitext(os.path.basename(shapefilename))[0]

# Create the datasource
ds = ogr.Open( shapefilename )

# Open the shapefile
if ds is None:
    print "Open failed.\n"
    sys.exit(0)
    
# Get the layer and iterate through the features
lyr = ds.GetLayer(0)

root = etree.Element("shapefile",name=layername)

for feat in lyr:
	
    featurenode = etree.SubElement(root,"feature")
    
    feat_defn = lyr.GetLayerDefn()
		
    for i in range(feat_defn.GetFieldCount()):
		
	field_defn = feat_defn.GetFieldDefn(i)
			
	fieldnode = etree.SubElement(featurenode,field_defn.GetName())
		
	if field_defn.GetType() == ogr.OFTInteger:
	    fieldnode.text = str(feat.GetFieldAsInteger(i))

	elif field_defn.GetType() == ogr.OFTReal:
	    fieldnode.text = str(feat.GetFieldAsDouble(i))

	elif field_defn.GetType() == ogr.OFTString:
	    FieldString = str(feat.GetFieldAsString(i))
	    fieldnode.text = FieldString.decode(encoding='UTF-8',errors='strict')
	    
    wktnode = etree.SubElement(featurenode,"wkt")
	
    geom = feat.GetGeometryRef()	
    wktnode.text = geom.ExportToWkt()    
		

# Test the etree object
xmlString = etree.tostring(root, pretty_print=True)
f = open("test.xml","w")
f.write(xmlString)

GIS BluePrints

Note: See TracWiki for help on using the wiki.