Robin Kraft blog about

15 April 2012 - San Francisco

JTS Topology Suite and Clojure

This is the first in a series of posts about using the JTS Topology Suite (JTS) in Clojure, particularly in conjunction with Cascalog and Hadoop. To start I’ll briefly look at the setup needed for using JTS with Clojure. Further along I’ll explore replicating GIS operations using Cascalog/Hadoop.

JTS Topology Suite is “an API for modelling and manipulating 2-dimensional linear geometry”. That really just means you can use it to do typical GIS operations, like intersecting polygons or determining whether a line touches a polygon, among many other things.

Written in Java, JTS should work directly with Clojure, but there are already at least three partial wrappers for JTS that provide greater convenience.

I haven’t worked with these enough to pick a favorite, but I started with cljts because of the spatial functions and because it seems simpler than geoscript-clj. I’ll probably revisit this at some point.

To get started with cljts, add [cljts "0.1.0"] to your project.clj file. Then you can create a simple coordinate geometry:

user> (use 'cljts.geom)
user> (c 10 20)
#<Coordinate (10.0, 20.0, NaN)>

And there you have it. Create a polygon by stringing together coordinates in a vector, being careful to close the polygon by making the first and last coordinates the same. Note that polygon expects two rings - the external border and a hole - but you can create a polygon without a hole by replacing the hole linear-ring with nil:

user> (polygon (linear-ring [(c 20 40) (c 20 46) (c 34 56) (c 20 40)]) nil)
#<Polygon POLYGON ((20 40, 20 46, 34 56, 20 40))>

cljts provides an interface to JTS’ DE9-IM spatial relationship methods. You can check intersection using intersects?.

user> (def poly (polygon (linear-ring [(c 20 40) (c 20 46) (c 34 56) (c 20 40)]) nil))
user> (def pt (point (c 21 45)))
user> (intersects? pt poly)
true

Other functions for determining spatial relationships are described in the cljts.relation documentation.