sg-heatmap
Version:
Open-source all-in-one Swiss Army knife tool for creating Choropleth maps
88 lines (80 loc) • 3.01 kB
JavaScript
//
// Deprecated
// Switched to using GeoJSON
//
import fs from 'fs';
import xml2js from 'xml2js';
import { html2json as htmlParser } from 'html2json';
import { maxBy, minBy } from 'lodash';
import { encodePolyline, fromSVY21 } from './helpers/geometry';
var kmlParser = new xml2js.Parser({ explicitArray: false });
var kmls = {
region: 'MP14_REGION_NO_SEA_PL.kml',
planning_area: 'MP14_PLNG_AREA_NO_SEA_PL.kml',
subzone: 'MP14_SUBZONE_NO_SEA_PL.kml'
};
Object.keys(kmls).forEach(function (layer) {
var data = fs.readFileSync('data/raw/' + kmls[layer]);
kmlParser.parseString(data, function (err, result) {
if (err) console.error(err);
var parsed = result.kml.Document.Folder.Placemark;
fs.writeFileSync('data/semi/' + layer + '_raw.json', JSON.stringify(parsed));
var cleaned = parsed.map(function (area) {
var meta = area.description.replace(/\r?\n|\r/g, '');
meta = htmlParser(meta).child[0].child.find(function (_ref) {
var node = _ref.node,
tag = _ref.tag;
return node === 'element' && tag === 'body';
}).child.find(function (_ref2) {
var node = _ref2.node,
tag = _ref2.tag;
return node === 'element' && tag === 'table';
}).child[1].child[0].child[0].child.reduce(function (tb, tr) {
var key = tr.child[0].child[0].text.replace(/ /g, '_');
var value = tr.child[1].child[0].text;
tb[key] = value;
return tb;
}, {});
var center = fromSVY21([meta.X_ADDR, meta.Y_ADDR]);
var polygons = area.MultiGeometry.Polygon;
var boundary = polygons instanceof Array ? polygons.map(formatPolygon) : [formatPolygon(polygons)];
var key = meta.Subzone_Code || meta.Planning_Area_Code || meta.Region_Code;
return { key: key, meta: meta, center: center, boundary: boundary };
});
fs.writeFileSync('data/' + layer + '.json', JSON.stringify(cleaned));
});
});
function formatPolygon(polygon) {
var outerBoundaryIs = polygon.outerBoundaryIs,
innerBoundaryIs = polygon.innerBoundaryIs;
var result = {};
result.outer = formatLatLng(outerBoundaryIs.LinearRing.coordinates);
result.bounds = {
sw: [minBy(result.outer, function (v) {
return v[0];
})[0], minBy(result.outer, function (v) {
return v[1];
})[1]],
ne: [maxBy(result.outer, function (v) {
return v[0];
})[0], maxBy(result.outer, function (v) {
return v[1];
})[1]]
};
result.outer = encodePolyline(result.outer);
if (innerBoundaryIs) {
result.inners = innerBoundaryIs instanceof Array ? innerBoundaryIs.map(function (b) {
return formatLatLng(b.LinearRing.coordinates);
}) : [formatLatLng(innerBoundaryIs.LinearRing.coordinates)];
result.inners = result.inners.map(function (v) {
return encodePolyline(v);
});
}
return result;
}
function formatLatLng(str) {
return str.trim().split(' ').map(function (substr) {
var xyz = substr.split(',');
return [+xyz[1], +xyz[0]];
});
}