1!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){ 2var xhr = _dereq_('corslite'), 3 csv2geojson = _dereq_('csv2geojson'), 4 wellknown = _dereq_('wellknown'), 5 topojson = _dereq_('topojson'), 6 toGeoJSON = _dereq_('togeojson'); 7 8module.exports.geojson = geojsonLoad; 9 10module.exports.topojson = topojsonLoad; 11module.exports.topojson.parse = topojsonParse; 12 13module.exports.csv = csvLoad; 14module.exports.csv.parse = csvParse; 15 16module.exports.gpx = gpxLoad; 17module.exports.gpx.parse = gpxParse; 18 19module.exports.kml = kmlLoad; 20module.exports.kml.parse = kmlParse; 21 22module.exports.wkt = wktLoad; 23module.exports.wkt.parse = wktParse; 24 25function addData(l, d) { 26 if ('addData' in l) l.addData(d); 27 if ('setGeoJSON' in l) l.setGeoJSON(d); 28} 29 30/** 31 * Load a [GeoJSON](http://geojson.org/) document into a layer and return the layer. 32 * 33 * @param {string} url 34 * @param {object} options 35 * @param {object} customLayer 36 * @returns {object} 37 */ 38function geojsonLoad(url, options, customLayer) { 39 var layer = customLayer || L.geoJson(); 40 xhr(url, function(err, response) { 41 if (err) return layer.fire('error', { error: err }); 42 addData(layer, JSON.parse(response.responseText)); 43 layer.fire('ready'); 44 }); 45 return layer; 46} 47 48/** 49 * Load a [TopoJSON](https://github.com/mbostock/topojson) document into a layer and return the layer. 50 * 51 * @param {string} url 52 * @param {object} options 53 * @param {object} customLayer 54 * @returns {object} 55 */ 56function topojsonLoad(url, options, customLayer) { 57 var layer = customLayer || L.geoJson(); 58 xhr(url, onload); 59 function onload(err, response) { 60 if (err) return layer.fire('error', { error: err }); 61 addData(layer, topojsonParse(response.responseText)); 62 layer.fire('ready'); 63 } 64 return layer; 65} 66 67/** 68 * Load a CSV document into a layer and return the layer. 69 * 70 * @param {string} url 71 * @param {object} options 72 * @param {object} customLayer 73 * @returns {object} 74 */ 75function csvLoad(url, options, customLayer) { 76 var layer = customLayer || L.geoJson(); 77 xhr(url, onload); 78 function onload(err, response) { 79 var error; 80 if (err) return layer.fire('error', { error: err }); 81 function avoidReady() { 82 error = true; 83 } 84 layer.on('error', avoidReady); 85 csvParse(response.responseText, options, layer); 86 layer.off('error', avoidReady); 87 if (!error) layer.fire('ready'); 88 } 89 return layer; 90} 91 92/** 93 * Load a GPX document into a layer and return the layer. 94 * 95 * @param {string} url 96 * @param {object} options 97 * @param {object} customLayer 98 * @returns {object} 99 */ 100function gpxLoad(url, options, customLayer) { 101 var layer = customLayer || L.geoJson(); 102 xhr(url, onload); 103 function onload(err, response) { 104 var error; 105 if (err) return layer.fire('error', { error: err }); 106 function avoidReady() { 107 error = true; 108 } 109 layer.on('error', avoidReady); 110 gpxParse(response.responseXML || response.responseText, options, layer); 111 layer.off('error', avoidReady); 112 if (!error) layer.fire('ready'); 113 } 114 return layer; 115} 116 117/** 118 * Load a [KML](https://developers.google.com/kml/documentation/) document into a layer and return the layer. 119 * 120 * @param {string} url 121 * @param {object} options 122 * @param {object} customLayer 123 * @returns {object} 124 */ 125function kmlLoad(url, options, customLayer) { 126 var layer = L.geoJson(); 127 xhr(url, onload); 128 function onload(err, response) { 129 var error; 130 if (err) return layer.fire('error', { error: err }); 131 function avoidReady() { 132 error = true; 133 } 134 layer.on('error', avoidReady); 135 kmlParse(response.responseXML || response.responseText, options, layer); 136 layer.off('error', avoidReady); 137 if (!error) layer.fire('ready'); 138 } 139 return layer; 140} 141 142/** 143 * Load a WKT (Well Known Text) string into a layer and return the layer 144 * 145 * @param {string} url 146 * @param {object} options 147 * @param {object} customLayer 148 * @returns {object} 149 */ 150function wktLoad(url, options, customLayer) { 151 var layer = customLayer || L.geoJson(); 152 xhr(url, onload); 153 function onload(err, response) { 154 if (err) return layer.fire('error', { error: err }); 155 wktParse(response.responseText, options, layer); 156 layer.fire('ready'); 157 } 158 return layer; 159} 160
161function topojsonParse(data) { 162 var o = typeof data === 'string' ? 163 JSON.parse(data) : data; 164 var features = []; 165 for (var i in o.objects) { 166 var ft = topojson.feature(o, o.objects[i]); 167 if (ft.features) features = features.concat(ft.features); 168 else features = features.concat([ft]); 169 } 170 return features; 171} 172 173function csvParse(csv, options, layer) { 174 layer = layer || L.geoJson(); 175 options = options || {}; 176 csv2geojson.csv2geojson(csv, options, onparse); 177 function onparse(err, geojson) { 178 if (err) return layer.fire('error', { error: err }); 179 addData(layer, geojson); 180 } 181 return layer; 182} 183 184function gpxParse(gpx, options, layer) { 185 var xml = parseXML(gpx); 186 if (!xml) return layer.fire('error', { 187 error: 'Could not parse GPX' 188 }); 189 layer = layer || L.geoJson(); 190 var geojson = toGeoJSON.gpx(xml); 191 addData(layer, geojson); 192 return layer; 193} 194 195 196function kmlParse(gpx, options, layer) { 197 var xml = parseXML(gpx); 198 if (!xml) return layer.fire('error', { 199 error: 'Could not parse GPX' 200 }); 201 layer = layer || L.geoJson(); 202 var geojson = toGeoJSON.kml(xml); 203 addData(layer, geojson); 204 return layer; 205} 206 207function wktParse(wkt, options, layer) { 208 layer = layer || L.geoJson(); 209 var geojson = wellknown(wkt); 210 addData(layer, geojson); 211 return layer; 212} 213 214function parseXML(str) { 215 if (typeof str === 'string') { 216 return (new DOMParser()).parseFromString(str, 'text/xml'); 217 } else { 218 return str; 219 } 220} 221 222},{"corslite":5,"csv2geojson":6,"togeojson":9,"topojson":10,"wellknown":38}],2:[function(_dereq_,module,exports){ 223 224},{}],3:[function(_dereq_,module,exports){ 225module.exports=_dereq_(2) 226},{}],4:[function(_dereq_,module,exports){ 227// shim for using process in browser 228 229var process = module.exports = {}; 230 231process.nextTick = (function () { 232 var canSetImmediate = typeof window !== 'undefined' 233 && window.setImmediate; 234 var canPost = typeof window !== 'undefined' 235 && window.postMessage && window.addEventListener 236 ; 237 238 if (canSetImmediate) { 239 return function (f) { return window.setImmediate(f) }; 240 } 241 242 if (canPost) { 243 var queue = []; 244 window.addEventListener('message', function (ev) { 245 var source = ev.source; 246 if ((source === window || source === null) && ev.data === 'process-tick') { 247 ev.stopPropagation(); 248 if (queue.length > 0) { 249 var fn = queue.shift(); 250 fn(); 251 } 252 } 253 }, true); 254 255 return function nextTick(fn) { 256 queue.push(fn); 257 window.postMessage('process-tick', '*'); 258 }; 259 } 260 261 return function nextTick(fn) { 262 setTimeout(fn, 0); 263 }; 264})(); 265 266process.title = 'browser'; 267process.browser = true; 268process.env = {}; 269process.argv = []; 270 271process.binding = function (name) { 272 throw new Error('process.binding is not supported'); 273} 274 275// TODO(shtylman) 276process.cwd = function () { return '/' }; 277process.chdir = function (dir) { 278 throw new Error('process.chdir is not supported'); 279}; 280 281},{}],5:[function(_dereq_,module,exports){ 282function xhr(url, callback, cors) { 283 var sent = false; 284 285 if (typeof window.XMLHttpRequest === 'undefined') { 286 return callback(Error('Browser not supported')); 287 } 288 289 if (typeof cors === 'undefined') { 290 var m = url.match(/^\s*https?:\/\/[^\/]*/); 291 cors = m && (m[0] !== location.protocol + '//' + location.domain + 292 (location.port ? ':' + location.port : '')); 293 } 294 295 var x; 296 297 function isSuccessful(status) { 298 return status >= 200 && status < 300 || status === 304; 299 } 300 301 if (cors && ( 302 // IE7-9 Quirks & Compatibility 303 typeof window.XDomainRequest === 'object' || 304 // IE9 Standards mode 305 typeof window.XDomainRequest === 'function' 306 )) { 307 // IE8-10 308 x = new window.XDomainRequest(); 309 310 // Ensure callback is never called synchronously, i.e., before 311 // x.send() returns (this has been observed in the wild). 312 // See https://github.com/mapbox/mapbox.js/issues/472 313 var original = callback; 314 callback = function() { 315 if (sent) { 316 original.apply(this, arguments); 317 } else { 318 var that = this, args = arguments; 319 setTimeout(function() { 320 original.apply(that, args); 321 }, 0); 322 } 323 } 324 } else { 325 x = new window.XMLHttpRequest(); 326 } 327 328 function loaded() { 329 if ( 330 // XDomainRequest 331 x.status === undefined || 332 // modern browsers 333 isSuccessful(x.status)) callback.call(x, null, x); 334 else callback.call(x, x, null); 335 } 336 337 // Both `onreadystatechange` and `onload` can fire. `onreadystatechange` 338 // has [been supported for longer](http://stackoverflow.com/a/9181508/229001). 339 if ('onload' in x) { 340 x.onload = loaded; 341 } else { 342 x.onreadystatechange = function readystate() { 343 if (x.readyState === 4) { 344 loaded(); 345 } 346 }; 347 } 348 349 // Call the callback with the XMLHttpRequest object as an error and prevent 350 // it from ever being called again by reassigning it to `noop` 351 x.onerror = function error(evt) { 352 // XDomainRequest provides no evt parameter 353 callback.call(this, evt || true, null); 354 callback = function() { }; 355 }; 356 357 // IE9 must have onprogress be set to a unique function. 358 x.onprogress = function() { }; 359 360 x.ontimeout = function(evt) { 361 callback.call(this, evt, null); 362 callback = function() { }; 363 }; 364 365 x.onabort = function(evt) { 366 callback.call(this, evt, null); 367 callback = function() { }; 368 }; 369 370 // GET is the only supported HTTP Verb by XDomainRequest and is the 371 // only one supported here. 372 x.open('GET', url, true); 373 374 // Send the request. Sending data is not supported. 375 x.send(null); 376 sent = true; 377 378 return x; 379} 380 381if (typeof module !== 'undefined') module.exports = xhr; 382 383},{}],6:[function(_dereq_,module,exports){ 384var dsv = _dereq_('dsv'), 385 sexagesimal = _dereq_('sexagesimal'); 386 387function isLat(f) { return !!f.match(/(Lat)(itude)?/gi); } 388function isLon(f) { return !!f.match(/(L)(on|ng)(gitude)?/i); } 389 390function keyCount(o) { 391 return (typeof o == 'object') ? Object.keys(o).length : 0; 392} 393 394function autoDelimiter(x) { 395 var delimiters = [',', ';', '\t', '|']; 396 var results = []; 397
398 delimiters.forEach(function(delimiter) { 399 var res = dsv(delimiter).parse(x); 400 if (res.length >= 1) { 401 var count = keyCount(res[0]); 402 for (var i = 0; i < res.length; i++) { 403 if (keyCount(res[i]) !== count) return; 404 } 405 results.push({ 406 delimiter: delimiter, 407 arity: Object.keys(res[0]).length, 408 }); 409 } 410 }); 411 412 if (results.length) { 413 return results.sort(function(a, b) { 414 return b.arity - a.arity; 415 })[0].delimiter; 416 } else { 417 return null; 418 } 419} 420 421function auto(x) { 422 var delimiter = autoDelimiter(x); 423 if (!delimiter) return null; 424 return dsv(delimiter).parse(x); 425} 426 427function csv2geojson(x, options, callback) { 428 429 if (!callback) { 430 callback = options; 431 options = {}; 432 } 433 434 options.delimiter = options.delimiter || ','; 435 436 var latfield = options.latfield || '', 437 lonfield = options.lonfield || ''; 438 439 var features = [], 440 featurecollection = { type: 'FeatureCollection', features: features }; 441 442 if (options.delimiter === 'auto' && typeof x == 'string') { 443 options.delimiter = autoDelimiter(x); 444 if (!options.delimiter) return callback({ 445 type: 'Error', 446 message: 'Could not autodetect delimiter' 447 }); 448 } 449 450 var parsed = (typeof x == 'string') ? dsv(options.delimiter).parse(x) : x; 451 452 if (!parsed.length) return callback(null, featurecollection); 453 454 if (!latfield || !lonfield) { 455 for (var f in parsed[0]) { 456 if (!latfield && isLat(f)) latfield = f; 457 if (!lonfield && isLon(f)) lonfield = f; 458 } 459 if (!latfield || !lonfield) { 460 var fields = []; 461 for (var k in parsed[0]) fields.push(k); 462 return callback({ 463 type: 'Error', 464 message: 'Latitude and longitude fields not present', 465 data: parsed, 466 fields: fields 467 }); 468 } 469 } 470 471 var errors = []; 472 473 for (var i = 0; i < parsed.length; i++) { 474 if (parsed[i][lonfield] !== undefined && 475 parsed[i][lonfield] !== undefined) { 476 477 var lonk = parsed[i][lonfield], 478 latk = parsed[i][latfield], 479 lonf, latf, 480 a; 481 482 a = sexagesimal(lonk, 'EW'); 483 if (a) lonk = a; 484 a = sexagesimal(latk, 'NS'); 485 if (a) latk = a; 486 487 lonf = parseFloat(lonk); 488 latf = parseFloat(latk); 489 490 if (isNaN(lonf) || 491 isNaN(latf)) { 492 errors.push({ 493 message: 'A row contained an invalid value for latitude or longitude', 494 row: parsed[i] 495 }); 496 } else { 497 if (!options.includeLatLon) { 498 delete parsed[i][lonfield]; 499 delete parsed[i][latfield]; 500 } 501 502 features.push({ 503 type: 'Feature', 504 properties: parsed[i], 505 geometry: { 506 type: 'Point', 507 coordinates: [ 508 parseFloat(lonf), 509 parseFloat(latf) 510 ] 511 } 512 }); 513 } 514 } 515 } 516 517 callback(errors.length ? errors: null, featurecollection); 518} 519 520function toLine(gj) { 521 var features = gj.features; 522 var line = { 523 type: 'Feature', 524 geometry: { 525 type: 'LineString', 526 coordinates: [] 527 } 528 }; 529 for (var i = 0; i < features.length; i++) { 530 line.geometry.coordinates.push(features[i].geometry.coordinates); 531 } 532 line.properties = features[0].properties; 533 return { 534 type: 'FeatureCollection', 535 features: [line] 536 }; 537} 538 539function toPolygon(gj) { 540 var features = gj.features; 541 var poly = { 542 type: 'Feature', 543 geometry: { 544 type: 'Polygon', 545 coordinates: [[]] 546 } 547 }; 548 for (var i = 0; i < features.length; i++) { 549 poly.geometry.coordinates[0].push(features[i].geometry.coordinates); 550 } 551 poly.properties = features[0].properties; 552 return { 553 type: 'FeatureCollection', 554 features: [poly] 555 }; 556} 557 558module.exports = { 559 isLon: isLon, 560 isLat: isLat, 561 csv: dsv.csv.parse, 562 tsv: dsv.tsv.parse, 563 dsv: dsv, 564 auto: auto, 565 csv2geojson: csv2geojson,
566 toLine: toLine, 567 toPolygon: toPolygon 568}; 569 570},{"dsv":7,"sexagesimal":8}],7:[function(_dereq_,module,exports){ 571var fs = _dereq_("fs"); 572 573module.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")(); 574 575},{"fs":2}],8:[function(_dereq_,module,exports){ 576module.exports = function(x, dims) { 577 if (!dims) dims = 'NSEW'; 578 if (typeof x !== 'string') return null; 579 var r = /^([0-9.]+)°? *(?:([0-9.]+)['ââ²â] *)?(?:([0-9.]+)(?:''|"|â|â³) *)?([NSEW])?/, 580 m = x.match(r); 581 if (!m) return null; 582 else if (m[4] && dims.indexOf(m[4]) === -1) return null; 583 else return (((m[1]) ? parseFloat(m[1]) : 0) + 584 ((m[2] ? parseFloat(m[2]) / 60 : 0)) + 585 ((m[3] ? parseFloat(m[3]) / 3600 : 0))) * 586 ((m[4] && m[4] === 'S' || m[4] === 'W') ? -1 : 1); 587}; 588 589},{}],9:[function(_dereq_,module,exports){ 590(function (process){toGeoJSON = (function() { 591 'use strict'; 592 593 var removeSpace = (/\s*/g), 594 trimSpace = (/^\s*|\s*$/g), 595 splitSpace = (/\s+/); 596 // generate a short, numeric hash of a string 597 function okhash(x) { 598 if (!x || !x.length) return 0; 599 for (var i = 0, h = 0; i < x.length; i++) { 600 h = ((h << 5) - h) + x.charCodeAt(i) | 0; 601 } return h; 602 } 603 // all Y children of X 604 function get(x, y) { return x.getElementsByTagName(y); } 605 function attr(x, y) { return x.getAttribute(y); } 606 function attrf(x, y) { return parseFloat(attr(x, y)); } 607 // one Y child of X, if any, otherwise null 608 function get1(x, y) { var n = get(x, y); return n.length ? n[0] : null; } 609 // https://developer.mozilla.org/en-US/docs/Web/API/Node.normalize 610 function norm(el) { if (el.normalize) { el.normalize(); } return el; } 611 // cast array x into numbers 612 function numarray(x) { 613 for (var j = 0, o = []; j < x.length; j++) o[j] = parseFloat(x[j]); 614 return o; 615 } 616 function clean(x) { 617 var o = {}; 618 for (var i in x) if (x[i]) o[i] = x[i]; 619 return o; 620 } 621 // get the content of a text node, if any 622 function nodeVal(x) { if (x) {norm(x);} return x && x.firstChild && x.firstChild.nodeValue; } 623 // get one coordinate from a coordinate array, if any 624 function coord1(v) { return numarray(v.replace(removeSpace, '').split(',')); } 625 // get all coordinates from a coordinate array as [[],[]] 626 function coord(v) { 627 var coords = v.replace(trimSpace, '').split(splitSpace), 628 o = []; 629 for (var i = 0; i < coords.length; i++) { 630 o.push(coord1(coords[i])); 631 } 632 return o; 633 } 634 function coordPair(x) { 635 var ll = [attrf(x, 'lon'), attrf(x, 'lat')], 636 ele = get1(x, 'ele'); 637 if (ele) ll.push(parseFloat(nodeVal(ele))); 638 return ll; 639 } 640 641 // create a new feature collection parent object 642 function fc() { 643 return { 644 type: 'FeatureCollection', 645 features: [] 646 }; 647 } 648 649 var serializer; 650 if (typeof XMLSerializer !== 'undefined') { 651 serializer = new XMLSerializer();
652 // only require xmldom in a node environment 653 } else if (typeof exports === 'object' && typeof process === 'object' && !process.browser) { 654 serializer = new (_dereq_('xmldom').XMLSerializer)(); 655 } 656 function xml2str(str) { return serializer.serializeToString(str); } 657 658 var t = { 659 kml: function(doc, o) { 660 o = o || {}; 661 662 var gj = fc(), 663 // styleindex keeps track of hashed styles in order to match features 664 styleIndex = {}, 665 // atomic geospatial types supported by KML - MultiGeometry is 666 // handled separately 667 geotypes = ['Polygon', 'LineString', 'Point', 'Track'], 668 // all root placemarks in the file 669 placemarks = get(doc, 'Placemark'), 670 styles = get(doc, 'Style'); 671 672 for (var k = 0; k < styles.length; k++) { 673 styleIndex['#' + attr(styles[k], 'id')] = okhash(xml2str(styles[k])).toString(16); 674 } 675 for (var j = 0; j < placemarks.length; j++) { 676 gj.features = gj.features.concat(getPlacemark(placemarks[j])); 677 } 678 function gxCoord(v) { return numarray(v.split(' ')); } 679 function gxCoords(root) { 680 var elems = get(root, 'coord', 'gx'), coords = []; 681 for (var i = 0; i < elems.length; i++) coords.push(gxCoord(nodeVal(elems[i]))); 682 return coords; 683 } 684 function getGeometry(root) { 685 var geomNode, geomNodes, i, j, k, geoms = []; 686 if (get1(root, 'MultiGeometry')) return getGeometry(get1(root, 'MultiGeometry')); 687 if (get1(root, 'MultiTrack')) return getGeometry(get1(root, 'MultiTrack')); 688 for (i = 0; i < geotypes.length; i++) { 689 geomNodes = get(root, geotypes[i]); 690 if (geomNodes) { 691 for (j = 0; j < geomNodes.length; j++) { 692 geomNode = geomNodes[j]; 693 if (geotypes[i] == 'Point') { 694 geoms.push({ 695 type: 'Point', 696 coordinates: coord1(nodeVal(get1(geomNode, 'coordinates'))) 697 }); 698 } else if (geotypes[i] == 'LineString') { 699 geoms.push({ 700 type: 'LineString', 701 coordinates: coord(nodeVal(get1(geomNode, 'coordinates'))) 702 }); 703 } else if (geotypes[i] == 'Polygon') { 704 var rings = get(geomNode, 'LinearRing'), 705 coords = []; 706 for (k = 0; k < rings.length; k++) { 707 coords.push(coord(nodeVal(get1(rings[k], 'coordinates')))); 708 } 709 geoms.push({ 710 type: 'Polygon', 711 coordinates: coords 712 }); 713 } else if (geotypes[i] == 'Track') { 714 geoms.push({ 715 type: 'LineString', 716 coordinates: gxCoords(geomNode) 717 }); 718 } 719 } 720 } 721 } 722 return geoms; 723 } 724 function getPlacemark(root) { 725 var geoms = getGeometry(root), i, properties = {}, 726 name = nodeVal(get1(root, 'name')), 727 styleUrl = nodeVal(get1(root, 'styleUrl')), 728 description = nodeVal(get1(root, 'description')), 729 timeSpan = get1(root, 'TimeSpan'), 730 extendedData = get1(root, 'ExtendedData'); 731 732 if (!geoms.length) return []; 733 if (name) properties.name = name; 734 if (styleUrl && styleIndex[styleUrl]) { 735 properties.styleUrl = styleUrl; 736 properties.styleHash = styleIndex[styleUrl]; 737 } 738 if (description) properties.description = description; 739 if (timeSpan) { 740 var begin = nodeVal(get1(timeSpan, 'begin')); 741 var end = nodeVal(get1(timeSpan, 'end')); 742 properties.timespan = { begin: begin, end: end }; 743 } 744 if (extendedData) { 745 var datas = get(extendedData, 'Data'), 746 simpleDatas = get(extendedData, 'SimpleData'); 747 748 for (i = 0; i < datas.length; i++) { 749 properties[datas[i].getAttribute('name')] = nodeVal(get1(datas[i], 'value')); 750 } 751 for (i = 0; i < simpleDatas.length; i++) { 752 properties[simpleDatas[i].getAttribute('name')] = nodeVal(simpleDatas[i]); 753 } 754 } 755 return [{ 756 type: 'Feature', 757 geometry: (geoms.length === 1) ? geoms[0] : { 758 type: 'GeometryCollection', 759 geometries: geoms 760 }, 761 properties: properties 762 }]; 763 } 764 return gj; 765 }, 766 gpx: function(doc, o) { 767 var i, 768 tracks = get(doc, 'trk'), 769 routes = get(doc, 'rte'), 770 waypoints = get(doc, 'wpt'), 771 // a feature collection 772 gj = fc(); 773 for (i = 0; i < tracks.length; i++) { 774 gj.features.push(getLinestring(tracks[i], 'trkpt')); 775 } 776 for (i = 0; i < routes.length; i++) { 777 gj.features.push(getLinestring(routes[i], 'rtept')); 778 } 779 for (i = 0; i < waypoints.length; i++) { 780 gj.features.push(getPoint(waypoints[i])); 781 } 782 function getLinestring(node, pointname) { 783 var j, pts = get(node, pointname), line = []; 784 for (j = 0; j < pts.length; j++) { 785 line.push(coordPair(pts[j])); 786 } 787 return { 788 type: 'Feature', 789 properties: getProperties(node), 790 geometry: { 791 type: 'LineString', 792 coordinates: line 793 } 794 }; 795 } 796 function getPoint(node) { 797 var prop = getProperties(node); 798 prop.sym = nodeVal(get1(node, 'sym')); 799 return { 800 type: 'Feature', 801 properties: prop, 802 geometry: { 803 type: 'Point', 804 coordinates: coordPair(node) 805 } 806 }; 807 } 808 function getProperties(node) { 809 var meta = ['name', 'desc', 'author', 'copyright', 'link', 810 'time', 'keywords'], 811 prop = {}, 812 k; 813 for (k = 0; k < meta.length; k++) { 814 prop[meta[k]] = nodeVal(get1(node, meta[k])); 815 } 816 return clean(prop); 817 } 818 return gj; 819 } 820 }; 821 return t; 822})(); 823 824if (typeof module !== 'undefined') module.exports = toGeoJSON; 825}).call(this,_dereq_("/Users/tmcw/src/leaflet-omnivore/node_modules/browserify/node_modules/insert-module-globals/node_modules/process/browser.js")) 826},{"/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){ 827var topojson = module.exports = _dereq_("./topojson"); 828topojson.topology = _dereq_("./lib/topojson/topology"); 829topojson.simplify = _dereq_("./lib/topojson/simplify"); 830topojson.clockwise = _dereq_("./lib/topojson/clockwise"); 831topojson.filter = _dereq_("./lib/topojson/filter"); 832topojson.prune = _dereq_("./lib/topojson/prune"); 833topojson.bind = _dereq_("./lib/topojson/bind"); 834 835},{"./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){ 836var type = _dereq_("./type"), 837 topojson = _dereq_("../../"); 838 839module.exports = function(topology, propertiesById) { 840 var bind = type({ 841 geometry: function(geometry) { 842 var properties0 = geometry.properties, 843 properties1 = propertiesById[geometry.id]; 844 if (properties1) { 845 if (properties0) for (var k in properties1) properties0[k] = properties1[k]; 846 else for (var k in properties1) { geometry.properties = properties1; break; } 847 } 848 this.defaults.geometry.call(this, geometry); 849 }, 850 LineString: noop, 851 MultiLineString: noop, 852 Point: noop, 853 MultiPoint: noop, 854 Polygon: noop, 855 MultiPolygon: noop 856 }); 857 858 for (var key in topology.objects) { 859 bind.object(topology.objects[key]); 860 } 861}; 862 863function noop() {} 864 865}
865,{"../../":10,"./type":36}],12:[function(_dereq_,module,exports){ 866 867// Computes the bounding box of the specified hash of GeoJSON objects. 868module.exports = function(objects) { 869 var x0 = Infinity, 870 y0 = Infinity, 871 x1 = -Infinity, 872 y1 = -Infinity; 873 874 function boundGeometry(geometry) { 875 if (geometry && boundGeometryType.hasOwnProperty(geometry.type)) boundGeometryType[geometry.type](geometry); 876 } 877 878 var boundGeometryType = { 879 GeometryCollection: function(o) { o.geometries.forEach(boundGeometry); }, 880 Point: function(o) { boundPoint(o.coordinates); }, 881 MultiPoint: function(o) { o.coordinates.forEach(boundPoint); }, 882 LineString: function(o) { boundLine(o.coordinates); }, 883 MultiLineString: function(o) { o.coordinates.forEach(boundLine); }, 884 Polygon: function(o) { o.coordinates.forEach(boundLine); }, 885 MultiPolygon: function(o) { o.coordinates.forEach(boundMultiLine); } 886 }; 887 888 function boundPoint(coordinates) { 889 var x = coordinates[0], 890 y = coordinates[1]; 891 if (x < x0) x0 = x; 892 if (x > x1) x1 = x; 893 if (y < y0) y0 = y; 894 if (y > y1) y1 = y; 895 } 896 897 function boundLine(coordinates) { 898 coordinates.forEach(boundPoint); 899 } 900 901 function boundMultiLine(coordinates) { 902 coordinates.forEach(boundLine); 903 } 904 905 for (var key in objects) { 906 boundGeometry(objects[key]); 907 } 908 909 return [x0, y0, x1, y1]; 910}; 911 912},{}],13:[function(_dereq_,module,exports){ 913exports.name = "cartesian"; 914exports.formatDistance = formatDistance; 915exports.ringArea = ringArea; 916exports.absoluteArea = Math.abs; 917exports.triangleArea = triangleArea; 918exports.distance = distance; 919 920function formatDistance(d) { 921 return d.toString(); 922} 923 924function ringArea(ring) { 925 var i = 0, 926 n = ring.length, 927 area = ring[n - 1][1] * ring[0][0] - ring[n - 1][0] * ring[0][1]; 928 while (++i < n) { 929 area += ring[i - 1][1] * ring[i][0] - ring[i - 1][0] * ring[i][1]; 930 } 931 return -area * .5; // ensure clockwise pixel areas are positive 932} 933 934function triangleArea(triangle) { 935 return Math.abs( 936 (triangle[0][0] - triangle[2][0]) * (triangle[1][1] - triangle[0][1]) 937 - (triangle[0][0] - triangle[1][0]) * (triangle[2][1] - triangle[0][1]) 938 ); 939} 940 941function distance(x0, y0, x1, y1) { 942 var dx = x0 - x1, dy = y0 - y1; 943 return Math.sqrt(dx * dx + dy * dy); 944} 945 946},{}],14:[function(_dereq_,module,exports){ 947var type = _dereq_("./type"), 948 systems = _dereq_("./coordinate-systems"), 949 topojson = _dereq_("../../"); 950 951module.exports = function(object, options) { 952 if (object.type === "Topology") clockwiseTopology(object, options); 953 else clockwiseGeometry(object, options); 954}; 955 956function clockwiseGeometry(object, options) { 957 var system = null; 958 959 if (options) 960 "coordinate-system" in options && (system = systems[options["coordinate-system"]]); 961 962 var clockwisePolygon = clockwisePolygonSystem(system.ringArea, reverse); 963 964 type({ 965 LineString: noop, 966 MultiLineString: noop, 967 Point: noop, 968 MultiPoint: noop, 969 Polygon: function(polygon) { clockwisePolygon(polygon.coordinates); }, 970 MultiPolygon: function(multiPolygon) { multiPolygon.coordinates.forEach(clockwisePolygon); } 971 }).object(object); 972 973 function reverse(array) { array.reverse(); } 974} 975 976function clockwiseTopology(topology, options) { 977 var system = null; 978 979 if (options) 980 "coordinate-system" in options && (system = systems[options["coordinate-system"]]); 981 982 var clockwisePolygon = clockwisePolygonSystem(ringArea, reverse); 983 984 var clockwise = type({ 985 LineString: noop, 986 MultiLineString: noop, 987 Point: noop, 988 MultiPoint: noop, 989 Polygon: function(polygon) { clockwisePolygon(polygon.arcs); }, 990 MultiPolygon: function(multiPolygon) { multiPolygon.arcs.forEach(clockwisePolygon); } 991 }); 992 993 for (var key in topology.objects) { 994 clockwise.object(topology.objects[key]); 995 } 996 997 function ringArea(ring) { 998 return system.ringArea(topojson.feature(topology, {type: "Polygon", arcs: [ring]}).geometry.coordinates[0]); 999 } 1000 1001 // TODO It might be slightly more compact to reverse the arc. 1002 function reverse(ring) { 1003 var i = -1, n = ring.length; 1004 ring.reverse(); 1005 while (++i < n) ring[i] = ~ring[i]; 1006 } 1007}; 1008 1009function clockwisePolygonSystem(ringArea, reverse) { 1010 return function(rings) { 1011 if (!(n = rings.length)) return; 1012 var n, 1013 areas = new Array(n), 1014 max = -Infinity, 1015 best, 1016 area,
1017 t; 1018 // Find the largest absolute ring area; this should be the exterior ring. 1019 for (var i = 0; i < n; ++i) { 1020 var area = Math.abs(areas[i] = ringArea(rings[i])); 1021 if (area > max) max = area, best = i; 1022 } 1023 // Ensure the largest ring appears first. 1024 if (best) { 1025 t = rings[best], rings[best] = rings[0], rings[0] = t; 1026 t = areas[best], areas[best] = areas[0], areas[0] = t; 1027 } 1028 if (areas[0] < 0) reverse(rings[0]); 1029 for (var i = 1; i < n; ++i) { 1030 if (areas[i] > 0) reverse(rings[i]); 1031 } 1032 }; 1033} 1034 1035function noop() {} 1036 1037},{"../../":10,"./coordinate-systems":16,"./type":36}],15:[function(_dereq_,module,exports){ 1038// Given a hash of GeoJSON objects and an id function, invokes the id function 1039// to compute a new id for each object that is a feature. The function is passed 1040// the feature and is expected to return the new feature id, or null if the 1041// feature should not have an id. 1042module.exports = function(objects, id) { 1043 if (arguments.length < 2) id = function(d) { return d.id; }; 1044 1045 function idObject(object) { 1046 if (object && idObjectType.hasOwnProperty(object.type)) idObjectType[object.type](object); 1047 } 1048 1049 function idFeature(feature) { 1050 var i = id(feature); 1051 if (i == null) delete feature.id; 1052 else feature.id = i; 1053 } 1054 1055 var idObjectType = { 1056 Feature: idFeature, 1057 FeatureCollection: function(collection) { collection.features.forEach(idFeature); } 1058 }; 1059 1060 for (var key in objects) { 1061 idObject(objects[key]); 1062 } 1063 1064 return objects; 1065}; 1066 1067},{}],16:[function(_dereq_,module,exports){ 1068module.exports = { 1069 cartesian: _dereq_("./cartesian"), 1070 spherical: _dereq_("./spherical") 1071}; 1072 1073},{"./cartesian":13,"./spherical":24}],17:[function(_dereq_,module,exports){ 1074// Given a TopoJSON topology in absolute (quantized) coordinates, 1075// converts to fixed-point delta encoding. 1076// This is a destructive operation that modifies the given topology! 1077module.exports = function(topology) { 1078 var arcs = topology.arcs, 1079 i = -1, 1080 n = arcs.length; 1081 1082 while (++i < n) { 1083 var arc = arcs[i], 1084 j = 0, 1085 m = arc.length, 1086 point = arc[0], 1087 x0 = point[0], 1088 y0 = point[1], 1089 x1, 1090 y1; 1091 while (++j < m) { 1092 point = arc[j]; 1093 x1 = point[0]; 1094 y1 = point[1]; 1095 arc[j] = [x1 - x0, y1 - y0]; 1096 x0 = x1; 1097 y0 = y1; 1098 } 1099 } 1100 1101 return topology; 1102}; 1103 1104},{}],18:[function(_dereq_,module,exports){ 1105var type = _dereq_("./type"), 1106 prune = _dereq_("./prune"), 1107 clockwise = _dereq_("./clockwise"), 1108 systems = _dereq_("./coordinate-systems"), 1109 topojson = _dereq_("../../"); 1110 1111module.exports = function(topology, options) { 1112 var system = null, 1113 forceClockwise = true, // force exterior rings to be clockwise? 1114 minimumArea; 1115 1116 if (options) 1117 "coordinate-system" in options && (system = systems[options["coordinate-system"]]), 1118 "minimum-area" in options && (minimumArea = +options["minimum-area"]), 1119 "force-clockwise" in options && (forceClockwise = !!options["force-clockwise"]); 1120 1121 if (forceClockwise) clockwise(topology, options); // deprecated; for backwards-compatibility 1122 1123 if (!(minimumArea > 0)) minimumArea = Number.MIN_VALUE; 1124 1125 var filter = type({ 1126 LineString: noop, // TODO remove empty lines 1127 MultiLineString: noop, 1128 Point: noop, 1129 MultiPoint: noop, 1130 Polygon: function(polygon) { 1131 polygon.arcs = polygon.arcs.filter(ringArea); 1132 if (!polygon.arcs.length) { 1133 polygon.type = null; 1134 delete polygon.arcs; 1135 } 1136 }, 1137 MultiPolygon: function(multiPolygon) { 1138 multiPolygon.arcs = multiPolygon.arcs.map(function(polygon) { 1139 return polygon.filter(ringArea); 1140 }).filter(function(polygon) { 1141 return polygon.length; 1142 }); 1143 if (!multiPolygon.arcs.length) { 1144 multiPolygon.type = null; 1145 delete multiPolygon.arcs; 1146 } 1147 }, 1148 GeometryCollection: function(collection) { 1149 this.defaults.GeometryCollection.call(this, collection); 1150 collection.geometries = collection.geometries.filter(function(geometry) { return geometry.type != null; }); 1151 if (!collection.geometries.length) { 1152 collection.type = null; 1153 delete collection.geometries; 1154 } 1155 } 1156 }); 1157 1158 for (var key in topology.objects) { 1159 filter.object(topology.objects[key]); 1160 } 1161 1162 prune(topology, options); 1163 1164 function ringArea(ring) { 1165 var topopolygon = {type: "Polygon", arcs: [ring]}, 1166 geopolygon = topojson.feature(topology, topopolygon), 1167 exterior = geopolygon.geometry.coordinates[0], 1168 exteriorArea = system.absoluteArea(system.ringArea(exterior)); 1169 return exteriorArea >= minimumArea; 1170 } 1171}; 1172 1173function noop() {} 1174 1175}
1175,{"../../":10,"./clockwise":14,"./coordinate-systems":16,"./prune":21,"./type":36}],19:[function(_dereq_,module,exports){ 1176// Given a hash of GeoJSON objects, replaces Features with geometry objects. 1177// This is a destructive operation that modifies the input objects! 1178module.exports = function(objects) { 1179 1180 function geomifyObject(object) { 1181 return (object && geomifyObjectType.hasOwnProperty(object.type) 1182 ? geomifyObjectType[object.type] 1183 : geomifyGeometry)(object); 1184 } 1185 1186 function geomifyFeature(feature) { 1187 var geometry = feature.geometry; 1188 if (geometry == null) { 1189 feature.type = null; 1190 } else { 1191 geomifyGeometry(geometry); 1192 feature.type = geometry.type; 1193 if (geometry.geometries) feature.geometries = geometry.geometries; 1194 else if (geometry.coordinates) feature.coordinates = geometry.coordinates; 1195 } 1196 delete feature.geometry; 1197 return feature; 1198 } 1199 1200 function geomifyGeometry(geometry) { 1201 if (!geometry) return {type: null}; 1202 if (geomifyGeometryType.hasOwnProperty(geometry.type)) geomifyGeometryType[geometry.type](geometry); 1203 return geometry; 1204 } 1205 1206 var geomifyObjectType = { 1207 Feature: geomifyFeature, 1208 FeatureCollection: function(collection) { 1209 collection.type = "GeometryCollection"; 1210 collection.geometries = collection.features; 1211 collection.features.forEach(geomifyFeature); 1212 delete collection.features; 1213 return collection; 1214 } 1215 }; 1216 1217 var geomifyGeometryType = { 1218 GeometryCollection: function(o) { 1219 var geometries = o.geometries, i = -1, n = geometries.length; 1220 while (++i < n) geometries[i] = geomifyGeometry(geometries[i]); 1221 }, 1222 MultiPoint: function(o) { 1223 if (!o.coordinates.length) { 1224 o.type = null; 1225 delete o.coordinates; 1226 } else if (o.coordinates.length < 2) { 1227 o.type = "Point"; 1228 o.coordinates = o.coordinates[0]; 1229 } 1230 }, 1231 LineString: function(o) { 1232 if (!o.coordinates.length) { 1233 o.type = null; 1234 delete o.coordinates; 1235 } 1236 }, 1237 MultiLineString: function(o) { 1238 for (var lines = o.coordinates, i = 0, N = 0, n = lines.length; i < n; ++i) { 1239 var line = lines[i]; 1240 if (line.length) lines[N++] = line; 1241 } 1242 if (!N) { 1243 o.type = null; 1244 delete o.coordinates; 1245 } else if (N < 2) { 1246 o.type = "LineString"; 1247 o.coordinates = lines[0]; 1248 } else { 1249 o.coordinates.length = N; 1250 } 1251 }, 1252 Polygon: function(o) { 1253 for (var rings = o.coordinates, i = 0, N = 0, n = rings.length; i < n; ++i) { 1254 var ring = rings[i]; 1255 if (ring.length) rings[N++] = ring; 1256 } 1257 if (!N) { 1258 o.type = null; 1259 delete o.coordinates; 1260 } else { 1261 o.coordinates.length = N; 1262 } 1263 }, 1264 MultiPolygon: function(o) { 1265 for (var polygons = o.coordinates, j = 0, M = 0, m = polygons.length; j < m; ++j) { 1266 for (var rings = polygons[j], i = 0, N = 0, n = rings.length; i < n; ++i) { 1267 var ring = rings[i]; 1268 if (ring.length) rings[N++] = ring; 1269 } 1270 if (N) { 1271 rings.length = N; 1272 polygons[M++] = rings; 1273 } 1274 } 1275 if (!M) { 1276 o.type = null; 1277 delete o.coordinates; 1278 } else if (M < 2) { 1279 o.type = "Polygon"; 1280 o.coordinates = polygons[0]; 1281 } else { 1282 polygons.length = M; 1283 } 1284 } 1285 }; 1286 1287 for (var key in objects) { 1288 objects[key] = geomifyObject(objects[key]); 1289 } 1290 1291 return objects; 1292}; 1293 1294},{}],20:[function(_dereq_,module,exports){ 1295module.exports = function(objects, filter) { 1296 1297 function prefilterGeometry(geometry) { 1298 if (!geometry) return {type: null}; 1299 if (prefilterGeometryType.hasOwnProperty(geometry.type)) prefilterGeometryType[geometry.type](geometry); 1300 return geometry; 1301 } 1302 1303 var prefilterGeometryType = { 1304 GeometryCollection: function(o) { 1305 var geometries = o.geometries, i = -1, n = geometries.length; 1306 while (++i < n) geometries[i] = prefilterGeometry(geometries[i]); 1307 }, 1308 Polygon: function(o) { 1309 for (var rings = o.coordinates, i = 0, N = 0, n = rings.length; i < n; ++i) { 1310 var ring = rings[i]; 1311 if (filter(ring)) rings[N++] = ring; 1312 } 1313 if (!N) { 1314 o.type = null; 1315 delete o.coordinates; 1316 } else { 1317 o.coordinates.length = N; 1318 } 1319 }, 1320 MultiPolygon: function(o) { 1321 for (var polygons = o.coordinates, j = 0, M = 0, m = polygons.length; j < m; ++j) { 1322 for (var rings = polygons[j], i = 0, N = 0, n = rings.length; i < n; ++i) { 1323 var ring = rings[i]; 1324 if (filter(ring)) rings[N++] = ring; 1325 } 1326 if (N) { 1327 rings.length = N; 1328 polygons[M++] = rings; 1329 } 1330 } 1331 if (!M) { 1332 o.type = null; 1333 delete o.coordinates; 1334 } else if (M < 2) { 1335 o.type = "Polygon"; 1336 o.coordinates = polygons[0]; 1337 } else { 1338 polygons.length = M; 1339 } 1340 } 1341 }; 1342 1343 for (var key in objects) { 1344 objects[key] = prefilterGeometry(objects[key]); 1345 } 1346 1347 return objects; 1348}; 1349 1350},{}],21:[function(_dereq_,module,exports){ 1351module.exports = function(topology, options) { 1352 var verbose = false, 1353 objects = topology.objects, 1354 oldArcs = topology.arcs, 1355 oldArcCount = oldArcs.length, 1356 newArcs = topology.arcs = [], 1357 newArcCount = 0, 1358 newIndexByOldIndex = new Array(oldArcs.length); 1359 1360 if (options) 1361 "verbose" in options && (verbose = !!options["verbose"]); 1362 1363 function pruneGeometry(geometry) { 1364 if (geometry && pruneGeometryType.hasOwnProperty(geometry.type)) pruneGeometryType[geometry.type](geometry); 1365 } 1366 1367 var pruneGeometryType = {
1368 GeometryCollection: function(o) { o.geometries.forEach(pruneGeometry); }, 1369 LineString: function(o) { pruneArcs(o.arcs); }, 1370 MultiLineString: function(o) { o.arcs.forEach(pruneArcs); }, 1371 Polygon: function(o) { o.arcs.forEach(pruneArcs); }, 1372 MultiPolygon: function(o) { o.arcs.forEach(pruneMultiArcs); } 1373 }; 1374 1375 function pruneArcs(arcs) { 1376 for (var i = 0, m = 0, n = arcs.length; i < n; ++i) { 1377 var oldIndex = arcs[i], 1378 oldReverse = oldIndex < 0 && (oldIndex = ~oldIndex, true), 1379 oldArc = oldArcs[oldIndex], 1380 newIndex; 1381 1382 // Skip collapsed arc segments. 1383 if (oldArc.length < 3 && !oldArc[1][0] && !oldArc[1][1]) continue; 1384 1385 // If this is the first instance of this arc, 1386 // record it under its new index. 1387 if ((newIndex = newIndexByOldIndex[oldIndex]) == null) { 1388 newIndexByOldIndex[oldIndex] = newIndex = newArcCount++; 1389 newArcs[newIndex] = oldArcs[oldIndex]; 1390 } 1391 1392 arcs[m++] = oldReverse ? ~newIndex : newIndex; 1393 } 1394 1395 // If all were collapsed, restore the last arc to avoid collapsing the line. 1396 if (!(arcs.length = m) && n) { 1397 1398 // If this is the first instance of this arc, 1399 // record it under its new index. 1400 if ((newIndex = newIndexByOldIndex[oldIndex]) == null) { 1401 newIndexByOldIndex[oldIndex] = newIndex = newArcCount++; 1402 newArcs[newIndex] = oldArcs[oldIndex]; 1403 } 1404 1405 arcs[0] = oldReverse ? ~newIndex : newIndex; 1406 } 1407 } 1408 1409 function pruneMultiArcs(arcs) { 1410 arcs.forEach(pruneArcs); 1411 } 1412 1413 for (var key in objects) { 1414 pruneGeometry(objects[key]); 1415 } 1416 1417 if (verbose) console.warn("prune: retained " + newArcCount + " / " + oldArcCount + " arcs (" + Math.round(newArcCount / oldArcCount * 100) + "%)"); 1418 1419 return topology; 1420}; 1421 1422function noop() {} 1423 1424},{}],22:[function(_dereq_,module,exports){ 1425module.exports = function(objects, bbox, Q) { 1426 var x0 = isFinite(bbox[0]) ? bbox[0] : 0, 1427 y0 = isFinite(bbox[1]) ? bbox[1] : 0, 1428 x1 = isFinite(bbox[2]) ? bbox[2] : 0, 1429 y1 = isFinite(bbox[3]) ? bbox[3] : 0, 1430 kx = x1 - x0 ? (Q - 1) / (x1 - x0) : 1, 1431 ky = y1 - y0 ? (Q - 1) / (y1 - y0) : 1; 1432 1433 function quantizeGeometry(geometry) { 1434 if (geometry && quantizeGeometryType.hasOwnProperty(geometry.type)) quantizeGeometryType[geometry.type](geometry); 1435 } 1436 1437 var quantizeGeometryType = { 1438 GeometryCollection: function(o) { o.geometries.forEach(quantizeGeometry); }, 1439 Point: function(o) { quantizePoint(o.coordinates); }, 1440 MultiPoint: function(o) { o.coordinates.forEach(quantizePoint); }, 1441 LineString: function(o) { 1442 var line = o.coordinates; 1443 quantizeLine(line); 1444 if (line.length < 2) line[1] = line[0]; // must have 2+ 1445 }, 1446 MultiLineString: function(o) { 1447 for (var lines = o.coordinates, i = 0, n = lines.length; i < n; ++i) { 1448 var line = lines[i]; 1449 quantizeLine(line); 1450 if (line.length < 2) line[1] = line[0]; // must have 2+ 1451 } 1452 }, 1453 Polygon: function(o) { 1454 for (var rings = o.coordinates, i = 0, n = rings.length; i < n; ++i) { 1455 var ring = rings[i]; 1456 quantizeLine(ring); 1457 while (ring.length < 4) ring.push(ring[0]); // must have 4+ 1458 } 1459 }, 1460 MultiPolygon: function(o) { 1461 for (var polygons = o.coordinates, i = 0, n = polygons.length; i < n; ++i) { 1462 for (var rings = polygons[i], j = 0, m = rings.length; j < m; ++j) { 1463 var ring = rings[j]; 1464 quantizeLine(ring); 1465 while (ring.length < 4) ring.push(ring[0]); // must have 4+ 1466 } 1467 } 1468 } 1469 }; 1470 1471 function quantizePoint(coordinates) { 1472 coordinates[0] = Math.round((coordinates[0] - x0) * kx); 1473 coordinates[1] = Math.round((coordinates[1] - y0) * ky); 1474 } 1475 1476 function quantizeLine(coordinates) { 1477 var i = 0, 1478 j = 1, 1479 n = coordinates.length, 1480 pi = coordinates[0], 1481 pj, 1482 px = pi[0] = Math.round((pi[0] - x0) * kx), 1483 py = pi[1] = Math.round((pi[1] - y0) * ky), 1484 x, 1485 y; 1486 1487 while (++i < n) { 1488 pi = coordinates[i]; 1489 x = Math.round((pi[0] - x0) * kx); 1490 y = Math.round((pi[1] - y0) * ky); 1491 if (x !== px || y !== py) { // skip coincident points 1492 pj = coordinates[j++]; 1493 pj[0] = px = x; 1494 pj[1] = py = y; 1495 } 1496 } 1497 1498 coordinates.length = j; 1499 } 1500 1501 for (var key in objects) { 1502 quantizeGeometry(objects[key]); 1503 } 1504 1505 return { 1506 scale: [1 / kx, 1 / ky], 1507 translate: [x0, y0] 1508 }; 1509}; 1510 1511},{}],23:[function(_dereq_,module,exports){ 1512var topojson = _dereq_("../../"), 1513 systems = _dereq_("./coordinate-systems"); 1514 1515module.exports = function(topology, options) { 1516 var minimumArea = 0, 1517 retainProportion, 1518 verbose = false, 1519 system = null, 1520 N = topology.arcs.reduce(function(p, v) { return p + v.length; }, 0), 1521 M = 0; 1522 1523 if (options) 1524 "minimum-area" in options && (minimumArea = +options["minimum-area"]), 1525 "coordinate-system" in options && (system = systems[options["coordinate-system"]]), 1526 "retain-proportion" in options && (retainProportion = +options["retain-proportion"]), 1527 "verbose" in options && (verbose = !!options["verbose"]); 1528 1529 topojson.presimplify(topology, system.triangleArea); 1530 1531 if (retainProportion) { 1532 var areas = [];
1533 topology.arcs.forEach(function(arc) { 1534 arc.forEach(function(point) { 1535 areas.push(point[2]); 1536 }); 1537 }); 1538 options["minimum-area"] = minimumArea = N ? areas.sort(function(a, b) { return b - a; })[Math.ceil((N - 1) * retainProportion)] : 0; 1539 if (verbose) console.warn("simplification: effective minimum area " + minimumArea.toPrecision(3)); 1540 } 1541 1542 topology.arcs.forEach(topology.transform ? function(arc) { 1543 var dx = 0, 1544 dy = 0, // accumulate removed points 1545 i = -1, 1546 j = -1, 1547 n = arc.length, 1548 source, 1549 target; 1550 1551 while (++i < n) { 1552 source = arc[i]; 1553 if (source[2] >= minimumArea) { 1554 target = arc[++j]; 1555 target[0] = source[0] + dx; 1556 target[1] = source[1] + dy; 1557 dx = dy = 0; 1558 } else { 1559 dx += source[0]; 1560 dy += source[1]; 1561 } 1562 } 1563 1564 arc.length = ++j; 1565 } : function(arc) { 1566 var i = -1, 1567 j = -1, 1568 n = arc.length, 1569 point; 1570 1571 while (++i < n) { 1572 point = arc[i]; 1573 if (point[2] >= minimumArea) { 1574 arc[++j] = point; 1575 } 1576 } 1577 1578 arc.length = ++j; 1579 }); 1580 1581 // Remove computed area (z) for each point. 1582 // This is done as a separate pass because some coordinates may be shared 1583 // between arcs (such as the last point and first point of a cut line). 1584 topology.arcs.forEach(function(arc) { 1585 var i = -1, n = arc.length; 1586 while (++i < n) arc[i].length = 2; 1587 M += arc.length; 1588 }); 1589 1590 if (verbose) console.warn("simplification: retained " + M + " / " + N + " points (" + Math.round((M / N) * 100) + "%)"); 1591 1592 return topology; 1593}; 1594 1595},{"../../":10,"./coordinate-systems":16}],24:[function(_dereq_,module,exports){ 1596var Ï = Math.PI, 1597 Ï_4 = Ï / 4, 1598 radians = Ï / 180; 1599 1600exports.name = "spherical"; 1601exports.formatDistance = formatDistance; 1602exports.ringArea = ringArea; 1603exports.absoluteArea = absoluteArea; 1604exports.triangleArea = triangleArea; 1605exports.distance = haversinDistance; // XXX why two implementations? 1606 1607function formatDistance(radians) { 1608 var km = radians * 6371; 1609 return (km > 1 ? km.toFixed(3) + "km" : (km * 1000).toPrecision(3) + "m") 1610 + " (" + (radians * 180 / Math.PI).toPrecision(3) + "°)"; 1611} 1612 1613function ringArea(ring) { 1614 if (!ring.length) return 0; 1615 var area = 0, 1616 p = ring[0], 1617 λ = p[0] * radians, 1618 Ï = p[1] * radians / 2 + Ï_4, 1619 λ0 = λ, 1620 cosÏ0 = Math.cos(Ï), 1621 sinÏ0 = Math.sin(Ï); 1622 1623 for (var i = 1, n = ring.length; i < n; ++i) { 1624 p = ring[i], λ = p[0] * radians, Ï = p[1] * radians / 2 + Ï_4; 1625 1626 // Spherical excess E for a spherical triangle with vertices: south pole, 1627 // previous point, current point. Uses a formula derived from Cagnoliâs 1628 // theorem. See Todhunter, Spherical Trig. (1871), Sec. 103, Eq. (2). 1629 var dλ = λ - λ0, 1630 cosÏ = Math.cos(Ï), 1631 sinÏ = Math.sin(Ï), 1632 k = sinÏ0 * sinÏ, 1633 u = cosÏ0 * cosÏ + k * Math.cos(dλ), 1634 v = k * Math.sin(dλ); 1635 area += Math.atan2(v, u); 1636 1637 // Advance the previous point. 1638 λ0 = λ, cosÏ0 = cosÏ, sinÏ0 = sinÏ; 1639 } 1640 1641 return 2 * (area > Ï ? area - 2 * Ï : area < -Ï ? area + 2 * Ï : area); 1642} 1643 1644function absoluteArea(a) { 1645 return a < 0 ? a + 4 * Ï : a; 1646} 1647 1648function triangleArea(t) { 1649 var a = distance(t[0], t[1]), 1650 b = distance(t[1], t[2]), 1651 c = distance(t[2], t[0]), 1652 s = (a + b + c) / 2; 1653 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)))); 1654} 1655 1656function distance(a, b) { 1657 var Îλ = (b[0] - a[0]) * radians, 1658 sinÎλ = Math.sin(Îλ), 1659 cosÎλ = Math.cos(Îλ), 1660 sinÏ0 = Math.sin(a[1] * radians), 1661 cosÏ0 = Math.cos(a[1] * radians), 1662 sinÏ1 = Math.sin(b[1] * radians), 1663 cosÏ1 = Math.cos(b[1] * radians), 1664 _; 1665 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Îλ); 1666} 1667 1668function haversinDistance(x0, y0, x1, y1) { 1669 x0 *= radians, y0 *= radians, x1 *= radians, y1 *= radians;
1670 return 2 * Math.asin(Math.sqrt(haversin(y1 - y0) + Math.cos(y0) * Math.cos(y1) * haversin(x1 - x0))); 1671} 1672 1673function haversin(x) { 1674 return (x = Math.sin(x / 2)) * x; 1675} 1676 1677},{}],25:[function(_dereq_,module,exports){ 1678var type = _dereq_("./type"); 1679 1680module.exports = function(objects, transform) { 1681 var ε = 1e-2, 1682 x0 = -180, x0e = x0 + ε, 1683 x1 = 180, x1e = x1 - ε, 1684 y0 = -90, y0e = y0 + ε, 1685 y1 = 90, y1e = y1 - ε, 1686 fragments = []; 1687 1688 if (transform) { 1689 var kx = transform.scale[0], 1690 ky = transform.scale[1], 1691 dx = transform.translate[0], 1692 dy = transform.translate[1]; 1693 1694 x0 = Math.round((x0 - dx) / kx); 1695 x1 = Math.round((x1 - dx) / kx); 1696 y0 = Math.round((y0 - dy) / ky); 1697 y1 = Math.round((y1 - dy) / ky); 1698 x0e = Math.round((x0e - dx) / kx); 1699 x1e = Math.round((x1e - dx) / kx); 1700 y0e = Math.round((y0e - dy) / ky); 1701 y1e = Math.round((y1e - dy) / ky); 1702 } 1703 1704 function normalizePoint(y) { 1705 return y <= y0e ? [0, y0] // south pole 1706 : y >= y1e ? [0, y1] // north pole 1707 : [x0, y]; // antimeridian 1708 } 1709 1710 var stitch = type({ 1711 polygon: function(polygon) { 1712 var rings = []; 1713 1714 // For each ring, detect where it crosses the antimeridian or pole. 1715 for (var j = 0, m = polygon.length; j < m; ++j) { 1716 var ring = polygon[j], 1717 fragments = []; 1718 1719 // By default, assume that this ring doesnât need any stitching. 1720 fragments.push(ring); 1721 1722 for (var i = 0, n = ring.length; i < n; ++i) { 1723 var point = ring[i], 1724 x = point[0], 1725 y = point[1]; 1726 1727 // If this is an antimeridian or polar point⦠1728 if (x <= x0e || x >= x1e || y <= y0e || y >= y1e) { 1729 1730 // Advance through any antimeridian or polar points⦠1731 for (var k = i + 1; k < n; ++k) { 1732 var pointk = ring[k], 1733 xk = pointk[0], 1734 yk = pointk[1]; 1735 if (xk > x0e && xk < x1e && yk > y0e && yk < y1e) break; 1736 } 1737 1738 // If this was just a single antimeridian or polar point, 1739 // we donât need to cut this ring into a fragment; 1740 // we can just leave it as-is. 1741 if (k === i + 1) continue; 1742 1743 // Otherwise, if this is not the first point in the ring, 1744 // cut the current fragment so that it ends at the current point. 1745 // The current point is also normalized for later joining. 1746 if (i) { 1747 var fragmentBefore = ring.slice(0, i + 1); 1748 fragmentBefore[fragmentBefore.length - 1] = normalizePoint(y); 1749 fragments[fragments.length - 1] = fragmentBefore; 1750 } 1751 1752 // If the ring started with an antimeridian fragment, 1753 // we can ignore that fragment entirely. 1754 else { 1755 fragments.pop(); 1756 } 1757 1758 // If the remainder of the ring is an antimeridian fragment, 1759 // move on to the next ring. 1760 if (k >= n) break; 1761 1762 // Otherwise, add the remaining ring fragment and continue. 1763 fragments.push(ring = ring.slice(k - 1)); 1764 ring[0] = normalizePoint(ring[0][1]); 1765 i = -1; 1766 n = ring.length; 1767 } 1768 } 1769 1770 // Now stitch the fragments back together into rings. 1771 // To connect the fragments start-to-end, create a simple index by end. 1772 var fragmentByStart = {}, 1773 fragmentByEnd = {}; 1774 1775 // For each fragment⦠1776 for (var i = 0, n = fragments.length; i < n; ++i) { 1777 var fragment = fragments[i], 1778 start = fragment[0], 1779 end = fragment[fragment.length - 1]; 1780 1781 // If this fragment is closed, add it as a standalone ring. 1782 if (start[0] === end[0] && start[1] === end[1]) { 1783 rings.push(fragment); 1784 fragments[i] = null; 1785 continue; 1786 } 1787 1788 fragment.index = i; 1789 fragmentByStart[start] = fragmentByEnd[end] = fragment; 1790 } 1791 1792 // For each open fragment⦠1793 for (var i = 0; i < n; ++i) { 1794 var fragment = fragments[i]; 1795 if (fragment) { 1796 1797 var start = fragment[0], 1798 end = fragment[fragment.length - 1], 1799 startFragment = fragmentByEnd[start], 1800 endFragment = fragmentByStart[end]; 1801 1802 delete fragmentByStart[start]; 1803 delete fragmentByEnd[end]; 1804 1805 // If this fragment is closed, add it as a standalone ring. 1806 if (start[0] === end[0] && start[1] === end[1]) { 1807 rings.push(fragment); 1808 continue; 1809 } 1810 1811 if (startFragment) { 1812 delete fragmentByEnd[start]; 1813 delete fragmentByStart[startFragment[0]]; 1814 startFragment.pop(); // drop the shared coordinate 1815 fragments[startFragment.index] = null; 1816 fragment = startFragment.concat(fragment); 1817 1818 if (startFragment === endFragment) { 1819 // Connect both ends to this single fragment to create a ring. 1820 rings.push(fragment); 1821 } else { 1822 fragment.index = n++; 1823 fragments.push(fragmentByStart[fragment[0]] = fragmentByEnd[fragment[fragment.length - 1]] = fragment); 1824 } 1825 } else if (endFragment) { 1826 delete fragmentByStart[end]; 1827 delete fragmentByEnd[endFragment[endFragment.length - 1]]; 1828 fragment.pop(); // drop the shared coordinate 1829 fragment = fragment.concat(endFragment); 1830 fragment.index = n++; 1831 fragments[endFragment.index] = null; 1832 fragments.push(fragmentByStart[fragment[0]] = fragmentByEnd[fragment[fragment.length - 1]] = fragment); 1833 } else { 1834 fragment.push(fragment[0]); // close ring 1835 rings.push(fragment); 1836 } 1837 } 1838 } 1839 } 1840 1841 // Copy the rings into the target polygon. 1842 for (var i = 0, n = polygon.length = rings.length; i < n; ++i) { 1843 polygon[i] = rings[i]; 1844 } 1845 } 1846 }); 1847 1848 for (var key in objects) { 1849 stitch.object(objects[key]); 1850 } 1851}; 1852 1853},{"./type":36}],26:[function(_dereq_,module,exports){ 1854var type = _dereq_("./type"), 1855 stitch = _dereq_("./stitch"), 1856 systems = _dereq_("./coordinate-systems"), 1857 topologize = _dereq_("./topology/index"), 1858 delta = _dereq_("./delta"), 1859 geomify = _dereq_("./geomify"), 1860 prefilter = _dereq_("./prefilter"), 1861 quantize = _dereq_("./quantize"), 1862 bounds = _dereq_("./bounds"), 1863 computeId = _dereq_("./compute-id"), 1864 transformProperties = _dereq_("./transform-properties"); 1865 1866var ε = 1e-6; 1867 1868module.exports = function(objects, options) { 1869 var Q = 1e4, // precision of quantization 1870 id = function(d) { return d.id; }, // function to compute object id 1871 propertyTransform = function() {}, // function to transform properties 1872 transform, 1873 minimumArea = 0, 1874 stitchPoles = true, 1875 verbose = false, 1876 system = null; 1877 1878 if (options) 1879 "verbose" in options && (verbose = !!options["verbose"]), 1880 "stitch-poles" in options && (stitchPoles = !!options["stitch-poles"]), 1881 "coordinate-system" in options && (system = systems[options["coordinate-system"]]), 1882 "minimum-area" in options && (minimumArea = +options["minimum-area"]), 1883 "quantization" in options && (Q = +options["quantization"]),
1884 "id" in options && (id = options["id"]), 1885 "property-transform" in options && (propertyTransform = options["property-transform"]); 1886 1887 // Compute the new feature id and transform properties. 1888 computeId(objects, id); 1889 transformProperties(objects, propertyTransform); 1890 1891 // Convert to geometry objects. 1892 geomify(objects); 1893 1894 // Compute initial bounding box. 1895 var bbox = bounds(objects); 1896 1897 // For automatic coordinate system determination, consider the bounding box. 1898 var oversize = bbox[0] < -180 - ε 1899 || bbox[1] < -90 - ε 1900 || bbox[2] > 180 + ε 1901 || bbox[3] > 90 + ε; 1902 if (!system) { 1903 system = systems[oversize ? "cartesian" : "spherical"]; 1904 if (options) options["coordinate-system"] = system.name; 1905 } 1906 1907 if (system === systems.spherical) { 1908 if (oversize) throw new Error("spherical coordinates outside of [±180°, ±90°]"); 1909 1910 // When near the spherical coordinate limits, clamp to nice round values. 1911 // This avoids quantized coordinates that are slightly outside the limits. 1912 if (bbox[0] < -180 + ε) bbox[0] = -180; 1913 if (bbox[1] < -90 + ε) bbox[1] = -90; 1914 if (bbox[2] > 180 - ε) bbox[2] = 180; 1915 if (bbox[3] > 90 - ε) bbox[3] = 90; 1916 } 1917 1918 if (verbose) { 1919 console.warn("bounds: " + bbox.join(" ") + " (" + system.name + ")"); 1920 } 1921 1922 // Filter rings smaller than the minimum area. 1923 // This can produce a simpler topology. 1924 if (minimumArea) prefilter(objects, function(ring) { 1925 return system.absoluteArea(system.ringArea(ring)) >= minimumArea; 1926 }); 1927 1928 // Compute the quantization transform. 1929 if (Q) { 1930 transform = quantize(objects, bbox, Q); 1931 if (verbose) { 1932 console.warn("quantization: " + transform.scale.map(function(degrees) { return system.formatDistance(degrees / 180 * Math.PI); }).join(" ")); 1933 } 1934 } 1935 1936 // Remove any antimeridian cuts and restitch. 1937 if (system === systems.spherical && stitchPoles) { 1938 stitch(objects, transform); 1939 } 1940 1941 // Compute the topology. 1942 var topology = topologize(objects); 1943 topology.bbox = bbox; 1944 1945 if (verbose) { 1946 console.warn("topology: " + topology.arcs.length + " arcs, " + topology.arcs.reduce(function(p, v) { return p + v.length; }, 0) + " points"); 1947 } 1948 1949 // Convert to delta-encoding. 1950 if (Q) topology.transform = transform, delta(topology); 1951 1952 return topology; 1953}; 1954 1955},{"./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){ 1956var join = _dereq_("./join"); 1957 1958// Given an extracted (pre-)topology, cuts (or rotates) arcs so that all shared 1959// point sequences are identified. The topology can then be subsequently deduped 1960// to remove exact duplicate arcs. 1961module.exports = function(topology) { 1962 var junctionByPoint = join(topology), 1963 coordinates = topology.coordinates, 1964 lines = topology.lines, 1965 rings = topology.rings; 1966 1967 for (var i = 0, n = lines.length; i < n; ++i) { 1968 var line = lines[i], 1969 lineMid = line[0], 1970 lineEnd = line[1]; 1971 while (++lineMid < lineEnd) { 1972 if (junctionByPoint.get(coordinates[lineMid])) { 1973 var next = {0: lineMid, 1: line[1]}; 1974 line[1] = lineMid; 1975 line = line.next = next; 1976 } 1977 } 1978 } 1979 1980 for (var i = 0, n = rings.length; i < n; ++i) { 1981 var ring = rings[i], 1982 ringStart = ring[0], 1983 ringMid = ringStart, 1984 ringEnd = ring[1], 1985 ringFixed = junctionByPoint.get(coordinates[ringStart]); 1986 while (++ringMid < ringEnd) { 1987 if (junctionByPoint.get(coordinates[ringMid])) { 1988 if (ringFixed) { 1989 var next = {0: ringMid, 1: ring[1]}; 1990 ring[1] = ringMid; 1991 ring = ring.next = next; 1992 } else { // For the first junction, we can rotate rather than cut. 1993 rotateArray(coordinates, ringStart, ringEnd, ringEnd - ringMid); 1994 coordinates[ringEnd] = coordinates[ringStart]; 1995 ringFixed = true; 1996 ringMid = ringStart; // restart; we may have skipped junctions 1997 } 1998 } 1999 } 2000 } 2001 2002 return topology; 2003}; 2004 2005function rotateArray(array, start, end, offset) { 2006 reverse(array, start, end); 2007 reverse(array, start, start + offset); 2008 reverse(array, start + offset, end); 2009} 2010 2011function reverse(array, start, end) { 2012 for (var mid = start + ((end-- - start) >> 1), t; start < mid; ++start, --end) { 2013 t = array[start], array[start] = array[end], array[end] = t; 2014 } 2015} 2016 2017},{"./join":32}],28:[function(_dereq_,module,exports){ 2018var join = _dereq_("./join"), 2019 hashtable = _dereq_("./hashtable"), 2020 hashPoint = _dereq_("./point-hash"), 2021 equalPoint = _dereq_("./point-equal"); 2022 2023// Given a cut topology, combines duplicate arcs. 2024module.exports = function(topology) { 2025 var coordinates = topology.coordinates, 2026 lines = topology.lines, 2027 rings = topology.rings, 2028 arcCount = lines.length + rings.length; 2029 2030 delete topology.lines; 2031 delete topology.rings; 2032 2033 // Count the number of (non-unique) arcs to initialize the hashtable safely. 2034 for (var i = 0, n = lines.length; i < n; ++i) { 2035 var line = lines[i]; while (line = line.next) ++arcCount; 2036 } 2037 for (var i = 0, n = rings.length; i < n; ++i) { 2038 var ring = rings[i]; while (ring = ring.next) ++arcCount; 2039 } 2040 2041 var arcsByEnd = hashtable(arcCount * 2, hashPoint, equalPoint), 2042 arcs = topology.arcs = []; 2043 2044 for (var i = 0, n = lines.length; i < n; ++i) { 2045 var line = lines[i]; 2046 do { 2047 dedupLine(line); 2048 } while (line = line.next); 2049 } 2050 2051 for (var i = 0, n = rings.length; i < n; ++i) { 2052 var ring = rings[i]; 2053 if (ring.next) { // arc is no longer closed 2054 do { 2055 dedupLine(ring); 2056 } while (ring = ring.next); 2057 } else { 2058 dedupRing(ring); 2059 } 2060 } 2061 2062 function dedupLine(arc) { 2063 var startPoint, 2064 endPoint, 2065 startArcs, 2066 endArcs; 2067 2068 // Does this arc match an existing arc in order? 2069 if (startArcs = arcsByEnd.get(startPoint = coordinates[arc[0]])) { 2070 for (var i = 0, n = startArcs.length; i < n; ++i) { 2071 var startArc = startArcs[i]; 2072 if (equalLine(startArc, arc)) { 2073 arc[0] = startArc[0]; 2074 arc[1] = startArc[1]; 2075 return; 2076 } 2077 } 2078 } 2079 2080 // Does this arc match an existing arc in reverse order? 2081 if (endArcs = arcsByEnd.get(endPoint = coordinates[arc[1]])) { 2082 for (var i = 0, n = endArcs.length; i < n; ++i) { 2083 var endArc = endArcs[i]; 2084 if (reverseEqualLine(endArc, arc)) { 2085 arc[1] = endArc[0]; 2086 arc[0] = endArc[1]; 2087 return; 2088 } 2089 } 2090 } 2091 2092 if (startArcs) startArcs.push(arc); else arcsByEnd.set(startPoint, [arc]); 2093 if (endArcs) endArcs.push(arc); else arcsByEnd.set(endPoint, [arc]); 2094 arcs.push(arc); 2095 } 2096 2097 function dedupRing(arc) { 2098 var endPoint, 2099 endArcs; 2100 2101 // Does this arc match an existing line in order, or reverse order? 2102 // Rings are closed, so their start point and end point is the same. 2103 if (endArcs = arcsByEnd.get(endPoint = coordinates[arc[0]])) { 2104 for (var i = 0, n = endArcs.length; i < n; ++i) { 2105 var endArc = endArcs[i]; 2106 if (equalRing(endArc, arc)) { 2107 arc[0] = endArc[0]; 2108 arc[1] = endArc[1]; 2109 return; 2110 } 2111 if (reverseEqualRing(endArc, arc)) { 2112 arc[0] = endArc[1]; 2113 arc[1] = endArc[0]; 2114 return; 2115 } 2116 } 2117 } 2118 2119 // Otherwise, does this arc match an existing ring in order, or reverse order? 2120 if (endArcs = arcsByEnd.get(endPoint = coordinates[arc[0] + findMinimumOffset(arc)])) { 2121 for (var i = 0, n = endArcs.length; i < n; ++i) { 2122 var endArc = endArcs[i]; 2123 if (equalRing(endArc, arc)) { 2124 arc[0] = endArc[0]; 2125 arc[1] = endArc[1]; 2126 return; 2127 } 2128 if (reverseEqualRing(endArc, arc)) { 2129 arc[0] = endArc[1]; 2130 arc[1] = endArc[0]; 2131 return; 2132 } 2133 } 2134 } 2135 2136 if (endArcs) endArcs.push(arc); else arcsByEnd.set(endPoint, [arc]); 2137 arcs.push(arc); 2138 } 2139 2140 function equalLine(arcA, arcB) { 2141 var ia = arcA[0], ib = arcB[0], 2142 ja = arcA[1], jb = arcB[1]; 2143 if (ia - ja !== ib - jb) return false;
2144 for (; ia <= ja; ++ia, ++ib) if (!equalPoint(coordinates[ia], coordinates[ib])) return false; 2145 return true; 2146 } 2147 2148 function reverseEqualLine(arcA, arcB) { 2149 var ia = arcA[0], ib = arcB[0], 2150 ja = arcA[1], jb = arcB[1]; 2151 if (ia - ja !== ib - jb) return false; 2152 for (; ia <= ja; ++ia, --jb) if (!equalPoint(coordinates[ia], coordinates[jb])) return false; 2153 return true; 2154 } 2155 2156 function equalRing(arcA, arcB) { 2157 var ia = arcA[0], ib = arcB[0], 2158 ja = arcA[1], jb = arcB[1], 2159 n = ja - ia; 2160 if (n !== jb - ib) return false; 2161 var ka = findMinimumOffset(arcA), 2162 kb = findMinimumOffset(arcB); 2163 for (var i = 0; i < n; ++i) { 2164 if (!equalPoint(coordinates[ia + (i + ka) % n], coordinates[ib + (i + kb) % n])) return false; 2165 } 2166 return true; 2167 } 2168 2169 function reverseEqualRing(arcA, arcB) { 2170 var ia = arcA[0], ib = arcB[0], 2171 ja = arcA[1], jb = arcB[1], 2172 n = ja - ia; 2173 if (n !== jb - ib) return false; 2174 var ka = findMinimumOffset(arcA), 2175 kb = n - findMinimumOffset(arcB); 2176 for (var i = 0; i < n; ++i) { 2177 if (!equalPoint(coordinates[ia + (i + ka) % n], coordinates[jb - (i + kb) % n])) return false; 2178 } 2179 return true; 2180 } 2181 2182 // Rings are rotated to a consistent, but arbitrary, start point. 2183 // This is necessary to detect when a ring and a rotated copy are dupes. 2184 function findMinimumOffset(arc) { 2185 var start = arc[0], 2186 end = arc[1], 2187 mid = start, 2188 minimum = mid, 2189 minimumPoint = coordinates[mid]; 2190 while (++mid < end) { 2191 var point = coordinates[mid]; 2192 if (point[0] < minimumPoint[0] || point[0] === minimumPoint[0] && point[1] < minimumPoint[1]) { 2193 minimum = mid; 2194 minimumPoint = point; 2195 } 2196 } 2197 return minimum - start; 2198 } 2199 2200 return topology; 2201}; 2202 2203},{"./hashtable":30,"./join":32,"./point-equal":33,"./point-hash":34}],29:[function(_dereq_,module,exports){ 2204// Extracts the lines and rings from the specified hash of geometry objects. 2205// 2206// Returns an object with three properties: 2207// 2208// * coordinates - shared buffer of [x, y] coordinates 2209// * lines - lines extracted from the hash, of the form [start, end] 2210// * rings - rings extracted from the hash, of the form [start, end] 2211// 2212// For each ring or line, start and end represent inclusive indexes into the 2213// coordinates buffer. For rings (and closed lines), coordinates[start] equals 2214// coordinates[end]. 2215// 2216// For each line or polygon geometry in the input hash, including nested 2217// geometries as in geometry collections, the `coordinates` array is replaced 2218// with an equivalent `arcs` array that, for each line (for line string 2219// geometries) or ring (for polygon geometries), points to one of the above 2220// lines or rings. 2221module.exports = function(objects) { 2222 var index = -1, 2223 lines = [], 2224 rings = [], 2225 coordinates = []; 2226 2227 function extractGeometry(geometry) { 2228 if (geometry && extractGeometryType.hasOwnProperty(geometry.type)) extractGeometryType[geometry.type](geometry); 2229 } 2230 2231 var extractGeometryType = { 2232 GeometryCollection: function(o) { o.geometries.forEach(extractGeometry); }, 2233 LineString: function(o) { o.arcs = extractLine(o.coordinates); delete o.coordinates; }, 2234 MultiLineString: function(o) { o.arcs = o.coordinates.map(extractLine); delete o.coordinates; }, 2235 Polygon: function(o) { o.arcs = o.coordinates.map(extractRing); delete o.coordinates; }, 2236 MultiPolygon: function(o) { o.arcs = o.coordinates.map(extractMultiRing); delete o.coordinates; } 2237 }; 2238 2239 function extractLine(line) { 2240 for (var i = 0, n = line.length; i < n; ++i) coordinates[++index] = line[i]; 2241 var arc = {0: index - n + 1, 1: index}; 2242 lines.push(arc); 2243 return arc; 2244 } 2245 2246 function extractRing(ring) { 2247 for (var i = 0, n = ring.length; i < n; ++i) coordinates[++index] = ring[i]; 2248 var arc = {0: index - n + 1, 1: index}; 2249 rings.push(arc); 2250 return arc; 2251 } 2252 2253 function extractMultiRing(rings) { 2254 return rings.map(extractRing); 2255 } 2256 2257 for (var key in objects) { 2258 extractGeometry(objects[key]); 2259 } 2260 2261 return { 2262 type: "Topology", 2263 coordinates: coordinates, 2264 lines: lines, 2265 rings: rings, 2266 objects: objects 2267 }; 2268}; 2269 2270},{}],30:[function(_dereq_,module,exports){ 2271module.exports = function(size, hash, equal) { 2272 var hashtable = new Array(size = 1 << Math.ceil(Math.log(size) / Math.LN2)), 2273 mask = size - 1, 2274 free = size; 2275 2276 function set(key, value) { 2277 var index = hash(key) & mask, 2278 match = hashtable[index], 2279 cycle = !index; 2280 while (match != null) {
2281 if (equal(match.key, key)) return match.value = value; 2282 match = hashtable[index = (index + 1) & mask]; 2283 if (!index && cycle++) throw new Error("full hashtable"); 2284 } 2285 hashtable[index] = {key: key, value: value}; 2286 --free; 2287 return value; 2288 } 2289 2290 function get(key, missingValue) { 2291 var index = hash(key) & mask, 2292 match = hashtable[index], 2293 cycle = !index; 2294 while (match != null) { 2295 if (equal(match.key, key)) return match.value; 2296 match = hashtable[index = (index + 1) & mask]; 2297 if (!index && cycle++) break; 2298 } 2299 return missingValue; 2300 } 2301 2302 function remove(key) { 2303 var index = hash(key) & mask, 2304 match = hashtable[index], 2305 cycle = !index; 2306 while (match != null) { 2307 if (equal(match.key, key)) { 2308 hashtable[index] = null; 2309 match = hashtable[index = (index + 1) & mask]; 2310 if (match != null) { // delete and re-add 2311 ++free; 2312 hashtable[index] = null; 2313 set(match.key, match.value); 2314 } 2315 ++free; 2316 return true; 2317 } 2318 match = hashtable[index = (index + 1) & mask]; 2319 if (!index && cycle++) break; 2320 } 2321 return false; 2322 } 2323 2324 function keys() { 2325 var keys = []; 2326 for (var i = 0, n = hashtable.length; i < n; ++i) { 2327 var match = hashtable[i]; 2328 if (match != null) keys.push(match.key); 2329 } 2330 return keys; 2331 } 2332 2333 return { 2334 set: set, 2335 get: get, 2336 remove: remove, 2337 keys: keys 2338 }; 2339}; 2340 2341},{}],31:[function(_dereq_,module,exports){ 2342var hashtable = _dereq_("./hashtable"), 2343 extract = _dereq_("./extract"), 2344 cut = _dereq_("./cut"), 2345 dedup = _dereq_("./dedup"); 2346 2347// Constructs the TopoJSON Topology for the specified hash of geometries. 2348// Each object in the specified hash must be a GeoJSON object, 2349// meaning FeatureCollection, a Feature or a geometry object. 2350module.exports = function(objects) { 2351 var topology = dedup(cut(extract(objects))), 2352 coordinates = topology.coordinates, 2353 indexByArc = hashtable(topology.arcs.length, hashArc, equalArc); 2354 2355 objects = topology.objects; // for garbage collection 2356 2357 topology.arcs = topology.arcs.map(function(arc, i) { 2358 indexByArc.set(arc, i); 2359 return coordinates.slice(arc[0], arc[1] + 1); 2360 }); 2361 2362 delete topology.coordinates; 2363 coordinates = null; 2364 2365 function indexGeometry(geometry) { 2366 if (geometry && indexGeometryType.hasOwnProperty(geometry.type)) indexGeometryType[geometry.type](geometry); 2367 } 2368 2369 var indexGeometryType = { 2370 GeometryCollection: function(o) { o.geometries.forEach(indexGeometry); }, 2371 LineString: function(o) { o.arcs = indexArcs(o.arcs); }, 2372 MultiLineString: function(o) { o.arcs = o.arcs.map(indexArcs); }, 2373 Polygon: function(o) { o.arcs = o.arcs.map(indexArcs); }, 2374 MultiPolygon: function(o) { o.arcs = o.arcs.map(indexMultiArcs); } 2375 }; 2376 2377 function indexArcs(arc) { 2378 var indexes = []; 2379 do { 2380 var index = indexByArc.get(arc); 2381 indexes.push(arc[0] < arc[1] ? index : ~index); 2382 } while (arc = arc.next); 2383 return indexes; 2384 } 2385 2386 function indexMultiArcs(arcs) { 2387 return arcs.map(indexArcs); 2388 } 2389 2390 for (var key in objects) { 2391 indexGeometry(objects[key]); 2392 } 2393 2394 return topology; 2395}; 2396 2397function hashArc(arc) { 2398 var i = arc[0], j = arc[1], t; 2399 if (j < i) t = i, i = j, j = t; 2400 return i + 31 * j; 2401} 2402 2403function equalArc(arcA, arcB) { 2404 var ia = arcA[0], ja = arcA[1], 2405 ib = arcB[0], jb = arcB[1], t; 2406 if (ja < ia) t = ia, ia = ja, ja = t; 2407 if (jb < ib) t = ib, ib = jb, jb = t; 2408 return ia === ib && ja === jb; 2409} 2410 2411},{"./cut":27,"./dedup":28,"./extract":29,"./hashtable":30}],32:[function(_dereq_,module,exports){ 2412var hashtable = _dereq_("./hashtable"), 2413 hashPoint = _dereq_("./point-hash"), 2414 equalPoint = _dereq_("./point-equal"); 2415 2416// Given an extracted (pre-)topology, identifies all of the junctions. These are 2417// the points at which arcs (lines or rings) will need to be cut so that each 2418// arc is represented uniquely. 2419// 2420// A junction is a point where at least one arc deviates from another arc going 2421// through the same point. For example, consider the point B. If there is a arc 2422// through ABC and another arc through CBA, then B is not a junction because in 2423// both cases the adjacent point pairs are {A,C}. However, if there is an 2424// additional arc ABD, then {A,D} != {A,C}, and thus B becomes a junction. 2425// 2426// For a closed ring ABCA, the first point Aâs adjacent points are the second 2427// and last point {B,C}. For a line, the first and last point are always 2428// considered junctions, even if the line is closed; this ensures that a closed 2429// line is never rotated. 2430module.exports = function(topology) { 2431 var coordinates = topology.coordinates, 2432 lines = topology.lines, 2433 rings = topology.rings, 2434 visitedByPoint, 2435 neighborsByPoint = hashtable(coordinates.length, hashPoint, equalPoint), 2436 junctionByPoint = hashtable(coordinates.length, hashPoint, equalPoint); 2437 2438 for (var i = 0, n = lines.length; i < n; ++i) { 2439 var line = lines[i], 2440 lineStart = line[0], 2441 lineEnd = line[1], 2442 previousPoint = null, 2443 currentPoint = coordinates[lineStart], 2444 nextPoint = coordinates[++lineStart]; 2445 visitedByPoint = hashtable(lineEnd - lineStart, hashPoint, equalPoint); 2446 junctionByPoint.set(currentPoint, true); // start 2447 while (++lineStart <= lineEnd) { 2448 sequence(previousPoint = currentPoint, currentPoint = nextPoint, nextPoint = coordinates[lineStart]); 2449 } 2450 junctionByPoint.set(nextPoint, true); // end 2451 } 2452 2453 for (var i = 0, n = rings.length; i < n; ++i) { 2454 var ring = rings[i], 2455 ringStart = ring[0] + 1, 2456 ringEnd = ring[1], 2457 previousPoint = coordinates[ringEnd - 1], 2458 currentPoint = coordinates[ringStart - 1], 2459 nextPoint = coordinates[ringStart]; 2460 visitedByPoint = hashtable(ringEnd - ringStart + 1, hashPoint, equalPoint); 2461 sequence(previousPoint, currentPoint, nextPoint); 2462 while (++ringStart <= ringEnd) { 2463 sequence(previousPoint = currentPoint, currentPoint = nextPoint, nextPoint = coordinates[ringStart]); 2464 } 2465 } 2466 2467 function sequence(previousPoint, currentPoint, nextPoint) { 2468 if (visitedByPoint.get(currentPoint)) return;
2468 // ignore self-intersection 2469 visitedByPoint.set(currentPoint, true); 2470 var neighbors = neighborsByPoint.get(currentPoint); 2471 if (neighbors) { 2472 if (!(equalPoint(neighbors[0], previousPoint) 2473 && equalPoint(neighbors[1], nextPoint)) 2474 && !(equalPoint(neighbors[0], nextPoint) 2475 && equalPoint(neighbors[1], previousPoint))) { 2476 junctionByPoint.set(currentPoint, true); 2477 } 2478 } else { 2479 neighborsByPoint.set(currentPoint, [previousPoint, nextPoint]); 2480 } 2481 } 2482 2483 return junctionByPoint; 2484}; 2485 2486},{"./hashtable":30,"./point-equal":33,"./point-hash":34}],33:[function(_dereq_,module,exports){ 2487module.exports = function(pointA, pointB) { 2488 return pointA[0] === pointB[0] && pointA[1] === pointB[1]; 2489}; 2490 2491},{}],34:[function(_dereq_,module,exports){ 2492// TODO if quantized, use simpler Int32 hashing? 2493 2494var hashBuffer = new ArrayBuffer(8), 2495 hashFloats = new Float64Array(hashBuffer), 2496 hashInts = new Int32Array(hashBuffer); 2497 2498function hashFloat(x) { 2499 hashFloats[0] = x; 2500 x = hashInts[1] ^ hashInts[0]; 2501 x ^= (x >>> 20) ^ (x >>> 12); 2502 x ^= (x >>> 7) ^ (x >>> 4); 2503 return x; 2504} 2505 2506module.exports = function(point) { 2507 var h = (hashFloat(point[0]) + 31 * hashFloat(point[1])) | 0; 2508 return h < 0 ? ~h : h; 2509}; 2510 2511},{}],35:[function(_dereq_,module,exports){ 2512// Given a hash of GeoJSON objects, transforms any properties on features using 2513// the specified transform function. The function is invoked for each existing 2514// property on the current feature, being passed the new properties hash, the 2515// property name, and the property value. The function is then expected to 2516// assign a new value to the given property hash if the feature is to be 2517// retained and return true. Or, to skip the property, do nothing and return 2518// false. If no properties are propagated to the new properties hash, the 2519// properties hash will be deleted from the current feature. 2520module.exports = function(objects, propertyTransform) { 2521 if (arguments.length < 2) propertyTransform = function() {}; 2522 2523 function transformObject(object) { 2524 if (object && transformObjectType.hasOwnProperty(object.type)) transformObjectType[object.type](object); 2525 } 2526 2527 function transformFeature(feature) { 2528 if (feature.properties) { 2529 var properties0 = feature.properties, 2530 properties1 = {}, 2531 empty = true; 2532 2533 for (var key0 in properties0) { 2534 if (propertyTransform(properties1, key0, properties0[key0])) { 2535 empty = false; 2536 } 2537 } 2538 2539 if (empty) delete feature.properties; 2540 else feature.properties = properties1; 2541 } 2542 } 2543 2544 var transformObjectType = { 2545 Feature: transformFeature, 2546 FeatureCollection: function(collection) { collection.features.forEach(transformFeature); } 2547 }; 2548 2549 for (var key in objects) { 2550 transformObject(objects[key]); 2551 } 2552 2553 return objects; 2554}; 2555 2556},{}],36:[function(_dereq_,module,exports){ 2557module.exports = function(types) { 2558 for (var type in typeDefaults) { 2559 if (!(type in types)) { 2560 types[type] = typeDefaults[type]; 2561 } 2562 } 2563 types.defaults = typeDefaults; 2564 return types; 2565}; 2566 2567var typeDefaults = { 2568 2569 Feature: function(feature) { 2570 if (feature.geometry) this.geometry(feature.geometry); 2571 }, 2572 2573 FeatureCollection: function(collection) { 2574 var features = collection.features, i = -1, n = features.length; 2575 while (++i < n) this.Feature(features[i]); 2576 }, 2577 2578 GeometryCollection: function(collection) { 2579 var geometries = collection.geometries, i = -1, n = geometries.length; 2580 while (++i < n) this.geometry(geometries[i]); 2581 }, 2582 2583 LineString: function(lineString) { 2584 this.line(lineString.coordinates); 2585 }, 2586 2587 MultiLineString: function(multiLineString) { 2588 var coordinates = multiLineString.coordinates, i = -1, n = coordinates.length; 2589 while (++i < n) this.line(coordinates[i]); 2590 }, 2591 2592 MultiPoint: function(multiPoint) { 2593 var coordinates = multiPoint.coordinates, i = -1, n = coordinates.length; 2594 while (++i < n) this.point(coordinates[i]); 2595 }, 2596 2597 MultiPolygon: function(multiPolygon) { 2598 var coordinates = multiPolygon.coordinates, i = -1, n = coordinates.length; 2599 while (++i < n) this.polygon(coordinates[i]); 2600 }, 2601 2602 Point: function(point) { 2603 this.point(point.coordinates); 2604 }, 2605 2606 Polygon: function(polygon) { 2607 this.polygon(polygon.coordinates); 2608 }, 2609 2610 object: function(object) { 2611 return object == null ? null 2612 : typeObjects.hasOwnProperty(object.type) ? this[object.type](object) 2613 : this.geometry(object); 2614 }, 2615 2616 geometry: function(geometry) { 2617 return geometry == null ? null 2618 : typeGeometries.hasOwnProperty(geometry.type) ? this[geometry.type](geometry) 2619 : null; 2620 }, 2621 2622 point: function() {}, 2623 2624 line: function(coordinates) {
2625 var i = -1, n = coordinates.length; 2626 while (++i < n) this.point(coordinates[i]); 2627 }, 2628 2629 polygon: function(coordinates) { 2630 var i = -1, n = coordinates.length; 2631 while (++i < n) this.line(coordinates[i]); 2632 } 2633}; 2634 2635var typeGeometries = { 2636 LineString: 1, 2637 MultiLineString: 1, 2638 MultiPoint: 1, 2639 MultiPolygon: 1, 2640 Point: 1, 2641 Polygon: 1, 2642 GeometryCollection: 1 2643}; 2644 2645var typeObjects = { 2646 Feature: 1, 2647 FeatureCollection: 1 2648}; 2649 2650},{}],37:[function(_dereq_,module,exports){ 2651!function() { 2652 var topojson = { 2653 version: "1.4.6", 2654 mesh: mesh, 2655 feature: featureOrCollection, 2656 neighbors: neighbors, 2657 presimplify: presimplify 2658 }; 2659 2660 function merge(topology, arcs) { 2661 var fragmentByStart = {}, 2662 fragmentByEnd = {}; 2663 2664 arcs.forEach(function(i) { 2665 var e = ends(i), 2666 start = e[0], 2667 end = e[1], 2668 f, g; 2669 2670 if (f = fragmentByEnd[start]) { 2671 delete fragmentByEnd[f.end]; 2672 f.push(i); 2673 f.end = end; 2674 if (g = fragmentByStart[end]) { 2675 delete fragmentByStart[g.start]; 2676 var fg = g === f ? f : f.concat(g); 2677 fragmentByStart[fg.start = f.start] = fragmentByEnd[fg.end = g.end] = fg; 2678 } else if (g = fragmentByEnd[end]) { 2679 delete fragmentByStart[g.start]; 2680 delete fragmentByEnd[g.end]; 2681 var fg = f.concat(g.map(function(i) { return ~i; }).reverse()); 2682 fragmentByStart[fg.start = f.start] = fragmentByEnd[fg.end = g.start] = fg; 2683 } else { 2684 fragmentByStart[f.start] = fragmentByEnd[f.end] = f; 2685 } 2686 } else if (f = fragmentByStart[end]) { 2687 delete fragmentByStart[f.start]; 2688 f.unshift(i); 2689 f.start = start; 2690 if (g = fragmentByEnd[start]) { 2691 delete fragmentByEnd[g.end]; 2692 var gf = g === f ? f : g.concat(f); 2693 fragmentByStart[gf.start = g.start] = fragmentByEnd[gf.end = f.end] = gf; 2694 } else if (g = fragmentByStart[start]) { 2695 delete fragmentByStart[g.start]; 2696 delete fragmentByEnd[g.end]; 2697 var gf = g.map(function(i) { return ~i; }).reverse().concat(f); 2698 fragmentByStart[gf.start = g.end] = fragmentByEnd[gf.end = f.end] = gf; 2699 } else { 2700 fragmentByStart[f.start] = fragmentByEnd[f.end] = f; 2701 } 2702 } else if (f = fragmentByStart[start]) { 2703 delete fragmentByStart[f.start]; 2704 f.unshift(~i); 2705 f.start = end; 2706 if (g = fragmentByEnd[end]) { 2707 delete fragmentByEnd[g.end]; 2708 var gf = g === f ? f : g.concat(f); 2709 fragmentByStart[gf.start = g.start] = fragmentByEnd[gf.end = f.end] = gf; 2710 } else if (g = fragmentByStart[end]) { 2711 delete fragmentByStart[g.start]; 2712 delete fragmentByEnd[g.end]; 2713 var gf = g.map(function(i) { return ~i; }).reverse().concat(f); 2714 fragmentByStart[gf.start = g.end] = fragmentByEnd[gf.end = f.end] = gf; 2715 } else { 2716 fragmentByStart[f.start] = fragmentByEnd[f.end] = f; 2717 } 2718 } else if (f = fragmentByEnd[end]) { 2719 delete fragmentByEnd[f.end]; 2720 f.push(~i); 2721 f.end = start; 2722 if (g = fragmentByEnd[start]) { 2723 delete fragmentByStart[g.start]; 2724 var fg = g === f ? f : f.concat(g); 2725 fragmentByStart[fg.start = f.start] = fragmentByEnd[fg.end = g.end] = fg; 2726 } else if (g = fragmentByStart[start]) { 2727 delete fragmentByStart[g.start]; 2728 delete fragmentByEnd[g.end]; 2729 var fg = f.concat(g.map(function(i) { return ~i; }).reverse()); 2730 fragmentByStart[fg.start = f.start] = fragmentByEnd[fg.end = g.start] = fg; 2731 } else { 2732 fragmentByStart[f.start] = fragmentByEnd[f.end] = f; 2733 } 2734 } else { 2735 f = [i]; 2736 fragmentByStart[f.start = start] = fragmentByEnd[f.end = end] = f; 2737 } 2738 }); 2739 2740 function ends(i) { 2741 var arc = topology.arcs[i], p0 = arc[0], p1 = [0, 0]; 2742 arc.forEach(function(dp) { p1[0] += dp[0], p1[1] += dp[1]; }); 2743 return [p0, p1]; 2744 } 2745 2746 var fragments = []; 2747 for (var k in fragmentByEnd) fragments.push(fragmentByEnd[k]); 2748 return fragments; 2749 } 2750 2751 function mesh(topology, o, filter) { 2752 var arcs = []; 2753 2754 if (arguments.length > 1) { 2755 var geomsByArc = [], 2756 geom; 2757 2758 function arc(i) { 2759 if (i < 0) i = ~i; 2760 (geomsByArc[i] || (geomsByArc[i] = [])).push(geom); 2761 } 2762 2763 function line(arcs) { 2764 arcs.forEach(arc); 2765 } 2766 2767 function polygon(arcs) { 2768 arcs.forEach(line); 2769 } 2770 2771 function geometry(o) { 2772 if (o.type === "GeometryCollection") o.geometries.forEac
2772h(geometry); 2773 else if (o.type in geometryType) { 2774 geom = o; 2775 geometryType[o.type](o.arcs); 2776 } 2777 } 2778 2779 var geometryType = { 2780 LineString: line, 2781 MultiLineString: polygon, 2782 Polygon: polygon, 2783 MultiPolygon: function(arcs) { arcs.forEach(polygon); } 2784 }; 2785 2786 geometry(o); 2787 2788 geomsByArc.forEach(arguments.length < 3 2789 ? function(geoms, i) { arcs.push(i); } 2790 : function(geoms, i) { if (filter(geoms[0], geoms[geoms.length - 1])) arcs.push(i); }); 2791 } else { 2792 for (var i = 0, n = topology.arcs.length; i < n; ++i) arcs.push(i); 2793 } 2794 2795 return object(topology, {type: "MultiLineString", arcs: merge(topology, arcs)}); 2796 } 2797 2798 function featureOrCollection(topology, o) { 2799 return o.type === "GeometryCollection" ? { 2800 type: "FeatureCollection", 2801 features: o.geometries.map(function(o) { return feature(topology, o); }) 2802 } : feature(topology, o); 2803 } 2804 2805 function feature(topology, o) { 2806 var f = { 2807 type: "Feature", 2808 id: o.id, 2809 properties: o.properties || {}, 2810 geometry: object(topology, o) 2811 }; 2812 if (o.id == null) delete f.id; 2813 return f; 2814 } 2815 2816 function object(topology, o) { 2817 var absolute = transformAbsolute(topology.transform), 2818 arcs = topology.arcs; 2819 2820 function arc(i, points) { 2821 if (points.length) points.pop(); 2822 for (var a = arcs[i < 0 ? ~i : i], k = 0, n = a.length, p; k < n; ++k) { 2823 points.push(p = a[k].slice()); 2824 absolute(p, k); 2825 } 2826 if (i < 0) reverse(points, n); 2827 } 2828 2829 function point(p) { 2830 p = p.slice(); 2831 absolute(p, 0); 2832 return p; 2833 } 2834 2835 function line(arcs) { 2836 var points = []; 2837 for (var i = 0, n = arcs.length; i < n; ++i) arc(arcs[i], points); 2838 if (points.length < 2) points.push(points[0].slice()); 2839 return points; 2840 } 2841 2842 function ring(arcs) { 2843 var points = line(arcs); 2844 while (points.length < 4) points.push(points[0].slice()); 2845 return points; 2846 } 2847 2848 function polygon(arcs) { 2849 return arcs.map(ring); 2850 } 2851 2852 function geometry(o) { 2853 var t = o.type; 2854 return t === "GeometryCollection" ? {type: t, geometries: o.geometries.map(geometry)} 2855 : t in geometryType ? {type: t, coordinates: geometryType[t](o)} 2856 : null; 2857 } 2858 2859 var geometryType = { 2860 Point: function(o) { return point(o.coordinates); }, 2861 MultiPoint: function(o) { return o.coordinates.map(point); }, 2862 LineString: function(o) { return line(o.arcs); }, 2863 MultiLineString: function(o) { return o.arcs.map(line); }, 2864 Polygon: function(o) { return polygon(o.arcs); }, 2865 MultiPolygon: function(o) { return o.arcs.map(polygon); } 2866 }; 2867 2868 return geometry(o); 2869 } 2870 2871 function reverse(array, n) { 2872 var t, j = array.length, i = j - n; while (i < --j) t = array[i], array[i++] = array[j], array[j] = t; 2873 } 2874 2875 function bisect(a, x) { 2876 var lo = 0, hi = a.length; 2877 while (lo < hi) { 2878 var mid = lo + hi >>> 1; 2879 if (a[mid] < x) lo = mid + 1; 2880 else hi = mid; 2881 } 2882 return lo; 2883 } 2884 2885 function neighbors(objects) { 2886 var indexesByArc = {}, // arc index -> array of object indexes 2887 neighbors = objects.map(function() { return []; }); 2888 2889 function line(arcs, i) { 2890 arcs.forEach(function(a) { 2891 if (a < 0) a = ~a; 2892 var o = indexesByArc[a]; 2893 if (o) o.push(i); 2894 else indexesByArc[a] = [i]; 2895 }); 2896 } 2897 2898 function polygon(arcs, i) { 2899 arcs.forEach(function(arc) { line(arc, i); }); 2900 } 2901 2902 function geometry(o, i) { 2903 if (o.type === "GeometryCollection") o.geometries.forEach(function(o) { geometry(o, i); }); 2904 else if (o.type in geometryType) geometryType[o.type](o.arcs, i); 2905 } 2906 2907 var geometryType = { 2908 LineString: line, 2909 MultiLineString: polygon, 2910 Polygon: polygon, 2911 MultiPolygon: function(arcs, i) { arcs.forEach(function(arc) { polygon(arc, i); }); } 2912 }; 2913 2914 objects.forEach(geometry); 2915 2916 for (var i in indexesByArc) { 2917 for (var indexes = indexesByArc[i], m = indexes.length, j = 0; j < m; ++j) { 2918 for (var k = j + 1; k < m; ++k) { 2919 var ij = indexes[j], ik = indexes[k], n; 2920 if ((n = neighbors[ij])[i = bisect(n, ik)] !== ik) n.splice(i, 0, ik); 2921 if ((n = neighbors[ik])[i = bisect(n, ij)] !== ij) n.splice(i, 0, ij); 2922 } 2923 } 2924 } 2925 2926 return neighbors; 2927 } 2928 2929 function presimplify(topology, triangleArea) { 2930 var absolute = transformAbsolute(topology.transform), 2931 relative = transformRelative(topology.transform), 2932 heap = minHeap(compareArea), 2933 maxArea = 0, 2934 triangle; 2935 2936 if (!triangleArea) triangleArea = cartesianArea; 2937
2938 topology.arcs.forEach(function(arc) { 2939 var triangles = []; 2940 2941 arc.forEach(absolute); 2942 2943 for (var i = 1, n = arc.length - 1; i < n; ++i) { 2944 triangle = arc.slice(i - 1, i + 2); 2945 triangle[1][2] = triangleArea(triangle); 2946 triangles.push(triangle); 2947 heap.push(triangle); 2948 } 2949 2950 // Always keep the arc endpoints! 2951 arc[0][2] = arc[n][2] = Infinity; 2952 2953 for (var i = 0, n = triangles.length; i < n; ++i) { 2954 triangle = triangles[i]; 2955 triangle.previous = triangles[i - 1]; 2956 triangle.next = triangles[i + 1]; 2957 } 2958 }); 2959 2960 while (triangle = heap.pop()) { 2961 var previous = triangle.previous, 2962 next = triangle.next; 2963 2964 // If the area of the current point is less than that of the previous point 2965 // to be eliminated, use the latter's area instead. This ensures that the 2966 // current point cannot be eliminated without eliminating previously- 2967 // eliminated points. 2968 if (triangle[1][2] < maxArea) triangle[1][2] = maxArea; 2969 else maxArea = triangle[1][2]; 2970 2971 if (previous) { 2972 previous.next = next; 2973 previous[2] = triangle[2]; 2974 update(previous); 2975 } 2976 2977 if (next) { 2978 next.previous = previous; 2979 next[0] = triangle[0]; 2980 update(next); 2981 } 2982 } 2983 2984 topology.arcs.forEach(function(arc) { 2985 arc.forEach(relative); 2986 }); 2987 2988 function update(triangle) { 2989 heap.remove(triangle); 2990 triangle[1][2] = triangleArea(triangle); 2991 heap.push(triangle); 2992 } 2993 2994 return topology; 2995 }; 2996 2997 function cartesianArea(triangle) { 2998 return Math.abs( 2999 (triangle[0][0] - triangle[2][0]) * (triangle[1][1] - triangle[0][1]) 3000 - (triangle[0][0] - triangle[1][0]) * (triangle[2][1] - triangle[0][1]) 3001 ); 3002 } 3003 3004 function compareArea(a, b) { 3005 return a[1][2] - b[1][2]; 3006 } 3007 3008 function minHeap(compare) { 3009 var heap = {}, 3010 array = []; 3011 3012 heap.push = function() { 3013 for (var i = 0, n = arguments.length; i < n; ++i) { 3014 var object = arguments[i]; 3015 up(object.index = array.push(object) - 1); 3016 } 3017 return array.length; 3018 }; 3019 3020 heap.pop = function() { 3021 var removed = array[0], 3022 object = array.pop(); 3023 if (array.length) { 3024 array[object.index = 0] = object; 3025 down(0); 3026 } 3027 return removed; 3028 }; 3029 3030 heap.remove = function(removed) { 3031 var i = removed.index, 3032 object = array.pop(); 3033 if (i !== array.length) { 3034 array[object.index = i] = object; 3035 (compare(object, removed) < 0 ? up : down)(i); 3036 } 3037 return i; 3038 }; 3039 3040 function up(i) { 3041 var object = array[i]; 3042 while (i > 0) { 3043 var up = ((i + 1) >> 1) - 1, 3044 parent = array[up]; 3045 if (compare(object, parent) >= 0) break; 3046 array[parent.index = i] = parent; 3047 array[object.index = i = up] = object; 3048 } 3049 } 3050 3051 function down(i) { 3052 var object = array[i]; 3053 while (true) { 3054 var right = (i + 1) << 1, 3055 left = right - 1, 3056 down = i, 3057 child = array[down]; 3058 if (left < array.length && compare(array[left], child) < 0) child = array[down = left]; 3059 if (right < array.length && compare(array[right], child) < 0) child = array[down = right]; 3060 if (down === i) break; 3061 array[child.index = i] = child; 3062 array[object.index = i = down] = object; 3063 } 3064 } 3065 3066 return heap; 3067 } 3068 3069 function transformAbsolute(transform) { 3070 if (!transform) return noop; 3071 var x0, 3072 y0, 3073 kx = transform.scale[0], 3074 ky = transform.scale[1], 3075 dx = transform.translate[0], 3076 dy = transform.translate[1]; 3077 return function(point, i) { 3078 if (!i) x0 = y0 = 0; 3079 point[0] = (x0 += point[0]) * kx + dx; 3080 point[1] = (y0 += point[1]) * ky + dy; 3081 }; 3082 } 3083 3084 function transformRelative(transform) { 3085 if (!transform) return noop; 3086 var x0, 3087 y0, 3088 kx = transform.scale[0], 3089 ky = transform.scale[1], 3090 dx = transform.translate[0], 3091 dy = transform.translate[1]; 3092 return function(point, i) { 3093 if (!i) x0 = y0 = 0; 3094 var x1 = (point[0] - dx) / kx | 0, 3095 y1 = (point[1] - dy) / ky | 0; 3096 point[0] = x1 - x0; 3097 point[1] = y1 - y0; 3098 x0 = x1; 3099 y0 = y1; 3100 }; 3101 } 3102 3103 function noop() {} 3104 3105 if (typeof define === "function" && define.amd) define(topojson); 3106 else if (typeof module === "object" && module.exports) module.exports = topojson; 3107 else this.topojson = topojson; 3108}(); 3109 3110},{}],38:[function(_dereq_,module,exports){ 3111module.exports = parse; 3112 3113/* 3114 * Parse WKT and return GeoJSON. 3115 * 3116 * @param {string} _ A WKT geometry 3117 * @return {?Object} A GeoJSON geometry object 3118 */ 3119function parse(_) { 3120 3121 var i = 0; 3122 3123 function $(re) { 3124 var match = _.substring(i).match(re); 3125 if (!match) return null; 3126 else { 3127 i += match[0].length; 3128 return match[0]; 3129 } 3130 } 3131 3132 function white() { $(/^\s*/); } 3133 3134 function multicoords() { 3135 white(); 3136 var depth = 0, rings = [], 3137 pointer = rings, elem; 3138 while (elem = 3139 $(/^(\()/) || 3140 $(/^(\))/) || 3141 $(/^(\,)/) || 3142 coords()) { 3143 if (elem == '(') { 3144 depth++; 3145 } else if (elem == ')') { 3146 depth--; 3147 if (depth == 0) break; 3148 } else if (elem && Array.isArray(elem) && elem.length) { 3149 pointer.push(elem); 3150 } else if (elem === ',') { 3151 } 3152 white(); 3153 } 3154 if (depth !== 0) return null; 3155 return rings; 3156 } 3157 3158 function coords() { 3159 var list = [], item, pt; 3160 while (pt = 3161 $(/^[-+]?([0-9]*\.[0-9]+|[0-9]+)/) || 3162 $(/^(\,)/)) { 3163 if (pt == ',') { 3164 list.push(item); 3165 item = []; 3166 } else { 3167 if (!item) item = []; 3168 item.push(parseFloat(pt)); 3169 } 3170 white(); 3171 } 3172 if (item) list.push(item); 3173 return list.length ? list : null; 3174 } 3175 3176 function point() { 3177 if (!$(/^(point)/i)) return null; 3178 white(); 3179 if (!$(/^(\()/)) return null; 3180 var c = coords(); 3181 white(); 3182 if (!$(/^(\))/)) return null; 3183 return { 3184 type: 'Point', 3185 coordinates: c[0] 3186 }; 3187 } 3188 3189 function multipoint() { 3190 if (!$(/^(multipoint)/i)) return null; 3191 white(); 3192 var c = multicoords(); 3193 white(); 3194 return { 3195 type: 'MultiPoint', 3196 coordinates: c[0] 3197 }; 3198 } 3199 3200 function multilinestring() { 3201 if (!$(/^(multilinestring)/i)) return null; 3202 white(); 3203 var c = multicoords(); 3204 white(); 3205 return { 3206 type: 'MultiLineString', 3207 coordinates: c 3208 }; 3209 } 3210 3211 function linestring() { 3212 if (!$(/^(linestring)/i)) return null; 3213 white(); 3214 if (!$(/^(\()/)) return null; 3215 var c = coords(); 3216 if (!$(/^(\))/)) return null; 3217 return { 3218 type: 'LineString', 3219 coordinates: c 3220 }; 3221 } 3222 3223 function polygon() { 3224 if (!$(/^(polygon)/i)) return null; 3225 white(); 3226 return { 3227 type: 'Polygon', 3228 coordinates: multicoords() 3229 }; 3230 } 3231 3232 function multipolygon() { 3233 if (!$(/^(multipolygon)/i)) return null; 3234 white(); 3235 return { 3236 type: 'MultiPolygon', 3237 coordinates: multicoords() 3238 }; 3239 } 3240 3241 function geometrycollection() { 3242 var geometries = [], geometry; 3243 3244 if (!$(/^(geometrycollection)/i)) return null; 3245 white(); 3246 3247 if (!$(/^(\()/)) return null; 3248 while (geometry = root()) { 3249 geometries.push(geometry); 3250 white(); 3251 $(/^(\,)/); 3252 white(); 3253 } 3254 if (!$(/^(\))/)) return null; 3255 3256 return { 3257 type: 'GeometryCollection', 3258 geometries: geometries 3259 }; 3260 } 3261 3262 function root() { 3263 return point() || 3264 linestring() || 3265 polygon() || 3266 multipoint() || 3267 multilinestring() || 3268 multipolygon() || 3269 geometrycollection(); 3270 } 3271
3272 return root(); 3273} 3274 3275},{}]},{},[1]) 3276(1) 3277});
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.