Today I felt rather like I was sifting through a bin of Lego looking for the parts to build a fantastical spaceship, but just not seeing it. I have been exploring the capabilities of polymaps. I like the code, and it seems like it is pretty functional, but I was missing something. The brochure content and examples made claims that polymaps could display GeoJSON tiles, but every time I followed a likely path to figure out how to make those tiles, I ran into a dead end.
I know how to clip GeoJSON data, or any vector format for that matter, using PostGIS. The example on this page describe the process in great detail. But I couldn’t see how that was useful. Even if I could pre-define the tile boundaries and generate clipped geometries, how was that going to help? I could only imagine every polygon getting sliced in at the tile boundary with a closing line.
So even though I knew about how to clip data to an arbitrary shape, I kept rummaging in Google and in various Geo Wikis looking for tips on how others did it, without finding anything useful.
Then I thought perhaps there was something in SVG that might help, perhaps a rule like a line up pen move without drawing that could be used to not draw the fake clipped boundary. On this page I found information on clipping. Because I used to generate my own map tiles and images back in the olden days (2002) for displaying maps generated from TIGER/Line data and for overlaying GPS traces on said maps, and because one (of many) approaches I used was to use the Batik toolkit to draw the GPS data inside of a bounding box and then clip the boundaries, I was familiar with the clipping command.
But what I didn’t think about was the fact that the clip could be applied to a tile and then tiles pushed together to form a map. The clipping boundary is a hard mask, and nothing outside of that boundary is drawn. So I had two pieces snapped into place. If I clipped the GeoJSON data to the tile bounding box, and if I then told the SVG render engine in Polymaps that the GeoJSON returned from the server should be clipped at the bounding box, then the hard black lines closing polygons at the tile border should not show up. Of course there are probably edge cases, like when a line of data actually lies right on the tile border. I would think the way to solve that would be to clip the GeoJSON one pixel bigger than requested on, say, the right and bottom of the four sides. But that is a minor detail that needs to be worked out, not a show stopper.
The last piece of the puzzle was to look at the source code and see if there was such a thing as clipping going on inside of the Polymaps source. And of course there is. Right at the top of the definition of the GeoJSON layer, there is the following code:
var geoJson = po.layer(load, unload), container = geoJson.container(), url, clip = true, clipId = "org.polymaps." + po.id(), clipHref = "url(#" + clipId + ")", clipPath = container.insertBefore(po.svg("clipPath"), container.firstChild), clipRect = clipPath.appendChild(po.svg("rect")), scale = "auto", zoom = null, features;
clipPath is being used to trim off all the data outside of the boundary of the tile, so I can generate GeoJSON tiles as needed using a simple bit of PostGIS enhanced SQL.