GeoScript - Spatial Capabilities for Scripting Languages

  • 1,988 views
Uploaded on

GeoScript adds spatial capabilities to dynamic scripting languages. With implementations in Python, JavaScript, Scala, and Groovy, GeoScript provides an interface to the powerful geospatial data …

GeoScript adds spatial capabilities to dynamic scripting languages. With implementations in Python, JavaScript, Scala, and Groovy, GeoScript provides an interface to the powerful geospatial data access, processing and rendering functionality of the GeoTools library.

GeoScript provides concise and simple apis that allow developers to perform a variety of tasks quickly. Some include:

Geoprocessing - Coordinate reference system transforms, geometry operations, and feature queries.
Data Juggling - GeoScript allows you to read and write feature data in a variety of formats. Converting Shapefiles to PostGIS tables, and processing on the fly while converting formats.
Mapping Services - Using a simple web framework in conjunction with GeoScript, it is possible to write custom geospatial services quickly and easily like a simple WMS or WFS implementation.


GeoScript is a new project but is growing in the number of users and contributors. Come check this talk out if you are interested in learning about a new tool to add to your geospatial hacking toolbox. Maybe you have tried to use GeoTools but find it too difficult and complex to use. Or perhaps your java skills are not where you would like them to be. If that is the case this talk, and GeoScript, might be just what you are looking for.

More in: Technology
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Be the first to comment
No Downloads

Views

Total Views
1,988
On Slideshare
0
From Embeds
0
Number of Embeds
1

Actions

Shares
Downloads
65
Comments
0
Likes
5

Embeds 0

No embeds

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
    No notes for slide

Transcript

  • 1. GeoScript Spatial Capabilities for Scripting Languages Justin Deolivera, Tim Schaub, and Jared Erickson
  • 2. Introduction
      • What is GeoScript?
        • Overview of languages
      • Motivation
        • GeoTools hard, scripting easy
        • Development turnaround
      • GeoScript Modules/API Overview
        • Geometry
        • Projection
        • Data Access
        • Styling
  • 3. Scripting Platform for JVM Languages
      • Similar API 
      • Respect languages differences
  • 4. Groovy
      • Groovy 
        • Dynamic language
        • Easy for Java programmers to learn 
        • Closures, DSLs
        • REPL, GUI Console
        • Compiles to Java Byte Code
        • Full access to Java libraries
      • http://geoscript.org/groovy
      • https://github.com/jericks/geoscript-groovy
  • 5. 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/
  • 6. Python
      • Jython 
        • Java implementation of Python 
        • Jython 2.5 = CPython 2.5
        • Full access to Java libraries
      • http://geoscript.org/py
      • https://github.com/jdeolive/geoscript-py
  • 7.
      • Scala
        • Combine functional and object-oriented programming
        • Statically typed
        • REPL
        • Compiles to Java bytecode
        • Full access to Java libraries
      • http://geoscript.org/scala/
      • https://github.com/dwins/geoscript.scala/
    Scala
  • 8. On the shoulders of giants...
  • 9. GeoScript Modules
  • 10. Geometry
      • Easy to use constructors
      • I/O
        • WKT/WKB
        • JSON
        • GML
      • Plotting
      • Transforms
  • 11. Geometry >>> from geoscript import geom >>> geom.Point(30, 10) POINT(30 10)
  • 12. Geometry >>>  import geoscript.geom.* >>> line = new LineString([[111.0, -47], [123.0, -48], [110.0, -47]]) LINESTRING (111 -47, 123 -48, 110 -47)
  • 13. Geometry js> var poly = geom.Point([10, 30]).   >     buffer(5) js> poly <Polygon [[[15, 30], [14.90...> js> poly.area 78.03612880645133
  • 14. Geometry - I/O >>>  from geoscript import geom >>>  point = geom.Point(30, 10) >>>  geom.writeKML(point) <kml:Point xmlns:kml=&quot;http://earth.google.com/kml/2.1&quot;>   <kml:coordinates>0.0,0.0</kml:coordinates> </kml:Point>
  • 15. 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>
  • 16. Geometry - I/O js> var geom = require(&quot;geoscript/geom&quot;); js> var point = geom.Point([1, 2]) js> point.json {&quot;type&quot;:&quot;Point&quot;,&quot;coordinates&quot;:[1,2]}
  • 17. 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)
  • 18. Geometry - Visualization js> var geom = require(&quot;geoscript/geom&quot;) js> require(&quot;geoscript/viewer&quot;).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...>
  • 19. Projection
      • Parse/encode WKT
      • Full GeoTools EPSG database
      • Re-projection
  • 20. Projection js> var proj = require(&quot;geoscript/proj&quot;); js> var p = proj.Projection(&quot;epsg:4326&quot;); js> p.wkt GEOGCS[&quot;WGS 84&quot;,    DATUM[&quot;World Geodetic System 1984&quot;,    ...
  • 21. 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
  • 22. Data Access
      • Read and Write Layers
      • Query Layers using CQL
      • I/O 
        • GeoJSON
        • GML
  • 23. Data Access - Workspace js> var ws = require(&quot;geoscript/workspace&quot;);        js> var dir = ws.Directory(&quot;data&quot;);    js> dir           <Directory [&quot;states&quot;]> js> var states = dir.get(&quot;states&quot;); js> states <Layer name: states, count: 49>
  • 24. Data Access - Workspace >>  from geoscript.workspace import PostGIS >>  pg = PostGIS('spearfish') >>  pg.layers() ['archsites', 'bugsites', ..., 'streams'] >> l = pg['archsites']
  • 25. Data Access - Workspace >>> import geoscript.workspace.H2 >>> import geoscript.geom.Point >>> import geoscript.feature.Feature >>> h2 = new H2(&quot;name&quot;, &quot;path&quot;) >>> layer = h2.create(&quot;points&quot;, [     new Field(&quot;geom&quot;,&quot;Point&quot;),     new Field(&quot;name&quot;,&quot;String&quot;) ]) >>> layer.add([new Point[1,1],&quot;one&quot;])
  • 26. Data Access - Layers >>> from geoscript.layer import Shapefile >>> states = Shapefile('states.shp') >>> states = states.reproject('epsg:3005')
  • 27. Data Access - Layer Info >>> import geoscript.layer.Shapefile >>> shp = new Shapefile(&quot;states.shp&quot;) >>> shp.count 49 >>> 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: String STATE_FIPS: String SUB_REGION: String STATE_ABBR: String
  • 28. Data Access - Layers js>  var ws = require(&quot;geoscript/workspace&quot;);        js>  var dir = ws.Directory(&quot;data&quot;);    js>  var states = dir.get(&quot;states&quot;); js> states.query(&quot;STATE_ABBR like 'M%'&quot;).forEach(   >     function(feature) {   >         print(feature.get(&quot;STATE_NAME&quot;));   >     }   > ) Maryland Missouri Mississippi ...
  • 29. Styling and Rendering
      • Taming SLD
        • Symbolizers
        • Scale dependence
        • Thematics
  • 30. 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')
  • 31. Styling - Fill >>> import geoscript.style.Fill >>>  new Fill(&quot;gray&quot;) >>>  new Fill(&quot;gray&quot;, 0.5)) >>>  new Fill(&quot;gray&quot;).hatch(&quot;backslash&quot;) >>>  new Stroke(&quot;red&quot;,2) + new Fill(&quot;gray&quot;).hatch(&quot;times&quot;)
  • 32. Styling - Shape and Icon js> var style = require(&quot;geoscript/style&quot;); js> style.Shape({name: &quot;star&quot;, fill: &quot;yellow&quot;}) <Shape name: 'star', size: 6> js> style.Icon(&quot;rainy.svg&quot;) <Icon url: 'rainy.svg'>
  • 33. 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)
  • 34. Styling - Scale >>> new Shape('#004d96', 5).range(3000)  + new Icon('school20.png').range(1500, 3000) + new Icon('school40.png').range(-1, 1500)
  • 35. 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')
  • 36. Demos
  • 37. Voronoi Diagram Example
    • import 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.voronoiDiagram
    • diagramLayer.add(schema.feature([voronoiGeom]))
  • 38. Gradient  Example var Directory = require(&quot;geoscript/workspace&quot;).Directory; var {Fill, gradient} = require(&quot;geoscript/style&quot;); var Map = require(&quot;geoscript/map&quot;).Map; var states = Directory(&quot;data&quot;).get(&quot;states&quot;); states.style = gradient({     expression: &quot;PERSONS / LAND_KM&quot;,      values: [0, 200],      styles: [Fill(&quot;#000066&quot;), Fill(&quot;red&quot;)],     classes: 10,      method: &quot;exponential&quot; }).and(     Fill(&quot;red&quot;).where(&quot;PERSONS / LAND_KM > 200&quot;) ); var map = Map([states]); map.render({path: &quot;states.png&quot;});
  • 39. Shapefile to PostGIS from geoscript.workspace import Directory, PostGIS shps = 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
  • 40. Road Map
      • Raster
      • Rendering
      • WPS/GeoServer
      • Map Printing
  • 41. 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
    •     
  • 42. Thank you!
  • 43. Centroids
    • import 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.cursor
    • while(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()  
  • 44. Shapefiles to PostGIS
    • import geoscript.workspace.*
    • import geoscript.layer.*
    • def dir = new Directory(&quot;/Users/jericks/Downloads/wash&quot;)
    • println(&quot;Shapefiles: ${dir.layers}&quot;)
    • def postgis = new PostGIS('postgres','localhost','5432','public','postgres', 'postgres')
    • println(&quot;PostGIS Layers: ${postgis.layers}&quot;)
    • dir.layers.each{name->
    •     def layer = dir.get(name)
    •     println(&quot;Adding ${layer.name}...&quot;)
    •     postgis.add(layer)
    • }
  • 45. USGS Earth Quakes Read RSS Feed to a Shapefile
  • 46.
    • import geoscript.geom.*
    • import geoscript.feature.*
    • import geoscript.layer.Layer
    • import 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 = &quot;http://earthquake.usgs.gov/earthquakes/catalogs/1day-M2.5.xml&quot;
    • def rss = new XmlParser().parse(url)
    • int c = 0
    • String dateFormat = &quot;yyyy-MM-dd'T'HH:mm:ss'Z'&quot;
    • rss.entry.each{e ->
    •     def title = e.title.text()
    •     def date = Date.parse(dateFormat, e.updated.text())
    •     def coordinate = e.&quot;georss:point&quot;.text().split(&quot; &quot;)
    •     double x = coordinate[1] as Double
    •     double y = coordinate[0] as Double
    •     def point = new Point(x,y)
    •     def elev = e.&quot;georss:elev&quot;.text() as Double
    •     Feature f = s.feature(['title':title,'date':date,
    •       'elevation': elev, 'the_geom': point],&quot;earthquake_${c}&quot;)
    •     layer.add(f)
    •     c++
    • }
  • 47. Web Applications
    • @GrabResolver(name=&quot;graffiti&quot;, root=&quot;http://simple-dm.googlecode.com/svn/repository&quot;)
    • @Grab(&quot;com.goodercode:graffiti:1.0-SNAPSHOT&quot;)
    • import graffiti.*
    • import geoscript.geom.Geometry
    • @Get(&quot;/buffer&quot;)
    • def buffer() {
    •     Geometry.fromWKT(params.geom).buffer(params.distance as double).wkt
    • }
    • @Get(&quot;/centroid&quot;)
    • def centroid() {
    •     Geometry.fromWKT(params.geom).centroid.wkt
    • }
    • @Get(&quot;/convexHull&quot;)
    • def convexHull() {
    •     Geometry.fromWKT(params.geom).convexHull.wkt
    • }
    • Graffiti.root 'graffiti'
    • Graffiti.serve this
    • Graffiti.start()
    •     
    Graffiti Micro Web Framework
  • 48. Geometry Web Services 
  • 49. Geometry Web Services Open Layers function centroid() {     var features = vectorLayer.features;     if (features.length == 0) {       alert(&quot;Please add some features!&quot;);     } 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(&quot;Error calculating centroids!&quot;);           }       );     } }
  • 50. WMS Server
    • import com.sun.grizzly.http.embed.GrizzlyWebServer
    • import com.sun.grizzly.http.servlet.ServletAdapter
    • import groovy.servlet.GroovySerlvet
    • @Grab(group='com.sun.grizzly',module='grizzly-servlet-webserver',  version='1.9.10')
    • def start() {
    •     def server = new GrizzlyWebServer(8080, &quot;web&quot;)
    •     def servlet = new ServletAdapter()
    •     servlet.contextPath = &quot;/geoscript&quot;
    •     servlet.servletInstance = new GroovyServlet()
    •     server.addGrizzlyAdapter(servlet, [&quot;/geoscript&quot;] as String[])
    •     server.start()
    • }
    • start()
  • 51. WMS Server... import geoscript.map.Map import geoscript.style.* import geoscript.layer.Shapefile import geoscript.geom.Bounds def file = new File(&quot;states.shp&quot;) def shp = new Shapefile(file) shp.style = new Fill(&quot;steelblue&quot;) + new Stroke(&quot;wheat&quot;, 0.1) def map = new Map(     width: 256,      height: 256,      layers: [shp],     proj: shp.proj,     fixAspectRatio: false ) def bbox = request.getParameter(&quot;BBOX&quot;).split(&quot;,&quot;) def bounds = new Bounds(bbox[0] as double, bbox[1] as double, bbox[2] as double, bbox[3] as double) map.bounds = bounds response.contentType = &quot;image/png&quot; map.render(response.outputStream) map.close()
  • 52. Geometry Command line 
    • echo &quot;POINT (1 1)&quot; | 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) return if (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) return if (opt.h) cli.usage() else println geoscript.geom.Geometry.fromWKT(System.in.text).bounds.geometry.wkt geom_buffer.groovy geom_envelope.groovy