We’ve been working on an R package to make creating and reading geojson and topojson easier in R. It’s a common way to encode spatial data often used in interactive maps. I put up a blog post recently at http://recology.info/2015/01/geojson-topojson-io/
Curious to get any feedback on this package. Been getting some from Twitter, but perhaps we can get some feedback in this location too…
The package looks great and covers a bunch of functionality I’ve been interested in for awhile, but never got around to implementing. I’ve actually run into a number of issues with using RGDAL and GeoJSON files particularly when it comes to writing polygons with holes, which seem to propagate into this package because of its use of RGDAL.
For example, the following is currently broken (the hole is missing):
library(sp)
library(geojsonio)
p1 = cbind(x=c(0,10,5,0),y=c(0,0,10,0))
p2 = cbind(x=c(2,8,5,2),y=c(2,2,8,2))
poly = SpatialPolygons(list(Polygons(list(Polygon(p1,FALSE),Polygon(p2,TRUE)),"1")))
geojson_json(poly)
library(rgeos) # Issue persists even if we assign hole ownership
poly2 = createSPComment(poly)
geojson_json(poly2)
Clearly this is an upstream issue with RGDAL and not specifically geojsonio but I think it is somewhat indicative of some of the existing infrastructure being broken. Has anyone at rOpenSci given any thought to working on updating/replacing core packages like sp, rgdal, etc.? I bring this up here because in my mind it make sense to move away from the existing sp classes (which are fundamentally broken) to something more geojson-like (e.g. more along the lines of the geo_list data structure in geojsonio). Being able to convert to the existing sp classes is clearly necessary for backwards compatibility but it would be great if newer useful packages like this could potentially start to move away from some of this legacy / liability.
I realize that most of this may not be directly relevant to the package and has more to do with the larger ecosystem but these are just some general thoughts and angst I’ve had for awhile. Clearly, I have not yet reached the point where I have started to tackle this on my own, but I’d be interested in finding others who similarly frustrated / motivated.
hi @rundel First of all, thanks for your feedback!
Embarrassingly, I think I may have caused that error. So in the geojson_list() functions, and related geojson_json() functions, they both try to coerce sp and friends spatial objects to lists or json manually within R just by manipulating the S4 objects. I have meant to finish these functions off, but haven’t gotten around to it yet. We could instead simply use the writeOGR() function to write geojson to disk, then read that raw json back in, coerce to a list if needed. However, I thought it would perhaps be better to avoid writing to and then reading from disk.
Maybe we should, at least for now, use writeOGR() when a sp class is given, so that we are getting proper geojson formatted json? Thoughts?
In terms of doing away with sp/rgdal - i’m up for that, but I’m definitely no geospatial expert. We can at least keep making geojsonio better and see how it goes…There is a lot of functionality in various packages based around sp classes, so would be good to not lose that as you say by maintaining backwards compat.
One thing we can do is leveraging javascript libraries. The new V8 package http://cran.r-project.org/web/packages/V8/index.html makes it easy to use a javascript library in R - there are lots of geospatial libraries in javascript
I made geojson_list() and geojson_json() use gdal’s geojson writer instead of the manual geojson creation stuff I was doing - not sure if we should stay with this in the long run, but this gives valid geojson quicker
The fix works on my end, I was misremembering (and oversimplifying) the RGDAL issue I had run across.
If you swap the order of the hole and exterior ring in the SpatialPolygon RGDAL gets confused and the resulting geojson polygon has the hole as the exterior and exterior and the hole:
library(sp)
library(geojsonio)
p1 = cbind(x=c(0,10,5,0),y=c(0,0,10,0))
p2 = cbind(x=c(2,8,5,2),y=c(2,2,8,2))
poly = SpatialPolygons(list(Polygons(list(Polygon(p2,TRUE),Polygon(p1,FALSE)),"1")))
geojson_json(poly)
library(rgeos) # Issue persists even if we assign hole ownership
poly2 = createSPComment(poly)
geojson_json(poly2)
This type of issue is not something that that geojsonlint picks up since it doesn’t do any kind of geometry checking.
Is there any way we can solve that problem you just described?
Going back to your larger issue of updating geospatial code to be more focused around geojson, etc. what are some topics you think we can tackle? We could start with some and see where it goes.
At the most fundamental level, in my mind there needs to be a replacement for the SpatialPolygons and descendent classes. If we replace that class we might as well go ahead and construct an entire new set of (internally consistent) geometry classes that more closely follow the Simple Features Standard so that there is a simple clean mapping between the native R objects and GeoJSON (or any of the other related data types). I’ve started playing around in this area a bit but have not put anything up on github yet.
@rundel It would be nice to see what you’re talking about, any chance of seeing some of the stuff you’ve been working on with respect to Simple Features Standard? What do you mean by descendant classes?
@sckott I’ve got the start of a package up at https://github.com/rundel/sfs that has all of the sfs classes and interfaces with the gdal library to directly read in files. This works on my machine but may need to some tweaking to play nice - as long as gdal is installed and reasonably current (1.11ish) and gdal-config is in your path everything should compile. Having a direct interface with gdal makes this a general solution that should be able to read everything from json to shapefiles (although gdal’s built in topojson implementation appears to be buggy).
I misspoke in referring to descendant classes, I meant the related classes SpatialPoints, SpatialLines, etc.