Transcript
Page 1: GeoScript - Spatial Capabilities for Scripting Languages

GeoScriptSpatial Capabilities for Scripting Languages

Justin Deolivera, Tim Schaub, and Jared Erickson

Page 2: GeoScript - Spatial Capabilities for Scripting Languages

Introduction• What is GeoScript?

o Overview of languages• Motivation

o GeoTools hard, scripting easyo Development turnaround

• GeoScript Modules/API Overviewo Geometryo Projectiono Data Accesso Styling

Page 3: GeoScript - Spatial Capabilities for Scripting Languages

Scripting Platform for JVM Languages

• Similar API • Respect languages differences

Page 4: GeoScript - Spatial Capabilities for Scripting Languages

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 5: GeoScript - Spatial Capabilities for Scripting Languages

JavaScript

Not just for the browser any more!

Common JS module loading with Rhino.

One language for client & server code.

Docs: http://geoscript.org/js/Source: https://github.com/tschaub/geoscript-js/

Page 6: GeoScript - Spatial Capabilities for Scripting Languages

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 7: GeoScript - Spatial Capabilities for Scripting Languages

• Scalao Combine functional and object-oriented

programmingo Statically typedo REPLo Compiles to Java bytecodeo Full access to Java libraries

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

Scala

Page 8: GeoScript - Spatial Capabilities for Scripting Languages

On the shoulders of giants...

Page 9: GeoScript - Spatial Capabilities for Scripting Languages

GeoScript Modules

Page 10: GeoScript - Spatial Capabilities for Scripting Languages

Geometry

• Easy to use constructors• I/O

o WKT/WKBo JSONo GML

• Plotting• Transforms

Page 11: GeoScript - Spatial Capabilities for Scripting Languages

Geometry

>>> from geoscript import geom>>> geom.Point(30, 10)POINT(30 10)

Page 12: GeoScript - Spatial Capabilities for Scripting Languages

Geometry

>>> import geoscript.geom.*>>> line = new LineString([[111.0, -47], [123.0, -48], [110.0, -47]])

LINESTRING (111 -47, 123 -48, 110 -47)

Page 13: GeoScript - Spatial Capabilities for Scripting Languages

Geometry

js> var poly = geom.Point([10, 30]).  >     buffer(5)js> poly<Polygon [[[15, 30], [14.90...>

js> poly.area78.03612880645133

Page 14: GeoScript - Spatial Capabilities for Scripting Languages

Geometry - I/O

>>> from geoscript import geom>>> point = geom.Point(30, 10)>>> geom.writeKML(point)<kml:Point xmlns:kml="http://earth.google.com/kml/2.1"> <kml:coordinates>0.0,0.0</kml:coordinates></kml:Point>

Page 15: GeoScript - Spatial Capabilities for Scripting Languages

Geometry - I/O

>>> import geoscript.geom.Point>>> import geoscript.geom.io.Gml2Writer

>>> p = new Point(111, -47)

>>> gml = new Gml2Writer()>>> gml.write(p)<gml:Point> <gml:coordinates>111.0,-47.0</gml:coordinates></gml:Point>

Page 16: GeoScript - Spatial Capabilities for Scripting Languages

Geometry - I/O

js> var geom = require("geoscript/geom");

js> var point = geom.Point([1, 2])js> point.json{"type":"Point","coordinates":[1,2]}

Page 17: GeoScript - Spatial Capabilities for Scripting Languages

Geometry - Visualization

>>> 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)

Page 18: GeoScript - Spatial Capabilities for Scripting Languages

Geometry - Visualization

js> var geom = require("geoscript/geom")js> require("geoscript/viewer").bind() js> var poly1 = geom.Point([0, 0]).buffer(1)js> var poly2 = poly1.transform({dx: 0.5, dy: 0.5})js> poly1.difference(poly2)<Polygon [[[0.9095298326166407, -0.409529...>

Page 19: GeoScript - Spatial Capabilities for Scripting Languages

Projection

• Parse/encode WKT• Full GeoTools EPSG

database• Re-projection

Page 20: GeoScript - Spatial Capabilities for Scripting Languages

Projection

js> var proj = require("geoscript/proj");js> var p = proj.Projection("epsg:4326");js> p.wktGEOGCS["WGS 84",   DATUM["World Geodetic System 1984",   ...

Page 21: GeoScript - Spatial Capabilities for Scripting Languages

Projection

>>> from geoscript import geom>>> 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)]])

>>> p.transform(g, 'epsg:26912')>>> p.transform(g, 'epsg:3005')

Reprojection

WGS 84 UTM Albers

Page 22: GeoScript - Spatial Capabilities for Scripting Languages

Data Access

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

o GeoJSONo GML

Page 23: GeoScript - Spatial Capabilities for Scripting Languages

Data Access - Workspace

js> var ws = require("geoscript/workspace");       js> var dir = ws.Directory("data");  js> dir          <Directory ["states"]>

js> var states = dir.get("states");js> states<Layer name: states, count: 49>

Page 24: GeoScript - Spatial Capabilities for Scripting Languages

Data Access - Workspace

>> from geoscript.workspace import PostGIS

>> pg = PostGIS('spearfish')>> pg.layers()['archsites', 'bugsites', ..., 'streams']>> l = pg['archsites']

Page 25: GeoScript - Spatial Capabilities for Scripting Languages

Data Access - Workspace

>>> import geoscript.workspace.H2>>> import geoscript.geom.Point>>> import geoscript.feature.Feature

>>> h2 = new H2("name", "path")

>>> layer = h2.create("points", [    new Field("geom","Point"),    new Field("name","String")])

>>> layer.add([new Point[1,1],"one"])

Page 26: GeoScript - Spatial Capabilities for Scripting Languages

Data Access - Layers

>>> from geoscript.layer import Shapefile

>>> states = Shapefile('states.shp')>>> states = states.reproject('epsg:3005')

Page 27: GeoScript - Spatial Capabilities for Scripting Languages

Data Access - Layer Info

>>> import geoscript.layer.Shapefile>>> shp = new Shapefile("states.shp")>>> shp.count49>>> shp.bounds(-124.73142200000001, 24.955967,-66.969849, 49.371735, EPSG:4326)

>>> shp.schema.fields.each {  fld -> println fld}the_geom: MultiPolygon(EPSG:4326)STATE_NAME: StringSTATE_FIPS: StringSUB_REGION: StringSTATE_ABBR: String

Page 28: GeoScript - Spatial Capabilities for Scripting Languages

Data Access - Layers

js> var ws = require("geoscript/workspace");      js> var dir = ws.Directory("data");  js> var states = dir.get("states");

js> states.query("STATE_ABBR like 'M%'").forEach(  >     function(feature) {  >         print(feature.get("STATE_NAME"));  >     }  > )MarylandMissouriMississippi...

Page 29: GeoScript - Spatial Capabilities for Scripting Languages

Styling and Rendering

• Taming SLDo Symbolizerso Scale dependenceo Thematics

Page 30: GeoScript - Spatial Capabilities for Scripting Languages

Styling - Stroke

>>> from geoscript.style import Stroke

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

Page 31: GeoScript - Spatial Capabilities for Scripting Languages

Styling - Fill

>>> import geoscript.style.Fill

>>> new Fill("gray")>>> new Fill("gray", 0.5))>>> new Fill("gray").hatch("backslash")>>> new Stroke("red",2) + new Fill("gray").hatch("times")

Page 32: GeoScript - Spatial Capabilities for Scripting Languages

Styling - Shape and Icon

js> var style = require("geoscript/style");

js> style.Shape({name: "star", fill: "yellow"})<Shape name: 'star', size: 6>

js> style.Icon("rainy.svg")<Icon url: 'rainy.svg'>

Page 33: GeoScript - Spatial Capabilities for Scripting Languages

Styling - Labels

>>> from geoscript.style import Label,Stroke,Fill,Shape

>>> font = 'bold 16px Arial'>>> Shape() + Label('name',font)     .point(displace=(20,0))

>>> Stroke() + Label('name',font)     .linear(offset=10)

>>> Fill() + Label('name',font).halo('white',2)

Page 34: GeoScript - Spatial Capabilities for Scripting Languages

Styling - Scale

>>> new Shape('#004d96', 5).range(3000) + new Icon('school20.png').range(1500, 3000)+ new Icon('school40.png').range(-1, 1500)

Page 35: GeoScript - Spatial Capabilities for Scripting Languages

Styling - Theming

>>> from geoscript.style Stroke, Fill, Label

>>> style = Stroke() + Label('STATE_ABBR', 14, 'Serif')>>> 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')

Page 36: GeoScript - Spatial Capabilities for Scripting Languages

Demos

Page 37: GeoScript - Spatial Capabilities for Scripting Languages

Voronoi Diagram Exampleimport geoscript.layer.*import geoscript.feature.*import geoscript.geom.*

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

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

Page 38: GeoScript - Spatial Capabilities for Scripting Languages

Gradient  Examplevar Directory = require("geoscript/workspace").Directory;var {Fill, gradient} = require("geoscript/style");var Map = require("geoscript/map").Map;

var states = Directory("data").get("states");

states.style = gradient({    expression: "PERSONS / LAND_KM",     values: [0, 200],     styles: [Fill("#000066"), Fill("red")],    classes: 10,     method: "exponential"}).and(    Fill("red").where("PERSONS / LAND_KM > 200"));

var map = Map([states]);

map.render({path: "states.png"});

Page 39: GeoScript - Spatial Capabilities for Scripting Languages

Shapefile to PostGISfrom geoscript.workspace import Directory, PostGISshps = Directory('shapefiles')shps.layers()

archsites = shps['archsites']archsites.proj.id

pg = PostGIS('demo')pg.layers()for layer in shps:  reprojected = shps[layer].reproject('epsg:4326')  pg.add(reprojected, name=layer)

pg.layers()archsites = pg['archsites']archsites.proj.id

Page 40: GeoScript - Spatial Capabilities for Scripting Languages

Road Map

• Raster• Rendering• WPS/GeoServer• Map Printing

Page 41: GeoScript - Spatial Capabilities for Scripting Languages

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 42: GeoScript - Spatial Capabilities for Scripting Languages

Thank you!

Page 43: GeoScript - Spatial Capabilities for Scripting Languages

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 44: GeoScript - Spatial Capabilities for Scripting Languages

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 45: GeoScript - Spatial Capabilities for Scripting Languages

USGS Earth Quakes

Read RSS Feed to a Shapefile

Page 46: GeoScript - Spatial Capabilities for Scripting Languages

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 47: GeoScript - Spatial Capabilities for Scripting Languages

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 48: GeoScript - Spatial Capabilities for Scripting Languages

Geometry Web Services 

Page 49: GeoScript - Spatial Capabilities for Scripting Languages

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 50: GeoScript - Spatial Capabilities for Scripting Languages

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 51: GeoScript - Spatial Capabilities for Scripting Languages

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 52: GeoScript - Spatial Capabilities for Scripting Languages

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


Top Related