GeoScript Spatial Capabilities for Scripting Languages Justin Deolivera and Jared Erickson.

45
GeoScript Spatial Capabilities for Scripting Languages Justin Deolivera and Jared Erickson

Transcript of GeoScript Spatial Capabilities for Scripting Languages Justin Deolivera and Jared Erickson.

Page 1: GeoScript Spatial Capabilities for Scripting Languages Justin Deolivera and Jared Erickson.

GeoScriptSpatial Capabilities for Scripting Languages

Justin Deolivera and Jared Erickson

Page 2: GeoScript Spatial Capabilities for Scripting Languages Justin Deolivera and Jared Erickson.

Scripting Platform for JVM Languages

Similar API Respect languages differences    Python GeoScript should be PythonicMake easy things easy, Make hard things possible

Page 3: GeoScript Spatial Capabilities for Scripting Languages Justin Deolivera and Jared Erickson.

Groovy

• Groovy o Dynamic languageo Easy for Java programmers to learn o Closures, DSLso REPL, GUI Consoleo Compiles to Java Byte Codeo Full access to Java libraries

• http://geoscript.org/groovy• https://github.com/jericks/geoscript-groovy

Page 4: GeoScript Spatial Capabilities for Scripting Languages Justin Deolivera and Jared Erickson.

JavaScript

 

Page 5: GeoScript Spatial Capabilities for Scripting Languages Justin Deolivera and Jared Erickson.

Python

• Jython o Java implementation of Python o Jython 2.5 = CPython 2.5o Full access to Java libraries

• http://geoscript.org/py• https://github.com/jdeolive/geoscript-py

Page 6: GeoScript Spatial Capabilities for Scripting Languages Justin Deolivera and Jared Erickson.

• Scalao Combine functional and object-oriented

programmingo Statically typed???o REPLo Compiles to Java bytecodeo Full access to Java libraries

• http://geoscript.org/scala/• https://github.com/dwins/geoscript.scala/

Scala

Page 7: GeoScript Spatial Capabilities for Scripting Languages Justin Deolivera and Jared Erickson.

On the shoulders of giants...

Page 8: GeoScript Spatial Capabilities for Scripting Languages Justin Deolivera and Jared Erickson.

On the shoulders of giants...

• Java Topology Suite (JTS)o Geometry API and Algorithms

• GeoToolso DataStoreso Features o Coverages/Rasters o Referencingo Renderering

• Java Tribe Base librarieso GeoServero uDigo Geomajas

Page 9: GeoScript Spatial Capabilities for Scripting Languages Justin Deolivera and Jared Erickson.

GeoScript Modules

Page 10: GeoScript Spatial Capabilities for Scripting Languages Justin Deolivera and Jared Erickson.

GeoScript Modules

• Geometry• Projection• Feature• Layer• Workspace• Style• Renderer

Page 11: GeoScript Spatial Capabilities for Scripting Languages Justin Deolivera and Jared Erickson.

Geometry

• Convenient constructors• I/O

o WKT/WKBo JSONo GML

• Plotting• Transforms

Page 12: GeoScript Spatial Capabilities for Scripting Languages Justin Deolivera and Jared Erickson.

Geometry

>>> from geoscript import geom

>>> geom.Point(30, 10)POINT(30 10)

>>> geom.LineString((30,10), (10,20), (20,40), (40,40), (30,10))  LINESTRING (30 10, 10 20, 20 40, 40 40, 30 10)

>>> geom.Polygon([(35,10), (10,20), (15,40), (45,45), (35,10)], [(20,30), (35,35), (30,20), (20,30)])POLYGON ((35 10, 10 20, ... 30 20, 20 30))

>>> geom.MultiLineString([(10,10), (20,20), (10,40)], [(40,40), (30,30), (40,20), (30,10)])MULTILINESTRING ((10 10, 20 20, ... 40 20, 30 10))

Constructors

Page 13: GeoScript Spatial Capabilities for Scripting Languages Justin Deolivera and Jared Erickson.

Geometry

>>> from geoscript import geom

>>> point = geom.Point(30, 10)>>> geom.writeGML(point)<gml:Point xmlns:gml="http://www.opengis.net/gml"> <gml:coord>  <gml:X>30.0</gml:X>  <gml:Y>10.0</gml:Y> </gml:coord></gml:Point>

>>> geom.readJSON('{"type":"Point","coordinates":[30,10]}')POINT(30 10)

>>> geom.writeWKB(point)array('b', [0, 0, 0, 0, 1, 64, 62, ... 64, 36, 0, 0, 0, 0, 0, 0])

Input/Output

Page 14: GeoScript Spatial Capabilities for Scripting Languages Justin Deolivera and Jared Erickson.

Geometry

>>> from geoscript.render import plot>>> from geoscript import geom

>>> poly = geom.Polygon([(35,10), (10,20), (15,40), (45,45), (35,10)], [(20,30), (35,35), (30,20), (20,30)])

>>> plot(poly)

Plotting

Page 15: GeoScript Spatial Capabilities for Scripting Languages Justin Deolivera and Jared Erickson.

Geometry

>>> from geoscript.geom import Point, transform>>> from geoscript.render import draw

>>> c = geom.Point(0, 0).buffer(10)>>> d = transform(c, dx=5) # translate>>> draw([c,d])

>>> e,f = transform(c, shx=0.5), transform(c, shx=-0.5) # shear>>> g = transform(c, sx=0.7) # scale>>> draw([e,f,g])

Transforms

Page 16: GeoScript Spatial Capabilities for Scripting Languages Justin Deolivera and Jared Erickson.

Projection

• Parse/encode WKT• Full GeoTools EPSG

database• Re-projection

Page 17: GeoScript Spatial Capabilities for Scripting Languages Justin Deolivera and Jared Erickson.

Projection

>>> from geoscript.proj import Projection

>>> Projection('EPSG:4326')GEOGCS["WGS 84",   DATUM["World Geodetic System 1984",     SPHEROID["WGS 84", 6378137.0, 298.257223563, AUTHORITY["EPSG","7030"]],     AUTHORITY["EPSG","6326"]],   PRIMEM["Greenwich", 0.0, AUTHORITY["EPSG","8901"]],   UNIT["degree", 0.017453292519943295],   AXIS["Geodetic longitude", EAST],   AXIS["Geodetic latitude", NORTH],   AUTHORITY["EPSG","4326"]]

>>> p = Projection('GEOGCS[..."Degree",0.017453292519943295]]') >>> p.id'EPSG:4326'

Constructors

Page 18: GeoScript Spatial Capabilities for Scripting Languages Justin Deolivera and Jared Erickson.

Projection

>>> from geoscript import geom, render>>> from geoscript.proj import Projection

>>> p = Projection('epsg:4326')>>> p.transform((-111, 45.7), 'epsg:26912')(500000.0, 5060716.313515949)

>>> g = geom.Point(0, 0).buffer(4)>>> g = reduce(lambda x,y:x.union(y),[geom.transform(g,dx=x,dy=y)      for x,y in [(3,0),(0,3),(-3,0),(0,-3)]])>>> render.draw(g)>>> render.draw(p.transform(g, 'epsg:26912'))>>> render.draw(p.transform(g, 'epsg:3005'))

Reprojection

WGS 84 UTM Albers

Page 19: GeoScript Spatial Capabilities for Scripting Languages Justin Deolivera and Jared Erickson.

Data Access

• Read and Write Layers• Query Layers using CQL• I/O 

o GeoJSONo GML

Page 20: GeoScript Spatial Capabilities for Scripting Languages Justin Deolivera and Jared Erickson.

Data Access

>>> from geoscript.workspace import PostGIS>>> from geoscript import geom

>>> pg = PostGIS('spearfish')>>> pg.layers()['archsites', 'bugsites', 'railroads', 'restricted', 'roads', 'streams']>>> l = pg['bugsites']>>> l.schemabugsites [cat: long, str1: str, the_geom: Point]

>>> l = Layer('foo')>>> l.add([geom.Point(0,0)]) >>> l = pg.add(l) 

>>> l = pg.create('bar', [('geom',geom.Point),('name',str)])

Workspaces

Page 21: GeoScript Spatial Capabilities for Scripting Languages Justin Deolivera and Jared Erickson.

Data Access

>>> from geoscript.layer import Shapefile

>>> shp = Shapefile('states.shp')>>> shp.count()49>>> shp.count('CARPOOL/PERSONS > 0.06')26

>>> shp.bounds()(-124.731422, 24.955967, -66.969849, 49.371735, EPSG:4326)

>>> shp.bounds("STATE_NAME = 'Colorado'")(-109.055199, 36.988972, -102.036758, 41.00341, EPSG:4326)

>>> for f in shp.features():...   print '%s has %f people' % (f['STATE_NAME'],f['PERSONS'])

>>> for f in shp.features('CARPOOL/PERSONS > 0.06'):...   print '%s likes to carpool' % f['STATE_NAME']

Layers

Page 22: GeoScript Spatial Capabilities for Scripting Languages Justin Deolivera and Jared Erickson.

Data Access

>>> from geoscript.feature import Schema, Feature>>> from geoscript.geom import *

>>> schema = Schema('shapes', [('geom',Polygon), ('name',str)]) 

>>> square = Feature([LineString((0,0),(1,1)).bounds().toPolygon(),      'square'], 0, schema)>>> square.id0>>> square['name']'square'>>> square.geomPOLYGON ((0 0, 0 1, 1 1, 1 0, 0 0))

>>> square.geom = LineString((0,0),(2,1)).bounds().toPolygon()>>> square['name'] = 'rectangle'

>>> circle = Feature({'geom':Point(0,0).buffer(1),'name':'circle'})

Features

Page 23: GeoScript Spatial Capabilities for Scripting Languages Justin Deolivera and Jared Erickson.

Data Access

>>> from geoscript.feature import *>>> from geoscript.geom import Polygon

>>> triangle = Feature({'geom':Polygon([(0,0),(1,1),(2,0),(0,0)])})>>> writeGML(triangle)<gsf:feature fid="fid--272f9bd3_1322c34ca2d_-8000" xmlns:gml="http://www.opengis.net/gml" xmlns:gsf="http://geoscript.org/feature"> <gsf:geom>  <gml:Polygon>...</gml:Polygon> </gsf:geom></gsf:feature>

>>> writeGML(triangle, version=3.2)...

>>> writeJSON(triangle){"type":"Feature","geometry":{"type":"Polygon","coordinates":[[[0.0,0.0],[1,1],[2,0.0],[0.0,0.0]]]},"properties":{},"id":"fid--272f9bd3_1322c34ca2d_-8000"}

>>> f = readJSON('{"type":"Feature", "geometry":{"type":"Point", "coordinates":[1.0, 2.0]}}')feature.fid--709b2d80_1322c512876_-8000 {geometry: POINT (1 2)}

Input/Output

Page 24: GeoScript Spatial Capabilities for Scripting Languages Justin Deolivera and Jared Erickson.

Styling and Rendering

• Taming SLDo Symbolizerso Scale dependenceo Thematics

Page 25: GeoScript Spatial Capabilities for Scripting Languages Justin Deolivera and Jared Erickson.

Styling

>>> from geoscript.style import Stroke>>> from geoscript.render import draw>>> from geoscript.geom import *

>>> line = LineString((0,0), (1,1))

>>> draw(line, Stroke('#000000', width=2)) # normal>>> draw(line, Stroke('black', width=2, dash=[5,5])) # dash>>> draw(line, Stroke((0,0,0), width=2).hatch('vertline')) # hatch

Stroke

Page 26: GeoScript Spatial Capabilities for Scripting Languages Justin Deolivera and Jared Erickson.

Styling

>>> from geoscript.style import Fill, Stroke>>> from geoscript.render import draw>>> from geoscript.geom import *

>>> poly = Point(0,0).buffer(1)

>>> draw(poly, Fill('gray')) # normal>>> draw(poly, Fill('gray', opacity=0.5)) # transparent>>> draw(poly, Fill('gray').hatch('backslash')) # hatch

>>> draw(poly, Stroke('red',2) + Fill().hatch('times'))

Fill

Page 27: GeoScript Spatial Capabilities for Scripting Languages Justin Deolivera and Jared Erickson.

Styling

>>> from geoscript.style import Shape>>> from geoscript.render import draw>>> from geoscript.geom import *

>>> mpoint = MultiPoint((0,0), (0,1), (1,1), (1,0), (0.5,0.5))

>>> draw(mpoint, Shape('black', 10))>>> draw(mpoint, Shape('yellow', 20, 'star'))>>> draw(mpoint, Shape('red', 20, 'x'))

Shape

Page 28: GeoScript Spatial Capabilities for Scripting Languages Justin Deolivera and Jared Erickson.

Styling

>>> from geoscript.style import Icon>>> from geoscript.render import draw>>> from geoscript.geom import *

>>> mpoint = MultiPoint((0,0), (0,1), (1,1), (1,0), (0.5,0.5))

>>> draw(mpoint, Icon('hospital.png'))>>> draw(mpoint, Icon('rainy.svg'))

Icon

Page 29: GeoScript Spatial Capabilities for Scripting Languages Justin Deolivera and Jared Erickson.

Styling

>>> from geoscript.style import Label, Stroke, Fill, Shape>>> from geoscript.feature import Feature>>> from geoscript.render import draw>>> from geoscript.geom import *

>>> font = 'bold 16px Arial'>>> f = Feature({'geom': Point(0,0), 'name': 'foo'})>>> draw(f, Shape() + Label('name', font).point(displace=(20,0)))

>>> f = Feature({'geom': LineString((0,0), (1,1)), 'name': 'bar'})>>> draw(f, Stroke() + Label('name', font).linear(offset=10))

>>> f = Feature({'geom': Point(0,0).buffer(1), 'name': 'baz'})>>> draw(f, Fill() + Label('name', font).halo('white', 2))

Labels

Page 30: GeoScript Spatial Capabilities for Scripting Languages Justin Deolivera and Jared Erickson.

Styling

>>> from geoscript.style Shape, Icon, Label>>> from geoscript.render import draw>>> from geoscript.feature import Feature>>> from geoscript.geom import *

>>> school = Feature({'loc': Point(0,0), 'name': 'J.L. Crowe'})

>>> style = Shape('#004d96', 5).range(min=3000) >>> style += Icon('school20.png').range(max=3000, min=1500)>>> style += Icon('school40.png').range(max=1500)

>>> bounds = Bounds(-100, -100, 100, 100, 'epsg:404000') >>> draw(school, style, bounds)>>> draw(school, style, bounds.scale(0.5))>>> draw(school, style, bounds.scale(0.1))

Scale

Page 31: GeoScript Spatial Capabilities for Scripting Languages Justin Deolivera and Jared Erickson.

Styling

>>> from geoscript.style Stroke, Fill, Label>>> from geoscript.render import draw>>> from geoscript.layer import Shapefile

>>> states = Shapefile('states.shp')

>>> style = Stroke() + Label('STATE_ABBR', '14 "Times New Roman"')>>> style += Fill('#4DFF4D', 0.7).where('PERSONS < 2000000')>>> style += Fill('#FF4D4D', 0.7).where('PERSONS BETWEEN 2000000 AND 4000000')>>> style += Fill('#4D4DFF', 0.7).where('PERSONS > 4000000')>>> draw(states, style)

Theming

Page 32: GeoScript Spatial Capabilities for Scripting Languages Justin Deolivera and Jared Erickson.

Centroidsimport geoscript.layer.*import geoscript.feature.*import geoscript.geom.*

Shapefile shp = new Shapefile('states.shp')Schema schema = shp.schema.changeGeometryType('Point','states_centroids')Layer centroidLayer = shp.workspace.create(schema) Cursor cursor = shp.cursorwhile(cursor.hasNext()) {   Feature f = cursor.next()   Map attributes = [:]   f.attributes.each{k,v ->      if (v instanceof Geometry) {          attributes[k] = v.centroid      }      else {         attributes[k] = v      }   }   Feature feature = schema.feature(attributes, f.id)   centroidLayer.add(feature)}

cursor.close() 

Page 33: GeoScript Spatial Capabilities for Scripting Languages Justin Deolivera and Jared Erickson.

Voronoi Diagramimport geoscript.layer.*import geoscript.feature.*import geoscript.geom.*

Shapefile shp = new Shapefile('states.shp')Schema schema = new Schema('states_voronoi',           [['the_geom','MultiPolygon','EPSG:4326']])

Layer diagramLayer = shp.workspace.create(schema)List geoms = shp.features.collect{f->    f.geom.centroid}GeometryCollection geomCol = new GeometryCollection(geoms)Geometry voronoiGeom = geomCol.voronoiDiagramdiagramLayer.add(schema.feature([voronoiGeom]))

Page 34: GeoScript Spatial Capabilities for Scripting Languages Justin Deolivera and Jared Erickson.

Shapefiles to PostGIS

import geoscript.workspace.*import geoscript.layer.*

def dir = new Directory("/Users/jericks/Downloads/wash")println("Shapefiles: ${dir.layers}")

def postgis = new PostGIS('postgres','localhost','5432','public','postgres', 'postgres')println("PostGIS Layers: ${postgis.layers}")

dir.layers.each{name->    def layer = dir.get(name)    println("Adding ${layer.name}...")    postgis.add(layer)}

Page 35: GeoScript Spatial Capabilities for Scripting Languages Justin Deolivera and Jared Erickson.

USGS Earth Quakes

Read RSS Feed to a Shapefile

Page 36: GeoScript Spatial Capabilities for Scripting Languages Justin Deolivera and Jared Erickson.

import geoscript.geom.*import geoscript.feature.*import geoscript.layer.Layerimport geoscript.workspace.Directory

Schema s = new Schema('earthquakes'[['the_geom', 'Point', 'EPSG:4326'], ['title','String'], ['date', 'java.util.Date'], ['elevation', 'Double']])Directory dir = new Directory('.')Layer layer = dir.create(s)

def url = "http://earthquake.usgs.gov/earthquakes/catalogs/1day-M2.5.xml"def rss = new XmlParser().parse(url)int c = 0String dateFormat = "yyyy-MM-dd'T'HH:mm:ss'Z'"rss.entry.each{e ->    def title = e.title.text()    def date = Date.parse(dateFormat, e.updated.text())    def coordinate = e."georss:point".text().split(" ")    double x = coordinate[1] as Double    double y = coordinate[0] as Double    def point = new Point(x,y)    def elev = e."georss:elev".text() as Double    Feature f = s.feature(['title':title,'date':date,      'elevation': elev, 'the_geom': point],"earthquake_${c}")    layer.add(f)    c++}

Page 37: GeoScript Spatial Capabilities for Scripting Languages Justin Deolivera and Jared Erickson.

Web Applications

@GrabResolver(name="graffiti", root="http://simple-dm.googlecode.com/svn/repository")@Grab("com.goodercode:graffiti:1.0-SNAPSHOT")import graffiti.*import geoscript.geom.Geometry

@Get("/buffer")def buffer() {    Geometry.fromWKT(params.geom).buffer(params.distance as double).wkt}@Get("/centroid")def centroid() {    Geometry.fromWKT(params.geom).centroid.wkt}@Get("/convexHull")def convexHull() {    Geometry.fromWKT(params.geom).convexHull.wkt}

Graffiti.root 'graffiti'Graffiti.serve thisGraffiti.start()    

Graffiti Micro Web Framework

Page 38: GeoScript Spatial Capabilities for Scripting Languages Justin Deolivera and Jared Erickson.

Geometry Web Services 

Page 39: GeoScript Spatial Capabilities for Scripting Languages Justin Deolivera and Jared Erickson.

Geometry Web ServicesOpen Layers

function centroid() {   var features = vectorLayer.features;   if (features.length == 0) {      alert("Please add some features!");   } else {      OpenLayers.loadURL('centroid', {            geom: wktFormat.write(features)         },          this,          function(request) {            var wkt = request.responseText;            var features = wktFormat.read(wkt);            if (features) vectorLayer.addFeatures(features);         },          function() {            alert("Error calculating centroids!");         }      );   }}

Page 40: GeoScript Spatial Capabilities for Scripting Languages Justin Deolivera and Jared Erickson.

WMS Serverimport com.sun.grizzly.http.embed.GrizzlyWebServerimport com.sun.grizzly.http.servlet.ServletAdapterimport groovy.servlet.GroovySerlvet

@Grab(group='com.sun.grizzly',module='grizzly-servlet-webserver',  version='1.9.10')def start() {    def server = new GrizzlyWebServer(8080, "web")    def servlet = new ServletAdapter()    servlet.contextPath = "/geoscript"    servlet.servletInstance = new GroovyServlet()    server.addGrizzlyAdapter(servlet, ["/geoscript"] as String[])    server.start()}start()

Page 41: GeoScript Spatial Capabilities for Scripting Languages Justin Deolivera and Jared Erickson.

WMS Server...import geoscript.map.Mapimport geoscript.style.*import geoscript.layer.Shapefileimport geoscript.geom.Bounds

def file = new File("states.shp")def shp = new Shapefile(file)shp.style = new Fill("steelblue") + new Stroke("wheat", 0.1)

def map = new Map(    width: 256,     height: 256,     layers: [shp],    proj: shp.proj,    fixAspectRatio: false)

def bbox = request.getParameter("BBOX").split(",")def bounds = new Bounds(bbox[0] as double, bbox[1] as double, bbox[2] as double, bbox[3] as double)

map.bounds = boundsresponse.contentType = "image/png"map.render(response.outputStream)map.close()

Page 42: GeoScript Spatial Capabilities for Scripting Languages Justin Deolivera and Jared Erickson.

Geometry Command line echo "POINT (1 1)" | geoscript-groovy geom_buffer.groovy -d 10 | geoscript-groovy geom_envelope.groovy

def cli = new CliBuilder(usage: 'geoscript-groovy geom_buffer.groovy -d')cli.d(longOpt: 'distance', 'buffer distance', args:1)cli.h(longOpt: 'help', 'Show usage information and quit')def opt = cli.parse(args)if(!opt) returnif (opt.h || !opt.d) cli.usage()else println geoscript.geom.Geometry.fromWKT(System.in.text).buffer(opt.d as double).wkt

def cli = new CliBuilder(usage: 'geoscript-groovy geom_envelope.groovy')cli.h(longOpt: 'help', 'Show usage information and quit')def opt = cli.parse(args)if(!opt) returnif (opt.h) cli.usage()else println geoscript.geom.Geometry.fromWKT(System.in.text).bounds.geometry.wkt

geom_buffer.groovy

geom_envelope.groovy

Page 43: GeoScript Spatial Capabilities for Scripting Languages Justin Deolivera and Jared Erickson.

Road Map• Rendering Module• Raster Module• WPS/GeoServer plugin(s)• Map Printing

Page 44: GeoScript Spatial Capabilities for Scripting Languages Justin Deolivera and Jared Erickson.

Resources

Web Site    http://geoscript.org

Google Group    http://groups.google.com/group/geoscript

Blog    http://geoscriptblog.blogspot.com

GitHub    https://github.com/jdeolive/geoscript-py    https://github.com/tschaub/geoscript-js    https://github.com/dwins/geoscript.scala    https://github.com/jericks/geoscript-groovy    

Page 45: GeoScript Spatial Capabilities for Scripting Languages Justin Deolivera and Jared Erickson.

Thank you!