3278 lines
		
	
	
		
			102 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			3278 lines
		
	
	
		
			102 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| !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)
 | ||
| });
 |