12

Question

How do I convert an SVG file to GeoJSON format?

Desired Outcome:

I want to make a choropleth map using something like D3.js, or any of the other libraries out there.

Challenge:

I have an SVG file that I was able to obtain from public domain of the administrative regions for a particular province of a particular country. I believe I need to convert that to GeoJSON before being able to use it in the libraries that I am aware of.

  • 1
    What are exact the administrative regions of the particular province of the particular country? We could help find SHP or GeoJSON available files instead of fighting to solve the wrong problem. – ThomasG77 Nov 21 '15 at 1:53
5

I just wrote a library that converts an SVG image to a (slightly-incorrect) GeoJSON.

svg2geojson

It requires that you hand-edit your SVG to add two XML tags that associate an SVG location with a lat/long, and it provides a command-line tool to convert the file. It will even, if you like, take all the top-level groups (which is what Illustrator exports its layers as) and export them as separate files.

Usage

# First, install Node.js

$ npm install svg2geojson -g  # install globally for easy access to executable

$ svg2geojson -h
Usage: svg2geojson [options] file.svg

Options:
 -t, --tolerance=0.1 Distance (world meters) to sample curves to. (default: 0.1)
 -l, --layers        Split top-level groups into separate files. (default: one file)
 -o, --stdout        Output GeoJSON to stdout. (default: write files with names based on the SVG/layer)
 -m, --minimal       Make the GeoJSON as small as possible (not pretty).
 -p, --precision     Number of decimal places to format JSON numbers to. (default:6, as GeoJSON recommends)
 -d, --debug         Include ids for each SVG element in the features. (default: no properties)
 -v, --version       Output the version of svg2geojson as the first line on stdout (0.7.0).
 -h, --help          Show this help message.

$ svg2geojson my.svg
Wrote my.geojson

Limitations

  • Uses a naive/incorrect un-projection technique that assumes that a rectangular region of the image corresponds to a rectangular lat/long region. For example, on a rectangle about 1 mile wide by half a mile tall near San Francisco, the bottom edge is about 4 inches longer than the top edge. This was close enough for my needs.

  • Currently does not support SVG that uses paths with quadratic Bézier or elliptical arc commands. (I'm working on adding these.)

  • The version from Dec 2017 in a pull request of that repository also works if you want/need to georeference with 3 points instead of 2. I still had trouble getting my head around which way is up with both versions, and my resulting polygon was mirrored upside-down. It also would have taken a bit more work to join the properties from the SVG into the GeoJSON. Look forward to using in the future though. Thanks for the cool module. – thadk Jul 30 '18 at 22:06
  • This probably isn't ideal but I used the QGIS georeferencer plugin on a converted PNG of your SVG to help you make a table of points and check if a linear rectangular shift was even plausible, though I'm not sure how to look up the points in the SVG space correctly. – thadk Jul 30 '18 at 22:12
  • I've examined the library. I understand that the conversion occurs via a transformation of the SVG points within a geocoordinate bounding rectangle. But that makes 4 points (i.e. leftLongitude="0.1617178" topLatitude="23.4999998" rightLongitude="15.9990339" bottomLatitude="11.694295"). The two XML tags, all in all imply 8 bits of data and the docmentation for Prognoz has me thoroughly confused <p5:GeoItem Longitude="22.1471203091967" Latitude="44.2498454806746" X="0" Y="1" /> How can those 4 geocoordinates get translated into this 8 item data set? – Jerome May 30 at 11:50
4

There is a command-line tool by Phrogz mentioned below that I have not checked out:

https://gis.stackexchange.com/a/245085/35596


To anyone that comes here, the answer is: "it is quite difficult (at least for an experienced programmer but inexperienced cartographer)." It requires a more-than-superficial understanding of how the Spacial Reference Systems (SRS) work. You more or less need to geocode your .SVG using something like QGIS. How that is done? Still no clue. But the answer is:

"You cannot simply convert SVG to GeoJSON, as SVG is missing the fundamental geo references."

If you would like to proceed, begin searching on how to georeference a DXF file.

How to compute parameters for QGIS Affine transformation?

Germán Carrillo's answer there is very useful.

  • 1
    Maybe this information should be included in the question, i.e., that the svg file is not georeferenced. Or maybe the question should be: how can I geocode a .SVG using something like QGIS? – user55937 Jan 8 '16 at 0:06
  • Is georeferencing possible within the SVG format? – Michael Pell Jan 8 '16 at 9:34
  • 2
    I don't know exactly. It sounds to me like you have a map in SVG format that is to scale but not in a srs. So it sounds like you would need some ground control points with known coordinates, and then apply some transformation to data to georeference it in some real coordinate system. Maybe these will help?: gis.stackexchange.com/questions/33208/… gisforthought.com/… – user55937 Jan 8 '16 at 15:07
2

The command line tool ogr2ogr should be able do that. Something like:

ogr2ogr -f "GeoJSON" dst.json src.svg

Both of those formats are supported http://www.gdal.org/ogr_formats.html. If you're not familiar with ogr2ogr, the easiest way to download and install it is probably through https://trac.osgeo.org/osgeo4w/.

  • 2
    It's not that straight forward, the OGR SVG driver only supports a special kind of SVG that are created by the "Cloudmade Vector Stream Server" and in EPSG:3857. – AndrewHarvey Jun 30 '16 at 5:41
1

You don't need to convert from SVG to GeoJSON to use the image for a choropleth in d3, although it may be necessary for other libraries.

The path information on the SVG file (there must be at least one path for each state/country/state/subdivision in your map) is enough to map data to your SVG image in d3.

Let me put it in another way: if you can do a d3.select on your original svg that will return just one path per state/country/region then you can use d3 to build a choropleth. This is usually the case when you have a map in SVG. It is actually simpler than using a GeoJSON file as you don't need to worry about space location, projection etc. You may even want to tweak the original SVG to add missing information (like state names, that you can add as DOM IDs or Classes) before using it with D3 but that's usually not necessary.

On the other hand, as it was said before, SVG have just path/lines information, not geographic/spatial information, so if you want to convert from SVG to GeoJSON then you need to ADD/MAP geolocation information to your SVG image. For example, you can convert from svg to JSON first, then calculate/add geolocation information (this will depend on the region you are mapping) and generate a GeoJSON from that. As far as I know there is no out of the box tool to do this job for you though.

0

I would try source the format instead of SVG for the province you're looking for. Since the data are public domain chances are good you can find it. Try http://www.naturalearthdata.com/ or ask a question here. Then convert from Shapefile to GeoJSON or TopoJSON; MapShaper is your friend. From this point D3 should be in reach (excellent tutorial Let’s Make a Map)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.