CartoDB-SQL-API/app/models/formats/topojson.js

133 lines
3.6 KiB
JavaScript
Raw Normal View History

2014-08-03 02:26:01 +08:00
var pg = require('./pg'),
_ = require('underscore'),
geojson = require('./geojson'),
TopoJSON = require('topojson');
2013-05-16 17:24:52 +08:00
function TopoJsonFormat() {
this.features = [];
}
2013-05-16 17:24:52 +08:00
2014-08-03 02:27:05 +08:00
TopoJsonFormat.prototype = new pg('topojson');
2013-05-16 17:24:52 +08:00
2014-08-03 02:27:05 +08:00
TopoJsonFormat.prototype.getQuery = function(sql, options) {
return geojson.prototype.getQuery(sql, options) + ' where ' + options.gn + ' is not null';
};
2013-05-16 17:24:52 +08:00
TopoJsonFormat.prototype.handleQueryRow = function(row) {
var _geojson = {
type: "Feature"
};
_geojson.geometry = JSON.parse(row[this.opts.gn]);
delete row[this.opts.gn];
delete row["the_geom_webmercator"];
_geojson.properties = row;
this.features.push(_geojson);
};
2013-05-16 17:24:52 +08:00
TopoJsonFormat.prototype.handleQueryEnd = function() {
if (this.error) {
this.callback(this.error);
return;
2013-05-16 17:24:52 +08:00
}
if ( this.opts.profiler ) this.opts.profiler.done('gotRows');
var topology = TopoJSON.topology(this.features, {
"quantization": 1e4,
"force-clockwise": true,
"property-filter": function(d) {
return d;
}
2013-05-16 17:24:52 +08:00
});
this.features = [];
var stream = this.opts.sink;
var jsonpCallback = this.opts.callback;
var bufferedRows = this.opts.bufferedRows;
var buffer = '';
function streamObjectSubtree(obj, key, done) {
buffer += '"' + key + '":';
var isObject = _.isObject(obj[key]),
isArray = _.isArray(obj[key]),
isIterable = isArray || isObject;
if (isIterable) {
buffer += isArray ? '[' : '{';
var subtreeKeys = Object.keys(obj[key]);
var pos = 0;
function streamNext() {
setImmediate(function() {
var subtreeKey = subtreeKeys.shift();
if (!isArray) {
buffer += '"' + subtreeKey + '":';
}
buffer += JSON.stringify(obj[key][subtreeKey]);
if (pos++ % (bufferedRows || 1000)) {
stream.write(buffer);
buffer = '';
}
if (subtreeKeys.length > 0) {
delete obj[key][subtreeKey];
buffer += ',';
streamNext();
} else {
buffer += isArray ? ']' : '}';
stream.write(buffer);
buffer = '';
done();
}
});
}
streamNext();
} else {
buffer += JSON.stringify(obj[key]);
done();
}
}
if (jsonpCallback) {
buffer += jsonpCallback + '(';
}
buffer += '{';
var keys = Object.keys(topology);
function sendResponse() {
setImmediate(function () {
var key = keys.shift();
function done() {
if (keys.length > 0) {
delete topology[key];
buffer += ',';
sendResponse();
} else {
buffer += '}';
if (jsonpCallback) {
buffer += ')';
}
stream.write(buffer);
stream.end();
topology = null;
}
}
streamObjectSubtree(topology, key, done);
});
}
sendResponse();
this.callback();
};
TopoJsonFormat.prototype.cancel = function() {
if (this.queryCanceller) {
this.queryCanceller.call();
}
};
2013-05-16 17:24:52 +08:00
2014-08-03 02:27:05 +08:00
module.exports = TopoJsonFormat;