diff --git a/assets/leaflet-omnivore/CHANGELOG.md b/assets/leaflet-omnivore/CHANGELOG.md
new file mode 100644
index 0000000..3958637
--- /dev/null
+++ b/assets/leaflet-omnivore/CHANGELOG.md
@@ -0,0 +1,28 @@
+## 0.3.2
+
+* Move `brfs` and `hintify` to dependencies.
+
+## 0.3.1
+
+* Updates [wellknown](https://github.com/mapbox/wellknown) to 0.3.0 with exponent coordinate support
+* Updates [togeojson](https://github.com/mapbox/togeojson) to 0.10.1 with timestamp, ie9 feature id, gx:Track, gx:MultiTrack support
+
+## 0.3.0
+
+* Includes [encoded polyline](https://developers.google.com/maps/documentation/utilities/polylinealgorithm) support.
+
+## 0.2.0
+
+* Only includes the necessary parts of [TopoJSON](https://github.com/mbostock/topojson): less bytes,
+ and **IE9** and **IE10** are now supported.
+* Tests now use Sauce Labs and run on real browsers for every commit.
+* Builds now use an `npm` script rather than a Makefile.
+
+## 0.1.0
+
+* loader functions now support a `customLayer` option for providing options to
+ `L.geoJson` or using a different layer type.
+
+## 0.0.1
+
+* `gpx.parse` and `kml.parse` support parsing from either strings or DOM objects
diff --git a/assets/leaflet-omnivore/LICENSE b/assets/leaflet-omnivore/LICENSE
new file mode 100644
index 0000000..9df952a
--- /dev/null
+++ b/assets/leaflet-omnivore/LICENSE
@@ -0,0 +1,58 @@
+Copyright (c) 2014, Mapbox
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+* Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+* Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+* Neither the name of the {organization} nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+-----------------------------------------------------------------------------
+
+TopoJSON
+
+Copyright (c) 2012, Michael Bostock
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+* Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+* Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+* The name Michael Bostock may not be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL MICHAEL BOSTOCK BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/assets/leaflet-omnivore/README.md b/assets/leaflet-omnivore/README.md
new file mode 100644
index 0000000..1c8b998
--- /dev/null
+++ b/assets/leaflet-omnivore/README.md
@@ -0,0 +1,186 @@
+[](https://travis-ci.org/mapbox/leaflet-omnivore)
+
+# leaflet-omnivore
+
+
+
+[Leaflet](http://leafletjs.com/) supports the [GeoJSON](http://geojson.org/) format
+by default. What if you have something else? That's where omnivore comes in.
+
+It currently supports:
+
+* [CSV](http://en.wikipedia.org/wiki/Comma-separated_values) (via [csv2geojson](https://github.com/mapbox/csv2geojson))
+* GPX (via [toGeoJSON](https://github.com/mapbox/togeojson))
+* [KML](http://developers.google.com/kml/documentation/) (via [toGeoJSON](https://github.com/mapbox/togeojson))
+* [WKT](http://en.wikipedia.org/wiki/Well-known_text) (via [wellknown](https://github.com/mapbox/wellknown))
+* [TopoJSON](https://github.com/mbostock/topojson)
+* [Encoded Polylines](https://developers.google.com/maps/documentation/utilities/polylinealgorithm) via [polyline](https://github.com/mapbox/polyline)
+
+Omnivore also includes an AJAX library, [corslite](https://github.com/mapbox/corslite),
+so you can specify what you want to add to the map with just a URL.
+
+## Installation
+
+use it easily with the [Mapbox Plugins CDN](http://mapbox.com/mapbox.js/plugins/#leaflet-omnivore):
+
+```html
+
+```
+
+
+Or download `leaflet-omnivore.min.js` from this repository.
+
+## example
+
+Live examples:
+
+* [WKT](https://www.mapbox.com/mapbox.js/example/v1.0.0/omnivore-wkt/)
+* [TopoJSON](https://www.mapbox.com/mapbox.js/example/v1.0.0/omnivore-topojson/)
+* [Tooltips](https://www.mapbox.com/mapbox.js/example/v1.0.0/omnivore-kml-tooltip/)
+* [KML](https://www.mapbox.com/mapbox.js/example/v1.0.0/omnivore-kml/)
+* [GPX](https://www.mapbox.com/mapbox.js/example/v1.0.0/omnivore-gpx/)
+* [Icons](https://www.mapbox.com/mapbox.js/example/v1.0.0/markers-from-csv-custom-style/)
+* [CSV](https://www.mapbox.com/mapbox.js/example/v1.0.0/markers-from-csv/)
+
+```js
+var map = L.mapbox.map('map', 'examples.map-9ijuk24y')
+ .setView([38, -102.0], 5);
+
+omnivore.csv('a.csv').addTo(map);
+omnivore.gpx('a.gpx').addTo(map);
+omnivore.kml('a.kml').addTo(map);
+omnivore.wkt('a.wkt').addTo(map);
+omnivore.topojson('a.topojson').addTo(map);
+omnivore.geojson('a.geojson').addTo(map);
+omnivore.polyline('a.txt').addTo(map);
+```
+
+## API
+
+Arguments with `?` are optional. **parser_options** consists of options
+sent to the parser library, _not_ to the layer: if you want to provide options
+to the layer, see the example in the Custom Layers section.
+
+By default, the library will construct a `L.geoJson()` layer internally and
+call `.addData(geojson)` on it in order to load it full of GeoJSON. If you want
+to use a different kind of layer, like a `L.mapbox.featureLayer()`, you can,
+by passing it as `customLayer`, as long as it supports events and `addData()`.
+You can also use this API to pass custom options to a `L.geoJson()` instance.:
+
+
+* `.csv(url, parser_options?, customLayer?)`: Load & parse CSV, and return layer. Options are the same as [csv2geojson](https://github.com/mapbox/csv2geojson#api): `latfield, lonfield, delimiter`
+* `.csv.parse(csvString, parser_options?)`: Parse CSV, and return layer.
+* `.kml(url)`: Load & parse KML, and return layer.
+* `.kml.parse(kmlString | gpxDom)`: Parse KML from a string of XML or XML DOM, and return layer.
+* `.gpx(url, parser_options?, customLayer?)`: Load & parse GPX, and return layer.
+* `.gpx.parse(gpxString | gpxDom)`: Parse GPX from a string of XML or XML DOM, and return layer.
+* `.geojson(url, parser_options?, customLayer?)`: Load GeoJSON file at URL, parse GeoJSON, and return layer.
+* `.wkt(url, parser_options?, customLayer?)`: Load & parse WKT, and return layer.
+* `.wkt.parse(wktString)`: Parse WKT, and return layer.
+* `.topojson(url, parser_options?, customLayer?)`: Load & parse TopoJSON, and return layer.
+* `.topojson.parse(topojson)`: Parse TopoJSON (given as a string or object), and return layer.
+* `.polyline(url, parser_options?, customLayer?)`: Load & parse polyline, and return layer.
+* `.polyline.parse(txt, options, layer)`: Parse polyline (given as a string or object), and return layer.
+
+Valid options:
+
+#### polyline
+
+* `precision` will change how the polyline is interpreted. By default, the value
+ is 5. This is the [factor in the algorithm](https://developers.google.com/maps/documentation/utilities/polylinealgorithm),
+ by default 1e5, which is adjustable.
+
+### Custom Layers
+
+Passing custom options:
+
+```js
+var customLayer = L.geoJson(null, {
+ filter: function() {
+ // my custom filter function
+ return true;
+ }
+});
+
+var myLayer = omnivore.csv('foo', null, customLayer);
+```
+
+Adding custom styles to a GeoJSON layer:
+
+```js
+var customLayer = L.geoJson(null, {
+ // http://leafletjs.com/reference.html#geojson-style
+ style: function(feature) {
+ return { color: '#f00' };
+ }
+});
+// this can be any kind of omnivore layer
+var runLayer = omnivore.kml('line.kml', null, customLayer)
+```
+
+Using a `L.mapbox.featureLayer`:
+
+```js
+var layer = omnivore.gpx('a.gpx', null, L.mapbox.featureLayer());
+```
+
+### Async & Events
+
+Each function returns an `L.geoJson` object. Functions that load from URLs
+are **asynchronous**, so they will **not** immediately expose accurate `.setGeoJSON()` functions.
+
+For this reason, we fire events:
+
+* `ready`: fired when all data is loaded into the layer
+* `error`: fired if data can't be loaded or parsed
+
+```js
+var layer = omnivore.gpx('a.gpx')
+ .on('ready', function() {
+ // when this is fired, the layer
+ // is done being initialized
+ })
+ .on('error', function() {
+ // fired if the layer can't be loaded over AJAX
+ // or can't be parsed
+ })
+ .addTo(map);
+```
+
+`ready` does **not** fire if you don't use an asynchronous form of the function
+like `.topojson.parse()`: because you don't need an event. Just run your code
+after the call.
+
+## Development
+
+This is a [browserify](http://browserify.org/) project:
+
+```sh
+git clone git@github.com:mapbox/leaflet-omnivore.git
+
+cd leaflet-omnivore
+
+# to run tests
+npm install
+
+# to build leaflet-omnivore.js
+npm run build
+```
+
+`leaflet-omnivore.js` and `leaflet-omnivore.min.js` are **built files** generated
+from `index.js` by `browserify`. If you find an issue, it either needs to be
+fixed in `index.js`, or in one of the libraries leaflet-omnivore uses
+to parse formats.
+
+## FAQ
+
+* **What if I just want one format?** Lucky for you, each format is specified
+ in a different module, so you can just use [TopoJSON](https://github.com/mbostock/topojson),
+ [csv2geojson](https://github.com/mapbox/csv2geojson), [wellknown](https://github.com/mapbox/wellknown), or
+ [toGeoJSON](https://github.com/mapbox/togeojson)
+ individually.
+* **My AJAX request is failing for a cross-domain request**. Read up on the [Same Origin Restriction](http://en.wikipedia.org/wiki/Same-origin_policy).
+ By default, we use corslite, so cross-domain requests will try to use [CORS](http://en.wikipedia.org/wiki/Cross-origin_resource_sharing)
+ if your server and browser supports it, but if one of them doesn't, there's no
+ way on the internet to support your request.
+* **Why isn't JSONP supported?** [Here's why](https://gist.github.com/tmcw/6244497).
diff --git a/assets/leaflet-omnivore/bower.json b/assets/leaflet-omnivore/bower.json
new file mode 100644
index 0000000..415e8dd
--- /dev/null
+++ b/assets/leaflet-omnivore/bower.json
@@ -0,0 +1,5 @@
+{
+ "name": "leaflet-omnivore",
+ "version": "0.3.0",
+ "description": "a geospatial format parser for Leaflet"
+}
diff --git a/assets/leaflet-omnivore/component.json b/assets/leaflet-omnivore/component.json
new file mode 100644
index 0000000..99feb3b
--- /dev/null
+++ b/assets/leaflet-omnivore/component.json
@@ -0,0 +1,8 @@
+{
+ "name": "leaflet-omnivore",
+ "version": "0.2.0",
+ "description": "a geospatial format parser for Leaflet",
+ "scripts": [
+ "leaflet-omnivore.js"
+ ]
+}
diff --git a/assets/leaflet-omnivore/index.js b/assets/leaflet-omnivore/index.js
new file mode 100644
index 0000000..e857a97
--- /dev/null
+++ b/assets/leaflet-omnivore/index.js
@@ -0,0 +1,255 @@
+var xhr = require('corslite'),
+ csv2geojson = require('csv2geojson'),
+ wellknown = require('wellknown'),
+ polyline = require('polyline'),
+ topojson = require('topojson/topojson.js'),
+ toGeoJSON = require('togeojson');
+
+module.exports.polyline = polylineLoad;
+module.exports.polyline.parse = polylineParse;
+
+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 });
+ topojsonParse(response.responseText, options, layer);
+ 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 = 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);
+ 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;
+}
+
+/**
+ * Load a polyline string into a layer and return the layer
+ *
+ * @param {string} url
+ * @param {object} options
+ * @param {object} customLayer
+ * @returns {object}
+ */
+function polylineLoad(url, options, customLayer) {
+ var layer = customLayer || L.geoJson();
+ xhr(url, onload);
+ function onload(err, response) {
+ if (err) return layer.fire('error', { error: err });
+ polylineParse(response.responseText, options, layer);
+ layer.fire('ready');
+ }
+ return layer;
+}
+
+function topojsonParse(data, options, layer) {
+ var o = typeof data === 'string' ?
+ JSON.parse(data) : data;
+ layer = layer || L.geoJson();
+ for (var i in o.objects) {
+ var ft = topojson.feature(o, o.objects[i]);
+ if (ft.features) addData(layer, ft.features);
+ else addData(layer, ft);
+ }
+ return layer;
+}
+
+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 KML'
+ });
+ layer = layer || L.geoJson();
+ var geojson = toGeoJSON.kml(xml);
+ addData(layer, geojson);
+ return layer;
+}
+
+function polylineParse(txt, options, layer) {
+ layer = layer || L.geoJson();
+ options = options || {};
+ var coords = polyline.decode(txt, options.precision);
+ var geojson = { type: 'LineString', coordinates: [] };
+ for (var i = 0; i < coords.length; i++) {
+ // polyline returns coords in lat, lng order, so flip for geojson
+ geojson.coordinates[i] = [coords[i][1], coords[i][0]];
+ }
+ 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;
+ }
+}
diff --git a/assets/leaflet-omnivore/leaflet-omnivore.js b/assets/leaflet-omnivore/leaflet-omnivore.js
new file mode 100644
index 0000000..dcdaba4
--- /dev/null
+++ b/assets/leaflet-omnivore/leaflet-omnivore.js
@@ -0,0 +1,1865 @@
+!function(e){if("object"==typeof exports&&"undefined"!=typeof module)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);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o 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 = [];
+
+function noop() {}
+
+process.on = noop;
+process.addListener = noop;
+process.once = noop;
+process.off = noop;
+process.removeListener = noop;
+process.removeAllListeners = noop;
+process.emit = noop;
+
+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(require,module,exports){
+function corslite(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 = new window.XMLHttpRequest();
+
+ function isSuccessful(status) {
+ return status >= 200 && status < 300 || status === 304;
+ }
+
+ if (cors && !('withCredentials' in x)) {
+ // IE8-9
+ 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);
+ }
+ }
+ }
+
+ 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 = corslite;
+
+},{}],6:[function(require,module,exports){
+var dsv = require('dsv'),
+ sexagesimal = require('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(require,module,exports){
+var fs = require("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(require,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(require,module,exports){
+var polyline = {};
+
+// Based off of [the offical Google document](https://developers.google.com/maps/documentation/utilities/polylinealgorithm)
+//
+// Some parts from [this implementation](http://facstaff.unca.edu/mcmcclur/GoogleMaps/EncodePolyline/PolylineEncoder.js)
+// by [Mark McClure](http://facstaff.unca.edu/mcmcclur/)
+
+function encode(coordinate, factor) {
+ coordinate = Math.round(coordinate * factor);
+ coordinate <<= 1;
+ if (coordinate < 0) {
+ coordinate = ~coordinate;
+ }
+ var output = '';
+ while (coordinate >= 0x20) {
+ output += String.fromCharCode((0x20 | (coordinate & 0x1f)) + 63);
+ coordinate >>= 5;
+ }
+ output += String.fromCharCode(coordinate + 63);
+ return output;
+}
+
+// This is adapted from the implementation in Project-OSRM
+// https://github.com/DennisOSRM/Project-OSRM-Web/blob/master/WebContent/routing/OSRM.RoutingGeometry.js
+polyline.decode = function(str, precision) {
+ var index = 0,
+ lat = 0,
+ lng = 0,
+ coordinates = [],
+ shift = 0,
+ result = 0,
+ byte = null,
+ latitude_change,
+ longitude_change,
+ factor = Math.pow(10, precision || 5);
+
+ // Coordinates have variable length when encoded, so just keep
+ // track of whether we've hit the end of the string. In each
+ // loop iteration, a single coordinate is decoded.
+ while (index < str.length) {
+
+ // Reset shift, result, and byte
+ byte = null;
+ shift = 0;
+ result = 0;
+
+ do {
+ byte = str.charCodeAt(index++) - 63;
+ result |= (byte & 0x1f) << shift;
+ shift += 5;
+ } while (byte >= 0x20);
+
+ latitude_change = ((result & 1) ? ~(result >> 1) : (result >> 1));
+
+ shift = result = 0;
+
+ do {
+ byte = str.charCodeAt(index++) - 63;
+ result |= (byte & 0x1f) << shift;
+ shift += 5;
+ } while (byte >= 0x20);
+
+ longitude_change = ((result & 1) ? ~(result >> 1) : (result >> 1));
+
+ lat += latitude_change;
+ lng += longitude_change;
+
+ coordinates.push([lat / factor, lng / factor]);
+ }
+
+ return coordinates;
+};
+
+polyline.encode = function(coordinates, precision) {
+ if (!coordinates.length) return '';
+
+ var factor = Math.pow(10, precision || 5),
+ output = encode(coordinates[0][0], factor) + encode(coordinates[0][1], factor);
+
+ for (var i = 1; i < coordinates.length; i++) {
+ var a = coordinates[i], b = coordinates[i - 1];
+ output += encode(a[0] - b[0], factor);
+ output += encode(a[1] - b[1], factor);
+ }
+
+ return output;
+};
+
+if (typeof module !== undefined) module.exports = polyline;
+
+},{}],10:[function(require,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'),
+ time = get1(x, 'time');
+ if (ele) ll.push(parseFloat(nodeVal(ele)));
+ return {
+ coordinates: ll,
+ time: time ? nodeVal(time) : null
+ };
+ }
+
+ // 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 (require('xmldom').XMLSerializer)();
+ }
+ function xml2str(str) {
+ // IE9 will create a new XMLSerializer but it'll crash immediately.
+ if (str.xml !== undefined) return str.xml;
+ return serializer.serializeToString(str);
+ }
+
+ var t = {
+ kml: function(doc) {
+
+ 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', 'gx: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 kmlColor(v) {
+ var color, opacity;
+ v = v || "";
+ if (v.substr(0, 1) === "#") v = v.substr(1);
+ if (v.length === 6 || v.length === 3) color = v;
+ if (v.length === 8) {
+ opacity = parseInt(v.substr(0, 2), 16) / 255;
+ color = v.substr(2);
+ }
+ return [color, isNaN(opacity) ? undefined : opacity];
+ }
+ function gxCoord(v) { return numarray(v.split(' ')); }
+ function gxCoords(root) {
+ var elems = get(root, 'coord', 'gx'), coords = [], times = [];
+ if (elems.length === 0) elems = get(root, 'gx:coord');
+ for (var i = 0; i < elems.length; i++) coords.push(gxCoord(nodeVal(elems[i])));
+ var timeElems = get(root, 'when');
+ for (var i = 0; i < timeElems.length; i++) times.push(nodeVal(timeElems[i]));
+ return {
+ coords: coords,
+ times: times
+ };
+ }
+ function getGeometry(root) {
+ var geomNode, geomNodes, i, j, k, geoms = [], coordTimes = [];
+ if (get1(root, 'MultiGeometry')) return getGeometry(get1(root, 'MultiGeometry'));
+ if (get1(root, 'MultiTrack')) return getGeometry(get1(root, 'MultiTrack'));
+ if (get1(root, 'gx:MultiTrack')) return getGeometry(get1(root, 'gx: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' ||
+ geotypes[i] == 'gx:Track') {
+ var track = gxCoords(geomNode);
+ geoms.push({
+ type: 'LineString',
+ coordinates: track.coords
+ });
+ if (track.times.length) coordTimes.push(track.times);
+ }
+ }
+ }
+ }
+ return {
+ geoms: geoms,
+ coordTimes: coordTimes
+ };
+ }
+ function getPlacemark(root) {
+ var geomsAndTimes = 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'),
+ lineStyle = get1(root, 'LineStyle'),
+ polyStyle = get1(root, 'PolyStyle');
+
+ if (!geomsAndTimes.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 (lineStyle) {
+ var linestyles = kmlColor(nodeVal(get1(lineStyle, 'color'))),
+ color = linestyles[0],
+ opacity = linestyles[1],
+ width = parseFloat(nodeVal(get1(lineStyle, 'width')));
+ if (color) properties.stroke = color;
+ if (!isNaN(opacity)) properties['stroke-opacity'] = opacity;
+ if (!isNaN(width)) properties['stroke-width'] = width;
+ }
+ if (polyStyle) {
+ var polystyles = kmlColor(nodeVal(get1(polyStyle, 'color'))),
+ pcolor = polystyles[0],
+ popacity = polystyles[1],
+ fill = nodeVal(get1(polyStyle, 'fill')),
+ outline = nodeVal(get1(polyStyle, 'outline'));
+ if (pcolor) properties.fill = pcolor;
+ if (!isNaN(popacity)) properties['fill-opacity'] = popacity;
+ if (fill) properties['fill-opacity'] = fill === "1" ? 1 : 0;
+ if (outline) properties['stroke-opacity'] = outline === "1" ? 1 : 0;
+ }
+ 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]);
+ }
+ }
+ if (geomsAndTimes.coordTimes.length) {
+ properties.coordTimes = (geomsAndTimes.coordTimes.length === 1) ?
+ geomsAndTimes.coordTimes[0] : geomsAndTimes.coordTimes;
+ }
+ var feature = {
+ type: 'Feature',
+ geometry: (geomsAndTimes.geoms.length === 1) ? geomsAndTimes.geoms[0] : {
+ type: 'GeometryCollection',
+ geometries: geomsAndTimes.geoms
+ },
+ properties: properties
+ };
+ if (attr(root, 'id')) feature.id = attr(root, 'id');
+ return [feature];
+ }
+ return gj;
+ },
+ gpx: function(doc) {
+ var i,
+ tracks = get(doc, 'trk'),
+ routes = get(doc, 'rte'),
+ waypoints = get(doc, 'wpt'),
+ // a feature collection
+ gj = fc(),
+ feature;
+ for (i = 0; i < tracks.length; i++) {
+ feature = getTrack(tracks[i]);
+ if (feature) gj.features.push(feature);
+ }
+ for (i = 0; i < routes.length; i++) {
+ feature = getRoute(routes[i]);
+ if (feature) gj.features.push(feature);
+ }
+ for (i = 0; i < waypoints.length; i++) {
+ gj.features.push(getPoint(waypoints[i]));
+ }
+ function getPoints(node, pointname) {
+ var pts = get(node, pointname), line = [], times = [],
+ l = pts.length;
+ if (l < 2) return; // Invalid line in GeoJSON
+ for (var i = 0; i < l; i++) {
+ var c = coordPair(pts[i]);
+ line.push(c.coordinates);
+ if (c.time) times.push(c.time);
+ }
+ return {
+ line: line,
+ times: times
+ };
+ }
+ function getTrack(node) {
+ var segments = get(node, 'trkseg'), track = [], times = [], line;
+ for (var i = 0; i < segments.length; i++) {
+ line = getPoints(segments[i], 'trkpt');
+ if (line.line) track.push(line.line);
+ if (line.times.length) times.push(line.times);
+ }
+ if (track.length === 0) return;
+ var properties = getProperties(node);
+ if (times.length) properties.coordTimes = track.length === 1 ? times[0] : times;
+ return {
+ type: 'Feature',
+ properties: properties,
+ geometry: {
+ type: track.length === 1 ? 'LineString' : 'MultiLineString',
+ coordinates: track.length === 1 ? track[0] : track
+ }
+ };
+ }
+ function getRoute(node) {
+ var line = getPoints(node, 'rtept');
+ if (!line) return;
+ var routeObj = {
+ type: 'Feature',
+ properties: getProperties(node),
+ geometry: {
+ type: 'LineString',
+ coordinates: line
+ }
+ };
+ if (line.times.length) routeObj.geometry.times = line.times;
+ return routeObj;
+ }
+ function getPoint(node) {
+ var prop = getProperties(node);
+ prop.sym = nodeVal(get1(node, 'sym'));
+ return {
+ type: 'Feature',
+ properties: prop,
+ geometry: {
+ type: 'Point',
+ coordinates: coordPair(node).coordinates
+ }
+ };
+ }
+ 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,require('_process'))
+},{"_process":4,"xmldom":3}],11:[function(require,module,exports){
+!function() {
+ var topojson = {
+ version: "1.6.8",
+ mesh: function(topology) { return object(topology, meshArcs.apply(this, arguments)); },
+ meshArcs: meshArcs,
+ merge: function(topology) { return object(topology, mergeArcs.apply(this, arguments)); },
+ mergeArcs: mergeArcs,
+ feature: featureOrCollection,
+ neighbors: neighbors,
+ presimplify: presimplify
+ };
+
+ function stitchArcs(topology, arcs) {
+ var stitchedArcs = {},
+ fragmentByStart = {},
+ fragmentByEnd = {},
+ fragments = [],
+ emptyIndex = -1;
+
+ // Stitch empty arcs first, since they may be subsumed by other arcs.
+ arcs.forEach(function(i, j) {
+ var arc = topology.arcs[i < 0 ? ~i : i], t;
+ if (arc.length < 3 && !arc[1][0] && !arc[1][1]) {
+ t = arcs[++emptyIndex], arcs[emptyIndex] = i, arcs[j] = t;
+ }
+ });
+
+ 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 {
+ 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 {
+ 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 < 0 ? ~i : i], p0 = arc[0], p1;
+ if (topology.transform) p1 = [0, 0], arc.forEach(function(dp) { p1[0] += dp[0], p1[1] += dp[1]; });
+ else p1 = arc[arc.length - 1];
+ return i < 0 ? [p1, p0] : [p0, p1];
+ }
+
+ function flush(fragmentByEnd, fragmentByStart) {
+ for (var k in fragmentByEnd) {
+ var f = fragmentByEnd[k];
+ delete fragmentByStart[f.start];
+ delete f.start;
+ delete f.end;
+ f.forEach(function(i) { stitchedArcs[i < 0 ? ~i : i] = 1; });
+ fragments.push(f);
+ }
+ }
+
+ flush(fragmentByEnd, fragmentByStart);
+ flush(fragmentByStart, fragmentByEnd);
+ arcs.forEach(function(i) { if (!stitchedArcs[i < 0 ? ~i : i]) fragments.push([i]); });
+
+ return fragments;
+ }
+
+ function meshArcs(topology, o, filter) {
+ var arcs = [];
+
+ if (arguments.length > 1) {
+ var geomsByArc = [],
+ geom;
+
+ function arc(i) {
+ var j = i < 0 ? ~i : i;
+ (geomsByArc[j] || (geomsByArc[j] = [])).push({i: i, g: 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) { arcs.push(geoms[0].i); }
+ : function(geoms) { if (filter(geoms[0].g, geoms[geoms.length - 1].g)) arcs.push(geoms[0].i); });
+ } else {
+ for (var i = 0, n = topology.arcs.length; i < n; ++i) arcs.push(i);
+ }
+
+ return {type: "MultiLineString", arcs: stitchArcs(topology, arcs)};
+ }
+
+ function mergeArcs(topology, objects) {
+ var polygonsByArc = {},
+ polygons = [],
+ components = [];
+
+ objects.forEach(function(o) {
+ if (o.type === "Polygon") register(o.arcs);
+ else if (o.type === "MultiPolygon") o.arcs.forEach(register);
+ });
+
+ function register(polygon) {
+ polygon.forEach(function(ring) {
+ ring.forEach(function(arc) {
+ (polygonsByArc[arc = arc < 0 ? ~arc : arc] || (polygonsByArc[arc] = [])).push(polygon);
+ });
+ });
+ polygons.push(polygon);
+ }
+
+ function exterior(ring) {
+ return cartesianRingArea(object(topology, {type: "Polygon", arcs: [ring]}).coordinates[0]) > 0; // TODO allow spherical?
+ }
+
+ polygons.forEach(function(polygon) {
+ if (!polygon._) {
+ var component = [],
+ neighbors = [polygon];
+ polygon._ = 1;
+ components.push(component);
+ while (polygon = neighbors.pop()) {
+ component.push(polygon);
+ polygon.forEach(function(ring) {
+ ring.forEach(function(arc) {
+ polygonsByArc[arc < 0 ? ~arc : arc].forEach(function(polygon) {
+ if (!polygon._) {
+ polygon._ = 1;
+ neighbors.push(polygon);
+ }
+ });
+ });
+ });
+ }
+ }
+ });
+
+ polygons.forEach(function(polygon) {
+ delete polygon._;
+ });
+
+ return {
+ type: "MultiPolygon",
+ arcs: components.map(function(polygons) {
+ var arcs = [];
+
+ // Extract the exterior (unique) arcs.
+ polygons.forEach(function(polygon) {
+ polygon.forEach(function(ring) {
+ ring.forEach(function(arc) {
+ if (polygonsByArc[arc < 0 ? ~arc : arc].length < 2) {
+ arcs.push(arc);
+ }
+ });
+ });
+ });
+
+ // Stitch the arcs into one or more rings.
+ arcs = stitchArcs(topology, arcs);
+
+ // If more than one ring is returned,
+ // at most one of these rings can be the exterior;
+ // this exterior ring has the same winding order
+ // as any exterior ring in the original polygons.
+ if ((n = arcs.length) > 1) {
+ var sgn = exterior(polygons[0][0]);
+ for (var i = 0, t; i < n; ++i) {
+ if (sgn === exterior(arcs[i])) {
+ t = arcs[0], arcs[0] = arcs[i], arcs[i] = t;
+ break;
+ }
+ }
+ }
+
+ return 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 = minAreaHeap(),
+ maxArea = 0,
+ triangle;
+
+ if (!triangleArea) triangleArea = cartesianTriangleArea;
+
+ 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 cartesianRingArea(ring) {
+ var i = -1,
+ n = ring.length,
+ a,
+ b = ring[n - 1],
+ area = 0;
+
+ while (++i < n) {
+ a = b;
+ b = ring[i];
+ area += a[0] * b[1] - a[1] * b[0];
+ }
+
+ return area * .5;
+ }
+
+ function cartesianTriangleArea(triangle) {
+ var a = triangle[0], b = triangle[1], c = triangle[2];
+ return Math.abs((a[0] - c[0]) * (b[1] - a[1]) - (a[0] - b[0]) * (c[1] - a[1]));
+ }
+
+ function compareArea(a, b) {
+ return a[1][2] - b[1][2];
+ }
+
+ function minAreaHeap() {
+ var heap = {},
+ array = [],
+ size = 0;
+
+ heap.push = function(object) {
+ up(array[object._ = size] = object, size++);
+ return size;
+ };
+
+ heap.pop = function() {
+ if (size <= 0) return;
+ var removed = array[0], object;
+ if (--size > 0) object = array[size], down(array[object._ = 0] = object, 0);
+ return removed;
+ };
+
+ heap.remove = function(removed) {
+ var i = removed._, object;
+ if (array[i] !== removed) return; // invalid request
+ if (i !== --size) object = array[size], (compareArea(object, removed) < 0 ? up : down)(array[object._ = i] = object, i);
+ return i;
+ };
+
+ function up(object, i) {
+ while (i > 0) {
+ var j = ((i + 1) >> 1) - 1,
+ parent = array[j];
+ if (compareArea(object, parent) >= 0) break;
+ array[parent._ = i] = parent;
+ array[object._ = i = j] = object;
+ }
+ }
+
+ function down(object, i) {
+ while (true) {
+ var r = (i + 1) << 1,
+ l = r - 1,
+ j = i,
+ child = array[j];
+ if (l < size && compareArea(array[l], child) < 0) child = array[j = l];
+ if (r < size && compareArea(array[r], child) < 0) child = array[j = r];
+ if (j === i) break;
+ array[child._ = i] = child;
+ array[object._ = i = j] = 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;
+}();
+
+},{}],12:[function(require,module,exports){
+module.exports = parse;
+module.exports.parse = parse;
+module.exports.stringify = stringify;
+
+var numberRegexp = /^[-+]?([0-9]*\.[0-9]+|[0-9]+)([eE][-+]?[0-9]+)?/;
+
+ /*
+ * Parse WKT and return GeoJSON.
+ *
+ * @param {string} _ A WKT geometry
+ * @return {?Object} A GeoJSON geometry object
+ */
+function parse(_) {
+ var parts = _.split(";"),
+ _ = parts.pop(),
+ srid = (parts.shift() || "").split("=").pop();
+
+ var i = 0;
+
+ function $(re) {
+ var match = _.substring(i).match(re);
+ if (!match) return null;
+ else {
+ i += match[0].length;
+ return match[0];
+ }
+ }
+
+ function crs(obj) {
+ if (obj && srid.match(/\d+/)) {
+ obj.crs = {
+ type: 'name',
+ properties: {
+ name: 'urn:ogc:def:crs:EPSG::' + srid
+ }
+ };
+ }
+
+ return obj;
+ }
+
+ function white() { $(/^\s*/); }
+
+ function multicoords() {
+ white();
+ var depth = 0, rings = [], stack = [rings],
+ pointer = rings, elem;
+
+ while (elem =
+ $(/^(\()/) ||
+ $(/^(\))/) ||
+ $(/^(\,)/) ||
+ $(numberRegexp)) {
+ if (elem == '(') {
+ stack.push(pointer);
+ pointer = [];
+ stack[stack.length - 1].push(pointer);
+ depth++;
+ } else if (elem == ')') {
+ pointer = stack.pop();
+ // the stack was empty, input was malformed
+ if (!pointer) return;
+ depth--;
+ if (depth === 0) break;
+ } else if (elem === ',') {
+ pointer = [];
+ stack[stack.length - 1].push(pointer);
+ } else if (!isNaN(parseFloat(elem))) {
+ pointer.push(parseFloat(elem));
+ } else {
+ return null;
+ }
+ white();
+ }
+
+ if (depth !== 0) return null;
+ return rings;
+ }
+
+ function coords() {
+ var list = [], item, pt;
+ while (pt =
+ $(numberRegexp) ||
+ $(/^(\,)/)) {
+ 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();
+ if (!c) return null;
+ white();
+ if (!$(/^(\))/)) return null;
+ return {
+ type: 'Point',
+ coordinates: c[0]
+ };
+ }
+
+ function multipoint() {
+ if (!$(/^(multipoint)/i)) return null;
+ white();
+ var c = multicoords();
+ if (!c) return null;
+ white();
+ return {
+ type: 'MultiPoint',
+ coordinates: c
+ };
+ }
+
+ function multilinestring() {
+ if (!$(/^(multilinestring)/i)) return null;
+ white();
+ var c = multicoords();
+ if (!c) return null;
+ white();
+ return {
+ type: 'MultiLineString',
+ coordinates: c
+ };
+ }
+
+ function linestring() {
+ if (!$(/^(linestring)/i)) return null;
+ white();
+ if (!$(/^(\()/)) return null;
+ var c = coords();
+ if (!c) return null;
+ 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 crs(root());
+}
+
+/**
+ * Stringifies a GeoJSON object into WKT
+ */
+function stringify(gj) {
+ if (gj.type === 'Feature') {
+ gj = gj.geometry;
+ }
+
+ function pairWKT(c) {
+ if (c.length === 2) {
+ return c[0] + ' ' + c[1];
+ } else if (c.length === 3) {
+ return c[0] + ' ' + c[1] + ' ' + c[2];
+ }
+ }
+
+ function ringWKT(r) {
+ return r.map(pairWKT).join(', ');
+ }
+
+ function ringsWKT(r) {
+ return r.map(ringWKT).map(wrapParens).join(', ');
+ }
+
+ function multiRingsWKT(r) {
+ return r.map(ringsWKT).map(wrapParens).join(', ');
+ }
+
+ function wrapParens(s) { return '(' + s + ')'; }
+
+ switch (gj.type) {
+ case 'Point':
+ return 'POINT (' + pairWKT(gj.coordinates) + ')';
+ case 'LineString':
+ return 'LINESTRING (' + ringWKT(gj.coordinates) + ')';
+ case 'Polygon':
+ return 'POLYGON (' + ringsWKT(gj.coordinates) + ')';
+ case 'MultiPoint':
+ return 'MULTIPOINT (' + ringWKT(gj.coordinates) + ')';
+ case 'MultiPolygon':
+ return 'MULTIPOLYGON (' + multiRingsWKT(gj.coordinates) + ')';
+ case 'MultiLineString':
+ return 'MULTILINESTRING (' + ringsWKT(gj.coordinates) + ')';
+ case 'GeometryCollection':
+ return 'GEOMETRYCOLLECTION (' + gj.geometries.map(stringify).join(', ') + ')';
+ default:
+ throw new Error('stringify requires a valid GeoJSON Feature or geometry object as input');
+ }
+}
+
+},{}]},{},[1])(1)
+});
\ No newline at end of file
diff --git a/assets/leaflet-omnivore/leaflet-omnivore.min.js b/assets/leaflet-omnivore/leaflet-omnivore.min.js
new file mode 100644
index 0000000..5c57282
--- /dev/null
+++ b/assets/leaflet-omnivore/leaflet-omnivore.min.js
@@ -0,0 +1 @@
+!function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var n;"undefined"!=typeof window?n=window:"undefined"!=typeof global?n=global:"undefined"!=typeof self&&(n=self),n.omnivore=e()}}(function(){var e;return function r(e,n,t){function o(u,a){if(!n[u]){if(!e[u]){var s="function"==typeof require&&require;if(!a&&s)return s(u,!0);if(i)return i(u,!0);var f=new Error("Cannot find module '"+u+"'");throw f.code="MODULE_NOT_FOUND",f}var c=n[u]={exports:{}};e[u][0].call(c.exports,function(n){var r=e[u][1][n];return o(r?r:n)},c,c.exports,r,e,n,t)}return n[u].exports}for(var i="function"==typeof require&&require,u=0;u0)){var r=t.shift();r()}},!0),function(e){t.push(e),window.postMessage("process-tick","*")}):function(e){setTimeout(e,0)}}(),t.title="browser",t.browser=!0,t.env={},t.argv=[],t.on=r,t.addListener=r,t.once=r,t.off=r,t.removeListener=r,t.removeAllListeners=r,t.emit=r,t.binding=function(){throw new Error("process.binding is not supported")},t.cwd=function(){return"/"},t.chdir=function(){throw new Error("process.chdir is not supported")}},{}],5:[function(e,n){function r(e,n,r){function t(e){return e>=200&&300>e||304===e}function o(){void 0===a.status||t(a.status)?n.call(a,null,a):n.call(a,a,null)}var i=!1;if("undefined"==typeof window.XMLHttpRequest)return n(Error("Browser not supported"));if("undefined"==typeof r){var u=e.match(/^\s*https?:\/\/[^\/]*/);r=u&&u[0]!==location.protocol+"//"+location.domain+(location.port?":"+location.port:"")}var a=new window.XMLHttpRequest;if(r&&!("withCredentials"in a)){a=new window.XDomainRequest;var s=n;n=function(){if(i)s.apply(this,arguments);else{var e=this,n=arguments;setTimeout(function(){s.apply(e,n)},0)}}}return"onload"in a?a.onload=o:a.onreadystatechange=function(){4===a.readyState&&o()},a.onerror=function(e){n.call(this,e||!0,null),n=function(){}},a.onprogress=function(){},a.ontimeout=function(e){n.call(this,e,null),n=function(){}},a.onabort=function(e){n.call(this,e,null),n=function(){}},a.open("GET",e,!0),a.send(null),i=!0,a}"undefined"!=typeof n&&(n.exports=r)},{}],6:[function(e,n){function r(e){return!!e.match(/(Lat)(itude)?/gi)}function t(e){return!!e.match(/(L)(on|ng)(gitude)?/i)}function o(e){return"object"==typeof e?Object.keys(e).length:0}function i(e){var n=[",",";"," ","|"],r=[];return n.forEach(function(n){var t=c(n).parse(e);if(t.length>=1){for(var i=o(t[0]),u=0;u= 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(e,n){n.exports=function(e,n){if(n||(n="NSEW"),"string"!=typeof e)return null;var r=/^([0-9.]+)°? *(?:([0-9.]+)['’′‘] *)?(?:([0-9.]+)(?:''|"|”|″) *)?([NSEW])?/,t=e.match(r);return t?t[4]&&-1===n.indexOf(t[4])?null:((t[1]?parseFloat(t[1]):0)+(t[2]?parseFloat(t[2])/60:0)+(t[3]?parseFloat(t[3])/3600:0))*(t[4]&&"S"===t[4]||"W"===t[4]?-1:1):null}},{}],9:[function(e,n){function r(e,n){e=Math.round(e*n),e<<=1,0>e&&(e=~e);for(var r="";e>=32;)r+=String.fromCharCode((32|31&e)+63),e>>=5;return r+=String.fromCharCode(e+63)}var t={};t.decode=function(e,n){for(var r,t,o=0,i=0,u=0,a=[],s=0,f=0,c=null,l=Math.pow(10,n||5);o=32);r=1&f?~(f>>1):f>>1,s=f=0;do c=e.charCodeAt(o++)-63,f|=(31&c)<=32);t=1&f?~(f>>1):f>>1,i+=r,u+=t,a.push([i/l,u/l])}return a},t.encode=function(e,n){if(!e.length)return"";for(var t=Math.pow(10,n||5),o=r(e[0][0],t)+r(e[0][1],t),i=1;iu)){for(var a=0;u>a;a++){var s=g(r[a]);t.push(s.coordinates),s.time&&i.push(s.time)}return{line:t,times:i}}}function r(e){for(var r,t=o(e,"trkseg"),i=[],a=[],s=0;sn?~n:n],o=t[0];return e.transform?(r=[0,0],t.forEach(function(e){r[0]+=e[0],r[1]+=e[1]})):r=t[t.length-1],0>n?[r,o]:[o,r]}function t(e,n){for(var r in e){var t=e[r];delete n[t.start],delete t.start,delete t.end,t.forEach(function(e){o[0>e?~e:e]=1}),a.push(t)}}var o={},i={},u={},a=[],s=-1;return n.forEach(function(r,t){var o,i=e.arcs[0>r?~r:r];i.length<3&&!i[1][0]&&!i[1][1]&&(o=n[++s],n[s]=r,n[t]=o)}),n.forEach(function(e){var n,t,o=r(e),a=o[0],s=o[1];if(n=u[a])if(delete u[n.end],n.push(e),n.end=s,t=i[s]){delete i[t.start];var f=t===n?n:n.concat(t);i[f.start=n.start]=u[f.end=t.end]=f}else i[n.start]=u[n.end]=n;else if(n=i[s])if(delete i[n.start],n.unshift(e),n.start=a,t=u[a]){delete u[t.end];var c=t===n?n:t.concat(n);i[c.start=t.start]=u[c.end=n.end]=c}else i[n.start]=u[n.end]=n;else n=[e],i[n.start=a]=u[n.end=s]=n}),t(u,i),t(i,u),n.forEach(function(e){o[0>e?~e:e]||a.push([e])}),a}function o(e,n,t){function o(e){var n=0>e?~e:e;(c[n]||(c[n]=[])).push({i:e,g:f})}function i(e){e.forEach(o)}function u(e){e.forEach(i)}function a(e){"GeometryCollection"===e.type?e.geometries.forEach(a):e.type in l&&(f=e,l[e.type](e.arcs))}var s=[];if(arguments.length>1){var f,c=[],l={LineString:i,MultiLineString:u,Polygon:u,MultiPolygon:function(e){e.forEach(u)}};a(n),c.forEach(arguments.length<3?function(e){s.push(e[0].i)}:function(e){t(e[0].g,e[e.length-1].g)&&s.push(e[0].i)})}else for(var p=0,d=e.arcs.length;d>p;++p)s.push(p);return{type:"MultiLineString",arcs:r(e,s)}}function i(e,t){function o(e){e.forEach(function(n){n.forEach(function(n){(u[n=0>n?~n:n]||(u[n]=[])).push(e)})}),a.push(e)}function i(n){return d(s(e,{type:"Polygon",arcs:[n]}).coordinates[0])>0}var u={},a=[],f=[];return t.forEach(function(e){"Polygon"===e.type?o(e.arcs):"MultiPolygon"===e.type&&e.arcs.forEach(o)}),a.forEach(function(e){if(!e._){var n=[],r=[e];for(e._=1,f.push(n);e=r.pop();)n.push(e),e.forEach(function(e){e.forEach(function(e){u[0>e?~e:e].forEach(function(e){e._||(e._=1,r.push(e))})})})}}),a.forEach(function(e){delete e._}),{type:"MultiPolygon",arcs:f.map(function(t){var o=[];if(t.forEach(function(e){e.forEach(function(e){e.forEach(function(e){u[0>e?~e:e].length<2&&o.push(e)})})}),o=r(e,o),(n=o.length)>1)for(var a,s=i(t[0][0]),f=0;fe?~e:e],o=0,i=t.length;i>o;++o)n.push(r=t[o].slice()),s(r,o);0>e&&f(n,i)}function t(e){return e=e.slice(),s(e,0),e}function o(e){for(var n=[],t=0,o=e.length;o>t;++t)r(e[t],n);return n.length<2&&n.push(n[0].slice()),n}function i(e){for(var n=o(e);n.length<4;)n.push(n[0].slice());return n}function u(e){return e.map(i)}function a(e){var n=e.type;return"GeometryCollection"===n?{type:n,geometries:e.geometries.map(a)}:n in l?{type:n,coordinates:l[n](e)}:null}var s=m(e.transform),c=e.arcs,l={Point:function(e){return t(e.coordinates)},MultiPoint:function(e){return e.coordinates.map(t)},LineString:function(e){return o(e.arcs)},MultiLineString:function(e){return e.arcs.map(o)},Polygon:function(e){return u(e.arcs)},MultiPolygon:function(e){return e.arcs.map(u)}};return a(n)}function f(e,n){for(var r,t=e.length,o=t-n;o<--t;)r=e[o],e[o++]=e[t],e[t]=r}function c(e,n){for(var r=0,t=e.length;t>r;){var o=r+t>>>1;e[o]e&&(e=~e);var r=o[e];r?r.push(n):o[e]=[n]})}function r(e,r){e.forEach(function(e){n(e,r)})}function t(e,n){"GeometryCollection"===e.type?e.geometries.forEach(function(e){t(e,n)}):e.type in u&&u[e.type](e.arcs,n)}var o={},i=e.map(function(){return[]}),u={LineString:n,MultiLineString:r,Polygon:r,MultiPolygon:function(e,n){e.forEach(function(e){r(e,n)})}};e.forEach(t);for(var a in o)for(var s=o[a],f=s.length,l=0;f>l;++l)for(var p=l+1;f>p;++p){var d,g=s[l],h=s[p];(d=i[g])[a=c(d,h)]!==h&&d.splice(a,0,h),(d=i[h])[a=c(d,g)]!==g&&d.splice(a,0,g)}return i}function p(e,n){function r(e){u.remove(e),e[1][2]=n(e),u.push(e)}var t,o=m(e.transform),i=y(e.transform),u=v(),a=0;for(n||(n=g),e.arcs.forEach(function(e){var r=[];e.forEach(o);for(var i=1,a=e.length-1;a>i;++i)t=e.slice(i-1,i+2),t[1][2]=n(t),r.push(t),u.push(t);e[0][2]=e[a][2]=1/0;for(var i=0,a=r.length;a>i;++i)t=r[i],t.previous=r[i-1],t.next=r[i+1]});t=u.pop();){var s=t.previous,f=t.next;t[1][2]0;){var r=(n+1>>1)-1,o=t[r];if(h(e,o)>=0)break;t[o._=n]=o,t[e._=n=r]=e}}function n(e,n){for(;;){var r=n+1<<1,i=r-1,u=n,a=t[u];if(o>i&&h(t[i],a)<0&&(a=t[u=i]),o>r&&h(t[r],a)<0&&(a=t[u=r]),u===n)break;t[a._=n]=a,t[e._=n=u]=e}}var r={},t=[],o=0;return r.push=function(n){return e(t[n._=o]=n,o++),o},r.pop=function(){if(!(0>=o)){var e,r=t[0];return--o>0&&(e=t[o],n(t[e._=0]=e,0)),r}},r.remove=function(r){var i,u=r._;if(t[u]===r)return u!==--o&&(i=t[o],(h(i,r)<0?e:n)(t[i._=u]=i,u)),u},r}function m(e){if(!e)return w;var n,r,t=e.scale[0],o=e.scale[1],i=e.translate[0],u=e.translate[1];return function(e,a){a||(n=r=0),e[0]=(n+=e[0])*t+i,e[1]=(r+=e[1])*o+u}}function y(e){if(!e)return w;var n,r,t=e.scale[0],o=e.scale[1],i=e.translate[0],u=e.translate[1];return function(e,a){a||(n=r=0);var s=(e[0]-i)/t|0,f=(e[1]-u)/o|0;e[0]=s-n,e[1]=f-r,n=s,r=f}}function w(){}var x={version:"1.6.8",mesh:function(e){return s(e,o.apply(this,arguments))},meshArcs:o,merge:function(e){return s(e,i.apply(this,arguments))},mergeArcs:i,feature:u,neighbors:l,presimplify:p};"function"==typeof e&&e.amd?e(x):"object"==typeof t&&t.exports?t.exports=x:this.topojson=x}()},{}],12:[function(e,n){function r(e){function n(n){var r=e.substring(m).match(n);return r?(m+=r[0].length,r[0]):null}function r(e){return e&&v.match(/\d+/)&&(e.crs={type:"name",properties:{name:"urn:ogc:def:crs:EPSG::"+v}}),e}function t(){n(/^\s*/)}function i(){t();for(var e,r=0,i=[],u=[i],a=i;e=n(/^(\()/)||n(/^(\))/)||n(/^(\,)/)||n(o);){if("("==e)u.push(a),a=[],u[u.length-1].push(a),r++;else if(")"==e){if(a=u.pop(),!a)return;if(r--,0===r)break}else if(","===e)a=[],u[u.length-1].push(a);else{if(isNaN(parseFloat(e)))return null;a.push(parseFloat(e))}t()}return 0!==r?null:i}function u(){for(var e,r,i=[];r=n(o)||n(/^(\,)/);)","==r?(i.push(e),e=[]):(e||(e=[]),e.push(parseFloat(r))),t();return e&&i.push(e),i.length?i:null}function a(){if(!n(/^(point)/i))return null;if(t(),!n(/^(\()/))return null;var e=u();return e?(t(),n(/^(\))/)?{type:"Point",coordinates:e[0]}:null):null}function s(){if(!n(/^(multipoint)/i))return null;t();var e=i();return e?(t(),{type:"MultiPoint",coordinates:e}):null}function f(){if(!n(/^(multilinestring)/i))return null;t();var e=i();return e?(t(),{type:"MultiLineString",coordinates:e}):null}function c(){if(!n(/^(linestring)/i))return null;if(t(),!n(/^(\()/))return null;var e=u();return e&&n(/^(\))/)?{type:"LineString",coordinates:e}:null}function l(){return n(/^(polygon)/i)?(t(),{type:"Polygon",coordinates:i()}):null}function p(){return n(/^(multipolygon)/i)?(t(),{type:"MultiPolygon",coordinates:i()}):null}function d(){var e,r=[];if(!n(/^(geometrycollection)/i))return null;if(t(),!n(/^(\()/))return null;for(;e=g();)r.push(e),t(),n(/^(\,)/),t();return n(/^(\))/)?{type:"GeometryCollection",geometries:r}:null}function g(){return a()||c()||l()||s()||f()||p()||d()}var h=e.split(";"),e=h.pop(),v=(h.shift()||"").split("=").pop(),m=0;return r(g())}function t(e){function n(e){return 2===e.length?e[0]+" "+e[1]:3===e.length?e[0]+" "+e[1]+" "+e[2]:void 0}function r(e){return e.map(n).join(", ")}function o(e){return e.map(r).map(u).join(", ")}function i(e){return e.map(o).map(u).join(", ")}function u(e){return"("+e+")"}switch("Feature"===e.type&&(e=e.geometry),e.type){case"Point":return"POINT ("+n(e.coordinates)+")";case"LineString":return"LINESTRING ("+r(e.coordinates)+")";case"Polygon":return"POLYGON ("+o(e.coordinates)+")";case"MultiPoint":return"MULTIPOINT ("+r(e.coordinates)+")";case"MultiPolygon":return"MULTIPOLYGON ("+i(e.coordinates)+")";case"MultiLineString":return"MULTILINESTRING ("+o(e.coordinates)+")";case"GeometryCollection":return"GEOMETRYCOLLECTION ("+e.geometries.map(t).join(", ")+")";default:throw new Error("stringify requires a valid GeoJSON Feature or geometry object as input")}}n.exports=r,n.exports.parse=r,n.exports.stringify=t;var o=/^[-+]?([0-9]*\.[0-9]+|[0-9]+)([eE][-+]?[0-9]+)?/},{}]},{},[1])(1)});
\ No newline at end of file
diff --git a/assets/leaflet-omnivore/package.json b/assets/leaflet-omnivore/package.json
new file mode 100644
index 0000000..59356d6
--- /dev/null
+++ b/assets/leaflet-omnivore/package.json
@@ -0,0 +1,67 @@
+{
+ "name": "leaflet-omnivore",
+ "version": "0.3.2",
+ "description": "a geospatial format parser for Leaflet",
+ "main": "index.js",
+ "scripts": {
+ "test": "zuul --local -- test/test.js",
+ "test-remote": "zuul -- test/test.js",
+ "test-headless": "zuul --phantom test/test.js",
+ "build": "browserify -s omnivore index.js > leaflet-omnivore.js && uglifyjs leaflet-omnivore.js -c -m > leaflet-omnivore.min.js"
+ },
+ "repository": {
+ "type": "git",
+ "url": "git@github.com:mapbox/leaflet-omnivore.git"
+ },
+ "browserify": {
+ "transform": [
+ "brfs",
+ "hintify"
+ ]
+ },
+ "keywords": [
+ "leaflet",
+ "formats",
+ "kml",
+ "csv",
+ "gpx",
+ "geojson",
+ "kml",
+ "leaflet",
+ "maps",
+ "gpx",
+ "wkt",
+ "osm",
+ "polyline",
+ "topojson",
+ "format",
+ "converter"
+ ],
+ "author": "Tom MacWright",
+ "license": "BSD",
+ "bugs": {
+ "url": "https://github.com/mapbox/leaflet-omnivore/issues"
+ },
+ "homepage": "https://github.com/mapbox/leaflet-omnivore",
+ "dependencies": {
+ "csv2geojson": "~3.6.1",
+ "togeojson": "0.10.1",
+ "corslite": "0.0.6",
+ "wellknown": "0.3.0",
+ "hintify": "~0.1.0",
+ "brfs": "0.2.1",
+ "topojson": "1.6.8",
+ "polyline": "0.0.3"
+ },
+ "devDependencies": {
+ "browserify": "7.0.2",
+ "tape": "2.4.2",
+ "uglify-js": "2.4.16",
+ "jshint": "2.5.0",
+ "mocha": "~1.20.1",
+ "zuul": "~1.7.0",
+ "st": "0.5.1",
+ "mapbox.js": "1.6.4",
+ "phantomjs": "~1.9.7-15"
+ }
+}
diff --git a/module/config/config.php b/module/config/config.php
index 7f3cb98..19eadaa 100644
--- a/module/config/config.php
+++ b/module/config/config.php
@@ -33,6 +33,15 @@ $GLOBALS['LEAFLET_LIBRARIES']['leaflet-providers'] = array
'javascript' => 'assets/leaflet/libs/leaflet-providers/leaflet-providers.js'
);
+$GLOBALS['LEAFLET_LIBRARIES']['leaflet-omnivore'] = array
+(
+ 'name' => 'Leaflet-omnivore',
+ 'version' => '0.3.2',
+ 'license' => 'BSD',
+ 'homepage' => 'https://github.com/mapbox/leaflet-omnivore',
+ 'javascript' => 'assets/leaflet/libs/leaflet-omnivore/leaflet-omnivore.min.js'
+);
+
$GLOBALS['LEAFLET_LIBRARIES']['leaflet-ajax'] = array
(
'name' => 'Leaflet-ajax',