Converting SVG into WKT

Last week, I wrote about the some of the new functionality in Neatline that makes it possible to take SVG documents created in vector-editing programs like Adobe Illustrator and drag them out as spatial geometry on the map. Under the hood, this involves converting the raw SVG markup – which encodes geometry relative to a “document” space (think of pixels in a Photoshop file) – into latitude/longitude coordinates that can be rendered dynamically on the map. Specifically, I needed to generate Well-Known Text (WKT), the serialization format used by spatially-enabled relational databases like PostGIS and MySQL.

It turned out that there wasn’t any pre-existing utility for this, so I wrote a little library called SVG-to-WKT that does the conversion.

The top-level convert method takes a raw SVG document and spits back the equivalent WKT GEOMETRYCOLLECTION:

The library supports all SVG elements that directly encode geometry information, and exposes the individual helper methods that handle each of the elements:

line

polyline

polygon

rect

circle

ellipse

path

If you look at the output strings, you’ll notice that the Y-axis coordinates in the WKT are inverted relative to the input: SVGtoWKT.polyline('1,2 3,4') returns LINESTRING(1 -2,3 -4), not LINESTRING(1 2,3 4). This is because the Y-axis “grows” in the opposite direction on maps as it does in document space. In Illustrator, the coordinate grid starts at the top left corner, and the Y-axis increases as you move down on the page; on maps, the Y-axis increases as you move “up,” to the north. SVG-to-WKT just flips the Y-axis coordinates to make the orientation correct on the map.

TODO

Make it work in Node.js. This is actually a bit trickier that I thought it would be, because Node doesn’t implement the browser-native methods that jQuery’s parseXML uses. It may make sense to move to a generic XML parser that works in Node, which would be lighter-weight than jQuery anyway.

Instead of just being purely functional (SVG in, WKT out), it might be useful to return some sort of SVGDocument object that could then be used to generate specific WKT strings at different density levels, orientations, etc. This would have come in handy while writing the custom OpenLayers handler that Neatline uses to actually position the generated WKT on the map (more on this later).