Jared Erickson & Justin Deoliveira
Spatial capabilities for scripting languages on the JVM.
Java
GeometryFactory geometryFactory = new GeometryFactory();
Point point = geometryFactory.createPoint(new Coordinate(-122.478899, 47.268195));
point.buffer(10);
Groovy
new Point(-122.478899, 47.268195).buffer(10)
Python
Point(-122.478899, 47.268195).buffer(10)
Java
StyleFactory styleFactory = CommonFactoryFinder.getStyleFactory(null);
SLDParser parser = new SLDParser(styleFactory, new File("states.sld"));
Style style = parser.readXML()[0];
ShapefileDataStore shapefile = new ShapefileDataStore(new File("states.shp").toURI().oURL());
FeatureSource<SimpleFeatureType, SimpleFeature> features =
shapefile.getFeatureSource(shapefile.getTypeNames()[0]);
MapContext context = new DefaultMapContext(new MapLayer[]{
new DefaultMapLayer(features, style)
});
BufferedImage image = new BufferedImage(300, 300, BufferedImage.TYPE_INT_ARGB);
Graphics2D graphics = image.createGraphics();
Rectangle screenArea = new Rectangle(0, 0, 300, 300);
ReferencedEnvelope mapArea = features.getBounds();
StreamingRenderer renderer = new StreamingRenderer();
renderer.setContext(context);
renderer.paint(graphics, screenArea, mapArea);
ImageIO.write(image, "png", new File("states.png"));
Groovy
Layer layer = new Shapefile("states.shp")
layer.style = new SLDReader().read(new File("states.sld"))
Map map = new Map(layers: [layer], width: 300, height: 300)
map.render(new File("states.png"))
Java
Map<String, Object> params = new HashMap<String, Object>();
params.put("dbtype", "postgis");
params.put("database", "usa");
params.put("schema", "public");
params.put("host", "localhost");
params.put("port", "5432");
params.put("user", "bob");
DataStore dataStore = DataStoreFinder.getDataStore(params);
try {
SimpleFeatureSource featureSource = dataStore.getFeatureSource("states");
SimpleFeatureCollection featureCollection = featureSource.getFeatures();
SimpleFeatureIterator it = featureCollection.features();
try {
while(it.hasNext()) {
SimpleFeature f = it.next();
System.out.println(f.getAttribute("STATE_NAME") + " at " + ((Geometry)f.DefaultGeometry()).getCentroid().toText());
}
} finally {
it.close();
}
} finally {
dataStore.dispose();
}
Python
PostGIS db = new PostGIS('usa', user: 'bob')
for f in db['states'].features():
print '%s at %s' % (f['STATE_NAME'], f.geom.centroid)
Java
SimpleFeatureTypeBuilder featureTypeBuilder = new SimpleFeatureTypeBuilder();
featureTypeBuilder.setName("points");
featureTypeBuilder.setSRS("EPSG:4326");
featureTypeBuilder.add("the_geom", Point);
featureTypeBuilder.add("id", Integer);
featureTypeBuilder.add("name", String);
SimpleFeatureType featureType = featureTypeBuilder.buildFeatureType();
File file = new File("points.shp");
Map<String,Object> params = new HashMap<String, Object>();
params.put("url", DataUtilities.fileToURL(file));
DataStore dataStore = DataStoreFinder.getDataStore(params);
dataStore.createSchema(featureType);
SimpleFeatureStore featureStore = (SimpleFeatureStore) dataStore.FeatureSource("points");
SimpleFeatureBuilder featureBuilder = new SimpleFeatureBuilder(featureType);
GeometryFactory geometryFactory = new GeometryFactory();
FeatureCollection features = new DefaultFeatureCollection(null, featureType)
featureBuilder.add(geometryFactory.createPoint(new Coordinate(1, 1)));
featureBuilder.add(1);
featureBuilder.add("one");
features.add(featureBuilder.buildFeature(null));
featureBuilder.add(geometryFactory.createPoint(new Coordinate(2, 2)));
featureBuilder.add(2);
featureBuilder.add("two");
features.add(featureBuilder.buildFeature(null));
featureStore.addFeatures(features);
dataStore.dispose();
JavaScript
var dir = new Directory('.');
var shp = dir.add(new Layer({
name: 'points',
fields: [{
name: 'geom', type: 'Point'
}, {
name: 'id', type: 'Integer'
}, {
name: 'name', type: 'String'
}]
});
shp.add([new Point([1,1], 1, 'one')]);
shp.add([new Point([2,2], 2, 'two')]);
Read, write, and translate spatial formats
import geoscript.workspace.*
import geoscript.layer.Layer
File dir = new File("shp")
PostGIS postgis = new PostGIS("naturalearth")
Directory directory = new Directory(dir)
directory.layers.each { Layer layer ->
postgis.add(layer)
}
Encode and decode exchange formats like GeoJSON, GML, WKT, and WKB
from geoscript.geom import readJSON, writeGML, readWKT, writeWKB
writeGML(readJSON("""{"type":"Point", "coordinates":[1,2]}"""))
writeWKB(readWKT("POINT (1 2)"))
Analyze data distribution
from geoscript.layer import GeoTIFF
dem = GeoTIFF('dem.tif')
h = dem.histogram()
data = zip(map(lambda (x,y): y, h.bins()), h.counts())
bar.xy(data, xlabel='Elevation').show()
Analyze data distribution
Process and transform data on the fly
var proj = require('geoscript/proj')
var Directory = require('geoscript/workspace').Directory
var Layer = require('geoscript/layer').Layer
var shp = new Directory('.').get('states.shp')
var points = new Layer({
name: 'Points',
fields: [{
name: 'geom', type: 'Point'
}]
});
shp.features.forEach(function(f) {
points.add({
name: proj.transform(f.get('geom').centroid), "epsg:4326", "epsg:26912"
});
});
Generate styles for rendering maps
from geoscript.style import *
from geoscript.render import *
from geoscript.layer import Shapefile
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')
style += Stroke(width=0.2) + Label('STATE_ABBR', 'Times New Roman 14px')
draw(Shapefile('states.shp'), style)
Generate styles for rendering maps
Generate styles for rendering maps
shp = Shapefile('counties.shp')
areas = [f['ALAND'] for f in shp.features()]
ranges = map(lambda r: 'ALAND BETWEEN %f AND %f'%r, zip(areas[:-1], areas[1:]))
fills = Fill('white').interpolate(Fill('red'), n=99)
style = reduce(lambda x,y:x+y, map(lambda (f,r): f.where(r), zip(fills, ranges)))
draw(shp, style, format='mapwindow')
Generate styles for rendering maps
Crop Raster with a Geometry
import geoscript.layer.*
import geoscript.geom.Point
import geoscript.proj.Projection
def tif = new GeoTIFF(new File("raster.tif"))
def raster = tif.read(new Projection("EPSG:4326"))
def geom = new Point(50,50).buffer(20)
def cropped = raster.crop(geom)
new GeoTIFF(new File("raster_circle_cropped.tif")).write(cropped)
Crop Raster with a Geometry
<repository>
<id>boundless</id>
<name>Boundless Maven Repository</name>
<url>http://repo.boundlessgeo.com/main</url>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
<dependency>
<groupId>org.geoscript</groupId>
<artifactId>geoscript-groovy</artifactId>
<version>1.3</version>
</dependency>
repositories {
maven {
url "http://repo.boundlessgeo.com/main"
}
}
dependencies {
compile "org.geoscript:geoscript-py:1.3"
}
Land Area Statistics
WNV Spatial Analysis
Goal was to create an animated map showing spread of WNV by state
CDC Data in PDF
Get Text from PDF
@Grapes(
@Grab(group='com.lowagie', module='itext', version='2.1.7')
)
import com.lowagie.text.pdf.parser.PdfTextExtractor
import com.lowagie.text.pdf.PdfReader
// Use iText to extract text from PDF
URL url = new URL("http://www.cdc.gov/westnile/resources/pdfs/cummulative/99_2013_cummulativeHumanCases.pdf")
PdfReader reader = new PdfReader(url)
PdfTextExtractor parser =new PdfTextExtractor(reader)
// Write text to a file in the data directory
File dir = new File("data")
dir.mkdir()
File file = new File(dir, "data.dat")
file.write(parser.getTextFromPage(1))
Convert text into CSV
State,1999,2000,2001,2002,2003,2004,2005,2006,2007,2008,2009,2010,2011,2012,2013,Total
Alabama,0,0,2,49,37,16,10,8,24,18,0,3,5,62,9,243
Alaska,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
Arizona,0,0,0,0,13,391,113,150,97,114,20,167,69,133,62,1329
Arkansas,0,0,0,43,25,28,28,29,20,9,6,7,1,64,18,278
...
Get data from Natural Earth
URL url = new URL("http://www.naturalearthdata.com/http//www.naturalearthdata.com/download/110m/cultural/ne_110m_admin_1_states_provinces_lakes.zip")
File file = new File("data/ne_110m_admin_1_states_provinces_lakes.zip")
if (!file.exists()) {
url.withInputStream { inp ->
file.withOutputStream { out ->
out << inp
}
}
}
File dir = new File("data")
def ant = new AntBuilder()
ant.unzip(src: file, dest: dir)
Join WNV Data to Natural Earth data
Workspace wk = new Directory("data")
Layer inLayer = wk.get("ne_110m_admin_1_states_provinces_lakes")
Schema schema = inLayer.schema
Schema newSchema = schema.addFields(newFields, "states")
Layer outLayer = wk.create(newSchema)
outLayer.withWriter { Writer w ->
inLayer.eachFeature { Feature f ->
w.add(f)
}
}
lines.subList(1, lines.size()).each { String line ->
List items = line.split(",")
String name = items[0]
if (name.equals("Dist. of")) {
name = "District of Columbia"
}
Filter filter = new Filter("name='${name}'")
items.eachWithIndex{ String item, int c ->
String fieldName = fieldNames[c]
if (!fieldName.equals("State")) {
Field field = outLayer.schema.field("y" + fieldName)
outLayer.update(field, Double.parseDouble(item), filter)
}
}
}
Draw maps of WNV spread for each year
List images = years.collect { String year ->
String name = "y${year}"
Field field = layer.schema.get(name)
Gradient style = new Gradient(layer, field, "EqualInterval", 5, "Reds")
layer.style = style
Map map = new Map(
layers: [osm, layer],
bounds: layer.bounds.expandBy(0.3),
proj: layer.proj,
backgroundColor: "white",
type: "gif"
)
def image = map.renderToImage()
def graphics = image.graphics
graphics.paint = Color.BLACK
graphics.font = new java.awt.Font("Arial", java.awt.Font.BOLD, 32)
graphics.drawString(year,5,30)
graphics.dispose()
ImageIO.write(image, "gif", new File(dir, "${year}.gif"))
image
}
GIF gif = new GIF()
gif.renderAnimated(images, new File(dir, "wnv.gif"), 1000)
WNV Spread by Year
Goal is to analyze protected lands usage for specific area.