Server : LiteSpeed System : Linux server 3.10.0-1160.90.1.el7.x86_64 #1 SMP Thu May 4 15:21:22 UTC 2023 x86_64 User : alsaif ( 1057) PHP Version : 7.4.33 Disable Function : show_source,posix_kill,posix_mkfifo,posix_getpwuid,posix_setpgid,posix_setsid,posix_setuid,posix_setgid,posix_seteuid,posix_setegid,posix_uname Directory : /home/alsaif/public_html/media/com_phocagallery/js/leaflet-omnivore/ |
!function(e){if("object"==typeof exports)module.exports=e();else if("function"==typeof define&&define.amd)define(e);else{var o;"undefined"!=typeof window?o=window:"undefined"!=typeof global?o=global:"undefined"!=typeof self&&(o=self),o.omnivore=e()}}(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error("Cannot find module '"+o+"'")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(_dereq_,module,exports){
var xhr = _dereq_('corslite'),
csv2geojson = _dereq_('csv2geojson'),
wellknown = _dereq_('wellknown'),
topojson = _dereq_('topojson'),
toGeoJSON = _dereq_('togeojson');
module.exports.geojson = geojsonLoad;
module.exports.topojson = topojsonLoad;
module.exports.topojson.parse = topojsonParse;
module.exports.csv = csvLoad;
module.exports.csv.parse = csvParse;
module.exports.gpx = gpxLoad;
module.exports.gpx.parse = gpxParse;
module.exports.kml = kmlLoad;
module.exports.kml.parse = kmlParse;
module.exports.wkt = wktLoad;
module.exports.wkt.parse = wktParse;
function addData(l, d) {
if ('addData' in l) l.addData(d);
if ('setGeoJSON' in l) l.setGeoJSON(d);
}
/**
* Load a [GeoJSON](http://geojson.org/) document into a layer and return the layer.
*
* @param {string} url
* @param {object} options
* @param {object} customLayer
* @returns {object}
*/
function geojsonLoad(url, options, customLayer) {
var layer = customLayer || L.geoJson();
xhr(url, function(err, response) {
if (err) return layer.fire('error', { error: err });
addData(layer, JSON.parse(response.responseText));
layer.fire('ready');
});
return layer;
}
/**
* Load a [TopoJSON](https://github.com/mbostock/topojson) document into a layer and return the layer.
*
* @param {string} url
* @param {object} options
* @param {object} customLayer
* @returns {object}
*/
function topojsonLoad(url, options, customLayer) {
var layer = customLayer || L.geoJson();
xhr(url, onload);
function onload(err, response) {
if (err) return layer.fire('error', { error: err });
addData(layer, topojsonParse(response.responseText));
layer.fire('ready');
}
return layer;
}
/**
* Load a CSV document into a layer and return the layer.
*
* @param {string} url
* @param {object} options
* @param {object} customLayer
* @returns {object}
*/
function csvLoad(url, options, customLayer) {
var layer = customLayer || L.geoJson();
xhr(url, onload);
function onload(err, response) {
var error;
if (err) return layer.fire('error', { error: err });
function avoidReady() {
error = true;
}
layer.on('error', avoidReady);
csvParse(response.responseText, options, layer);
layer.off('error', avoidReady);
if (!error) layer.fire('ready');
}
return layer;
}
/**
* Load a GPX document into a layer and return the layer.
*
* @param {string} url
* @param {object} options
* @param {object} customLayer
* @returns {object}
*/
function gpxLoad(url, options, customLayer) {
var layer = customLayer || L.geoJson();
xhr(url, onload);
function onload(err, response) {
var error;
if (err) return layer.fire('error', { error: err });
function avoidReady() {
error = true;
}
layer.on('error', avoidReady);
gpxParse(response.responseXML || response.responseText, options, layer);
layer.off('error', avoidReady);
if (!error) layer.fire('ready');
}
return layer;
}
/**
* Load a [KML](https://developers.google.com/kml/documentation/) document into a layer and return the layer.
*
* @param {string} url
* @param {object} options
* @param {object} customLayer
* @returns {object}
*/
function kmlLoad(url, options, customLayer) {
var layer = L.geoJson();
xhr(url, onload);
function onload(err, response) {
var error;
if (err) return layer.fire('error', { error: err });
function avoidReady() {
error = true;
}
layer.on('error', avoidReady);
kmlParse(response.responseXML || response.responseText, options, layer);
layer.off('error', avoidReady);
if (!error) layer.fire('ready');
}
return layer;
}
/**
* Load a WKT (Well Known Text) string into a layer and return the layer
*
* @param {string} url
* @param {object} options
* @param {object} customLayer
* @returns {object}
*/
function wktLoad(url, options, customLayer) {
var layer = customLayer || L.geoJson();
xhr(url, onload);
function onload(err, response) {
if (err) return layer.fire('error', { error: err });
wktParse(response.responseText, options, layer);
layer.fire('ready');
}
return layer;
}
function topojsonParse(data) {
var o = typeof data === 'string' ?
JSON.parse(data) : data;
var features = [];
for (var i in o.objects) {
var ft = topojson.feature(o, o.objects[i]);
if (ft.features) features = features.concat(ft.features);
else features = features.concat([ft]);
}
return features;
}
function csvParse(csv, options, layer) {
layer = layer || L.geoJson();
options = options || {};
csv2geojson.csv2geojson(csv, options, onparse);
function onparse(err, geojson) {
if (err) return layer.fire('error', { error: err });
addData(layer, geojson);
}
return layer;
}
function gpxParse(gpx, options, layer) {
var xml = parseXML(gpx);
if (!xml) return layer.fire('error', {
error: 'Could not parse GPX'
});
layer = layer || L.geoJson();
var geojson = toGeoJSON.gpx(xml);
addData(layer, geojson);
return layer;
}
function kmlParse(gpx, options, layer) {
var xml = parseXML(gpx);
if (!xml) return layer.fire('error', {
error: 'Could not parse GPX'
});
layer = layer || L.geoJson();
var geojson = toGeoJSON.kml(xml);
addData(layer, geojson);
return layer;
}
function wktParse(wkt, options, layer) {
layer = layer || L.geoJson();
var geojson = wellknown(wkt);
addData(layer, geojson);
return layer;
}
function parseXML(str) {
if (typeof str === 'string') {
return (new DOMParser()).parseFromString(str, 'text/xml');
} else {
return str;
}
}
},{"corslite":5,"csv2geojson":6,"togeojson":9,"topojson":10,"wellknown":38}],2:[function(_dereq_,module,exports){
},{}],3:[function(_dereq_,module,exports){
module.exports=_dereq_(2)
},{}],4:[function(_dereq_,module,exports){
// shim for using process in browser
var process = module.exports = {};
process.nextTick = (function () {
var canSetImmediate = typeof window !== 'undefined'
&& window.setImmediate;
var canPost = typeof window !== 'undefined'
&& window.postMessage && window.addEventListener
;
if (canSetImmediate) {
return function (f) { return window.setImmediate(f) };
}
if (canPost) {
var queue = [];
window.addEventListener('message', function (ev) {
var source = ev.source;
if ((source === window || source === null) && ev.data === 'process-tick') {
ev.stopPropagation();
if (queue.length > 0) {
var fn = queue.shift();
fn();
}
}
}, true);
return function nextTick(fn) {
queue.push(fn);
window.postMessage('process-tick', '*');
};
}
return function nextTick(fn) {
setTimeout(fn, 0);
};
})();
process.title = 'browser';
process.browser = true;
process.env = {};
process.argv = [];
process.binding = function (name) {
throw new Error('process.binding is not supported');
}
// TODO(shtylman)
process.cwd = function () { return '/' };
process.chdir = function (dir) {
throw new Error('process.chdir is not supported');
};
},{}],5:[function(_dereq_,module,exports){
function xhr(url, callback, cors) {
var sent = false;
if (typeof window.XMLHttpRequest === 'undefined') {
return callback(Error('Browser not supported'));
}
if (typeof cors === 'undefined') {
var m = url.match(/^\s*https?:\/\/[^\/]*/);
cors = m && (m[0] !== location.protocol + '//' + location.domain +
(location.port ? ':' + location.port : ''));
}
var x;
function isSuccessful(status) {
return status >= 200 && status < 300 || status === 304;
}
if (cors && (
// IE7-9 Quirks & Compatibility
typeof window.XDomainRequest === 'object' ||
// IE9 Standards mode
typeof window.XDomainRequest === 'function'
)) {
// IE8-10
x = new window.XDomainRequest();
// Ensure callback is never called synchronously, i.e., before
// x.send() returns (this has been observed in the wild).
// See https://github.com/mapbox/mapbox.js/issues/472
var original = callback;
callback = function() {
if (sent) {
original.apply(this, arguments);
} else {
var that = this, args = arguments;
setTimeout(function() {
original.apply(that, args);
}, 0);
}
}
} else {
x = new window.XMLHttpRequest();
}
function loaded() {
if (
// XDomainRequest
x.status === undefined ||
// modern browsers
isSuccessful(x.status)) callback.call(x, null, x);
else callback.call(x, x, null);
}
// Both `onreadystatechange` and `onload` can fire. `onreadystatechange`
// has [been supported for longer](http://stackoverflow.com/a/9181508/229001).
if ('onload' in x) {
x.onload = loaded;
} else {
x.onreadystatechange = function readystate() {
if (x.readyState === 4) {
loaded();
}
};
}
// Call the callback with the XMLHttpRequest object as an error and prevent
// it from ever being called again by reassigning it to `noop`
x.onerror = function error(evt) {
// XDomainRequest provides no evt parameter
callback.call(this, evt || true, null);
callback = function() { };
};
// IE9 must have onprogress be set to a unique function.
x.onprogress = function() { };
x.ontimeout = function(evt) {
callback.call(this, evt, null);
callback = function() { };
};
x.onabort = function(evt) {
callback.call(this, evt, null);
callback = function() { };
};
// GET is the only supported HTTP Verb by XDomainRequest and is the
// only one supported here.
x.open('GET', url, true);
// Send the request. Sending data is not supported.
x.send(null);
sent = true;
return x;
}
if (typeof module !== 'undefined') module.exports = xhr;
},{}],6:[function(_dereq_,module,exports){
var dsv = _dereq_('dsv'),
sexagesimal = _dereq_('sexagesimal');
function isLat(f) { return !!f.match(/(Lat)(itude)?/gi); }
function isLon(f) { return !!f.match(/(L)(on|ng)(gitude)?/i); }
function keyCount(o) {
return (typeof o == 'object') ? Object.keys(o).length : 0;
}
function autoDelimiter(x) {
var delimiters = [',', ';', '\t', '|'];
var results = [];
delimiters.forEach(function(delimiter) {
var res = dsv(delimiter).parse(x);
if (res.length >= 1) {
var count = keyCount(res[0]);
for (var i = 0; i < res.length; i++) {
if (keyCount(res[i]) !== count) return;
}
results.push({
delimiter: delimiter,
arity: Object.keys(res[0]).length,
});
}
});
if (results.length) {
return results.sort(function(a, b) {
return b.arity - a.arity;
})[0].delimiter;
} else {
return null;
}
}
function auto(x) {
var delimiter = autoDelimiter(x);
if (!delimiter) return null;
return dsv(delimiter).parse(x);
}
function csv2geojson(x, options, callback) {
if (!callback) {
callback = options;
options = {};
}
options.delimiter = options.delimiter || ',';
var latfield = options.latfield || '',
lonfield = options.lonfield || '';
var features = [],
featurecollection = { type: 'FeatureCollection', features: features };
if (options.delimiter === 'auto' && typeof x == 'string') {
options.delimiter = autoDelimiter(x);
if (!options.delimiter) return callback({
type: 'Error',
message: 'Could not autodetect delimiter'
});
}
var parsed = (typeof x == 'string') ? dsv(options.delimiter).parse(x) : x;
if (!parsed.length) return callback(null, featurecollection);
if (!latfield || !lonfield) {
for (var f in parsed[0]) {
if (!latfield && isLat(f)) latfield = f;
if (!lonfield && isLon(f)) lonfield = f;
}
if (!latfield || !lonfield) {
var fields = [];
for (var k in parsed[0]) fields.push(k);
return callback({
type: 'Error',
message: 'Latitude and longitude fields not present',
data: parsed,
fields: fields
});
}
}
var errors = [];
for (var i = 0; i < parsed.length; i++) {
if (parsed[i][lonfield] !== undefined &&
parsed[i][lonfield] !== undefined) {
var lonk = parsed[i][lonfield],
latk = parsed[i][latfield],
lonf, latf,
a;
a = sexagesimal(lonk, 'EW');
if (a) lonk = a;
a = sexagesimal(latk, 'NS');
if (a) latk = a;
lonf = parseFloat(lonk);
latf = parseFloat(latk);
if (isNaN(lonf) ||
isNaN(latf)) {
errors.push({
message: 'A row contained an invalid value for latitude or longitude',
row: parsed[i]
});
} else {
if (!options.includeLatLon) {
delete parsed[i][lonfield];
delete parsed[i][latfield];
}
features.push({
type: 'Feature',
properties: parsed[i],
geometry: {
type: 'Point',
coordinates: [
parseFloat(lonf),
parseFloat(latf)
]
}
});
}
}
}
callback(errors.length ? errors: null, featurecollection);
}
function toLine(gj) {
var features = gj.features;
var line = {
type: 'Feature',
geometry: {
type: 'LineString',
coordinates: []
}
};
for (var i = 0; i < features.length; i++) {
line.geometry.coordinates.push(features[i].geometry.coordinates);
}
line.properties = features[0].properties;
return {
type: 'FeatureCollection',
features: [line]
};
}
function toPolygon(gj) {
var features = gj.features;
var poly = {
type: 'Feature',
geometry: {
type: 'Polygon',
coordinates: [[]]
}
};
for (var i = 0; i < features.length; i++) {
poly.geometry.coordinates[0].push(features[i].geometry.coordinates);
}
poly.properties = features[0].properties;
return {
type: 'FeatureCollection',
features: [poly]
};
}
module.exports = {
isLon: isLon,
isLat: isLat,
csv: dsv.csv.parse,
tsv: dsv.tsv.parse,
dsv: dsv,
auto: auto,
csv2geojson: csv2geojson,
toLine: toLine,
toPolygon: toPolygon
};
},{"dsv":7,"sexagesimal":8}],7:[function(_dereq_,module,exports){
var fs = _dereq_("fs");
module.exports = new Function("dsv.version = \"0.0.3\";\n\ndsv.tsv = dsv(\"\\t\");\ndsv.csv = dsv(\",\");\n\nfunction dsv(delimiter) {\n var dsv = {},\n reFormat = new RegExp(\"[\\\"\" + delimiter + \"\\n]\"),\n delimiterCode = delimiter.charCodeAt(0);\n\n dsv.parse = function(text, f) {\n var o;\n return dsv.parseRows(text, function(row, i) {\n if (o) return o(row, i - 1);\n var a = new Function(\"d\", \"return {\" + row.map(function(name, i) {\n return JSON.stringify(name) + \": d[\" + i + \"]\";\n }).join(\",\") + \"}\");\n o = f ? function(row, i) { return f(a(row), i); } : a;\n });\n };\n\n dsv.parseRows = function(text, f) {\n var EOL = {}, // sentinel value for end-of-line\n EOF = {}, // sentinel value for end-of-file\n rows = [], // output rows\n N = text.length,\n I = 0, // current character index\n n = 0, // the current line number\n t, // the current token\n eol; // is the current token followed by EOL?\n\n function token() {\n if (I >= N) return EOF; // special case: end of file\n if (eol) return eol = false, EOL; // special case: end of line\n\n // special case: quotes\n var j = I;\n if (text.charCodeAt(j) === 34) {\n var i = j;\n while (i++ < N) {\n if (text.charCodeAt(i) === 34) {\n if (text.charCodeAt(i + 1) !== 34) break;\n ++i;\n }\n }\n I = i + 2;\n var c = text.charCodeAt(i + 1);\n if (c === 13) {\n eol = true;\n if (text.charCodeAt(i + 2) === 10) ++I;\n } else if (c === 10) {\n eol = true;\n }\n return text.substring(j + 1, i).replace(/\"\"/g, \"\\\"\");\n }\n\n // common case: find next delimiter or newline\n while (I < N) {\n var c = text.charCodeAt(I++), k = 1;\n if (c === 10) eol = true; // \\n\n else if (c === 13) { eol = true; if (text.charCodeAt(I) === 10) ++I, ++k; } // \\r|\\r\\n\n else if (c !== delimiterCode) continue;\n return text.substring(j, I - k);\n }\n\n // special case: last token before EOF\n return text.substring(j);\n }\n\n while ((t = token()) !== EOF) {\n var a = [];\n while (t !== EOL && t !== EOF) {\n a.push(t);\n t = token();\n }\n if (f && !(a = f(a, n++))) continue;\n rows.push(a);\n }\n\n return rows;\n };\n\n dsv.format = function(rows) {\n if (Array.isArray(rows[0])) return dsv.formatRows(rows); // deprecated; use formatRows\n var fieldSet = {}, fields = [];\n\n // Compute unique fields in order of discovery.\n rows.forEach(function(row) {\n for (var field in row) {\n if (!(field in fieldSet)) {\n fields.push(fieldSet[field] = field);\n }\n }\n });\n\n return [fields.map(formatValue).join(delimiter)].concat(rows.map(function(row) {\n return fields.map(function(field) {\n return formatValue(row[field]);\n }).join(delimiter);\n })).join(\"\\n\");\n };\n\n dsv.formatRows = function(rows) {\n return rows.map(formatRow).join(\"\\n\");\n };\n\n function formatRow(row) {\n return row.map(formatValue).join(delimiter);\n }\n\n function formatValue(text) {\n return reFormat.test(text) ? \"\\\"\" + text.replace(/\\\"/g, \"\\\"\\\"\") + \"\\\"\" : text;\n }\n\n return dsv;\n}\n" + ";return dsv")();
},{"fs":2}],8:[function(_dereq_,module,exports){
module.exports = function(x, dims) {
if (!dims) dims = 'NSEW';
if (typeof x !== 'string') return null;
var r = /^([0-9.]+)°? *(?:([0-9.]+)['’′‘] *)?(?:([0-9.]+)(?:''|"|”|″) *)?([NSEW])?/,
m = x.match(r);
if (!m) return null;
else if (m[4] && dims.indexOf(m[4]) === -1) return null;
else return (((m[1]) ? parseFloat(m[1]) : 0) +
((m[2] ? parseFloat(m[2]) / 60 : 0)) +
((m[3] ? parseFloat(m[3]) / 3600 : 0))) *
((m[4] && m[4] === 'S' || m[4] === 'W') ? -1 : 1);
};
},{}],9:[function(_dereq_,module,exports){
(function (process){toGeoJSON = (function() {
'use strict';
var removeSpace = (/\s*/g),
trimSpace = (/^\s*|\s*$/g),
splitSpace = (/\s+/);
// generate a short, numeric hash of a string
function okhash(x) {
if (!x || !x.length) return 0;
for (var i = 0, h = 0; i < x.length; i++) {
h = ((h << 5) - h) + x.charCodeAt(i) | 0;
} return h;
}
// all Y children of X
function get(x, y) { return x.getElementsByTagName(y); }
function attr(x, y) { return x.getAttribute(y); }
function attrf(x, y) { return parseFloat(attr(x, y)); }
// one Y child of X, if any, otherwise null
function get1(x, y) { var n = get(x, y); return n.length ? n[0] : null; }
// https://developer.mozilla.org/en-US/docs/Web/API/Node.normalize
function norm(el) { if (el.normalize) { el.normalize(); } return el; }
// cast array x into numbers
function numarray(x) {
for (var j = 0, o = []; j < x.length; j++) o[j] = parseFloat(x[j]);
return o;
}
function clean(x) {
var o = {};
for (var i in x) if (x[i]) o[i] = x[i];
return o;
}
// get the content of a text node, if any
function nodeVal(x) { if (x) {norm(x);} return x && x.firstChild && x.firstChild.nodeValue; }
// get one coordinate from a coordinate array, if any
function coord1(v) { return numarray(v.replace(removeSpace, '').split(',')); }
// get all coordinates from a coordinate array as [[],[]]
function coord(v) {
var coords = v.replace(trimSpace, '').split(splitSpace),
o = [];
for (var i = 0; i < coords.length; i++) {
o.push(coord1(coords[i]));
}
return o;
}
function coordPair(x) {
var ll = [attrf(x, 'lon'), attrf(x, 'lat')],
ele = get1(x, 'ele');
if (ele) ll.push(parseFloat(nodeVal(ele)));
return ll;
}
// create a new feature collection parent object
function fc() {
return {
type: 'FeatureCollection',
features: []
};
}
var serializer;
if (typeof XMLSerializer !== 'undefined') {
serializer = new XMLSerializer();
// only require xmldom in a node environment
} else if (typeof exports === 'object' && typeof process === 'object' && !process.browser) {
serializer = new (_dereq_('xmldom').XMLSerializer)();
}
function xml2str(str) { return serializer.serializeToString(str); }
var t = {
kml: function(doc, o) {
o = o || {};
var gj = fc(),
// styleindex keeps track of hashed styles in order to match features
styleIndex = {},
// atomic geospatial types supported by KML - MultiGeometry is
// handled separately
geotypes = ['Polygon', 'LineString', 'Point', 'Track'],
// all root placemarks in the file
placemarks = get(doc, 'Placemark'),
styles = get(doc, 'Style');
for (var k = 0; k < styles.length; k++) {
styleIndex['#' + attr(styles[k], 'id')] = okhash(xml2str(styles[k])).toString(16);
}
for (var j = 0; j < placemarks.length; j++) {
gj.features = gj.features.concat(getPlacemark(placemarks[j]));
}
function gxCoord(v) { return numarray(v.split(' ')); }
function gxCoords(root) {
var elems = get(root, 'coord', 'gx'), coords = [];
for (var i = 0; i < elems.length; i++) coords.push(gxCoord(nodeVal(elems[i])));
return coords;
}
function getGeometry(root) {
var geomNode, geomNodes, i, j, k, geoms = [];
if (get1(root, 'MultiGeometry')) return getGeometry(get1(root, 'MultiGeometry'));
if (get1(root, 'MultiTrack')) return getGeometry(get1(root, 'MultiTrack'));
for (i = 0; i < geotypes.length; i++) {
geomNodes = get(root, geotypes[i]);
if (geomNodes) {
for (j = 0; j < geomNodes.length; j++) {
geomNode = geomNodes[j];
if (geotypes[i] == 'Point') {
geoms.push({
type: 'Point',
coordinates: coord1(nodeVal(get1(geomNode, 'coordinates')))
});
} else if (geotypes[i] == 'LineString') {
geoms.push({
type: 'LineString',
coordinates: coord(nodeVal(get1(geomNode, 'coordinates')))
});
} else if (geotypes[i] == 'Polygon') {
var rings = get(geomNode, 'LinearRing'),
coords = [];
for (k = 0; k < rings.length; k++) {
coords.push(coord(nodeVal(get1(rings[k], 'coordinates'))));
}
geoms.push({
type: 'Polygon',
coordinates: coords
});
} else if (geotypes[i] == 'Track') {
geoms.push({
type: 'LineString',
coordinates: gxCoords(geomNode)
});
}
}
}
}
return geoms;
}
function getPlacemark(root) {
var geoms = getGeometry(root), i, properties = {},
name = nodeVal(get1(root, 'name')),
styleUrl = nodeVal(get1(root, 'styleUrl')),
description = nodeVal(get1(root, 'description')),
timeSpan = get1(root, 'TimeSpan'),
extendedData = get1(root, 'ExtendedData');
if (!geoms.length) return [];
if (name) properties.name = name;
if (styleUrl && styleIndex[styleUrl]) {
properties.styleUrl = styleUrl;
properties.styleHash = styleIndex[styleUrl];
}
if (description) properties.description = description;
if (timeSpan) {
var begin = nodeVal(get1(timeSpan, 'begin'));
var end = nodeVal(get1(timeSpan, 'end'));
properties.timespan = { begin: begin, end: end };
}
if (extendedData) {
var datas = get(extendedData, 'Data'),
simpleDatas = get(extendedData, 'SimpleData');
for (i = 0; i < datas.length; i++) {
properties[datas[i].getAttribute('name')] = nodeVal(get1(datas[i], 'value'));
}
for (i = 0; i < simpleDatas.length; i++) {
properties[simpleDatas[i].getAttribute('name')] = nodeVal(simpleDatas[i]);
}
}
return [{
type: 'Feature',
geometry: (geoms.length === 1) ? geoms[0] : {
type: 'GeometryCollection',
geometries: geoms
},
properties: properties
}];
}
return gj;
},
gpx: function(doc, o) {
var i,
tracks = get(doc, 'trk'),
routes = get(doc, 'rte'),
waypoints = get(doc, 'wpt'),
// a feature collection
gj = fc();
for (i = 0; i < tracks.length; i++) {
gj.features.push(getLinestring(tracks[i], 'trkpt'));
}
for (i = 0; i < routes.length; i++) {
gj.features.push(getLinestring(routes[i], 'rtept'));
}
for (i = 0; i < waypoints.length; i++) {
gj.features.push(getPoint(waypoints[i]));
}
function getLinestring(node, pointname) {
var j, pts = get(node, pointname), line = [];
for (j = 0; j < pts.length; j++) {
line.push(coordPair(pts[j]));
}
return {
type: 'Feature',
properties: getProperties(node),
geometry: {
type: 'LineString',
coordinates: line
}
};
}
function getPoint(node) {
var prop = getProperties(node);
prop.sym = nodeVal(get1(node, 'sym'));
return {
type: 'Feature',
properties: prop,
geometry: {
type: 'Point',
coordinates: coordPair(node)
}
};
}
function getProperties(node) {
var meta = ['name', 'desc', 'author', 'copyright', 'link',
'time', 'keywords'],
prop = {},
k;
for (k = 0; k < meta.length; k++) {
prop[meta[k]] = nodeVal(get1(node, meta[k]));
}
return clean(prop);
}
return gj;
}
};
return t;
})();
if (typeof module !== 'undefined') module.exports = toGeoJSON;
}).call(this,_dereq_("/Users/tmcw/src/leaflet-omnivore/node_modules/browserify/node_modules/insert-module-globals/node_modules/process/browser.js"))
},{"/Users/tmcw/src/leaflet-omnivore/node_modules/browserify/node_modules/insert-module-globals/node_modules/process/browser.js":4,"xmldom":3}],10:[function(_dereq_,module,exports){
var topojson = module.exports = _dereq_("./topojson");
topojson.topology = _dereq_("./lib/topojson/topology");
topojson.simplify = _dereq_("./lib/topojson/simplify");
topojson.clockwise = _dereq_("./lib/topojson/clockwise");
topojson.filter = _dereq_("./lib/topojson/filter");
topojson.prune = _dereq_("./lib/topojson/prune");
topojson.bind = _dereq_("./lib/topojson/bind");
},{"./lib/topojson/bind":11,"./lib/topojson/clockwise":14,"./lib/topojson/filter":18,"./lib/topojson/prune":21,"./lib/topojson/simplify":23,"./lib/topojson/topology":26,"./topojson":37}],11:[function(_dereq_,module,exports){
var type = _dereq_("./type"),
topojson = _dereq_("../../");
module.exports = function(topology, propertiesById) {
var bind = type({
geometry: function(geometry) {
var properties0 = geometry.properties,
properties1 = propertiesById[geometry.id];
if (properties1) {
if (properties0) for (var k in properties1) properties0[k] = properties1[k];
else for (var k in properties1) { geometry.properties = properties1; break; }
}
this.defaults.geometry.call(this, geometry);
},
LineString: noop,
MultiLineString: noop,
Point: noop,
MultiPoint: noop,
Polygon: noop,
MultiPolygon: noop
});
for (var key in topology.objects) {
bind.object(topology.objects[key]);
}
};
function noop() {}
},{"../../":10,"./type":36}],12:[function(_dereq_,module,exports){
// Computes the bounding box of the specified hash of GeoJSON objects.
module.exports = function(objects) {
var x0 = Infinity,
y0 = Infinity,
x1 = -Infinity,
y1 = -Infinity;
function boundGeometry(geometry) {
if (geometry && boundGeometryType.hasOwnProperty(geometry.type)) boundGeometryType[geometry.type](geometry);
}
var boundGeometryType = {
GeometryCollection: function(o) { o.geometries.forEach(boundGeometry); },
Point: function(o) { boundPoint(o.coordinates); },
MultiPoint: function(o) { o.coordinates.forEach(boundPoint); },
LineString: function(o) { boundLine(o.coordinates); },
MultiLineString: function(o) { o.coordinates.forEach(boundLine); },
Polygon: function(o) { o.coordinates.forEach(boundLine); },
MultiPolygon: function(o) { o.coordinates.forEach(boundMultiLine); }
};
function boundPoint(coordinates) {
var x = coordinates[0],
y = coordinates[1];
if (x < x0) x0 = x;
if (x > x1) x1 = x;
if (y < y0) y0 = y;
if (y > y1) y1 = y;
}
function boundLine(coordinates) {
coordinates.forEach(boundPoint);
}
function boundMultiLine(coordinates) {
coordinates.forEach(boundLine);
}
for (var key in objects) {
boundGeometry(objects[key]);
}
return [x0, y0, x1, y1];
};
},{}],13:[function(_dereq_,module,exports){
exports.name = "cartesian";
exports.formatDistance = formatDistance;
exports.ringArea = ringArea;
exports.absoluteArea = Math.abs;
exports.triangleArea = triangleArea;
exports.distance = distance;
function formatDistance(d) {
return d.toString();
}
function ringArea(ring) {
var i = 0,
n = ring.length,
area = ring[n - 1][1] * ring[0][0] - ring[n - 1][0] * ring[0][1];
while (++i < n) {
area += ring[i - 1][1] * ring[i][0] - ring[i - 1][0] * ring[i][1];
}
return -area * .5; // ensure clockwise pixel areas are positive
}
function triangleArea(triangle) {
return Math.abs(
(triangle[0][0] - triangle[2][0]) * (triangle[1][1] - triangle[0][1])
- (triangle[0][0] - triangle[1][0]) * (triangle[2][1] - triangle[0][1])
);
}
function distance(x0, y0, x1, y1) {
var dx = x0 - x1, dy = y0 - y1;
return Math.sqrt(dx * dx + dy * dy);
}
},{}],14:[function(_dereq_,module,exports){
var type = _dereq_("./type"),
systems = _dereq_("./coordinate-systems"),
topojson = _dereq_("../../");
module.exports = function(object, options) {
if (object.type === "Topology") clockwiseTopology(object, options);
else clockwiseGeometry(object, options);
};
function clockwiseGeometry(object, options) {
var system = null;
if (options)
"coordinate-system" in options && (system = systems[options["coordinate-system"]]);
var clockwisePolygon = clockwisePolygonSystem(system.ringArea, reverse);
type({
LineString: noop,
MultiLineString: noop,
Point: noop,
MultiPoint: noop,
Polygon: function(polygon) { clockwisePolygon(polygon.coordinates); },
MultiPolygon: function(multiPolygon) { multiPolygon.coordinates.forEach(clockwisePolygon); }
}).object(object);
function reverse(array) { array.reverse(); }
}
function clockwiseTopology(topology, options) {
var system = null;
if (options)
"coordinate-system" in options && (system = systems[options["coordinate-system"]]);
var clockwisePolygon = clockwisePolygonSystem(ringArea, reverse);
var clockwise = type({
LineString: noop,
MultiLineString: noop,
Point: noop,
MultiPoint: noop,
Polygon: function(polygon) { clockwisePolygon(polygon.arcs); },
MultiPolygon: function(multiPolygon) { multiPolygon.arcs.forEach(clockwisePolygon); }
});
for (var key in topology.objects) {
clockwise.object(topology.objects[key]);
}
function ringArea(ring) {
return system.ringArea(topojson.feature(topology, {type: "Polygon", arcs: [ring]}).geometry.coordinates[0]);
}
// TODO It might be slightly more compact to reverse the arc.
function reverse(ring) {
var i = -1, n = ring.length;
ring.reverse();
while (++i < n) ring[i] = ~ring[i];
}
};
function clockwisePolygonSystem(ringArea, reverse) {
return function(rings) {
if (!(n = rings.length)) return;
var n,
areas = new Array(n),
max = -Infinity,
best,
area,
t;
// Find the largest absolute ring area; this should be the exterior ring.
for (var i = 0; i < n; ++i) {
var area = Math.abs(areas[i] = ringArea(rings[i]));
if (area > max) max = area, best = i;
}
// Ensure the largest ring appears first.
if (best) {
t = rings[best], rings[best] = rings[0], rings[0] = t;
t = areas[best], areas[best] = areas[0], areas[0] = t;
}
if (areas[0] < 0) reverse(rings[0]);
for (var i = 1; i < n; ++i) {
if (areas[i] > 0) reverse(rings[i]);
}
};
}
function noop() {}
},{"../../":10,"./coordinate-systems":16,"./type":36}],15:[function(_dereq_,module,exports){
// Given a hash of GeoJSON objects and an id function, invokes the id function
// to compute a new id for each object that is a feature. The function is passed
// the feature and is expected to return the new feature id, or null if the
// feature should not have an id.
module.exports = function(objects, id) {
if (arguments.length < 2) id = function(d) { return d.id; };
function idObject(object) {
if (object && idObjectType.hasOwnProperty(object.type)) idObjectType[object.type](object);
}
function idFeature(feature) {
var i = id(feature);
if (i == null) delete feature.id;
else feature.id = i;
}
var idObjectType = {
Feature: idFeature,
FeatureCollection: function(collection) { collection.features.forEach(idFeature); }
};
for (var key in objects) {
idObject(objects[key]);
}
return objects;
};
},{}],16:[function(_dereq_,module,exports){
module.exports = {
cartesian: _dereq_("./cartesian"),
spherical: _dereq_("./spherical")
};
},{"./cartesian":13,"./spherical":24}],17:[function(_dereq_,module,exports){
// Given a TopoJSON topology in absolute (quantized) coordinates,
// converts to fixed-point delta encoding.
// This is a destructive operation that modifies the given topology!
module.exports = function(topology) {
var arcs = topology.arcs,
i = -1,
n = arcs.length;
while (++i < n) {
var arc = arcs[i],
j = 0,
m = arc.length,
point = arc[0],
x0 = point[0],
y0 = point[1],
x1,
y1;
while (++j < m) {
point = arc[j];
x1 = point[0];
y1 = point[1];
arc[j] = [x1 - x0, y1 - y0];
x0 = x1;
y0 = y1;
}
}
return topology;
};
},{}],18:[function(_dereq_,module,exports){
var type = _dereq_("./type"),
prune = _dereq_("./prune"),
clockwise = _dereq_("./clockwise"),
systems = _dereq_("./coordinate-systems"),
topojson = _dereq_("../../");
module.exports = function(topology, options) {
var system = null,
forceClockwise = true, // force exterior rings to be clockwise?
minimumArea;
if (options)
"coordinate-system" in options && (system = systems[options["coordinate-system"]]),
"minimum-area" in options && (minimumArea = +options["minimum-area"]),
"force-clockwise" in options && (forceClockwise = !!options["force-clockwise"]);
if (forceClockwise) clockwise(topology, options); // deprecated; for backwards-compatibility
if (!(minimumArea > 0)) minimumArea = Number.MIN_VALUE;
var filter = type({
LineString: noop, // TODO remove empty lines
MultiLineString: noop,
Point: noop,
MultiPoint: noop,
Polygon: function(polygon) {
polygon.arcs = polygon.arcs.filter(ringArea);
if (!polygon.arcs.length) {
polygon.type = null;
delete polygon.arcs;
}
},
MultiPolygon: function(multiPolygon) {
multiPolygon.arcs = multiPolygon.arcs.map(function(polygon) {
return polygon.filter(ringArea);
}).filter(function(polygon) {
return polygon.length;
});
if (!multiPolygon.arcs.length) {
multiPolygon.type = null;
delete multiPolygon.arcs;
}
},
GeometryCollection: function(collection) {
this.defaults.GeometryCollection.call(this, collection);
collection.geometries = collection.geometries.filter(function(geometry) { return geometry.type != null; });
if (!collection.geometries.length) {
collection.type = null;
delete collection.geometries;
}
}
});
for (var key in topology.objects) {
filter.object(topology.objects[key]);
}
prune(topology, options);
function ringArea(ring) {
var topopolygon = {type: "Polygon", arcs: [ring]},
geopolygon = topojson.feature(topology, topopolygon),
exterior = geopolygon.geometry.coordinates[0],
exteriorArea = system.absoluteArea(system.ringArea(exterior));
return exteriorArea >= minimumArea;
}
};
function noop() {}
},{"../../":10,"./clockwise":14,"./coordinate-systems":16,"./prune":21,"./type":36}],19:[function(_dereq_,module,exports){
// Given a hash of GeoJSON objects, replaces Features with geometry objects.
// This is a destructive operation that modifies the input objects!
module.exports = function(objects) {
function geomifyObject(object) {
return (object && geomifyObjectType.hasOwnProperty(object.type)
? geomifyObjectType[object.type]
: geomifyGeometry)(object);
}
function geomifyFeature(feature) {
var geometry = feature.geometry;
if (geometry == null) {
feature.type = null;
} else {
geomifyGeometry(geometry);
feature.type = geometry.type;
if (geometry.geometries) feature.geometries = geometry.geometries;
else if (geometry.coordinates) feature.coordinates = geometry.coordinates;
}
delete feature.geometry;
return feature;
}
function geomifyGeometry(geometry) {
if (!geometry) return {type: null};
if (geomifyGeometryType.hasOwnProperty(geometry.type)) geomifyGeometryType[geometry.type](geometry);
return geometry;
}
var geomifyObjectType = {
Feature: geomifyFeature,
FeatureCollection: function(collection) {
collection.type = "GeometryCollection";
collection.geometries = collection.features;
collection.features.forEach(geomifyFeature);
delete collection.features;
return collection;
}
};
var geomifyGeometryType = {
GeometryCollection: function(o) {
var geometries = o.geometries, i = -1, n = geometries.length;
while (++i < n) geometries[i] = geomifyGeometry(geometries[i]);
},
MultiPoint: function(o) {
if (!o.coordinates.length) {
o.type = null;
delete o.coordinates;
} else if (o.coordinates.length < 2) {
o.type = "Point";
o.coordinates = o.coordinates[0];
}
},
LineString: function(o) {
if (!o.coordinates.length) {
o.type = null;
delete o.coordinates;
}
},
MultiLineString: function(o) {
for (var lines = o.coordinates, i = 0, N = 0, n = lines.length; i < n; ++i) {
var line = lines[i];
if (line.length) lines[N++] = line;
}
if (!N) {
o.type = null;
delete o.coordinates;
} else if (N < 2) {
o.type = "LineString";
o.coordinates = lines[0];
} else {
o.coordinates.length = N;
}
},
Polygon: function(o) {
for (var rings = o.coordinates, i = 0, N = 0, n = rings.length; i < n; ++i) {
var ring = rings[i];
if (ring.length) rings[N++] = ring;
}
if (!N) {
o.type = null;
delete o.coordinates;
} else {
o.coordinates.length = N;
}
},
MultiPolygon: function(o) {
for (var polygons = o.coordinates, j = 0, M = 0, m = polygons.length; j < m; ++j) {
for (var rings = polygons[j], i = 0, N = 0, n = rings.length; i < n; ++i) {
var ring = rings[i];
if (ring.length) rings[N++] = ring;
}
if (N) {
rings.length = N;
polygons[M++] = rings;
}
}
if (!M) {
o.type = null;
delete o.coordinates;
} else if (M < 2) {
o.type = "Polygon";
o.coordinates = polygons[0];
} else {
polygons.length = M;
}
}
};
for (var key in objects) {
objects[key] = geomifyObject(objects[key]);
}
return objects;
};
},{}],20:[function(_dereq_,module,exports){
module.exports = function(objects, filter) {
function prefilterGeometry(geometry) {
if (!geometry) return {type: null};
if (prefilterGeometryType.hasOwnProperty(geometry.type)) prefilterGeometryType[geometry.type](geometry);
return geometry;
}
var prefilterGeometryType = {
GeometryCollection: function(o) {
var geometries = o.geometries, i = -1, n = geometries.length;
while (++i < n) geometries[i] = prefilterGeometry(geometries[i]);
},
Polygon: function(o) {
for (var rings = o.coordinates, i = 0, N = 0, n = rings.length; i < n; ++i) {
var ring = rings[i];
if (filter(ring)) rings[N++] = ring;
}
if (!N) {
o.type = null;
delete o.coordinates;
} else {
o.coordinates.length = N;
}
},
MultiPolygon: function(o) {
for (var polygons = o.coordinates, j = 0, M = 0, m = polygons.length; j < m; ++j) {
for (var rings = polygons[j], i = 0, N = 0, n = rings.length; i < n; ++i) {
var ring = rings[i];
if (filter(ring)) rings[N++] = ring;
}
if (N) {
rings.length = N;
polygons[M++] = rings;
}
}
if (!M) {
o.type = null;
delete o.coordinates;
} else if (M < 2) {
o.type = "Polygon";
o.coordinates = polygons[0];
} else {
polygons.length = M;
}
}
};
for (var key in objects) {
objects[key] = prefilterGeometry(objects[key]);
}
return objects;
};
},{}],21:[function(_dereq_,module,exports){
module.exports = function(topology, options) {
var verbose = false,
objects = topology.objects,
oldArcs = topology.arcs,
oldArcCount = oldArcs.length,
newArcs = topology.arcs = [],
newArcCount = 0,
newIndexByOldIndex = new Array(oldArcs.length);
if (options)
"verbose" in options && (verbose = !!options["verbose"]);
function pruneGeometry(geometry) {
if (geometry && pruneGeometryType.hasOwnProperty(geometry.type)) pruneGeometryType[geometry.type](geometry);
}
var pruneGeometryType = {
GeometryCollection: function(o) { o.geometries.forEach(pruneGeometry); },
LineString: function(o) { pruneArcs(o.arcs); },
MultiLineString: function(o) { o.arcs.forEach(pruneArcs); },
Polygon: function(o) { o.arcs.forEach(pruneArcs); },
MultiPolygon: function(o) { o.arcs.forEach(pruneMultiArcs); }
};
function pruneArcs(arcs) {
for (var i = 0, m = 0, n = arcs.length; i < n; ++i) {
var oldIndex = arcs[i],
oldReverse = oldIndex < 0 && (oldIndex = ~oldIndex, true),
oldArc = oldArcs[oldIndex],
newIndex;
// Skip collapsed arc segments.
if (oldArc.length < 3 && !oldArc[1][0] && !oldArc[1][1]) continue;
// If this is the first instance of this arc,
// record it under its new index.
if ((newIndex = newIndexByOldIndex[oldIndex]) == null) {
newIndexByOldIndex[oldIndex] = newIndex = newArcCount++;
newArcs[newIndex] = oldArcs[oldIndex];
}
arcs[m++] = oldReverse ? ~newIndex : newIndex;
}
// If all were collapsed, restore the last arc to avoid collapsing the line.
if (!(arcs.length = m) && n) {
// If this is the first instance of this arc,
// record it under its new index.
if ((newIndex = newIndexByOldIndex[oldIndex]) == null) {
newIndexByOldIndex[oldIndex] = newIndex = newArcCount++;
newArcs[newIndex] = oldArcs[oldIndex];
}
arcs[0] = oldReverse ? ~newIndex : newIndex;
}
}
function pruneMultiArcs(arcs) {
arcs.forEach(pruneArcs);
}
for (var key in objects) {
pruneGeometry(objects[key]);
}
if (verbose) console.warn("prune: retained " + newArcCount + " / " + oldArcCount + " arcs (" + Math.round(newArcCount / oldArcCount * 100) + "%)");
return topology;
};
function noop() {}
},{}],22:[function(_dereq_,module,exports){
module.exports = function(objects, bbox, Q) {
var x0 = isFinite(bbox[0]) ? bbox[0] : 0,
y0 = isFinite(bbox[1]) ? bbox[1] : 0,
x1 = isFinite(bbox[2]) ? bbox[2] : 0,
y1 = isFinite(bbox[3]) ? bbox[3] : 0,
kx = x1 - x0 ? (Q - 1) / (x1 - x0) : 1,
ky = y1 - y0 ? (Q - 1) / (y1 - y0) : 1;
function quantizeGeometry(geometry) {
if (geometry && quantizeGeometryType.hasOwnProperty(geometry.type)) quantizeGeometryType[geometry.type](geometry);
}
var quantizeGeometryType = {
GeometryCollection: function(o) { o.geometries.forEach(quantizeGeometry); },
Point: function(o) { quantizePoint(o.coordinates); },
MultiPoint: function(o) { o.coordinates.forEach(quantizePoint); },
LineString: function(o) {
var line = o.coordinates;
quantizeLine(line);
if (line.length < 2) line[1] = line[0]; // must have 2+
},
MultiLineString: function(o) {
for (var lines = o.coordinates, i = 0, n = lines.length; i < n; ++i) {
var line = lines[i];
quantizeLine(line);
if (line.length < 2) line[1] = line[0]; // must have 2+
}
},
Polygon: function(o) {
for (var rings = o.coordinates, i = 0, n = rings.length; i < n; ++i) {
var ring = rings[i];
quantizeLine(ring);
while (ring.length < 4) ring.push(ring[0]); // must have 4+
}
},
MultiPolygon: function(o) {
for (var polygons = o.coordinates, i = 0, n = polygons.length; i < n; ++i) {
for (var rings = polygons[i], j = 0, m = rings.length; j < m; ++j) {
var ring = rings[j];
quantizeLine(ring);
while (ring.length < 4) ring.push(ring[0]); // must have 4+
}
}
}
};
function quantizePoint(coordinates) {
coordinates[0] = Math.round((coordinates[0] - x0) * kx);
coordinates[1] = Math.round((coordinates[1] - y0) * ky);
}
function quantizeLine(coordinates) {
var i = 0,
j = 1,
n = coordinates.length,
pi = coordinates[0],
pj,
px = pi[0] = Math.round((pi[0] - x0) * kx),
py = pi[1] = Math.round((pi[1] - y0) * ky),
x,
y;
while (++i < n) {
pi = coordinates[i];
x = Math.round((pi[0] - x0) * kx);
y = Math.round((pi[1] - y0) * ky);
if (x !== px || y !== py) { // skip coincident points
pj = coordinates[j++];
pj[0] = px = x;
pj[1] = py = y;
}
}
coordinates.length = j;
}
for (var key in objects) {
quantizeGeometry(objects[key]);
}
return {
scale: [1 / kx, 1 / ky],
translate: [x0, y0]
};
};
},{}],23:[function(_dereq_,module,exports){
var topojson = _dereq_("../../"),
systems = _dereq_("./coordinate-systems");
module.exports = function(topology, options) {
var minimumArea = 0,
retainProportion,
verbose = false,
system = null,
N = topology.arcs.reduce(function(p, v) { return p + v.length; }, 0),
M = 0;
if (options)
"minimum-area" in options && (minimumArea = +options["minimum-area"]),
"coordinate-system" in options && (system = systems[options["coordinate-system"]]),
"retain-proportion" in options && (retainProportion = +options["retain-proportion"]),
"verbose" in options && (verbose = !!options["verbose"]);
topojson.presimplify(topology, system.triangleArea);
if (retainProportion) {
var areas = [];
topology.arcs.forEach(function(arc) {
arc.forEach(function(point) {
areas.push(point[2]);
});
});
options["minimum-area"] = minimumArea = N ? areas.sort(function(a, b) { return b - a; })[Math.ceil((N - 1) * retainProportion)] : 0;
if (verbose) console.warn("simplification: effective minimum area " + minimumArea.toPrecision(3));
}
topology.arcs.forEach(topology.transform ? function(arc) {
var dx = 0,
dy = 0, // accumulate removed points
i = -1,
j = -1,
n = arc.length,
source,
target;
while (++i < n) {
source = arc[i];
if (source[2] >= minimumArea) {
target = arc[++j];
target[0] = source[0] + dx;
target[1] = source[1] + dy;
dx = dy = 0;
} else {
dx += source[0];
dy += source[1];
}
}
arc.length = ++j;
} : function(arc) {
var i = -1,
j = -1,
n = arc.length,
point;
while (++i < n) {
point = arc[i];
if (point[2] >= minimumArea) {
arc[++j] = point;
}
}
arc.length = ++j;
});
// Remove computed area (z) for each point.
// This is done as a separate pass because some coordinates may be shared
// between arcs (such as the last point and first point of a cut line).
topology.arcs.forEach(function(arc) {
var i = -1, n = arc.length;
while (++i < n) arc[i].length = 2;
M += arc.length;
});
if (verbose) console.warn("simplification: retained " + M + " / " + N + " points (" + Math.round((M / N) * 100) + "%)");
return topology;
};
},{"../../":10,"./coordinate-systems":16}],24:[function(_dereq_,module,exports){
var π = Math.PI,
π_4 = π / 4,
radians = π / 180;
exports.name = "spherical";
exports.formatDistance = formatDistance;
exports.ringArea = ringArea;
exports.absoluteArea = absoluteArea;
exports.triangleArea = triangleArea;
exports.distance = haversinDistance; // why two implementations?
function formatDistance(radians) {
var km = radians * 6371;
return (km > 1 ? km.toFixed(3) + "km" : (km * 1000).toPrecision(3) + "m")
+ " (" + (radians * 180 / Math.PI).toPrecision(3) + "°)";
}
function ringArea(ring) {
if (!ring.length) return 0;
var area = 0,
p = ring[0],
λ = p[0] * radians,
φ = p[1] * radians / 2 + π_4,
λ0 = λ,
cosφ0 = Math.cos(φ),
sinφ0 = Math.sin(φ);
for (var i = 1, n = ring.length; i < n; ++i) {
p = ring[i], λ = p[0] * radians, φ = p[1] * radians / 2 + π_4;
// Spherical excess E for a spherical triangle with vertices: south pole,
// previous point, current point. Uses a formula derived from Cagnoli’s
// theorem. See Todhunter, Spherical Trig. (1871), Sec. 103, Eq. (2).
var dλ = λ - λ0,
cosφ = Math.cos(φ),
sinφ = Math.sin(φ),
k = sinφ0 * sinφ,
u = cosφ0 * cosφ + k * Math.cos(dλ),
v = k * Math.sin(dλ);
area += Math.atan2(v, u);
// Advance the previous point.
λ0 = λ, cosφ0 = cosφ, sinφ0 = sinφ;
}
return 2 * (area > π ? area - 2 * π : area < -π ? area + 2 * π : area);
}
function absoluteArea(a) {
return a < 0 ? a + 4 * π : a;
}
function triangleArea(t) {
var a = distance(t[0], t[1]),
b = distance(t[1], t[2]),
c = distance(t[2], t[0]),
s = (a + b + c) / 2;
return 4 * Math.atan(Math.sqrt(Math.max(0, Math.tan(s / 2) * Math.tan((s - a) / 2) * Math.tan((s - b) / 2) * Math.tan((s - c) / 2))));
}
function distance(a, b) {
var Δλ = (b[0] - a[0]) * radians,
sinΔλ = Math.sin(Δλ),
cosΔλ = Math.cos(Δλ),
sinφ0 = Math.sin(a[1] * radians),
cosφ0 = Math.cos(a[1] * radians),
sinφ1 = Math.sin(b[1] * radians),
cosφ1 = Math.cos(b[1] * radians),
_;
return Math.atan2(Math.sqrt((_ = cosφ1 * sinΔλ) * _ + (_ = cosφ0 * sinφ1 - sinφ0 * cosφ1 * cosΔλ) * _), sinφ0 * sinφ1 + cosφ0 * cosφ1 * cosΔλ);
}
function haversinDistance(x0, y0, x1, y1) {
x0 *= radians, y0 *= radians, x1 *= radians, y1 *= radians;
return 2 * Math.asin(Math.sqrt(haversin(y1 - y0) + Math.cos(y0) * Math.cos(y1) * haversin(x1 - x0)));
}
function haversin(x) {
return (x = Math.sin(x / 2)) * x;
}
},{}],25:[function(_dereq_,module,exports){
var type = _dereq_("./type");
module.exports = function(objects, transform) {
var ε = 1e-2,
x0 = -180, x0e = x0 + ε,
x1 = 180, x1e = x1 - ε,
y0 = -90, y0e = y0 + ε,
y1 = 90, y1e = y1 - ε,
fragments = [];
if (transform) {
var kx = transform.scale[0],
ky = transform.scale[1],
dx = transform.translate[0],
dy = transform.translate[1];
x0 = Math.round((x0 - dx) / kx);
x1 = Math.round((x1 - dx) / kx);
y0 = Math.round((y0 - dy) / ky);
y1 = Math.round((y1 - dy) / ky);
x0e = Math.round((x0e - dx) / kx);
x1e = Math.round((x1e - dx) / kx);
y0e = Math.round((y0e - dy) / ky);
y1e = Math.round((y1e - dy) / ky);
}
function normalizePoint(y) {
return y <= y0e ? [0, y0] // south pole
: y >= y1e ? [0, y1] // north pole
: [x0, y]; // antimeridian
}
var stitch = type({
polygon: function(polygon) {
var rings = [];
// For each ring, detect where it crosses the antimeridian or pole.
for (var j = 0, m = polygon.length; j < m; ++j) {
var ring = polygon[j],
fragments = [];
// By default, assume that this ring doesn’t need any stitching.
fragments.push(ring);
for (var i = 0, n = ring.length; i < n; ++i) {
var point = ring[i],
x = point[0],
y = point[1];
// If this is an antimeridian or polar point…
if (x <= x0e || x >= x1e || y <= y0e || y >= y1e) {
// Advance through any antimeridian or polar points…
for (var k = i + 1; k < n; ++k) {
var pointk = ring[k],
xk = pointk[0],
yk = pointk[1];
if (xk > x0e && xk < x1e && yk > y0e && yk < y1e) break;
}
// If this was just a single antimeridian or polar point,
// we don’t need to cut this ring into a fragment;
// we can just leave it as-is.
if (k === i + 1) continue;
// Otherwise, if this is not the first point in the ring,
// cut the current fragment so that it ends at the current point.
// The current point is also normalized for later joining.
if (i) {
var fragmentBefore = ring.slice(0, i + 1);
fragmentBefore[fragmentBefore.length - 1] = normalizePoint(y);
fragments[fragments.length - 1] = fragmentBefore;
}
// If the ring started with an antimeridian fragment,
// we can ignore that fragment entirely.
else {
fragments.pop();
}
// If the remainder of the ring is an antimeridian fragment,
// move on to the next ring.
if (k >= n) break;
// Otherwise, add the remaining ring fragment and continue.
fragments.push(ring = ring.slice(k - 1));
ring[0] = normalizePoint(ring[0][1]);
i = -1;
n = ring.length;
}
}
// Now stitch the fragments back together into rings.
// To connect the fragments start-to-end, create a simple index by end.
var fragmentByStart = {},
fragmentByEnd = {};
// For each fragment…
for (var i = 0, n = fragments.length; i < n; ++i) {
var fragment = fragments[i],
start = fragment[0],
end = fragment[fragment.length - 1];
// If this fragment is closed, add it as a standalone ring.
if (start[0] === end[0] && start[1] === end[1]) {
rings.push(fragment);
fragments[i] = null;
continue;
}
fragment.index = i;
fragmentByStart[start] = fragmentByEnd[end] = fragment;
}
// For each open fragment…
for (var i = 0; i < n; ++i) {
var fragment = fragments[i];
if (fragment) {
var start = fragment[0],
end = fragment[fragment.length - 1],
startFragment = fragmentByEnd[start],
endFragment = fragmentByStart[end];
delete fragmentByStart[start];
delete fragmentByEnd[end];
// If this fragment is closed, add it as a standalone ring.
if (start[0] === end[0] && start[1] === end[1]) {
rings.push(fragment);
continue;
}
if (startFragment) {
delete fragmentByEnd[start];
delete fragmentByStart[startFragment[0]];
startFragment.pop(); // drop the shared coordinate
fragments[startFragment.index] = null;
fragment = startFragment.concat(fragment);
if (startFragment === endFragment) {
// Connect both ends to this single fragment to create a ring.
rings.push(fragment);
} else {
fragment.index = n++;
fragments.push(fragmentByStart[fragment[0]] = fragmentByEnd[fragment[fragment.length - 1]] = fragment);
}
} else if (endFragment) {
delete fragmentByStart[end];
delete fragmentByEnd[endFragment[endFragment.length - 1]];
fragment.pop(); // drop the shared coordinate
fragment = fragment.concat(endFragment);
fragment.index = n++;
fragments[endFragment.index] = null;
fragments.push(fragmentByStart[fragment[0]] = fragmentByEnd[fragment[fragment.length - 1]] = fragment);
} else {
fragment.push(fragment[0]); // close ring
rings.push(fragment);
}
}
}
}
// Copy the rings into the target polygon.
for (var i = 0, n = polygon.length = rings.length; i < n; ++i) {
polygon[i] = rings[i];
}
}
});
for (var key in objects) {
stitch.object(objects[key]);
}
};
},{"./type":36}],26:[function(_dereq_,module,exports){
var type = _dereq_("./type"),
stitch = _dereq_("./stitch"),
systems = _dereq_("./coordinate-systems"),
topologize = _dereq_("./topology/index"),
delta = _dereq_("./delta"),
geomify = _dereq_("./geomify"),
prefilter = _dereq_("./prefilter"),
quantize = _dereq_("./quantize"),
bounds = _dereq_("./bounds"),
computeId = _dereq_("./compute-id"),
transformProperties = _dereq_("./transform-properties");
var ε = 1e-6;
module.exports = function(objects, options) {
var Q = 1e4, // precision of quantization
id = function(d) { return d.id; }, // function to compute object id
propertyTransform = function() {}, // function to transform properties
transform,
minimumArea = 0,
stitchPoles = true,
verbose = false,
system = null;
if (options)
"verbose" in options && (verbose = !!options["verbose"]),
"stitch-poles" in options && (stitchPoles = !!options["stitch-poles"]),
"coordinate-system" in options && (system = systems[options["coordinate-system"]]),
"minimum-area" in options && (minimumArea = +options["minimum-area"]),
"quantization" in options && (Q = +options["quantization"]),
"id" in options && (id = options["id"]),
"property-transform" in options && (propertyTransform = options["property-transform"]);
// Compute the new feature id and transform properties.
computeId(objects, id);
transformProperties(objects, propertyTransform);
// Convert to geometry objects.
geomify(objects);
// Compute initial bounding box.
var bbox = bounds(objects);
// For automatic coordinate system determination, consider the bounding box.
var oversize = bbox[0] < -180 - ε
|| bbox[1] < -90 - ε
|| bbox[2] > 180 + ε
|| bbox[3] > 90 + ε;
if (!system) {
system = systems[oversize ? "cartesian" : "spherical"];
if (options) options["coordinate-system"] = system.name;
}
if (system === systems.spherical) {
if (oversize) throw new Error("spherical coordinates outside of [±180°, ±90°]");
// When near the spherical coordinate limits, clamp to nice round values.
// This avoids quantized coordinates that are slightly outside the limits.
if (bbox[0] < -180 + ε) bbox[0] = -180;
if (bbox[1] < -90 + ε) bbox[1] = -90;
if (bbox[2] > 180 - ε) bbox[2] = 180;
if (bbox[3] > 90 - ε) bbox[3] = 90;
}
if (verbose) {
console.warn("bounds: " + bbox.join(" ") + " (" + system.name + ")");
}
// Filter rings smaller than the minimum area.
// This can produce a simpler topology.
if (minimumArea) prefilter(objects, function(ring) {
return system.absoluteArea(system.ringArea(ring)) >= minimumArea;
});
// Compute the quantization transform.
if (Q) {
transform = quantize(objects, bbox, Q);
if (verbose) {
console.warn("quantization: " + transform.scale.map(function(degrees) { return system.formatDistance(degrees / 180 * Math.PI); }).join(" "));
}
}
// Remove any antimeridian cuts and restitch.
if (system === systems.spherical && stitchPoles) {
stitch(objects, transform);
}
// Compute the topology.
var topology = topologize(objects);
topology.bbox = bbox;
if (verbose) {
console.warn("topology: " + topology.arcs.length + " arcs, " + topology.arcs.reduce(function(p, v) { return p + v.length; }, 0) + " points");
}
// Convert to delta-encoding.
if (Q) topology.transform = transform, delta(topology);
return topology;
};
},{"./bounds":12,"./compute-id":15,"./coordinate-systems":16,"./delta":17,"./geomify":19,"./prefilter":20,"./quantize":22,"./stitch":25,"./topology/index":31,"./transform-properties":35,"./type":36}],27:[function(_dereq_,module,exports){
var join = _dereq_("./join");
// Given an extracted (pre-)topology, cuts (or rotates) arcs so that all shared
// point sequences are identified. The topology can then be subsequently deduped
// to remove exact duplicate arcs.
module.exports = function(topology) {
var junctionByPoint = join(topology),
coordinates = topology.coordinates,
lines = topology.lines,
rings = topology.rings;
for (var i = 0, n = lines.length; i < n; ++i) {
var line = lines[i],
lineMid = line[0],
lineEnd = line[1];
while (++lineMid < lineEnd) {
if (junctionByPoint.get(coordinates[lineMid])) {
var next = {0: lineMid, 1: line[1]};
line[1] = lineMid;
line = line.next = next;
}
}
}
for (var i = 0, n = rings.length; i < n; ++i) {
var ring = rings[i],
ringStart = ring[0],
ringMid = ringStart,
ringEnd = ring[1],
ringFixed = junctionByPoint.get(coordinates[ringStart]);
while (++ringMid < ringEnd) {
if (junctionByPoint.get(coordinates[ringMid])) {
if (ringFixed) {
var next = {0: ringMid, 1: ring[1]};
ring[1] = ringMid;
ring = ring.next = next;
} else { // For the first junction, we can rotate rather than cut.
rotateArray(coordinates, ringStart, ringEnd, ringEnd - ringMid);
coordinates[ringEnd] = coordinates[ringStart];
ringFixed = true;
ringMid = ringStart; // restart; we may have skipped junctions
}
}
}
}
return topology;
};
function rotateArray(array, start, end, offset) {
reverse(array, start, end);
reverse(array, start, start + offset);
reverse(array, start + offset, end);
}
function reverse(array, start, end) {
for (var mid = start + ((end-- - start) >> 1), t; start < mid; ++start, --end) {
t = array[start], array[start] = array[end], array[end] = t;
}
}
},{"./join":32}],28:[function(_dereq_,module,exports){
var join = _dereq_("./join"),
hashtable = _dereq_("./hashtable"),
hashPoint = _dereq_("./point-hash"),
equalPoint = _dereq_("./point-equal");
// Given a cut topology, combines duplicate arcs.
module.exports = function(topology) {
var coordinates = topology.coordinates,
lines = topology.lines,
rings = topology.rings,
arcCount = lines.length + rings.length;
delete topology.lines;
delete topology.rings;
// Count the number of (non-unique) arcs to initialize the hashtable safely.
for (var i = 0, n = lines.length; i < n; ++i) {
var line = lines[i]; while (line = line.next) ++arcCount;
}
for (var i = 0, n = rings.length; i < n; ++i) {
var ring = rings[i]; while (ring = ring.next) ++arcCount;
}
var arcsByEnd = hashtable(arcCount * 2, hashPoint, equalPoint),
arcs = topology.arcs = [];
for (var i = 0, n = lines.length; i < n; ++i) {
var line = lines[i];
do {
dedupLine(line);
} while (line = line.next);
}
for (var i = 0, n = rings.length; i < n; ++i) {
var ring = rings[i];
if (ring.next) { // arc is no longer closed
do {
dedupLine(ring);
} while (ring = ring.next);
} else {
dedupRing(ring);
}
}
function dedupLine(arc) {
var startPoint,
endPoint,
startArcs,
endArcs;
// Does this arc match an existing arc in order?
if (startArcs = arcsByEnd.get(startPoint = coordinates[arc[0]])) {
for (var i = 0, n = startArcs.length; i < n; ++i) {
var startArc = startArcs[i];
if (equalLine(startArc, arc)) {
arc[0] = startArc[0];
arc[1] = startArc[1];
return;
}
}
}
// Does this arc match an existing arc in reverse order?
if (endArcs = arcsByEnd.get(endPoint = coordinates[arc[1]])) {
for (var i = 0, n = endArcs.length; i < n; ++i) {
var endArc = endArcs[i];
if (reverseEqualLine(endArc, arc)) {
arc[1] = endArc[0];
arc[0] = endArc[1];
return;
}
}
}
if (startArcs) startArcs.push(arc); else arcsByEnd.set(startPoint, [arc]);
if (endArcs) endArcs.push(arc); else arcsByEnd.set(endPoint, [arc]);
arcs.push(arc);
}
function dedupRing(arc) {
var endPoint,
endArcs;
// Does this arc match an existing line in order, or reverse order?
// Rings are closed, so their start point and end point is the same.
if (endArcs = arcsByEnd.get(endPoint = coordinates[arc[0]])) {
for (var i = 0, n = endArcs.length; i < n; ++i) {
var endArc = endArcs[i];
if (equalRing(endArc, arc)) {
arc[0] = endArc[0];
arc[1] = endArc[1];
return;
}
if (reverseEqualRing(endArc, arc)) {
arc[0] = endArc[1];
arc[1] = endArc[0];
return;
}
}
}
// Otherwise, does this arc match an existing ring in order, or reverse order?
if (endArcs = arcsByEnd.get(endPoint = coordinates[arc[0] + findMinimumOffset(arc)])) {
for (var i = 0, n = endArcs.length; i < n; ++i) {
var endArc = endArcs[i];
if (equalRing(endArc, arc)) {
arc[0] = endArc[0];
arc[1] = endArc[1];
return;
}
if (reverseEqualRing(endArc, arc)) {
arc[0] = endArc[1];
arc[1] = endArc[0];
return;
}
}
}
if (endArcs) endArcs.push(arc); else arcsByEnd.set(endPoint, [arc]);
arcs.push(arc);
}
function equalLine(arcA, arcB) {
var ia = arcA[0], ib = arcB[0],
ja = arcA[1], jb = arcB[1];
if (ia - ja !== ib - jb) return false;
for (; ia <= ja; ++ia, ++ib) if (!equalPoint(coordinates[ia], coordinates[ib])) return false;
return true;
}
function reverseEqualLine(arcA, arcB) {
var ia = arcA[0], ib = arcB[0],
ja = arcA[1], jb = arcB[1];
if (ia - ja !== ib - jb) return false;
for (; ia <= ja; ++ia, --jb) if (!equalPoint(coordinates[ia], coordinates[jb])) return false;
return true;
}
function equalRing(arcA, arcB) {
var ia = arcA[0], ib = arcB[0],
ja = arcA[1], jb = arcB[1],
n = ja - ia;
if (n !== jb - ib) return false;
var ka = findMinimumOffset(arcA),
kb = findMinimumOffset(arcB);
for (var i = 0; i < n; ++i) {
if (!equalPoint(coordinates[ia + (i + ka) % n], coordinates[ib + (i + kb) % n])) return false;
}
return true;
}
function reverseEqualRing(arcA, arcB) {
var ia = arcA[0], ib = arcB[0],
ja = arcA[1], jb = arcB[1],
n = ja - ia;
if (n !== jb - ib) return false;
var ka = findMinimumOffset(arcA),
kb = n - findMinimumOffset(arcB);
for (var i = 0; i < n; ++i) {
if (!equalPoint(coordinates[ia + (i + ka) % n], coordinates[jb - (i + kb) % n])) return false;
}
return true;
}
// Rings are rotated to a consistent, but arbitrary, start point.
// This is necessary to detect when a ring and a rotated copy are dupes.
function findMinimumOffset(arc) {
var start = arc[0],
end = arc[1],
mid = start,
minimum = mid,
minimumPoint = coordinates[mid];
while (++mid < end) {
var point = coordinates[mid];
if (point[0] < minimumPoint[0] || point[0] === minimumPoint[0] && point[1] < minimumPoint[1]) {
minimum = mid;
minimumPoint = point;
}
}
return minimum - start;
}
return topology;
};
},{"./hashtable":30,"./join":32,"./point-equal":33,"./point-hash":34}],29:[function(_dereq_,module,exports){
// Extracts the lines and rings from the specified hash of geometry objects.
//
// Returns an object with three properties:
//
// * coordinates - shared buffer of [x, y] coordinates
// * lines - lines extracted from the hash, of the form [start, end]
// * rings - rings extracted from the hash, of the form [start, end]
//
// For each ring or line, start and end represent inclusive indexes into the
// coordinates buffer. For rings (and closed lines), coordinates[start] equals
// coordinates[end].
//
// For each line or polygon geometry in the input hash, including nested
// geometries as in geometry collections, the `coordinates` array is replaced
// with an equivalent `arcs` array that, for each line (for line string
// geometries) or ring (for polygon geometries), points to one of the above
// lines or rings.
module.exports = function(objects) {
var index = -1,
lines = [],
rings = [],
coordinates = [];
function extractGeometry(geometry) {
if (geometry && extractGeometryType.hasOwnProperty(geometry.type)) extractGeometryType[geometry.type](geometry);
}
var extractGeometryType = {
GeometryCollection: function(o) { o.geometries.forEach(extractGeometry); },
LineString: function(o) { o.arcs = extractLine(o.coordinates); delete o.coordinates; },
MultiLineString: function(o) { o.arcs = o.coordinates.map(extractLine); delete o.coordinates; },
Polygon: function(o) { o.arcs = o.coordinates.map(extractRing); delete o.coordinates; },
MultiPolygon: function(o) { o.arcs = o.coordinates.map(extractMultiRing); delete o.coordinates; }
};
function extractLine(line) {
for (var i = 0, n = line.length; i < n; ++i) coordinates[++index] = line[i];
var arc = {0: index - n + 1, 1: index};
lines.push(arc);
return arc;
}
function extractRing(ring) {
for (var i = 0, n = ring.length; i < n; ++i) coordinates[++index] = ring[i];
var arc = {0: index - n + 1, 1: index};
rings.push(arc);
return arc;
}
function extractMultiRing(rings) {
return rings.map(extractRing);
}
for (var key in objects) {
extractGeometry(objects[key]);
}
return {
type: "Topology",
coordinates: coordinates,
lines: lines,
rings: rings,
objects: objects
};
};
},{}],30:[function(_dereq_,module,exports){
module.exports = function(size, hash, equal) {
var hashtable = new Array(size = 1 << Math.ceil(Math.log(size) / Math.LN2)),
mask = size - 1,
free = size;
function set(key, value) {
var index = hash(key) & mask,
match = hashtable[index],
cycle = !index;
while (match != null) {
if (equal(match.key, key)) return match.value = value;
match = hashtable[index = (index + 1) & mask];
if (!index && cycle++) throw new Error("full hashtable");
}
hashtable[index] = {key: key, value: value};
--free;
return value;
}
function get(key, missingValue) {
var index = hash(key) & mask,
match = hashtable[index],
cycle = !index;
while (match != null) {
if (equal(match.key, key)) return match.value;
match = hashtable[index = (index + 1) & mask];
if (!index && cycle++) break;
}
return missingValue;
}
function remove(key) {
var index = hash(key) & mask,
match = hashtable[index],
cycle = !index;
while (match != null) {
if (equal(match.key, key)) {
hashtable[index] = null;
match = hashtable[index = (index + 1) & mask];
if (match != null) { // delete and re-add
++free;
hashtable[index] = null;
set(match.key, match.value);
}
++free;
return true;
}
match = hashtable[index = (index + 1) & mask];
if (!index && cycle++) break;
}
return false;
}
function keys() {
var keys = [];
for (var i = 0, n = hashtable.length; i < n; ++i) {
var match = hashtable[i];
if (match != null) keys.push(match.key);
}
return keys;
}
return {
set: set,
get: get,
remove: remove,
keys: keys
};
};
},{}],31:[function(_dereq_,module,exports){
var hashtable = _dereq_("./hashtable"),
extract = _dereq_("./extract"),
cut = _dereq_("./cut"),
dedup = _dereq_("./dedup");
// Constructs the TopoJSON Topology for the specified hash of geometries.
// Each object in the specified hash must be a GeoJSON object,
// meaning FeatureCollection, a Feature or a geometry object.
module.exports = function(objects) {
var topology = dedup(cut(extract(objects))),
coordinates = topology.coordinates,
indexByArc = hashtable(topology.arcs.length, hashArc, equalArc);
objects = topology.objects; // for garbage collection
topology.arcs = topology.arcs.map(function(arc, i) {
indexByArc.set(arc, i);
return coordinates.slice(arc[0], arc[1] + 1);
});
delete topology.coordinates;
coordinates = null;
function indexGeometry(geometry) {
if (geometry && indexGeometryType.hasOwnProperty(geometry.type)) indexGeometryType[geometry.type](geometry);
}
var indexGeometryType = {
GeometryCollection: function(o) { o.geometries.forEach(indexGeometry); },
LineString: function(o) { o.arcs = indexArcs(o.arcs); },
MultiLineString: function(o) { o.arcs = o.arcs.map(indexArcs); },
Polygon: function(o) { o.arcs = o.arcs.map(indexArcs); },
MultiPolygon: function(o) { o.arcs = o.arcs.map(indexMultiArcs); }
};
function indexArcs(arc) {
var indexes = [];
do {
var index = indexByArc.get(arc);
indexes.push(arc[0] < arc[1] ? index : ~index);
} while (arc = arc.next);
return indexes;
}
function indexMultiArcs(arcs) {
return arcs.map(indexArcs);
}
for (var key in objects) {
indexGeometry(objects[key]);
}
return topology;
};
function hashArc(arc) {
var i = arc[0], j = arc[1], t;
if (j < i) t = i, i = j, j = t;
return i + 31 * j;
}
function equalArc(arcA, arcB) {
var ia = arcA[0], ja = arcA[1],
ib = arcB[0], jb = arcB[1], t;
if (ja < ia) t = ia, ia = ja, ja = t;
if (jb < ib) t = ib, ib = jb, jb = t;
return ia === ib && ja === jb;
}
},{"./cut":27,"./dedup":28,"./extract":29,"./hashtable":30}],32:[function(_dereq_,module,exports){
var hashtable = _dereq_("./hashtable"),
hashPoint = _dereq_("./point-hash"),
equalPoint = _dereq_("./point-equal");
// Given an extracted (pre-)topology, identifies all of the junctions. These are
// the points at which arcs (lines or rings) will need to be cut so that each
// arc is represented uniquely.
//
// A junction is a point where at least one arc deviates from another arc going
// through the same point. For example, consider the point B. If there is a arc
// through ABC and another arc through CBA, then B is not a junction because in
// both cases the adjacent point pairs are {A,C}. However, if there is an
// additional arc ABD, then {A,D} != {A,C}, and thus B becomes a junction.
//
// For a closed ring ABCA, the first point A’s adjacent points are the second
// and last point {B,C}. For a line, the first and last point are always
// considered junctions, even if the line is closed; this ensures that a closed
// line is never rotated.
module.exports = function(topology) {
var coordinates = topology.coordinates,
lines = topology.lines,
rings = topology.rings,
visitedByPoint,
neighborsByPoint = hashtable(coordinates.length, hashPoint, equalPoint),
junctionByPoint = hashtable(coordinates.length, hashPoint, equalPoint);
for (var i = 0, n = lines.length; i < n; ++i) {
var line = lines[i],
lineStart = line[0],
lineEnd = line[1],
previousPoint = null,
currentPoint = coordinates[lineStart],
nextPoint = coordinates[++lineStart];
visitedByPoint = hashtable(lineEnd - lineStart, hashPoint, equalPoint);
junctionByPoint.set(currentPoint, true); // start
while (++lineStart <= lineEnd) {
sequence(previousPoint = currentPoint, currentPoint = nextPoint, nextPoint = coordinates[lineStart]);
}
junctionByPoint.set(nextPoint, true); // end
}
for (var i = 0, n = rings.length; i < n; ++i) {
var ring = rings[i],
ringStart = ring[0] + 1,
ringEnd = ring[1],
previousPoint = coordinates[ringEnd - 1],
currentPoint = coordinates[ringStart - 1],
nextPoint = coordinates[ringStart];
visitedByPoint = hashtable(ringEnd - ringStart + 1, hashPoint, equalPoint);
sequence(previousPoint, currentPoint, nextPoint);
while (++ringStart <= ringEnd) {
sequence(previousPoint = currentPoint, currentPoint = nextPoint, nextPoint = coordinates[ringStart]);
}
}
function sequence(previousPoint, currentPoint, nextPoint) {
if (visitedByPoint.get(currentPoint)) return; // ignore self-intersection
visitedByPoint.set(currentPoint, true);
var neighbors = neighborsByPoint.get(currentPoint);
if (neighbors) {
if (!(equalPoint(neighbors[0], previousPoint)
&& equalPoint(neighbors[1], nextPoint))
&& !(equalPoint(neighbors[0], nextPoint)
&& equalPoint(neighbors[1], previousPoint))) {
junctionByPoint.set(currentPoint, true);
}
} else {
neighborsByPoint.set(currentPoint, [previousPoint, nextPoint]);
}
}
return junctionByPoint;
};
},{"./hashtable":30,"./point-equal":33,"./point-hash":34}],33:[function(_dereq_,module,exports){
module.exports = function(pointA, pointB) {
return pointA[0] === pointB[0] && pointA[1] === pointB[1];
};
},{}],34:[function(_dereq_,module,exports){
// TODO if quantized, use simpler Int32 hashing?
var hashBuffer = new ArrayBuffer(8),
hashFloats = new Float64Array(hashBuffer),
hashInts = new Int32Array(hashBuffer);
function hashFloat(x) {
hashFloats[0] = x;
x = hashInts[1] ^ hashInts[0];
x ^= (x >>> 20) ^ (x >>> 12);
x ^= (x >>> 7) ^ (x >>> 4);
return x;
}
module.exports = function(point) {
var h = (hashFloat(point[0]) + 31 * hashFloat(point[1])) | 0;
return h < 0 ? ~h : h;
};
},{}],35:[function(_dereq_,module,exports){
// Given a hash of GeoJSON objects, transforms any properties on features using
// the specified transform function. The function is invoked for each existing
// property on the current feature, being passed the new properties hash, the
// property name, and the property value. The function is then expected to
// assign a new value to the given property hash if the feature is to be
// retained and return true. Or, to skip the property, do nothing and return
// false. If no properties are propagated to the new properties hash, the
// properties hash will be deleted from the current feature.
module.exports = function(objects, propertyTransform) {
if (arguments.length < 2) propertyTransform = function() {};
function transformObject(object) {
if (object && transformObjectType.hasOwnProperty(object.type)) transformObjectType[object.type](object);
}
function transformFeature(feature) {
if (feature.properties) {
var properties0 = feature.properties,
properties1 = {},
empty = true;
for (var key0 in properties0) {
if (propertyTransform(properties1, key0, properties0[key0])) {
empty = false;
}
}
if (empty) delete feature.properties;
else feature.properties = properties1;
}
}
var transformObjectType = {
Feature: transformFeature,
FeatureCollection: function(collection) { collection.features.forEach(transformFeature); }
};
for (var key in objects) {
transformObject(objects[key]);
}
return objects;
};
},{}],36:[function(_dereq_,module,exports){
module.exports = function(types) {
for (var type in typeDefaults) {
if (!(type in types)) {
types[type] = typeDefaults[type];
}
}
types.defaults = typeDefaults;
return types;
};
var typeDefaults = {
Feature: function(feature) {
if (feature.geometry) this.geometry(feature.geometry);
},
FeatureCollection: function(collection) {
var features = collection.features, i = -1, n = features.length;
while (++i < n) this.Feature(features[i]);
},
GeometryCollection: function(collection) {
var geometries = collection.geometries, i = -1, n = geometries.length;
while (++i < n) this.geometry(geometries[i]);
},
LineString: function(lineString) {
this.line(lineString.coordinates);
},
MultiLineString: function(multiLineString) {
var coordinates = multiLineString.coordinates, i = -1, n = coordinates.length;
while (++i < n) this.line(coordinates[i]);
},
MultiPoint: function(multiPoint) {
var coordinates = multiPoint.coordinates, i = -1, n = coordinates.length;
while (++i < n) this.point(coordinates[i]);
},
MultiPolygon: function(multiPolygon) {
var coordinates = multiPolygon.coordinates, i = -1, n = coordinates.length;
while (++i < n) this.polygon(coordinates[i]);
},
Point: function(point) {
this.point(point.coordinates);
},
Polygon: function(polygon) {
this.polygon(polygon.coordinates);
},
object: function(object) {
return object == null ? null
: typeObjects.hasOwnProperty(object.type) ? this[object.type](object)
: this.geometry(object);
},
geometry: function(geometry) {
return geometry == null ? null
: typeGeometries.hasOwnProperty(geometry.type) ? this[geometry.type](geometry)
: null;
},
point: function() {},
line: function(coordinates) {
var i = -1, n = coordinates.length;
while (++i < n) this.point(coordinates[i]);
},
polygon: function(coordinates) {
var i = -1, n = coordinates.length;
while (++i < n) this.line(coordinates[i]);
}
};
var typeGeometries = {
LineString: 1,
MultiLineString: 1,
MultiPoint: 1,
MultiPolygon: 1,
Point: 1,
Polygon: 1,
GeometryCollection: 1
};
var typeObjects = {
Feature: 1,
FeatureCollection: 1
};
},{}],37:[function(_dereq_,module,exports){
!function() {
var topojson = {
version: "1.4.6",
mesh: mesh,
feature: featureOrCollection,
neighbors: neighbors,
presimplify: presimplify
};
function merge(topology, arcs) {
var fragmentByStart = {},
fragmentByEnd = {};
arcs.forEach(function(i) {
var e = ends(i),
start = e[0],
end = e[1],
f, g;
if (f = fragmentByEnd[start]) {
delete fragmentByEnd[f.end];
f.push(i);
f.end = end;
if (g = fragmentByStart[end]) {
delete fragmentByStart[g.start];
var fg = g === f ? f : f.concat(g);
fragmentByStart[fg.start = f.start] = fragmentByEnd[fg.end = g.end] = fg;
} else if (g = fragmentByEnd[end]) {
delete fragmentByStart[g.start];
delete fragmentByEnd[g.end];
var fg = f.concat(g.map(function(i) { return ~i; }).reverse());
fragmentByStart[fg.start = f.start] = fragmentByEnd[fg.end = g.start] = fg;
} else {
fragmentByStart[f.start] = fragmentByEnd[f.end] = f;
}
} else if (f = fragmentByStart[end]) {
delete fragmentByStart[f.start];
f.unshift(i);
f.start = start;
if (g = fragmentByEnd[start]) {
delete fragmentByEnd[g.end];
var gf = g === f ? f : g.concat(f);
fragmentByStart[gf.start = g.start] = fragmentByEnd[gf.end = f.end] = gf;
} else if (g = fragmentByStart[start]) {
delete fragmentByStart[g.start];
delete fragmentByEnd[g.end];
var gf = g.map(function(i) { return ~i; }).reverse().concat(f);
fragmentByStart[gf.start = g.end] = fragmentByEnd[gf.end = f.end] = gf;
} else {
fragmentByStart[f.start] = fragmentByEnd[f.end] = f;
}
} else if (f = fragmentByStart[start]) {
delete fragmentByStart[f.start];
f.unshift(~i);
f.start = end;
if (g = fragmentByEnd[end]) {
delete fragmentByEnd[g.end];
var gf = g === f ? f : g.concat(f);
fragmentByStart[gf.start = g.start] = fragmentByEnd[gf.end = f.end] = gf;
} else if (g = fragmentByStart[end]) {
delete fragmentByStart[g.start];
delete fragmentByEnd[g.end];
var gf = g.map(function(i) { return ~i; }).reverse().concat(f);
fragmentByStart[gf.start = g.end] = fragmentByEnd[gf.end = f.end] = gf;
} else {
fragmentByStart[f.start] = fragmentByEnd[f.end] = f;
}
} else if (f = fragmentByEnd[end]) {
delete fragmentByEnd[f.end];
f.push(~i);
f.end = start;
if (g = fragmentByEnd[start]) {
delete fragmentByStart[g.start];
var fg = g === f ? f : f.concat(g);
fragmentByStart[fg.start = f.start] = fragmentByEnd[fg.end = g.end] = fg;
} else if (g = fragmentByStart[start]) {
delete fragmentByStart[g.start];
delete fragmentByEnd[g.end];
var fg = f.concat(g.map(function(i) { return ~i; }).reverse());
fragmentByStart[fg.start = f.start] = fragmentByEnd[fg.end = g.start] = fg;
} else {
fragmentByStart[f.start] = fragmentByEnd[f.end] = f;
}
} else {
f = [i];
fragmentByStart[f.start = start] = fragmentByEnd[f.end = end] = f;
}
});
function ends(i) {
var arc = topology.arcs[i], p0 = arc[0], p1 = [0, 0];
arc.forEach(function(dp) { p1[0] += dp[0], p1[1] += dp[1]; });
return [p0, p1];
}
var fragments = [];
for (var k in fragmentByEnd) fragments.push(fragmentByEnd[k]);
return fragments;
}
function mesh(topology, o, filter) {
var arcs = [];
if (arguments.length > 1) {
var geomsByArc = [],
geom;
function arc(i) {
if (i < 0) i = ~i;
(geomsByArc[i] || (geomsByArc[i] = [])).push(geom);
}
function line(arcs) {
arcs.forEach(arc);
}
function polygon(arcs) {
arcs.forEach(line);
}
function geometry(o) {
if (o.type === "GeometryCollection") o.geometries.forEach(geometry);
else if (o.type in geometryType) {
geom = o;
geometryType[o.type](o.arcs);
}
}
var geometryType = {
LineString: line,
MultiLineString: polygon,
Polygon: polygon,
MultiPolygon: function(arcs) { arcs.forEach(polygon); }
};
geometry(o);
geomsByArc.forEach(arguments.length < 3
? function(geoms, i) { arcs.push(i); }
: function(geoms, i) { if (filter(geoms[0], geoms[geoms.length - 1])) arcs.push(i); });
} else {
for (var i = 0, n = topology.arcs.length; i < n; ++i) arcs.push(i);
}
return object(topology, {type: "MultiLineString", arcs: merge(topology, arcs)});
}
function featureOrCollection(topology, o) {
return o.type === "GeometryCollection" ? {
type: "FeatureCollection",
features: o.geometries.map(function(o) { return feature(topology, o); })
} : feature(topology, o);
}
function feature(topology, o) {
var f = {
type: "Feature",
id: o.id,
properties: o.properties || {},
geometry: object(topology, o)
};
if (o.id == null) delete f.id;
return f;
}
function object(topology, o) {
var absolute = transformAbsolute(topology.transform),
arcs = topology.arcs;
function arc(i, points) {
if (points.length) points.pop();
for (var a = arcs[i < 0 ? ~i : i], k = 0, n = a.length, p; k < n; ++k) {
points.push(p = a[k].slice());
absolute(p, k);
}
if (i < 0) reverse(points, n);
}
function point(p) {
p = p.slice();
absolute(p, 0);
return p;
}
function line(arcs) {
var points = [];
for (var i = 0, n = arcs.length; i < n; ++i) arc(arcs[i], points);
if (points.length < 2) points.push(points[0].slice());
return points;
}
function ring(arcs) {
var points = line(arcs);
while (points.length < 4) points.push(points[0].slice());
return points;
}
function polygon(arcs) {
return arcs.map(ring);
}
function geometry(o) {
var t = o.type;
return t === "GeometryCollection" ? {type: t, geometries: o.geometries.map(geometry)}
: t in geometryType ? {type: t, coordinates: geometryType[t](o)}
: null;
}
var geometryType = {
Point: function(o) { return point(o.coordinates); },
MultiPoint: function(o) { return o.coordinates.map(point); },
LineString: function(o) { return line(o.arcs); },
MultiLineString: function(o) { return o.arcs.map(line); },
Polygon: function(o) { return polygon(o.arcs); },
MultiPolygon: function(o) { return o.arcs.map(polygon); }
};
return geometry(o);
}
function reverse(array, n) {
var t, j = array.length, i = j - n; while (i < --j) t = array[i], array[i++] = array[j], array[j] = t;
}
function bisect(a, x) {
var lo = 0, hi = a.length;
while (lo < hi) {
var mid = lo + hi >>> 1;
if (a[mid] < x) lo = mid + 1;
else hi = mid;
}
return lo;
}
function neighbors(objects) {
var indexesByArc = {}, // arc index -> array of object indexes
neighbors = objects.map(function() { return []; });
function line(arcs, i) {
arcs.forEach(function(a) {
if (a < 0) a = ~a;
var o = indexesByArc[a];
if (o) o.push(i);
else indexesByArc[a] = [i];
});
}
function polygon(arcs, i) {
arcs.forEach(function(arc) { line(arc, i); });
}
function geometry(o, i) {
if (o.type === "GeometryCollection") o.geometries.forEach(function(o) { geometry(o, i); });
else if (o.type in geometryType) geometryType[o.type](o.arcs, i);
}
var geometryType = {
LineString: line,
MultiLineString: polygon,
Polygon: polygon,
MultiPolygon: function(arcs, i) { arcs.forEach(function(arc) { polygon(arc, i); }); }
};
objects.forEach(geometry);
for (var i in indexesByArc) {
for (var indexes = indexesByArc[i], m = indexes.length, j = 0; j < m; ++j) {
for (var k = j + 1; k < m; ++k) {
var ij = indexes[j], ik = indexes[k], n;
if ((n = neighbors[ij])[i = bisect(n, ik)] !== ik) n.splice(i, 0, ik);
if ((n = neighbors[ik])[i = bisect(n, ij)] !== ij) n.splice(i, 0, ij);
}
}
}
return neighbors;
}
function presimplify(topology, triangleArea) {
var absolute = transformAbsolute(topology.transform),
relative = transformRelative(topology.transform),
heap = minHeap(compareArea),
maxArea = 0,
triangle;
if (!triangleArea) triangleArea = cartesianArea;
topology.arcs.forEach(function(arc) {
var triangles = [];
arc.forEach(absolute);
for (var i = 1, n = arc.length - 1; i < n; ++i) {
triangle = arc.slice(i - 1, i + 2);
triangle[1][2] = triangleArea(triangle);
triangles.push(triangle);
heap.push(triangle);
}
// Always keep the arc endpoints!
arc[0][2] = arc[n][2] = Infinity;
for (var i = 0, n = triangles.length; i < n; ++i) {
triangle = triangles[i];
triangle.previous = triangles[i - 1];
triangle.next = triangles[i + 1];
}
});
while (triangle = heap.pop()) {
var previous = triangle.previous,
next = triangle.next;
// If the area of the current point is less than that of the previous point
// to be eliminated, use the latter's area instead. This ensures that the
// current point cannot be eliminated without eliminating previously-
// eliminated points.
if (triangle[1][2] < maxArea) triangle[1][2] = maxArea;
else maxArea = triangle[1][2];
if (previous) {
previous.next = next;
previous[2] = triangle[2];
update(previous);
}
if (next) {
next.previous = previous;
next[0] = triangle[0];
update(next);
}
}
topology.arcs.forEach(function(arc) {
arc.forEach(relative);
});
function update(triangle) {
heap.remove(triangle);
triangle[1][2] = triangleArea(triangle);
heap.push(triangle);
}
return topology;
};
function cartesianArea(triangle) {
return Math.abs(
(triangle[0][0] - triangle[2][0]) * (triangle[1][1] - triangle[0][1])
- (triangle[0][0] - triangle[1][0]) * (triangle[2][1] - triangle[0][1])
);
}
function compareArea(a, b) {
return a[1][2] - b[1][2];
}
function minHeap(compare) {
var heap = {},
array = [];
heap.push = function() {
for (var i = 0, n = arguments.length; i < n; ++i) {
var object = arguments[i];
up(object.index = array.push(object) - 1);
}
return array.length;
};
heap.pop = function() {
var removed = array[0],
object = array.pop();
if (array.length) {
array[object.index = 0] = object;
down(0);
}
return removed;
};
heap.remove = function(removed) {
var i = removed.index,
object = array.pop();
if (i !== array.length) {
array[object.index = i] = object;
(compare(object, removed) < 0 ? up : down)(i);
}
return i;
};
function up(i) {
var object = array[i];
while (i > 0) {
var up = ((i + 1) >> 1) - 1,
parent = array[up];
if (compare(object, parent) >= 0) break;
array[parent.index = i] = parent;
array[object.index = i = up] = object;
}
}
function down(i) {
var object = array[i];
while (true) {
var right = (i + 1) << 1,
left = right - 1,
down = i,
child = array[down];
if (left < array.length && compare(array[left], child) < 0) child = array[down = left];
if (right < array.length && compare(array[right], child) < 0) child = array[down = right];
if (down === i) break;
array[child.index = i] = child;
array[object.index = i = down] = object;
}
}
return heap;
}
function transformAbsolute(transform) {
if (!transform) return noop;
var x0,
y0,
kx = transform.scale[0],
ky = transform.scale[1],
dx = transform.translate[0],
dy = transform.translate[1];
return function(point, i) {
if (!i) x0 = y0 = 0;
point[0] = (x0 += point[0]) * kx + dx;
point[1] = (y0 += point[1]) * ky + dy;
};
}
function transformRelative(transform) {
if (!transform) return noop;
var x0,
y0,
kx = transform.scale[0],
ky = transform.scale[1],
dx = transform.translate[0],
dy = transform.translate[1];
return function(point, i) {
if (!i) x0 = y0 = 0;
var x1 = (point[0] - dx) / kx | 0,
y1 = (point[1] - dy) / ky | 0;
point[0] = x1 - x0;
point[1] = y1 - y0;
x0 = x1;
y0 = y1;
};
}
function noop() {}
if (typeof define === "function" && define.amd) define(topojson);
else if (typeof module === "object" && module.exports) module.exports = topojson;
else this.topojson = topojson;
}();
},{}],38:[function(_dereq_,module,exports){
module.exports = parse;
/*
* Parse WKT and return GeoJSON.
*
* @param {string} _ A WKT geometry
* @return {?Object} A GeoJSON geometry object
*/
function parse(_) {
var i = 0;
function $(re) {
var match = _.substring(i).match(re);
if (!match) return null;
else {
i += match[0].length;
return match[0];
}
}
function white() { $(/^\s*/); }
function multicoords() {
white();
var depth = 0, rings = [],
pointer = rings, elem;
while (elem =
$(/^(\()/) ||
$(/^(\))/) ||
$(/^(\,)/) ||
coords()) {
if (elem == '(') {
depth++;
} else if (elem == ')') {
depth--;
if (depth == 0) break;
} else if (elem && Array.isArray(elem) && elem.length) {
pointer.push(elem);
} else if (elem === ',') {
}
white();
}
if (depth !== 0) return null;
return rings;
}
function coords() {
var list = [], item, pt;
while (pt =
$(/^[-+]?([0-9]*\.[0-9]+|[0-9]+)/) ||
$(/^(\,)/)) {
if (pt == ',') {
list.push(item);
item = [];
} else {
if (!item) item = [];
item.push(parseFloat(pt));
}
white();
}
if (item) list.push(item);
return list.length ? list : null;
}
function point() {
if (!$(/^(point)/i)) return null;
white();
if (!$(/^(\()/)) return null;
var c = coords();
white();
if (!$(/^(\))/)) return null;
return {
type: 'Point',
coordinates: c[0]
};
}
function multipoint() {
if (!$(/^(multipoint)/i)) return null;
white();
var c = multicoords();
white();
return {
type: 'MultiPoint',
coordinates: c[0]
};
}
function multilinestring() {
if (!$(/^(multilinestring)/i)) return null;
white();
var c = multicoords();
white();
return {
type: 'MultiLineString',
coordinates: c
};
}
function linestring() {
if (!$(/^(linestring)/i)) return null;
white();
if (!$(/^(\()/)) return null;
var c = coords();
if (!$(/^(\))/)) return null;
return {
type: 'LineString',
coordinates: c
};
}
function polygon() {
if (!$(/^(polygon)/i)) return null;
white();
return {
type: 'Polygon',
coordinates: multicoords()
};
}
function multipolygon() {
if (!$(/^(multipolygon)/i)) return null;
white();
return {
type: 'MultiPolygon',
coordinates: multicoords()
};
}
function geometrycollection() {
var geometries = [], geometry;
if (!$(/^(geometrycollection)/i)) return null;
white();
if (!$(/^(\()/)) return null;
while (geometry = root()) {
geometries.push(geometry);
white();
$(/^(\,)/);
white();
}
if (!$(/^(\))/)) return null;
return {
type: 'GeometryCollection',
geometries: geometries
};
}
function root() {
return point() ||
linestring() ||
polygon() ||
multipoint() ||
multilinestring() ||
multipolygon() ||
geometrycollection();
}
return root();
}
},{}]},{},[1])
(1)
});