WKT to SVG, the Hard Way

I needed an SVG with boundaries of "circoscrizioni" (administrative sub-municipal areas) in Turin (the city in which I live). The only thing I found was a CSV with the coordinates, in WKT format. "No problem, for sure a geo-hacker published some tool to convert the data!", I thought. I was wrong. A lot.

The only hint I found, aside installing dedicated geo-applications and import and modify and correct and export random stuffs, was about crunching the informations with a JS library to convert them in GeoJSON, then use another JS library to format in SVG. Apparently easy. Than I noticed that the coordinates in the original CSV where codified in EPSG:3003, an esotic coordinates system common in Italy (yes, each country has his own system. "The nice thing about standards is that you have so many to choose from", cit. Andrew Tanenbaum), and I had to map them in another one to put things together.

To make a long story short: here is the JS code I managed to assemble to produce my SVG file. It uses Omnivore, Proj4, D3 and jQuery (the latter, just for habit).

<hml>
  <head>
    <script src="https://code.jquery.com/jquery-2.2.4.min.js"></script>
    <link rel="stylesheet" href="http://cdn.leafletjs.com/leaflet/v0.7.7/leaflet.css" />
    <script src="http://cdn.leafletjs.com/leaflet/v0.7.7/leaflet.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/proj4js/2.3.14/proj4.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/proj4leaflet/0.7.2/proj4leaflet.min.js"></script>
    <script src='http://api.tiles.mapbox.com/mapbox.js/plugins/leaflet-omnivore/v0.3.1/leaflet-omnivore.min.js'></script>
    <script src="https://d3js.org/d3.v3.min.js" charset="utf-8"></script>
  </head>
  <body>

    <div id="map" style="width: 100%; height: 500px"></div>

    <script>
      $(document).ready(function() {
        /*
          Here I've created an array with my WKT elements. By hand, due those was just
          10, but this can be easily automated with a script
        */
        var nodes = new Array();
        nodes.push("POLYGON ((numbers numbers, numbers numbers...))");
        nodes.push("POLYGON ((numbers numbers, numbers numbers...))");
        nodes.push("POLYGON ((numbers numbers, numbers numbers...))");

        var jsons = new Array();
        var svg = d3.select("#map").append("svg").attr("width", 500).attr("height", 500);

        /*
          Here the input and output coordinates systems are inited.
          EPSG:4326 is quite common, and already included in the Proj4 library;
          for EPSG:3003 I needed to copy the definition from
          http://epsg.io/3003
          as suggested on the Proj4 website itself
        */
        proj4.defs('EPSG:3003', '+proj=tmerc +lat_0=0 +lon_0=9 +k=0.9996 +x_0=1500000 +y_0=0 +ellps=intl +towgs84=-104.1,-49.1,-9.9,0.971,-2.917,0.714,-11.68 +units=m +no_defs');
        var source = new proj4.Proj('EPSG:3003');
        var dest = new proj4.Proj('EPSG:4326');

        for(var e = 0; e < nodes.length; e++) {
          /*
            Here each WKT node is converted in GeoJSON
          */
          var node = nodes[e];
          var layer = omnivore.wkt.parse(node);
          var json = layer.toGeoJSON();
          
          /*
            Rude conversion of coordinates just into the parsed GeoJSON
          */
          for (var i = 0; i < json.features.length; i++) {
            var f = json.features[i];
            for (var j = 0; j < f.geometry.coordinates.length; j++) {
              for (var a = 0; a < f.geometry.coordinates[j].length; a++) {
                var p = f.geometry.coordinates[j][a];
                var p = new proj4.Point(p[0], p[1]);
                proj4.transform(source, dest, p);
                f.geometry.coordinates[j][a] = [p.x, p.y];
              }
            }
          }

          /*
            With D3, the GeoJSON is converted into SVG
          */          
          var path = d3.geo.path().projection(d3.geo.mercator().scale(20000));
          svg.append("g").attr("class", "black").selectAll("path").data(json.features).enter().append("path").attr("d", path);
        }
      });
    </script>
  </body>
</html>

Opening this into a browser, and waiting for a few seconds (the rude conversion with many nested loops is not that efficient), you obtain... a blank HTML page. The SVG image is shifted somewhere outside the viewport, probably I would had to translate the paths with some more refine on the D3 part but I preferred to just copy'n'paste the node on an empty file and adjust it in Inkscape.

For the records, here the final result. Not optimal, but at least something on which work a little more.

It is sad to see that, despite the many claims, geo-hacking and opendata manipulation is still not something everyone can do (and even nerds need to give a lot of fucks).