Stay Connected with the Boundless Blog

GeoScript Ruby Port for Developers

ScooterLike many geospatial developers, I did not originally set out with the goal of becoming a developer. I was interested in geospatial applications and realized to get the most out of them I was going to need to learn how to “code”. After some early work with Python I realized that like Indiana Jones, I am not terribly fond of snakes. I had been experimenting with Ruby and found myself wishing I could be mining gems instead of charming snakes.

Many who’ve used Ruby in spatial applications know that Ruby and spatial are not always the best of friends and in my quest to make them play nice, I discovered JRuby and began my torrid love affair with the Java Virtual Machine (JVM). JRuby is an implementation of Ruby for the JVM, the benefits of using JRuby are many, but in this post I will focus on its interoperability with Java and other JVM languages.

At FOSS4G 2011 in Denver I first learned about GeoScript, which makes it easy to take advantage of GeoTools using dynamic scripting languages. I thought it sounded great but it left me wondering: “Why is there not a GeoScript for Ruby?” After a bit of poking around and not finding what I was looking for, I set to hacking and created GeoScript for Ruby. It is available on GitHub and as a gem.

gem install geoscript

The Ruby port is not as far along as the others (Python, JavaScript, Groovy, and Scala), but is capable of doing some basic spatial operations. For my own purposes, I needed to be able to reproject geometries, and convert to and from WKB and WKT. This functionality was the basis for the first release, and is what we’ll go over for the rest of this post.

We will look at these code samples as though they are being driven interactively using IRB (Interactive RuBy):

 >> require 'geoscript' # load geoscript library into IRB session
=> true

Geometries may be read easily from Well-Known Text (WKT) strings:

 >> ls = GeoScript::Geom.from_wkt 'LINESTRING (30 10, 10 30, 40 40)'
=> #<GeoScript::Geom::LineString:0x7f63e307>

The last line shows that an instance of GeoScript::Geom::LineString has been created from the specified (LINESTRING) WKT. This is an instance of GeoScript::Geom::LineString and not the underlying Java class of com.vividsolutions.jts.geom.LineString, because GeoScript takes advantage of the fact that JRuby allows Ruby class inheritance directly from Java classes to add additional niceties to the library with little effort. We can verify that this is the case by checking the class and java_class of our LineString object.

 >> ls.class 
=> GeoScript::Geom::LineString
>> ls.java_class
=> class com.vividsolutions.jts.geom.LineString

This means that all of the methods available to the Java class are exposed to the JRuby class as well. JRuby exposes the Java methods in their typical camel case form, but also in the snake case style with all lower case characters that is more typical of Ruby.

In the rest of the post we will use the Ruby style.

 >> ls.numPoints # Oppan Java Style 
=> 3
>> ls.num_points # Ruby Style
=> 3

Reprojecting geometries is easily accomplished with GeoScript.

 >> ls_2 = GeoScript::Projection.reproject ls, 'epsg:4326', 'epsg:3857' 
=> #<GeoScript::Geom::LineString:0x2c6f6fe1>

You may have noticed that we have been leaving the parentheses off of our method calls. This is intentional, as they are (mostly) optional in Ruby and Ruby style leans toward omitting them when possible. Another instance of GeoScript::Geom::LineString has been created here, this time with its coordinates reprojected from EPSG:4326 to EPSG:3857.

 >> ls.to_wkt 
=> "LINESTRING (30 10, 10 30, 40 40)"
>> ls_2.to_wkt
=> "LINESTRING (79544978.84519245 74569282.31931569, 8713934.405939918 30398359.508842178, -29513984.25511929 22214960.256206784)"

In addition to WKT, geometries may also be read from Well-Known Binary (WKB) from sources like PostGIS.

 >> p = GeoScript::Geom.from_wkb '0101000000000000000000F03F000000000000F03F' 
=> #<GeoScript::Geom::Point:0x79aa3359>
>> p.to_wkt
=> "POINT (1 1)"

If you need more of the functionality of GeoTools covered, the other implementations for Python, JavaScript, Scala, and Groovy are better options at this time. As demonstrated in this post, the Ruby implementation is currently capable of handling basic operations. Check out GeoScript Ruby on GitHub. I look forward to seeing your filed issues and pull requests. Let’s build this together!

Scooter  joined the team in July.  He previously worked at  Sanborn, where he built spatial web applications using both Esri and open source stacks as well as combinations of the two. At Boundless, he works on collaborative data management tools like GeoGit. Interested in joining our team? We’re hiring!