3   var bootstrap = (typeof exports.bootstrap === "object") ?
 
   5     (exports.bootstrap = {});
 
   7   bootstrap.tooltip = function() {
 
   9     var tooltip = function(selection) {
 
  10         selection.each(setup);
 
  12       animation = d3.functor(false),
 
  13       html = d3.functor(false),
 
  15         var title = this.getAttribute("data-original-title");
 
  19           title = this.getAttribute("title");
 
  20           this.removeAttribute("title");
 
  21           this.setAttribute("data-original-title", title);
 
  25       over = "mouseenter.tooltip",
 
  26       out = "mouseleave.tooltip",
 
  27       placements = "top left bottom right".split(" "),
 
  28       placement = d3.functor("top");
 
  30     tooltip.title = function(_) {
 
  31       if (arguments.length) {
 
  32         title = d3.functor(_);
 
  39     tooltip.html = function(_) {
 
  40       if (arguments.length) {
 
  48     tooltip.placement = function(_) {
 
  49       if (arguments.length) {
 
  50         placement = d3.functor(_);
 
  57     tooltip.show = function(selection) {
 
  61     tooltip.hide = function(selection) {
 
  65     tooltip.toggle = function(selection) {
 
  66       selection.each(toggle);
 
  69     tooltip.destroy = function(selection) {
 
  73         .attr("title", function() {
 
  74           return this.getAttribute("data-original-title") || this.getAttribute("title");
 
  76         .attr("data-original-title", null)
 
  82       var root = d3.select(this),
 
  83           animate = animation.apply(this, arguments),
 
  84           tip = root.append("div")
 
  85             .attr("class", "tooltip");
 
  88         tip.classed("fade", true);
 
  91       // TODO "inside" checks?
 
  94         .attr("class", "tooltip-arrow");
 
  96         .attr("class", "tooltip-inner");
 
  98       var place = placement.apply(this, arguments);
 
  99       tip.classed(place, true);
 
 106       var root = d3.select(this),
 
 107           content = title.apply(this, arguments),
 
 108           tip = root.select(".tooltip")
 
 109             .classed("in", true),
 
 110           markup = html.apply(this, arguments),
 
 111           innercontent = tip.select(".tooltip-inner")[markup ? "html" : "text"](content),
 
 112           place = placement.apply(this, arguments),
 
 113           outer = getPosition(root.node()),
 
 114           inner = getPosition(tip.node()),
 
 119           pos = {x: outer.x + (outer.w - inner.w) / 2, y: outer.y - inner.h};
 
 122           pos = {x: outer.x + outer.w, y: outer.y + (outer.h - inner.h) / 2};
 
 125           pos = {x: outer.x - inner.w, y: outer.y + (outer.h - inner.h) / 2};
 
 128           pos = {x: Math.max(0, outer.x + (outer.w - inner.w) / 2), y: outer.y + outer.h};
 
 133         {left: ~~pos.x + "px", top: ~~pos.y + "px"} :
 
 134         {left: null, top: null});
 
 136       this.tooltipVisible = true;
 
 140       d3.select(this).select(".tooltip")
 
 141         .classed("in", false);
 
 143       this.tooltipVisible = false;
 
 147       if (this.tooltipVisible) {
 
 148         hide.apply(this, arguments);
 
 150         show.apply(this, arguments);
 
 157   function getPosition(node) {
 
 158     var mode = d3.select(node).style('position');
 
 159     if (mode === 'absolute' || mode === 'static') {
 
 178   var d3 = {version: "3.5.5"}; // semver
 
 179 d3.ascending = d3_ascending;
 
 181 function d3_ascending(a, b) {
 
 182   return a < b ? -1 : a > b ? 1 : a >= b ? 0 : NaN;
 
 184 d3.descending = function(a, b) {
 
 185   return b < a ? -1 : b > a ? 1 : b >= a ? 0 : NaN;
 
 187 d3.min = function(array, f) {
 
 192   if (arguments.length === 1) {
 
 193     while (++i < n) if ((b = array[i]) != null && b >= b) { a = b; break; }
 
 194     while (++i < n) if ((b = array[i]) != null && a > b) a = b;
 
 196     while (++i < n) if ((b = f.call(array, array[i], i)) != null && b >= b) { a = b; break; }
 
 197     while (++i < n) if ((b = f.call(array, array[i], i)) != null && a > b) a = b;
 
 201 d3.max = function(array, f) {
 
 206   if (arguments.length === 1) {
 
 207     while (++i < n) if ((b = array[i]) != null && b >= b) { a = b; break; }
 
 208     while (++i < n) if ((b = array[i]) != null && b > a) a = b;
 
 210     while (++i < n) if ((b = f.call(array, array[i], i)) != null && b >= b) { a = b; break; }
 
 211     while (++i < n) if ((b = f.call(array, array[i], i)) != null && b > a) a = b;
 
 215 d3.extent = function(array, f) {
 
 221   if (arguments.length === 1) {
 
 222     while (++i < n) if ((b = array[i]) != null && b >= b) { a = c = b; break; }
 
 223     while (++i < n) if ((b = array[i]) != null) {
 
 228     while (++i < n) if ((b = f.call(array, array[i], i)) != null && b >= b) { a = c = b; break; }
 
 229     while (++i < n) if ((b = f.call(array, array[i], i)) != null) {
 
 236 function d3_number(x) {
 
 237   return x === null ? NaN : +x;
 
 240 function d3_numeric(x) {
 
 244 d3.sum = function(array, f) {
 
 249   if (arguments.length === 1) {
 
 250     while (++i < n) if (d3_numeric(a = +array[i])) s += a; // zero and null are equivalent
 
 252     while (++i < n) if (d3_numeric(a = +f.call(array, array[i], i))) s += a;
 
 257 d3.mean = function(array, f) {
 
 263   if (arguments.length === 1) {
 
 264     while (++i < n) if (d3_numeric(a = d3_number(array[i]))) s += a; else --j;
 
 266     while (++i < n) if (d3_numeric(a = d3_number(f.call(array, array[i], i)))) s += a; else --j;
 
 270 // R-7 per <http://en.wikipedia.org/wiki/Quantile>
 
 271 d3.quantile = function(values, p) {
 
 272   var H = (values.length - 1) * p + 1,
 
 276   return e ? v + e * (values[h] - v) : v;
 
 279 d3.median = function(array, f) {
 
 284   if (arguments.length === 1) {
 
 285     while (++i < n) if (d3_numeric(a = d3_number(array[i]))) numbers.push(a);
 
 287     while (++i < n) if (d3_numeric(a = d3_number(f.call(array, array[i], i)))) numbers.push(a);
 
 289   if (numbers.length) return d3.quantile(numbers.sort(d3_ascending), .5);
 
 292 d3.variance = function(array, f) {
 
 293   var n = array.length,
 
 300   if (arguments.length === 1) {
 
 302       if (d3_numeric(a = d3_number(array[i]))) {
 
 310       if (d3_numeric(a = d3_number(f.call(array, array[i], i)))) {
 
 317   if (j > 1) return s / (j - 1);
 
 320 d3.deviation = function() {
 
 321   var v = d3.variance.apply(this, arguments);
 
 322   return v ? Math.sqrt(v) : v;
 
 325 function d3_bisector(compare) {
 
 327     left: function(a, x, lo, hi) {
 
 328       if (arguments.length < 3) lo = 0;
 
 329       if (arguments.length < 4) hi = a.length;
 
 331         var mid = lo + hi >>> 1;
 
 332         if (compare(a[mid], x) < 0) lo = mid + 1;
 
 337     right: function(a, x, lo, hi) {
 
 338       if (arguments.length < 3) lo = 0;
 
 339       if (arguments.length < 4) hi = a.length;
 
 341         var mid = lo + hi >>> 1;
 
 342         if (compare(a[mid], x) > 0) hi = mid;
 
 350 var d3_bisect = d3_bisector(d3_ascending);
 
 351 d3.bisectLeft = d3_bisect.left;
 
 352 d3.bisect = d3.bisectRight = d3_bisect.right;
 
 354 d3.bisector = function(f) {
 
 355   return d3_bisector(f.length === 1
 
 356       ? function(d, x) { return d3_ascending(f(d), x); }
 
 359 d3.shuffle = function(array, i0, i1) {
 
 360   if ((m = arguments.length) < 3) { i1 = array.length; if (m < 2) i0 = 0; }
 
 361   var m = i1 - i0, t, i;
 
 363     i = Math.random() * m-- | 0;
 
 364     t = array[m + i0], array[m + i0] = array[i + i0], array[i + i0] = t;
 
 368 d3.permute = function(array, indexes) {
 
 369   var i = indexes.length, permutes = new Array(i);
 
 370   while (i--) permutes[i] = array[indexes[i]];
 
 373 d3.pairs = function(array) {
 
 374   var i = 0, n = array.length - 1, p0, p1 = array[0], pairs = new Array(n < 0 ? 0 : n);
 
 375   while (i < n) pairs[i] = [p0 = p1, p1 = array[++i]];
 
 379 d3.zip = function() {
 
 380   if (!(n = arguments.length)) return [];
 
 381   for (var i = -1, m = d3.min(arguments, d3_zipLength), zips = new Array(m); ++i < m;) {
 
 382     for (var j = -1, n, zip = zips[i] = new Array(n); ++j < n;) {
 
 383       zip[j] = arguments[j][i];
 
 389 function d3_zipLength(d) {
 
 393 d3.transpose = function(matrix) {
 
 394   return d3.zip.apply(d3, matrix);
 
 396 d3.keys = function(map) {
 
 398   for (var key in map) keys.push(key);
 
 401 d3.values = function(map) {
 
 403   for (var key in map) values.push(map[key]);
 
 406 d3.entries = function(map) {
 
 408   for (var key in map) entries.push({key: key, value: map[key]});
 
 411 d3.merge = function(arrays) {
 
 412   var n = arrays.length,
 
 419   while (++i < n) j += arrays[i].length;
 
 420   merged = new Array(j);
 
 426       merged[--j] = array[m];
 
 434 d3.range = function(start, stop, step) {
 
 435   if (arguments.length < 3) {
 
 437     if (arguments.length < 2) {
 
 442   if ((stop - start) / step === Infinity) throw new Error("infinite range");
 
 444        k = d3_range_integerScale(abs(step)),
 
 447   start *= k, stop *= k, step *= k;
 
 448   if (step < 0) while ((j = start + step * ++i) > stop) range.push(j / k);
 
 449   else while ((j = start + step * ++i) < stop) range.push(j / k);
 
 453 function d3_range_integerScale(x) {
 
 455   while (x * k % 1) k *= 10;
 
 458 function d3_class(ctor, properties) {
 
 459   for (var key in properties) {
 
 460     Object.defineProperty(ctor.prototype, key, {
 
 461       value: properties[key],
 
 467 d3.map = function(object, f) {
 
 468   var map = new d3_Map;
 
 469   if (object instanceof d3_Map) {
 
 470     object.forEach(function(key, value) { map.set(key, value); });
 
 471   } else if (Array.isArray(object)) {
 
 475     if (arguments.length === 1) while (++i < n) map.set(i, object[i]);
 
 476     else while (++i < n) map.set(f.call(object, o = object[i], i), o);
 
 478     for (var key in object) map.set(key, object[key]);
 
 484   this._ = Object.create(null);
 
 487 var d3_map_proto = "__proto__",
 
 493     return this._[d3_map_escape(key)];
 
 495   set: function(key, value) {
 
 496     return this._[d3_map_escape(key)] = value;
 
 498   remove: d3_map_remove,
 
 502     for (var key in this._) values.push(this._[key]);
 
 505   entries: function() {
 
 507     for (var key in this._) entries.push({key: d3_map_unescape(key), value: this._[key]});
 
 512   forEach: function(f) {
 
 513     for (var key in this._) f.call(this, d3_map_unescape(key), this._[key]);
 
 517 function d3_map_escape(key) {
 
 518   return (key += "") === d3_map_proto || key[0] === d3_map_zero ? d3_map_zero + key : key;
 
 521 function d3_map_unescape(key) {
 
 522   return (key += "")[0] === d3_map_zero ? key.slice(1) : key;
 
 525 function d3_map_has(key) {
 
 526   return d3_map_escape(key) in this._;
 
 529 function d3_map_remove(key) {
 
 530   return (key = d3_map_escape(key)) in this._ && delete this._[key];
 
 533 function d3_map_keys() {
 
 535   for (var key in this._) keys.push(d3_map_unescape(key));
 
 539 function d3_map_size() {
 
 541   for (var key in this._) ++size;
 
 545 function d3_map_empty() {
 
 546   for (var key in this._) return false;
 
 550 d3.nest = function() {
 
 557   function map(mapType, array, depth) {
 
 558     if (depth >= keys.length) return rollup
 
 559         ? rollup.call(nest, array) : (sortValues
 
 560         ? array.sort(sortValues)
 
 569         valuesByKey = new d3_Map,
 
 573       if (values = valuesByKey.get(keyValue = key(object = array[i]))) {
 
 576         valuesByKey.set(keyValue, [object]);
 
 582       setter = function(keyValue, values) {
 
 583         object.set(keyValue, map(mapType, values, depth));
 
 587       setter = function(keyValue, values) {
 
 588         object[keyValue] = map(mapType, values, depth);
 
 592     valuesByKey.forEach(setter);
 
 596   function entries(map, depth) {
 
 597     if (depth >= keys.length) return map;
 
 600         sortKey = sortKeys[depth++];
 
 602     map.forEach(function(key, keyMap) {
 
 603       array.push({key: key, values: entries(keyMap, depth)});
 
 607         ? array.sort(function(a, b) { return sortKey(a.key, b.key); })
 
 611   nest.map = function(array, mapType) {
 
 612     return map(mapType, array, 0);
 
 615   nest.entries = function(array) {
 
 616     return entries(map(d3.map, array, 0), 0);
 
 619   nest.key = function(d) {
 
 624   // Specifies the order for the most-recently specified key.
 
 625   // Note: only applies to entries. Map keys are unordered!
 
 626   nest.sortKeys = function(order) {
 
 627     sortKeys[keys.length - 1] = order;
 
 631   // Specifies the order for leaf values.
 
 632   // Applies to both maps and entries array.
 
 633   nest.sortValues = function(order) {
 
 638   nest.rollup = function(f) {
 
 646 d3.set = function(array) {
 
 647   var set = new d3_Set;
 
 648   if (array) for (var i = 0, n = array.length; i < n; ++i) set.add(array[i]);
 
 653   this._ = Object.create(null);
 
 659     this._[d3_map_escape(key += "")] = true;
 
 662   remove: d3_map_remove,
 
 666   forEach: function(f) {
 
 667     for (var key in this._) f.call(this, d3_map_unescape(key));
 
 671 var d3_document = this.document;
 
 673 function d3_documentElement(node) {
 
 675       && (node.ownerDocument // node is a Node
 
 676       || node.document // node is a Window
 
 677       || node).documentElement; // node is a Document
 
 680 function d3_window(node) {
 
 682       && ((node.ownerDocument && node.ownerDocument.defaultView) // node is a Node
 
 683         || (node.document && node) // node is a Window
 
 684         || node.defaultView); // node is a Document
 
 686 // Copies a variable number of methods from source to target.
 
 687 d3.rebind = function(target, source) {
 
 688   var i = 1, n = arguments.length, method;
 
 689   while (++i < n) target[method = arguments[i]] = d3_rebind(target, source, source[method]);
 
 693 // Method is assumed to be a standard D3 getter-setter:
 
 694 // If passed with no arguments, gets the value.
 
 695 // If passed with arguments, sets the value and returns the target.
 
 696 function d3_rebind(target, source, method) {
 
 698     var value = method.apply(source, arguments);
 
 699     return value === source ? target : value;
 
 702 function d3_vendorSymbol(object, name) {
 
 703   if (name in object) return name;
 
 704   name = name.charAt(0).toUpperCase() + name.slice(1);
 
 705   for (var i = 0, n = d3_vendorPrefixes.length; i < n; ++i) {
 
 706     var prefixName = d3_vendorPrefixes[i] + name;
 
 707     if (prefixName in object) return prefixName;
 
 711 var d3_vendorPrefixes = ["webkit", "ms", "moz", "Moz", "o", "O"];
 
 712 var d3_arraySlice = [].slice,
 
 713     d3_array = function(list) { return d3_arraySlice.call(list); }; // conversion for NodeLists
 
 714 function d3_noop() {}
 
 716 d3.dispatch = function() {
 
 717   var dispatch = new d3_dispatch,
 
 719       n = arguments.length;
 
 720   while (++i < n) dispatch[arguments[i]] = d3_dispatch_event(dispatch);
 
 724 function d3_dispatch() {}
 
 726 d3_dispatch.prototype.on = function(type, listener) {
 
 727   var i = type.indexOf("."),
 
 730   // Extract optional namespace, e.g., "click.foo"
 
 732     name = type.slice(i + 1);
 
 733     type = type.slice(0, i);
 
 736   if (type) return arguments.length < 2
 
 737       ? this[type].on(name)
 
 738       : this[type].on(name, listener);
 
 740   if (arguments.length === 2) {
 
 741     if (listener == null) for (type in this) {
 
 742       if (this.hasOwnProperty(type)) this[type].on(name, null);
 
 748 function d3_dispatch_event(dispatch) {
 
 750       listenerByName = new d3_Map;
 
 753     var z = listeners, // defensive reference
 
 757     while (++i < n) if (l = z[i].on) l.apply(this, arguments);
 
 761   event.on = function(name, listener) {
 
 762     var l = listenerByName.get(name),
 
 765     // return the current listener, if any
 
 766     if (arguments.length < 2) return l && l.on;
 
 768     // remove the old listener, if any (with copy-on-write)
 
 771       listeners = listeners.slice(0, i = listeners.indexOf(l)).concat(listeners.slice(i + 1));
 
 772       listenerByName.remove(name);
 
 775     // add the new listener, if any
 
 776     if (listener) listeners.push(listenerByName.set(name, {on: listener}));
 
 786 function d3_eventPreventDefault() {
 
 787   d3.event.preventDefault();
 
 790 function d3_eventCancel() {
 
 791   d3.event.preventDefault();
 
 792   d3.event.stopPropagation();
 
 795 function d3_eventSource() {
 
 797   while (s = e.sourceEvent) e = s;
 
 801 // Like d3.dispatch, but for custom events abstracting native UI events. These
 
 802 // events have a target component (such as a brush), a target element (such as
 
 803 // the svg:g element containing the brush) and the standard arguments `d` (the
 
 804 // target element's data) and `i` (the selection index of the target element).
 
 805 function d3_eventDispatch(target) {
 
 806   var dispatch = new d3_dispatch,
 
 808       n = arguments.length;
 
 810   while (++i < n) dispatch[arguments[i]] = d3_dispatch_event(dispatch);
 
 812   // Creates a dispatch context for the specified `thiz` (typically, the target
 
 813   // DOM element that received the source event) and `argumentz` (typically, the
 
 814   // data `d` and index `i` of the target element). The returned function can be
 
 815   // used to dispatch an event to any registered listeners; the function takes a
 
 816   // single argument as input, being the event to dispatch. The event must have
 
 817   // a "type" attribute which corresponds to a type registered in the
 
 818   // constructor. This context will automatically populate the "sourceEvent" and
 
 819   // "target" attributes of the event, as well as setting the `d3.event` global
 
 820   // for the duration of the notification.
 
 821   dispatch.of = function(thiz, argumentz) {
 
 822     return function(e1) {
 
 825         e1.sourceEvent = d3.event;
 
 828         dispatch[e1.type].apply(thiz, argumentz);
 
 837 d3.requote = function(s) {
 
 838   return s.replace(d3_requote_re, "\\$&");
 
 841 var d3_requote_re = /[\\\^\$\*\+\?\|\[\]\(\)\.\{\}]/g;
 
 842 var d3_subclass = {}.__proto__?
 
 844 // Until ECMAScript supports array subclassing, prototype injection works well.
 
 845 function(object, prototype) {
 
 846   object.__proto__ = prototype;
 
 849 // And if your browser doesn't support __proto__, we'll use direct extension.
 
 850 function(object, prototype) {
 
 851   for (var property in prototype) object[property] = prototype[property];
 
 854 function d3_selection(groups) {
 
 855   d3_subclass(groups, d3_selectionPrototype);
 
 859 var d3_select = function(s, n) { return n.querySelector(s); },
 
 860     d3_selectAll = function(s, n) { return n.querySelectorAll(s); },
 
 861     d3_selectMatches = function(n, s) {
 
 862       var d3_selectMatcher = n.matches || n[d3_vendorSymbol(n, "matchesSelector")];
 
 863       d3_selectMatches = function(n, s) {
 
 864         return d3_selectMatcher.call(n, s);
 
 866       return d3_selectMatches(n, s);
 
 869 // Prefer Sizzle, if available.
 
 870 if (typeof Sizzle === "function") {
 
 871   d3_select = function(s, n) { return Sizzle(s, n)[0] || null; };
 
 872   d3_selectAll = Sizzle;
 
 873   d3_selectMatches = Sizzle.matchesSelector;
 
 876 d3.selection = function() {
 
 877   return d3.select(d3_document.documentElement);
 
 880 var d3_selectionPrototype = d3.selection.prototype = [];
 
 883 d3_selectionPrototype.select = function(selector) {
 
 890   selector = d3_selection_selector(selector);
 
 892   for (var j = -1, m = this.length; ++j < m;) {
 
 893     subgroups.push(subgroup = []);
 
 894     subgroup.parentNode = (group = this[j]).parentNode;
 
 895     for (var i = -1, n = group.length; ++i < n;) {
 
 896       if (node = group[i]) {
 
 897         subgroup.push(subnode = selector.call(node, node.__data__, i, j));
 
 898         if (subnode && "__data__" in node) subnode.__data__ = node.__data__;
 
 905   return d3_selection(subgroups);
 
 908 function d3_selection_selector(selector) {
 
 909   return typeof selector === "function" ? selector : function() {
 
 910     return d3_select(selector, this);
 
 914 d3_selectionPrototype.selectAll = function(selector) {
 
 919   selector = d3_selection_selectorAll(selector);
 
 921   for (var j = -1, m = this.length; ++j < m;) {
 
 922     for (var group = this[j], i = -1, n = group.length; ++i < n;) {
 
 923       if (node = group[i]) {
 
 924         subgroups.push(subgroup = d3_array(selector.call(node, node.__data__, i, j)));
 
 925         subgroup.parentNode = node;
 
 930   return d3_selection(subgroups);
 
 933 function d3_selection_selectorAll(selector) {
 
 934   return typeof selector === "function" ? selector : function() {
 
 935     return d3_selectAll(selector, this);
 
 939   svg: "http://www.w3.org/2000/svg",
 
 940   xhtml: "http://www.w3.org/1999/xhtml",
 
 941   xlink: "http://www.w3.org/1999/xlink",
 
 942   xml: "http://www.w3.org/XML/1998/namespace",
 
 943   xmlns: "http://www.w3.org/2000/xmlns/"
 
 948   qualify: function(name) {
 
 949     var i = name.indexOf(":"),
 
 952       prefix = name.slice(0, i);
 
 953       name = name.slice(i + 1);
 
 955     return d3_nsPrefix.hasOwnProperty(prefix)
 
 956         ? {space: d3_nsPrefix[prefix], local: name}
 
 961 d3_selectionPrototype.attr = function(name, value) {
 
 962   if (arguments.length < 2) {
 
 964     // For attr(string), return the attribute value for the first node.
 
 965     if (typeof name === "string") {
 
 966       var node = this.node();
 
 967       name = d3.ns.qualify(name);
 
 969           ? node.getAttributeNS(name.space, name.local)
 
 970           : node.getAttribute(name);
 
 973     // For attr(object), the object specifies the names and values of the
 
 974     // attributes to set or remove. The values may be functions that are
 
 975     // evaluated for each element.
 
 976     for (value in name) this.each(d3_selection_attr(value, name[value]));
 
 980   return this.each(d3_selection_attr(name, value));
 
 983 function d3_selection_attr(name, value) {
 
 984   name = d3.ns.qualify(name);
 
 986   // For attr(string, null), remove the attribute with the specified name.
 
 987   function attrNull() {
 
 988     this.removeAttribute(name);
 
 990   function attrNullNS() {
 
 991     this.removeAttributeNS(name.space, name.local);
 
 994   // For attr(string, string), set the attribute with the specified name.
 
 995   function attrConstant() {
 
 996     this.setAttribute(name, value);
 
 998   function attrConstantNS() {
 
 999     this.setAttributeNS(name.space, name.local, value);
 
1002   // For attr(string, function), evaluate the function for each element, and set
 
1003   // or remove the attribute as appropriate.
 
1004   function attrFunction() {
 
1005     var x = value.apply(this, arguments);
 
1006     if (x == null) this.removeAttribute(name);
 
1007     else this.setAttribute(name, x);
 
1009   function attrFunctionNS() {
 
1010     var x = value.apply(this, arguments);
 
1011     if (x == null) this.removeAttributeNS(name.space, name.local);
 
1012     else this.setAttributeNS(name.space, name.local, x);
 
1015   return value == null
 
1016       ? (name.local ? attrNullNS : attrNull) : (typeof value === "function"
 
1017       ? (name.local ? attrFunctionNS : attrFunction)
 
1018       : (name.local ? attrConstantNS : attrConstant));
 
1020 function d3_collapse(s) {
 
1021   return s.trim().replace(/\s+/g, " ");
 
1024 d3_selectionPrototype.classed = function(name, value) {
 
1025   if (arguments.length < 2) {
 
1027     // For classed(string), return true only if the first node has the specified
 
1028     // class or classes. Note that even if the browser supports DOMTokenList, it
 
1029     // probably doesn't support it on SVG elements (which can be animated).
 
1030     if (typeof name === "string") {
 
1031       var node = this.node(),
 
1032           n = (name = d3_selection_classes(name)).length,
 
1034       if (value = node.classList) {
 
1035         while (++i < n) if (!value.contains(name[i])) return false;
 
1037         value = node.getAttribute("class");
 
1038         while (++i < n) if (!d3_selection_classedRe(name[i]).test(value)) return false;
 
1043     // For classed(object), the object specifies the names of classes to add or
 
1044     // remove. The values may be functions that are evaluated for each element.
 
1045     for (value in name) this.each(d3_selection_classed(value, name[value]));
 
1049   // Otherwise, both a name and a value are specified, and are handled as below.
 
1050   return this.each(d3_selection_classed(name, value));
 
1053 function d3_selection_classedRe(name) {
 
1054   return new RegExp("(?:^|\\s+)" + d3.requote(name) + "(?:\\s+|$)", "g");
 
1057 function d3_selection_classes(name) {
 
1058   return (name + "").trim().split(/^|\s+/);
 
1061 // Multiple class names are allowed (e.g., "foo bar").
 
1062 function d3_selection_classed(name, value) {
 
1063   name = d3_selection_classes(name).map(d3_selection_classedName);
 
1064   var n = name.length;
 
1066   function classedConstant() {
 
1068     while (++i < n) name[i](this, value);
 
1071   // When the value is a function, the function is still evaluated only once per
 
1072   // element even if there are multiple class names.
 
1073   function classedFunction() {
 
1074     var i = -1, x = value.apply(this, arguments);
 
1075     while (++i < n) name[i](this, x);
 
1078   return typeof value === "function"
 
1083 function d3_selection_classedName(name) {
 
1084   var re = d3_selection_classedRe(name);
 
1085   return function(node, value) {
 
1086     if (c = node.classList) return value ? c.add(name) : c.remove(name);
 
1087     var c = node.getAttribute("class") || "";
 
1090       if (!re.test(c)) node.setAttribute("class", d3_collapse(c + " " + name));
 
1092       node.setAttribute("class", d3_collapse(c.replace(re, " ")));
 
1097 d3_selectionPrototype.style = function(name, value, priority) {
 
1098   var n = arguments.length;
 
1101     // For style(object) or style(object, string), the object specifies the
 
1102     // names and values of the attributes to set or remove. The values may be
 
1103     // functions that are evaluated for each element. The optional string
 
1104     // specifies the priority.
 
1105     if (typeof name !== "string") {
 
1106       if (n < 2) value = "";
 
1107       for (priority in name) this.each(d3_selection_style(priority, name[priority], value));
 
1111     // For style(string), return the computed style value for the first node.
 
1113       var node = this.node();
 
1114       return d3_window(node).getComputedStyle(node, null).getPropertyValue(name);
 
1117     // For style(string, string) or style(string, function), use the default
 
1118     // priority. The priority is ignored for style(string, null).
 
1122   // Otherwise, a name, value and priority are specified, and handled as below.
 
1123   return this.each(d3_selection_style(name, value, priority));
 
1126 function d3_selection_style(name, value, priority) {
 
1128   // For style(name, null) or style(name, null, priority), remove the style
 
1129   // property with the specified name. The priority is ignored.
 
1130   function styleNull() {
 
1131     this.style.removeProperty(name);
 
1134   // For style(name, string) or style(name, string, priority), set the style
 
1135   // property with the specified name, using the specified priority.
 
1136   function styleConstant() {
 
1137     this.style.setProperty(name, value, priority);
 
1140   // For style(name, function) or style(name, function, priority), evaluate the
 
1141   // function for each element, and set or remove the style property as
 
1142   // appropriate. When setting, use the specified priority.
 
1143   function styleFunction() {
 
1144     var x = value.apply(this, arguments);
 
1145     if (x == null) this.style.removeProperty(name);
 
1146     else this.style.setProperty(name, x, priority);
 
1149   return value == null
 
1150       ? styleNull : (typeof value === "function"
 
1151       ? styleFunction : styleConstant);
 
1154 d3_selectionPrototype.property = function(name, value) {
 
1155   if (arguments.length < 2) {
 
1157     // For property(string), return the property value for the first node.
 
1158     if (typeof name === "string") return this.node()[name];
 
1160     // For property(object), the object specifies the names and values of the
 
1161     // properties to set or remove. The values may be functions that are
 
1162     // evaluated for each element.
 
1163     for (value in name) this.each(d3_selection_property(value, name[value]));
 
1167   // Otherwise, both a name and a value are specified, and are handled as below.
 
1168   return this.each(d3_selection_property(name, value));
 
1171 function d3_selection_property(name, value) {
 
1173   // For property(name, null), remove the property with the specified name.
 
1174   function propertyNull() {
 
1178   // For property(name, string), set the property with the specified name.
 
1179   function propertyConstant() {
 
1183   // For property(name, function), evaluate the function for each element, and
 
1184   // set or remove the property as appropriate.
 
1185   function propertyFunction() {
 
1186     var x = value.apply(this, arguments);
 
1187     if (x == null) delete this[name];
 
1188     else this[name] = x;
 
1191   return value == null
 
1192       ? propertyNull : (typeof value === "function"
 
1193       ? propertyFunction : propertyConstant);
 
1196 d3_selectionPrototype.text = function(value) {
 
1197   return arguments.length
 
1198       ? this.each(typeof value === "function"
 
1199       ? function() { var v = value.apply(this, arguments); this.textContent = v == null ? "" : v; } : value == null
 
1200       ? function() { if (this.textContent !== "") this.textContent = ""; }
 
1201       : function() { if (this.textContent !== value) this.textContent = value; })
 
1202       : this.node().textContent;
 
1205 d3_selectionPrototype.html = function(value) {
 
1206   return arguments.length
 
1207       ? this.each(typeof value === "function"
 
1208       ? function() { var v = value.apply(this, arguments); this.innerHTML = v == null ? "" : v; } : value == null
 
1209       ? function() { this.innerHTML = ""; }
 
1210       : function() { this.innerHTML = value; })
 
1211       : this.node().innerHTML;
 
1214 d3_selectionPrototype.append = function(name) {
 
1215   name = d3_selection_creator(name);
 
1216   return this.select(function() {
 
1217     return this.appendChild(name.apply(this, arguments));
 
1221 function d3_selection_creator(name) {
 
1224     var document = this.ownerDocument,
 
1225         namespace = this.namespaceURI;
 
1227         ? document.createElementNS(namespace, name)
 
1228         : document.createElement(name);
 
1231   function createNS() {
 
1232     return this.ownerDocument.createElementNS(name.space, name.local);
 
1235   return typeof name === "function" ? name
 
1236       : (name = d3.ns.qualify(name)).local ? createNS
 
1240 d3_selectionPrototype.insert = function(name, before) {
 
1241   name = d3_selection_creator(name);
 
1242   before = d3_selection_selector(before);
 
1243   return this.select(function() {
 
1244     return this.insertBefore(name.apply(this, arguments), before.apply(this, arguments) || null);
 
1248 // TODO remove(selector)?
 
1249 // TODO remove(node)?
 
1250 // TODO remove(function)?
 
1251 d3_selectionPrototype.remove = function() {
 
1252   return this.each(d3_selectionRemove);
 
1255 function d3_selectionRemove() {
 
1256   var parent = this.parentNode;
 
1257   if (parent) parent.removeChild(this);
 
1260 d3_selectionPrototype.data = function(value, key) {
 
1266   // If no value is specified, return the first value.
 
1267   if (!arguments.length) {
 
1268     value = new Array(n = (group = this[0]).length);
 
1270       if (node = group[i]) {
 
1271         value[i] = node.__data__;
 
1277   function bind(group, groupData) {
 
1280         m = groupData.length,
 
1281         n0 = Math.min(n, m),
 
1282         updateNodes = new Array(m),
 
1283         enterNodes = new Array(m),
 
1284         exitNodes = new Array(n),
 
1289       var nodeByKeyValue = new d3_Map,
 
1290           keyValues = new Array(n),
 
1293       for (i = -1; ++i < n;) {
 
1294         if (nodeByKeyValue.has(keyValue = key.call(node = group[i], node.__data__, i))) {
 
1295           exitNodes[i] = node; // duplicate selection key
 
1297           nodeByKeyValue.set(keyValue, node);
 
1299         keyValues[i] = keyValue;
 
1302       for (i = -1; ++i < m;) {
 
1303         if (!(node = nodeByKeyValue.get(keyValue = key.call(groupData, nodeData = groupData[i], i)))) {
 
1304           enterNodes[i] = d3_selection_dataNode(nodeData);
 
1305         } else if (node !== true) { // no duplicate data key
 
1306           updateNodes[i] = node;
 
1307           node.__data__ = nodeData;
 
1309         nodeByKeyValue.set(keyValue, true);
 
1312       for (i = -1; ++i < n;) {
 
1313         if (nodeByKeyValue.get(keyValues[i]) !== true) {
 
1314           exitNodes[i] = group[i];
 
1318       for (i = -1; ++i < n0;) {
 
1320         nodeData = groupData[i];
 
1322           node.__data__ = nodeData;
 
1323           updateNodes[i] = node;
 
1325           enterNodes[i] = d3_selection_dataNode(nodeData);
 
1328       for (; i < m; ++i) {
 
1329         enterNodes[i] = d3_selection_dataNode(groupData[i]);
 
1331       for (; i < n; ++i) {
 
1332         exitNodes[i] = group[i];
 
1339     enterNodes.parentNode
 
1340         = updateNodes.parentNode
 
1341         = exitNodes.parentNode
 
1344     enter.push(enterNodes);
 
1345     update.push(updateNodes);
 
1346     exit.push(exitNodes);
 
1349   var enter = d3_selection_enter([]),
 
1350       update = d3_selection([]),
 
1351       exit = d3_selection([]);
 
1353   if (typeof value === "function") {
 
1355       bind(group = this[i], value.call(group, group.parentNode.__data__, i));
 
1359       bind(group = this[i], value);
 
1363   update.enter = function() { return enter; };
 
1364   update.exit = function() { return exit; };
 
1368 function d3_selection_dataNode(data) {
 
1369   return {__data__: data};
 
1372 d3_selectionPrototype.datum = function(value) {
 
1373   return arguments.length
 
1374       ? this.property("__data__", value)
 
1375       : this.property("__data__");
 
1378 d3_selectionPrototype.filter = function(filter) {
 
1384   if (typeof filter !== "function") filter = d3_selection_filter(filter);
 
1386   for (var j = 0, m = this.length; j < m; j++) {
 
1387     subgroups.push(subgroup = []);
 
1388     subgroup.parentNode = (group = this[j]).parentNode;
 
1389     for (var i = 0, n = group.length; i < n; i++) {
 
1390       if ((node = group[i]) && filter.call(node, node.__data__, i, j)) {
 
1391         subgroup.push(node);
 
1396   return d3_selection(subgroups);
 
1399 function d3_selection_filter(selector) {
 
1401     return d3_selectMatches(this, selector);
 
1405 d3_selectionPrototype.order = function() {
 
1406   for (var j = -1, m = this.length; ++j < m;) {
 
1407     for (var group = this[j], i = group.length - 1, next = group[i], node; --i >= 0;) {
 
1408       if (node = group[i]) {
 
1409         if (next && next !== node.nextSibling) next.parentNode.insertBefore(node, next);
 
1417 d3_selectionPrototype.sort = function(comparator) {
 
1418   comparator = d3_selection_sortComparator.apply(this, arguments);
 
1419   for (var j = -1, m = this.length; ++j < m;) this[j].sort(comparator);
 
1420   return this.order();
 
1423 function d3_selection_sortComparator(comparator) {
 
1424   if (!arguments.length) comparator = d3_ascending;
 
1425   return function(a, b) {
 
1426     return a && b ? comparator(a.__data__, b.__data__) : !a - !b;
 
1430 d3_selectionPrototype.each = function(callback) {
 
1431   return d3_selection_each(this, function(node, i, j) {
 
1432     callback.call(node, node.__data__, i, j);
 
1436 function d3_selection_each(groups, callback) {
 
1437   for (var j = 0, m = groups.length; j < m; j++) {
 
1438     for (var group = groups[j], i = 0, n = group.length, node; i < n; i++) {
 
1439       if (node = group[i]) callback(node, i, j);
 
1445 d3_selectionPrototype.call = function(callback) {
 
1446   var args = d3_array(arguments);
 
1447   callback.apply(args[0] = this, args);
 
1451 d3_selectionPrototype.empty = function() {
 
1452   return !this.node();
 
1455 d3_selectionPrototype.node = function() {
 
1456   for (var j = 0, m = this.length; j < m; j++) {
 
1457     for (var group = this[j], i = 0, n = group.length; i < n; i++) {
 
1458       var node = group[i];
 
1459       if (node) return node;
 
1465 d3_selectionPrototype.size = function() {
 
1467   d3_selection_each(this, function() { ++n; });
 
1471 function d3_selection_enter(selection) {
 
1472   d3_subclass(selection, d3_selection_enterPrototype);
 
1476 var d3_selection_enterPrototype = [];
 
1478 d3.selection.enter = d3_selection_enter;
 
1479 d3.selection.enter.prototype = d3_selection_enterPrototype;
 
1481 d3_selection_enterPrototype.append = d3_selectionPrototype.append;
 
1482 d3_selection_enterPrototype.empty = d3_selectionPrototype.empty;
 
1483 d3_selection_enterPrototype.node = d3_selectionPrototype.node;
 
1484 d3_selection_enterPrototype.call = d3_selectionPrototype.call;
 
1485 d3_selection_enterPrototype.size = d3_selectionPrototype.size;
 
1488 d3_selection_enterPrototype.select = function(selector) {
 
1496   for (var j = -1, m = this.length; ++j < m;) {
 
1497     upgroup = (group = this[j]).update;
 
1498     subgroups.push(subgroup = []);
 
1499     subgroup.parentNode = group.parentNode;
 
1500     for (var i = -1, n = group.length; ++i < n;) {
 
1501       if (node = group[i]) {
 
1502         subgroup.push(upgroup[i] = subnode = selector.call(group.parentNode, node.__data__, i, j));
 
1503         subnode.__data__ = node.__data__;
 
1505         subgroup.push(null);
 
1510   return d3_selection(subgroups);
 
1513 d3_selection_enterPrototype.insert = function(name, before) {
 
1514   if (arguments.length < 2) before = d3_selection_enterInsertBefore(this);
 
1515   return d3_selectionPrototype.insert.call(this, name, before);
 
1518 function d3_selection_enterInsertBefore(enter) {
 
1520   return function(d, i, j) {
 
1521     var group = enter[j].update,
 
1524     if (j != j0) j0 = j, i0 = 0;
 
1525     if (i >= i0) i0 = i + 1;
 
1526     while (!(node = group[i0]) && ++i0 < n);
 
1531 // TODO fast singleton implementation?
 
1532 d3.select = function(node) {
 
1534   if (typeof node === "string") {
 
1535     group = [d3_select(node, d3_document)];
 
1536     group.parentNode = d3_document.documentElement;
 
1539     group.parentNode = d3_documentElement(node);
 
1541   return d3_selection([group]);
 
1544 d3.selectAll = function(nodes) {
 
1546   if (typeof nodes === "string") {
 
1547     group = d3_array(d3_selectAll(nodes, d3_document));
 
1548     group.parentNode = d3_document.documentElement;
 
1551     group.parentNode = null;
 
1553   return d3_selection([group]);
 
1556 d3_selectionPrototype.on = function(type, listener, capture) {
 
1557   var n = arguments.length;
 
1560     // For on(object) or on(object, boolean), the object specifies the event
 
1561     // types and listeners to add or remove. The optional boolean specifies
 
1562     // whether the listener captures events.
 
1563     if (typeof type !== "string") {
 
1564       if (n < 2) listener = false;
 
1565       for (capture in type) this.each(d3_selection_on(capture, type[capture], listener));
 
1569     // For on(string), return the listener for the first node.
 
1570     if (n < 2) return (n = this.node()["__on" + type]) && n._;
 
1572     // For on(string, function), use the default capture.
 
1576   // Otherwise, a type, listener and capture are specified, and handled as below.
 
1577   return this.each(d3_selection_on(type, listener, capture));
 
1580 function d3_selection_on(type, listener, capture) {
 
1581   var name = "__on" + type,
 
1582       i = type.indexOf("."),
 
1583       wrap = d3_selection_onListener;
 
1585   if (i > 0) type = type.slice(0, i);
 
1586   var filter = d3_selection_onFilters.get(type);
 
1587   if (filter) type = filter, wrap = d3_selection_onFilter;
 
1589   function onRemove() {
 
1592       this.removeEventListener(type, l, l.$);
 
1598     var l = wrap(listener, d3_array(arguments));
 
1599     if (typeof Raven !== 'undefined') l = Raven.wrap(l);
 
1600     onRemove.call(this);
 
1601     this.addEventListener(type, this[name] = l, l.$ = capture);
 
1605   function removeAll() {
 
1606     var re = new RegExp("^__on([^.]+)" + d3.requote(type) + "$"),
 
1608     for (var name in this) {
 
1609       if (match = name.match(re)) {
 
1611         this.removeEventListener(match[1], l, l.$);
 
1618       ? listener ? onAdd : onRemove
 
1619       : listener ? d3_noop : removeAll;
 
1622 var d3_selection_onFilters = d3.map({
 
1623   mouseenter: "mouseover",
 
1624   mouseleave: "mouseout"
 
1628   d3_selection_onFilters.forEach(function(k) {
 
1629     if ("on" + k in d3_document) d3_selection_onFilters.remove(k);
 
1633 function d3_selection_onListener(listener, argumentz) {
 
1634   return function(e) {
 
1635     var o = d3.event; // Events can be reentrant (e.g., focus).
 
1637     argumentz[0] = this.__data__;
 
1639       listener.apply(this, argumentz);
 
1646 function d3_selection_onFilter(listener, argumentz) {
 
1647   var l = d3_selection_onListener(listener, argumentz);
 
1648   return function(e) {
 
1649     var target = this, related = e.relatedTarget;
 
1650     if (!related || (related !== target && !(related.compareDocumentPosition(target) & 8))) {
 
1656 var d3_event_dragSelect,
 
1657     d3_event_dragId = 0;
 
1659 function d3_event_dragSuppress(node) {
 
1660   var name = ".dragsuppress-" + ++d3_event_dragId,
 
1661       click = "click" + name,
 
1662       w = d3.select(d3_window(node))
 
1663           .on("touchmove" + name, d3_eventPreventDefault)
 
1664           .on("dragstart" + name, d3_eventPreventDefault)
 
1665           .on("selectstart" + name, d3_eventPreventDefault);
 
1667   if (d3_event_dragSelect == null) {
 
1668     d3_event_dragSelect = "onselectstart" in node ? false
 
1669         : d3_vendorSymbol(node.style, "userSelect");
 
1672   if (d3_event_dragSelect) {
 
1673     var style = d3_documentElement(node).style,
 
1674         select = style[d3_event_dragSelect];
 
1675     style[d3_event_dragSelect] = "none";
 
1678   return function(suppressClick) {
 
1680     if (d3_event_dragSelect) style[d3_event_dragSelect] = select;
 
1681     if (suppressClick) { // suppress the next click, but only if it’s immediate
 
1682       var off = function() { w.on(click, null); };
 
1683       w.on(click, function() { d3_eventCancel(); off(); }, true);
 
1689 d3.mouse = function(container) {
 
1690   return d3_mousePoint(container, d3_eventSource());
 
1693 // https://bugs.webkit.org/show_bug.cgi?id=44083
 
1694 var d3_mouse_bug44083 = this.navigator && /WebKit/.test(this.navigator.userAgent) ? -1 : 0;
 
1696 function d3_mousePoint(container, e) {
 
1697   if (e.changedTouches) e = e.changedTouches[0];
 
1698   var svg = container.ownerSVGElement || container;
 
1699   if (svg.createSVGPoint) {
 
1700     var point = svg.createSVGPoint();
 
1701     if (d3_mouse_bug44083 < 0) {
 
1702       var window = d3_window(container);
 
1703       if (window.scrollX || window.scrollY) {
 
1704         svg = d3.select("body").append("svg").style({
 
1705           position: "absolute",
 
1712         var ctm = svg[0][0].getScreenCTM();
 
1713         d3_mouse_bug44083 = !(ctm.f || ctm.e);
 
1717     if (d3_mouse_bug44083) point.x = e.pageX, point.y = e.pageY;
 
1718     else point.x = e.clientX, point.y = e.clientY;
 
1719     point = point.matrixTransform(container.getScreenCTM().inverse());
 
1720     return [point.x, point.y];
 
1722   var rect = container.getBoundingClientRect();
 
1723   return [e.clientX - rect.left - container.clientLeft, e.clientY - rect.top - container.clientTop];
 
1726 d3.touches = function(container, touches) {
 
1727   if (arguments.length < 2) touches = d3_eventSource().touches;
 
1728   return touches ? d3_array(touches).map(function(touch) {
 
1729     var point = d3_mousePoint(container, touch);
 
1730     point.identifier = touch.identifier;
 
1740     d3_radians = π / 180,
 
1741     d3_degrees = 180 / π;
 
1743 function d3_sgn(x) {
 
1744   return x > 0 ? 1 : x < 0 ? -1 : 0;
 
1747 // Returns the 2D cross product of AB and AC vectors, i.e., the z-component of
 
1748 // the 3D cross product in a quadrant I Cartesian coordinate system (+x is
 
1749 // right, +y is up). Returns a positive value if ABC is counter-clockwise,
 
1750 // negative if clockwise, and zero if the points are collinear.
 
1751 function d3_cross2d(a, b, c) {
 
1752   return (b[0] - a[0]) * (c[1] - a[1]) - (b[1] - a[1]) * (c[0] - a[0]);
 
1755 function d3_acos(x) {
 
1756   return x > 1 ? 0 : x < -1 ? π : Math.acos(x);
 
1759 function d3_asin(x) {
 
1760   return x > 1 ? halfπ : x < -1 ? -halfπ : Math.asin(x);
 
1763 function d3_sinh(x) {
 
1764   return ((x = Math.exp(x)) - 1 / x) / 2;
 
1767 function d3_cosh(x) {
 
1768   return ((x = Math.exp(x)) + 1 / x) / 2;
 
1771 function d3_tanh(x) {
 
1772   return ((x = Math.exp(2 * x)) - 1) / (x + 1);
 
1775 function d3_haversin(x) {
 
1776   return (x = Math.sin(x / 2)) * x;
 
1783 // p0 = [ux0, uy0, w0]
 
1784 // p1 = [ux1, uy1, w1]
 
1785 d3.interpolateZoom = function(p0, p1) {
 
1786   var ux0 = p0[0], uy0 = p0[1], w0 = p0[2],
 
1787       ux1 = p1[0], uy1 = p1[1], w1 = p1[2];
 
1791       d2 = dx * dx + dy * dy,
 
1793       b0 = (w1 * w1 - w0 * w0 + ρ4 * d2) / (2 * w0 * ρ2 * d1),
 
1794       b1 = (w1 * w1 - w0 * w0 - ρ4 * d2) / (2 * w1 * ρ2 * d1),
 
1795       r0 = Math.log(Math.sqrt(b0 * b0 + 1) - b0),
 
1796       r1 = Math.log(Math.sqrt(b1 * b1 + 1) - b1),
 
1798       S = (dr || Math.log(w1 / w0)) / ρ;
 
1800   function interpolate(t) {
 
1804       var coshr0 = d3_cosh(r0),
 
1805           u = w0 / (ρ2 * d1) * (coshr0 * d3_tanh(ρ * s + r0) - d3_sinh(r0));
 
1809         w0 * coshr0 / d3_cosh(ρ * s + r0)
 
1812     // Special case for u0 ~= u1.
 
1816       w0 * Math.exp(ρ * s)
 
1820   interpolate.duration = S * 1000;
 
1825 d3.behavior.zoom = function() {
 
1826   var view = {x: 0, y: 0, k: 1},
 
1827       translate0, // translate when we started zooming (to avoid drift)
 
1828       center0, // implicit desired position of translate0 after zooming
 
1829       center, // explicit desired position of translate0 after zooming
 
1830       size = [960, 500], // viewport size; required for zoom interpolation
 
1831       scaleExtent = d3_behavior_zoomInfinity,
 
1834       mousedown = "mousedown.zoom",
 
1835       mousemove = "mousemove.zoom",
 
1836       mouseup = "mouseup.zoom",
 
1838       touchstart = "touchstart.zoom",
 
1839       touchtime, // time of last touchstart (to detect double-tap)
 
1840       event = d3_eventDispatch(zoom, "zoomstart", "zoom", "zoomend"),
 
1846   // Lazily determine the DOM’s support for Wheel events.
 
1847   // https://developer.mozilla.org/en-US/docs/Mozilla_event_reference/wheel
 
1848   if (!d3_behavior_zoomWheel) {
 
1849     d3_behavior_zoomWheel = "onwheel" in d3_document ? (d3_behavior_zoomDelta = function() { return -d3.event.deltaY * (d3.event.deltaMode ? 120 : 1); }, "wheel")
 
1850         : "onmousewheel" in d3_document ? (d3_behavior_zoomDelta = function() { return d3.event.wheelDelta; }, "mousewheel")
 
1851         : (d3_behavior_zoomDelta = function() { return -d3.event.detail; }, "MozMousePixelScroll");
 
1855     g   .on(mousedown, mousedowned)
 
1856         .on(d3_behavior_zoomWheel + ".zoom", mousewheeled)
 
1857         .on("dblclick.zoom", dblclicked)
 
1858         .on(touchstart, touchstarted);
 
1861   zoom.event = function(g) {
 
1863       var dispatch = event.of(this, arguments),
 
1865       if (d3_transitionInheritId) {
 
1866         d3.select(this).transition()
 
1867             .each("start.zoom", function() {
 
1868               view = this.__chart__ || {x: 0, y: 0, k: 1}; // pre-transition state
 
1869               zoomstarted(dispatch);
 
1871             .tween("zoom:zoom", function() {
 
1874                   cx = center0 ? center0[0] : dx / 2,
 
1875                   cy = center0 ? center0[1] : dy / 2,
 
1876                   i = d3.interpolateZoom(
 
1877                     [(cx - view.x) / view.k, (cy - view.y) / view.k, dx / view.k],
 
1878                     [(cx - view1.x) / view1.k, (cy - view1.y) / view1.k, dx / view1.k]
 
1880               return function(t) {
 
1881                 var l = i(t), k = dx / l[2];
 
1882                 this.__chart__ = view = {x: cx - l[0] * k, y: cy - l[1] * k, k: k};
 
1886             .each("interrupt.zoom", function() {
 
1887               zoomended(dispatch);
 
1889             .each("end.zoom", function() {
 
1890               zoomended(dispatch);
 
1893         this.__chart__ = view;
 
1894         zoomstarted(dispatch);
 
1896         zoomended(dispatch);
 
1901   zoom.translate = function(_) {
 
1902     if (!arguments.length) return [view.x, view.y];
 
1903     view = {x: +_[0], y: +_[1], k: view.k}; // copy-on-write
 
1908   zoom.scale = function(_) {
 
1909     if (!arguments.length) return view.k;
 
1910     view = {x: view.x, y: view.y, k: +_}; // copy-on-write
 
1915   zoom.scaleExtent = function(_) {
 
1916     if (!arguments.length) return scaleExtent;
 
1917     scaleExtent = _ == null ? d3_behavior_zoomInfinity : [+_[0], +_[1]];
 
1921   zoom.center = function(_) {
 
1922     if (!arguments.length) return center;
 
1923     center = _ && [+_[0], +_[1]];
 
1927   zoom.size = function(_) {
 
1928     if (!arguments.length) return size;
 
1929     size = _ && [+_[0], +_[1]];
 
1933   zoom.duration = function(_) {
 
1934     if (!arguments.length) return duration;
 
1935     duration = +_; // TODO function based on interpolateZoom distance?
 
1939   zoom.x = function(z) {
 
1940     if (!arguments.length) return x1;
 
1943     view = {x: 0, y: 0, k: 1}; // copy-on-write
 
1947   zoom.y = function(z) {
 
1948     if (!arguments.length) return y1;
 
1951     view = {x: 0, y: 0, k: 1}; // copy-on-write
 
1955   function location(p) {
 
1956     return [(p[0] - view.x) / view.k, (p[1] - view.y) / view.k];
 
1960     return [l[0] * view.k + view.x, l[1] * view.k + view.y];
 
1963   function scaleTo(s) {
 
1964     view.k = Math.max(scaleExtent[0], Math.min(scaleExtent[1], s));
 
1967   function translateTo(p, l) {
 
1969     view.x += p[0] - l[0];
 
1970     view.y += p[1] - l[1];
 
1973   function zoomTo(that, p, l, k) {
 
1974     that.__chart__ = {x: view.x, y: view.y, k: view.k};
 
1976     scaleTo(Math.pow(2, k));
 
1977     translateTo(center0 = p, l);
 
1979     that = d3.select(that);
 
1980     if (duration > 0) that = that.transition().duration(duration);
 
1981     that.call(zoom.event);
 
1984   function rescale() {
 
1985     if (x1) x1.domain(x0.range().map(function(x) { return (x - view.x) / view.k; }).map(x0.invert));
 
1986     if (y1) y1.domain(y0.range().map(function(y) { return (y - view.y) / view.k; }).map(y0.invert));
 
1989   function zoomstarted(dispatch) {
 
1990     if (!zooming++) dispatch({type: "zoomstart"});
 
1993   function zoomed(dispatch) {
 
1995     dispatch({type: "zoom", scale: view.k, translate: [view.x, view.y]});
 
1998   function zoomended(dispatch) {
 
1999     if (!--zooming) dispatch({type: "zoomend"});
 
2003   function mousedowned() {
 
2005         target = d3.event.target,
 
2006         dispatch = event.of(that, arguments),
 
2008         subject = d3.select(d3_window(that)).on(mousemove, moved).on(mouseup, ended),
 
2009         location0 = location(d3.mouse(that)),
 
2010         dragRestore = d3_event_dragSuppress(that);
 
2012     d3_selection_interrupt.call(that);
 
2013     zoomstarted(dispatch);
 
2017       translateTo(d3.mouse(that), location0);
 
2022       subject.on(mousemove, null).on(mouseup, null);
 
2023       dragRestore(dragged && d3.event.target === target);
 
2024       zoomended(dispatch);
 
2028   // These closures persist for as long as at least one touch is active.
 
2029   function touchstarted() {
 
2031         dispatch = event.of(that, arguments),
 
2032         locations0 = {}, // touchstart locations
 
2033         distance0 = 0, // distance² between initial touches
 
2034         scale0, // scale when we started touching
 
2035         zoomName = ".zoom-" + d3.event.changedTouches[0].identifier,
 
2036         touchmove = "touchmove" + zoomName,
 
2037         touchend = "touchend" + zoomName,
 
2039         subject = d3.select(that),
 
2040         dragRestore = d3_event_dragSuppress(that);
 
2043     zoomstarted(dispatch);
 
2045     // Workaround for Chrome issue 412723: the touchstart listener must be set
 
2046     // after the touchmove listener.
 
2047     subject.on(mousedown, null).on(touchstart, started); // prevent duplicate events
 
2049     // Updates locations of any touches in locations0.
 
2050     function relocate() {
 
2051       var touches = d3.touches(that);
 
2053       touches.forEach(function(t) {
 
2054         if (t.identifier in locations0) locations0[t.identifier] = location(t);
 
2059     // Temporarily override touchstart while gesture is active.
 
2060     function started() {
 
2062       // Listen for touchmove and touchend on the target of touchstart.
 
2063       var target = d3.event.target;
 
2064       d3.select(target).on(touchmove, moved).on(touchend, ended);
 
2065       targets.push(target);
 
2067       // Only track touches started on the same subject element.
 
2068       var changed = d3.event.changedTouches;
 
2069       for (var i = 0, n = changed.length; i < n; ++i) {
 
2070         locations0[changed[i].identifier] = null;
 
2073       var touches = relocate(),
 
2076       if (touches.length === 1) {
 
2077         if (now - touchtime < 500) { // dbltap
 
2079           zoomTo(that, p, locations0[p.identifier], Math.floor(Math.log(view.k) / Math.LN2) + 1);
 
2080           d3_eventPreventDefault();
 
2083       } else if (touches.length > 1) {
 
2084         var p = touches[0], q = touches[1],
 
2085             dx = p[0] - q[0], dy = p[1] - q[1];
 
2086         distance0 = dx * dx + dy * dy;
 
2091       var touches = d3.touches(that),
 
2095       d3_selection_interrupt.call(that);
 
2097       for (var i = 0, n = touches.length; i < n; ++i, l1 = null) {
 
2099         if (l1 = locations0[p1.identifier]) {
 
2106         var distance1 = (distance1 = p1[0] - p0[0]) * distance1 + (distance1 = p1[1] - p0[1]) * distance1,
 
2107             scale1 = distance0 && Math.sqrt(distance1 / distance0);
 
2108         p0 = [(p0[0] + p1[0]) / 2, (p0[1] + p1[1]) / 2];
 
2109         l0 = [(l0[0] + l1[0]) / 2, (l0[1] + l1[1]) / 2];
 
2110         scaleTo(scale1 * scale0);
 
2114       translateTo(p0, l0);
 
2119       // If there are any globally-active touches remaining, remove the ended
 
2120       // touches from locations0.
 
2121       if (d3.event.touches.length) {
 
2122         var changed = d3.event.changedTouches;
 
2123         for (var i = 0, n = changed.length; i < n; ++i) {
 
2124           delete locations0[changed[i].identifier];
 
2126         // If locations0 is not empty, then relocate and continue listening for
 
2127         // touchmove and touchend.
 
2128         for (var identifier in locations0) {
 
2129           return void relocate(); // locations may have detached due to rotation
 
2132       // Otherwise, remove touchmove and touchend listeners.
 
2133       d3.selectAll(targets).on(zoomName, null);
 
2134       subject.on(mousedown, mousedowned).on(touchstart, touchstarted);
 
2136       zoomended(dispatch);
 
2140   function mousewheeled() {
 
2141     var dispatch = event.of(this, arguments);
 
2142     if (mousewheelTimer) clearTimeout(mousewheelTimer);
 
2143     else translate0 = location(center0 = center || d3.mouse(this)), d3_selection_interrupt.call(this), zoomstarted(dispatch);
 
2144     mousewheelTimer = setTimeout(function() { mousewheelTimer = null; zoomended(dispatch); }, 50);
 
2145     d3_eventPreventDefault();
 
2146     scaleTo(Math.pow(2, d3_behavior_zoomDelta() * .002) * view.k);
 
2147     translateTo(center0, translate0);
 
2151   function dblclicked() {
 
2152     var p = d3.mouse(this),
 
2153         k = Math.log(view.k) / Math.LN2;
 
2155     zoomTo(this, p, location(p), d3.event.shiftKey ? Math.ceil(k) - 1 : Math.floor(k) + 1);
 
2158   return d3.rebind(zoom, event, "on");
 
2161 var d3_behavior_zoomInfinity = [0, Infinity], // default scale extent
 
2162     d3_behavior_zoomDelta, // initialized lazily
 
2163     d3_behavior_zoomWheel;
 
2164 function d3_functor(v) {
 
2165   return typeof v === "function" ? v : function() { return v; };
 
2168 d3.functor = d3_functor;
 
2170 d3.touch = function(container, touches, identifier) {
 
2171   if (arguments.length < 3) identifier = touches, touches = d3_eventSource().changedTouches;
 
2172   if (touches) for (var i = 0, n = touches.length, touch; i < n; ++i) {
 
2173     if ((touch = touches[i]).identifier === identifier) {
 
2174       return d3_mousePoint(container, touch);
 
2179 var d3_timer_queueHead,
 
2181     d3_timer_interval, // is an interval (or frame) active?
 
2182     d3_timer_timeout, // is a timeout active?
 
2183     d3_timer_active, // active timer object
 
2184     d3_timer_frame = this[d3_vendorSymbol(this, "requestAnimationFrame")] || function(callback) { setTimeout(callback, 17); };
 
2186 // The timer will continue to fire until callback returns true.
 
2187 d3.timer = function(callback, delay, then) {
 
2188   var n = arguments.length;
 
2189   if (n < 2) delay = 0;
 
2190   if (n < 3) then = Date.now();
 
2192   // Add the callback to the tail of the queue.
 
2193   var time = then + delay, timer = {c: callback, t: time, f: false, n: null};
 
2194   if (d3_timer_queueTail) d3_timer_queueTail.n = timer;
 
2195   else d3_timer_queueHead = timer;
 
2196   d3_timer_queueTail = timer;
 
2199   if (!d3_timer_interval) {
 
2200     d3_timer_timeout = clearTimeout(d3_timer_timeout);
 
2201     d3_timer_interval = 1;
 
2202     d3_timer_frame(d3_timer_step);
 
2206 function d3_timer_step() {
 
2207   var now = d3_timer_mark(),
 
2208       delay = d3_timer_sweep() - now;
 
2210     if (isFinite(delay)) {
 
2211       clearTimeout(d3_timer_timeout);
 
2212       d3_timer_timeout = setTimeout(d3_timer_step, delay);
 
2214     d3_timer_interval = 0;
 
2216     d3_timer_interval = 1;
 
2217     d3_timer_frame(d3_timer_step);
 
2221 d3.timer.flush = function() {
 
2226 function d3_timer_mark() {
 
2227   var now = Date.now();
 
2228   d3_timer_active = d3_timer_queueHead;
 
2229   while (d3_timer_active) {
 
2230     if (now >= d3_timer_active.t) d3_timer_active.f = d3_timer_active.c(now - d3_timer_active.t);
 
2231     d3_timer_active = d3_timer_active.n;
 
2236 // Flush after callbacks to avoid concurrent queue modification.
 
2237 // Returns the time of the earliest active timer, post-sweep.
 
2238 function d3_timer_sweep() {
 
2240       t1 = d3_timer_queueHead,
 
2244       t1 = t0 ? t0.n = t1.n : d3_timer_queueHead = t1.n;
 
2246       if (t1.t < time) time = t1.t;
 
2250   d3_timer_queueTail = t0;
 
2255 d3.geo.stream = function(object, listener) {
 
2256   if (object && d3_geo_streamObjectType.hasOwnProperty(object.type)) {
 
2257     d3_geo_streamObjectType[object.type](object, listener);
 
2259     d3_geo_streamGeometry(object, listener);
 
2263 function d3_geo_streamGeometry(geometry, listener) {
 
2264   if (geometry && d3_geo_streamGeometryType.hasOwnProperty(geometry.type)) {
 
2265     d3_geo_streamGeometryType[geometry.type](geometry, listener);
 
2269 var d3_geo_streamObjectType = {
 
2270   Feature: function(feature, listener) {
 
2271     d3_geo_streamGeometry(feature.geometry, listener);
 
2273   FeatureCollection: function(object, listener) {
 
2274     var features = object.features, i = -1, n = features.length;
 
2275     while (++i < n) d3_geo_streamGeometry(features[i].geometry, listener);
 
2279 var d3_geo_streamGeometryType = {
 
2280   Sphere: function(object, listener) {
 
2283   Point: function(object, listener) {
 
2284     object = object.coordinates;
 
2285     listener.point(object[0], object[1], object[2]);
 
2287   MultiPoint: function(object, listener) {
 
2288     var coordinates = object.coordinates, i = -1, n = coordinates.length;
 
2289     while (++i < n) object = coordinates[i], listener.point(object[0], object[1], object[2]);
 
2291   LineString: function(object, listener) {
 
2292     d3_geo_streamLine(object.coordinates, listener, 0);
 
2294   MultiLineString: function(object, listener) {
 
2295     var coordinates = object.coordinates, i = -1, n = coordinates.length;
 
2296     while (++i < n) d3_geo_streamLine(coordinates[i], listener, 0);
 
2298   Polygon: function(object, listener) {
 
2299     d3_geo_streamPolygon(object.coordinates, listener);
 
2301   MultiPolygon: function(object, listener) {
 
2302     var coordinates = object.coordinates, i = -1, n = coordinates.length;
 
2303     while (++i < n) d3_geo_streamPolygon(coordinates[i], listener);
 
2305   GeometryCollection: function(object, listener) {
 
2306     var geometries = object.geometries, i = -1, n = geometries.length;
 
2307     while (++i < n) d3_geo_streamGeometry(geometries[i], listener);
 
2311 function d3_geo_streamLine(coordinates, listener, closed) {
 
2312   var i = -1, n = coordinates.length - closed, coordinate;
 
2313   listener.lineStart();
 
2314   while (++i < n) coordinate = coordinates[i], listener.point(coordinate[0], coordinate[1], coordinate[2]);
 
2318 function d3_geo_streamPolygon(coordinates, listener) {
 
2319   var i = -1, n = coordinates.length;
 
2320   listener.polygonStart();
 
2321   while (++i < n) d3_geo_streamLine(coordinates[i], listener, 1);
 
2322   listener.polygonEnd();
 
2325 d3.geo.length = function(object) {
 
2326   d3_geo_lengthSum = 0;
 
2327   d3.geo.stream(object, d3_geo_length);
 
2328   return d3_geo_lengthSum;
 
2331 var d3_geo_lengthSum;
 
2333 var d3_geo_length = {
 
2336   lineStart: d3_geo_lengthLineStart,
 
2338   polygonStart: d3_noop,
 
2342 function d3_geo_lengthLineStart() {
 
2343   var λ0, sinφ0, cosφ0;
 
2345   d3_geo_length.point = function(λ, φ) {
 
2346     λ0 = λ * d3_radians, sinφ0 = Math.sin(φ *= d3_radians), cosφ0 = Math.cos(φ);
 
2347     d3_geo_length.point = nextPoint;
 
2350   d3_geo_length.lineEnd = function() {
 
2351     d3_geo_length.point = d3_geo_length.lineEnd = d3_noop;
 
2354   function nextPoint(λ, φ) {
 
2355     var sinφ = Math.sin(φ *= d3_radians),
 
2357         t = abs((λ *= d3_radians) - λ0),
 
2358         cosΔλ = Math.cos(t);
 
2359     d3_geo_lengthSum += Math.atan2(Math.sqrt((t = cosφ * Math.sin(t)) * t + (t = cosφ0 * sinφ - sinφ0 * cosφ * cosΔλ) * t), sinφ0 * sinφ + cosφ0 * cosφ * cosΔλ);
 
2360     λ0 = λ, sinφ0 = sinφ, cosφ0 = cosφ;
 
2363 function d3_identity(d) {
 
2366 function d3_true() {
 
2370 function d3_geo_spherical(cartesian) {
 
2372     Math.atan2(cartesian[1], cartesian[0]),
 
2373     d3_asin(cartesian[2])
 
2377 function d3_geo_sphericalEqual(a, b) {
 
2378   return abs(a[0] - b[0]) < ε && abs(a[1] - b[1]) < ε;
 
2381 // General spherical polygon clipping algorithm: takes a polygon, cuts it into
 
2382 // visible line segments and rejoins the segments by interpolating along the
 
2384 function d3_geo_clipPolygon(segments, compare, clipStartInside, interpolate, listener) {
 
2388   segments.forEach(function(segment) {
 
2389     if ((n = segment.length - 1) <= 0) return;
 
2390     var n, p0 = segment[0], p1 = segment[n];
 
2392     // If the first and last points of a segment are coincident, then treat as
 
2394     // TODO if all rings are closed, then the winding order of the exterior
 
2395     // ring should be checked.
 
2396     if (d3_geo_sphericalEqual(p0, p1)) {
 
2397       listener.lineStart();
 
2398       for (var i = 0; i < n; ++i) listener.point((p0 = segment[i])[0], p0[1]);
 
2403     var a = new d3_geo_clipPolygonIntersection(p0, segment, null, true),
 
2404         b = new d3_geo_clipPolygonIntersection(p0, null, a, false);
 
2408     a = new d3_geo_clipPolygonIntersection(p1, segment, null, false);
 
2409     b = new d3_geo_clipPolygonIntersection(p1, null, a, true);
 
2415   d3_geo_clipPolygonLinkCircular(subject);
 
2416   d3_geo_clipPolygonLinkCircular(clip);
 
2417   if (!subject.length) return;
 
2419   for (var i = 0, entry = clipStartInside, n = clip.length; i < n; ++i) {
 
2420     clip[i].e = entry = !entry;
 
2423   var start = subject[0],
 
2427     // Find first unvisited intersection.
 
2428     var current = start,
 
2430     while (current.v) if ((current = current.n) === start) return;
 
2432     listener.lineStart();
 
2434       current.v = current.o.v = true;
 
2437           for (var i = 0, n = points.length; i < n; ++i) listener.point((point = points[i])[0], point[1]);
 
2439           interpolate(current.x, current.n.x, 1, listener);
 
2441         current = current.n;
 
2444           points = current.p.z;
 
2445           for (var i = points.length - 1; i >= 0; --i) listener.point((point = points[i])[0], point[1]);
 
2447           interpolate(current.x, current.p.x, -1, listener);
 
2449         current = current.p;
 
2451       current = current.o;
 
2453       isSubject = !isSubject;
 
2454     } while (!current.v);
 
2459 function d3_geo_clipPolygonLinkCircular(array) {
 
2460   if (!(n = array.length)) return;
 
2474 function d3_geo_clipPolygonIntersection(point, points, other, entry) {
 
2477   this.o = other; // another intersection
 
2478   this.e = entry; // is an entry?
 
2479   this.v = false; // visited
 
2480   this.n = this.p = null; // next & previous
 
2483 function d3_geo_clip(pointVisible, clipLine, interpolate, clipStart) {
 
2484   return function(rotate, listener) {
 
2485     var line = clipLine(listener),
 
2486         rotatedClipStart = rotate.invert(clipStart[0], clipStart[1]);
 
2490       lineStart: lineStart,
 
2492       polygonStart: function() {
 
2493         clip.point = pointRing;
 
2494         clip.lineStart = ringStart;
 
2495         clip.lineEnd = ringEnd;
 
2499       polygonEnd: function() {
 
2501         clip.lineStart = lineStart;
 
2502         clip.lineEnd = lineEnd;
 
2504         segments = d3.merge(segments);
 
2505         var clipStartInside = d3_geo_pointInPolygon(rotatedClipStart, polygon);
 
2506         if (segments.length) {
 
2507           if (!polygonStarted) listener.polygonStart(), polygonStarted = true;
 
2508           d3_geo_clipPolygon(segments, d3_geo_clipSort, clipStartInside, interpolate, listener);
 
2509         } else if (clipStartInside) {
 
2510           if (!polygonStarted) listener.polygonStart(), polygonStarted = true;
 
2511           listener.lineStart();
 
2512           interpolate(null, null, 1, listener);
 
2515         if (polygonStarted) listener.polygonEnd(), polygonStarted = false;
 
2516         segments = polygon = null;
 
2518       sphere: function() {
 
2519         listener.polygonStart();
 
2520         listener.lineStart();
 
2521         interpolate(null, null, 1, listener);
 
2523         listener.polygonEnd();
 
2527     function point(λ, φ) {
 
2528       var point = rotate(λ, φ);
 
2529       if (pointVisible(λ = point[0], φ = point[1])) listener.point(λ, φ);
 
2531     function pointLine(λ, φ) {
 
2532       var point = rotate(λ, φ);
 
2533       line.point(point[0], point[1]);
 
2535     function lineStart() { clip.point = pointLine; line.lineStart(); }
 
2536     function lineEnd() { clip.point = point; line.lineEnd(); }
 
2540     var buffer = d3_geo_clipBufferListener(),
 
2541         ringListener = clipLine(buffer),
 
2542         polygonStarted = false,
 
2546     function pointRing(λ, φ) {
 
2548       var point = rotate(λ, φ);
 
2549       ringListener.point(point[0], point[1]);
 
2552     function ringStart() {
 
2553       ringListener.lineStart();
 
2557     function ringEnd() {
 
2558       pointRing(ring[0][0], ring[0][1]);
 
2559       ringListener.lineEnd();
 
2561       var clean = ringListener.clean(),
 
2562           ringSegments = buffer.buffer(),
 
2564           n = ringSegments.length;
 
2572       // No intersections.
 
2574         segment = ringSegments[0];
 
2575         var n = segment.length - 1,
 
2579           if (!polygonStarted) listener.polygonStart(), polygonStarted = true;
 
2580           listener.lineStart();
 
2581           while (++i < n) listener.point((point = segment[i])[0], point[1]);
 
2587       // Rejoin connected segments.
 
2588       // TODO reuse bufferListener.rejoin()?
 
2589       if (n > 1 && clean & 2) ringSegments.push(ringSegments.pop().concat(ringSegments.shift()));
 
2591       segments.push(ringSegments.filter(d3_geo_clipSegmentLength1));
 
2598 function d3_geo_clipSegmentLength1(segment) {
 
2599   return segment.length > 1;
 
2602 function d3_geo_clipBufferListener() {
 
2606     lineStart: function() { lines.push(line = []); },
 
2607     point: function(λ, φ) { line.push([λ, φ]); },
 
2609     buffer: function() {
 
2615     rejoin: function() {
 
2616       if (lines.length > 1) lines.push(lines.pop().concat(lines.shift()));
 
2621 // Intersection points are sorted along the clip edge. For both antimeridian
 
2622 // cutting and circle clipping, the same comparison is used.
 
2623 function d3_geo_clipSort(a, b) {
 
2624   return ((a = a.x)[0] < 0 ? a[1] - halfπ - ε : halfπ - a[1])
 
2625        - ((b = b.x)[0] < 0 ? b[1] - halfπ - ε : halfπ - b[1]);
 
2628 var d3_geo_clipAntimeridian = d3_geo_clip(
 
2630     d3_geo_clipAntimeridianLine,
 
2631     d3_geo_clipAntimeridianInterpolate,
 
2634 // Takes a line and cuts into visible segments. Return values:
 
2635 //   0: there were intersections or the line was empty.
 
2636 //   1: no intersections.
 
2637 //   2: there were intersections, and the first and last segments should be
 
2639 function d3_geo_clipAntimeridianLine(listener) {
 
2643       clean; // no intersections
 
2646     lineStart: function() {
 
2647       listener.lineStart();
 
2650     point: function(λ1, φ1) {
 
2651       var sλ1 = λ1 > 0 ? π : -π,
 
2653       if (abs(dλ - π) < ε) { // line crosses a pole
 
2654         listener.point(λ0, φ0 = (φ0 + φ1) / 2 > 0 ? halfπ : -halfπ);
 
2655         listener.point(sλ0, φ0);
 
2657         listener.lineStart();
 
2658         listener.point(sλ1, φ0);
 
2659         listener.point(λ1, φ0);
 
2661       } else if (sλ0 !== sλ1 && dλ >= π) { // line crosses antimeridian
 
2662         // handle degeneracies
 
2663         if (abs(λ0 - sλ0) < ε) λ0 -= sλ0 * ε;
 
2664         if (abs(λ1 - sλ1) < ε) λ1 -= sλ1 * ε;
 
2665         φ0 = d3_geo_clipAntimeridianIntersect(λ0, φ0, λ1, φ1);
 
2666         listener.point(sλ0, φ0);
 
2668         listener.lineStart();
 
2669         listener.point(sλ1, φ0);
 
2672       listener.point(λ0 = λ1, φ0 = φ1);
 
2675     lineEnd: function() {
 
2679     // if there are intersections, we always rejoin the first and last segments.
 
2680     clean: function() { return 2 - clean; }
 
2684 function d3_geo_clipAntimeridianIntersect(λ0, φ0, λ1, φ1) {
 
2687       sinλ0_λ1 = Math.sin(λ0 - λ1);
 
2688   return abs(sinλ0_λ1) > ε
 
2689       ? Math.atan((Math.sin(φ0) * (cosφ1 = Math.cos(φ1)) * Math.sin(λ1)
 
2690                  - Math.sin(φ1) * (cosφ0 = Math.cos(φ0)) * Math.sin(λ0))
 
2691                  / (cosφ0 * cosφ1 * sinλ0_λ1))
 
2695 function d3_geo_clipAntimeridianInterpolate(from, to, direction, listener) {
 
2698     φ = direction * halfπ;
 
2699     listener.point(-π,  φ);
 
2700     listener.point( 0,  φ);
 
2701     listener.point( π,  φ);
 
2702     listener.point( π,  0);
 
2703     listener.point( π, -φ);
 
2704     listener.point( 0, -φ);
 
2705     listener.point(-π, -φ);
 
2706     listener.point(-π,  0);
 
2707     listener.point(-π,  φ);
 
2708   } else if (abs(from[0] - to[0]) > ε) {
 
2709     var s = from[0] < to[0] ? π : -π;
 
2710     φ = direction * s / 2;
 
2711     listener.point(-s, φ);
 
2712     listener.point( 0, φ);
 
2713     listener.point( s, φ);
 
2715     listener.point(to[0], to[1]);
 
2719 // cross and scale return new vectors,
 
2720 // whereas add and normalize operate in-place
 
2722 function d3_geo_cartesian(spherical) {
 
2723   var λ = spherical[0],
 
2733 function d3_geo_cartesianDot(a, b) {
 
2734   return a[0] * b[0] + a[1] * b[1] + a[2] * b[2];
 
2737 function d3_geo_cartesianCross(a, b) {
 
2739     a[1] * b[2] - a[2] * b[1],
 
2740     a[2] * b[0] - a[0] * b[2],
 
2741     a[0] * b[1] - a[1] * b[0]
 
2745 function d3_geo_cartesianAdd(a, b) {
 
2751 function d3_geo_cartesianScale(vector, k) {
 
2759 function d3_geo_cartesianNormalize(d) {
 
2760   var l = Math.sqrt(d[0] * d[0] + d[1] * d[1] + d[2] * d[2]);
 
2765 function d3_geo_compose(a, b) {
 
2767   function compose(x, y) {
 
2768     return x = a(x, y), b(x[0], x[1]);
 
2771   if (a.invert && b.invert) compose.invert = function(x, y) {
 
2772     return x = b.invert(x, y), x && a.invert(x[0], x[1]);
 
2778 function d3_geo_equirectangular(λ, φ) {
 
2782 (d3.geo.equirectangular = function() {
 
2783   return d3_geo_projection(d3_geo_equirectangular);
 
2784 }).raw = d3_geo_equirectangular.invert = d3_geo_equirectangular;
 
2786 d3.geo.rotation = function(rotate) {
 
2787   rotate = d3_geo_rotation(rotate[0] % 360 * d3_radians, rotate[1] * d3_radians, rotate.length > 2 ? rotate[2] * d3_radians : 0);
 
2789   function forward(coordinates) {
 
2790     coordinates = rotate(coordinates[0] * d3_radians, coordinates[1] * d3_radians);
 
2791     return coordinates[0] *= d3_degrees, coordinates[1] *= d3_degrees, coordinates;
 
2794   forward.invert = function(coordinates) {
 
2795     coordinates = rotate.invert(coordinates[0] * d3_radians, coordinates[1] * d3_radians);
 
2796     return coordinates[0] *= d3_degrees, coordinates[1] *= d3_degrees, coordinates;
 
2802 function d3_geo_identityRotation(λ, φ) {
 
2803   return [λ > π ? λ - τ : λ < -π ? λ + τ : λ, φ];
 
2806 d3_geo_identityRotation.invert = d3_geo_equirectangular;
 
2808 // Note: |δλ| must be < 2π
 
2809 function d3_geo_rotation(δλ, δφ, δγ) {
 
2810   return δλ ? (δφ || δγ ? d3_geo_compose(d3_geo_rotationλ(δλ), d3_geo_rotationφγ(δφ, δγ))
 
2811     : d3_geo_rotationλ(δλ))
 
2812     : (δφ || δγ ? d3_geo_rotationφγ(δφ, δγ)
 
2813     : d3_geo_identityRotation);
 
2816 function d3_geo_forwardRotationλ(δλ) {
 
2817   return function(λ, φ) {
 
2818     return λ += δλ, [λ > π ? λ - τ : λ < -π ? λ + τ : λ, φ];
 
2822 function d3_geo_rotationλ(δλ) {
 
2823   var rotation = d3_geo_forwardRotationλ(δλ);
 
2824   rotation.invert = d3_geo_forwardRotationλ(-δλ);
 
2828 function d3_geo_rotationφγ(δφ, δγ) {
 
2829   var cosδφ = Math.cos(δφ),
 
2830       sinδφ = Math.sin(δφ),
 
2831       cosδγ = Math.cos(δγ),
 
2832       sinδγ = Math.sin(δγ);
 
2834   function rotation(λ, φ) {
 
2835     var cosφ = Math.cos(φ),
 
2836         x = Math.cos(λ) * cosφ,
 
2837         y = Math.sin(λ) * cosφ,
 
2839         k = z * cosδφ + x * sinδφ;
 
2841       Math.atan2(y * cosδγ - k * sinδγ, x * cosδφ - z * sinδφ),
 
2842       d3_asin(k * cosδγ + y * sinδγ)
 
2846   rotation.invert = function(λ, φ) {
 
2847     var cosφ = Math.cos(φ),
 
2848         x = Math.cos(λ) * cosφ,
 
2849         y = Math.sin(λ) * cosφ,
 
2851         k = z * cosδγ - y * sinδγ;
 
2853       Math.atan2(y * cosδγ + z * sinδγ, x * cosδφ + k * sinδφ),
 
2854       d3_asin(k * cosδφ - x * sinδφ)
 
2861 d3.geo.circle = function() {
 
2862   var origin = [0, 0],
 
2868     var center = typeof origin === "function" ? origin.apply(this, arguments) : origin,
 
2869         rotate = d3_geo_rotation(-center[0] * d3_radians, -center[1] * d3_radians, 0).invert,
 
2872     interpolate(null, null, 1, {
 
2873       point: function(x, y) {
 
2874         ring.push(x = rotate(x, y));
 
2875         x[0] *= d3_degrees, x[1] *= d3_degrees;
 
2879     return {type: "Polygon", coordinates: [ring]};
 
2882   circle.origin = function(x) {
 
2883     if (!arguments.length) return origin;
 
2888   circle.angle = function(x) {
 
2889     if (!arguments.length) return angle;
 
2890     interpolate = d3_geo_circleInterpolate((angle = +x) * d3_radians, precision * d3_radians);
 
2894   circle.precision = function(_) {
 
2895     if (!arguments.length) return precision;
 
2896     interpolate = d3_geo_circleInterpolate(angle * d3_radians, (precision = +_) * d3_radians);
 
2900   return circle.angle(90);
 
2903 // Interpolates along a circle centered at [0°, 0°], with a given radius and
 
2905 function d3_geo_circleInterpolate(radius, precision) {
 
2906   var cr = Math.cos(radius),
 
2907       sr = Math.sin(radius);
 
2908   return function(from, to, direction, listener) {
 
2909     var step = direction * precision;
 
2911       from = d3_geo_circleAngle(cr, from);
 
2912       to = d3_geo_circleAngle(cr, to);
 
2913       if (direction > 0 ? from < to: from > to) from += direction * τ;
 
2915       from = radius + direction * τ;
 
2916       to = radius - .5 * step;
 
2918     for (var point, t = from; direction > 0 ? t > to : t < to; t -= step) {
 
2919       listener.point((point = d3_geo_spherical([
 
2928 // Signed angle of a cartesian point relative to [cr, 0, 0].
 
2929 function d3_geo_circleAngle(cr, point) {
 
2930   var a = d3_geo_cartesian(point);
 
2932   d3_geo_cartesianNormalize(a);
 
2933   var angle = d3_acos(-a[1]);
 
2934   return ((-a[2] < 0 ? -angle : angle) + 2 * Math.PI - ε) % (2 * Math.PI);
 
2936 // Adds floating point numbers with twice the normal precision.
 
2937 // Reference: J. R. Shewchuk, Adaptive Precision Floating-Point Arithmetic and
 
2938 // Fast Robust Geometric Predicates, Discrete & Computational Geometry 18(3)
 
2940 // Code adapted from GeographicLib by Charles F. F. Karney,
 
2941 // http://geographiclib.sourceforge.net/
 
2942 // See lib/geographiclib/LICENSE for details.
 
2944 function d3_adder() {}
 
2946 d3_adder.prototype = {
 
2947   s: 0, // rounded value
 
2948   t: 0, // exact error
 
2950     d3_adderSum(y, this.t, d3_adderTemp);
 
2951     d3_adderSum(d3_adderTemp.s, this.s, this);
 
2952     if (this.s) this.t += d3_adderTemp.t;
 
2953     else this.s = d3_adderTemp.t;
 
2956     this.s = this.t = 0;
 
2958   valueOf: function() {
 
2963 var d3_adderTemp = new d3_adder;
 
2965 function d3_adderSum(a, b, o) {
 
2966   var x = o.s = a + b, // a + b
 
2967       bv = x - a, av = x - bv; // b_virtual & a_virtual
 
2968   o.t = (a - av) + (b - bv); // a_roundoff + b_roundoff
 
2971 d3.geo.area = function(object) {
 
2973   d3.geo.stream(object, d3_geo_area);
 
2974   return d3_geo_areaSum;
 
2978     d3_geo_areaRingSum = new d3_adder;
 
2981   sphere: function() { d3_geo_areaSum += 4 * π; },
 
2986   // Only count area for polygon rings.
 
2987   polygonStart: function() {
 
2988     d3_geo_areaRingSum.reset();
 
2989     d3_geo_area.lineStart = d3_geo_areaRingStart;
 
2991   polygonEnd: function() {
 
2992     var area = 2 * d3_geo_areaRingSum;
 
2993     d3_geo_areaSum += area < 0 ? 4 * π + area : area;
 
2994     d3_geo_area.lineStart = d3_geo_area.lineEnd = d3_geo_area.point = d3_noop;
 
2998 function d3_geo_areaRingStart() {
 
2999   var λ00, φ00, λ0, cosφ0, sinφ0; // start point and previous point
 
3001   // For the first point, …
 
3002   d3_geo_area.point = function(λ, φ) {
 
3003     d3_geo_area.point = nextPoint;
 
3004     λ0 = (λ00 = λ) * d3_radians, cosφ0 = Math.cos(φ = (φ00 = φ) * d3_radians / 2 + π / 4), sinφ0 = Math.sin(φ);
 
3007   // For subsequent points, …
 
3008   function nextPoint(λ, φ) {
 
3010     φ = φ * d3_radians / 2 + π / 4; // half the angular distance from south pole
 
3012     // Spherical excess E for a spherical triangle with vertices: south pole,
 
3013     // previous point, current point.  Uses a formula derived from Cagnoli’s
 
3014     // theorem.  See Todhunter, Spherical Trig. (1871), Sec. 103, Eq. (2).
 
3016         sdλ = dλ >= 0 ? 1 : -1,
 
3021         u = cosφ0 * cosφ + k * Math.cos(adλ),
 
3022         v = k * sdλ * Math.sin(adλ);
 
3023     d3_geo_areaRingSum.add(Math.atan2(v, u));
 
3025     // Advance the previous points.
 
3026     λ0 = λ, cosφ0 = cosφ, sinφ0 = sinφ;
 
3029   // For the last point, return to the start.
 
3030   d3_geo_area.lineEnd = function() {
 
3031     nextPoint(λ00, φ00);
 
3035 function d3_geo_pointInPolygon(point, polygon) {
 
3036   var meridian = point[0],
 
3037       parallel = point[1],
 
3038       meridianNormal = [Math.sin(meridian), -Math.cos(meridian), 0],
 
3041   d3_geo_areaRingSum.reset();
 
3043   for (var i = 0, n = polygon.length; i < n; ++i) {
 
3044     var ring = polygon[i],
 
3047     var point0 = ring[0],
 
3049         φ0 = point0[1] / 2 + π / 4,
 
3050         sinφ0 = Math.sin(φ0),
 
3051         cosφ0 = Math.cos(φ0),
 
3058           φ = point[1] / 2 + π / 4,
 
3062           sdλ = dλ >= 0 ? 1 : -1,
 
3064           antimeridian = adλ > π,
 
3066       d3_geo_areaRingSum.add(Math.atan2(k * sdλ * Math.sin(adλ), cosφ0 * cosφ + k * Math.cos(adλ)));
 
3068       polarAngle += antimeridian ? dλ + sdλ * τ : dλ;
 
3070       // Are the longitudes either side of the point's meridian, and are the
 
3071       // latitudes smaller than the parallel?
 
3072       if (antimeridian ^ λ0 >= meridian ^ λ >= meridian) {
 
3073         var arc = d3_geo_cartesianCross(d3_geo_cartesian(point0), d3_geo_cartesian(point));
 
3074         d3_geo_cartesianNormalize(arc);
 
3075         var intersection = d3_geo_cartesianCross(meridianNormal, arc);
 
3076         d3_geo_cartesianNormalize(intersection);
 
3077         var φarc = (antimeridian ^ dλ >= 0 ? -1 : 1) * d3_asin(intersection[2]);
 
3078         if (parallel > φarc || parallel === φarc && (arc[0] || arc[1])) {
 
3079           winding += antimeridian ^ dλ >= 0 ? 1 : -1;
 
3083       λ0 = λ, sinφ0 = sinφ, cosφ0 = cosφ, point0 = point;
 
3087   // First, determine whether the South pole is inside or outside:
 
3090   // * the polygon winds around it in a clockwise direction.
 
3091   // * the polygon does not (cumulatively) wind around it, but has a negative
 
3092   //   (counter-clockwise) area.
 
3094   // Second, count the (signed) number of times a segment crosses a meridian
 
3095   // from the point to the South pole.  If it is zero, then the point is the
 
3096   // same side as the South pole.
 
3098   return (polarAngle < -ε || polarAngle < ε && d3_geo_areaRingSum < 0) ^ (winding & 1);
 
3101 // Clip features against a small circle centered at [0°, 0°].
 
3102 function d3_geo_clipCircle(radius) {
 
3103   var cr = Math.cos(radius),
 
3104       smallRadius = cr > 0,
 
3105       notHemisphere = abs(cr) > ε, // TODO optimise for this common case
 
3106       interpolate = d3_geo_circleInterpolate(radius, 6 * d3_radians);
 
3108   return d3_geo_clip(visible, clipLine, interpolate, smallRadius ? [0, -radius] : [-π, radius - π]);
 
3110   function visible(λ, φ) {
 
3111     return Math.cos(λ) * Math.cos(φ) > cr;
 
3114   // Takes a line and cuts into visible segments. Return values used for
 
3115   // polygon clipping:
 
3116   //   0: there were intersections or the line was empty.
 
3117   //   1: no intersections.
 
3118   //   2: there were intersections, and the first and last segments should be
 
3120   function clipLine(listener) {
 
3121     var point0, // previous point
 
3122         c0, // code for previous point
 
3123         v0, // visibility of previous point
 
3124         v00, // visibility of first point
 
3125         clean; // no intersections
 
3127       lineStart: function() {
 
3131       point: function(λ, φ) {
 
3132         var point1 = [λ, φ],
 
3136               ? v ? 0 : code(λ, φ)
 
3137               : v ? code(λ + (λ < 0 ? π : -π), φ) : 0;
 
3138         if (!point0 && (v00 = v0 = v)) listener.lineStart();
 
3139         // Handle degeneracies.
 
3140         // TODO ignore if not clipping polygons.
 
3142           point2 = intersect(point0, point1);
 
3143           if (d3_geo_sphericalEqual(point0, point2) || d3_geo_sphericalEqual(point1, point2)) {
 
3146             v = visible(point1[0], point1[1]);
 
3153             listener.lineStart();
 
3154             point2 = intersect(point1, point0);
 
3155             listener.point(point2[0], point2[1]);
 
3158             point2 = intersect(point0, point1);
 
3159             listener.point(point2[0], point2[1]);
 
3163         } else if (notHemisphere && point0 && smallRadius ^ v) {
 
3165           // If the codes for two points are different, or are both zero,
 
3166           // and there this segment intersects with the small circle.
 
3167           if (!(c & c0) && (t = intersect(point1, point0, true))) {
 
3170               listener.lineStart();
 
3171               listener.point(t[0][0], t[0][1]);
 
3172               listener.point(t[1][0], t[1][1]);
 
3175               listener.point(t[1][0], t[1][1]);
 
3177               listener.lineStart();
 
3178               listener.point(t[0][0], t[0][1]);
 
3182         if (v && (!point0 || !d3_geo_sphericalEqual(point0, point1))) {
 
3183           listener.point(point1[0], point1[1]);
 
3185         point0 = point1, v0 = v, c0 = c;
 
3187       lineEnd: function() {
 
3188         if (v0) listener.lineEnd();
 
3191       // Rejoin first and last segments if there were intersections and the first
 
3192       // and last points were visible.
 
3193       clean: function() { return clean | ((v00 && v0) << 1); }
 
3197   // Intersects the great circle between a and b with the clip circle.
 
3198   function intersect(a, b, two) {
 
3199     var pa = d3_geo_cartesian(a),
 
3200         pb = d3_geo_cartesian(b);
 
3202     // We have two planes, n1.p = d1 and n2.p = d2.
 
3203     // Find intersection line p(t) = c1 n1 + c2 n2 + t (n1 ⨯ n2).
 
3204     var n1 = [1, 0, 0], // normal
 
3205         n2 = d3_geo_cartesianCross(pa, pb),
 
3206         n2n2 = d3_geo_cartesianDot(n2, n2),
 
3207         n1n2 = n2[0], // d3_geo_cartesianDot(n1, n2),
 
3208         determinant = n2n2 - n1n2 * n1n2;
 
3210     // Two polar points.
 
3211     if (!determinant) return !two && a;
 
3213     var c1 =  cr * n2n2 / determinant,
 
3214         c2 = -cr * n1n2 / determinant,
 
3215         n1xn2 = d3_geo_cartesianCross(n1, n2),
 
3216         A = d3_geo_cartesianScale(n1, c1),
 
3217         B = d3_geo_cartesianScale(n2, c2);
 
3218     d3_geo_cartesianAdd(A, B);
 
3220     // Solve |p(t)|^2 = 1.
 
3222         w = d3_geo_cartesianDot(A, u),
 
3223         uu = d3_geo_cartesianDot(u, u),
 
3224         t2 = w * w - uu * (d3_geo_cartesianDot(A, A) - 1);
 
3228     var t = Math.sqrt(t2),
 
3229         q = d3_geo_cartesianScale(u, (-w - t) / uu);
 
3230     d3_geo_cartesianAdd(q, A);
 
3231     q = d3_geo_spherical(q);
 
3234     // Two intersection points.
 
3240     if (λ1 < λ0) z = λ0, λ0 = λ1, λ1 = z;
 
3242         polar = abs(δλ - π) < ε,
 
3243         meridian = polar || δλ < ε;
 
3245     if (!polar && φ1 < φ0) z = φ0, φ0 = φ1, φ1 = z;
 
3247     // Check that the first point is between a and b.
 
3250           ? φ0 + φ1 > 0 ^ q[1] < (abs(q[0] - λ0) < ε ? φ0 : φ1)
 
3251           : φ0 <= q[1] && q[1] <= φ1
 
3252         : δλ > π ^ (λ0 <= q[0] && q[0] <= λ1)) {
 
3253       var q1 = d3_geo_cartesianScale(u, (-w + t) / uu);
 
3254       d3_geo_cartesianAdd(q1, A);
 
3255       return [q, d3_geo_spherical(q1)];
 
3259   // Generates a 4-bit vector representing the location of a point relative to
 
3260   // the small circle's bounding box.
 
3261   function code(λ, φ) {
 
3262     var r = smallRadius ? radius : π - radius,
 
3264     if (λ < -r) code |= 1; // left
 
3265     else if (λ > r) code |= 2; // right
 
3266     if (φ < -r) code |= 4; // below
 
3267     else if (φ > r) code |= 8; // above
 
3272 // Liang–Barsky line clipping.
 
3273 function d3_geom_clipLine(x0, y0, x1, y1) {
 
3274   return function(line) {
 
3288     if (!dx && r > 0) return;
 
3293     } else if (dx > 0) {
 
3299     if (!dx && r < 0) return;
 
3304     } else if (dx > 0) {
 
3310     if (!dy && r > 0) return;
 
3315     } else if (dy > 0) {
 
3321     if (!dy && r < 0) return;
 
3326     } else if (dy > 0) {
 
3331     if (t0 > 0) line.a = {x: ax + t0 * dx, y: ay + t0 * dy};
 
3332     if (t1 < 1) line.b = {x: ax + t1 * dx, y: ay + t1 * dy};
 
3337 var d3_geo_clipExtentMAX = 1e9;
 
3339 d3.geo.clipExtent = function() {
 
3344         stream: function(output) {
 
3345           if (stream) stream.valid = false;
 
3346           stream = clip(output);
 
3347           stream.valid = true; // allow caching by d3.geo.path
 
3350         extent: function(_) {
 
3351           if (!arguments.length) return [[x0, y0], [x1, y1]];
 
3352           clip = d3_geo_clipExtent(x0 = +_[0][0], y0 = +_[0][1], x1 = +_[1][0], y1 = +_[1][1]);
 
3353           if (stream) stream.valid = false, stream = null;
 
3357   return clipExtent.extent([[0, 0], [960, 500]]);
 
3360 function d3_geo_clipExtent(x0, y0, x1, y1) {
 
3361   return function(listener) {
 
3362     var listener_ = listener,
 
3363         bufferListener = d3_geo_clipBufferListener(),
 
3364         clipLine = d3_geom_clipLine(x0, y0, x1, y1),
 
3371       lineStart: lineStart,
 
3373       polygonStart: function() {
 
3374         listener = bufferListener;
 
3379       polygonEnd: function() {
 
3380         listener = listener_;
 
3381         segments = d3.merge(segments);
 
3382         var clipStartInside = insidePolygon([x0, y1]),
 
3383             inside = clean && clipStartInside,
 
3384             visible = segments.length;
 
3385         if (inside || visible) {
 
3386           listener.polygonStart();
 
3388             listener.lineStart();
 
3389             interpolate(null, null, 1, listener);
 
3393             d3_geo_clipPolygon(segments, compare, clipStartInside, interpolate, listener);
 
3395           listener.polygonEnd();
 
3397         segments = polygon = ring = null;
 
3401     function insidePolygon(p) {
 
3402       var wn = 0, // the winding number counter
 
3406       for (var i = 0; i < n; ++i) {
 
3407         for (var j = 1, v = polygon[i], m = v.length, a = v[0], b; j < m; ++j) {
 
3410             if (b[1] >  y && d3_cross2d(a, b, p) > 0) ++wn;
 
3412             if (b[1] <= y && d3_cross2d(a, b, p) < 0) --wn;
 
3420     function interpolate(from, to, direction, listener) {
 
3423           (a = corner(from, direction)) !== (a1 = corner(to, direction)) ||
 
3424           comparePoints(from, to) < 0 ^ direction > 0) {
 
3426           listener.point(a === 0 || a === 3 ? x0 : x1, a > 1 ? y1 : y0);
 
3427         } while ((a = (a + direction + 4) % 4) !== a1);
 
3429         listener.point(to[0], to[1]);
 
3433     function pointVisible(x, y) {
 
3434       return x0 <= x && x <= x1 && y0 <= y && y <= y1;
 
3437     function point(x, y) {
 
3438       if (pointVisible(x, y)) listener.point(x, y);
 
3441     var x__, y__, v__, // first point
 
3442         x_, y_, v_, // previous point
 
3446     function lineStart() {
 
3447       clip.point = linePoint;
 
3448       if (polygon) polygon.push(ring = []);
 
3454     function lineEnd() {
 
3455       // TODO rather than special-case polygons, simply handle them separately.
 
3456       // Ideally, coincident intersection points should be jittered to avoid
 
3459         linePoint(x__, y__);
 
3460         if (v__ && v_) bufferListener.rejoin();
 
3461         segments.push(bufferListener.buffer());
 
3464       if (v_) listener.lineEnd();
 
3467     function linePoint(x, y) {
 
3468       x = Math.max(-d3_geo_clipExtentMAX, Math.min(d3_geo_clipExtentMAX, x));
 
3469       y = Math.max(-d3_geo_clipExtentMAX, Math.min(d3_geo_clipExtentMAX, y));
 
3470       var v = pointVisible(x, y);
 
3471       if (polygon) ring.push([x, y]);
 
3473         x__ = x, y__ = y, v__ = v;
 
3476           listener.lineStart();
 
3477           listener.point(x, y);
 
3480         if (v && v_) listener.point(x, y);
 
3482           var l = {a: {x: x_, y: y_}, b: {x: x, y: y}};
 
3485               listener.lineStart();
 
3486               listener.point(l.a.x, l.a.y);
 
3488             listener.point(l.b.x, l.b.y);
 
3489             if (!v) listener.lineEnd();
 
3492             listener.lineStart();
 
3493             listener.point(x, y);
 
3498       x_ = x, y_ = y, v_ = v;
 
3504   function corner(p, direction) {
 
3505     return abs(p[0] - x0) < ε ? direction > 0 ? 0 : 3
 
3506         : abs(p[0] - x1) < ε ? direction > 0 ? 2 : 1
 
3507         : abs(p[1] - y0) < ε ? direction > 0 ? 1 : 0
 
3508         : direction > 0 ? 3 : 2; // abs(p[1] - y1) < ε
 
3511   function compare(a, b) {
 
3512     return comparePoints(a.x, b.x);
 
3515   function comparePoints(a, b) {
 
3516     var ca = corner(a, 1),
 
3518     return ca !== cb ? ca - cb
 
3519         : ca === 0 ? b[1] - a[1]
 
3520         : ca === 1 ? a[0] - b[0]
 
3521         : ca === 2 ? a[1] - b[1]
 
3526 function d3_geo_conic(projectAt) {
 
3529       m = d3_geo_projectionMutator(projectAt),
 
3532   p.parallels = function(_) {
 
3533     if (!arguments.length) return [φ0 / π * 180, φ1 / π * 180];
 
3534     return m(φ0 = _[0] * π / 180, φ1 = _[1] * π / 180);
 
3540 function d3_geo_conicEqualArea(φ0, φ1) {
 
3541   var sinφ0 = Math.sin(φ0),
 
3542       n = (sinφ0 + Math.sin(φ1)) / 2,
 
3543       C = 1 + sinφ0 * (2 * n - sinφ0),
 
3544       ρ0 = Math.sqrt(C) / n;
 
3546   function forward(λ, φ) {
 
3547     var ρ = Math.sqrt(C - 2 * n * Math.sin(φ)) / n;
 
3549       ρ * Math.sin(λ *= n),
 
3550       ρ0 - ρ * Math.cos(λ)
 
3554   forward.invert = function(x, y) {
 
3557       Math.atan2(x, ρ0_y) / n,
 
3558       d3_asin((C - (x * x + ρ0_y * ρ0_y) * n * n) / (2 * n))
 
3565 (d3.geo.conicEqualArea = function() {
 
3566   return d3_geo_conic(d3_geo_conicEqualArea);
 
3567 }).raw = d3_geo_conicEqualArea;
 
3570 d3.geo.albers = function() {
 
3571   return d3.geo.conicEqualArea()
 
3573       .center([-.6, 38.7])
 
3574       .parallels([29.5, 45.5])
 
3578 // A composite projection for the United States, configured by default for
 
3579 // 960×500. Also works quite well at 960×600 with scale 1285. The set of
 
3580 // standard parallels for each region comes from USGS, which is published here:
 
3581 // http://egsc.usgs.gov/isb/pubs/MapProjections/projections.html#albers
 
3582 d3.geo.albersUsa = function() {
 
3583   var lower48 = d3.geo.albers();
 
3586   var alaska = d3.geo.conicEqualArea()
 
3589       .parallels([55, 65]);
 
3592   var hawaii = d3.geo.conicEqualArea()
 
3595       .parallels([8, 18]);
 
3598       pointStream = {point: function(x, y) { point = [x, y]; }},
 
3603   function albersUsa(coordinates) {
 
3604     var x = coordinates[0], y = coordinates[1];
 
3606     (lower48Point(x, y), point)
 
3607         || (alaskaPoint(x, y), point)
 
3608         || hawaiiPoint(x, y);
 
3612   albersUsa.invert = function(coordinates) {
 
3613     var k = lower48.scale(),
 
3614         t = lower48.translate(),
 
3615         x = (coordinates[0] - t[0]) / k,
 
3616         y = (coordinates[1] - t[1]) / k;
 
3617     return (y >= .120 && y < .234 && x >= -.425 && x < -.214 ? alaska
 
3618         : y >= .166 && y < .234 && x >= -.214 && x < -.115 ? hawaii
 
3619         : lower48).invert(coordinates);
 
3622   // A naïve multi-projection stream.
 
3623   // The projections must have mutually exclusive clip regions on the sphere,
 
3624   // as this will avoid emitting interleaving lines and polygons.
 
3625   albersUsa.stream = function(stream) {
 
3626     var lower48Stream = lower48.stream(stream),
 
3627         alaskaStream = alaska.stream(stream),
 
3628         hawaiiStream = hawaii.stream(stream);
 
3630       point: function(x, y) {
 
3631         lower48Stream.point(x, y);
 
3632         alaskaStream.point(x, y);
 
3633         hawaiiStream.point(x, y);
 
3635       sphere: function() {
 
3636         lower48Stream.sphere();
 
3637         alaskaStream.sphere();
 
3638         hawaiiStream.sphere();
 
3640       lineStart: function() {
 
3641         lower48Stream.lineStart();
 
3642         alaskaStream.lineStart();
 
3643         hawaiiStream.lineStart();
 
3645       lineEnd: function() {
 
3646         lower48Stream.lineEnd();
 
3647         alaskaStream.lineEnd();
 
3648         hawaiiStream.lineEnd();
 
3650       polygonStart: function() {
 
3651         lower48Stream.polygonStart();
 
3652         alaskaStream.polygonStart();
 
3653         hawaiiStream.polygonStart();
 
3655       polygonEnd: function() {
 
3656         lower48Stream.polygonEnd();
 
3657         alaskaStream.polygonEnd();
 
3658         hawaiiStream.polygonEnd();
 
3663   albersUsa.precision = function(_) {
 
3664     if (!arguments.length) return lower48.precision();
 
3665     lower48.precision(_);
 
3666     alaska.precision(_);
 
3667     hawaii.precision(_);
 
3671   albersUsa.scale = function(_) {
 
3672     if (!arguments.length) return lower48.scale();
 
3674     alaska.scale(_ * .35);
 
3676     return albersUsa.translate(lower48.translate());
 
3679   albersUsa.translate = function(_) {
 
3680     if (!arguments.length) return lower48.translate();
 
3681     var k = lower48.scale(), x = +_[0], y = +_[1];
 
3683     lower48Point = lower48
 
3685         .clipExtent([[x - .455 * k, y - .238 * k], [x + .455 * k, y + .238 * k]])
 
3686         .stream(pointStream).point;
 
3688     alaskaPoint = alaska
 
3689         .translate([x - .307 * k, y + .201 * k])
 
3690         .clipExtent([[x - .425 * k + ε, y + .120 * k + ε], [x - .214 * k - ε, y + .234 * k - ε]])
 
3691         .stream(pointStream).point;
 
3693     hawaiiPoint = hawaii
 
3694         .translate([x - .205 * k, y + .212 * k])
 
3695         .clipExtent([[x - .214 * k + ε, y + .166 * k + ε], [x - .115 * k - ε, y + .234 * k - ε]])
 
3696         .stream(pointStream).point;
 
3701   return albersUsa.scale(1070);
 
3704 d3.geo.bounds = (function() {
 
3705   var λ0, φ0, λ1, φ1, // bounds
 
3706       λ_, // previous λ-coordinate
 
3707       λ__, φ__, // first point
 
3708       p0, // previous 3D point
 
3715     lineStart: lineStart,
 
3718     polygonStart: function() {
 
3719       bound.point = ringPoint;
 
3720       bound.lineStart = ringStart;
 
3721       bound.lineEnd = ringEnd;
 
3723       d3_geo_area.polygonStart();
 
3725     polygonEnd: function() {
 
3726       d3_geo_area.polygonEnd();
 
3727       bound.point = point;
 
3728       bound.lineStart = lineStart;
 
3729       bound.lineEnd = lineEnd;
 
3730       if (d3_geo_areaRingSum < 0) λ0 = -(λ1 = 180), φ0 = -(φ1 = 90);
 
3731       else if (dλSum > ε) φ1 = 90;
 
3732       else if (dλSum < -ε) φ0 = -90;
 
3733       range[0] = λ0, range[1] = λ1;
 
3737   function point(λ, φ) {
 
3738     ranges.push(range = [λ0 = λ, λ1 = λ]);
 
3743   function linePoint(λ, φ) {
 
3744     var p = d3_geo_cartesian([λ * d3_radians, φ * d3_radians]);
 
3746       var normal = d3_geo_cartesianCross(p0, p),
 
3747           equatorial = [normal[1], -normal[0], 0],
 
3748           inflection = d3_geo_cartesianCross(equatorial, normal);
 
3749       d3_geo_cartesianNormalize(inflection);
 
3750       inflection = d3_geo_spherical(inflection);
 
3752           s = dλ > 0 ? 1 : -1,
 
3753           λi = inflection[0] * d3_degrees * s,
 
3754           antimeridian = abs(dλ) > 180;
 
3755       if (antimeridian ^ (s * λ_ < λi && λi < s * λ)) {
 
3756         var φi = inflection[1] * d3_degrees;
 
3757         if (φi > φ1) φ1 = φi;
 
3758       } else if (λi = (λi + 360) % 360 - 180, antimeridian ^ (s * λ_ < λi && λi < s * λ)) {
 
3759         var φi = -inflection[1] * d3_degrees;
 
3760         if (φi < φ0) φ0 = φi;
 
3767           if (angle(λ0, λ) > angle(λ0, λ1)) λ1 = λ;
 
3769           if (angle(λ, λ1) > angle(λ0, λ1)) λ0 = λ;
 
3777             if (angle(λ0, λ) > angle(λ0, λ1)) λ1 = λ;
 
3779             if (angle(λ, λ1) > angle(λ0, λ1)) λ0 = λ;
 
3789   function lineStart() { bound.point = linePoint; }
 
3790   function lineEnd() {
 
3791     range[0] = λ0, range[1] = λ1;
 
3792     bound.point = point;
 
3796   function ringPoint(λ, φ) {
 
3799       dλSum += abs(dλ) > 180 ? dλ + (dλ > 0 ? 360 : -360) : dλ;
 
3800     } else λ__ = λ, φ__ = φ;
 
3801     d3_geo_area.point(λ, φ);
 
3805   function ringStart() {
 
3806     d3_geo_area.lineStart();
 
3809   function ringEnd() {
 
3810     ringPoint(λ__, φ__);
 
3811     d3_geo_area.lineEnd();
 
3812     if (abs(dλSum) > ε) λ0 = -(λ1 = 180);
 
3813     range[0] = λ0, range[1] = λ1;
 
3817   // Finds the left-right distance between two longitudes.
 
3818   // This is almost the same as (λ1 - λ0 + 360°) % 360°, except that we want
 
3819   // the distance between ±180° to be 360°.
 
3820   function angle(λ0, λ1) { return (λ1 -= λ0) < 0 ? λ1 + 360 : λ1; }
 
3822   function compareRanges(a, b) { return a[0] - b[0]; }
 
3824   function withinRange(x, range) {
 
3825     return range[0] <= range[1] ? range[0] <= x && x <= range[1] : x < range[0] || range[1] < x;
 
3828   return function(feature) {
 
3829     φ1 = λ1 = -(λ0 = φ0 = Infinity);
 
3832     d3.geo.stream(feature, bound);
 
3834     var n = ranges.length;
 
3836       // First, sort ranges by their minimum longitudes.
 
3837       ranges.sort(compareRanges);
 
3839       // Then, merge any ranges that overlap.
 
3840       for (var i = 1, a = ranges[0], b, merged = [a]; i < n; ++i) {
 
3842         if (withinRange(b[0], a) || withinRange(b[1], a)) {
 
3843           if (angle(a[0], b[1]) > angle(a[0], a[1])) a[1] = b[1];
 
3844           if (angle(b[0], a[1]) > angle(a[0], a[1])) a[0] = b[0];
 
3850       // Finally, find the largest gap between the merged ranges.
 
3851       // The final bounding box will be the inverse of this gap.
 
3852       var best = -Infinity, dλ;
 
3853       for (var n = merged.length - 1, i = 0, a = merged[n], b; i <= n; a = b, ++i) {
 
3855         if ((dλ = angle(a[1], b[0])) > best) best = dλ, λ0 = b[0], λ1 = a[1];
 
3858     ranges = range = null;
 
3860     return λ0 === Infinity || φ0 === Infinity
 
3861         ? [[NaN, NaN], [NaN, NaN]]
 
3862         : [[λ0, φ0], [λ1, φ1]];
 
3866 d3.geo.centroid = function(object) {
 
3867   d3_geo_centroidW0 = d3_geo_centroidW1 =
 
3868   d3_geo_centroidX0 = d3_geo_centroidY0 = d3_geo_centroidZ0 =
 
3869   d3_geo_centroidX1 = d3_geo_centroidY1 = d3_geo_centroidZ1 =
 
3870   d3_geo_centroidX2 = d3_geo_centroidY2 = d3_geo_centroidZ2 = 0;
 
3871   d3.geo.stream(object, d3_geo_centroid);
 
3873   var x = d3_geo_centroidX2,
 
3874       y = d3_geo_centroidY2,
 
3875       z = d3_geo_centroidZ2,
 
3876       m = x * x + y * y + z * z;
 
3878   // If the area-weighted centroid is undefined, fall back to length-weighted centroid.
 
3880     x = d3_geo_centroidX1, y = d3_geo_centroidY1, z = d3_geo_centroidZ1;
 
3881     // If the feature has zero length, fall back to arithmetic mean of point vectors.
 
3882     if (d3_geo_centroidW1 < ε) x = d3_geo_centroidX0, y = d3_geo_centroidY0, z = d3_geo_centroidZ0;
 
3883     m = x * x + y * y + z * z;
 
3884     // If the feature still has an undefined centroid, then return.
 
3885     if (m < ε2) return [NaN, NaN];
 
3888   return [Math.atan2(y, x) * d3_degrees, d3_asin(z / Math.sqrt(m)) * d3_degrees];
 
3891 var d3_geo_centroidW0,
 
3903 var d3_geo_centroid = {
 
3905   point: d3_geo_centroidPoint,
 
3906   lineStart: d3_geo_centroidLineStart,
 
3907   lineEnd: d3_geo_centroidLineEnd,
 
3908   polygonStart: function() {
 
3909     d3_geo_centroid.lineStart = d3_geo_centroidRingStart;
 
3911   polygonEnd: function() {
 
3912     d3_geo_centroid.lineStart = d3_geo_centroidLineStart;
 
3916 // Arithmetic mean of Cartesian vectors.
 
3917 function d3_geo_centroidPoint(λ, φ) {
 
3919   var cosφ = Math.cos(φ *= d3_radians);
 
3920   d3_geo_centroidPointXYZ(cosφ * Math.cos(λ), cosφ * Math.sin(λ), Math.sin(φ));
 
3923 function d3_geo_centroidPointXYZ(x, y, z) {
 
3924   ++d3_geo_centroidW0;
 
3925   d3_geo_centroidX0 += (x - d3_geo_centroidX0) / d3_geo_centroidW0;
 
3926   d3_geo_centroidY0 += (y - d3_geo_centroidY0) / d3_geo_centroidW0;
 
3927   d3_geo_centroidZ0 += (z - d3_geo_centroidZ0) / d3_geo_centroidW0;
 
3930 function d3_geo_centroidLineStart() {
 
3931   var x0, y0, z0; // previous point
 
3933   d3_geo_centroid.point = function(λ, φ) {
 
3935     var cosφ = Math.cos(φ *= d3_radians);
 
3936     x0 = cosφ * Math.cos(λ);
 
3937     y0 = cosφ * Math.sin(λ);
 
3939     d3_geo_centroid.point = nextPoint;
 
3940     d3_geo_centroidPointXYZ(x0, y0, z0);
 
3943   function nextPoint(λ, φ) {
 
3945     var cosφ = Math.cos(φ *= d3_radians),
 
3946         x = cosφ * Math.cos(λ),
 
3947         y = cosφ * Math.sin(λ),
 
3950           Math.sqrt((w = y0 * z - z0 * y) * w + (w = z0 * x - x0 * z) * w + (w = x0 * y - y0 * x) * w),
 
3951           x0 * x + y0 * y + z0 * z);
 
3952     d3_geo_centroidW1 += w;
 
3953     d3_geo_centroidX1 += w * (x0 + (x0 = x));
 
3954     d3_geo_centroidY1 += w * (y0 + (y0 = y));
 
3955     d3_geo_centroidZ1 += w * (z0 + (z0 = z));
 
3956     d3_geo_centroidPointXYZ(x0, y0, z0);
 
3960 function d3_geo_centroidLineEnd() {
 
3961   d3_geo_centroid.point = d3_geo_centroidPoint;
 
3964 // See J. E. Brock, The Inertia Tensor for a Spherical Triangle,
 
3965 // J. Applied Mechanics 42, 239 (1975).
 
3966 function d3_geo_centroidRingStart() {
 
3967   var λ00, φ00, // first point
 
3968       x0, y0, z0; // previous point
 
3970   d3_geo_centroid.point = function(λ, φ) {
 
3972     d3_geo_centroid.point = nextPoint;
 
3974     var cosφ = Math.cos(φ *= d3_radians);
 
3975     x0 = cosφ * Math.cos(λ);
 
3976     y0 = cosφ * Math.sin(λ);
 
3978     d3_geo_centroidPointXYZ(x0, y0, z0);
 
3981   d3_geo_centroid.lineEnd = function() {
 
3982     nextPoint(λ00, φ00);
 
3983     d3_geo_centroid.lineEnd = d3_geo_centroidLineEnd;
 
3984     d3_geo_centroid.point = d3_geo_centroidPoint;
 
3987   function nextPoint(λ, φ) {
 
3989     var cosφ = Math.cos(φ *= d3_radians),
 
3990         x = cosφ * Math.cos(λ),
 
3991         y = cosφ * Math.sin(λ),
 
3993         cx = y0 * z - z0 * y,
 
3994         cy = z0 * x - x0 * z,
 
3995         cz = x0 * y - y0 * x,
 
3996         m = Math.sqrt(cx * cx + cy * cy + cz * cz),
 
3997         u = x0 * x + y0 * y + z0 * z,
 
3998         v = m && -d3_acos(u) / m, // area weight
 
3999         w = Math.atan2(m, u); // line weight
 
4000     d3_geo_centroidX2 += v * cx;
 
4001     d3_geo_centroidY2 += v * cy;
 
4002     d3_geo_centroidZ2 += v * cz;
 
4003     d3_geo_centroidW1 += w;
 
4004     d3_geo_centroidX1 += w * (x0 + (x0 = x));
 
4005     d3_geo_centroidY1 += w * (y0 + (y0 = y));
 
4006     d3_geo_centroidZ1 += w * (z0 + (z0 = z));
 
4007     d3_geo_centroidPointXYZ(x0, y0, z0);
 
4011 // TODO Unify this code with d3.geom.polygon area?
 
4013 var d3_geo_pathAreaSum, d3_geo_pathAreaPolygon, d3_geo_pathArea = {
 
4018   // Only count area for polygon rings.
 
4019   polygonStart: function() {
 
4020     d3_geo_pathAreaPolygon = 0;
 
4021     d3_geo_pathArea.lineStart = d3_geo_pathAreaRingStart;
 
4023   polygonEnd: function() {
 
4024     d3_geo_pathArea.lineStart = d3_geo_pathArea.lineEnd = d3_geo_pathArea.point = d3_noop;
 
4025     d3_geo_pathAreaSum += abs(d3_geo_pathAreaPolygon / 2);
 
4029 function d3_geo_pathAreaRingStart() {
 
4030   var x00, y00, x0, y0;
 
4032   // For the first point, …
 
4033   d3_geo_pathArea.point = function(x, y) {
 
4034     d3_geo_pathArea.point = nextPoint;
 
4035     x00 = x0 = x, y00 = y0 = y;
 
4038   // For subsequent points, …
 
4039   function nextPoint(x, y) {
 
4040     d3_geo_pathAreaPolygon += y0 * x - x0 * y;
 
4044   // For the last point, return to the start.
 
4045   d3_geo_pathArea.lineEnd = function() {
 
4046     nextPoint(x00, y00);
 
4050 var d3_geo_pathBoundsX0,
 
4051     d3_geo_pathBoundsY0,
 
4052     d3_geo_pathBoundsX1,
 
4053     d3_geo_pathBoundsY1;
 
4055 var d3_geo_pathBounds = {
 
4056   point: d3_geo_pathBoundsPoint,
 
4059   polygonStart: d3_noop,
 
4063 function d3_geo_pathBoundsPoint(x, y) {
 
4064   if (x < d3_geo_pathBoundsX0) d3_geo_pathBoundsX0 = x;
 
4065   if (x > d3_geo_pathBoundsX1) d3_geo_pathBoundsX1 = x;
 
4066   if (y < d3_geo_pathBoundsY0) d3_geo_pathBoundsY0 = y;
 
4067   if (y > d3_geo_pathBoundsY1) d3_geo_pathBoundsY1 = y;
 
4069 function d3_geo_pathBuffer() {
 
4070   var pointCircle = d3_geo_pathBufferCircle(4.5),
 
4076     // While inside a line, override point to moveTo then lineTo.
 
4077     lineStart: function() { stream.point = pointLineStart; },
 
4080     // While inside a polygon, override lineEnd to closePath.
 
4081     polygonStart: function() { stream.lineEnd = lineEndPolygon; },
 
4082     polygonEnd: function() { stream.lineEnd = lineEnd; stream.point = point; },
 
4084     pointRadius: function(_) {
 
4085       pointCircle = d3_geo_pathBufferCircle(_);
 
4089     result: function() {
 
4090       if (buffer.length) {
 
4091         var result = buffer.join("");
 
4098   function point(x, y) {
 
4099     buffer.push("M", x, ",", y, pointCircle);
 
4102   function pointLineStart(x, y) {
 
4103     buffer.push("M", x, ",", y);
 
4104     stream.point = pointLine;
 
4107   function pointLine(x, y) {
 
4108     buffer.push("L", x, ",", y);
 
4111   function lineEnd() {
 
4112     stream.point = point;
 
4115   function lineEndPolygon() {
 
4122 function d3_geo_pathBufferCircle(radius) {
 
4123   return "m0," + radius
 
4124       + "a" + radius + "," + radius + " 0 1,1 0," + -2 * radius
 
4125       + "a" + radius + "," + radius + " 0 1,1 0," + 2 * radius
 
4129 // TODO Unify this code with d3.geom.polygon centroid?
 
4130 // TODO Enforce positive area for exterior, negative area for interior?
 
4132 var d3_geo_pathCentroid = {
 
4133   point: d3_geo_pathCentroidPoint,
 
4135   // For lines, weight by length.
 
4136   lineStart: d3_geo_pathCentroidLineStart,
 
4137   lineEnd: d3_geo_pathCentroidLineEnd,
 
4139   // For polygons, weight by area.
 
4140   polygonStart: function() {
 
4141     d3_geo_pathCentroid.lineStart = d3_geo_pathCentroidRingStart;
 
4143   polygonEnd: function() {
 
4144     d3_geo_pathCentroid.point = d3_geo_pathCentroidPoint;
 
4145     d3_geo_pathCentroid.lineStart = d3_geo_pathCentroidLineStart;
 
4146     d3_geo_pathCentroid.lineEnd = d3_geo_pathCentroidLineEnd;
 
4150 function d3_geo_pathCentroidPoint(x, y) {
 
4151   d3_geo_centroidX0 += x;
 
4152   d3_geo_centroidY0 += y;
 
4153   ++d3_geo_centroidZ0;
 
4156 function d3_geo_pathCentroidLineStart() {
 
4159   d3_geo_pathCentroid.point = function(x, y) {
 
4160     d3_geo_pathCentroid.point = nextPoint;
 
4161     d3_geo_pathCentroidPoint(x0 = x, y0 = y);
 
4164   function nextPoint(x, y) {
 
4165     var dx = x - x0, dy = y - y0, z = Math.sqrt(dx * dx + dy * dy);
 
4166     d3_geo_centroidX1 += z * (x0 + x) / 2;
 
4167     d3_geo_centroidY1 += z * (y0 + y) / 2;
 
4168     d3_geo_centroidZ1 += z;
 
4169     d3_geo_pathCentroidPoint(x0 = x, y0 = y);
 
4173 function d3_geo_pathCentroidLineEnd() {
 
4174   d3_geo_pathCentroid.point = d3_geo_pathCentroidPoint;
 
4177 function d3_geo_pathCentroidRingStart() {
 
4178   var x00, y00, x0, y0;
 
4180   // For the first point, …
 
4181   d3_geo_pathCentroid.point = function(x, y) {
 
4182     d3_geo_pathCentroid.point = nextPoint;
 
4183     d3_geo_pathCentroidPoint(x00 = x0 = x, y00 = y0 = y);
 
4186   // For subsequent points, …
 
4187   function nextPoint(x, y) {
 
4188     var dx = x - x0, dy = y - y0, z = Math.sqrt(dx * dx + dy * dy);
 
4189     d3_geo_centroidX1 += z * (x0 + x) / 2;
 
4190     d3_geo_centroidY1 += z * (y0 + y) / 2;
 
4191     d3_geo_centroidZ1 += z;
 
4193     z = y0 * x - x0 * y;
 
4194     d3_geo_centroidX2 += z * (x0 + x);
 
4195     d3_geo_centroidY2 += z * (y0 + y);
 
4196     d3_geo_centroidZ2 += z * 3;
 
4197     d3_geo_pathCentroidPoint(x0 = x, y0 = y);
 
4200   // For the last point, return to the start.
 
4201   d3_geo_pathCentroid.lineEnd = function() {
 
4202     nextPoint(x00, y00);
 
4206 function d3_geo_pathContext(context) {
 
4207   var pointRadius = 4.5;
 
4212     // While inside a line, override point to moveTo then lineTo.
 
4213     lineStart: function() { stream.point = pointLineStart; },
 
4216     // While inside a polygon, override lineEnd to closePath.
 
4217     polygonStart: function() { stream.lineEnd = lineEndPolygon; },
 
4218     polygonEnd: function() { stream.lineEnd = lineEnd; stream.point = point; },
 
4220     pointRadius: function(_) {
 
4228   function point(x, y) {
 
4229     context.moveTo(x + pointRadius, y);
 
4230     context.arc(x, y, pointRadius, 0, τ);
 
4233   function pointLineStart(x, y) {
 
4234     context.moveTo(x, y);
 
4235     stream.point = pointLine;
 
4238   function pointLine(x, y) {
 
4239     context.lineTo(x, y);
 
4242   function lineEnd() {
 
4243     stream.point = point;
 
4246   function lineEndPolygon() {
 
4247     context.closePath();
 
4253 function d3_geo_resample(project) {
 
4254   var δ2 = .5, // precision, px²
 
4255       cosMinDistance = Math.cos(30 * d3_radians), // cos(minimum angular distance)
 
4258   function resample(stream) {
 
4259     return (maxDepth ? resampleRecursive : resampleNone)(stream);
 
4262   function resampleNone(stream) {
 
4263     return d3_geo_transformPoint(stream, function(x, y) {
 
4265       stream.point(x[0], x[1]);
 
4269   function resampleRecursive(stream) {
 
4270     var λ00, φ00, x00, y00, a00, b00, c00, // first point
 
4271         λ0, x0, y0, a0, b0, c0; // previous point
 
4275       lineStart: lineStart,
 
4277       polygonStart: function() { stream.polygonStart(); resample.lineStart = ringStart; },
 
4278       polygonEnd: function() { stream.polygonEnd(); resample.lineStart = lineStart; }
 
4281     function point(x, y) {
 
4283       stream.point(x[0], x[1]);
 
4286     function lineStart() {
 
4288       resample.point = linePoint;
 
4292     function linePoint(λ, φ) {
 
4293       var c = d3_geo_cartesian([λ, φ]), p = project(λ, φ);
 
4294       resampleLineTo(x0, y0, λ0, a0, b0, c0, x0 = p[0], y0 = p[1], λ0 = λ, a0 = c[0], b0 = c[1], c0 = c[2], maxDepth, stream);
 
4295       stream.point(x0, y0);
 
4298     function lineEnd() {
 
4299       resample.point = point;
 
4303     function ringStart() {
 
4305       resample.point = ringPoint;
 
4306       resample.lineEnd = ringEnd;
 
4309     function ringPoint(λ, φ) {
 
4310       linePoint(λ00 = λ, φ00 = φ), x00 = x0, y00 = y0, a00 = a0, b00 = b0, c00 = c0;
 
4311       resample.point = linePoint;
 
4314     function ringEnd() {
 
4315       resampleLineTo(x0, y0, λ0, a0, b0, c0, x00, y00, λ00, a00, b00, c00, maxDepth, stream);
 
4316       resample.lineEnd = lineEnd;
 
4323   function resampleLineTo(x0, y0, λ0, a0, b0, c0, x1, y1, λ1, a1, b1, c1, depth, stream) {
 
4326         d2 = dx * dx + dy * dy;
 
4327     if (d2 > 4 * δ2 && depth--) {
 
4331           m = Math.sqrt(a * a + b * b + c * c),
 
4332           φ2 = Math.asin(c /= m),
 
4333           λ2 = abs(abs(c) - 1) < ε || abs(λ0 - λ1) < ε ? (λ0 + λ1) / 2 : Math.atan2(b, a),
 
4334           p = project(λ2, φ2),
 
4339           dz = dy * dx2 - dx * dy2;
 
4340       if (dz * dz / d2 > δ2 // perpendicular projected distance
 
4341           || abs((dx * dx2 + dy * dy2) / d2 - .5) > .3 // midpoint close to an end
 
4342           || a0 * a1 + b0 * b1 + c0 * c1 < cosMinDistance) { // angular distance
 
4343         resampleLineTo(x0, y0, λ0, a0, b0, c0, x2, y2, λ2, a /= m, b /= m, c, depth, stream);
 
4344         stream.point(x2, y2);
 
4345         resampleLineTo(x2, y2, λ2, a, b, c, x1, y1, λ1, a1, b1, c1, depth, stream);
 
4350   resample.precision = function(_) {
 
4351     if (!arguments.length) return Math.sqrt(δ2);
 
4352     maxDepth = (δ2 = _ * _) > 0 && 16;
 
4359 d3.geo.path = function() {
 
4360   var pointRadius = 4.5,
 
4367   function path(object) {
 
4369       if (typeof pointRadius === "function") contextStream.pointRadius(+pointRadius.apply(this, arguments));
 
4370       if (!cacheStream || !cacheStream.valid) cacheStream = projectStream(contextStream);
 
4371       d3.geo.stream(object, cacheStream);
 
4373     return contextStream.result();
 
4376   path.area = function(object) {
 
4377     d3_geo_pathAreaSum = 0;
 
4378     d3.geo.stream(object, projectStream(d3_geo_pathArea));
 
4379     return d3_geo_pathAreaSum;
 
4382   path.centroid = function(object) {
 
4383     d3_geo_centroidX0 = d3_geo_centroidY0 = d3_geo_centroidZ0 =
 
4384     d3_geo_centroidX1 = d3_geo_centroidY1 = d3_geo_centroidZ1 =
 
4385     d3_geo_centroidX2 = d3_geo_centroidY2 = d3_geo_centroidZ2 = 0;
 
4386     d3.geo.stream(object, projectStream(d3_geo_pathCentroid));
 
4387     return d3_geo_centroidZ2 ? [d3_geo_centroidX2 / d3_geo_centroidZ2, d3_geo_centroidY2 / d3_geo_centroidZ2]
 
4388         : d3_geo_centroidZ1 ? [d3_geo_centroidX1 / d3_geo_centroidZ1, d3_geo_centroidY1 / d3_geo_centroidZ1]
 
4389         : d3_geo_centroidZ0 ? [d3_geo_centroidX0 / d3_geo_centroidZ0, d3_geo_centroidY0 / d3_geo_centroidZ0]
 
4393   path.bounds = function(object) {
 
4394     d3_geo_pathBoundsX1 = d3_geo_pathBoundsY1 = -(d3_geo_pathBoundsX0 = d3_geo_pathBoundsY0 = Infinity);
 
4395     d3.geo.stream(object, projectStream(d3_geo_pathBounds));
 
4396     return [[d3_geo_pathBoundsX0, d3_geo_pathBoundsY0], [d3_geo_pathBoundsX1, d3_geo_pathBoundsY1]];
 
4399   path.projection = function(_) {
 
4400     if (!arguments.length) return projection;
 
4401     projectStream = (projection = _) ? _.stream || d3_geo_pathProjectStream(_) : d3_identity;
 
4405   path.context = function(_) {
 
4406     if (!arguments.length) return context;
 
4407     contextStream = (context = _) == null ? new d3_geo_pathBuffer : new d3_geo_pathContext(_);
 
4408     if (typeof pointRadius !== "function") contextStream.pointRadius(pointRadius);
 
4412   path.pointRadius = function(_) {
 
4413     if (!arguments.length) return pointRadius;
 
4414     pointRadius = typeof _ === "function" ? _ : (contextStream.pointRadius(+_), +_);
 
4423   return path.projection(d3.geo.albersUsa()).context(null);
 
4426 function d3_geo_pathProjectStream(project) {
 
4427   var resample = d3_geo_resample(function(x, y) { return project([x * d3_degrees, y * d3_degrees]); });
 
4428   return function(stream) { return d3_geo_projectionRadians(resample(stream)); };
 
4431 d3.geo.transform = function(methods) {
 
4433     stream: function(stream) {
 
4434       var transform = new d3_geo_transform(stream);
 
4435       for (var k in methods) transform[k] = methods[k];
 
4441 function d3_geo_transform(stream) {
 
4442   this.stream = stream;
 
4445 d3_geo_transform.prototype = {
 
4446   point: function(x, y) { this.stream.point(x, y); },
 
4447   sphere: function() { this.stream.sphere(); },
 
4448   lineStart: function() { this.stream.lineStart(); },
 
4449   lineEnd: function() { this.stream.lineEnd(); },
 
4450   polygonStart: function() { this.stream.polygonStart(); },
 
4451   polygonEnd: function() { this.stream.polygonEnd(); }
 
4454 function d3_geo_transformPoint(stream, point) {
 
4457     sphere: function() { stream.sphere(); },
 
4458     lineStart: function() { stream.lineStart(); },
 
4459     lineEnd: function() { stream.lineEnd(); },
 
4460     polygonStart: function() { stream.polygonStart(); },
 
4461     polygonEnd: function() { stream.polygonEnd(); },
 
4465 d3.geo.projection = d3_geo_projection;
 
4466 d3.geo.projectionMutator = d3_geo_projectionMutator;
 
4468 function d3_geo_projection(project) {
 
4469   return d3_geo_projectionMutator(function() { return project; })();
 
4472 function d3_geo_projectionMutator(projectAt) {
 
4476       projectResample = d3_geo_resample(function(x, y) { x = project(x, y); return [x[0] * k + δx, δy - x[1] * k]; }),
 
4478       x = 480, y = 250, // translate
 
4479       λ = 0, φ = 0, // center
 
4480       δλ = 0, δφ = 0, δγ = 0, // rotate
 
4482       preclip = d3_geo_clipAntimeridian,
 
4483       postclip = d3_identity,
 
4488   function projection(point) {
 
4489     point = projectRotate(point[0] * d3_radians, point[1] * d3_radians);
 
4490     return [point[0] * k + δx, δy - point[1] * k];
 
4493   function invert(point) {
 
4494     point = projectRotate.invert((point[0] - δx) / k, (δy - point[1]) / k);
 
4495     return point && [point[0] * d3_degrees, point[1] * d3_degrees];
 
4498   projection.stream = function(output) {
 
4499     if (stream) stream.valid = false;
 
4500     stream = d3_geo_projectionRadians(preclip(rotate, projectResample(postclip(output))));
 
4501     stream.valid = true; // allow caching by d3.geo.path
 
4505   projection.clipAngle = function(_) {
 
4506     if (!arguments.length) return clipAngle;
 
4507     preclip = _ == null ? (clipAngle = _, d3_geo_clipAntimeridian) : d3_geo_clipCircle((clipAngle = +_) * d3_radians);
 
4508     return invalidate();
 
4511   projection.clipExtent = function(_) {
 
4512     if (!arguments.length) return clipExtent;
 
4514     postclip = _ ? d3_geo_clipExtent(_[0][0], _[0][1], _[1][0], _[1][1]) : d3_identity;
 
4515     return invalidate();
 
4518   projection.scale = function(_) {
 
4519     if (!arguments.length) return k;
 
4524   projection.translate = function(_) {
 
4525     if (!arguments.length) return [x, y];
 
4531   projection.center = function(_) {
 
4532     if (!arguments.length) return [λ * d3_degrees, φ * d3_degrees];
 
4533     λ = _[0] % 360 * d3_radians;
 
4534     φ = _[1] % 360 * d3_radians;
 
4538   projection.rotate = function(_) {
 
4539     if (!arguments.length) return [δλ * d3_degrees, δφ * d3_degrees, δγ * d3_degrees];
 
4540     δλ = _[0] % 360 * d3_radians;
 
4541     δφ = _[1] % 360 * d3_radians;
 
4542     δγ = _.length > 2 ? _[2] % 360 * d3_radians : 0;
 
4546   d3.rebind(projection, projectResample, "precision");
 
4549     projectRotate = d3_geo_compose(rotate = d3_geo_rotation(δλ, δφ, δγ), project);
 
4550     var center = project(λ, φ);
 
4551     δx = x - center[0] * k;
 
4552     δy = y + center[1] * k;
 
4553     return invalidate();
 
4556   function invalidate() {
 
4557     if (stream) stream.valid = false, stream = null;
 
4562     project = projectAt.apply(this, arguments);
 
4563     projection.invert = project.invert && invert;
 
4568 function d3_geo_projectionRadians(stream) {
 
4569   return d3_geo_transformPoint(stream, function(x, y) {
 
4570     stream.point(x * d3_radians, y * d3_radians);
 
4574 function d3_geo_mercator(λ, φ) {
 
4575   return [λ, Math.log(Math.tan(π / 4 + φ / 2))];
 
4578 d3_geo_mercator.invert = function(x, y) {
 
4579   return [x, 2 * Math.atan(Math.exp(y)) - halfπ];
 
4582 function d3_geo_mercatorProjection(project) {
 
4583   var m = d3_geo_projection(project),
 
4585       translate = m.translate,
 
4586       clipExtent = m.clipExtent,
 
4589   m.scale = function() {
 
4590     var v = scale.apply(m, arguments);
 
4591     return v === m ? (clipAuto ? m.clipExtent(null) : m) : v;
 
4594   m.translate = function() {
 
4595     var v = translate.apply(m, arguments);
 
4596     return v === m ? (clipAuto ? m.clipExtent(null) : m) : v;
 
4599   m.clipExtent = function(_) {
 
4600     var v = clipExtent.apply(m, arguments);
 
4602       if (clipAuto = _ == null) {
 
4603         var k = π * scale(), t = translate();
 
4604         clipExtent([[t[0] - k, t[1] - k], [t[0] + k, t[1] + k]]);
 
4606     } else if (clipAuto) {
 
4612   return m.clipExtent(null);
 
4615 (d3.geo.mercator = function() {
 
4616   return d3_geo_mercatorProjection(d3_geo_mercator);
 
4617 }).raw = d3_geo_mercator;
 
4620 d3.geom.polygon = function(coordinates) {
 
4621   d3_subclass(coordinates, d3_geom_polygonPrototype);
 
4625 var d3_geom_polygonPrototype = d3.geom.polygon.prototype = [];
 
4627 d3_geom_polygonPrototype.area = function() {
 
4637     area += a[1] * b[0] - a[0] * b[1];
 
4643 d3_geom_polygonPrototype.centroid = function(k) {
 
4652   if (!arguments.length) k = -1 / (6 * this.area());
 
4657     c = a[0] * b[1] - b[0] * a[1];
 
4658     x += (a[0] + b[0]) * c;
 
4659     y += (a[1] + b[1]) * c;
 
4662   return [x * k, y * k];
 
4665 // The Sutherland-Hodgman clipping algorithm.
 
4666 // Note: requires the clip polygon to be counterclockwise and convex.
 
4667 d3_geom_polygonPrototype.clip = function(subject) {
 
4669       closed = d3_geom_polygonClosed(subject),
 
4671       n = this.length - d3_geom_polygonClosed(this),
 
4680     input = subject.slice();
 
4683     c = input[(m = input.length - closed) - 1];
 
4687       if (d3_geom_polygonInside(d, a, b)) {
 
4688         if (!d3_geom_polygonInside(c, a, b)) {
 
4689           subject.push(d3_geom_polygonIntersect(c, d, a, b));
 
4692       } else if (d3_geom_polygonInside(c, a, b)) {
 
4693         subject.push(d3_geom_polygonIntersect(c, d, a, b));
 
4697     if (closed) subject.push(subject[0]);
 
4704 function d3_geom_polygonInside(p, a, b) {
 
4705   return (b[0] - a[0]) * (p[1] - a[1]) < (b[1] - a[1]) * (p[0] - a[0]);
 
4708 // Intersect two infinite lines cd and ab.
 
4709 function d3_geom_polygonIntersect(c, d, a, b) {
 
4710   var x1 = c[0], x3 = a[0], x21 = d[0] - x1, x43 = b[0] - x3,
 
4711       y1 = c[1], y3 = a[1], y21 = d[1] - y1, y43 = b[1] - y3,
 
4712       ua = (x43 * (y1 - y3) - y43 * (x1 - x3)) / (y43 * x21 - x43 * y21);
 
4713   return [x1 + ua * x21, y1 + ua * y21];
 
4716 // Returns true if the polygon is closed.
 
4717 function d3_geom_polygonClosed(coordinates) {
 
4718   var a = coordinates[0],
 
4719       b = coordinates[coordinates.length - 1];
 
4720   return !(a[0] - b[0] || a[1] - b[1]);
 
4722 function d3_geom_pointX(d) {
 
4726 function d3_geom_pointY(d) {
 
4731  * Computes the 2D convex hull of a set of points using the monotone chain
 
4733  * http://en.wikibooks.org/wiki/Algorithm_Implementation/Geometry/Convex_hull/Monotone_chain)
 
4735  * The runtime of this algorithm is O(n log n), where n is the number of input
 
4736  * points. However in practice it outperforms other O(n log n) hulls.
 
4738  * @param vertices [[x1, y1], [x2, y2], ...]
 
4739  * @returns polygon [[x1, y1], [x2, y2], ...]
 
4741 d3.geom.hull = function(vertices) {
 
4742   var x = d3_geom_pointX,
 
4745   if (arguments.length) return hull(vertices);
 
4747   function hull(data) {
 
4748     // Hull of < 3 points is not well-defined
 
4749     if (data.length < 3) return [];
 
4751     var fx = d3_functor(x),
 
4755         points = [], // of the form [[x0, y0, 0], ..., [xn, yn, n]]
 
4758     for (i = 0 ; i < n; i++) {
 
4759       points.push([+fx.call(this, data[i], i), +fy.call(this, data[i], i), i]);
 
4762     // sort ascending by x-coord first, y-coord second
 
4763     points.sort(d3_geom_hullOrder);
 
4765     // we flip bottommost points across y axis so we can use the upper hull routine on both
 
4766     for (i = 0; i < n; i++) flippedPoints.push([points[i][0], -points[i][1]]);
 
4768     var upper = d3_geom_hullUpper(points),
 
4769         lower = d3_geom_hullUpper(flippedPoints);
 
4771     // construct the polygon, removing possible duplicate endpoints
 
4772     var skipLeft = lower[0] === upper[0],
 
4773         skipRight  = lower[lower.length - 1] === upper[upper.length - 1],
 
4776     // add upper hull in r->l order
 
4777     // then add lower hull in l->r order
 
4778     for (i = upper.length - 1; i >= 0; --i) polygon.push(data[points[upper[i]][2]]);
 
4779     for (i = +skipLeft; i < lower.length - skipRight; ++i) polygon.push(data[points[lower[i]][2]]);
 
4784   hull.x = function(_) {
 
4785     return arguments.length ? (x = _, hull) : x;
 
4788   hull.y = function(_) {
 
4789     return arguments.length ? (y = _, hull) : y;
 
4795 // finds the 'upper convex hull' (see wiki link above)
 
4796 // assumes points arg has >=3 elements, is sorted by x, unique in y
 
4797 // returns array of indices into points in left to right order
 
4798 function d3_geom_hullUpper(points) {
 
4799   var n = points.length,
 
4801       hs = 2; // hull size
 
4803   for (var i = 2; i < n; i++) {
 
4804     while (hs > 1 && d3_cross2d(points[hull[hs-2]], points[hull[hs-1]], points[i]) <= 0) --hs;
 
4808   // we slice to make sure that the points we 'popped' from hull don't stay behind
 
4809   return hull.slice(0, hs);
 
4812 // comparator for ascending sort by x-coord first, y-coord second
 
4813 function d3_geom_hullOrder(a, b) {
 
4814   return a[0] - b[0] || a[1] - b[1];
 
4816 // import "../transition/transition";
 
4818 d3_selectionPrototype.transition = function(name) {
 
4819   var id = d3_transitionInheritId || ++d3_transitionId,
 
4820       ns = d3_transitionNamespace(name),
 
4824       transition = d3_transitionInherit || {time: Date.now(), ease: d3_ease_cubicInOut, delay: 0, duration: 250};
 
4826   for (var j = -1, m = this.length; ++j < m;) {
 
4827     subgroups.push(subgroup = []);
 
4828     for (var group = this[j], i = -1, n = group.length; ++i < n;) {
 
4829       if (node = group[i]) d3_transitionNode(node, i, ns, id, transition);
 
4830       subgroup.push(node);
 
4834   return d3_transition(subgroups, ns, id);
 
4836 // import "../transition/transition";
 
4838 // TODO Interrupt transitions for all namespaces?
 
4839 d3_selectionPrototype.interrupt = function(name) {
 
4840   return this.each(name == null
 
4841       ? d3_selection_interrupt
 
4842       : d3_selection_interruptNS(d3_transitionNamespace(name)));
 
4845 var d3_selection_interrupt = d3_selection_interruptNS(d3_transitionNamespace());
 
4847 function d3_selection_interruptNS(ns) {
 
4850     if ((lock = this[ns]) && (active = lock[lock.active])) {
 
4851       if (--lock.count) delete lock[lock.active];
 
4852       else delete this[ns];
 
4854       active.event && active.event.interrupt.call(this, this.__data__, active.index);
 
4859 function d3_transition(groups, ns, id) {
 
4860   d3_subclass(groups, d3_transitionPrototype);
 
4863   groups.namespace = ns;
 
4869 var d3_transitionPrototype = [],
 
4870     d3_transitionId = 0,
 
4871     d3_transitionInheritId,
 
4872     d3_transitionInherit;
 
4874 d3_transitionPrototype.call = d3_selectionPrototype.call;
 
4875 d3_transitionPrototype.empty = d3_selectionPrototype.empty;
 
4876 d3_transitionPrototype.node = d3_selectionPrototype.node;
 
4877 d3_transitionPrototype.size = d3_selectionPrototype.size;
 
4879 d3.transition = function(selection, name) {
 
4880   return selection && selection.transition
 
4881       ? (d3_transitionInheritId ? selection.transition(name) : selection)
 
4882       : d3.selection().transition(selection);
 
4885 d3.transition.prototype = d3_transitionPrototype;
 
4888 d3_transitionPrototype.select = function(selector) {
 
4890       ns = this.namespace,
 
4896   selector = d3_selection_selector(selector);
 
4898   for (var j = -1, m = this.length; ++j < m;) {
 
4899     subgroups.push(subgroup = []);
 
4900     for (var group = this[j], i = -1, n = group.length; ++i < n;) {
 
4901       if ((node = group[i]) && (subnode = selector.call(node, node.__data__, i, j))) {
 
4902         if ("__data__" in node) subnode.__data__ = node.__data__;
 
4903         d3_transitionNode(subnode, i, ns, id, node[ns][id]);
 
4904         subgroup.push(subnode);
 
4906         subgroup.push(null);
 
4911   return d3_transition(subgroups, ns, id);
 
4914 d3_transitionPrototype.selectAll = function(selector) {
 
4916       ns = this.namespace,
 
4924   selector = d3_selection_selectorAll(selector);
 
4926   for (var j = -1, m = this.length; ++j < m;) {
 
4927     for (var group = this[j], i = -1, n = group.length; ++i < n;) {
 
4928       if (node = group[i]) {
 
4929         transition = node[ns][id];
 
4930         subnodes = selector.call(node, node.__data__, i, j);
 
4931         subgroups.push(subgroup = []);
 
4932         for (var k = -1, o = subnodes.length; ++k < o;) {
 
4933           if (subnode = subnodes[k]) d3_transitionNode(subnode, k, ns, id, transition);
 
4934           subgroup.push(subnode);
 
4940   return d3_transition(subgroups, ns, id);
 
4943 d3_transitionPrototype.filter = function(filter) {
 
4949   if (typeof filter !== "function") filter = d3_selection_filter(filter);
 
4951   for (var j = 0, m = this.length; j < m; j++) {
 
4952     subgroups.push(subgroup = []);
 
4953     for (var group = this[j], i = 0, n = group.length; i < n; i++) {
 
4954       if ((node = group[i]) && filter.call(node, node.__data__, i, j)) {
 
4955         subgroup.push(node);
 
4960   return d3_transition(subgroups, this.namespace, this.id);
 
4962 d3.color = d3_color;
 
4964 function d3_color() {}
 
4966 d3_color.prototype.toString = function() {
 
4967   return this.rgb() + "";
 
4972 function d3_hsl(h, s, l) {
 
4973   return this instanceof d3_hsl ? void (this.h = +h, this.s = +s, this.l = +l)
 
4974       : arguments.length < 2 ? (h instanceof d3_hsl ? new d3_hsl(h.h, h.s, h.l)
 
4975       : d3_rgb_parse("" + h, d3_rgb_hsl, d3_hsl))
 
4976       : new d3_hsl(h, s, l);
 
4979 var d3_hslPrototype = d3_hsl.prototype = new d3_color;
 
4981 d3_hslPrototype.brighter = function(k) {
 
4982   k = Math.pow(0.7, arguments.length ? k : 1);
 
4983   return new d3_hsl(this.h, this.s, this.l / k);
 
4986 d3_hslPrototype.darker = function(k) {
 
4987   k = Math.pow(0.7, arguments.length ? k : 1);
 
4988   return new d3_hsl(this.h, this.s, k * this.l);
 
4991 d3_hslPrototype.rgb = function() {
 
4992   return d3_hsl_rgb(this.h, this.s, this.l);
 
4995 function d3_hsl_rgb(h, s, l) {
 
4999   /* Some simple corrections for h, s and l. */
 
5000   h = isNaN(h) ? 0 : (h %= 360) < 0 ? h + 360 : h;
 
5001   s = isNaN(s) ? 0 : s < 0 ? 0 : s > 1 ? 1 : s;
 
5002   l = l < 0 ? 0 : l > 1 ? 1 : l;
 
5004   /* From FvD 13.37, CSS Color Module Level 3 */
 
5005   m2 = l <= .5 ? l * (1 + s) : l + s - l * s;
 
5009     if (h > 360) h -= 360;
 
5010     else if (h < 0) h += 360;
 
5011     if (h < 60) return m1 + (m2 - m1) * h / 60;
 
5012     if (h < 180) return m2;
 
5013     if (h < 240) return m1 + (m2 - m1) * (240 - h) / 60;
 
5018     return Math.round(v(h) * 255);
 
5021   return new d3_rgb(vv(h + 120), vv(h), vv(h - 120));
 
5026 function d3_hcl(h, c, l) {
 
5027   return this instanceof d3_hcl ? void (this.h = +h, this.c = +c, this.l = +l)
 
5028       : arguments.length < 2 ? (h instanceof d3_hcl ? new d3_hcl(h.h, h.c, h.l)
 
5029       : (h instanceof d3_lab ? d3_lab_hcl(h.l, h.a, h.b)
 
5030       : d3_lab_hcl((h = d3_rgb_lab((h = d3.rgb(h)).r, h.g, h.b)).l, h.a, h.b)))
 
5031       : new d3_hcl(h, c, l);
 
5034 var d3_hclPrototype = d3_hcl.prototype = new d3_color;
 
5036 d3_hclPrototype.brighter = function(k) {
 
5037   return new d3_hcl(this.h, this.c, Math.min(100, this.l + d3_lab_K * (arguments.length ? k : 1)));
 
5040 d3_hclPrototype.darker = function(k) {
 
5041   return new d3_hcl(this.h, this.c, Math.max(0, this.l - d3_lab_K * (arguments.length ? k : 1)));
 
5044 d3_hclPrototype.rgb = function() {
 
5045   return d3_hcl_lab(this.h, this.c, this.l).rgb();
 
5048 function d3_hcl_lab(h, c, l) {
 
5049   if (isNaN(h)) h = 0;
 
5050   if (isNaN(c)) c = 0;
 
5051   return new d3_lab(l, Math.cos(h *= d3_radians) * c, Math.sin(h) * c);
 
5056 function d3_lab(l, a, b) {
 
5057   return this instanceof d3_lab ? void (this.l = +l, this.a = +a, this.b = +b)
 
5058       : arguments.length < 2 ? (l instanceof d3_lab ? new d3_lab(l.l, l.a, l.b)
 
5059       : (l instanceof d3_hcl ? d3_hcl_lab(l.h, l.c, l.l)
 
5060       : d3_rgb_lab((l = d3_rgb(l)).r, l.g, l.b)))
 
5061       : new d3_lab(l, a, b);
 
5064 // Corresponds roughly to RGB brighter/darker
 
5067 // D65 standard referent
 
5068 var d3_lab_X = 0.950470,
 
5070     d3_lab_Z = 1.088830;
 
5072 var d3_labPrototype = d3_lab.prototype = new d3_color;
 
5074 d3_labPrototype.brighter = function(k) {
 
5075   return new d3_lab(Math.min(100, this.l + d3_lab_K * (arguments.length ? k : 1)), this.a, this.b);
 
5078 d3_labPrototype.darker = function(k) {
 
5079   return new d3_lab(Math.max(0, this.l - d3_lab_K * (arguments.length ? k : 1)), this.a, this.b);
 
5082 d3_labPrototype.rgb = function() {
 
5083   return d3_lab_rgb(this.l, this.a, this.b);
 
5086 function d3_lab_rgb(l, a, b) {
 
5087   var y = (l + 16) / 116,
 
5090   x = d3_lab_xyz(x) * d3_lab_X;
 
5091   y = d3_lab_xyz(y) * d3_lab_Y;
 
5092   z = d3_lab_xyz(z) * d3_lab_Z;
 
5094     d3_xyz_rgb( 3.2404542 * x - 1.5371385 * y - 0.4985314 * z),
 
5095     d3_xyz_rgb(-0.9692660 * x + 1.8760108 * y + 0.0415560 * z),
 
5096     d3_xyz_rgb( 0.0556434 * x - 0.2040259 * y + 1.0572252 * z)
 
5100 function d3_lab_hcl(l, a, b) {
 
5102       ? new d3_hcl(Math.atan2(b, a) * d3_degrees, Math.sqrt(a * a + b * b), l)
 
5103       : new d3_hcl(NaN, NaN, l);
 
5106 function d3_lab_xyz(x) {
 
5107   return x > 0.206893034 ? x * x * x : (x - 4 / 29) / 7.787037;
 
5109 function d3_xyz_lab(x) {
 
5110   return x > 0.008856 ? Math.pow(x, 1 / 3) : 7.787037 * x + 4 / 29;
 
5113 function d3_xyz_rgb(r) {
 
5114   return Math.round(255 * (r <= 0.00304 ? 12.92 * r : 1.055 * Math.pow(r, 1 / 2.4) - 0.055));
 
5119 function d3_rgb(r, g, b) {
 
5120   return this instanceof d3_rgb ? void (this.r = ~~r, this.g = ~~g, this.b = ~~b)
 
5121       : arguments.length < 2 ? (r instanceof d3_rgb ? new d3_rgb(r.r, r.g, r.b)
 
5122       : d3_rgb_parse("" + r, d3_rgb, d3_hsl_rgb))
 
5123       : new d3_rgb(r, g, b);
 
5126 function d3_rgbNumber(value) {
 
5127   return new d3_rgb(value >> 16, value >> 8 & 0xff, value & 0xff);
 
5130 function d3_rgbString(value) {
 
5131   return d3_rgbNumber(value) + "";
 
5134 var d3_rgbPrototype = d3_rgb.prototype = new d3_color;
 
5136 d3_rgbPrototype.brighter = function(k) {
 
5137   k = Math.pow(0.7, arguments.length ? k : 1);
 
5142   if (!r && !g && !b) return new d3_rgb(i, i, i);
 
5143   if (r && r < i) r = i;
 
5144   if (g && g < i) g = i;
 
5145   if (b && b < i) b = i;
 
5146   return new d3_rgb(Math.min(255, r / k), Math.min(255, g / k), Math.min(255, b / k));
 
5149 d3_rgbPrototype.darker = function(k) {
 
5150   k = Math.pow(0.7, arguments.length ? k : 1);
 
5151   return new d3_rgb(k * this.r, k * this.g, k * this.b);
 
5154 d3_rgbPrototype.hsl = function() {
 
5155   return d3_rgb_hsl(this.r, this.g, this.b);
 
5158 d3_rgbPrototype.toString = function() {
 
5159   return "#" + d3_rgb_hex(this.r) + d3_rgb_hex(this.g) + d3_rgb_hex(this.b);
 
5162 function d3_rgb_hex(v) {
 
5164       ? "0" + Math.max(0, v).toString(16)
 
5165       : Math.min(255, v).toString(16);
 
5168 function d3_rgb_parse(format, rgb, hsl) {
 
5169   var r = 0, // red channel; int in [0, 255]
 
5170       g = 0, // green channel; int in [0, 255]
 
5171       b = 0, // blue channel; int in [0, 255]
 
5172       m1, // CSS color specification match
 
5173       m2, // CSS color specification type (e.g., rgb)
 
5176   /* Handle hsl, rgb. */
 
5177   m1 = /([a-z]+)\((.*)\)/i.exec(format);
 
5179     m2 = m1[2].split(",");
 
5183           parseFloat(m2[0]), // degrees
 
5184           parseFloat(m2[1]) / 100, // percentage
 
5185           parseFloat(m2[2]) / 100 // percentage
 
5190           d3_rgb_parseNumber(m2[0]),
 
5191           d3_rgb_parseNumber(m2[1]),
 
5192           d3_rgb_parseNumber(m2[2])
 
5199   if (color = d3_rgb_names.get(format.toLowerCase())) {
 
5200     return rgb(color.r, color.g, color.b);
 
5203   /* Hexadecimal colors: #rgb and #rrggbb. */
 
5204   if (format != null && format.charAt(0) === "#" && !isNaN(color = parseInt(format.slice(1), 16))) {
 
5205     if (format.length === 4) {
 
5206       r = (color & 0xf00) >> 4; r = (r >> 4) | r;
 
5207       g = (color & 0xf0); g = (g >> 4) | g;
 
5208       b = (color & 0xf); b = (b << 4) | b;
 
5209     } else if (format.length === 7) {
 
5210       r = (color & 0xff0000) >> 16;
 
5211       g = (color & 0xff00) >> 8;
 
5216   return rgb(r, g, b);
 
5219 function d3_rgb_hsl(r, g, b) {
 
5220   var min = Math.min(r /= 255, g /= 255, b /= 255),
 
5221       max = Math.max(r, g, b),
 
5225       l = (max + min) / 2;
 
5227     s = l < .5 ? d / (max + min) : d / (2 - max - min);
 
5228     if (r == max) h = (g - b) / d + (g < b ? 6 : 0);
 
5229     else if (g == max) h = (b - r) / d + 2;
 
5230     else h = (r - g) / d + 4;
 
5234     s = l > 0 && l < 1 ? 0 : h;
 
5236   return new d3_hsl(h, s, l);
 
5239 function d3_rgb_lab(r, g, b) {
 
5243   var x = d3_xyz_lab((0.4124564 * r + 0.3575761 * g + 0.1804375 * b) / d3_lab_X),
 
5244       y = d3_xyz_lab((0.2126729 * r + 0.7151522 * g + 0.0721750 * b) / d3_lab_Y),
 
5245       z = d3_xyz_lab((0.0193339 * r + 0.1191920 * g + 0.9503041 * b) / d3_lab_Z);
 
5246   return d3_lab(116 * y - 16, 500 * (x - y), 200 * (y - z));
 
5249 function d3_rgb_xyz(r) {
 
5250   return (r /= 255) <= 0.04045 ? r / 12.92 : Math.pow((r + 0.055) / 1.055, 2.4);
 
5253 function d3_rgb_parseNumber(c) { // either integer or percentage
 
5254   var f = parseFloat(c);
 
5255   return c.charAt(c.length - 1) === "%" ? Math.round(f * 2.55) : f;
 
5258 var d3_rgb_names = d3.map({
 
5259   aliceblue: 0xf0f8ff,
 
5260   antiquewhite: 0xfaebd7,
 
5262   aquamarine: 0x7fffd4,
 
5267   blanchedalmond: 0xffebcd,
 
5269   blueviolet: 0x8a2be2,
 
5271   burlywood: 0xdeb887,
 
5272   cadetblue: 0x5f9ea0,
 
5273   chartreuse: 0x7fff00,
 
5274   chocolate: 0xd2691e,
 
5276   cornflowerblue: 0x6495ed,
 
5282   darkgoldenrod: 0xb8860b,
 
5284   darkgreen: 0x006400,
 
5286   darkkhaki: 0xbdb76b,
 
5287   darkmagenta: 0x8b008b,
 
5288   darkolivegreen: 0x556b2f,
 
5289   darkorange: 0xff8c00,
 
5290   darkorchid: 0x9932cc,
 
5292   darksalmon: 0xe9967a,
 
5293   darkseagreen: 0x8fbc8f,
 
5294   darkslateblue: 0x483d8b,
 
5295   darkslategray: 0x2f4f4f,
 
5296   darkslategrey: 0x2f4f4f,
 
5297   darkturquoise: 0x00ced1,
 
5298   darkviolet: 0x9400d3,
 
5300   deepskyblue: 0x00bfff,
 
5303   dodgerblue: 0x1e90ff,
 
5304   firebrick: 0xb22222,
 
5305   floralwhite: 0xfffaf0,
 
5306   forestgreen: 0x228b22,
 
5308   gainsboro: 0xdcdcdc,
 
5309   ghostwhite: 0xf8f8ff,
 
5311   goldenrod: 0xdaa520,
 
5314   greenyellow: 0xadff2f,
 
5318   indianred: 0xcd5c5c,
 
5323   lavenderblush: 0xfff0f5,
 
5324   lawngreen: 0x7cfc00,
 
5325   lemonchiffon: 0xfffacd,
 
5326   lightblue: 0xadd8e6,
 
5327   lightcoral: 0xf08080,
 
5328   lightcyan: 0xe0ffff,
 
5329   lightgoldenrodyellow: 0xfafad2,
 
5330   lightgray: 0xd3d3d3,
 
5331   lightgreen: 0x90ee90,
 
5332   lightgrey: 0xd3d3d3,
 
5333   lightpink: 0xffb6c1,
 
5334   lightsalmon: 0xffa07a,
 
5335   lightseagreen: 0x20b2aa,
 
5336   lightskyblue: 0x87cefa,
 
5337   lightslategray: 0x778899,
 
5338   lightslategrey: 0x778899,
 
5339   lightsteelblue: 0xb0c4de,
 
5340   lightyellow: 0xffffe0,
 
5342   limegreen: 0x32cd32,
 
5346   mediumaquamarine: 0x66cdaa,
 
5347   mediumblue: 0x0000cd,
 
5348   mediumorchid: 0xba55d3,
 
5349   mediumpurple: 0x9370db,
 
5350   mediumseagreen: 0x3cb371,
 
5351   mediumslateblue: 0x7b68ee,
 
5352   mediumspringgreen: 0x00fa9a,
 
5353   mediumturquoise: 0x48d1cc,
 
5354   mediumvioletred: 0xc71585,
 
5355   midnightblue: 0x191970,
 
5356   mintcream: 0xf5fffa,
 
5357   mistyrose: 0xffe4e1,
 
5359   navajowhite: 0xffdead,
 
5363   olivedrab: 0x6b8e23,
 
5365   orangered: 0xff4500,
 
5367   palegoldenrod: 0xeee8aa,
 
5368   palegreen: 0x98fb98,
 
5369   paleturquoise: 0xafeeee,
 
5370   palevioletred: 0xdb7093,
 
5371   papayawhip: 0xffefd5,
 
5372   peachpuff: 0xffdab9,
 
5376   powderblue: 0xb0e0e6,
 
5378   rebeccapurple: 0x663399,
 
5380   rosybrown: 0xbc8f8f,
 
5381   royalblue: 0x4169e1,
 
5382   saddlebrown: 0x8b4513,
 
5384   sandybrown: 0xf4a460,
 
5390   slateblue: 0x6a5acd,
 
5391   slategray: 0x708090,
 
5392   slategrey: 0x708090,
 
5394   springgreen: 0x00ff7f,
 
5395   steelblue: 0x4682b4,
 
5400   turquoise: 0x40e0d0,
 
5404   whitesmoke: 0xf5f5f5,
 
5406   yellowgreen: 0x9acd32
 
5409 d3_rgb_names.forEach(function(key, value) {
 
5410   d3_rgb_names.set(key, d3_rgbNumber(value));
 
5413 d3.interpolateRgb = d3_interpolateRgb;
 
5415 function d3_interpolateRgb(a, b) {
 
5424   return function(t) {
 
5426         + d3_rgb_hex(Math.round(ar + br * t))
 
5427         + d3_rgb_hex(Math.round(ag + bg * t))
 
5428         + d3_rgb_hex(Math.round(ab + bb * t));
 
5432 d3.interpolateObject = d3_interpolateObject;
 
5434 function d3_interpolateObject(a, b) {
 
5440       i[k] = d3_interpolate(a[k], b[k]);
 
5450   return function(t) {
 
5451     for (k in i) c[k] = i[k](t);
 
5456 d3.interpolateArray = d3_interpolateArray;
 
5458 function d3_interpolateArray(a, b) {
 
5463       n0 = Math.min(a.length, b.length),
 
5465   for (i = 0; i < n0; ++i) x.push(d3_interpolate(a[i], b[i]));
 
5466   for (; i < na; ++i) c[i] = a[i];
 
5467   for (; i < nb; ++i) c[i] = b[i];
 
5468   return function(t) {
 
5469     for (i = 0; i < n0; ++i) c[i] = x[i](t);
 
5473 d3.interpolateNumber = d3_interpolateNumber;
 
5475 function d3_interpolateNumber(a, b) {
 
5477   return function(t) { return a * (1 - t) + b * t; };
 
5480 d3.interpolateString = d3_interpolateString;
 
5482 function d3_interpolateString(a, b) {
 
5483   var bi = d3_interpolate_numberA.lastIndex = d3_interpolate_numberB.lastIndex = 0, // scan index for next number in b
 
5484       am, // current match in a
 
5485       bm, // current match in b
 
5486       bs, // string preceding current number in b, if any
 
5487       i = -1, // index in s
 
5488       s = [], // string constants and placeholders
 
5489       q = []; // number interpolators
 
5491   // Coerce inputs to strings.
 
5492   a = a + "", b = b + "";
 
5494   // Interpolate pairs of numbers in a & b.
 
5495   while ((am = d3_interpolate_numberA.exec(a))
 
5496       && (bm = d3_interpolate_numberB.exec(b))) {
 
5497     if ((bs = bm.index) > bi) { // a string precedes the next number in b
 
5498       bs = b.slice(bi, bs);
 
5499       if (s[i]) s[i] += bs; // coalesce with previous string
 
5502     if ((am = am[0]) === (bm = bm[0])) { // numbers in a & b match
 
5503       if (s[i]) s[i] += bm; // coalesce with previous string
 
5505     } else { // interpolate non-matching numbers
 
5507       q.push({i: i, x: d3_interpolateNumber(am, bm)});
 
5509     bi = d3_interpolate_numberB.lastIndex;
 
5512   // Add remains of b.
 
5513   if (bi < b.length) {
 
5515     if (s[i]) s[i] += bs; // coalesce with previous string
 
5519   // Special optimization for only a single match.
 
5520   // Otherwise, interpolate each of the numbers and rejoin the string.
 
5522       ? (q[0] ? (b = q[0].x, function(t) { return b(t) + ""; })
 
5523       : function() { return b; })
 
5524       : (b = q.length, function(t) {
 
5525           for (var i = 0, o; i < b; ++i) s[(o = q[i]).i] = o.x(t);
 
5530 var d3_interpolate_numberA = /[-+]?(?:\d+\.?\d*|\.?\d+)(?:[eE][-+]?\d+)?/g,
 
5531     d3_interpolate_numberB = new RegExp(d3_interpolate_numberA.source, "g");
 
5533 d3.interpolate = d3_interpolate;
 
5535 function d3_interpolate(a, b) {
 
5536   var i = d3.interpolators.length, f;
 
5537   while (--i >= 0 && !(f = d3.interpolators[i](a, b)));
 
5541 d3.interpolators = [
 
5544     return (t === "string" ? (d3_rgb_names.has(b) || /^(#|rgb\(|hsl\()/.test(b) ? d3_interpolateRgb : d3_interpolateString)
 
5545         : b instanceof d3_color ? d3_interpolateRgb
 
5546         : Array.isArray(b) ? d3_interpolateArray
 
5547         : t === "object" && isNaN(b) ? d3_interpolateObject
 
5548         : d3_interpolateNumber)(a, b);
 
5552 d3.transform = function(string) {
 
5553   var g = d3_document.createElementNS(d3.ns.prefix.svg, "g");
 
5554   return (d3.transform = function(string) {
 
5555     if (string != null) {
 
5556       g.setAttribute("transform", string);
 
5557       var t = g.transform.baseVal.consolidate();
 
5559     return new d3_transform(t ? t.matrix : d3_transformIdentity);
 
5563 // Compute x-scale and normalize the first row.
 
5564 // Compute shear and make second row orthogonal to first.
 
5565 // Compute y-scale and normalize the second row.
 
5566 // Finally, compute the rotation.
 
5567 function d3_transform(m) {
 
5568   var r0 = [m.a, m.b],
 
5570       kx = d3_transformNormalize(r0),
 
5571       kz = d3_transformDot(r0, r1),
 
5572       ky = d3_transformNormalize(d3_transformCombine(r1, r0, -kz)) || 0;
 
5573   if (r0[0] * r1[1] < r1[0] * r0[1]) {
 
5579   this.rotate = (kx ? Math.atan2(r0[1], r0[0]) : Math.atan2(-r1[0], r1[1])) * d3_degrees;
 
5580   this.translate = [m.e, m.f];
 
5581   this.scale = [kx, ky];
 
5582   this.skew = ky ? Math.atan2(kz, ky) * d3_degrees : 0;
 
5585 d3_transform.prototype.toString = function() {
 
5586   return "translate(" + this.translate
 
5587       + ")rotate(" + this.rotate
 
5588       + ")skewX(" + this.skew
 
5589       + ")scale(" + this.scale
 
5593 function d3_transformDot(a, b) {
 
5594   return a[0] * b[0] + a[1] * b[1];
 
5597 function d3_transformNormalize(a) {
 
5598   var k = Math.sqrt(d3_transformDot(a, a));
 
5606 function d3_transformCombine(a, b, k) {
 
5612 var d3_transformIdentity = {a: 1, b: 0, c: 0, d: 1, e: 0, f: 0};
 
5614 d3.interpolateTransform = d3_interpolateTransform;
 
5616 function d3_interpolateTransform(a, b) {
 
5617   var s = [], // string constants and placeholders
 
5618       q = [], // number interpolators
 
5620       A = d3.transform(a),
 
5621       B = d3.transform(b),
 
5631   if (ta[0] != tb[0] || ta[1] != tb[1]) {
 
5632     s.push("translate(", null, ",", null, ")");
 
5633     q.push({i: 1, x: d3_interpolateNumber(ta[0], tb[0])}, {i: 3, x: d3_interpolateNumber(ta[1], tb[1])});
 
5634   } else if (tb[0] || tb[1]) {
 
5635     s.push("translate(" + tb + ")");
 
5641     if (ra - rb > 180) rb += 360; else if (rb - ra > 180) ra += 360; // shortest path
 
5642     q.push({i: s.push(s.pop() + "rotate(", null, ")") - 2, x: d3_interpolateNumber(ra, rb)});
 
5644     s.push(s.pop() + "rotate(" + rb + ")");
 
5648     q.push({i: s.push(s.pop() + "skewX(", null, ")") - 2, x: d3_interpolateNumber(wa, wb)});
 
5650     s.push(s.pop() + "skewX(" + wb + ")");
 
5653   if (ka[0] != kb[0] || ka[1] != kb[1]) {
 
5654     n = s.push(s.pop() + "scale(", null, ",", null, ")");
 
5655     q.push({i: n - 4, x: d3_interpolateNumber(ka[0], kb[0])}, {i: n - 2, x: d3_interpolateNumber(ka[1], kb[1])});
 
5656   } else if (kb[0] != 1 || kb[1] != 1) {
 
5657     s.push(s.pop() + "scale(" + kb + ")");
 
5661   return function(t) {
 
5663     while (++i < n) s[(o = q[i]).i] = o.x(t);
 
5668 d3_transitionPrototype.tween = function(name, tween) {
 
5669   var id = this.id, ns = this.namespace;
 
5670   if (arguments.length < 2) return this.node()[ns][id].tween.get(name);
 
5671   return d3_selection_each(this, tween == null
 
5672         ? function(node) { node[ns][id].tween.remove(name); }
 
5673         : function(node) { node[ns][id].tween.set(name, tween); });
 
5676 function d3_transition_tween(groups, name, value, tween) {
 
5677   var id = groups.id, ns = groups.namespace;
 
5678   return d3_selection_each(groups, typeof value === "function"
 
5679       ? function(node, i, j) { node[ns][id].tween.set(name, tween(value.call(node, node.__data__, i, j))); }
 
5680       : (value = tween(value), function(node) { node[ns][id].tween.set(name, value); }));
 
5683 d3_transitionPrototype.attr = function(nameNS, value) {
 
5684   if (arguments.length < 2) {
 
5686     // For attr(object), the object specifies the names and values of the
 
5687     // attributes to transition. The values may be functions that are
 
5688     // evaluated for each element.
 
5689     for (value in nameNS) this.attr(value, nameNS[value]);
 
5693   var interpolate = nameNS == "transform" ? d3_interpolateTransform : d3_interpolate,
 
5694       name = d3.ns.qualify(nameNS);
 
5696   // For attr(string, null), remove the attribute with the specified name.
 
5697   function attrNull() {
 
5698     this.removeAttribute(name);
 
5700   function attrNullNS() {
 
5701     this.removeAttributeNS(name.space, name.local);
 
5704   // For attr(string, string), set the attribute with the specified name.
 
5705   function attrTween(b) {
 
5706     return b == null ? attrNull : (b += "", function() {
 
5707       var a = this.getAttribute(name), i;
 
5708       return a !== b && (i = interpolate(a, b), function(t) { this.setAttribute(name, i(t)); });
 
5711   function attrTweenNS(b) {
 
5712     return b == null ? attrNullNS : (b += "", function() {
 
5713       var a = this.getAttributeNS(name.space, name.local), i;
 
5714       return a !== b && (i = interpolate(a, b), function(t) { this.setAttributeNS(name.space, name.local, i(t)); });
 
5718   return d3_transition_tween(this, "attr." + nameNS, value, name.local ? attrTweenNS : attrTween);
 
5721 d3_transitionPrototype.attrTween = function(nameNS, tween) {
 
5722   var name = d3.ns.qualify(nameNS);
 
5724   function attrTween(d, i) {
 
5725     var f = tween.call(this, d, i, this.getAttribute(name));
 
5726     return f && function(t) { this.setAttribute(name, f(t)); };
 
5728   function attrTweenNS(d, i) {
 
5729     var f = tween.call(this, d, i, this.getAttributeNS(name.space, name.local));
 
5730     return f && function(t) { this.setAttributeNS(name.space, name.local, f(t)); };
 
5733   return this.tween("attr." + nameNS, name.local ? attrTweenNS : attrTween);
 
5736 d3_transitionPrototype.style = function(name, value, priority) {
 
5737   var n = arguments.length;
 
5740     // For style(object) or style(object, string), the object specifies the
 
5741     // names and values of the attributes to set or remove. The values may be
 
5742     // functions that are evaluated for each element. The optional string
 
5743     // specifies the priority.
 
5744     if (typeof name !== "string") {
 
5745       if (n < 2) value = "";
 
5746       for (priority in name) this.style(priority, name[priority], value);
 
5750     // For style(string, string) or style(string, function), use the default
 
5751     // priority. The priority is ignored for style(string, null).
 
5755   // For style(name, null) or style(name, null, priority), remove the style
 
5756   // property with the specified name. The priority is ignored.
 
5757   function styleNull() {
 
5758     this.style.removeProperty(name);
 
5761   // For style(name, string) or style(name, string, priority), set the style
 
5762   // property with the specified name, using the specified priority.
 
5763   // Otherwise, a name, value and priority are specified, and handled as below.
 
5764   function styleString(b) {
 
5765     return b == null ? styleNull : (b += "", function() {
 
5766       var a = d3_window(this).getComputedStyle(this, null).getPropertyValue(name), i;
 
5767       return a !== b && (i = d3_interpolate(a, b), function(t) { this.style.setProperty(name, i(t), priority); });
 
5771   return d3_transition_tween(this, "style." + name, value, styleString);
 
5774 d3_transitionPrototype.styleTween = function(name, tween, priority) {
 
5775   if (arguments.length < 3) priority = "";
 
5777   function styleTween(d, i) {
 
5778     var f = tween.call(this, d, i, d3_window(this).getComputedStyle(this, null).getPropertyValue(name));
 
5779     return f && function(t) { this.style.setProperty(name, f(t), priority); };
 
5782   return this.tween("style." + name, styleTween);
 
5785 d3_transitionPrototype.text = function(value) {
 
5786   return d3_transition_tween(this, "text", value, d3_transition_text);
 
5789 function d3_transition_text(b) {
 
5790   if (b == null) b = "";
 
5791   return function() { this.textContent = b; };
 
5794 d3_transitionPrototype.remove = function() {
 
5795   var ns = this.namespace;
 
5796   return this.each("end.transition", function() {
 
5798     if (this[ns].count < 2 && (p = this.parentNode)) p.removeChild(this);
 
5802 var d3_ease_default = function() { return d3_identity; };
 
5804 var d3_ease = d3.map({
 
5805   linear: d3_ease_default,
 
5807   quad: function() { return d3_ease_quad; },
 
5808   cubic: function() { return d3_ease_cubic; },
 
5809   sin: function() { return d3_ease_sin; },
 
5810   exp: function() { return d3_ease_exp; },
 
5811   circle: function() { return d3_ease_circle; },
 
5812   elastic: d3_ease_elastic,
 
5814   bounce: function() { return d3_ease_bounce; }
 
5817 var d3_ease_mode = d3.map({
 
5819   "out": d3_ease_reverse,
 
5820   "in-out": d3_ease_reflect,
 
5821   "out-in": function(f) { return d3_ease_reflect(d3_ease_reverse(f)); }
 
5824 d3.ease = function(name) {
 
5825   var i = name.indexOf("-"),
 
5826       t = i >= 0 ? name.slice(0, i) : name,
 
5827       m = i >= 0 ? name.slice(i + 1) : "in";
 
5828   t = d3_ease.get(t) || d3_ease_default;
 
5829   m = d3_ease_mode.get(m) || d3_identity;
 
5830   return d3_ease_clamp(m(t.apply(null, d3_arraySlice.call(arguments, 1))));
 
5833 function d3_ease_clamp(f) {
 
5834   return function(t) {
 
5835     return t <= 0 ? 0 : t >= 1 ? 1 : f(t);
 
5839 function d3_ease_reverse(f) {
 
5840   return function(t) {
 
5841     return 1 - f(1 - t);
 
5845 function d3_ease_reflect(f) {
 
5846   return function(t) {
 
5847     return .5 * (t < .5 ? f(2 * t) : (2 - f(2 - 2 * t)));
 
5851 function d3_ease_quad(t) {
 
5855 function d3_ease_cubic(t) {
 
5859 // Optimized clamp(reflect(poly(3))).
 
5860 function d3_ease_cubicInOut(t) {
 
5861   if (t <= 0) return 0;
 
5862   if (t >= 1) return 1;
 
5863   var t2 = t * t, t3 = t2 * t;
 
5864   return 4 * (t < .5 ? t3 : 3 * (t - t2) + t3 - .75);
 
5867 function d3_ease_poly(e) {
 
5868   return function(t) {
 
5869     return Math.pow(t, e);
 
5873 function d3_ease_sin(t) {
 
5874   return 1 - Math.cos(t * halfπ);
 
5877 function d3_ease_exp(t) {
 
5878   return Math.pow(2, 10 * (t - 1));
 
5881 function d3_ease_circle(t) {
 
5882   return 1 - Math.sqrt(1 - t * t);
 
5885 function d3_ease_elastic(a, p) {
 
5887   if (arguments.length < 2) p = 0.45;
 
5888   if (arguments.length) s = p / τ * Math.asin(1 / a);
 
5889   else a = 1, s = p / 4;
 
5890   return function(t) {
 
5891     return 1 + a * Math.pow(2, -10 * t) * Math.sin((t - s) * τ / p);
 
5895 function d3_ease_back(s) {
 
5896   if (!s) s = 1.70158;
 
5897   return function(t) {
 
5898     return t * t * ((s + 1) * t - s);
 
5902 function d3_ease_bounce(t) {
 
5903   return t < 1 / 2.75 ? 7.5625 * t * t
 
5904       : t < 2 / 2.75 ? 7.5625 * (t -= 1.5 / 2.75) * t + .75
 
5905       : t < 2.5 / 2.75 ? 7.5625 * (t -= 2.25 / 2.75) * t + .9375
 
5906       : 7.5625 * (t -= 2.625 / 2.75) * t + .984375;
 
5909 d3_transitionPrototype.ease = function(value) {
 
5910   var id = this.id, ns = this.namespace;
 
5911   if (arguments.length < 1) return this.node()[ns][id].ease;
 
5912   if (typeof value !== "function") value = d3.ease.apply(d3, arguments);
 
5913   return d3_selection_each(this, function(node) { node[ns][id].ease = value; });
 
5916 d3_transitionPrototype.delay = function(value) {
 
5917   var id = this.id, ns = this.namespace;
 
5918   if (arguments.length < 1) return this.node()[ns][id].delay;
 
5919   return d3_selection_each(this, typeof value === "function"
 
5920       ? function(node, i, j) { node[ns][id].delay = +value.call(node, node.__data__, i, j); }
 
5921       : (value = +value, function(node) { node[ns][id].delay = value; }));
 
5924 d3_transitionPrototype.duration = function(value) {
 
5925   var id = this.id, ns = this.namespace;
 
5926   if (arguments.length < 1) return this.node()[ns][id].duration;
 
5927   return d3_selection_each(this, typeof value === "function"
 
5928       ? function(node, i, j) { node[ns][id].duration = Math.max(1, value.call(node, node.__data__, i, j)); }
 
5929       : (value = Math.max(1, value), function(node) { node[ns][id].duration = value; }));
 
5932 d3_transitionPrototype.each = function(type, listener) {
 
5933   var id = this.id, ns = this.namespace;
 
5934   if (arguments.length < 2) {
 
5935     var inherit = d3_transitionInherit,
 
5936         inheritId = d3_transitionInheritId;
 
5938       d3_transitionInheritId = id;
 
5939       d3_selection_each(this, function(node, i, j) {
 
5940         d3_transitionInherit = node[ns][id];
 
5941         type.call(node, node.__data__, i, j);
 
5944       d3_transitionInherit = inherit;
 
5945       d3_transitionInheritId = inheritId;
 
5948     d3_selection_each(this, function(node) {
 
5949       var transition = node[ns][id];
 
5950       (transition.event || (transition.event = d3.dispatch("start", "end", "interrupt"))).on(type, listener);
 
5956 d3_transitionPrototype.transition = function() {
 
5958       id1 = ++d3_transitionId,
 
5959       ns = this.namespace,
 
5966   for (var j = 0, m = this.length; j < m; j++) {
 
5967     subgroups.push(subgroup = []);
 
5968     for (var group = this[j], i = 0, n = group.length; i < n; i++) {
 
5969       if (node = group[i]) {
 
5970         transition = node[ns][id0];
 
5971         d3_transitionNode(node, i, ns, id1, {time: transition.time, ease: transition.ease, delay: transition.delay + transition.duration, duration: transition.duration});
 
5973       subgroup.push(node);
 
5977   return d3_transition(subgroups, ns, id1);
 
5980 function d3_transitionNamespace(name) {
 
5981   return name == null ? "__transition__" : "__transition_" + name + "__";
 
5984 function d3_transitionNode(node, i, ns, id, inherit) {
 
5985   var lock = node[ns] || (node[ns] = {active: 0, count: 0}),
 
5986       transition = lock[id];
 
5989     var time = inherit.time;
 
5991     transition = lock[id] = {
 
5994       delay: inherit.delay,
 
5995       duration: inherit.duration,
 
6000     inherit = null; // allow gc
 
6004     d3.timer(function(elapsed) {
 
6005       var delay = transition.delay,
 
6008           timer = d3_timer_active,
 
6011       timer.t = delay + time;
 
6012       if (delay <= elapsed) return start(elapsed - delay);
 
6015       function start(elapsed) {
 
6016         if (lock.active > id) return stop();
 
6018         var active = lock[lock.active];
 
6021           delete lock[lock.active];
 
6022           active.event && active.event.interrupt.call(node, node.__data__, active.index);
 
6027         transition.event && transition.event.start.call(node, node.__data__, i);
 
6029         transition.tween.forEach(function(key, value) {
 
6030           if (value = value.call(node, node.__data__, i)) {
 
6031             tweened.push(value);
 
6035         // Deferred capture to allow tweens to initialize ease & duration.
 
6036         ease = transition.ease;
 
6037         duration = transition.duration;
 
6039         d3.timer(function() { // defer to end of current frame
 
6040           timer.c = tick(elapsed || 1) ? d3_true : tick;
 
6045       function tick(elapsed) {
 
6046         if (lock.active !== id) return 1;
 
6048         var t = elapsed / duration,
 
6053           tweened[--n].call(node, e);
 
6057           transition.event && transition.event.end.call(node, node.__data__, i);
 
6063         if (--lock.count) delete lock[id];
 
6064         else delete node[ns];
 
6071 d3.xhr = d3_xhrType(d3_identity);
 
6073 function d3_xhrType(response) {
 
6074   return function(url, mimeType, callback) {
 
6075     if (arguments.length === 2 && typeof mimeType === "function") callback = mimeType, mimeType = null;
 
6076     return d3_xhr(url, mimeType, response, callback);
 
6080 function d3_xhr(url, mimeType, response, callback) {
 
6082       dispatch = d3.dispatch("beforesend", "progress", "load", "error"),
 
6084       request = new XMLHttpRequest,
 
6085       responseType = null;
 
6087   // If IE does not support CORS, use XDomainRequest.
 
6088   if (this.XDomainRequest
 
6089       && !("withCredentials" in request)
 
6090       && /^(http(s)?:)?\/\//.test(url)) request = new XDomainRequest;
 
6093       ? request.onload = request.onerror = respond
 
6094       : request.onreadystatechange = function() { request.readyState > 3 && respond(); };
 
6096   function respond() {
 
6097     var status = request.status, result;
 
6098     if (!status && d3_xhrHasResponse(request) || status >= 200 && status < 300 || status === 304) {
 
6100         result = response.call(xhr, request);
 
6102         dispatch.error.call(xhr, e);
 
6105       dispatch.load.call(xhr, result);
 
6107       dispatch.error.call(xhr, request);
 
6111   request.onprogress = function(event) {
 
6114     try { dispatch.progress.call(xhr, request); }
 
6115     finally { d3.event = o; }
 
6118   xhr.header = function(name, value) {
 
6119     name = (name + "").toLowerCase();
 
6120     if (arguments.length < 2) return headers[name];
 
6121     if (value == null) delete headers[name];
 
6122     else headers[name] = value + "";
 
6126   // If mimeType is non-null and no Accept header is set, a default is used.
 
6127   xhr.mimeType = function(value) {
 
6128     if (!arguments.length) return mimeType;
 
6129     mimeType = value == null ? null : value + "";
 
6133   // Specifies what type the response value should take;
 
6134   // for instance, arraybuffer, blob, document, or text.
 
6135   xhr.responseType = function(value) {
 
6136     if (!arguments.length) return responseType;
 
6137     responseType = value;
 
6141   // Specify how to convert the response content to a specific type;
 
6142   // changes the callback value on "load" events.
 
6143   xhr.response = function(value) {
 
6148   // Convenience methods.
 
6149   ["get", "post"].forEach(function(method) {
 
6150     xhr[method] = function() {
 
6151       return xhr.send.apply(xhr, [method].concat(d3_array(arguments)));
 
6155   // If callback is non-null, it will be used for error and load events.
 
6156   xhr.send = function(method, data, callback) {
 
6157     if (arguments.length === 2 && typeof data === "function") callback = data, data = null;
 
6158     request.open(method, url, true);
 
6159     if (mimeType != null && !("accept" in headers)) headers["accept"] = mimeType + ",*/*";
 
6160     if (request.setRequestHeader) for (var name in headers) request.setRequestHeader(name, headers[name]);
 
6161     if (mimeType != null && request.overrideMimeType) request.overrideMimeType(mimeType);
 
6162     if (responseType != null) request.responseType = responseType;
 
6163     if (callback != null) xhr.on("error", callback).on("load", function(request) { callback(null, request); });
 
6164     dispatch.beforesend.call(xhr, request);
 
6165     request.send(data == null ? null : data);
 
6169   xhr.abort = function() {
 
6174   d3.rebind(xhr, dispatch, "on");
 
6176   return callback == null ? xhr : xhr.get(d3_xhr_fixCallback(callback));
 
6179 function d3_xhr_fixCallback(callback) {
 
6180   return callback.length === 1
 
6181       ? function(error, request) { callback(error == null ? request : null); }
 
6185 function d3_xhrHasResponse(request) {
 
6186   var type = request.responseType;
 
6187   return type && type !== "text"
 
6188       ? request.response // null on error
 
6189       : request.responseText; // "" on error
 
6192 d3.text = d3_xhrType(function(request) {
 
6193   return request.responseText;
 
6196 d3.json = function(url, callback) {
 
6197   return d3_xhr(url, "application/json", d3_json, callback);
 
6200 function d3_json(request) {
 
6201   return JSON.parse(request.responseText);
 
6204 d3.html = function(url, callback) {
 
6205   return d3_xhr(url, "text/html", d3_html, callback);
 
6208 function d3_html(request) {
 
6209   var range = d3_document.createRange();
 
6210   range.selectNode(d3_document.body);
 
6211   return range.createContextualFragment(request.responseText);
 
6214 d3.xml = d3_xhrType(function(request) {
 
6215   return request.responseXML;
 
6217   if (typeof define === "function" && define.amd) define(d3);
 
6218   else if (typeof module === "object" && module.exports) module.exports = d3;
 
6221 d3.combobox = function() {
 
6222     var event = d3.dispatch('accept'),
 
6227     var fetcher = function(val, cb) {
 
6228         cb(data.filter(function(d) {
 
6232                 .indexOf(val.toLowerCase()) !== -1;
 
6236     var combobox = function(input) {
 
6238             container = d3.select(document.body)
 
6239                 .selectAll('div.combobox')
 
6240                 .filter(function(d) { return d === input.node(); }),
 
6241             shown = !container.empty();
 
6244             .classed('combobox-input', true)
 
6245             .on('focus.typeahead', focus)
 
6246             .on('blur.typeahead', blur)
 
6247             .on('keydown.typeahead', keydown)
 
6248             .on('keyup.typeahead', keyup)
 
6249             .on('input.typeahead', change)
 
6251                 var parent = this.parentNode,
 
6252                     sibling = this.nextSibling;
 
6254                 var caret = d3.select(parent).selectAll('.combobox-caret')
 
6255                     .filter(function(d) { return d === input.node(); })
 
6256                     .data([input.node()]);
 
6258                 caret.enter().insert('div', function() { return sibling; })
 
6259                     .attr('class', 'combobox-caret');
 
6262                     .on('mousedown', function () {
 
6263                         // prevent the form element from blurring. it blurs
 
6265                         d3.event.stopPropagation();
 
6266                         d3.event.preventDefault();
 
6268                             input.node().focus();
 
6277             fetch(value(), render);
 
6281             window.setTimeout(hide, 150);
 
6286                 container = d3.select(document.body)
 
6287                     .insert('div', ':first-child')
 
6288                     .datum(input.node())
 
6289                     .attr('class', 'combobox')
 
6291                         position: 'absolute',
 
6295                     .on('mousedown', function () {
 
6296                         // prevent moving focus out of the text field
 
6297                         d3.event.preventDefault();
 
6300                 d3.select(document.body)
 
6301                     .on('scroll.combobox', render, true);
 
6312                 d3.select(document.body)
 
6313                     .on('scroll.combobox', null);
 
6319         function keydown() {
 
6320            switch (d3.event.keyCode) {
 
6321                // backspace, delete
 
6324                    input.on('input.typeahead', function() {
 
6327                        var start = input.property('selectionStart');
 
6328                        input.node().setSelectionRange(start, start);
 
6329                        input.on('input.typeahead', change);
 
6334                    container.selectAll('a.selected').each(event.accept);
 
6338                    d3.event.preventDefault();
 
6343                    d3.event.preventDefault();
 
6348                    d3.event.preventDefault();
 
6351            d3.event.stopPropagation();
 
6355             switch (d3.event.keyCode) {
 
6362                     container.selectAll('a.selected').each(event.accept);
 
6369             fetch(value(), function() {
 
6376             idx = Math.max(Math.min(idx + dir, suggestions.length - 1), 0);
 
6377             input.property('value', suggestions[idx].value);
 
6383             var value = input.property('value'),
 
6384                 start = input.property('selectionStart'),
 
6385                 end = input.property('selectionEnd');
 
6388                 value = value.substring(0, start);
 
6394         function fetch(v, cb) {
 
6395             fetcher.call(input, v, function(_) {
 
6401         function autocomplete() {
 
6408             for (var i = 0; i < suggestions.length; i++) {
 
6409                 if (suggestions[i].value.toLowerCase().indexOf(v.toLowerCase()) === 0) {
 
6410                     var completion = suggestions[i].value;
 
6412                     input.property('value', completion);
 
6413                     input.node().setSelectionRange(v.length, completion.length);
 
6420             if (suggestions.length >= minItems && document.activeElement === input.node()) {
 
6427             var options = container
 
6428                 .selectAll('a.combobox-option')
 
6429                 .data(suggestions, function(d) { return d.value; });
 
6431             options.enter().append('a')
 
6432                 .attr('class', 'combobox-option')
 
6433                 .text(function(d) { return d.value; });
 
6436                 .attr('title', function(d) { return d.title; })
 
6437                 .classed('selected', function(d, i) { return i == idx; })
 
6438                 .on('mouseover', select)
 
6439                 .on('click', accept)
 
6445             var rect = input.node().getBoundingClientRect();
 
6448                 'left': rect.left + 'px',
 
6449                 'width': rect.width + 'px',
 
6450                 'top': rect.height + rect.top + 'px'
 
6454         function select(d, i) {
 
6459         function ensureVisible() {
 
6460             var node = container.selectAll('a.selected').node();
 
6461             if (node) node.scrollIntoView();
 
6464         function accept(d) {
 
6467                 .property('value', d.value)
 
6474     combobox.fetcher = function(_) {
 
6475         if (!arguments.length) return fetcher;
 
6480     combobox.data = function(_) {
 
6481         if (!arguments.length) return data;
 
6486     combobox.minItems = function(_) {
 
6487         if (!arguments.length) return minItems;
 
6492     return d3.rebind(combobox, event, 'on');
 
6495 d3.combobox.off = function(input) {
 
6500         .on('focus.typeahead', null)
 
6501         .on('blur.typeahead', null)
 
6502         .on('keydown.typeahead', null)
 
6503         .on('keyup.typeahead', null)
 
6504         .on('input.typeahead', null)
 
6506             d3.select(this.parentNode).selectAll('.combobox-caret')
 
6507                 .filter(function(d) { return d === input.node(); })
 
6508                 .on('mousedown', null);
 
6511     d3.select(document.body)
 
6512         .on('scroll.combobox', null);
 
6514 d3.geo.tile = function() {
 
6515   var size = [960, 500],
 
6517       scaleExtent = [0, 20],
 
6518       translate = [size[0] / 2, size[1] / 2],
 
6522       return Math.min(scaleExtent[1], Math.max(scaleExtent[0], _));
 
6526     var z = Math.max(Math.log(scale) / Math.LN2 - 8, 0),
 
6527         z0 = bound(Math.round(z + zoomDelta)),
 
6528         k = Math.pow(2, z - z0 + 8),
 
6529         origin = [(translate[0] - scale / 2) / k, (translate[1] - scale / 2) / k],
 
6531         cols = d3.range(Math.max(0, Math.floor(-origin[0])), Math.max(0, Math.ceil(size[0] / k - origin[0]))),
 
6532         rows = d3.range(Math.max(0, Math.floor(-origin[1])), Math.max(0, Math.ceil(size[1] / k - origin[1])));
 
6534     rows.forEach(function(y) {
 
6535       cols.forEach(function(x) {
 
6536         tiles.push([x, y, z0]);
 
6540     tiles.translate = origin;
 
6546   tile.scaleExtent = function(_) {
 
6547     if (!arguments.length) return scaleExtent;
 
6552   tile.size = function(_) {
 
6553     if (!arguments.length) return size;
 
6558   tile.scale = function(_) {
 
6559     if (!arguments.length) return scale;
 
6564   tile.translate = function(_) {
 
6565     if (!arguments.length) return translate;
 
6570   tile.zoomDelta = function(_) {
 
6571     if (!arguments.length) return zoomDelta;
 
6578 d3.jsonp = function (url, callback) {
 
6580     var chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz',
 
6582     while (++i < 15) c += chars.charAt(Math.floor(Math.random() * 52));
 
6586   function create(url) {
 
6587     var e = url.match(/callback=d3.jsonp.(\w+)/),
 
6588       c = e ? e[1] : rand();
 
6589     d3.jsonp[c] = function(data) {
 
6594     return 'd3.jsonp.' + c;
 
6597   var cb = create(url),
 
6598     script = d3.select('head')
 
6600     .attr('type', 'text/javascript')
 
6601     .attr('src', url.replace(/(\{|%7B)callback(\}|%7D)/, cb));
 
6604  * This code is licensed under the MIT license.
 
6606  * Copyright © 2013, iD authors.
 
6608  * Portions copyright © 2011, Keith Cirkel
 
6609  * See https://github.com/keithamus/jwerty
 
6612 d3.keybinding = function(namespace) {
 
6615     function matches(binding, event) {
 
6616         for (var p in binding.event) {
 
6617             if (event[p] != binding.event[p])
 
6621         return (!binding.capture) === (event.eventPhase !== Event.CAPTURING_PHASE);
 
6624     function capture() {
 
6625         for (var i = 0; i < bindings.length; i++) {
 
6626             var binding = bindings[i];
 
6627             if (matches(binding, d3.event)) {
 
6634         var tagName = d3.select(d3.event.target).node().tagName;
 
6635         if (tagName == 'INPUT' || tagName == 'SELECT' || tagName == 'TEXTAREA') {
 
6641     function keybinding(selection) {
 
6642         selection = selection || d3.select(document);
 
6643         selection.on('keydown.capture' + namespace, capture, true);
 
6644         selection.on('keydown.bubble' + namespace, bubble, false);
 
6648     keybinding.off = function(selection) {
 
6649         selection = selection || d3.select(document);
 
6650         selection.on('keydown.capture' + namespace, null);
 
6651         selection.on('keydown.bubble' + namespace, null);
 
6655     keybinding.on = function(code, callback, capture) {
 
6668         code = code.toLowerCase().match(/(?:(?:[^+⇧⌃⌥⌘])+|[⇧⌃⌥⌘]|\+\+|^\+$)/g);
 
6670         for (var i = 0; i < code.length; i++) {
 
6671             // Normalise matching errors
 
6672             if (code[i] === '++') code[i] = '+';
 
6674             if (code[i] in d3.keybinding.modifierCodes) {
 
6675                 binding.event[d3.keybinding.modifierProperties[d3.keybinding.modifierCodes[code[i]]]] = true;
 
6676             } else if (code[i] in d3.keybinding.keyCodes) {
 
6677                 binding.event.keyCode = d3.keybinding.keyCodes[code[i]];
 
6681         bindings.push(binding);
 
6690     d3.keybinding.modifierCodes = {
 
6693         // CTRL key, on Mac: ⌃
 
6695         // ALT key, on Mac: ⌥ (Alt)
 
6696         '⌥': 18, alt: 18, option: 18,
 
6697         // META, on Mac: ⌘ (CMD), on Windows (Win), on Linux (Super)
 
6698         '⌘': 91, meta: 91, cmd: 91, 'super': 91, win: 91
 
6701     d3.keybinding.modifierProperties = {
 
6708     d3.keybinding.keyCodes = {
 
6709         // Backspace key, on Mac: ⌫ (Backspace)
 
6710         '⌫': 8, backspace: 8,
 
6711         // Tab Key, on Mac: ⇥ (Tab), on Windows ⇥⇥
 
6712         '⇥': 9, '⇆': 9, tab: 9,
 
6714         '↩': 13, 'return': 13, enter: 13, '⌅': 13,
 
6716         'pause': 19, 'pause-break': 19,
 
6718         '⇪': 20, caps: 20, 'caps-lock': 20,
 
6719         // Escape key, on Mac: ⎋, on Windows: Esc
 
6720         '⎋': 27, escape: 27, esc: 27,
 
6723         // Page-Up key, or pgup, on Mac: ↖
 
6724         '↖': 33, pgup: 33, 'page-up': 33,
 
6725         // Page-Down key, or pgdown, on Mac: ↘
 
6726         '↘': 34, pgdown: 34, 'page-down': 34,
 
6727         // END key, on Mac: ⇟
 
6729         // HOME key, on Mac: ⇞
 
6731         // Insert key, or ins
 
6732         ins: 45, insert: 45,
 
6733         // Delete key, on Mac: ⌦ (Delete)
 
6734         '⌦': 46, del: 46, 'delete': 46,
 
6735         // Left Arrow Key, or ←
 
6736         '←': 37, left: 37, 'arrow-left': 37,
 
6737         // Up Arrow Key, or ↑
 
6738         '↑': 38, up: 38, 'arrow-up': 38,
 
6739         // Right Arrow Key, or →
 
6740         '→': 39, right: 39, 'arrow-right': 39,
 
6741         // Up Arrow Key, or ↓
 
6742         '↓': 40, down: 40, 'arrow-down': 40,
 
6743         // odities, printing characters that come out wrong:
 
6746         // Num-Multiply, or *
 
6747         '*': 106, star: 106, asterisk: 106, multiply: 106,
 
6749         '+': 107, 'plus': 107,
 
6750         // Num-Subtract, or -
 
6751         '-': 109, subtract: 109,
 
6757         ';': 186, semicolon: 186,
 
6759         '=': 187, 'equals': 187,
 
6761         ',': 188, comma: 188,
 
6763         // Period, or ., or full-stop
 
6764         '.': 190, period: 190, 'full-stop': 190,
 
6765         // Slash, or /, or forward-slash
 
6766         '/': 191, slash: 191, 'forward-slash': 191,
 
6767         // Tick, or `, or back-quote
 
6768         '`': 192, tick: 192, 'back-quote': 192,
 
6769         // Open bracket, or [
 
6770         '[': 219, 'open-bracket': 219,
 
6772         '\\': 220, 'back-slash': 220,
 
6773         // Close backet, or ]
 
6774         ']': 221, 'close-bracket': 221,
 
6775         // Apostrophe, or Quote, or '
 
6776         '\'': 222, quote: 222, apostrophe: 222
 
6782         d3.keybinding.keyCodes['num-' + n] = i;
 
6789         d3.keybinding.keyCodes[n] = i;
 
6796         d3.keybinding.keyCodes['f' + n] = i;
 
6803         d3.keybinding.keyCodes[String.fromCharCode(i).toLowerCase()] = i;
 
6806 d3.selection.prototype.one = function (type, listener, capture) {
 
6807     var target = this, typeOnce = type + ".once";
 
6809         target.on(typeOnce, null);
 
6810         listener.apply(this, arguments);
 
6812     target.on(typeOnce, one, capture);
 
6815 d3.selection.prototype.dimensions = function (dimensions) {
 
6816     var refresh = (function(node) {
 
6817         var cr = node.getBoundingClientRect();
 
6818         prop = [cr.width, cr.height];
 
6819         this.property('__dimensions__', prop);
 
6823     var node = this.node();
 
6825     if (!arguments.length) {
 
6826         if (!node) return [0,0];
 
6827         return this.property('__dimensions__') || refresh(node);
 
6829     if (dimensions === null) {
 
6830         if (!node) return [0,0];
 
6831         return refresh(node);
 
6835         .property('__dimensions__', [dimensions[0], dimensions[1]])
 
6836         .attr({width: dimensions[0], height: dimensions[1]});
 
6838 d3.selection.prototype.trigger = function (type) {
 
6839     this.each(function() {
 
6840         var evt = document.createEvent('HTMLEvents');
 
6841         evt.initEvent(type, true, true);
 
6842         this.dispatchEvent(evt);
 
6845 // Tooltips and svg mask used to highlight certain features
 
6846 d3.curtain = function() {
 
6848     var event = d3.dispatch(),
 
6853     function curtain(selection) {
 
6855         surface = selection.append('svg')
 
6856             .attr('id', 'curtain')
 
6859                 'pointer-events': 'none',
 
6860                 'position': 'absolute',
 
6865         darkness = surface.append('path')
 
6869                 'class': 'curtain-darkness'
 
6872         d3.select(window).on('resize.curtain', resize);
 
6874         tooltip = selection.append('div')
 
6875             .attr('class', 'tooltip')
 
6876             .style('z-index', 1002);
 
6878         tooltip.append('div').attr('class', 'tooltip-arrow');
 
6879         tooltip.append('div').attr('class', 'tooltip-inner');
 
6885                 width: window.innerWidth,
 
6886                 height: window.innerHeight
 
6888             curtain.cut(darkness.datum());
 
6892     curtain.reveal = function(box, text, tooltipclass, duration) {
 
6893         if (typeof box === 'string') box = d3.select(box).node();
 
6894         if (box.getBoundingClientRect) box = box.getBoundingClientRect();
 
6896         curtain.cut(box, duration);
 
6899             // pseudo markdown bold text hack
 
6900             var parts = text.split('**');
 
6901             var html = parts[0] ? '<span>' + parts[0] + '</span>' : '';
 
6902             if (parts[1]) html += '<span class="bold">' + parts[1] + '</span>';
 
6904             var dimensions = tooltip.classed('in', true)
 
6905                 .select('.tooltip-inner')
 
6911             var w = window.innerWidth,
 
6912                 h = window.innerHeight;
 
6914             if (box.top + box.height < Math.min(100, box.width + box.left)) {
 
6916                 pos = [box.left + box.width / 2 - dimensions[0]/ 2, box.top + box.height];
 
6918             } else if (box.left + box.width + 300 < window.innerWidth) {
 
6920                 pos = [box.left + box.width, box.top + box.height / 2 - dimensions[1] / 2];
 
6922             } else if (box.left > 300) {
 
6924                 pos = [box.left - 200, box.top + box.height / 2 - dimensions[1] / 2];
 
6927                 pos = [box.left, box.top + box.height];
 
6931                 Math.min(Math.max(10, pos[0]), w - dimensions[0] - 10),
 
6932                 Math.min(Math.max(10, pos[1]), h - dimensions[1] - 10)
 
6936             if (duration !== 0 || !tooltip.classed(side)) tooltip.call(iD.ui.Toggle(true));
 
6939                 .style('top', pos[1] + 'px')
 
6940                 .style('left', pos[0] + 'px')
 
6941                 .attr('class', 'curtain-tooltip tooltip in ' + side + ' ' + tooltipclass)
 
6942                 .select('.tooltip-inner')
 
6946             tooltip.call(iD.ui.Toggle(false));
 
6950     curtain.cut = function(datum, duration) {
 
6951         darkness.datum(datum);
 
6953         (duration === 0 ? darkness : darkness.transition().duration(duration || 600))
 
6954             .attr('d', function(d) {
 
6955                 var string = "M 0,0 L 0," + window.innerHeight + " L " +
 
6956                     window.innerWidth + "," + window.innerHeight + "L" +
 
6957                     window.innerWidth + ",0 Z";
 
6959                 if (!d) return string;
 
6960                 return string + 'M' +
 
6961                     d.left + ',' + d.top + 'L' +
 
6962                     d.left + ',' + (d.top + d.height) + 'L' +
 
6963                     (d.left + d.width) + ',' + (d.top + d.height) + 'L' +
 
6964                     (d.left + d.width) + ',' + (d.top) + 'Z';
 
6969     curtain.remove = function() {
 
6974     return d3.rebind(curtain, event, 'on');
 
6976 // Like selection.property('value', ...), but avoids no-op value sets,
 
6977 // which can result in layout/repaint thrashing in some situations.
 
6978 d3.selection.prototype.value = function(value) {
 
6979     function d3_selection_value(value) {
 
6980       function valueNull() {
 
6984       function valueConstant() {
 
6985         if (this.value !== value) this.value = value;
 
6988       function valueFunction() {
 
6989         var x = value.apply(this, arguments);
 
6990         if (x == null) delete this.value;
 
6991         else if (this.value !== x) this.value = x;
 
6994       return value == null
 
6995           ? valueNull : (typeof value === "function"
 
6996           ? valueFunction : valueConstant);
 
6999     if (!arguments.length) return this.property('value');
 
7000     return this.each(d3_selection_value(value));
 
7002 // Copyright (c) 2006, 2008 Tony Garnock-Jones <tonyg@lshift.net>
 
7003 // Copyright (c) 2006, 2008 LShift Ltd. <query@lshift.net>
 
7005 // Permission is hereby granted, free of charge, to any person
 
7006 // obtaining a copy of this software and associated documentation files
 
7007 // (the "Software"), to deal in the Software without restriction,
 
7008 // including without limitation the rights to use, copy, modify, merge,
 
7009 // publish, distribute, sublicense, and/or sell copies of the Software,
 
7010 // and to permit persons to whom the Software is furnished to do so,
 
7011 // subject to the following conditions:
 
7013 // The above copyright notice and this permission notice shall be
 
7014 // included in all copies or substantial portions of the Software.
 
7016 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 
7017 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 
7018 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 
7019 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
 
7020 // BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
 
7021 // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 
7022 // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 
7025 // source:  https://bitbucket.org/lshift/synchrotron/src
 
7027 Diff3 = (function() {
 
7031         longest_common_subsequence: function(file1, file2) {
 
7032             /* Text diff algorithm following Hunt and McIlroy 1976.
 
7033              * J. W. Hunt and M. D. McIlroy, An algorithm for differential file
 
7034              * comparison, Bell Telephone Laboratories CSTR #41 (1976)
 
7035              * http://www.cs.dartmouth.edu/~doug/
 
7037              * Expects two arrays of strings.
 
7039             var equivalenceClasses;
 
7044             var c, i, j, jX, r, s;
 
7046             equivalenceClasses = {};
 
7047             for (j = 0; j < file2.length; j++) {
 
7049                 if (equivalenceClasses[line]) {
 
7050                     equivalenceClasses[line].push(j);
 
7052                     equivalenceClasses[line] = [j];
 
7056             candidates = [{file1index: -1,
 
7060             for (i = 0; i < file1.length; i++) {
 
7062                 file2indices = equivalenceClasses[line] || [];
 
7067                 for (jX = 0; jX < file2indices.length; jX++) {
 
7068                     j = file2indices[jX];
 
7070                     for (s = 0; s < candidates.length; s++) {
 
7071                         if ((candidates[s].file2index < j) &&
 
7072                             ((s == candidates.length - 1) ||
 
7073                              (candidates[s + 1].file2index > j)))
 
7077                     if (s < candidates.length) {
 
7078                         newCandidate = {file1index: i,
 
7080                                         chain: candidates[s]};
 
7081                         if (r == candidates.length) {
 
7088                         if (r == candidates.length) {
 
7089                             break; // no point in examining further (j)s
 
7097             // At this point, we know the LCS: it's in the reverse of the
 
7098             // linked-list through .chain of
 
7099             // candidates[candidates.length - 1].
 
7101             return candidates[candidates.length - 1];
 
7104         diff_comm: function(file1, file2) {
 
7105             // We apply the LCS to build a "comm"-style picture of the
 
7106             // differences between file1 and file2.
 
7109             var tail1 = file1.length;
 
7110             var tail2 = file2.length;
 
7111             var common = {common: []};
 
7113             function processCommon() {
 
7114                 if (common.common.length) {
 
7115                     common.common.reverse();
 
7116                     result.push(common);
 
7117                     common = {common: []};
 
7121             for (var candidate = Diff3.longest_common_subsequence(file1, file2);
 
7123                  candidate = candidate.chain)
 
7125                 var different = {file1: [], file2: []};
 
7127                 while (--tail1 > candidate.file1index) {
 
7128                     different.file1.push(file1[tail1]);
 
7131                 while (--tail2 > candidate.file2index) {
 
7132                     different.file2.push(file2[tail2]);
 
7135                 if (different.file1.length || different.file2.length) {
 
7137                     different.file1.reverse();
 
7138                     different.file2.reverse();
 
7139                     result.push(different);
 
7143                     common.common.push(file1[tail1]);
 
7153         diff_patch: function(file1, file2) {
 
7154             // We apply the LCD to build a JSON representation of a
 
7155             // diff(1)-style patch.
 
7158             var tail1 = file1.length;
 
7159             var tail2 = file2.length;
 
7161             function chunkDescription(file, offset, length) {
 
7163                 for (var i = 0; i < length; i++) {
 
7164                     chunk.push(file[offset + i]);
 
7166                 return {offset: offset,
 
7171             for (var candidate = Diff3.longest_common_subsequence(file1, file2);
 
7173                  candidate = candidate.chain)
 
7175                 var mismatchLength1 = tail1 - candidate.file1index - 1;
 
7176                 var mismatchLength2 = tail2 - candidate.file2index - 1;
 
7177                 tail1 = candidate.file1index;
 
7178                 tail2 = candidate.file2index;
 
7180                 if (mismatchLength1 || mismatchLength2) {
 
7181                     result.push({file1: chunkDescription(file1,
 
7182                                                          candidate.file1index + 1,
 
7184                                  file2: chunkDescription(file2,
 
7185                                                          candidate.file2index + 1,
 
7194         strip_patch: function(patch) {
 
7195         // Takes the output of Diff3.diff_patch(), and removes
 
7196         // information from it. It can still be used by patch(),
 
7197         // below, but can no longer be inverted.
 
7199         for (var i = 0; i < patch.length; i++) {
 
7200             var chunk = patch[i];
 
7201             newpatch.push({file1: {offset: chunk.file1.offset,
 
7202                        length: chunk.file1.length},
 
7203                    file2: {chunk: chunk.file2.chunk}});
 
7208         invert_patch: function(patch) {
 
7209             // Takes the output of Diff3.diff_patch(), and inverts the
 
7210             // sense of it, so that it can be applied to file2 to give
 
7211             // file1 rather than the other way around.
 
7213             for (var i = 0; i < patch.length; i++) {
 
7214                 var chunk = patch[i];
 
7215                 var tmp = chunk.file1;
 
7216                 chunk.file1 = chunk.file2;
 
7221         patch: function (file, patch) {
 
7222             // Applies a patch to a file.
 
7224             // Given file1 and file2, Diff3.patch(file1,
 
7225             // Diff3.diff_patch(file1, file2)) should give file2.
 
7228             var commonOffset = 0;
 
7230             function copyCommon(targetOffset) {
 
7231                 while (commonOffset < targetOffset) {
 
7232                     result.push(file[commonOffset]);
 
7237             for (var chunkIndex = 0; chunkIndex < patch.length; chunkIndex++) {
 
7238                 var chunk = patch[chunkIndex];
 
7239                 copyCommon(chunk.file1.offset);
 
7240                 for (var lineIndex = 0; lineIndex < chunk.file2.chunk.length; lineIndex++) {
 
7241                     result.push(chunk.file2.chunk[lineIndex]);
 
7243                 commonOffset += chunk.file1.length;
 
7246             copyCommon(file.length);
 
7250         diff_indices: function(file1, file2) {
 
7251             // We apply the LCS to give a simple representation of the
 
7252             // offsets and lengths of mismatched chunks in the input
 
7253             // files. This is used by diff3_merge_indices below.
 
7256             var tail1 = file1.length;
 
7257             var tail2 = file2.length;
 
7259             for (var candidate = Diff3.longest_common_subsequence(file1, file2);
 
7261                  candidate = candidate.chain)
 
7263                 var mismatchLength1 = tail1 - candidate.file1index - 1;
 
7264                 var mismatchLength2 = tail2 - candidate.file2index - 1;
 
7265                 tail1 = candidate.file1index;
 
7266                 tail2 = candidate.file2index;
 
7268                 if (mismatchLength1 || mismatchLength2) {
 
7269                     result.push({file1: [tail1 + 1, mismatchLength1],
 
7270                                  file2: [tail2 + 1, mismatchLength2]});
 
7278         diff3_merge_indices: function (a, o, b) {
 
7279             // Given three files, A, O, and B, where both A and B are
 
7280             // independently derived from O, returns a fairly complicated
 
7281             // internal representation of merge decisions it's taken. The
 
7282             // interested reader may wish to consult
 
7284             // Sanjeev Khanna, Keshav Kunal, and Benjamin C. Pierce. "A
 
7285             // Formal Investigation of Diff3." In Arvind and Prasad,
 
7286             // editors, Foundations of Software Technology and Theoretical
 
7287             // Computer Science (FSTTCS), December 2007.
 
7289             // (http://www.cis.upenn.edu/~bcpierce/papers/diff3-short.pdf)
 
7292             var m1 = Diff3.diff_indices(o, a);
 
7293             var m2 = Diff3.diff_indices(o, b);
 
7296             function addHunk(h, side) {
 
7297                 hunks.push([h.file1[0], side, h.file1[1], h.file2[0], h.file2[1]]);
 
7299             for (i = 0; i < m1.length; i++) { addHunk(m1[i], 0); }
 
7300             for (i = 0; i < m2.length; i++) { addHunk(m2[i], 2); }
 
7304             var commonOffset = 0;
 
7305             function copyCommon(targetOffset) {
 
7306                 if (targetOffset > commonOffset) {
 
7307                     result.push([1, commonOffset, targetOffset - commonOffset]);
 
7308                     commonOffset = targetOffset;
 
7312             for (var hunkIndex = 0; hunkIndex < hunks.length; hunkIndex++) {
 
7313                 var firstHunkIndex = hunkIndex;
 
7314                 var hunk = hunks[hunkIndex];
 
7315                 var regionLhs = hunk[0];
 
7316                 var regionRhs = regionLhs + hunk[2];
 
7317                 while (hunkIndex < hunks.length - 1) {
 
7318                     var maybeOverlapping = hunks[hunkIndex + 1];
 
7319                     var maybeLhs = maybeOverlapping[0];
 
7320                     if (maybeLhs > regionRhs) break;
 
7321                     regionRhs = maybeLhs + maybeOverlapping[2];
 
7325                 copyCommon(regionLhs);
 
7326                 if (firstHunkIndex == hunkIndex) {
 
7327             // The "overlap" was only one hunk long, meaning that
 
7328             // there's no conflict here. Either a and o were the
 
7329             // same, or b and o were the same.
 
7331                         result.push([hunk[1], hunk[3], hunk[4]]);
 
7334             // A proper conflict. Determine the extents of the
 
7335             // regions involved from a, o and b. Effectively merge
 
7336             // all the hunks on the left into one giant hunk, and
 
7337             // do the same for the right; then, correct for skew
 
7338             // in the regions of o that each side changed, and
 
7339             // report appropriate spans for the three sides.
 
7341                 0: [a.length, -1, o.length, -1],
 
7342                 2: [b.length, -1, o.length, -1]
 
7344                     for (i = firstHunkIndex; i <= hunkIndex; i++) {
 
7347                 var r = regions[side];
 
7349                 var oRhs = oLhs + hunk[2];
 
7350                         var abLhs = hunk[3];
 
7351                         var abRhs = abLhs + hunk[4];
 
7352                 r[0] = Math.min(abLhs, r[0]);
 
7353                 r[1] = Math.max(abRhs, r[1]);
 
7354                 r[2] = Math.min(oLhs, r[2]);
 
7355                 r[3] = Math.max(oRhs, r[3]);
 
7357             var aLhs = regions[0][0] + (regionLhs - regions[0][2]);
 
7358             var aRhs = regions[0][1] + (regionRhs - regions[0][3]);
 
7359             var bLhs = regions[2][0] + (regionLhs - regions[2][2]);
 
7360             var bRhs = regions[2][1] + (regionRhs - regions[2][3]);
 
7363                      regionLhs, regionRhs - regionLhs,
 
7364                      bLhs,      bRhs      - bLhs]);
 
7366                 commonOffset = regionRhs;
 
7369             copyCommon(o.length);
 
7373         diff3_merge: function (a, o, b, excludeFalseConflicts) {
 
7374             // Applies the output of Diff3.diff3_merge_indices to actually
 
7375             // construct the merged file; the returned result alternates
 
7376             // between "ok" and "conflict" blocks.
 
7379             var files = [a, o, b];
 
7380             var indices = Diff3.diff3_merge_indices(a, o, b);
 
7383             function flushOk() {
 
7384                 if (okLines.length) {
 
7385                     result.push({ok: okLines});
 
7389             function pushOk(xs) {
 
7390                 for (var j = 0; j < xs.length; j++) {
 
7391                     okLines.push(xs[j]);
 
7395             function isTrueConflict(rec) {
 
7396                 if (rec[2] != rec[6]) return true;
 
7399                 for (var j = 0; j < rec[2]; j++) {
 
7400                     if (a[j + aoff] != b[j + boff]) return true;
 
7405             for (var i = 0; i < indices.length; i++) {
 
7409                     if (excludeFalseConflicts && !isTrueConflict(x)) {
 
7410                         pushOk(files[0].slice(x[1], x[1] + x[2]));
 
7413                         result.push({conflict: {a: a.slice(x[1], x[1] + x[2]),
 
7415                                                 o: o.slice(x[3], x[3] + x[4]),
 
7417                                                 b: b.slice(x[5], x[5] + x[6]),
 
7421                     pushOk(files[side].slice(x[1], x[1] + x[2]));
 
7432 if (typeof module !== 'undefined') module.exports = Diff3;
 
7433 var JXON = new (function () {
 
7435     sValueProp = "keyValue", sAttributesProp = "keyAttributes", sAttrPref = "@", /* you can customize these values */
 
7436     aCache = [], rIsNull = /^\s*$/, rIsBool = /^(?:true|false)$/i;
 
7438   function parseText (sValue) {
 
7439     if (rIsNull.test(sValue)) { return null; }
 
7440     if (rIsBool.test(sValue)) { return sValue.toLowerCase() === "true"; }
 
7441     if (isFinite(sValue)) { return parseFloat(sValue); }
 
7442     if (isFinite(Date.parse(sValue))) { return new Date(sValue); }
 
7446   function EmptyTree () { }
 
7447   EmptyTree.prototype.toString = function () { return "null"; };
 
7448   EmptyTree.prototype.valueOf = function () { return null; };
 
7450   function objectify (vValue) {
 
7451     return vValue === null ? new EmptyTree() : vValue instanceof Object ? vValue : new vValue.constructor(vValue);
 
7454   function createObjTree (oParentNode, nVerb, bFreeze, bNesteAttr) {
 
7456       nLevelStart = aCache.length, bChildren = oParentNode.hasChildNodes(),
 
7457       bAttributes = oParentNode.hasAttributes(), bHighVerb = Boolean(nVerb & 2);
 
7460       sProp, vContent, nLength = 0, sCollectedTxt = "",
 
7461       vResult = bHighVerb ? {} : /* put here the default value for empty nodes: */ true;
 
7464       for (var oNode, nItem = 0; nItem < oParentNode.childNodes.length; nItem++) {
 
7465         oNode = oParentNode.childNodes.item(nItem);
 
7466         if (oNode.nodeType === 4) { sCollectedTxt += oNode.nodeValue; } /* nodeType is "CDATASection" (4) */
 
7467         else if (oNode.nodeType === 3) { sCollectedTxt += oNode.nodeValue.trim(); } /* nodeType is "Text" (3) */
 
7468         else if (oNode.nodeType === 1 && !oNode.prefix) { aCache.push(oNode); } /* nodeType is "Element" (1) */
 
7472     var nLevelEnd = aCache.length, vBuiltVal = parseText(sCollectedTxt);
 
7474     if (!bHighVerb && (bChildren || bAttributes)) { vResult = nVerb === 0 ? objectify(vBuiltVal) : {}; }
 
7476     for (var nElId = nLevelStart; nElId < nLevelEnd; nElId++) {
 
7477       sProp = aCache[nElId].nodeName.toLowerCase();
 
7478       vContent = createObjTree(aCache[nElId], nVerb, bFreeze, bNesteAttr);
 
7479       if (vResult.hasOwnProperty(sProp)) {
 
7480         if (vResult[sProp].constructor !== Array) { vResult[sProp] = [vResult[sProp]]; }
 
7481         vResult[sProp].push(vContent);
 
7483         vResult[sProp] = vContent;
 
7490         nAttrLen = oParentNode.attributes.length,
 
7491         sAPrefix = bNesteAttr ? "" : sAttrPref, oAttrParent = bNesteAttr ? {} : vResult;
 
7493       for (var oAttrib, nAttrib = 0; nAttrib < nAttrLen; nLength++, nAttrib++) {
 
7494         oAttrib = oParentNode.attributes.item(nAttrib);
 
7495         oAttrParent[sAPrefix + oAttrib.name.toLowerCase()] = parseText(oAttrib.value.trim());
 
7499         if (bFreeze) { Object.freeze(oAttrParent); }
 
7500         vResult[sAttributesProp] = oAttrParent;
 
7501         nLength -= nAttrLen - 1;
 
7505     if (nVerb === 3 || (nVerb === 2 || nVerb === 1 && nLength > 0) && sCollectedTxt) {
 
7506       vResult[sValueProp] = vBuiltVal;
 
7507     } else if (!bHighVerb && nLength === 0 && sCollectedTxt) {
 
7508       vResult = vBuiltVal;
 
7511     if (bFreeze && (bHighVerb || nLength > 0)) { Object.freeze(vResult); }
 
7513     aCache.length = nLevelStart;
 
7518   function loadObjTree (oXMLDoc, oParentEl, oParentObj) {
 
7521     if (oParentObj instanceof String || oParentObj instanceof Number || oParentObj instanceof Boolean) {
 
7522       oParentEl.appendChild(oXMLDoc.createTextNode(oParentObj.toString())); /* verbosity level is 0 */
 
7523     } else if (oParentObj.constructor === Date) {
 
7524       oParentEl.appendChild(oXMLDoc.createTextNode(oParentObj.toGMTString()));    
 
7527     for (var sName in oParentObj) {
 
7528       vValue = oParentObj[sName];
 
7529       if (isFinite(sName) || vValue instanceof Function) { continue; } /* verbosity level is 0 */
 
7530       if (sName === sValueProp) {
 
7531         if (vValue !== null && vValue !== true) { oParentEl.appendChild(oXMLDoc.createTextNode(vValue.constructor === Date ? vValue.toGMTString() : String(vValue))); }
 
7532       } else if (sName === sAttributesProp) { /* verbosity level is 3 */
 
7533         for (var sAttrib in vValue) { oParentEl.setAttribute(sAttrib, vValue[sAttrib]); }
 
7534       } else if (sName.charAt(0) === sAttrPref) {
 
7535         oParentEl.setAttribute(sName.slice(1), vValue);
 
7536       } else if (vValue.constructor === Array) {
 
7537         for (var nItem = 0; nItem < vValue.length; nItem++) {
 
7538           oChild = oXMLDoc.createElement(sName);
 
7539           loadObjTree(oXMLDoc, oChild, vValue[nItem]);
 
7540           oParentEl.appendChild(oChild);
 
7543         oChild = oXMLDoc.createElement(sName);
 
7544         if (vValue instanceof Object) {
 
7545           loadObjTree(oXMLDoc, oChild, vValue);
 
7546         } else if (vValue !== null && vValue !== true) {
 
7547           oChild.appendChild(oXMLDoc.createTextNode(vValue.toString()));
 
7549         oParentEl.appendChild(oChild);
 
7554   this.build = function (oXMLParent, nVerbosity /* optional */, bFreeze /* optional */, bNesteAttributes /* optional */) {
 
7555     var _nVerb = arguments.length > 1 && typeof nVerbosity === "number" ? nVerbosity & 3 : /* put here the default verbosity level: */ 1;
 
7556     return createObjTree(oXMLParent, _nVerb, bFreeze || false, arguments.length > 3 ? bNesteAttributes : _nVerb === 3);    
 
7559   this.unbuild = function (oObjTree) {    
 
7560     var oNewDoc = document.implementation.createDocument("", "", null);
 
7561     loadObjTree(oNewDoc, oNewDoc, oObjTree);
 
7565   this.stringify = function (oObjTree) {
 
7566     return (new XMLSerializer()).serializeToString(JXON.unbuild(oObjTree));
 
7569 // var myObject = JXON.build(doc);
 
7570 // we got our javascript object! try: alert(JSON.stringify(myObject));
 
7572 // var newDoc = JXON.unbuild(myObject);
 
7573 // we got our Document instance! try: alert((new XMLSerializer()).serializeToString(newDoc));
 
7576  * lodash 3.9.3 (Custom Build) <https://lodash.com/>
 
7577  * Build: `lodash --development --output js/lib/lodash.js include="any,assign,bind,chunk,clone,compact,contains,debounce,difference,each,every,extend,filter,find,first,forEach,forOwn,groupBy,indexOf,intersection,isEmpty,isEqual,isFunction,keys,last,map,omit,pairs,pluck,reject,some,throttle,union,uniq,unique,values,without,flatten,value,chain,cloneDeep,merge,pick,reduce" exports="global,node"`
 
7578  * Copyright 2012-2015 The Dojo Foundation <http://dojofoundation.org/>
 
7579  * Based on Underscore.js 1.8.3 <http://underscorejs.org/LICENSE>
 
7580  * Copyright 2009-2015 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
 
7581  * Available under MIT license <https://lodash.com/license>
 
7585   /** Used as a safe reference for `undefined` in pre-ES5 environments. */
 
7588   /** Used as the semantic version number. */
 
7589   var VERSION = '3.9.3';
 
7591   /** Used to compose bitmasks for wrapper metadata. */
 
7594       CURRY_BOUND_FLAG = 4,
 
7596       CURRY_RIGHT_FLAG = 16,
 
7598       PARTIAL_RIGHT_FLAG = 64,
 
7602   /** Used to detect when a function becomes hot. */
 
7603   var HOT_COUNT = 150,
 
7606   /** Used to indicate the type of lazy iteratees. */
 
7607   var LAZY_DROP_WHILE_FLAG = 0,
 
7608       LAZY_FILTER_FLAG = 1,
 
7611   /** Used as the `TypeError` message for "Functions" methods. */
 
7612   var FUNC_ERROR_TEXT = 'Expected a function';
 
7614   /** Used as the internal argument placeholder. */
 
7615   var PLACEHOLDER = '__lodash_placeholder__';
 
7617   /** `Object#toString` result references. */
 
7618   var argsTag = '[object Arguments]',
 
7619       arrayTag = '[object Array]',
 
7620       boolTag = '[object Boolean]',
 
7621       dateTag = '[object Date]',
 
7622       errorTag = '[object Error]',
 
7623       funcTag = '[object Function]',
 
7624       mapTag = '[object Map]',
 
7625       numberTag = '[object Number]',
 
7626       objectTag = '[object Object]',
 
7627       regexpTag = '[object RegExp]',
 
7628       setTag = '[object Set]',
 
7629       stringTag = '[object String]',
 
7630       weakMapTag = '[object WeakMap]';
 
7632   var arrayBufferTag = '[object ArrayBuffer]',
 
7633       float32Tag = '[object Float32Array]',
 
7634       float64Tag = '[object Float64Array]',
 
7635       int8Tag = '[object Int8Array]',
 
7636       int16Tag = '[object Int16Array]',
 
7637       int32Tag = '[object Int32Array]',
 
7638       uint8Tag = '[object Uint8Array]',
 
7639       uint8ClampedTag = '[object Uint8ClampedArray]',
 
7640       uint16Tag = '[object Uint16Array]',
 
7641       uint32Tag = '[object Uint32Array]';
 
7643   /** Used to match property names within property paths. */
 
7644   var reIsDeepProp = /\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\n\\]|\\.)*?\1)\]/,
 
7645       reIsPlainProp = /^\w*$/,
 
7646       rePropName = /[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\n\\]|\\.)*?)\2)\]/g;
 
7649    * Used to match `RegExp` [special characters](http://www.regular-expressions.info/characters.html#special).
 
7650    * In addition to special characters the forward slash is escaped to allow for
 
7651    * easier `eval` use and `Function` compilation.
 
7653   var reRegExpChars = /[.*+?^${}()|[\]\/\\]/g,
 
7654       reHasRegExpChars = RegExp(reRegExpChars.source);
 
7656   /** Used to match backslashes in property paths. */
 
7657   var reEscapeChar = /\\(\\)?/g;
 
7659   /** Used to match `RegExp` flags from their coerced string values. */
 
7660   var reFlags = /\w*$/;
 
7662   /** Used to detect host constructors (Safari > 5). */
 
7663   var reIsHostCtor = /^\[object .+?Constructor\]$/;
 
7665   /** Used to detect unsigned integer values. */
 
7666   var reIsUint = /^\d+$/;
 
7668   /** Used to fix the JScript `[[DontEnum]]` bug. */
 
7670     'constructor', 'hasOwnProperty', 'isPrototypeOf', 'propertyIsEnumerable',
 
7671     'toLocaleString', 'toString', 'valueOf'
 
7674   /** Used to identify `toStringTag` values of typed arrays. */
 
7675   var typedArrayTags = {};
 
7676   typedArrayTags[float32Tag] = typedArrayTags[float64Tag] =
 
7677   typedArrayTags[int8Tag] = typedArrayTags[int16Tag] =
 
7678   typedArrayTags[int32Tag] = typedArrayTags[uint8Tag] =
 
7679   typedArrayTags[uint8ClampedTag] = typedArrayTags[uint16Tag] =
 
7680   typedArrayTags[uint32Tag] = true;
 
7681   typedArrayTags[argsTag] = typedArrayTags[arrayTag] =
 
7682   typedArrayTags[arrayBufferTag] = typedArrayTags[boolTag] =
 
7683   typedArrayTags[dateTag] = typedArrayTags[errorTag] =
 
7684   typedArrayTags[funcTag] = typedArrayTags[mapTag] =
 
7685   typedArrayTags[numberTag] = typedArrayTags[objectTag] =
 
7686   typedArrayTags[regexpTag] = typedArrayTags[setTag] =
 
7687   typedArrayTags[stringTag] = typedArrayTags[weakMapTag] = false;
 
7689   /** Used to identify `toStringTag` values supported by `_.clone`. */
 
7690   var cloneableTags = {};
 
7691   cloneableTags[argsTag] = cloneableTags[arrayTag] =
 
7692   cloneableTags[arrayBufferTag] = cloneableTags[boolTag] =
 
7693   cloneableTags[dateTag] = cloneableTags[float32Tag] =
 
7694   cloneableTags[float64Tag] = cloneableTags[int8Tag] =
 
7695   cloneableTags[int16Tag] = cloneableTags[int32Tag] =
 
7696   cloneableTags[numberTag] = cloneableTags[objectTag] =
 
7697   cloneableTags[regexpTag] = cloneableTags[stringTag] =
 
7698   cloneableTags[uint8Tag] = cloneableTags[uint8ClampedTag] =
 
7699   cloneableTags[uint16Tag] = cloneableTags[uint32Tag] = true;
 
7700   cloneableTags[errorTag] = cloneableTags[funcTag] =
 
7701   cloneableTags[mapTag] = cloneableTags[setTag] =
 
7702   cloneableTags[weakMapTag] = false;
 
7704   /** Used as an internal `_.debounce` options object by `_.throttle`. */
 
7705   var debounceOptions = {
 
7711   /** Used to determine if values are of the language type `Object`. */
 
7717   /** Detect free variable `exports`. */
 
7718   var freeExports = objectTypes[typeof exports] && exports && !exports.nodeType && exports;
 
7720   /** Detect free variable `module`. */
 
7721   var freeModule = objectTypes[typeof module] && module && !module.nodeType && module;
 
7723   /** Detect free variable `global` from Node.js. */
 
7724   var freeGlobal = freeExports && freeModule && typeof global == 'object' && global && global.Object && global;
 
7726   /** Detect free variable `self`. */
 
7727   var freeSelf = objectTypes[typeof self] && self && self.Object && self;
 
7729   /** Detect free variable `window`. */
 
7730   var freeWindow = objectTypes[typeof window] && window && window.Object && window;
 
7732   /** Detect the popular CommonJS extension `module.exports`. */
 
7733   var moduleExports = freeModule && freeModule.exports === freeExports && freeExports;
 
7736    * Used as a reference to the global object.
 
7738    * The `this` value is used if it's the global object to avoid Greasemonkey's
 
7739    * restricted `window` object, otherwise the `window` object is used.
 
7741   var root = freeGlobal || ((freeWindow !== (this && this.window)) && freeWindow) || freeSelf || this;
 
7743   /*--------------------------------------------------------------------------*/
 
7746    * The base implementation of `_.findIndex` and `_.findLastIndex` without
 
7747    * support for callback shorthands and `this` binding.
 
7750    * @param {Array} array The array to search.
 
7751    * @param {Function} predicate The function invoked per iteration.
 
7752    * @param {boolean} [fromRight] Specify iterating from right to left.
 
7753    * @returns {number} Returns the index of the matched value, else `-1`.
 
7755   function baseFindIndex(array, predicate, fromRight) {
 
7756     var length = array.length,
 
7757         index = fromRight ? length : -1;
 
7759     while ((fromRight ? index-- : ++index < length)) {
 
7760       if (predicate(array[index], index, array)) {
 
7768    * The base implementation of `_.indexOf` without support for binary searches.
 
7771    * @param {Array} array The array to search.
 
7772    * @param {*} value The value to search for.
 
7773    * @param {number} fromIndex The index to search from.
 
7774    * @returns {number} Returns the index of the matched value, else `-1`.
 
7776   function baseIndexOf(array, value, fromIndex) {
 
7777     if (value !== value) {
 
7778       return indexOfNaN(array, fromIndex);
 
7780     var index = fromIndex - 1,
 
7781         length = array.length;
 
7783     while (++index < length) {
 
7784       if (array[index] === value) {
 
7792    * The base implementation of `_.isFunction` without support for environments
 
7793    * with incorrect `typeof` results.
 
7796    * @param {*} value The value to check.
 
7797    * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`.
 
7799   function baseIsFunction(value) {
 
7800     // Avoid a Chakra JIT bug in compatibility modes of IE 11.
 
7801     // See https://github.com/jashkenas/underscore/issues/1621 for more details.
 
7802     return typeof value == 'function' || false;
 
7806    * Converts `value` to a string if it's not one. An empty string is returned
 
7807    * for `null` or `undefined` values.
 
7810    * @param {*} value The value to process.
 
7811    * @returns {string} Returns the string.
 
7813   function baseToString(value) {
 
7814     if (typeof value == 'string') {
 
7817     return value == null ? '' : (value + '');
 
7821    * Gets the index at which the first occurrence of `NaN` is found in `array`.
 
7824    * @param {Array} array The array to search.
 
7825    * @param {number} fromIndex The index to search from.
 
7826    * @param {boolean} [fromRight] Specify iterating from right to left.
 
7827    * @returns {number} Returns the index of the matched `NaN`, else `-1`.
 
7829   function indexOfNaN(array, fromIndex, fromRight) {
 
7830     var length = array.length,
 
7831         index = fromIndex + (fromRight ? 0 : -1);
 
7833     while ((fromRight ? index-- : ++index < length)) {
 
7834       var other = array[index];
 
7835       if (other !== other) {
 
7843    * Checks if `value` is a host object in IE < 9.
 
7846    * @param {*} value The value to check.
 
7847    * @returns {boolean} Returns `true` if `value` is a host object, else `false`.
 
7849   var isHostObject = (function() {
 
7851       Object({ 'toString': 0 } + '');
 
7853       return function() { return false; };
 
7855     return function(value) {
 
7856       // IE < 9 presents many host objects as `Object` objects that can coerce
 
7857       // to strings despite having improperly defined `toString` methods.
 
7858       return typeof value.toString != 'function' && typeof (value + '') == 'string';
 
7863    * Checks if `value` is object-like.
 
7866    * @param {*} value The value to check.
 
7867    * @returns {boolean} Returns `true` if `value` is object-like, else `false`.
 
7869   function isObjectLike(value) {
 
7870     return !!value && typeof value == 'object';
 
7874    * Replaces all `placeholder` elements in `array` with an internal placeholder
 
7875    * and returns an array of their indexes.
 
7878    * @param {Array} array The array to modify.
 
7879    * @param {*} placeholder The placeholder to replace.
 
7880    * @returns {Array} Returns the new array of placeholder indexes.
 
7882   function replaceHolders(array, placeholder) {
 
7884         length = array.length,
 
7888     while (++index < length) {
 
7889       if (array[index] === placeholder) {
 
7890         array[index] = PLACEHOLDER;
 
7891         result[++resIndex] = index;
 
7898    * An implementation of `_.uniq` optimized for sorted arrays without support
 
7899    * for callback shorthands and `this` binding.
 
7902    * @param {Array} array The array to inspect.
 
7903    * @param {Function} [iteratee] The function invoked per iteration.
 
7904    * @returns {Array} Returns the new duplicate-value-free array.
 
7906   function sortedUniq(array, iteratee) {
 
7909         length = array.length,
 
7913     while (++index < length) {
 
7914       var value = array[index],
 
7915           computed = iteratee ? iteratee(value, index, array) : value;
 
7917       if (!index || seen !== computed) {
 
7919         result[++resIndex] = value;
 
7925   /*--------------------------------------------------------------------------*/
 
7927   /** Used for native method references. */
 
7928   var arrayProto = Array.prototype,
 
7929       errorProto = Error.prototype,
 
7930       objectProto = Object.prototype,
 
7931       stringProto = String.prototype;
 
7933   /** Used to resolve the decompiled source of functions. */
 
7934   var fnToString = Function.prototype.toString;
 
7936   /** Used to check objects for own properties. */
 
7937   var hasOwnProperty = objectProto.hasOwnProperty;
 
7940    * Used to resolve the [`toStringTag`](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-object.prototype.tostring)
 
7943   var objToString = objectProto.toString;
 
7945   /** Used to detect if a method is native. */
 
7946   var reIsNative = RegExp('^' +
 
7947     escapeRegExp(fnToString.call(hasOwnProperty))
 
7948     .replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g, '$1.*?') + '$'
 
7951   /** Native method references. */
 
7952   var ArrayBuffer = getNative(root, 'ArrayBuffer'),
 
7953       bufferSlice = getNative(ArrayBuffer && new ArrayBuffer(0), 'slice'),
 
7956       getPrototypeOf = getNative(Object, 'getPrototypeOf'),
 
7957       push = arrayProto.push,
 
7958       propertyIsEnumerable = objectProto.propertyIsEnumerable,
 
7959       Set = getNative(root, 'Set'),
 
7960       splice = arrayProto.splice,
 
7961       Uint8Array = getNative(root, 'Uint8Array'),
 
7962       WeakMap = getNative(root, 'WeakMap');
 
7964   /** Used to clone array buffers. */
 
7965   var Float64Array = (function() {
 
7966     // Safari 5 errors when using an array buffer to initialize a typed array
 
7967     // where the array buffer's `byteLength` is not a multiple of the typed
 
7968     // array's `BYTES_PER_ELEMENT`.
 
7970       var func = getNative(root, 'Float64Array'),
 
7971           result = new func(new ArrayBuffer(10), 0, 1) && func;
 
7973     return result || null;
 
7976   /* Native method references for those with the same name as other `lodash` methods. */
 
7977   var nativeCreate = getNative(Object, 'create'),
 
7978       nativeIsArray = getNative(Array, 'isArray'),
 
7979       nativeKeys = getNative(Object, 'keys'),
 
7980       nativeMax = Math.max,
 
7981       nativeMin = Math.min,
 
7982       nativeNow = getNative(Date, 'now');
 
7984   /** Used as references for `-Infinity` and `Infinity`. */
 
7985   var POSITIVE_INFINITY = Number.POSITIVE_INFINITY;
 
7987   /** Used as references for the maximum length and index of an array. */
 
7988   var MAX_ARRAY_LENGTH = 4294967295,
 
7989       MAX_ARRAY_INDEX = MAX_ARRAY_LENGTH - 1,
 
7990       HALF_MAX_ARRAY_LENGTH = MAX_ARRAY_LENGTH >>> 1;
 
7992   /** Used as the size, in bytes, of each `Float64Array` element. */
 
7993   var FLOAT64_BYTES_PER_ELEMENT = Float64Array ? Float64Array.BYTES_PER_ELEMENT : 0;
 
7996    * Used as the [maximum length](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-number.max_safe_integer)
 
7997    * of an array-like value.
 
7999   var MAX_SAFE_INTEGER = 9007199254740991;
 
8001   /** Used to store function metadata. */
 
8002   var metaMap = WeakMap && new WeakMap;
 
8004   /** Used to lookup unminified function names. */
 
8007   /** Used to lookup a type array constructors by `toStringTag`. */
 
8009   ctorByTag[float32Tag] = root.Float32Array;
 
8010   ctorByTag[float64Tag] = root.Float64Array;
 
8011   ctorByTag[int8Tag] = root.Int8Array;
 
8012   ctorByTag[int16Tag] = root.Int16Array;
 
8013   ctorByTag[int32Tag] = root.Int32Array;
 
8014   ctorByTag[uint8Tag] = root.Uint8Array;
 
8015   ctorByTag[uint8ClampedTag] = root.Uint8ClampedArray;
 
8016   ctorByTag[uint16Tag] = root.Uint16Array;
 
8017   ctorByTag[uint32Tag] = root.Uint32Array;
 
8019   /** Used to avoid iterating over non-enumerable properties in IE < 9. */
 
8020   var nonEnumProps = {};
 
8021   nonEnumProps[arrayTag] = nonEnumProps[dateTag] = nonEnumProps[numberTag] = { 'constructor': true, 'toLocaleString': true, 'toString': true, 'valueOf': true };
 
8022   nonEnumProps[boolTag] = nonEnumProps[stringTag] = { 'constructor': true, 'toString': true, 'valueOf': true };
 
8023   nonEnumProps[errorTag] = nonEnumProps[funcTag] = nonEnumProps[regexpTag] = { 'constructor': true, 'toString': true };
 
8024   nonEnumProps[objectTag] = { 'constructor': true };
 
8026   arrayEach(shadowProps, function(key) {
 
8027     for (var tag in nonEnumProps) {
 
8028       if (hasOwnProperty.call(nonEnumProps, tag)) {
 
8029         var props = nonEnumProps[tag];
 
8030         props[key] = hasOwnProperty.call(props, key);
 
8035   /*------------------------------------------------------------------------*/
 
8038    * Creates a `lodash` object which wraps `value` to enable implicit chaining.
 
8039    * Methods that operate on and return arrays, collections, and functions can
 
8040    * be chained together. Methods that return a boolean or single value will
 
8041    * automatically end the chain returning the unwrapped value. Explicit chaining
 
8042    * may be enabled using `_.chain`. The execution of chained methods is lazy,
 
8043    * that is, execution is deferred until `_#value` is implicitly or explicitly
 
8046    * Lazy evaluation allows several methods to support shortcut fusion. Shortcut
 
8047    * fusion is an optimization that merges iteratees to avoid creating intermediate
 
8048    * arrays and reduce the number of iteratee executions.
 
8050    * Chaining is supported in custom builds as long as the `_#value` method is
 
8051    * directly or indirectly included in the build.
 
8053    * In addition to lodash methods, wrappers have `Array` and `String` methods.
 
8055    * The wrapper `Array` methods are:
 
8056    * `concat`, `join`, `pop`, `push`, `reverse`, `shift`, `slice`, `sort`,
 
8057    * `splice`, and `unshift`
 
8059    * The wrapper `String` methods are:
 
8060    * `replace` and `split`
 
8062    * The wrapper methods that support shortcut fusion are:
 
8063    * `compact`, `drop`, `dropRight`, `dropRightWhile`, `dropWhile`, `filter`,
 
8064    * `first`, `initial`, `last`, `map`, `pluck`, `reject`, `rest`, `reverse`,
 
8065    * `slice`, `take`, `takeRight`, `takeRightWhile`, `takeWhile`, `toArray`,
 
8068    * The chainable wrapper methods are:
 
8069    * `after`, `ary`, `assign`, `at`, `before`, `bind`, `bindAll`, `bindKey`,
 
8070    * `callback`, `chain`, `chunk`, `commit`, `compact`, `concat`, `constant`,
 
8071    * `countBy`, `create`, `curry`, `debounce`, `defaults`, `defer`, `delay`,
 
8072    * `difference`, `drop`, `dropRight`, `dropRightWhile`, `dropWhile`, `fill`,
 
8073    * `filter`, `flatten`, `flattenDeep`, `flow`, `flowRight`, `forEach`,
 
8074    * `forEachRight`, `forIn`, `forInRight`, `forOwn`, `forOwnRight`, `functions`,
 
8075    * `groupBy`, `indexBy`, `initial`, `intersection`, `invert`, `invoke`, `keys`,
 
8076    * `keysIn`, `map`, `mapKeys`, `mapValues`, `matches`, `matchesProperty`,
 
8077    * `memoize`, `merge`, `method`, `methodOf`, `mixin`, `negate`, `omit`, `once`,
 
8078    * `pairs`, `partial`, `partialRight`, `partition`, `pick`, `plant`, `pluck`,
 
8079    * `property`, `propertyOf`, `pull`, `pullAt`, `push`, `range`, `rearg`,
 
8080    * `reject`, `remove`, `rest`, `restParam`, `reverse`, `set`, `shuffle`,
 
8081    * `slice`, `sort`, `sortBy`, `sortByAll`, `sortByOrder`, `splice`, `spread`,
 
8082    * `take`, `takeRight`, `takeRightWhile`, `takeWhile`, `tap`, `throttle`,
 
8083    * `thru`, `times`, `toArray`, `toPlainObject`, `transform`, `union`, `uniq`,
 
8084    * `unshift`, `unzip`, `unzipWith`, `values`, `valuesIn`, `where`, `without`,
 
8085    * `wrap`, `xor`, `zip`, `zipObject`, `zipWith`
 
8087    * The wrapper methods that are **not** chainable by default are:
 
8088    * `add`, `attempt`, `camelCase`, `capitalize`, `clone`, `cloneDeep`, `deburr`,
 
8089    * `endsWith`, `escape`, `escapeRegExp`, `every`, `find`, `findIndex`, `findKey`,
 
8090    * `findLast`, `findLastIndex`, `findLastKey`, `findWhere`, `first`, `get`,
 
8091    * `gt`, `gte`, `has`, `identity`, `includes`, `indexOf`, `inRange`, `isArguments`,
 
8092    * `isArray`, `isBoolean`, `isDate`, `isElement`, `isEmpty`, `isEqual`, `isError`,
 
8093    * `isFinite` `isFunction`, `isMatch`, `isNative`, `isNaN`, `isNull`, `isNumber`,
 
8094    * `isObject`, `isPlainObject`, `isRegExp`, `isString`, `isUndefined`,
 
8095    * `isTypedArray`, `join`, `kebabCase`, `last`, `lastIndexOf`, `lt`, `lte`,
 
8096    * `max`, `min`, `noConflict`, `noop`, `now`, `pad`, `padLeft`, `padRight`,
 
8097    * `parseInt`, `pop`, `random`, `reduce`, `reduceRight`, `repeat`, `result`,
 
8098    * `runInContext`, `shift`, `size`, `snakeCase`, `some`, `sortedIndex`,
 
8099    * `sortedLastIndex`, `startCase`, `startsWith`, `sum`, `template`, `trim`,
 
8100    * `trimLeft`, `trimRight`, `trunc`, `unescape`, `uniqueId`, `value`, and `words`
 
8102    * The wrapper method `sample` will return a wrapped value when `n` is provided,
 
8103    * otherwise an unwrapped value is returned.
 
8108    * @param {*} value The value to wrap in a `lodash` instance.
 
8109    * @returns {Object} Returns the new `lodash` wrapper instance.
 
8112    * var wrapped = _([1, 2, 3]);
 
8114    * // returns an unwrapped value
 
8115    * wrapped.reduce(function(total, n) {
 
8120    * // returns a wrapped value
 
8121    * var squares = wrapped.map(function(n) {
 
8125    * _.isArray(squares);
 
8128    * _.isArray(squares.value());
 
8131   function lodash(value) {
 
8132     if (isObjectLike(value) && !isArray(value) && !(value instanceof LazyWrapper)) {
 
8133       if (value instanceof LodashWrapper) {
 
8136       if (hasOwnProperty.call(value, '__chain__') && hasOwnProperty.call(value, '__wrapped__')) {
 
8137         return wrapperClone(value);
 
8140     return new LodashWrapper(value);
 
8144    * The function whose prototype all chaining wrappers inherit from.
 
8148   function baseLodash() {
 
8149     // No operation performed.
 
8153    * The base constructor for creating `lodash` wrapper objects.
 
8156    * @param {*} value The value to wrap.
 
8157    * @param {boolean} [chainAll] Enable chaining for all wrapper methods.
 
8158    * @param {Array} [actions=[]] Actions to peform to resolve the unwrapped value.
 
8160   function LodashWrapper(value, chainAll, actions) {
 
8161     this.__wrapped__ = value;
 
8162     this.__actions__ = actions || [];
 
8163     this.__chain__ = !!chainAll;
 
8167    * An object environment feature flags.
 
8173   var support = lodash.support = {};
 
8176     var Ctor = function() { this.x = x; },
 
8177         object = { '0': x, 'length': x },
 
8180     Ctor.prototype = { 'valueOf': x, 'y': x };
 
8181     for (var key in new Ctor) { props.push(key); }
 
8184      * Detect if the `toStringTag` of `arguments` objects is resolvable
 
8185      * (all but Firefox < 4, IE < 9).
 
8187      * @memberOf _.support
 
8190     support.argsTag = objToString.call(arguments) == argsTag;
 
8193      * Detect if `name` or `message` properties of `Error.prototype` are
 
8194      * enumerable by default (IE < 9, Safari < 5.1).
 
8196      * @memberOf _.support
 
8199     support.enumErrorProps = propertyIsEnumerable.call(errorProto, 'message') ||
 
8200       propertyIsEnumerable.call(errorProto, 'name');
 
8203      * Detect if `prototype` properties are enumerable by default.
 
8205      * Firefox < 3.6, Opera > 9.50 - Opera < 11.60, and Safari < 5.1
 
8206      * (if the prototype or a property on the prototype has been set)
 
8207      * incorrectly set the `[[Enumerable]]` value of a function's `prototype`
 
8208      * property to `true`.
 
8210      * @memberOf _.support
 
8213     support.enumPrototypes = propertyIsEnumerable.call(Ctor, 'prototype');
 
8216      * Detect if properties shadowing those on `Object.prototype` are non-enumerable.
 
8218      * In IE < 9 an object's own properties, shadowing non-enumerable ones,
 
8219      * are made non-enumerable as well (a.k.a the JScript `[[DontEnum]]` bug).
 
8221      * @memberOf _.support
 
8224     support.nonEnumShadows = !/valueOf/.test(props);
 
8227      * Detect if own properties are iterated after inherited properties (IE < 9).
 
8229      * @memberOf _.support
 
8232     support.ownLast = props[0] != 'x';
 
8235      * Detect if `Array#shift` and `Array#splice` augment array-like objects
 
8238      * Firefox < 10, compatibility modes of IE 8, and IE < 9 have buggy Array
 
8239      * `shift()` and `splice()` functions that fail to remove the last element,
 
8240      * `value[0]`, of array-like objects even though the "length" property is
 
8241      * set to `0`. The `shift()` method is buggy in compatibility modes of IE 8,
 
8242      * while `splice()` is buggy regardless of mode in IE < 9.
 
8244      * @memberOf _.support
 
8247     support.spliceObjects = (splice.call(object, 0, 1), !object[0]);
 
8250      * Detect lack of support for accessing string characters by index.
 
8252      * IE < 8 can't access characters by index. IE 8 can only access characters
 
8253      * by index on string literals, not string objects.
 
8255      * @memberOf _.support
 
8258     support.unindexedChars = ('x'[0] + Object('x')[0]) != 'xx';
 
8261   /*------------------------------------------------------------------------*/
 
8264    * Creates a lazy wrapper object which wraps `value` to enable lazy evaluation.
 
8267    * @param {*} value The value to wrap.
 
8269   function LazyWrapper(value) {
 
8270     this.__wrapped__ = value;
 
8271     this.__actions__ = null;
 
8273     this.__dropCount__ = 0;
 
8274     this.__filtered__ = false;
 
8275     this.__iteratees__ = null;
 
8276     this.__takeCount__ = POSITIVE_INFINITY;
 
8277     this.__views__ = null;
 
8281    * Creates a clone of the lazy wrapper object.
 
8285    * @memberOf LazyWrapper
 
8286    * @returns {Object} Returns the cloned `LazyWrapper` object.
 
8288   function lazyClone() {
 
8289     var actions = this.__actions__,
 
8290         iteratees = this.__iteratees__,
 
8291         views = this.__views__,
 
8292         result = new LazyWrapper(this.__wrapped__);
 
8294     result.__actions__ = actions ? arrayCopy(actions) : null;
 
8295     result.__dir__ = this.__dir__;
 
8296     result.__filtered__ = this.__filtered__;
 
8297     result.__iteratees__ = iteratees ? arrayCopy(iteratees) : null;
 
8298     result.__takeCount__ = this.__takeCount__;
 
8299     result.__views__ = views ? arrayCopy(views) : null;
 
8304    * Reverses the direction of lazy iteration.
 
8308    * @memberOf LazyWrapper
 
8309    * @returns {Object} Returns the new reversed `LazyWrapper` object.
 
8311   function lazyReverse() {
 
8312     if (this.__filtered__) {
 
8313       var result = new LazyWrapper(this);
 
8314       result.__dir__ = -1;
 
8315       result.__filtered__ = true;
 
8317       result = this.clone();
 
8318       result.__dir__ *= -1;
 
8324    * Extracts the unwrapped value from its lazy wrapper.
 
8328    * @memberOf LazyWrapper
 
8329    * @returns {*} Returns the unwrapped value.
 
8331   function lazyValue() {
 
8332     var array = this.__wrapped__.value();
 
8333     if (!isArray(array)) {
 
8334       return baseWrapperValue(array, this.__actions__);
 
8336     var dir = this.__dir__,
 
8338         view = getView(0, array.length, this.__views__),
 
8341         length = end - start,
 
8342         index = isRight ? end : (start - 1),
 
8343         takeCount = nativeMin(length, this.__takeCount__),
 
8344         iteratees = this.__iteratees__,
 
8345         iterLength = iteratees ? iteratees.length : 0,
 
8350     while (length-- && resIndex < takeCount) {
 
8354           value = array[index];
 
8356       while (++iterIndex < iterLength) {
 
8357         var data = iteratees[iterIndex],
 
8358             iteratee = data.iteratee,
 
8361         if (type == LAZY_DROP_WHILE_FLAG) {
 
8362           if (data.done && (isRight ? (index > data.index) : (index < data.index))) {
 
8368             var limit = data.limit;
 
8369             if (!(data.done = limit > -1 ? (data.count++ >= limit) : !iteratee(value))) {
 
8374           var computed = iteratee(value);
 
8375           if (type == LAZY_MAP_FLAG) {
 
8377           } else if (!computed) {
 
8378             if (type == LAZY_FILTER_FLAG) {
 
8386       result[resIndex++] = value;
 
8391   /*------------------------------------------------------------------------*/
 
8395    * Creates a cache object to store unique values.
 
8398    * @param {Array} [values] The values to cache.
 
8400   function SetCache(values) {
 
8401     var length = values ? values.length : 0;
 
8403     this.data = { 'hash': nativeCreate(null), 'set': new Set };
 
8405       this.push(values[length]);
 
8410    * Checks if `value` is in `cache` mimicking the return signature of
 
8411    * `_.indexOf` by returning `0` if the value is found, else `-1`.
 
8414    * @param {Object} cache The cache to search.
 
8415    * @param {*} value The value to search for.
 
8416    * @returns {number} Returns `0` if `value` is found, else `-1`.
 
8418   function cacheIndexOf(cache, value) {
 
8419     var data = cache.data,
 
8420         result = (typeof value == 'string' || isObject(value)) ? data.set.has(value) : data.hash[value];
 
8422     return result ? 0 : -1;
 
8426    * Adds `value` to the cache.
 
8430    * @memberOf SetCache
 
8431    * @param {*} value The value to cache.
 
8433   function cachePush(value) {
 
8434     var data = this.data;
 
8435     if (typeof value == 'string' || isObject(value)) {
 
8436       data.set.add(value);
 
8438       data.hash[value] = true;
 
8442   /*------------------------------------------------------------------------*/
 
8445    * Copies the values of `source` to `array`.
 
8448    * @param {Array} source The array to copy values from.
 
8449    * @param {Array} [array=[]] The array to copy values to.
 
8450    * @returns {Array} Returns `array`.
 
8452   function arrayCopy(source, array) {
 
8454         length = source.length;
 
8456     array || (array = Array(length));
 
8457     while (++index < length) {
 
8458       array[index] = source[index];
 
8464    * A specialized version of `_.forEach` for arrays without support for callback
 
8465    * shorthands and `this` binding.
 
8468    * @param {Array} array The array to iterate over.
 
8469    * @param {Function} iteratee The function invoked per iteration.
 
8470    * @returns {Array} Returns `array`.
 
8472   function arrayEach(array, iteratee) {
 
8474         length = array.length;
 
8476     while (++index < length) {
 
8477       if (iteratee(array[index], index, array) === false) {
 
8485    * A specialized version of `_.every` for arrays without support for callback
 
8486    * shorthands and `this` binding.
 
8489    * @param {Array} array The array to iterate over.
 
8490    * @param {Function} predicate The function invoked per iteration.
 
8491    * @returns {boolean} Returns `true` if all elements pass the predicate check,
 
8494   function arrayEvery(array, predicate) {
 
8496         length = array.length;
 
8498     while (++index < length) {
 
8499       if (!predicate(array[index], index, array)) {
 
8507    * A specialized version of `_.filter` for arrays without support for callback
 
8508    * shorthands and `this` binding.
 
8511    * @param {Array} array The array to iterate over.
 
8512    * @param {Function} predicate The function invoked per iteration.
 
8513    * @returns {Array} Returns the new filtered array.
 
8515   function arrayFilter(array, predicate) {
 
8517         length = array.length,
 
8521     while (++index < length) {
 
8522       var value = array[index];
 
8523       if (predicate(value, index, array)) {
 
8524         result[++resIndex] = value;
 
8531    * A specialized version of `_.map` for arrays without support for callback
 
8532    * shorthands and `this` binding.
 
8535    * @param {Array} array The array to iterate over.
 
8536    * @param {Function} iteratee The function invoked per iteration.
 
8537    * @returns {Array} Returns the new mapped array.
 
8539   function arrayMap(array, iteratee) {
 
8541         length = array.length,
 
8542         result = Array(length);
 
8544     while (++index < length) {
 
8545       result[index] = iteratee(array[index], index, array);
 
8551    * A specialized version of `_.reduce` for arrays without support for callback
 
8552    * shorthands and `this` binding.
 
8555    * @param {Array} array The array to iterate over.
 
8556    * @param {Function} iteratee The function invoked per iteration.
 
8557    * @param {*} [accumulator] The initial value.
 
8558    * @param {boolean} [initFromArray] Specify using the first element of `array`
 
8559    *  as the initial value.
 
8560    * @returns {*} Returns the accumulated value.
 
8562   function arrayReduce(array, iteratee, accumulator, initFromArray) {
 
8564         length = array.length;
 
8566     if (initFromArray && length) {
 
8567       accumulator = array[++index];
 
8569     while (++index < length) {
 
8570       accumulator = iteratee(accumulator, array[index], index, array);
 
8576    * A specialized version of `_.some` for arrays without support for callback
 
8577    * shorthands and `this` binding.
 
8580    * @param {Array} array The array to iterate over.
 
8581    * @param {Function} predicate The function invoked per iteration.
 
8582    * @returns {boolean} Returns `true` if any element passes the predicate check,
 
8585   function arraySome(array, predicate) {
 
8587         length = array.length;
 
8589     while (++index < length) {
 
8590       if (predicate(array[index], index, array)) {
 
8598    * A specialized version of `_.assign` for customizing assigned values without
 
8599    * support for argument juggling, multiple sources, and `this` binding `customizer`
 
8603    * @param {Object} object The destination object.
 
8604    * @param {Object} source The source object.
 
8605    * @param {Function} customizer The function to customize assigned values.
 
8606    * @returns {Object} Returns `object`.
 
8608   function assignWith(object, source, customizer) {
 
8610         props = keys(source),
 
8611         length = props.length;
 
8613     while (++index < length) {
 
8614       var key = props[index],
 
8615           value = object[key],
 
8616           result = customizer(value, source[key], key, object, source);
 
8618       if ((result === result ? (result !== value) : (value === value)) ||
 
8619           (value === undefined && !(key in object))) {
 
8620         object[key] = result;
 
8627    * The base implementation of `_.assign` without support for argument juggling,
 
8628    * multiple sources, and `customizer` functions.
 
8631    * @param {Object} object The destination object.
 
8632    * @param {Object} source The source object.
 
8633    * @returns {Object} Returns `object`.
 
8635   function baseAssign(object, source) {
 
8636     return source == null
 
8638       : baseCopy(source, keys(source), object);
 
8642    * Copies properties of `source` to `object`.
 
8645    * @param {Object} source The object to copy properties from.
 
8646    * @param {Array} props The property names to copy.
 
8647    * @param {Object} [object={}] The object to copy properties to.
 
8648    * @returns {Object} Returns `object`.
 
8650   function baseCopy(source, props, object) {
 
8651     object || (object = {});
 
8654         length = props.length;
 
8656     while (++index < length) {
 
8657       var key = props[index];
 
8658       object[key] = source[key];
 
8664    * The base implementation of `_.callback` which supports specifying the
 
8665    * number of arguments to provide to `func`.
 
8668    * @param {*} [func=_.identity] The value to convert to a callback.
 
8669    * @param {*} [thisArg] The `this` binding of `func`.
 
8670    * @param {number} [argCount] The number of arguments to provide to `func`.
 
8671    * @returns {Function} Returns the callback.
 
8673   function baseCallback(func, thisArg, argCount) {
 
8674     var type = typeof func;
 
8675     if (type == 'function') {
 
8676       return thisArg === undefined
 
8678         : bindCallback(func, thisArg, argCount);
 
8683     if (type == 'object') {
 
8684       return baseMatches(func);
 
8686     return thisArg === undefined
 
8688       : baseMatchesProperty(func, thisArg);
 
8692    * The base implementation of `_.clone` without support for argument juggling
 
8693    * and `this` binding `customizer` functions.
 
8696    * @param {*} value The value to clone.
 
8697    * @param {boolean} [isDeep] Specify a deep clone.
 
8698    * @param {Function} [customizer] The function to customize cloning values.
 
8699    * @param {string} [key] The key of `value`.
 
8700    * @param {Object} [object] The object `value` belongs to.
 
8701    * @param {Array} [stackA=[]] Tracks traversed source objects.
 
8702    * @param {Array} [stackB=[]] Associates clones with source counterparts.
 
8703    * @returns {*} Returns the cloned value.
 
8705   function baseClone(value, isDeep, customizer, key, object, stackA, stackB) {
 
8708       result = object ? customizer(value, key, object) : customizer(value);
 
8710     if (result !== undefined) {
 
8713     if (!isObject(value)) {
 
8716     var isArr = isArray(value);
 
8718       result = initCloneArray(value);
 
8720         return arrayCopy(value, result);
 
8723       var tag = objToString.call(value),
 
8724           isFunc = tag == funcTag;
 
8726       if (tag == objectTag || tag == argsTag || (isFunc && !object)) {
 
8727         if (isHostObject(value)) {
 
8728           return object ? value : {};
 
8730         result = initCloneObject(isFunc ? {} : value);
 
8732           return baseAssign(result, value);
 
8735         return cloneableTags[tag]
 
8736           ? initCloneByTag(value, tag, isDeep)
 
8737           : (object ? value : {});
 
8740     // Check for circular references and return corresponding clone.
 
8741     stackA || (stackA = []);
 
8742     stackB || (stackB = []);
 
8744     var length = stackA.length;
 
8746       if (stackA[length] == value) {
 
8747         return stackB[length];
 
8750     // Add the source value to the stack of traversed objects and associate it with its clone.
 
8752     stackB.push(result);
 
8754     // Recursively populate clone (susceptible to call stack limits).
 
8755     (isArr ? arrayEach : baseForOwn)(value, function(subValue, key) {
 
8756       result[key] = baseClone(subValue, isDeep, customizer, key, value, stackA, stackB);
 
8762    * The base implementation of `_.create` without support for assigning
 
8763    * properties to the created object.
 
8766    * @param {Object} prototype The object to inherit from.
 
8767    * @returns {Object} Returns the new object.
 
8769   var baseCreate = (function() {
 
8770     function object() {}
 
8771     return function(prototype) {
 
8772       if (isObject(prototype)) {
 
8773         object.prototype = prototype;
 
8774         var result = new object;
 
8775         object.prototype = null;
 
8777       return result || {};
 
8782    * The base implementation of `_.difference` which accepts a single array
 
8783    * of values to exclude.
 
8786    * @param {Array} array The array to inspect.
 
8787    * @param {Array} values The values to exclude.
 
8788    * @returns {Array} Returns the new array of filtered values.
 
8790   function baseDifference(array, values) {
 
8791     var length = array ? array.length : 0,
 
8798         indexOf = getIndexOf(),
 
8799         isCommon = indexOf == baseIndexOf,
 
8800         cache = (isCommon && values.length >= 200) ? createCache(values) : null,
 
8801         valuesLength = values.length;
 
8804       indexOf = cacheIndexOf;
 
8809     while (++index < length) {
 
8810       var value = array[index];
 
8812       if (isCommon && value === value) {
 
8813         var valuesIndex = valuesLength;
 
8814         while (valuesIndex--) {
 
8815           if (values[valuesIndex] === value) {
 
8821       else if (indexOf(values, value, 0) < 0) {
 
8829    * The base implementation of `_.forEach` without support for callback
 
8830    * shorthands and `this` binding.
 
8833    * @param {Array|Object|string} collection The collection to iterate over.
 
8834    * @param {Function} iteratee The function invoked per iteration.
 
8835    * @returns {Array|Object|string} Returns `collection`.
 
8837   var baseEach = createBaseEach(baseForOwn);
 
8840    * The base implementation of `_.every` without support for callback
 
8841    * shorthands and `this` binding.
 
8844    * @param {Array|Object|string} collection The collection to iterate over.
 
8845    * @param {Function} predicate The function invoked per iteration.
 
8846    * @returns {boolean} Returns `true` if all elements pass the predicate check,
 
8849   function baseEvery(collection, predicate) {
 
8851     baseEach(collection, function(value, index, collection) {
 
8852       result = !!predicate(value, index, collection);
 
8859    * The base implementation of `_.filter` without support for callback
 
8860    * shorthands and `this` binding.
 
8863    * @param {Array|Object|string} collection The collection to iterate over.
 
8864    * @param {Function} predicate The function invoked per iteration.
 
8865    * @returns {Array} Returns the new filtered array.
 
8867   function baseFilter(collection, predicate) {
 
8869     baseEach(collection, function(value, index, collection) {
 
8870       if (predicate(value, index, collection)) {
 
8878    * The base implementation of `_.find`, `_.findLast`, `_.findKey`, and `_.findLastKey`,
 
8879    * without support for callback shorthands and `this` binding, which iterates
 
8880    * over `collection` using the provided `eachFunc`.
 
8883    * @param {Array|Object|string} collection The collection to search.
 
8884    * @param {Function} predicate The function invoked per iteration.
 
8885    * @param {Function} eachFunc The function to iterate over `collection`.
 
8886    * @param {boolean} [retKey] Specify returning the key of the found element
 
8887    *  instead of the element itself.
 
8888    * @returns {*} Returns the found element or its key, else `undefined`.
 
8890   function baseFind(collection, predicate, eachFunc, retKey) {
 
8892     eachFunc(collection, function(value, key, collection) {
 
8893       if (predicate(value, key, collection)) {
 
8894         result = retKey ? key : value;
 
8902    * The base implementation of `_.flatten` with added support for restricting
 
8903    * flattening and specifying the start index.
 
8906    * @param {Array} array The array to flatten.
 
8907    * @param {boolean} [isDeep] Specify a deep flatten.
 
8908    * @param {boolean} [isStrict] Restrict flattening to arrays-like objects.
 
8909    * @returns {Array} Returns the new flattened array.
 
8911   function baseFlatten(array, isDeep, isStrict) {
 
8913         length = array.length,
 
8917     while (++index < length) {
 
8918       var value = array[index];
 
8919       if (isObjectLike(value) && isArrayLike(value) &&
 
8920           (isStrict || isArray(value) || isArguments(value))) {
 
8922           // Recursively flatten arrays (susceptible to call stack limits).
 
8923           value = baseFlatten(value, isDeep, isStrict);
 
8926             valLength = value.length;
 
8928         while (++valIndex < valLength) {
 
8929           result[++resIndex] = value[valIndex];
 
8931       } else if (!isStrict) {
 
8932         result[++resIndex] = value;
 
8939    * The base implementation of `baseForIn` and `baseForOwn` which iterates
 
8940    * over `object` properties returned by `keysFunc` invoking `iteratee` for
 
8941    * each property. Iteratee functions may exit iteration early by explicitly
 
8942    * returning `false`.
 
8945    * @param {Object} object The object to iterate over.
 
8946    * @param {Function} iteratee The function invoked per iteration.
 
8947    * @param {Function} keysFunc The function to get the keys of `object`.
 
8948    * @returns {Object} Returns `object`.
 
8950   var baseFor = createBaseFor();
 
8953    * The base implementation of `_.forIn` without support for callback
 
8954    * shorthands and `this` binding.
 
8957    * @param {Object} object The object to iterate over.
 
8958    * @param {Function} iteratee The function invoked per iteration.
 
8959    * @returns {Object} Returns `object`.
 
8961   function baseForIn(object, iteratee) {
 
8962     return baseFor(object, iteratee, keysIn);
 
8966    * The base implementation of `_.forOwn` without support for callback
 
8967    * shorthands and `this` binding.
 
8970    * @param {Object} object The object to iterate over.
 
8971    * @param {Function} iteratee The function invoked per iteration.
 
8972    * @returns {Object} Returns `object`.
 
8974   function baseForOwn(object, iteratee) {
 
8975     return baseFor(object, iteratee, keys);
 
8979    * The base implementation of `_.functions` which creates an array of
 
8980    * `object` function property names filtered from those provided.
 
8983    * @param {Object} object The object to inspect.
 
8984    * @param {Array} props The property names to filter.
 
8985    * @returns {Array} Returns the new array of filtered property names.
 
8987   function baseFunctions(object, props) {
 
8989         length = props.length,
 
8993     while (++index < length) {
 
8994       var key = props[index];
 
8995       if (isFunction(object[key])) {
 
8996         result[++resIndex] = key;
 
9003    * The base implementation of `get` without support for string paths
 
9004    * and default values.
 
9007    * @param {Object} object The object to query.
 
9008    * @param {Array} path The path of the property to get.
 
9009    * @param {string} [pathKey] The key representation of path.
 
9010    * @returns {*} Returns the resolved value.
 
9012   function baseGet(object, path, pathKey) {
 
9013     if (object == null) {
 
9016     object = toObject(object);
 
9017     if (pathKey !== undefined && pathKey in object) {
 
9021         length = path.length;
 
9023     while (object != null && index < length) {
 
9024       object = toObject(object)[path[index++]];
 
9026     return (index && index == length) ? object : undefined;
 
9030    * The base implementation of `_.isEqual` without support for `this` binding
 
9031    * `customizer` functions.
 
9034    * @param {*} value The value to compare.
 
9035    * @param {*} other The other value to compare.
 
9036    * @param {Function} [customizer] The function to customize comparing values.
 
9037    * @param {boolean} [isLoose] Specify performing partial comparisons.
 
9038    * @param {Array} [stackA] Tracks traversed `value` objects.
 
9039    * @param {Array} [stackB] Tracks traversed `other` objects.
 
9040    * @returns {boolean} Returns `true` if the values are equivalent, else `false`.
 
9042   function baseIsEqual(value, other, customizer, isLoose, stackA, stackB) {
 
9043     if (value === other) {
 
9046     if (value == null || other == null || (!isObject(value) && !isObjectLike(other))) {
 
9047       return value !== value && other !== other;
 
9049     return baseIsEqualDeep(value, other, baseIsEqual, customizer, isLoose, stackA, stackB);
 
9053    * A specialized version of `baseIsEqual` for arrays and objects which performs
 
9054    * deep comparisons and tracks traversed objects enabling objects with circular
 
9055    * references to be compared.
 
9058    * @param {Object} object The object to compare.
 
9059    * @param {Object} other The other object to compare.
 
9060    * @param {Function} equalFunc The function to determine equivalents of values.
 
9061    * @param {Function} [customizer] The function to customize comparing objects.
 
9062    * @param {boolean} [isLoose] Specify performing partial comparisons.
 
9063    * @param {Array} [stackA=[]] Tracks traversed `value` objects.
 
9064    * @param {Array} [stackB=[]] Tracks traversed `other` objects.
 
9065    * @returns {boolean} Returns `true` if the objects are equivalent, else `false`.
 
9067   function baseIsEqualDeep(object, other, equalFunc, customizer, isLoose, stackA, stackB) {
 
9068     var objIsArr = isArray(object),
 
9069         othIsArr = isArray(other),
 
9074       objTag = objToString.call(object);
 
9075       if (objTag == argsTag) {
 
9077       } else if (objTag != objectTag) {
 
9078         objIsArr = isTypedArray(object);
 
9082       othTag = objToString.call(other);
 
9083       if (othTag == argsTag) {
 
9085       } else if (othTag != objectTag) {
 
9086         othIsArr = isTypedArray(other);
 
9089     var objIsObj = objTag == objectTag && !isHostObject(object),
 
9090         othIsObj = othTag == objectTag && !isHostObject(other),
 
9091         isSameTag = objTag == othTag;
 
9093     if (isSameTag && !(objIsArr || objIsObj)) {
 
9094       return equalByTag(object, other, objTag);
 
9097       var objIsWrapped = objIsObj && hasOwnProperty.call(object, '__wrapped__'),
 
9098           othIsWrapped = othIsObj && hasOwnProperty.call(other, '__wrapped__');
 
9100       if (objIsWrapped || othIsWrapped) {
 
9101         return equalFunc(objIsWrapped ? object.value() : object, othIsWrapped ? other.value() : other, customizer, isLoose, stackA, stackB);
 
9107     // Assume cyclic values are equal.
 
9108     // For more information on detecting circular references see https://es5.github.io/#JO.
 
9109     stackA || (stackA = []);
 
9110     stackB || (stackB = []);
 
9112     var length = stackA.length;
 
9114       if (stackA[length] == object) {
 
9115         return stackB[length] == other;
 
9118     // Add `object` and `other` to the stack of traversed objects.
 
9119     stackA.push(object);
 
9122     var result = (objIsArr ? equalArrays : equalObjects)(object, other, equalFunc, customizer, isLoose, stackA, stackB);
 
9131    * The base implementation of `_.isMatch` without support for callback
 
9132    * shorthands and `this` binding.
 
9135    * @param {Object} object The object to inspect.
 
9136    * @param {Array} matchData The propery names, values, and compare flags to match.
 
9137    * @param {Function} [customizer] The function to customize comparing objects.
 
9138    * @returns {boolean} Returns `true` if `object` is a match, else `false`.
 
9140   function baseIsMatch(object, matchData, customizer) {
 
9141     var index = matchData.length,
 
9143         noCustomizer = !customizer;
 
9145     if (object == null) {
 
9148     object = toObject(object);
 
9150       var data = matchData[index];
 
9151       if ((noCustomizer && data[2])
 
9152             ? data[1] !== object[data[0]]
 
9153             : !(data[0] in object)
 
9158     while (++index < length) {
 
9159       data = matchData[index];
 
9161           objValue = object[key],
 
9164       if (noCustomizer && data[2]) {
 
9165         if (objValue === undefined && !(key in object)) {
 
9169         var result = customizer ? customizer(objValue, srcValue, key) : undefined;
 
9170         if (!(result === undefined ? baseIsEqual(srcValue, objValue, customizer, true) : result)) {
 
9179    * The base implementation of `_.map` without support for callback shorthands
 
9180    * and `this` binding.
 
9183    * @param {Array|Object|string} collection The collection to iterate over.
 
9184    * @param {Function} iteratee The function invoked per iteration.
 
9185    * @returns {Array} Returns the new mapped array.
 
9187   function baseMap(collection, iteratee) {
 
9189         result = isArrayLike(collection) ? Array(collection.length) : [];
 
9191     baseEach(collection, function(value, key, collection) {
 
9192       result[++index] = iteratee(value, key, collection);
 
9198    * The base implementation of `_.matches` which does not clone `source`.
 
9201    * @param {Object} source The object of property values to match.
 
9202    * @returns {Function} Returns the new function.
 
9204   function baseMatches(source) {
 
9205     var matchData = getMatchData(source);
 
9206     if (matchData.length == 1 && matchData[0][2]) {
 
9207       var key = matchData[0][0],
 
9208           value = matchData[0][1];
 
9210       return function(object) {
 
9211         if (object == null) {
 
9214         object = toObject(object);
 
9215         return object[key] === value && (value !== undefined || (key in object));
 
9218     return function(object) {
 
9219       return baseIsMatch(object, matchData);
 
9224    * The base implementation of `_.matchesProperty` which does not clone `srcValue`.
 
9227    * @param {string} path The path of the property to get.
 
9228    * @param {*} srcValue The value to compare.
 
9229    * @returns {Function} Returns the new function.
 
9231   function baseMatchesProperty(path, srcValue) {
 
9232     var isArr = isArray(path),
 
9233         isCommon = isKey(path) && isStrictComparable(srcValue),
 
9234         pathKey = (path + '');
 
9236     path = toPath(path);
 
9237     return function(object) {
 
9238       if (object == null) {
 
9242       object = toObject(object);
 
9243       if ((isArr || !isCommon) && !(key in object)) {
 
9244         object = path.length == 1 ? object : baseGet(object, baseSlice(path, 0, -1));
 
9245         if (object == null) {
 
9249         object = toObject(object);
 
9251       return object[key] === srcValue
 
9252         ? (srcValue !== undefined || (key in object))
 
9253         : baseIsEqual(srcValue, object[key], undefined, true);
 
9258    * The base implementation of `_.merge` without support for argument juggling,
 
9259    * multiple sources, and `this` binding `customizer` functions.
 
9262    * @param {Object} object The destination object.
 
9263    * @param {Object} source The source object.
 
9264    * @param {Function} [customizer] The function to customize merging properties.
 
9265    * @param {Array} [stackA=[]] Tracks traversed source objects.
 
9266    * @param {Array} [stackB=[]] Associates values with source counterparts.
 
9267    * @returns {Object} Returns `object`.
 
9269   function baseMerge(object, source, customizer, stackA, stackB) {
 
9270     if (!isObject(object)) {
 
9273     var isSrcArr = isArrayLike(source) && (isArray(source) || isTypedArray(source)),
 
9274         props = isSrcArr ? null : keys(source);
 
9276     arrayEach(props || source, function(srcValue, key) {
 
9279         srcValue = source[key];
 
9281       if (isObjectLike(srcValue)) {
 
9282         stackA || (stackA = []);
 
9283         stackB || (stackB = []);
 
9284         baseMergeDeep(object, source, key, baseMerge, customizer, stackA, stackB);
 
9287         var value = object[key],
 
9288             result = customizer ? customizer(value, srcValue, key, object, source) : undefined,
 
9289             isCommon = result === undefined;
 
9294         if ((result !== undefined || (isSrcArr && !(key in object))) &&
 
9295             (isCommon || (result === result ? (result !== value) : (value === value)))) {
 
9296           object[key] = result;
 
9304    * A specialized version of `baseMerge` for arrays and objects which performs
 
9305    * deep merges and tracks traversed objects enabling objects with circular
 
9306    * references to be merged.
 
9309    * @param {Object} object The destination object.
 
9310    * @param {Object} source The source object.
 
9311    * @param {string} key The key of the value to merge.
 
9312    * @param {Function} mergeFunc The function to merge values.
 
9313    * @param {Function} [customizer] The function to customize merging properties.
 
9314    * @param {Array} [stackA=[]] Tracks traversed source objects.
 
9315    * @param {Array} [stackB=[]] Associates values with source counterparts.
 
9316    * @returns {boolean} Returns `true` if the objects are equivalent, else `false`.
 
9318   function baseMergeDeep(object, source, key, mergeFunc, customizer, stackA, stackB) {
 
9319     var length = stackA.length,
 
9320         srcValue = source[key];
 
9323       if (stackA[length] == srcValue) {
 
9324         object[key] = stackB[length];
 
9328     var value = object[key],
 
9329         result = customizer ? customizer(value, srcValue, key, object, source) : undefined,
 
9330         isCommon = result === undefined;
 
9334       if (isArrayLike(srcValue) && (isArray(srcValue) || isTypedArray(srcValue))) {
 
9335         result = isArray(value)
 
9337           : (isArrayLike(value) ? arrayCopy(value) : []);
 
9339       else if (isPlainObject(srcValue) || isArguments(srcValue)) {
 
9340         result = isArguments(value)
 
9341           ? toPlainObject(value)
 
9342           : (isPlainObject(value) ? value : {});
 
9348     // Add the source value to the stack of traversed objects and associate
 
9349     // it with its merged value.
 
9350     stackA.push(srcValue);
 
9351     stackB.push(result);
 
9354       // Recursively merge objects and arrays (susceptible to call stack limits).
 
9355       object[key] = mergeFunc(result, srcValue, customizer, stackA, stackB);
 
9356     } else if (result === result ? (result !== value) : (value === value)) {
 
9357       object[key] = result;
 
9362    * The base implementation of `_.property` without support for deep paths.
 
9365    * @param {string} key The key of the property to get.
 
9366    * @returns {Function} Returns the new function.
 
9368   function baseProperty(key) {
 
9369     return function(object) {
 
9370       return object == null ? undefined : toObject(object)[key];
 
9375    * A specialized version of `baseProperty` which supports deep paths.
 
9378    * @param {Array|string} path The path of the property to get.
 
9379    * @returns {Function} Returns the new function.
 
9381   function basePropertyDeep(path) {
 
9382     var pathKey = (path + '');
 
9383     path = toPath(path);
 
9384     return function(object) {
 
9385       return baseGet(object, path, pathKey);
 
9390    * The base implementation of `_.reduce` and `_.reduceRight` without support
 
9391    * for callback shorthands and `this` binding, which iterates over `collection`
 
9392    * using the provided `eachFunc`.
 
9395    * @param {Array|Object|string} collection The collection to iterate over.
 
9396    * @param {Function} iteratee The function invoked per iteration.
 
9397    * @param {*} accumulator The initial value.
 
9398    * @param {boolean} initFromCollection Specify using the first or last element
 
9399    *  of `collection` as the initial value.
 
9400    * @param {Function} eachFunc The function to iterate over `collection`.
 
9401    * @returns {*} Returns the accumulated value.
 
9403   function baseReduce(collection, iteratee, accumulator, initFromCollection, eachFunc) {
 
9404     eachFunc(collection, function(value, index, collection) {
 
9405       accumulator = initFromCollection
 
9406         ? (initFromCollection = false, value)
 
9407         : iteratee(accumulator, value, index, collection);
 
9413    * The base implementation of `setData` without support for hot loop detection.
 
9416    * @param {Function} func The function to associate metadata with.
 
9417    * @param {*} data The metadata.
 
9418    * @returns {Function} Returns `func`.
 
9420   var baseSetData = !metaMap ? identity : function(func, data) {
 
9421     metaMap.set(func, data);
 
9426    * The base implementation of `_.slice` without an iteratee call guard.
 
9429    * @param {Array} array The array to slice.
 
9430    * @param {number} [start=0] The start position.
 
9431    * @param {number} [end=array.length] The end position.
 
9432    * @returns {Array} Returns the slice of `array`.
 
9434   function baseSlice(array, start, end) {
 
9436         length = array.length;
 
9438     start = start == null ? 0 : (+start || 0);
 
9440       start = -start > length ? 0 : (length + start);
 
9442     end = (end === undefined || end > length) ? length : (+end || 0);
 
9446     length = start > end ? 0 : ((end - start) >>> 0);
 
9449     var result = Array(length);
 
9450     while (++index < length) {
 
9451       result[index] = array[index + start];
 
9457    * The base implementation of `_.some` without support for callback shorthands
 
9458    * and `this` binding.
 
9461    * @param {Array|Object|string} collection The collection to iterate over.
 
9462    * @param {Function} predicate The function invoked per iteration.
 
9463    * @returns {boolean} Returns `true` if any element passes the predicate check,
 
9466   function baseSome(collection, predicate) {
 
9469     baseEach(collection, function(value, index, collection) {
 
9470       result = predicate(value, index, collection);
 
9477    * The base implementation of `_.uniq` without support for callback shorthands
 
9478    * and `this` binding.
 
9481    * @param {Array} array The array to inspect.
 
9482    * @param {Function} [iteratee] The function invoked per iteration.
 
9483    * @returns {Array} Returns the new duplicate-value-free array.
 
9485   function baseUniq(array, iteratee) {
 
9487         indexOf = getIndexOf(),
 
9488         length = array.length,
 
9489         isCommon = indexOf == baseIndexOf,
 
9490         isLarge = isCommon && length >= 200,
 
9491         seen = isLarge ? createCache() : null,
 
9495       indexOf = cacheIndexOf;
 
9499       seen = iteratee ? [] : result;
 
9502     while (++index < length) {
 
9503       var value = array[index],
 
9504           computed = iteratee ? iteratee(value, index, array) : value;
 
9506       if (isCommon && value === value) {
 
9507         var seenIndex = seen.length;
 
9508         while (seenIndex--) {
 
9509           if (seen[seenIndex] === computed) {
 
9514           seen.push(computed);
 
9518       else if (indexOf(seen, computed, 0) < 0) {
 
9519         if (iteratee || isLarge) {
 
9520           seen.push(computed);
 
9529    * The base implementation of `_.values` and `_.valuesIn` which creates an
 
9530    * array of `object` property values corresponding to the property names
 
9534    * @param {Object} object The object to query.
 
9535    * @param {Array} props The property names to get values for.
 
9536    * @returns {Object} Returns the array of property values.
 
9538   function baseValues(object, props) {
 
9540         length = props.length,
 
9541         result = Array(length);
 
9543     while (++index < length) {
 
9544       result[index] = object[props[index]];
 
9550    * The base implementation of `wrapperValue` which returns the result of
 
9551    * performing a sequence of actions on the unwrapped `value`, where each
 
9552    * successive action is supplied the return value of the previous.
 
9555    * @param {*} value The unwrapped value.
 
9556    * @param {Array} actions Actions to peform to resolve the unwrapped value.
 
9557    * @returns {*} Returns the resolved value.
 
9559   function baseWrapperValue(value, actions) {
 
9561     if (result instanceof LazyWrapper) {
 
9562       result = result.value();
 
9565         length = actions.length;
 
9567     while (++index < length) {
 
9568       var args = [result],
 
9569           action = actions[index];
 
9571       push.apply(args, action.args);
 
9572       result = action.func.apply(action.thisArg, args);
 
9578    * Performs a binary search of `array` to determine the index at which `value`
 
9579    * should be inserted into `array` in order to maintain its sort order.
 
9582    * @param {Array} array The sorted array to inspect.
 
9583    * @param {*} value The value to evaluate.
 
9584    * @param {boolean} [retHighest] Specify returning the highest qualified index.
 
9585    * @returns {number} Returns the index at which `value` should be inserted
 
9588   function binaryIndex(array, value, retHighest) {
 
9590         high = array ? array.length : low;
 
9592     if (typeof value == 'number' && value === value && high <= HALF_MAX_ARRAY_LENGTH) {
 
9593       while (low < high) {
 
9594         var mid = (low + high) >>> 1,
 
9595             computed = array[mid];
 
9597         if ((retHighest ? (computed <= value) : (computed < value)) && computed !== null) {
 
9605     return binaryIndexBy(array, value, identity, retHighest);
 
9609    * This function is like `binaryIndex` except that it invokes `iteratee` for
 
9610    * `value` and each element of `array` to compute their sort ranking. The
 
9611    * iteratee is invoked with one argument; (value).
 
9614    * @param {Array} array The sorted array to inspect.
 
9615    * @param {*} value The value to evaluate.
 
9616    * @param {Function} iteratee The function invoked per iteration.
 
9617    * @param {boolean} [retHighest] Specify returning the highest qualified index.
 
9618    * @returns {number} Returns the index at which `value` should be inserted
 
9621   function binaryIndexBy(array, value, iteratee, retHighest) {
 
9622     value = iteratee(value);
 
9625         high = array ? array.length : 0,
 
9626         valIsNaN = value !== value,
 
9627         valIsNull = value === null,
 
9628         valIsUndef = value === undefined;
 
9630     while (low < high) {
 
9631       var mid = floor((low + high) / 2),
 
9632           computed = iteratee(array[mid]),
 
9633           isDef = computed !== undefined,
 
9634           isReflexive = computed === computed;
 
9637         var setLow = isReflexive || retHighest;
 
9638       } else if (valIsNull) {
 
9639         setLow = isReflexive && isDef && (retHighest || computed != null);
 
9640       } else if (valIsUndef) {
 
9641         setLow = isReflexive && (retHighest || isDef);
 
9642       } else if (computed == null) {
 
9645         setLow = retHighest ? (computed <= value) : (computed < value);
 
9653     return nativeMin(high, MAX_ARRAY_INDEX);
 
9657    * A specialized version of `baseCallback` which only supports `this` binding
 
9658    * and specifying the number of arguments to provide to `func`.
 
9661    * @param {Function} func The function to bind.
 
9662    * @param {*} thisArg The `this` binding of `func`.
 
9663    * @param {number} [argCount] The number of arguments to provide to `func`.
 
9664    * @returns {Function} Returns the callback.
 
9666   function bindCallback(func, thisArg, argCount) {
 
9667     if (typeof func != 'function') {
 
9670     if (thisArg === undefined) {
 
9674       case 1: return function(value) {
 
9675         return func.call(thisArg, value);
 
9677       case 3: return function(value, index, collection) {
 
9678         return func.call(thisArg, value, index, collection);
 
9680       case 4: return function(accumulator, value, index, collection) {
 
9681         return func.call(thisArg, accumulator, value, index, collection);
 
9683       case 5: return function(value, other, key, object, source) {
 
9684         return func.call(thisArg, value, other, key, object, source);
 
9688       return func.apply(thisArg, arguments);
 
9693    * Creates a clone of the given array buffer.
 
9696    * @param {ArrayBuffer} buffer The array buffer to clone.
 
9697    * @returns {ArrayBuffer} Returns the cloned array buffer.
 
9699   function bufferClone(buffer) {
 
9700     return bufferSlice.call(buffer, 0);
 
9703     // PhantomJS has `ArrayBuffer` and `Uint8Array` but not `Float64Array`.
 
9704     bufferClone = !(ArrayBuffer && Uint8Array) ? constant(null) : function(buffer) {
 
9705       var byteLength = buffer.byteLength,
 
9706           floatLength = Float64Array ? floor(byteLength / FLOAT64_BYTES_PER_ELEMENT) : 0,
 
9707           offset = floatLength * FLOAT64_BYTES_PER_ELEMENT,
 
9708           result = new ArrayBuffer(byteLength);
 
9711         var view = new Float64Array(result, 0, floatLength);
 
9712         view.set(new Float64Array(buffer, 0, floatLength));
 
9714       if (byteLength != offset) {
 
9715         view = new Uint8Array(result, offset);
 
9716         view.set(new Uint8Array(buffer, offset));
 
9723    * Creates an array that is the composition of partially applied arguments,
 
9724    * placeholders, and provided arguments into a single array of arguments.
 
9727    * @param {Array|Object} args The provided arguments.
 
9728    * @param {Array} partials The arguments to prepend to those provided.
 
9729    * @param {Array} holders The `partials` placeholder indexes.
 
9730    * @returns {Array} Returns the new array of composed arguments.
 
9732   function composeArgs(args, partials, holders) {
 
9733     var holdersLength = holders.length,
 
9735         argsLength = nativeMax(args.length - holdersLength, 0),
 
9737         leftLength = partials.length,
 
9738         result = Array(argsLength + leftLength);
 
9740     while (++leftIndex < leftLength) {
 
9741       result[leftIndex] = partials[leftIndex];
 
9743     while (++argsIndex < holdersLength) {
 
9744       result[holders[argsIndex]] = args[argsIndex];
 
9746     while (argsLength--) {
 
9747       result[leftIndex++] = args[argsIndex++];
 
9753    * This function is like `composeArgs` except that the arguments composition
 
9754    * is tailored for `_.partialRight`.
 
9757    * @param {Array|Object} args The provided arguments.
 
9758    * @param {Array} partials The arguments to append to those provided.
 
9759    * @param {Array} holders The `partials` placeholder indexes.
 
9760    * @returns {Array} Returns the new array of composed arguments.
 
9762   function composeArgsRight(args, partials, holders) {
 
9763     var holdersIndex = -1,
 
9764         holdersLength = holders.length,
 
9766         argsLength = nativeMax(args.length - holdersLength, 0),
 
9768         rightLength = partials.length,
 
9769         result = Array(argsLength + rightLength);
 
9771     while (++argsIndex < argsLength) {
 
9772       result[argsIndex] = args[argsIndex];
 
9774     var offset = argsIndex;
 
9775     while (++rightIndex < rightLength) {
 
9776       result[offset + rightIndex] = partials[rightIndex];
 
9778     while (++holdersIndex < holdersLength) {
 
9779       result[offset + holders[holdersIndex]] = args[argsIndex++];
 
9785    * Creates a function that aggregates a collection, creating an accumulator
 
9786    * object composed from the results of running each element in the collection
 
9787    * through an iteratee.
 
9789    * **Note:** This function is used to create `_.countBy`, `_.groupBy`, `_.indexBy`,
 
9790    * and `_.partition`.
 
9793    * @param {Function} setter The function to set keys and values of the accumulator object.
 
9794    * @param {Function} [initializer] The function to initialize the accumulator object.
 
9795    * @returns {Function} Returns the new aggregator function.
 
9797   function createAggregator(setter, initializer) {
 
9798     return function(collection, iteratee, thisArg) {
 
9799       var result = initializer ? initializer() : {};
 
9800       iteratee = getCallback(iteratee, thisArg, 3);
 
9802       if (isArray(collection)) {
 
9804             length = collection.length;
 
9806         while (++index < length) {
 
9807           var value = collection[index];
 
9808           setter(result, value, iteratee(value, index, collection), collection);
 
9811         baseEach(collection, function(value, key, collection) {
 
9812           setter(result, value, iteratee(value, key, collection), collection);
 
9820    * Creates a function that assigns properties of source object(s) to a given
 
9821    * destination object.
 
9823    * **Note:** This function is used to create `_.assign`, `_.defaults`, and `_.merge`.
 
9826    * @param {Function} assigner The function to assign values.
 
9827    * @returns {Function} Returns the new assigner function.
 
9829   function createAssigner(assigner) {
 
9830     return restParam(function(object, sources) {
 
9832           length = object == null ? 0 : sources.length,
 
9833           customizer = length > 2 ? sources[length - 2] : undefined,
 
9834           guard = length > 2 ? sources[2] : undefined,
 
9835           thisArg = length > 1 ? sources[length - 1] : undefined;
 
9837       if (typeof customizer == 'function') {
 
9838         customizer = bindCallback(customizer, thisArg, 5);
 
9841         customizer = typeof thisArg == 'function' ? thisArg : undefined;
 
9842         length -= (customizer ? 1 : 0);
 
9844       if (guard && isIterateeCall(sources[0], sources[1], guard)) {
 
9845         customizer = length < 3 ? undefined : customizer;
 
9848       while (++index < length) {
 
9849         var source = sources[index];
 
9851           assigner(object, source, customizer);
 
9859    * Creates a `baseEach` or `baseEachRight` function.
 
9862    * @param {Function} eachFunc The function to iterate over a collection.
 
9863    * @param {boolean} [fromRight] Specify iterating from right to left.
 
9864    * @returns {Function} Returns the new base function.
 
9866   function createBaseEach(eachFunc, fromRight) {
 
9867     return function(collection, iteratee) {
 
9868       var length = collection ? getLength(collection) : 0;
 
9869       if (!isLength(length)) {
 
9870         return eachFunc(collection, iteratee);
 
9872       var index = fromRight ? length : -1,
 
9873           iterable = toObject(collection);
 
9875       while ((fromRight ? index-- : ++index < length)) {
 
9876         if (iteratee(iterable[index], index, iterable) === false) {
 
9885    * Creates a base function for `_.forIn` or `_.forInRight`.
 
9888    * @param {boolean} [fromRight] Specify iterating from right to left.
 
9889    * @returns {Function} Returns the new base function.
 
9891   function createBaseFor(fromRight) {
 
9892     return function(object, iteratee, keysFunc) {
 
9893       var iterable = toObject(object),
 
9894           props = keysFunc(object),
 
9895           length = props.length,
 
9896           index = fromRight ? length : -1;
 
9898       while ((fromRight ? index-- : ++index < length)) {
 
9899         var key = props[index];
 
9900         if (iteratee(iterable[key], key, iterable) === false) {
 
9909    * Creates a function that wraps `func` and invokes it with the `this`
 
9910    * binding of `thisArg`.
 
9913    * @param {Function} func The function to bind.
 
9914    * @param {*} [thisArg] The `this` binding of `func`.
 
9915    * @returns {Function} Returns the new bound function.
 
9917   function createBindWrapper(func, thisArg) {
 
9918     var Ctor = createCtorWrapper(func);
 
9920     function wrapper() {
 
9921       var fn = (this && this !== root && this instanceof wrapper) ? Ctor : func;
 
9922       return fn.apply(thisArg, arguments);
 
9928    * Creates a `Set` cache object to optimize linear searches of large arrays.
 
9931    * @param {Array} [values] The values to cache.
 
9932    * @returns {null|Object} Returns the new cache object if `Set` is supported, else `null`.
 
9934   var createCache = !(nativeCreate && Set) ? constant(null) : function(values) {
 
9935     return new SetCache(values);
 
9939    * Creates a function that produces an instance of `Ctor` regardless of
 
9940    * whether it was invoked as part of a `new` expression or by `call` or `apply`.
 
9943    * @param {Function} Ctor The constructor to wrap.
 
9944    * @returns {Function} Returns the new wrapped function.
 
9946   function createCtorWrapper(Ctor) {
 
9948       // Use a `switch` statement to work with class constructors.
 
9949       // See https://people.mozilla.org/~jorendorff/es6-draft.html#sec-ecmascript-function-objects-call-thisargument-argumentslist
 
9950       // for more details.
 
9951       var args = arguments;
 
9952       switch (args.length) {
 
9953         case 0: return new Ctor;
 
9954         case 1: return new Ctor(args[0]);
 
9955         case 2: return new Ctor(args[0], args[1]);
 
9956         case 3: return new Ctor(args[0], args[1], args[2]);
 
9957         case 4: return new Ctor(args[0], args[1], args[2], args[3]);
 
9958         case 5: return new Ctor(args[0], args[1], args[2], args[3], args[4]);
 
9960       var thisBinding = baseCreate(Ctor.prototype),
 
9961           result = Ctor.apply(thisBinding, args);
 
9963       // Mimic the constructor's `return` behavior.
 
9964       // See https://es5.github.io/#x13.2.2 for more details.
 
9965       return isObject(result) ? result : thisBinding;
 
9970    * Creates a `_.find` or `_.findLast` function.
 
9973    * @param {Function} eachFunc The function to iterate over a collection.
 
9974    * @param {boolean} [fromRight] Specify iterating from right to left.
 
9975    * @returns {Function} Returns the new find function.
 
9977   function createFind(eachFunc, fromRight) {
 
9978     return function(collection, predicate, thisArg) {
 
9979       predicate = getCallback(predicate, thisArg, 3);
 
9980       if (isArray(collection)) {
 
9981         var index = baseFindIndex(collection, predicate, fromRight);
 
9982         return index > -1 ? collection[index] : undefined;
 
9984       return baseFind(collection, predicate, eachFunc);
 
9989    * Creates a function for `_.forEach` or `_.forEachRight`.
 
9992    * @param {Function} arrayFunc The function to iterate over an array.
 
9993    * @param {Function} eachFunc The function to iterate over a collection.
 
9994    * @returns {Function} Returns the new each function.
 
9996   function createForEach(arrayFunc, eachFunc) {
 
9997     return function(collection, iteratee, thisArg) {
 
9998       return (typeof iteratee == 'function' && thisArg === undefined && isArray(collection))
 
9999         ? arrayFunc(collection, iteratee)
 
10000         : eachFunc(collection, bindCallback(iteratee, thisArg, 3));
 
10005    * Creates a function for `_.forOwn` or `_.forOwnRight`.
 
10008    * @param {Function} objectFunc The function to iterate over an object.
 
10009    * @returns {Function} Returns the new each function.
 
10011   function createForOwn(objectFunc) {
 
10012     return function(object, iteratee, thisArg) {
 
10013       if (typeof iteratee != 'function' || thisArg !== undefined) {
 
10014         iteratee = bindCallback(iteratee, thisArg, 3);
 
10016       return objectFunc(object, iteratee);
 
10021    * Creates a function for `_.reduce` or `_.reduceRight`.
 
10024    * @param {Function} arrayFunc The function to iterate over an array.
 
10025    * @param {Function} eachFunc The function to iterate over a collection.
 
10026    * @returns {Function} Returns the new each function.
 
10028   function createReduce(arrayFunc, eachFunc) {
 
10029     return function(collection, iteratee, accumulator, thisArg) {
 
10030       var initFromArray = arguments.length < 3;
 
10031       return (typeof iteratee == 'function' && thisArg === undefined && isArray(collection))
 
10032         ? arrayFunc(collection, iteratee, accumulator, initFromArray)
 
10033         : baseReduce(collection, getCallback(iteratee, thisArg, 4), accumulator, initFromArray, eachFunc);
 
10038    * Creates a function that wraps `func` and invokes it with optional `this`
 
10039    * binding of, partial application, and currying.
 
10042    * @param {Function|string} func The function or method name to reference.
 
10043    * @param {number} bitmask The bitmask of flags. See `createWrapper` for more details.
 
10044    * @param {*} [thisArg] The `this` binding of `func`.
 
10045    * @param {Array} [partials] The arguments to prepend to those provided to the new function.
 
10046    * @param {Array} [holders] The `partials` placeholder indexes.
 
10047    * @param {Array} [partialsRight] The arguments to append to those provided to the new function.
 
10048    * @param {Array} [holdersRight] The `partialsRight` placeholder indexes.
 
10049    * @param {Array} [argPos] The argument positions of the new function.
 
10050    * @param {number} [ary] The arity cap of `func`.
 
10051    * @param {number} [arity] The arity of `func`.
 
10052    * @returns {Function} Returns the new wrapped function.
 
10054   function createHybridWrapper(func, bitmask, thisArg, partials, holders, partialsRight, holdersRight, argPos, ary, arity) {
 
10055     var isAry = bitmask & ARY_FLAG,
 
10056         isBind = bitmask & BIND_FLAG,
 
10057         isBindKey = bitmask & BIND_KEY_FLAG,
 
10058         isCurry = bitmask & CURRY_FLAG,
 
10059         isCurryBound = bitmask & CURRY_BOUND_FLAG,
 
10060         isCurryRight = bitmask & CURRY_RIGHT_FLAG,
 
10061         Ctor = isBindKey ? null : createCtorWrapper(func);
 
10063     function wrapper() {
 
10064       // Avoid `arguments` object use disqualifying optimizations by
 
10065       // converting it to an array before providing it to other functions.
 
10066       var length = arguments.length,
 
10068           args = Array(length);
 
10071         args[index] = arguments[index];
 
10074         args = composeArgs(args, partials, holders);
 
10076       if (partialsRight) {
 
10077         args = composeArgsRight(args, partialsRight, holdersRight);
 
10079       if (isCurry || isCurryRight) {
 
10080         var placeholder = wrapper.placeholder,
 
10081             argsHolders = replaceHolders(args, placeholder);
 
10083         length -= argsHolders.length;
 
10084         if (length < arity) {
 
10085           var newArgPos = argPos ? arrayCopy(argPos) : null,
 
10086               newArity = nativeMax(arity - length, 0),
 
10087               newsHolders = isCurry ? argsHolders : null,
 
10088               newHoldersRight = isCurry ? null : argsHolders,
 
10089               newPartials = isCurry ? args : null,
 
10090               newPartialsRight = isCurry ? null : args;
 
10092           bitmask |= (isCurry ? PARTIAL_FLAG : PARTIAL_RIGHT_FLAG);
 
10093           bitmask &= ~(isCurry ? PARTIAL_RIGHT_FLAG : PARTIAL_FLAG);
 
10095           if (!isCurryBound) {
 
10096             bitmask &= ~(BIND_FLAG | BIND_KEY_FLAG);
 
10098           var newData = [func, bitmask, thisArg, newPartials, newsHolders, newPartialsRight, newHoldersRight, newArgPos, ary, newArity],
 
10099               result = createHybridWrapper.apply(undefined, newData);
 
10101           if (isLaziable(func)) {
 
10102             setData(result, newData);
 
10104           result.placeholder = placeholder;
 
10108       var thisBinding = isBind ? thisArg : this,
 
10109           fn = isBindKey ? thisBinding[func] : func;
 
10112         args = reorder(args, argPos);
 
10114       if (isAry && ary < args.length) {
 
10117       if (this && this !== root && this instanceof wrapper) {
 
10118         fn = Ctor || createCtorWrapper(func);
 
10120       return fn.apply(thisBinding, args);
 
10126    * Creates a function that wraps `func` and invokes it with the optional `this`
 
10127    * binding of `thisArg` and the `partials` prepended to those provided to
 
10131    * @param {Function} func The function to partially apply arguments to.
 
10132    * @param {number} bitmask The bitmask of flags. See `createWrapper` for more details.
 
10133    * @param {*} thisArg The `this` binding of `func`.
 
10134    * @param {Array} partials The arguments to prepend to those provided to the new function.
 
10135    * @returns {Function} Returns the new bound function.
 
10137   function createPartialWrapper(func, bitmask, thisArg, partials) {
 
10138     var isBind = bitmask & BIND_FLAG,
 
10139         Ctor = createCtorWrapper(func);
 
10141     function wrapper() {
 
10142       // Avoid `arguments` object use disqualifying optimizations by
 
10143       // converting it to an array before providing it `func`.
 
10144       var argsIndex = -1,
 
10145           argsLength = arguments.length,
 
10147           leftLength = partials.length,
 
10148           args = Array(argsLength + leftLength);
 
10150       while (++leftIndex < leftLength) {
 
10151         args[leftIndex] = partials[leftIndex];
 
10153       while (argsLength--) {
 
10154         args[leftIndex++] = arguments[++argsIndex];
 
10156       var fn = (this && this !== root && this instanceof wrapper) ? Ctor : func;
 
10157       return fn.apply(isBind ? thisArg : this, args);
 
10163    * Creates a function that either curries or invokes `func` with optional
 
10164    * `this` binding and partially applied arguments.
 
10167    * @param {Function|string} func The function or method name to reference.
 
10168    * @param {number} bitmask The bitmask of flags.
 
10169    *  The bitmask may be composed of the following flags:
 
10172    *     4 - `_.curry` or `_.curryRight` of a bound function
 
10174    *    16 - `_.curryRight`
 
10176    *    64 - `_.partialRight`
 
10179    * @param {*} [thisArg] The `this` binding of `func`.
 
10180    * @param {Array} [partials] The arguments to be partially applied.
 
10181    * @param {Array} [holders] The `partials` placeholder indexes.
 
10182    * @param {Array} [argPos] The argument positions of the new function.
 
10183    * @param {number} [ary] The arity cap of `func`.
 
10184    * @param {number} [arity] The arity of `func`.
 
10185    * @returns {Function} Returns the new wrapped function.
 
10187   function createWrapper(func, bitmask, thisArg, partials, holders, argPos, ary, arity) {
 
10188     var isBindKey = bitmask & BIND_KEY_FLAG;
 
10189     if (!isBindKey && typeof func != 'function') {
 
10190       throw new TypeError(FUNC_ERROR_TEXT);
 
10192     var length = partials ? partials.length : 0;
 
10194       bitmask &= ~(PARTIAL_FLAG | PARTIAL_RIGHT_FLAG);
 
10195       partials = holders = null;
 
10197     length -= (holders ? holders.length : 0);
 
10198     if (bitmask & PARTIAL_RIGHT_FLAG) {
 
10199       var partialsRight = partials,
 
10200           holdersRight = holders;
 
10202       partials = holders = null;
 
10204     var data = isBindKey ? null : getData(func),
 
10205         newData = [func, bitmask, thisArg, partials, holders, partialsRight, holdersRight, argPos, ary, arity];
 
10208       mergeData(newData, data);
 
10209       bitmask = newData[1];
 
10210       arity = newData[9];
 
10212     newData[9] = arity == null
 
10213       ? (isBindKey ? 0 : func.length)
 
10214       : (nativeMax(arity - length, 0) || 0);
 
10216     if (bitmask == BIND_FLAG) {
 
10217       var result = createBindWrapper(newData[0], newData[2]);
 
10218     } else if ((bitmask == PARTIAL_FLAG || bitmask == (BIND_FLAG | PARTIAL_FLAG)) && !newData[4].length) {
 
10219       result = createPartialWrapper.apply(undefined, newData);
 
10221       result = createHybridWrapper.apply(undefined, newData);
 
10223     var setter = data ? baseSetData : setData;
 
10224     return setter(result, newData);
 
10228    * A specialized version of `baseIsEqualDeep` for arrays with support for
 
10229    * partial deep comparisons.
 
10232    * @param {Array} array The array to compare.
 
10233    * @param {Array} other The other array to compare.
 
10234    * @param {Function} equalFunc The function to determine equivalents of values.
 
10235    * @param {Function} [customizer] The function to customize comparing arrays.
 
10236    * @param {boolean} [isLoose] Specify performing partial comparisons.
 
10237    * @param {Array} [stackA] Tracks traversed `value` objects.
 
10238    * @param {Array} [stackB] Tracks traversed `other` objects.
 
10239    * @returns {boolean} Returns `true` if the arrays are equivalent, else `false`.
 
10241   function equalArrays(array, other, equalFunc, customizer, isLoose, stackA, stackB) {
 
10243         arrLength = array.length,
 
10244         othLength = other.length;
 
10246     if (arrLength != othLength && !(isLoose && othLength > arrLength)) {
 
10249     // Ignore non-index properties.
 
10250     while (++index < arrLength) {
 
10251       var arrValue = array[index],
 
10252           othValue = other[index],
 
10253           result = customizer ? customizer(isLoose ? othValue : arrValue, isLoose ? arrValue : othValue, index) : undefined;
 
10255       if (result !== undefined) {
 
10261       // Recursively compare arrays (susceptible to call stack limits).
 
10263         if (!arraySome(other, function(othValue) {
 
10264               return arrValue === othValue || equalFunc(arrValue, othValue, customizer, isLoose, stackA, stackB);
 
10268       } else if (!(arrValue === othValue || equalFunc(arrValue, othValue, customizer, isLoose, stackA, stackB))) {
 
10276    * A specialized version of `baseIsEqualDeep` for comparing objects of
 
10277    * the same `toStringTag`.
 
10279    * **Note:** This function only supports comparing values with tags of
 
10280    * `Boolean`, `Date`, `Error`, `Number`, `RegExp`, or `String`.
 
10283    * @param {Object} value The object to compare.
 
10284    * @param {Object} other The other object to compare.
 
10285    * @param {string} tag The `toStringTag` of the objects to compare.
 
10286    * @returns {boolean} Returns `true` if the objects are equivalent, else `false`.
 
10288   function equalByTag(object, other, tag) {
 
10292         // Coerce dates and booleans to numbers, dates to milliseconds and booleans
 
10293         // to `1` or `0` treating invalid dates coerced to `NaN` as not equal.
 
10294         return +object == +other;
 
10297         return object.name == other.name && object.message == other.message;
 
10300         // Treat `NaN` vs. `NaN` as equal.
 
10301         return (object != +object)
 
10303           : object == +other;
 
10307         // Coerce regexes to strings and treat strings primitives and string
 
10308         // objects as equal. See https://es5.github.io/#x15.10.6.4 for more details.
 
10309         return object == (other + '');
 
10315    * A specialized version of `baseIsEqualDeep` for objects with support for
 
10316    * partial deep comparisons.
 
10319    * @param {Object} object The object to compare.
 
10320    * @param {Object} other The other object to compare.
 
10321    * @param {Function} equalFunc The function to determine equivalents of values.
 
10322    * @param {Function} [customizer] The function to customize comparing values.
 
10323    * @param {boolean} [isLoose] Specify performing partial comparisons.
 
10324    * @param {Array} [stackA] Tracks traversed `value` objects.
 
10325    * @param {Array} [stackB] Tracks traversed `other` objects.
 
10326    * @returns {boolean} Returns `true` if the objects are equivalent, else `false`.
 
10328   function equalObjects(object, other, equalFunc, customizer, isLoose, stackA, stackB) {
 
10329     var objProps = keys(object),
 
10330         objLength = objProps.length,
 
10331         othProps = keys(other),
 
10332         othLength = othProps.length;
 
10334     if (objLength != othLength && !isLoose) {
 
10337     var index = objLength;
 
10339       var key = objProps[index];
 
10340       if (!(isLoose ? key in other : hasOwnProperty.call(other, key))) {
 
10344     var skipCtor = isLoose;
 
10345     while (++index < objLength) {
 
10346       key = objProps[index];
 
10347       var objValue = object[key],
 
10348           othValue = other[key],
 
10349           result = customizer ? customizer(isLoose ? othValue : objValue, isLoose? objValue : othValue, key) : undefined;
 
10351       // Recursively compare objects (susceptible to call stack limits).
 
10352       if (!(result === undefined ? equalFunc(objValue, othValue, customizer, isLoose, stackA, stackB) : result)) {
 
10355       skipCtor || (skipCtor = key == 'constructor');
 
10358       var objCtor = object.constructor,
 
10359           othCtor = other.constructor;
 
10361       // Non `Object` object instances with different constructors are not equal.
 
10362       if (objCtor != othCtor &&
 
10363           ('constructor' in object && 'constructor' in other) &&
 
10364           !(typeof objCtor == 'function' && objCtor instanceof objCtor &&
 
10365             typeof othCtor == 'function' && othCtor instanceof othCtor)) {
 
10373    * Gets the appropriate "callback" function. If the `_.callback` method is
 
10374    * customized this function returns the custom method, otherwise it returns
 
10375    * the `baseCallback` function. If arguments are provided the chosen function
 
10376    * is invoked with them and its result is returned.
 
10379    * @returns {Function} Returns the chosen function or its result.
 
10381   function getCallback(func, thisArg, argCount) {
 
10382     var result = lodash.callback || callback;
 
10383     result = result === callback ? baseCallback : result;
 
10384     return argCount ? result(func, thisArg, argCount) : result;
 
10388    * Gets metadata for `func`.
 
10391    * @param {Function} func The function to query.
 
10392    * @returns {*} Returns the metadata for `func`.
 
10394   var getData = !metaMap ? noop : function(func) {
 
10395     return metaMap.get(func);
 
10399    * Gets the name of `func`.
 
10402    * @param {Function} func The function to query.
 
10403    * @returns {string} Returns the function name.
 
10405   function getFuncName(func) {
 
10406     var result = func.name,
 
10407         array = realNames[result],
 
10408         length = array ? array.length : 0;
 
10411       var data = array[length],
 
10412           otherFunc = data.func;
 
10413       if (otherFunc == null || otherFunc == func) {
 
10421    * Gets the appropriate "indexOf" function. If the `_.indexOf` method is
 
10422    * customized this function returns the custom method, otherwise it returns
 
10423    * the `baseIndexOf` function. If arguments are provided the chosen function
 
10424    * is invoked with them and its result is returned.
 
10427    * @returns {Function|number} Returns the chosen function or its result.
 
10429   function getIndexOf(collection, target, fromIndex) {
 
10430     var result = lodash.indexOf || indexOf;
 
10431     result = result === indexOf ? baseIndexOf : result;
 
10432     return collection ? result(collection, target, fromIndex) : result;
 
10436    * Gets the "length" property value of `object`.
 
10438    * **Note:** This function is used to avoid a [JIT bug](https://bugs.webkit.org/show_bug.cgi?id=142792)
 
10439    * that affects Safari on at least iOS 8.1-8.3 ARM64.
 
10442    * @param {Object} object The object to query.
 
10443    * @returns {*} Returns the "length" value.
 
10445   var getLength = baseProperty('length');
 
10448    * Gets the propery names, values, and compare flags of `object`.
 
10451    * @param {Object} object The object to query.
 
10452    * @returns {Array} Returns the match data of `object`.
 
10454   function getMatchData(object) {
 
10455     var result = pairs(object),
 
10456         length = result.length;
 
10459       result[length][2] = isStrictComparable(result[length][1]);
 
10465    * Gets the native function at `key` of `object`.
 
10468    * @param {Object} object The object to query.
 
10469    * @param {string} key The key of the method to get.
 
10470    * @returns {*} Returns the function if it's native, else `undefined`.
 
10472   function getNative(object, key) {
 
10473     var value = object == null ? undefined : object[key];
 
10474     return isNative(value) ? value : undefined;
 
10478    * Gets the view, applying any `transforms` to the `start` and `end` positions.
 
10481    * @param {number} start The start of the view.
 
10482    * @param {number} end The end of the view.
 
10483    * @param {Array} [transforms] The transformations to apply to the view.
 
10484    * @returns {Object} Returns an object containing the `start` and `end`
 
10485    *  positions of the view.
 
10487   function getView(start, end, transforms) {
 
10489         length = transforms ? transforms.length : 0;
 
10491     while (++index < length) {
 
10492       var data = transforms[index],
 
10495       switch (data.type) {
 
10496         case 'drop':      start += size; break;
 
10497         case 'dropRight': end -= size; break;
 
10498         case 'take':      end = nativeMin(end, start + size); break;
 
10499         case 'takeRight': start = nativeMax(start, end - size); break;
 
10502     return { 'start': start, 'end': end };
 
10506    * Initializes an array clone.
 
10509    * @param {Array} array The array to clone.
 
10510    * @returns {Array} Returns the initialized clone.
 
10512   function initCloneArray(array) {
 
10513     var length = array.length,
 
10514         result = new array.constructor(length);
 
10516     // Add array properties assigned by `RegExp#exec`.
 
10517     if (length && typeof array[0] == 'string' && hasOwnProperty.call(array, 'index')) {
 
10518       result.index = array.index;
 
10519       result.input = array.input;
 
10525    * Initializes an object clone.
 
10528    * @param {Object} object The object to clone.
 
10529    * @returns {Object} Returns the initialized clone.
 
10531   function initCloneObject(object) {
 
10532     var Ctor = object.constructor;
 
10533     if (!(typeof Ctor == 'function' && Ctor instanceof Ctor)) {
 
10540    * Initializes an object clone based on its `toStringTag`.
 
10542    * **Note:** This function only supports cloning values with tags of
 
10543    * `Boolean`, `Date`, `Error`, `Number`, `RegExp`, or `String`.
 
10546    * @param {Object} object The object to clone.
 
10547    * @param {string} tag The `toStringTag` of the object to clone.
 
10548    * @param {boolean} [isDeep] Specify a deep clone.
 
10549    * @returns {Object} Returns the initialized clone.
 
10551   function initCloneByTag(object, tag, isDeep) {
 
10552     var Ctor = object.constructor;
 
10554       case arrayBufferTag:
 
10555         return bufferClone(object);
 
10559         return new Ctor(+object);
 
10561       case float32Tag: case float64Tag:
 
10562       case int8Tag: case int16Tag: case int32Tag:
 
10563       case uint8Tag: case uint8ClampedTag: case uint16Tag: case uint32Tag:
 
10564         // Safari 5 mobile incorrectly has `Object` as the constructor of typed arrays.
 
10565         if (Ctor instanceof Ctor) {
 
10566           Ctor = ctorByTag[tag];
 
10568         var buffer = object.buffer;
 
10569         return new Ctor(isDeep ? bufferClone(buffer) : buffer, object.byteOffset, object.length);
 
10573         return new Ctor(object);
 
10576         var result = new Ctor(object.source, reFlags.exec(object));
 
10577         result.lastIndex = object.lastIndex;
 
10583    * Checks if `value` is array-like.
 
10586    * @param {*} value The value to check.
 
10587    * @returns {boolean} Returns `true` if `value` is array-like, else `false`.
 
10589   function isArrayLike(value) {
 
10590     return value != null && isLength(getLength(value));
 
10594    * Checks if `value` is a valid array-like index.
 
10597    * @param {*} value The value to check.
 
10598    * @param {number} [length=MAX_SAFE_INTEGER] The upper bounds of a valid index.
 
10599    * @returns {boolean} Returns `true` if `value` is a valid index, else `false`.
 
10601   function isIndex(value, length) {
 
10602     value = (typeof value == 'number' || reIsUint.test(value)) ? +value : -1;
 
10603     length = length == null ? MAX_SAFE_INTEGER : length;
 
10604     return value > -1 && value % 1 == 0 && value < length;
 
10608    * Checks if the provided arguments are from an iteratee call.
 
10611    * @param {*} value The potential iteratee value argument.
 
10612    * @param {*} index The potential iteratee index or key argument.
 
10613    * @param {*} object The potential iteratee object argument.
 
10614    * @returns {boolean} Returns `true` if the arguments are from an iteratee call, else `false`.
 
10616   function isIterateeCall(value, index, object) {
 
10617     if (!isObject(object)) {
 
10620     var type = typeof index;
 
10621     if (type == 'number'
 
10622         ? (isArrayLike(object) && isIndex(index, object.length))
 
10623         : (type == 'string' && index in object)) {
 
10624       var other = object[index];
 
10625       return value === value ? (value === other) : (other !== other);
 
10631    * Checks if `value` is a property name and not a property path.
 
10634    * @param {*} value The value to check.
 
10635    * @param {Object} [object] The object to query keys on.
 
10636    * @returns {boolean} Returns `true` if `value` is a property name, else `false`.
 
10638   function isKey(value, object) {
 
10639     var type = typeof value;
 
10640     if ((type == 'string' && reIsPlainProp.test(value)) || type == 'number') {
 
10643     if (isArray(value)) {
 
10646     var result = !reIsDeepProp.test(value);
 
10647     return result || (object != null && value in toObject(object));
 
10651    * Checks if `func` has a lazy counterpart.
 
10654    * @param {Function} func The function to check.
 
10655    * @returns {boolean} Returns `true` if `func` has a lazy counterpart, else `false`.
 
10657   function isLaziable(func) {
 
10658     var funcName = getFuncName(func);
 
10659     if (!(funcName in LazyWrapper.prototype)) {
 
10662     var other = lodash[funcName];
 
10663     if (func === other) {
 
10666     var data = getData(other);
 
10667     return !!data && func === data[0];
 
10671    * Checks if `value` is a valid array-like length.
 
10673    * **Note:** This function is based on [`ToLength`](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-tolength).
 
10676    * @param {*} value The value to check.
 
10677    * @returns {boolean} Returns `true` if `value` is a valid length, else `false`.
 
10679   function isLength(value) {
 
10680     return typeof value == 'number' && value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER;
 
10684    * Checks if `value` is suitable for strict equality comparisons, i.e. `===`.
 
10687    * @param {*} value The value to check.
 
10688    * @returns {boolean} Returns `true` if `value` if suitable for strict
 
10689    *  equality comparisons, else `false`.
 
10691   function isStrictComparable(value) {
 
10692     return value === value && !isObject(value);
 
10696    * Merges the function metadata of `source` into `data`.
 
10698    * Merging metadata reduces the number of wrappers required to invoke a function.
 
10699    * This is possible because methods like `_.bind`, `_.curry`, and `_.partial`
 
10700    * may be applied regardless of execution order. Methods like `_.ary` and `_.rearg`
 
10701    * augment function arguments, making the order in which they are executed important,
 
10702    * preventing the merging of metadata. However, we make an exception for a safe
 
10703    * common case where curried functions have `_.ary` and or `_.rearg` applied.
 
10706    * @param {Array} data The destination metadata.
 
10707    * @param {Array} source The source metadata.
 
10708    * @returns {Array} Returns `data`.
 
10710   function mergeData(data, source) {
 
10711     var bitmask = data[1],
 
10712         srcBitmask = source[1],
 
10713         newBitmask = bitmask | srcBitmask,
 
10714         isCommon = newBitmask < ARY_FLAG;
 
10717       (srcBitmask == ARY_FLAG && bitmask == CURRY_FLAG) ||
 
10718       (srcBitmask == ARY_FLAG && bitmask == REARG_FLAG && data[7].length <= source[8]) ||
 
10719       (srcBitmask == (ARY_FLAG | REARG_FLAG) && bitmask == CURRY_FLAG);
 
10721     // Exit early if metadata can't be merged.
 
10722     if (!(isCommon || isCombo)) {
 
10725     // Use source `thisArg` if available.
 
10726     if (srcBitmask & BIND_FLAG) {
 
10727       data[2] = source[2];
 
10728       // Set when currying a bound function.
 
10729       newBitmask |= (bitmask & BIND_FLAG) ? 0 : CURRY_BOUND_FLAG;
 
10731     // Compose partial arguments.
 
10732     var value = source[3];
 
10734       var partials = data[3];
 
10735       data[3] = partials ? composeArgs(partials, value, source[4]) : arrayCopy(value);
 
10736       data[4] = partials ? replaceHolders(data[3], PLACEHOLDER) : arrayCopy(source[4]);
 
10738     // Compose partial right arguments.
 
10741       partials = data[5];
 
10742       data[5] = partials ? composeArgsRight(partials, value, source[6]) : arrayCopy(value);
 
10743       data[6] = partials ? replaceHolders(data[5], PLACEHOLDER) : arrayCopy(source[6]);
 
10745     // Use source `argPos` if available.
 
10748       data[7] = arrayCopy(value);
 
10750     // Use source `ary` if it's smaller.
 
10751     if (srcBitmask & ARY_FLAG) {
 
10752       data[8] = data[8] == null ? source[8] : nativeMin(data[8], source[8]);
 
10754     // Use source `arity` if one is not provided.
 
10755     if (data[9] == null) {
 
10756       data[9] = source[9];
 
10758     // Use source `func` and merge bitmasks.
 
10759     data[0] = source[0];
 
10760     data[1] = newBitmask;
 
10766    * A specialized version of `_.pick` which picks `object` properties specified
 
10770    * @param {Object} object The source object.
 
10771    * @param {string[]} props The property names to pick.
 
10772    * @returns {Object} Returns the new object.
 
10774   function pickByArray(object, props) {
 
10775     object = toObject(object);
 
10778         length = props.length,
 
10781     while (++index < length) {
 
10782       var key = props[index];
 
10783       if (key in object) {
 
10784         result[key] = object[key];
 
10791    * A specialized version of `_.pick` which picks `object` properties `predicate`
 
10792    * returns truthy for.
 
10795    * @param {Object} object The source object.
 
10796    * @param {Function} predicate The function invoked per iteration.
 
10797    * @returns {Object} Returns the new object.
 
10799   function pickByCallback(object, predicate) {
 
10801     baseForIn(object, function(value, key, object) {
 
10802       if (predicate(value, key, object)) {
 
10803         result[key] = value;
 
10810    * Reorder `array` according to the specified indexes where the element at
 
10811    * the first index is assigned as the first element, the element at
 
10812    * the second index is assigned as the second element, and so on.
 
10815    * @param {Array} array The array to reorder.
 
10816    * @param {Array} indexes The arranged array indexes.
 
10817    * @returns {Array} Returns `array`.
 
10819   function reorder(array, indexes) {
 
10820     var arrLength = array.length,
 
10821         length = nativeMin(indexes.length, arrLength),
 
10822         oldArray = arrayCopy(array);
 
10825       var index = indexes[length];
 
10826       array[length] = isIndex(index, arrLength) ? oldArray[index] : undefined;
 
10832    * Sets metadata for `func`.
 
10834    * **Note:** If this function becomes hot, i.e. is invoked a lot in a short
 
10835    * period of time, it will trip its breaker and transition to an identity function
 
10836    * to avoid garbage collection pauses in V8. See [V8 issue 2070](https://code.google.com/p/v8/issues/detail?id=2070)
 
10837    * for more details.
 
10840    * @param {Function} func The function to associate metadata with.
 
10841    * @param {*} data The metadata.
 
10842    * @returns {Function} Returns `func`.
 
10844   var setData = (function() {
 
10848     return function(key, value) {
 
10850           remaining = HOT_SPAN - (stamp - lastCalled);
 
10852       lastCalled = stamp;
 
10853       if (remaining > 0) {
 
10854         if (++count >= HOT_COUNT) {
 
10860       return baseSetData(key, value);
 
10865    * A fallback implementation of `_.isPlainObject` which checks if `value`
 
10866    * is an object created by the `Object` constructor or has a `[[Prototype]]`
 
10870    * @param {*} value The value to check.
 
10871    * @returns {boolean} Returns `true` if `value` is a plain object, else `false`.
 
10873   function shimIsPlainObject(value) {
 
10875         support = lodash.support;
 
10877     // Exit early for non `Object` objects.
 
10878     if (!(isObjectLike(value) && objToString.call(value) == objectTag && !isHostObject(value)) ||
 
10879         (!hasOwnProperty.call(value, 'constructor') &&
 
10880           (Ctor = value.constructor, typeof Ctor == 'function' && !(Ctor instanceof Ctor))) ||
 
10881         (!support.argsTag && isArguments(value))) {
 
10884     // IE < 9 iterates inherited properties before own properties. If the first
 
10885     // iterated property is an object's own property then there are no inherited
 
10886     // enumerable properties.
 
10888     if (support.ownLast) {
 
10889       baseForIn(value, function(subValue, key, object) {
 
10890         result = hasOwnProperty.call(object, key);
 
10893       return result !== false;
 
10895     // In most environments an object's own properties are iterated before
 
10896     // its inherited properties. If the last iterated property is an object's
 
10897     // own property then there are no inherited enumerable properties.
 
10898     baseForIn(value, function(subValue, key) {
 
10901     return result === undefined || hasOwnProperty.call(value, result);
 
10905    * A fallback implementation of `Object.keys` which creates an array of the
 
10906    * own enumerable property names of `object`.
 
10909    * @param {Object} object The object to query.
 
10910    * @returns {Array} Returns the array of property names.
 
10912   function shimKeys(object) {
 
10913     var props = keysIn(object),
 
10914         propsLength = props.length,
 
10915         length = propsLength && object.length;
 
10917     var allowIndexes = !!length && isLength(length) &&
 
10918       (isArray(object) || isArguments(object) || isString(object));
 
10923     while (++index < propsLength) {
 
10924       var key = props[index];
 
10925       if ((allowIndexes && isIndex(key, length)) || hasOwnProperty.call(object, key)) {
 
10933    * Converts `value` to an object if it's not one.
 
10936    * @param {*} value The value to process.
 
10937    * @returns {Object} Returns the object.
 
10939   function toObject(value) {
 
10940     if (lodash.support.unindexedChars && isString(value)) {
 
10942           length = value.length,
 
10943           result = Object(value);
 
10945       while (++index < length) {
 
10946         result[index] = value.charAt(index);
 
10950     return isObject(value) ? value : Object(value);
 
10954    * Converts `value` to property path array if it's not one.
 
10957    * @param {*} value The value to process.
 
10958    * @returns {Array} Returns the property path array.
 
10960   function toPath(value) {
 
10961     if (isArray(value)) {
 
10965     baseToString(value).replace(rePropName, function(match, number, quote, string) {
 
10966       result.push(quote ? string.replace(reEscapeChar, '$1') : (number || match));
 
10972    * Creates a clone of `wrapper`.
 
10975    * @param {Object} wrapper The wrapper to clone.
 
10976    * @returns {Object} Returns the cloned wrapper.
 
10978   function wrapperClone(wrapper) {
 
10979     return wrapper instanceof LazyWrapper
 
10981       : new LodashWrapper(wrapper.__wrapped__, wrapper.__chain__, arrayCopy(wrapper.__actions__));
 
10984   /*------------------------------------------------------------------------*/
 
10987    * Creates an array of elements split into groups the length of `size`.
 
10988    * If `collection` can't be split evenly, the final chunk will be the remaining
 
10994    * @param {Array} array The array to process.
 
10995    * @param {number} [size=1] The length of each chunk.
 
10996    * @param- {Object} [guard] Enables use as a callback for functions like `_.map`.
 
10997    * @returns {Array} Returns the new array containing chunks.
 
11000    * _.chunk(['a', 'b', 'c', 'd'], 2);
 
11001    * // => [['a', 'b'], ['c', 'd']]
 
11003    * _.chunk(['a', 'b', 'c', 'd'], 3);
 
11004    * // => [['a', 'b', 'c'], ['d']]
 
11006   function chunk(array, size, guard) {
 
11007     if (guard ? isIterateeCall(array, size, guard) : size == null) {
 
11010       size = nativeMax(+size || 1, 1);
 
11013         length = array ? array.length : 0,
 
11015         result = Array(ceil(length / size));
 
11017     while (index < length) {
 
11018       result[++resIndex] = baseSlice(array, index, (index += size));
 
11024    * Creates an array with all falsey values removed. The values `false`, `null`,
 
11025    * `0`, `""`, `undefined`, and `NaN` are falsey.
 
11030    * @param {Array} array The array to compact.
 
11031    * @returns {Array} Returns the new array of filtered values.
 
11034    * _.compact([0, 1, false, 2, '', 3]);
 
11037   function compact(array) {
 
11039         length = array ? array.length : 0,
 
11043     while (++index < length) {
 
11044       var value = array[index];
 
11046         result[++resIndex] = value;
 
11053    * Creates an array of unique `array` values not included in the other
 
11054    * provided arrays using [`SameValueZero`](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-samevaluezero)
 
11055    * for equality comparisons.
 
11060    * @param {Array} array The array to inspect.
 
11061    * @param {...Array} [values] The arrays of values to exclude.
 
11062    * @returns {Array} Returns the new array of filtered values.
 
11065    * _.difference([1, 2, 3], [4, 2]);
 
11068   var difference = restParam(function(array, values) {
 
11069     return isArrayLike(array)
 
11070       ? baseDifference(array, baseFlatten(values, false, true))
 
11075    * Gets the first element of `array`.
 
11081    * @param {Array} array The array to query.
 
11082    * @returns {*} Returns the first element of `array`.
 
11085    * _.first([1, 2, 3]);
 
11091   function first(array) {
 
11092     return array ? array[0] : undefined;
 
11096    * Flattens a nested array. If `isDeep` is `true` the array is recursively
 
11097    * flattened, otherwise it is only flattened a single level.
 
11102    * @param {Array} array The array to flatten.
 
11103    * @param {boolean} [isDeep] Specify a deep flatten.
 
11104    * @param- {Object} [guard] Enables use as a callback for functions like `_.map`.
 
11105    * @returns {Array} Returns the new flattened array.
 
11108    * _.flatten([1, [2, 3, [4]]]);
 
11109    * // => [1, 2, 3, [4]]
 
11111    * // using `isDeep`
 
11112    * _.flatten([1, [2, 3, [4]]], true);
 
11113    * // => [1, 2, 3, 4]
 
11115   function flatten(array, isDeep, guard) {
 
11116     var length = array ? array.length : 0;
 
11117     if (guard && isIterateeCall(array, isDeep, guard)) {
 
11120     return length ? baseFlatten(array, isDeep) : [];
 
11124    * Gets the index at which the first occurrence of `value` is found in `array`
 
11125    * using [`SameValueZero`](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-samevaluezero)
 
11126    * for equality comparisons. If `fromIndex` is negative, it is used as the offset
 
11127    * from the end of `array`. If `array` is sorted providing `true` for `fromIndex`
 
11128    * performs a faster binary search.
 
11133    * @param {Array} array The array to search.
 
11134    * @param {*} value The value to search for.
 
11135    * @param {boolean|number} [fromIndex=0] The index to search from or `true`
 
11136    *  to perform a binary search on a sorted array.
 
11137    * @returns {number} Returns the index of the matched value, else `-1`.
 
11140    * _.indexOf([1, 2, 1, 2], 2);
 
11143    * // using `fromIndex`
 
11144    * _.indexOf([1, 2, 1, 2], 2, 2);
 
11147    * // performing a binary search
 
11148    * _.indexOf([1, 1, 2, 2], 2, true);
 
11151   function indexOf(array, value, fromIndex) {
 
11152     var length = array ? array.length : 0;
 
11156     if (typeof fromIndex == 'number') {
 
11157       fromIndex = fromIndex < 0 ? nativeMax(length + fromIndex, 0) : fromIndex;
 
11158     } else if (fromIndex) {
 
11159       var index = binaryIndex(array, value),
 
11160           other = array[index];
 
11162       if (value === value ? (value === other) : (other !== other)) {
 
11167     return baseIndexOf(array, value, fromIndex || 0);
 
11171    * Creates an array of unique values that are included in all of the provided
 
11172    * arrays using [`SameValueZero`](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-samevaluezero)
 
11173    * for equality comparisons.
 
11178    * @param {...Array} [arrays] The arrays to inspect.
 
11179    * @returns {Array} Returns the new array of shared values.
 
11181    * _.intersection([1, 2], [4, 2], [2, 1]);
 
11184   var intersection = restParam(function(arrays) {
 
11185     var othLength = arrays.length,
 
11186         othIndex = othLength,
 
11187         caches = Array(length),
 
11188         indexOf = getIndexOf(),
 
11189         isCommon = indexOf == baseIndexOf,
 
11192     while (othIndex--) {
 
11193       var value = arrays[othIndex] = isArrayLike(value = arrays[othIndex]) ? value : [];
 
11194       caches[othIndex] = (isCommon && value.length >= 120) ? createCache(othIndex && value) : null;
 
11196     var array = arrays[0],
 
11198         length = array ? array.length : 0,
 
11202     while (++index < length) {
 
11203       value = array[index];
 
11204       if ((seen ? cacheIndexOf(seen, value) : indexOf(result, value, 0)) < 0) {
 
11205         var othIndex = othLength;
 
11206         while (--othIndex) {
 
11207           var cache = caches[othIndex];
 
11208           if ((cache ? cacheIndexOf(cache, value) : indexOf(arrays[othIndex], value, 0)) < 0) {
 
11215         result.push(value);
 
11222    * Gets the last element of `array`.
 
11227    * @param {Array} array The array to query.
 
11228    * @returns {*} Returns the last element of `array`.
 
11231    * _.last([1, 2, 3]);
 
11234   function last(array) {
 
11235     var length = array ? array.length : 0;
 
11236     return length ? array[length - 1] : undefined;
 
11240    * Creates an array of unique values, in order, from all of the provided arrays
 
11241    * using [`SameValueZero`](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-samevaluezero)
 
11242    * for equality comparisons.
 
11247    * @param {...Array} [arrays] The arrays to inspect.
 
11248    * @returns {Array} Returns the new array of combined values.
 
11251    * _.union([1, 2], [4, 2], [2, 1]);
 
11254   var union = restParam(function(arrays) {
 
11255     return baseUniq(baseFlatten(arrays, false, true));
 
11259    * Creates a duplicate-free version of an array, using
 
11260    * [`SameValueZero`](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-samevaluezero)
 
11261    * for equality comparisons, in which only the first occurence of each element
 
11262    * is kept. Providing `true` for `isSorted` performs a faster search algorithm
 
11263    * for sorted arrays. If an iteratee function is provided it is invoked for
 
11264    * each element in the array to generate the criterion by which uniqueness
 
11265    * is computed. The `iteratee` is bound to `thisArg` and invoked with three
 
11266    * arguments: (value, index, array).
 
11268    * If a property name is provided for `iteratee` the created `_.property`
 
11269    * style callback returns the property value of the given element.
 
11271    * If a value is also provided for `thisArg` the created `_.matchesProperty`
 
11272    * style callback returns `true` for elements that have a matching property
 
11273    * value, else `false`.
 
11275    * If an object is provided for `iteratee` the created `_.matches` style
 
11276    * callback returns `true` for elements that have the properties of the given
 
11277    * object, else `false`.
 
11283    * @param {Array} array The array to inspect.
 
11284    * @param {boolean} [isSorted] Specify the array is sorted.
 
11285    * @param {Function|Object|string} [iteratee] The function invoked per iteration.
 
11286    * @param {*} [thisArg] The `this` binding of `iteratee`.
 
11287    * @returns {Array} Returns the new duplicate-value-free array.
 
11290    * _.uniq([2, 1, 2]);
 
11293    * // using `isSorted`
 
11294    * _.uniq([1, 1, 2], true);
 
11297    * // using an iteratee function
 
11298    * _.uniq([1, 2.5, 1.5, 2], function(n) {
 
11299    *   return this.floor(n);
 
11303    * // using the `_.property` callback shorthand
 
11304    * _.uniq([{ 'x': 1 }, { 'x': 2 }, { 'x': 1 }], 'x');
 
11305    * // => [{ 'x': 1 }, { 'x': 2 }]
 
11307   function uniq(array, isSorted, iteratee, thisArg) {
 
11308     var length = array ? array.length : 0;
 
11312     if (isSorted != null && typeof isSorted != 'boolean') {
 
11313       thisArg = iteratee;
 
11314       iteratee = isIterateeCall(array, isSorted, thisArg) ? null : isSorted;
 
11317     var callback = getCallback();
 
11318     if (!(iteratee == null && callback === baseCallback)) {
 
11319       iteratee = callback(iteratee, thisArg, 3);
 
11321     return (isSorted && getIndexOf() == baseIndexOf)
 
11322       ? sortedUniq(array, iteratee)
 
11323       : baseUniq(array, iteratee);
 
11327    * Creates an array excluding all provided values using
 
11328    * [`SameValueZero`](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-samevaluezero)
 
11329    * for equality comparisons.
 
11334    * @param {Array} array The array to filter.
 
11335    * @param {...*} [values] The values to exclude.
 
11336    * @returns {Array} Returns the new array of filtered values.
 
11339    * _.without([1, 2, 1, 3], 1, 2);
 
11342   var without = restParam(function(array, values) {
 
11343     return isArrayLike(array)
 
11344       ? baseDifference(array, values)
 
11348   /*------------------------------------------------------------------------*/
 
11351    * Creates a `lodash` object that wraps `value` with explicit method
 
11352    * chaining enabled.
 
11357    * @param {*} value The value to wrap.
 
11358    * @returns {Object} Returns the new `lodash` wrapper instance.
 
11362    *   { 'user': 'barney',  'age': 36 },
 
11363    *   { 'user': 'fred',    'age': 40 },
 
11364    *   { 'user': 'pebbles', 'age': 1 }
 
11367    * var youngest = _.chain(users)
 
11369    *   .map(function(chr) {
 
11370    *     return chr.user + ' is ' + chr.age;
 
11374    * // => 'pebbles is 1'
 
11376   function chain(value) {
 
11377     var result = lodash(value);
 
11378     result.__chain__ = true;
 
11383    * This method invokes `interceptor` and returns `value`. The interceptor is
 
11384    * bound to `thisArg` and invoked with one argument; (value). The purpose of
 
11385    * this method is to "tap into" a method chain in order to perform operations
 
11386    * on intermediate results within the chain.
 
11391    * @param {*} value The value to provide to `interceptor`.
 
11392    * @param {Function} interceptor The function to invoke.
 
11393    * @param {*} [thisArg] The `this` binding of `interceptor`.
 
11394    * @returns {*} Returns `value`.
 
11398    *  .tap(function(array) {
 
11405   function tap(value, interceptor, thisArg) {
 
11406     interceptor.call(thisArg, value);
 
11411    * This method is like `_.tap` except that it returns the result of `interceptor`.
 
11416    * @param {*} value The value to provide to `interceptor`.
 
11417    * @param {Function} interceptor The function to invoke.
 
11418    * @param {*} [thisArg] The `this` binding of `interceptor`.
 
11419    * @returns {*} Returns the result of `interceptor`.
 
11425    *  .thru(function(value) {
 
11431   function thru(value, interceptor, thisArg) {
 
11432     return interceptor.call(thisArg, value);
 
11436    * Enables explicit method chaining on the wrapper object.
 
11441    * @returns {Object} Returns the new `lodash` wrapper instance.
 
11445    *   { 'user': 'barney', 'age': 36 },
 
11446    *   { 'user': 'fred',   'age': 40 }
 
11449    * // without explicit chaining
 
11450    * _(users).first();
 
11451    * // => { 'user': 'barney', 'age': 36 }
 
11453    * // with explicit chaining
 
11458    * // => { 'user': 'barney' }
 
11460   function wrapperChain() {
 
11461     return chain(this);
 
11465    * Executes the chained sequence and returns the wrapped result.
 
11470    * @returns {Object} Returns the new `lodash` wrapper instance.
 
11473    * var array = [1, 2];
 
11474    * var wrapper = _(array).push(3);
 
11476    * console.log(array);
 
11479    * wrapper = wrapper.commit();
 
11480    * console.log(array);
 
11486    * console.log(array);
 
11489   function wrapperCommit() {
 
11490     return new LodashWrapper(this.value(), this.__chain__);
 
11494    * Creates a clone of the chained sequence planting `value` as the wrapped value.
 
11499    * @returns {Object} Returns the new `lodash` wrapper instance.
 
11502    * var array = [1, 2];
 
11503    * var wrapper = _(array).map(function(value) {
 
11504    *   return Math.pow(value, 2);
 
11507    * var other = [3, 4];
 
11508    * var otherWrapper = wrapper.plant(other);
 
11510    * otherWrapper.value();
 
11516   function wrapperPlant(value) {
 
11520     while (parent instanceof baseLodash) {
 
11521       var clone = wrapperClone(parent);
 
11523         previous.__wrapped__ = clone;
 
11527       var previous = clone;
 
11528       parent = parent.__wrapped__;
 
11530     previous.__wrapped__ = value;
 
11535    * Reverses the wrapped array so the first element becomes the last, the
 
11536    * second element becomes the second to last, and so on.
 
11538    * **Note:** This method mutates the wrapped array.
 
11543    * @returns {Object} Returns the new reversed `lodash` wrapper instance.
 
11546    * var array = [1, 2, 3];
 
11548    * _(array).reverse().value()
 
11551    * console.log(array);
 
11554   function wrapperReverse() {
 
11555     var value = this.__wrapped__;
 
11556     if (value instanceof LazyWrapper) {
 
11557       if (this.__actions__.length) {
 
11558         value = new LazyWrapper(this);
 
11560       return new LodashWrapper(value.reverse(), this.__chain__);
 
11562     return this.thru(function(value) {
 
11563       return value.reverse();
 
11568    * Produces the result of coercing the unwrapped value to a string.
 
11573    * @returns {string} Returns the coerced string value.
 
11576    * _([1, 2, 3]).toString();
 
11579   function wrapperToString() {
 
11580     return (this.value() + '');
 
11584    * Executes the chained sequence to extract the unwrapped value.
 
11588    * @alias run, toJSON, valueOf
 
11590    * @returns {*} Returns the resolved unwrapped value.
 
11593    * _([1, 2, 3]).value();
 
11596   function wrapperValue() {
 
11597     return baseWrapperValue(this.__wrapped__, this.__actions__);
 
11600   /*------------------------------------------------------------------------*/
 
11603    * Checks if `predicate` returns truthy for **all** elements of `collection`.
 
11604    * The predicate is bound to `thisArg` and invoked with three arguments:
 
11605    * (value, index|key, collection).
 
11607    * If a property name is provided for `predicate` the created `_.property`
 
11608    * style callback returns the property value of the given element.
 
11610    * If a value is also provided for `thisArg` the created `_.matchesProperty`
 
11611    * style callback returns `true` for elements that have a matching property
 
11612    * value, else `false`.
 
11614    * If an object is provided for `predicate` the created `_.matches` style
 
11615    * callback returns `true` for elements that have the properties of the given
 
11616    * object, else `false`.
 
11621    * @category Collection
 
11622    * @param {Array|Object|string} collection The collection to iterate over.
 
11623    * @param {Function|Object|string} [predicate=_.identity] The function invoked
 
11625    * @param {*} [thisArg] The `this` binding of `predicate`.
 
11626    * @returns {boolean} Returns `true` if all elements pass the predicate check,
 
11630    * _.every([true, 1, null, 'yes'], Boolean);
 
11634    *   { 'user': 'barney', 'active': false },
 
11635    *   { 'user': 'fred',   'active': false }
 
11638    * // using the `_.matches` callback shorthand
 
11639    * _.every(users, { 'user': 'barney', 'active': false });
 
11642    * // using the `_.matchesProperty` callback shorthand
 
11643    * _.every(users, 'active', false);
 
11646    * // using the `_.property` callback shorthand
 
11647    * _.every(users, 'active');
 
11650   function every(collection, predicate, thisArg) {
 
11651     var func = isArray(collection) ? arrayEvery : baseEvery;
 
11652     if (thisArg && isIterateeCall(collection, predicate, thisArg)) {
 
11655     if (typeof predicate != 'function' || thisArg !== undefined) {
 
11656       predicate = getCallback(predicate, thisArg, 3);
 
11658     return func(collection, predicate);
 
11662    * Iterates over elements of `collection`, returning an array of all elements
 
11663    * `predicate` returns truthy for. The predicate is bound to `thisArg` and
 
11664    * invoked with three arguments: (value, index|key, collection).
 
11666    * If a property name is provided for `predicate` the created `_.property`
 
11667    * style callback returns the property value of the given element.
 
11669    * If a value is also provided for `thisArg` the created `_.matchesProperty`
 
11670    * style callback returns `true` for elements that have a matching property
 
11671    * value, else `false`.
 
11673    * If an object is provided for `predicate` the created `_.matches` style
 
11674    * callback returns `true` for elements that have the properties of the given
 
11675    * object, else `false`.
 
11680    * @category Collection
 
11681    * @param {Array|Object|string} collection The collection to iterate over.
 
11682    * @param {Function|Object|string} [predicate=_.identity] The function invoked
 
11684    * @param {*} [thisArg] The `this` binding of `predicate`.
 
11685    * @returns {Array} Returns the new filtered array.
 
11688    * _.filter([4, 5, 6], function(n) {
 
11689    *   return n % 2 == 0;
 
11694    *   { 'user': 'barney', 'age': 36, 'active': true },
 
11695    *   { 'user': 'fred',   'age': 40, 'active': false }
 
11698    * // using the `_.matches` callback shorthand
 
11699    * _.pluck(_.filter(users, { 'age': 36, 'active': true }), 'user');
 
11702    * // using the `_.matchesProperty` callback shorthand
 
11703    * _.pluck(_.filter(users, 'active', false), 'user');
 
11706    * // using the `_.property` callback shorthand
 
11707    * _.pluck(_.filter(users, 'active'), 'user');
 
11710   function filter(collection, predicate, thisArg) {
 
11711     var func = isArray(collection) ? arrayFilter : baseFilter;
 
11712     predicate = getCallback(predicate, thisArg, 3);
 
11713     return func(collection, predicate);
 
11717    * Iterates over elements of `collection`, returning the first element
 
11718    * `predicate` returns truthy for. The predicate is bound to `thisArg` and
 
11719    * invoked with three arguments: (value, index|key, collection).
 
11721    * If a property name is provided for `predicate` the created `_.property`
 
11722    * style callback returns the property value of the given element.
 
11724    * If a value is also provided for `thisArg` the created `_.matchesProperty`
 
11725    * style callback returns `true` for elements that have a matching property
 
11726    * value, else `false`.
 
11728    * If an object is provided for `predicate` the created `_.matches` style
 
11729    * callback returns `true` for elements that have the properties of the given
 
11730    * object, else `false`.
 
11735    * @category Collection
 
11736    * @param {Array|Object|string} collection The collection to search.
 
11737    * @param {Function|Object|string} [predicate=_.identity] The function invoked
 
11739    * @param {*} [thisArg] The `this` binding of `predicate`.
 
11740    * @returns {*} Returns the matched element, else `undefined`.
 
11744    *   { 'user': 'barney',  'age': 36, 'active': true },
 
11745    *   { 'user': 'fred',    'age': 40, 'active': false },
 
11746    *   { 'user': 'pebbles', 'age': 1,  'active': true }
 
11749    * _.result(_.find(users, function(chr) {
 
11750    *   return chr.age < 40;
 
11754    * // using the `_.matches` callback shorthand
 
11755    * _.result(_.find(users, { 'age': 1, 'active': true }), 'user');
 
11758    * // using the `_.matchesProperty` callback shorthand
 
11759    * _.result(_.find(users, 'active', false), 'user');
 
11762    * // using the `_.property` callback shorthand
 
11763    * _.result(_.find(users, 'active'), 'user');
 
11766   var find = createFind(baseEach);
 
11769    * Iterates over elements of `collection` invoking `iteratee` for each element.
 
11770    * The `iteratee` is bound to `thisArg` and invoked with three arguments:
 
11771    * (value, index|key, collection). Iteratee functions may exit iteration early
 
11772    * by explicitly returning `false`.
 
11774    * **Note:** As with other "Collections" methods, objects with a "length" property
 
11775    * are iterated like arrays. To avoid this behavior `_.forIn` or `_.forOwn`
 
11776    * may be used for object iteration.
 
11781    * @category Collection
 
11782    * @param {Array|Object|string} collection The collection to iterate over.
 
11783    * @param {Function} [iteratee=_.identity] The function invoked per iteration.
 
11784    * @param {*} [thisArg] The `this` binding of `iteratee`.
 
11785    * @returns {Array|Object|string} Returns `collection`.
 
11788    * _([1, 2]).forEach(function(n) {
 
11791    * // => logs each value from left to right and returns the array
 
11793    * _.forEach({ 'a': 1, 'b': 2 }, function(n, key) {
 
11794    *   console.log(n, key);
 
11796    * // => logs each value-key pair and returns the object (iteration order is not guaranteed)
 
11798   var forEach = createForEach(arrayEach, baseEach);
 
11801    * Creates an object composed of keys generated from the results of running
 
11802    * each element of `collection` through `iteratee`. The corresponding value
 
11803    * of each key is an array of the elements responsible for generating the key.
 
11804    * The `iteratee` is bound to `thisArg` and invoked with three arguments:
 
11805    * (value, index|key, collection).
 
11807    * If a property name is provided for `iteratee` the created `_.property`
 
11808    * style callback returns the property value of the given element.
 
11810    * If a value is also provided for `thisArg` the created `_.matchesProperty`
 
11811    * style callback returns `true` for elements that have a matching property
 
11812    * value, else `false`.
 
11814    * If an object is provided for `iteratee` the created `_.matches` style
 
11815    * callback returns `true` for elements that have the properties of the given
 
11816    * object, else `false`.
 
11820    * @category Collection
 
11821    * @param {Array|Object|string} collection The collection to iterate over.
 
11822    * @param {Function|Object|string} [iteratee=_.identity] The function invoked
 
11824    * @param {*} [thisArg] The `this` binding of `iteratee`.
 
11825    * @returns {Object} Returns the composed aggregate object.
 
11828    * _.groupBy([4.2, 6.1, 6.4], function(n) {
 
11829    *   return Math.floor(n);
 
11831    * // => { '4': [4.2], '6': [6.1, 6.4] }
 
11833    * _.groupBy([4.2, 6.1, 6.4], function(n) {
 
11834    *   return this.floor(n);
 
11836    * // => { '4': [4.2], '6': [6.1, 6.4] }
 
11838    * // using the `_.property` callback shorthand
 
11839    * _.groupBy(['one', 'two', 'three'], 'length');
 
11840    * // => { '3': ['one', 'two'], '5': ['three'] }
 
11842   var groupBy = createAggregator(function(result, value, key) {
 
11843     if (hasOwnProperty.call(result, key)) {
 
11844       result[key].push(value);
 
11846       result[key] = [value];
 
11851    * Checks if `value` is in `collection` using
 
11852    * [`SameValueZero`](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-samevaluezero)
 
11853    * for equality comparisons. If `fromIndex` is negative, it is used as the offset
 
11854    * from the end of `collection`.
 
11858    * @alias contains, include
 
11859    * @category Collection
 
11860    * @param {Array|Object|string} collection The collection to search.
 
11861    * @param {*} target The value to search for.
 
11862    * @param {number} [fromIndex=0] The index to search from.
 
11863    * @param- {Object} [guard] Enables use as a callback for functions like `_.reduce`.
 
11864    * @returns {boolean} Returns `true` if a matching element is found, else `false`.
 
11867    * _.includes([1, 2, 3], 1);
 
11870    * _.includes([1, 2, 3], 1, 2);
 
11873    * _.includes({ 'user': 'fred', 'age': 40 }, 'fred');
 
11876    * _.includes('pebbles', 'eb');
 
11879   function includes(collection, target, fromIndex, guard) {
 
11880     var length = collection ? getLength(collection) : 0;
 
11881     if (!isLength(length)) {
 
11882       collection = values(collection);
 
11883       length = collection.length;
 
11888     if (typeof fromIndex != 'number' || (guard && isIterateeCall(target, fromIndex, guard))) {
 
11891       fromIndex = fromIndex < 0 ? nativeMax(length + fromIndex, 0) : (fromIndex || 0);
 
11893     return (typeof collection == 'string' || !isArray(collection) && isString(collection))
 
11894       ? (fromIndex < length && collection.indexOf(target, fromIndex) > -1)
 
11895       : (getIndexOf(collection, target, fromIndex) > -1);
 
11899    * Creates an array of values by running each element in `collection` through
 
11900    * `iteratee`. The `iteratee` is bound to `thisArg` and invoked with three
 
11901    * arguments: (value, index|key, collection).
 
11903    * If a property name is provided for `iteratee` the created `_.property`
 
11904    * style callback returns the property value of the given element.
 
11906    * If a value is also provided for `thisArg` the created `_.matchesProperty`
 
11907    * style callback returns `true` for elements that have a matching property
 
11908    * value, else `false`.
 
11910    * If an object is provided for `iteratee` the created `_.matches` style
 
11911    * callback returns `true` for elements that have the properties of the given
 
11912    * object, else `false`.
 
11914    * Many lodash methods are guarded to work as iteratees for methods like
 
11915    * `_.every`, `_.filter`, `_.map`, `_.mapValues`, `_.reject`, and `_.some`.
 
11917    * The guarded methods are:
 
11918    * `ary`, `callback`, `chunk`, `clone`, `create`, `curry`, `curryRight`,
 
11919    * `drop`, `dropRight`, `every`, `fill`, `flatten`, `invert`, `max`, `min`,
 
11920    * `parseInt`, `slice`, `sortBy`, `take`, `takeRight`, `template`, `trim`,
 
11921    * `trimLeft`, `trimRight`, `trunc`, `random`, `range`, `sample`, `some`,
 
11922    * `sum`, `uniq`, and `words`
 
11927    * @category Collection
 
11928    * @param {Array|Object|string} collection The collection to iterate over.
 
11929    * @param {Function|Object|string} [iteratee=_.identity] The function invoked
 
11931    * @param {*} [thisArg] The `this` binding of `iteratee`.
 
11932    * @returns {Array} Returns the new mapped array.
 
11935    * function timesThree(n) {
 
11939    * _.map([1, 2], timesThree);
 
11942    * _.map({ 'a': 1, 'b': 2 }, timesThree);
 
11943    * // => [3, 6] (iteration order is not guaranteed)
 
11946    *   { 'user': 'barney' },
 
11947    *   { 'user': 'fred' }
 
11950    * // using the `_.property` callback shorthand
 
11951    * _.map(users, 'user');
 
11952    * // => ['barney', 'fred']
 
11954   function map(collection, iteratee, thisArg) {
 
11955     var func = isArray(collection) ? arrayMap : baseMap;
 
11956     iteratee = getCallback(iteratee, thisArg, 3);
 
11957     return func(collection, iteratee);
 
11961    * Gets the property value of `path` from all elements in `collection`.
 
11965    * @category Collection
 
11966    * @param {Array|Object|string} collection The collection to iterate over.
 
11967    * @param {Array|string} path The path of the property to pluck.
 
11968    * @returns {Array} Returns the property values.
 
11972    *   { 'user': 'barney', 'age': 36 },
 
11973    *   { 'user': 'fred',   'age': 40 }
 
11976    * _.pluck(users, 'user');
 
11977    * // => ['barney', 'fred']
 
11979    * var userIndex = _.indexBy(users, 'user');
 
11980    * _.pluck(userIndex, 'age');
 
11981    * // => [36, 40] (iteration order is not guaranteed)
 
11983   function pluck(collection, path) {
 
11984     return map(collection, property(path));
 
11988    * Reduces `collection` to a value which is the accumulated result of running
 
11989    * each element in `collection` through `iteratee`, where each successive
 
11990    * invocation is supplied the return value of the previous. If `accumulator`
 
11991    * is not provided the first element of `collection` is used as the initial
 
11992    * value. The `iteratee` is bound to `thisArg` and invoked with four arguments:
 
11993    * (accumulator, value, index|key, collection).
 
11995    * Many lodash methods are guarded to work as iteratees for methods like
 
11996    * `_.reduce`, `_.reduceRight`, and `_.transform`.
 
11998    * The guarded methods are:
 
11999    * `assign`, `defaults`, `includes`, `merge`, `sortByAll`, and `sortByOrder`
 
12003    * @alias foldl, inject
 
12004    * @category Collection
 
12005    * @param {Array|Object|string} collection The collection to iterate over.
 
12006    * @param {Function} [iteratee=_.identity] The function invoked per iteration.
 
12007    * @param {*} [accumulator] The initial value.
 
12008    * @param {*} [thisArg] The `this` binding of `iteratee`.
 
12009    * @returns {*} Returns the accumulated value.
 
12012    * _.reduce([1, 2], function(total, n) {
 
12013    *   return total + n;
 
12017    * _.reduce({ 'a': 1, 'b': 2 }, function(result, n, key) {
 
12018    *   result[key] = n * 3;
 
12021    * // => { 'a': 3, 'b': 6 } (iteration order is not guaranteed)
 
12023   var reduce = createReduce(arrayReduce, baseEach);
 
12026    * The opposite of `_.filter`; this method returns the elements of `collection`
 
12027    * that `predicate` does **not** return truthy for.
 
12031    * @category Collection
 
12032    * @param {Array|Object|string} collection The collection to iterate over.
 
12033    * @param {Function|Object|string} [predicate=_.identity] The function invoked
 
12035    * @param {*} [thisArg] The `this` binding of `predicate`.
 
12036    * @returns {Array} Returns the new filtered array.
 
12039    * _.reject([1, 2, 3, 4], function(n) {
 
12040    *   return n % 2 == 0;
 
12045    *   { 'user': 'barney', 'age': 36, 'active': false },
 
12046    *   { 'user': 'fred',   'age': 40, 'active': true }
 
12049    * // using the `_.matches` callback shorthand
 
12050    * _.pluck(_.reject(users, { 'age': 40, 'active': true }), 'user');
 
12053    * // using the `_.matchesProperty` callback shorthand
 
12054    * _.pluck(_.reject(users, 'active', false), 'user');
 
12057    * // using the `_.property` callback shorthand
 
12058    * _.pluck(_.reject(users, 'active'), 'user');
 
12061   function reject(collection, predicate, thisArg) {
 
12062     var func = isArray(collection) ? arrayFilter : baseFilter;
 
12063     predicate = getCallback(predicate, thisArg, 3);
 
12064     return func(collection, function(value, index, collection) {
 
12065       return !predicate(value, index, collection);
 
12070    * Checks if `predicate` returns truthy for **any** element of `collection`.
 
12071    * The function returns as soon as it finds a passing value and does not iterate
 
12072    * over the entire collection. The predicate is bound to `thisArg` and invoked
 
12073    * with three arguments: (value, index|key, collection).
 
12075    * If a property name is provided for `predicate` the created `_.property`
 
12076    * style callback returns the property value of the given element.
 
12078    * If a value is also provided for `thisArg` the created `_.matchesProperty`
 
12079    * style callback returns `true` for elements that have a matching property
 
12080    * value, else `false`.
 
12082    * If an object is provided for `predicate` the created `_.matches` style
 
12083    * callback returns `true` for elements that have the properties of the given
 
12084    * object, else `false`.
 
12089    * @category Collection
 
12090    * @param {Array|Object|string} collection The collection to iterate over.
 
12091    * @param {Function|Object|string} [predicate=_.identity] The function invoked
 
12093    * @param {*} [thisArg] The `this` binding of `predicate`.
 
12094    * @returns {boolean} Returns `true` if any element passes the predicate check,
 
12098    * _.some([null, 0, 'yes', false], Boolean);
 
12102    *   { 'user': 'barney', 'active': true },
 
12103    *   { 'user': 'fred',   'active': false }
 
12106    * // using the `_.matches` callback shorthand
 
12107    * _.some(users, { 'user': 'barney', 'active': false });
 
12110    * // using the `_.matchesProperty` callback shorthand
 
12111    * _.some(users, 'active', false);
 
12114    * // using the `_.property` callback shorthand
 
12115    * _.some(users, 'active');
 
12118   function some(collection, predicate, thisArg) {
 
12119     var func = isArray(collection) ? arraySome : baseSome;
 
12120     if (thisArg && isIterateeCall(collection, predicate, thisArg)) {
 
12123     if (typeof predicate != 'function' || thisArg !== undefined) {
 
12124       predicate = getCallback(predicate, thisArg, 3);
 
12126     return func(collection, predicate);
 
12129   /*------------------------------------------------------------------------*/
 
12132    * Gets the number of milliseconds that have elapsed since the Unix epoch
 
12133    * (1 January 1970 00:00:00 UTC).
 
12140    * _.defer(function(stamp) {
 
12141    *   console.log(_.now() - stamp);
 
12143    * // => logs the number of milliseconds it took for the deferred function to be invoked
 
12145   var now = nativeNow || function() {
 
12146     return new Date().getTime();
 
12149   /*------------------------------------------------------------------------*/
 
12152    * Creates a function that invokes `func` with the `this` binding of `thisArg`
 
12153    * and prepends any additional `_.bind` arguments to those provided to the
 
12156    * The `_.bind.placeholder` value, which defaults to `_` in monolithic builds,
 
12157    * may be used as a placeholder for partially applied arguments.
 
12159    * **Note:** Unlike native `Function#bind` this method does not set the "length"
 
12160    * property of bound functions.
 
12164    * @category Function
 
12165    * @param {Function} func The function to bind.
 
12166    * @param {*} thisArg The `this` binding of `func`.
 
12167    * @param {...*} [partials] The arguments to be partially applied.
 
12168    * @returns {Function} Returns the new bound function.
 
12171    * var greet = function(greeting, punctuation) {
 
12172    *   return greeting + ' ' + this.user + punctuation;
 
12175    * var object = { 'user': 'fred' };
 
12177    * var bound = _.bind(greet, object, 'hi');
 
12181    * // using placeholders
 
12182    * var bound = _.bind(greet, object, _, '!');
 
12186   var bind = restParam(function(func, thisArg, partials) {
 
12187     var bitmask = BIND_FLAG;
 
12188     if (partials.length) {
 
12189       var holders = replaceHolders(partials, bind.placeholder);
 
12190       bitmask |= PARTIAL_FLAG;
 
12192     return createWrapper(func, bitmask, thisArg, partials, holders);
 
12196    * Creates a debounced function that delays invoking `func` until after `wait`
 
12197    * milliseconds have elapsed since the last time the debounced function was
 
12198    * invoked. The debounced function comes with a `cancel` method to cancel
 
12199    * delayed invocations. Provide an options object to indicate that `func`
 
12200    * should be invoked on the leading and/or trailing edge of the `wait` timeout.
 
12201    * Subsequent calls to the debounced function return the result of the last
 
12202    * `func` invocation.
 
12204    * **Note:** If `leading` and `trailing` options are `true`, `func` is invoked
 
12205    * on the trailing edge of the timeout only if the the debounced function is
 
12206    * invoked more than once during the `wait` timeout.
 
12208    * See [David Corbacho's article](http://drupalmotion.com/article/debounce-and-throttle-visual-explanation)
 
12209    * for details over the differences between `_.debounce` and `_.throttle`.
 
12213    * @category Function
 
12214    * @param {Function} func The function to debounce.
 
12215    * @param {number} [wait=0] The number of milliseconds to delay.
 
12216    * @param {Object} [options] The options object.
 
12217    * @param {boolean} [options.leading=false] Specify invoking on the leading
 
12218    *  edge of the timeout.
 
12219    * @param {number} [options.maxWait] The maximum time `func` is allowed to be
 
12220    *  delayed before it is invoked.
 
12221    * @param {boolean} [options.trailing=true] Specify invoking on the trailing
 
12222    *  edge of the timeout.
 
12223    * @returns {Function} Returns the new debounced function.
 
12226    * // avoid costly calculations while the window size is in flux
 
12227    * jQuery(window).on('resize', _.debounce(calculateLayout, 150));
 
12229    * // invoke `sendMail` when the click event is fired, debouncing subsequent calls
 
12230    * jQuery('#postbox').on('click', _.debounce(sendMail, 300, {
 
12232    *   'trailing': false
 
12235    * // ensure `batchLog` is invoked once after 1 second of debounced calls
 
12236    * var source = new EventSource('/stream');
 
12237    * jQuery(source).on('message', _.debounce(batchLog, 250, {
 
12241    * // cancel a debounced call
 
12242    * var todoChanges = _.debounce(batchLog, 1000);
 
12243    * Object.observe(models.todo, todoChanges);
 
12245    * Object.observe(models, function(changes) {
 
12246    *   if (_.find(changes, { 'user': 'todo', 'type': 'delete'})) {
 
12247    *     todoChanges.cancel();
 
12251    * // ...at some point `models.todo` is changed
 
12252    * models.todo.completed = true;
 
12254    * // ...before 1 second has passed `models.todo` is deleted
 
12255    * // which cancels the debounced `todoChanges` call
 
12256    * delete models.todo;
 
12258   function debounce(func, wait, options) {
 
12270     if (typeof func != 'function') {
 
12271       throw new TypeError(FUNC_ERROR_TEXT);
 
12273     wait = wait < 0 ? 0 : (+wait || 0);
 
12274     if (options === true) {
 
12275       var leading = true;
 
12277     } else if (isObject(options)) {
 
12278       leading = options.leading;
 
12279       maxWait = 'maxWait' in options && nativeMax(+options.maxWait || 0, wait);
 
12280       trailing = 'trailing' in options ? options.trailing : trailing;
 
12283     function cancel() {
 
12285         clearTimeout(timeoutId);
 
12287       if (maxTimeoutId) {
 
12288         clearTimeout(maxTimeoutId);
 
12290       maxTimeoutId = timeoutId = trailingCall = undefined;
 
12293     function delayed() {
 
12294       var remaining = wait - (now() - stamp);
 
12295       if (remaining <= 0 || remaining > wait) {
 
12296         if (maxTimeoutId) {
 
12297           clearTimeout(maxTimeoutId);
 
12299         var isCalled = trailingCall;
 
12300         maxTimeoutId = timeoutId = trailingCall = undefined;
 
12302           lastCalled = now();
 
12303           result = func.apply(thisArg, args);
 
12304           if (!timeoutId && !maxTimeoutId) {
 
12305             args = thisArg = null;
 
12309         timeoutId = setTimeout(delayed, remaining);
 
12313     function maxDelayed() {
 
12315         clearTimeout(timeoutId);
 
12317       maxTimeoutId = timeoutId = trailingCall = undefined;
 
12318       if (trailing || (maxWait !== wait)) {
 
12319         lastCalled = now();
 
12320         result = func.apply(thisArg, args);
 
12321         if (!timeoutId && !maxTimeoutId) {
 
12322           args = thisArg = null;
 
12327     function debounced() {
 
12331       trailingCall = trailing && (timeoutId || !leading);
 
12333       if (maxWait === false) {
 
12334         var leadingCall = leading && !timeoutId;
 
12336         if (!maxTimeoutId && !leading) {
 
12337           lastCalled = stamp;
 
12339         var remaining = maxWait - (stamp - lastCalled),
 
12340             isCalled = remaining <= 0 || remaining > maxWait;
 
12343           if (maxTimeoutId) {
 
12344             maxTimeoutId = clearTimeout(maxTimeoutId);
 
12346           lastCalled = stamp;
 
12347           result = func.apply(thisArg, args);
 
12349         else if (!maxTimeoutId) {
 
12350           maxTimeoutId = setTimeout(maxDelayed, remaining);
 
12353       if (isCalled && timeoutId) {
 
12354         timeoutId = clearTimeout(timeoutId);
 
12356       else if (!timeoutId && wait !== maxWait) {
 
12357         timeoutId = setTimeout(delayed, wait);
 
12361         result = func.apply(thisArg, args);
 
12363       if (isCalled && !timeoutId && !maxTimeoutId) {
 
12364         args = thisArg = null;
 
12368     debounced.cancel = cancel;
 
12373    * Creates a function that invokes `func` with the `this` binding of the
 
12374    * created function and arguments from `start` and beyond provided as an array.
 
12376    * **Note:** This method is based on the [rest parameter](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/rest_parameters).
 
12380    * @category Function
 
12381    * @param {Function} func The function to apply a rest parameter to.
 
12382    * @param {number} [start=func.length-1] The start position of the rest parameter.
 
12383    * @returns {Function} Returns the new function.
 
12386    * var say = _.restParam(function(what, names) {
 
12387    *   return what + ' ' + _.initial(names).join(', ') +
 
12388    *     (_.size(names) > 1 ? ', & ' : '') + _.last(names);
 
12391    * say('hello', 'fred', 'barney', 'pebbles');
 
12392    * // => 'hello fred, barney, & pebbles'
 
12394   function restParam(func, start) {
 
12395     if (typeof func != 'function') {
 
12396       throw new TypeError(FUNC_ERROR_TEXT);
 
12398     start = nativeMax(start === undefined ? (func.length - 1) : (+start || 0), 0);
 
12399     return function() {
 
12400       var args = arguments,
 
12402           length = nativeMax(args.length - start, 0),
 
12403           rest = Array(length);
 
12405       while (++index < length) {
 
12406         rest[index] = args[start + index];
 
12409         case 0: return func.call(this, rest);
 
12410         case 1: return func.call(this, args[0], rest);
 
12411         case 2: return func.call(this, args[0], args[1], rest);
 
12413       var otherArgs = Array(start + 1);
 
12415       while (++index < start) {
 
12416         otherArgs[index] = args[index];
 
12418       otherArgs[start] = rest;
 
12419       return func.apply(this, otherArgs);
 
12424    * Creates a throttled function that only invokes `func` at most once per
 
12425    * every `wait` milliseconds. The throttled function comes with a `cancel`
 
12426    * method to cancel delayed invocations. Provide an options object to indicate
 
12427    * that `func` should be invoked on the leading and/or trailing edge of the
 
12428    * `wait` timeout. Subsequent calls to the throttled function return the
 
12429    * result of the last `func` call.
 
12431    * **Note:** If `leading` and `trailing` options are `true`, `func` is invoked
 
12432    * on the trailing edge of the timeout only if the the throttled function is
 
12433    * invoked more than once during the `wait` timeout.
 
12435    * See [David Corbacho's article](http://drupalmotion.com/article/debounce-and-throttle-visual-explanation)
 
12436    * for details over the differences between `_.throttle` and `_.debounce`.
 
12440    * @category Function
 
12441    * @param {Function} func The function to throttle.
 
12442    * @param {number} [wait=0] The number of milliseconds to throttle invocations to.
 
12443    * @param {Object} [options] The options object.
 
12444    * @param {boolean} [options.leading=true] Specify invoking on the leading
 
12445    *  edge of the timeout.
 
12446    * @param {boolean} [options.trailing=true] Specify invoking on the trailing
 
12447    *  edge of the timeout.
 
12448    * @returns {Function} Returns the new throttled function.
 
12451    * // avoid excessively updating the position while scrolling
 
12452    * jQuery(window).on('scroll', _.throttle(updatePosition, 100));
 
12454    * // invoke `renewToken` when the click event is fired, but not more than once every 5 minutes
 
12455    * jQuery('.interactive').on('click', _.throttle(renewToken, 300000, {
 
12456    *   'trailing': false
 
12459    * // cancel a trailing throttled call
 
12460    * jQuery(window).on('popstate', throttled.cancel);
 
12462   function throttle(func, wait, options) {
 
12463     var leading = true,
 
12466     if (typeof func != 'function') {
 
12467       throw new TypeError(FUNC_ERROR_TEXT);
 
12469     if (options === false) {
 
12471     } else if (isObject(options)) {
 
12472       leading = 'leading' in options ? !!options.leading : leading;
 
12473       trailing = 'trailing' in options ? !!options.trailing : trailing;
 
12475     debounceOptions.leading = leading;
 
12476     debounceOptions.maxWait = +wait;
 
12477     debounceOptions.trailing = trailing;
 
12478     return debounce(func, wait, debounceOptions);
 
12481   /*------------------------------------------------------------------------*/
 
12484    * Creates a clone of `value`. If `isDeep` is `true` nested objects are cloned,
 
12485    * otherwise they are assigned by reference. If `customizer` is provided it is
 
12486    * invoked to produce the cloned values. If `customizer` returns `undefined`
 
12487    * cloning is handled by the method instead. The `customizer` is bound to
 
12488    * `thisArg` and invoked with two argument; (value [, index|key, object]).
 
12490    * **Note:** This method is loosely based on the
 
12491    * [structured clone algorithm](http://www.w3.org/TR/html5/infrastructure.html#internal-structured-cloning-algorithm).
 
12492    * The enumerable properties of `arguments` objects and objects created by
 
12493    * constructors other than `Object` are cloned to plain `Object` objects. An
 
12494    * empty object is returned for uncloneable values such as functions, DOM nodes,
 
12495    * Maps, Sets, and WeakMaps.
 
12500    * @param {*} value The value to clone.
 
12501    * @param {boolean} [isDeep] Specify a deep clone.
 
12502    * @param {Function} [customizer] The function to customize cloning values.
 
12503    * @param {*} [thisArg] The `this` binding of `customizer`.
 
12504    * @returns {*} Returns the cloned value.
 
12508    *   { 'user': 'barney' },
 
12509    *   { 'user': 'fred' }
 
12512    * var shallow = _.clone(users);
 
12513    * shallow[0] === users[0];
 
12516    * var deep = _.clone(users, true);
 
12517    * deep[0] === users[0];
 
12520    * // using a customizer callback
 
12521    * var el = _.clone(document.body, function(value) {
 
12522    *   if (_.isElement(value)) {
 
12523    *     return value.cloneNode(false);
 
12527    * el === document.body
 
12531    * el.childNodes.length;
 
12534   function clone(value, isDeep, customizer, thisArg) {
 
12535     if (isDeep && typeof isDeep != 'boolean' && isIterateeCall(value, isDeep, customizer)) {
 
12538     else if (typeof isDeep == 'function') {
 
12539       thisArg = customizer;
 
12540       customizer = isDeep;
 
12543     return typeof customizer == 'function'
 
12544       ? baseClone(value, isDeep, bindCallback(customizer, thisArg, 1))
 
12545       : baseClone(value, isDeep);
 
12549    * Creates a deep clone of `value`. If `customizer` is provided it is invoked
 
12550    * to produce the cloned values. If `customizer` returns `undefined` cloning
 
12551    * is handled by the method instead. The `customizer` is bound to `thisArg`
 
12552    * and invoked with two argument; (value [, index|key, object]).
 
12554    * **Note:** This method is loosely based on the
 
12555    * [structured clone algorithm](http://www.w3.org/TR/html5/infrastructure.html#internal-structured-cloning-algorithm).
 
12556    * The enumerable properties of `arguments` objects and objects created by
 
12557    * constructors other than `Object` are cloned to plain `Object` objects. An
 
12558    * empty object is returned for uncloneable values such as functions, DOM nodes,
 
12559    * Maps, Sets, and WeakMaps.
 
12564    * @param {*} value The value to deep clone.
 
12565    * @param {Function} [customizer] The function to customize cloning values.
 
12566    * @param {*} [thisArg] The `this` binding of `customizer`.
 
12567    * @returns {*} Returns the deep cloned value.
 
12571    *   { 'user': 'barney' },
 
12572    *   { 'user': 'fred' }
 
12575    * var deep = _.cloneDeep(users);
 
12576    * deep[0] === users[0];
 
12579    * // using a customizer callback
 
12580    * var el = _.cloneDeep(document.body, function(value) {
 
12581    *   if (_.isElement(value)) {
 
12582    *     return value.cloneNode(true);
 
12586    * el === document.body
 
12590    * el.childNodes.length;
 
12593   function cloneDeep(value, customizer, thisArg) {
 
12594     return typeof customizer == 'function'
 
12595       ? baseClone(value, true, bindCallback(customizer, thisArg, 1))
 
12596       : baseClone(value, true);
 
12600    * Checks if `value` is classified as an `arguments` object.
 
12605    * @param {*} value The value to check.
 
12606    * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`.
 
12609    * _.isArguments(function() { return arguments; }());
 
12612    * _.isArguments([1, 2, 3]);
 
12615   function isArguments(value) {
 
12616     return isObjectLike(value) && isArrayLike(value) && objToString.call(value) == argsTag;
 
12618   // Fallback for environments without a `toStringTag` for `arguments` objects.
 
12619   if (!support.argsTag) {
 
12620     isArguments = function(value) {
 
12621       return isObjectLike(value) && isArrayLike(value) &&
 
12622         hasOwnProperty.call(value, 'callee') && !propertyIsEnumerable.call(value, 'callee');
 
12627    * Checks if `value` is classified as an `Array` object.
 
12632    * @param {*} value The value to check.
 
12633    * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`.
 
12636    * _.isArray([1, 2, 3]);
 
12639    * _.isArray(function() { return arguments; }());
 
12642   var isArray = nativeIsArray || function(value) {
 
12643     return isObjectLike(value) && isLength(value.length) && objToString.call(value) == arrayTag;
 
12647    * Checks if `value` is empty. A value is considered empty unless it is an
 
12648    * `arguments` object, array, string, or jQuery-like collection with a length
 
12649    * greater than `0` or an object with own enumerable properties.
 
12654    * @param {Array|Object|string} value The value to inspect.
 
12655    * @returns {boolean} Returns `true` if `value` is empty, else `false`.
 
12667    * _.isEmpty([1, 2, 3]);
 
12670    * _.isEmpty({ 'a': 1 });
 
12673   function isEmpty(value) {
 
12674     if (value == null) {
 
12677     if (isArrayLike(value) && (isArray(value) || isString(value) || isArguments(value) ||
 
12678         (isObjectLike(value) && isFunction(value.splice)))) {
 
12679       return !value.length;
 
12681     return !keys(value).length;
 
12685    * Performs a deep comparison between two values to determine if they are
 
12686    * equivalent. If `customizer` is provided it is invoked to compare values.
 
12687    * If `customizer` returns `undefined` comparisons are handled by the method
 
12688    * instead. The `customizer` is bound to `thisArg` and invoked with three
 
12689    * arguments: (value, other [, index|key]).
 
12691    * **Note:** This method supports comparing arrays, booleans, `Date` objects,
 
12692    * numbers, `Object` objects, regexes, and strings. Objects are compared by
 
12693    * their own, not inherited, enumerable properties. Functions and DOM nodes
 
12694    * are **not** supported. Provide a customizer function to extend support
 
12695    * for comparing other values.
 
12701    * @param {*} value The value to compare.
 
12702    * @param {*} other The other value to compare.
 
12703    * @param {Function} [customizer] The function to customize value comparisons.
 
12704    * @param {*} [thisArg] The `this` binding of `customizer`.
 
12705    * @returns {boolean} Returns `true` if the values are equivalent, else `false`.
 
12708    * var object = { 'user': 'fred' };
 
12709    * var other = { 'user': 'fred' };
 
12714    * _.isEqual(object, other);
 
12717    * // using a customizer callback
 
12718    * var array = ['hello', 'goodbye'];
 
12719    * var other = ['hi', 'goodbye'];
 
12721    * _.isEqual(array, other, function(value, other) {
 
12722    *   if (_.every([value, other], RegExp.prototype.test, /^h(?:i|ello)$/)) {
 
12728   function isEqual(value, other, customizer, thisArg) {
 
12729     customizer = typeof customizer == 'function' ? bindCallback(customizer, thisArg, 3) : undefined;
 
12730     var result = customizer ? customizer(value, other) : undefined;
 
12731     return  result === undefined ? baseIsEqual(value, other, customizer) : !!result;
 
12735    * Checks if `value` is classified as a `Function` object.
 
12740    * @param {*} value The value to check.
 
12741    * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`.
 
12747    * _.isFunction(/abc/);
 
12750   var isFunction = !(baseIsFunction(/x/) || (Uint8Array && !baseIsFunction(Uint8Array))) ? baseIsFunction : function(value) {
 
12751     // The use of `Object#toString` avoids issues with the `typeof` operator
 
12752     // in older versions of Chrome and Safari which return 'function' for regexes
 
12753     // and Safari 8 equivalents which return 'object' for typed array constructors.
 
12754     return objToString.call(value) == funcTag;
 
12758    * Checks if `value` is the [language type](https://es5.github.io/#x8) of `Object`.
 
12759    * (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`)
 
12764    * @param {*} value The value to check.
 
12765    * @returns {boolean} Returns `true` if `value` is an object, else `false`.
 
12771    * _.isObject([1, 2, 3]);
 
12777   function isObject(value) {
 
12778     // Avoid a V8 JIT bug in Chrome 19-20.
 
12779     // See https://code.google.com/p/v8/issues/detail?id=2291 for more details.
 
12780     var type = typeof value;
 
12781     return !!value && (type == 'object' || type == 'function');
 
12785    * Checks if `value` is a native function.
 
12790    * @param {*} value The value to check.
 
12791    * @returns {boolean} Returns `true` if `value` is a native function, else `false`.
 
12794    * _.isNative(Array.prototype.push);
 
12800   function isNative(value) {
 
12801     if (value == null) {
 
12804     if (objToString.call(value) == funcTag) {
 
12805       return reIsNative.test(fnToString.call(value));
 
12807     return isObjectLike(value) && (isHostObject(value) ? reIsNative : reIsHostCtor).test(value);
 
12811    * Checks if `value` is a plain object, that is, an object created by the
 
12812    * `Object` constructor or one with a `[[Prototype]]` of `null`.
 
12814    * **Note:** This method assumes objects created by the `Object` constructor
 
12815    * have no inherited enumerable properties.
 
12820    * @param {*} value The value to check.
 
12821    * @returns {boolean} Returns `true` if `value` is a plain object, else `false`.
 
12828    * _.isPlainObject(new Foo);
 
12831    * _.isPlainObject([1, 2, 3]);
 
12834    * _.isPlainObject({ 'x': 0, 'y': 0 });
 
12837    * _.isPlainObject(Object.create(null));
 
12840   var isPlainObject = !getPrototypeOf ? shimIsPlainObject : function(value) {
 
12841     if (!(value && objToString.call(value) == objectTag) || (!lodash.support.argsTag && isArguments(value))) {
 
12844     var valueOf = getNative(value, 'valueOf'),
 
12845         objProto = valueOf && (objProto = getPrototypeOf(valueOf)) && getPrototypeOf(objProto);
 
12848       ? (value == objProto || getPrototypeOf(value) == objProto)
 
12849       : shimIsPlainObject(value);
 
12853    * Checks if `value` is classified as a `String` primitive or object.
 
12858    * @param {*} value The value to check.
 
12859    * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`.
 
12862    * _.isString('abc');
 
12868   function isString(value) {
 
12869     return typeof value == 'string' || (isObjectLike(value) && objToString.call(value) == stringTag);
 
12873    * Checks if `value` is classified as a typed array.
 
12878    * @param {*} value The value to check.
 
12879    * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`.
 
12882    * _.isTypedArray(new Uint8Array);
 
12885    * _.isTypedArray([]);
 
12888   function isTypedArray(value) {
 
12889     return isObjectLike(value) && isLength(value.length) && !!typedArrayTags[objToString.call(value)];
 
12893    * Converts `value` to a plain object flattening inherited enumerable
 
12894    * properties of `value` to own properties of the plain object.
 
12899    * @param {*} value The value to convert.
 
12900    * @returns {Object} Returns the converted plain object.
 
12907    * Foo.prototype.c = 3;
 
12909    * _.assign({ 'a': 1 }, new Foo);
 
12910    * // => { 'a': 1, 'b': 2 }
 
12912    * _.assign({ 'a': 1 }, _.toPlainObject(new Foo));
 
12913    * // => { 'a': 1, 'b': 2, 'c': 3 }
 
12915   function toPlainObject(value) {
 
12916     return baseCopy(value, keysIn(value));
 
12919   /*------------------------------------------------------------------------*/
 
12922    * Assigns own enumerable properties of source object(s) to the destination
 
12923    * object. Subsequent sources overwrite property assignments of previous sources.
 
12924    * If `customizer` is provided it is invoked to produce the assigned values.
 
12925    * The `customizer` is bound to `thisArg` and invoked with five arguments:
 
12926    * (objectValue, sourceValue, key, object, source).
 
12928    * **Note:** This method mutates `object` and is based on
 
12929    * [`Object.assign`](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-object.assign).
 
12935    * @param {Object} object The destination object.
 
12936    * @param {...Object} [sources] The source objects.
 
12937    * @param {Function} [customizer] The function to customize assigned values.
 
12938    * @param {*} [thisArg] The `this` binding of `customizer`.
 
12939    * @returns {Object} Returns `object`.
 
12942    * _.assign({ 'user': 'barney' }, { 'age': 40 }, { 'user': 'fred' });
 
12943    * // => { 'user': 'fred', 'age': 40 }
 
12945    * // using a customizer callback
 
12946    * var defaults = _.partialRight(_.assign, function(value, other) {
 
12947    *   return _.isUndefined(value) ? other : value;
 
12950    * defaults({ 'user': 'barney' }, { 'age': 36 }, { 'user': 'fred' });
 
12951    * // => { 'user': 'barney', 'age': 36 }
 
12953   var assign = createAssigner(function(object, source, customizer) {
 
12955       ? assignWith(object, source, customizer)
 
12956       : baseAssign(object, source);
 
12960    * Iterates over own enumerable properties of an object invoking `iteratee`
 
12961    * for each property. The `iteratee` is bound to `thisArg` and invoked with
 
12962    * three arguments: (value, key, object). Iteratee functions may exit iteration
 
12963    * early by explicitly returning `false`.
 
12968    * @param {Object} object The object to iterate over.
 
12969    * @param {Function} [iteratee=_.identity] The function invoked per iteration.
 
12970    * @param {*} [thisArg] The `this` binding of `iteratee`.
 
12971    * @returns {Object} Returns `object`.
 
12979    * Foo.prototype.c = 3;
 
12981    * _.forOwn(new Foo, function(value, key) {
 
12982    *   console.log(key);
 
12984    * // => logs 'a' and 'b' (iteration order is not guaranteed)
 
12986   var forOwn = createForOwn(baseForOwn);
 
12989    * Creates an array of the own enumerable property names of `object`.
 
12991    * **Note:** Non-object values are coerced to objects. See the
 
12992    * [ES spec](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-object.keys)
 
12993    * for more details.
 
12998    * @param {Object} object The object to query.
 
12999    * @returns {Array} Returns the array of property names.
 
13007    * Foo.prototype.c = 3;
 
13010    * // => ['a', 'b'] (iteration order is not guaranteed)
 
13015   var keys = !nativeKeys ? shimKeys : function(object) {
 
13016     var Ctor = object == null ? null : object.constructor;
 
13017     if ((typeof Ctor == 'function' && Ctor.prototype === object) ||
 
13018         (typeof object == 'function' ? lodash.support.enumPrototypes : isArrayLike(object))) {
 
13019       return shimKeys(object);
 
13021     return isObject(object) ? nativeKeys(object) : [];
 
13025    * Creates an array of the own and inherited enumerable property names of `object`.
 
13027    * **Note:** Non-object values are coerced to objects.
 
13032    * @param {Object} object The object to query.
 
13033    * @returns {Array} Returns the array of property names.
 
13041    * Foo.prototype.c = 3;
 
13043    * _.keysIn(new Foo);
 
13044    * // => ['a', 'b', 'c'] (iteration order is not guaranteed)
 
13046   function keysIn(object) {
 
13047     if (object == null) {
 
13050     if (!isObject(object)) {
 
13051       object = Object(object);
 
13053     var length = object.length,
 
13054         support = lodash.support;
 
13056     length = (length && isLength(length) &&
 
13057       (isArray(object) || isArguments(object) || isString(object)) && length) || 0;
 
13059     var Ctor = object.constructor,
 
13061         proto = (isFunction(Ctor) && Ctor.prototype) || objectProto,
 
13062         isProto = proto === object,
 
13063         result = Array(length),
 
13064         skipIndexes = length > 0,
 
13065         skipErrorProps = support.enumErrorProps && (object === errorProto || object instanceof Error),
 
13066         skipProto = support.enumPrototypes && isFunction(object);
 
13068     while (++index < length) {
 
13069       result[index] = (index + '');
 
13071     // lodash skips the `constructor` property when it infers it is iterating
 
13072     // over a `prototype` object because IE < 9 can't set the `[[Enumerable]]`
 
13073     // attribute of an existing property and the `constructor` property of a
 
13074     // prototype defaults to non-enumerable.
 
13075     for (var key in object) {
 
13076       if (!(skipProto && key == 'prototype') &&
 
13077           !(skipErrorProps && (key == 'message' || key == 'name')) &&
 
13078           !(skipIndexes && isIndex(key, length)) &&
 
13079           !(key == 'constructor' && (isProto || !hasOwnProperty.call(object, key)))) {
 
13083     if (support.nonEnumShadows && object !== objectProto) {
 
13084       var tag = object === stringProto ? stringTag : (object === errorProto ? errorTag : objToString.call(object)),
 
13085           nonEnums = nonEnumProps[tag] || nonEnumProps[objectTag];
 
13087       if (tag == objectTag) {
 
13088         proto = objectProto;
 
13090       length = shadowProps.length;
 
13092         key = shadowProps[length];
 
13093         var nonEnum = nonEnums[key];
 
13094         if (!(isProto && nonEnum) &&
 
13095             (nonEnum ? hasOwnProperty.call(object, key) : object[key] !== proto[key])) {
 
13104    * Recursively merges own enumerable properties of the source object(s), that
 
13105    * don't resolve to `undefined` into the destination object. Subsequent sources
 
13106    * overwrite property assignments of previous sources. If `customizer` is
 
13107    * provided it is invoked to produce the merged values of the destination and
 
13108    * source properties. If `customizer` returns `undefined` merging is handled
 
13109    * by the method instead. The `customizer` is bound to `thisArg` and invoked
 
13110    * with five arguments: (objectValue, sourceValue, key, object, source).
 
13115    * @param {Object} object The destination object.
 
13116    * @param {...Object} [sources] The source objects.
 
13117    * @param {Function} [customizer] The function to customize assigned values.
 
13118    * @param {*} [thisArg] The `this` binding of `customizer`.
 
13119    * @returns {Object} Returns `object`.
 
13123    *   'data': [{ 'user': 'barney' }, { 'user': 'fred' }]
 
13127    *   'data': [{ 'age': 36 }, { 'age': 40 }]
 
13130    * _.merge(users, ages);
 
13131    * // => { 'data': [{ 'user': 'barney', 'age': 36 }, { 'user': 'fred', 'age': 40 }] }
 
13133    * // using a customizer callback
 
13135    *   'fruits': ['apple'],
 
13136    *   'vegetables': ['beet']
 
13140    *   'fruits': ['banana'],
 
13141    *   'vegetables': ['carrot']
 
13144    * _.merge(object, other, function(a, b) {
 
13145    *   if (_.isArray(a)) {
 
13146    *     return a.concat(b);
 
13149    * // => { 'fruits': ['apple', 'banana'], 'vegetables': ['beet', 'carrot'] }
 
13151   var merge = createAssigner(baseMerge);
 
13154    * The opposite of `_.pick`; this method creates an object composed of the
 
13155    * own and inherited enumerable properties of `object` that are not omitted.
 
13160    * @param {Object} object The source object.
 
13161    * @param {Function|...(string|string[])} [predicate] The function invoked per
 
13162    *  iteration or property names to omit, specified as individual property
 
13163    *  names or arrays of property names.
 
13164    * @param {*} [thisArg] The `this` binding of `predicate`.
 
13165    * @returns {Object} Returns the new object.
 
13168    * var object = { 'user': 'fred', 'age': 40 };
 
13170    * _.omit(object, 'age');
 
13171    * // => { 'user': 'fred' }
 
13173    * _.omit(object, _.isNumber);
 
13174    * // => { 'user': 'fred' }
 
13176   var omit = restParam(function(object, props) {
 
13177     if (object == null) {
 
13180     if (typeof props[0] != 'function') {
 
13181       var props = arrayMap(baseFlatten(props), String);
 
13182       return pickByArray(object, baseDifference(keysIn(object), props));
 
13184     var predicate = bindCallback(props[0], props[1], 3);
 
13185     return pickByCallback(object, function(value, key, object) {
 
13186       return !predicate(value, key, object);
 
13191    * Creates a two dimensional array of the key-value pairs for `object`,
 
13192    * e.g. `[[key1, value1], [key2, value2]]`.
 
13197    * @param {Object} object The object to query.
 
13198    * @returns {Array} Returns the new array of key-value pairs.
 
13201    * _.pairs({ 'barney': 36, 'fred': 40 });
 
13202    * // => [['barney', 36], ['fred', 40]] (iteration order is not guaranteed)
 
13204   function pairs(object) {
 
13205     object = toObject(object);
 
13208         props = keys(object),
 
13209         length = props.length,
 
13210         result = Array(length);
 
13212     while (++index < length) {
 
13213       var key = props[index];
 
13214       result[index] = [key, object[key]];
 
13220    * Creates an object composed of the picked `object` properties. Property
 
13221    * names may be specified as individual arguments or as arrays of property
 
13222    * names. If `predicate` is provided it is invoked for each property of `object`
 
13223    * picking the properties `predicate` returns truthy for. The predicate is
 
13224    * bound to `thisArg` and invoked with three arguments: (value, key, object).
 
13229    * @param {Object} object The source object.
 
13230    * @param {Function|...(string|string[])} [predicate] The function invoked per
 
13231    *  iteration or property names to pick, specified as individual property
 
13232    *  names or arrays of property names.
 
13233    * @param {*} [thisArg] The `this` binding of `predicate`.
 
13234    * @returns {Object} Returns the new object.
 
13237    * var object = { 'user': 'fred', 'age': 40 };
 
13239    * _.pick(object, 'user');
 
13240    * // => { 'user': 'fred' }
 
13242    * _.pick(object, _.isString);
 
13243    * // => { 'user': 'fred' }
 
13245   var pick = restParam(function(object, props) {
 
13246     if (object == null) {
 
13249     return typeof props[0] == 'function'
 
13250       ? pickByCallback(object, bindCallback(props[0], props[1], 3))
 
13251       : pickByArray(object, baseFlatten(props));
 
13255    * Creates an array of the own enumerable property values of `object`.
 
13257    * **Note:** Non-object values are coerced to objects.
 
13262    * @param {Object} object The object to query.
 
13263    * @returns {Array} Returns the array of property values.
 
13271    * Foo.prototype.c = 3;
 
13273    * _.values(new Foo);
 
13274    * // => [1, 2] (iteration order is not guaranteed)
 
13279   function values(object) {
 
13280     return baseValues(object, keys(object));
 
13283   /*------------------------------------------------------------------------*/
 
13286    * Escapes the `RegExp` special characters "\", "/", "^", "$", ".", "|", "?",
 
13287    * "*", "+", "(", ")", "[", "]", "{" and "}" in `string`.
 
13292    * @param {string} [string=''] The string to escape.
 
13293    * @returns {string} Returns the escaped string.
 
13296    * _.escapeRegExp('[lodash](https://lodash.com/)');
 
13297    * // => '\[lodash\]\(https:\/\/lodash\.com\/\)'
 
13299   function escapeRegExp(string) {
 
13300     string = baseToString(string);
 
13301     return (string && reHasRegExpChars.test(string))
 
13302       ? string.replace(reRegExpChars, '\\$&')
 
13306   /*------------------------------------------------------------------------*/
 
13309    * Creates a function that invokes `func` with the `this` binding of `thisArg`
 
13310    * and arguments of the created function. If `func` is a property name the
 
13311    * created callback returns the property value for a given element. If `func`
 
13312    * is an object the created callback returns `true` for elements that contain
 
13313    * the equivalent object properties, otherwise it returns `false`.
 
13318    * @category Utility
 
13319    * @param {*} [func=_.identity] The value to convert to a callback.
 
13320    * @param {*} [thisArg] The `this` binding of `func`.
 
13321    * @param- {Object} [guard] Enables use as a callback for functions like `_.map`.
 
13322    * @returns {Function} Returns the callback.
 
13326    *   { 'user': 'barney', 'age': 36 },
 
13327    *   { 'user': 'fred',   'age': 40 }
 
13330    * // wrap to create custom callback shorthands
 
13331    * _.callback = _.wrap(_.callback, function(callback, func, thisArg) {
 
13332    *   var match = /^(.+?)__([gl]t)(.+)$/.exec(func);
 
13334    *     return callback(func, thisArg);
 
13336    *   return function(object) {
 
13337    *     return match[2] == 'gt'
 
13338    *       ? object[match[1]] > match[3]
 
13339    *       : object[match[1]] < match[3];
 
13343    * _.filter(users, 'age__gt36');
 
13344    * // => [{ 'user': 'fred', 'age': 40 }]
 
13346   function callback(func, thisArg, guard) {
 
13347     if (guard && isIterateeCall(func, thisArg, guard)) {
 
13350     return isObjectLike(func)
 
13352       : baseCallback(func, thisArg);
 
13356    * Creates a function that returns `value`.
 
13360    * @category Utility
 
13361    * @param {*} value The value to return from the new function.
 
13362    * @returns {Function} Returns the new function.
 
13365    * var object = { 'user': 'fred' };
 
13366    * var getter = _.constant(object);
 
13368    * getter() === object;
 
13371   function constant(value) {
 
13372     return function() {
 
13378    * This method returns the first argument provided to it.
 
13382    * @category Utility
 
13383    * @param {*} value Any value.
 
13384    * @returns {*} Returns `value`.
 
13387    * var object = { 'user': 'fred' };
 
13389    * _.identity(object) === object;
 
13392   function identity(value) {
 
13397    * Creates a function that performs a deep comparison between a given object
 
13398    * and `source`, returning `true` if the given object has equivalent property
 
13399    * values, else `false`.
 
13401    * **Note:** This method supports comparing arrays, booleans, `Date` objects,
 
13402    * numbers, `Object` objects, regexes, and strings. Objects are compared by
 
13403    * their own, not inherited, enumerable properties. For comparing a single
 
13404    * own or inherited property value see `_.matchesProperty`.
 
13408    * @category Utility
 
13409    * @param {Object} source The object of property values to match.
 
13410    * @returns {Function} Returns the new function.
 
13414    *   { 'user': 'barney', 'age': 36, 'active': true },
 
13415    *   { 'user': 'fred',   'age': 40, 'active': false }
 
13418    * _.filter(users, _.matches({ 'age': 40, 'active': false }));
 
13419    * // => [{ 'user': 'fred', 'age': 40, 'active': false }]
 
13421   function matches(source) {
 
13422     return baseMatches(baseClone(source, true));
 
13426    * Adds all own enumerable function properties of a source object to the
 
13427    * destination object. If `object` is a function then methods are added to
 
13428    * its prototype as well.
 
13430    * **Note:** Use `_.runInContext` to create a pristine `lodash` function to
 
13431    * avoid conflicts caused by modifying the original.
 
13435    * @category Utility
 
13436    * @param {Function|Object} [object=lodash] The destination object.
 
13437    * @param {Object} source The object of functions to add.
 
13438    * @param {Object} [options] The options object.
 
13439    * @param {boolean} [options.chain=true] Specify whether the functions added
 
13441    * @returns {Function|Object} Returns `object`.
 
13444    * function vowels(string) {
 
13445    *   return _.filter(string, function(v) {
 
13446    *     return /[aeiou]/i.test(v);
 
13450    * _.mixin({ 'vowels': vowels });
 
13451    * _.vowels('fred');
 
13454    * _('fred').vowels().value();
 
13457    * _.mixin({ 'vowels': vowels }, { 'chain': false });
 
13458    * _('fred').vowels();
 
13461   function mixin(object, source, options) {
 
13462     if (options == null) {
 
13463       var isObj = isObject(source),
 
13464           props = isObj ? keys(source) : null,
 
13465           methodNames = (props && props.length) ? baseFunctions(source, props) : null;
 
13467       if (!(methodNames ? methodNames.length : isObj)) {
 
13468         methodNames = false;
 
13474     if (!methodNames) {
 
13475       methodNames = baseFunctions(source, keys(source));
 
13479         isFunc = isFunction(object),
 
13480         length = methodNames.length;
 
13482     if (options === false) {
 
13484     } else if (isObject(options) && 'chain' in options) {
 
13485       chain = options.chain;
 
13487     while (++index < length) {
 
13488       var methodName = methodNames[index],
 
13489           func = source[methodName];
 
13491       object[methodName] = func;
 
13493         object.prototype[methodName] = (function(func) {
 
13494           return function() {
 
13495             var chainAll = this.__chain__;
 
13496             if (chain || chainAll) {
 
13497               var result = object(this.__wrapped__),
 
13498                   actions = result.__actions__ = arrayCopy(this.__actions__);
 
13500               actions.push({ 'func': func, 'args': arguments, 'thisArg': object });
 
13501               result.__chain__ = chainAll;
 
13504             var args = [this.value()];
 
13505             push.apply(args, arguments);
 
13506             return func.apply(object, args);
 
13515    * A no-operation function that returns `undefined` regardless of the
 
13516    * arguments it receives.
 
13520    * @category Utility
 
13523    * var object = { 'user': 'fred' };
 
13525    * _.noop(object) === undefined;
 
13529     // No operation performed.
 
13533    * Creates a function that returns the property value at `path` on a
 
13538    * @category Utility
 
13539    * @param {Array|string} path The path of the property to get.
 
13540    * @returns {Function} Returns the new function.
 
13544    *   { 'a': { 'b': { 'c': 2 } } },
 
13545    *   { 'a': { 'b': { 'c': 1 } } }
 
13548    * _.map(objects, _.property('a.b.c'));
 
13551    * _.pluck(_.sortBy(objects, _.property(['a', 'b', 'c'])), 'a.b.c');
 
13554   function property(path) {
 
13555     return isKey(path) ? baseProperty(path) : basePropertyDeep(path);
 
13558   /*------------------------------------------------------------------------*/
 
13560   // Ensure wrappers are instances of `baseLodash`.
 
13561   lodash.prototype = baseLodash.prototype;
 
13563   LodashWrapper.prototype = baseCreate(baseLodash.prototype);
 
13564   LodashWrapper.prototype.constructor = LodashWrapper;
 
13566   LazyWrapper.prototype = baseCreate(baseLodash.prototype);
 
13567   LazyWrapper.prototype.constructor = LazyWrapper;
 
13569   // Add functions to the `Set` cache.
 
13570   SetCache.prototype.push = cachePush;
 
13572   // Add functions that return wrapped values when chaining.
 
13573   lodash.assign = assign;
 
13574   lodash.bind = bind;
 
13575   lodash.callback = callback;
 
13576   lodash.chain = chain;
 
13577   lodash.chunk = chunk;
 
13578   lodash.compact = compact;
 
13579   lodash.constant = constant;
 
13580   lodash.debounce = debounce;
 
13581   lodash.difference = difference;
 
13582   lodash.filter = filter;
 
13583   lodash.flatten = flatten;
 
13584   lodash.forEach = forEach;
 
13585   lodash.forOwn = forOwn;
 
13586   lodash.groupBy = groupBy;
 
13587   lodash.intersection = intersection;
 
13588   lodash.keys = keys;
 
13589   lodash.keysIn = keysIn;
 
13591   lodash.matches = matches;
 
13592   lodash.merge = merge;
 
13593   lodash.mixin = mixin;
 
13594   lodash.omit = omit;
 
13595   lodash.pairs = pairs;
 
13596   lodash.pick = pick;
 
13597   lodash.pluck = pluck;
 
13598   lodash.property = property;
 
13599   lodash.reject = reject;
 
13600   lodash.restParam = restParam;
 
13602   lodash.throttle = throttle;
 
13603   lodash.thru = thru;
 
13604   lodash.toPlainObject = toPlainObject;
 
13605   lodash.union = union;
 
13606   lodash.uniq = uniq;
 
13607   lodash.values = values;
 
13608   lodash.without = without;
 
13611   lodash.collect = map;
 
13612   lodash.each = forEach;
 
13613   lodash.extend = assign;
 
13614   lodash.iteratee = callback;
 
13615   lodash.select = filter;
 
13616   lodash.unique = uniq;
 
13618   // Add functions to `lodash.prototype`.
 
13619   mixin(lodash, lodash);
 
13621   /*------------------------------------------------------------------------*/
 
13623   // Add functions that return unwrapped values when chaining.
 
13624   lodash.clone = clone;
 
13625   lodash.cloneDeep = cloneDeep;
 
13626   lodash.escapeRegExp = escapeRegExp;
 
13627   lodash.every = every;
 
13628   lodash.find = find;
 
13629   lodash.first = first;
 
13630   lodash.identity = identity;
 
13631   lodash.includes = includes;
 
13632   lodash.indexOf = indexOf;
 
13633   lodash.isArguments = isArguments;
 
13634   lodash.isArray = isArray;
 
13635   lodash.isEmpty = isEmpty;
 
13636   lodash.isEqual = isEqual;
 
13637   lodash.isFunction = isFunction;
 
13638   lodash.isNative = isNative;
 
13639   lodash.isObject = isObject;
 
13640   lodash.isPlainObject = isPlainObject;
 
13641   lodash.isString = isString;
 
13642   lodash.isTypedArray = isTypedArray;
 
13643   lodash.last = last;
 
13644   lodash.noop = noop;
 
13646   lodash.reduce = reduce;
 
13647   lodash.some = some;
 
13650   lodash.all = every;
 
13652   lodash.contains = includes;
 
13653   lodash.eq = isEqual;
 
13654   lodash.detect = find;
 
13655   lodash.foldl = reduce;
 
13656   lodash.head = first;
 
13657   lodash.include = includes;
 
13658   lodash.inject = reduce;
 
13660   mixin(lodash, (function() {
 
13662     baseForOwn(lodash, function(func, methodName) {
 
13663       if (!lodash.prototype[methodName]) {
 
13664         source[methodName] = func;
 
13670   /*------------------------------------------------------------------------*/
 
13672   lodash.prototype.sample = function(n) {
 
13673     if (!this.__chain__ && n == null) {
 
13674       return sample(this.value());
 
13676     return this.thru(function(value) {
 
13677       return sample(value, n);
 
13681   /*------------------------------------------------------------------------*/
 
13684    * The semantic version number.
 
13690   lodash.VERSION = VERSION;
 
13692   // Assign default placeholders.
 
13693   bind.placeholder = lodash;
 
13695   // Add `LazyWrapper` methods that accept an `iteratee` value.
 
13696   arrayEach(['dropWhile', 'filter', 'map', 'takeWhile'], function(methodName, type) {
 
13697     var isFilter = type != LAZY_MAP_FLAG,
 
13698         isDropWhile = type == LAZY_DROP_WHILE_FLAG;
 
13700     LazyWrapper.prototype[methodName] = function(iteratee, thisArg) {
 
13701       var filtered = this.__filtered__,
 
13702           result = (filtered && isDropWhile) ? new LazyWrapper(this) : this.clone(),
 
13703           iteratees = result.__iteratees__ || (result.__iteratees__ = []);
 
13709         'iteratee': getCallback(iteratee, thisArg, 1),
 
13714       result.__filtered__ = filtered || isFilter;
 
13719   // Add `LazyWrapper` methods for `_.drop` and `_.take` variants.
 
13720   arrayEach(['drop', 'take'], function(methodName, index) {
 
13721     var whileName = methodName + 'While';
 
13723     LazyWrapper.prototype[methodName] = function(n) {
 
13724       var filtered = this.__filtered__,
 
13725           result = (filtered && !index) ? this.dropWhile() : this.clone();
 
13727       n = n == null ? 1 : nativeMax(floor(n) || 0, 0);
 
13730           result.__takeCount__ = nativeMin(result.__takeCount__, n);
 
13732           last(result.__iteratees__).limit = n;
 
13735         var views = result.__views__ || (result.__views__ = []);
 
13736         views.push({ 'size': n, 'type': methodName + (result.__dir__ < 0 ? 'Right' : '') });
 
13741     LazyWrapper.prototype[methodName + 'Right'] = function(n) {
 
13742       return this.reverse()[methodName](n).reverse();
 
13745     LazyWrapper.prototype[methodName + 'RightWhile'] = function(predicate, thisArg) {
 
13746       return this.reverse()[whileName](predicate, thisArg).reverse();
 
13750   // Add `LazyWrapper` methods for `_.first` and `_.last`.
 
13751   arrayEach(['first', 'last'], function(methodName, index) {
 
13752     var takeName = 'take' + (index ? 'Right' : '');
 
13754     LazyWrapper.prototype[methodName] = function() {
 
13755       return this[takeName](1).value()[0];
 
13759   // Add `LazyWrapper` methods for `_.initial` and `_.rest`.
 
13760   arrayEach(['initial', 'rest'], function(methodName, index) {
 
13761     var dropName = 'drop' + (index ? '' : 'Right');
 
13763     LazyWrapper.prototype[methodName] = function() {
 
13764       return this[dropName](1);
 
13768   // Add `LazyWrapper` methods for `_.pluck` and `_.where`.
 
13769   arrayEach(['pluck', 'where'], function(methodName, index) {
 
13770     var operationName = index ? 'filter' : 'map',
 
13771         createCallback = index ? baseMatches : property;
 
13773     LazyWrapper.prototype[methodName] = function(value) {
 
13774       return this[operationName](createCallback(value));
 
13778   LazyWrapper.prototype.compact = function() {
 
13779     return this.filter(identity);
 
13782   LazyWrapper.prototype.reject = function(predicate, thisArg) {
 
13783     predicate = getCallback(predicate, thisArg, 1);
 
13784     return this.filter(function(value) {
 
13785       return !predicate(value);
 
13789   LazyWrapper.prototype.slice = function(start, end) {
 
13790     start = start == null ? 0 : (+start || 0);
 
13794       result = this.takeRight(-start);
 
13795     } else if (start) {
 
13796       result = this.drop(start);
 
13798     if (end !== undefined) {
 
13800       result = end < 0 ? result.dropRight(-end) : result.take(end - start);
 
13805   LazyWrapper.prototype.toArray = function() {
 
13806     return this.drop(0);
 
13809   // Add `LazyWrapper` methods to `lodash.prototype`.
 
13810   baseForOwn(LazyWrapper.prototype, function(func, methodName) {
 
13811     var lodashFunc = lodash[methodName];
 
13815     var checkIteratee = /^(?:filter|map|reject)|While$/.test(methodName),
 
13816         retUnwrapped = /^(?:first|last)$/.test(methodName);
 
13818     lodash.prototype[methodName] = function() {
 
13819       var args = arguments,
 
13820           chainAll = this.__chain__,
 
13821           value = this.__wrapped__,
 
13822           isHybrid = !!this.__actions__.length,
 
13823           isLazy = value instanceof LazyWrapper,
 
13824           iteratee = args[0],
 
13825           useLazy = isLazy || isArray(value);
 
13827       if (useLazy && checkIteratee && typeof iteratee == 'function' && iteratee.length != 1) {
 
13828         // avoid lazy use if the iteratee has a "length" value other than `1`
 
13829         isLazy = useLazy = false;
 
13831       var onlyLazy = isLazy && !isHybrid;
 
13832       if (retUnwrapped && !chainAll) {
 
13835           : lodashFunc.call(lodash, this.value());
 
13837       var interceptor = function(value) {
 
13838         var otherArgs = [value];
 
13839         push.apply(otherArgs, args);
 
13840         return lodashFunc.apply(lodash, otherArgs);
 
13843         var wrapper = onlyLazy ? value : new LazyWrapper(this),
 
13844             result = func.apply(wrapper, args);
 
13846         if (!retUnwrapped && (isHybrid || result.__actions__)) {
 
13847           var actions = result.__actions__ || (result.__actions__ = []);
 
13848           actions.push({ 'func': thru, 'args': [interceptor], 'thisArg': lodash });
 
13850         return new LodashWrapper(result, chainAll);
 
13852       return this.thru(interceptor);
 
13856   // Add `Array` and `String` methods to `lodash.prototype`.
 
13857   arrayEach(['concat', 'join', 'pop', 'push', 'replace', 'shift', 'sort', 'splice', 'split', 'unshift'], function(methodName) {
 
13858     var protoFunc = (/^(?:replace|split)$/.test(methodName) ? stringProto : arrayProto)[methodName],
 
13859         chainName = /^(?:push|sort|unshift)$/.test(methodName) ? 'tap' : 'thru',
 
13860         fixObjects = !support.spliceObjects && /^(?:pop|shift|splice)$/.test(methodName),
 
13861         retUnwrapped = /^(?:join|pop|replace|shift)$/.test(methodName);
 
13863     // Avoid array-like object bugs with `Array#shift` and `Array#splice` in
 
13864     // IE < 9, Firefox < 10, and RingoJS.
 
13865     var func = !fixObjects ? protoFunc : function() {
 
13866       var result = protoFunc.apply(this, arguments);
 
13867       if (this.length === 0) {
 
13873     lodash.prototype[methodName] = function() {
 
13874       var args = arguments;
 
13875       if (retUnwrapped && !this.__chain__) {
 
13876         return func.apply(this.value(), args);
 
13878       return this[chainName](function(value) {
 
13879         return func.apply(value, args);
 
13884   // Map minified function names to their real names.
 
13885   baseForOwn(LazyWrapper.prototype, function(func, methodName) {
 
13886     var lodashFunc = lodash[methodName];
 
13888       var key = lodashFunc.name,
 
13889           names = realNames[key] || (realNames[key] = []);
 
13891       names.push({ 'name': methodName, 'func': lodashFunc });
 
13895   realNames[createHybridWrapper(null, BIND_KEY_FLAG).name] = [{ 'name': 'wrapper', 'func': null }];
 
13897   // Add functions to the lazy wrapper.
 
13898   LazyWrapper.prototype.clone = lazyClone;
 
13899   LazyWrapper.prototype.reverse = lazyReverse;
 
13900   LazyWrapper.prototype.value = lazyValue;
 
13902   // Add chaining functions to the `lodash` wrapper.
 
13903   lodash.prototype.chain = wrapperChain;
 
13904   lodash.prototype.commit = wrapperCommit;
 
13905   lodash.prototype.plant = wrapperPlant;
 
13906   lodash.prototype.reverse = wrapperReverse;
 
13907   lodash.prototype.toString = wrapperToString;
 
13908   lodash.prototype.run = lodash.prototype.toJSON = lodash.prototype.valueOf = lodash.prototype.value = wrapperValue;
 
13910   // Add function aliases to the `lodash` wrapper.
 
13911   lodash.prototype.collect = lodash.prototype.map;
 
13912   lodash.prototype.head = lodash.prototype.first;
 
13913   lodash.prototype.select = lodash.prototype.filter;
 
13914   lodash.prototype.tail = lodash.prototype.rest;
 
13916   /*--------------------------------------------------------------------------*/
 
13918   if (freeExports && freeModule) {
 
13919     // Export for Node.js or RingoJS.
 
13920     if (moduleExports) {
 
13921       (freeModule.exports = lodash)._ = lodash;
 
13925     // Export for a browser or Rhino.
 
13929 (function(e){if("function"==typeof bootstrap)bootstrap("osmauth",e);else if("object"==typeof exports)module.exports=e();else if("function"==typeof define&&define.amd)define(e);else if("undefined"!=typeof ses){if(!ses.ok())return;ses.makeOsmAuth=e}else"undefined"!=typeof window?window.osmAuth=e():global.osmAuth=e()})(function(){var define,ses,bootstrap,module,exports;
 
13930 return (function(e,t,n){function i(n,s){if(!t[n]){if(!e[n]){var o=typeof require=="function"&&require;if(!s&&o)return o(n,!0);if(r)return r(n,!0);throw new Error("Cannot find module '"+n+"'")}var u=t[n]={exports:{}};e[n][0].call(u.exports,function(t){var r=e[n][1][t];return i(r?r:t)},u,u.exports)}return t[n].exports}var r=typeof require=="function"&&require;for(var s=0;s<n.length;s++)i(n[s]);return i})({1:[function(require,module,exports){
 
13933 var ohauth = require('ohauth'),
 
13934     xtend = require('xtend'),
 
13935     store = require('store');
 
13939 // This code is only compatible with IE10+ because the [XDomainRequest](http://bit.ly/LfO7xo)
 
13940 // object, IE<10's idea of [CORS](http://en.wikipedia.org/wiki/Cross-origin_resource_sharing),
 
13941 // does not support custom headers, which this uses everywhere.
 
13942 module.exports = function(o) {
 
13946     // authenticated users will also have a request token secret, but it's
 
13947     // not used in transactions with the server
 
13948     oauth.authenticated = function() {
 
13949         return !!(token('oauth_token') && token('oauth_token_secret'));
 
13952     oauth.logout = function() {
 
13953         token('oauth_token', '');
 
13954         token('oauth_token_secret', '');
 
13955         token('oauth_request_token_secret', '');
 
13959     // TODO: detect lack of click event
 
13960     oauth.authenticate = function(callback) {
 
13961         if (oauth.authenticated()) return callback();
 
13965         // ## Getting a request token
 
13966         var params = timenonce(getAuth(o)),
 
13967             url = o.url + '/oauth/request_token',
 
13970         params.oauth_signature = ohauth.signature(
 
13971             o.oauth_secret, '',
 
13972             ohauth.baseString('POST', url, params));
 
13974         if (!o.singlepage) {
 
13975             // Create a 600x550 popup window in the center of the screen
 
13976             var w = 600, h = 550,
 
13978                     ['width', w], ['height', h],
 
13979                     ['left', screen.width / 2 - w / 2],
 
13980                     ['top', screen.height / 2 - h / 2]].map(function(x) {
 
13981                         return x.join('=');
 
13983                 popup = window.open('about:blank', 'oauth_window', settings);
 
13986             timer = setInterval(function() {
 
13987                 if (popup.closed) {
 
13989                     clearInterval(timer);
 
13990                     callback('not authenticated', null);
 
13995         // Request a request token. When this is complete, the popup
 
13996         // window is redirected to OSM's authorization page.
 
13997         ohauth.xhr('POST', url, params, null, {}, reqTokenDone);
 
14000         function reqTokenDone(err, xhr) {
 
14003                 if (timer) clearInterval(timer);
 
14004                 return callback(err);
 
14006             var resp = ohauth.stringQs(xhr.response);
 
14007             token('oauth_request_token_secret', resp.oauth_token_secret);
 
14008             var authorize_url = o.url + '/oauth/authorize?' + ohauth.qsString({
 
14009                 oauth_token: resp.oauth_token,
 
14010                 oauth_callback: location.href.replace('index.html', '')
 
14011                     .replace(/#.*/, '') + o.landing
 
14014             if (o.singlepage) {
 
14015                 location.href = authorize_url;
 
14017                 popup.location = authorize_url;
 
14021         // Called by a function in a landing page, in the popup window. The
 
14022         // window closes itself.
 
14023         window.authComplete = function(token) {
 
14024             if (timer) clearInterval(timer);
 
14025             var oauth_token = ohauth.stringQs(token.split('?')[1]);
 
14026             get_access_token(oauth_token.oauth_token);
 
14027             delete window.authComplete;
 
14030         // ## Getting an request token
 
14032         // At this point we have an `oauth_token`, brought in from a function
 
14033         // call on a landing page popup.
 
14034         function get_access_token(oauth_token) {
 
14035             var url = o.url + '/oauth/access_token',
 
14036                 params = timenonce(getAuth(o)),
 
14037                 request_token_secret = token('oauth_request_token_secret');
 
14038             params.oauth_token = oauth_token;
 
14039             params.oauth_signature = ohauth.signature(
 
14041                 request_token_secret,
 
14042                 ohauth.baseString('POST', url, params));
 
14044             // ## Getting an access token
 
14046             // The final token required for authentication. At this point
 
14047             // we have a `request token secret`
 
14048             ohauth.xhr('POST', url, params, null, {}, accessTokenDone);
 
14052         function accessTokenDone(err, xhr) {
 
14054             if (timer) clearInterval(timer);
 
14055             if (err) return callback(err);
 
14056             var access_token = ohauth.stringQs(xhr.response);
 
14057             token('oauth_token', access_token.oauth_token);
 
14058             token('oauth_token_secret', access_token.oauth_token_secret);
 
14059             callback(null, oauth);
 
14063     oauth.bootstrapToken = function(oauth_token, callback) {
 
14064         // ## Getting an request token
 
14065         // At this point we have an `oauth_token`, brought in from a function
 
14066         // call on a landing page popup.
 
14067         function get_access_token(oauth_token) {
 
14068             var url = o.url + '/oauth/access_token',
 
14069                 params = timenonce(getAuth(o)),
 
14070                 request_token_secret = token('oauth_request_token_secret');
 
14071             params.oauth_token = oauth_token;
 
14072             params.oauth_signature = ohauth.signature(
 
14074                 request_token_secret,
 
14075                 ohauth.baseString('POST', url, params));
 
14077             // ## Getting an access token
 
14078             // The final token required for authentication. At this point
 
14079             // we have a `request token secret`
 
14080             ohauth.xhr('POST', url, params, null, {}, accessTokenDone);
 
14084         function accessTokenDone(err, xhr) {
 
14086             if (err) return callback(err);
 
14087             var access_token = ohauth.stringQs(xhr.response);
 
14088             token('oauth_token', access_token.oauth_token);
 
14089             token('oauth_token_secret', access_token.oauth_token_secret);
 
14090             callback(null, oauth);
 
14093         get_access_token(oauth_token);
 
14098     // A single XMLHttpRequest wrapper that does authenticated calls if the
 
14099     // user has logged in.
 
14100     oauth.xhr = function(options, callback) {
 
14101         if (!oauth.authenticated()) {
 
14102             if (o.auto) return oauth.authenticate(run);
 
14103             else return callback('not authenticated', null);
 
14104         } else return run();
 
14107             var params = timenonce(getAuth(o)),
 
14108                 url = o.url + options.path,
 
14109                 oauth_token_secret = token('oauth_token_secret');
 
14111             // https://tools.ietf.org/html/rfc5849#section-3.4.1.3.1
 
14112             if ((!options.options || !options.options.header ||
 
14113                 options.options.header['Content-Type'] === 'application/x-www-form-urlencoded') &&
 
14115                 params = xtend(params, ohauth.stringQs(options.content));
 
14118             params.oauth_token = token('oauth_token');
 
14119             params.oauth_signature = ohauth.signature(
 
14121                 oauth_token_secret,
 
14122                 ohauth.baseString(options.method, url, params));
 
14124             ohauth.xhr(options.method,
 
14125                 url, params, options.content, options.options, done);
 
14128         function done(err, xhr) {
 
14129             if (err) return callback(err);
 
14130             else if (xhr.responseXML) return callback(err, xhr.responseXML);
 
14131             else return callback(err, xhr.response);
 
14135     // pre-authorize this object, if we can just get a token and token_secret
 
14137     oauth.preauth = function(c) {
 
14139         if (c.oauth_token) token('oauth_token', c.oauth_token);
 
14140         if (c.oauth_token_secret) token('oauth_token_secret', c.oauth_token_secret);
 
14144     oauth.options = function(_) {
 
14145         if (!arguments.length) return o;
 
14149         o.url = o.url || 'http://www.openstreetmap.org';
 
14150         o.landing = o.landing || 'land.html';
 
14152         o.singlepage = o.singlepage || false;
 
14154         // Optional loading and loading-done functions for nice UI feedback.
 
14155         // by default, no-ops
 
14156         o.loading = o.loading || function() {};
 
14157         o.done = o.done || function() {};
 
14159         return oauth.preauth(o);
 
14162     // 'stamp' an authentication object from `getAuth()`
 
14163     // with a [nonce](http://en.wikipedia.org/wiki/Cryptographic_nonce)
 
14165     function timenonce(o) {
 
14166         o.oauth_timestamp = ohauth.timestamp();
 
14167         o.oauth_nonce = ohauth.nonce();
 
14171     // get/set tokens. These are prefixed with the base URL so that `osm-auth`
 
14172     // can be used with multiple APIs and the keys in `localStorage`
 
14176     if (store.enabled) {
 
14177         token = function (x, y) {
 
14178             if (arguments.length === 1) return store.get(o.url + x);
 
14179             else if (arguments.length === 2) return store.set(o.url + x, y);
 
14183         token = function (x, y) {
 
14184             if (arguments.length === 1) return storage[o.url + x];
 
14185             else if (arguments.length === 2) return storage[o.url + x] = y;
 
14189     // Get an authentication object. If you just add and remove properties
 
14190     // from a single object, you'll need to use `delete` to make sure that
 
14191     // it doesn't contain undesired properties for authentication
 
14192     function getAuth(o) {
 
14194             oauth_consumer_key: o.oauth_consumer_key,
 
14195             oauth_signature_method: "HMAC-SHA1"
 
14199     // potentially pre-authorize
 
14205 },{"ohauth":2,"store":3,"xtend":4}],3:[function(require,module,exports){
 
14206 (function(global){;(function(win){
 
14208                 doc = win.document,
 
14209                 localStorageName = 'localStorage',
 
14212         store.disabled = false
 
14213         store.set = function(key, value) {}
 
14214         store.get = function(key) {}
 
14215         store.remove = function(key) {}
 
14216         store.clear = function() {}
 
14217         store.transact = function(key, defaultVal, transactionFn) {
 
14218                 var val = store.get(key)
 
14219                 if (transactionFn == null) {
 
14220                         transactionFn = defaultVal
 
14223                 if (typeof val == 'undefined') { val = defaultVal || {} }
 
14225                 store.set(key, val)
 
14227         store.getAll = function() {}
 
14228         store.forEach = function() {}
 
14230         store.serialize = function(value) {
 
14231                 return JSON.stringify(value)
 
14233         store.deserialize = function(value) {
 
14234                 if (typeof value != 'string') { return undefined }
 
14235                 try { return JSON.parse(value) }
 
14236                 catch(e) { return value || undefined }
 
14239         // Functions to encapsulate questionable FireFox 3.6.13 behavior
 
14240         // when about.config::dom.storage.enabled === false
 
14241         // See https://github.com/marcuswestin/store.js/issues#issue/13
 
14242         function isLocalStorageNameSupported() {
 
14243                 try { return (localStorageName in win && win[localStorageName]) }
 
14244                 catch(err) { return false }
 
14247         if (isLocalStorageNameSupported()) {
 
14248                 storage = win[localStorageName]
 
14249                 store.set = function(key, val) {
 
14250                         if (val === undefined) { return store.remove(key) }
 
14251                         storage.setItem(key, store.serialize(val))
 
14254                 store.get = function(key) { return store.deserialize(storage.getItem(key)) }
 
14255                 store.remove = function(key) { storage.removeItem(key) }
 
14256                 store.clear = function() { storage.clear() }
 
14257                 store.getAll = function() {
 
14259                         store.forEach(function(key, val) {
 
14264                 store.forEach = function(callback) {
 
14265                         for (var i=0; i<storage.length; i++) {
 
14266                                 var key = storage.key(i)
 
14267                                 callback(key, store.get(key))
 
14270         } else if (doc.documentElement.addBehavior) {
 
14273                 // Since #userData storage applies only to specific paths, we need to
 
14274                 // somehow link our data to a specific path.  We choose /favicon.ico
 
14275                 // as a pretty safe option, since all browsers already make a request to
 
14276                 // this URL anyway and being a 404 will not hurt us here.  We wrap an
 
14277                 // iframe pointing to the favicon in an ActiveXObject(htmlfile) object
 
14278                 // (see: http://msdn.microsoft.com/en-us/library/aa752574(v=VS.85).aspx)
 
14279                 // since the iframe access rules appear to allow direct access and
 
14280                 // manipulation of the document element, even for a 404 page.  This
 
14281                 // document can be used instead of the current document (which would
 
14282                 // have been limited to the current path) to perform #userData storage.
 
14284                         storageContainer = new ActiveXObject('htmlfile')
 
14285                         storageContainer.open()
 
14286                         storageContainer.write('<s' + 'cript>document.w=window</s' + 'cript><iframe src="/favicon.ico"></iframe>')
 
14287                         storageContainer.close()
 
14288                         storageOwner = storageContainer.w.frames[0].document
 
14289                         storage = storageOwner.createElement('div')
 
14291                         // somehow ActiveXObject instantiation failed (perhaps some special
 
14292                         // security settings or otherwse), fall back to per-path storage
 
14293                         storage = doc.createElement('div')
 
14294                         storageOwner = doc.body
 
14296                 function withIEStorage(storeFunction) {
 
14297                         return function() {
 
14298                                 var args = Array.prototype.slice.call(arguments, 0)
 
14299                                 args.unshift(storage)
 
14300                                 // See http://msdn.microsoft.com/en-us/library/ms531081(v=VS.85).aspx
 
14301                                 // and http://msdn.microsoft.com/en-us/library/ms531424(v=VS.85).aspx
 
14302                                 storageOwner.appendChild(storage)
 
14303                                 storage.addBehavior('#default#userData')
 
14304                                 storage.load(localStorageName)
 
14305                                 var result = storeFunction.apply(store, args)
 
14306                                 storageOwner.removeChild(storage)
 
14311                 // In IE7, keys may not contain special chars. See all of https://github.com/marcuswestin/store.js/issues/40
 
14312                 var forbiddenCharsRegex = new RegExp("[!\"#$%&'()*+,/\\\\:;<=>?@[\\]^`{|}~]", "g")
 
14313                 function ieKeyFix(key) {
 
14314                         return key.replace(forbiddenCharsRegex, '___')
 
14316                 store.set = withIEStorage(function(storage, key, val) {
 
14317                         key = ieKeyFix(key)
 
14318                         if (val === undefined) { return store.remove(key) }
 
14319                         storage.setAttribute(key, store.serialize(val))
 
14320                         storage.save(localStorageName)
 
14323                 store.get = withIEStorage(function(storage, key) {
 
14324                         key = ieKeyFix(key)
 
14325                         return store.deserialize(storage.getAttribute(key))
 
14327                 store.remove = withIEStorage(function(storage, key) {
 
14328                         key = ieKeyFix(key)
 
14329                         storage.removeAttribute(key)
 
14330                         storage.save(localStorageName)
 
14332                 store.clear = withIEStorage(function(storage) {
 
14333                         var attributes = storage.XMLDocument.documentElement.attributes
 
14334                         storage.load(localStorageName)
 
14335                         for (var i=0, attr; attr=attributes[i]; i++) {
 
14336                                 storage.removeAttribute(attr.name)
 
14338                         storage.save(localStorageName)
 
14340                 store.getAll = function(storage) {
 
14342                         store.forEach(function(key, val) {
 
14347                 store.forEach = withIEStorage(function(storage, callback) {
 
14348                         var attributes = storage.XMLDocument.documentElement.attributes
 
14349                         for (var i=0, attr; attr=attributes[i]; ++i) {
 
14350                                 callback(attr.name, store.deserialize(storage.getAttribute(attr.name)))
 
14356                 var testKey = '__storejs__'
 
14357                 store.set(testKey, testKey)
 
14358                 if (store.get(testKey) != testKey) { store.disabled = true }
 
14359                 store.remove(testKey)
 
14361                 store.disabled = true
 
14363         store.enabled = !store.disabled
 
14365         if (typeof module != 'undefined' && module.exports) { module.exports = store }
 
14366         else if (typeof define === 'function' && define.amd) { define(store) }
 
14367         else { win.store = store }
 
14369 })(this.window || global);
 
14372 },{}],5:[function(require,module,exports){
 
14373 module.exports = hasKeys
 
14375 function hasKeys(source) {
 
14376     return source !== null &&
 
14377         (typeof source === "object" ||
 
14378         typeof source === "function")
 
14381 },{}],4:[function(require,module,exports){
 
14382 var Keys = require("object-keys")
 
14383 var hasKeys = require("./has-keys")
 
14385 module.exports = extend
 
14387 function extend() {
 
14390     for (var i = 0; i < arguments.length; i++) {
 
14391         var source = arguments[i]
 
14393         if (!hasKeys(source)) {
 
14397         var keys = Keys(source)
 
14399         for (var j = 0; j < keys.length; j++) {
 
14401             target[name] = source[name]
 
14408 },{"./has-keys":5,"object-keys":6}],7:[function(require,module,exports){
 
14409 (function(global){/**
 
14410  * jsHashes - A fast and independent hashing library pure JavaScript implemented (ES3 compliant) for both server and client side
 
14413  * @author Tomas Aparicio <tomas@rijndael-project.com>
 
14414  * @license New BSD (see LICENSE file)
 
14417  * Algorithms specification:
 
14419  * MD5 <http://www.ietf.org/rfc/rfc1321.txt>
 
14420  * RIPEMD-160 <http://homes.esat.kuleuven.be/~bosselae/ripemd160.html>
 
14421  * SHA1   <http://csrc.nist.gov/publications/fips/fips180-4/fips-180-4.pdf>
 
14422  * SHA256 <http://csrc.nist.gov/publications/fips/fips180-4/fips-180-4.pdf>
 
14423  * SHA512 <http://csrc.nist.gov/publications/fips/fips180-4/fips-180-4.pdf>
 
14424  * HMAC <http://www.ietf.org/rfc/rfc2104.txt>
 
14430   // private helper methods
 
14431   function utf8Encode(str) {
 
14432     var  x, y, output = '', i = -1, l;
 
14434     if (str && str.length) {
 
14436       while ((i+=1) < l) {
 
14437         /* Decode utf-16 surrogate pairs */
 
14438         x = str.charCodeAt(i);
 
14439         y = i + 1 < l ? str.charCodeAt(i + 1) : 0;
 
14440         if (0xD800 <= x && x <= 0xDBFF && 0xDC00 <= y && y <= 0xDFFF) {
 
14441             x = 0x10000 + ((x & 0x03FF) << 10) + (y & 0x03FF);
 
14444         /* Encode output as utf-8 */
 
14446             output += String.fromCharCode(x);
 
14447         } else if (x <= 0x7FF) {
 
14448             output += String.fromCharCode(0xC0 | ((x >>> 6 ) & 0x1F),
 
14449                         0x80 | ( x & 0x3F));
 
14450         } else if (x <= 0xFFFF) {
 
14451             output += String.fromCharCode(0xE0 | ((x >>> 12) & 0x0F),
 
14452                         0x80 | ((x >>> 6 ) & 0x3F),
 
14453                         0x80 | ( x & 0x3F));
 
14454         } else if (x <= 0x1FFFFF) {
 
14455             output += String.fromCharCode(0xF0 | ((x >>> 18) & 0x07),
 
14456                         0x80 | ((x >>> 12) & 0x3F),
 
14457                         0x80 | ((x >>> 6 ) & 0x3F),
 
14458                         0x80 | ( x & 0x3F));
 
14465   function utf8Decode(str) {
 
14466     var i, ac, c1, c2, c3, arr = [], l;
 
14467     i = ac = c1 = c2 = c3 = 0;
 
14469     if (str && str.length) {
 
14474           c1 = str.charCodeAt(i);
 
14477               arr[ac] = String.fromCharCode(c1);
 
14479           } else if (c1 > 191 && c1 < 224) {
 
14480               c2 = str.charCodeAt(i + 1);
 
14481               arr[ac] = String.fromCharCode(((c1 & 31) << 6) | (c2 & 63));
 
14484               c2 = str.charCodeAt(i + 1);
 
14485               c3 = str.charCodeAt(i + 2);
 
14486               arr[ac] = String.fromCharCode(((c1 & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));
 
14491     return arr.join('');
 
14495    * Add integers, wrapping at 2^32. This uses 16-bit operations internally
 
14496    * to work around bugs in some JS interpreters.
 
14498   function safe_add(x, y) {
 
14499     var lsw = (x & 0xFFFF) + (y & 0xFFFF),
 
14500         msw = (x >> 16) + (y >> 16) + (lsw >> 16);
 
14501     return (msw << 16) | (lsw & 0xFFFF);
 
14505    * Bitwise rotate a 32-bit number to the left.
 
14507   function bit_rol(num, cnt) {
 
14508     return (num << cnt) | (num >>> (32 - cnt));
 
14512    * Convert a raw string to a hex string
 
14514   function rstr2hex(input, hexcase) {
 
14515     var hex_tab = hexcase ? '0123456789ABCDEF' : '0123456789abcdef',
 
14516         output = '', x, i = 0, l = input.length;
 
14517     for (; i < l; i+=1) {
 
14518       x = input.charCodeAt(i);
 
14519       output += hex_tab.charAt((x >>> 4) & 0x0F) + hex_tab.charAt(x & 0x0F);
 
14525    * Encode a string as utf-16
 
14527   function str2rstr_utf16le(input) {
 
14528     var i, l = input.length, output = '';
 
14529     for (i = 0; i < l; i+=1) {
 
14530       output += String.fromCharCode( input.charCodeAt(i) & 0xFF, (input.charCodeAt(i) >>> 8) & 0xFF);
 
14535   function str2rstr_utf16be(input) {
 
14536     var i, l = input.length, output = '';
 
14537     for (i = 0; i < l; i+=1) {
 
14538       output += String.fromCharCode((input.charCodeAt(i) >>> 8) & 0xFF, input.charCodeAt(i) & 0xFF);
 
14544    * Convert an array of big-endian words to a string
 
14546   function binb2rstr(input) {
 
14547     var i, l = input.length * 32, output = '';
 
14548     for (i = 0; i < l; i += 8) {
 
14549         output += String.fromCharCode((input[i>>5] >>> (24 - i % 32)) & 0xFF);
 
14555    * Convert an array of little-endian words to a string
 
14557   function binl2rstr(input) {
 
14558     var i, l = input.length * 32, output = '';
 
14559     for (i = 0;i < l; i += 8) {
 
14560       output += String.fromCharCode((input[i>>5] >>> (i % 32)) & 0xFF);
 
14566    * Convert a raw string to an array of little-endian words
 
14567    * Characters >255 have their high-byte silently ignored.
 
14569   function rstr2binl(input) {
 
14570     var i, l = input.length * 8, output = Array(input.length >> 2), lo = output.length;
 
14571     for (i = 0; i < lo; i+=1) {
 
14574     for (i = 0; i < l; i += 8) {
 
14575       output[i>>5] |= (input.charCodeAt(i / 8) & 0xFF) << (i%32);
 
14581    * Convert a raw string to an array of big-endian words
 
14582    * Characters >255 have their high-byte silently ignored.
 
14584    function rstr2binb(input) {
 
14585       var i, l = input.length * 8, output = Array(input.length >> 2), lo = output.length;
 
14586       for (i = 0; i < lo; i+=1) {
 
14589       for (i = 0; i < l; i += 8) {
 
14590             output[i>>5] |= (input.charCodeAt(i / 8) & 0xFF) << (24 - i % 32);
 
14596    * Convert a raw string to an arbitrary string encoding
 
14598   function rstr2any(input, encoding) {
 
14599     var divisor = encoding.length,
 
14600         remainders = Array(),
 
14601         i, q, x, ld, quotient, dividend, output, full_length;
 
14603     /* Convert to an array of 16-bit big-endian values, forming the dividend */
 
14604     dividend = Array(Math.ceil(input.length / 2));
 
14605     ld = dividend.length;
 
14606     for (i = 0; i < ld; i+=1) {
 
14607       dividend[i] = (input.charCodeAt(i * 2) << 8) | input.charCodeAt(i * 2 + 1);
 
14611      * Repeatedly perform a long division. The binary array forms the dividend,
 
14612      * the length of the encoding is the divisor. Once computed, the quotient
 
14613      * forms the dividend for the next step. We stop when the dividend is zerHashes.
 
14614      * All remainders are stored for later use.
 
14616     while(dividend.length > 0) {
 
14617       quotient = Array();
 
14619       for (i = 0; i < dividend.length; i+=1) {
 
14620         x = (x << 16) + dividend[i];
 
14621         q = Math.floor(x / divisor);
 
14623         if (quotient.length > 0 || q > 0) {
 
14624           quotient[quotient.length] = q;
 
14627       remainders[remainders.length] = x;
 
14628       dividend = quotient;
 
14631     /* Convert the remainders to the output string */
 
14633     for (i = remainders.length - 1; i >= 0; i--) {
 
14634       output += encoding.charAt(remainders[i]);
 
14637     /* Append leading zero equivalents */
 
14638     full_length = Math.ceil(input.length * 8 / (Math.log(encoding.length) / Math.log(2)));
 
14639     for (i = output.length; i < full_length; i+=1) {
 
14640       output = encoding[0] + output;
 
14646    * Convert a raw string to a base-64 string
 
14648   function rstr2b64(input, b64pad) {
 
14649     var tab = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/',
 
14651         len = input.length, i, j, triplet;
 
14652     b64pad= b64pad || '=';
 
14653     for (i = 0; i < len; i += 3) {
 
14654       triplet = (input.charCodeAt(i) << 16)
 
14655             | (i + 1 < len ? input.charCodeAt(i+1) << 8 : 0)
 
14656             | (i + 2 < len ? input.charCodeAt(i+2)      : 0);
 
14657       for (j = 0; j < 4; j+=1) {
 
14658         if (i * 8 + j * 6 > input.length * 8) {
 
14661           output += tab.charAt((triplet >>> 6*(3-j)) & 0x3F);
 
14670    * @property {String} version
 
14679   Base64 : function () {
 
14680     // private properties
 
14681     var tab = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/',
 
14682         pad = '=', // default pad according with the RFC standard
 
14683         url = false, // URL encoding support @todo
 
14684         utf8 = true; // by default enable UTF-8 support encoding
 
14686     // public method for encoding
 
14687     this.encode = function (input) {
 
14690           len = input.length;
 
14693       input = (utf8) ? utf8Encode(input) : input;
 
14695       for (i = 0; i < len; i += 3) {
 
14696         triplet = (input.charCodeAt(i) << 16)
 
14697               | (i + 1 < len ? input.charCodeAt(i+1) << 8 : 0)
 
14698               | (i + 2 < len ? input.charCodeAt(i+2) : 0);
 
14699         for (j = 0; j < 4; j+=1) {
 
14700           if (i * 8 + j * 6 > len * 8) {
 
14703               output += tab.charAt((triplet >>> 6*(3-j)) & 0x3F);
 
14710     // public method for decoding
 
14711     this.decode = function (input) {
 
14712       // var b64 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
 
14713       var i, o1, o2, o3, h1, h2, h3, h4, bits, ac,
 
14716       if (!input) { return input; }
 
14719       input = input.replace(new RegExp('\\'+pad,'gi'),''); // use '='
 
14722       do { // unpack four hexets into three octets using index points in b64
 
14723         h1 = tab.indexOf(input.charAt(i+=1));
 
14724         h2 = tab.indexOf(input.charAt(i+=1));
 
14725         h3 = tab.indexOf(input.charAt(i+=1));
 
14726         h4 = tab.indexOf(input.charAt(i+=1));
 
14728         bits = h1 << 18 | h2 << 12 | h3 << 6 | h4;
 
14730         o1 = bits >> 16 & 0xff;
 
14731         o2 = bits >> 8 & 0xff;
 
14736           arr[ac] = String.fromCharCode(o1);
 
14737         } else if (h4 === 64) {
 
14738           arr[ac] = String.fromCharCode(o1, o2);
 
14740           arr[ac] = String.fromCharCode(o1, o2, o3);
 
14742       } while (i < input.length);
 
14744       dec = arr.join('');
 
14745       dec = (utf8) ? utf8Decode(dec) : dec;
 
14750     // set custom pad string
 
14751     this.setPad = function (str) {
 
14755     // set custom tab string characters
 
14756     this.setTab = function (str) {
 
14760     this.setUTF8 = function (bool) {
 
14761         if (typeof bool === 'boolean') {
 
14769    * CRC-32 calculation
 
14773    * @param {String} str Input String
 
14776   CRC32 : function (str) {
 
14777     var crc = 0, x = 0, y = 0, table, i, iTop;
 
14778     str = utf8Encode(str);
 
14781         '00000000 77073096 EE0E612C 990951BA 076DC419 706AF48F E963A535 9E6495A3 0EDB8832 ',
 
14782         '79DCB8A4 E0D5E91E 97D2D988 09B64C2B 7EB17CBD E7B82D07 90BF1D91 1DB71064 6AB020F2 F3B97148 ',
 
14783         '84BE41DE 1ADAD47D 6DDDE4EB F4D4B551 83D385C7 136C9856 646BA8C0 FD62F97A 8A65C9EC 14015C4F ',
 
14784         '63066CD9 FA0F3D63 8D080DF5 3B6E20C8 4C69105E D56041E4 A2677172 3C03E4D1 4B04D447 D20D85FD ',
 
14785         'A50AB56B 35B5A8FA 42B2986C DBBBC9D6 ACBCF940 32D86CE3 45DF5C75 DCD60DCF ABD13D59 26D930AC ',
 
14786         '51DE003A C8D75180 BFD06116 21B4F4B5 56B3C423 CFBA9599 B8BDA50F 2802B89E 5F058808 C60CD9B2 ',
 
14787         'B10BE924 2F6F7C87 58684C11 C1611DAB B6662D3D 76DC4190 01DB7106 98D220BC EFD5102A 71B18589 ',
 
14788         '06B6B51F 9FBFE4A5 E8B8D433 7807C9A2 0F00F934 9609A88E E10E9818 7F6A0DBB 086D3D2D 91646C97 ',
 
14789         'E6635C01 6B6B51F4 1C6C6162 856530D8 F262004E 6C0695ED 1B01A57B 8208F4C1 F50FC457 65B0D9C6 ',
 
14790         '12B7E950 8BBEB8EA FCB9887C 62DD1DDF 15DA2D49 8CD37CF3 FBD44C65 4DB26158 3AB551CE A3BC0074 ',
 
14791         'D4BB30E2 4ADFA541 3DD895D7 A4D1C46D D3D6F4FB 4369E96A 346ED9FC AD678846 DA60B8D0 44042D73 ',
 
14792         '33031DE5 AA0A4C5F DD0D7CC9 5005713C 270241AA BE0B1010 C90C2086 5768B525 206F85B3 B966D409 ',
 
14793         'CE61E49F 5EDEF90E 29D9C998 B0D09822 C7D7A8B4 59B33D17 2EB40D81 B7BD5C3B C0BA6CAD EDB88320 ',
 
14794         '9ABFB3B6 03B6E20C 74B1D29A EAD54739 9DD277AF 04DB2615 73DC1683 E3630B12 94643B84 0D6D6A3E ',
 
14795         '7A6A5AA8 E40ECF0B 9309FF9D 0A00AE27 7D079EB1 F00F9344 8708A3D2 1E01F268 6906C2FE F762575D ',
 
14796         '806567CB 196C3671 6E6B06E7 FED41B76 89D32BE0 10DA7A5A 67DD4ACC F9B9DF6F 8EBEEFF9 17B7BE43 ',
 
14797         '60B08ED5 D6D6A3E8 A1D1937E 38D8C2C4 4FDFF252 D1BB67F1 A6BC5767 3FB506DD 48B2364B D80D2BDA ',
 
14798         'AF0A1B4C 36034AF6 41047A60 DF60EFC3 A867DF55 316E8EEF 4669BE79 CB61B38C BC66831A 256FD2A0 ',
 
14799         '5268E236 CC0C7795 BB0B4703 220216B9 5505262F C5BA3BBE B2BD0B28 2BB45A92 5CB36A04 C2D7FFA7 ',
 
14800         'B5D0CF31 2CD99E8B 5BDEAE1D 9B64C2B0 EC63F226 756AA39C 026D930A 9C0906A9 EB0E363F 72076785 ',
 
14801         '05005713 95BF4A82 E2B87A14 7BB12BAE 0CB61B38 92D28E9B E5D5BE0D 7CDCEFB7 0BDBDF21 86D3D2D4 ',
 
14802         'F1D4E242 68DDB3F8 1FDA836E 81BE16CD F6B9265B 6FB077E1 18B74777 88085AE6 FF0F6A70 66063BCA ',
 
14803         '11010B5C 8F659EFF F862AE69 616BFFD3 166CCF45 A00AE278 D70DD2EE 4E048354 3903B3C2 A7672661 ',
 
14804         'D06016F7 4969474D 3E6E77DB AED16A4A D9D65ADC 40DF0B66 37D83BF0 A9BCAE53 DEBB9EC5 47B2CF7F ',
 
14805         '30B5FFE9 BDBDF21C CABAC28A 53B39330 24B4A3A6 BAD03605 CDD70693 54DE5729 23D967BF B3667A2E ',
 
14806         'C4614AB8 5D681B02 2A6F2B94 B40BBE37 C30C8EA1 5A05DF1B 2D02EF8D'
 
14810     for (i = 0, iTop = str.length; i < iTop; i+=1 ) {
 
14811         y = ( crc ^ str.charCodeAt( i ) ) & 0xFF;
 
14812         x = '0x' + table.substr( y * 9, 8 );
 
14813         crc = ( crc >>> 8 ) ^ x;
 
14815     // always return a positive number (that's what >>> 0 does)
 
14816     return (crc ^ (-1)) >>> 0;
 
14822    * @param {Object} [config]
 
14824    * A JavaScript implementation of the RSA Data Security, Inc. MD5 Message
 
14825    * Digest Algorithm, as defined in RFC 1321.
 
14826    * Version 2.2 Copyright (C) Paul Johnston 1999 - 2009
 
14827    * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
 
14828    * See <http://pajhome.org.uk/crypt/md5> for more infHashes.
 
14830   MD5 : function (options) {
 
14832      * Private config properties. You may need to tweak these to be compatible with
 
14833      * the server-side, but the defaults work in most cases.
 
14834      * See {@link Hashes.MD5#method-setUpperCase} and {@link Hashes.SHA1#method-setUpperCase}
 
14836     var hexcase = (options && typeof options.uppercase === 'boolean') ? options.uppercase : false, // hexadecimal output case format. false - lowercase; true - uppercase
 
14837         b64pad = (options && typeof options.pad === 'string') ? options.pda : '=', // base-64 pad character. Defaults to '=' for strict RFC compliance
 
14838         utf8 = (options && typeof options.utf8 === 'boolean') ? options.utf8 : true; // enable/disable utf8 encoding
 
14840     // privileged (public) methods
 
14841     this.hex = function (s) {
 
14842       return rstr2hex(rstr(s, utf8), hexcase);
 
14844     this.b64 = function (s) {
 
14845       return rstr2b64(rstr(s), b64pad);
 
14847     this.any = function(s, e) {
 
14848       return rstr2any(rstr(s, utf8), e);
 
14850     this.hex_hmac = function (k, d) {
 
14851       return rstr2hex(rstr_hmac(k, d), hexcase);
 
14853     this.b64_hmac = function (k, d) {
 
14854       return rstr2b64(rstr_hmac(k,d), b64pad);
 
14856     this.any_hmac = function (k, d, e) {
 
14857       return rstr2any(rstr_hmac(k, d), e);
 
14860      * Perform a simple self-test to see if the VM is working
 
14861      * @return {String} Hexadecimal hash sample
 
14863     this.vm_test = function () {
 
14864       return hex('abc').toLowerCase() === '900150983cd24fb0d6963f7d28e17f72';
 
14867      * Enable/disable uppercase hexadecimal returned string
 
14869      * @return {Object} this
 
14871     this.setUpperCase = function (a) {
 
14872       if (typeof a === 'boolean' ) {
 
14878      * Defines a base64 pad string
 
14879      * @param {String} Pad
 
14880      * @return {Object} this
 
14882     this.setPad = function (a) {
 
14883       b64pad = a || b64pad;
 
14887      * Defines a base64 pad string
 
14889      * @return {Object} [this]
 
14891     this.setUTF8 = function (a) {
 
14892       if (typeof a === 'boolean') {
 
14901      * Calculate the MD5 of a raw string
 
14904       s = (utf8) ? utf8Encode(s): s;
 
14905       return binl2rstr(binl(rstr2binl(s), s.length * 8));
 
14909      * Calculate the HMAC-MD5, of a key and some data (raw strings)
 
14911     function rstr_hmac(key, data) {
 
14912       var bkey, ipad, opad, hash, i;
 
14914       key = (utf8) ? utf8Encode(key) : key;
 
14915       data = (utf8) ? utf8Encode(data) : data;
 
14916       bkey = rstr2binl(key);
 
14917       if (bkey.length > 16) {
 
14918         bkey = binl(bkey, key.length * 8);
 
14921       ipad = Array(16), opad = Array(16);
 
14922       for (i = 0; i < 16; i+=1) {
 
14923           ipad[i] = bkey[i] ^ 0x36363636;
 
14924           opad[i] = bkey[i] ^ 0x5C5C5C5C;
 
14926       hash = binl(ipad.concat(rstr2binl(data)), 512 + data.length * 8);
 
14927       return binl2rstr(binl(opad.concat(hash), 512 + 128));
 
14931      * Calculate the MD5 of an array of little-endian words, and a bit length.
 
14933     function binl(x, len) {
 
14934       var i, olda, oldb, oldc, oldd,
 
14940       /* append padding */
 
14941       x[len >> 5] |= 0x80 << ((len) % 32);
 
14942       x[(((len + 64) >>> 9) << 4) + 14] = len;
 
14944       for (i = 0; i < x.length; i += 16) {
 
14950         a = md5_ff(a, b, c, d, x[i+ 0], 7 , -680876936);
 
14951         d = md5_ff(d, a, b, c, x[i+ 1], 12, -389564586);
 
14952         c = md5_ff(c, d, a, b, x[i+ 2], 17,  606105819);
 
14953         b = md5_ff(b, c, d, a, x[i+ 3], 22, -1044525330);
 
14954         a = md5_ff(a, b, c, d, x[i+ 4], 7 , -176418897);
 
14955         d = md5_ff(d, a, b, c, x[i+ 5], 12,  1200080426);
 
14956         c = md5_ff(c, d, a, b, x[i+ 6], 17, -1473231341);
 
14957         b = md5_ff(b, c, d, a, x[i+ 7], 22, -45705983);
 
14958         a = md5_ff(a, b, c, d, x[i+ 8], 7 ,  1770035416);
 
14959         d = md5_ff(d, a, b, c, x[i+ 9], 12, -1958414417);
 
14960         c = md5_ff(c, d, a, b, x[i+10], 17, -42063);
 
14961         b = md5_ff(b, c, d, a, x[i+11], 22, -1990404162);
 
14962         a = md5_ff(a, b, c, d, x[i+12], 7 ,  1804603682);
 
14963         d = md5_ff(d, a, b, c, x[i+13], 12, -40341101);
 
14964         c = md5_ff(c, d, a, b, x[i+14], 17, -1502002290);
 
14965         b = md5_ff(b, c, d, a, x[i+15], 22,  1236535329);
 
14967         a = md5_gg(a, b, c, d, x[i+ 1], 5 , -165796510);
 
14968         d = md5_gg(d, a, b, c, x[i+ 6], 9 , -1069501632);
 
14969         c = md5_gg(c, d, a, b, x[i+11], 14,  643717713);
 
14970         b = md5_gg(b, c, d, a, x[i+ 0], 20, -373897302);
 
14971         a = md5_gg(a, b, c, d, x[i+ 5], 5 , -701558691);
 
14972         d = md5_gg(d, a, b, c, x[i+10], 9 ,  38016083);
 
14973         c = md5_gg(c, d, a, b, x[i+15], 14, -660478335);
 
14974         b = md5_gg(b, c, d, a, x[i+ 4], 20, -405537848);
 
14975         a = md5_gg(a, b, c, d, x[i+ 9], 5 ,  568446438);
 
14976         d = md5_gg(d, a, b, c, x[i+14], 9 , -1019803690);
 
14977         c = md5_gg(c, d, a, b, x[i+ 3], 14, -187363961);
 
14978         b = md5_gg(b, c, d, a, x[i+ 8], 20,  1163531501);
 
14979         a = md5_gg(a, b, c, d, x[i+13], 5 , -1444681467);
 
14980         d = md5_gg(d, a, b, c, x[i+ 2], 9 , -51403784);
 
14981         c = md5_gg(c, d, a, b, x[i+ 7], 14,  1735328473);
 
14982         b = md5_gg(b, c, d, a, x[i+12], 20, -1926607734);
 
14984         a = md5_hh(a, b, c, d, x[i+ 5], 4 , -378558);
 
14985         d = md5_hh(d, a, b, c, x[i+ 8], 11, -2022574463);
 
14986         c = md5_hh(c, d, a, b, x[i+11], 16,  1839030562);
 
14987         b = md5_hh(b, c, d, a, x[i+14], 23, -35309556);
 
14988         a = md5_hh(a, b, c, d, x[i+ 1], 4 , -1530992060);
 
14989         d = md5_hh(d, a, b, c, x[i+ 4], 11,  1272893353);
 
14990         c = md5_hh(c, d, a, b, x[i+ 7], 16, -155497632);
 
14991         b = md5_hh(b, c, d, a, x[i+10], 23, -1094730640);
 
14992         a = md5_hh(a, b, c, d, x[i+13], 4 ,  681279174);
 
14993         d = md5_hh(d, a, b, c, x[i+ 0], 11, -358537222);
 
14994         c = md5_hh(c, d, a, b, x[i+ 3], 16, -722521979);
 
14995         b = md5_hh(b, c, d, a, x[i+ 6], 23,  76029189);
 
14996         a = md5_hh(a, b, c, d, x[i+ 9], 4 , -640364487);
 
14997         d = md5_hh(d, a, b, c, x[i+12], 11, -421815835);
 
14998         c = md5_hh(c, d, a, b, x[i+15], 16,  530742520);
 
14999         b = md5_hh(b, c, d, a, x[i+ 2], 23, -995338651);
 
15001         a = md5_ii(a, b, c, d, x[i+ 0], 6 , -198630844);
 
15002         d = md5_ii(d, a, b, c, x[i+ 7], 10,  1126891415);
 
15003         c = md5_ii(c, d, a, b, x[i+14], 15, -1416354905);
 
15004         b = md5_ii(b, c, d, a, x[i+ 5], 21, -57434055);
 
15005         a = md5_ii(a, b, c, d, x[i+12], 6 ,  1700485571);
 
15006         d = md5_ii(d, a, b, c, x[i+ 3], 10, -1894986606);
 
15007         c = md5_ii(c, d, a, b, x[i+10], 15, -1051523);
 
15008         b = md5_ii(b, c, d, a, x[i+ 1], 21, -2054922799);
 
15009         a = md5_ii(a, b, c, d, x[i+ 8], 6 ,  1873313359);
 
15010         d = md5_ii(d, a, b, c, x[i+15], 10, -30611744);
 
15011         c = md5_ii(c, d, a, b, x[i+ 6], 15, -1560198380);
 
15012         b = md5_ii(b, c, d, a, x[i+13], 21,  1309151649);
 
15013         a = md5_ii(a, b, c, d, x[i+ 4], 6 , -145523070);
 
15014         d = md5_ii(d, a, b, c, x[i+11], 10, -1120210379);
 
15015         c = md5_ii(c, d, a, b, x[i+ 2], 15,  718787259);
 
15016         b = md5_ii(b, c, d, a, x[i+ 9], 21, -343485551);
 
15018         a = safe_add(a, olda);
 
15019         b = safe_add(b, oldb);
 
15020         c = safe_add(c, oldc);
 
15021         d = safe_add(d, oldd);
 
15023       return Array(a, b, c, d);
 
15027      * These functions implement the four basic operations the algorithm uses.
 
15029     function md5_cmn(q, a, b, x, s, t) {
 
15030       return safe_add(bit_rol(safe_add(safe_add(a, q), safe_add(x, t)), s),b);
 
15032     function md5_ff(a, b, c, d, x, s, t) {
 
15033       return md5_cmn((b & c) | ((~b) & d), a, b, x, s, t);
 
15035     function md5_gg(a, b, c, d, x, s, t) {
 
15036       return md5_cmn((b & d) | (c & (~d)), a, b, x, s, t);
 
15038     function md5_hh(a, b, c, d, x, s, t) {
 
15039       return md5_cmn(b ^ c ^ d, a, b, x, s, t);
 
15041     function md5_ii(a, b, c, d, x, s, t) {
 
15042       return md5_cmn(c ^ (b | (~d)), a, b, x, s, t);
 
15047    * @class Hashes.SHA1
 
15048    * @param {Object} [config]
 
15051    * A JavaScript implementation of the Secure Hash Algorithm, SHA-1, as defined in FIPS 180-1
 
15052    * Version 2.2 Copyright Paul Johnston 2000 - 2009.
 
15053    * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
 
15054    * See http://pajhome.org.uk/crypt/md5 for details.
 
15056   SHA1 : function (options) {
 
15058      * Private config properties. You may need to tweak these to be compatible with
 
15059      * the server-side, but the defaults work in most cases.
 
15060      * See {@link Hashes.MD5#method-setUpperCase} and {@link Hashes.SHA1#method-setUpperCase}
 
15062     var hexcase = (options && typeof options.uppercase === 'boolean') ? options.uppercase : false, // hexadecimal output case format. false - lowercase; true - uppercase
 
15063         b64pad = (options && typeof options.pad === 'string') ? options.pda : '=', // base-64 pad character. Defaults to '=' for strict RFC compliance
 
15064         utf8 = (options && typeof options.utf8 === 'boolean') ? options.utf8 : true; // enable/disable utf8 encoding
 
15067     this.hex = function (s) {
 
15068         return rstr2hex(rstr(s, utf8), hexcase);
 
15070     this.b64 = function (s) {
 
15071         return rstr2b64(rstr(s, utf8), b64pad);
 
15073     this.any = function (s, e) {
 
15074         return rstr2any(rstr(s, utf8), e);
 
15076     this.hex_hmac = function (k, d) {
 
15077         return rstr2hex(rstr_hmac(k, d));
 
15079     this.b64_hmac = function (k, d) {
 
15080         return rstr2b64(rstr_hmac(k, d), b64pad);
 
15082     this.any_hmac = function (k, d, e) {
 
15083         return rstr2any(rstr_hmac(k, d), e);
 
15086      * Perform a simple self-test to see if the VM is working
 
15087      * @return {String} Hexadecimal hash sample
 
15090     this.vm_test = function () {
 
15091       return hex('abc').toLowerCase() === '900150983cd24fb0d6963f7d28e17f72';
 
15094      * @description Enable/disable uppercase hexadecimal returned string
 
15096      * @return {Object} this
 
15099     this.setUpperCase = function (a) {
 
15100         if (typeof a === 'boolean') {
 
15106      * @description Defines a base64 pad string
 
15107      * @param {string} Pad
 
15108      * @return {Object} this
 
15111     this.setPad = function (a) {
 
15112       b64pad = a || b64pad;
 
15116      * @description Defines a base64 pad string
 
15118      * @return {Object} this
 
15121     this.setUTF8 = function (a) {
 
15122         if (typeof a === 'boolean') {
 
15131          * Calculate the SHA-512 of a raw string
 
15134       s = (utf8) ? utf8Encode(s) : s;
 
15135       return binb2rstr(binb(rstr2binb(s), s.length * 8));
 
15139      * Calculate the HMAC-SHA1 of a key and some data (raw strings)
 
15141     function rstr_hmac(key, data) {
 
15142         var bkey, ipad, opad, i, hash;
 
15143         key = (utf8) ? utf8Encode(key) : key;
 
15144         data = (utf8) ? utf8Encode(data) : data;
 
15145         bkey = rstr2binb(key);
 
15147         if (bkey.length > 16) {
 
15148         bkey = binb(bkey, key.length * 8);
 
15150         ipad = Array(16), opad = Array(16);
 
15151         for (i = 0; i < 16; i+=1) {
 
15152                 ipad[i] = bkey[i] ^ 0x36363636;
 
15153                 opad[i] = bkey[i] ^ 0x5C5C5C5C;
 
15155         hash = binb(ipad.concat(rstr2binb(data)), 512 + data.length * 8);
 
15156         return binb2rstr(binb(opad.concat(hash), 512 + 160));
 
15160      * Calculate the SHA-1 of an array of big-endian words, and a bit length
 
15162     function binb(x, len) {
 
15163       var i, j, t, olda, oldb, oldc, oldd, olde,
 
15171       /* append padding */
 
15172       x[len >> 5] |= 0x80 << (24 - len % 32);
 
15173       x[((len + 64 >> 9) << 4) + 15] = len;
 
15175       for (i = 0; i < x.length; i += 16) {
 
15182         for (j = 0; j < 80; j+=1)       {
 
15186             w[j] = bit_rol(w[j-3] ^ w[j-8] ^ w[j-14] ^ w[j-16], 1);
 
15188           t = safe_add(safe_add(bit_rol(a, 5), sha1_ft(j, b, c, d)),
 
15189                                            safe_add(safe_add(e, w[j]), sha1_kt(j)));
 
15192           c = bit_rol(b, 30);
 
15197         a = safe_add(a, olda);
 
15198         b = safe_add(b, oldb);
 
15199         c = safe_add(c, oldc);
 
15200         d = safe_add(d, oldd);
 
15201         e = safe_add(e, olde);
 
15203       return Array(a, b, c, d, e);
 
15207      * Perform the appropriate triplet combination function for the current
 
15210     function sha1_ft(t, b, c, d) {
 
15211       if (t < 20) { return (b & c) | ((~b) & d); }
 
15212       if (t < 40) { return b ^ c ^ d; }
 
15213       if (t < 60) { return (b & c) | (b & d) | (c & d); }
 
15218      * Determine the appropriate additive constant for the current iteration
 
15220     function sha1_kt(t) {
 
15221       return (t < 20) ?  1518500249 : (t < 40) ?  1859775393 :
 
15222                  (t < 60) ? -1894007588 : -899497514;
 
15226    * @class Hashes.SHA256
 
15229    * A JavaScript implementation of the Secure Hash Algorithm, SHA-256, as defined in FIPS 180-2
 
15230    * Version 2.2 Copyright Angel Marin, Paul Johnston 2000 - 2009.
 
15231    * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
 
15232    * See http://pajhome.org.uk/crypt/md5 for details.
 
15233    * Also http://anmar.eu.org/projects/jssha2/
 
15235   SHA256 : function (options) {
 
15237      * Private properties configuration variables. You may need to tweak these to be compatible with
 
15238      * the server-side, but the defaults work in most cases.
 
15239      * @see this.setUpperCase() method
 
15240      * @see this.setPad() method
 
15242     var hexcase = (options && typeof options.uppercase === 'boolean') ? options.uppercase : false, // hexadecimal output case format. false - lowercase; true - uppercase  */
 
15243               b64pad = (options && typeof options.pad === 'string') ? options.pda : '=', /* base-64 pad character. Default '=' for strict RFC compliance   */
 
15244               utf8 = (options && typeof options.utf8 === 'boolean') ? options.utf8 : true, /* enable/disable utf8 encoding */
 
15247     /* privileged (public) methods */
 
15248     this.hex = function (s) {
 
15249       return rstr2hex(rstr(s, utf8));
 
15251     this.b64 = function (s) {
 
15252       return rstr2b64(rstr(s, utf8), b64pad);
 
15254     this.any = function (s, e) {
 
15255       return rstr2any(rstr(s, utf8), e);
 
15257     this.hex_hmac = function (k, d) {
 
15258       return rstr2hex(rstr_hmac(k, d));
 
15260     this.b64_hmac = function (k, d) {
 
15261       return rstr2b64(rstr_hmac(k, d), b64pad);
 
15263     this.any_hmac = function (k, d, e) {
 
15264       return rstr2any(rstr_hmac(k, d), e);
 
15267      * Perform a simple self-test to see if the VM is working
 
15268      * @return {String} Hexadecimal hash sample
 
15271     this.vm_test = function () {
 
15272       return hex('abc').toLowerCase() === '900150983cd24fb0d6963f7d28e17f72';
 
15275      * Enable/disable uppercase hexadecimal returned string
 
15277      * @return {Object} this
 
15280     this.setUpperCase = function (a) {
 
15281       if (typeof a === 'boolean') {
 
15287      * @description Defines a base64 pad string
 
15288      * @param {string} Pad
 
15289      * @return {Object} this
 
15292     this.setPad = function (a) {
 
15293       b64pad = a || b64pad;
 
15297      * Defines a base64 pad string
 
15299      * @return {Object} this
 
15302     this.setUTF8 = function (a) {
 
15303       if (typeof a === 'boolean') {
 
15312      * Calculate the SHA-512 of a raw string
 
15314     function rstr(s, utf8) {
 
15315       s = (utf8) ? utf8Encode(s) : s;
 
15316       return binb2rstr(binb(rstr2binb(s), s.length * 8));
 
15320      * Calculate the HMAC-sha256 of a key and some data (raw strings)
 
15322     function rstr_hmac(key, data) {
 
15323       key = (utf8) ? utf8Encode(key) : key;
 
15324       data = (utf8) ? utf8Encode(data) : data;
 
15326           bkey = rstr2binb(key),
 
15330       if (bkey.length > 16) { bkey = binb(bkey, key.length * 8); }
 
15332       for (; i < 16; i+=1) {
 
15333         ipad[i] = bkey[i] ^ 0x36363636;
 
15334         opad[i] = bkey[i] ^ 0x5C5C5C5C;
 
15337       hash = binb(ipad.concat(rstr2binb(data)), 512 + data.length * 8);
 
15338       return binb2rstr(binb(opad.concat(hash), 512 + 256));
 
15342      * Main sha256 function, with its support functions
 
15344     function sha256_S (X, n) {return ( X >>> n ) | (X << (32 - n));}
 
15345     function sha256_R (X, n) {return ( X >>> n );}
 
15346     function sha256_Ch(x, y, z) {return ((x & y) ^ ((~x) & z));}
 
15347     function sha256_Maj(x, y, z) {return ((x & y) ^ (x & z) ^ (y & z));}
 
15348     function sha256_Sigma0256(x) {return (sha256_S(x, 2) ^ sha256_S(x, 13) ^ sha256_S(x, 22));}
 
15349     function sha256_Sigma1256(x) {return (sha256_S(x, 6) ^ sha256_S(x, 11) ^ sha256_S(x, 25));}
 
15350     function sha256_Gamma0256(x) {return (sha256_S(x, 7) ^ sha256_S(x, 18) ^ sha256_R(x, 3));}
 
15351     function sha256_Gamma1256(x) {return (sha256_S(x, 17) ^ sha256_S(x, 19) ^ sha256_R(x, 10));}
 
15352     function sha256_Sigma0512(x) {return (sha256_S(x, 28) ^ sha256_S(x, 34) ^ sha256_S(x, 39));}
 
15353     function sha256_Sigma1512(x) {return (sha256_S(x, 14) ^ sha256_S(x, 18) ^ sha256_S(x, 41));}
 
15354     function sha256_Gamma0512(x) {return (sha256_S(x, 1)  ^ sha256_S(x, 8) ^ sha256_R(x, 7));}
 
15355     function sha256_Gamma1512(x) {return (sha256_S(x, 19) ^ sha256_S(x, 61) ^ sha256_R(x, 6));}
 
15358       1116352408, 1899447441, -1245643825, -373957723, 961987163, 1508970993,
 
15359       -1841331548, -1424204075, -670586216, 310598401, 607225278, 1426881987,
 
15360       1925078388, -2132889090, -1680079193, -1046744716, -459576895, -272742522,
 
15361       264347078, 604807628, 770255983, 1249150122, 1555081692, 1996064986,
 
15362       -1740746414, -1473132947, -1341970488, -1084653625, -958395405, -710438585,
 
15363       113926993, 338241895, 666307205, 773529912, 1294757372, 1396182291,
 
15364       1695183700, 1986661051, -2117940946, -1838011259, -1564481375, -1474664885,
 
15365       -1035236496, -949202525, -778901479, -694614492, -200395387, 275423344,
 
15366       430227734, 506948616, 659060556, 883997877, 958139571, 1322822218,
 
15367       1537002063, 1747873779, 1955562222, 2024104815, -2067236844, -1933114872,
 
15368       -1866530822, -1538233109, -1090935817, -965641998
 
15371     function binb(m, l) {
 
15372       var HASH = [1779033703, -1150833019, 1013904242, -1521486534,
 
15373                  1359893119, -1694144372, 528734635, 1541459225];
 
15374       var W = new Array(64);
 
15375       var a, b, c, d, e, f, g, h;
 
15378       /* append padding */
 
15379       m[l >> 5] |= 0x80 << (24 - l % 32);
 
15380       m[((l + 64 >> 9) << 4) + 15] = l;
 
15382       for (i = 0; i < m.length; i += 16)
 
15393       for (j = 0; j < 64; j+=1)
 
15398           W[j] = safe_add(safe_add(safe_add(sha256_Gamma1256(W[j - 2]), W[j - 7]),
 
15399                           sha256_Gamma0256(W[j - 15])), W[j - 16]);
 
15402         T1 = safe_add(safe_add(safe_add(safe_add(h, sha256_Sigma1256(e)), sha256_Ch(e, f, g)),
 
15403                                   sha256_K[j]), W[j]);
 
15404         T2 = safe_add(sha256_Sigma0256(a), sha256_Maj(a, b, c));
 
15408         e = safe_add(d, T1);
 
15412         a = safe_add(T1, T2);
 
15415       HASH[0] = safe_add(a, HASH[0]);
 
15416       HASH[1] = safe_add(b, HASH[1]);
 
15417       HASH[2] = safe_add(c, HASH[2]);
 
15418       HASH[3] = safe_add(d, HASH[3]);
 
15419       HASH[4] = safe_add(e, HASH[4]);
 
15420       HASH[5] = safe_add(f, HASH[5]);
 
15421       HASH[6] = safe_add(g, HASH[6]);
 
15422       HASH[7] = safe_add(h, HASH[7]);
 
15430    * @class Hashes.SHA512
 
15433    * A JavaScript implementation of the Secure Hash Algorithm, SHA-512, as defined in FIPS 180-2
 
15434    * Version 2.2 Copyright Anonymous Contributor, Paul Johnston 2000 - 2009.
 
15435    * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
 
15436    * See http://pajhome.org.uk/crypt/md5 for details.
 
15438   SHA512 : function (options) {
 
15440      * Private properties configuration variables. You may need to tweak these to be compatible with
 
15441      * the server-side, but the defaults work in most cases.
 
15442      * @see this.setUpperCase() method
 
15443      * @see this.setPad() method
 
15445     var hexcase = (options && typeof options.uppercase === 'boolean') ? options.uppercase : false , /* hexadecimal output case format. false - lowercase; true - uppercase  */
 
15446         b64pad = (options && typeof options.pad === 'string') ? options.pda : '=',  /* base-64 pad character. Default '=' for strict RFC compliance   */
 
15447         utf8 = (options && typeof options.utf8 === 'boolean') ? options.utf8 : true, /* enable/disable utf8 encoding */
 
15450     /* privileged (public) methods */
 
15451     this.hex = function (s) {
 
15452       return rstr2hex(rstr(s));
 
15454     this.b64 = function (s) {
 
15455       return rstr2b64(rstr(s), b64pad);
 
15457     this.any = function (s, e) {
 
15458       return rstr2any(rstr(s), e);
 
15460     this.hex_hmac = function (k, d) {
 
15461       return rstr2hex(rstr_hmac(k, d));
 
15463     this.b64_hmac = function (k, d) {
 
15464       return rstr2b64(rstr_hmac(k, d), b64pad);
 
15466     this.any_hmac = function (k, d, e) {
 
15467       return rstr2any(rstr_hmac(k, d), e);
 
15470      * Perform a simple self-test to see if the VM is working
 
15471      * @return {String} Hexadecimal hash sample
 
15474     this.vm_test = function () {
 
15475       return hex('abc').toLowerCase() === '900150983cd24fb0d6963f7d28e17f72';
 
15478      * @description Enable/disable uppercase hexadecimal returned string
 
15480      * @return {Object} this
 
15483     this.setUpperCase = function (a) {
 
15484       if (typeof a === 'boolean') {
 
15490      * @description Defines a base64 pad string
 
15491      * @param {string} Pad
 
15492      * @return {Object} this
 
15495     this.setPad = function (a) {
 
15496       b64pad = a || b64pad;
 
15500      * @description Defines a base64 pad string
 
15502      * @return {Object} this
 
15505     this.setUTF8 = function (a) {
 
15506       if (typeof a === 'boolean') {
 
15512     /* private methods */
 
15515      * Calculate the SHA-512 of a raw string
 
15518       s = (utf8) ? utf8Encode(s) : s;
 
15519       return binb2rstr(binb(rstr2binb(s), s.length * 8));
 
15522      * Calculate the HMAC-SHA-512 of a key and some data (raw strings)
 
15524     function rstr_hmac(key, data) {
 
15525       key = (utf8) ? utf8Encode(key) : key;
 
15526       data = (utf8) ? utf8Encode(data) : data;
 
15529           bkey = rstr2binb(key),
 
15530           ipad = Array(32), opad = Array(32);
 
15532       if (bkey.length > 32) { bkey = binb(bkey, key.length * 8); }
 
15534       for (; i < 32; i+=1) {
 
15535         ipad[i] = bkey[i] ^ 0x36363636;
 
15536         opad[i] = bkey[i] ^ 0x5C5C5C5C;
 
15539       hash = binb(ipad.concat(rstr2binb(data)), 1024 + data.length * 8);
 
15540       return binb2rstr(binb(opad.concat(hash), 1024 + 512));
 
15544      * Calculate the SHA-512 of an array of big-endian dwords, and a bit length
 
15546     function binb(x, len) {
 
15549           hash = new Array(16),
 
15550           //Initial hash values
 
15552             new int64(0x6a09e667, -205731576),
 
15553             new int64(-1150833019, -2067093701),
 
15554             new int64(0x3c6ef372, -23791573),
 
15555             new int64(-1521486534, 0x5f1d36f1),
 
15556             new int64(0x510e527f, -1377402159),
 
15557             new int64(-1694144372, 0x2b3e6c1f),
 
15558             new int64(0x1f83d9ab, -79577749),
 
15559             new int64(0x5be0cd19, 0x137e2179)
 
15561           T1 = new int64(0, 0),
 
15562           T2 = new int64(0, 0),
 
15563           a = new int64(0,0),
 
15564           b = new int64(0,0),
 
15565           c = new int64(0,0),
 
15566           d = new int64(0,0),
 
15567           e = new int64(0,0),
 
15568           f = new int64(0,0),
 
15569           g = new int64(0,0),
 
15570           h = new int64(0,0),
 
15571           //Temporary variables not specified by the document
 
15572           s0 = new int64(0, 0),
 
15573           s1 = new int64(0, 0),
 
15574           Ch = new int64(0, 0),
 
15575           Maj = new int64(0, 0),
 
15576           r1 = new int64(0, 0),
 
15577           r2 = new int64(0, 0),
 
15578           r3 = new int64(0, 0);
 
15580       if (sha512_k === undefined) {
 
15583             new int64(0x428a2f98, -685199838), new int64(0x71374491, 0x23ef65cd),
 
15584             new int64(-1245643825, -330482897), new int64(-373957723, -2121671748),
 
15585             new int64(0x3956c25b, -213338824), new int64(0x59f111f1, -1241133031),
 
15586             new int64(-1841331548, -1357295717), new int64(-1424204075, -630357736),
 
15587             new int64(-670586216, -1560083902), new int64(0x12835b01, 0x45706fbe),
 
15588             new int64(0x243185be, 0x4ee4b28c), new int64(0x550c7dc3, -704662302),
 
15589             new int64(0x72be5d74, -226784913), new int64(-2132889090, 0x3b1696b1),
 
15590             new int64(-1680079193, 0x25c71235), new int64(-1046744716, -815192428),
 
15591             new int64(-459576895, -1628353838), new int64(-272742522, 0x384f25e3),
 
15592             new int64(0xfc19dc6, -1953704523), new int64(0x240ca1cc, 0x77ac9c65),
 
15593             new int64(0x2de92c6f, 0x592b0275), new int64(0x4a7484aa, 0x6ea6e483),
 
15594             new int64(0x5cb0a9dc, -1119749164), new int64(0x76f988da, -2096016459),
 
15595             new int64(-1740746414, -295247957), new int64(-1473132947, 0x2db43210),
 
15596             new int64(-1341970488, -1728372417), new int64(-1084653625, -1091629340),
 
15597             new int64(-958395405, 0x3da88fc2), new int64(-710438585, -1828018395),
 
15598             new int64(0x6ca6351, -536640913), new int64(0x14292967, 0xa0e6e70),
 
15599             new int64(0x27b70a85, 0x46d22ffc), new int64(0x2e1b2138, 0x5c26c926),
 
15600             new int64(0x4d2c6dfc, 0x5ac42aed), new int64(0x53380d13, -1651133473),
 
15601             new int64(0x650a7354, -1951439906), new int64(0x766a0abb, 0x3c77b2a8),
 
15602             new int64(-2117940946, 0x47edaee6), new int64(-1838011259, 0x1482353b),
 
15603             new int64(-1564481375, 0x4cf10364), new int64(-1474664885, -1136513023),
 
15604             new int64(-1035236496, -789014639), new int64(-949202525, 0x654be30),
 
15605             new int64(-778901479, -688958952), new int64(-694614492, 0x5565a910),
 
15606             new int64(-200395387, 0x5771202a), new int64(0x106aa070, 0x32bbd1b8),
 
15607             new int64(0x19a4c116, -1194143544), new int64(0x1e376c08, 0x5141ab53),
 
15608             new int64(0x2748774c, -544281703), new int64(0x34b0bcb5, -509917016),
 
15609             new int64(0x391c0cb3, -976659869), new int64(0x4ed8aa4a, -482243893),
 
15610             new int64(0x5b9cca4f, 0x7763e373), new int64(0x682e6ff3, -692930397),
 
15611             new int64(0x748f82ee, 0x5defb2fc), new int64(0x78a5636f, 0x43172f60),
 
15612             new int64(-2067236844, -1578062990), new int64(-1933114872, 0x1a6439ec),
 
15613             new int64(-1866530822, 0x23631e28), new int64(-1538233109, -561857047),
 
15614             new int64(-1090935817, -1295615723), new int64(-965641998, -479046869),
 
15615             new int64(-903397682, -366583396), new int64(-779700025, 0x21c0c207),
 
15616             new int64(-354779690, -840897762), new int64(-176337025, -294727304),
 
15617             new int64(0x6f067aa, 0x72176fba), new int64(0xa637dc5, -1563912026),
 
15618             new int64(0x113f9804, -1090974290), new int64(0x1b710b35, 0x131c471b),
 
15619             new int64(0x28db77f5, 0x23047d84), new int64(0x32caab7b, 0x40c72493),
 
15620             new int64(0x3c9ebe0a, 0x15c9bebc), new int64(0x431d67c4, -1676669620),
 
15621             new int64(0x4cc5d4be, -885112138), new int64(0x597f299c, -60457430),
 
15622             new int64(0x5fcb6fab, 0x3ad6faec), new int64(0x6c44198c, 0x4a475817)
 
15626       for (i=0; i<80; i+=1) {
 
15627         W[i] = new int64(0, 0);
 
15630       // append padding to the source string. The format is described in the FIPS.
 
15631       x[len >> 5] |= 0x80 << (24 - (len & 0x1f));
 
15632       x[((len + 128 >> 10)<< 5) + 31] = len;
 
15634       for (i = 0; i<l; i+=32) { //32 dwords is the block size
 
15635         int64copy(a, H[0]);
 
15636         int64copy(b, H[1]);
 
15637         int64copy(c, H[2]);
 
15638         int64copy(d, H[3]);
 
15639         int64copy(e, H[4]);
 
15640         int64copy(f, H[5]);
 
15641         int64copy(g, H[6]);
 
15642         int64copy(h, H[7]);
 
15644         for (j=0; j<16; j+=1) {
 
15645           W[j].h = x[i + 2*j];
 
15646           W[j].l = x[i + 2*j + 1];
 
15649         for (j=16; j<80; j+=1) {
 
15651           int64rrot(r1, W[j-2], 19);
 
15652           int64revrrot(r2, W[j-2], 29);
 
15653           int64shr(r3, W[j-2], 6);
 
15654           s1.l = r1.l ^ r2.l ^ r3.l;
 
15655           s1.h = r1.h ^ r2.h ^ r3.h;
 
15657           int64rrot(r1, W[j-15], 1);
 
15658           int64rrot(r2, W[j-15], 8);
 
15659           int64shr(r3, W[j-15], 7);
 
15660           s0.l = r1.l ^ r2.l ^ r3.l;
 
15661           s0.h = r1.h ^ r2.h ^ r3.h;
 
15663           int64add4(W[j], s1, W[j-7], s0, W[j-16]);
 
15666         for (j = 0; j < 80; j+=1) {
 
15668           Ch.l = (e.l & f.l) ^ (~e.l & g.l);
 
15669           Ch.h = (e.h & f.h) ^ (~e.h & g.h);
 
15672           int64rrot(r1, e, 14);
 
15673           int64rrot(r2, e, 18);
 
15674           int64revrrot(r3, e, 9);
 
15675           s1.l = r1.l ^ r2.l ^ r3.l;
 
15676           s1.h = r1.h ^ r2.h ^ r3.h;
 
15679           int64rrot(r1, a, 28);
 
15680           int64revrrot(r2, a, 2);
 
15681           int64revrrot(r3, a, 7);
 
15682           s0.l = r1.l ^ r2.l ^ r3.l;
 
15683           s0.h = r1.h ^ r2.h ^ r3.h;
 
15686           Maj.l = (a.l & b.l) ^ (a.l & c.l) ^ (b.l & c.l);
 
15687           Maj.h = (a.h & b.h) ^ (a.h & c.h) ^ (b.h & c.h);
 
15689           int64add5(T1, h, s1, Ch, sha512_k[j], W[j]);
 
15690           int64add(T2, s0, Maj);
 
15695           int64add(e, d, T1);
 
15699           int64add(a, T1, T2);
 
15701         int64add(H[0], H[0], a);
 
15702         int64add(H[1], H[1], b);
 
15703         int64add(H[2], H[2], c);
 
15704         int64add(H[3], H[3], d);
 
15705         int64add(H[4], H[4], e);
 
15706         int64add(H[5], H[5], f);
 
15707         int64add(H[6], H[6], g);
 
15708         int64add(H[7], H[7], h);
 
15711       //represent the hash as an array of 32-bit dwords
 
15712       for (i=0; i<8; i+=1) {
 
15713         hash[2*i] = H[i].h;
 
15714         hash[2*i + 1] = H[i].l;
 
15719     //A constructor for 64-bit numbers
 
15720     function int64(h, l) {
 
15723       //this.toString = int64toString;
 
15726     //Copies src into dst, assuming both are 64-bit numbers
 
15727     function int64copy(dst, src) {
 
15732     //Right-rotates a 64-bit number by shift
 
15733     //Won't handle cases of shift>=32
 
15734     //The function revrrot() is for that
 
15735     function int64rrot(dst, x, shift) {
 
15736       dst.l = (x.l >>> shift) | (x.h << (32-shift));
 
15737       dst.h = (x.h >>> shift) | (x.l << (32-shift));
 
15740     //Reverses the dwords of the source and then rotates right by shift.
 
15741     //This is equivalent to rotation by 32+shift
 
15742     function int64revrrot(dst, x, shift) {
 
15743       dst.l = (x.h >>> shift) | (x.l << (32-shift));
 
15744       dst.h = (x.l >>> shift) | (x.h << (32-shift));
 
15747     //Bitwise-shifts right a 64-bit number by shift
 
15748     //Won't handle shift>=32, but it's never needed in SHA512
 
15749     function int64shr(dst, x, shift) {
 
15750       dst.l = (x.l >>> shift) | (x.h << (32-shift));
 
15751       dst.h = (x.h >>> shift);
 
15754     //Adds two 64-bit numbers
 
15755     //Like the original implementation, does not rely on 32-bit operations
 
15756     function int64add(dst, x, y) {
 
15757        var w0 = (x.l & 0xffff) + (y.l & 0xffff);
 
15758        var w1 = (x.l >>> 16) + (y.l >>> 16) + (w0 >>> 16);
 
15759        var w2 = (x.h & 0xffff) + (y.h & 0xffff) + (w1 >>> 16);
 
15760        var w3 = (x.h >>> 16) + (y.h >>> 16) + (w2 >>> 16);
 
15761        dst.l = (w0 & 0xffff) | (w1 << 16);
 
15762        dst.h = (w2 & 0xffff) | (w3 << 16);
 
15765     //Same, except with 4 addends. Works faster than adding them one by one.
 
15766     function int64add4(dst, a, b, c, d) {
 
15767        var w0 = (a.l & 0xffff) + (b.l & 0xffff) + (c.l & 0xffff) + (d.l & 0xffff);
 
15768        var w1 = (a.l >>> 16) + (b.l >>> 16) + (c.l >>> 16) + (d.l >>> 16) + (w0 >>> 16);
 
15769        var w2 = (a.h & 0xffff) + (b.h & 0xffff) + (c.h & 0xffff) + (d.h & 0xffff) + (w1 >>> 16);
 
15770        var w3 = (a.h >>> 16) + (b.h >>> 16) + (c.h >>> 16) + (d.h >>> 16) + (w2 >>> 16);
 
15771        dst.l = (w0 & 0xffff) | (w1 << 16);
 
15772        dst.h = (w2 & 0xffff) | (w3 << 16);
 
15775     //Same, except with 5 addends
 
15776     function int64add5(dst, a, b, c, d, e) {
 
15777       var w0 = (a.l & 0xffff) + (b.l & 0xffff) + (c.l & 0xffff) + (d.l & 0xffff) + (e.l & 0xffff),
 
15778           w1 = (a.l >>> 16) + (b.l >>> 16) + (c.l >>> 16) + (d.l >>> 16) + (e.l >>> 16) + (w0 >>> 16),
 
15779           w2 = (a.h & 0xffff) + (b.h & 0xffff) + (c.h & 0xffff) + (d.h & 0xffff) + (e.h & 0xffff) + (w1 >>> 16),
 
15780           w3 = (a.h >>> 16) + (b.h >>> 16) + (c.h >>> 16) + (d.h >>> 16) + (e.h >>> 16) + (w2 >>> 16);
 
15781        dst.l = (w0 & 0xffff) | (w1 << 16);
 
15782        dst.h = (w2 & 0xffff) | (w3 << 16);
 
15786    * @class Hashes.RMD160
 
15788    * @param {Object} [config]
 
15790    * A JavaScript implementation of the RIPEMD-160 Algorithm
 
15791    * Version 2.2 Copyright Jeremy Lin, Paul Johnston 2000 - 2009.
 
15792    * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
 
15793    * See http://pajhome.org.uk/crypt/md5 for details.
 
15794    * Also http://www.ocf.berkeley.edu/~jjlin/jsotp/
 
15796   RMD160 : function (options) {
 
15798      * Private properties configuration variables. You may need to tweak these to be compatible with
 
15799      * the server-side, but the defaults work in most cases.
 
15800      * @see this.setUpperCase() method
 
15801      * @see this.setPad() method
 
15803     var hexcase = (options && typeof options.uppercase === 'boolean') ? options.uppercase : false,   /* hexadecimal output case format. false - lowercase; true - uppercase  */
 
15804         b64pad = (options && typeof options.pad === 'string') ? options.pda : '=',  /* base-64 pad character. Default '=' for strict RFC compliance   */
 
15805         utf8 = (options && typeof options.utf8 === 'boolean') ? options.utf8 : true, /* enable/disable utf8 encoding */
 
15807            0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15,
 
15808            7,  4, 13,  1, 10,  6, 15,  3, 12,  0,  9,  5,  2, 14, 11,  8,
 
15809            3, 10, 14,  4,  9, 15,  8,  1,  2,  7,  0,  6, 13, 11,  5, 12,
 
15810            1,  9, 11, 10,  0,  8, 12,  4, 13,  3,  7, 15, 14,  5,  6,  2,
 
15811            4,  0,  5,  9,  7, 12,  2, 10, 14,  1,  3,  8, 11,  6, 15, 13
 
15814            5, 14,  7,  0,  9,  2, 11,  4, 13,  6, 15,  8,  1, 10,  3, 12,
 
15815            6, 11,  3,  7,  0, 13,  5, 10, 14, 15,  8, 12,  4,  9,  1,  2,
 
15816           15,  5,  1,  3,  7, 14,  6,  9, 11,  8, 12,  2, 10,  0,  4, 13,
 
15817            8,  6,  4,  1,  3, 11, 15,  0,  5, 12,  2, 13,  9,  7, 10, 14,
 
15818           12, 15, 10,  4,  1,  5,  8,  7,  6,  2, 13, 14,  0,  3,  9, 11
 
15821           11, 14, 15, 12,  5,  8,  7,  9, 11, 13, 14, 15,  6,  7,  9,  8,
 
15822            7,  6,  8, 13, 11,  9,  7, 15,  7, 12, 15,  9, 11,  7, 13, 12,
 
15823           11, 13,  6,  7, 14,  9, 13, 15, 14,  8, 13,  6,  5, 12,  7,  5,
 
15824           11, 12, 14, 15, 14, 15,  9,  8,  9, 14,  5,  6,  8,  6,  5, 12,
 
15825            9, 15,  5, 11,  6,  8, 13, 12,  5, 12, 13, 14, 11,  8,  5,  6
 
15828            8,  9,  9, 11, 13, 15, 15,  5,  7,  7,  8, 11, 14, 14, 12,  6,
 
15829            9, 13, 15,  7, 12,  8,  9, 11,  7,  7, 12,  7,  6, 15, 13, 11,
 
15830            9,  7, 15, 11,  8,  6,  6, 14, 12, 13,  5, 14, 13, 13,  7,  5,
 
15831           15,  5,  8, 11, 14, 14,  6, 14,  6,  9, 12,  9, 12,  5, 15,  8,
 
15832            8,  5, 12,  9, 12,  5, 14,  6,  8, 13,  6,  5, 15, 13, 11, 11
 
15835     /* privileged (public) methods */
 
15836     this.hex = function (s) {
 
15837       return rstr2hex(rstr(s, utf8));
 
15839     this.b64 = function (s) {
 
15840       return rstr2b64(rstr(s, utf8), b64pad);
 
15842     this.any = function (s, e) {
 
15843       return rstr2any(rstr(s, utf8), e);
 
15845     this.hex_hmac = function (k, d) {
 
15846       return rstr2hex(rstr_hmac(k, d));
 
15848     this.b64_hmac = function (k, d) {
 
15849       return rstr2b64(rstr_hmac(k, d), b64pad);
 
15851     this.any_hmac = function (k, d, e) {
 
15852       return rstr2any(rstr_hmac(k, d), e);
 
15855      * Perform a simple self-test to see if the VM is working
 
15856      * @return {String} Hexadecimal hash sample
 
15859     this.vm_test = function () {
 
15860       return hex('abc').toLowerCase() === '900150983cd24fb0d6963f7d28e17f72';
 
15863      * @description Enable/disable uppercase hexadecimal returned string
 
15865      * @return {Object} this
 
15868     this.setUpperCase = function (a) {
 
15869       if (typeof a === 'boolean' ) { hexcase = a; }
 
15873      * @description Defines a base64 pad string
 
15874      * @param {string} Pad
 
15875      * @return {Object} this
 
15878     this.setPad = function (a) {
 
15879       if (typeof a !== 'undefined' ) { b64pad = a; }
 
15883      * @description Defines a base64 pad string
 
15885      * @return {Object} this
 
15888     this.setUTF8 = function (a) {
 
15889       if (typeof a === 'boolean') { utf8 = a; }
 
15893     /* private methods */
 
15896      * Calculate the rmd160 of a raw string
 
15899       s = (utf8) ? utf8Encode(s) : s;
 
15900       return binl2rstr(binl(rstr2binl(s), s.length * 8));
 
15904      * Calculate the HMAC-rmd160 of a key and some data (raw strings)
 
15906     function rstr_hmac(key, data) {
 
15907       key = (utf8) ? utf8Encode(key) : key;
 
15908       data = (utf8) ? utf8Encode(data) : data;
 
15910           bkey = rstr2binl(key),
 
15911           ipad = Array(16), opad = Array(16);
 
15913       if (bkey.length > 16) {
 
15914         bkey = binl(bkey, key.length * 8);
 
15917       for (i = 0; i < 16; i+=1) {
 
15918         ipad[i] = bkey[i] ^ 0x36363636;
 
15919         opad[i] = bkey[i] ^ 0x5C5C5C5C;
 
15921       hash = binl(ipad.concat(rstr2binl(data)), 512 + data.length * 8);
 
15922       return binl2rstr(binl(opad.concat(hash), 512 + 160));
 
15926      * Convert an array of little-endian words to a string
 
15928     function binl2rstr(input) {
 
15929       var i, output = '', l = input.length * 32;
 
15930       for (i = 0; i < l; i += 8) {
 
15931         output += String.fromCharCode((input[i>>5] >>> (i % 32)) & 0xFF);
 
15937      * Calculate the RIPE-MD160 of an array of little-endian words, and a bit length.
 
15939     function binl(x, len) {
 
15946           A1, B1, C1, D1, E1,
 
15947           A2, B2, C2, D2, E2;
 
15949       /* append padding */
 
15950       x[len >> 5] |= 0x80 << (len % 32);
 
15951       x[(((len + 64) >>> 9) << 4) + 14] = len;
 
15954       for (i = 0; i < l; i+=16) {
 
15955         A1 = A2 = h0; B1 = B2 = h1; C1 = C2 = h2; D1 = D2 = h3; E1 = E2 = h4;
 
15956         for (j = 0; j <= 79; j+=1) {
 
15957           T = safe_add(A1, rmd160_f(j, B1, C1, D1));
 
15958           T = safe_add(T, x[i + rmd160_r1[j]]);
 
15959           T = safe_add(T, rmd160_K1(j));
 
15960           T = safe_add(bit_rol(T, rmd160_s1[j]), E1);
 
15961           A1 = E1; E1 = D1; D1 = bit_rol(C1, 10); C1 = B1; B1 = T;
 
15962           T = safe_add(A2, rmd160_f(79-j, B2, C2, D2));
 
15963           T = safe_add(T, x[i + rmd160_r2[j]]);
 
15964           T = safe_add(T, rmd160_K2(j));
 
15965           T = safe_add(bit_rol(T, rmd160_s2[j]), E2);
 
15966           A2 = E2; E2 = D2; D2 = bit_rol(C2, 10); C2 = B2; B2 = T;
 
15969         T = safe_add(h1, safe_add(C1, D2));
 
15970         h1 = safe_add(h2, safe_add(D1, E2));
 
15971         h2 = safe_add(h3, safe_add(E1, A2));
 
15972         h3 = safe_add(h4, safe_add(A1, B2));
 
15973         h4 = safe_add(h0, safe_add(B1, C2));
 
15976       return [h0, h1, h2, h3, h4];
 
15979     // specific algorithm methods
 
15980     function rmd160_f(j, x, y, z) {
 
15981       return ( 0 <= j && j <= 15) ? (x ^ y ^ z) :
 
15982          (16 <= j && j <= 31) ? (x & y) | (~x & z) :
 
15983          (32 <= j && j <= 47) ? (x | ~y) ^ z :
 
15984          (48 <= j && j <= 63) ? (x & z) | (y & ~z) :
 
15985          (64 <= j && j <= 79) ? x ^ (y | ~z) :
 
15986          'rmd160_f: j out of range';
 
15989     function rmd160_K1(j) {
 
15990       return ( 0 <= j && j <= 15) ? 0x00000000 :
 
15991          (16 <= j && j <= 31) ? 0x5a827999 :
 
15992          (32 <= j && j <= 47) ? 0x6ed9eba1 :
 
15993          (48 <= j && j <= 63) ? 0x8f1bbcdc :
 
15994          (64 <= j && j <= 79) ? 0xa953fd4e :
 
15995          'rmd160_K1: j out of range';
 
15998     function rmd160_K2(j){
 
15999       return ( 0 <= j && j <= 15) ? 0x50a28be6 :
 
16000          (16 <= j && j <= 31) ? 0x5c4dd124 :
 
16001          (32 <= j && j <= 47) ? 0x6d703ef3 :
 
16002          (48 <= j && j <= 63) ? 0x7a6d76e9 :
 
16003          (64 <= j && j <= 79) ? 0x00000000 :
 
16004          'rmd160_K2: j out of range';
 
16010   (function( window, undefined ) {
 
16011     var freeExports = false;
 
16012     if (typeof exports === 'object' ) {
 
16013       freeExports = exports;
 
16014       if (exports && typeof global === 'object' && global && global === global.global ) { window = global; }
 
16017     if (typeof define === 'function' && typeof define.amd === 'object' && define.amd) {
 
16018       // define as an anonymous module, so, through path mapping, it can be aliased
 
16019       define(function () { return Hashes; });
 
16021     else if ( freeExports ) {
 
16022       // in Node.js or RingoJS v0.8.0+
 
16023       if ( typeof module === 'object' && module && module.exports === freeExports ) {
 
16024         module.exports = Hashes;
 
16026       // in Narwhal or RingoJS v0.7.0-
 
16028         freeExports.Hashes = Hashes;
 
16032       // in a browser or Rhino
 
16033       window.Hashes = Hashes;
 
16039 },{}],2:[function(require,module,exports){
 
16042 var hashes = require('jshashes'),
 
16043     xtend = require('xtend'),
 
16044     sha1 = new hashes.SHA1();
 
16048 ohauth.qsString = function(obj) {
 
16049     return Object.keys(obj).sort().map(function(key) {
 
16050         return ohauth.percentEncode(key) + '=' +
 
16051             ohauth.percentEncode(obj[key]);
 
16055 ohauth.stringQs = function(str) {
 
16056     return str.split('&').reduce(function(obj, pair){
 
16057         var parts = pair.split('=');
 
16058         obj[decodeURIComponent(parts[0])] = (null === parts[1]) ?
 
16059             '' : decodeURIComponent(parts[1]);
 
16064 ohauth.rawxhr = function(method, url, data, headers, callback) {
 
16065     var xhr = new XMLHttpRequest(),
 
16066         twoHundred = /^20\d$/;
 
16067     xhr.onreadystatechange = function() {
 
16068         if (4 == xhr.readyState && 0 !== xhr.status) {
 
16069             if (twoHundred.test(xhr.status)) callback(null, xhr);
 
16070             else return callback(xhr, null);
 
16073     xhr.onerror = function(e) { return callback(e, null); };
 
16074     xhr.open(method, url, true);
 
16075     for (var h in headers) xhr.setRequestHeader(h, headers[h]);
 
16079 ohauth.xhr = function(method, url, auth, data, options, callback) {
 
16080     var headers = (options && options.header) || {
 
16081         'Content-Type': 'application/x-www-form-urlencoded'
 
16083     headers.Authorization = 'OAuth ' + ohauth.authHeader(auth);
 
16084     ohauth.rawxhr(method, url, data, headers, callback);
 
16087 ohauth.nonce = function() {
 
16088     for (var o = ''; o.length < 6;) {
 
16089         o += '0123456789ABCDEFGHIJKLMNOPQRSTUVWXTZabcdefghiklmnopqrstuvwxyz'[Math.floor(Math.random() * 61)];
 
16094 ohauth.authHeader = function(obj) {
 
16095     return Object.keys(obj).sort().map(function(key) {
 
16096         return encodeURIComponent(key) + '="' + encodeURIComponent(obj[key]) + '"';
 
16100 ohauth.timestamp = function() { return ~~((+new Date()) / 1000); };
 
16102 ohauth.percentEncode = function(s) {
 
16103     return encodeURIComponent(s)
 
16104         .replace(/\!/g, '%21').replace(/\'/g, '%27')
 
16105         .replace(/\*/g, '%2A').replace(/\(/g, '%28').replace(/\)/g, '%29');
 
16108 ohauth.baseString = function(method, url, params) {
 
16109     if (params.oauth_signature) delete params.oauth_signature;
 
16112         ohauth.percentEncode(url),
 
16113         ohauth.percentEncode(ohauth.qsString(params))].join('&');
 
16116 ohauth.signature = function(oauth_secret, token_secret, baseString) {
 
16117     return sha1.b64_hmac(
 
16118         ohauth.percentEncode(oauth_secret) + '&' +
 
16119         ohauth.percentEncode(token_secret),
 
16124  * Takes an options object for configuration (consumer_key,
 
16125  * consumer_secret, version, signature_method, token) and returns a
 
16126  * function that generates the Authorization header for given data.
 
16128  * The returned function takes these parameters:
 
16129  * - method: GET/POST/...
 
16130  * - uri: full URI with protocol, port, path and query string
 
16131  * - extra_params: any extra parameters (that are passed in the POST data),
 
16132  *   can be an object or a from-urlencoded string.
 
16134  * Returned function returns full OAuth header with "OAuth" string in it.
 
16137 ohauth.headerGenerator = function(options) {
 
16138     options = options || {};
 
16139     var consumer_key = options.consumer_key || '',
 
16140         consumer_secret = options.consumer_secret || '',
 
16141         signature_method = options.signature_method || 'HMAC-SHA1',
 
16142         version = options.version || '1.0',
 
16143         token = options.token || '';
 
16145     return function(method, uri, extra_params) {
 
16146         method = method.toUpperCase();
 
16147         if (typeof extra_params === 'string' && extra_params.length > 0) {
 
16148             extra_params = ohauth.stringQs(extra_params);
 
16151         var uri_parts = uri.split('?', 2),
 
16152         base_uri = uri_parts[0];
 
16154         var query_params = uri_parts.length === 2 ?
 
16155             ohauth.stringQs(uri_parts[1]) : {};
 
16157         var oauth_params = {
 
16158             oauth_consumer_key: consumer_key,
 
16159             oauth_signature_method: signature_method,
 
16160             oauth_version: version,
 
16161             oauth_timestamp: ohauth.timestamp(),
 
16162             oauth_nonce: ohauth.nonce()
 
16165         if (token) oauth_params.oauth_token = token;
 
16167         var all_params = xtend({}, oauth_params, query_params, extra_params),
 
16168             base_str = ohauth.baseString(method, base_uri, all_params);
 
16170         oauth_params.oauth_signature = ohauth.signature(consumer_secret, token, base_str);
 
16172         return 'OAuth ' + ohauth.authHeader(oauth_params);
 
16176 module.exports = ohauth;
 
16178 },{"jshashes":7,"xtend":4}],6:[function(require,module,exports){
 
16179 module.exports = Object.keys || require('./shim');
 
16182 },{"./shim":8}],8:[function(require,module,exports){
 
16186         // modified from https://github.com/kriskowal/es5-shim
 
16187         var has = Object.prototype.hasOwnProperty,
 
16188                 is = require('is'),
 
16189                 forEach = require('foreach'),
 
16190                 hasDontEnumBug = !({'toString': null}).propertyIsEnumerable('toString'),
 
16197                         "propertyIsEnumerable",
 
16202         keysShim = function keys(object) {
 
16203                 if (!is.object(object) && !is.array(object)) {
 
16204                         throw new TypeError("Object.keys called on a non-object");
 
16207                 var name, theKeys = [];
 
16208                 for (name in object) {
 
16209                         if (has.call(object, name)) {
 
16210                                 theKeys.push(name);
 
16214                 if (hasDontEnumBug) {
 
16215                         forEach(dontEnums, function (dontEnum) {
 
16216                                 if (has.call(object, dontEnum)) {
 
16217                                         theKeys.push(dontEnum);
 
16224         module.exports = keysShim;
 
16228 },{"is":9,"foreach":10}],9:[function(require,module,exports){
 
16232  * the definitive JavaScript type testing library
 
16234  * @copyright 2013 Enrico Marino
 
16238 var objProto = Object.prototype;
 
16239 var owns = objProto.hasOwnProperty;
 
16240 var toString = objProto.toString;
 
16241 var isActualNaN = function (value) {
 
16242   return value !== value;
 
16244 var NON_HOST_TYPES = {
 
16255 var is = module.exports = {};
 
16263  * Test if `value` is a type of `type`.
 
16265  * @param {Mixed} value value to test
 
16266  * @param {String} type type
 
16267  * @return {Boolean} true if `value` is a type of `type`, false otherwise
 
16272 is.type = function (value, type) {
 
16273   return typeof value === type;
 
16278  * Test if `value` is defined.
 
16280  * @param {Mixed} value value to test
 
16281  * @return {Boolean} true if 'value' is defined, false otherwise
 
16285 is.defined = function (value) {
 
16286   return value !== undefined;
 
16291  * Test if `value` is empty.
 
16293  * @param {Mixed} value value to test
 
16294  * @return {Boolean} true if `value` is empty, false otherwise
 
16298 is.empty = function (value) {
 
16299   var type = toString.call(value);
 
16302   if ('[object Array]' === type || '[object Arguments]' === type) {
 
16303     return value.length === 0;
 
16306   if ('[object Object]' === type) {
 
16307     for (key in value) if (owns.call(value, key)) return false;
 
16311   if ('[object String]' === type) {
 
16312     return '' === value;
 
16320  * Test if `value` is equal to `other`.
 
16322  * @param {Mixed} value value to test
 
16323  * @param {Mixed} other value to compare with
 
16324  * @return {Boolean} true if `value` is equal to `other`, false otherwise
 
16327 is.equal = function (value, other) {
 
16328   var type = toString.call(value)
 
16331   if (type !== toString.call(other)) {
 
16335   if ('[object Object]' === type) {
 
16336     for (key in value) {
 
16337       if (!is.equal(value[key], other[key])) {
 
16344   if ('[object Array]' === type) {
 
16345     key = value.length;
 
16346     if (key !== other.length) {
 
16350       if (!is.equal(value[key], other[key])) {
 
16357   if ('[object Function]' === type) {
 
16358     return value.prototype === other.prototype;
 
16361   if ('[object Date]' === type) {
 
16362     return value.getTime() === other.getTime();
 
16365   return value === other;
 
16370  * Test if `value` is hosted by `host`.
 
16372  * @param {Mixed} value to test
 
16373  * @param {Mixed} host host to test with
 
16374  * @return {Boolean} true if `value` is hosted by `host`, false otherwise
 
16378 is.hosted = function (value, host) {
 
16379   var type = typeof host[value];
 
16380   return type === 'object' ? !!host[value] : !NON_HOST_TYPES[type];
 
16385  * Test if `value` is an instance of `constructor`.
 
16387  * @param {Mixed} value value to test
 
16388  * @return {Boolean} true if `value` is an instance of `constructor`
 
16392 is.instance = is['instanceof'] = function (value, constructor) {
 
16393   return value instanceof constructor;
 
16398  * Test if `value` is null.
 
16400  * @param {Mixed} value value to test
 
16401  * @return {Boolean} true if `value` is null, false otherwise
 
16405 is['null'] = function (value) {
 
16406   return value === null;
 
16411  * Test if `value` is undefined.
 
16413  * @param {Mixed} value value to test
 
16414  * @return {Boolean} true if `value` is undefined, false otherwise
 
16418 is.undefined = function (value) {
 
16419   return value === undefined;
 
16428  * Test if `value` is an arguments object.
 
16430  * @param {Mixed} value value to test
 
16431  * @return {Boolean} true if `value` is an arguments object, false otherwise
 
16435 is.arguments = function (value) {
 
16436   var isStandardArguments = '[object Arguments]' === toString.call(value);
 
16437   var isOldArguments = !is.array(value) && is.arraylike(value) && is.object(value) && is.fn(value.callee);
 
16438   return isStandardArguments || isOldArguments;
 
16447  * Test if 'value' is an array.
 
16449  * @param {Mixed} value value to test
 
16450  * @return {Boolean} true if `value` is an array, false otherwise
 
16454 is.array = function (value) {
 
16455   return '[object Array]' === toString.call(value);
 
16459  * is.arguments.empty
 
16460  * Test if `value` is an empty arguments object.
 
16462  * @param {Mixed} value value to test
 
16463  * @return {Boolean} true if `value` is an empty arguments object, false otherwise
 
16466 is.arguments.empty = function (value) {
 
16467   return is.arguments(value) && value.length === 0;
 
16472  * Test if `value` is an empty array.
 
16474  * @param {Mixed} value value to test
 
16475  * @return {Boolean} true if `value` is an empty array, false otherwise
 
16478 is.array.empty = function (value) {
 
16479   return is.array(value) && value.length === 0;
 
16484  * Test if `value` is an arraylike object.
 
16486  * @param {Mixed} value value to test
 
16487  * @return {Boolean} true if `value` is an arguments object, false otherwise
 
16491 is.arraylike = function (value) {
 
16492   return !!value && !is.boolean(value)
 
16493     && owns.call(value, 'length')
 
16494     && isFinite(value.length)
 
16495     && is.number(value.length)
 
16496     && value.length >= 0;
 
16505  * Test if `value` is a boolean.
 
16507  * @param {Mixed} value value to test
 
16508  * @return {Boolean} true if `value` is a boolean, false otherwise
 
16512 is.boolean = function (value) {
 
16513   return '[object Boolean]' === toString.call(value);
 
16518  * Test if `value` is false.
 
16520  * @param {Mixed} value value to test
 
16521  * @return {Boolean} true if `value` is false, false otherwise
 
16525 is['false'] = function (value) {
 
16526   return is.boolean(value) && (value === false || value.valueOf() === false);
 
16531  * Test if `value` is true.
 
16533  * @param {Mixed} value value to test
 
16534  * @return {Boolean} true if `value` is true, false otherwise
 
16538 is['true'] = function (value) {
 
16539   return is.boolean(value) && (value === true || value.valueOf() === true);
 
16548  * Test if `value` is a date.
 
16550  * @param {Mixed} value value to test
 
16551  * @return {Boolean} true if `value` is a date, false otherwise
 
16555 is.date = function (value) {
 
16556   return '[object Date]' === toString.call(value);
 
16565  * Test if `value` is an html element.
 
16567  * @param {Mixed} value value to test
 
16568  * @return {Boolean} true if `value` is an HTML Element, false otherwise
 
16572 is.element = function (value) {
 
16573   return value !== undefined
 
16574     && typeof HTMLElement !== 'undefined'
 
16575     && value instanceof HTMLElement
 
16576     && value.nodeType === 1;
 
16585  * Test if `value` is an error object.
 
16587  * @param {Mixed} value value to test
 
16588  * @return {Boolean} true if `value` is an error object, false otherwise
 
16592 is.error = function (value) {
 
16593   return '[object Error]' === toString.call(value);
 
16601  * is.fn / is.function (deprecated)
 
16602  * Test if `value` is a function.
 
16604  * @param {Mixed} value value to test
 
16605  * @return {Boolean} true if `value` is a function, false otherwise
 
16609 is.fn = is['function'] = function (value) {
 
16610   var isAlert = typeof window !== 'undefined' && value === window.alert;
 
16611   return isAlert || '[object Function]' === toString.call(value);
 
16620  * Test if `value` is a number.
 
16622  * @param {Mixed} value value to test
 
16623  * @return {Boolean} true if `value` is a number, false otherwise
 
16627 is.number = function (value) {
 
16628   return '[object Number]' === toString.call(value);
 
16633  * Test if `value` is positive or negative infinity.
 
16635  * @param {Mixed} value value to test
 
16636  * @return {Boolean} true if `value` is positive or negative Infinity, false otherwise
 
16639 is.infinite = function (value) {
 
16640   return value === Infinity || value === -Infinity;
 
16645  * Test if `value` is a decimal number.
 
16647  * @param {Mixed} value value to test
 
16648  * @return {Boolean} true if `value` is a decimal number, false otherwise
 
16652 is.decimal = function (value) {
 
16653   return is.number(value) && !isActualNaN(value) && value % 1 !== 0;
 
16658  * Test if `value` is divisible by `n`.
 
16660  * @param {Number} value value to test
 
16661  * @param {Number} n dividend
 
16662  * @return {Boolean} true if `value` is divisible by `n`, false otherwise
 
16666 is.divisibleBy = function (value, n) {
 
16667   var isDividendInfinite = is.infinite(value);
 
16668   var isDivisorInfinite = is.infinite(n);
 
16669   var isNonZeroNumber = is.number(value) && !isActualNaN(value) && is.number(n) && !isActualNaN(n) && n !== 0;
 
16670   return isDividendInfinite || isDivisorInfinite || (isNonZeroNumber && value % n === 0);
 
16675  * Test if `value` is an integer.
 
16677  * @param value to test
 
16678  * @return {Boolean} true if `value` is an integer, false otherwise
 
16682 is.int = function (value) {
 
16683   return is.number(value) && !isActualNaN(value) && value % 1 === 0;
 
16688  * Test if `value` is greater than 'others' values.
 
16690  * @param {Number} value value to test
 
16691  * @param {Array} others values to compare with
 
16692  * @return {Boolean} true if `value` is greater than `others` values
 
16696 is.maximum = function (value, others) {
 
16697   if (isActualNaN(value)) {
 
16698     throw new TypeError('NaN is not a valid value');
 
16699   } else if (!is.arraylike(others)) {
 
16700     throw new TypeError('second argument must be array-like');
 
16702   var len = others.length;
 
16704   while (--len >= 0) {
 
16705     if (value < others[len]) {
 
16715  * Test if `value` is less than `others` values.
 
16717  * @param {Number} value value to test
 
16718  * @param {Array} others values to compare with
 
16719  * @return {Boolean} true if `value` is less than `others` values
 
16723 is.minimum = function (value, others) {
 
16724   if (isActualNaN(value)) {
 
16725     throw new TypeError('NaN is not a valid value');
 
16726   } else if (!is.arraylike(others)) {
 
16727     throw new TypeError('second argument must be array-like');
 
16729   var len = others.length;
 
16731   while (--len >= 0) {
 
16732     if (value > others[len]) {
 
16742  * Test if `value` is not a number.
 
16744  * @param {Mixed} value value to test
 
16745  * @return {Boolean} true if `value` is not a number, false otherwise
 
16749 is.nan = function (value) {
 
16750   return !is.number(value) || value !== value;
 
16755  * Test if `value` is an even number.
 
16757  * @param {Number} value value to test
 
16758  * @return {Boolean} true if `value` is an even number, false otherwise
 
16762 is.even = function (value) {
 
16763   return is.infinite(value) || (is.number(value) && value === value && value % 2 === 0);
 
16768  * Test if `value` is an odd number.
 
16770  * @param {Number} value value to test
 
16771  * @return {Boolean} true if `value` is an odd number, false otherwise
 
16775 is.odd = function (value) {
 
16776   return is.infinite(value) || (is.number(value) && value === value && value % 2 !== 0);
 
16781  * Test if `value` is greater than or equal to `other`.
 
16783  * @param {Number} value value to test
 
16784  * @param {Number} other value to compare with
 
16785  * @return {Boolean}
 
16789 is.ge = function (value, other) {
 
16790   if (isActualNaN(value) || isActualNaN(other)) {
 
16791     throw new TypeError('NaN is not a valid value');
 
16793   return !is.infinite(value) && !is.infinite(other) && value >= other;
 
16798  * Test if `value` is greater than `other`.
 
16800  * @param {Number} value value to test
 
16801  * @param {Number} other value to compare with
 
16802  * @return {Boolean}
 
16806 is.gt = function (value, other) {
 
16807   if (isActualNaN(value) || isActualNaN(other)) {
 
16808     throw new TypeError('NaN is not a valid value');
 
16810   return !is.infinite(value) && !is.infinite(other) && value > other;
 
16815  * Test if `value` is less than or equal to `other`.
 
16817  * @param {Number} value value to test
 
16818  * @param {Number} other value to compare with
 
16819  * @return {Boolean} if 'value' is less than or equal to 'other'
 
16823 is.le = function (value, other) {
 
16824   if (isActualNaN(value) || isActualNaN(other)) {
 
16825     throw new TypeError('NaN is not a valid value');
 
16827   return !is.infinite(value) && !is.infinite(other) && value <= other;
 
16832  * Test if `value` is less than `other`.
 
16834  * @param {Number} value value to test
 
16835  * @param {Number} other value to compare with
 
16836  * @return {Boolean} if `value` is less than `other`
 
16840 is.lt = function (value, other) {
 
16841   if (isActualNaN(value) || isActualNaN(other)) {
 
16842     throw new TypeError('NaN is not a valid value');
 
16844   return !is.infinite(value) && !is.infinite(other) && value < other;
 
16849  * Test if `value` is within `start` and `finish`.
 
16851  * @param {Number} value value to test
 
16852  * @param {Number} start lower bound
 
16853  * @param {Number} finish upper bound
 
16854  * @return {Boolean} true if 'value' is is within 'start' and 'finish'
 
16857 is.within = function (value, start, finish) {
 
16858   if (isActualNaN(value) || isActualNaN(start) || isActualNaN(finish)) {
 
16859     throw new TypeError('NaN is not a valid value');
 
16860   } else if (!is.number(value) || !is.number(start) || !is.number(finish)) {
 
16861     throw new TypeError('all arguments must be numbers');
 
16863   var isAnyInfinite = is.infinite(value) || is.infinite(start) || is.infinite(finish);
 
16864   return isAnyInfinite || (value >= start && value <= finish);
 
16873  * Test if `value` is an object.
 
16875  * @param {Mixed} value value to test
 
16876  * @return {Boolean} true if `value` is an object, false otherwise
 
16880 is.object = function (value) {
 
16881   return value && '[object Object]' === toString.call(value);
 
16886  * Test if `value` is a hash - a plain object literal.
 
16888  * @param {Mixed} value value to test
 
16889  * @return {Boolean} true if `value` is a hash, false otherwise
 
16893 is.hash = function (value) {
 
16894   return is.object(value) && value.constructor === Object && !value.nodeType && !value.setInterval;
 
16903  * Test if `value` is a regular expression.
 
16905  * @param {Mixed} value value to test
 
16906  * @return {Boolean} true if `value` is a regexp, false otherwise
 
16910 is.regexp = function (value) {
 
16911   return '[object RegExp]' === toString.call(value);
 
16920  * Test if `value` is a string.
 
16922  * @param {Mixed} value value to test
 
16923  * @return {Boolean} true if 'value' is a string, false otherwise
 
16927 is.string = function (value) {
 
16928   return '[object String]' === toString.call(value);
 
16932 },{}],10:[function(require,module,exports){
 
16934 var hasOwn = Object.prototype.hasOwnProperty;
 
16935 var toString = Object.prototype.toString;
 
16937 module.exports = function forEach (obj, fn, ctx) {
 
16938     if (toString.call(fn) !== '[object Function]') {
 
16939         throw new TypeError('iterator must be a function');
 
16941     var l = obj.length;
 
16943         for (var i = 0; i < l; i++) {
 
16944             fn.call(ctx, obj[i], i, obj);
 
16947         for (var k in obj) {
 
16948             if (hasOwn.call(obj, k)) {
 
16949                 fn.call(ctx, obj[k], k, obj);
 
16960  (c) 2015, Vladimir Agafonkin
 
16961  RBush, a JavaScript library for high-performance 2D spatial indexing of points and rectangles.
 
16962  https://github.com/mourner/rbush
 
16968 function rbush(maxEntries, format) {
 
16970     // jshint newcap: false, validthis: true
 
16971     if (!(this instanceof rbush)) return new rbush(maxEntries, format);
 
16973     // max entries in a node is 9 by default; min node fill is 40% for best performance
 
16974     this._maxEntries = Math.max(4, maxEntries || 9);
 
16975     this._minEntries = Math.max(2, Math.ceil(this._maxEntries * 0.4));
 
16978         this._initFormat(format);
 
16984 rbush.prototype = {
 
16987         return this._all(this.data, []);
 
16990     search: function (bbox) {
 
16992         var node = this.data,
 
16994             toBBox = this.toBBox;
 
16996         if (!intersects(bbox, node.bbox)) return result;
 
16998         var nodesToSearch = [],
 
16999             i, len, child, childBBox;
 
17002             for (i = 0, len = node.children.length; i < len; i++) {
 
17004                 child = node.children[i];
 
17005                 childBBox = node.leaf ? toBBox(child) : child.bbox;
 
17007                 if (intersects(bbox, childBBox)) {
 
17008                     if (node.leaf) result.push(child);
 
17009                     else if (contains(bbox, childBBox)) this._all(child, result);
 
17010                     else nodesToSearch.push(child);
 
17013             node = nodesToSearch.pop();
 
17019     collides: function (bbox) {
 
17021         var node = this.data,
 
17022             toBBox = this.toBBox;
 
17024         if (!intersects(bbox, node.bbox)) return false;
 
17026         var nodesToSearch = [],
 
17027             i, len, child, childBBox;
 
17030             for (i = 0, len = node.children.length; i < len; i++) {
 
17032                 child = node.children[i];
 
17033                 childBBox = node.leaf ? toBBox(child) : child.bbox;
 
17035                 if (intersects(bbox, childBBox)) {
 
17036                     if (node.leaf || contains(bbox, childBBox)) return true;
 
17037                     nodesToSearch.push(child);
 
17040             node = nodesToSearch.pop();
 
17046     load: function (data) {
 
17047         if (!(data && data.length)) return this;
 
17049         if (data.length < this._minEntries) {
 
17050             for (var i = 0, len = data.length; i < len; i++) {
 
17051                 this.insert(data[i]);
 
17056         // recursively build the tree with the given data from stratch using OMT algorithm
 
17057         var node = this._build(data.slice(), 0, data.length - 1, 0);
 
17059         if (!this.data.children.length) {
 
17060             // save as is if tree is empty
 
17063         } else if (this.data.height === node.height) {
 
17064             // split root if trees have the same height
 
17065             this._splitRoot(this.data, node);
 
17068             if (this.data.height < node.height) {
 
17069                 // swap trees if inserted one is bigger
 
17070                 var tmpNode = this.data;
 
17075             // insert the small tree into the large tree at appropriate level
 
17076             this._insert(node, this.data.height - node.height - 1, true);
 
17082     insert: function (item) {
 
17083         if (item) this._insert(item, this.data.height - 1);
 
17087     clear: function () {
 
17097     remove: function (item) {
 
17098         if (!item) return this;
 
17100         var node = this.data,
 
17101             bbox = this.toBBox(item),
 
17104             i, parent, index, goingUp;
 
17106         // depth-first iterative tree traversal
 
17107         while (node || path.length) {
 
17109             if (!node) { // go up
 
17111                 parent = path[path.length - 1];
 
17116             if (node.leaf) { // check current node
 
17117                 index = node.children.indexOf(item);
 
17119                 if (index !== -1) {
 
17120                     // item found, remove the item and condense tree upwards
 
17121                     node.children.splice(index, 1);
 
17123                     this._condense(path);
 
17128             if (!goingUp && !node.leaf && contains(node.bbox, bbox)) { // go down
 
17133                 node = node.children[0];
 
17135             } else if (parent) { // go right
 
17137                 node = parent.children[i];
 
17140             } else node = null; // nothing found
 
17146     toBBox: function (item) { return item; },
 
17148     compareMinX: function (a, b) { return a[0] - b[0]; },
 
17149     compareMinY: function (a, b) { return a[1] - b[1]; },
 
17151     toJSON: function () { return this.data; },
 
17153     fromJSON: function (data) {
 
17158     _all: function (node, result) {
 
17159         var nodesToSearch = [];
 
17161             if (node.leaf) result.push.apply(result, node.children);
 
17162             else nodesToSearch.push.apply(nodesToSearch, node.children);
 
17164             node = nodesToSearch.pop();
 
17169     _build: function (items, left, right, height) {
 
17171         var N = right - left + 1,
 
17172             M = this._maxEntries,
 
17176             // reached leaf level; return leaf
 
17178                 children: items.slice(left, right + 1),
 
17183             calcBBox(node, this.toBBox);
 
17188             // target height of the bulk-loaded tree
 
17189             height = Math.ceil(Math.log(N) / Math.log(M));
 
17191             // target number of root entries to maximize storage utilization
 
17192             M = Math.ceil(N / Math.pow(M, height - 1));
 
17202         // split the items into M mostly square tiles
 
17204         var N2 = Math.ceil(N / M),
 
17205             N1 = N2 * Math.ceil(Math.sqrt(M)),
 
17206             i, j, right2, right3;
 
17208         multiSelect(items, left, right, N1, this.compareMinX);
 
17210         for (i = left; i <= right; i += N1) {
 
17212             right2 = Math.min(i + N1 - 1, right);
 
17214             multiSelect(items, i, right2, N2, this.compareMinY);
 
17216             for (j = i; j <= right2; j += N2) {
 
17218                 right3 = Math.min(j + N2 - 1, right2);
 
17220                 // pack each entry recursively
 
17221                 node.children.push(this._build(items, j, right3, height - 1));
 
17225         calcBBox(node, this.toBBox);
 
17230     _chooseSubtree: function (bbox, node, level, path) {
 
17232         var i, len, child, targetNode, area, enlargement, minArea, minEnlargement;
 
17237             if (node.leaf || path.length - 1 === level) break;
 
17239             minArea = minEnlargement = Infinity;
 
17241             for (i = 0, len = node.children.length; i < len; i++) {
 
17242                 child = node.children[i];
 
17243                 area = bboxArea(child.bbox);
 
17244                 enlargement = enlargedArea(bbox, child.bbox) - area;
 
17246                 // choose entry with the least area enlargement
 
17247                 if (enlargement < minEnlargement) {
 
17248                     minEnlargement = enlargement;
 
17249                     minArea = area < minArea ? area : minArea;
 
17250                     targetNode = child;
 
17252                 } else if (enlargement === minEnlargement) {
 
17253                     // otherwise choose one with the smallest area
 
17254                     if (area < minArea) {
 
17256                         targetNode = child;
 
17267     _insert: function (item, level, isNode) {
 
17269         var toBBox = this.toBBox,
 
17270             bbox = isNode ? item.bbox : toBBox(item),
 
17273         // find the best node for accommodating the item, saving all nodes along the path too
 
17274         var node = this._chooseSubtree(bbox, this.data, level, insertPath);
 
17276         // put the item into the node
 
17277         node.children.push(item);
 
17278         extend(node.bbox, bbox);
 
17280         // split on node overflow; propagate upwards if necessary
 
17281         while (level >= 0) {
 
17282             if (insertPath[level].children.length > this._maxEntries) {
 
17283                 this._split(insertPath, level);
 
17288         // adjust bboxes along the insertion path
 
17289         this._adjustParentBBoxes(bbox, insertPath, level);
 
17292     // split overflowed node into two
 
17293     _split: function (insertPath, level) {
 
17295         var node = insertPath[level],
 
17296             M = node.children.length,
 
17297             m = this._minEntries;
 
17299         this._chooseSplitAxis(node, m, M);
 
17301         var splitIndex = this._chooseSplitIndex(node, m, M);
 
17304             children: node.children.splice(splitIndex, node.children.length - splitIndex),
 
17305             height: node.height,
 
17310         if (node.leaf) newNode.leaf = true;
 
17312         calcBBox(node, this.toBBox);
 
17313         calcBBox(newNode, this.toBBox);
 
17315         if (level) insertPath[level - 1].children.push(newNode);
 
17316         else this._splitRoot(node, newNode);
 
17319     _splitRoot: function (node, newNode) {
 
17322             children: [node, newNode],
 
17323             height: node.height + 1,
 
17327         calcBBox(this.data, this.toBBox);
 
17330     _chooseSplitIndex: function (node, m, M) {
 
17332         var i, bbox1, bbox2, overlap, area, minOverlap, minArea, index;
 
17334         minOverlap = minArea = Infinity;
 
17336         for (i = m; i <= M - m; i++) {
 
17337             bbox1 = distBBox(node, 0, i, this.toBBox);
 
17338             bbox2 = distBBox(node, i, M, this.toBBox);
 
17340             overlap = intersectionArea(bbox1, bbox2);
 
17341             area = bboxArea(bbox1) + bboxArea(bbox2);
 
17343             // choose distribution with minimum overlap
 
17344             if (overlap < minOverlap) {
 
17345                 minOverlap = overlap;
 
17348                 minArea = area < minArea ? area : minArea;
 
17350             } else if (overlap === minOverlap) {
 
17351                 // otherwise choose distribution with minimum area
 
17352                 if (area < minArea) {
 
17362     // sorts node children by the best axis for split
 
17363     _chooseSplitAxis: function (node, m, M) {
 
17365         var compareMinX = node.leaf ? this.compareMinX : compareNodeMinX,
 
17366             compareMinY = node.leaf ? this.compareMinY : compareNodeMinY,
 
17367             xMargin = this._allDistMargin(node, m, M, compareMinX),
 
17368             yMargin = this._allDistMargin(node, m, M, compareMinY);
 
17370         // if total distributions margin value is minimal for x, sort by minX,
 
17371         // otherwise it's already sorted by minY
 
17372         if (xMargin < yMargin) node.children.sort(compareMinX);
 
17375     // total margin of all possible split distributions where each node is at least m full
 
17376     _allDistMargin: function (node, m, M, compare) {
 
17378         node.children.sort(compare);
 
17380         var toBBox = this.toBBox,
 
17381             leftBBox = distBBox(node, 0, m, toBBox),
 
17382             rightBBox = distBBox(node, M - m, M, toBBox),
 
17383             margin = bboxMargin(leftBBox) + bboxMargin(rightBBox),
 
17386         for (i = m; i < M - m; i++) {
 
17387             child = node.children[i];
 
17388             extend(leftBBox, node.leaf ? toBBox(child) : child.bbox);
 
17389             margin += bboxMargin(leftBBox);
 
17392         for (i = M - m - 1; i >= m; i--) {
 
17393             child = node.children[i];
 
17394             extend(rightBBox, node.leaf ? toBBox(child) : child.bbox);
 
17395             margin += bboxMargin(rightBBox);
 
17401     _adjustParentBBoxes: function (bbox, path, level) {
 
17402         // adjust bboxes along the given tree path
 
17403         for (var i = level; i >= 0; i--) {
 
17404             extend(path[i].bbox, bbox);
 
17408     _condense: function (path) {
 
17409         // go through the path, removing empty nodes and updating bboxes
 
17410         for (var i = path.length - 1, siblings; i >= 0; i--) {
 
17411             if (path[i].children.length === 0) {
 
17413                     siblings = path[i - 1].children;
 
17414                     siblings.splice(siblings.indexOf(path[i]), 1);
 
17416                 } else this.clear();
 
17418             } else calcBBox(path[i], this.toBBox);
 
17422     _initFormat: function (format) {
 
17423         // data format (minX, minY, maxX, maxY accessors)
 
17425         // uses eval-type function compilation instead of just accepting a toBBox function
 
17426         // because the algorithms are very sensitive to sorting functions performance,
 
17427         // so they should be dead simple and without inner calls
 
17429         // jshint evil: true
 
17431         var compareArr = ['return a', ' - b', ';'];
 
17433         this.compareMinX = new Function('a', 'b', compareArr.join(format[0]));
 
17434         this.compareMinY = new Function('a', 'b', compareArr.join(format[1]));
 
17436         this.toBBox = new Function('a', 'return [a' + format.join(', a') + '];');
 
17441 // calculate node's bbox from bboxes of its children
 
17442 function calcBBox(node, toBBox) {
 
17443     node.bbox = distBBox(node, 0, node.children.length, toBBox);
 
17446 // min bounding rectangle of node children from k to p-1
 
17447 function distBBox(node, k, p, toBBox) {
 
17448     var bbox = empty();
 
17450     for (var i = k, child; i < p; i++) {
 
17451         child = node.children[i];
 
17452         extend(bbox, node.leaf ? toBBox(child) : child.bbox);
 
17458 function empty() { return [Infinity, Infinity, -Infinity, -Infinity]; }
 
17460 function extend(a, b) {
 
17461     a[0] = Math.min(a[0], b[0]);
 
17462     a[1] = Math.min(a[1], b[1]);
 
17463     a[2] = Math.max(a[2], b[2]);
 
17464     a[3] = Math.max(a[3], b[3]);
 
17468 function compareNodeMinX(a, b) { return a.bbox[0] - b.bbox[0]; }
 
17469 function compareNodeMinY(a, b) { return a.bbox[1] - b.bbox[1]; }
 
17471 function bboxArea(a)   { return (a[2] - a[0]) * (a[3] - a[1]); }
 
17472 function bboxMargin(a) { return (a[2] - a[0]) + (a[3] - a[1]); }
 
17474 function enlargedArea(a, b) {
 
17475     return (Math.max(b[2], a[2]) - Math.min(b[0], a[0])) *
 
17476            (Math.max(b[3], a[3]) - Math.min(b[1], a[1]));
 
17479 function intersectionArea(a, b) {
 
17480     var minX = Math.max(a[0], b[0]),
 
17481         minY = Math.max(a[1], b[1]),
 
17482         maxX = Math.min(a[2], b[2]),
 
17483         maxY = Math.min(a[3], b[3]);
 
17485     return Math.max(0, maxX - minX) *
 
17486            Math.max(0, maxY - minY);
 
17489 function contains(a, b) {
 
17490     return a[0] <= b[0] &&
 
17496 function intersects(a, b) {
 
17497     return b[0] <= a[2] &&
 
17503 // sort an array so that items come in groups of n unsorted items, with groups sorted between each other;
 
17504 // combines selection algorithm with binary divide & conquer approach
 
17506 function multiSelect(arr, left, right, n, compare) {
 
17507     var stack = [left, right],
 
17510     while (stack.length) {
 
17511         right = stack.pop();
 
17512         left = stack.pop();
 
17514         if (right - left <= n) continue;
 
17516         mid = left + Math.ceil((right - left) / n / 2) * n;
 
17517         select(arr, left, right, mid, compare);
 
17519         stack.push(left, mid, mid, right);
 
17523 // Floyd-Rivest selection algorithm:
 
17524 // sort an array between left and right (inclusive) so that the smallest k elements come first (unordered)
 
17525 function select(arr, left, right, k, compare) {
 
17526     var n, i, z, s, sd, newLeft, newRight, t, j;
 
17528     while (right > left) {
 
17529         if (right - left > 600) {
 
17530             n = right - left + 1;
 
17533             s = 0.5 * Math.exp(2 * z / 3);
 
17534             sd = 0.5 * Math.sqrt(z * s * (n - s) / n) * (i - n / 2 < 0 ? -1 : 1);
 
17535             newLeft = Math.max(left, Math.floor(k - i * s / n + sd));
 
17536             newRight = Math.min(right, Math.floor(k + (n - i) * s / n + sd));
 
17537             select(arr, newLeft, newRight, k, compare);
 
17544         swap(arr, left, k);
 
17545         if (compare(arr[right], t) > 0) swap(arr, left, right);
 
17551             while (compare(arr[i], t) < 0) i++;
 
17552             while (compare(arr[j], t) > 0) j--;
 
17555         if (compare(arr[left], t) === 0) swap(arr, left, j);
 
17558             swap(arr, j, right);
 
17561         if (j <= k) left = j + 1;
 
17562         if (k <= j) right = j - 1;
 
17566 function swap(arr, i, j) {
 
17573 // export as AMD/CommonJS module or global variable
 
17574 if (typeof define === 'function' && define.amd) define('rbush', function () { return rbush; });
 
17575 else if (typeof module !== 'undefined') module.exports = rbush;
 
17576 else if (typeof self !== 'undefined') self.rbush = rbush;
 
17577 else window.rbush = rbush;
 
17580 (function(e){if("function"==typeof bootstrap)bootstrap("sexagesimal",e);else if("object"==typeof exports)module.exports=e();else if("function"==typeof define&&define.amd)define(e);else if("undefined"!=typeof ses){if(!ses.ok())return;ses.makeSexagesimal=e}else"undefined"!=typeof window?window.sexagesimal=e():global.sexagesimal=e()})(function(){var define,ses,bootstrap,module,exports;
 
17581 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(require,module,exports){
 
17582 module.exports = element;
 
17583 module.exports.pair = pair;
 
17584 module.exports.format = format;
 
17585 module.exports.formatPair = formatPair;
 
17587 function element(x, dims) {
 
17588     return search(x, dims).val;
 
17591 function formatPair(x) {
 
17592     return format(x.lat, 'lat') + ' ' + format(x.lon, 'lon');
 
17595 // Is 0 North or South?
 
17596 function format(x, dim) {
 
17601         dir = dirs[x >= 0 ? 0 : 1],
 
17603         whole = Math.floor(abs),
 
17604         fraction = abs - whole,
 
17605         fractionMinutes = fraction * 60,
 
17606         minutes = Math.floor(fractionMinutes),
 
17607         seconds = Math.floor((fractionMinutes - minutes) * 60);
 
17609     return whole + '° ' +
 
17610         (minutes ? minutes + "' " : '') +
 
17611         (seconds ? seconds + '" ' : '') + dir;
 
17614 function search(x, dims, r) {
 
17615     if (!dims) dims = 'NSEW';
 
17616     if (typeof x !== 'string') return { val: null, regex: r };
 
17617     r = r || /[\s\,]*([\-|\—|\―]?[0-9.]+)°? *(?:([0-9.]+)['’′‘] *)?(?:([0-9.]+)(?:''|"|”|″) *)?([NSEW])?/gi;
 
17619     if (!m) return { val: null, regex: r };
 
17620     else if (m[4] && dims.indexOf(m[4]) === -1) return { val: null, regex: r };
 
17622         val: (((m[1]) ? parseFloat(m[1]) : 0) +
 
17623             ((m[2] ? parseFloat(m[2]) / 60 : 0)) +
 
17624             ((m[3] ? parseFloat(m[3]) / 3600 : 0))) *
 
17625             ((m[4] && m[4] === 'S' || m[4] === 'W') ? -1 : 1),
 
17632 function pair(x, dims) {
 
17634     var one = search(x, dims);
 
17635     if (one.val === null) return null;
 
17636     var two = search(x, dims, one.regex);
 
17637     if (two.val === null) return null;
 
17638     // null if one/two are not contiguous.
 
17639     if (one.raw + two.raw !== x) return null;
 
17640     if (one.dim) return swapdim(one.val, two.val, one.dim);
 
17641     else return [one.val, two.val];
 
17644 function swapdim(a, b, dim) {
 
17645     if (dim == 'N' || dim == 'S') return [a, b];
 
17646     if (dim == 'W' || dim == 'E') return [b, a];
 
17652 ;toGeoJSON = (function() {
 
17655     var removeSpace = (/\s*/g),
 
17656         trimSpace = (/^\s*|\s*$/g),
 
17657         splitSpace = (/\s+/);
 
17658     // generate a short, numeric hash of a string
 
17659     function okhash(x) {
 
17660         if (!x || !x.length) return 0;
 
17661         for (var i = 0, h = 0; i < x.length; i++) {
 
17662             h = ((h << 5) - h) + x.charCodeAt(i) | 0;
 
17665     // all Y children of X
 
17666     function get(x, y) { return x.getElementsByTagName(y); }
 
17667     function attr(x, y) { return x.getAttribute(y); }
 
17668     function attrf(x, y) { return parseFloat(attr(x, y)); }
 
17669     // one Y child of X, if any, otherwise null
 
17670     function get1(x, y) { var n = get(x, y); return n.length ? n[0] : null; }
 
17671     // https://developer.mozilla.org/en-US/docs/Web/API/Node.normalize
 
17672     function norm(el) { if (el.normalize) { el.normalize(); } return el; }
 
17673     // cast array x into numbers
 
17674     function numarray(x) {
 
17675         for (var j = 0, o = []; j < x.length; j++) o[j] = parseFloat(x[j]);
 
17678     function clean(x) {
 
17680         for (var i in x) if (x[i]) o[i] = x[i];
 
17683     // get the content of a text node, if any
 
17684     function nodeVal(x) { if (x) {norm(x);} return x && x.firstChild && x.firstChild.nodeValue; }
 
17685     // get one coordinate from a coordinate array, if any
 
17686     function coord1(v) { return numarray(v.replace(removeSpace, '').split(',')); }
 
17687     // get all coordinates from a coordinate array as [[],[]]
 
17688     function coord(v) {
 
17689         var coords = v.replace(trimSpace, '').split(splitSpace),
 
17691         for (var i = 0; i < coords.length; i++) {
 
17692             o.push(coord1(coords[i]));
 
17696     function coordPair(x) { return [attrf(x, 'lon'), attrf(x, 'lat')]; }
 
17698     // create a new feature collection parent object
 
17701             type: 'FeatureCollection',
 
17706     var styleSupport = false;
 
17707     if (typeof XMLSerializer !== 'undefined') {
 
17708         var serializer = new XMLSerializer();
 
17709         styleSupport = true;
 
17711     function xml2str(str) { return serializer.serializeToString(str); }
 
17714         kml: function(doc, o) {
 
17718                 // styleindex keeps track of hashed styles in order to match features
 
17720                 // atomic geospatial types supported by KML - MultiGeometry is
 
17721                 // handled separately
 
17722                 geotypes = ['Polygon', 'LineString', 'Point', 'Track'],
 
17723                 // all root placemarks in the file
 
17724                 placemarks = get(doc, 'Placemark'),
 
17725                 styles = get(doc, 'Style');
 
17727             if (styleSupport) for (var k = 0; k < styles.length; k++) {
 
17728                 styleIndex['#' + attr(styles[k], 'id')] = okhash(xml2str(styles[k])).toString(16);
 
17730             for (var j = 0; j < placemarks.length; j++) {
 
17731                 gj.features = gj.features.concat(getPlacemark(placemarks[j]));
 
17733             function gxCoord(v) { return numarray(v.split(' ')); }
 
17734             function gxCoords(root) {
 
17735                 var elems = get(root, 'coord', 'gx'), coords = [];
 
17736                 for (var i = 0; i < elems.length; i++) coords.push(gxCoord(nodeVal(elems[i])));
 
17739             function getGeometry(root) {
 
17740                 var geomNode, geomNodes, i, j, k, geoms = [];
 
17741                 if (get1(root, 'MultiGeometry')) return getGeometry(get1(root, 'MultiGeometry'));
 
17742                 if (get1(root, 'MultiTrack')) return getGeometry(get1(root, 'MultiTrack'));
 
17743                 for (i = 0; i < geotypes.length; i++) {
 
17744                     geomNodes = get(root, geotypes[i]);
 
17746                         for (j = 0; j < geomNodes.length; j++) {
 
17747                             geomNode = geomNodes[j];
 
17748                             if (geotypes[i] == 'Point') {
 
17751                                     coordinates: coord1(nodeVal(get1(geomNode, 'coordinates')))
 
17753                             } else if (geotypes[i] == 'LineString') {
 
17755                                     type: 'LineString',
 
17756                                     coordinates: coord(nodeVal(get1(geomNode, 'coordinates')))
 
17758                             } else if (geotypes[i] == 'Polygon') {
 
17759                                 var rings = get(geomNode, 'LinearRing'),
 
17761                                 for (k = 0; k < rings.length; k++) {
 
17762                                     coords.push(coord(nodeVal(get1(rings[k], 'coordinates'))));
 
17766                                     coordinates: coords
 
17768                             } else if (geotypes[i] == 'Track') {
 
17770                                     type: 'LineString',
 
17771                                     coordinates: gxCoords(geomNode)
 
17779             function getPlacemark(root) {
 
17780                 var geoms = getGeometry(root), i, properties = {},
 
17781                     name = nodeVal(get1(root, 'name')),
 
17782                     styleUrl = nodeVal(get1(root, 'styleUrl')),
 
17783                     description = nodeVal(get1(root, 'description')),
 
17784                     extendedData = get1(root, 'ExtendedData');
 
17786                 if (!geoms.length) return [];
 
17787                 if (name) properties.name = name;
 
17788                 if (styleUrl && styleIndex[styleUrl]) {
 
17789                     properties.styleUrl = styleUrl;
 
17790                     properties.styleHash = styleIndex[styleUrl];
 
17792                 if (description) properties.description = description;
 
17793                 if (extendedData) {
 
17794                     var datas = get(extendedData, 'Data'),
 
17795                         simpleDatas = get(extendedData, 'SimpleData');
 
17797                     for (i = 0; i < datas.length; i++) {
 
17798                         properties[datas[i].getAttribute('name')] = nodeVal(get1(datas[i], 'value'));
 
17800                     for (i = 0; i < simpleDatas.length; i++) {
 
17801                         properties[simpleDatas[i].getAttribute('name')] = nodeVal(simpleDatas[i]);
 
17806                     geometry: (geoms.length === 1) ? geoms[0] : {
 
17807                         type: 'GeometryCollection',
 
17810                     properties: properties
 
17815         gpx: function(doc, o) {
 
17817                 tracks = get(doc, 'trk'),
 
17818                 routes = get(doc, 'rte'),
 
17819                 waypoints = get(doc, 'wpt'),
 
17820                 // a feature collection
 
17822             for (i = 0; i < tracks.length; i++) {
 
17823                 gj.features.push(getLinestring(tracks[i], 'trkpt'));
 
17825             for (i = 0; i < routes.length; i++) {
 
17826                 gj.features.push(getLinestring(routes[i], 'rtept'));
 
17828             for (i = 0; i < waypoints.length; i++) {
 
17829                 gj.features.push(getPoint(waypoints[i]));
 
17831             function getLinestring(node, pointname) {
 
17832                 var j, pts = get(node, pointname), line = [];
 
17833                 for (j = 0; j < pts.length; j++) {
 
17834                     line.push(coordPair(pts[j]));
 
17838                     properties: getProperties(node),
 
17840                         type: 'LineString',
 
17845             function getPoint(node) {
 
17846                 var prop = getProperties(node);
 
17847                 prop.ele = nodeVal(get1(node, 'ele'));
 
17848                 prop.sym = nodeVal(get1(node, 'sym'));
 
17854                         coordinates: coordPair(node)
 
17858             function getProperties(node) {
 
17859                 var meta = ['name', 'desc', 'author', 'copyright', 'link',
 
17860                             'time', 'keywords'],
 
17863                 for (k = 0; k < meta.length; k++) {
 
17864                     prop[meta[k]] = nodeVal(get1(node, meta[k]));
 
17866                 return clean(prop);
 
17874 if (typeof module !== 'undefined') module.exports = toGeoJSON;
 
17876  * marked - a markdown parser
 
17877  * Copyright (c) 2011-2013, Christopher Jeffrey. (MIT Licensed)
 
17878  * https://github.com/chjj/marked
 
17884  * Block-Level Grammar
 
17889   code: /^( {4}[^\n]+\n*)+/,
 
17891   hr: /^( *[-*_]){3,} *(?:\n+|$)/,
 
17892   heading: /^ *(#{1,6}) *([^\n]+?) *#* *(?:\n+|$)/,
 
17894   lheading: /^([^\n]+)\n *(=|-){3,} *\n*/,
 
17895   blockquote: /^( *>[^\n]+(\n[^\n]+)*\n*)+/,
 
17896   list: /^( *)(bull) [\s\S]+?(?:hr|\n{2,}(?! )(?!\1bull )\n*|\s*$)/,
 
17897   html: /^ *(?:comment|closed|closing) *(?:\n{2,}|\s*$)/,
 
17898   def: /^ *\[([^\]]+)\]: *<?([^\s>]+)>?(?: +["(]([^\n]+)[")])? *(?:\n+|$)/,
 
17900   paragraph: /^((?:[^\n]+\n?(?!hr|heading|lheading|blockquote|tag|def))+)\n*/,
 
17904 block.bullet = /(?:[*+-]|\d+\.)/;
 
17905 block.item = /^( *)(bull) [^\n]*(?:\n(?!\1bull )[^\n]*)*/;
 
17906 block.item = replace(block.item, 'gm')
 
17907   (/bull/g, block.bullet)
 
17910 block.list = replace(block.list)
 
17911   (/bull/g, block.bullet)
 
17912   ('hr', /\n+(?=(?: *[-*_]){3,} *(?:\n+|$))/)
 
17915 block._tag = '(?!(?:'
 
17916   + 'a|em|strong|small|s|cite|q|dfn|abbr|data|time|code'
 
17917   + '|var|samp|kbd|sub|sup|i|b|u|mark|ruby|rt|rp|bdi|bdo'
 
17918   + '|span|br|wbr|ins|del|img)\\b)\\w+(?!:/|@)\\b';
 
17920 block.html = replace(block.html)
 
17921   ('comment', /<!--[\s\S]*?-->/)
 
17922   ('closed', /<(tag)[\s\S]+?<\/\1>/)
 
17923   ('closing', /<tag(?:"[^"]*"|'[^']*'|[^'">])*?>/)
 
17924   (/tag/g, block._tag)
 
17927 block.paragraph = replace(block.paragraph)
 
17929   ('heading', block.heading)
 
17930   ('lheading', block.lheading)
 
17931   ('blockquote', block.blockquote)
 
17932   ('tag', '<' + block._tag)
 
17937  * Normal Block Grammar
 
17940 block.normal = merge({}, block);
 
17943  * GFM Block Grammar
 
17946 block.gfm = merge({}, block.normal, {
 
17947   fences: /^ *(`{3,}|~{3,}) *(\S+)? *\n([\s\S]+?)\s*\1 *(?:\n+|$)/,
 
17951 block.gfm.paragraph = replace(block.paragraph)
 
17952   ('(?!', '(?!' + block.gfm.fences.source.replace('\\1', '\\2') + '|')
 
17956  * GFM + Tables Block Grammar
 
17959 block.tables = merge({}, block.gfm, {
 
17960   nptable: /^ *(\S.*\|.*)\n *([-:]+ *\|[-| :]*)\n((?:.*\|.*(?:\n|$))*)\n*/,
 
17961   table: /^ *\|(.+)\n *\|( *[-:]+[-| :]*)\n((?: *\|.*(?:\n|$))*)\n*/
 
17968 function Lexer(options) {
 
17970   this.tokens.links = {};
 
17971   this.options = options || marked.defaults;
 
17972   this.rules = block.normal;
 
17974   if (this.options.gfm) {
 
17975     if (this.options.tables) {
 
17976       this.rules = block.tables;
 
17978       this.rules = block.gfm;
 
17984  * Expose Block Rules
 
17987 Lexer.rules = block;
 
17990  * Static Lex Method
 
17993 Lexer.lex = function(src, options) {
 
17994   var lexer = new Lexer(options);
 
17995   return lexer.lex(src);
 
18002 Lexer.prototype.lex = function(src) {
 
18004     .replace(/\r\n|\r/g, '\n')
 
18005     .replace(/\t/g, '    ')
 
18006     .replace(/\u00a0/g, ' ')
 
18007     .replace(/\u2424/g, '\n');
 
18009   return this.token(src, true);
 
18016 Lexer.prototype.token = function(src, top) {
 
18017   var src = src.replace(/^ +$/gm, '')
 
18030     if (cap = this.rules.newline.exec(src)) {
 
18031       src = src.substring(cap[0].length);
 
18032       if (cap[0].length > 1) {
 
18040     if (cap = this.rules.code.exec(src)) {
 
18041       src = src.substring(cap[0].length);
 
18042       cap = cap[0].replace(/^ {4}/gm, '');
 
18045         text: !this.options.pedantic
 
18046           ? cap.replace(/\n+$/, '')
 
18053     if (cap = this.rules.fences.exec(src)) {
 
18054       src = src.substring(cap[0].length);
 
18064     if (cap = this.rules.heading.exec(src)) {
 
18065       src = src.substring(cap[0].length);
 
18068         depth: cap[1].length,
 
18074     // table no leading pipe (gfm)
 
18075     if (top && (cap = this.rules.nptable.exec(src))) {
 
18076       src = src.substring(cap[0].length);
 
18080         header: cap[1].replace(/^ *| *\| *$/g, '').split(/ *\| */),
 
18081         align: cap[2].replace(/^ *|\| *$/g, '').split(/ *\| */),
 
18082         cells: cap[3].replace(/\n$/, '').split('\n')
 
18085       for (i = 0; i < item.align.length; i++) {
 
18086         if (/^ *-+: *$/.test(item.align[i])) {
 
18087           item.align[i] = 'right';
 
18088         } else if (/^ *:-+: *$/.test(item.align[i])) {
 
18089           item.align[i] = 'center';
 
18090         } else if (/^ *:-+ *$/.test(item.align[i])) {
 
18091           item.align[i] = 'left';
 
18093           item.align[i] = null;
 
18097       for (i = 0; i < item.cells.length; i++) {
 
18098         item.cells[i] = item.cells[i].split(/ *\| */);
 
18101       this.tokens.push(item);
 
18107     if (cap = this.rules.lheading.exec(src)) {
 
18108       src = src.substring(cap[0].length);
 
18111         depth: cap[2] === '=' ? 1 : 2,
 
18118     if (cap = this.rules.hr.exec(src)) {
 
18119       src = src.substring(cap[0].length);
 
18127     if (cap = this.rules.blockquote.exec(src)) {
 
18128       src = src.substring(cap[0].length);
 
18131         type: 'blockquote_start'
 
18134       cap = cap[0].replace(/^ *> ?/gm, '');
 
18136       // Pass `top` to keep the current
 
18137       // "toplevel" state. This is exactly
 
18138       // how markdown.pl works.
 
18139       this.token(cap, top);
 
18142         type: 'blockquote_end'
 
18149     if (cap = this.rules.list.exec(src)) {
 
18150       src = src.substring(cap[0].length);
 
18154         type: 'list_start',
 
18155         ordered: bull.length > 1
 
18158       // Get each top-level item.
 
18159       cap = cap[0].match(this.rules.item);
 
18165       for (; i < l; i++) {
 
18168         // Remove the list item's bullet
 
18169         // so it is seen as the next token.
 
18170         space = item.length;
 
18171         item = item.replace(/^ *([*+-]|\d+\.) +/, '');
 
18173         // Outdent whatever the
 
18174         // list item contains. Hacky.
 
18175         if (~item.indexOf('\n ')) {
 
18176           space -= item.length;
 
18177           item = !this.options.pedantic
 
18178             ? item.replace(new RegExp('^ {1,' + space + '}', 'gm'), '')
 
18179             : item.replace(/^ {1,4}/gm, '');
 
18182         // Determine whether the next list item belongs here.
 
18183         // Backpedal if it does not belong in this list.
 
18184         if (this.options.smartLists && i !== l - 1) {
 
18185           b = block.bullet.exec(cap[i+1])[0];
 
18186           if (bull !== b && !(bull.length > 1 && b.length > 1)) {
 
18187             src = cap.slice(i + 1).join('\n') + src;
 
18192         // Determine whether item is loose or not.
 
18193         // Use: /(^|\n)(?! )[^\n]+\n\n(?!\s*$)/
 
18194         // for discount behavior.
 
18195         loose = next || /\n\n(?!\s*$)/.test(item);
 
18197           next = item[item.length-1] === '\n';
 
18198           if (!loose) loose = next;
 
18203             ? 'loose_item_start'
 
18204             : 'list_item_start'
 
18208         this.token(item, false);
 
18211           type: 'list_item_end'
 
18223     if (cap = this.rules.html.exec(src)) {
 
18224       src = src.substring(cap[0].length);
 
18226         type: this.options.sanitize
 
18229         pre: cap[1] === 'pre' || cap[1] === 'script',
 
18236     if (top && (cap = this.rules.def.exec(src))) {
 
18237       src = src.substring(cap[0].length);
 
18238       this.tokens.links[cap[1].toLowerCase()] = {
 
18246     if (top && (cap = this.rules.table.exec(src))) {
 
18247       src = src.substring(cap[0].length);
 
18251         header: cap[1].replace(/^ *| *\| *$/g, '').split(/ *\| */),
 
18252         align: cap[2].replace(/^ *|\| *$/g, '').split(/ *\| */),
 
18253         cells: cap[3].replace(/(?: *\| *)?\n$/, '').split('\n')
 
18256       for (i = 0; i < item.align.length; i++) {
 
18257         if (/^ *-+: *$/.test(item.align[i])) {
 
18258           item.align[i] = 'right';
 
18259         } else if (/^ *:-+: *$/.test(item.align[i])) {
 
18260           item.align[i] = 'center';
 
18261         } else if (/^ *:-+ *$/.test(item.align[i])) {
 
18262           item.align[i] = 'left';
 
18264           item.align[i] = null;
 
18268       for (i = 0; i < item.cells.length; i++) {
 
18269         item.cells[i] = item.cells[i]
 
18270           .replace(/^ *\| *| *\| *$/g, '')
 
18274       this.tokens.push(item);
 
18279     // top-level paragraph
 
18280     if (top && (cap = this.rules.paragraph.exec(src))) {
 
18281       src = src.substring(cap[0].length);
 
18284         text: cap[1][cap[1].length-1] === '\n'
 
18285           ? cap[1].slice(0, -1)
 
18292     if (cap = this.rules.text.exec(src)) {
 
18293       // Top-level should never reach here.
 
18294       src = src.substring(cap[0].length);
 
18304         Error('Infinite loop on byte: ' + src.charCodeAt(0));
 
18308   return this.tokens;
 
18312  * Inline-Level Grammar
 
18316   escape: /^\\([\\`*{}\[\]()#+\-.!_>])/,
 
18317   autolink: /^<([^ >]+(@|:\/)[^ >]+)>/,
 
18319   tag: /^<!--[\s\S]*?-->|^<\/?\w+(?:"[^"]*"|'[^']*'|[^'">])*?>/,
 
18320   link: /^!?\[(inside)\]\(href\)/,
 
18321   reflink: /^!?\[(inside)\]\s*\[([^\]]*)\]/,
 
18322   nolink: /^!?\[((?:\[[^\]]*\]|[^\[\]])*)\]/,
 
18323   strong: /^__([\s\S]+?)__(?!_)|^\*\*([\s\S]+?)\*\*(?!\*)/,
 
18324   em: /^\b_((?:__|[\s\S])+?)_\b|^\*((?:\*\*|[\s\S])+?)\*(?!\*)/,
 
18325   code: /^(`+)\s*([\s\S]*?[^`])\s*\1(?!`)/,
 
18326   br: /^ {2,}\n(?!\s*$)/,
 
18328   text: /^[\s\S]+?(?=[\\<!\[_*`]| {2,}\n|$)/
 
18331 inline._inside = /(?:\[[^\]]*\]|[^\]]|\](?=[^\[]*\]))*/;
 
18332 inline._href = /\s*<?([^\s]*?)>?(?:\s+['"]([\s\S]*?)['"])?\s*/;
 
18334 inline.link = replace(inline.link)
 
18335   ('inside', inline._inside)
 
18336   ('href', inline._href)
 
18339 inline.reflink = replace(inline.reflink)
 
18340   ('inside', inline._inside)
 
18344  * Normal Inline Grammar
 
18347 inline.normal = merge({}, inline);
 
18350  * Pedantic Inline Grammar
 
18353 inline.pedantic = merge({}, inline.normal, {
 
18354   strong: /^__(?=\S)([\s\S]*?\S)__(?!_)|^\*\*(?=\S)([\s\S]*?\S)\*\*(?!\*)/,
 
18355   em: /^_(?=\S)([\s\S]*?\S)_(?!_)|^\*(?=\S)([\s\S]*?\S)\*(?!\*)/
 
18359  * GFM Inline Grammar
 
18362 inline.gfm = merge({}, inline.normal, {
 
18363   escape: replace(inline.escape)('])', '~|])')(),
 
18364   url: /^(https?:\/\/[^\s<]+[^<.,:;"')\]\s])/,
 
18365   del: /^~~(?=\S)([\s\S]*?\S)~~/,
 
18366   text: replace(inline.text)
 
18368     ('|', '|https?://|')
 
18373  * GFM + Line Breaks Inline Grammar
 
18376 inline.breaks = merge({}, inline.gfm, {
 
18377   br: replace(inline.br)('{2,}', '*')(),
 
18378   text: replace(inline.gfm.text)('{2,}', '*')()
 
18382  * Inline Lexer & Compiler
 
18385 function InlineLexer(links, options) {
 
18386   this.options = options || marked.defaults;
 
18387   this.links = links;
 
18388   this.rules = inline.normal;
 
18392       Error('Tokens array requires a `links` property.');
 
18395   if (this.options.gfm) {
 
18396     if (this.options.breaks) {
 
18397       this.rules = inline.breaks;
 
18399       this.rules = inline.gfm;
 
18401   } else if (this.options.pedantic) {
 
18402     this.rules = inline.pedantic;
 
18407  * Expose Inline Rules
 
18410 InlineLexer.rules = inline;
 
18413  * Static Lexing/Compiling Method
 
18416 InlineLexer.output = function(src, links, options) {
 
18417   var inline = new InlineLexer(links, options);
 
18418   return inline.output(src);
 
18425 InlineLexer.prototype.output = function(src) {
 
18434     if (cap = this.rules.escape.exec(src)) {
 
18435       src = src.substring(cap[0].length);
 
18441     if (cap = this.rules.autolink.exec(src)) {
 
18442       src = src.substring(cap[0].length);
 
18443       if (cap[2] === '@') {
 
18444         text = cap[1][6] === ':'
 
18445           ? this.mangle(cap[1].substring(7))
 
18446           : this.mangle(cap[1]);
 
18447         href = this.mangle('mailto:') + text;
 
18449         text = escape(cap[1]);
 
18461     if (cap = this.rules.url.exec(src)) {
 
18462       src = src.substring(cap[0].length);
 
18463       text = escape(cap[1]);
 
18474     if (cap = this.rules.tag.exec(src)) {
 
18475       src = src.substring(cap[0].length);
 
18476       out += this.options.sanitize
 
18483     if (cap = this.rules.link.exec(src)) {
 
18484       src = src.substring(cap[0].length);
 
18485       out += this.outputLink(cap, {
 
18493     if ((cap = this.rules.reflink.exec(src))
 
18494         || (cap = this.rules.nolink.exec(src))) {
 
18495       src = src.substring(cap[0].length);
 
18496       link = (cap[2] || cap[1]).replace(/\s+/g, ' ');
 
18497       link = this.links[link.toLowerCase()];
 
18498       if (!link || !link.href) {
 
18500         src = cap[0].substring(1) + src;
 
18503       out += this.outputLink(cap, link);
 
18508     if (cap = this.rules.strong.exec(src)) {
 
18509       src = src.substring(cap[0].length);
 
18511         + this.output(cap[2] || cap[1])
 
18517     if (cap = this.rules.em.exec(src)) {
 
18518       src = src.substring(cap[0].length);
 
18520         + this.output(cap[2] || cap[1])
 
18526     if (cap = this.rules.code.exec(src)) {
 
18527       src = src.substring(cap[0].length);
 
18529         + escape(cap[2], true)
 
18535     if (cap = this.rules.br.exec(src)) {
 
18536       src = src.substring(cap[0].length);
 
18542     if (cap = this.rules.del.exec(src)) {
 
18543       src = src.substring(cap[0].length);
 
18545         + this.output(cap[1])
 
18551     if (cap = this.rules.text.exec(src)) {
 
18552       src = src.substring(cap[0].length);
 
18553       out += escape(cap[0]);
 
18559         Error('Infinite loop on byte: ' + src.charCodeAt(0));
 
18570 InlineLexer.prototype.outputLink = function(cap, link) {
 
18571   if (cap[0][0] !== '!') {
 
18573       + escape(link.href)
 
18577       + escape(link.title)
 
18581       + this.output(cap[1])
 
18584     return '<img src="'
 
18585       + escape(link.href)
 
18591       + escape(link.title)
 
18599  * Smartypants Transformations
 
18602 InlineLexer.prototype.smartypants = function(text) {
 
18603   if (!this.options.smartypants) return text;
 
18605     .replace(/--/g, '—')
 
18606     .replace(/'([^']*)'/g, '‘$1’')
 
18607     .replace(/"([^"]*)"/g, '“$1”')
 
18608     .replace(/\.{3}/g, '…');
 
18615 InlineLexer.prototype.mangle = function(text) {
 
18621   for (; i < l; i++) {
 
18622     ch = text.charCodeAt(i);
 
18623     if (Math.random() > 0.5) {
 
18624       ch = 'x' + ch.toString(16);
 
18626     out += '&#' + ch + ';';
 
18633  * Parsing & Compiling
 
18636 function Parser(options) {
 
18639   this.options = options || marked.defaults;
 
18643  * Static Parse Method
 
18646 Parser.parse = function(src, options) {
 
18647   var parser = new Parser(options);
 
18648   return parser.parse(src);
 
18655 Parser.prototype.parse = function(src) {
 
18656   this.inline = new InlineLexer(src.links, this.options);
 
18657   this.tokens = src.reverse();
 
18660   while (this.next()) {
 
18671 Parser.prototype.next = function() {
 
18672   return this.token = this.tokens.pop();
 
18676  * Preview Next Token
 
18679 Parser.prototype.peek = function() {
 
18680   return this.tokens[this.tokens.length-1] || 0;
 
18684  * Parse Text Tokens
 
18687 Parser.prototype.parseText = function() {
 
18688   var body = this.token.text;
 
18690   while (this.peek().type === 'text') {
 
18691     body += '\n' + this.next().text;
 
18694   return this.inline.output(body);
 
18698  * Parse Current Token
 
18701 Parser.prototype.tok = function() {
 
18702   switch (this.token.type) {
 
18713         + this.inline.output(this.token.text)
 
18719       if (this.options.highlight) {
 
18720         var code = this.options.highlight(this.token.text, this.token.lang);
 
18721         if (code != null && code !== this.token.text) {
 
18722           this.token.escaped = true;
 
18723           this.token.text = code;
 
18727       if (!this.token.escaped) {
 
18728         this.token.text = escape(this.token.text, true);
 
18731       return '<pre><code'
 
18734         + this.options.langPrefix
 
18740         + '</code></pre>\n';
 
18751       body += '<thead>\n<tr>\n';
 
18752       for (i = 0; i < this.token.header.length; i++) {
 
18753         heading = this.inline.output(this.token.header[i]);
 
18754         body += this.token.align[i]
 
18755           ? '<th align="' + this.token.align[i] + '">' + heading + '</th>\n'
 
18756           : '<th>' + heading + '</th>\n';
 
18758       body += '</tr>\n</thead>\n';
 
18761       body += '<tbody>\n'
 
18762       for (i = 0; i < this.token.cells.length; i++) {
 
18763         row = this.token.cells[i];
 
18765         for (j = 0; j < row.length; j++) {
 
18766           cell = this.inline.output(row[j]);
 
18767           body += this.token.align[j]
 
18768             ? '<td align="' + this.token.align[j] + '">' + cell + '</td>\n'
 
18769             : '<td>' + cell + '</td>\n';
 
18773       body += '</tbody>\n';
 
18779     case 'blockquote_start': {
 
18782       while (this.next().type !== 'blockquote_end') {
 
18783         body += this.tok();
 
18786       return '<blockquote>\n'
 
18788         + '</blockquote>\n';
 
18790     case 'list_start': {
 
18791       var type = this.token.ordered ? 'ol' : 'ul'
 
18794       while (this.next().type !== 'list_end') {
 
18795         body += this.tok();
 
18806     case 'list_item_start': {
 
18809       while (this.next().type !== 'list_item_end') {
 
18810         body += this.token.type === 'text'
 
18819     case 'loose_item_start': {
 
18822       while (this.next().type !== 'list_item_end') {
 
18823         body += this.tok();
 
18831       return !this.token.pre && !this.options.pedantic
 
18832         ? this.inline.output(this.token.text)
 
18835     case 'paragraph': {
 
18837         + this.inline.output(this.token.text)
 
18852 function escape(html, encode) {
 
18854     .replace(!encode ? /&(?!#?\w+;)/g : /&/g, '&')
 
18855     .replace(/</g, '<')
 
18856     .replace(/>/g, '>')
 
18857     .replace(/"/g, '"')
 
18858     .replace(/'/g, ''');
 
18861 function replace(regex, opt) {
 
18862   regex = regex.source;
 
18864   return function self(name, val) {
 
18865     if (!name) return new RegExp(regex, opt);
 
18866     val = val.source || val;
 
18867     val = val.replace(/(^|[^\[])\^/g, '$1');
 
18868     regex = regex.replace(name, val);
 
18876 function merge(obj) {
 
18881   for (; i < arguments.length; i++) {
 
18882     target = arguments[i];
 
18883     for (key in target) {
 
18884       if (Object.prototype.hasOwnProperty.call(target, key)) {
 
18885         obj[key] = target[key];
 
18897 function marked(src, opt, callback) {
 
18898   if (callback || typeof opt === 'function') {
 
18904     if (opt) opt = merge({}, marked.defaults, opt);
 
18906     var tokens = Lexer.lex(tokens, opt)
 
18907       , highlight = opt.highlight
 
18909       , l = tokens.length
 
18912     if (!highlight || highlight.length < 3) {
 
18913       return callback(null, Parser.parse(tokens, opt));
 
18916     var done = function() {
 
18917       delete opt.highlight;
 
18918       var out = Parser.parse(tokens, opt);
 
18919       opt.highlight = highlight;
 
18920       return callback(null, out);
 
18923     for (; i < l; i++) {
 
18925         if (token.type !== 'code') return;
 
18927         return highlight(token.text, token.lang, function(err, code) {
 
18928           if (code == null || code === token.text) {
 
18929             return --pending || done();
 
18932           token.escaped = true;
 
18933           --pending || done();
 
18941     if (opt) opt = merge({}, marked.defaults, opt);
 
18942     return Parser.parse(Lexer.lex(src, opt), opt);
 
18944     e.message += '\nPlease report this to https://github.com/chjj/marked.';
 
18945     if ((opt || marked.defaults).silent) {
 
18946       return '<p>An error occured:</p><pre>'
 
18947         + escape(e.message + '', true)
 
18959 marked.setOptions = function(opt) {
 
18960   merge(marked.defaults, opt);
 
18964 marked.defaults = {
 
18973   langPrefix: 'lang-'
 
18980 marked.Parser = Parser;
 
18981 marked.parser = Parser.parse;
 
18983 marked.Lexer = Lexer;
 
18984 marked.lexer = Lexer.lex;
 
18986 marked.InlineLexer = InlineLexer;
 
18987 marked.inlineLexer = InlineLexer.output;
 
18989 marked.parse = marked;
 
18991 if (typeof exports === 'object') {
 
18992   module.exports = marked;
 
18993 } else if (typeof define === 'function' && define.amd) {
 
18994   define(function() { return marked; });
 
18996   this.marked = marked;
 
18999 }).call(function() {
 
19000   return this || (typeof window !== 'undefined' ? window : global);
 
19004 window.iD = function () {
 
19005     window.locale.en = iD.data.en;
 
19006     window.locale.current('en');
 
19008     var dispatch = d3.dispatch('enter', 'exit'),
 
19011     // https://github.com/openstreetmap/iD/issues/772
 
19012     // http://mathiasbynens.be/notes/localstorage-pattern#comment-9
 
19014     try { storage = localStorage; } catch (e) {}  // eslint-disable-line no-empty
 
19015     storage = storage || (function() {
 
19018             getItem: function(k) { return s[k]; },
 
19019             setItem: function(k, v) { s[k] = v; },
 
19020             removeItem: function(k) { delete s[k]; }
 
19024     context.storage = function(k, v) {
 
19026             if (arguments.length === 1) return storage.getItem(k);
 
19027             else if (v === null) storage.removeItem(k);
 
19028             else storage.setItem(k, v);
 
19030             // localstorage quota exceeded
 
19031             /* eslint-disable no-console */
 
19032             if (typeof console !== 'undefined') console.error('localStorage quota exceeded');
 
19033             /* eslint-enable no-console */
 
19038     /* Straight accessors. Avoid using these if you can. */
 
19039     var ui, connection, history;
 
19040     context.ui = function() { return ui; };
 
19041     context.connection = function() { return connection; };
 
19042     context.history = function() { return history; };
 
19046     function entitiesLoaded(err, result) {
 
19047         if (!err) history.merge(result.data, result.extent);
 
19050     context.preauth = function(options) {
 
19051         connection.switch(options);
 
19055     context.loadTiles = function(projection, dimensions, callback) {
 
19056         function done(err, result) {
 
19057             entitiesLoaded(err, result);
 
19058             if (callback) callback(err, result);
 
19060         connection.loadTiles(projection, dimensions, done);
 
19063     context.loadEntity = function(id, callback) {
 
19064         function done(err, result) {
 
19065             entitiesLoaded(err, result);
 
19066             if (callback) callback(err, result);
 
19068         connection.loadEntity(id, done);
 
19071     context.zoomToEntity = function(id, zoomTo) {
 
19072         if (zoomTo !== false) {
 
19073             this.loadEntity(id, function(err, result) {
 
19075                 var entity = _.find(result.data, function(e) { return e.id === id; });
 
19076                 if (entity) { map.zoomTo(entity); }
 
19080         map.on('drawn.zoomToEntity', function() {
 
19081             if (!context.hasEntity(id)) return;
 
19082             map.on('drawn.zoomToEntity', null);
 
19083             context.on('enter.zoomToEntity', null);
 
19084             context.enter(iD.modes.Select(context, [id]));
 
19087         context.on('enter.zoomToEntity', function() {
 
19088             if (mode.id !== 'browse') {
 
19089                 map.on('drawn.zoomToEntity', null);
 
19090                 context.on('enter.zoomToEntity', null);
 
19095     var minEditableZoom = 16;
 
19096     context.minEditableZoom = function(_) {
 
19097         if (!arguments.length) return minEditableZoom;
 
19098         minEditableZoom = _;
 
19099         connection.tileZoom(_);
 
19105     var inIntro = false;
 
19106     context.inIntro = function(_) {
 
19107         if (!arguments.length) return inIntro;
 
19112     context.save = function() {
 
19113         if (inIntro || (mode && mode.id === 'save')) return;
 
19115         if (history.hasChanges()) return t('save.unsaved_changes');
 
19118     context.flush = function() {
 
19119         context.debouncedSave.cancel();
 
19120         connection.flush();
 
19123         _.each(iD.services, function(service) {
 
19124             var reset = service().reset;
 
19125             if (reset) reset(context);
 
19132     context.hasEntity = function(id) {
 
19133         return history.graph().hasEntity(id);
 
19135     context.entity = function(id) {
 
19136         return history.graph().entity(id);
 
19138     context.childNodes = function(way) {
 
19139         return history.graph().childNodes(way);
 
19141     context.geometry = function(id) {
 
19142         return context.entity(id).geometry(history.graph());
 
19148     context.mode = function() {
 
19151     context.enter = function(newMode) {
 
19154             dispatch.exit(mode);
 
19159         dispatch.enter(mode);
 
19162     context.selectedIDs = function() {
 
19163         if (mode && mode.selectedIDs) {
 
19164             return mode.selectedIDs();
 
19172     context.install = function(behavior) {
 
19173         context.surface().call(behavior);
 
19175     context.uninstall = function(behavior) {
 
19176         context.surface().call(behavior.off);
 
19181     var copyIDs = [], copyGraph;
 
19182     context.copyGraph = function() { return copyGraph; };
 
19183     context.copyIDs = function(_) {
 
19184         if (!arguments.length) return copyIDs;
 
19186         copyGraph = history.graph();
 
19193     context.background = function() { return background; };
 
19198     context.features = function() { return features; };
 
19199     context.hasHiddenConnections = function(id) {
 
19200         var graph = history.graph(),
 
19201             entity = graph.entity(id);
 
19202         return features.hasHiddenConnections(entity, graph);
 
19208     context.map = function() { return map; };
 
19209     context.layers = function() { return map.layers; };
 
19210     context.surface = function() { return map.surface; };
 
19211     context.editable = function() { return map.editable(); };
 
19213     context.surfaceRect = function() {
 
19214         // Work around a bug in Firefox.
 
19215         //   http://stackoverflow.com/questions/18153989/
 
19216         //   https://bugzilla.mozilla.org/show_bug.cgi?id=530985
 
19217         return context.surface().node().parentNode.getBoundingClientRect();
 
19223     context.presets = function(_) {
 
19224         if (!arguments.length) return presets;
 
19226         iD.areaKeys = presets.areaKeys();
 
19232     context.imagery = function(_) {
 
19233         background.load(_);
 
19239     var container, embed;
 
19240     context.container = function(_) {
 
19241         if (!arguments.length) return container;
 
19243         container.classed('id-container', true);
 
19246     context.embed = function(_) {
 
19247         if (!arguments.length) return embed;
 
19255     context.taginfo = function(_) {
 
19256         if (!arguments.length) return taginfo;
 
19263     var assetPath = '';
 
19264     context.assetPath = function(_) {
 
19265         if (!arguments.length) return assetPath;
 
19271     context.assetMap = function(_) {
 
19272         if (!arguments.length) return assetMap;
 
19277     context.asset = function(_) {
 
19278         var filename = assetPath + _;
 
19279         return assetMap[filename] || filename;
 
19282     context.imagePath = function(_) {
 
19283         return context.asset('img/' + _);
 
19286     var locale, localePath;
 
19287     context.locale = function(loc, path) {
 
19291         // Also set iD.detect().locale (unless we detected 'en-us' and openstreetmap wants 'en')..
 
19292         if (!(loc.toLowerCase() === 'en' && iD.detect().locale.toLowerCase() === 'en-us')) {
 
19293             iD.detect().locale = loc;
 
19299     context.loadLocale = function(cb) {
 
19300         if (locale && locale !== 'en' && iD.data.locales.indexOf(locale) !== -1) {
 
19301             localePath = localePath || context.asset('locales/' + locale + '.json');
 
19302             d3.json(localePath, function(err, result) {
 
19303                 window.locale[locale] = result;
 
19304                 window.locale.current(locale);
 
19315     context.projection = iD.geo.RawMercator();
 
19317     locale = iD.detect().locale;
 
19318     if (locale && iD.data.locales.indexOf(locale) === -1) {
 
19319         locale = locale.split('-')[0];
 
19322     history = iD.History(context);
 
19323     context.graph = history.graph;
 
19324     context.changes = history.changes;
 
19325     context.intersects = history.intersects;
 
19327     // Debounce save, since it's a synchronous localStorage write,
 
19328     // and history changes can happen frequently (e.g. when dragging).
 
19329     context.debouncedSave = _.debounce(context.save, 350);
 
19330     function withDebouncedSave(fn) {
 
19331         return function() {
 
19332             var result = fn.apply(history, arguments);
 
19333             context.debouncedSave();
 
19338     context.perform = withDebouncedSave(history.perform);
 
19339     context.replace = withDebouncedSave(history.replace);
 
19340     context.pop = withDebouncedSave(history.pop);
 
19341     context.overwrite = withDebouncedSave(history.overwrite);
 
19342     context.undo = withDebouncedSave(history.undo);
 
19343     context.redo = withDebouncedSave(history.redo);
 
19345     ui = iD.ui(context);
 
19347     connection = iD.Connection();
 
19349     background = iD.Background(context);
 
19351     features = iD.Features(context);
 
19353     map = iD.Map(context);
 
19354     context.mouse = map.mouse;
 
19355     context.extent = map.extent;
 
19356     context.pan = map.pan;
 
19357     context.zoomIn = map.zoomIn;
 
19358     context.zoomOut = map.zoomOut;
 
19359     context.zoomInFurther = map.zoomInFurther;
 
19360     context.zoomOutFurther = map.zoomOutFurther;
 
19361     context.redrawEnable = map.redrawEnable;
 
19363     presets = iD.presets();
 
19365     return d3.rebind(context, dispatch, 'on');
 
19369 iD.version = '1.9.1';
 
19374     var ua = navigator.userAgent,
 
19377     m = ua.match(/(edge)\/?\s*(\.?\d+(\.\d+)*)/i);   // Edge
 
19379         detected.browser = m[1];
 
19380         detected.version = m[2];
 
19382     if (!detected.browser) {
 
19383         m = ua.match(/Trident\/.*rv:([0-9]{1,}[\.0-9]{0,})/i);   // IE11
 
19385             detected.browser = 'msie';
 
19386             detected.version = m[1];
 
19389     if (!detected.browser) {
 
19390         m = ua.match(/(opr)\/?\s*(\.?\d+(\.\d+)*)/i);   // Opera 15+
 
19392             detected.browser = 'Opera';
 
19393             detected.version = m[2];
 
19396     if (!detected.browser) {
 
19397         m = ua.match(/(opera|chrome|safari|firefox|msie)\/?\s*(\.?\d+(\.\d+)*)/i);
 
19399             detected.browser = m[1];
 
19400             detected.version = m[2];
 
19401             m = ua.match(/version\/([\.\d]+)/i);
 
19402             if (m !== null) detected.version = m[1];
 
19405     if (!detected.browser) {
 
19406         detected.browser = navigator.appName;
 
19407         detected.version = navigator.appVersion;
 
19410     // keep major.minor version only..
 
19411     detected.version = detected.version.split(/\W/).slice(0,2).join('.');
 
19413     if (detected.browser.toLowerCase() === 'msie') {
 
19414         detected.ie = true;
 
19415         detected.browser = 'Internet Explorer';
 
19416         detected.support = parseFloat(detected.version) >= 11;
 
19418         detected.ie = false;
 
19419         detected.support = true;
 
19422     // Added due to incomplete svg style support. See #715
 
19423     detected.opera = (detected.browser.toLowerCase() === 'opera' && parseFloat(detected.version) < 15 );
 
19425     detected.locale = (navigator.languages && navigator.languages.length)
 
19426         ? navigator.languages[0] : (navigator.language || navigator.userLanguage || 'en-US');
 
19428     detected.filedrop = (window.FileReader && 'ondrop' in window);
 
19431         return navigator.userAgent.indexOf(x) !== -1;
 
19435         detected.os = 'win';
 
19436         detected.platform = 'Windows';
 
19438     else if (nav('Mac')) {
 
19439         detected.os = 'mac';
 
19440         detected.platform = 'Macintosh';
 
19442     else if (nav('X11') || nav('Linux')) {
 
19443         detected.os = 'linux';
 
19444         detected.platform = 'Linux';
 
19447         detected.os = 'win';
 
19448         detected.platform = 'Unknown';
 
19451     iD.detect = function() { return detected; };
 
19454 iD.services.mapillary = function() {
 
19455     var mapillary = {},
 
19456         dispatch = d3.dispatch('loadedImages', 'loadedSigns'),
 
19457         apibase = 'https://a.mapillary.com/v2/',
 
19458         urlImage = 'https://www.mapillary.com/map/im/',
 
19459         urlThumb = 'https://d1cuyjsrcm0gby.cloudfront.net/',
 
19460         clientId = 'NzNRM2otQkR2SHJzaXJmNmdQWVQ0dzo1ZWYyMmYwNjdmNDdlNmVi',
 
19465     function loadSignStyles(context) {
 
19466         d3.select('head').selectAll('#traffico')
 
19470             .attr('id', 'traffico')
 
19471             .attr('rel', 'stylesheet')
 
19472             .attr('href', context.asset('traffico/stylesheets/traffico.css'));
 
19475     function loadSignDefs(context) {
 
19476         if (!iD.services.mapillary.sign_defs) {
 
19477             iD.services.mapillary.sign_defs = {};
 
19478             _.each(['au', 'br', 'ca', 'de', 'us'], function(region) {
 
19479                 d3.json(context.asset('traffico/string-maps/' + region + '-map.json'), function(err, data) {
 
19481                     if (region === 'de') region = 'eu';
 
19482                     iD.services.mapillary.sign_defs[region] = data;
 
19488     function abortRequest(i) {
 
19492     function getTiles(projection, dimensions) {
 
19493         var s = projection.scale() * 2 * Math.PI,
 
19494             z = Math.max(Math.log(s) / Math.log(2) - 8, 0),
 
19495             ts = 256 * Math.pow(2, z - tileZoom),
 
19497                 s / 2 - projection.translate()[0],
 
19498                 s / 2 - projection.translate()[1]];
 
19500         return d3.geo.tile()
 
19501             .scaleExtent([tileZoom, tileZoom])
 
19504             .translate(projection.translate())()
 
19505             .map(function(tile) {
 
19506                 var x = tile[0] * ts - origin[0],
 
19507                     y = tile[1] * ts - origin[1];
 
19510                     id: tile.toString(),
 
19511                     extent: iD.geo.Extent(
 
19512                         projection.invert([x, y + ts]),
 
19513                         projection.invert([x + ts, y]))
 
19519     function loadTiles(which, url, projection, dimensions) {
 
19520         var tiles = getTiles(projection, dimensions);
 
19522         _.filter(which.inflight, function(v, k) {
 
19523             var wanted = _.find(tiles, function(tile) { return k === (tile.id + ',0'); });
 
19524             if (!wanted) delete which.inflight[k];
 
19526         }).map(abortRequest);
 
19528         tiles.forEach(function(tile) {
 
19529             loadTilePage(which, url, tile, 0);
 
19533     function loadTilePage(which, url, tile, page) {
 
19534         var cache = iD.services.mapillary.cache[which],
 
19535             id = tile.id + ',' + String(page),
 
19536             rect = tile.extent.rectangle();
 
19538         if (cache.loaded[id] || cache.inflight[id]) return;
 
19540         cache.inflight[id] = d3.json(url +
 
19545                 client_id: clientId,
 
19550             }), function(err, data) {
 
19551                 cache.loaded[id] = true;
 
19552                 delete cache.inflight[id];
 
19553                 if (err || !data.features || !data.features.length) return;
 
19558                 for (var i = 0; i < data.features.length; i++) {
 
19559                     feature = data.features[i];
 
19560                     loc = feature.geometry.coordinates;
 
19561                     d = { key: feature.properties.key, loc: loc };
 
19562                     if (which === 'images') d.ca = feature.properties.ca;
 
19563                     if (which === 'signs') d.signs = feature.properties.rects;
 
19565                     features.push([loc[0], loc[1], loc[0], loc[1], d]);
 
19568                 cache.rtree.load(features);
 
19570                 if (which === 'images') dispatch.loadedImages();
 
19571                 if (which === 'signs') dispatch.loadedSigns();
 
19573                 if (data.features.length === maxResults) {
 
19574                     loadTilePage(which, url, tile, ++page);
 
19580     mapillary.loadImages = function(projection, dimensions) {
 
19581         var url = apibase + 'search/im/geojson?';
 
19582         loadTiles('images', url, projection, dimensions);
 
19585     mapillary.loadSigns = function(context, projection, dimensions) {
 
19586         var url = apibase + 'search/im/geojson/or?';
 
19587         loadSignStyles(context);
 
19588         loadSignDefs(context);
 
19589         loadTiles('signs', url, projection, dimensions);
 
19593     // partition viewport into `psize` x `psize` regions
 
19594     function partitionViewport(psize, projection, dimensions) {
 
19595         psize = psize || 16;
 
19596         var cols = d3.range(0, dimensions[0], psize),
 
19597             rows = d3.range(0, dimensions[1], psize),
 
19600         rows.forEach(function(y) {
 
19601             cols.forEach(function(x) {
 
19602                 var min = [x, y + psize],
 
19603                     max = [x + psize, y];
 
19605                     iD.geo.Extent(projection.invert(min), projection.invert(max)));
 
19612     // no more than `limit` results per partition.
 
19613     function searchLimited(psize, limit, projection, dimensions, rtree) {
 
19614         limit = limit || 3;
 
19616         var partitions = partitionViewport(psize, projection, dimensions);
 
19617         return _.flatten(_.compact(_.map(partitions, function(extent) {
 
19618             return rtree.search(extent.rectangle())
 
19620                 .map(function(d) { return d[4]; });
 
19624     mapillary.images = function(projection, dimensions) {
 
19625         var psize = 16, limit = 3;
 
19626         return searchLimited(psize, limit, projection, dimensions, iD.services.mapillary.cache.images.rtree);
 
19629     mapillary.signs = function(projection, dimensions) {
 
19630         var psize = 32, limit = 3;
 
19631         return searchLimited(psize, limit, projection, dimensions, iD.services.mapillary.cache.signs.rtree);
 
19634     mapillary.signsSupported = function() {
 
19635         var detected = iD.detect();
 
19636         return (!(detected.ie || detected.browser.toLowerCase() === 'safari'));
 
19639     mapillary.signHTML = function(d) {
 
19640         if (!iD.services.mapillary.sign_defs) return;
 
19642         var detectionPackage = d.signs[0].package,
 
19643             type = d.signs[0].type,
 
19644             country = detectionPackage.split('_')[1];
 
19645         return iD.services.mapillary.sign_defs[country][type];
 
19648     mapillary.showThumbnail = function(imageKey, position) {
 
19649         if (!imageKey) return;
 
19651         var positionClass = {
 
19652             'ar': (position !== 'left'),
 
19653             'al': (position === 'left')
 
19656         var thumbnail = d3.select('#content').selectAll('.mapillary-image')
 
19660         var enter = thumbnail.enter().append('div')
 
19661             .attr('class', 'mapillary-image ar');
 
19663         enter.append('button')
 
19664             .on('click', function () {
 
19665                 mapillary.hideThumbnail();
 
19668             .call(iD.svg.Icon('#icon-close'));
 
19670         enter.append('img');
 
19673             .attr('class', 'link ar')
 
19674             .attr('target', '_blank')
 
19675             .call(iD.svg.Icon('#icon-out-link', 'inline'))
 
19677             .text(t('mapillary.view_on_mapillary'));
 
19680         thumbnail.selectAll('img')
 
19681             .attr('src', urlThumb + imageKey + '/thumb-320.jpg');
 
19683         var link = thumbnail.selectAll('a')
 
19684             .attr('href', urlImage + imageKey);
 
19687             thumbnail.classed(positionClass);
 
19688             link.classed(positionClass);
 
19694             .style('opacity', 1);
 
19697     mapillary.hideThumbnail = function() {
 
19698         if (iD.services.mapillary) {
 
19699             iD.services.mapillary.thumb = null;
 
19701         d3.select('#content').selectAll('.mapillary-image')
 
19704             .style('opacity', 0)
 
19708     mapillary.selectedThumbnail = function(d) {
 
19709         if (!iD.services.mapillary) return null;
 
19710         if (!arguments.length) return iD.services.mapillary.thumb;
 
19711         iD.services.mapillary.thumb = d;
 
19714     mapillary.reset = function() {
 
19715         var cache = iD.services.mapillary.cache;
 
19718             _.forEach(cache.images.inflight, abortRequest);
 
19719             _.forEach(cache.signs.inflight, abortRequest);
 
19722         iD.services.mapillary.cache = {
 
19723             images: { inflight: {}, loaded: {}, rtree: rbush() },
 
19724             signs:  { inflight: {}, loaded: {}, rtree: rbush() }
 
19727         iD.services.mapillary.thumb = null;
 
19733     if (!iD.services.mapillary.cache) {
 
19737     return d3.rebind(mapillary, dispatch, 'on');
 
19739 iD.services.nominatim  = function() {
 
19740     var nominatim = {},
 
19741         endpoint = 'https://nominatim.openstreetmap.org/reverse?';
 
19744     nominatim.countryCode = function(location, callback) {
 
19745         var cache = iD.services.nominatim.cache,
 
19746             countryCodes = cache.search([location[0], location[1], location[0], location[1]]);
 
19748         if (countryCodes.length > 0)
 
19749             return callback(null, countryCodes[0][4]);
 
19757             }), function(err, result) {
 
19759                     return callback(err);
 
19760                 else if (result && result.error)
 
19761                     return callback(result.error);
 
19763                 var extent = iD.geo.Extent(location).padByMeters(1000);
 
19765                 cache.insert(extent.rectangle().concat(result.address.country_code));
 
19767                 callback(null, result.address.country_code);
 
19771     nominatim.reset = function() {
 
19772         iD.services.nominatim.cache = rbush();
 
19777     if (!iD.services.nominatim.cache) {
 
19783 iD.services.taginfo = function() {
 
19785         endpoint = 'https://taginfo.openstreetmap.org/api/4/',
 
19787             point: 'count_nodes',
 
19788             vertex: 'count_nodes',
 
19789             area: 'count_ways',
 
19800     function sets(parameters, n, o) {
 
19801         if (parameters.geometry && o[parameters.geometry]) {
 
19802             parameters[n] = o[parameters.geometry];
 
19807     function setFilter(parameters) {
 
19808         return sets(parameters, 'filter', tag_filters);
 
19811     function setSort(parameters) {
 
19812         return sets(parameters, 'sortname', tag_sorts);
 
19815     function clean(parameters) {
 
19816         return _.omit(parameters, 'geometry', 'debounce');
 
19819     function popularKeys(parameters) {
 
19820         var pop_field = 'count_all';
 
19821         if (parameters.filter) pop_field = 'count_' + parameters.filter;
 
19822         return function(d) { return parseFloat(d[pop_field]) > 5000 || d.in_wiki; };
 
19825     function popularValues() {
 
19826         return function(d) { return parseFloat(d.fraction) > 0.01 || d.in_wiki; };
 
19829     function valKey(d) { return { value: d.key }; }
 
19831     function valKeyDescription(d) {
 
19834             title: d.description
 
19838     // sort keys with ':' lower than keys without ':'
 
19839     function sortKeys(a, b) {
 
19840         return (a.key.indexOf(':') === -1 && b.key.indexOf(':') !== -1) ? -1
 
19841             : (a.key.indexOf(':') !== -1 && b.key.indexOf(':') === -1) ? 1
 
19845     var debounced = _.debounce(d3.json, 100, true);
 
19847     function request(url, debounce, callback) {
 
19848         var cache = iD.services.taginfo.cache;
 
19851             callback(null, cache[url]);
 
19852         } else if (debounce) {
 
19853             debounced(url, done);
 
19855             d3.json(url, done);
 
19858         function done(err, data) {
 
19859             if (!err) cache[url] = data;
 
19860             callback(err, data);
 
19864     taginfo.keys = function(parameters, callback) {
 
19865         var debounce = parameters.debounce;
 
19866         parameters = clean(setSort(parameters));
 
19867         request(endpoint + 'keys/all?' +
 
19868             iD.util.qsString(_.extend({
 
19870                 sortname: 'count_all',
 
19873             }, parameters)), debounce, function(err, d) {
 
19874                 if (err) return callback(err);
 
19875                 callback(null, d.data.filter(popularKeys(parameters)).sort(sortKeys).map(valKey));
 
19879     taginfo.values = function(parameters, callback) {
 
19880         var debounce = parameters.debounce;
 
19881         parameters = clean(setSort(setFilter(parameters)));
 
19882         request(endpoint + 'key/values?' +
 
19883             iD.util.qsString(_.extend({
 
19885                 sortname: 'count_all',
 
19888             }, parameters)), debounce, function(err, d) {
 
19889                 if (err) return callback(err);
 
19890                 callback(null, d.data.filter(popularValues()).map(valKeyDescription), parameters);
 
19894     taginfo.docs = function(parameters, callback) {
 
19895         var debounce = parameters.debounce;
 
19896         parameters = clean(setSort(parameters));
 
19898         var path = 'key/wiki_pages?';
 
19899         if (parameters.value) path = 'tag/wiki_pages?';
 
19900         else if (parameters.rtype) path = 'relation/wiki_pages?';
 
19902         request(endpoint + path + iD.util.qsString(parameters), debounce, function(err, d) {
 
19903             if (err) return callback(err);
 
19904             callback(null, d.data);
 
19908     taginfo.endpoint = function(_) {
 
19909         if (!arguments.length) return endpoint;
 
19914     taginfo.reset = function() {
 
19915         iD.services.taginfo.cache = {};
 
19920     if (!iD.services.taginfo.cache) {
 
19926 iD.services.wikipedia = function() {
 
19928         endpoint = 'https://en.wikipedia.org/w/api.php?';
 
19930     wiki.search = function(lang, query, callback) {
 
19931         lang = lang || 'en';
 
19932         d3.jsonp(endpoint.replace('en', lang) +
 
19937                 srinfo: 'suggestion',
 
19939                 callback: '{callback}',
 
19941             }), function(data) {
 
19942                 if (!data.query) return;
 
19943                 callback(query, data.query.search.map(function(d) {
 
19949     wiki.suggestions = function(lang, query, callback) {
 
19950         lang = lang || 'en';
 
19951         d3.jsonp(endpoint.replace('en', lang) +
 
19953                 action: 'opensearch',
 
19957                 callback: '{callback}',
 
19960                 callback(d[0], d[1]);
 
19964     wiki.translations = function(lang, title, callback) {
 
19965         d3.jsonp(endpoint.replace('en', lang) +
 
19970                 callback: '{callback}',
 
19974                 var list = d.query.pages[Object.keys(d.query.pages)[0]],
 
19976                 if (list && list.langlinks) {
 
19977                     list.langlinks.forEach(function(d) {
 
19978                         translations[d.lang] = d['*'];
 
19980                     callback(translations);
 
19989 iD.util.tagText = function(entity) {
 
19990     return d3.entries(entity.tags).map(function(e) {
 
19991         return e.key + '=' + e.value;
 
19995 iD.util.entitySelector = function(ids) {
 
19996     return ids.length ? '.' + ids.join(',.') : 'nothing';
 
19999 iD.util.entityOrMemberSelector = function(ids, graph) {
 
20000     var s = iD.util.entitySelector(ids);
 
20002     ids.forEach(function(id) {
 
20003         var entity = graph.hasEntity(id);
 
20004         if (entity && entity.type === 'relation') {
 
20005             entity.members.forEach(function(member) {
 
20006                 s += ',.' + member.id;
 
20014 iD.util.displayName = function(entity) {
 
20015     var localeName = 'name:' + iD.detect().locale.toLowerCase().split('-')[0];
 
20016     return entity.tags[localeName] || entity.tags.name || entity.tags.ref;
 
20019 iD.util.displayType = function(id) {
 
20021         n: t('inspector.node'),
 
20022         w: t('inspector.way'),
 
20023         r: t('inspector.relation')
 
20027 iD.util.stringQs = function(str) {
 
20028     return str.split('&').reduce(function(obj, pair){
 
20029         var parts = pair.split('=');
 
20030         if (parts.length === 2) {
 
20031             obj[parts[0]] = (null === parts[1]) ? '' : decodeURIComponent(parts[1]);
 
20037 iD.util.qsString = function(obj, noencode) {
 
20038     function softEncode(s) {
 
20039       // encode everything except special characters used in certain hash parameters:
 
20040       // "/" in map states, ":", ",", {" and "}" in background
 
20041       return encodeURIComponent(s).replace(/(%2F|%3A|%2C|%7B|%7D)/g, decodeURIComponent);
 
20043     return Object.keys(obj).sort().map(function(key) {
 
20044         return encodeURIComponent(key) + '=' + (
 
20045             noencode ? softEncode(obj[key]) : encodeURIComponent(obj[key]));
 
20049 iD.util.prefixDOMProperty = function(property) {
 
20050     var prefixes = ['webkit', 'ms', 'moz', 'o'],
 
20052         n = prefixes.length,
 
20058     property = property.substr(0, 1).toUpperCase() + property.substr(1);
 
20061         if (prefixes[i] + property in s)
 
20062             return prefixes[i] + property;
 
20067 iD.util.prefixCSSProperty = function(property) {
 
20068     var prefixes = ['webkit', 'ms', 'Moz', 'O'],
 
20070         n = prefixes.length,
 
20071         s = document.body.style;
 
20073     if (property.toLowerCase() in s)
 
20074         return property.toLowerCase();
 
20077         if (prefixes[i] + property in s)
 
20078             return '-' + prefixes[i].toLowerCase() + property.replace(/([A-Z])/g, '-$1').toLowerCase();
 
20084 iD.util.setTransform = function(el, x, y, scale) {
 
20085     var prop = iD.util.transformProperty = iD.util.transformProperty || iD.util.prefixCSSProperty('Transform'),
 
20086         translate = iD.detect().opera ?
 
20087             'translate('   + x + 'px,' + y + 'px)' :
 
20088             'translate3d(' + x + 'px,' + y + 'px,0)';
 
20089     return el.style(prop, translate + (scale ? ' scale(' + scale + ')' : ''));
 
20092 iD.util.getStyle = function(selector) {
 
20093     for (var i = 0; i < document.styleSheets.length; i++) {
 
20094         var rules = document.styleSheets[i].rules || document.styleSheets[i].cssRules || [];
 
20095         for (var k = 0; k < rules.length; k++) {
 
20096             var selectorText = rules[k].selectorText && rules[k].selectorText.split(', ');
 
20097             if (_.contains(selectorText, selector)) {
 
20104 iD.util.editDistance = function(a, b) {
 
20105     if (a.length === 0) return b.length;
 
20106     if (b.length === 0) return a.length;
 
20108     for (var i = 0; i <= b.length; i++) { matrix[i] = [i]; }
 
20109     for (var j = 0; j <= a.length; j++) { matrix[0][j] = j; }
 
20110     for (i = 1; i <= b.length; i++) {
 
20111         for (j = 1; j <= a.length; j++) {
 
20112             if (b.charAt(i-1) === a.charAt(j-1)) {
 
20113                 matrix[i][j] = matrix[i-1][j-1];
 
20115                 matrix[i][j] = Math.min(matrix[i-1][j-1] + 1, // substitution
 
20116                     Math.min(matrix[i][j-1] + 1, // insertion
 
20117                     matrix[i-1][j] + 1)); // deletion
 
20121     return matrix[b.length][a.length];
 
20124 // a d3.mouse-alike which
 
20125 // 1. Only works on HTML elements, not SVG
 
20126 // 2. Does not cause style recalculation
 
20127 iD.util.fastMouse = function(container) {
 
20128     var rect = container.getBoundingClientRect(),
 
20129         rectLeft = rect.left,
 
20130         rectTop = rect.top,
 
20131         clientLeft = +container.clientLeft,
 
20132         clientTop = +container.clientTop;
 
20133     return function(e) {
 
20135             e.clientX - rectLeft - clientLeft,
 
20136             e.clientY - rectTop - clientTop];
 
20140 /* eslint-disable no-proto */
 
20141 iD.util.getPrototypeOf = Object.getPrototypeOf || function(obj) { return obj.__proto__; };
 
20142 /* eslint-enable no-proto */
 
20144 iD.util.asyncMap = function(inputs, func, callback) {
 
20145     var remaining = inputs.length,
 
20149     inputs.forEach(function(d, i) {
 
20150         func(d, function done(err, data) {
 
20154             if (!remaining) callback(errors, results);
 
20159 // wraps an index to an interval [0..length-1]
 
20160 iD.util.wrap = function(index, length) {
 
20162         index += Math.ceil(-index/length)*length;
 
20163     return index % length;
 
20165 // A per-domain session mutex backed by a cookie and dead man's
 
20166 // switch. If the session crashes, the mutex will auto-release
 
20167 // after 5 seconds.
 
20169 iD.util.SessionMutex = function(name) {
 
20174         var expires = new Date();
 
20175         expires.setSeconds(expires.getSeconds() + 5);
 
20176         document.cookie = name + '=1; expires=' + expires.toUTCString();
 
20179     mutex.lock = function() {
 
20180         if (intervalID) return true;
 
20181         var cookie = document.cookie.replace(new RegExp('(?:(?:^|.*;)\\s*' + name + '\\s*\\=\\s*([^;]*).*$)|^.*$'), '$1');
 
20182         if (cookie) return false;
 
20184         intervalID = window.setInterval(renew, 4000);
 
20188     mutex.unlock = function() {
 
20189         if (!intervalID) return;
 
20190         document.cookie = name + '=; expires=Thu, 01 Jan 1970 00:00:00 GMT';
 
20191         clearInterval(intervalID);
 
20195     mutex.locked = function() {
 
20196         return !!intervalID;
 
20201 iD.util.SuggestNames = function(preset, suggestions) {
 
20202     preset = preset.id.split('/', 2);
 
20206     return function(value, callback) {
 
20208         if (value && value.length > 2) {
 
20209             if (suggestions[k] && suggestions[k][v]) {
 
20210                 for (var sugg in suggestions[k][v]) {
 
20211                     var dist = iD.util.editDistance(value, sugg.substring(0, value.length));
 
20221             result.sort(function(a, b) {
 
20222                 return a.dist - b.dist;
 
20225         result = result.slice(0,3);
 
20231 iD.geo.roundCoords = function(c) {
 
20232     return [Math.floor(c[0]), Math.floor(c[1])];
 
20235 iD.geo.interp = function(p1, p2, t) {
 
20236     return [p1[0] + (p2[0] - p1[0]) * t,
 
20237             p1[1] + (p2[1] - p1[1]) * t];
 
20240 // 2D cross product of OA and OB vectors, i.e. z-component of their 3D cross product.
 
20241 // Returns a positive value, if OAB makes a counter-clockwise turn,
 
20242 // negative for clockwise turn, and zero if the points are collinear.
 
20243 iD.geo.cross = function(o, a, b) {
 
20244     return (a[0] - o[0]) * (b[1] - o[1]) - (a[1] - o[1]) * (b[0] - o[0]);
 
20247 // http://jsperf.com/id-dist-optimization
 
20248 iD.geo.euclideanDistance = function(a, b) {
 
20249     var x = a[0] - b[0], y = a[1] - b[1];
 
20250     return Math.sqrt((x * x) + (y * y));
 
20253 // using WGS84 polar radius (6356752.314245179 m)
 
20254 // const = 2 * PI * r / 360
 
20255 iD.geo.latToMeters = function(dLat) {
 
20256     return dLat * 110946.257617;
 
20259 // using WGS84 equatorial radius (6378137.0 m)
 
20260 // const = 2 * PI * r / 360
 
20261 iD.geo.lonToMeters = function(dLon, atLat) {
 
20262     return Math.abs(atLat) >= 90 ? 0 :
 
20263         dLon * 111319.490793 * Math.abs(Math.cos(atLat * (Math.PI/180)));
 
20266 // using WGS84 polar radius (6356752.314245179 m)
 
20267 // const = 2 * PI * r / 360
 
20268 iD.geo.metersToLat = function(m) {
 
20269     return m / 110946.257617;
 
20272 // using WGS84 equatorial radius (6378137.0 m)
 
20273 // const = 2 * PI * r / 360
 
20274 iD.geo.metersToLon = function(m, atLat) {
 
20275     return Math.abs(atLat) >= 90 ? 0 :
 
20276         m / 111319.490793 / Math.abs(Math.cos(atLat * (Math.PI/180)));
 
20279 // Equirectangular approximation of spherical distances on Earth
 
20280 iD.geo.sphericalDistance = function(a, b) {
 
20281     var x = iD.geo.lonToMeters(a[0] - b[0], (a[1] + b[1]) / 2),
 
20282         y = iD.geo.latToMeters(a[1] - b[1]);
 
20283     return Math.sqrt((x * x) + (y * y));
 
20286 iD.geo.edgeEqual = function(a, b) {
 
20287     return (a[0] === b[0] && a[1] === b[1]) ||
 
20288         (a[0] === b[1] && a[1] === b[0]);
 
20291 // Return the counterclockwise angle in the range (-pi, pi)
 
20292 // between the positive X axis and the line intersecting a and b.
 
20293 iD.geo.angle = function(a, b, projection) {
 
20294     a = projection(a.loc);
 
20295     b = projection(b.loc);
 
20296     return Math.atan2(b[1] - a[1], b[0] - a[0]);
 
20299 // Choose the edge with the minimal distance from `point` to its orthogonal
 
20300 // projection onto that edge, if such a projection exists, or the distance to
 
20301 // the closest vertex on that edge. Returns an object with the `index` of the
 
20302 // chosen edge, the chosen `loc` on that edge, and the `distance` to to it.
 
20303 iD.geo.chooseEdge = function(nodes, point, projection) {
 
20304     var dist = iD.geo.euclideanDistance,
 
20305         points = nodes.map(function(n) { return projection(n.loc); }),
 
20309     function dot(p, q) {
 
20310         return p[0] * q[0] + p[1] * q[1];
 
20313     for (var i = 0; i < points.length - 1; i++) {
 
20315             s = [points[i + 1][0] - o[0],
 
20316                  points[i + 1][1] - o[1]],
 
20317             v = [point[0] - o[0],
 
20319             proj = dot(v, s) / dot(s, s),
 
20324         } else if (proj > 1) {
 
20327             p = [o[0] + proj * s[0], o[1] + proj * s[1]];
 
20330         var d = dist(p, point);
 
20334             loc = projection.invert(p);
 
20345 // Return the intersection point of 2 line segments.
 
20346 // From https://github.com/pgkelley4/line-segments-intersect
 
20347 // This uses the vector cross product approach described below:
 
20348 //  http://stackoverflow.com/a/565282/786339
 
20349 iD.geo.lineIntersection = function(a, b) {
 
20350     function subtractPoints(point1, point2) {
 
20351         return [point1[0] - point2[0], point1[1] - point2[1]];
 
20353     function crossProduct(point1, point2) {
 
20354         return point1[0] * point2[1] - point1[1] * point2[0];
 
20357     var p = [a[0][0], a[0][1]],
 
20358         p2 = [a[1][0], a[1][1]],
 
20359         q = [b[0][0], b[0][1]],
 
20360         q2 = [b[1][0], b[1][1]],
 
20361         r = subtractPoints(p2, p),
 
20362         s = subtractPoints(q2, q),
 
20363         uNumerator = crossProduct(subtractPoints(q, p), r),
 
20364         denominator = crossProduct(r, s);
 
20366     if (uNumerator && denominator) {
 
20367         var u = uNumerator / denominator,
 
20368             t = crossProduct(subtractPoints(q, p), s) / denominator;
 
20370         if ((t >= 0) && (t <= 1) && (u >= 0) && (u <= 1)) {
 
20371             return iD.geo.interp(p, p2, t);
 
20378 iD.geo.pathIntersections = function(path1, path2) {
 
20379     var intersections = [];
 
20380     for (var i = 0; i < path1.length - 1; i++) {
 
20381         for (var j = 0; j < path2.length - 1; j++) {
 
20382             var a = [ path1[i], path1[i+1] ],
 
20383                 b = [ path2[j], path2[j+1] ],
 
20384                 hit = iD.geo.lineIntersection(a, b);
 
20385             if (hit) intersections.push(hit);
 
20388     return intersections;
 
20391 // Return whether point is contained in polygon.
 
20393 // `point` should be a 2-item array of coordinates.
 
20394 // `polygon` should be an array of 2-item arrays of coordinates.
 
20396 // From https://github.com/substack/point-in-polygon.
 
20397 // ray-casting algorithm based on
 
20398 // http://www.ecse.rpi.edu/Homepages/wrf/Research/Short_Notes/pnpoly.html
 
20400 iD.geo.pointInPolygon = function(point, polygon) {
 
20405     for (var i = 0, j = polygon.length - 1; i < polygon.length; j = i++) {
 
20406         var xi = polygon[i][0], yi = polygon[i][1];
 
20407         var xj = polygon[j][0], yj = polygon[j][1];
 
20409         var intersect = ((yi > y) !== (yj > y)) &&
 
20410             (x < (xj - xi) * (y - yi) / (yj - yi) + xi);
 
20411         if (intersect) inside = !inside;
 
20417 iD.geo.polygonContainsPolygon = function(outer, inner) {
 
20418     return _.every(inner, function(point) {
 
20419         return iD.geo.pointInPolygon(point, outer);
 
20423 iD.geo.polygonIntersectsPolygon = function(outer, inner, checkSegments) {
 
20424     function testSegments(outer, inner) {
 
20425         for (var i = 0; i < outer.length - 1; i++) {
 
20426             for (var j = 0; j < inner.length - 1; j++) {
 
20427                 var a = [ outer[i], outer[i+1] ],
 
20428                     b = [ inner[j], inner[j+1] ];
 
20429                 if (iD.geo.lineIntersection(a, b)) return true;
 
20435     function testPoints(outer, inner) {
 
20436         return _.some(inner, function(point) {
 
20437             return iD.geo.pointInPolygon(point, outer);
 
20441    return testPoints(outer, inner) || (!!checkSegments && testSegments(outer, inner));
 
20444 iD.geo.pathLength = function(path) {
 
20447     for (var i = 0; i < path.length - 1; i++) {
 
20448         dx = path[i][0] - path[i + 1][0];
 
20449         dy = path[i][1] - path[i + 1][1];
 
20450         length += Math.sqrt(dx * dx + dy * dy);
 
20454 iD.geo.Extent = function geoExtent(min, max) {
 
20455     if (!(this instanceof iD.geo.Extent)) return new iD.geo.Extent(min, max);
 
20456     if (min instanceof iD.geo.Extent) {
 
20458     } else if (min && min.length === 2 && min[0].length === 2 && min[1].length === 2) {
 
20462         this[0] = min        || [ Infinity,  Infinity];
 
20463         this[1] = max || min || [-Infinity, -Infinity];
 
20467 iD.geo.Extent.prototype = new Array(2);
 
20469 _.extend(iD.geo.Extent.prototype, {
 
20470     equals: function (obj) {
 
20471         return this[0][0] === obj[0][0] &&
 
20472             this[0][1] === obj[0][1] &&
 
20473             this[1][0] === obj[1][0] &&
 
20474             this[1][1] === obj[1][1];
 
20477     extend: function(obj) {
 
20478         if (!(obj instanceof iD.geo.Extent)) obj = new iD.geo.Extent(obj);
 
20479         return iD.geo.Extent([Math.min(obj[0][0], this[0][0]),
 
20480                               Math.min(obj[0][1], this[0][1])],
 
20481                              [Math.max(obj[1][0], this[1][0]),
 
20482                               Math.max(obj[1][1], this[1][1])]);
 
20485     _extend: function(extent) {
 
20486         this[0][0] = Math.min(extent[0][0], this[0][0]);
 
20487         this[0][1] = Math.min(extent[0][1], this[0][1]);
 
20488         this[1][0] = Math.max(extent[1][0], this[1][0]);
 
20489         this[1][1] = Math.max(extent[1][1], this[1][1]);
 
20493         return Math.abs((this[1][0] - this[0][0]) * (this[1][1] - this[0][1]));
 
20496     center: function() {
 
20497         return [(this[0][0] + this[1][0]) / 2,
 
20498                 (this[0][1] + this[1][1]) / 2];
 
20501     rectangle: function() {
 
20502         return [this[0][0], this[0][1], this[1][0], this[1][1]];
 
20505     polygon: function() {
 
20507             [this[0][0], this[0][1]],
 
20508             [this[0][0], this[1][1]],
 
20509             [this[1][0], this[1][1]],
 
20510             [this[1][0], this[0][1]],
 
20511             [this[0][0], this[0][1]]
 
20515     contains: function(obj) {
 
20516         if (!(obj instanceof iD.geo.Extent)) obj = new iD.geo.Extent(obj);
 
20517         return obj[0][0] >= this[0][0] &&
 
20518                obj[0][1] >= this[0][1] &&
 
20519                obj[1][0] <= this[1][0] &&
 
20520                obj[1][1] <= this[1][1];
 
20523     intersects: function(obj) {
 
20524         if (!(obj instanceof iD.geo.Extent)) obj = new iD.geo.Extent(obj);
 
20525         return obj[0][0] <= this[1][0] &&
 
20526                obj[0][1] <= this[1][1] &&
 
20527                obj[1][0] >= this[0][0] &&
 
20528                obj[1][1] >= this[0][1];
 
20531     intersection: function(obj) {
 
20532         if (!this.intersects(obj)) return new iD.geo.Extent();
 
20533         return new iD.geo.Extent([Math.max(obj[0][0], this[0][0]),
 
20534                                   Math.max(obj[0][1], this[0][1])],
 
20535                                  [Math.min(obj[1][0], this[1][0]),
 
20536                                   Math.min(obj[1][1], this[1][1])]);
 
20539     percentContainedIn: function(obj) {
 
20540         if (!(obj instanceof iD.geo.Extent)) obj = new iD.geo.Extent(obj);
 
20541         var a1 = this.intersection(obj).area(),
 
20544         if (a1 === Infinity || a2 === Infinity || a1 === 0 || a2 === 0) {
 
20551     padByMeters: function(meters) {
 
20552         var dLat = iD.geo.metersToLat(meters),
 
20553             dLon = iD.geo.metersToLon(meters, this.center()[1]);
 
20554         return iD.geo.Extent(
 
20555                 [this[0][0] - dLon, this[0][1] - dLat],
 
20556                 [this[1][0] + dLon, this[1][1] + dLat]);
 
20559     toParam: function() {
 
20560         return this.rectangle().join(',');
 
20564 iD.geo.Turn = function(turn) {
 
20565     if (!(this instanceof iD.geo.Turn))
 
20566         return new iD.geo.Turn(turn);
 
20567     _.extend(this, turn);
 
20570 iD.geo.Intersection = function(graph, vertexId) {
 
20571     var vertex = graph.entity(vertexId),
 
20572         parentWays = graph.parentWays(vertex),
 
20576     function addHighway(way, adjacentNodeId) {
 
20577         if (highways[adjacentNodeId]) {
 
20578             coincident.push(adjacentNodeId);
 
20580             highways[adjacentNodeId] = way;
 
20584     // Pre-split ways that would need to be split in
 
20585     // order to add a restriction. The real split will
 
20586     // happen when the restriction is added.
 
20587     parentWays.forEach(function(way) {
 
20588         if (!way.tags.highway || way.isArea() || way.isDegenerate())
 
20591         var isFirst = (vertexId === way.first()),
 
20592             isLast = (vertexId === way.last()),
 
20593             isAffix = (isFirst || isLast),
 
20594             isClosingNode = (isFirst && isLast);
 
20596         if (isAffix && !isClosingNode) {
 
20597             var index = (isFirst ? 1 : way.nodes.length - 2);
 
20598             addHighway(way, way.nodes[index]);
 
20601             var splitIndex, wayA, wayB, indexA, indexB;
 
20602             if (isClosingNode) {
 
20603                 splitIndex = Math.ceil(way.nodes.length / 2);  // split at midpoint
 
20604                 wayA = iD.Way({id: way.id + '-a', tags: way.tags, nodes: way.nodes.slice(0, splitIndex)});
 
20605                 wayB = iD.Way({id: way.id + '-b', tags: way.tags, nodes: way.nodes.slice(splitIndex)});
 
20607                 indexB = way.nodes.length - 2;
 
20609                 splitIndex = _.indexOf(way.nodes, vertex.id, 1);  // split at vertexid
 
20610                 wayA = iD.Way({id: way.id + '-a', tags: way.tags, nodes: way.nodes.slice(0, splitIndex + 1)});
 
20611                 wayB = iD.Way({id: way.id + '-b', tags: way.tags, nodes: way.nodes.slice(splitIndex)});
 
20612                 indexA = splitIndex - 1;
 
20613                 indexB = splitIndex + 1;
 
20615             graph = graph.replace(wayA).replace(wayB);
 
20616             addHighway(wayA, way.nodes[indexA]);
 
20617             addHighway(wayB, way.nodes[indexB]);
 
20621     // remove any ways from this intersection that are coincident
 
20622     // (i.e. any adjacent node used by more than one intersecting way)
 
20623     coincident.forEach(function (n) {
 
20624         delete highways[n];
 
20628     var intersection = {
 
20629         highways: highways,
 
20630         ways: _.values(highways),
 
20634     intersection.adjacentNodeId = function(fromWayId) {
 
20635         return _.find(_.keys(highways), function(k) {
 
20636             return highways[k].id === fromWayId;
 
20640     intersection.turns = function(fromNodeId) {
 
20641         var start = highways[fromNodeId];
 
20645         if (start.first() === vertex.id && start.tags.oneway === 'yes')
 
20647         if (start.last() === vertex.id && start.tags.oneway === '-1')
 
20650         function withRestriction(turn) {
 
20651             graph.parentRelations(graph.entity(turn.from.way)).forEach(function(relation) {
 
20652                 if (relation.tags.type !== 'restriction')
 
20655                 var f = relation.memberByRole('from'),
 
20656                     t = relation.memberByRole('to'),
 
20657                     v = relation.memberByRole('via');
 
20659                 if (f && f.id === turn.from.way &&
 
20660                     v && v.id === turn.via.node &&
 
20661                     t && t.id === turn.to.way) {
 
20662                     turn.restriction = relation.id;
 
20663                 } else if (/^only_/.test(relation.tags.restriction) &&
 
20664                     f && f.id === turn.from.way &&
 
20665                     v && v.id === turn.via.node &&
 
20666                     t && t.id !== turn.to.way) {
 
20667                     turn.restriction = relation.id;
 
20668                     turn.indirect_restriction = true;
 
20672             return iD.geo.Turn(turn);
 
20677                 way: start.id.split(/-(a|b)/)[0]
 
20679             via = { node: vertex.id },
 
20682         _.each(highways, function(end, adjacentNodeId) {
 
20687             if (end.first() !== vertex.id && end.tags.oneway !== 'yes') {
 
20688                 turns.push(withRestriction({
 
20692                         node: adjacentNodeId,
 
20693                         way: end.id.split(/-(a|b)/)[0]
 
20699             if (end.last() !== vertex.id && end.tags.oneway !== '-1') {
 
20700                 turns.push(withRestriction({
 
20704                         node: adjacentNodeId,
 
20705                         way: end.id.split(/-(a|b)/)[0]
 
20713         if (start.tags.oneway !== 'yes' && start.tags.oneway !== '-1') {
 
20714             turns.push(withRestriction({
 
20725     return intersection;
 
20729 iD.geo.inferRestriction = function(graph, from, via, to, projection) {
 
20730     var fromWay = graph.entity(from.way),
 
20731         fromNode = graph.entity(from.node),
 
20732         toWay = graph.entity(to.way),
 
20733         toNode = graph.entity(to.node),
 
20734         viaNode = graph.entity(via.node),
 
20735         fromOneWay = (fromWay.tags.oneway === 'yes' && fromWay.last() === via.node) ||
 
20736             (fromWay.tags.oneway === '-1' && fromWay.first() === via.node),
 
20737         toOneWay = (toWay.tags.oneway === 'yes' && toWay.first() === via.node) ||
 
20738             (toWay.tags.oneway === '-1' && toWay.last() === via.node),
 
20739         angle = iD.geo.angle(viaNode, fromNode, projection) -
 
20740                 iD.geo.angle(viaNode, toNode, projection);
 
20742     angle = angle * 180 / Math.PI;
 
20747     if (fromNode === toNode)
 
20748         return 'no_u_turn';
 
20749     if ((angle < 23 || angle > 336) && fromOneWay && toOneWay)
 
20750         return 'no_u_turn';
 
20752         return 'no_right_turn';
 
20754         return 'no_left_turn';
 
20756     return 'no_straight_on';
 
20758 // For fixing up rendering of multipolygons with tags on the outer member.
 
20759 // https://github.com/openstreetmap/iD/issues/613
 
20760 iD.geo.isSimpleMultipolygonOuterMember = function(entity, graph) {
 
20761     if (entity.type !== 'way')
 
20764     var parents = graph.parentRelations(entity);
 
20765     if (parents.length !== 1)
 
20768     var parent = parents[0];
 
20769     if (!parent.isMultipolygon() || Object.keys(parent.tags).length > 1)
 
20772     var members = parent.members, member;
 
20773     for (var i = 0; i < members.length; i++) {
 
20774         member = members[i];
 
20775         if (member.id === entity.id && member.role && member.role !== 'outer')
 
20776             return false; // Not outer member
 
20777         if (member.id !== entity.id && (!member.role || member.role === 'outer'))
 
20778             return false; // Not a simple multipolygon
 
20784 iD.geo.simpleMultipolygonOuterMember = function(entity, graph) {
 
20785     if (entity.type !== 'way')
 
20788     var parents = graph.parentRelations(entity);
 
20789     if (parents.length !== 1)
 
20792     var parent = parents[0];
 
20793     if (!parent.isMultipolygon() || Object.keys(parent.tags).length > 1)
 
20796     var members = parent.members, member, outerMember;
 
20797     for (var i = 0; i < members.length; i++) {
 
20798         member = members[i];
 
20799         if (!member.role || member.role === 'outer') {
 
20801                 return false; // Not a simple multipolygon
 
20802             outerMember = member;
 
20806     return outerMember && graph.hasEntity(outerMember.id);
 
20809 // Join `array` into sequences of connecting ways.
 
20811 // Segments which share identical start/end nodes will, as much as possible,
 
20812 // be connected with each other.
 
20814 // The return value is a nested array. Each constituent array contains elements
 
20815 // of `array` which have been determined to connect. Each consitituent array
 
20816 // also has a `nodes` property whose value is an ordered array of member nodes,
 
20817 // with appropriate order reversal and start/end coordinate de-duplication.
 
20819 // Members of `array` must have, at minimum, `type` and `id` properties.
 
20820 // Thus either an array of `iD.Way`s or a relation member array may be
 
20823 // If an member has a `tags` property, its tags will be reversed via
 
20824 // `iD.actions.Reverse` in the output.
 
20826 // Incomplete members (those for which `graph.hasEntity(element.id)` returns
 
20827 // false) and non-way members are ignored.
 
20829 iD.geo.joinWays = function(array, graph) {
 
20830     var joined = [], member, current, nodes, first, last, i, how, what;
 
20832     array = array.filter(function(member) {
 
20833         return member.type === 'way' && graph.hasEntity(member.id);
 
20836     function resolve(member) {
 
20837         return graph.childNodes(graph.entity(member.id));
 
20840     function reverse(member) {
 
20841         return member.tags ? iD.actions.Reverse(member.id, {reverseOneway: true})(graph).entity(member.id) : member;
 
20844     while (array.length) {
 
20845         member = array.shift();
 
20846         current = [member];
 
20847         current.nodes = nodes = resolve(member).slice();
 
20848         joined.push(current);
 
20850         while (array.length && _.first(nodes) !== _.last(nodes)) {
 
20851             first = _.first(nodes);
 
20852             last  = _.last(nodes);
 
20854             for (i = 0; i < array.length; i++) {
 
20856                 what = resolve(member);
 
20858                 if (last === _.first(what)) {
 
20860                     what = what.slice(1);
 
20862                 } else if (last === _.last(what)) {
 
20864                     what = what.slice(0, -1).reverse();
 
20865                     member = reverse(member);
 
20867                 } else if (first === _.last(what)) {
 
20868                     how  = nodes.unshift;
 
20869                     what = what.slice(0, -1);
 
20871                 } else if (first === _.first(what)) {
 
20872                     how  = nodes.unshift;
 
20873                     what = what.slice(1).reverse();
 
20874                     member = reverse(member);
 
20882                 break; // No more joinable ways.
 
20884             how.apply(current, [member]);
 
20885             how.apply(nodes, what);
 
20887             array.splice(i, 1);
 
20894     Bypasses features of D3's default projection stream pipeline that are unnecessary:
 
20895     * Antimeridian clipping
 
20896     * Spherical rotation
 
20899 iD.geo.RawMercator = function () {
 
20900     var project = d3.geo.mercator.raw,
 
20901         k = 512 / Math.PI, // scale
 
20902         x = 0, y = 0, // translate
 
20903         clipExtent = [[0, 0], [0, 0]];
 
20905     function projection(point) {
 
20906         point = project(point[0] * Math.PI / 180, point[1] * Math.PI / 180);
 
20907         return [point[0] * k + x, y - point[1] * k];
 
20910     projection.invert = function(point) {
 
20911         point = project.invert((point[0] - x) / k, (y - point[1]) / k);
 
20912         return point && [point[0] * 180 / Math.PI, point[1] * 180 / Math.PI];
 
20915     projection.scale = function(_) {
 
20916         if (!arguments.length) return k;
 
20921     projection.translate = function(_) {
 
20922         if (!arguments.length) return [x, y];
 
20928     projection.clipExtent = function(_) {
 
20929         if (!arguments.length) return clipExtent;
 
20934     projection.stream = d3.geo.transform({
 
20935         point: function(x, y) {
 
20936             x = projection([x, y]);
 
20937             this.stream.point(x[0], x[1]);
 
20944 iD.actions.AddEntity = function(way) {
 
20945     return function(graph) {
 
20946         return graph.replace(way);
 
20949 iD.actions.AddMember = function(relationId, member, memberIndex) {
 
20950     return function(graph) {
 
20951         var relation = graph.entity(relationId);
 
20953         if (isNaN(memberIndex) && member.type === 'way') {
 
20954             var members = relation.indexedMembers();
 
20955             members.push(member);
 
20957             var joined = iD.geo.joinWays(members, graph);
 
20958             for (var i = 0; i < joined.length; i++) {
 
20959                 var segment = joined[i];
 
20960                 for (var j = 0; j < segment.length && segment.length >= 2; j++) {
 
20961                     if (segment[j] !== member)
 
20965                         memberIndex = segment[j + 1].index;
 
20966                     } else if (j === segment.length - 1) {
 
20967                         memberIndex = segment[j - 1].index + 1;
 
20969                         memberIndex = Math.min(segment[j - 1].index + 1, segment[j + 1].index + 1);
 
20975         return graph.replace(relation.addMember(member, memberIndex));
 
20978 iD.actions.AddMidpoint = function(midpoint, node) {
 
20979     return function(graph) {
 
20980         graph = graph.replace(node.move(midpoint.loc));
 
20982         var parents = _.intersection(
 
20983             graph.parentWays(graph.entity(midpoint.edge[0])),
 
20984             graph.parentWays(graph.entity(midpoint.edge[1])));
 
20986         parents.forEach(function(way) {
 
20987             for (var i = 0; i < way.nodes.length - 1; i++) {
 
20988                 if (iD.geo.edgeEqual([way.nodes[i], way.nodes[i + 1]], midpoint.edge)) {
 
20989                     graph = graph.replace(graph.entity(way.id).addNode(node.id, i + 1));
 
20991                     // Add only one midpoint on doubled-back segments,
 
20992                     // turning them into self-intersections.
 
21001 // https://github.com/openstreetmap/potlatch2/blob/master/net/systemeD/halcyon/connection/actions/AddNodeToWayAction.as
 
21002 iD.actions.AddVertex = function(wayId, nodeId, index) {
 
21003     return function(graph) {
 
21004         return graph.replace(graph.entity(wayId).addNode(nodeId, index));
 
21007 iD.actions.ChangeMember = function(relationId, member, memberIndex) {
 
21008     return function(graph) {
 
21009         return graph.replace(graph.entity(relationId).updateMember(member, memberIndex));
 
21012 iD.actions.ChangePreset = function(entityId, oldPreset, newPreset) {
 
21013     return function(graph) {
 
21014         var entity = graph.entity(entityId),
 
21015             geometry = entity.geometry(graph),
 
21016             tags = entity.tags;
 
21018         if (oldPreset) tags = oldPreset.removeTags(tags, geometry);
 
21019         if (newPreset) tags = newPreset.applyTags(tags, geometry);
 
21021         return graph.replace(entity.update({tags: tags}));
 
21024 iD.actions.ChangeTags = function(entityId, tags) {
 
21025     return function(graph) {
 
21026         var entity = graph.entity(entityId);
 
21027         return graph.replace(entity.update({tags: tags}));
 
21030 iD.actions.Circularize = function(wayId, projection, maxAngle) {
 
21031     maxAngle = (maxAngle || 20) * Math.PI / 180;
 
21033     var action = function(graph) {
 
21034         var way = graph.entity(wayId);
 
21036         if (!way.isConvex(graph)) {
 
21037             graph = action.makeConvex(graph);
 
21040         var nodes = _.uniq(graph.childNodes(way)),
 
21041             keyNodes = nodes.filter(function(n) { return graph.parentWays(n).length !== 1; }),
 
21042             points = nodes.map(function(n) { return projection(n.loc); }),
 
21043             keyPoints = keyNodes.map(function(n) { return projection(n.loc); }),
 
21044             centroid = (points.length === 2) ? iD.geo.interp(points[0], points[1], 0.5) : d3.geom.polygon(points).centroid(),
 
21045             radius = d3.median(points, function(p) { return iD.geo.euclideanDistance(centroid, p); }),
 
21046             sign = d3.geom.polygon(points).area() > 0 ? 1 : -1,
 
21049         // we need atleast two key nodes for the algorithm to work
 
21050         if (!keyNodes.length) {
 
21051             keyNodes = [nodes[0]];
 
21052             keyPoints = [points[0]];
 
21055         if (keyNodes.length === 1) {
 
21056             var index = nodes.indexOf(keyNodes[0]),
 
21057                 oppositeIndex = Math.floor((index + nodes.length / 2) % nodes.length);
 
21059             keyNodes.push(nodes[oppositeIndex]);
 
21060             keyPoints.push(points[oppositeIndex]);
 
21063         // key points and nodes are those connected to the ways,
 
21064         // they are projected onto the circle, inbetween nodes are moved
 
21065         // to constant intervals between key nodes, extra inbetween nodes are
 
21066         // added if necessary.
 
21067         for (var i = 0; i < keyPoints.length; i++) {
 
21068             var nextKeyNodeIndex = (i + 1) % keyNodes.length,
 
21069                 startNode = keyNodes[i],
 
21070                 endNode = keyNodes[nextKeyNodeIndex],
 
21071                 startNodeIndex = nodes.indexOf(startNode),
 
21072                 endNodeIndex = nodes.indexOf(endNode),
 
21073                 numberNewPoints = -1,
 
21074                 indexRange = endNodeIndex - startNodeIndex,
 
21075                 distance, totalAngle, eachAngle, startAngle, endAngle,
 
21076                 angle, loc, node, j,
 
21077                 inBetweenNodes = [];
 
21079             if (indexRange < 0) {
 
21080                 indexRange += nodes.length;
 
21083             // position this key node
 
21084             distance = iD.geo.euclideanDistance(centroid, keyPoints[i]);
 
21085             if (distance === 0) { distance = 1e-4; }
 
21087                 centroid[0] + (keyPoints[i][0] - centroid[0]) / distance * radius,
 
21088                 centroid[1] + (keyPoints[i][1] - centroid[1]) / distance * radius];
 
21089             graph = graph.replace(keyNodes[i].move(projection.invert(keyPoints[i])));
 
21091             // figure out the between delta angle we want to match to
 
21092             startAngle = Math.atan2(keyPoints[i][1] - centroid[1], keyPoints[i][0] - centroid[0]);
 
21093             endAngle = Math.atan2(keyPoints[nextKeyNodeIndex][1] - centroid[1], keyPoints[nextKeyNodeIndex][0] - centroid[0]);
 
21094             totalAngle = endAngle - startAngle;
 
21096             // detects looping around -pi/pi
 
21097             if (totalAngle * sign > 0) {
 
21098                 totalAngle = -sign * (2 * Math.PI - Math.abs(totalAngle));
 
21103                 eachAngle = totalAngle / (indexRange + numberNewPoints);
 
21104             } while (Math.abs(eachAngle) > maxAngle);
 
21106             // move existing points
 
21107             for (j = 1; j < indexRange; j++) {
 
21108                 angle = startAngle + j * eachAngle;
 
21109                 loc = projection.invert([
 
21110                     centroid[0] + Math.cos(angle)*radius,
 
21111                     centroid[1] + Math.sin(angle)*radius]);
 
21113                 node = nodes[(j + startNodeIndex) % nodes.length].move(loc);
 
21114                 graph = graph.replace(node);
 
21117             // add new inbetween nodes if necessary
 
21118             for (j = 0; j < numberNewPoints; j++) {
 
21119                 angle = startAngle + (indexRange + j) * eachAngle;
 
21120                 loc = projection.invert([
 
21121                     centroid[0] + Math.cos(angle) * radius,
 
21122                     centroid[1] + Math.sin(angle) * radius]);
 
21124                 node = iD.Node({loc: loc});
 
21125                 graph = graph.replace(node);
 
21127                 nodes.splice(endNodeIndex + j, 0, node);
 
21128                 inBetweenNodes.push(node.id);
 
21131             // Check for other ways that share these keyNodes..
 
21132             // If keyNodes are adjacent in both ways,
 
21133             // we can add inBetween nodes to that shared way too..
 
21134             if (indexRange === 1 && inBetweenNodes.length) {
 
21135                 var startIndex1 = way.nodes.lastIndexOf(startNode.id),
 
21136                     endIndex1 = way.nodes.lastIndexOf(endNode.id),
 
21137                     wayDirection1 = (endIndex1 - startIndex1);
 
21138                 if (wayDirection1 < -1) { wayDirection1 = 1; }
 
21140                 /* eslint-disable no-loop-func */
 
21141                 _.each(_.without(graph.parentWays(keyNodes[i]), way), function(sharedWay) {
 
21142                     if (sharedWay.areAdjacent(startNode.id, endNode.id)) {
 
21143                         var startIndex2 = sharedWay.nodes.lastIndexOf(startNode.id),
 
21144                             endIndex2 = sharedWay.nodes.lastIndexOf(endNode.id),
 
21145                             wayDirection2 = (endIndex2 - startIndex2),
 
21146                             insertAt = endIndex2;
 
21147                         if (wayDirection2 < -1) { wayDirection2 = 1; }
 
21149                         if (wayDirection1 !== wayDirection2) {
 
21150                             inBetweenNodes.reverse();
 
21151                             insertAt = startIndex2;
 
21153                         for (j = 0; j < inBetweenNodes.length; j++) {
 
21154                             sharedWay = sharedWay.addNode(inBetweenNodes[j], insertAt + j);
 
21156                         graph = graph.replace(sharedWay);
 
21159                 /* eslint-enable no-loop-func */
 
21164         // update the way to have all the new nodes
 
21165         ids = nodes.map(function(n) { return n.id; });
 
21168         way = way.update({nodes: ids});
 
21169         graph = graph.replace(way);
 
21174     action.makeConvex = function(graph) {
 
21175         var way = graph.entity(wayId),
 
21176             nodes = _.uniq(graph.childNodes(way)),
 
21177             points = nodes.map(function(n) { return projection(n.loc); }),
 
21178             sign = d3.geom.polygon(points).area() > 0 ? 1 : -1,
 
21179             hull = d3.geom.hull(points);
 
21181         // D3 convex hulls go counterclockwise..
 
21187         for (var i = 0; i < hull.length - 1; i++) {
 
21188             var startIndex = points.indexOf(hull[i]),
 
21189                 endIndex = points.indexOf(hull[i+1]),
 
21190                 indexRange = (endIndex - startIndex);
 
21192             if (indexRange < 0) {
 
21193                 indexRange += nodes.length;
 
21196             // move interior nodes to the surface of the convex hull..
 
21197             for (var j = 1; j < indexRange; j++) {
 
21198                 var point = iD.geo.interp(hull[i], hull[i+1], j / indexRange),
 
21199                     node = nodes[(j + startIndex) % nodes.length].move(projection.invert(point));
 
21200                 graph = graph.replace(node);
 
21206     action.disabled = function(graph) {
 
21207         if (!graph.entity(wayId).isClosed())
 
21208             return 'not_closed';
 
21213 // Connect the ways at the given nodes.
 
21215 // The last node will survive. All other nodes will be replaced with
 
21216 // the surviving node in parent ways, and then removed.
 
21218 // Tags and relation memberships of of non-surviving nodes are merged
 
21219 // to the survivor.
 
21221 // This is the inverse of `iD.actions.Disconnect`.
 
21224 //   https://github.com/openstreetmap/potlatch2/blob/master/net/systemeD/halcyon/connection/actions/MergeNodesAction.as
 
21225 //   https://github.com/openstreetmap/josm/blob/mirror/src/org/openstreetmap/josm/actions/MergeNodesAction.java
 
21227 iD.actions.Connect = function(nodeIds) {
 
21228     return function(graph) {
 
21229         var survivor = graph.entity(_.last(nodeIds));
 
21231         for (var i = 0; i < nodeIds.length - 1; i++) {
 
21232             var node = graph.entity(nodeIds[i]);
 
21234             /* eslint-disable no-loop-func */
 
21235             graph.parentWays(node).forEach(function(parent) {
 
21236                 if (!parent.areAdjacent(node.id, survivor.id)) {
 
21237                     graph = graph.replace(parent.replaceNode(node.id, survivor.id));
 
21241             graph.parentRelations(node).forEach(function(parent) {
 
21242                 graph = graph.replace(parent.replaceMember(node, survivor));
 
21244             /* eslint-enable no-loop-func */
 
21246             survivor = survivor.mergeTags(node.tags);
 
21247             graph = iD.actions.DeleteNode(node.id)(graph);
 
21250         graph = graph.replace(survivor);
 
21255 iD.actions.CopyEntities = function(ids, fromGraph) {
 
21258     var action = function(graph) {
 
21259         ids.forEach(function(id) {
 
21260             fromGraph.entity(id).copy(fromGraph, copies);
 
21263         for (var id in copies) {
 
21264             graph = graph.replace(copies[id]);
 
21270     action.copies = function() {
 
21276 iD.actions.DeleteMember = function(relationId, memberIndex) {
 
21277     return function(graph) {
 
21278         var relation = graph.entity(relationId)
 
21279             .removeMember(memberIndex);
 
21281         graph = graph.replace(relation);
 
21283         if (relation.isDegenerate())
 
21284             graph = iD.actions.DeleteRelation(relation.id)(graph);
 
21289 iD.actions.DeleteMultiple = function(ids) {
 
21291         way: iD.actions.DeleteWay,
 
21292         node: iD.actions.DeleteNode,
 
21293         relation: iD.actions.DeleteRelation
 
21296     var action = function(graph) {
 
21297         ids.forEach(function(id) {
 
21298             if (graph.hasEntity(id)) { // It may have been deleted aready.
 
21299                 graph = actions[graph.entity(id).type](id)(graph);
 
21306     action.disabled = function(graph) {
 
21307         for (var i = 0; i < ids.length; i++) {
 
21309                 disabled = actions[graph.entity(id).type](id).disabled(graph);
 
21310             if (disabled) return disabled;
 
21316 // https://github.com/openstreetmap/potlatch2/blob/master/net/systemeD/halcyon/connection/actions/DeleteNodeAction.as
 
21317 iD.actions.DeleteNode = function(nodeId) {
 
21318     var action = function(graph) {
 
21319         var node = graph.entity(nodeId);
 
21321         graph.parentWays(node)
 
21322             .forEach(function(parent) {
 
21323                 parent = parent.removeNode(nodeId);
 
21324                 graph = graph.replace(parent);
 
21326                 if (parent.isDegenerate()) {
 
21327                     graph = iD.actions.DeleteWay(parent.id)(graph);
 
21331         graph.parentRelations(node)
 
21332             .forEach(function(parent) {
 
21333                 parent = parent.removeMembersWithID(nodeId);
 
21334                 graph = graph.replace(parent);
 
21336                 if (parent.isDegenerate()) {
 
21337                     graph = iD.actions.DeleteRelation(parent.id)(graph);
 
21341         return graph.remove(node);
 
21344     action.disabled = function() {
 
21350 // https://github.com/openstreetmap/potlatch2/blob/master/net/systemeD/halcyon/connection/actions/DeleteRelationAction.as
 
21351 iD.actions.DeleteRelation = function(relationId) {
 
21352     function deleteEntity(entity, graph) {
 
21353         return !graph.parentWays(entity).length &&
 
21354             !graph.parentRelations(entity).length &&
 
21355             !entity.hasInterestingTags();
 
21358     var action = function(graph) {
 
21359         var relation = graph.entity(relationId);
 
21361         graph.parentRelations(relation)
 
21362             .forEach(function(parent) {
 
21363                 parent = parent.removeMembersWithID(relationId);
 
21364                 graph = graph.replace(parent);
 
21366                 if (parent.isDegenerate()) {
 
21367                     graph = iD.actions.DeleteRelation(parent.id)(graph);
 
21371         _.uniq(_.pluck(relation.members, 'id')).forEach(function(memberId) {
 
21372             graph = graph.replace(relation.removeMembersWithID(memberId));
 
21374             var entity = graph.entity(memberId);
 
21375             if (deleteEntity(entity, graph)) {
 
21376                 graph = iD.actions.DeleteMultiple([memberId])(graph);
 
21380         return graph.remove(relation);
 
21383     action.disabled = function(graph) {
 
21384         if (!graph.entity(relationId).isComplete(graph))
 
21385             return 'incomplete_relation';
 
21390 // https://github.com/openstreetmap/potlatch2/blob/master/net/systemeD/halcyon/connection/actions/DeleteWayAction.as
 
21391 iD.actions.DeleteWay = function(wayId) {
 
21392     function deleteNode(node, graph) {
 
21393         return !graph.parentWays(node).length &&
 
21394             !graph.parentRelations(node).length &&
 
21395             !node.hasInterestingTags();
 
21398     var action = function(graph) {
 
21399         var way = graph.entity(wayId);
 
21401         graph.parentRelations(way)
 
21402             .forEach(function(parent) {
 
21403                 parent = parent.removeMembersWithID(wayId);
 
21404                 graph = graph.replace(parent);
 
21406                 if (parent.isDegenerate()) {
 
21407                     graph = iD.actions.DeleteRelation(parent.id)(graph);
 
21411         _.uniq(way.nodes).forEach(function(nodeId) {
 
21412             graph = graph.replace(way.removeNode(nodeId));
 
21414             var node = graph.entity(nodeId);
 
21415             if (deleteNode(node, graph)) {
 
21416                 graph = graph.remove(node);
 
21420         return graph.remove(way);
 
21423     action.disabled = function(graph) {
 
21424         var disabled = false;
 
21426         graph.parentRelations(graph.entity(wayId)).forEach(function(parent) {
 
21427             var type = parent.tags.type,
 
21428                 role = parent.memberById(wayId).role || 'outer';
 
21429             if (type === 'route' || type === 'boundary' || (type === 'multipolygon' && role === 'outer')) {
 
21430                 disabled = 'part_of_relation';
 
21439 iD.actions.DeprecateTags = function(entityId) {
 
21440     return function(graph) {
 
21441         var entity = graph.entity(entityId),
 
21442             newtags = _.clone(entity.tags),
 
21446         // This handles deprecated tags with a single condition
 
21447         for (var i = 0; i < iD.data.deprecated.length; i++) {
 
21449             rule = iD.data.deprecated[i];
 
21450             var match = _.pairs(rule.old)[0],
 
21451                 replacements = rule.replace ? _.pairs(rule.replace) : null;
 
21453             if (entity.tags[match[0]] && match[1] === '*') {
 
21455                 var value = entity.tags[match[0]];
 
21456                 if (replacements && !newtags[replacements[0][0]]) {
 
21457                     newtags[replacements[0][0]] = value;
 
21459                 delete newtags[match[0]];
 
21462             } else if (entity.tags[match[0]] === match[1]) {
 
21463                 newtags = _.assign({}, rule.replace || {}, _.omit(newtags, match[0]));
 
21469             return graph.replace(entity.update({tags: newtags}));
 
21475 iD.actions.DiscardTags = function(difference) {
 
21476     return function(graph) {
 
21477         function discardTags(entity) {
 
21478             if (!_.isEmpty(entity.tags)) {
 
21480                 _.each(entity.tags, function(v, k) {
 
21481                     if (v) tags[k] = v;
 
21484                 graph = graph.replace(entity.update({
 
21485                     tags: _.omit(tags, iD.data.discarded)
 
21490         difference.modified().forEach(discardTags);
 
21491         difference.created().forEach(discardTags);
 
21496 // Disconect the ways at the given node.
 
21498 // Optionally, disconnect only the given ways.
 
21500 // For testing convenience, accepts an ID to assign to the (first) new node.
 
21501 // Normally, this will be undefined and the way will automatically
 
21502 // be assigned a new ID.
 
21504 // This is the inverse of `iD.actions.Connect`.
 
21507 //   https://github.com/openstreetmap/potlatch2/blob/master/net/systemeD/halcyon/connection/actions/UnjoinNodeAction.as
 
21508 //   https://github.com/openstreetmap/josm/blob/mirror/src/org/openstreetmap/josm/actions/UnGlueAction.java
 
21510 iD.actions.Disconnect = function(nodeId, newNodeId) {
 
21513     var action = function(graph) {
 
21514         var node = graph.entity(nodeId),
 
21515             connections = action.connections(graph);
 
21517         connections.forEach(function(connection) {
 
21518             var way = graph.entity(connection.wayID),
 
21519                 newNode = iD.Node({id: newNodeId, loc: node.loc, tags: node.tags});
 
21521             graph = graph.replace(newNode);
 
21522             if (connection.index === 0 && way.isArea()) {
 
21523                 // replace shared node with shared node..
 
21524                 graph = graph.replace(way.replaceNode(way.nodes[0], newNode.id));
 
21526                 // replace shared node with multiple new nodes..
 
21527                 graph = graph.replace(way.updateNode(newNode.id, connection.index));
 
21534     action.connections = function(graph) {
 
21535         var candidates = [],
 
21537             parentWays = graph.parentWays(graph.entity(nodeId));
 
21539         parentWays.forEach(function(way) {
 
21540             if (wayIds && wayIds.indexOf(way.id) === -1) {
 
21544             if (way.isArea() && (way.nodes[0] === nodeId)) {
 
21545                 candidates.push({wayID: way.id, index: 0});
 
21547                 way.nodes.forEach(function(waynode, index) {
 
21548                     if (waynode === nodeId) {
 
21549                         candidates.push({wayID: way.id, index: index});
 
21555         return keeping ? candidates : candidates.slice(1);
 
21558     action.disabled = function(graph) {
 
21559         var connections = action.connections(graph);
 
21560         if (connections.length === 0 || (wayIds && wayIds.length !== connections.length))
 
21561             return 'not_connected';
 
21563         var parentWays = graph.parentWays(graph.entity(nodeId)),
 
21564             seenRelationIds = {},
 
21567         parentWays.forEach(function(way) {
 
21568             if (wayIds && wayIds.indexOf(way.id) === -1)
 
21571             var relations = graph.parentRelations(way);
 
21572             relations.forEach(function(relation) {
 
21573                 if (relation.id in seenRelationIds) {
 
21574                     sharedRelation = relation;
 
21576                     seenRelationIds[relation.id] = true;
 
21581         if (sharedRelation)
 
21585     action.limitWays = function(_) {
 
21586         if (!arguments.length) return wayIds;
 
21593 // Join ways at the end node they share.
 
21595 // This is the inverse of `iD.actions.Split`.
 
21598 //   https://github.com/systemed/potlatch2/blob/master/net/systemeD/halcyon/connection/actions/MergeWaysAction.as
 
21599 //   https://github.com/openstreetmap/josm/blob/mirror/src/org/openstreetmap/josm/actions/CombineWayAction.java
 
21601 iD.actions.Join = function(ids) {
 
21603     function groupEntitiesByGeometry(graph) {
 
21604         var entities = ids.map(function(id) { return graph.entity(id); });
 
21605         return _.extend({line: []}, _.groupBy(entities, function(entity) { return entity.geometry(graph); }));
 
21608     var action = function(graph) {
 
21609         var ways = ids.map(graph.entity, graph),
 
21610             survivor = ways[0];
 
21612         // Prefer to keep an existing way.
 
21613         for (var i = 0; i < ways.length; i++) {
 
21614             if (!ways[i].isNew()) {
 
21615                 survivor = ways[i];
 
21620         var joined = iD.geo.joinWays(ways, graph)[0];
 
21622         survivor = survivor.update({nodes: _.pluck(joined.nodes, 'id')});
 
21623         graph = graph.replace(survivor);
 
21625         joined.forEach(function(way) {
 
21626             if (way.id === survivor.id)
 
21629             graph.parentRelations(way).forEach(function(parent) {
 
21630                 graph = graph.replace(parent.replaceMember(way, survivor));
 
21633             survivor = survivor.mergeTags(way.tags);
 
21635             graph = graph.replace(survivor);
 
21636             graph = iD.actions.DeleteWay(way.id)(graph);
 
21642     action.disabled = function(graph) {
 
21643         var geometries = groupEntitiesByGeometry(graph);
 
21644         if (ids.length < 2 || ids.length !== geometries.line.length)
 
21645             return 'not_eligible';
 
21647         var joined = iD.geo.joinWays(ids.map(graph.entity, graph), graph);
 
21648         if (joined.length > 1)
 
21649             return 'not_adjacent';
 
21651         var nodeIds = _.pluck(joined[0].nodes, 'id').slice(1, -1),
 
21654             conflicting = false;
 
21656         joined[0].forEach(function(way) {
 
21657             var parents = graph.parentRelations(way);
 
21658             parents.forEach(function(parent) {
 
21659                 if (parent.isRestriction() && parent.members.some(function(m) { return nodeIds.indexOf(m.id) >= 0; }))
 
21663             for (var k in way.tags) {
 
21664                 if (!(k in tags)) {
 
21665                     tags[k] = way.tags[k];
 
21666                 } else if (tags[k] && iD.interestingTag(k) && tags[k] !== way.tags[k]) {
 
21667                     conflicting = true;
 
21673             return 'restriction';
 
21676             return 'conflicting_tags';
 
21681 iD.actions.Merge = function(ids) {
 
21682     function groupEntitiesByGeometry(graph) {
 
21683         var entities = ids.map(function(id) { return graph.entity(id); });
 
21684         return _.extend({point: [], area: [], line: [], relation: []},
 
21685             _.groupBy(entities, function(entity) { return entity.geometry(graph); }));
 
21688     var action = function(graph) {
 
21689         var geometries = groupEntitiesByGeometry(graph),
 
21690             target = geometries.area[0] || geometries.line[0],
 
21691             points = geometries.point;
 
21693         points.forEach(function(point) {
 
21694             target = target.mergeTags(point.tags);
 
21696             graph.parentRelations(point).forEach(function(parent) {
 
21697                 graph = graph.replace(parent.replaceMember(point, target));
 
21700             graph = graph.remove(point);
 
21703         graph = graph.replace(target);
 
21708     action.disabled = function(graph) {
 
21709         var geometries = groupEntitiesByGeometry(graph);
 
21710         if (geometries.point.length === 0 ||
 
21711             (geometries.area.length + geometries.line.length) !== 1 ||
 
21712             geometries.relation.length !== 0)
 
21713             return 'not_eligible';
 
21718 iD.actions.MergePolygon = function(ids, newRelationId) {
 
21720     function groupEntities(graph) {
 
21721         var entities = ids.map(function (id) { return graph.entity(id); });
 
21726             }, _.groupBy(entities, function(entity) {
 
21727                 if (entity.type === 'way' && entity.isClosed()) {
 
21728                     return 'closedWay';
 
21729                 } else if (entity.type === 'relation' && entity.isMultipolygon()) {
 
21730                     return 'multipolygon';
 
21737     var action = function(graph) {
 
21738         var entities = groupEntities(graph);
 
21740         // An array representing all the polygons that are part of the multipolygon.
 
21742         // Each element is itself an array of objects with an id property, and has a
 
21743         // locs property which is an array of the locations forming the polygon.
 
21744         var polygons = entities.multipolygon.reduce(function(polygons, m) {
 
21745             return polygons.concat(iD.geo.joinWays(m.members, graph));
 
21746         }, []).concat(entities.closedWay.map(function(d) {
 
21747             var member = [{id: d.id}];
 
21748             member.nodes = graph.childNodes(d);
 
21752         // contained is an array of arrays of boolean values,
 
21753         // where contained[j][k] is true iff the jth way is
 
21754         // contained by the kth way.
 
21755         var contained = polygons.map(function(w, i) {
 
21756             return polygons.map(function(d, n) {
 
21757                 if (i === n) return null;
 
21758                 return iD.geo.polygonContainsPolygon(
 
21759                     _.pluck(d.nodes, 'loc'),
 
21760                     _.pluck(w.nodes, 'loc'));
 
21764         // Sort all polygons as either outer or inner ways
 
21768         while (polygons.length) {
 
21769             extractUncontained(polygons);
 
21770             polygons = polygons.filter(isContained);
 
21771             contained = contained.filter(isContained).map(filterContained);
 
21774         function isContained(d, i) {
 
21775             return _.any(contained[i]);
 
21778         function filterContained(d) {
 
21779             return d.filter(isContained);
 
21782         function extractUncontained(polygons) {
 
21783             polygons.forEach(function(d, i) {
 
21784                 if (!isContained(d, i)) {
 
21785                     d.forEach(function(member) {
 
21789                             role: outer ? 'outer' : 'inner'
 
21797         // Move all tags to one relation
 
21798         var relation = entities.multipolygon[0] ||
 
21799             iD.Relation({ id: newRelationId, tags: { type: 'multipolygon' }});
 
21801         entities.multipolygon.slice(1).forEach(function(m) {
 
21802             relation = relation.mergeTags(m.tags);
 
21803             graph = graph.remove(m);
 
21806         entities.closedWay.forEach(function(way) {
 
21807             function isThisOuter(m) {
 
21808                 return m.id === way.id && m.role !== 'inner';
 
21810             if (members.some(isThisOuter)) {
 
21811                 relation = relation.mergeTags(way.tags);
 
21812                 graph = graph.replace(way.update({ tags: {} }));
 
21816         return graph.replace(relation.update({
 
21818             tags: _.omit(relation.tags, 'area')
 
21822     action.disabled = function(graph) {
 
21823         var entities = groupEntities(graph);
 
21824         if (entities.other.length > 0 ||
 
21825             entities.closedWay.length + entities.multipolygon.length < 2)
 
21826             return 'not_eligible';
 
21827         if (!entities.multipolygon.every(function(r) { return r.isComplete(graph); }))
 
21828             return 'incomplete_relation';
 
21833 iD.actions.MergeRemoteChanges = function(id, localGraph, remoteGraph, formatUser) {
 
21834     var option = 'safe',  // 'safe', 'force_local', 'force_remote'
 
21838         return _.isFunction(formatUser) ? formatUser(d) : d;
 
21842     function mergeLocation(remote, target) {
 
21843         function pointEqual(a, b) {
 
21844             var epsilon = 1e-6;
 
21845             return (Math.abs(a[0] - b[0]) < epsilon) && (Math.abs(a[1] - b[1]) < epsilon);
 
21848         if (option === 'force_local' || pointEqual(target.loc, remote.loc)) {
 
21851         if (option === 'force_remote') {
 
21852             return target.update({loc: remote.loc});
 
21855         conflicts.push(t('merge_remote_changes.conflict.location', { user: user(remote.user) }));
 
21860     function mergeNodes(base, remote, target) {
 
21861         if (option === 'force_local' || _.isEqual(target.nodes, remote.nodes)) {
 
21864         if (option === 'force_remote') {
 
21865             return target.update({nodes: remote.nodes});
 
21868         var ccount = conflicts.length,
 
21869             o = base.nodes || [],
 
21870             a = target.nodes || [],
 
21871             b = remote.nodes || [],
 
21873             hunks = Diff3.diff3_merge(a, o, b, true);
 
21875         for (var i = 0; i < hunks.length; i++) {
 
21876             var hunk = hunks[i];
 
21878                 nodes.push.apply(nodes, hunk.ok);
 
21880                 // for all conflicts, we can assume c.a !== c.b
 
21881                 // because `diff3_merge` called with `true` option to exclude false conflicts..
 
21882                 var c = hunk.conflict;
 
21883                 if (_.isEqual(c.o, c.a)) {  // only changed remotely
 
21884                     nodes.push.apply(nodes, c.b);
 
21885                 } else if (_.isEqual(c.o, c.b)) {  // only changed locally
 
21886                     nodes.push.apply(nodes, c.a);
 
21887                 } else {       // changed both locally and remotely
 
21888                     conflicts.push(t('merge_remote_changes.conflict.nodelist', { user: user(remote.user) }));
 
21894         return (conflicts.length === ccount) ? target.update({nodes: nodes}) : target;
 
21898     function mergeChildren(targetWay, children, updates, graph) {
 
21899         function isUsed(node, targetWay) {
 
21900             var parentWays = _.pluck(graph.parentWays(node), 'id');
 
21901             return node.hasInterestingTags() ||
 
21902                 _.without(parentWays, targetWay.id).length > 0 ||
 
21903                 graph.parentRelations(node).length > 0;
 
21906         var ccount = conflicts.length;
 
21908         for (var i = 0; i < children.length; i++) {
 
21909             var id = children[i],
 
21910                 node = graph.hasEntity(id);
 
21912             // remove unused childNodes..
 
21913             if (targetWay.nodes.indexOf(id) === -1) {
 
21914                 if (node && !isUsed(node, targetWay)) {
 
21915                     updates.removeIds.push(id);
 
21920             // restore used childNodes..
 
21921             var local = localGraph.hasEntity(id),
 
21922                 remote = remoteGraph.hasEntity(id),
 
21925             if (option === 'force_remote' && remote && remote.visible) {
 
21926                 updates.replacements.push(remote);
 
21928             } else if (option === 'force_local' && local) {
 
21929                 target = iD.Entity(local);
 
21931                     target = target.update({ version: remote.version });
 
21933                 updates.replacements.push(target);
 
21935             } else if (option === 'safe' && local && remote && local.version !== remote.version) {
 
21936                 target = iD.Entity(local, { version: remote.version });
 
21937                 if (remote.visible) {
 
21938                     target = mergeLocation(remote, target);
 
21940                     conflicts.push(t('merge_remote_changes.conflict.deleted', { user: user(remote.user) }));
 
21943                 if (conflicts.length !== ccount) break;
 
21944                 updates.replacements.push(target);
 
21952     function updateChildren(updates, graph) {
 
21953         for (var i = 0; i < updates.replacements.length; i++) {
 
21954             graph = graph.replace(updates.replacements[i]);
 
21956         if (updates.removeIds.length) {
 
21957             graph = iD.actions.DeleteMultiple(updates.removeIds)(graph);
 
21963     function mergeMembers(remote, target) {
 
21964         if (option === 'force_local' || _.isEqual(target.members, remote.members)) {
 
21967         if (option === 'force_remote') {
 
21968             return target.update({members: remote.members});
 
21971         conflicts.push(t('merge_remote_changes.conflict.memberlist', { user: user(remote.user) }));
 
21976     function mergeTags(base, remote, target) {
 
21977         function ignoreKey(k) {
 
21978             return _.contains(iD.data.discarded, k);
 
21981         if (option === 'force_local' || _.isEqual(target.tags, remote.tags)) {
 
21984         if (option === 'force_remote') {
 
21985             return target.update({tags: remote.tags});
 
21988         var ccount = conflicts.length,
 
21989             o = base.tags || {},
 
21990             a = target.tags || {},
 
21991             b = remote.tags || {},
 
21992             keys = _.reject(_.union(_.keys(o), _.keys(a), _.keys(b)), ignoreKey),
 
21996         for (var i = 0; i < keys.length; i++) {
 
21999             if (o[k] !== b[k] && a[k] !== b[k]) {    // changed remotely..
 
22000                 if (o[k] !== a[k]) {      // changed locally..
 
22001                     conflicts.push(t('merge_remote_changes.conflict.tags',
 
22002                         { tag: k, local: a[k], remote: b[k], user: user(remote.user) }));
 
22004                 } else {                  // unchanged locally, accept remote change..
 
22005                     if (b.hasOwnProperty(k)) {
 
22015         return (changed && conflicts.length === ccount) ? target.update({tags: tags}) : target;
 
22019     //  `graph.base()` is the common ancestor of the two graphs.
 
22020     //  `localGraph` contains user's edits up to saving
 
22021     //  `remoteGraph` contains remote edits to modified nodes
 
22022     //  `graph` must be a descendent of `localGraph` and may include
 
22023     //      some conflict resolution actions performed on it.
 
22025     //                  --- ... --- `localGraph` -- ... -- `graph`
 
22027     //  `graph.base()` --- ... --- `remoteGraph`
 
22029     var action = function(graph) {
 
22030         var updates = { replacements: [], removeIds: [] },
 
22031             base = graph.base().entities[id],
 
22032             local = localGraph.entity(id),
 
22033             remote = remoteGraph.entity(id),
 
22034             target = iD.Entity(local, { version: remote.version });
 
22037         if (!remote.visible) {
 
22038             if (option === 'force_remote') {
 
22039                 return iD.actions.DeleteMultiple([id])(graph);
 
22041             } else if (option === 'force_local') {
 
22042                 if (target.type === 'way') {
 
22043                     target = mergeChildren(target, _.uniq(local.nodes), updates, graph);
 
22044                     graph = updateChildren(updates, graph);
 
22046                 return graph.replace(target);
 
22049                 conflicts.push(t('merge_remote_changes.conflict.deleted', { user: user(remote.user) }));
 
22050                 return graph;  // do nothing
 
22055         if (target.type === 'node') {
 
22056             target = mergeLocation(remote, target);
 
22058         } else if (target.type === 'way') {
 
22059             // pull in any child nodes that may not be present locally..
 
22060             graph.rebase(remoteGraph.childNodes(remote), [graph], false);
 
22061             target = mergeNodes(base, remote, target);
 
22062             target = mergeChildren(target, _.union(local.nodes, remote.nodes), updates, graph);
 
22064         } else if (target.type === 'relation') {
 
22065             target = mergeMembers(remote, target);
 
22068         target = mergeTags(base, remote, target);
 
22070         if (!conflicts.length) {
 
22071             graph = updateChildren(updates, graph).replace(target);
 
22077     action.withOption = function(opt) {
 
22082     action.conflicts = function() {
 
22088 // https://github.com/openstreetmap/josm/blob/mirror/src/org/openstreetmap/josm/command/MoveCommand.java
 
22089 // https://github.com/openstreetmap/potlatch2/blob/master/net/systemeD/halcyon/connection/actions/MoveNodeAction.as
 
22090 iD.actions.Move = function(moveIds, tryDelta, projection, cache) {
 
22091     var delta = tryDelta;
 
22093     function vecAdd(a, b) { return [a[0] + b[0], a[1] + b[1]]; }
 
22094     function vecSub(a, b) { return [a[0] - b[0], a[1] - b[1]]; }
 
22096     function setupCache(graph) {
 
22097         function canMove(nodeId) {
 
22098             var parents = _.pluck(graph.parentWays(graph.entity(nodeId)), 'id');
 
22099             if (parents.length < 3) return true;
 
22101             // Don't move a vertex where >2 ways meet, unless all parentWays are moving too..
 
22102             var parentsMoving = _.all(parents, function(id) { return cache.moving[id]; });
 
22103             if (!parentsMoving) delete cache.moving[nodeId];
 
22105             return parentsMoving;
 
22108         function cacheEntities(ids) {
 
22109             _.each(ids, function(id) {
 
22110                 if (cache.moving[id]) return;
 
22111                 cache.moving[id] = true;
 
22113                 var entity = graph.hasEntity(id);
 
22114                 if (!entity) return;
 
22116                 if (entity.type === 'node') {
 
22117                     cache.nodes.push(id);
 
22118                     cache.startLoc[id] = entity.loc;
 
22119                 } else if (entity.type === 'way') {
 
22120                     cache.ways.push(id);
 
22121                     cacheEntities(entity.nodes);
 
22123                     cacheEntities(_.pluck(entity.members, 'id'));
 
22128         function cacheIntersections(ids) {
 
22129             function isEndpoint(way, id) { return !way.isClosed() && !!way.affix(id); }
 
22131             _.each(ids, function(id) {
 
22132                 // consider only intersections with 1 moved and 1 unmoved way.
 
22133                 _.each(graph.childNodes(graph.entity(id)), function(node) {
 
22134                     var parents = graph.parentWays(node);
 
22135                     if (parents.length !== 2) return;
 
22137                     var moved = graph.entity(id),
 
22138                         unmoved = _.find(parents, function(way) { return !cache.moving[way.id]; });
 
22139                     if (!unmoved) return;
 
22141                     // exclude ways that are overly connected..
 
22142                     if (_.intersection(moved.nodes, unmoved.nodes).length > 2) return;
 
22144                     if (moved.isArea() || unmoved.isArea()) return;
 
22146                     cache.intersection[node.id] = {
 
22149                         unmovedId: unmoved.id,
 
22150                         movedIsEP: isEndpoint(moved, node.id),
 
22151                         unmovedIsEP: isEndpoint(unmoved, node.id)
 
22163             cache.intersection = {};
 
22164             cache.replacedVertex = {};
 
22165             cache.startLoc = {};
 
22169             cacheEntities(moveIds);
 
22170             cacheIntersections(cache.ways);
 
22171             cache.nodes = _.filter(cache.nodes, canMove);
 
22178     // Place a vertex where the moved vertex used to be, to preserve way shape..
 
22179     function replaceMovedVertex(nodeId, wayId, graph, delta) {
 
22180         var way = graph.entity(wayId),
 
22181             moved = graph.entity(nodeId),
 
22182             movedIndex = way.nodes.indexOf(nodeId),
 
22183             len, prevIndex, nextIndex;
 
22185         if (way.isClosed()) {
 
22186             len = way.nodes.length - 1;
 
22187             prevIndex = (movedIndex + len - 1) % len;
 
22188             nextIndex = (movedIndex + len + 1) % len;
 
22190             len = way.nodes.length;
 
22191             prevIndex = movedIndex - 1;
 
22192             nextIndex = movedIndex + 1;
 
22195         var prev = graph.hasEntity(way.nodes[prevIndex]),
 
22196             next = graph.hasEntity(way.nodes[nextIndex]);
 
22198         // Don't add orig vertex at endpoint..
 
22199         if (!prev || !next) return graph;
 
22201         var key = wayId + '_' + nodeId,
 
22202             orig = cache.replacedVertex[key];
 
22205             cache.replacedVertex[key] = orig;
 
22206             cache.startLoc[orig.id] = cache.startLoc[nodeId];
 
22211             start = projection(cache.startLoc[nodeId]);
 
22212             end = projection.invert(vecAdd(start, delta));
 
22214             end = cache.startLoc[nodeId];
 
22216         orig = orig.move(end);
 
22218         var angle = Math.abs(iD.geo.angle(orig, prev, projection) -
 
22219                 iD.geo.angle(orig, next, projection)) * 180 / Math.PI;
 
22221         // Don't add orig vertex if it would just make a straight line..
 
22222         if (angle > 175 && angle < 185) return graph;
 
22224         // Don't add orig vertex if another point is already nearby (within 10m)
 
22225         if (iD.geo.sphericalDistance(prev.loc, orig.loc) < 10 ||
 
22226             iD.geo.sphericalDistance(orig.loc, next.loc) < 10) return graph;
 
22228         // moving forward or backward along way?
 
22229         var p1 = [prev.loc, orig.loc, moved.loc, next.loc].map(projection),
 
22230             p2 = [prev.loc, moved.loc, orig.loc, next.loc].map(projection),
 
22231             d1 = iD.geo.pathLength(p1),
 
22232             d2 = iD.geo.pathLength(p2),
 
22233             insertAt = (d1 < d2) ? movedIndex : nextIndex;
 
22235         // moving around closed loop?
 
22236         if (way.isClosed() && insertAt === 0) insertAt = len;
 
22238         way = way.addNode(orig.id, insertAt);
 
22239         return graph.replace(orig).replace(way);
 
22242     // Reorder nodes around intersections that have moved..
 
22243     function unZorroIntersection(intersection, graph) {
 
22244         var vertex = graph.entity(intersection.nodeId),
 
22245             way1 = graph.entity(intersection.movedId),
 
22246             way2 = graph.entity(intersection.unmovedId),
 
22247             isEP1 = intersection.movedIsEP,
 
22248             isEP2 = intersection.unmovedIsEP;
 
22250         // don't move the vertex if it is the endpoint of both ways.
 
22251         if (isEP1 && isEP2) return graph;
 
22253         var nodes1 = _.without(graph.childNodes(way1), vertex),
 
22254             nodes2 = _.without(graph.childNodes(way2), vertex);
 
22256         if (way1.isClosed() && way1.first() === vertex.id) nodes1.push(nodes1[0]);
 
22257         if (way2.isClosed() && way2.first() === vertex.id) nodes2.push(nodes2[0]);
 
22259         var edge1 = !isEP1 && iD.geo.chooseEdge(nodes1, projection(vertex.loc), projection),
 
22260             edge2 = !isEP2 && iD.geo.chooseEdge(nodes2, projection(vertex.loc), projection),
 
22263         // snap vertex to nearest edge (or some point between them)..
 
22264         if (!isEP1 && !isEP2) {
 
22265             var epsilon = 1e-4, maxIter = 10;
 
22266             for (var i = 0; i < maxIter; i++) {
 
22267                 loc = iD.geo.interp(edge1.loc, edge2.loc, 0.5);
 
22268                 edge1 = iD.geo.chooseEdge(nodes1, projection(loc), projection);
 
22269                 edge2 = iD.geo.chooseEdge(nodes2, projection(loc), projection);
 
22270                 if (Math.abs(edge1.distance - edge2.distance) < epsilon) break;
 
22272         } else if (!isEP1) {
 
22278         graph = graph.replace(vertex.move(loc));
 
22280         // if zorro happened, reorder nodes..
 
22281         if (!isEP1 && edge1.index !== way1.nodes.indexOf(vertex.id)) {
 
22282             way1 = way1.removeNode(vertex.id).addNode(vertex.id, edge1.index);
 
22283             graph = graph.replace(way1);
 
22285         if (!isEP2 && edge2.index !== way2.nodes.indexOf(vertex.id)) {
 
22286             way2 = way2.removeNode(vertex.id).addNode(vertex.id, edge2.index);
 
22287             graph = graph.replace(way2);
 
22294     function cleanupIntersections(graph) {
 
22295         _.each(cache.intersection, function(obj) {
 
22296             graph = replaceMovedVertex(obj.nodeId, obj.movedId, graph, delta);
 
22297             graph = replaceMovedVertex(obj.nodeId, obj.unmovedId, graph, null);
 
22298             graph = unZorroIntersection(obj, graph);
 
22304     // check if moving way endpoint can cross an unmoved way, if so limit delta..
 
22305     function limitDelta(graph) {
 
22306         _.each(cache.intersection, function(obj) {
 
22307             if (!obj.movedIsEP) return;
 
22309             var node = graph.entity(obj.nodeId),
 
22310                 start = projection(node.loc),
 
22311                 end = vecAdd(start, delta),
 
22312                 movedNodes = graph.childNodes(graph.entity(obj.movedId)),
 
22313                 movedPath = _.map(_.pluck(movedNodes, 'loc'),
 
22314                     function(loc) { return vecAdd(projection(loc), delta); }),
 
22315                 unmovedNodes = graph.childNodes(graph.entity(obj.unmovedId)),
 
22316                 unmovedPath = _.map(_.pluck(unmovedNodes, 'loc'), projection),
 
22317                 hits = iD.geo.pathIntersections(movedPath, unmovedPath);
 
22319             for (var i = 0; i < hits.length; i++) {
 
22320                 if (_.isEqual(hits[i], end)) continue;
 
22321                 var edge = iD.geo.chooseEdge(unmovedNodes, end, projection);
 
22322                 delta = vecSub(projection(edge.loc), start);
 
22328     var action = function(graph) {
 
22329         if (delta[0] === 0 && delta[1] === 0) return graph;
 
22333         if (!_.isEmpty(cache.intersection)) {
 
22337         _.each(cache.nodes, function(id) {
 
22338             var node = graph.entity(id),
 
22339                 start = projection(node.loc),
 
22340                 end = vecAdd(start, delta);
 
22341             graph = graph.replace(node.move(projection.invert(end)));
 
22344         if (!_.isEmpty(cache.intersection)) {
 
22345             graph = cleanupIntersections(graph);
 
22351     action.disabled = function(graph) {
 
22352         function incompleteRelation(id) {
 
22353             var entity = graph.entity(id);
 
22354             return entity.type === 'relation' && !entity.isComplete(graph);
 
22357         if (_.any(moveIds, incompleteRelation))
 
22358             return 'incomplete_relation';
 
22361     action.delta = function() {
 
22367 // https://github.com/openstreetmap/josm/blob/mirror/src/org/openstreetmap/josm/command/MoveCommand.java
 
22368 // https://github.com/openstreetmap/potlatch2/blob/master/net/systemeD/halcyon/connection/actions/MoveNodeAction.as
 
22369 iD.actions.MoveNode = function(nodeId, loc) {
 
22370     return function(graph) {
 
22371         return graph.replace(graph.entity(nodeId).move(loc));
 
22374 iD.actions.Noop = function() {
 
22375     return function(graph) {
 
22380  * Based on https://github.com/openstreetmap/potlatch2/blob/master/net/systemeD/potlatch2/tools/Quadrilateralise.as
 
22383 iD.actions.Orthogonalize = function(wayId, projection) {
 
22384     var threshold = 12, // degrees within right or straight to alter
 
22385         lowerThreshold = Math.cos((90 - threshold) * Math.PI / 180),
 
22386         upperThreshold = Math.cos(threshold * Math.PI / 180);
 
22388     var action = function(graph) {
 
22389         var way = graph.entity(wayId),
 
22390             nodes = graph.childNodes(way),
 
22391             points = _.uniq(nodes).map(function(n) { return projection(n.loc); }),
 
22392             corner = {i: 0, dotp: 1},
 
22394             i, j, score, motions;
 
22396         if (nodes.length === 4) {
 
22397             for (i = 0; i < 1000; i++) {
 
22398                 motions = points.map(calcMotion);
 
22399                 points[corner.i] = addPoints(points[corner.i],motions[corner.i]);
 
22400                 score = corner.dotp;
 
22401                 if (score < epsilon) {
 
22406             graph = graph.replace(graph.entity(nodes[corner.i].id)
 
22407                 .move(projection.invert(points[corner.i])));
 
22410                 originalPoints = _.clone(points);
 
22413             for (i = 0; i < 1000; i++) {
 
22414                 motions = points.map(calcMotion);
 
22415                 for (j = 0; j < motions.length; j++) {
 
22416                     points[j] = addPoints(points[j],motions[j]);
 
22418                 var newScore = squareness(points);
 
22419                 if (newScore < score) {
 
22420                     best = _.clone(points);
 
22423                 if (score < epsilon) {
 
22430             for (i = 0; i < points.length; i++) {
 
22431                 // only move the points that actually moved
 
22432                 if (originalPoints[i][0] !== points[i][0] || originalPoints[i][1] !== points[i][1]) {
 
22433                     graph = graph.replace(graph.entity(nodes[i].id)
 
22434                         .move(projection.invert(points[i])));
 
22438             // remove empty nodes on straight sections
 
22439             for (i = 0; i < points.length; i++) {
 
22440                 var node = nodes[i];
 
22442                 if (graph.parentWays(node).length > 1 ||
 
22443                     graph.parentRelations(node).length ||
 
22444                     node.hasInterestingTags()) {
 
22449                 var dotp = normalizedDotProduct(i, points);
 
22450                 if (dotp < -1 + epsilon) {
 
22451                     graph = iD.actions.DeleteNode(nodes[i].id)(graph);
 
22458         function calcMotion(b, i, array) {
 
22459             var a = array[(i - 1 + array.length) % array.length],
 
22460                 c = array[(i + 1) % array.length],
 
22461                 p = subtractPoints(a, b),
 
22462                 q = subtractPoints(c, b),
 
22465             scale = 2 * Math.min(iD.geo.euclideanDistance(p, [0, 0]), iD.geo.euclideanDistance(q, [0, 0]));
 
22466             p = normalizePoint(p, 1.0);
 
22467             q = normalizePoint(q, 1.0);
 
22469             dotp = filterDotProduct(p[0] * q[0] + p[1] * q[1]);
 
22471             // nasty hack to deal with almost-straight segments (angle is closer to 180 than to 90/270).
 
22472             if (array.length > 3) {
 
22473                 if (dotp < -0.707106781186547) {
 
22476             } else if (dotp && Math.abs(dotp) < corner.dotp) {
 
22478                 corner.dotp = Math.abs(dotp);
 
22481             return normalizePoint(addPoints(p, q), 0.1 * dotp * scale);
 
22485     function squareness(points) {
 
22486         return points.reduce(function(sum, val, i, array) {
 
22487             var dotp = normalizedDotProduct(i, array);
 
22489             dotp = filterDotProduct(dotp);
 
22490             return sum + 2.0 * Math.min(Math.abs(dotp - 1.0), Math.min(Math.abs(dotp), Math.abs(dotp + 1)));
 
22494     function normalizedDotProduct(i, points) {
 
22495         var a = points[(i - 1 + points.length) % points.length],
 
22497             c = points[(i + 1) % points.length],
 
22498             p = subtractPoints(a, b),
 
22499             q = subtractPoints(c, b);
 
22501         p = normalizePoint(p, 1.0);
 
22502         q = normalizePoint(q, 1.0);
 
22504         return p[0] * q[0] + p[1] * q[1];
 
22507     function subtractPoints(a, b) {
 
22508         return [a[0] - b[0], a[1] - b[1]];
 
22511     function addPoints(a, b) {
 
22512         return [a[0] + b[0], a[1] + b[1]];
 
22515     function normalizePoint(point, scale) {
 
22516         var vector = [0, 0];
 
22517         var length = Math.sqrt(point[0] * point[0] + point[1] * point[1]);
 
22518         if (length !== 0) {
 
22519             vector[0] = point[0] / length;
 
22520             vector[1] = point[1] / length;
 
22523         vector[0] *= scale;
 
22524         vector[1] *= scale;
 
22529     function filterDotProduct(dotp) {
 
22530         if (lowerThreshold > Math.abs(dotp) || Math.abs(dotp) > upperThreshold) {
 
22537     action.disabled = function(graph) {
 
22538         var way = graph.entity(wayId),
 
22539             nodes = graph.childNodes(way),
 
22540             points = _.uniq(nodes).map(function(n) { return projection(n.loc); });
 
22542         if (squareness(points)) {
 
22546         return 'not_squarish';
 
22551 // Create a restriction relation for `turn`, which must have the following structure:
 
22554 //         from: { node: <node ID>, way: <way ID> },
 
22555 //         via:  { node: <node ID> },
 
22556 //         to:   { node: <node ID>, way: <way ID> },
 
22557 //         restriction: <'no_right_turn', 'no_left_turn', etc.>
 
22560 // This specifies a restriction of type `restriction` when traveling from
 
22561 // `from.node` in `from.way` toward `to.node` in `to.way` via `via.node`.
 
22562 // (The action does not check that these entities form a valid intersection.)
 
22564 // If `restriction` is not provided, it is automatically determined by
 
22565 // iD.geo.inferRestriction.
 
22567 // If necessary, the `from` and `to` ways are split. In these cases, `from.node`
 
22568 // and `to.node` are used to determine which portion of the split ways become
 
22569 // members of the restriction.
 
22571 // For testing convenience, accepts an ID to assign to the new relation.
 
22572 // Normally, this will be undefined and the relation will automatically
 
22573 // be assigned a new ID.
 
22575 iD.actions.RestrictTurn = function(turn, projection, restrictionId) {
 
22576     return function(graph) {
 
22577         var from = graph.entity(turn.from.way),
 
22578             via  = graph.entity(turn.via.node),
 
22579             to   = graph.entity(turn.to.way);
 
22581         function isClosingNode(way, nodeId) {
 
22582             return nodeId === way.first() && nodeId === way.last();
 
22585         function split(toOrFrom) {
 
22586             var newID = toOrFrom.newID || iD.Way().id;
 
22587             graph = iD.actions.Split(via.id, [newID])
 
22588                 .limitWays([toOrFrom.way])(graph);
 
22590             var a = graph.entity(newID),
 
22591                 b = graph.entity(toOrFrom.way);
 
22593             if (a.nodes.indexOf(toOrFrom.node) !== -1) {
 
22600         if (!from.affix(via.id) || isClosingNode(from, via.id)) {
 
22601             if (turn.from.node === turn.to.node) {
 
22603                 from = to = split(turn.from)[0];
 
22604             } else if (turn.from.way === turn.to.way) {
 
22605                 // Straight-on or circular
 
22606                 var s = split(turn.from);
 
22611                 from = split(turn.from)[0];
 
22615         if (!to.affix(via.id) || isClosingNode(to, via.id)) {
 
22616             to = split(turn.to)[0];
 
22619         return graph.replace(iD.Relation({
 
22622                 type: 'restriction',
 
22623                 restriction: turn.restriction ||
 
22624                     iD.geo.inferRestriction(
 
22632                 {id: from.id, type: 'way',  role: 'from'},
 
22633                 {id: via.id,  type: 'node', role: 'via'},
 
22634                 {id: to.id,   type: 'way',  role: 'to'}
 
22640   Order the nodes of a way in reverse order and reverse any direction dependent tags
 
22641   other than `oneway`. (We assume that correcting a backwards oneway is the primary
 
22642   reason for reversing a way.)
 
22644   The following transforms are performed:
 
22647           *:right=* ⟺ *:left=*
 
22648         *:forward=* ⟺ *:backward=*
 
22649        direction=up ⟺ direction=down
 
22650          incline=up ⟺ incline=down
 
22654        role=forward ⟺ role=backward
 
22655          role=north ⟺ role=south
 
22656           role=east ⟺ role=west
 
22658    In addition, numeric-valued `incline` tags are negated.
 
22660    The JOSM implementation was used as a guide, but transformations that were of unclear benefit
 
22661    or adjusted tags that don't seem to be used in practice were omitted.
 
22664       http://wiki.openstreetmap.org/wiki/Forward_%26_backward,_left_%26_right
 
22665       http://wiki.openstreetmap.org/wiki/Key:direction#Steps
 
22666       http://wiki.openstreetmap.org/wiki/Key:incline
 
22667       http://wiki.openstreetmap.org/wiki/Route#Members
 
22668       http://josm.openstreetmap.de/browser/josm/trunk/src/org/openstreetmap/josm/corrector/ReverseWayTagCorrector.java
 
22670 iD.actions.Reverse = function(wayId, options) {
 
22671     var replacements = [
 
22672             [/:right$/, ':left'], [/:left$/, ':right'],
 
22673             [/:forward$/, ':backward'], [/:backward$/, ':forward']
 
22675         numeric = /^([+\-]?)(?=[\d.])/,
 
22677             forward: 'backward',
 
22678             backward: 'forward',
 
22685     function reverseKey(key) {
 
22686         for (var i = 0; i < replacements.length; ++i) {
 
22687             var replacement = replacements[i];
 
22688             if (replacement[0].test(key)) {
 
22689                 return key.replace(replacement[0], replacement[1]);
 
22695     function reverseValue(key, value) {
 
22696         if (key === 'incline' && numeric.test(value)) {
 
22697             return value.replace(numeric, function(_, sign) { return sign === '-' ? '' : '-'; });
 
22698         } else if (key === 'incline' || key === 'direction') {
 
22699             return {up: 'down', down: 'up'}[value] || value;
 
22700         } else if (options && options.reverseOneway && key === 'oneway') {
 
22701             return {yes: '-1', '1': '-1', '-1': 'yes'}[value] || value;
 
22703             return {left: 'right', right: 'left'}[value] || value;
 
22707     return function(graph) {
 
22708         var way = graph.entity(wayId),
 
22709             nodes = way.nodes.slice().reverse(),
 
22710             tags = {}, key, role;
 
22712         for (key in way.tags) {
 
22713             tags[reverseKey(key)] = reverseValue(key, way.tags[key]);
 
22716         graph.parentRelations(way).forEach(function(relation) {
 
22717             relation.members.forEach(function(member, index) {
 
22718                 if (member.id === way.id && (role = roleReversals[member.role])) {
 
22719                     relation = relation.updateMember({role: role}, index);
 
22720                     graph = graph.replace(relation);
 
22725         return graph.replace(way.update({nodes: nodes, tags: tags}));
 
22728 iD.actions.Revert = function(id) {
 
22730     var action = function(graph) {
 
22731         var entity = graph.hasEntity(id),
 
22732             base = graph.base().entities[id];
 
22734         if (entity && !base) {    // entity will be removed..
 
22735             if (entity.type === 'node') {
 
22736                 graph.parentWays(entity)
 
22737                     .forEach(function(parent) {
 
22738                         parent = parent.removeNode(id);
 
22739                         graph = graph.replace(parent);
 
22741                         if (parent.isDegenerate()) {
 
22742                             graph = iD.actions.DeleteWay(parent.id)(graph);
 
22747             graph.parentRelations(entity)
 
22748                 .forEach(function(parent) {
 
22749                     parent = parent.removeMembersWithID(id);
 
22750                     graph = graph.replace(parent);
 
22752                     if (parent.isDegenerate()) {
 
22753                         graph = iD.actions.DeleteRelation(parent.id)(graph);
 
22758         return graph.revert(id);
 
22763 iD.actions.RotateWay = function(wayId, pivot, angle, projection) {
 
22764     return function(graph) {
 
22765         return graph.update(function(graph) {
 
22766             var way = graph.entity(wayId);
 
22768             _.unique(way.nodes).forEach(function(id) {
 
22770                 var node = graph.entity(id),
 
22771                     point = projection(node.loc),
 
22774                 radial[0] = point[0] - pivot[0];
 
22775                 radial[1] = point[1] - pivot[1];
 
22778                     radial[0] * Math.cos(angle) - radial[1] * Math.sin(angle) + pivot[0],
 
22779                     radial[0] * Math.sin(angle) + radial[1] * Math.cos(angle) + pivot[1]
 
22782                 graph = graph.replace(node.move(projection.invert(point)));
 
22789 // Split a way at the given node.
 
22791 // Optionally, split only the given ways, if multiple ways share
 
22794 // This is the inverse of `iD.actions.Join`.
 
22796 // For testing convenience, accepts an ID to assign to the new way.
 
22797 // Normally, this will be undefined and the way will automatically
 
22798 // be assigned a new ID.
 
22801 //   https://github.com/systemed/potlatch2/blob/master/net/systemeD/halcyon/connection/actions/SplitWayAction.as
 
22803 iD.actions.Split = function(nodeId, newWayIds) {
 
22806     // if the way is closed, we need to search for a partner node
 
22807     // to split the way at.
 
22809     // The following looks for a node that is both far away from
 
22810     // the initial node in terms of way segment length and nearby
 
22811     // in terms of beeline-distance. This assures that areas get
 
22812     // split on the most "natural" points (independent of the number
 
22814     // For example: bone-shaped areas get split across their waist
 
22815     // line, circles across the diameter.
 
22816     function splitArea(nodes, idxA, graph) {
 
22817         var lengths = new Array(nodes.length),
 
22823         function wrap(index) {
 
22824             return iD.util.wrap(index, nodes.length);
 
22827         function dist(nA, nB) {
 
22828             return iD.geo.sphericalDistance(graph.entity(nA).loc, graph.entity(nB).loc);
 
22831         // calculate lengths
 
22833         for (i = wrap(idxA+1); i !== idxA; i = wrap(i+1)) {
 
22834             length += dist(nodes[i], nodes[wrap(i-1)]);
 
22835             lengths[i] = length;
 
22839         for (i = wrap(idxA-1); i !== idxA; i = wrap(i-1)) {
 
22840             length += dist(nodes[i], nodes[wrap(i+1)]);
 
22841             if (length < lengths[i])
 
22842                 lengths[i] = length;
 
22845         // determine best opposite node to split
 
22846         for (i = 0; i < nodes.length; i++) {
 
22847             var cost = lengths[i] / dist(nodes[idxA], nodes[i]);
 
22857     function split(graph, wayA, newWayId) {
 
22858         var wayB = iD.Way({id: newWayId, tags: wayA.tags}),
 
22861             isArea = wayA.isArea(),
 
22862             isOuter = iD.geo.isSimpleMultipolygonOuterMember(wayA, graph);
 
22864         if (wayA.isClosed()) {
 
22865             var nodes = wayA.nodes.slice(0, -1),
 
22866                 idxA = _.indexOf(nodes, nodeId),
 
22867                 idxB = splitArea(nodes, idxA, graph);
 
22870                 nodesA = nodes.slice(idxA).concat(nodes.slice(0, idxB + 1));
 
22871                 nodesB = nodes.slice(idxB, idxA + 1);
 
22873                 nodesA = nodes.slice(idxA, idxB + 1);
 
22874                 nodesB = nodes.slice(idxB).concat(nodes.slice(0, idxA + 1));
 
22877             var idx = _.indexOf(wayA.nodes, nodeId, 1);
 
22878             nodesA = wayA.nodes.slice(0, idx + 1);
 
22879             nodesB = wayA.nodes.slice(idx);
 
22882         wayA = wayA.update({nodes: nodesA});
 
22883         wayB = wayB.update({nodes: nodesB});
 
22885         graph = graph.replace(wayA);
 
22886         graph = graph.replace(wayB);
 
22888         graph.parentRelations(wayA).forEach(function(relation) {
 
22889             if (relation.isRestriction()) {
 
22890                 var via = relation.memberByRole('via');
 
22891                 if (via && wayB.contains(via.id)) {
 
22892                     relation = relation.updateMember({id: wayB.id}, relation.memberById(wayA.id).index);
 
22893                     graph = graph.replace(relation);
 
22896                 if (relation === isOuter) {
 
22897                     graph = graph.replace(relation.mergeTags(wayA.tags));
 
22898                     graph = graph.replace(wayA.update({tags: {}}));
 
22899                     graph = graph.replace(wayB.update({tags: {}}));
 
22905                     role: relation.memberById(wayA.id).role
 
22908                 graph = iD.actions.AddMember(relation.id, member)(graph);
 
22912         if (!isOuter && isArea) {
 
22913             var multipolygon = iD.Relation({
 
22914                 tags: _.extend({}, wayA.tags, {type: 'multipolygon'}),
 
22916                     {id: wayA.id, role: 'outer', type: 'way'},
 
22917                     {id: wayB.id, role: 'outer', type: 'way'}
 
22920             graph = graph.replace(multipolygon);
 
22921             graph = graph.replace(wayA.update({tags: {}}));
 
22922             graph = graph.replace(wayB.update({tags: {}}));
 
22928     var action = function(graph) {
 
22929         var candidates = action.ways(graph);
 
22930         for (var i = 0; i < candidates.length; i++) {
 
22931             graph = split(graph, candidates[i], newWayIds && newWayIds[i]);
 
22936     action.ways = function(graph) {
 
22937         var node = graph.entity(nodeId),
 
22938             parents = graph.parentWays(node),
 
22939             hasLines = _.any(parents, function(parent) { return parent.geometry(graph) === 'line'; });
 
22941         return parents.filter(function(parent) {
 
22942             if (wayIds && wayIds.indexOf(parent.id) === -1)
 
22945             if (!wayIds && hasLines && parent.geometry(graph) !== 'line')
 
22948             if (parent.isClosed()) {
 
22952             for (var i = 1; i < parent.nodes.length - 1; i++) {
 
22953                 if (parent.nodes[i] === nodeId) {
 
22962     action.disabled = function(graph) {
 
22963         var candidates = action.ways(graph);
 
22964         if (candidates.length === 0 || (wayIds && wayIds.length !== candidates.length))
 
22965             return 'not_eligible';
 
22968     action.limitWays = function(_) {
 
22969         if (!arguments.length) return wayIds;
 
22977  * Based on https://github.com/openstreetmap/potlatch2/net/systemeD/potlatch2/tools/Straighten.as
 
22980 iD.actions.Straighten = function(wayId, projection) {
 
22981     function positionAlongWay(n, s, e) {
 
22982         return ((n[0] - s[0]) * (e[0] - s[0]) + (n[1] - s[1]) * (e[1] - s[1]))/
 
22983                 (Math.pow(e[0] - s[0], 2) + Math.pow(e[1] - s[1], 2));
 
22986     var action = function(graph) {
 
22987         var way = graph.entity(wayId),
 
22988             nodes = graph.childNodes(way),
 
22989             points = nodes.map(function(n) { return projection(n.loc); }),
 
22990             startPoint = points[0],
 
22991             endPoint = points[points.length-1],
 
22995         for (i = 1; i < points.length-1; i++) {
 
22996             var node = nodes[i],
 
22999             if (graph.parentWays(node).length > 1 ||
 
23000                 graph.parentRelations(node).length ||
 
23001                 node.hasInterestingTags()) {
 
23003                 var u = positionAlongWay(point, startPoint, endPoint),
 
23004                     p0 = startPoint[0] + u * (endPoint[0] - startPoint[0]),
 
23005                     p1 = startPoint[1] + u * (endPoint[1] - startPoint[1]);
 
23007                 graph = graph.replace(graph.entity(node.id)
 
23008                     .move(projection.invert([p0, p1])));
 
23011                 if (toDelete.indexOf(node) === -1) {
 
23012                     toDelete.push(node);
 
23017         for (i = 0; i < toDelete.length; i++) {
 
23018             graph = iD.actions.DeleteNode(toDelete[i].id)(graph);
 
23024     action.disabled = function(graph) {
 
23025         // check way isn't too bendy
 
23026         var way = graph.entity(wayId),
 
23027             nodes = graph.childNodes(way),
 
23028             points = nodes.map(function(n) { return projection(n.loc); }),
 
23029             startPoint = points[0],
 
23030             endPoint = points[points.length-1],
 
23031             threshold = 0.2 * Math.sqrt(Math.pow(startPoint[0] - endPoint[0], 2) + Math.pow(startPoint[1] - endPoint[1], 2)),
 
23034         for (i = 1; i < points.length-1; i++) {
 
23035             var point = points[i],
 
23036                 u = positionAlongWay(point, startPoint, endPoint),
 
23037                 p0 = startPoint[0] + u * (endPoint[0] - startPoint[0]),
 
23038                 p1 = startPoint[1] + u * (endPoint[1] - startPoint[1]),
 
23039                 dist = Math.sqrt(Math.pow(p0 - point[0], 2) + Math.pow(p1 - point[1], 2));
 
23041             // to bendy if point is off by 20% of total start/end distance in projected space
 
23042             if (dist > threshold) {
 
23043                 return 'too_bendy';
 
23050 // Remove the effects of `turn.restriction` on `turn`, which must have the
 
23051 // following structure:
 
23054 //         from: { node: <node ID>, way: <way ID> },
 
23055 //         via:  { node: <node ID> },
 
23056 //         to:   { node: <node ID>, way: <way ID> },
 
23057 //         restriction: <relation ID>
 
23060 // In the simple case, `restriction` is a reference to a `no_*` restriction
 
23061 // on the turn itself. In this case, it is simply deleted.
 
23063 // The more complex case is where `restriction` references an `only_*`
 
23064 // restriction on a different turn in the same intersection. In that case,
 
23065 // that restriction is also deleted, but at the same time restrictions on
 
23066 // the turns other than the first two are created.
 
23068 iD.actions.UnrestrictTurn = function(turn) {
 
23069     return function(graph) {
 
23070         return iD.actions.DeleteRelation(turn.restriction)(graph);
 
23074 iD.behavior.AddWay = function(context) {
 
23075     var event = d3.dispatch('start', 'startFromWay', 'startFromNode'),
 
23076         draw = iD.behavior.Draw(context);
 
23078     var addWay = function(surface) {
 
23079         draw.on('click', event.start)
 
23080             .on('clickWay', event.startFromWay)
 
23081             .on('clickNode', event.startFromNode)
 
23082             .on('cancel', addWay.cancel)
 
23083             .on('finish', addWay.cancel);
 
23086             .dblclickEnable(false);
 
23088         surface.call(draw);
 
23091     addWay.off = function(surface) {
 
23092         surface.call(draw.off);
 
23095     addWay.cancel = function() {
 
23096         window.setTimeout(function() {
 
23097             context.map().dblclickEnable(true);
 
23100         context.enter(iD.modes.Browse(context));
 
23103     addWay.tail = function(text) {
 
23108     return d3.rebind(addWay, event, 'on');
 
23110 iD.behavior.Breathe = function() {
 
23111     var duration = 800,
 
23112         selector = '.selected.shadow, .selected .shadow',
 
23113         selected = d3.select(null),
 
23118     function reset(selection) {
 
23120             .style('stroke-opacity', null)
 
23121             .style('stroke-width', null)
 
23122             .style('fill-opacity', null)
 
23126     function setAnimationParams(transition, fromTo) {
 
23128             .style('stroke-opacity', function(d) { return params[d.id][fromTo].opacity; })
 
23129             .style('stroke-width', function(d) { return params[d.id][fromTo].width; })
 
23130             .style('fill-opacity', function(d) { return params[d.id][fromTo].opacity; })
 
23131             .style('r', function(d) { return params[d.id][fromTo].width; });
 
23134     function calcAnimationParams(selection) {
 
23137             .each(function(d) {
 
23138                 var s = d3.select(this),
 
23139                     tag = s.node().tagName,
 
23140                     p = {'from': {}, 'to': {}},
 
23143                 // determine base opacity and width
 
23144                 if (tag === 'circle') {
 
23145                     opacity = parseFloat(s.style('fill-opacity') || 0.5);
 
23146                     width = parseFloat(s.style('r') || 15.5);
 
23148                     opacity = parseFloat(s.style('stroke-opacity') || 0.7);
 
23149                     width = parseFloat(s.style('stroke-width') || 10);
 
23152                 // calculate from/to interpolation params..
 
23154                 p.from.opacity = opacity * 0.6;
 
23155                 p.to.opacity = opacity * 1.25;
 
23156                 p.from.width = width * 0.9;
 
23157                 p.to.width = width * (tag === 'circle' ? 1.5 : 1.25);
 
23162     function run(surface, fromTo) {
 
23163         var toFrom = (fromTo === 'from' ? 'to': 'from'),
 
23164             currSelected = surface.selectAll(selector),
 
23165             currClassed = surface.attr('class'),
 
23168         if (done || currSelected.empty()) {
 
23169             selected.call(reset);
 
23173         if (!_.isEqual(currSelected, selected) || currClassed !== classed) {
 
23174             selected.call(reset);
 
23175             classed = currClassed;
 
23176             selected = currSelected.call(calcAnimationParams);
 
23181             .call(setAnimationParams, fromTo)
 
23182             .duration(duration)
 
23183             .each(function() { ++n; })
 
23184             .each('end', function() {
 
23185                 if (!--n) {  // call once
 
23186                     surface.call(run, toFrom);
 
23191     var breathe = function(surface) {
 
23193         d3.timer(function() {
 
23194             if (done) return true;
 
23196             var currSelected = surface.selectAll(selector);
 
23197             if (currSelected.empty()) return false;
 
23199             surface.call(run, 'from');
 
23204     breathe.off = function() {
 
23215 iD.behavior.Copy = function(context) {
 
23216     var keybinding = d3.keybinding('copy');
 
23218     function groupEntities(ids, graph) {
 
23219         var entities = ids.map(function (id) { return graph.entity(id); });
 
23220         return _.extend({relation: [], way: [], node: []},
 
23221             _.groupBy(entities, function(entity) { return entity.type; }));
 
23224     function getDescendants(id, graph, descendants) {
 
23225         var entity = graph.entity(id),
 
23228         descendants = descendants || {};
 
23230         if (entity.type === 'relation') {
 
23231             children = _.pluck(entity.members, 'id');
 
23232         } else if (entity.type === 'way') {
 
23233             children = entity.nodes;
 
23238         for (i = 0; i < children.length; i++) {
 
23239             if (!descendants[children[i]]) {
 
23240                 descendants[children[i]] = true;
 
23241                 descendants = getDescendants(children[i], graph, descendants);
 
23245         return descendants;
 
23248     function doCopy() {
 
23249         d3.event.preventDefault();
 
23250         if (context.inIntro()) return;
 
23252         var graph = context.graph(),
 
23253             selected = groupEntities(context.selectedIDs(), graph),
 
23258         for (i = 0; i < selected.relation.length; i++) {
 
23259             entity = selected.relation[i];
 
23260             if (!skip[entity.id] && entity.isComplete(graph)) {
 
23261                 canCopy.push(entity.id);
 
23262                 skip = getDescendants(entity.id, graph, skip);
 
23265         for (i = 0; i < selected.way.length; i++) {
 
23266             entity = selected.way[i];
 
23267             if (!skip[entity.id]) {
 
23268                 canCopy.push(entity.id);
 
23269                 skip = getDescendants(entity.id, graph, skip);
 
23272         for (i = 0; i < selected.node.length; i++) {
 
23273             entity = selected.node[i];
 
23274             if (!skip[entity.id]) {
 
23275                 canCopy.push(entity.id);
 
23279         context.copyIDs(canCopy);
 
23283         keybinding.on(iD.ui.cmd('⌘C'), doCopy);
 
23284         d3.select(document).call(keybinding);
 
23288     copy.off = function() {
 
23289         d3.select(document).call(keybinding.off);
 
23295     `iD.behavior.drag` is like `d3.behavior.drag`, with the following differences:
 
23297     * The `origin` function is expected to return an [x, y] tuple rather than an
 
23299     * The events are `start`, `move`, and `end`.
 
23300       (https://github.com/mbostock/d3/issues/563)
 
23301     * The `start` event is not dispatched until the first cursor movement occurs.
 
23302       (https://github.com/mbostock/d3/pull/368)
 
23303     * The `move` event has a `point` and `delta` [x, y] tuple properties rather
 
23304       than `x`, `y`, `dx`, and `dy` properties.
 
23305     * The `end` event is not dispatched if no movement occurs.
 
23306     * An `off` function is available that unbinds the drag's internal event handlers.
 
23307     * Delegation is supported via the `delegate` function.
 
23310 iD.behavior.drag = function() {
 
23311     function d3_eventCancel() {
 
23312       d3.event.stopPropagation();
 
23313       d3.event.preventDefault();
 
23316     var event = d3.dispatch('start', 'move', 'end'),
 
23320         event_, target, surface;
 
23322     event.of = function(thiz, argumentz) {
 
23323       return function(e1) {
 
23324         var e0 = e1.sourceEvent = d3.event;
 
23328           event[e1.type].apply(thiz, argumentz);
 
23335     var d3_event_userSelectProperty = iD.util.prefixCSSProperty('UserSelect'),
 
23336         d3_event_userSelectSuppress = d3_event_userSelectProperty ?
 
23338                 var selection = d3.selection(),
 
23339                     select = selection.style(d3_event_userSelectProperty);
 
23340                 selection.style(d3_event_userSelectProperty, 'none');
 
23341                 return function () {
 
23342                     selection.style(d3_event_userSelectProperty, select);
 
23346                 var w = d3.select(window).on('selectstart.' + type, d3_eventCancel);
 
23347                 return function () {
 
23348                     w.on('selectstart.' + type, null);
 
23352     function mousedown() {
 
23354         event_ = event.of(target, arguments);
 
23355         var eventTarget = d3.event.target,
 
23356             touchId = d3.event.touches ? d3.event.changedTouches[0].identifier : null,
 
23360             selectEnable = d3_event_userSelectSuppress(touchId !== null ? 'drag-' + touchId : 'drag');
 
23362         var w = d3.select(window)
 
23363             .on(touchId !== null ? 'touchmove.drag-' + touchId : 'mousemove.drag', dragmove)
 
23364             .on(touchId !== null ? 'touchend.drag-' + touchId : 'mouseup.drag', dragend, true);
 
23367             offset = origin.apply(target, arguments);
 
23368             offset = [offset[0] - origin_[0], offset[1] - origin_[1]];
 
23373         if (touchId === null) d3.event.stopPropagation();
 
23376             var p = target.parentNode || surface;
 
23377             return touchId !== null ? d3.touches(p).filter(function(p) {
 
23378                 return p.identifier === touchId;
 
23379             })[0] : d3.mouse(p);
 
23382         function dragmove() {
 
23385                 dx = p[0] - origin_[0],
 
23386                 dy = p[1] - origin_[1];
 
23388             if (dx === 0 && dy === 0)
 
23403                 point: [p[0] + offset[0],  p[1] + offset[1]],
 
23408         function dragend() {
 
23415                 if (d3.event.target === eventTarget) w.on('click.drag', click, true);
 
23418             w.on(touchId !== null ? 'touchmove.drag-' + touchId : 'mousemove.drag', null)
 
23419                 .on(touchId !== null ? 'touchend.drag-' + touchId : 'mouseup.drag', null);
 
23425             w.on('click.drag', null);
 
23429     function drag(selection) {
 
23430         var matchesSelector = iD.util.prefixDOMProperty('matchesSelector'),
 
23431             delegate = mousedown;
 
23434             delegate = function() {
 
23436                     target = d3.event.target;
 
23437                 for (; target && target !== root; target = target.parentNode) {
 
23438                     if (target[matchesSelector](selector) &&
 
23439                             (!filter || filter(target.__data__))) {
 
23440                         return mousedown.call(target, target.__data__);
 
23446         selection.on('mousedown.drag' + selector, delegate)
 
23447             .on('touchstart.drag' + selector, delegate);
 
23450     drag.off = function(selection) {
 
23451         selection.on('mousedown.drag' + selector, null)
 
23452             .on('touchstart.drag' + selector, null);
 
23455     drag.delegate = function(_) {
 
23456         if (!arguments.length) return selector;
 
23461     drag.filter = function(_) {
 
23462         if (!arguments.length) return origin;
 
23467     drag.origin = function (_) {
 
23468         if (!arguments.length) return origin;
 
23473     drag.cancel = function() {
 
23475             .on('mousemove.drag', null)
 
23476             .on('mouseup.drag', null);
 
23480     drag.target = function() {
 
23481         if (!arguments.length) return target;
 
23482         target = arguments[0];
 
23483         event_ = event.of(target, Array.prototype.slice.call(arguments, 1));
 
23487     drag.surface = function() {
 
23488         if (!arguments.length) return surface;
 
23489         surface = arguments[0];
 
23493     return d3.rebind(drag, event, 'on');
 
23495 iD.behavior.Draw = function(context) {
 
23496     var event = d3.dispatch('move', 'click', 'clickWay',
 
23497             'clickNode', 'undo', 'cancel', 'finish'),
 
23498         keybinding = d3.keybinding('draw'),
 
23499         hover = iD.behavior.Hover(context)
 
23501             .on('hover', context.ui().sidebar.hover),
 
23502         tail = iD.behavior.Tail(),
 
23503         edit = iD.behavior.Edit(context),
 
23504         closeTolerance = 4,
 
23508         if (d3.event.altKey) return {};
 
23509         else return d3.event.target.__data__ || {};
 
23512     function mousedown() {
 
23515             var p = context.container().node();
 
23516             return touchId !== null ? d3.touches(p).filter(function(p) {
 
23517                 return p.identifier === touchId;
 
23518             })[0] : d3.mouse(p);
 
23521         var element = d3.select(this),
 
23522             touchId = d3.event.touches ? d3.event.changedTouches[0].identifier : null,
 
23526         element.on('mousemove.draw', null);
 
23528         d3.select(window).on('mouseup.draw', function() {
 
23529             var t2 = +new Date(),
 
23531                 dist = iD.geo.euclideanDistance(p1, p2);
 
23533             element.on('mousemove.draw', mousemove);
 
23534             d3.select(window).on('mouseup.draw', null);
 
23536             if (dist < closeTolerance || (dist < tolerance && (t2 - t1) < 500)) {
 
23537                 // Prevent a quick second click
 
23538                 d3.select(window).on('click.draw-block', function() {
 
23539                     d3.event.stopPropagation();
 
23542                 context.map().dblclickEnable(false);
 
23544                 window.setTimeout(function() {
 
23545                     context.map().dblclickEnable(true);
 
23546                     d3.select(window).on('click.draw-block', null);
 
23554     function mousemove() {
 
23555         event.move(datum());
 
23560         if (d.type === 'way') {
 
23561             var choice = iD.geo.chooseEdge(context.childNodes(d), context.mouse(), context.projection),
 
23562                 edge = [d.nodes[choice.index - 1], d.nodes[choice.index]];
 
23563             event.clickWay(choice.loc, edge);
 
23565         } else if (d.type === 'node') {
 
23566             event.clickNode(d);
 
23569             event.click(context.map().mouseCoordinates());
 
23573     function backspace() {
 
23574         d3.event.preventDefault();
 
23579         d3.event.preventDefault();
 
23584         d3.event.preventDefault();
 
23588     function draw(selection) {
 
23589         context.install(hover);
 
23590         context.install(edit);
 
23592         if (!context.inIntro() && !iD.behavior.Draw.usedTails[tail.text()]) {
 
23593             context.install(tail);
 
23597             .on('⌫', backspace)
 
23603             .on('mousedown.draw', mousedown)
 
23604             .on('mousemove.draw', mousemove);
 
23606         d3.select(document)
 
23612     draw.off = function(selection) {
 
23613         context.ui().sidebar.hover.cancel();
 
23614         context.uninstall(hover);
 
23615         context.uninstall(edit);
 
23617         if (!context.inIntro() && !iD.behavior.Draw.usedTails[tail.text()]) {
 
23618             context.uninstall(tail);
 
23619             iD.behavior.Draw.usedTails[tail.text()] = true;
 
23623             .on('mousedown.draw', null)
 
23624             .on('mousemove.draw', null);
 
23627             .on('mouseup.draw', null);
 
23629         d3.select(document)
 
23630             .call(keybinding.off);
 
23633     draw.tail = function(_) {
 
23638     return d3.rebind(draw, event, 'on');
 
23641 iD.behavior.Draw.usedTails = {};
 
23642 iD.behavior.DrawWay = function(context, wayId, index, mode, baseGraph) {
 
23643     var way = context.entity(wayId),
 
23644         isArea = context.geometry(wayId) === 'area',
 
23646         annotation = t((way.isDegenerate() ?
 
23647             'operations.start.annotation.' :
 
23648             'operations.continue.annotation.') + context.geometry(wayId)),
 
23649         draw = iD.behavior.Draw(context);
 
23651     var startIndex = typeof index === 'undefined' ? way.nodes.length - 1 : 0,
 
23652         start = iD.Node({loc: context.graph().entity(way.nodes[startIndex]).loc}),
 
23653         end = iD.Node({loc: context.map().mouseCoordinates()}),
 
23655             nodes: typeof index === 'undefined' ? [start.id, end.id] : [end.id, start.id],
 
23656             tags: _.clone(way.tags)
 
23659     var f = context[way.isDegenerate() ? 'replace' : 'perform'];
 
23661         f(iD.actions.AddEntity(end),
 
23662             iD.actions.AddVertex(wayId, end.id, index));
 
23664         f(iD.actions.AddEntity(start),
 
23665             iD.actions.AddEntity(end),
 
23666             iD.actions.AddEntity(segment));
 
23669     function move(datum) {
 
23672         if (datum.type === 'node' && datum.id !== end.id) {
 
23674         } else if (datum.type === 'way' && datum.id !== segment.id) {
 
23675             loc = iD.geo.chooseEdge(context.childNodes(datum), context.mouse(), context.projection).loc;
 
23677             loc = context.map().mouseCoordinates();
 
23680         context.replace(iD.actions.MoveNode(end.id, loc));
 
23683     function undone() {
 
23685         context.enter(iD.modes.Browse(context));
 
23688     function setActiveElements() {
 
23689         var active = isArea ? [wayId, end.id] : [segment.id, start.id, end.id];
 
23690         context.surface().selectAll(iD.util.entitySelector(active))
 
23691             .classed('active', true);
 
23694     var drawWay = function(surface) {
 
23695         draw.on('move', move)
 
23696             .on('click', drawWay.add)
 
23697             .on('clickWay', drawWay.addWay)
 
23698             .on('clickNode', drawWay.addNode)
 
23699             .on('undo', context.undo)
 
23700             .on('cancel', drawWay.cancel)
 
23701             .on('finish', drawWay.finish);
 
23704             .dblclickEnable(false)
 
23705             .on('drawn.draw', setActiveElements);
 
23707         setActiveElements();
 
23709         surface.call(draw);
 
23712             .on('undone.draw', undone);
 
23715     drawWay.off = function(surface) {
 
23720             .on('drawn.draw', null);
 
23722         surface.call(draw.off)
 
23723             .selectAll('.active')
 
23724             .classed('active', false);
 
23727             .on('undone.draw', null);
 
23730     function ReplaceTemporaryNode(newNode) {
 
23731         return function(graph) {
 
23734                     .replace(way.addNode(newNode.id, index))
 
23739                     .replace(graph.entity(wayId).addNode(newNode.id, index))
 
23747     // Accept the current position of the temporary node and continue drawing.
 
23748     drawWay.add = function(loc) {
 
23750         // prevent duplicate nodes
 
23751         var last = context.hasEntity(way.nodes[way.nodes.length - (isArea ? 2 : 1)]);
 
23752         if (last && last.loc[0] === loc[0] && last.loc[1] === loc[1]) return;
 
23754         var newNode = iD.Node({loc: loc});
 
23757             iD.actions.AddEntity(newNode),
 
23758             ReplaceTemporaryNode(newNode),
 
23762         context.enter(mode);
 
23765     // Connect the way to an existing way.
 
23766     drawWay.addWay = function(loc, edge) {
 
23767         var previousEdge = startIndex ?
 
23768             [way.nodes[startIndex], way.nodes[startIndex - 1]] :
 
23769             [way.nodes[0], way.nodes[1]];
 
23771         // Avoid creating duplicate segments
 
23772         if (!isArea && iD.geo.edgeEqual(edge, previousEdge))
 
23775         var newNode = iD.Node({ loc: loc });
 
23778             iD.actions.AddMidpoint({ loc: loc, edge: edge}, newNode),
 
23779             ReplaceTemporaryNode(newNode),
 
23783         context.enter(mode);
 
23786     // Connect the way to an existing node and continue drawing.
 
23787     drawWay.addNode = function(node) {
 
23789         // Avoid creating duplicate segments
 
23790         if (way.areAdjacent(node.id, way.nodes[way.nodes.length - 1])) return;
 
23793             ReplaceTemporaryNode(node),
 
23797         context.enter(mode);
 
23800     // Finish the draw operation, removing the temporary node. If the way has enough
 
23801     // nodes to be valid, it's selected. Otherwise, return to browse mode.
 
23802     drawWay.finish = function() {
 
23806         window.setTimeout(function() {
 
23807             context.map().dblclickEnable(true);
 
23810         if (context.hasEntity(wayId)) {
 
23812                 iD.modes.Select(context, [wayId])
 
23813                     .suppressMenu(true)
 
23814                     .newFeature(true));
 
23816             context.enter(iD.modes.Browse(context));
 
23820     // Cancel the draw operation and return to browse, deleting everything drawn.
 
23821     drawWay.cancel = function() {
 
23823             d3.functor(baseGraph),
 
23824             t('operations.cancel_draw.annotation'));
 
23826         window.setTimeout(function() {
 
23827             context.map().dblclickEnable(true);
 
23831         context.enter(iD.modes.Browse(context));
 
23834     drawWay.tail = function(text) {
 
23841 iD.behavior.Edit = function(context) {
 
23844             .minzoom(context.minEditableZoom());
 
23847     edit.off = function() {
 
23854 iD.behavior.Hash = function(context) {
 
23855     var s0 = null, // cached location.hash
 
23856         lat = 90 - 1e-8; // allowable latitude range
 
23858     var parser = function(map, s) {
 
23859         var q = iD.util.stringQs(s);
 
23860         var args = (q.map || '').split('/').map(Number);
 
23861         if (args.length < 3 || args.some(isNaN)) {
 
23862             return true; // replace bogus hash
 
23863         } else if (s !== formatter(map).slice(1)) {
 
23864             map.centerZoom([args[1],
 
23865                 Math.min(lat, Math.max(-lat, args[2]))], args[0]);
 
23869     var formatter = function(map) {
 
23870         var mode = context.mode(),
 
23871             center = map.center(),
 
23873             precision = Math.max(0, Math.ceil(Math.log(zoom) / Math.LN2)),
 
23874             q = _.omit(iD.util.stringQs(location.hash.substring(1)), 'comment'),
 
23877         if (mode && mode.id === 'browse') {
 
23880             var selected = context.selectedIDs().filter(function(id) {
 
23881                 return !context.entity(id).isNew();
 
23883             if (selected.length) {
 
23884                 newParams.id = selected.join(',');
 
23888         newParams.map = zoom.toFixed(2) +
 
23889                 '/' + center[0].toFixed(precision) +
 
23890                 '/' + center[1].toFixed(precision);
 
23892         return '#' + iD.util.qsString(_.assign(q, newParams), true);
 
23895     function update() {
 
23896         if (context.inIntro()) return;
 
23897         var s1 = formatter(context.map());
 
23898         if (s0 !== s1) location.replace(s0 = s1); // don't recenter the map!
 
23901     var throttledUpdate = _.throttle(update, 500);
 
23903     function hashchange() {
 
23904         if (location.hash === s0) return; // ignore spurious hashchange events
 
23905         if (parser(context.map(), (s0 = location.hash).substring(1))) {
 
23906             update(); // replace bogus hash
 
23912             .on('move.hash', throttledUpdate);
 
23915             .on('enter.hash', throttledUpdate);
 
23918             .on('hashchange.hash', hashchange);
 
23920         if (location.hash) {
 
23921             var q = iD.util.stringQs(location.hash.substring(1));
 
23922             if (q.id) context.zoomToEntity(q.id.split(',')[0], !q.map);
 
23923             if (q.comment) context.storage('comment', q.comment);
 
23925             if (q.map) hash.hadHash = true;
 
23929     hash.off = function() {
 
23930         throttledUpdate.cancel();
 
23933             .on('move.hash', null);
 
23936             .on('enter.hash', null);
 
23939             .on('hashchange.hash', null);
 
23941         location.hash = '';
 
23947    The hover behavior adds the `.hover` class on mouseover to all elements to which
 
23948    the identical datum is bound, and removes it on mouseout.
 
23950    The :hover pseudo-class is insufficient for iD's purposes because a datum's visual
 
23951    representation may consist of several elements scattered throughout the DOM hierarchy.
 
23952    Only one of these elements can have the :hover pseudo-class, but all of them will
 
23953    have the .hover class.
 
23955 iD.behavior.Hover = function() {
 
23956     var dispatch = d3.dispatch('hover'),
 
23961     function keydown() {
 
23962         if (altDisables && d3.event.keyCode === d3.keybinding.modifierCodes.alt) {
 
23963             dispatch.hover(null);
 
23964             selection.selectAll('.hover')
 
23965                 .classed('hover-suppressed', true)
 
23966                 .classed('hover', false);
 
23971         if (altDisables && d3.event.keyCode === d3.keybinding.modifierCodes.alt) {
 
23972             dispatch.hover(target ? target.id : null);
 
23973             selection.selectAll('.hover-suppressed')
 
23974                 .classed('hover-suppressed', false)
 
23975                 .classed('hover', true);
 
23979     var hover = function(__) {
 
23982         function enter(d) {
 
23983             if (d === target) return;
 
23987             selection.selectAll('.hover')
 
23988                 .classed('hover', false);
 
23989             selection.selectAll('.hover-suppressed')
 
23990                 .classed('hover-suppressed', false);
 
23992             if (target instanceof iD.Entity) {
 
23993                 var selector = '.' + target.id;
 
23995                 if (target.type === 'relation') {
 
23996                     target.members.forEach(function(member) {
 
23997                         selector += ', .' + member.id;
 
24001                 var suppressed = altDisables && d3.event && d3.event.altKey;
 
24003                 selection.selectAll(selector)
 
24004                     .classed(suppressed ? 'hover-suppressed' : 'hover', true);
 
24006                 dispatch.hover(target.id);
 
24008                 dispatch.hover(null);
 
24014         function mouseover() {
 
24016             var target = d3.event.target;
 
24017             enter(target ? target.__data__ : null);
 
24020         function mouseout() {
 
24022             var target = d3.event.relatedTarget;
 
24023             enter(target ? target.__data__ : null);
 
24026         function mousedown() {
 
24029                 .on('mouseup.hover', mouseup);
 
24032         function mouseup() {
 
24037             .on('mouseover.hover', mouseover)
 
24038             .on('mouseout.hover', mouseout)
 
24039             .on('mousedown.hover', mousedown)
 
24040             .on('mouseup.hover', mouseup);
 
24043             .on('keydown.hover', keydown)
 
24044             .on('keyup.hover', keyup);
 
24047     hover.off = function(selection) {
 
24048         selection.selectAll('.hover')
 
24049             .classed('hover', false);
 
24050         selection.selectAll('.hover-suppressed')
 
24051             .classed('hover-suppressed', false);
 
24054             .on('mouseover.hover', null)
 
24055             .on('mouseout.hover', null)
 
24056             .on('mousedown.hover', null)
 
24057             .on('mouseup.hover', null);
 
24060             .on('keydown.hover', null)
 
24061             .on('keyup.hover', null)
 
24062             .on('mouseup.hover', null);
 
24065     hover.altDisables = function(_) {
 
24066         if (!arguments.length) return altDisables;
 
24071     return d3.rebind(hover, dispatch, 'on');
 
24073 iD.behavior.Lasso = function(context) {
 
24075     var behavior = function(selection) {
 
24079         function mousedown() {
 
24080             if (d3.event.shiftKey === true) {
 
24082                 mouse = context.mouse();
 
24086                     .on('mousemove.lasso', mousemove)
 
24087                     .on('mouseup.lasso', mouseup);
 
24089                 d3.event.stopPropagation();
 
24093         function mousemove() {
 
24095                 lasso = iD.ui.Lasso(context).a(mouse);
 
24096                 context.surface().call(lasso);
 
24099             lasso.b(context.mouse());
 
24102         function normalize(a, b) {
 
24104                 [Math.min(a[0], b[0]), Math.min(a[1], b[1])],
 
24105                 [Math.max(a[0], b[0]), Math.max(a[1], b[1])]];
 
24108         function mouseup() {
 
24110                 .on('mousemove.lasso', null)
 
24111                 .on('mouseup.lasso', null);
 
24113             if (!lasso) return;
 
24115             var graph = context.graph(),
 
24116                 extent = iD.geo.Extent(
 
24117                 normalize(context.projection.invert(lasso.a()),
 
24118                 context.projection.invert(lasso.b())));
 
24122             var selected = context.intersects(extent).filter(function(entity) {
 
24123                 return entity.type === 'node' &&
 
24124                     !context.features().isHidden(entity, graph, entity.geometry(graph));
 
24127             if (selected.length) {
 
24128                 context.enter(iD.modes.Select(context, _.pluck(selected, 'id')));
 
24133             .on('mousedown.lasso', mousedown);
 
24136     behavior.off = function(selection) {
 
24137         selection.on('mousedown.lasso', null);
 
24142 iD.behavior.Paste = function(context) {
 
24143     var keybinding = d3.keybinding('paste');
 
24145     function omitTag(v, k) {
 
24153             k === 'description' ||
 
24154             k.indexOf('name') !== -1 ||
 
24155             k.indexOf('wiki') === 0 ||
 
24156             k.indexOf('addr:') === 0 ||
 
24157             k.indexOf('contact:') === 0
 
24161     function doPaste() {
 
24162         d3.event.preventDefault();
 
24163         if (context.inIntro()) return;
 
24165         var baseGraph = context.graph(),
 
24166             mouse = context.mouse(),
 
24167             projection = context.projection,
 
24168             viewport = iD.geo.Extent(projection.clipExtent()).polygon();
 
24170         if (!iD.geo.pointInPolygon(mouse, viewport)) return;
 
24172         var extent = iD.geo.Extent(),
 
24173             oldIDs = context.copyIDs(),
 
24174             oldGraph = context.copyGraph(),
 
24177         if (!oldIDs.length) return;
 
24179         var action = iD.actions.CopyEntities(oldIDs, oldGraph);
 
24180         context.perform(action);
 
24182         var copies = action.copies();
 
24183         for (var id in copies) {
 
24184             var oldEntity = oldGraph.entity(id),
 
24185                 newEntity = copies[id];
 
24187             extent._extend(oldEntity.extent(oldGraph));
 
24188             newIDs.push(newEntity.id);
 
24189             context.perform(iD.actions.ChangeTags(newEntity.id, _.omit(newEntity.tags, omitTag)));
 
24192         // Put pasted objects where mouse pointer is..
 
24193         var center = projection(extent.center()),
 
24194             delta = [ mouse[0] - center[0], mouse[1] - center[1] ];
 
24196         context.perform(iD.actions.Move(newIDs, delta, projection));
 
24197         context.enter(iD.modes.Move(context, newIDs, baseGraph));
 
24201         keybinding.on(iD.ui.cmd('⌘V'), doPaste);
 
24202         d3.select(document).call(keybinding);
 
24206     paste.off = function() {
 
24207         d3.select(document).call(keybinding.off);
 
24212 iD.behavior.Select = function(context) {
 
24213     function keydown() {
 
24214         if (d3.event && d3.event.shiftKey) {
 
24216                 .classed('behavior-multiselect', true);
 
24221         if (!d3.event || !d3.event.shiftKey) {
 
24223                 .classed('behavior-multiselect', false);
 
24228         var datum = d3.event.target.__data__,
 
24229             lasso = d3.select('#surface .lasso').node(),
 
24230             mode = context.mode();
 
24232         if (!(datum instanceof iD.Entity)) {
 
24233             if (!d3.event.shiftKey && !lasso && mode.id !== 'browse')
 
24234                 context.enter(iD.modes.Browse(context));
 
24236         } else if (!d3.event.shiftKey && !lasso) {
 
24237             // Avoid re-entering Select mode with same entity.
 
24238             if (context.selectedIDs().length !== 1 || context.selectedIDs()[0] !== datum.id) {
 
24239                 context.enter(iD.modes.Select(context, [datum.id]));
 
24241                 mode.suppressMenu(false).reselect();
 
24243         } else if (context.selectedIDs().indexOf(datum.id) >= 0) {
 
24244             var selectedIDs = _.without(context.selectedIDs(), datum.id);
 
24245             context.enter(selectedIDs.length ?
 
24246                 iD.modes.Select(context, selectedIDs) :
 
24247                 iD.modes.Browse(context));
 
24250             context.enter(iD.modes.Select(context, context.selectedIDs().concat([datum.id])));
 
24254     var behavior = function(selection) {
 
24256             .on('keydown.select', keydown)
 
24257             .on('keyup.select', keyup);
 
24259         selection.on('click.select', click);
 
24264     behavior.off = function(selection) {
 
24266             .on('keydown.select', null)
 
24267             .on('keyup.select', null);
 
24269         selection.on('click.select', null);
 
24276 iD.behavior.Tail = function() {
 
24280         tooltipSize = [0, 0],
 
24281         selectionSize = [0, 0];
 
24283     function tail(selection) {
 
24287             .on('resize.tail', function() { selectionSize = selection.dimensions(); });
 
24290             container.style('display', 'block');
 
24291             tooltipSize = container.dimensions();
 
24294         function mousemove() {
 
24295             if (container.style('display') === 'none') show();
 
24296             var xoffset = ((d3.event.clientX + tooltipSize[0] + xmargin) > selectionSize[0]) ?
 
24297                 -tooltipSize[0] - xmargin : xmargin;
 
24298             container.classed('left', xoffset > 0);
 
24299             iD.util.setTransform(container, d3.event.clientX + xoffset, d3.event.clientY);
 
24302         function mouseleave() {
 
24303             if (d3.event.relatedTarget !== container.node()) {
 
24304                 container.style('display', 'none');
 
24308         function mouseenter() {
 
24309             if (d3.event.relatedTarget !== container.node()) {
 
24314         container = d3.select(document.body)
 
24316             .style('display', 'none')
 
24317             .attr('class', 'tail tooltip-inner');
 
24319         container.append('div')
 
24323             .on('mousemove.tail', mousemove)
 
24324             .on('mouseenter.tail', mouseenter)
 
24325             .on('mouseleave.tail', mouseleave);
 
24328             .on('mousemove.tail', mousemove);
 
24330         tooltipSize = container.dimensions();
 
24331         selectionSize = selection.dimensions();
 
24334     tail.off = function(selection) {
 
24338             .on('mousemove.tail', null)
 
24342             .on('mousemove.tail', null)
 
24343             .on('mouseenter.tail', null)
 
24344             .on('mouseleave.tail', null);
 
24347             .on('resize.tail', null);
 
24350     tail.text = function(_) {
 
24351         if (!arguments.length) return text;
 
24359 iD.modes.AddArea = function(context) {
 
24363         title: t('modes.add_area.title'),
 
24364         description: t('modes.add_area.description'),
 
24368     var behavior = iD.behavior.AddWay(context)
 
24369             .tail(t('modes.add_area.tail'))
 
24370             .on('start', start)
 
24371             .on('startFromWay', startFromWay)
 
24372             .on('startFromNode', startFromNode),
 
24373         defaultTags = {area: 'yes'};
 
24375     function start(loc) {
 
24376         var graph = context.graph(),
 
24377             node = iD.Node({loc: loc}),
 
24378             way = iD.Way({tags: defaultTags});
 
24381             iD.actions.AddEntity(node),
 
24382             iD.actions.AddEntity(way),
 
24383             iD.actions.AddVertex(way.id, node.id),
 
24384             iD.actions.AddVertex(way.id, node.id));
 
24386         context.enter(iD.modes.DrawArea(context, way.id, graph));
 
24389     function startFromWay(loc, edge) {
 
24390         var graph = context.graph(),
 
24391             node = iD.Node({loc: loc}),
 
24392             way = iD.Way({tags: defaultTags});
 
24395             iD.actions.AddEntity(node),
 
24396             iD.actions.AddEntity(way),
 
24397             iD.actions.AddVertex(way.id, node.id),
 
24398             iD.actions.AddVertex(way.id, node.id),
 
24399             iD.actions.AddMidpoint({ loc: loc, edge: edge }, node));
 
24401         context.enter(iD.modes.DrawArea(context, way.id, graph));
 
24404     function startFromNode(node) {
 
24405         var graph = context.graph(),
 
24406             way = iD.Way({tags: defaultTags});
 
24409             iD.actions.AddEntity(way),
 
24410             iD.actions.AddVertex(way.id, node.id),
 
24411             iD.actions.AddVertex(way.id, node.id));
 
24413         context.enter(iD.modes.DrawArea(context, way.id, graph));
 
24416     mode.enter = function() {
 
24417         context.install(behavior);
 
24420     mode.exit = function() {
 
24421         context.uninstall(behavior);
 
24426 iD.modes.AddLine = function(context) {
 
24430         title: t('modes.add_line.title'),
 
24431         description: t('modes.add_line.description'),
 
24435     var behavior = iD.behavior.AddWay(context)
 
24436         .tail(t('modes.add_line.tail'))
 
24437         .on('start', start)
 
24438         .on('startFromWay', startFromWay)
 
24439         .on('startFromNode', startFromNode);
 
24441     function start(loc) {
 
24442         var baseGraph = context.graph(),
 
24443             node = iD.Node({loc: loc}),
 
24447             iD.actions.AddEntity(node),
 
24448             iD.actions.AddEntity(way),
 
24449             iD.actions.AddVertex(way.id, node.id));
 
24451         context.enter(iD.modes.DrawLine(context, way.id, baseGraph));
 
24454     function startFromWay(loc, edge) {
 
24455         var baseGraph = context.graph(),
 
24456             node = iD.Node({loc: loc}),
 
24460             iD.actions.AddEntity(node),
 
24461             iD.actions.AddEntity(way),
 
24462             iD.actions.AddVertex(way.id, node.id),
 
24463             iD.actions.AddMidpoint({ loc: loc, edge: edge }, node));
 
24465         context.enter(iD.modes.DrawLine(context, way.id, baseGraph));
 
24468     function startFromNode(node) {
 
24469         var baseGraph = context.graph(),
 
24473             iD.actions.AddEntity(way),
 
24474             iD.actions.AddVertex(way.id, node.id));
 
24476         context.enter(iD.modes.DrawLine(context, way.id, baseGraph));
 
24479     mode.enter = function() {
 
24480         context.install(behavior);
 
24483     mode.exit = function() {
 
24484         context.uninstall(behavior);
 
24489 iD.modes.AddPoint = function(context) {
 
24493         title: t('modes.add_point.title'),
 
24494         description: t('modes.add_point.description'),
 
24498     var behavior = iD.behavior.Draw(context)
 
24499         .tail(t('modes.add_point.tail'))
 
24501         .on('clickWay', addWay)
 
24502         .on('clickNode', addNode)
 
24503         .on('cancel', cancel)
 
24504         .on('finish', cancel);
 
24506     function add(loc) {
 
24507         var node = iD.Node({loc: loc});
 
24510             iD.actions.AddEntity(node),
 
24511             t('operations.add.annotation.point'));
 
24514             iD.modes.Select(context, [node.id])
 
24515                 .suppressMenu(true)
 
24516                 .newFeature(true));
 
24519     function addWay(loc) {
 
24523     function addNode(node) {
 
24527     function cancel() {
 
24528         context.enter(iD.modes.Browse(context));
 
24531     mode.enter = function() {
 
24532         context.install(behavior);
 
24535     mode.exit = function() {
 
24536         context.uninstall(behavior);
 
24541 iD.modes.Browse = function(context) {
 
24545         title: t('modes.browse.title'),
 
24546         description: t('modes.browse.description')
 
24550         iD.behavior.Paste(context),
 
24551         iD.behavior.Hover(context)
 
24552             .on('hover', context.ui().sidebar.hover),
 
24553         iD.behavior.Select(context),
 
24554         iD.behavior.Lasso(context),
 
24555         iD.modes.DragNode(context).behavior];
 
24557     mode.enter = function() {
 
24558         behaviors.forEach(function(behavior) {
 
24559             context.install(behavior);
 
24562         // Get focus on the body.
 
24563         if (document.activeElement && document.activeElement.blur) {
 
24564             document.activeElement.blur();
 
24568             context.ui().sidebar.show(sidebar);
 
24570             context.ui().sidebar.select(null);
 
24574     mode.exit = function() {
 
24575         context.ui().sidebar.hover.cancel();
 
24576         behaviors.forEach(function(behavior) {
 
24577             context.uninstall(behavior);
 
24581             context.ui().sidebar.hide();
 
24585     mode.sidebar = function(_) {
 
24586         if (!arguments.length) return sidebar;
 
24593 iD.modes.DragNode = function(context) {
 
24604         hover = iD.behavior.Hover(context)
 
24606             .on('hover', context.ui().sidebar.hover),
 
24607         edit = iD.behavior.Edit(context);
 
24609     function edge(point, size) {
 
24610         var pad = [30, 100, 30, 100];
 
24611         if (point[0] > size[0] - pad[0]) return [-10, 0];
 
24612         else if (point[0] < pad[2]) return [10, 0];
 
24613         else if (point[1] > size[1] - pad[1]) return [0, -10];
 
24614         else if (point[1] < pad[3]) return [0, 10];
 
24618     function startNudge(nudge) {
 
24619         if (nudgeInterval) window.clearInterval(nudgeInterval);
 
24620         nudgeInterval = window.setInterval(function() {
 
24621             context.pan(nudge);
 
24625     function stopNudge() {
 
24626         if (nudgeInterval) window.clearInterval(nudgeInterval);
 
24627         nudgeInterval = null;
 
24630     function moveAnnotation(entity) {
 
24631         return t('operations.move.annotation.' + entity.geometry(context.graph()));
 
24634     function connectAnnotation(entity) {
 
24635         return t('operations.connect.annotation.' + entity.geometry(context.graph()));
 
24638     function origin(entity) {
 
24639         return context.projection(entity.loc);
 
24642     function start(entity) {
 
24643         cancelled = d3.event.sourceEvent.shiftKey ||
 
24644             context.features().hasHiddenConnections(entity, context.graph());
 
24646         if (cancelled) return behavior.cancel();
 
24648         wasMidpoint = entity.type === 'midpoint';
 
24650             var midpoint = entity;
 
24651             entity = iD.Node();
 
24652             context.perform(iD.actions.AddMidpoint(midpoint, entity));
 
24654              var vertex = context.surface()
 
24655                 .selectAll('.' + entity.id);
 
24656              behavior.target(vertex.node(), entity);
 
24660                 iD.actions.Noop());
 
24663         activeIDs = _.pluck(context.graph().parentWays(entity), 'id');
 
24664         activeIDs.push(entity.id);
 
24666         context.enter(mode);
 
24670         if (d3.event.sourceEvent.altKey) {
 
24674         return d3.event.sourceEvent.target.__data__ || {};
 
24677     // via https://gist.github.com/shawnbot/4166283
 
24678     function childOf(p, c) {
 
24679         if (p === c) return false;
 
24680         while (c && c !== p) c = c.parentNode;
 
24684     function move(entity) {
 
24685         if (cancelled) return;
 
24686         d3.event.sourceEvent.stopPropagation();
 
24688         var nudge = childOf(context.container().node(),
 
24689             d3.event.sourceEvent.toElement) &&
 
24690             edge(d3.event.point, context.map().dimensions());
 
24692         if (nudge) startNudge(nudge);
 
24695         var loc = context.map().mouseCoordinates();
 
24698         if (d.type === 'node' && d.id !== entity.id) {
 
24700         } else if (d.type === 'way' && !d3.select(d3.event.sourceEvent.target).classed('fill')) {
 
24701             loc = iD.geo.chooseEdge(context.childNodes(d), context.mouse(), context.projection).loc;
 
24705             iD.actions.MoveNode(entity.id, loc),
 
24706             moveAnnotation(entity));
 
24709     function end(entity) {
 
24710         if (cancelled) return;
 
24714         if (d.type === 'way') {
 
24715             var choice = iD.geo.chooseEdge(context.childNodes(d), context.mouse(), context.projection);
 
24717                 iD.actions.AddMidpoint({ loc: choice.loc, edge: [d.nodes[choice.index - 1], d.nodes[choice.index]] }, entity),
 
24718                 connectAnnotation(d));
 
24720         } else if (d.type === 'node' && d.id !== entity.id) {
 
24722                 iD.actions.Connect([d.id, entity.id]),
 
24723                 connectAnnotation(d));
 
24725         } else if (wasMidpoint) {
 
24728                 t('operations.add.annotation.vertex'));
 
24733                 moveAnnotation(entity));
 
24736         var reselection = selectedIDs.filter(function(id) {
 
24737             return context.graph().hasEntity(id);
 
24740         if (reselection.length) {
 
24742                 iD.modes.Select(context, reselection)
 
24743                     .suppressMenu(true));
 
24745             context.enter(iD.modes.Browse(context));
 
24749     function cancel() {
 
24751         context.enter(iD.modes.Browse(context));
 
24754     function setActiveElements() {
 
24755         context.surface().selectAll(iD.util.entitySelector(activeIDs))
 
24756             .classed('active', true);
 
24759     var behavior = iD.behavior.drag()
 
24760         .delegate('g.node, g.point, g.midpoint')
 
24761         .surface(context.surface().node())
 
24763         .on('start', start)
 
24767     mode.enter = function() {
 
24768         context.install(hover);
 
24769         context.install(edit);
 
24772             .on('undone.drag-node', cancel);
 
24775             .on('drawn.drag-node', setActiveElements);
 
24777         setActiveElements();
 
24780     mode.exit = function() {
 
24781         context.ui().sidebar.hover.cancel();
 
24782         context.uninstall(hover);
 
24783         context.uninstall(edit);
 
24786             .on('undone.drag-node', null);
 
24789             .on('drawn.drag-node', null);
 
24792             .selectAll('.active')
 
24793             .classed('active', false);
 
24798     mode.selectedIDs = function(_) {
 
24799         if (!arguments.length) return selectedIDs;
 
24804     mode.behavior = behavior;
 
24808 iD.modes.DrawArea = function(context, wayId, baseGraph) {
 
24816     mode.enter = function() {
 
24817         var way = context.entity(wayId),
 
24818             headId = way.nodes[way.nodes.length - 2],
 
24819             tailId = way.first();
 
24821         behavior = iD.behavior.DrawWay(context, wayId, -1, mode, baseGraph)
 
24822             .tail(t('modes.draw_area.tail'));
 
24824         var addNode = behavior.addNode;
 
24826         behavior.addNode = function(node) {
 
24827             if (node.id === headId || node.id === tailId) {
 
24834         context.install(behavior);
 
24837     mode.exit = function() {
 
24838         context.uninstall(behavior);
 
24841     mode.selectedIDs = function() {
 
24847 iD.modes.DrawLine = function(context, wayId, baseGraph, affix) {
 
24855     mode.enter = function() {
 
24856         var way = context.entity(wayId),
 
24857             index = (affix === 'prefix') ? 0 : undefined,
 
24858             headId = (affix === 'prefix') ? way.first() : way.last();
 
24860         behavior = iD.behavior.DrawWay(context, wayId, index, mode, baseGraph)
 
24861             .tail(t('modes.draw_line.tail'));
 
24863         var addNode = behavior.addNode;
 
24865         behavior.addNode = function(node) {
 
24866             if (node.id === headId) {
 
24873         context.install(behavior);
 
24876     mode.exit = function() {
 
24877         context.uninstall(behavior);
 
24880     mode.selectedIDs = function() {
 
24886 iD.modes.Move = function(context, entityIDs, baseGraph) {
 
24892     var keybinding = d3.keybinding('move'),
 
24893         edit = iD.behavior.Edit(context),
 
24894         annotation = entityIDs.length === 1 ?
 
24895             t('operations.move.annotation.' + context.geometry(entityIDs[0])) :
 
24896             t('operations.move.annotation.multiple'),
 
24901     function vecSub(a, b) { return [a[0] - b[0], a[1] - b[1]]; }
 
24903     function edge(point, size) {
 
24904         var pad = [30, 100, 30, 100];
 
24905         if (point[0] > size[0] - pad[0]) return [-10, 0];
 
24906         else if (point[0] < pad[2]) return [10, 0];
 
24907         else if (point[1] > size[1] - pad[1]) return [0, -10];
 
24908         else if (point[1] < pad[3]) return [0, 10];
 
24912     function startNudge(nudge) {
 
24913         if (nudgeInterval) window.clearInterval(nudgeInterval);
 
24914         nudgeInterval = window.setInterval(function() {
 
24915             context.pan(nudge);
 
24917             var currMouse = context.mouse(),
 
24918                 origMouse = context.projection(origin),
 
24919                 delta = vecSub(vecSub(currMouse, origMouse), nudge),
 
24920                 action = iD.actions.Move(entityIDs, delta, context.projection, cache);
 
24922             context.overwrite(action, annotation);
 
24927     function stopNudge() {
 
24928         if (nudgeInterval) window.clearInterval(nudgeInterval);
 
24929         nudgeInterval = null;
 
24933         var currMouse = context.mouse(),
 
24934             origMouse = context.projection(origin),
 
24935             delta = vecSub(currMouse, origMouse),
 
24936             action = iD.actions.Move(entityIDs, delta, context.projection, cache);
 
24938         context.overwrite(action, annotation);
 
24940         var nudge = edge(currMouse, context.map().dimensions());
 
24941         if (nudge) startNudge(nudge);
 
24945     function finish() {
 
24946         d3.event.stopPropagation();
 
24947         context.enter(iD.modes.Select(context, entityIDs).suppressMenu(true));
 
24951     function cancel() {
 
24953             while (context.graph() !== baseGraph) context.pop();
 
24954             context.enter(iD.modes.Browse(context));
 
24957             context.enter(iD.modes.Select(context, entityIDs).suppressMenu(true));
 
24962     function undone() {
 
24963         context.enter(iD.modes.Browse(context));
 
24966     mode.enter = function() {
 
24967         origin = context.map().mouseCoordinates();
 
24970         context.install(edit);
 
24977             .on('mousemove.move', move)
 
24978             .on('click.move', finish);
 
24981             .on('undone.move', undone);
 
24987         d3.select(document)
 
24991     mode.exit = function() {
 
24994         context.uninstall(edit);
 
24997             .on('mousemove.move', null)
 
24998             .on('click.move', null);
 
25001             .on('undone.move', null);
 
25008 iD.modes.RotateWay = function(context, wayId) {
 
25014     var keybinding = d3.keybinding('rotate-way'),
 
25015         edit = iD.behavior.Edit(context);
 
25017     mode.enter = function() {
 
25018         context.install(edit);
 
25020         var annotation = t('operations.rotate.annotation.' + context.geometry(wayId)),
 
25021             way = context.graph().entity(wayId),
 
25022             nodes = _.uniq(context.graph().childNodes(way)),
 
25023             points = nodes.map(function(n) { return context.projection(n.loc); }),
 
25024             pivot = d3.geom.polygon(points).centroid(),
 
25031         function rotate() {
 
25033             var mousePoint = context.mouse(),
 
25034                 newAngle = Math.atan2(mousePoint[1] - pivot[1], mousePoint[0] - pivot[0]);
 
25036             if (typeof angle === 'undefined') angle = newAngle;
 
25039                 iD.actions.RotateWay(wayId, pivot, newAngle - angle, context.projection),
 
25045         function finish() {
 
25046             d3.event.stopPropagation();
 
25047             context.enter(iD.modes.Select(context, [wayId])
 
25048                 .suppressMenu(true));
 
25051         function cancel() {
 
25053             context.enter(iD.modes.Select(context, [wayId])
 
25054                 .suppressMenu(true));
 
25057         function undone() {
 
25058             context.enter(iD.modes.Browse(context));
 
25062             .on('mousemove.rotate-way', rotate)
 
25063             .on('click.rotate-way', finish);
 
25066             .on('undone.rotate-way', undone);
 
25072         d3.select(document)
 
25076     mode.exit = function() {
 
25077         context.uninstall(edit);
 
25080             .on('mousemove.rotate-way', null)
 
25081             .on('click.rotate-way', null);
 
25084             .on('undone.rotate-way', null);
 
25091 iD.modes.Save = function(context) {
 
25092     var ui = iD.ui.Commit(context)
 
25093             .on('cancel', cancel)
 
25096     function cancel() {
 
25097         context.enter(iD.modes.Browse(context));
 
25100     function save(e, tryAgain) {
 
25101         function withChildNodes(ids, graph) {
 
25102             return _.uniq(_.reduce(ids, function(result, id) {
 
25103                 var e = graph.entity(id);
 
25104                 if (e.type === 'way') {
 
25106                         var cn = graph.childNodes(e);
 
25107                         result.push.apply(result, _.pluck(_.filter(cn, 'version'), 'id'));
 
25109                         /* eslint-disable no-console */
 
25110                         if (typeof console !== 'undefined') console.error(err);
 
25111                         /* eslint-enable no-console */
 
25118         var loading = iD.ui.Loading(context).message(t('save.uploading')).blocking(true),
 
25119             history = context.history(),
 
25120             origChanges = history.changes(iD.actions.DiscardTags(history.difference())),
 
25121             localGraph = context.graph(),
 
25122             remoteGraph = iD.Graph(history.base(), true),
 
25123             modified = _.filter(history.difference().summary(), {changeType: 'modified'}),
 
25124             toCheck = _.pluck(_.pluck(modified, 'entity'), 'id'),
 
25125             toLoad = withChildNodes(toCheck, localGraph),
 
25129         if (!tryAgain) history.perform(iD.actions.Noop());  // checkpoint
 
25130         context.container().call(loading);
 
25132         if (toCheck.length) {
 
25133             context.connection().loadMultiple(toLoad, loaded);
 
25139         // Reload modified entities into an alternate graph and check for conflicts..
 
25140         function loaded(err, result) {
 
25141             if (errors.length) return;
 
25145                     msg: err.responseText,
 
25146                     details: [ t('save.status_code', { code: err.status }) ]
 
25152                 _.each(result.data, function(entity) {
 
25153                     remoteGraph.replace(entity);
 
25154                     toLoad = _.without(toLoad, entity.id);
 
25156                     // Because loadMultiple doesn't download /full like loadEntity,
 
25157                     // need to also load children that aren't already being checked..
 
25158                     if (!entity.visible) return;
 
25159                     if (entity.type === 'way') {
 
25160                         loadMore.push.apply(loadMore,
 
25161                             _.difference(entity.nodes, toCheck, toLoad, loadMore));
 
25162                     } else if (entity.type === 'relation' && entity.isMultipolygon()) {
 
25163                         loadMore.push.apply(loadMore,
 
25164                             _.difference(_.pluck(entity.members, 'id'), toCheck, toLoad, loadMore));
 
25168                 if (loadMore.length) {
 
25169                     toLoad.push.apply(toLoad, loadMore);
 
25170                     context.connection().loadMultiple(loadMore, loaded);
 
25173                 if (!toLoad.length) {
 
25180         function checkConflicts() {
 
25181             function choice(id, text, action) {
 
25182                 return { id: id, text: text, action: function() { history.replace(action); } };
 
25184             function formatUser(d) {
 
25185                 return '<a href="' + context.connection().userURL(d) + '" target="_blank">' + d + '</a>';
 
25187             function entityName(entity) {
 
25188                 return iD.util.displayName(entity) || (iD.util.displayType(entity.id) + ' ' + entity.id);
 
25191             function compareVersions(local, remote) {
 
25192                 if (local.version !== remote.version) return false;
 
25194                 if (local.type === 'way') {
 
25195                     var children = _.union(local.nodes, remote.nodes);
 
25197                     for (var i = 0; i < children.length; i++) {
 
25198                         var a = localGraph.hasEntity(children[i]),
 
25199                             b = remoteGraph.hasEntity(children[i]);
 
25201                         if (a && b && a.version !== b.version) return false;
 
25208             _.each(toCheck, function(id) {
 
25209                 var local = localGraph.entity(id),
 
25210                     remote = remoteGraph.entity(id);
 
25212                 if (compareVersions(local, remote)) return;
 
25214                 var action = iD.actions.MergeRemoteChanges,
 
25215                     merge = action(id, localGraph, remoteGraph, formatUser);
 
25217                 history.replace(merge);
 
25219                 var mergeConflicts = merge.conflicts();
 
25220                 if (!mergeConflicts.length) return;  // merged safely
 
25222                 var forceLocal = action(id, localGraph, remoteGraph).withOption('force_local'),
 
25223                     forceRemote = action(id, localGraph, remoteGraph).withOption('force_remote'),
 
25224                     keepMine = t('save.conflict.' + (remote.visible ? 'keep_local' : 'restore')),
 
25225                     keepTheirs = t('save.conflict.' + (remote.visible ? 'keep_remote' : 'delete'));
 
25229                     name: entityName(local),
 
25230                     details: mergeConflicts,
 
25233                         choice(id, keepMine, forceLocal),
 
25234                         choice(id, keepTheirs, forceRemote)
 
25243         function finalize() {
 
25244             if (conflicts.length) {
 
25245                 conflicts.sort(function(a,b) { return b.id.localeCompare(a.id); });
 
25247             } else if (errors.length) {
 
25250                 var changes = history.changes(iD.actions.DiscardTags(history.difference()));
 
25251                 if (changes.modified.length || changes.created.length || changes.deleted.length) {
 
25252                     context.connection().putChangeset(
 
25255                         history.imageryUsed(),
 
25256                         function(err, changeset_id) {
 
25259                                     msg: err.responseText,
 
25260                                     details: [ t('save.status_code', { code: err.status }) ]
 
25264                                 history.clearSaved();
 
25265                                 success(e, changeset_id);
 
25266                                 // Add delay to allow for postgres replication #1646 #2678
 
25267                                 window.setTimeout(function() {
 
25273                 } else {        // changes were insignificant or reverted by user
 
25282         function showConflicts() {
 
25283             var selection = context.container()
 
25284                 .select('#sidebar')
 
25286                 .attr('class','sidebar-component');
 
25290             selection.call(iD.ui.Conflicts(context)
 
25292                 .on('download', function() {
 
25293                     var data = JXON.stringify(context.connection().osmChangeJXON('CHANGEME', origChanges)),
 
25294                         win = window.open('data:text/xml,' + encodeURIComponent(data), '_blank');
 
25297                 .on('cancel', function() {
 
25299                     selection.remove();
 
25301                 .on('save', function() {
 
25302                     for (var i = 0; i < conflicts.length; i++) {
 
25303                         if (conflicts[i].chosen === 1) {  // user chose "keep theirs"
 
25304                             var entity = context.hasEntity(conflicts[i].id);
 
25305                             if (entity && entity.type === 'way') {
 
25306                                 var children = _.uniq(entity.nodes);
 
25307                                 for (var j = 0; j < children.length; j++) {
 
25308                                     history.replace(iD.actions.Revert(children[j]));
 
25311                             history.replace(iD.actions.Revert(conflicts[i].id));
 
25315                     selection.remove();
 
25322         function showErrors() {
 
25323             var selection = iD.ui.confirm(context.container());
 
25329                 .select('.modal-section.header')
 
25331                 .text(t('save.error'));
 
25333             addErrors(selection, errors);
 
25334             selection.okButton();
 
25338         function addErrors(selection, data) {
 
25339             var message = selection
 
25340                 .select('.modal-section.message-text');
 
25342             var items = message
 
25343                 .selectAll('.error-container')
 
25346             var enter = items.enter()
 
25348                 .attr('class', 'error-container');
 
25352                 .attr('class', 'error-description')
 
25354                 .classed('hide-toggle', true)
 
25355                 .text(function(d) { return d.msg || t('save.unknown_error_details'); })
 
25356                 .on('click', function() {
 
25357                     var error = d3.select(this),
 
25358                         detail = d3.select(this.nextElementSibling),
 
25359                         exp = error.classed('expanded');
 
25361                     detail.style('display', exp ? 'none' : 'block');
 
25362                     error.classed('expanded', !exp);
 
25364                     d3.event.preventDefault();
 
25367             var details = enter
 
25369                 .attr('class', 'error-detail-container')
 
25370                 .style('display', 'none');
 
25374                 .attr('class', 'error-detail-list')
 
25376                 .data(function(d) { return d.details || []; })
 
25379                 .attr('class', 'error-detail-item')
 
25380                 .text(function(d) { return d; });
 
25389     function success(e, changeset_id) {
 
25390         context.enter(iD.modes.Browse(context)
 
25391             .sidebar(iD.ui.Success(context)
 
25396                 .on('cancel', function() {
 
25397                     context.ui().sidebar.hide();
 
25405     mode.enter = function() {
 
25406         context.connection().authenticate(function(err) {
 
25410                 context.ui().sidebar.show(ui);
 
25415     mode.exit = function() {
 
25416         context.ui().sidebar.hide();
 
25421 iD.modes.Select = function(context, selectedIDs) {
 
25427     var keybinding = d3.keybinding('select'),
 
25430             iD.behavior.Copy(context),
 
25431             iD.behavior.Paste(context),
 
25432             iD.behavior.Breathe(context),
 
25433             iD.behavior.Hover(context),
 
25434             iD.behavior.Select(context),
 
25435             iD.behavior.Lasso(context),
 
25436             iD.modes.DragNode(context)
 
25437                 .selectedIDs(selectedIDs)
 
25441         newFeature = false,
 
25442         suppressMenu = false;
 
25444     var wrap = context.container()
 
25445         .select('.inspector-wrap');
 
25448     function singular() {
 
25449         if (selectedIDs.length === 1) {
 
25450             return context.hasEntity(selectedIDs[0]);
 
25454     function closeMenu() {
 
25456             context.surface().call(radialMenu.close);
 
25460     function positionMenu() {
 
25461         if (suppressMenu || !radialMenu) { return; }
 
25463         var entity = singular();
 
25464         if (entity && context.geometry(entity.id) === 'relation') {
 
25465             suppressMenu = true;
 
25466         } else if (entity && entity.type === 'node') {
 
25467             radialMenu.center(context.projection(entity.loc));
 
25469             var point = context.mouse(),
 
25470                 viewport = iD.geo.Extent(context.projection.clipExtent()).polygon();
 
25471             if (iD.geo.pointInPolygon(point, viewport)) {
 
25472                 radialMenu.center(point);
 
25474                 suppressMenu = true;
 
25479     function showMenu() {
 
25481         if (!suppressMenu && radialMenu) {
 
25482             context.surface().call(radialMenu);
 
25486     function toggleMenu() {
 
25487         if (d3.select('.radial-menu').empty()) {
 
25494     mode.selectedIDs = function() {
 
25495         return selectedIDs;
 
25498     mode.reselect = function() {
 
25499         var surfaceNode = context.surface().node();
 
25500         if (surfaceNode.focus) { // FF doesn't support it
 
25501             surfaceNode.focus();
 
25508     mode.newFeature = function(_) {
 
25509         if (!arguments.length) return newFeature;
 
25514     mode.suppressMenu = function(_) {
 
25515         if (!arguments.length) return suppressMenu;
 
25520     mode.enter = function() {
 
25521         function update() {
 
25523             if (_.any(selectedIDs, function(id) { return !context.hasEntity(id); })) {
 
25524                 // Exit mode if selected entity gets undone
 
25525                 context.enter(iD.modes.Browse(context));
 
25529         function dblclick() {
 
25530             var target = d3.select(d3.event.target),
 
25531                 datum = target.datum();
 
25533             if (datum instanceof iD.Way && !target.classed('fill')) {
 
25534                 var choice = iD.geo.chooseEdge(context.childNodes(datum), context.mouse(), context.projection),
 
25537                 var prev = datum.nodes[choice.index - 1],
 
25538                     next = datum.nodes[choice.index];
 
25541                     iD.actions.AddMidpoint({loc: choice.loc, edge: [prev, next]}, node),
 
25542                     t('operations.add.annotation.vertex'));
 
25544                 d3.event.preventDefault();
 
25545                 d3.event.stopPropagation();
 
25549         function selectElements(drawn) {
 
25550             var entity = singular();
 
25551             if (entity && context.geometry(entity.id) === 'relation') {
 
25552                 suppressMenu = true;
 
25556             var selection = context.surface()
 
25557                     .selectAll(iD.util.entityOrMemberSelector(selectedIDs, context.graph()));
 
25559             if (selection.empty()) {
 
25560                 if (drawn) {  // Exit mode if selected DOM elements have disappeared..
 
25561                     context.enter(iD.modes.Browse(context));
 
25565                     .classed('selected', true);
 
25570             if (!context.inIntro()) {
 
25571                 context.enter(iD.modes.Browse(context));
 
25576         behaviors.forEach(function(behavior) {
 
25577             context.install(behavior);
 
25580         var operations = _.without(d3.values(iD.operations), iD.operations.Delete)
 
25581                 .map(function(o) { return o(selectedIDs, context); })
 
25582                 .filter(function(o) { return o.available(); });
 
25584         operations.unshift(iD.operations.Delete(selectedIDs, context));
 
25587             .on('⎋', esc, true)
 
25588             .on('space', toggleMenu);
 
25590         operations.forEach(function(operation) {
 
25591             operation.keys.forEach(function(key) {
 
25592                 keybinding.on(key, function() {
 
25593                     if (!(context.inIntro() || operation.disabled())) {
 
25600         d3.select(document)
 
25603         radialMenu = iD.ui.RadialMenu(context, operations);
 
25605         context.ui().sidebar
 
25606             .select(singular() ? singular().id : null, newFeature);
 
25609             .on('undone.select', update)
 
25610             .on('redone.select', update);
 
25613             .on('move.select', closeMenu)
 
25614             .on('drawn.select', selectElements);
 
25618         var show = d3.event && !suppressMenu;
 
25624         timeout = window.setTimeout(function() {
 
25630                 .on('dblclick.select', dblclick);
 
25633         if (selectedIDs.length > 1) {
 
25634             var entities = iD.ui.SelectionList(context, selectedIDs);
 
25635             context.ui().sidebar.show(entities);
 
25639     mode.exit = function() {
 
25640         if (timeout) window.clearTimeout(timeout);
 
25642         if (inspector) wrap.call(inspector.close);
 
25644         behaviors.forEach(function(behavior) {
 
25645             context.uninstall(behavior);
 
25650         radialMenu = undefined;
 
25653             .on('undone.select', null)
 
25654             .on('redone.select', null);
 
25657             .on('dblclick.select', null)
 
25658             .selectAll('.selected')
 
25659             .classed('selected', false);
 
25661         context.map().on('drawn.select', null);
 
25662         context.ui().sidebar.hide();
 
25667 iD.operations = {};
 
25668 iD.operations.Circularize = function(selectedIDs, context) {
 
25669     var entityId = selectedIDs[0],
 
25670         entity = context.entity(entityId),
 
25671         extent = entity.extent(context.graph()),
 
25672         geometry = context.geometry(entityId),
 
25673         action = iD.actions.Circularize(entityId, context.projection);
 
25675     var operation = function() {
 
25676         var annotation = t('operations.circularize.annotation.' + geometry);
 
25677         context.perform(action, annotation);
 
25680     operation.available = function() {
 
25681         return selectedIDs.length === 1 &&
 
25682             entity.type === 'way' &&
 
25683             _.uniq(entity.nodes).length > 1;
 
25686     operation.disabled = function() {
 
25688         if (extent.percentContainedIn(context.extent()) < 0.8) {
 
25689             reason = 'too_large';
 
25690         } else if (context.hasHiddenConnections(entityId)) {
 
25691             reason = 'connected_to_hidden';
 
25693         return action.disabled(context.graph()) || reason;
 
25696     operation.tooltip = function() {
 
25697         var disable = operation.disabled();
 
25699             t('operations.circularize.' + disable) :
 
25700             t('operations.circularize.description.' + geometry);
 
25703     operation.id = 'circularize';
 
25704     operation.keys = [t('operations.circularize.key')];
 
25705     operation.title = t('operations.circularize.title');
 
25709 iD.operations.Continue = function(selectedIDs, context) {
 
25710     var graph = context.graph(),
 
25711         entities = selectedIDs.map(function(id) { return graph.entity(id); }),
 
25712         geometries = _.extend({line: [], vertex: []},
 
25713             _.groupBy(entities, function(entity) { return entity.geometry(graph); })),
 
25714         vertex = geometries.vertex[0];
 
25716     function candidateWays() {
 
25717         return graph.parentWays(vertex).filter(function(parent) {
 
25718             return parent.geometry(graph) === 'line' &&
 
25719                 parent.affix(vertex.id) &&
 
25720                 (geometries.line.length === 0 || geometries.line[0] === parent);
 
25724     var operation = function() {
 
25725         var candidate = candidateWays()[0];
 
25726         context.enter(iD.modes.DrawLine(
 
25730             candidate.affix(vertex.id)));
 
25733     operation.available = function() {
 
25734         return geometries.vertex.length === 1 && geometries.line.length <= 1 &&
 
25735             !context.features().hasHiddenConnections(vertex, context.graph());
 
25738     operation.disabled = function() {
 
25739         var candidates = candidateWays();
 
25740         if (candidates.length === 0)
 
25741             return 'not_eligible';
 
25742         if (candidates.length > 1)
 
25746     operation.tooltip = function() {
 
25747         var disable = operation.disabled();
 
25749             t('operations.continue.' + disable) :
 
25750             t('operations.continue.description');
 
25753     operation.id = 'continue';
 
25754     operation.keys = [t('operations.continue.key')];
 
25755     operation.title = t('operations.continue.title');
 
25759 iD.operations.Delete = function(selectedIDs, context) {
 
25760     var action = iD.actions.DeleteMultiple(selectedIDs);
 
25762     var operation = function() {
 
25766         if (selectedIDs.length > 1) {
 
25767             annotation = t('operations.delete.annotation.multiple', {n: selectedIDs.length});
 
25770             var id = selectedIDs[0],
 
25771                 entity = context.entity(id),
 
25772                 geometry = context.geometry(id),
 
25773                 parents = context.graph().parentWays(entity),
 
25774                 parent = parents[0];
 
25776             annotation = t('operations.delete.annotation.' + geometry);
 
25778             // Select the next closest node in the way.
 
25779             if (geometry === 'vertex' && parents.length === 1 && parent.nodes.length > 2) {
 
25780                 var nodes = parent.nodes,
 
25781                     i = nodes.indexOf(id);
 
25785                 } else if (i === nodes.length - 1) {
 
25788                     var a = iD.geo.sphericalDistance(entity.loc, context.entity(nodes[i - 1]).loc),
 
25789                         b = iD.geo.sphericalDistance(entity.loc, context.entity(nodes[i + 1]).loc);
 
25790                     i = a < b ? i - 1 : i + 1;
 
25793                 nextSelectedID = nodes[i];
 
25797         if (nextSelectedID && context.hasEntity(nextSelectedID)) {
 
25798             context.enter(iD.modes.Select(context, [nextSelectedID]));
 
25800             context.enter(iD.modes.Browse(context));
 
25808     operation.available = function() {
 
25812     operation.disabled = function() {
 
25814         if (_.any(selectedIDs, context.hasHiddenConnections)) {
 
25815             reason = 'connected_to_hidden';
 
25817         return action.disabled(context.graph()) || reason;
 
25820     operation.tooltip = function() {
 
25821         var disable = operation.disabled();
 
25823             t('operations.delete.' + disable) :
 
25824             t('operations.delete.description');
 
25827     operation.id = 'delete';
 
25828     operation.keys = [iD.ui.cmd('⌘⌫'), iD.ui.cmd('⌘⌦')];
 
25829     operation.title = t('operations.delete.title');
 
25833 iD.operations.Disconnect = function(selectedIDs, context) {
 
25834     var vertices = _.filter(selectedIDs, function vertex(entityId) {
 
25835         return context.geometry(entityId) === 'vertex';
 
25838     var entityId = vertices[0],
 
25839         action = iD.actions.Disconnect(entityId);
 
25841     if (selectedIDs.length > 1) {
 
25842         action.limitWays(_.without(selectedIDs, entityId));
 
25845     var operation = function() {
 
25846         context.perform(action, t('operations.disconnect.annotation'));
 
25849     operation.available = function() {
 
25850         return vertices.length === 1;
 
25853     operation.disabled = function() {
 
25855         if (_.any(selectedIDs, context.hasHiddenConnections)) {
 
25856             reason = 'connected_to_hidden';
 
25858         return action.disabled(context.graph()) || reason;
 
25861     operation.tooltip = function() {
 
25862         var disable = operation.disabled();
 
25864             t('operations.disconnect.' + disable) :
 
25865             t('operations.disconnect.description');
 
25868     operation.id = 'disconnect';
 
25869     operation.keys = [t('operations.disconnect.key')];
 
25870     operation.title = t('operations.disconnect.title');
 
25874 iD.operations.Merge = function(selectedIDs, context) {
 
25875     var join = iD.actions.Join(selectedIDs),
 
25876         merge = iD.actions.Merge(selectedIDs),
 
25877         mergePolygon = iD.actions.MergePolygon(selectedIDs);
 
25879     var operation = function() {
 
25880         var annotation = t('operations.merge.annotation', {n: selectedIDs.length}),
 
25883         if (!join.disabled(context.graph())) {
 
25885         } else if (!merge.disabled(context.graph())) {
 
25888             action = mergePolygon;
 
25891         context.perform(action, annotation);
 
25892         context.enter(iD.modes.Select(context, selectedIDs.filter(function(id) { return context.hasEntity(id); }))
 
25893             .suppressMenu(true));
 
25896     operation.available = function() {
 
25897         return selectedIDs.length >= 2;
 
25900     operation.disabled = function() {
 
25901         return join.disabled(context.graph()) &&
 
25902             merge.disabled(context.graph()) &&
 
25903             mergePolygon.disabled(context.graph());
 
25906     operation.tooltip = function() {
 
25907         var j = join.disabled(context.graph()),
 
25908             m = merge.disabled(context.graph()),
 
25909             p = mergePolygon.disabled(context.graph());
 
25911         if (j === 'restriction' && m && p)
 
25912             return t('operations.merge.restriction', {relation: context.presets().item('type/restriction').name()});
 
25914         if (p === 'incomplete_relation' && j && m)
 
25915             return t('operations.merge.incomplete_relation');
 
25918             return t('operations.merge.' + j);
 
25920         return t('operations.merge.description');
 
25923     operation.id = 'merge';
 
25924     operation.keys = [t('operations.merge.key')];
 
25925     operation.title = t('operations.merge.title');
 
25929 iD.operations.Move = function(selectedIDs, context) {
 
25930     var extent = selectedIDs.reduce(function(extent, id) {
 
25931             return extent.extend(context.entity(id).extent(context.graph()));
 
25932         }, iD.geo.Extent());
 
25934     var operation = function() {
 
25935         context.enter(iD.modes.Move(context, selectedIDs));
 
25938     operation.available = function() {
 
25939         return selectedIDs.length > 1 ||
 
25940             context.entity(selectedIDs[0]).type !== 'node';
 
25943     operation.disabled = function() {
 
25945         if (extent.area() && extent.percentContainedIn(context.extent()) < 0.8) {
 
25946             reason = 'too_large';
 
25947         } else if (_.any(selectedIDs, context.hasHiddenConnections)) {
 
25948             reason = 'connected_to_hidden';
 
25950         return iD.actions.Move(selectedIDs).disabled(context.graph()) || reason;
 
25953     operation.tooltip = function() {
 
25954         var disable = operation.disabled();
 
25956             t('operations.move.' + disable) :
 
25957             t('operations.move.description');
 
25960     operation.id = 'move';
 
25961     operation.keys = [t('operations.move.key')];
 
25962     operation.title = t('operations.move.title');
 
25966 iD.operations.Orthogonalize = function(selectedIDs, context) {
 
25967     var entityId = selectedIDs[0],
 
25968         entity = context.entity(entityId),
 
25969         extent = entity.extent(context.graph()),
 
25970         geometry = context.geometry(entityId),
 
25971         action = iD.actions.Orthogonalize(entityId, context.projection);
 
25973     var operation = function() {
 
25974         var annotation = t('operations.orthogonalize.annotation.' + geometry);
 
25975         context.perform(action, annotation);
 
25978     operation.available = function() {
 
25979         return selectedIDs.length === 1 &&
 
25980             entity.type === 'way' &&
 
25981             entity.isClosed() &&
 
25982             _.uniq(entity.nodes).length > 2;
 
25985     operation.disabled = function() {
 
25987         if (extent.percentContainedIn(context.extent()) < 0.8) {
 
25988             reason = 'too_large';
 
25989         } else if (context.hasHiddenConnections(entityId)) {
 
25990             reason = 'connected_to_hidden';
 
25992         return action.disabled(context.graph()) || reason;
 
25995     operation.tooltip = function() {
 
25996         var disable = operation.disabled();
 
25998             t('operations.orthogonalize.' + disable) :
 
25999             t('operations.orthogonalize.description.' + geometry);
 
26002     operation.id = 'orthogonalize';
 
26003     operation.keys = [t('operations.orthogonalize.key')];
 
26004     operation.title = t('operations.orthogonalize.title');
 
26008 iD.operations.Reverse = function(selectedIDs, context) {
 
26009     var entityId = selectedIDs[0];
 
26011     var operation = function() {
 
26013             iD.actions.Reverse(entityId),
 
26014             t('operations.reverse.annotation'));
 
26017     operation.available = function() {
 
26018         return selectedIDs.length === 1 &&
 
26019             context.geometry(entityId) === 'line';
 
26022     operation.disabled = function() {
 
26026     operation.tooltip = function() {
 
26027         return t('operations.reverse.description');
 
26030     operation.id = 'reverse';
 
26031     operation.keys = [t('operations.reverse.key')];
 
26032     operation.title = t('operations.reverse.title');
 
26036 iD.operations.Rotate = function(selectedIDs, context) {
 
26037     var entityId = selectedIDs[0],
 
26038         entity = context.entity(entityId),
 
26039         extent = entity.extent(context.graph()),
 
26040         geometry = context.geometry(entityId);
 
26042     var operation = function() {
 
26043         context.enter(iD.modes.RotateWay(context, entityId));
 
26046     operation.available = function() {
 
26047         if (selectedIDs.length !== 1 || entity.type !== 'way')
 
26049         if (geometry === 'area')
 
26051         if (entity.isClosed() &&
 
26052             context.graph().parentRelations(entity).some(function(r) { return r.isMultipolygon(); }))
 
26057     operation.disabled = function() {
 
26058         if (extent.percentContainedIn(context.extent()) < 0.8) {
 
26059             return 'too_large';
 
26060         } else if (context.hasHiddenConnections(entityId)) {
 
26061             return 'connected_to_hidden';
 
26067     operation.tooltip = function() {
 
26068         var disable = operation.disabled();
 
26070             t('operations.rotate.' + disable) :
 
26071             t('operations.rotate.description');
 
26074     operation.id = 'rotate';
 
26075     operation.keys = [t('operations.rotate.key')];
 
26076     operation.title = t('operations.rotate.title');
 
26080 iD.operations.Split = function(selectedIDs, context) {
 
26081     var vertices = _.filter(selectedIDs, function vertex(entityId) {
 
26082         return context.geometry(entityId) === 'vertex';
 
26085     var entityId = vertices[0],
 
26086         action = iD.actions.Split(entityId);
 
26088     if (selectedIDs.length > 1) {
 
26089         action.limitWays(_.without(selectedIDs, entityId));
 
26092     var operation = function() {
 
26095         var ways = action.ways(context.graph());
 
26096         if (ways.length === 1) {
 
26097             annotation = t('operations.split.annotation.' + context.geometry(ways[0].id));
 
26099             annotation = t('operations.split.annotation.multiple', {n: ways.length});
 
26102         var difference = context.perform(action, annotation);
 
26103         context.enter(iD.modes.Select(context, difference.extantIDs()));
 
26106     operation.available = function() {
 
26107         return vertices.length === 1;
 
26110     operation.disabled = function() {
 
26112         if (_.any(selectedIDs, context.hasHiddenConnections)) {
 
26113             reason = 'connected_to_hidden';
 
26115         return action.disabled(context.graph()) || reason;
 
26118     operation.tooltip = function() {
 
26119         var disable = operation.disabled();
 
26121             return t('operations.split.' + disable);
 
26124         var ways = action.ways(context.graph());
 
26125         if (ways.length === 1) {
 
26126             return t('operations.split.description.' + context.geometry(ways[0].id));
 
26128             return t('operations.split.description.multiple');
 
26132     operation.id = 'split';
 
26133     operation.keys = [t('operations.split.key')];
 
26134     operation.title = t('operations.split.title');
 
26138 iD.operations.Straighten = function(selectedIDs, context) {
 
26139     var entityId = selectedIDs[0],
 
26140         action = iD.actions.Straighten(entityId, context.projection);
 
26142     function operation() {
 
26143         var annotation = t('operations.straighten.annotation');
 
26144         context.perform(action, annotation);
 
26147     operation.available = function() {
 
26148         var entity = context.entity(entityId);
 
26149         return selectedIDs.length === 1 &&
 
26150             entity.type === 'way' &&
 
26151             !entity.isClosed() &&
 
26152             _.uniq(entity.nodes).length > 2;
 
26155     operation.disabled = function() {
 
26157         if (context.hasHiddenConnections(entityId)) {
 
26158             reason = 'connected_to_hidden';
 
26160         return action.disabled(context.graph()) || reason;
 
26163     operation.tooltip = function() {
 
26164         var disable = operation.disabled();
 
26166             t('operations.straighten.' + disable) :
 
26167             t('operations.straighten.description');
 
26170     operation.id = 'straighten';
 
26171     operation.keys = [t('operations.straighten.key')];
 
26172     operation.title = t('operations.straighten.title');
 
26176 iD.Connection = function(useHttps) {
 
26177     if (typeof useHttps !== 'boolean') {
 
26178       useHttps = window.location.protocol === 'https:';
 
26181     var event = d3.dispatch('authenticating', 'authenticated', 'auth', 'loading', 'loaded'),
 
26182         protocol = useHttps ? 'https:' : 'http:',
 
26183         url = protocol + '//www.openstreetmap.org',
 
26189             url: protocol + '//www.openstreetmap.org',
 
26190             oauth_consumer_key: '5A043yRSEugj4DJ5TljuapfnrflWDte8jTOcWLlT',
 
26191             oauth_secret: 'aB3jKq1TRsCOUrfOIZ6oQMEDmv2ptV76PA54NGLL',
 
26192             loading: authenticating,
 
26193             done: authenticated
 
26197         memberStr = 'member',
 
26200         relationStr = 'relation',
 
26205     connection.changesetURL = function(changesetId) {
 
26206         return url + '/changeset/' + changesetId;
 
26209     connection.changesetsURL = function(center, zoom) {
 
26210         var precision = Math.max(0, Math.ceil(Math.log(zoom) / Math.LN2));
 
26211         return url + '/history#map=' +
 
26212             Math.floor(zoom) + '/' +
 
26213             center[1].toFixed(precision) + '/' +
 
26214             center[0].toFixed(precision);
 
26217     connection.entityURL = function(entity) {
 
26218         return url + '/' + entity.type + '/' + entity.osmId();
 
26221     connection.userURL = function(username) {
 
26222         return url + '/user/' + username;
 
26225     connection.loadFromURL = function(url, callback) {
 
26226         function done(err, dom) {
 
26227             return callback(err, parse(dom));
 
26229         return d3.xml(url).get(done);
 
26232     connection.loadEntity = function(id, callback) {
 
26233         var type = iD.Entity.id.type(id),
 
26234             osmID = iD.Entity.id.toOSM(id);
 
26236         connection.loadFromURL(
 
26237             url + '/api/0.6/' + type + '/' + osmID + (type !== 'node' ? '/full' : ''),
 
26238             function(err, entities) {
 
26239                 if (callback) callback(err, {data: entities});
 
26243     connection.loadEntityVersion = function(id, version, callback) {
 
26244         var type = iD.Entity.id.type(id),
 
26245             osmID = iD.Entity.id.toOSM(id);
 
26247         connection.loadFromURL(
 
26248             url + '/api/0.6/' + type + '/' + osmID + '/' + version,
 
26249             function(err, entities) {
 
26250                 if (callback) callback(err, {data: entities});
 
26254     connection.loadMultiple = function(ids, callback) {
 
26255         _.each(_.groupBy(_.uniq(ids), iD.Entity.id.type), function(v, k) {
 
26256             var type = k + 's',
 
26257                 osmIDs = _.map(v, iD.Entity.id.toOSM);
 
26259             _.each(_.chunk(osmIDs, 150), function(arr) {
 
26260                 connection.loadFromURL(
 
26261                     url + '/api/0.6/' + type + '?' + type + '=' + arr.join(),
 
26262                     function(err, entities) {
 
26263                         if (callback) callback(err, {data: entities});
 
26269     function authenticating() {
 
26270         event.authenticating();
 
26273     function authenticated() {
 
26274         event.authenticated();
 
26277     function getLoc(attrs) {
 
26278         var lon = attrs.lon && attrs.lon.value,
 
26279             lat = attrs.lat && attrs.lat.value;
 
26280         return [parseFloat(lon), parseFloat(lat)];
 
26283     function getNodes(obj) {
 
26284         var elems = obj.getElementsByTagName(ndStr),
 
26285             nodes = new Array(elems.length);
 
26286         for (var i = 0, l = elems.length; i < l; i++) {
 
26287             nodes[i] = 'n' + elems[i].attributes.ref.value;
 
26292     function getTags(obj) {
 
26293         var elems = obj.getElementsByTagName(tagStr),
 
26295         for (var i = 0, l = elems.length; i < l; i++) {
 
26296             var attrs = elems[i].attributes;
 
26297             tags[attrs.k.value] = attrs.v.value;
 
26302     function getMembers(obj) {
 
26303         var elems = obj.getElementsByTagName(memberStr),
 
26304             members = new Array(elems.length);
 
26305         for (var i = 0, l = elems.length; i < l; i++) {
 
26306             var attrs = elems[i].attributes;
 
26308                 id: attrs.type.value[0] + attrs.ref.value,
 
26309                 type: attrs.type.value,
 
26310                 role: attrs.role.value
 
26316     function getVisible(attrs) {
 
26317         return (!attrs.visible || attrs.visible.value !== 'false');
 
26321         node: function nodeData(obj) {
 
26322             var attrs = obj.attributes;
 
26323             return new iD.Node({
 
26324                 id: iD.Entity.id.fromOSM(nodeStr, attrs.id.value),
 
26325                 loc: getLoc(attrs),
 
26326                 version: attrs.version.value,
 
26327                 user: attrs.user && attrs.user.value,
 
26328                 tags: getTags(obj),
 
26329                 visible: getVisible(attrs)
 
26333         way: function wayData(obj) {
 
26334             var attrs = obj.attributes;
 
26335             return new iD.Way({
 
26336                 id: iD.Entity.id.fromOSM(wayStr, attrs.id.value),
 
26337                 version: attrs.version.value,
 
26338                 user: attrs.user && attrs.user.value,
 
26339                 tags: getTags(obj),
 
26340                 nodes: getNodes(obj),
 
26341                 visible: getVisible(attrs)
 
26345         relation: function relationData(obj) {
 
26346             var attrs = obj.attributes;
 
26347             return new iD.Relation({
 
26348                 id: iD.Entity.id.fromOSM(relationStr, attrs.id.value),
 
26349                 version: attrs.version.value,
 
26350                 user: attrs.user && attrs.user.value,
 
26351                 tags: getTags(obj),
 
26352                 members: getMembers(obj),
 
26353                 visible: getVisible(attrs)
 
26358     function parse(dom) {
 
26359         if (!dom || !dom.childNodes) return;
 
26361         var root = dom.childNodes[0],
 
26362             children = root.childNodes,
 
26365         for (var i = 0, l = children.length; i < l; i++) {
 
26366             var child = children[i],
 
26367                 parser = parsers[child.nodeName];
 
26369                 entities.push(parser(child));
 
26376     connection.authenticated = function() {
 
26377         return oauth.authenticated();
 
26380     // Generate Changeset XML. Returns a string.
 
26381     connection.changesetJXON = function(tags) {
 
26385                     tag: _.map(tags, function(value, key) {
 
26386                         return { '@k': key, '@v': value };
 
26395     // Generate [osmChange](http://wiki.openstreetmap.org/wiki/OsmChange)
 
26396     // XML. Returns a string.
 
26397     connection.osmChangeJXON = function(changeset_id, changes) {
 
26398         function nest(x, order) {
 
26400             for (var i = 0; i < x.length; i++) {
 
26401                 var tagName = Object.keys(x[i])[0];
 
26402                 if (!groups[tagName]) groups[tagName] = [];
 
26403                 groups[tagName].push(x[i][tagName]);
 
26406             order.forEach(function(o) {
 
26407                 if (groups[o]) ordered[o] = groups[o];
 
26412         function rep(entity) {
 
26413             return entity.asJXON(changeset_id);
 
26419                 '@generator': 'iD',
 
26420                 'create': nest(changes.created.map(rep), ['node', 'way', 'relation']),
 
26421                 'modify': nest(changes.modified.map(rep), ['node', 'way', 'relation']),
 
26422                 'delete': _.extend(nest(changes.deleted.map(rep), ['relation', 'way', 'node']), {'@if-unused': true})
 
26427     connection.changesetTags = function(comment, imageryUsed) {
 
26428         var detected = iD.detect(),
 
26430                 created_by: 'iD ' + iD.version,
 
26431                 imagery_used: imageryUsed.join(';').substr(0, 255),
 
26432                 host: (window.location.origin + window.location.pathname).substr(0, 255),
 
26433                 locale: detected.locale
 
26437             tags.comment = comment.substr(0, 255);
 
26443     connection.putChangeset = function(changes, comment, imageryUsed, callback) {
 
26446                 path: '/api/0.6/changeset/create',
 
26447                 options: { header: { 'Content-Type': 'text/xml' } },
 
26448                 content: JXON.stringify(connection.changesetJXON(connection.changesetTags(comment, imageryUsed)))
 
26449             }, function(err, changeset_id) {
 
26450                 if (err) return callback(err);
 
26453                     path: '/api/0.6/changeset/' + changeset_id + '/upload',
 
26454                     options: { header: { 'Content-Type': 'text/xml' } },
 
26455                     content: JXON.stringify(connection.osmChangeJXON(changeset_id, changes))
 
26457                     if (err) return callback(err);
 
26458                     // POST was successful, safe to call the callback.
 
26459                     // Still attempt to close changeset, but ignore response because #2667
 
26460                     // Add delay to allow for postgres replication #1646 #2678
 
26461                     window.setTimeout(function() { callback(null, changeset_id); }, 2500);
 
26464                         path: '/api/0.6/changeset/' + changeset_id + '/close',
 
26465                         options: { header: { 'Content-Type': 'text/xml' } }
 
26466                     }, d3.functor(true));
 
26471     connection.userDetails = function(callback) {
 
26473             callback(undefined, userDetails);
 
26477         function done(err, user_details) {
 
26478             if (err) return callback(err);
 
26480             var u = user_details.getElementsByTagName('user')[0],
 
26481                 img = u.getElementsByTagName('img'),
 
26484             if (img && img[0] && img[0].getAttribute('href')) {
 
26485                 image_url = img[0].getAttribute('href');
 
26489                 display_name: u.attributes.display_name.value,
 
26490                 image_url: image_url,
 
26491                 id: u.attributes.id.value
 
26494             callback(undefined, userDetails);
 
26497         oauth.xhr({ method: 'GET', path: '/api/0.6/user/details' }, done);
 
26500     connection.userChangesets = function(callback) {
 
26501         connection.userDetails(function(err, user) {
 
26502             if (err) return callback(err);
 
26504             function done(changesets) {
 
26505                 callback(undefined, Array.prototype.map.call(changesets.getElementsByTagName('changeset'),
 
26506                     function (changeset) {
 
26507                         return { tags: getTags(changeset) };
 
26511             d3.xml(url + '/api/0.6/changesets?user=' + user.id).get()
 
26513                 .on('error', callback);
 
26517     connection.status = function(callback) {
 
26518         function done(capabilities) {
 
26519             var apiStatus = capabilities.getElementsByTagName('status');
 
26520             callback(undefined, apiStatus[0].getAttribute('api'));
 
26522         d3.xml(url + '/api/capabilities').get()
 
26524             .on('error', callback);
 
26527     function abortRequest(i) { i.abort(); }
 
26529     connection.tileZoom = function(_) {
 
26530         if (!arguments.length) return tileZoom;
 
26535     connection.loadTiles = function(projection, dimensions, callback) {
 
26539         var s = projection.scale() * 2 * Math.PI,
 
26540             z = Math.max(Math.log(s) / Math.log(2) - 8, 0),
 
26541             ts = 256 * Math.pow(2, z - tileZoom),
 
26543                 s / 2 - projection.translate()[0],
 
26544                 s / 2 - projection.translate()[1]];
 
26546         var tiles = d3.geo.tile()
 
26547             .scaleExtent([tileZoom, tileZoom])
 
26550             .translate(projection.translate())()
 
26551             .map(function(tile) {
 
26552                 var x = tile[0] * ts - origin[0],
 
26553                     y = tile[1] * ts - origin[1];
 
26556                     id: tile.toString(),
 
26557                     extent: iD.geo.Extent(
 
26558                         projection.invert([x, y + ts]),
 
26559                         projection.invert([x + ts, y]))
 
26563         function bboxUrl(tile) {
 
26564             return url + '/api/0.6/map?bbox=' + tile.extent.toParam();
 
26567         _.filter(inflight, function(v, i) {
 
26568             var wanted = _.find(tiles, function(tile) {
 
26569                 return i === tile.id;
 
26571             if (!wanted) delete inflight[i];
 
26573         }).map(abortRequest);
 
26575         tiles.forEach(function(tile) {
 
26578             if (loadedTiles[id] || inflight[id]) return;
 
26580             if (_.isEmpty(inflight)) {
 
26584             inflight[id] = connection.loadFromURL(bboxUrl(tile), function(err, parsed) {
 
26585                 loadedTiles[id] = true;
 
26586                 delete inflight[id];
 
26588                 if (callback) callback(err, _.extend({data: parsed}, tile));
 
26590                 if (_.isEmpty(inflight)) {
 
26597     connection.switch = function(options) {
 
26599         oauth.options(_.extend({
 
26600             loading: authenticating,
 
26601             done: authenticated
 
26604         connection.flush();
 
26608     connection.toggle = function(_) {
 
26613     connection.flush = function() {
 
26614         userDetails = undefined;
 
26615         _.forEach(inflight, abortRequest);
 
26621     connection.loadedTiles = function(_) {
 
26622         if (!arguments.length) return loadedTiles;
 
26627     connection.logout = function() {
 
26628         userDetails = undefined;
 
26634     connection.authenticate = function(callback) {
 
26635         userDetails = undefined;
 
26636         function done(err, res) {
 
26638             if (callback) callback(err, res);
 
26640         return oauth.authenticate(done);
 
26643     return d3.rebind(connection, event, 'on');
 
26646     iD.Difference represents the difference between two graphs.
 
26647     It knows how to calculate the set of entities that were
 
26648     created, modified, or deleted, and also contains the logic
 
26649     for recursively extending a difference to the complete set
 
26650     of entities that will require a redraw, taking into account
 
26651     child and parent relationships.
 
26653 iD.Difference = function(base, head) {
 
26654     var changes = {}, length = 0;
 
26656     function changed(h, b) {
 
26657         return h !== b && !_.isEqual(_.omit(h, 'v'), _.omit(b, 'v'));
 
26660     _.each(head.entities, function(h, id) {
 
26661         var b = base.entities[id];
 
26662         if (changed(h, b)) {
 
26663             changes[id] = {base: b, head: h};
 
26668     _.each(base.entities, function(b, id) {
 
26669         var h = head.entities[id];
 
26670         if (!changes[id] && changed(h, b)) {
 
26671             changes[id] = {base: b, head: h};
 
26676     function addParents(parents, result) {
 
26677         for (var i = 0; i < parents.length; i++) {
 
26678             var parent = parents[i];
 
26680             if (parent.id in result)
 
26683             result[parent.id] = parent;
 
26684             addParents(head.parentRelations(parent), result);
 
26688     var difference = {};
 
26690     difference.length = function() {
 
26694     difference.changes = function() {
 
26698     difference.extantIDs = function() {
 
26700         _.each(changes, function(change, id) {
 
26701             if (change.head) result.push(id);
 
26706     difference.modified = function() {
 
26708         _.each(changes, function(change) {
 
26709             if (change.base && change.head) result.push(change.head);
 
26714     difference.created = function() {
 
26716         _.each(changes, function(change) {
 
26717             if (!change.base && change.head) result.push(change.head);
 
26722     difference.deleted = function() {
 
26724         _.each(changes, function(change) {
 
26725             if (change.base && !change.head) result.push(change.base);
 
26730     difference.summary = function() {
 
26733         function addEntity(entity, graph, changeType) {
 
26734             relevant[entity.id] = {
 
26737                 changeType: changeType
 
26741         function addParents(entity) {
 
26742             var parents = head.parentWays(entity);
 
26743             for (var j = parents.length - 1; j >= 0; j--) {
 
26744                 var parent = parents[j];
 
26745                 if (!(parent.id in relevant)) addEntity(parent, head, 'modified');
 
26749         _.each(changes, function(change) {
 
26750             if (change.head && change.head.geometry(head) !== 'vertex') {
 
26751                 addEntity(change.head, head, change.base ? 'modified' : 'created');
 
26753             } else if (change.base && change.base.geometry(base) !== 'vertex') {
 
26754                 addEntity(change.base, base, 'deleted');
 
26756             } else if (change.base && change.head) { // modified vertex
 
26757                 var moved    = !_.isEqual(change.base.loc,  change.head.loc),
 
26758                     retagged = !_.isEqual(change.base.tags, change.head.tags);
 
26761                     addParents(change.head);
 
26764                 if (retagged || (moved && change.head.hasInterestingTags())) {
 
26765                     addEntity(change.head, head, 'modified');
 
26768             } else if (change.head && change.head.hasInterestingTags()) { // created vertex
 
26769                 addEntity(change.head, head, 'created');
 
26771             } else if (change.base && change.base.hasInterestingTags()) { // deleted vertex
 
26772                 addEntity(change.base, base, 'deleted');
 
26776         return d3.values(relevant);
 
26779     difference.complete = function(extent) {
 
26780         var result = {}, id, change;
 
26782         for (id in changes) {
 
26783             change = changes[id];
 
26785             var h = change.head,
 
26790                 (!h || !h.intersects(extent, head)) &&
 
26791                 (!b || !b.intersects(extent, base)))
 
26796             if (entity.type === 'way') {
 
26797                 var nh = h ? h.nodes : [],
 
26798                     nb = b ? b.nodes : [],
 
26801                 diff = _.difference(nh, nb);
 
26802                 for (i = 0; i < diff.length; i++) {
 
26803                     result[diff[i]] = head.hasEntity(diff[i]);
 
26806                 diff = _.difference(nb, nh);
 
26807                 for (i = 0; i < diff.length; i++) {
 
26808                     result[diff[i]] = head.hasEntity(diff[i]);
 
26812             addParents(head.parentWays(entity), result);
 
26813             addParents(head.parentRelations(entity), result);
 
26821 iD.Entity = function(attrs) {
 
26822     // For prototypal inheritance.
 
26823     if (this instanceof iD.Entity) return;
 
26825     // Create the appropriate subtype.
 
26826     if (attrs && attrs.type) {
 
26827         return iD.Entity[attrs.type].apply(this, arguments);
 
26828     } else if (attrs && attrs.id) {
 
26829         return iD.Entity[iD.Entity.id.type(attrs.id)].apply(this, arguments);
 
26832     // Initialize a generic Entity (used only in tests).
 
26833     return (new iD.Entity()).initialize(arguments);
 
26836 iD.Entity.id = function(type) {
 
26837     return iD.Entity.id.fromOSM(type, iD.Entity.id.next[type]--);
 
26840 iD.Entity.id.next = {node: -1, way: -1, relation: -1};
 
26842 iD.Entity.id.fromOSM = function(type, id) {
 
26843     return type[0] + id;
 
26846 iD.Entity.id.toOSM = function(id) {
 
26847     return id.slice(1);
 
26850 iD.Entity.id.type = function(id) {
 
26851     return {'n': 'node', 'w': 'way', 'r': 'relation'}[id[0]];
 
26854 // A function suitable for use as the second argument to d3.selection#data().
 
26855 iD.Entity.key = function(entity) {
 
26856     return entity.id + 'v' + (entity.v || 0);
 
26859 iD.Entity.prototype = {
 
26862     initialize: function(sources) {
 
26863         for (var i = 0; i < sources.length; ++i) {
 
26864             var source = sources[i];
 
26865             for (var prop in source) {
 
26866                 if (Object.prototype.hasOwnProperty.call(source, prop)) {
 
26867                     if (source[prop] === undefined) {
 
26870                         this[prop] = source[prop];
 
26876         if (!this.id && this.type) {
 
26877             this.id = iD.Entity.id(this.type);
 
26879         if (!this.hasOwnProperty('visible')) {
 
26880             this.visible = true;
 
26884             Object.freeze(this);
 
26885             Object.freeze(this.tags);
 
26887             if (this.loc) Object.freeze(this.loc);
 
26888             if (this.nodes) Object.freeze(this.nodes);
 
26889             if (this.members) Object.freeze(this.members);
 
26895     copy: function(resolver, copies) {
 
26896         if (copies[this.id])
 
26897             return copies[this.id];
 
26899         var copy = iD.Entity(this, {id: undefined, user: undefined, version: undefined});
 
26900         copies[this.id] = copy;
 
26905     osmId: function() {
 
26906         return iD.Entity.id.toOSM(this.id);
 
26909     isNew: function() {
 
26910         return this.osmId() < 0;
 
26913     update: function(attrs) {
 
26914         return iD.Entity(this, attrs, {v: 1 + (this.v || 0)});
 
26917     mergeTags: function(tags) {
 
26918         var merged = _.clone(this.tags), changed = false;
 
26919         for (var k in tags) {
 
26920             var t1 = merged[k],
 
26925             } else if (t1 !== t2) {
 
26927                 merged[k] = _.union(t1.split(/;\s*/), t2.split(/;\s*/)).join(';');
 
26930         return changed ? this.update({tags: merged}) : this;
 
26933     intersects: function(extent, resolver) {
 
26934         return this.extent(resolver).intersects(extent);
 
26937     isUsed: function(resolver) {
 
26938         return _.without(Object.keys(this.tags), 'area').length > 0 ||
 
26939             resolver.parentRelations(this).length > 0;
 
26942     hasInterestingTags: function() {
 
26943         return _.keys(this.tags).some(iD.interestingTag);
 
26946     isHighwayIntersection: function() {
 
26950     deprecatedTags: function() {
 
26951         var tags = _.pairs(this.tags);
 
26952         var deprecated = {};
 
26954         iD.data.deprecated.forEach(function(d) {
 
26955             var match = _.pairs(d.old)[0];
 
26956             tags.forEach(function(t) {
 
26957                 if (t[0] === match[0] &&
 
26958                     (t[1] === match[1] || match[1] === '*')) {
 
26959                     deprecated[t[0]] = t[1];
 
26967 iD.Graph = function(other, mutable) {
 
26968     if (!(this instanceof iD.Graph)) return new iD.Graph(other, mutable);
 
26970     if (other instanceof iD.Graph) {
 
26971         var base = other.base();
 
26972         this.entities = _.assign(Object.create(base.entities), other.entities);
 
26973         this._parentWays = _.assign(Object.create(base.parentWays), other._parentWays);
 
26974         this._parentRels = _.assign(Object.create(base.parentRels), other._parentRels);
 
26977         this.entities = Object.create({});
 
26978         this._parentWays = Object.create({});
 
26979         this._parentRels = Object.create({});
 
26980         this.rebase(other || [], [this]);
 
26983     this.transients = {};
 
26984     this._childNodes = {};
 
26985     this.frozen = !mutable;
 
26988 iD.Graph.prototype = {
 
26989     hasEntity: function(id) {
 
26990         return this.entities[id];
 
26993     entity: function(id) {
 
26994         var entity = this.entities[id];
 
26996             throw new Error('entity ' + id + ' not found');
 
27001     transient: function(entity, key, fn) {
 
27002         var id = entity.id,
 
27003             transients = this.transients[id] ||
 
27004             (this.transients[id] = {});
 
27006         if (transients[key] !== undefined) {
 
27007             return transients[key];
 
27010         transients[key] = fn.call(entity);
 
27012         return transients[key];
 
27015     parentWays: function(entity) {
 
27016         var parents = this._parentWays[entity.id],
 
27020             for (var i = 0; i < parents.length; i++) {
 
27021                 result.push(this.entity(parents[i]));
 
27027     isPoi: function(entity) {
 
27028         var parentWays = this._parentWays[entity.id];
 
27029         return !parentWays || parentWays.length === 0;
 
27032     isShared: function(entity) {
 
27033         var parentWays = this._parentWays[entity.id];
 
27034         return parentWays && parentWays.length > 1;
 
27037     parentRelations: function(entity) {
 
27038         var parents = this._parentRels[entity.id],
 
27042             for (var i = 0; i < parents.length; i++) {
 
27043                 result.push(this.entity(parents[i]));
 
27049     childNodes: function(entity) {
 
27050         if (this._childNodes[entity.id]) return this._childNodes[entity.id];
 
27051         if (!entity.nodes) return [];
 
27054         for (var i = 0; i < entity.nodes.length; i++) {
 
27055             nodes[i] = this.entity(entity.nodes[i]);
 
27058         if (iD.debug) Object.freeze(nodes);
 
27060         this._childNodes[entity.id] = nodes;
 
27061         return this._childNodes[entity.id];
 
27066             'entities': iD.util.getPrototypeOf(this.entities),
 
27067             'parentWays': iD.util.getPrototypeOf(this._parentWays),
 
27068             'parentRels': iD.util.getPrototypeOf(this._parentRels)
 
27072     // Unlike other graph methods, rebase mutates in place. This is because it
 
27073     // is used only during the history operation that merges newly downloaded
 
27074     // data into each state. To external consumers, it should appear as if the
 
27075     // graph always contained the newly downloaded data.
 
27076     rebase: function(entities, stack, force) {
 
27077         var base = this.base(),
 
27080         for (i = 0; i < entities.length; i++) {
 
27081             var entity = entities[i];
 
27083             if (!entity.visible || (!force && base.entities[entity.id]))
 
27086             // Merging data into the base graph
 
27087             base.entities[entity.id] = entity;
 
27088             this._updateCalculated(undefined, entity, base.parentWays, base.parentRels);
 
27090             // Restore provisionally-deleted nodes that are discovered to have an extant parent
 
27091             if (entity.type === 'way') {
 
27092                 for (j = 0; j < entity.nodes.length; j++) {
 
27093                     id = entity.nodes[j];
 
27094                     for (k = 1; k < stack.length; k++) {
 
27095                         var ents = stack[k].entities;
 
27096                         if (ents.hasOwnProperty(id) && ents[id] === undefined) {
 
27104         for (i = 0; i < stack.length; i++) {
 
27105             stack[i]._updateRebased();
 
27109     _updateRebased: function() {
 
27110         var base = this.base(),
 
27111             i, k, child, id, keys;
 
27113         keys = Object.keys(this._parentWays);
 
27114         for (i = 0; i < keys.length; i++) {
 
27116             if (base.parentWays[child]) {
 
27117                 for (k = 0; k < base.parentWays[child].length; k++) {
 
27118                     id = base.parentWays[child][k];
 
27119                     if (!this.entities.hasOwnProperty(id) && !_.contains(this._parentWays[child], id)) {
 
27120                         this._parentWays[child].push(id);
 
27126         keys = Object.keys(this._parentRels);
 
27127         for (i = 0; i < keys.length; i++) {
 
27129             if (base.parentRels[child]) {
 
27130                 for (k = 0; k < base.parentRels[child].length; k++) {
 
27131                     id = base.parentRels[child][k];
 
27132                     if (!this.entities.hasOwnProperty(id) && !_.contains(this._parentRels[child], id)) {
 
27133                         this._parentRels[child].push(id);
 
27139         this.transients = {};
 
27141         // this._childNodes is not updated, under the assumption that
 
27142         // ways are always downloaded with their child nodes.
 
27145     // Updates calculated properties (parentWays, parentRels) for the specified change
 
27146     _updateCalculated: function(oldentity, entity, parentWays, parentRels) {
 
27148         parentWays = parentWays || this._parentWays;
 
27149         parentRels = parentRels || this._parentRels;
 
27151         var type = entity && entity.type || oldentity && oldentity.type,
 
27152             removed, added, ways, rels, i;
 
27155         if (type === 'way') {
 
27157             // Update parentWays
 
27158             if (oldentity && entity) {
 
27159                 removed = _.difference(oldentity.nodes, entity.nodes);
 
27160                 added = _.difference(entity.nodes, oldentity.nodes);
 
27161             } else if (oldentity) {
 
27162                 removed = oldentity.nodes;
 
27164             } else if (entity) {
 
27166                 added = entity.nodes;
 
27168             for (i = 0; i < removed.length; i++) {
 
27169                 parentWays[removed[i]] = _.without(parentWays[removed[i]], oldentity.id);
 
27171             for (i = 0; i < added.length; i++) {
 
27172                 ways = _.without(parentWays[added[i]], entity.id);
 
27173                 ways.push(entity.id);
 
27174                 parentWays[added[i]] = ways;
 
27177         } else if (type === 'relation') {
 
27179             // Update parentRels
 
27180             if (oldentity && entity) {
 
27181                 removed = _.difference(oldentity.members, entity.members);
 
27182                 added = _.difference(entity.members, oldentity);
 
27183             } else if (oldentity) {
 
27184                 removed = oldentity.members;
 
27186             } else if (entity) {
 
27188                 added = entity.members;
 
27190             for (i = 0; i < removed.length; i++) {
 
27191                 parentRels[removed[i].id] = _.without(parentRels[removed[i].id], oldentity.id);
 
27193             for (i = 0; i < added.length; i++) {
 
27194                 rels = _.without(parentRels[added[i].id], entity.id);
 
27195                 rels.push(entity.id);
 
27196                 parentRels[added[i].id] = rels;
 
27201     replace: function(entity) {
 
27202         if (this.entities[entity.id] === entity)
 
27205         return this.update(function() {
 
27206             this._updateCalculated(this.entities[entity.id], entity);
 
27207             this.entities[entity.id] = entity;
 
27211     remove: function(entity) {
 
27212         return this.update(function() {
 
27213             this._updateCalculated(entity, undefined);
 
27214             this.entities[entity.id] = undefined;
 
27218     revert: function(id) {
 
27219         var baseEntity = this.base().entities[id],
 
27220             headEntity = this.entities[id];
 
27222         if (headEntity === baseEntity)
 
27225         return this.update(function() {
 
27226             this._updateCalculated(headEntity, baseEntity);
 
27227             delete this.entities[id];
 
27231     update: function() {
 
27232         var graph = this.frozen ? iD.Graph(this, true) : this;
 
27234         for (var i = 0; i < arguments.length; i++) {
 
27235             arguments[i].call(graph, graph);
 
27238         if (this.frozen) graph.frozen = true;
 
27243     // Obliterates any existing entities
 
27244     load: function(entities) {
 
27245         var base = this.base();
 
27246         this.entities = Object.create(base.entities);
 
27248         for (var i in entities) {
 
27249             this.entities[i] = entities[i];
 
27250             this._updateCalculated(base.entities[i], this.entities[i]);
 
27256 iD.History = function(context) {
 
27257     var stack, index, tree,
 
27258         imageryUsed = ['Bing'],
 
27259         dispatch = d3.dispatch('change', 'undone', 'redone'),
 
27260         lock = iD.util.SessionMutex('lock');
 
27262     function perform(actions) {
 
27263         actions = Array.prototype.slice.call(actions);
 
27267         if (!_.isFunction(_.last(actions))) {
 
27268             annotation = actions.pop();
 
27271         var graph = stack[index].graph;
 
27272         for (var i = 0; i < actions.length; i++) {
 
27273             graph = actions[i](graph);
 
27278             annotation: annotation,
 
27279             imageryUsed: imageryUsed
 
27283     function change(previous) {
 
27284         var difference = iD.Difference(previous, history.graph());
 
27285         dispatch.change(difference);
 
27289     // iD uses namespaced keys so multiple installations do not conflict
 
27290     function getKey(n) {
 
27291         return 'iD_' + window.location.origin + '_' + n;
 
27295         graph: function() {
 
27296             return stack[index].graph;
 
27300             return stack[0].graph;
 
27303         merge: function(entities, extent) {
 
27304             stack[0].graph.rebase(entities, _.pluck(stack, 'graph'), false);
 
27305             tree.rebase(entities, false);
 
27307             dispatch.change(undefined, extent);
 
27310         perform: function() {
 
27311             var previous = stack[index].graph;
 
27313             stack = stack.slice(0, index + 1);
 
27314             stack.push(perform(arguments));
 
27317             return change(previous);
 
27320         replace: function() {
 
27321             var previous = stack[index].graph;
 
27323             // assert(index == stack.length - 1)
 
27324             stack[index] = perform(arguments);
 
27326             return change(previous);
 
27330             var previous = stack[index].graph;
 
27335                 return change(previous);
 
27339         // Same as calling pop and then perform
 
27340         overwrite: function() {
 
27341             var previous = stack[index].graph;
 
27347             stack = stack.slice(0, index + 1);
 
27348             stack.push(perform(arguments));
 
27351             return change(previous);
 
27355             var previous = stack[index].graph;
 
27357             // Pop to the next annotated state.
 
27358             while (index > 0) {
 
27360                 if (stack[index].annotation) break;
 
27364             return change(previous);
 
27368             var previous = stack[index].graph;
 
27370             while (index < stack.length - 1) {
 
27372                 if (stack[index].annotation) break;
 
27376             return change(previous);
 
27379         undoAnnotation: function() {
 
27382                 if (stack[i].annotation) return stack[i].annotation;
 
27387         redoAnnotation: function() {
 
27389             while (i <= stack.length - 1) {
 
27390                 if (stack[i].annotation) return stack[i].annotation;
 
27395         intersects: function(extent) {
 
27396             return tree.intersects(extent, stack[index].graph);
 
27399         difference: function() {
 
27400             var base = stack[0].graph,
 
27401                 head = stack[index].graph;
 
27402             return iD.Difference(base, head);
 
27405         changes: function(action) {
 
27406             var base = stack[0].graph,
 
27407                 head = stack[index].graph;
 
27410                 head = action(head);
 
27413             var difference = iD.Difference(base, head);
 
27416                 modified: difference.modified(),
 
27417                 created: difference.created(),
 
27418                 deleted: difference.deleted()
 
27422         validate: function(changes) {
 
27423             return _(iD.validations)
 
27424                 .map(function(fn) { return fn()(changes, stack[index].graph); })
 
27429         hasChanges: function() {
 
27430             return this.difference().length() > 0;
 
27433         imageryUsed: function(sources) {
 
27435                 imageryUsed = sources;
 
27438                 return _(stack.slice(1, index + 1))
 
27439                     .pluck('imageryUsed')
 
27442                     .without(undefined, 'Custom')
 
27447         reset: function() {
 
27448             stack = [{graph: iD.Graph()}];
 
27450             tree = iD.Tree(stack[0].graph);
 
27455         toJSON: function() {
 
27456             if (!this.hasChanges()) return;
 
27458             var allEntities = {},
 
27462             var s = stack.map(function(i) {
 
27463                 var modified = [], deleted = [];
 
27465                 _.forEach(i.graph.entities, function(entity, id) {
 
27467                         var key = iD.Entity.key(entity);
 
27468                         allEntities[key] = entity;
 
27469                         modified.push(key);
 
27474                     // make sure that the originals of changed or deleted entities get merged
 
27475                     // into the base of the stack after restoring the data from JSON.
 
27476                     if (id in base.graph.entities) {
 
27477                         baseEntities[id] = base.graph.entities[id];
 
27479                     // get originals of parent entities too
 
27480                     _.forEach(base.graph._parentWays[id], function(parentId) {
 
27481                         if (parentId in base.graph.entities) {
 
27482                             baseEntities[parentId] = base.graph.entities[parentId];
 
27489                 if (modified.length) x.modified = modified;
 
27490                 if (deleted.length) x.deleted = deleted;
 
27491                 if (i.imageryUsed) x.imageryUsed = i.imageryUsed;
 
27492                 if (i.annotation) x.annotation = i.annotation;
 
27497             return JSON.stringify({
 
27499                 entities: _.values(allEntities),
 
27500                 baseEntities: _.values(baseEntities),
 
27502                 nextIDs: iD.Entity.id.next,
 
27507         fromJSON: function(json, loadChildNodes) {
 
27508             var h = JSON.parse(json),
 
27509                 loadComplete = true;
 
27511             iD.Entity.id.next = h.nextIDs;
 
27514             if (h.version === 2 || h.version === 3) {
 
27515                 var allEntities = {};
 
27517                 h.entities.forEach(function(entity) {
 
27518                     allEntities[iD.Entity.key(entity)] = iD.Entity(entity);
 
27521                 if (h.version === 3) {
 
27522                     // This merges originals for changed entities into the base of
 
27523                     // the stack even if the current stack doesn't have them (for
 
27524                     // example when iD has been restarted in a different region)
 
27525                     var baseEntities = h.baseEntities.map(function(d) { return iD.Entity(d); });
 
27526                     stack[0].graph.rebase(baseEntities, _.pluck(stack, 'graph'), true);
 
27527                     tree.rebase(baseEntities, true);
 
27529                     // When we restore a modified way, we also need to fetch any missing
 
27530                     // childnodes that would normally have been downloaded with it.. #2142
 
27531                     if (loadChildNodes) {
 
27532                         var missing =  _(baseEntities)
 
27533                                 .filter('type', 'way')
 
27537                                 .reject(function(n) { return stack[0].graph.hasEntity(n); })
 
27540                         if (!_.isEmpty(missing)) {
 
27541                             loadComplete = false;
 
27542                             context.redrawEnable(false);
 
27544                             var loading = iD.ui.Loading(context).blocking(true);
 
27545                             context.container().call(loading);
 
27547                             var childNodesLoaded = function(err, result) {
 
27549                                     var visible = _.groupBy(result.data, 'visible');
 
27550                                     if (!_.isEmpty(visible.true)) {
 
27551                                         missing = _.difference(missing, _.pluck(visible.true, 'id'));
 
27552                                         stack[0].graph.rebase(visible.true, _.pluck(stack, 'graph'), true);
 
27553                                         tree.rebase(visible.true, true);
 
27556                                     // fetch older versions of nodes that were deleted..
 
27557                                     _.each(visible.false, function(entity) {
 
27558                                         context.connection()
 
27559                                             .loadEntityVersion(entity.id, +entity.version - 1, childNodesLoaded);
 
27563                                 if (err || _.isEmpty(missing)) {
 
27565                                     context.redrawEnable(true);
 
27570                             context.connection().loadMultiple(missing, childNodesLoaded);
 
27575                 stack = h.stack.map(function(d) {
 
27576                     var entities = {}, entity;
 
27579                         d.modified.forEach(function(key) {
 
27580                             entity = allEntities[key];
 
27581                             entities[entity.id] = entity;
 
27586                         d.deleted.forEach(function(id) {
 
27587                             entities[id] = undefined;
 
27592                         graph: iD.Graph(stack[0].graph).load(entities),
 
27593                         annotation: d.annotation,
 
27594                         imageryUsed: d.imageryUsed
 
27598             } else { // original version
 
27599                 stack = h.stack.map(function(d) {
 
27602                     for (var i in d.entities) {
 
27603                         var entity = d.entities[i];
 
27604                         entities[i] = entity === 'undefined' ? undefined : iD.Entity(entity);
 
27607                     d.graph = iD.Graph(stack[0].graph).load(entities);
 
27612             if (loadComplete) {
 
27620             if (lock.locked()) context.storage(getKey('saved_history'), history.toJSON() || null);
 
27624         clearSaved: function() {
 
27625             context.debouncedSave.cancel();
 
27626             if (lock.locked()) context.storage(getKey('saved_history'), null);
 
27631             return lock.lock();
 
27634         unlock: function() {
 
27638         // is iD not open in another window and it detects that
 
27639         // there's a history stored in localStorage that's recoverable?
 
27640         restorableChanges: function() {
 
27641             return lock.locked() && !!context.storage(getKey('saved_history'));
 
27644         // load history from a version stored in localStorage
 
27645         restore: function() {
 
27646             if (!lock.locked()) return;
 
27648             var json = context.storage(getKey('saved_history'));
 
27649             if (json) history.fromJSON(json, true);
 
27658     return d3.rebind(history, dispatch, 'on');
 
27660 iD.Node = iD.Entity.node = function iD_Node() {
 
27661     if (!(this instanceof iD_Node)) {
 
27662         return (new iD_Node()).initialize(arguments);
 
27663     } else if (arguments.length) {
 
27664         this.initialize(arguments);
 
27668 iD.Node.prototype = Object.create(iD.Entity.prototype);
 
27670 _.extend(iD.Node.prototype, {
 
27673     extent: function() {
 
27674         return new iD.geo.Extent(this.loc);
 
27677     geometry: function(graph) {
 
27678         return graph.transient(this, 'geometry', function() {
 
27679             return graph.isPoi(this) ? 'point' : 'vertex';
 
27683     move: function(loc) {
 
27684         return this.update({loc: loc});
 
27687     isIntersection: function(resolver) {
 
27688         return resolver.transient(this, 'isIntersection', function() {
 
27689             return resolver.parentWays(this).filter(function(parent) {
 
27690                 return (parent.tags.highway ||
 
27691                     parent.tags.waterway ||
 
27692                     parent.tags.railway ||
 
27693                     parent.tags.aeroway) &&
 
27694                     parent.geometry(resolver) === 'line';
 
27699     isHighwayIntersection: function(resolver) {
 
27700         return resolver.transient(this, 'isHighwayIntersection', function() {
 
27701             return resolver.parentWays(this).filter(function(parent) {
 
27702                 return parent.tags.highway && parent.geometry(resolver) === 'line';
 
27707     asJXON: function(changeset_id) {
 
27710                 '@id': this.osmId(),
 
27711                 '@lon': this.loc[0],
 
27712                 '@lat': this.loc[1],
 
27713                 '@version': (this.version || 0),
 
27714                 tag: _.map(this.tags, function(v, k) {
 
27715                     return { keyAttributes: { k: k, v: v } };
 
27719         if (changeset_id) r.node['@changeset'] = changeset_id;
 
27723     asGeoJSON: function() {
 
27726             coordinates: this.loc
 
27730 iD.Relation = iD.Entity.relation = function iD_Relation() {
 
27731     if (!(this instanceof iD_Relation)) {
 
27732         return (new iD_Relation()).initialize(arguments);
 
27733     } else if (arguments.length) {
 
27734         this.initialize(arguments);
 
27738 iD.Relation.prototype = Object.create(iD.Entity.prototype);
 
27740 iD.Relation.creationOrder = function(a, b) {
 
27741     var aId = parseInt(iD.Entity.id.toOSM(a.id), 10);
 
27742     var bId = parseInt(iD.Entity.id.toOSM(b.id), 10);
 
27744     if (aId < 0 || bId < 0) return aId - bId;
 
27748 _.extend(iD.Relation.prototype, {
 
27752     copy: function(resolver, copies) {
 
27753         if (copies[this.id])
 
27754             return copies[this.id];
 
27756         var copy = iD.Entity.prototype.copy.call(this, resolver, copies);
 
27758         var members = this.members.map(function(member) {
 
27759             return _.extend({}, member, {id: resolver.entity(member.id).copy(resolver, copies).id});
 
27762         copy = copy.update({members: members});
 
27763         copies[this.id] = copy;
 
27768     extent: function(resolver, memo) {
 
27769         return resolver.transient(this, 'extent', function() {
 
27770             if (memo && memo[this.id]) return iD.geo.Extent();
 
27772             memo[this.id] = true;
 
27774             var extent = iD.geo.Extent();
 
27775             for (var i = 0; i < this.members.length; i++) {
 
27776                 var member = resolver.hasEntity(this.members[i].id);
 
27778                     extent._extend(member.extent(resolver, memo));
 
27785     geometry: function(graph) {
 
27786         return graph.transient(this, 'geometry', function() {
 
27787             return this.isMultipolygon() ? 'area' : 'relation';
 
27791     isDegenerate: function() {
 
27792         return this.members.length === 0;
 
27795     // Return an array of members, each extended with an 'index' property whose value
 
27796     // is the member index.
 
27797     indexedMembers: function() {
 
27798         var result = new Array(this.members.length);
 
27799         for (var i = 0; i < this.members.length; i++) {
 
27800             result[i] = _.extend({}, this.members[i], {index: i});
 
27805     // Return the first member with the given role. A copy of the member object
 
27806     // is returned, extended with an 'index' property whose value is the member index.
 
27807     memberByRole: function(role) {
 
27808         for (var i = 0; i < this.members.length; i++) {
 
27809             if (this.members[i].role === role) {
 
27810                 return _.extend({}, this.members[i], {index: i});
 
27815     // Return the first member with the given id. A copy of the member object
 
27816     // is returned, extended with an 'index' property whose value is the member index.
 
27817     memberById: function(id) {
 
27818         for (var i = 0; i < this.members.length; i++) {
 
27819             if (this.members[i].id === id) {
 
27820                 return _.extend({}, this.members[i], {index: i});
 
27825     // Return the first member with the given id and role. A copy of the member object
 
27826     // is returned, extended with an 'index' property whose value is the member index.
 
27827     memberByIdAndRole: function(id, role) {
 
27828         for (var i = 0; i < this.members.length; i++) {
 
27829             if (this.members[i].id === id && this.members[i].role === role) {
 
27830                 return _.extend({}, this.members[i], {index: i});
 
27835     addMember: function(member, index) {
 
27836         var members = this.members.slice();
 
27837         members.splice(index === undefined ? members.length : index, 0, member);
 
27838         return this.update({members: members});
 
27841     updateMember: function(member, index) {
 
27842         var members = this.members.slice();
 
27843         members.splice(index, 1, _.extend({}, members[index], member));
 
27844         return this.update({members: members});
 
27847     removeMember: function(index) {
 
27848         var members = this.members.slice();
 
27849         members.splice(index, 1);
 
27850         return this.update({members: members});
 
27853     removeMembersWithID: function(id) {
 
27854         var members = _.reject(this.members, function(m) { return m.id === id; });
 
27855         return this.update({members: members});
 
27858     // Wherever a member appears with id `needle.id`, replace it with a member
 
27859     // with id `replacement.id`, type `replacement.type`, and the original role,
 
27860     // unless a member already exists with that id and role. Return an updated
 
27862     replaceMember: function(needle, replacement) {
 
27863         if (!this.memberById(needle.id))
 
27868         for (var i = 0; i < this.members.length; i++) {
 
27869             var member = this.members[i];
 
27870             if (member.id !== needle.id) {
 
27871                 members.push(member);
 
27872             } else if (!this.memberByIdAndRole(replacement.id, member.role)) {
 
27873                 members.push({id: replacement.id, type: replacement.type, role: member.role});
 
27877         return this.update({members: members});
 
27880     asJXON: function(changeset_id) {
 
27883                 '@id': this.osmId(),
 
27884                 '@version': this.version || 0,
 
27885                 member: _.map(this.members, function(member) {
 
27886                     return { keyAttributes: { type: member.type, role: member.role, ref: iD.Entity.id.toOSM(member.id) } };
 
27888                 tag: _.map(this.tags, function(v, k) {
 
27889                     return { keyAttributes: { k: k, v: v } };
 
27893         if (changeset_id) r.relation['@changeset'] = changeset_id;
 
27897     asGeoJSON: function(resolver) {
 
27898         return resolver.transient(this, 'GeoJSON', function () {
 
27899             if (this.isMultipolygon()) {
 
27901                     type: 'MultiPolygon',
 
27902                     coordinates: this.multipolygon(resolver)
 
27906                     type: 'FeatureCollection',
 
27907                     properties: this.tags,
 
27908                     features: this.members.map(function (member) {
 
27909                         return _.extend({role: member.role}, resolver.entity(member.id).asGeoJSON(resolver));
 
27916     area: function(resolver) {
 
27917         return resolver.transient(this, 'area', function() {
 
27918             return d3.geo.area(this.asGeoJSON(resolver));
 
27922     isMultipolygon: function() {
 
27923         return this.tags.type === 'multipolygon';
 
27926     isComplete: function(resolver) {
 
27927         for (var i = 0; i < this.members.length; i++) {
 
27928             if (!resolver.hasEntity(this.members[i].id)) {
 
27935     isRestriction: function() {
 
27936         return !!(this.tags.type && this.tags.type.match(/^restriction:?/));
 
27939     // Returns an array [A0, ... An], each Ai being an array of node arrays [Nds0, ... Ndsm],
 
27940     // where Nds0 is an outer ring and subsequent Ndsi's (if any i > 0) being inner rings.
 
27942     // This corresponds to the structure needed for rendering a multipolygon path using a
 
27943     // `evenodd` fill rule, as well as the structure of a GeoJSON MultiPolygon geometry.
 
27945     // In the case of invalid geometries, this function will still return a result which
 
27946     // includes the nodes of all way members, but some Nds may be unclosed and some inner
 
27947     // rings not matched with the intended outer ring.
 
27949     multipolygon: function(resolver) {
 
27950         var outers = this.members.filter(function(m) { return 'outer' === (m.role || 'outer'); }),
 
27951             inners = this.members.filter(function(m) { return 'inner' === m.role; });
 
27953         outers = iD.geo.joinWays(outers, resolver);
 
27954         inners = iD.geo.joinWays(inners, resolver);
 
27956         outers = outers.map(function(outer) { return _.pluck(outer.nodes, 'loc'); });
 
27957         inners = inners.map(function(inner) { return _.pluck(inner.nodes, 'loc'); });
 
27959         var result = outers.map(function(o) {
 
27960             // Heuristic for detecting counterclockwise winding order. Assumes
 
27961             // that OpenStreetMap polygons are not hemisphere-spanning.
 
27962             return [d3.geo.area({type: 'Polygon', coordinates: [o]}) > 2 * Math.PI ? o.reverse() : o];
 
27965         function findOuter(inner) {
 
27968             for (o = 0; o < outers.length; o++) {
 
27970                 if (iD.geo.polygonContainsPolygon(outer, inner))
 
27974             for (o = 0; o < outers.length; o++) {
 
27976                 if (iD.geo.polygonIntersectsPolygon(outer, inner))
 
27981         for (var i = 0; i < inners.length; i++) {
 
27982             var inner = inners[i];
 
27984             if (d3.geo.area({type: 'Polygon', coordinates: [inner]}) < 2 * Math.PI) {
 
27985                 inner = inner.reverse();
 
27988             var o = findOuter(inners[i]);
 
27989             if (o !== undefined)
 
27990                 result[o].push(inners[i]);
 
27992                 result.push([inners[i]]); // Invalid geometry
 
28000         'chair_lift': true,
 
28001         'mixed_lift': true,
 
28006         'magic_carpet': true,
 
28011         'motorway_link': true
 
28017         'piste:halfpipe': true
 
28041 iD.interestingTag = function (key) {
 
28042     return key !== 'attribution' &&
 
28043         key !== 'created_by' &&
 
28044         key !== 'source' &&
 
28046         key.indexOf('tiger:') !== 0;
 
28049 iD.Tree = function(head) {
 
28050     var rtree = rbush(),
 
28053     function entityRectangle(entity) {
 
28054         var rect = entity.extent(head).rectangle();
 
28055         rect.id = entity.id;
 
28056         rectangles[entity.id] = rect;
 
28060     function updateParents(entity, insertions, memo) {
 
28061         head.parentWays(entity).forEach(function(way) {
 
28062             if (rectangles[way.id]) {
 
28063                 rtree.remove(rectangles[way.id]);
 
28064                 insertions[way.id] = way;
 
28066             updateParents(way, insertions, memo);
 
28069         head.parentRelations(entity).forEach(function(relation) {
 
28070             if (memo[entity.id]) return;
 
28071             memo[entity.id] = true;
 
28072             if (rectangles[relation.id]) {
 
28073                 rtree.remove(rectangles[relation.id]);
 
28074                 insertions[relation.id] = relation;
 
28076             updateParents(relation, insertions, memo);
 
28082     tree.rebase = function(entities, force) {
 
28083         var insertions = {};
 
28085         for (var i = 0; i < entities.length; i++) {
 
28086             var entity = entities[i];
 
28088             if (!entity.visible)
 
28091             if (head.entities.hasOwnProperty(entity.id) || rectangles[entity.id]) {
 
28094                 } else if (rectangles[entity.id]) {
 
28095                     rtree.remove(rectangles[entity.id]);
 
28099             insertions[entity.id] = entity;
 
28100             updateParents(entity, insertions, {});
 
28103         rtree.load(_.map(insertions, entityRectangle));
 
28108     tree.intersects = function(extent, graph) {
 
28109         if (graph !== head) {
 
28110             var diff = iD.Difference(head, graph),
 
28115             diff.deleted().forEach(function(entity) {
 
28116                 rtree.remove(rectangles[entity.id]);
 
28117                 delete rectangles[entity.id];
 
28120             diff.modified().forEach(function(entity) {
 
28121                 rtree.remove(rectangles[entity.id]);
 
28122                 insertions[entity.id] = entity;
 
28123                 updateParents(entity, insertions, {});
 
28126             diff.created().forEach(function(entity) {
 
28127                 insertions[entity.id] = entity;
 
28130             rtree.load(_.map(insertions, entityRectangle));
 
28133         return rtree.search(extent.rectangle()).map(function(rect) {
 
28134             return head.entity(rect.id);
 
28140 iD.Way = iD.Entity.way = function iD_Way() {
 
28141     if (!(this instanceof iD_Way)) {
 
28142         return (new iD_Way()).initialize(arguments);
 
28143     } else if (arguments.length) {
 
28144         this.initialize(arguments);
 
28148 iD.Way.prototype = Object.create(iD.Entity.prototype);
 
28150 _.extend(iD.Way.prototype, {
 
28154     copy: function(resolver, copies) {
 
28155         if (copies[this.id])
 
28156             return copies[this.id];
 
28158         var copy = iD.Entity.prototype.copy.call(this, resolver, copies);
 
28160         var nodes = this.nodes.map(function(id) {
 
28161             return resolver.entity(id).copy(resolver, copies).id;
 
28164         copy = copy.update({nodes: nodes});
 
28165         copies[this.id] = copy;
 
28170     extent: function(resolver) {
 
28171         return resolver.transient(this, 'extent', function() {
 
28172             var extent = iD.geo.Extent();
 
28173             for (var i = 0; i < this.nodes.length; i++) {
 
28174                 var node = resolver.hasEntity(this.nodes[i]);
 
28176                     extent._extend(node.extent());
 
28183     first: function() {
 
28184         return this.nodes[0];
 
28188         return this.nodes[this.nodes.length - 1];
 
28191     contains: function(node) {
 
28192         return this.nodes.indexOf(node) >= 0;
 
28195     affix: function(node) {
 
28196         if (this.nodes[0] === node) return 'prefix';
 
28197         if (this.nodes[this.nodes.length - 1] === node) return 'suffix';
 
28200     layer: function() {
 
28201         // explicit layer tag, clamp between -10, 10..
 
28202         if (this.tags.layer !== undefined) {
 
28203             return Math.max(-10, Math.min(+(this.tags.layer), 10));
 
28206         // implied layer tag..
 
28207         if (this.tags.location === 'overground') return 1;
 
28208         if (this.tags.location === 'underground') return -1;
 
28209         if (this.tags.location === 'underwater') return -10;
 
28211         if (this.tags.power === 'line') return 10;
 
28212         if (this.tags.power === 'minor_line') return 10;
 
28213         if (this.tags.aerialway) return 10;
 
28214         if (this.tags.bridge) return 1;
 
28215         if (this.tags.cutting) return -1;
 
28216         if (this.tags.tunnel) return -1;
 
28217         if (this.tags.waterway) return -1;
 
28218         if (this.tags.man_made === 'pipeline') return -10;
 
28219         if (this.tags.boundary) return -10;
 
28223     isOneWay: function() {
 
28224         // explicit oneway tag..
 
28225         if (['yes', '1', '-1'].indexOf(this.tags.oneway) !== -1) { return true; }
 
28226         if (['no', '0'].indexOf(this.tags.oneway) !== -1) { return false; }
 
28228         // implied oneway tag..
 
28229         for (var key in this.tags) {
 
28230             if (key in iD.oneWayTags && (this.tags[key] in iD.oneWayTags[key]))
 
28236     isClosed: function() {
 
28237         return this.nodes.length > 0 && this.first() === this.last();
 
28240     isConvex: function(resolver) {
 
28241         if (!this.isClosed() || this.isDegenerate()) return null;
 
28243         var nodes = _.uniq(resolver.childNodes(this)),
 
28244             coords = _.pluck(nodes, 'loc'),
 
28245             curr = 0, prev = 0;
 
28247         for (var i = 0; i < coords.length; i++) {
 
28248             var o = coords[(i+1) % coords.length],
 
28250                 b = coords[(i+2) % coords.length],
 
28251                 res = iD.geo.cross(o, a, b);
 
28253             curr = (res > 0) ? 1 : (res < 0) ? -1 : 0;
 
28256             } else if (prev && curr !== prev) {
 
28264     isArea: function() {
 
28265         if (this.tags.area === 'yes')
 
28267         if (!this.isClosed() || this.tags.area === 'no')
 
28269         for (var key in this.tags)
 
28270             if (key in iD.areaKeys && !(this.tags[key] in iD.areaKeys[key]))
 
28275     isDegenerate: function() {
 
28276         return _.uniq(this.nodes).length < (this.isArea() ? 3 : 2);
 
28279     areAdjacent: function(n1, n2) {
 
28280         for (var i = 0; i < this.nodes.length; i++) {
 
28281             if (this.nodes[i] === n1) {
 
28282                 if (this.nodes[i - 1] === n2) return true;
 
28283                 if (this.nodes[i + 1] === n2) return true;
 
28289     geometry: function(graph) {
 
28290         return graph.transient(this, 'geometry', function() {
 
28291             return this.isArea() ? 'area' : 'line';
 
28295     addNode: function(id, index) {
 
28296         var nodes = this.nodes.slice();
 
28297         nodes.splice(index === undefined ? nodes.length : index, 0, id);
 
28298         return this.update({nodes: nodes});
 
28301     updateNode: function(id, index) {
 
28302         var nodes = this.nodes.slice();
 
28303         nodes.splice(index, 1, id);
 
28304         return this.update({nodes: nodes});
 
28307     replaceNode: function(needle, replacement) {
 
28308         if (this.nodes.indexOf(needle) < 0)
 
28311         var nodes = this.nodes.slice();
 
28312         for (var i = 0; i < nodes.length; i++) {
 
28313             if (nodes[i] === needle) {
 
28314                 nodes[i] = replacement;
 
28317         return this.update({nodes: nodes});
 
28320     removeNode: function(id) {
 
28323         for (var i = 0; i < this.nodes.length; i++) {
 
28324             var node = this.nodes[i];
 
28325             if (node !== id && nodes[nodes.length - 1] !== node) {
 
28330         // Preserve circularity
 
28331         if (this.nodes.length > 1 && this.first() === id && this.last() === id && nodes[nodes.length - 1] !== nodes[0]) {
 
28332             nodes.push(nodes[0]);
 
28335         return this.update({nodes: nodes});
 
28338     asJXON: function(changeset_id) {
 
28341                 '@id': this.osmId(),
 
28342                 '@version': this.version || 0,
 
28343                 nd: _.map(this.nodes, function(id) {
 
28344                     return { keyAttributes: { ref: iD.Entity.id.toOSM(id) } };
 
28346                 tag: _.map(this.tags, function(v, k) {
 
28347                     return { keyAttributes: { k: k, v: v } };
 
28351         if (changeset_id) r.way['@changeset'] = changeset_id;
 
28355     asGeoJSON: function(resolver) {
 
28356         return resolver.transient(this, 'GeoJSON', function() {
 
28357             var coordinates = _.pluck(resolver.childNodes(this), 'loc');
 
28358             if (this.isArea() && this.isClosed()) {
 
28361                     coordinates: [coordinates]
 
28365                     type: 'LineString',
 
28366                     coordinates: coordinates
 
28372     area: function(resolver) {
 
28373         return resolver.transient(this, 'area', function() {
 
28374             var nodes = resolver.childNodes(this);
 
28378                 coordinates: [_.pluck(nodes, 'loc')]
 
28381             if (!this.isClosed() && nodes.length) {
 
28382                 json.coordinates[0].push(nodes[0].loc);
 
28385             var area = d3.geo.area(json);
 
28387             // Heuristic for detecting counterclockwise winding order. Assumes
 
28388             // that OpenStreetMap polygons are not hemisphere-spanning.
 
28389             if (area > 2 * Math.PI) {
 
28390                 json.coordinates[0] = json.coordinates[0].reverse();
 
28391                 area = d3.geo.area(json);
 
28394             return isNaN(area) ? 0 : area;
 
28398 iD.Background = function(context) {
 
28399     var dispatch = d3.dispatch('change'),
 
28400         baseLayer = iD.TileLayer().projection(context.projection),
 
28401         overlayLayers = [];
 
28403     var backgroundSources;
 
28405     function findSource(id) {
 
28406         return _.find(backgroundSources, function(d) {
 
28407             return d.id && d.id === id;
 
28411     function updateImagery() {
 
28412         var b = background.baseLayerSource(),
 
28413             o = overlayLayers.map(function (d) { return d.source().id; }).join(','),
 
28414             q = iD.util.stringQs(location.hash.substring(1));
 
28417         if (id === 'custom') {
 
28418             id = 'custom:' + b.template;
 
28424             delete q.background;
 
28433         location.replace('#' + iD.util.qsString(q, true));
 
28435         var imageryUsed = [b.imageryUsed()];
 
28437         overlayLayers.forEach(function (d) {
 
28438             var source = d.source();
 
28439             if (!source.isLocatorOverlay()) {
 
28440                 imageryUsed.push(source.imageryUsed());
 
28444         var gpx = context.layers().layer('gpx');
 
28445         if (gpx && gpx.enabled() && gpx.hasGpx()) {
 
28446             imageryUsed.push('Local GPX');
 
28449         context.history().imageryUsed(imageryUsed);
 
28452     function background(selection) {
 
28453         var base = selection.selectAll('.layer-background')
 
28457             .insert('div', '.layer-data')
 
28458             .attr('class', 'layer layer-background');
 
28460         base.call(baseLayer);
 
28462         var overlays = selection.selectAll('.layer-overlay')
 
28463             .data(overlayLayers, function(d) { return d.source().name(); });
 
28466             .insert('div', '.layer-data')
 
28467             .attr('class', 'layer layer-overlay');
 
28469         overlays.each(function(layer) {
 
28470             d3.select(this).call(layer);
 
28477     background.sources = function(extent) {
 
28478         return backgroundSources.filter(function(source) {
 
28479             return source.intersects(extent);
 
28483     background.dimensions = function(_) {
 
28484         baseLayer.dimensions(_);
 
28486         overlayLayers.forEach(function(layer) {
 
28487             layer.dimensions(_);
 
28491     background.baseLayerSource = function(d) {
 
28492         if (!arguments.length) return baseLayer.source();
 
28494         baseLayer.source(d);
 
28501     background.bing = function() {
 
28502         background.baseLayerSource(findSource('Bing'));
 
28505     background.showsLayer = function(d) {
 
28506         return d === baseLayer.source() ||
 
28507             (d.id === 'custom' && baseLayer.source().id === 'custom') ||
 
28508             overlayLayers.some(function(l) { return l.source() === d; });
 
28511     background.overlayLayerSources = function() {
 
28512         return overlayLayers.map(function (l) { return l.source(); });
 
28515     background.toggleOverlayLayer = function(d) {
 
28518         for (var i = 0; i < overlayLayers.length; i++) {
 
28519             layer = overlayLayers[i];
 
28520             if (layer.source() === d) {
 
28521                 overlayLayers.splice(i, 1);
 
28528         layer = iD.TileLayer()
 
28530             .projection(context.projection)
 
28531             .dimensions(baseLayer.dimensions());
 
28533         overlayLayers.push(layer);
 
28538     background.nudge = function(d, zoom) {
 
28539         baseLayer.source().nudge(d, zoom);
 
28544     background.offset = function(d) {
 
28545         if (!arguments.length) return baseLayer.source().offset();
 
28546         baseLayer.source().offset(d);
 
28551     background.load = function(imagery) {
 
28552         function parseMap(qmap) {
 
28553             if (!qmap) return false;
 
28554             var args = qmap.split('/').map(Number);
 
28555             if (args.length < 3 || args.some(isNaN)) return false;
 
28556             return iD.geo.Extent([args[1], args[2]]);
 
28559         var q = iD.util.stringQs(location.hash.substring(1)),
 
28560             chosen = q.background || q.layer,
 
28561             extent = parseMap(q.map),
 
28564         backgroundSources = imagery.map(function(source) {
 
28565             if (source.type === 'bing') {
 
28566                 return iD.BackgroundSource.Bing(source, dispatch);
 
28568                 return iD.BackgroundSource(source);
 
28572         backgroundSources.unshift(iD.BackgroundSource.None());
 
28574         if (!chosen && extent) {
 
28575             best = _.find(this.sources(extent), function(s) { return s.best(); });
 
28578         if (chosen && chosen.indexOf('custom:') === 0) {
 
28579             background.baseLayerSource(iD.BackgroundSource.Custom(chosen.replace(/^custom:/, '')));
 
28581             background.baseLayerSource(findSource(chosen) || best || findSource('Bing') || backgroundSources[1] || backgroundSources[0]);
 
28584         var locator = _.find(backgroundSources, function(d) {
 
28585             return d.overlay && d.default;
 
28589             background.toggleOverlayLayer(locator);
 
28592         var overlays = (q.overlays || '').split(',');
 
28593         overlays.forEach(function(overlay) {
 
28594             overlay = findSource(overlay);
 
28595             if (overlay) background.toggleOverlayLayer(overlay);
 
28599             var gpx = context.layers().layer('gpx');
 
28600             if (gpx) { gpx.url(q.gpx); }
 
28604     return d3.rebind(background, dispatch, 'on');
 
28606 iD.BackgroundSource = function(data) {
 
28607     var source = _.clone(data),
 
28609         name = source.name,
 
28610         best = !!source.best;
 
28612     source.scaleExtent = data.scaleExtent || [0, 20];
 
28613     source.overzoom = data.overzoom !== false;
 
28615     source.offset = function(_) {
 
28616         if (!arguments.length) return offset;
 
28621     source.nudge = function(_, zoomlevel) {
 
28622         offset[0] += _[0] / Math.pow(2, zoomlevel);
 
28623         offset[1] += _[1] / Math.pow(2, zoomlevel);
 
28627     source.name = function() {
 
28631     source.best = function() {
 
28635     source.imageryUsed = function() {
 
28636         return source.id || name;
 
28639     source.url = function(coord) {
 
28640         return data.template
 
28641             .replace('{x}', coord[0])
 
28642             .replace('{y}', coord[1])
 
28643             // TMS-flipped y coordinate
 
28644             .replace(/\{[t-]y\}/, Math.pow(2, coord[2]) - coord[1] - 1)
 
28645             .replace(/\{z(oom)?\}/, coord[2])
 
28646             .replace(/\{switch:([^}]+)\}/, function(s, r) {
 
28647                 var subdomains = r.split(',');
 
28648                 return subdomains[(coord[0] + coord[1]) % subdomains.length];
 
28650             .replace('{u}', function() {
 
28652                 for (var zoom = coord[2]; zoom > 0; zoom--) {
 
28654                     var mask = 1 << (zoom - 1);
 
28655                     if ((coord[0] & mask) !== 0) b++;
 
28656                     if ((coord[1] & mask) !== 0) b += 2;
 
28663     source.intersects = function(extent) {
 
28664         extent = extent.polygon();
 
28665         return !data.polygon || data.polygon.some(function(polygon) {
 
28666             return iD.geo.polygonIntersectsPolygon(polygon, extent, true);
 
28670     source.validZoom = function(z) {
 
28671         return source.scaleExtent[0] <= z &&
 
28672             (source.overzoom || source.scaleExtent[1] > z);
 
28675     source.isLocatorOverlay = function() {
 
28676         return name === 'Locator Overlay';
 
28679     source.copyrightNotices = function() {};
 
28684 iD.BackgroundSource.Bing = function(data, dispatch) {
 
28685     // http://msdn.microsoft.com/en-us/library/ff701716.aspx
 
28686     // http://msdn.microsoft.com/en-us/library/ff701701.aspx
 
28688     data.template = 'https://ecn.t{switch:0,1,2,3}.tiles.virtualearth.net/tiles/a{u}.jpeg?g=587&mkt=en-gb&n=z';
 
28690     var bing = iD.BackgroundSource(data),
 
28691         key = 'Arzdiw4nlOJzRwOz__qailc8NiR31Tt51dN2D7cm57NrnceZnCpgOkmJhNpGoppU', // Same as P2 and JOSM
 
28692         url = 'https://dev.virtualearth.net/REST/v1/Imagery/Metadata/Aerial?include=ImageryProviders&key=' +
 
28693             key + '&jsonp={callback}',
 
28696     d3.jsonp(url, function(json) {
 
28697         providers = json.resourceSets[0].resources[0].imageryProviders.map(function(provider) {
 
28699                 attribution: provider.attribution,
 
28700                 areas: provider.coverageAreas.map(function(area) {
 
28702                         zoom: [area.zoomMin, area.zoomMax],
 
28703                         extent: iD.geo.Extent([area.bbox[1], area.bbox[0]], [area.bbox[3], area.bbox[2]])
 
28711     bing.copyrightNotices = function(zoom, extent) {
 
28712         zoom = Math.min(zoom, 21);
 
28713         return providers.filter(function(provider) {
 
28714             return _.any(provider.areas, function(area) {
 
28715                 return extent.intersects(area.extent) &&
 
28716                     area.zoom[0] <= zoom &&
 
28717                     area.zoom[1] >= zoom;
 
28719         }).map(function(provider) {
 
28720             return provider.attribution;
 
28724     bing.logo = 'bing_maps.png';
 
28725     bing.terms_url = 'https://blog.openstreetmap.org/2010/11/30/microsoft-imagery-details';
 
28730 iD.BackgroundSource.None = function() {
 
28731     var source = iD.BackgroundSource({id: 'none', template: ''});
 
28733     source.name = function() {
 
28734         return t('background.none');
 
28737     source.imageryUsed = function() {
 
28744 iD.BackgroundSource.Custom = function(template) {
 
28745     var source = iD.BackgroundSource({id: 'custom', template: template});
 
28747     source.name = function() {
 
28748         return t('background.custom');
 
28751     source.imageryUsed = function() {
 
28752         return 'Custom (' + template + ')';
 
28757 iD.Features = function(context) {
 
28758     var major_roads = {
 
28760         'motorway_link': true,
 
28762         'trunk_link': true,
 
28764         'primary_link': true,
 
28766         'secondary_link': true,
 
28768         'tertiary_link': true,
 
28769         'residential': true
 
28772     var minor_roads = {
 
28774         'living_street': true,
 
28776         'unclassified': true,
 
28786         'pedestrian': true,
 
28790     var past_futures = {
 
28792         'construction': true,
 
28794         'dismantled': true,
 
28797         'demolished': true,
 
28798         'obliterated': true
 
28801     var dispatch = d3.dispatch('change', 'redraw'),
 
28809     function update() {
 
28810         _hidden = features.hidden();
 
28815     function defineFeature(k, filter, max) {
 
28819             enabled: true,   // whether the user wants it enabled..
 
28821             currentMax: (max || Infinity),
 
28822             defaultMax: (max || Infinity),
 
28823             enable: function() { this.enabled = true; this.currentMax = this.defaultMax; },
 
28824             disable: function() { this.enabled = false; this.currentMax = 0; },
 
28825             hidden: function() { return !context.editable() || this.count > this.currentMax * _cullFactor; },
 
28826             autoHidden: function() { return this.hidden() && this.currentMax > 0; }
 
28831     defineFeature('points', function isPoint(entity, resolver, geometry) {
 
28832         return geometry === 'point';
 
28835     defineFeature('major_roads', function isMajorRoad(entity) {
 
28836         return major_roads[entity.tags.highway];
 
28839     defineFeature('minor_roads', function isMinorRoad(entity) {
 
28840         return minor_roads[entity.tags.highway];
 
28843     defineFeature('paths', function isPath(entity) {
 
28844         return paths[entity.tags.highway];
 
28847     defineFeature('buildings', function isBuilding(entity) {
 
28849             !!entity.tags['building:part'] ||
 
28850             (!!entity.tags.building && entity.tags.building !== 'no') ||
 
28851             entity.tags.amenity === 'shelter' ||
 
28852             entity.tags.parking === 'multi-storey' ||
 
28853             entity.tags.parking === 'sheds' ||
 
28854             entity.tags.parking === 'carports' ||
 
28855             entity.tags.parking === 'garage_boxes'
 
28859     defineFeature('landuse', function isLanduse(entity, resolver, geometry) {
 
28860         return geometry === 'area' &&
 
28861             !_features.buildings.filter(entity) &&
 
28862             !_features.water.filter(entity);
 
28865     defineFeature('boundaries', function isBoundary(entity) {
 
28866         return !!entity.tags.boundary;
 
28869     defineFeature('water', function isWater(entity) {
 
28871             !!entity.tags.waterway ||
 
28872             entity.tags.natural === 'water' ||
 
28873             entity.tags.natural === 'coastline' ||
 
28874             entity.tags.natural === 'bay' ||
 
28875             entity.tags.landuse === 'pond' ||
 
28876             entity.tags.landuse === 'basin' ||
 
28877             entity.tags.landuse === 'reservoir' ||
 
28878             entity.tags.landuse === 'salt_pond'
 
28882     defineFeature('rail', function isRail(entity) {
 
28884             !!entity.tags.railway ||
 
28885             entity.tags.landuse === 'railway'
 
28887             major_roads[entity.tags.highway] ||
 
28888             minor_roads[entity.tags.highway] ||
 
28889             paths[entity.tags.highway]
 
28893     defineFeature('power', function isPower(entity) {
 
28894         return !!entity.tags.power;
 
28897     // contains a past/future tag, but not in active use as a road/path/cycleway/etc..
 
28898     defineFeature('past_future', function isPastFuture(entity) {
 
28900             major_roads[entity.tags.highway] ||
 
28901             minor_roads[entity.tags.highway] ||
 
28902             paths[entity.tags.highway]
 
28903         ) { return false; }
 
28905         var strings = Object.keys(entity.tags);
 
28907         for (var i = 0; i < strings.length; i++) {
 
28908             var s = strings[i];
 
28909             if (past_futures[s] || past_futures[entity.tags[s]]) { return true; }
 
28914     // Lines or areas that don't match another feature filter.
 
28915     // IMPORTANT: The 'others' feature must be the last one defined,
 
28916     //   so that code in getMatches can skip this test if `hasMatch = true`
 
28917     defineFeature('others', function isOther(entity, resolver, geometry) {
 
28918         return (geometry === 'line' || geometry === 'area');
 
28922     function features() {}
 
28924     features.features = function() {
 
28928     features.keys = function() {
 
28932     features.enabled = function(k) {
 
28933         if (!arguments.length) {
 
28934             return _.filter(_keys, function(k) { return _features[k].enabled; });
 
28936         return _features[k] && _features[k].enabled;
 
28939     features.disabled = function(k) {
 
28940         if (!arguments.length) {
 
28941             return _.reject(_keys, function(k) { return _features[k].enabled; });
 
28943         return _features[k] && !_features[k].enabled;
 
28946     features.hidden = function(k) {
 
28947         if (!arguments.length) {
 
28948             return _.filter(_keys, function(k) { return _features[k].hidden(); });
 
28950         return _features[k] && _features[k].hidden();
 
28953     features.autoHidden = function(k) {
 
28954         if (!arguments.length) {
 
28955             return _.filter(_keys, function(k) { return _features[k].autoHidden(); });
 
28957         return _features[k] && _features[k].autoHidden();
 
28960     features.enable = function(k) {
 
28961         if (_features[k] && !_features[k].enabled) {
 
28962             _features[k].enable();
 
28967     features.disable = function(k) {
 
28968         if (_features[k] && _features[k].enabled) {
 
28969             _features[k].disable();
 
28974     features.toggle = function(k) {
 
28975         if (_features[k]) {
 
28976             (function(f) { return f.enabled ? f.disable() : f.enable(); }(_features[k]));
 
28981     features.resetStats = function() {
 
28982         _.each(_features, function(f) { f.count = 0; });
 
28986     features.gatherStats = function(d, resolver, dimensions) {
 
28987         var needsRedraw = false,
 
28988             type = _.groupBy(d, function(ent) { return ent.type; }),
 
28989             entities = [].concat(type.relation || [], type.way || [], type.node || []),
 
28990             currHidden, geometry, matches;
 
28992         _.each(_features, function(f) { f.count = 0; });
 
28994         // adjust the threshold for point/building culling based on viewport size..
 
28995         // a _cullFactor of 1 corresponds to a 1000x1000px viewport..
 
28996         _cullFactor = dimensions[0] * dimensions[1] / 1000000;
 
28998         for (var i = 0; i < entities.length; i++) {
 
28999             geometry = entities[i].geometry(resolver);
 
29000             if (!(geometry === 'vertex' || geometry === 'relation')) {
 
29001                 matches = Object.keys(features.getMatches(entities[i], resolver, geometry));
 
29002                 for (var j = 0; j < matches.length; j++) {
 
29003                     _features[matches[j]].count++;
 
29008         currHidden = features.hidden();
 
29009         if (currHidden !== _hidden) {
 
29010             _hidden = currHidden;
 
29011             needsRedraw = true;
 
29015         return needsRedraw;
 
29018     features.stats = function() {
 
29019         _.each(_keys, function(k) { _stats[k] = _features[k].count; });
 
29023     features.clear = function(d) {
 
29024         for (var i = 0; i < d.length; i++) {
 
29025             features.clearEntity(d[i]);
 
29029     features.clearEntity = function(entity) {
 
29030         delete _cache[iD.Entity.key(entity)];
 
29033     features.reset = function() {
 
29037     features.getMatches = function(entity, resolver, geometry) {
 
29038         if (geometry === 'vertex' || geometry === 'relation') return {};
 
29040         var ent = iD.Entity.key(entity);
 
29041         if (!_cache[ent]) {
 
29045         if (!_cache[ent].matches) {
 
29049             for (var i = 0; i < _keys.length; i++) {
 
29050                 if (_keys[i] === 'others') {
 
29051                     if (hasMatch) continue;
 
29053                     // Multipolygon members:
 
29055                     //   1. is a way that hasn't matched other "interesting" feature rules,
 
29056                     //   2. and it belongs to a single parent multipolygon relation
 
29057                     // ...then match whatever feature rules the parent multipolygon has matched.
 
29058                     // see #2548, #2887
 
29061                     // For this to work, getMatches must be called on relations before ways.
 
29063                     if (entity.type === 'way') {
 
29064                         var parents = features.getParents(entity, resolver, geometry);
 
29065                         if (parents.length === 1 && parents[0].isMultipolygon()) {
 
29066                             var pkey = iD.Entity.key(parents[0]);
 
29067                             if (_cache[pkey] && _cache[pkey].matches) {
 
29068                                 matches = _.clone(_cache[pkey].matches);
 
29075                 if (_features[_keys[i]].filter(entity, resolver, geometry)) {
 
29076                     matches[_keys[i]] = hasMatch = true;
 
29079             _cache[ent].matches = matches;
 
29082         return _cache[ent].matches;
 
29085     features.getParents = function(entity, resolver, geometry) {
 
29086         if (geometry === 'point') return [];
 
29088         var ent = iD.Entity.key(entity);
 
29089         if (!_cache[ent]) {
 
29093         if (!_cache[ent].parents) {
 
29095             if (geometry === 'vertex') {
 
29096                 parents = resolver.parentWays(entity);
 
29097             } else {   // 'line', 'area', 'relation'
 
29098                 parents = resolver.parentRelations(entity);
 
29100             _cache[ent].parents = parents;
 
29102         return _cache[ent].parents;
 
29105     features.isHiddenFeature = function(entity, resolver, geometry) {
 
29106         if (!_hidden.length) return false;
 
29107         if (!entity.version) return false;
 
29109         var matches = features.getMatches(entity, resolver, geometry);
 
29111         for (var i = 0; i < _hidden.length; i++) {
 
29112             if (matches[_hidden[i]]) return true;
 
29117     features.isHiddenChild = function(entity, resolver, geometry) {
 
29118         if (!_hidden.length) return false;
 
29119         if (!entity.version || geometry === 'point') return false;
 
29121         var parents = features.getParents(entity, resolver, geometry);
 
29122         if (!parents.length) return false;
 
29124         for (var i = 0; i < parents.length; i++) {
 
29125             if (!features.isHidden(parents[i], resolver, parents[i].geometry(resolver))) {
 
29132     features.hasHiddenConnections = function(entity, resolver) {
 
29133         if (!_hidden.length) return false;
 
29134         var childNodes, connections;
 
29136         if (entity.type === 'midpoint') {
 
29137             childNodes = [resolver.entity(entity.edge[0]), resolver.entity(entity.edge[1])];
 
29140             childNodes = entity.nodes ? resolver.childNodes(entity) : [];
 
29141             connections = features.getParents(entity, resolver, entity.geometry(resolver));
 
29144         // gather ways connected to child nodes..
 
29145         connections = _.reduce(childNodes, function(result, e) {
 
29146             return resolver.isShared(e) ? _.union(result, resolver.parentWays(e)) : result;
 
29149         return connections.length ? _.any(connections, function(e) {
 
29150             return features.isHidden(e, resolver, e.geometry(resolver));
 
29154     features.isHidden = function(entity, resolver, geometry) {
 
29155         if (!_hidden.length) return false;
 
29156         if (!entity.version) return false;
 
29158         var fn = (geometry === 'vertex' ? features.isHiddenChild : features.isHiddenFeature);
 
29159         return fn(entity, resolver, geometry);
 
29162     features.filter = function(d, resolver) {
 
29163         if (!_hidden.length) return d;
 
29166         for (var i = 0; i < d.length; i++) {
 
29168             if (!features.isHidden(entity, resolver, entity.geometry(resolver))) {
 
29169                 result.push(entity);
 
29175     return d3.rebind(features, dispatch, 'on');
 
29177 iD.Map = function(context) {
 
29178     var dimensions = [1, 1],
 
29179         dispatch = d3.dispatch('move', 'drawn'),
 
29180         projection = context.projection,
 
29181         zoom = d3.behavior.zoom()
 
29182             .translate(projection.translate())
 
29183             .scale(projection.scale() * 2 * Math.PI)
 
29184             .scaleExtent([1024, 256 * Math.pow(2, 24)])
 
29185             .on('zoom', zoomPan),
 
29186         dblclickEnabled = true,
 
29187         redrawEnabled = true,
 
29189         transformed = false,
 
29191         drawLayers = iD.svg.Layers(projection, context),
 
29192         drawPoints = iD.svg.Points(projection, context),
 
29193         drawVertices = iD.svg.Vertices(projection, context),
 
29194         drawLines = iD.svg.Lines(projection),
 
29195         drawAreas = iD.svg.Areas(projection),
 
29196         drawMidpoints = iD.svg.Midpoints(projection, context),
 
29197         drawLabels = iD.svg.Labels(projection, context),
 
29204     function map(selection) {
 
29206             .on('change.map', redraw);
 
29207         context.background()
 
29208             .on('change.map', redraw);
 
29210             .on('redraw.map', redraw);
 
29213             .on('dblclick.map', dblClick)
 
29216         supersurface = selection.append('div')
 
29217             .attr('id', 'supersurface')
 
29218             .call(iD.util.setTransform, 0, 0);
 
29220         // Need a wrapper div because Opera can't cope with an absolutely positioned
 
29221         // SVG element: http://bl.ocks.org/jfirebaugh/6fbfbd922552bf776c16
 
29222         wrapper = supersurface
 
29224             .attr('class', 'layer layer-data');
 
29226         map.surface = surface = wrapper
 
29228             .selectAll('.surface')
 
29229             .attr('id', 'surface');
 
29232             .on('mousedown.zoom', function() {
 
29233                 if (d3.event.button === 2) {
 
29234                     d3.event.stopPropagation();
 
29237             .on('mouseup.zoom', function() {
 
29238                 if (resetTransform()) redraw();
 
29240             .on('mousemove.map', function() {
 
29241                 mousemove = d3.event;
 
29243             .on('mouseover.vertices', function() {
 
29244                 if (map.editable() && !transformed) {
 
29245                     var hover = d3.event.target.__data__;
 
29246                     surface.call(drawVertices.drawHover, context.graph(), hover, map.extent(), map.zoom());
 
29247                     dispatch.drawn({full: false});
 
29250             .on('mouseout.vertices', function() {
 
29251                 if (map.editable() && !transformed) {
 
29252                     var hover = d3.event.relatedTarget && d3.event.relatedTarget.__data__;
 
29253                     surface.call(drawVertices.drawHover, context.graph(), hover, map.extent(), map.zoom());
 
29254                     dispatch.drawn({full: false});
 
29260             .call(context.background());
 
29263         context.on('enter.map', function() {
 
29264             if (map.editable() && !transformed) {
 
29265                 var all = context.intersects(map.extent()),
 
29266                     filter = d3.functor(true),
 
29267                     graph = context.graph();
 
29269                 all = context.features().filter(all, graph);
 
29271                     .call(drawVertices, graph, all, filter, map.extent(), map.zoom())
 
29272                     .call(drawMidpoints, graph, all, filter, map.trimmedExtent());
 
29273                 dispatch.drawn({full: false});
 
29277         map.dimensions(selection.dimensions());
 
29279         drawLabels.supersurface(supersurface);
 
29282     function pxCenter() { return [dimensions[0] / 2, dimensions[1] / 2]; }
 
29284     function drawVector(difference, extent) {
 
29285         var graph = context.graph(),
 
29286             features = context.features(),
 
29287             all = context.intersects(map.extent()),
 
29291             var complete = difference.complete(map.extent());
 
29292             data = _.compact(_.values(complete));
 
29293             filter = function(d) { return d.id in complete; };
 
29294             features.clear(data);
 
29297             // force a full redraw if gatherStats detects that a feature
 
29298             // should be auto-hidden (e.g. points or buildings)..
 
29299             if (features.gatherStats(all, graph, dimensions)) {
 
29300                 extent = undefined;
 
29304                 data = context.intersects(map.extent().intersection(extent));
 
29305                 var set = d3.set(_.pluck(data, 'id'));
 
29306                 filter = function(d) { return set.has(d.id); };
 
29310                 filter = d3.functor(true);
 
29314         data = features.filter(data, graph);
 
29317             .call(drawVertices, graph, data, filter, map.extent(), map.zoom())
 
29318             .call(drawLines, graph, data, filter)
 
29319             .call(drawAreas, graph, data, filter)
 
29320             .call(drawMidpoints, graph, data, filter, map.trimmedExtent())
 
29321             .call(drawLabels, graph, data, filter, dimensions, !difference && !extent)
 
29322             .call(drawPoints, graph, data, filter);
 
29324         dispatch.drawn({full: true});
 
29327     function editOff() {
 
29328         context.features().resetStats();
 
29329         surface.selectAll('.layer-osm *').remove();
 
29330         dispatch.drawn({full: true});
 
29333     function dblClick() {
 
29334         if (!dblclickEnabled) {
 
29335             d3.event.preventDefault();
 
29336             d3.event.stopImmediatePropagation();
 
29340     function zoomPan() {
 
29341         if (Math.log(d3.event.scale) / Math.LN2 - 8 < minzoom) {
 
29342             surface.interrupt();
 
29343             iD.ui.flash(context.container())
 
29344                 .select('.content')
 
29345                 .text(t('cannot_zoom'));
 
29346             setZoom(context.minEditableZoom(), true);
 
29348             dispatch.move(map);
 
29353             .translate(d3.event.translate)
 
29354             .scale(d3.event.scale / (2 * Math.PI));
 
29356         var scale = d3.event.scale / transformStart[0],
 
29357             tX = (d3.event.translate[0] / scale - transformStart[1][0]) * scale,
 
29358             tY = (d3.event.translate[1] / scale - transformStart[1][1]) * scale;
 
29360         transformed = true;
 
29361         iD.util.setTransform(supersurface, tX, tY, scale);
 
29364         dispatch.move(map);
 
29367     function resetTransform() {
 
29368         if (!transformed) return false;
 
29370         surface.selectAll('.radial-menu').interrupt().remove();
 
29371         iD.util.setTransform(supersurface, 0, 0);
 
29372         transformed = false;
 
29376     function redraw(difference, extent) {
 
29377         if (!surface || !redrawEnabled) return;
 
29379         clearTimeout(timeoutId);
 
29381         // If we are in the middle of a zoom/pan, we can't do differenced redraws.
 
29382         // It would result in artifacts where differenced entities are redrawn with
 
29383         // one transform and unchanged entities with another.
 
29384         if (resetTransform()) {
 
29385             difference = extent = undefined;
 
29388         var zoom = String(~~map.zoom());
 
29389         if (surface.attr('data-zoom') !== zoom) {
 
29390             surface.attr('data-zoom', zoom)
 
29391                 .classed('low-zoom', zoom <= 16);
 
29395             supersurface.call(context.background());
 
29399         if (map.editable()) {
 
29400             context.loadTiles(projection, dimensions);
 
29401             drawVector(difference, extent);
 
29410             projection.scale() * 2 * Math.PI,
 
29411             projection.translate().slice()];
 
29417     function queueRedraw() {
 
29418         clearTimeout(timeoutId);
 
29419         timeoutId = setTimeout(function() { redraw(); }, 300);
 
29422     function pointLocation(p) {
 
29423         var translate = projection.translate(),
 
29424             scale = projection.scale() * 2 * Math.PI;
 
29425         return [(p[0] - translate[0]) / scale, (p[1] - translate[1]) / scale];
 
29428     function locationPoint(l) {
 
29429         var translate = projection.translate(),
 
29430             scale = projection.scale() * 2 * Math.PI;
 
29431         return [l[0] * scale + translate[0], l[1] * scale + translate[1]];
 
29434     map.mouse = function() {
 
29435         var e = mousemove || d3.event, s;
 
29436         while ((s = e.sourceEvent)) e = s;
 
29440     map.mouseCoordinates = function() {
 
29441         return projection.invert(map.mouse());
 
29444     map.dblclickEnable = function(_) {
 
29445         if (!arguments.length) return dblclickEnabled;
 
29446         dblclickEnabled = _;
 
29450     map.redrawEnable = function(_) {
 
29451         if (!arguments.length) return redrawEnabled;
 
29456     function interpolateZoom(_) {
 
29457         var k = projection.scale(),
 
29458             t = projection.translate();
 
29460         surface.node().__chart__ = {
 
29467         projection.scale(k).translate(t);  // undo setZoom projection changes
 
29469         zoom.event(surface.transition());
 
29472     function setZoom(_, force) {
 
29473         if (_ === map.zoom() && !force)
 
29475         var scale = 256 * Math.pow(2, _),
 
29476             center = pxCenter(),
 
29477             l = pointLocation(center);
 
29478         scale = Math.max(1024, Math.min(256 * Math.pow(2, 24), scale));
 
29479         projection.scale(scale / (2 * Math.PI));
 
29481         var t = projection.translate();
 
29482         l = locationPoint(l);
 
29483         t[0] += center[0] - l[0];
 
29484         t[1] += center[1] - l[1];
 
29485         projection.translate(t);
 
29486         zoom.translate(projection.translate());
 
29490     function setCenter(_) {
 
29491         var c = map.center();
 
29492         if (_[0] === c[0] && _[1] === c[1])
 
29494         var t = projection.translate(),
 
29496             ll = projection(_);
 
29497         projection.translate([
 
29498             t[0] - ll[0] + pxC[0],
 
29499             t[1] - ll[1] + pxC[1]]);
 
29500         zoom.translate(projection.translate());
 
29504     map.pan = function(d) {
 
29505         var t = projection.translate();
 
29508         projection.translate(t);
 
29509         zoom.translate(projection.translate());
 
29510         dispatch.move(map);
 
29514     map.dimensions = function(_) {
 
29515         if (!arguments.length) return dimensions;
 
29516         var center = map.center();
 
29518         drawLayers.dimensions(dimensions);
 
29519         context.background().dimensions(dimensions);
 
29520         projection.clipExtent([[0, 0], dimensions]);
 
29521         mouse = iD.util.fastMouse(supersurface.node());
 
29526     function zoomIn(integer) {
 
29527       interpolateZoom(~~map.zoom() + integer);
 
29530     function zoomOut(integer) {
 
29531       interpolateZoom(~~map.zoom() - integer);
 
29534     map.zoomIn = function() { zoomIn(1); };
 
29535     map.zoomInFurther = function() { zoomIn(4); };
 
29537     map.zoomOut = function() { zoomOut(1); };
 
29538     map.zoomOutFurther = function() { zoomOut(4); };
 
29540     map.center = function(loc) {
 
29541         if (!arguments.length) {
 
29542             return projection.invert(pxCenter());
 
29545         if (setCenter(loc)) {
 
29546             dispatch.move(map);
 
29552     map.zoom = function(z) {
 
29553         if (!arguments.length) {
 
29554             return Math.max(Math.log(projection.scale() * 2 * Math.PI) / Math.LN2 - 8, 0);
 
29558             surface.interrupt();
 
29559             iD.ui.flash(context.container())
 
29560                 .select('.content')
 
29561                 .text(t('cannot_zoom'));
 
29562             z = context.minEditableZoom();
 
29566             dispatch.move(map);
 
29572     map.zoomTo = function(entity, zoomLimits) {
 
29573         var extent = entity.extent(context.graph());
 
29574         if (!isFinite(extent.area())) return;
 
29576         var zoom = map.trimmedExtentZoom(extent);
 
29577         zoomLimits = zoomLimits || [context.minEditableZoom(), 20];
 
29578         map.centerZoom(extent.center(), Math.min(Math.max(zoom, zoomLimits[0]), zoomLimits[1]));
 
29581     map.centerZoom = function(loc, z) {
 
29582         var centered = setCenter(loc),
 
29583             zoomed   = setZoom(z);
 
29585         if (centered || zoomed) {
 
29586             dispatch.move(map);
 
29592     map.centerEase = function(loc) {
 
29593         var from = map.center().slice(),
 
29597         surface.one('mousedown.ease', function() {
 
29601         d3.timer(function() {
 
29602             if (stop) return true;
 
29603             map.center(iD.geo.interp(from, loc, (t += 1) / 10));
 
29609     map.extent = function(_) {
 
29610         if (!arguments.length) {
 
29611             return new iD.geo.Extent(projection.invert([0, dimensions[1]]),
 
29612                                  projection.invert([dimensions[0], 0]));
 
29614             var extent = iD.geo.Extent(_);
 
29615             map.centerZoom(extent.center(), map.extentZoom(extent));
 
29619     map.trimmedExtent = function(_) {
 
29620         if (!arguments.length) {
 
29621             var headerY = 60, footerY = 30, pad = 10;
 
29622             return new iD.geo.Extent(projection.invert([pad, dimensions[1] - footerY - pad]),
 
29623                     projection.invert([dimensions[0] - pad, headerY + pad]));
 
29625             var extent = iD.geo.Extent(_);
 
29626             map.centerZoom(extent.center(), map.trimmedExtentZoom(extent));
 
29630     function calcZoom(extent, dim) {
 
29631         var tl = projection([extent[0][0], extent[1][1]]),
 
29632             br = projection([extent[1][0], extent[0][1]]);
 
29634         // Calculate maximum zoom that fits extent
 
29635         var hFactor = (br[0] - tl[0]) / dim[0],
 
29636             vFactor = (br[1] - tl[1]) / dim[1],
 
29637             hZoomDiff = Math.log(Math.abs(hFactor)) / Math.LN2,
 
29638             vZoomDiff = Math.log(Math.abs(vFactor)) / Math.LN2,
 
29639             newZoom = map.zoom() - Math.max(hZoomDiff, vZoomDiff);
 
29644     map.extentZoom = function(_) {
 
29645         return calcZoom(iD.geo.Extent(_), dimensions);
 
29648     map.trimmedExtentZoom = function(_) {
 
29649         var trimY = 120, trimX = 40,
 
29650             trimmed = [dimensions[0] - trimX, dimensions[1] - trimY];
 
29651         return calcZoom(iD.geo.Extent(_), trimmed);
 
29654     map.editable = function() {
 
29655         return map.zoom() >= context.minEditableZoom();
 
29658     map.minzoom = function(_) {
 
29659         if (!arguments.length) return minzoom;
 
29664     map.layers = drawLayers;
 
29666     return d3.rebind(map, dispatch, 'on');
 
29668 iD.TileLayer = function() {
 
29669     var tileSize = 256,
 
29670         tile = d3.geo.tile(),
 
29675         transformProp = iD.util.prefixCSSProperty('Transform'),
 
29676         source = d3.functor('');
 
29678     function tileSizeAtZoom(d, z) {
 
29679         return (tileSize * Math.pow(2, z - d[2])) / tileSize;
 
29682     function atZoom(t, distance) {
 
29683         var power = Math.pow(2, distance);
 
29685             Math.floor(t[0] * power),
 
29686             Math.floor(t[1] * power),
 
29690     function lookUp(d) {
 
29691         for (var up = -1; up > -d[2]; up--) {
 
29692             var tile = atZoom(d, up);
 
29693             if (cache[source.url(tile)] !== false) {
 
29699     function uniqueBy(a, n) {
 
29700         var o = [], seen = {};
 
29701         for (var i = 0; i < a.length; i++) {
 
29702             if (seen[a[i][n]] === undefined) {
 
29704                 seen[a[i][n]] = true;
 
29710     function addSource(d) {
 
29711         d.push(source.url(d));
 
29715     // Update tiles based on current state of `projection`.
 
29716     function background(selection) {
 
29717         tile.scale(projection.scale() * 2 * Math.PI)
 
29718             .translate(projection.translate());
 
29721             projection.scale() * Math.PI - projection.translate()[0],
 
29722             projection.scale() * Math.PI - projection.translate()[1]];
 
29724         z = Math.max(Math.log(projection.scale() * 2 * Math.PI) / Math.log(2) - 8, 0);
 
29729     // Derive the tiles onscreen, remove those offscreen and position them.
 
29730     // Important that this part not depend on `projection` because it's
 
29731     // rentered when tiles load/error (see #644).
 
29732     function render(selection) {
 
29735         if (source.validZoom(z)) {
 
29736             tile().forEach(function(d) {
 
29738                 if (d[3] === '') return;
 
29739                 if (typeof d[3] !== 'string') return; // Workaround for chrome crash https://github.com/openstreetmap/iD/issues/2295
 
29741                 if (cache[d[3]] === false && lookUp(d)) {
 
29742                     requests.push(addSource(lookUp(d)));
 
29746             requests = uniqueBy(requests, 3).filter(function(r) {
 
29747                 // don't re-request tiles which have failed in the past
 
29748                 return cache[r[3]] !== false;
 
29752         var pixelOffset = [
 
29753             source.offset()[0] * Math.pow(2, z),
 
29754             source.offset()[1] * Math.pow(2, z)
 
29758             cache[d[3]] = true;
 
29762                 .classed('tile-loaded', true);
 
29766         function error(d) {
 
29767             cache[d[3]] = false;
 
29775         function imageTransform(d) {
 
29776             var _ts = tileSize * Math.pow(2, z - d[2]);
 
29777             var scale = tileSizeAtZoom(d, z);
 
29778             return 'translate(' +
 
29779                 ((d[0] * _ts) - tileOrigin[0] + pixelOffset[0]) + 'px,' +
 
29780                 ((d[1] * _ts) - tileOrigin[1] + pixelOffset[1]) + 'px)' +
 
29781                 'scale(' + scale + ',' + scale + ')';
 
29784         var image = selection
 
29786             .data(requests, function(d) { return d[3]; });
 
29789             .style(transformProp, imageTransform)
 
29790             .classed('tile-removing', true)
 
29792                 var tile = d3.select(this);
 
29793                 window.setTimeout(function() {
 
29794                     if (tile.classed('tile-removing')) {
 
29800         image.enter().append('img')
 
29801             .attr('class', 'tile')
 
29802             .attr('src', function(d) { return d[3]; })
 
29803             .on('error', error)
 
29807             .style(transformProp, imageTransform)
 
29808             .classed('tile-removing', false);
 
29811     background.projection = function(_) {
 
29812         if (!arguments.length) return projection;
 
29817     background.dimensions = function(_) {
 
29818         if (!arguments.length) return tile.size();
 
29823     background.source = function(_) {
 
29824         if (!arguments.length) return source;
 
29827         tile.scaleExtent(source.scaleExtent);
 
29834     PointTransform: function(projection) {
 
29835         return function(entity) {
 
29836             // http://jsperf.com/short-array-join
 
29837             var pt = projection(entity.loc);
 
29838             return 'translate(' + pt[0] + ',' + pt[1] + ')';
 
29842     Path: function(projection, graph, polygon) {
 
29844             clip = d3.geo.clipExtent().extent(projection.clipExtent()).stream,
 
29845             project = projection.stream,
 
29846             path = d3.geo.path()
 
29847                 .projection({stream: function(output) { return polygon ? project(output) : project(clip(output)); }});
 
29849         return function(entity) {
 
29850             if (entity.id in cache) {
 
29851                 return cache[entity.id];
 
29853                 return cache[entity.id] = path(entity.asGeoJSON(graph));
 
29858     OneWaySegments: function(projection, graph, dt) {
 
29859         return function(entity) {
 
29865                 clip = d3.geo.clipExtent().extent(projection.clipExtent()).stream,
 
29866                 coordinates = graph.childNodes(entity).map(function(n) {
 
29870             if (entity.tags.oneway === '-1') coordinates.reverse();
 
29873                 type: 'LineString',
 
29874                 coordinates: coordinates
 
29875             }, projection.stream(clip({
 
29876                 lineStart: function() {},
 
29877                 lineEnd: function() {
 
29880                 point: function(x, y) {
 
29884                         var span = iD.geo.euclideanDistance(a, b) - offset;
 
29887                             var angle = Math.atan2(b[1] - a[1], b[0] - a[0]),
 
29888                                 dx = dt * Math.cos(angle),
 
29889                                 dy = dt * Math.sin(angle),
 
29890                                 p = [a[0] + offset * Math.cos(angle),
 
29891                                      a[1] + offset * Math.sin(angle)];
 
29893                             var segment = 'M' + a[0] + ',' + a[1] +
 
29894                                           'L' + p[0] + ',' + p[1];
 
29896                             for (span -= dt; span >= 0; span -= dt) {
 
29899                                 segment += 'L' + p[0] + ',' + p[1];
 
29902                             segment += 'L' + b[0] + ',' + b[1];
 
29903                             segments.push({id: entity.id, index: i, d: segment});
 
29918     RelationMemberTags: function(graph) {
 
29919         return function(entity) {
 
29920             var tags = entity.tags;
 
29921             graph.parentRelations(entity).forEach(function(relation) {
 
29922                 var type = relation.tags.type;
 
29923                 if (type === 'multipolygon' || type === 'boundary') {
 
29924                     tags = _.extend({}, relation.tags, tags);
 
29931 iD.svg.Areas = function(projection) {
 
29932     // Patterns only work in Firefox when set directly on element.
 
29933     // (This is not a bug: https://bugzilla.mozilla.org/show_bug.cgi?id=750632)
 
29935         wetland: 'wetland',
 
29938         construction: 'construction',
 
29939         military: 'construction',
 
29940         cemetery: 'cemetery',
 
29941         grave_yard: 'cemetery',
 
29944         farmland: 'farmland',
 
29948     var patternKeys = ['landuse', 'natural', 'amenity'];
 
29950     function setPattern(d) {
 
29951         for (var i = 0; i < patternKeys.length; i++) {
 
29952             if (patterns.hasOwnProperty(d.tags[patternKeys[i]])) {
 
29953                 this.style.fill = this.style.stroke = 'url("#pattern-' + patterns[d.tags[patternKeys[i]]] + '")';
 
29957         this.style.fill = this.style.stroke = '';
 
29960     return function drawAreas(surface, graph, entities, filter) {
 
29961         var path = iD.svg.Path(projection, graph, true),
 
29965         for (var i = 0; i < entities.length; i++) {
 
29966             var entity = entities[i];
 
29967             if (entity.geometry(graph) !== 'area') continue;
 
29969             multipolygon = iD.geo.isSimpleMultipolygonOuterMember(entity, graph);
 
29970             if (multipolygon) {
 
29971                 areas[multipolygon.id] = {
 
29972                     entity: multipolygon.mergeTags(entity.tags),
 
29973                     area: Math.abs(entity.area(graph))
 
29975             } else if (!areas[entity.id]) {
 
29976                 areas[entity.id] = {
 
29978                     area: Math.abs(entity.area(graph))
 
29983         areas = d3.values(areas).filter(function hasPath(a) { return path(a.entity); });
 
29984         areas.sort(function areaSort(a, b) { return b.area - a.area; });
 
29985         areas = _.pluck(areas, 'entity');
 
29987         var strokes = areas.filter(function(area) {
 
29988             return area.type === 'way';
 
29998         var clipPaths = surface.selectAll('defs').selectAll('.clipPath')
 
30000            .data(data.clip, iD.Entity.key);
 
30003            .append('clipPath')
 
30004            .attr('class', 'clipPath')
 
30005            .attr('id', function(entity) { return entity.id + '-clippath'; })
 
30008         clipPaths.selectAll('path')
 
30014         var areagroup = surface
 
30015             .selectAll('.layer-areas')
 
30016             .selectAll('g.areagroup')
 
30017             .data(['fill', 'shadow', 'stroke']);
 
30021             .attr('class', function(d) { return 'layer areagroup area-' + d; });
 
30023         var paths = areagroup
 
30026             .data(function(layer) { return data[layer]; }, iD.Entity.key);
 
30028         // Remove exiting areas first, so they aren't included in the `fills`
 
30029         // array used for sorting below (https://github.com/openstreetmap/iD/issues/1903).
 
30033         var fills = surface.selectAll('.area-fill path.area')[0];
 
30035         var bisect = d3.bisector(function(node) {
 
30036             return -node.__data__.area(graph);
 
30039         function sortedByArea(entity) {
 
30040             if (this.__data__ === 'fill') {
 
30041                 return fills[bisect(fills, -entity.area(graph))];
 
30046             .insert('path', sortedByArea)
 
30047             .each(function(entity) {
 
30048                 var layer = this.parentNode.__data__;
 
30050                 this.setAttribute('class', entity.type + ' area ' + layer + ' ' + entity.id);
 
30052                 if (layer === 'fill') {
 
30053                     this.setAttribute('clip-path', 'url(#' + entity.id + '-clippath)');
 
30054                     setPattern.apply(this, arguments);
 
30057             .call(iD.svg.TagClasses());
 
30064     A standalone SVG element that contains only a `defs` sub-element. To be
 
30065     used once globally, since defs IDs must be unique within a document.
 
30067 iD.svg.Defs = function(context) {
 
30069     function SVGSpriteDefinition(id, href) {
 
30070         return function(defs) {
 
30071             d3.xml(href, 'image/svg+xml', function(err, svg) {
 
30073                 defs.node().appendChild(
 
30074                     d3.select(svg.documentElement).attr('id', id).node()
 
30080     return function drawDefs(selection) {
 
30081         var defs = selection.append('defs');
 
30084         defs.append('marker')
 
30086                 id: 'oneway-marker',
 
30087                 viewBox: '0 0 10 10',
 
30092                 markerUnits: 'strokeWidth',
 
30096             .attr('class', 'oneway')
 
30097             .attr('d', 'M 5 3 L 0 3 L 0 2 L 5 2 L 5 0 L 10 2.5 L 5 5 z')
 
30098             .attr('stroke', 'none')
 
30099             .attr('fill', '#000')
 
30100             .attr('opacity', '0.5');
 
30103         var patterns = defs.selectAll('pattern')
 
30105                 // pattern name, pattern image name
 
30106                 ['wetland', 'wetland'],
 
30107                 ['construction', 'construction'],
 
30108                 ['cemetery', 'cemetery'],
 
30109                 ['orchard', 'orchard'],
 
30110                 ['farmland', 'farmland'],
 
30119                     return 'pattern-' + d[0];
 
30123                 patternUnits: 'userSpaceOnUse'
 
30126         patterns.append('rect')
 
30132                 'class': function (d) {
 
30133                     return 'pattern-color-' + d[0];
 
30137         patterns.append('image')
 
30144             .attr('xlink:href', function (d) {
 
30145                 return context.imagePath('pattern/' + d[1] + '.png');
 
30150             .data([12, 18, 20, 32, 45])
 
30151             .enter().append('clipPath')
 
30152             .attr('id', function (d) {
 
30153                 return 'clip-square-' + d;
 
30158             .attr('width', function (d) {
 
30161             .attr('height', function (d) {
 
30165         defs.call(SVGSpriteDefinition(
 
30167             context.imagePath('iD-sprite.svg')));
 
30169         defs.call(SVGSpriteDefinition(
 
30171             context.imagePath('maki-sprite.svg')));
 
30174 iD.svg.Gpx = function(projection, context) {
 
30175     var showLabels = true,
 
30179         if (iD.svg.Gpx.initialized) return;  // run once
 
30181         iD.svg.Gpx.geojson = {};
 
30182         iD.svg.Gpx.enabled = true;
 
30185             d3.event.stopPropagation();
 
30186             d3.event.preventDefault();
 
30187             d3.event.dataTransfer.dropEffect = 'copy';
 
30191             .attr('dropzone', 'copy')
 
30192             .on('drop.localgpx', function() {
 
30193                 d3.event.stopPropagation();
 
30194                 d3.event.preventDefault();
 
30195                 if (!iD.detect().filedrop) return;
 
30196                 drawGpx.files(d3.event.dataTransfer.files);
 
30198             .on('dragenter.localgpx', over)
 
30199             .on('dragexit.localgpx', over)
 
30200             .on('dragover.localgpx', over);
 
30202         iD.svg.Gpx.initialized = true;
 
30206     function drawGpx(surface) {
 
30207         var geojson = iD.svg.Gpx.geojson,
 
30208             enabled = iD.svg.Gpx.enabled;
 
30210         layer = surface.selectAll('.layer-gpx')
 
30211             .data(enabled ? [0] : []);
 
30215             .attr('class', 'layer-gpx');
 
30227             .attr('class', 'gpx');
 
30232         var path = d3.geo.path()
 
30233             .projection(projection);
 
30239         var labels = layer.selectAll('text')
 
30240             .data(showLabels && geojson.features ? geojson.features : []);
 
30244             .attr('class', 'gpx')
 
30245             .text(function(d) {
 
30246                 return d.properties.desc || d.properties.name;
 
30253             .attr('x', function(d) {
 
30254                 var centroid = path.centroid(d);
 
30255                 return centroid[0] + 7;
 
30257             .attr('y', function(d) {
 
30258                 var centroid = path.centroid(d);
 
30259                 return centroid[1];
 
30264     function toDom(x) {
 
30265         return (new DOMParser()).parseFromString(x, 'text/xml');
 
30268     function redraw() {
 
30269         context.pan([0,0]);
 
30272     drawGpx.showLabels = function(_) {
 
30273         if (!arguments.length) return showLabels;
 
30278     drawGpx.enabled = function(_) {
 
30279         if (!arguments.length) return iD.svg.Gpx.enabled;
 
30280         iD.svg.Gpx.enabled = _;
 
30284     drawGpx.hasGpx = function() {
 
30285         var geojson = iD.svg.Gpx.geojson;
 
30286         return (!(_.isEmpty(geojson) || _.isEmpty(geojson.features)));
 
30289     drawGpx.geojson = function(gj) {
 
30290         if (!arguments.length) return iD.svg.Gpx.geojson;
 
30291         if (_.isEmpty(gj) || _.isEmpty(gj.features)) return this;
 
30292         iD.svg.Gpx.geojson = gj;
 
30296     drawGpx.url = function(url) {
 
30297         d3.text(url, function(err, data) {
 
30299                 drawGpx.geojson(toGeoJSON.gpx(toDom(data)));
 
30306     drawGpx.files = function(fileList) {
 
30307         var f = fileList[0],
 
30308             reader = new FileReader();
 
30310         reader.onload = function(e) {
 
30311             drawGpx.geojson(toGeoJSON.gpx(toDom(e.target.result))).fitZoom();
 
30315         reader.readAsText(f);
 
30319     drawGpx.fitZoom = function() {
 
30320         if (!this.hasGpx()) return this;
 
30321         var geojson = iD.svg.Gpx.geojson;
 
30323         var map = context.map(),
 
30324             viewport = map.trimmedExtent().polygon(),
 
30325             coords = _.reduce(geojson.features, function(coords, feature) {
 
30326                 var c = feature.geometry.coordinates;
 
30327                 return _.union(coords, feature.geometry.type === 'Point' ? [c] : c);
 
30330         if (!iD.geo.polygonIntersectsPolygon(viewport, coords, true)) {
 
30331             var extent = iD.geo.Extent(d3.geo.bounds(geojson));
 
30332             map.centerZoom(extent.center(), map.trimmedExtentZoom(extent));
 
30341 iD.svg.Icon = function(name, svgklass, useklass) {
 
30342     return function drawIcon(selection) {
 
30343         selection.selectAll('svg')
 
30347             .attr('class', 'icon ' + (svgklass || ''))
 
30349             .attr('xlink:href', name)
 
30350             .attr('class', useklass);
 
30353 iD.svg.Labels = function(projection, context) {
 
30354     var path = d3.geo.path().projection(projection);
 
30356     // Replace with dict and iterate over entities tags instead?
 
30357     var label_stack = [
 
30358         ['line', 'aeroway'],
 
30359         ['line', 'highway'],
 
30360         ['line', 'railway'],
 
30361         ['line', 'waterway'],
 
30362         ['area', 'aeroway'],
 
30363         ['area', 'amenity'],
 
30364         ['area', 'building'],
 
30365         ['area', 'historic'],
 
30366         ['area', 'leisure'],
 
30367         ['area', 'man_made'],
 
30368         ['area', 'natural'],
 
30370         ['area', 'tourism'],
 
30371         ['point', 'aeroway'],
 
30372         ['point', 'amenity'],
 
30373         ['point', 'building'],
 
30374         ['point', 'historic'],
 
30375         ['point', 'leisure'],
 
30376         ['point', 'man_made'],
 
30377         ['point', 'natural'],
 
30379         ['point', 'tourism'],
 
30385     var default_size = 12;
 
30387     var font_sizes = label_stack.map(function(d) {
 
30388         var style = iD.util.getStyle('text.' + d[0] + '.tag-' + d[1]),
 
30389             m = style && style.cssText.match('font-size: ([0-9]{1,2})px;');
 
30390         if (m) return parseInt(m[1], 10);
 
30392         style = iD.util.getStyle('text.' + d[0]);
 
30393         m = style && style.cssText.match('font-size: ([0-9]{1,2})px;');
 
30394         if (m) return parseInt(m[1], 10);
 
30396         return default_size;
 
30401     var pointOffsets = [
 
30402         [15, -11, 'start'], // right
 
30403         [10, -11, 'start'], // unused right now
 
30407     var lineOffsets = [50, 45, 55, 40, 60, 35, 65, 30, 70, 25,
 
30408         75, 20, 80, 15, 95, 10, 90, 5, 95];
 
30411     var noIcons = ['building', 'landuse', 'natural'];
 
30412     function blacklisted(preset) {
 
30413         return _.any(noIcons, function(s) {
 
30414             return preset.id.indexOf(s) >= 0;
 
30418     function get(array, prop) {
 
30419         return function(d, i) { return array[i][prop]; };
 
30422     var textWidthCache = {};
 
30424     function textWidth(text, size, elem) {
 
30425         var c = textWidthCache[size];
 
30426         if (!c) c = textWidthCache[size] = {};
 
30432             c[text] = elem.getComputedTextLength();
 
30436             var str = encodeURIComponent(text).match(/%[CDEFcdef]/g);
 
30437             if (str === null) {
 
30438                 return size / 3 * 2 * text.length;
 
30440                 return size / 3 * (2 * text.length + str.length);
 
30445     function drawLineLabels(group, entities, filter, classes, labels) {
 
30446         var texts = group.selectAll('text.' + classes)
 
30448             .data(entities, iD.Entity.key);
 
30452             .attr('class', function(d, i) { return classes + ' ' + labels[i].classes + ' ' + d.id; })
 
30453             .append('textPath')
 
30454             .attr('class', 'textpath');
 
30457         texts.selectAll('.textpath')
 
30459             .data(entities, iD.Entity.key)
 
30461                 'startOffset': '50%',
 
30462                 'xlink:href': function(d) { return '#labelpath-' + d.id; }
 
30464             .text(iD.util.displayName);
 
30466         texts.exit().remove();
 
30469     function drawLinePaths(group, entities, filter, classes, labels) {
 
30470         var halos = group.selectAll('path')
 
30472             .data(entities, iD.Entity.key);
 
30476             .style('stroke-width', get(labels, 'font-size'))
 
30477             .attr('id', function(d) { return 'labelpath-' + d.id; })
 
30478             .attr('class', classes);
 
30480         halos.attr('d', get(labels, 'lineString'));
 
30482         halos.exit().remove();
 
30485     function drawPointLabels(group, entities, filter, classes, labels) {
 
30486         var texts = group.selectAll('text.' + classes)
 
30488             .data(entities, iD.Entity.key);
 
30492             .attr('class', function(d, i) { return classes + ' ' + labels[i].classes + ' ' + d.id; });
 
30494         texts.attr('x', get(labels, 'x'))
 
30495             .attr('y', get(labels, 'y'))
 
30496             .style('text-anchor', get(labels, 'textAnchor'))
 
30497             .text(iD.util.displayName)
 
30498             .each(function(d, i) { textWidth(iD.util.displayName(d), labels[i].height, this); });
 
30500         texts.exit().remove();
 
30504     function drawAreaLabels(group, entities, filter, classes, labels) {
 
30505         entities = entities.filter(hasText);
 
30506         labels = labels.filter(hasText);
 
30507         return drawPointLabels(group, entities, filter, classes, labels);
 
30509         function hasText(d, i) {
 
30510             return labels[i].hasOwnProperty('x') && labels[i].hasOwnProperty('y');
 
30514     function drawAreaIcons(group, entities, filter, classes, labels) {
 
30515         var icons = group.selectAll('use')
 
30517             .data(entities, iD.Entity.key);
 
30521             .attr('class', 'icon areaicon')
 
30522             .attr('width', '18px')
 
30523             .attr('height', '18px');
 
30525         icons.attr('transform', get(labels, 'transform'))
 
30526             .attr('xlink:href', function(d) {
 
30527                 var icon = context.presets().match(d, context.graph()).icon;
 
30528                 return '#' + icon + (icon === 'hairdresser' ? '-24': '-18');    // workaround: maki hairdresser-18 broken?
 
30532         icons.exit().remove();
 
30535     function reverse(p) {
 
30536         var angle = Math.atan2(p[1][1] - p[0][1], p[1][0] - p[0][0]);
 
30537         return !(p[0][0] < p[p.length - 1][0] && angle < Math.PI/2 && angle > -Math.PI/2);
 
30540     function lineString(nodes) {
 
30541         return 'M' + nodes.join('L');
 
30544     function subpath(nodes, from, to) {
 
30545         function segmentLength(i) {
 
30546             var dx = nodes[i][0] - nodes[i + 1][0];
 
30547             var dy = nodes[i][1] - nodes[i + 1][1];
 
30548             return Math.sqrt(dx * dx + dy * dy);
 
30552             start, end, i0, i1;
 
30553         for (var i = 0; i < nodes.length - 1; i++) {
 
30554             var current = segmentLength(i);
 
30556             if (!start && sofar + current >= from) {
 
30557                 portion = (from - sofar) / current;
 
30559                     nodes[i][0] + portion * (nodes[i + 1][0] - nodes[i][0]),
 
30560                     nodes[i][1] + portion * (nodes[i + 1][1] - nodes[i][1])
 
30564             if (!end && sofar + current >= to) {
 
30565                 portion = (to - sofar) / current;
 
30567                     nodes[i][0] + portion * (nodes[i + 1][0] - nodes[i][0]),
 
30568                     nodes[i][1] + portion * (nodes[i + 1][1] - nodes[i][1])
 
30575         var ret = nodes.slice(i0, i1);
 
30576         ret.unshift(start);
 
30582     function hideOnMouseover() {
 
30583         var layers = d3.select(this)
 
30584             .selectAll('.layer-label, .layer-halo');
 
30586         layers.selectAll('.proximate')
 
30587             .classed('proximate', false);
 
30589         var mouse = context.mouse(),
 
30591             rect = [mouse[0] - pad, mouse[1] - pad, mouse[0] + pad, mouse[1] + pad],
 
30592             ids = _.pluck(rtree.search(rect), 'id');
 
30594         if (!ids.length) return;
 
30595         layers.selectAll('.' + ids.join(', .'))
 
30596             .classed('proximate', true);
 
30599     var rtree = rbush(),
 
30602     function drawLabels(surface, graph, entities, filter, dimensions, fullRedraw) {
 
30603         var hidePoints = !surface.selectAll('.node.point').node();
 
30605         var labelable = [], i, k, entity;
 
30606         for (i = 0; i < label_stack.length; i++) labelable.push([]);
 
30612             for (i = 0; i < entities.length; i++) {
 
30613                 rtree.remove(rectangles[entities[i].id]);
 
30617         // Split entities into groups specified by label_stack
 
30618         for (i = 0; i < entities.length; i++) {
 
30619             entity = entities[i];
 
30620             var geometry = entity.geometry(graph);
 
30622             if (geometry === 'vertex')
 
30624             if (hidePoints && geometry === 'point')
 
30627             var preset = geometry === 'area' && context.presets().match(entity, graph),
 
30628                 icon = preset && !blacklisted(preset) && preset.icon;
 
30630             if (!icon && !iD.util.displayName(entity))
 
30633             for (k = 0; k < label_stack.length; k++) {
 
30634                 if (geometry === label_stack[k][0] && entity.tags[label_stack[k][1]]) {
 
30635                     labelable[k].push(entity);
 
30653         // Try and find a valid label for labellable entities
 
30654         for (k = 0; k < labelable.length; k++) {
 
30655             var font_size = font_sizes[k];
 
30656             for (i = 0; i < labelable[k].length; i++) {
 
30657                 entity = labelable[k][i];
 
30658                 var name = iD.util.displayName(entity),
 
30659                     width = name && textWidth(name, font_size),
 
30661                 if (entity.geometry(graph) === 'point') {
 
30662                     p = getPointLabel(entity, width, font_size);
 
30663                 } else if (entity.geometry(graph) === 'line') {
 
30664                     p = getLineLabel(entity, width, font_size);
 
30665                 } else if (entity.geometry(graph) === 'area') {
 
30666                     p = getAreaLabel(entity, width, font_size);
 
30669                     p.classes = entity.geometry(graph) + ' tag-' + label_stack[k][1];
 
30670                     positions[entity.geometry(graph)].push(p);
 
30671                     labelled[entity.geometry(graph)].push(entity);
 
30676         function getPointLabel(entity, width, height) {
 
30677             var coord = projection(entity.loc),
 
30679                 offset = pointOffsets[0],
 
30683                     x: coord[0] + offset[0],
 
30684                     y: coord[1] + offset[1],
 
30685                     textAnchor: offset[2]
 
30687             var rect = [p.x - m, p.y - m, p.x + width + m, p.y + height + m];
 
30688             if (tryInsert(rect, entity.id)) return p;
 
30692         function getLineLabel(entity, width, height) {
 
30693             var nodes = _.pluck(graph.childNodes(entity), 'loc').map(projection),
 
30694                 length = iD.geo.pathLength(nodes);
 
30695             if (length < width + 20) return;
 
30697             for (var i = 0; i < lineOffsets.length; i++) {
 
30698                 var offset = lineOffsets[i],
 
30699                     middle = offset / 100 * length,
 
30700                     start = middle - width/2;
 
30701                 if (start < 0 || start + width > length) continue;
 
30702                 var sub = subpath(nodes, start, start + width),
 
30703                     rev = reverse(sub),
 
30705                         Math.min(sub[0][0], sub[sub.length - 1][0]) - 10,
 
30706                         Math.min(sub[0][1], sub[sub.length - 1][1]) - 10,
 
30707                         Math.max(sub[0][0], sub[sub.length - 1][0]) + 20,
 
30708                         Math.max(sub[0][1], sub[sub.length - 1][1]) + 30
 
30710                 if (rev) sub = sub.reverse();
 
30711                 if (tryInsert(rect, entity.id)) return {
 
30712                     'font-size': height + 2,
 
30713                     lineString: lineString(sub),
 
30714                     startOffset: offset + '%'
 
30719         function getAreaLabel(entity, width, height) {
 
30720             var centroid = path.centroid(entity.asGeoJSON(graph, true)),
 
30721                 extent = entity.extent(graph),
 
30722                 entitywidth = projection(extent[1])[0] - projection(extent[0])[0],
 
30725             if (isNaN(centroid[0]) || entitywidth < 20) return;
 
30727             var iconX = centroid[0] - (iconSize/2),
 
30728                 iconY = centroid[1] - (iconSize/2),
 
30729                 textOffset = iconSize + 5;
 
30732                 transform: 'translate(' + iconX + ',' + iconY + ')'
 
30735             if (width && entitywidth >= width + 20) {
 
30737                 p.y = centroid[1] + textOffset;
 
30738                 p.textAnchor = 'middle';
 
30740                 rect = [p.x - width/2, p.y, p.x + width/2, p.y + height + textOffset];
 
30742                 rect = [iconX, iconY, iconX + iconSize, iconY + iconSize];
 
30745             if (tryInsert(rect, entity.id)) return p;
 
30749         function tryInsert(rect, id) {
 
30750             // Check that label is visible
 
30751             if (rect[0] < 0 || rect[1] < 0 || rect[2] > dimensions[0] ||
 
30752                 rect[3] > dimensions[1]) return false;
 
30753             var v = rtree.search(rect).length === 0;
 
30756                 rtree.insert(rect);
 
30757                 rectangles[id] = rect;
 
30762         var label = surface.selectAll('.layer-label'),
 
30763             halo = surface.selectAll('.layer-halo');
 
30766         drawPointLabels(label, labelled.point, filter, 'pointlabel', positions.point);
 
30767         drawPointLabels(halo, labelled.point, filter, 'pointlabel-halo', positions.point);
 
30770         drawLinePaths(halo, labelled.line, filter, '', positions.line);
 
30771         drawLineLabels(label, labelled.line, filter, 'linelabel', positions.line);
 
30772         drawLineLabels(halo, labelled.line, filter, 'linelabel-halo', positions.line);
 
30775         drawAreaLabels(label, labelled.area, filter, 'arealabel', positions.area);
 
30776         drawAreaLabels(halo, labelled.area, filter, 'arealabel-halo', positions.area);
 
30777         drawAreaIcons(label, labelled.area, filter, 'arealabel-icon', positions.area);
 
30780     drawLabels.supersurface = function(supersurface) {
 
30782             .on('mousemove.hidelabels', hideOnMouseover)
 
30783             .on('mousedown.hidelabels', function () {
 
30784                 supersurface.on('mousemove.hidelabels', null);
 
30786             .on('mouseup.hidelabels', function () {
 
30787                 supersurface.on('mousemove.hidelabels', hideOnMouseover);
 
30793 iD.svg.Layers = function(projection, context) {
 
30794     var svg = d3.select(null),
 
30796             { id: 'osm', layer: iD.svg.Osm(projection, context) },
 
30797             { id: 'gpx', layer: iD.svg.Gpx(projection, context) },
 
30798             { id: 'mapillary-images', layer: iD.svg.MapillaryImages(projection, context) },
 
30799             { id: 'mapillary-signs',  layer: iD.svg.MapillarySigns(projection, context) }
 
30803     function drawLayers(selection) {
 
30804         svg = selection.selectAll('.surface')
 
30809             .attr('class', 'surface')
 
30812         var groups = svg.selectAll('.data-layer')
 
30817             .attr('class', function(d) { return 'data-layer data-layer-' + d.id; });
 
30820             .each(function(d) { d3.select(this).call(d.layer); });
 
30826     drawLayers.all = function() {
 
30830     drawLayers.layer = function(id) {
 
30831         var obj = _.find(layers, 'id', id);
 
30832         return obj && obj.layer;
 
30835     drawLayers.only = function(what) {
 
30836         var arr = [].concat(what);
 
30837         drawLayers.remove(_.difference(_.pluck(layers, 'id'), arr));
 
30841     drawLayers.remove = function(what) {
 
30842         var arr = [].concat(what);
 
30843         arr.forEach(function(id) {
 
30844             layers = _.reject(layers, 'id', id);
 
30849     drawLayers.add = function(what) {
 
30850         var arr = [].concat(what);
 
30851         arr.forEach(function(obj) {
 
30852             if ('id' in obj && 'layer' in obj) {
 
30859     drawLayers.dimensions = function(_) {
 
30860         if (!arguments.length) return svg.dimensions();
 
30862         layers.forEach(function(obj) {
 
30863             if (obj.layer.dimensions) {
 
30864                 obj.layer.dimensions(_);
 
30873 iD.svg.Lines = function(projection) {
 
30875     var highway_stack = {
 
30890     function waystack(a, b) {
 
30891         var as = 0, bs = 0;
 
30893         if (a.tags.highway) { as -= highway_stack[a.tags.highway]; }
 
30894         if (b.tags.highway) { bs -= highway_stack[b.tags.highway]; }
 
30898     return function drawLines(surface, graph, entities, filter) {
 
30899         var ways = [], pathdata = {}, onewaydata = {},
 
30900             getPath = iD.svg.Path(projection, graph);
 
30902         for (var i = 0; i < entities.length; i++) {
 
30903             var entity = entities[i],
 
30904                 outer = iD.geo.simpleMultipolygonOuterMember(entity, graph);
 
30906                 ways.push(entity.mergeTags(outer.tags));
 
30907             } else if (entity.geometry(graph) === 'line') {
 
30912         ways = ways.filter(getPath);
 
30914         pathdata = _.groupBy(ways, function(way) { return way.layer(); });
 
30916         _.forOwn(pathdata, function(v, k) {
 
30917             onewaydata[k] = _(v)
 
30918                 .filter(function(d) { return d.isOneWay(); })
 
30919                 .map(iD.svg.OneWaySegments(projection, graph, 35))
 
30924         var layergroup = surface
 
30925             .selectAll('.layer-lines')
 
30926             .selectAll('g.layergroup')
 
30927             .data(d3.range(-10, 11));
 
30931             .attr('class', function(d) { return 'layer layergroup layer' + String(d); });
 
30934         var linegroup = layergroup
 
30935             .selectAll('g.linegroup')
 
30936             .data(['shadow', 'casing', 'stroke']);
 
30940             .attr('class', function(d) { return 'layer linegroup line-' + d; });
 
30943         var lines = linegroup
 
30947                 function() { return pathdata[this.parentNode.parentNode.__data__] || []; },
 
30951         // Optimization: call simple TagClasses only on enter selection. This
 
30952         // works because iD.Entity.key is defined to include the entity v attribute.
 
30955             .attr('class', function(d) { return 'way line ' + this.parentNode.__data__ + ' ' + d.id; })
 
30956             .call(iD.svg.TagClasses());
 
30960             .attr('d', getPath)
 
30961             .call(iD.svg.TagClasses().tags(iD.svg.RelationMemberTags(graph)));
 
30967         var onewaygroup = layergroup
 
30968             .selectAll('g.onewaygroup')
 
30971         onewaygroup.enter()
 
30973             .attr('class', 'layer onewaygroup');
 
30976         var oneways = onewaygroup
 
30980                 function() { return onewaydata[this.parentNode.parentNode.__data__] || []; },
 
30981                 function(d) { return [d.id, d.index]; }
 
30986             .attr('class', 'oneway')
 
30987             .attr('marker-mid', 'url(#oneway-marker)');
 
30990             .attr('d', function(d) { return d.d; });
 
30992         if (iD.detect().ie) {
 
30993             oneways.each(function() { this.parentNode.insertBefore(this, this); });
 
31001 iD.svg.MapillaryImages = function(projection, context) {
 
31002     var debouncedRedraw = _.debounce(function () { context.pan([0,0]); }, 1000),
 
31004         layer = d3.select(null),
 
31009         if (iD.svg.MapillaryImages.initialized) return;  // run once
 
31010         iD.svg.MapillaryImages.enabled = false;
 
31011         iD.svg.MapillaryImages.initialized = true;
 
31014     function getMapillary() {
 
31015         if (iD.services.mapillary && !_mapillary) {
 
31016             _mapillary = iD.services.mapillary().on('loadedImages', debouncedRedraw);
 
31017         } else if (!iD.services.mapillary && _mapillary) {
 
31023     function showThumbnail(image) {
 
31024         var mapillary = getMapillary();
 
31025         if (!mapillary) return;
 
31027         var thumb = mapillary.selectedThumbnail(),
 
31028             posX = projection(image.loc)[0],
 
31029             width = layer.dimensions()[0],
 
31030             position = (posX < width / 2) ? 'right' : 'left';
 
31033             d3.selectAll('.layer-mapillary-images .viewfield-group, .layer-mapillary-signs .icon-sign')
 
31034                 .classed('selected', function(d) { return d.key === thumb.key; });
 
31037         mapillary.showThumbnail(image.key, position);
 
31040     function hideThumbnail() {
 
31041         d3.selectAll('.layer-mapillary-images .viewfield-group, .layer-mapillary-signs .icon-sign')
 
31042             .classed('selected', false);
 
31044         var mapillary = getMapillary();
 
31046             mapillary.hideThumbnail();
 
31050     function showLayer() {
 
31053             .style('opacity', 0)
 
31056             .style('opacity', 1)
 
31057             .each('end', debouncedRedraw);
 
31060     function hideLayer() {
 
31061         debouncedRedraw.cancel();
 
31066             .style('opacity', 0)
 
31067             .each('end', editOff);
 
31070     function editOn() {
 
31071         layer.style('display', 'block');
 
31074     function editOff() {
 
31075         layer.selectAll('.viewfield-group').remove();
 
31076         layer.style('display', 'none');
 
31079     function transform(d) {
 
31080         var t = iD.svg.PointTransform(projection)(d);
 
31081         if (d.ca) t += ' rotate(' + Math.floor(d.ca) + ',0,0)';
 
31085     function update() {
 
31086         var mapillary = getMapillary(),
 
31087             data = (mapillary ? mapillary.images(projection, layer.dimensions()) : []);
 
31089         var markers = layer.selectAll('.viewfield-group')
 
31090             .data(data, function(d) { return d.key; });
 
31093         var enter = markers.enter()
 
31095             .attr('class', 'viewfield-group');
 
31097         enter.append('path')
 
31098             .attr('class', 'viewfield')
 
31099             .attr('transform', 'scale(1.5,1.5),translate(-8, -13)')
 
31100             .attr('d', 'M 6,9 C 8,8.4 8,8.4 10,9 L 16,-2 C 12,-5 4,-5 0,-2 z');
 
31102         enter.append('circle')
 
31113             .attr('transform', transform);
 
31116     function drawImages(selection) {
 
31117         var enabled = iD.svg.MapillaryImages.enabled,
 
31118             mapillary = getMapillary();
 
31120         layer = selection.selectAll('.layer-mapillary-images')
 
31121             .data(mapillary ? [0] : []);
 
31125             .attr('class', 'layer-mapillary-images')
 
31126             .style('display', enabled ? 'block' : 'none')
 
31127             .on('click', function() {   // deselect/select
 
31128                 var mapillary = getMapillary();
 
31129                 if (!mapillary) return;
 
31130                 var d = d3.event.target.__data__,
 
31131                     thumb = mapillary.selectedThumbnail();
 
31132                 if (thumb && thumb.key === d.key) {
 
31135                     mapillary.selectedThumbnail(d);
 
31136                     context.map().centerEase(d.loc);
 
31140             .on('mouseover', function() {
 
31141                 var mapillary = getMapillary();
 
31142                 if (!mapillary) return;
 
31143                 showThumbnail(d3.event.target.__data__);
 
31145             .on('mouseout', function() {
 
31146                 var mapillary = getMapillary();
 
31147                 if (!mapillary) return;
 
31148                 var thumb = mapillary.selectedThumbnail();
 
31150                     showThumbnail(thumb);
 
31160             if (mapillary && ~~context.map().zoom() >= minZoom) {
 
31163                 mapillary.loadImages(projection, layer.dimensions());
 
31170     drawImages.enabled = function(_) {
 
31171         if (!arguments.length) return iD.svg.MapillaryImages.enabled;
 
31172         iD.svg.MapillaryImages.enabled = _;
 
31173         if (iD.svg.MapillaryImages.enabled) {
 
31181     drawImages.supported = function() {
 
31182         return !!getMapillary();
 
31185     drawImages.dimensions = function(_) {
 
31186         if (!arguments.length) return layer.dimensions();
 
31187         layer.dimensions(_);
 
31194 iD.svg.MapillarySigns = function(projection, context) {
 
31195     var debouncedRedraw = _.debounce(function () { context.pan([0,0]); }, 1000),
 
31197         layer = d3.select(null),
 
31202         if (iD.svg.MapillarySigns.initialized) return;  // run once
 
31203         iD.svg.MapillarySigns.enabled = false;
 
31204         iD.svg.MapillarySigns.initialized = true;
 
31207     function getMapillary() {
 
31208         if (iD.services.mapillary && !_mapillary) {
 
31209             _mapillary = iD.services.mapillary().on('loadedSigns', debouncedRedraw);
 
31210         } else if (!iD.services.mapillary && _mapillary) {
 
31216     function showThumbnail(image) {
 
31217         var mapillary = getMapillary();
 
31218         if (!mapillary) return;
 
31220         var thumb = mapillary.selectedThumbnail(),
 
31221             posX = projection(image.loc)[0],
 
31222             width = layer.dimensions()[0],
 
31223             position = (posX < width / 2) ? 'right' : 'left';
 
31226             d3.selectAll('.layer-mapillary-images .viewfield-group, .layer-mapillary-signs .icon-sign')
 
31227                 .classed('selected', function(d) { return d.key === thumb.key; });
 
31230         mapillary.showThumbnail(image.key, position);
 
31233     function hideThumbnail() {
 
31234         d3.selectAll('.layer-mapillary-images .viewfield-group, .layer-mapillary-signs .icon-sign')
 
31235             .classed('selected', false);
 
31237         var mapillary = getMapillary();
 
31239             mapillary.hideThumbnail();
 
31243     function showLayer() {
 
31248     function hideLayer() {
 
31249         debouncedRedraw.cancel();
 
31254     function editOn() {
 
31255         layer.style('display', 'block');
 
31258     function editOff() {
 
31259         layer.selectAll('.icon-sign').remove();
 
31260         layer.style('display', 'none');
 
31263     function update() {
 
31264         var mapillary = getMapillary(),
 
31265             data = (mapillary ? mapillary.signs(projection, layer.dimensions()) : []);
 
31267         var signs = layer.selectAll('.icon-sign')
 
31268             .data(data, function(d) { return d.key; });
 
31271         var enter = signs.enter()
 
31272             .append('foreignObject')
 
31273             .attr('class', 'icon-sign')
 
31274             .attr('width', '32px')      // for Firefox
 
31275             .attr('height', '32px');    // for Firefox
 
31278             .append('xhtml:body')
 
31279             .html(mapillary.signHTML);
 
31282             .on('click', function(d) {   // deselect/select
 
31283                 var mapillary = getMapillary();
 
31284                 if (!mapillary) return;
 
31285                 var thumb = mapillary.selectedThumbnail();
 
31286                 if (thumb && thumb.key === d.key) {
 
31289                     mapillary.selectedThumbnail(d);
 
31290                     context.map().centerEase(d.loc);
 
31294             .on('mouseover', showThumbnail)
 
31295             .on('mouseout', function() {
 
31296                 var mapillary = getMapillary();
 
31297                 if (!mapillary) return;
 
31298                 var thumb = mapillary.selectedThumbnail();
 
31300                     showThumbnail(thumb);
 
31312             .attr('transform', iD.svg.PointTransform(projection));
 
31315     function drawSigns(selection) {
 
31316         var enabled = iD.svg.MapillarySigns.enabled,
 
31317             mapillary = getMapillary();
 
31319         layer = selection.selectAll('.layer-mapillary-signs')
 
31320             .data(mapillary ? [0] : []);
 
31324             .attr('class', 'layer-mapillary-signs')
 
31325             .style('display', enabled ? 'block' : 'none')
 
31326             .attr('transform', 'translate(-16, -16)');  // center signs on loc
 
31332             if (mapillary && ~~context.map().zoom() >= minZoom) {
 
31335                 mapillary.loadSigns(context, projection, layer.dimensions());
 
31342     drawSigns.enabled = function(_) {
 
31343         if (!arguments.length) return iD.svg.MapillarySigns.enabled;
 
31344         iD.svg.MapillarySigns.enabled = _;
 
31345         if (iD.svg.MapillarySigns.enabled) {
 
31353     drawSigns.supported = function() {
 
31354         var mapillary = getMapillary();
 
31355         return (mapillary && mapillary.signsSupported());
 
31358     drawSigns.dimensions = function(_) {
 
31359         if (!arguments.length) return layer.dimensions();
 
31360         layer.dimensions(_);
 
31367 iD.svg.Midpoints = function(projection, context) {
 
31368     return function drawMidpoints(surface, graph, entities, filter, extent) {
 
31369         var poly = extent.polygon(),
 
31372         for (var i = 0; i < entities.length; i++) {
 
31373             var entity = entities[i];
 
31375             if (entity.type !== 'way')
 
31377             if (!filter(entity))
 
31379             if (context.selectedIDs().indexOf(entity.id) < 0)
 
31382             var nodes = graph.childNodes(entity);
 
31383             for (var j = 0; j < nodes.length - 1; j++) {
 
31387                     id = [a.id, b.id].sort().join('-');
 
31389                 if (midpoints[id]) {
 
31390                     midpoints[id].parents.push(entity);
 
31392                     if (iD.geo.euclideanDistance(projection(a.loc), projection(b.loc)) > 40) {
 
31393                         var point = iD.geo.interp(a.loc, b.loc, 0.5),
 
31396                         if (extent.intersects(point)) {
 
31399                             for (var k = 0; k < 4; k++) {
 
31400                                 point = iD.geo.lineIntersection([a.loc, b.loc], [poly[k], poly[k+1]]);
 
31402                                     iD.geo.euclideanDistance(projection(a.loc), projection(point)) > 20 &&
 
31403                                     iD.geo.euclideanDistance(projection(b.loc), projection(point)) > 20)
 
31416                                 edge: [a.id, b.id],
 
31425         function midpointFilter(d) {
 
31426             if (midpoints[d.id])
 
31429             for (var i = 0; i < d.parents.length; i++)
 
31430                 if (filter(d.parents[i]))
 
31436         var groups = surface.selectAll('.layer-hit').selectAll('g.midpoint')
 
31437             .filter(midpointFilter)
 
31438             .data(_.values(midpoints), function(d) { return d.id; });
 
31440         var enter = groups.enter()
 
31441             .insert('g', ':first-child')
 
31442             .attr('class', 'midpoint');
 
31444         enter.append('polygon')
 
31445             .attr('points', '-6,8 10,0 -6,-8')
 
31446             .attr('class', 'shadow');
 
31448         enter.append('polygon')
 
31449             .attr('points', '-3,4 5,0 -3,-4')
 
31450             .attr('class', 'fill');
 
31453             .attr('transform', function(d) {
 
31454                 var translate = iD.svg.PointTransform(projection),
 
31455                     a = context.entity(d.edge[0]),
 
31456                     b = context.entity(d.edge[1]),
 
31457                     angle = Math.round(iD.geo.angle(a, b, projection) * (180 / Math.PI));
 
31458                 return translate(d) + ' rotate(' + angle + ')';
 
31460             .call(iD.svg.TagClasses().tags(
 
31461                 function(d) { return d.parents[0].tags; }
 
31464         // Propagate data bindings.
 
31465         groups.select('polygon.shadow');
 
31466         groups.select('polygon.fill');
 
31472 iD.svg.Osm = function() {
 
31473     return function drawOsm(selection) {
 
31474         var layers = selection.selectAll('.layer-osm')
 
31475             .data(['areas', 'lines', 'hit', 'halo', 'label']);
 
31477         layers.enter().append('g')
 
31478             .attr('class', function(d) { return 'layer-osm layer-' + d; });
 
31481 iD.svg.Points = function(projection, context) {
 
31482     function markerPath(selection, klass) {
 
31484             .attr('class', klass)
 
31485             .attr('transform', 'translate(-8, -23)')
 
31486             .attr('d', 'M 17,8 C 17,13 11,21 8.5,23.5 C 6,21 0,13 0,8 C 0,4 4,-0.5 8.5,-0.5 C 13,-0.5 17,4 17,8 z');
 
31489     function sortY(a, b) {
 
31490         return b.loc[1] - a.loc[1];
 
31493     return function drawPoints(surface, graph, entities, filter) {
 
31494         var wireframe = surface.classed('fill-wireframe'),
 
31495             points = wireframe ? [] : _.filter(entities, function(e) {
 
31496                 return e.geometry(graph) === 'point';
 
31499         points.sort(sortY);
 
31501         var groups = surface.selectAll('.layer-hit').selectAll('g.point')
 
31503             .data(points, iD.Entity.key);
 
31505         var group = groups.enter()
 
31507             .attr('class', function(d) { return 'node point ' + d.id; })
 
31510         group.append('path')
 
31511             .call(markerPath, 'shadow');
 
31513         group.append('path')
 
31514             .call(markerPath, 'stroke');
 
31516         group.append('use')
 
31517             .attr('transform', 'translate(-6, -20)')
 
31518             .attr('class', 'icon')
 
31519             .attr('width', '12px')
 
31520             .attr('height', '12px');
 
31522         groups.attr('transform', iD.svg.PointTransform(projection))
 
31523             .call(iD.svg.TagClasses());
 
31525         // Selecting the following implicitly
 
31526         // sets the data (point entity) on the element
 
31527         groups.select('.shadow');
 
31528         groups.select('.stroke');
 
31529         groups.select('.icon')
 
31530             .attr('xlink:href', function(entity) {
 
31531                 var preset = context.presets().match(entity, graph);
 
31532                 return preset.icon ? '#' + preset.icon + '-12' : '';
 
31539 iD.svg.TagClasses = function() {
 
31541             'building', 'highway', 'railway', 'waterway', 'aeroway',
 
31542             'motorway', 'boundary', 'power', 'amenity', 'natural', 'landuse',
 
31546             'proposed', 'construction', 'disused', 'abandoned', 'dismantled',
 
31547             'razed', 'demolished', 'obliterated'
 
31550             'oneway', 'bridge', 'tunnel', 'embankment', 'cutting', 'barrier',
 
31551             'surface', 'tracktype', 'crossing'
 
31553         tagClassRe = /^tag-/,
 
31554         tags = function(entity) { return entity.tags; };
 
31557     var tagClasses = function(selection) {
 
31558         selection.each(function tagClassesEach(entity) {
 
31559             var value = this.className,
 
31560                 classes, primary, status;
 
31562             if (value.baseVal !== undefined) value = value.baseVal;
 
31564             classes = value.trim().split(/\s+/).filter(function(name) {
 
31565                 return name.length && !tagClassRe.test(name);
 
31568             var t = tags(entity), i, k, v;
 
31570             // pick at most one primary classification tag..
 
31571             for (i = 0; i < primaries.length; i++) {
 
31574                 if (!v || v === 'no') continue;
 
31577                 if (statuses.indexOf(v) !== -1) {   // e.g. `railway=abandoned`
 
31579                     classes += ' tag-' + k;
 
31581                     classes += ' tag-' + k + ' tag-' + k + '-' + v;
 
31587             // add at most one status tag, only if relates to primary tag..
 
31589                 for (i = 0; i < statuses.length; i++) {
 
31592                     if (!v || v === 'no') continue;
 
31594                     if (v === 'yes') {   // e.g. `railway=rail + abandoned=yes`
 
31597                     else if (primary && primary === v) {  // e.g. `railway=rail + abandoned=railway`
 
31599                     } else if (!primary && primaries.indexOf(v) !== -1) {  // e.g. `abandoned=railway`
 
31602                         classes += ' tag-' + v;
 
31603                     }  // else ignore e.g.  `highway=path + abandoned=railway`
 
31610                 classes += ' tag-status tag-status-' + status;
 
31613             // add any secondary (structure) tags
 
31614             for (i = 0; i < secondaries.length; i++) {
 
31615                 k = secondaries[i];
 
31617                 if (!v || v === 'no') continue;
 
31618                 classes += ' tag-' + k + ' tag-' + k + '-' + v;
 
31621             // For highways, look for surface tagging..
 
31622             if (primary === 'highway') {
 
31623                 var paved = (t.highway !== 'track');
 
31626                     if (k in iD.pavedTags) {
 
31627                         paved = !!iD.pavedTags[k][v];
 
31632                     classes += ' tag-unpaved';
 
31636             classes = classes.trim();
 
31638             if (classes !== value) {
 
31639                 d3.select(this).attr('class', classes);
 
31644     tagClasses.tags = function(_) {
 
31645         if (!arguments.length) return tags;
 
31652 iD.svg.Turns = function(projection) {
 
31653     return function drawTurns(surface, graph, turns) {
 
31654         function key(turn) {
 
31655             return [turn.from.node + turn.via.node + turn.to.node].join('-');
 
31658         function icon(turn) {
 
31659             var u = turn.u ? '-u' : '';
 
31660             if (!turn.restriction)
 
31661                 return '#turn-yes' + u;
 
31662             var restriction = graph.entity(turn.restriction).tags.restriction;
 
31664                 (!turn.indirect_restriction && /^only_/.test(restriction) ? 'only' : 'no') + u;
 
31667         var groups = surface.selectAll('.layer-hit').selectAll('g.turn')
 
31671         var enter = groups.enter().append('g')
 
31672             .attr('class', 'turn');
 
31674         var nEnter = enter.filter(function (turn) { return !turn.u; });
 
31676         nEnter.append('rect')
 
31677             .attr('transform', 'translate(-22, -12)')
 
31678             .attr('width', '44')
 
31679             .attr('height', '24');
 
31681         nEnter.append('use')
 
31682             .attr('transform', 'translate(-22, -12)')
 
31683             .attr('width', '44')
 
31684             .attr('height', '24');
 
31687         var uEnter = enter.filter(function (turn) { return turn.u; });
 
31689         uEnter.append('circle')
 
31692         uEnter.append('use')
 
31693             .attr('transform', 'translate(-16, -16)')
 
31694             .attr('width', '32')
 
31695             .attr('height', '32');
 
31700             .attr('transform', function (turn) {
 
31701                 var v = graph.entity(turn.via.node),
 
31702                     t = graph.entity(turn.to.node),
 
31703                     a = iD.geo.angle(v, t, projection),
 
31704                     p = projection(v.loc),
 
31705                     r = turn.u ? 0 : 60;
 
31707                 return 'translate(' + (r * Math.cos(a) + p[0]) + ',' + (r * Math.sin(a) + p[1]) + ') ' +
 
31708                     'rotate(' + a * 180 / Math.PI + ')';
 
31711         groups.select('use')
 
31712             .attr('xlink:href', icon);
 
31714         groups.select('rect');
 
31715         groups.select('circle');
 
31725 iD.svg.Vertices = function(projection, context) {
 
31727         //       z16-, z17, z18+, tagged
 
31728         shadow: [6,    7.5,   7.5,  11.5],
 
31729         stroke: [2.5,  3.5,   3.5,  7],
 
31730         fill:   [1,    1.5,   1.5,  1.5]
 
31735     function siblingAndChildVertices(ids, graph, extent) {
 
31738         function addChildVertices(entity) {
 
31739             if (!context.features().isHiddenFeature(entity, graph, entity.geometry(graph))) {
 
31741                 if (entity.type === 'way') {
 
31742                     for (i = 0; i < entity.nodes.length; i++) {
 
31743                         addChildVertices(graph.entity(entity.nodes[i]));
 
31745                 } else if (entity.type === 'relation') {
 
31746                     for (i = 0; i < entity.members.length; i++) {
 
31747                         var member = context.hasEntity(entity.members[i].id);
 
31749                             addChildVertices(member);
 
31752                 } else if (entity.intersects(extent, graph)) {
 
31753                     vertices[entity.id] = entity;
 
31758         ids.forEach(function(id) {
 
31759             var entity = context.hasEntity(id);
 
31760             if (entity && entity.type === 'node') {
 
31761                 vertices[entity.id] = entity;
 
31762                 context.graph().parentWays(entity).forEach(function(entity) {
 
31763                     addChildVertices(entity);
 
31765             } else if (entity) {
 
31766                 addChildVertices(entity);
 
31773     function draw(selection, vertices, klass, graph, zoom) {
 
31775             z = (zoom < 17 ? 0 : zoom < 18 ? 1 : 2);
 
31777         var groups = selection
 
31778             .data(vertices, iD.Entity.key);
 
31780         function icon(entity) {
 
31781             if (entity.id in icons) return icons[entity.id];
 
31783                 entity.hasInterestingTags() &&
 
31784                 context.presets().match(entity, graph).icon;
 
31785             return icons[entity.id];
 
31788         function setClass(klass) {
 
31789             return function(entity) {
 
31790                 this.setAttribute('class', 'node vertex ' + klass + ' ' + entity.id);
 
31794         function setAttributes(selection) {
 
31795             ['shadow','stroke','fill'].forEach(function(klass) {
 
31796                 var rads = radiuses[klass];
 
31797                 selection.selectAll('.' + klass)
 
31798                     .each(function(entity) {
 
31799                         var i = z && icon(entity),
 
31801                             r = rads[i ? 3 : z];
 
31802                         this.setAttribute('cx', c);
 
31803                         this.setAttribute('cy', -c);
 
31804                         this.setAttribute('r', r);
 
31805                         if (i && klass === 'fill') {
 
31806                             this.setAttribute('visibility', 'hidden');
 
31808                             this.removeAttribute('visibility');
 
31813             selection.selectAll('use')
 
31816                         this.removeAttribute('visibility');
 
31818                         this.setAttribute('visibility', 'hidden');
 
31823         var enter = groups.enter()
 
31825             .attr('class', function(d) { return 'node vertex ' + klass + ' ' + d.id; });
 
31827         enter.append('circle')
 
31828             .each(setClass('shadow'));
 
31830         enter.append('circle')
 
31831             .each(setClass('stroke'));
 
31833         // Vertices with icons get a `use`.
 
31834         enter.filter(function(d) { return icon(d); })
 
31836             .attr('transform', 'translate(-6, -6)')
 
31837             .attr('xlink:href', function(d) { return '#' + icon(d) + '-12'; })
 
31838             .attr('width', '12px')
 
31839             .attr('height', '12px')
 
31840             .each(setClass('icon'));
 
31842         // Vertices with tags get a fill.
 
31843         enter.filter(function(d) { return d.hasInterestingTags(); })
 
31845             .each(setClass('fill'));
 
31848             .attr('transform', iD.svg.PointTransform(projection))
 
31849             .classed('shared', function(entity) { return graph.isShared(entity); })
 
31850             .call(setAttributes);
 
31856     function drawVertices(surface, graph, entities, filter, extent, zoom) {
 
31857         var selected = siblingAndChildVertices(context.selectedIDs(), graph, extent),
 
31858             wireframe = surface.classed('fill-wireframe'),
 
31861         for (var i = 0; i < entities.length; i++) {
 
31862             var entity = entities[i],
 
31863                 geometry = entity.geometry(graph);
 
31865             if (wireframe && geometry === 'point') {
 
31866                 vertices.push(entity);
 
31870             if (geometry !== 'vertex')
 
31873             if (entity.id in selected ||
 
31874                 entity.hasInterestingTags() ||
 
31875                 entity.isIntersection(graph)) {
 
31876                 vertices.push(entity);
 
31880         surface.selectAll('.layer-hit').selectAll('g.vertex.vertex-persistent')
 
31882             .call(draw, vertices, 'vertex-persistent', graph, zoom);
 
31884         drawHover(surface, graph, extent, zoom);
 
31887     function drawHover(surface, graph, extent, zoom) {
 
31888         var hovered = hover ? siblingAndChildVertices([hover.id], graph, extent) : {};
 
31890         surface.selectAll('.layer-hit').selectAll('g.vertex.vertex-hover')
 
31891             .call(draw, d3.values(hovered), 'vertex-hover', graph, zoom);
 
31894     drawVertices.drawHover = function(surface, graph, target, extent, zoom) {
 
31895         if (target === hover) return;
 
31897         drawHover(surface, graph, extent, zoom);
 
31900     return drawVertices;
 
31902 iD.ui = function(context) {
 
31903     function render(container) {
 
31904         var map = context.map();
 
31906         if (iD.detect().opera) container.classed('opera', true);
 
31908         var hash = iD.behavior.Hash(context);
 
31912         if (!hash.hadHash) {
 
31913             map.centerZoom([0, 0], 2);
 
31916         container.append('svg')
 
31917             .attr('id', 'defs')
 
31918             .call(iD.svg.Defs(context));
 
31920         container.append('div')
 
31921             .attr('id', 'sidebar')
 
31922             .attr('class', 'col4')
 
31925         var content = container.append('div')
 
31926             .attr('id', 'content');
 
31928         var bar = content.append('div')
 
31930             .attr('class', 'fillD');
 
31932         content.append('div')
 
31937             .call(iD.ui.MapInMap(context));
 
31939         content.append('div')
 
31940             .call(iD.ui.Info(context));
 
31943             .attr('class', 'spacer col4');
 
31945         var limiter = bar.append('div')
 
31946             .attr('class', 'limiter');
 
31948         limiter.append('div')
 
31949             .attr('class', 'button-wrap joined col3')
 
31950             .call(iD.ui.Modes(context), limiter);
 
31952         limiter.append('div')
 
31953             .attr('class', 'button-wrap joined col1')
 
31954             .call(iD.ui.UndoRedo(context));
 
31956         limiter.append('div')
 
31957             .attr('class', 'button-wrap col1')
 
31958             .call(iD.ui.Save(context));
 
31961             .attr('class', 'full-screen')
 
31962             .call(iD.ui.FullScreen(context));
 
31965             .attr('class', 'spinner')
 
31966             .call(iD.ui.Spinner(context));
 
31968         var controls = bar.append('div')
 
31969             .attr('class', 'map-controls');
 
31971         controls.append('div')
 
31972             .attr('class', 'map-control zoombuttons')
 
31973             .call(iD.ui.Zoom(context));
 
31975         controls.append('div')
 
31976             .attr('class', 'map-control geolocate-control')
 
31977             .call(iD.ui.Geolocate(map));
 
31979         controls.append('div')
 
31980             .attr('class', 'map-control background-control')
 
31981             .call(iD.ui.Background(context));
 
31983         controls.append('div')
 
31984             .attr('class', 'map-control map-data-control')
 
31985             .call(iD.ui.MapData(context));
 
31987         controls.append('div')
 
31988             .attr('class', 'map-control help-control')
 
31989             .call(iD.ui.Help(context));
 
31991         var about = content.append('div')
 
31992             .attr('id', 'about');
 
31994         about.append('div')
 
31995             .attr('id', 'attrib')
 
31996             .call(iD.ui.Attribution(context));
 
31998         var footer = about.append('div')
 
31999             .attr('id', 'footer')
 
32000             .attr('class', 'fillD');
 
32002         footer.append('div')
 
32003             .attr('class', 'api-status')
 
32004             .call(iD.ui.Status(context));
 
32006         footer.append('div')
 
32007             .attr('id', 'scale-block')
 
32008             .call(iD.ui.Scale(context));
 
32010         var aboutList = footer.append('div')
 
32011             .attr('id', 'info-block')
 
32013             .attr('id', 'about-list');
 
32015         if (!context.embed()) {
 
32016             aboutList.call(iD.ui.Account(context));
 
32019         aboutList.append('li')
 
32021             .attr('target', '_blank')
 
32022             .attr('tabindex', -1)
 
32023             .attr('href', 'https://github.com/openstreetmap/iD')
 
32026         var issueLinks = aboutList.append('li');
 
32028         issueLinks.append('a')
 
32029             .attr('target', '_blank')
 
32030             .attr('tabindex', -1)
 
32031             .attr('href', 'https://github.com/openstreetmap/iD/issues')
 
32032             .call(iD.svg.Icon('#icon-bug', 'light'))
 
32033             .call(bootstrap.tooltip()
 
32034                 .title(t('report_a_bug'))
 
32038         issueLinks.append('a')
 
32039             .attr('target', '_blank')
 
32040             .attr('tabindex', -1)
 
32041             .attr('href', 'https://github.com/openstreetmap/iD/blob/master/CONTRIBUTING.md#translating')
 
32042             .call(iD.svg.Icon('#icon-translate', 'light'))
 
32043             .call(bootstrap.tooltip()
 
32044                 .title(t('help_translate'))
 
32048         aboutList.append('li')
 
32049             .attr('class', 'feature-warning')
 
32050             .attr('tabindex', -1)
 
32051             .call(iD.ui.FeatureInfo(context));
 
32053         aboutList.append('li')
 
32054             .attr('class', 'user-list')
 
32055             .attr('tabindex', -1)
 
32056             .call(iD.ui.Contributors(context));
 
32058         window.onbeforeunload = function() {
 
32059             return context.save();
 
32062         window.onunload = function() {
 
32063             context.history().unlock();
 
32066         var mapDimensions = map.dimensions();
 
32068         d3.select(window).on('resize.editor', function() {
 
32069             mapDimensions = content.dimensions(null);
 
32070             map.dimensions(mapDimensions);
 
32074             return function() {
 
32075                 d3.event.preventDefault();
 
32076                 if (!context.inIntro()) context.pan(d);
 
32083         var keybinding = d3.keybinding('main')
 
32084             .on('⌫', function() { d3.event.preventDefault(); })
 
32085             .on('←', pan([pa, 0]))
 
32086             .on('↑', pan([0, pa]))
 
32087             .on('→', pan([-pa, 0]))
 
32088             .on('↓', pan([0, -pa]))
 
32089             .on('⇧←', pan([mapDimensions[0], 0]))
 
32090             .on('⇧↑', pan([0, mapDimensions[1]]))
 
32091             .on('⇧→', pan([-mapDimensions[0], 0]))
 
32092             .on('⇧↓', pan([0, -mapDimensions[1]]))
 
32093             .on(iD.ui.cmd('⌘←'), pan([mapDimensions[0], 0]))
 
32094             .on(iD.ui.cmd('⌘↑'), pan([0, mapDimensions[1]]))
 
32095             .on(iD.ui.cmd('⌘→'), pan([-mapDimensions[0], 0]))
 
32096             .on(iD.ui.cmd('⌘↓'), pan([0, -mapDimensions[1]]));
 
32098         d3.select(document)
 
32101         context.enter(iD.modes.Browse(context));
 
32103         context.container()
 
32104             .call(iD.ui.Splash(context))
 
32105             .call(iD.ui.Restore(context));
 
32107         var authenticating = iD.ui.Loading(context)
 
32108             .message(t('loading_auth'));
 
32110         context.connection()
 
32111             .on('authenticating.ui', function() {
 
32112                 context.container()
 
32113                     .call(authenticating);
 
32115             .on('authenticated.ui', function() {
 
32116                 authenticating.close();
 
32120     function ui(container) {
 
32121         context.container(container);
 
32122         context.loadLocale(function() {
 
32127     ui.sidebar = iD.ui.Sidebar(context);
 
32132 iD.ui.tooltipHtml = function(text, key) {
 
32133     var s = '<span>' + text + '</span>';
 
32135         s += '<div class="keyhint-wrap">' +
 
32136             '<span> ' + (t('tooltip_keyhint')) + ' </span>' +
 
32137             '<span class="keyhint"> ' + key + '</span></div>';
 
32141 iD.ui.Account = function(context) {
 
32142     var connection = context.connection();
 
32144     function update(selection) {
 
32145         if (!connection.authenticated()) {
 
32146             selection.selectAll('#userLink, #logoutLink')
 
32147                 .classed('hide', true);
 
32151         connection.userDetails(function(err, details) {
 
32152             var userLink = selection.select('#userLink'),
 
32153                 logoutLink = selection.select('#logoutLink');
 
32156             logoutLink.html('');
 
32160             selection.selectAll('#userLink, #logoutLink')
 
32161                 .classed('hide', false);
 
32164             userLink.append('a')
 
32165                 .attr('href', connection.userURL(details.display_name))
 
32166                 .attr('target', '_blank');
 
32168             // Add thumbnail or dont
 
32169             if (details.image_url) {
 
32170                 userLink.append('img')
 
32171                     .attr('class', 'icon pre-text user-icon')
 
32172                     .attr('src', details.image_url);
 
32175                     .call(iD.svg.Icon('#icon-avatar', 'pre-text light'));
 
32179             userLink.append('span')
 
32180                 .attr('class', 'label')
 
32181                 .text(details.display_name);
 
32183             logoutLink.append('a')
 
32184                 .attr('class', 'logout')
 
32187                 .on('click.logout', function() {
 
32188                     d3.event.preventDefault();
 
32189                     connection.logout();
 
32194     return function(selection) {
 
32195         selection.append('li')
 
32196             .attr('id', 'logoutLink')
 
32197             .classed('hide', true);
 
32199         selection.append('li')
 
32200             .attr('id', 'userLink')
 
32201             .classed('hide', true);
 
32203         connection.on('auth.account', function() { update(selection); });
 
32207 iD.ui.Attribution = function(context) {
 
32210     function attribution(data, klass) {
 
32211         var div = selection.selectAll('.' + klass)
 
32216             .attr('class', klass);
 
32218         var background = div.selectAll('.attribution')
 
32219             .data(data, function(d) { return d.name(); });
 
32223             .attr('class', 'attribution')
 
32224             .each(function(d) {
 
32225                 if (d.terms_html) {
 
32227                         .html(d.terms_html);
 
32231                 var source = d.terms_text || d.id || d.name();
 
32234                     source = '<img class="source-image" src="' + context.imagePath(d.logo) + '">';
 
32240                         .attr('href', d.terms_url)
 
32241                         .attr('target', '_blank')
 
32252         var copyright = background.selectAll('.copyright-notice')
 
32253             .data(function(d) {
 
32254                 var notice = d.copyrightNotices(context.map().zoom(), context.map().extent());
 
32255                 return notice ? [notice] : [];
 
32260             .attr('class', 'copyright-notice');
 
32262         copyright.text(String);
 
32268     function update() {
 
32269         attribution([context.background().baseLayerSource()], 'base-layer-attribution');
 
32270         attribution(context.background().overlayLayerSources().filter(function (s) {
 
32271             return s.validZoom(context.map().zoom());
 
32272         }), 'overlay-layer-attribution');
 
32275     return function(select) {
 
32276         selection = select;
 
32278         context.background()
 
32279             .on('change.attribution', update);
 
32282             .on('move.attribution', _.throttle(update, 400, {leading: false}));
 
32287 iD.ui.Background = function(context) {
 
32289         opacities = [1, 0.75, 0.5, 0.25],
 
32293             ['right', [-1, 0]],
 
32294             ['bottom', [0, 1]]],
 
32295         opacityDefault = (context.storage('background-opacity') !== null) ?
 
32296             (+context.storage('background-opacity')) : 1.0,
 
32297         customTemplate = context.storage('background-custom-template') || '';
 
32299     // Can be 0 from <1.3.0 use or due to issue #1923.
 
32300     if (opacityDefault === 0) opacityDefault = 1.0;
 
32302     function background(selection) {
 
32304         function sortSources(a, b) {
 
32305             return a.best() ? -1
 
32307                 : a.id === 'none' ? 1
 
32308                 : b.id === 'none' ? -1
 
32309                 : d3.ascending(a, b);
 
32312         function setOpacity(d) {
 
32313             var bg = context.container().selectAll('.layer-background')
 
32315                 .style('opacity', d)
 
32316                 .attr('data-opacity', d);
 
32318             if (!iD.detect().opera) {
 
32319                 iD.util.setTransform(bg, 0, 0);
 
32322             opacityList.selectAll('li')
 
32323                 .classed('active', function(_) { return _ === d; });
 
32325             context.storage('background-opacity', d);
 
32328         function selectLayer() {
 
32329             function active(d) {
 
32330                 return context.background().showsLayer(d);
 
32333             content.selectAll('.layer, .custom_layer')
 
32334                 .classed('active', active)
 
32335                 .selectAll('input')
 
32336                 .property('checked', active);
 
32339         function clickSetSource(d) {
 
32340             d3.event.preventDefault();
 
32341             context.background().baseLayerSource(d);
 
32345         function editCustom() {
 
32346             d3.event.preventDefault();
 
32347             var template = window.prompt(t('background.custom_prompt'), customTemplate);
 
32349                 template.indexOf('google.com') !== -1 ||
 
32350                 template.indexOf('googleapis.com') !== -1 ||
 
32351                 template.indexOf('google.ru') !== -1) {
 
32355             setCustom(template);
 
32358         function setCustom(template) {
 
32359             context.background().baseLayerSource(iD.BackgroundSource.Custom(template));
 
32361             context.storage('background-custom-template', template);
 
32364         function clickSetOverlay(d) {
 
32365             d3.event.preventDefault();
 
32366             context.background().toggleOverlayLayer(d);
 
32370         function drawList(layerList, type, change, filter) {
 
32371             var sources = context.background()
 
32372                 .sources(context.map().extent())
 
32375             var layerLinks = layerList.selectAll('li.layer')
 
32376                 .data(sources, function(d) { return d.name(); })
 
32377                 .sort(sortSources);
 
32379             var enter = layerLinks.enter()
 
32380                 .insert('li', '.custom_layer')
 
32381                 .attr('class', 'layer')
 
32382                 .classed('best', function(d) { return d.best(); });
 
32384             // only set tooltips for layers with tooltips
 
32385             enter.filter(function(d) { return d.description; })
 
32386                 .call(bootstrap.tooltip()
 
32387                     .title(function(d) { return d.description; })
 
32388                     .placement('top'));
 
32390             enter.filter(function(d) { return d.best(); })
 
32392                 .attr('class', 'best')
 
32393                 .call(bootstrap.tooltip()
 
32394                     .title(t('background.best_imagery'))
 
32395                     .placement('left'))
 
32399             var label = enter.append('label');
 
32401             label.append('input')
 
32402                 .attr('type', type)
 
32403                 .attr('name', 'layers')
 
32404                 .on('change', change);
 
32406             label.append('span')
 
32407                 .text(function(d) { return d.name(); });
 
32412             layerList.style('display', layerList.selectAll('li.layer').data().length > 0 ? 'block' : 'none');
 
32415         function update() {
 
32416             backgroundList.call(drawList, 'radio', clickSetSource, function(d) { return !d.overlay; });
 
32417             overlayList.call(drawList, 'checkbox', clickSetOverlay, function(d) { return d.overlay; });
 
32421             var source = context.background().baseLayerSource();
 
32422             if (source.id === 'custom') {
 
32423                 customTemplate = source.template;
 
32427         function clickNudge(d) {
 
32428             var timeout = window.setTimeout(function() {
 
32429                     interval = window.setInterval(nudge, 100);
 
32433             d3.select(this).on('mouseup', function() {
 
32434                 window.clearInterval(interval);
 
32435                 window.clearTimeout(timeout);
 
32440                 var offset = context.background()
 
32441                     .nudge(d[1], context.map().zoom())
 
32443                 resetButton.classed('disabled', offset[0] === 0 && offset[1] === 0);
 
32447         function hide() { setVisible(false); }
 
32449         function toggle() {
 
32450             if (d3.event) d3.event.preventDefault();
 
32451             tooltip.hide(button);
 
32452             setVisible(!button.classed('active'));
 
32455         function setVisible(show) {
 
32456             if (show !== shown) {
 
32457                 button.classed('active', show);
 
32461                     selection.on('mousedown.background-inside', function() {
 
32462                         return d3.event.stopPropagation();
 
32464                     content.style('display', 'block')
 
32465                         .style('right', '-300px')
 
32468                         .style('right', '0px');
 
32470                     content.style('display', 'block')
 
32471                         .style('right', '0px')
 
32474                         .style('right', '-300px')
 
32475                         .each('end', function() {
 
32476                             d3.select(this).style('display', 'none');
 
32478                     selection.on('mousedown.background-inside', null);
 
32484         var content = selection.append('div')
 
32485                 .attr('class', 'fillL map-overlay col3 content hide'),
 
32486             tooltip = bootstrap.tooltip()
 
32489                 .title(iD.ui.tooltipHtml(t('background.description'), key)),
 
32490             button = selection.append('button')
 
32491                 .attr('tabindex', -1)
 
32492                 .on('click', toggle)
 
32493                 .call(iD.svg.Icon('#icon-layers', 'light'))
 
32497         var opa = content.append('div')
 
32498                 .attr('class', 'opacity-options-wrapper');
 
32501             .text(t('background.title'));
 
32503         var opacityList = opa.append('ul')
 
32504             .attr('class', 'opacity-options');
 
32506         opacityList.selectAll('div.opacity')
 
32510             .attr('data-original-title', function(d) {
 
32511                 return t('background.percent_brightness', { opacity: (d * 100) });
 
32513             .on('click.set-opacity', setOpacity)
 
32514             .html('<div class="select-box"></div>')
 
32515             .call(bootstrap.tooltip()
 
32516                 .placement('left'))
 
32518             .attr('class', 'opacity')
 
32519             .style('opacity', function(d) { return 1.25 - d; });
 
32521         var backgroundList = content.append('ul')
 
32522             .attr('class', 'layer-list');
 
32524         var custom = backgroundList.append('li')
 
32525             .attr('class', 'custom_layer')
 
32526             .datum(iD.BackgroundSource.Custom());
 
32528         custom.append('button')
 
32529             .attr('class', 'layer-browse')
 
32530             .call(bootstrap.tooltip()
 
32531                 .title(t('background.custom_button'))
 
32532                 .placement('left'))
 
32533             .on('click', editCustom)
 
32534             .call(iD.svg.Icon('#icon-search'));
 
32536         var label = custom.append('label');
 
32538         label.append('input')
 
32539             .attr('type', 'radio')
 
32540             .attr('name', 'layers')
 
32541             .on('change', function () {
 
32542                 if (customTemplate) {
 
32543                     setCustom(customTemplate);
 
32549         label.append('span')
 
32550             .text(t('background.custom'));
 
32552         content.append('div')
 
32553           .attr('class', 'imagery-faq')
 
32555           .attr('target', '_blank')
 
32556           .attr('tabindex', -1)
 
32557           .call(iD.svg.Icon('#icon-out-link', 'inline'))
 
32558           .attr('href', 'https://github.com/openstreetmap/iD/blob/master/FAQ.md#how-can-i-report-an-issue-with-background-imagery')
 
32560           .text(t('background.imagery_source_faq'));
 
32562         var overlayList = content.append('ul')
 
32563             .attr('class', 'layer-list');
 
32565         var controls = content.append('div')
 
32566             .attr('class', 'controls-list');
 
32568         var minimapLabel = controls
 
32570             .call(bootstrap.tooltip()
 
32572                 .title(iD.ui.tooltipHtml(t('background.minimap.tooltip'), '/'))
 
32576         minimapLabel.classed('minimap-toggle', true)
 
32578             .attr('type', 'checkbox')
 
32579             .on('change', function() {
 
32580                 iD.ui.MapInMap.toggle();
 
32581                 d3.event.preventDefault();
 
32584         minimapLabel.append('span')
 
32585             .text(t('background.minimap.description'));
 
32587         var adjustments = content.append('div')
 
32588             .attr('class', 'adjustments');
 
32590         adjustments.append('a')
 
32591             .text(t('background.fix_misalignment'))
 
32593             .classed('hide-toggle', true)
 
32594             .classed('expanded', false)
 
32595             .on('click', function() {
 
32596                 var exp = d3.select(this).classed('expanded');
 
32597                 nudgeContainer.style('display', exp ? 'none' : 'block');
 
32598                 d3.select(this).classed('expanded', !exp);
 
32599                 d3.event.preventDefault();
 
32602         var nudgeContainer = adjustments.append('div')
 
32603             .attr('class', 'nudge-container cf')
 
32604             .style('display', 'none');
 
32606         nudgeContainer.selectAll('button')
 
32607             .data(directions).enter()
 
32609             .attr('class', function(d) { return d[0] + ' nudge'; })
 
32610             .on('mousedown', clickNudge);
 
32612         var resetButton = nudgeContainer
 
32614             .attr('class', 'reset disabled')
 
32615             .on('click', function () {
 
32616                 context.background().offset([0, 0]);
 
32617                 resetButton.classed('disabled', true);
 
32619             .call(iD.svg.Icon('#icon-undo'));
 
32622             .on('move.background-update', _.debounce(update, 1000));
 
32624         context.background()
 
32625             .on('change.background-update', update);
 
32628         setOpacity(opacityDefault);
 
32630         var keybinding = d3.keybinding('background')
 
32635         d3.select(document)
 
32638         context.surface().on('mousedown.background-outside', hide);
 
32639         context.container().on('mousedown.background-outside', hide);
 
32644 // Translate a MacOS key command into the appropriate Windows/Linux equivalent.
 
32645 // For example, ⌘Z -> Ctrl+Z
 
32646 iD.ui.cmd = function(code) {
 
32647     if (iD.detect().os === 'mac') {
 
32651     if (iD.detect().os === 'win') {
 
32652         if (code === '⌘⇧Z') return 'Ctrl+Y';
 
32664     for (var i = 0; i < code.length; i++) {
 
32665         if (code[i] in replacements) {
 
32666             result += replacements[code[i]] + '+';
 
32674 iD.ui.Commit = function(context) {
 
32675     var dispatch = d3.dispatch('cancel', 'save');
 
32677     function commit(selection) {
 
32678         var changes = context.history().changes(),
 
32679             summary = context.history().difference().summary();
 
32681         function zoomToEntity(change) {
 
32682             var entity = change.entity;
 
32683             if (change.changeType !== 'deleted' &&
 
32684                 context.graph().entity(entity.id).geometry(context.graph()) !== 'vertex') {
 
32685                 context.map().zoomTo(entity);
 
32686                 context.surface().selectAll(
 
32687                     iD.util.entityOrMemberSelector([entity.id], context.graph()))
 
32688                     .classed('hover', true);
 
32692         var header = selection.append('div')
 
32693             .attr('class', 'header fillL');
 
32695         header.append('h3')
 
32696             .text(t('commit.title'));
 
32698         var body = selection.append('div')
 
32699             .attr('class', 'body');
 
32703         var commentSection = body.append('div')
 
32704             .attr('class', 'modal-section form-field commit-form');
 
32706         commentSection.append('label')
 
32707             .attr('class', 'form-label')
 
32708             .text(t('commit.message_label'));
 
32710         var commentField = commentSection.append('textarea')
 
32711             .attr('placeholder', t('commit.description_placeholder'))
 
32712             .attr('maxlength', 255)
 
32713             .property('value', context.storage('comment') || '')
 
32714             .on('input.save', enableDisableSaveButton)
 
32715             .on('change.save', enableDisableSaveButton)
 
32716             .on('blur.save', function() {
 
32717                 context.storage('comment', this.value);
 
32720         function enableDisableSaveButton() {
 
32721             d3.selectAll('.save-section .save-button')
 
32722                 .attr('disabled', (this.value.length ? null : true));
 
32725         commentField.node().select();
 
32727         context.connection().userChangesets(function (err, changesets) {
 
32732             for (var i = 0; i < changesets.length; i++) {
 
32733                 if (changesets[i].tags.comment) {
 
32735                         title: changesets[i].tags.comment,
 
32736                         value: changesets[i].tags.comment
 
32741             commentField.call(d3.combobox().data(comments));
 
32744         var changeSetInfo = commentSection.append('div')
 
32745             .attr('class', 'changeset-info');
 
32747         changeSetInfo.append('a')
 
32748           .attr('target', '_blank')
 
32749           .attr('tabindex', -1)
 
32750           .call(iD.svg.Icon('#icon-out-link', 'inline'))
 
32751           .attr('href', t('commit.about_changeset_comments_link'))
 
32753           .text(t('commit.about_changeset_comments'));
 
32756         var warnings = body.selectAll('div.warning-section')
 
32757             .data([context.history().validate(changes)])
 
32760             .attr('class', 'modal-section warning-section fillL2')
 
32761             .style('display', function(d) { return _.isEmpty(d) ? 'none' : null; })
 
32762             .style('background', '#ffb');
 
32764         warnings.append('h3')
 
32765             .text(t('commit.warnings'));
 
32767         var warningLi = warnings.append('ul')
 
32768             .attr('class', 'changeset-list')
 
32770             .data(function(d) { return d; })
 
32774             .on('mouseover', mouseover)
 
32775             .on('mouseout', mouseout)
 
32776             .on('click', warningClick);
 
32779             .call(iD.svg.Icon('#icon-alert', 'pre-text'));
 
32782             .append('strong').text(function(d) {
 
32786         warningLi.filter(function(d) { return d.tooltip; })
 
32787             .call(bootstrap.tooltip()
 
32788                 .title(function(d) { return d.tooltip; })
 
32793         // Upload Explanation
 
32794         var saveSection = body.append('div')
 
32795             .attr('class','modal-section save-section fillL cf');
 
32797         var prose = saveSection.append('p')
 
32798             .attr('class', 'commit-info')
 
32799             .html(t('commit.upload_explanation'));
 
32801         context.connection().userDetails(function(err, user) {
 
32804             var userLink = d3.select(document.createElement('div'));
 
32806             if (user.image_url) {
 
32807                 userLink.append('img')
 
32808                     .attr('src', user.image_url)
 
32809                     .attr('class', 'icon pre-text user-icon');
 
32812             userLink.append('a')
 
32813                 .attr('class','user-info')
 
32814                 .text(user.display_name)
 
32815                 .attr('href', context.connection().userURL(user.display_name))
 
32816                 .attr('tabindex', -1)
 
32817                 .attr('target', '_blank');
 
32819             prose.html(t('commit.upload_explanation_with_user', {user: userLink.html()}));
 
32824         var buttonSection = saveSection.append('div')
 
32825             .attr('class','buttons fillL cf');
 
32827         var saveButton = buttonSection.append('button')
 
32828             .attr('class', 'action col5 button save-button')
 
32829             .attr('disabled', function() {
 
32830                 var n = d3.select('.commit-form textarea').node();
 
32831                 return (n && n.value.length) ? null : true;
 
32833             .on('click.save', function() {
 
32835                     comment: commentField.node().value
 
32839         saveButton.append('span')
 
32840             .attr('class', 'label')
 
32841             .text(t('commit.save'));
 
32843         var cancelButton = buttonSection.append('button')
 
32844             .attr('class', 'action col5 button cancel-button')
 
32845             .on('click.cancel', function() { dispatch.cancel(); });
 
32847         cancelButton.append('span')
 
32848             .attr('class', 'label')
 
32849             .text(t('commit.cancel'));
 
32853         var changeSection = body.selectAll('div.commit-section')
 
32857             .attr('class', 'commit-section modal-section fillL2');
 
32859         changeSection.append('h3')
 
32860             .text(t('commit.changes', {count: summary.length}));
 
32862         var li = changeSection.append('ul')
 
32863             .attr('class', 'changeset-list')
 
32868             .on('mouseover', mouseover)
 
32869             .on('mouseout', mouseout)
 
32870             .on('click', zoomToEntity);
 
32872         li.each(function(d) {
 
32874                 .call(iD.svg.Icon('#icon-' + d.entity.geometry(d.graph), 'pre-text ' + d.changeType));
 
32878             .attr('class', 'change-type')
 
32879             .text(function(d) {
 
32880                 return t('commit.' + d.changeType) + ' ';
 
32883         li.append('strong')
 
32884             .attr('class', 'entity-type')
 
32885             .text(function(d) {
 
32886                 return context.presets().match(d.entity, d.graph).name();
 
32890             .attr('class', 'entity-name')
 
32891             .text(function(d) {
 
32892                 var name = iD.util.displayName(d.entity) || '',
 
32894                 if (name !== '') string += ':';
 
32895                 return string += ' ' + name;
 
32898         li.style('opacity', 0)
 
32900             .style('opacity', 1);
 
32902         li.style('opacity', 0)
 
32904             .style('opacity', 1);
 
32906         function mouseover(d) {
 
32908                 context.surface().selectAll(
 
32909                     iD.util.entityOrMemberSelector([d.entity.id], context.graph())
 
32910                 ).classed('hover', true);
 
32914         function mouseout() {
 
32915             context.surface().selectAll('.hover')
 
32916                 .classed('hover', false);
 
32919         function warningClick(d) {
 
32921                 context.map().zoomTo(d.entity);
 
32923                     iD.modes.Select(context, [d.entity.id])
 
32924                         .suppressMenu(true));
 
32929     return d3.rebind(commit, dispatch, 'on');
 
32931 iD.ui.confirm = function(selection) {
 
32932     var modal = iD.ui.modal(selection);
 
32934     modal.select('.modal')
 
32935         .classed('modal-alert', true);
 
32937     var section = modal.select('.content');
 
32939     section.append('div')
 
32940         .attr('class', 'modal-section header');
 
32942     section.append('div')
 
32943         .attr('class', 'modal-section message-text');
 
32945     var buttons = section.append('div')
 
32946         .attr('class', 'modal-section buttons cf');
 
32948     modal.okButton = function() {
 
32951             .attr('class', 'action col4')
 
32952             .on('click.confirm', function() {
 
32955             .text(t('confirm.okay'));
 
32962 iD.ui.Conflicts = function(context) {
 
32963     var dispatch = d3.dispatch('download', 'cancel', 'save'),
 
32966     function conflicts(selection) {
 
32967         var header = selection
 
32969             .attr('class', 'header fillL');
 
32973             .attr('class', 'fr')
 
32974             .on('click', function() { dispatch.cancel(); })
 
32975             .call(iD.svg.Icon('#icon-close'));
 
32979             .text(t('save.conflict.header'));
 
32981         var body = selection
 
32983             .attr('class', 'body fillL');
 
32987             .attr('class', 'conflicts-help')
 
32988             .text(t('save.conflict.help'))
 
32990             .attr('class', 'conflicts-download')
 
32991             .text(t('save.conflict.download_changes'))
 
32992             .on('click.download', function() { dispatch.download(); });
 
32996             .attr('class', 'conflict-container fillL3')
 
32997             .call(showConflict, 0);
 
33001             .attr('class', 'conflicts-done')
 
33002             .attr('opacity', 0)
 
33003             .style('display', 'none')
 
33004             .text(t('save.conflict.done'));
 
33008             .attr('class','buttons col12 joined conflicts-buttons');
 
33012             .attr('disabled', list.length > 1)
 
33013             .attr('class', 'action conflicts-button col6')
 
33014             .text(t('save.title'))
 
33015             .on('click.try_again', function() { dispatch.save(); });
 
33019             .attr('class', 'secondary-action conflicts-button col6')
 
33020             .text(t('confirm.cancel'))
 
33021             .on('click.cancel', function() { dispatch.cancel(); });
 
33025     function showConflict(selection, index) {
 
33026         if (index < 0 || index >= list.length) return;
 
33028         var parent = d3.select(selection.node().parentNode);
 
33030         // enable save button if this is the last conflict being reviewed..
 
33031         if (index === list.length - 1) {
 
33032             window.setTimeout(function() {
 
33033                 parent.select('.conflicts-button')
 
33034                     .attr('disabled', null);
 
33036                 parent.select('.conflicts-done')
 
33038                     .attr('opacity', 1)
 
33039                     .style('display', 'block');
 
33043         var item = selection
 
33044             .selectAll('.conflict')
 
33045             .data([list[index]]);
 
33047         var enter = item.enter()
 
33049             .attr('class', 'conflict');
 
33053             .attr('class', 'conflict-count')
 
33054             .text(t('save.conflict.count', { num: index + 1, total: list.length }));
 
33058             .attr('class', 'conflict-description')
 
33060             .text(function(d) { return d.name; })
 
33061             .on('click', function(d) {
 
33062                 zoomToEntity(d.id);
 
33063                 d3.event.preventDefault();
 
33066         var details = enter
 
33068             .attr('class', 'conflict-detail-container');
 
33072             .attr('class', 'conflict-detail-list')
 
33074             .data(function(d) { return d.details || []; })
 
33077             .attr('class', 'conflict-detail-item')
 
33078             .html(function(d) { return d; });
 
33082             .attr('class', 'conflict-choices')
 
33087             .attr('class', 'conflict-nav-buttons joined cf')
 
33088             .selectAll('button')
 
33089             .data(['previous', 'next'])
 
33092             .text(function(d) { return t('save.conflict.' + d); })
 
33093             .attr('class', 'conflict-nav-button action col6')
 
33094             .attr('disabled', function(d, i) {
 
33095                 return (i === 0 && index === 0) ||
 
33096                     (i === 1 && index === list.length - 1) || null;
 
33098             .on('click', function(d, i) {
 
33099                 var container = parent.select('.conflict-container'),
 
33100                 sign = (i === 0 ? -1 : 1);
 
33103                     .selectAll('.conflict')
 
33107                     .call(showConflict, index + sign);
 
33109                 d3.event.preventDefault();
 
33117     function addChoices(selection) {
 
33118         var choices = selection
 
33120             .attr('class', 'layer-list')
 
33122             .data(function(d) { return d.choices || []; });
 
33124         var enter = choices.enter()
 
33126             .attr('class', 'layer');
 
33133             .attr('type', 'radio')
 
33134             .attr('name', function(d) { return d.id; })
 
33135             .on('change', function(d, i) {
 
33136                 var ul = this.parentNode.parentNode.parentNode;
 
33137                 ul.__data__.chosen = i;
 
33143             .text(function(d) { return d.text; });
 
33146             .each(function(d, i) {
 
33147                 var ul = this.parentNode;
 
33148                 if (ul.__data__.chosen === i) choose(ul, d);
 
33152     function choose(ul, datum) {
 
33153         if (d3.event) d3.event.preventDefault();
 
33157             .classed('active', function(d) { return d === datum; })
 
33158             .selectAll('input')
 
33159             .property('checked', function(d) { return d === datum; });
 
33161         var extent = iD.geo.Extent(),
 
33164         entity = context.graph().hasEntity(datum.id);
 
33165         if (entity) extent._extend(entity.extent(context.graph()));
 
33169         entity = context.graph().hasEntity(datum.id);
 
33170         if (entity) extent._extend(entity.extent(context.graph()));
 
33172         zoomToEntity(datum.id, extent);
 
33175     function zoomToEntity(id, extent) {
 
33176         context.surface().selectAll('.hover')
 
33177             .classed('hover', false);
 
33179         var entity = context.graph().hasEntity(id);
 
33182                 context.map().trimmedExtent(extent);
 
33184                 context.map().zoomTo(entity);
 
33186             context.surface().selectAll(
 
33187                 iD.util.entityOrMemberSelector([entity.id], context.graph()))
 
33188                 .classed('hover', true);
 
33193     // The conflict list should be an array of objects like:
 
33196     //     name: entityName(local),
 
33197     //     details: merge.conflicts(),
 
33200     //         choice(id, keepMine, forceLocal),
 
33201     //         choice(id, keepTheirs, forceRemote)
 
33204     conflicts.list = function(_) {
 
33205         if (!arguments.length) return list;
 
33210     return d3.rebind(conflicts, dispatch, 'on');
 
33212 iD.ui.Contributors = function(context) {
 
33213     var debouncedUpdate = _.debounce(function() { update(); }, 1000),
 
33216         wrap = d3.select(null);
 
33218     function update() {
 
33220             entities = context.intersects(context.map().extent());
 
33222         entities.forEach(function(entity) {
 
33223             if (entity && entity.user) users[entity.user] = true;
 
33226         var u = Object.keys(users),
 
33227             subset = u.slice(0, u.length > limit ? limit - 1 : limit);
 
33230             .call(iD.svg.Icon('#icon-nearby', 'pre-text light'));
 
33232         var userList = d3.select(document.createElement('span'));
 
33234         userList.selectAll()
 
33238             .attr('class', 'user-link')
 
33239             .attr('href', function(d) { return context.connection().userURL(d); })
 
33240             .attr('target', '_blank')
 
33241             .attr('tabindex', -1)
 
33244         if (u.length > limit) {
 
33245             var count = d3.select(document.createElement('span'));
 
33248                 .attr('target', '_blank')
 
33249                 .attr('tabindex', -1)
 
33250                 .attr('href', function() {
 
33251                     return context.connection().changesetsURL(context.map().center(), context.map().zoom());
 
33253                 .text(u.length - limit + 1);
 
33255             wrap.append('span')
 
33256                 .html(t('contributors.truncated_list', { users: userList.html(), count: count.html() }));
 
33259             wrap.append('span')
 
33260                 .html(t('contributors.list', { users: userList.html() }));
 
33267                 .style('opacity', 0);
 
33269         } else if (hidden) {
 
33272                 .style('opacity', 1);
 
33276     return function(selection) {
 
33280         context.connection().on('loaded.contributors', debouncedUpdate);
 
33281         context.map().on('move.contributors', debouncedUpdate);
 
33284 iD.ui.Disclosure = function() {
 
33285     var dispatch = d3.dispatch('toggled'),
 
33288         content = function () {};
 
33290     var disclosure = function(selection) {
 
33291         var $link = selection.selectAll('.hide-toggle')
 
33294         $link.enter().append('a')
 
33296             .attr('class', 'hide-toggle');
 
33299             .on('click', toggle)
 
33300             .classed('expanded', expanded);
 
33302         var $body = selection.selectAll('div')
 
33305         $body.enter().append('div');
 
33307         $body.classed('hide', !expanded)
 
33310         function toggle() {
 
33311             expanded = !expanded;
 
33312             $link.classed('expanded', expanded);
 
33313             $body.call(iD.ui.Toggle(expanded));
 
33314             dispatch.toggled(expanded);
 
33318     disclosure.title = function(_) {
 
33319         if (!arguments.length) return title;
 
33324     disclosure.expanded = function(_) {
 
33325         if (!arguments.length) return expanded;
 
33330     disclosure.content = function(_) {
 
33331         if (!arguments.length) return content;
 
33336     return d3.rebind(disclosure, dispatch, 'on');
 
33338 iD.ui.EntityEditor = function(context) {
 
33339     var dispatch = d3.dispatch('choose'),
 
33341         coalesceChanges = false,
 
33348     var presetEditor = iD.ui.preset(context)
 
33349         .on('change', changeTags);
 
33350     var rawTagEditor = iD.ui.RawTagEditor(context)
 
33351         .on('change', changeTags);
 
33353     function entityEditor(selection) {
 
33354         var entity = context.entity(id),
 
33355             tags = _.clone(entity.tags);
 
33357         var $header = selection.selectAll('.header')
 
33361         var $enter = $header.enter().append('div')
 
33362             .attr('class', 'header fillL cf');
 
33364         $enter.append('button')
 
33365             .attr('class', 'fl preset-reset preset-choose')
 
33369         $enter.append('button')
 
33370             .attr('class', 'fr preset-close')
 
33371             .call(iD.svg.Icon(modified ? '#icon-apply' : '#icon-close'));
 
33373         $enter.append('h3');
 
33376         $header.select('h3')
 
33377             .text(t('inspector.edit'));
 
33379         $header.select('.preset-close')
 
33380             .on('click', function() {
 
33381                 context.enter(iD.modes.Browse(context));
 
33384         var $body = selection.selectAll('.inspector-body')
 
33388         $enter = $body.enter().append('div')
 
33389             .attr('class', 'inspector-body');
 
33391         $enter.append('div')
 
33392             .attr('class', 'preset-list-item inspector-inner')
 
33394             .attr('class', 'preset-list-button-wrap')
 
33396             .attr('class', 'preset-list-button preset-reset')
 
33397             .call(bootstrap.tooltip()
 
33398                 .title(t('inspector.back_tooltip'))
 
33399                 .placement('bottom'))
 
33401             .attr('class', 'label');
 
33403         $body.select('.preset-list-button-wrap')
 
33404             .call(reference.button);
 
33406         $body.select('.preset-list-item')
 
33407             .call(reference.body);
 
33409         $enter.append('div')
 
33410             .attr('class', 'inspector-border inspector-preset');
 
33412         $enter.append('div')
 
33413             .attr('class', 'inspector-border raw-tag-editor inspector-inner');
 
33415         $enter.append('div')
 
33416             .attr('class', 'inspector-border raw-member-editor inspector-inner');
 
33418         $enter.append('div')
 
33419             .attr('class', 'raw-membership-editor inspector-inner');
 
33421         selection.selectAll('.preset-reset')
 
33422             .on('click', function() {
 
33423                 dispatch.choose(preset);
 
33427         $body.select('.preset-list-item button')
 
33428             .call(iD.ui.PresetIcon()
 
33429                 .geometry(context.geometry(id))
 
33432         $body.select('.preset-list-item .label')
 
33433             .text(preset.name());
 
33435         $body.select('.inspector-preset')
 
33442         $body.select('.raw-tag-editor')
 
33449         if (entity.type === 'relation') {
 
33450             $body.select('.raw-member-editor')
 
33451                 .style('display', 'block')
 
33452                 .call(iD.ui.RawMemberEditor(context)
 
33455             $body.select('.raw-member-editor')
 
33456                 .style('display', 'none');
 
33459         $body.select('.raw-membership-editor')
 
33460             .call(iD.ui.RawMembershipEditor(context)
 
33463         function historyChanged() {
 
33464             if (state === 'hide') return;
 
33466             var entity = context.hasEntity(id),
 
33467                 graph = context.graph();
 
33468             if (!entity) return;
 
33470             entityEditor.preset(context.presets().match(entity, graph));
 
33471             entityEditor.modified(base !== graph);
 
33472             entityEditor(selection);
 
33476             .on('change.entity-editor', historyChanged);
 
33479     function clean(o) {
 
33481         function cleanVal(k, v) {
 
33482             function keepSpaces(k) {
 
33483                 var whitelist = ['opening_hours', 'service_times', 'collection_times',
 
33484                     'operating_times', 'smoking_hours', 'happy_hours'];
 
33485                 return _.any(whitelist, function(s) { return k.indexOf(s) !== -1; });
 
33488             var blacklist = ['description', 'note', 'fixme'];
 
33489             if (_.any(blacklist, function(s) { return k.indexOf(s) !== -1; })) return v;
 
33491             var cleaned = v.split(';')
 
33492                 .map(function(s) { return s.trim(); })
 
33493                 .join(keepSpaces(k) ? '; ' : ';');
 
33495             // The code below is not intended to validate websites and emails.
 
33496             // It is only intended to prevent obvious copy-paste errors. (#2323)
 
33498             // clean website- and email-like tags
 
33499             if (k.indexOf('website') !== -1 ||
 
33500                 k.indexOf('email') !== -1 ||
 
33501                 cleaned.indexOf('http') === 0) {
 
33503                     .replace(/[\u200B-\u200F\uFEFF]/g, '');  // strip LRM and other zero width chars
 
33510         var out = {}, k, v;
 
33512             if (k && (v = o[k]) !== undefined) {
 
33513                 out[k] = cleanVal(k, v);
 
33519     // Tag changes that fire on input can all get coalesced into a single
 
33520     // history operation when the user leaves the field.  #2342
 
33521     function changeTags(changed, onInput) {
 
33522         var entity = context.entity(id),
 
33523             annotation = t('operations.change_tags.annotation'),
 
33524             tags = clean(_.extend({}, entity.tags, changed));
 
33526         if (!_.isEqual(entity.tags, tags)) {
 
33527             if (coalesceChanges) {
 
33528                 context.overwrite(iD.actions.ChangeTags(id, tags), annotation);
 
33530                 context.perform(iD.actions.ChangeTags(id, tags), annotation);
 
33534         coalesceChanges = !!onInput;
 
33537     entityEditor.modified = function(_) {
 
33538         if (!arguments.length) return modified;
 
33540         d3.selectAll('button.preset-close use')
 
33541             .attr('xlink:href', (modified ? '#icon-apply' : '#icon-close'));
 
33544     entityEditor.state = function(_) {
 
33545         if (!arguments.length) return state;
 
33547         return entityEditor;
 
33550     entityEditor.entityID = function(_) {
 
33551         if (!arguments.length) return id;
 
33553         base = context.graph();
 
33554         entityEditor.preset(context.presets().match(context.entity(id), base));
 
33555         entityEditor.modified(false);
 
33556         coalesceChanges = false;
 
33557         return entityEditor;
 
33560     entityEditor.preset = function(_) {
 
33561         if (!arguments.length) return preset;
 
33562         if (_ !== preset) {
 
33564             reference = iD.ui.TagReference(preset.reference(context.geometry(id)), context)
 
33567         return entityEditor;
 
33570     return d3.rebind(entityEditor, dispatch, 'on');
 
33572 iD.ui.FeatureInfo = function(context) {
 
33573     function update(selection) {
 
33574         var features = context.features(),
 
33575             stats = features.stats(),
 
33577             hiddenList = _.compact(_.map(features.hidden(), function(k) {
 
33580                     return String(stats[k]) + ' ' + t('feature.' + k + '.description');
 
33584         selection.html('');
 
33586         if (hiddenList.length) {
 
33587             var tooltip = bootstrap.tooltip()
 
33590                     .title(function() {
 
33591                         return iD.ui.tooltipHtml(hiddenList.join('<br/>'));
 
33594             var warning = selection.append('a')
 
33596                 .attr('tabindex', -1)
 
33597                 .html(t('feature_info.hidden_warning', { count: count }))
 
33599                 .on('click', function() {
 
33600                     tooltip.hide(warning);
 
33601                     // open map data panel?
 
33602                     d3.event.preventDefault();
 
33607             .classed('hide', !hiddenList.length);
 
33610     return function(selection) {
 
33613         context.features().on('change.feature_info', function() {
 
33618 iD.ui.FeatureList = function(context) {
 
33619     var geocodeResults;
 
33621     function featureList(selection) {
 
33622         var header = selection.append('div')
 
33623             .attr('class', 'header fillL cf');
 
33625         header.append('h3')
 
33626             .text(t('inspector.feature_list'));
 
33628         function keypress() {
 
33629             var q = search.property('value'),
 
33630                 items = list.selectAll('.feature-list-item');
 
33631             if (d3.event.keyCode === 13 && q.length && items.size()) {
 
33632                 click(items.datum());
 
33636         function inputevent() {
 
33637             geocodeResults = undefined;
 
33641         var searchWrap = selection.append('div')
 
33642             .attr('class', 'search-header');
 
33644         var search = searchWrap.append('input')
 
33645             .attr('placeholder', t('inspector.search'))
 
33646             .attr('type', 'search')
 
33647             .on('keypress', keypress)
 
33648             .on('input', inputevent);
 
33651             .call(iD.svg.Icon('#icon-search', 'pre-text'));
 
33653         var listWrap = selection.append('div')
 
33654             .attr('class', 'inspector-body');
 
33656         var list = listWrap.append('div')
 
33657             .attr('class', 'feature-list cf');
 
33660             .on('exit.feature-list', clearSearch);
 
33662             .on('drawn.feature-list', mapDrawn);
 
33664         function clearSearch() {
 
33665             search.property('value', '');
 
33669         function mapDrawn(e) {
 
33675         function features() {
 
33678                 graph = context.graph(),
 
33679                 q = search.property('value').toLowerCase();
 
33681             if (!q) return result;
 
33683             var idMatch = q.match(/^([nwr])([0-9]+)$/);
 
33688                     geometry: idMatch[1] === 'n' ? 'point' : idMatch[1] === 'w' ? 'line' : 'relation',
 
33689                     type: idMatch[1] === 'n' ? t('inspector.node') : idMatch[1] === 'w' ? t('inspector.way') : t('inspector.relation'),
 
33694             var locationMatch = sexagesimal.pair(q.toUpperCase()) || q.match(/^(-?\d+\.?\d*)\s+(-?\d+\.?\d*)$/);
 
33696             if (locationMatch) {
 
33697                 var loc = [parseFloat(locationMatch[0]), parseFloat(locationMatch[1])];
 
33701                     type: t('inspector.location'),
 
33702                     name: loc[0].toFixed(6) + ', ' + loc[1].toFixed(6),
 
33707             function addEntity(entity) {
 
33708                 if (entity.id in entities || result.length > 200)
 
33711                 entities[entity.id] = true;
 
33713                 var name = iD.util.displayName(entity) || '';
 
33714                 if (name.toLowerCase().indexOf(q) >= 0) {
 
33718                         geometry: context.geometry(entity.id),
 
33719                         type: context.presets().match(entity, graph).name(),
 
33724                 graph.parentRelations(entity).forEach(function(parent) {
 
33729             var visible = context.surface().selectAll('.point, .line, .area')[0];
 
33730             for (var i = 0; i < visible.length && result.length <= 200; i++) {
 
33731                 addEntity(visible[i].__data__);
 
33734             (geocodeResults || []).forEach(function(d) {
 
33735                 // https://github.com/openstreetmap/iD/issues/1890
 
33736                 if (d.osm_type && d.osm_id) {
 
33738                         id: iD.Entity.id.fromOSM(d.osm_type, d.osm_id),
 
33739                         geometry: d.osm_type === 'relation' ? 'relation' : d.osm_type === 'way' ? 'line' : 'point',
 
33740                         type: d.type !== 'yes' ? (d.type.charAt(0).toUpperCase() + d.type.slice(1)).replace('_', ' ')
 
33741                                                : (d.class.charAt(0).toUpperCase() + d.class.slice(1)).replace('_', ' '),
 
33742                         name: d.display_name,
 
33743                         extent: new iD.geo.Extent(
 
33744                             [parseFloat(d.boundingbox[3]), parseFloat(d.boundingbox[0])],
 
33745                             [parseFloat(d.boundingbox[2]), parseFloat(d.boundingbox[1])])
 
33753         function drawList() {
 
33754             var value = search.property('value'),
 
33755                 results = features();
 
33757             list.classed('filtered', value.length);
 
33759             var noResultsWorldwide = geocodeResults && geocodeResults.length === 0;
 
33761             var resultsIndicator = list.selectAll('.no-results-item')
 
33763                 .enter().append('button')
 
33764                 .property('disabled', true)
 
33765                 .attr('class', 'no-results-item')
 
33766                 .call(iD.svg.Icon('#icon-alert', 'pre-text'));
 
33768             resultsIndicator.append('span')
 
33769                 .attr('class', 'entity-name');
 
33771             list.selectAll('.no-results-item .entity-name')
 
33772                 .text(noResultsWorldwide ? t('geocoder.no_results_worldwide') : t('geocoder.no_results_visible'));
 
33774             list.selectAll('.geocode-item')
 
33776                 .enter().append('button')
 
33777                 .attr('class', 'geocode-item')
 
33778                 .on('click', geocode)
 
33780                 .attr('class', 'label')
 
33782                 .attr('class', 'entity-name')
 
33783                 .text(t('geocoder.search'));
 
33785             list.selectAll('.no-results-item')
 
33786                 .style('display', (value.length && !results.length) ? 'block' : 'none');
 
33788             list.selectAll('.geocode-item')
 
33789                 .style('display', (value && geocodeResults === undefined) ? 'block' : 'none');
 
33791             list.selectAll('.feature-list-item')
 
33795             var items = list.selectAll('.feature-list-item')
 
33796                 .data(results, function(d) { return d.id; });
 
33798             var enter = items.enter()
 
33799                 .insert('button', '.geocode-item')
 
33800                 .attr('class', 'feature-list-item')
 
33801                 .on('mouseover', mouseover)
 
33802                 .on('mouseout', mouseout)
 
33803                 .on('click', click);
 
33807                 .attr('class', 'label');
 
33809             label.each(function(d) {
 
33811                     .call(iD.svg.Icon('#icon-' + d.geometry, 'pre-text'));
 
33814             label.append('span')
 
33815                 .attr('class', 'entity-type')
 
33816                 .text(function(d) { return d.type; });
 
33818             label.append('span')
 
33819                 .attr('class', 'entity-name')
 
33820                 .text(function(d) { return d.name; });
 
33822             enter.style('opacity', 0)
 
33824                 .style('opacity', 1);
 
33832         function mouseover(d) {
 
33833             if (d.id === -1) return;
 
33835             context.surface().selectAll(iD.util.entityOrMemberSelector([d.id], context.graph()))
 
33836                 .classed('hover', true);
 
33839         function mouseout() {
 
33840             context.surface().selectAll('.hover')
 
33841                 .classed('hover', false);
 
33844         function click(d) {
 
33845             d3.event.preventDefault();
 
33847                 context.map().centerZoom([d.location[1], d.location[0]], 20);
 
33849             else if (d.entity) {
 
33850                 if (d.entity.type === 'node') {
 
33851                     context.map().center(d.entity.loc);
 
33852                 } else if (d.entity.type === 'way') {
 
33853                     var center = context.projection(context.map().center()),
 
33854                         edge = iD.geo.chooseEdge(context.childNodes(d.entity), center, context.projection);
 
33855                     context.map().center(edge.loc);
 
33857                 context.enter(iD.modes.Select(context, [d.entity.id]).suppressMenu(true));
 
33859                 context.zoomToEntity(d.id);
 
33863         function geocode() {
 
33864             var searchVal = encodeURIComponent(search.property('value'));
 
33865             d3.json('https://nominatim.openstreetmap.org/search/' + searchVal + '?limit=10&format=json', function(err, resp) {
 
33866                 geocodeResults = resp || [];
 
33872     return featureList;
 
33874 iD.ui.flash = function(selection) {
 
33875     var modal = iD.ui.modal(selection);
 
33877     modal.select('.modal').classed('modal-flash', true);
 
33879     modal.select('.content')
 
33880         .classed('modal-section', true)
 
33882         .attr('class', 'description');
 
33884     modal.on('click.flash', function() { modal.remove(); });
 
33886     setTimeout(function() {
 
33893 iD.ui.FullScreen = function(context) {
 
33894     var element = context.container().node(),
 
33895         keybinding = d3.keybinding('full-screen');
 
33898     function getFullScreenFn() {
 
33899         if (element.requestFullscreen) {
 
33900             return element.requestFullscreen;
 
33901         } else if (element.msRequestFullscreen) {
 
33902             return  element.msRequestFullscreen;
 
33903         } else if (element.mozRequestFullScreen) {
 
33904             return  element.mozRequestFullScreen;
 
33905         } else if (element.webkitRequestFullscreen) {
 
33906             return element.webkitRequestFullscreen;
 
33910     function getExitFullScreenFn() {
 
33911         if (document.exitFullscreen) {
 
33912             return document.exitFullscreen;
 
33913         } else if (document.msExitFullscreen) {
 
33914             return  document.msExitFullscreen;
 
33915         } else if (document.mozCancelFullScreen) {
 
33916             return  document.mozCancelFullScreen;
 
33917         } else if (document.webkitExitFullscreen) {
 
33918             return document.webkitExitFullscreen;
 
33922     function isFullScreen() {
 
33923         return document.fullscreenElement || document.mozFullScreenElement || document.webkitFullscreenElement ||
 
33924             document.msFullscreenElement;
 
33927     function isSupported() {
 
33928         return !!getFullScreenFn();
 
33931     function fullScreen() {
 
33932         d3.event.preventDefault();
 
33933         if (!isFullScreen()) {
 
33934             // button.classed('active', true);
 
33935             getFullScreenFn().apply(element);
 
33937             // button.classed('active', false);
 
33938             getExitFullScreenFn().apply(document);
 
33942     return function() { // selection) {
 
33943         if (!isSupported())
 
33946         // var tooltip = bootstrap.tooltip()
 
33947         //     .placement('left');
 
33949         // button = selection.append('button')
 
33950         //     .attr('title', t('full_screen'))
 
33951         //     .attr('tabindex', -1)
 
33952         //     .on('click', fullScreen)
 
33955         // button.append('span')
 
33956         //     .attr('class', 'icon full-screen');
 
33959             .on('f11', fullScreen)
 
33960             .on(iD.ui.cmd('⌘⇧F'), fullScreen);
 
33962         d3.select(document)
 
33966 iD.ui.Geolocate = function(map) {
 
33968         navigator.geolocation.getCurrentPosition(
 
33972     function success(position) {
 
33973         var extent = iD.geo.Extent([position.coords.longitude, position.coords.latitude])
 
33974             .padByMeters(position.coords.accuracy);
 
33976         map.centerZoom(extent.center(), Math.min(20, map.extentZoom(extent)));
 
33979     function error() { }
 
33981     return function(selection) {
 
33982         if (!navigator.geolocation) return;
 
33984         selection.append('button')
 
33985             .attr('tabindex', -1)
 
33986             .attr('title', t('geolocate.title'))
 
33987             .on('click', click)
 
33988             .call(iD.svg.Icon('#icon-geolocate', 'light'))
 
33989             .call(bootstrap.tooltip()
 
33990                 .placement('left'));
 
33993 iD.ui.Help = function(context) {
 
33998         'help.editing_saving',
 
34007     var docs = docKeys.map(function(key) {
 
34010             title: text.split('\n')[0].replace('#', '').trim(),
 
34011             html: marked(text.split('\n').slice(1).join('\n'))
 
34015     function help(selection) {
 
34021         function toggle() {
 
34022             if (d3.event) d3.event.preventDefault();
 
34023             tooltip.hide(button);
 
34024             setVisible(!button.classed('active'));
 
34027         function setVisible(show) {
 
34028             if (show !== shown) {
 
34029                 button.classed('active', show);
 
34033                     selection.on('mousedown.help-inside', function() {
 
34034                         return d3.event.stopPropagation();
 
34036                     pane.style('display', 'block')
 
34037                         .style('right', '-500px')
 
34040                         .style('right', '0px');
 
34042                     pane.style('right', '0px')
 
34045                         .style('right', '-500px')
 
34046                         .each('end', function() {
 
34047                             d3.select(this).style('display', 'none');
 
34049                     selection.on('mousedown.help-inside', null);
 
34054         function clickHelp(d, i) {
 
34055             pane.property('scrollTop', 0);
 
34056             doctitle.html(d.title);
 
34058             body.selectAll('a')
 
34059                 .attr('target', '_blank');
 
34060             menuItems.classed('selected', function(m) {
 
34061                 return m.title === d.title;
 
34067                 var prevLink = nav.append('a')
 
34068                     .attr('class', 'previous')
 
34069                     .on('click', function() {
 
34070                         clickHelp(docs[i - 1], i - 1);
 
34072                 prevLink.append('span').html('◄ ' + docs[i - 1].title);
 
34074             if (i < docs.length - 1) {
 
34075                 var nextLink = nav.append('a')
 
34076                     .attr('class', 'next')
 
34077                     .on('click', function() {
 
34078                         clickHelp(docs[i + 1], i + 1);
 
34080                 nextLink.append('span').html(docs[i + 1].title + ' ►');
 
34084         function clickWalkthrough() {
 
34085             d3.select(document.body).call(iD.ui.intro(context));
 
34090         var pane = selection.append('div')
 
34091                 .attr('class', 'help-wrap map-overlay fillL col5 content hide'),
 
34092             tooltip = bootstrap.tooltip()
 
34095                 .title(iD.ui.tooltipHtml(t('help.title'), key)),
 
34096             button = selection.append('button')
 
34097                 .attr('tabindex', -1)
 
34098                 .on('click', toggle)
 
34099                 .call(iD.svg.Icon('#icon-help', 'light'))
 
34104         var toc = pane.append('ul')
 
34105             .attr('class', 'toc');
 
34107         var menuItems = toc.selectAll('li')
 
34112             .html(function(d) { return d.title; })
 
34113             .on('click', clickHelp);
 
34116             .attr('class','walkthrough')
 
34118             .text(t('splash.walkthrough'))
 
34119             .on('click', clickWalkthrough);
 
34121         var content = pane.append('div')
 
34122             .attr('class', 'left-content');
 
34124         var doctitle = content.append('h2')
 
34125             .text(t('help.title'));
 
34127         var body = content.append('div')
 
34128             .attr('class', 'body');
 
34130         var nav = content.append('div')
 
34131             .attr('class', 'nav');
 
34133         clickHelp(docs[0], 0);
 
34135         var keybinding = d3.keybinding('help')
 
34140         d3.select(document)
 
34143         context.surface().on('mousedown.help-outside', hide);
 
34144         context.container().on('mousedown.help-outside', hide);
 
34149 iD.ui.Info = function(context) {
 
34150     var key = iD.ui.cmd('⌘I'),
 
34151         imperial = (iD.detect().locale.toLowerCase() === 'en-us'),
 
34154     function info(selection) {
 
34155         function radiansToMeters(r) {
 
34156             // using WGS84 authalic radius (6371007.1809 m)
 
34157             return r * 6371007.1809;
 
34160         function steradiansToSqmeters(r) {
 
34161             // http://gis.stackexchange.com/a/124857/40446
 
34162             return r / 12.56637 * 510065621724000;
 
34165         function toLineString(feature) {
 
34166             if (feature.type === 'LineString') return feature;
 
34168             var result = { type: 'LineString', coordinates: [] };
 
34169             if (feature.type === 'Polygon') {
 
34170                 result.coordinates = feature.coordinates[0];
 
34171             } else if (feature.type === 'MultiPolygon') {
 
34172                 result.coordinates = feature.coordinates[0][0];
 
34178         function displayLength(m) {
 
34179             var d = m * (imperial ? 3.28084 : 1),
 
34198             // drop unnecessary precision
 
34199             p = d > 1000 ? 0 : d > 100 ? 1 : 2;
 
34201             return String(d.toFixed(p)) + ' ' + unit;
 
34204         function displayArea(m2) {
 
34205             var d = m2 * (imperial ? 10.7639111056 : 1),
 
34206                 d1, d2, p1, p2, unit1, unit2;
 
34209                 if (d >= 6969600) {     // > 0.25mi² show mi²
 
34217                 if (d > 4356 && d < 43560000) {   // 0.1 - 1000 acres
 
34223                 if (d >= 250000) {    // > 0.25km² show km²
 
34231                 if (d > 1000 && d < 10000000) {   // 0.1 - 1000 hectares
 
34237             // drop unnecessary precision
 
34238             p1 = d1 > 1000 ? 0 : d1 > 100 ? 1 : 2;
 
34239             p2 = d2 > 1000 ? 0 : d2 > 100 ? 1 : 2;
 
34241             return String(d1.toFixed(p1)) + ' ' + unit1 +
 
34242                 (d2 ? ' (' + String(d2.toFixed(p2)) + ' ' + unit2 + ')' : '');
 
34246         function redraw() {
 
34247             if (hidden) return;
 
34249             var resolver = context.graph(),
 
34250                 selected = _.filter(context.selectedIDs(), function(e) { return context.hasEntity(e); }),
 
34251                 singular = selected.length === 1 ? selected[0] : null,
 
34252                 extent = iD.geo.Extent(),
 
34257                 .attr('class', 'infobox-heading fillD')
 
34258                 .text(singular || t('infobox.selected', { n: selected.length }));
 
34260             if (!selected.length) return;
 
34263             for (var i = 0; i < selected.length; i++) {
 
34264                 entity = context.entity(selected[i]);
 
34265                 extent._extend(entity.extent(resolver));
 
34267             center = extent.center();
 
34270             var list = wrap.append('ul');
 
34272             // multiple wrap, just display extent center..
 
34275                     .text(t('infobox.center') + ': ' + center[0].toFixed(5) + ', ' + center[1].toFixed(5));
 
34279             // single wrap, display details..
 
34280             if (!entity) return;
 
34281             var geometry = entity.geometry(resolver);
 
34283             if (geometry === 'line' || geometry === 'area') {
 
34284                 var closed = (entity.type === 'relation') || (entity.isClosed() && !entity.isDegenerate()),
 
34285                     feature = entity.asGeoJSON(resolver),
 
34286                     length = radiansToMeters(d3.geo.length(toLineString(feature))),
 
34287                     lengthLabel = t('infobox.' + (closed ? 'perimeter' : 'length')),
 
34288                     centroid = d3.geo.centroid(feature);
 
34291                     .text(t('infobox.geometry') + ': ' +
 
34292                         (closed ? t('infobox.closed') + ' ' : '') + t('geometry.' + geometry) );
 
34295                     var area = steradiansToSqmeters(entity.area(resolver));
 
34297                         .text(t('infobox.area') + ': ' + displayArea(area));
 
34301                     .text(lengthLabel + ': ' + displayLength(length));
 
34304                     .text(t('infobox.centroid') + ': ' + centroid[0].toFixed(5) + ', ' + centroid[1].toFixed(5));
 
34307                 var toggle  = imperial ? 'imperial' : 'metric';
 
34309                     .text(t('infobox.' + toggle))
 
34311                     .attr('class', 'button')
 
34312                     .on('click', function() {
 
34313                         d3.event.preventDefault();
 
34314                         imperial = !imperial;
 
34319                 var centerLabel = t('infobox.' + (entity.type === 'node' ? 'location' : 'center'));
 
34322                     .text(t('infobox.geometry') + ': ' + t('geometry.' + geometry));
 
34325                     .text(centerLabel + ': ' + center[0].toFixed(5) + ', ' + center[1].toFixed(5));
 
34330         function toggle() {
 
34331             if (d3.event) d3.event.preventDefault();
 
34337                     .style('display', 'block')
 
34338                     .style('opacity', 1)
 
34341                     .style('opacity', 0)
 
34342                     .each('end', function() {
 
34343                         d3.select(this).style('display', 'none');
 
34347                     .style('display', 'block')
 
34348                     .style('opacity', 0)
 
34351                     .style('opacity', 1);
 
34358         var wrap = selection.selectAll('.infobox')
 
34363             .attr('class', 'infobox fillD2')
 
34364             .style('display', (hidden ? 'none' : 'block'));
 
34367             .on('drawn.info', redraw);
 
34371         var keybinding = d3.keybinding('info')
 
34374         d3.select(document)
 
34380 iD.ui.Inspector = function(context) {
 
34381     var presetList = iD.ui.PresetList(context),
 
34382         entityEditor = iD.ui.EntityEditor(context),
 
34385         newFeature = false;
 
34387     function inspector(selection) {
 
34389             .entityID(entityID)
 
34390             .autofocus(newFeature)
 
34391             .on('choose', setPreset);
 
34395             .entityID(entityID)
 
34396             .on('choose', showList);
 
34398         var $wrap = selection.selectAll('.panewrap')
 
34401         var $enter = $wrap.enter().append('div')
 
34402             .attr('class', 'panewrap');
 
34404         $enter.append('div')
 
34405             .attr('class', 'preset-list-pane pane');
 
34407         $enter.append('div')
 
34408             .attr('class', 'entity-editor-pane pane');
 
34410         var $presetPane = $wrap.select('.preset-list-pane');
 
34411         var $editorPane = $wrap.select('.entity-editor-pane');
 
34413         var graph = context.graph(),
 
34414             entity = context.entity(entityID),
 
34415             showEditor = state === 'hover' ||
 
34416                 entity.isUsed(graph) ||
 
34417                 entity.isHighwayIntersection(graph);
 
34420             $wrap.style('right', '0%');
 
34421             $editorPane.call(entityEditor);
 
34423             $wrap.style('right', '-100%');
 
34424             $presetPane.call(presetList);
 
34427         var $footer = selection.selectAll('.footer')
 
34430         $footer.enter().append('div')
 
34431             .attr('class', 'footer');
 
34433         selection.select('.footer')
 
34434             .call(iD.ui.ViewOnOSM(context)
 
34435                 .entityID(entityID));
 
34437         function showList(preset) {
 
34439                 .styleTween('right', function() { return d3.interpolate('0%', '-100%'); });
 
34441             $presetPane.call(presetList
 
34446         function setPreset(preset) {
 
34448                 .styleTween('right', function() { return d3.interpolate('-100%', '0%'); });
 
34450             $editorPane.call(entityEditor
 
34455     inspector.state = function(_) {
 
34456         if (!arguments.length) return state;
 
34458         entityEditor.state(state);
 
34462     inspector.entityID = function(_) {
 
34463         if (!arguments.length) return entityID;
 
34468     inspector.newFeature = function(_) {
 
34469         if (!arguments.length) return newFeature;
 
34476 iD.ui.intro = function(context) {
 
34479     function intro(selection) {
 
34481         function localizedName(id) {
 
34483                 n2140018997: 'city_hall',
 
34484                 n367813436: 'fire_department',
 
34485                 w203988286: 'memory_isle_park',
 
34486                 w203972937: 'riverwalk_trail',
 
34487                 w203972938: 'riverwalk_trail',
 
34488                 w203972940: 'riverwalk_trail',
 
34489                 w41785752: 'w_michigan_ave',
 
34490                 w134150789: 'w_michigan_ave',
 
34491                 w134150795: 'w_michigan_ave',
 
34492                 w134150800: 'w_michigan_ave',
 
34493                 w134150811: 'w_michigan_ave',
 
34494                 w134150802: 'e_michigan_ave',
 
34495                 w134150836: 'e_michigan_ave',
 
34496                 w41074896: 'e_michigan_ave',
 
34497                 w17965834: 'spring_st',
 
34498                 w203986457: 'scidmore_park',
 
34499                 w203049587: 'petting_zoo',
 
34500                 w17967397: 'n_andrews_st',
 
34501                 w17967315: 's_andrews_st',
 
34502                 w17967326: 'n_constantine_st',
 
34503                 w17966400: 's_constantine_st',
 
34504                 w170848823: 'rocky_river',
 
34505                 w170848824: 'rocky_river',
 
34506                 w170848331: 'rocky_river',
 
34507                 w17967752: 'railroad_dr',
 
34508                 w17965998: 'conrail_rr',
 
34509                 w134150845: 'conrail_rr',
 
34510                 w170989131: 'st_joseph_river',
 
34511                 w143497377: 'n_main_st',
 
34512                 w134150801: 's_main_st',
 
34513                 w134150830: 's_main_st',
 
34514                 w17966462: 's_main_st',
 
34515                 w17967734: 'water_st',
 
34516                 w17964996: 'foster_st',
 
34517                 w170848330: 'portage_river',
 
34518                 w17965351: 'flower_st',
 
34519                 w17965502: 'elm_st',
 
34520                 w17965402: 'walnut_st',
 
34521                 w17964793: 'morris_ave',
 
34522                 w17967444: 'east_st',
 
34523                 w17966984: 'portage_ave'
 
34525             return features[id] && t('intro.graph.' + features[id]);
 
34528         context.enter(iD.modes.Browse(context));
 
34530         // Save current map state
 
34531         var history = context.history().toJSON(),
 
34532             hash = window.location.hash,
 
34533             center = context.map().center(),
 
34534             zoom = context.map().zoom(),
 
34535             background = context.background().baseLayerSource(),
 
34536             opacity = d3.selectAll('#map .layer-background').style('opacity'),
 
34537             loadedTiles = context.connection().loadedTiles(),
 
34538             baseEntities = context.history().graph().base().entities,
 
34542         context.inIntro(true);
 
34544         // Load semi-real data used in intro
 
34545         context.connection().toggle(false).flush();
 
34546         context.history().reset();
 
34548         introGraph = JSON.parse(iD.introGraph);
 
34549         for (var key in introGraph) {
 
34550             introGraph[key] = iD.Entity(introGraph[key]);
 
34551             name = localizedName(key);
 
34553                 introGraph[key].tags.name = name;
 
34556         context.history().merge(d3.values(iD.Graph().load(introGraph).entities));
 
34557         context.background().bing();
 
34559         d3.selectAll('#map .layer-background').style('opacity', 1);
 
34561         var curtain = d3.curtain();
 
34562         selection.call(curtain);
 
34564         function reveal(box, text, options) {
 
34565             options = options || {};
 
34566             if (text) curtain.reveal(box, text, options.tooltipClass, options.duration);
 
34567             else curtain.reveal(box, '', '', options.duration);
 
34570         var steps = ['navigation', 'point', 'area', 'line', 'startEditing'].map(function(step, i) {
 
34571             var s = iD.ui.intro[step](context, reveal)
 
34572                 .on('done', function() {
 
34573                     entered.filter(function(d) {
 
34574                         return d.title === s.title;
 
34575                     }).classed('finished', true);
 
34576                     enter(steps[i + 1]);
 
34581         steps[steps.length - 1].on('startEditing', function() {
 
34584             d3.selectAll('#map .layer-background').style('opacity', opacity);
 
34585             context.connection().toggle(true).flush().loadedTiles(loadedTiles);
 
34586             context.history().reset().merge(d3.values(baseEntities));
 
34587             context.background().baseLayerSource(background);
 
34588             if (history) context.history().fromJSON(history, false);
 
34589             context.map().centerZoom(center, zoom);
 
34590             window.location.replace(hash);
 
34591             context.inIntro(false);
 
34594         var navwrap = selection.append('div').attr('class', 'intro-nav-wrap fillD');
 
34596         var buttonwrap = navwrap.append('div')
 
34597             .attr('class', 'joined')
 
34598             .selectAll('button.step');
 
34600         var entered = buttonwrap
 
34604             .attr('class', 'step')
 
34605             .on('click', enter);
 
34608             .call(iD.svg.Icon('#icon-apply', 'pre-text'));
 
34612             .text(function(d) { return t(d.title); });
 
34616         function enter (newStep) {
 
34617             if (step) { step.exit(); }
 
34619             context.enter(iD.modes.Browse(context));
 
34624             entered.classed('active', function(d) {
 
34625                 return d.title === step.title;
 
34633 iD.ui.intro.pointBox = function(point, context) {
 
34634     var rect = context.surfaceRect();
 
34635     point = context.projection(point);
 
34637         left: point[0] + rect.left - 30,
 
34638         top: point[1] + rect.top - 50,
 
34644 iD.ui.intro.pad = function(box, padding, context) {
 
34645     if (box instanceof Array) {
 
34646         var rect = context.surfaceRect();
 
34647         box = context.projection(box);
 
34649             left: box[0] + rect.left,
 
34650             top: box[1] + rect.top
 
34654         left: box.left - padding,
 
34655         top: box.top - padding,
 
34656         width: (box.width || 0) + 2 * padding,
 
34657         height: (box.width || 0) + 2 * padding
 
34661 iD.ui.intro.icon = function(name, svgklass) {
 
34662     return '<svg class="icon ' + (svgklass || '') + '">' +
 
34663         '<use xlink:href="' + name + '"></use></svg>';
 
34665 iD.ui.Lasso = function(context) {
 
34671     function lasso(selection) {
 
34673         context.container().classed('lasso', true);
 
34675         group = selection.append('g')
 
34676             .attr('class', 'lasso hide');
 
34678         box = group.append('rect')
 
34679             .attr('class', 'lasso-box');
 
34681         group.call(iD.ui.Toggle(true));
 
34686     function topLeft(d) {
 
34687         return 'translate(' + Math.min(d[0][0], d[1][0]) + ',' + Math.min(d[0][1], d[1][1]) + ')';
 
34690     function width(d) { return Math.abs(d[0][0] - d[1][0]); }
 
34691     function height(d) { return Math.abs(d[0][1] - d[1][1]); }
 
34696                 .attr('transform', topLeft)
 
34697                 .attr('width', width)
 
34698                 .attr('height', height);
 
34702     lasso.a = function(_) {
 
34703         if (!arguments.length) return a;
 
34709     lasso.b = function(_) {
 
34710         if (!arguments.length) return b;
 
34716     lasso.close = function() {
 
34718             group.call(iD.ui.Toggle(false, function() {
 
34719                 d3.select(this).remove();
 
34722         context.container().classed('lasso', false);
 
34727 iD.ui.Loading = function(context) {
 
34732     var loading = function(selection) {
 
34733         modal = iD.ui.modal(selection, blocking);
 
34735         var loadertext = modal.select('.content')
 
34736             .classed('loading-modal', true)
 
34738             .attr('class', 'modal-section fillL');
 
34740         loadertext.append('img')
 
34741             .attr('class', 'loader')
 
34742             .attr('src', context.imagePath('loader-white.gif'));
 
34744         loadertext.append('h3')
 
34747         modal.select('button.close')
 
34748             .attr('class', 'hide');
 
34753     loading.message = function(_) {
 
34754         if (!arguments.length) return message;
 
34759     loading.blocking = function(_) {
 
34760         if (!arguments.length) return blocking;
 
34765     loading.close = function() {
 
34771 iD.ui.MapData = function(context) {
 
34773         features = context.features().keys(),
 
34774         layers = context.layers(),
 
34775         fills = ['wireframe', 'partial', 'full'],
 
34776         fillDefault = context.storage('area-fill') || 'partial',
 
34777         fillSelected = fillDefault;
 
34780     function map_data(selection) {
 
34782         function showsFeature(d) {
 
34783             return context.features().enabled(d);
 
34786         function autoHiddenFeature(d) {
 
34787             return context.features().autoHidden(d);
 
34790         function clickFeature(d) {
 
34791             context.features().toggle(d);
 
34795         function showsFill(d) {
 
34796             return fillSelected === d;
 
34799         function setFill(d) {
 
34800             _.each(fills, function(opt) {
 
34801                 context.surface().classed('fill-' + opt, Boolean(opt === d));
 
34805             if (d !== 'wireframe') {
 
34807                 context.storage('area-fill', d);
 
34812         function toggleLayer(which) {
 
34813             var layer = layers.layer(which);
 
34815                 layer.enabled(!layer.enabled());
 
34820         function clickGpx() {
 
34821             toggleLayer('gpx');
 
34824         function clickMapillaryImages() {
 
34825             toggleLayer('mapillary-images');
 
34828         function clickMapillarySigns() {
 
34829             toggleLayer('mapillary-signs');
 
34833         function drawMapillaryItems(selection) {
 
34834             var mapillaryImages = layers.layer('mapillary-images'),
 
34835                 mapillarySigns = layers.layer('mapillary-signs'),
 
34836                 supportsMapillaryImages = mapillaryImages && mapillaryImages.supported(),
 
34837                 supportsMapillarySigns = mapillarySigns && mapillarySigns.supported(),
 
34838                 showsMapillaryImages = supportsMapillaryImages && mapillaryImages.enabled(),
 
34839                 showsMapillarySigns = supportsMapillarySigns && mapillarySigns.enabled();
 
34841             var mapillaryList = selection
 
34842                 .selectAll('.layer-list-mapillary')
 
34849                 .attr('class', 'layer-list layer-list-mapillary');
 
34851             var mapillaryImageLayerItem = mapillaryList
 
34852                 .selectAll('.list-item-mapillary-images')
 
34853                 .data(supportsMapillaryImages ? [0] : []);
 
34855             var enterImages = mapillaryImageLayerItem.enter()
 
34857                 .attr('class', 'list-item-mapillary-images');
 
34859             var labelImages = enterImages.append('label')
 
34860                 .call(bootstrap.tooltip()
 
34861                     .title(t('mapillary_images.tooltip'))
 
34862                     .placement('top'));
 
34864             labelImages.append('input')
 
34865                 .attr('type', 'checkbox')
 
34866                 .on('change', clickMapillaryImages);
 
34868             labelImages.append('span')
 
34869                 .text(t('mapillary_images.title'));
 
34872             var mapillarySignLayerItem = mapillaryList
 
34873                 .selectAll('.list-item-mapillary-signs')
 
34874                 .data(supportsMapillarySigns ? [0] : []);
 
34876             var enterSigns = mapillarySignLayerItem.enter()
 
34878                 .attr('class', 'list-item-mapillary-signs');
 
34880             var labelSigns = enterSigns.append('label')
 
34881                 .call(bootstrap.tooltip()
 
34882                     .title(t('mapillary_signs.tooltip'))
 
34883                     .placement('top'));
 
34885             labelSigns.append('input')
 
34886                 .attr('type', 'checkbox')
 
34887                 .on('change', clickMapillarySigns);
 
34889             labelSigns.append('span')
 
34890                 .text(t('mapillary_signs.title'));
 
34893             mapillaryImageLayerItem
 
34894                 .classed('active', showsMapillaryImages)
 
34895                 .selectAll('input')
 
34896                 .property('checked', showsMapillaryImages);
 
34898             mapillarySignLayerItem
 
34899                 .classed('active', showsMapillarySigns)
 
34900                 .selectAll('input')
 
34901                 .property('checked', showsMapillarySigns);
 
34904             mapillaryImageLayerItem.exit()
 
34906             mapillarySignLayerItem.exit()
 
34911         function drawGpxItem(selection) {
 
34912             var gpx = layers.layer('gpx'),
 
34913                 hasGpx = gpx && gpx.hasGpx(),
 
34914                 showsGpx = hasGpx && gpx.enabled();
 
34916             var gpxLayerItem = selection
 
34917                 .selectAll('.layer-list-gpx')
 
34918                 .data(gpx ? [0] : []);
 
34921             var enter = gpxLayerItem.enter()
 
34923                 .attr('class', 'layer-list layer-list-gpx')
 
34925                 .classed('list-item-gpx', true);
 
34927             enter.append('button')
 
34928                 .attr('class', 'list-item-gpx-extent')
 
34929                 .call(bootstrap.tooltip()
 
34930                     .title(t('gpx.zoom'))
 
34931                     .placement('left'))
 
34932                 .on('click', function() {
 
34933                     d3.event.preventDefault();
 
34934                     d3.event.stopPropagation();
 
34937                 .call(iD.svg.Icon('#icon-search'));
 
34939             enter.append('button')
 
34940                 .attr('class', 'list-item-gpx-browse')
 
34941                 .call(bootstrap.tooltip()
 
34942                     .title(t('gpx.browse'))
 
34943                     .placement('left'))
 
34944                 .on('click', function() {
 
34945                     d3.select(document.createElement('input'))
 
34946                         .attr('type', 'file')
 
34947                         .on('change', function() {
 
34948                             gpx.files(d3.event.target.files);
 
34952                 .call(iD.svg.Icon('#icon-geolocate'));
 
34954             var labelGpx = enter.append('label')
 
34955                 .call(bootstrap.tooltip()
 
34956                     .title(t('gpx.drag_drop'))
 
34957                     .placement('top'));
 
34959             labelGpx.append('input')
 
34960                 .attr('type', 'checkbox')
 
34961                 .on('change', clickGpx);
 
34963             labelGpx.append('span')
 
34964                 .text(t('gpx.local_layer'));
 
34968                 .classed('active', showsGpx)
 
34969                 .selectAll('input')
 
34970                 .property('disabled', !hasGpx)
 
34971                 .property('checked', showsGpx);
 
34974             gpxLayerItem.exit()
 
34979         function drawList(selection, data, type, name, change, active) {
 
34980             var items = selection.selectAll('li')
 
34984             var enter = items.enter()
 
34986                 .attr('class', 'layer')
 
34987                 .call(bootstrap.tooltip()
 
34989                     .title(function(d) {
 
34990                         var tip = t(name + '.' + d + '.tooltip'),
 
34991                             key = (d === 'wireframe' ? 'W' : null);
 
34993                         if (name === 'feature' && autoHiddenFeature(d)) {
 
34994                             tip += '<div>' + t('map_data.autohidden') + '</div>';
 
34996                         return iD.ui.tooltipHtml(tip, key);
 
35001             var label = enter.append('label');
 
35003             label.append('input')
 
35004                 .attr('type', type)
 
35005                 .attr('name', name)
 
35006                 .on('change', change);
 
35008             label.append('span')
 
35009                 .text(function(d) { return t(name + '.' + d + '.description'); });
 
35013                 .classed('active', active)
 
35014                 .selectAll('input')
 
35015                 .property('checked', active)
 
35016                 .property('indeterminate', function(d) {
 
35017                     return (name === 'feature' && autoHiddenFeature(d));
 
35026         function update() {
 
35027             dataLayerContainer.call(drawMapillaryItems);
 
35028             dataLayerContainer.call(drawGpxItem);
 
35030             fillList.call(drawList, fills, 'radio', 'area_fill', setFill, showsFill);
 
35032             featureList.call(drawList, features, 'checkbox', 'feature', clickFeature, showsFeature);
 
35035         function hidePanel() {
 
35039         function togglePanel() {
 
35040             if (d3.event) d3.event.preventDefault();
 
35041             tooltip.hide(button);
 
35042             setVisible(!button.classed('active'));
 
35045         function toggleWireframe() {
 
35047                 d3.event.preventDefault();
 
35048                 d3.event.stopPropagation();
 
35050             setFill((fillSelected === 'wireframe' ? fillDefault : 'wireframe'));
 
35051             context.map().pan([0,0]);  // trigger a redraw
 
35054         function setVisible(show) {
 
35055             if (show !== shown) {
 
35056                 button.classed('active', show);
 
35061                     selection.on('mousedown.map_data-inside', function() {
 
35062                         return d3.event.stopPropagation();
 
35064                     content.style('display', 'block')
 
35065                         .style('right', '-300px')
 
35068                         .style('right', '0px');
 
35070                     content.style('display', 'block')
 
35071                         .style('right', '0px')
 
35074                         .style('right', '-300px')
 
35075                         .each('end', function() {
 
35076                             d3.select(this).style('display', 'none');
 
35078                     selection.on('mousedown.map_data-inside', null);
 
35084         var content = selection.append('div')
 
35085                 .attr('class', 'fillL map-overlay col3 content hide'),
 
35086             tooltip = bootstrap.tooltip()
 
35089                 .title(iD.ui.tooltipHtml(t('map_data.description'), key)),
 
35090             button = selection.append('button')
 
35091                 .attr('tabindex', -1)
 
35092                 .on('click', togglePanel)
 
35093                 .call(iD.svg.Icon('#icon-data', 'light'))
 
35097         content.append('h4')
 
35098             .text(t('map_data.title'));
 
35102         content.append('a')
 
35103             .text(t('map_data.data_layers'))
 
35105             .classed('hide-toggle', true)
 
35106             .classed('expanded', true)
 
35107             .on('click', function() {
 
35108                 var exp = d3.select(this).classed('expanded');
 
35109                 dataLayerContainer.style('display', exp ? 'none' : 'block');
 
35110                 d3.select(this).classed('expanded', !exp);
 
35111                 d3.event.preventDefault();
 
35114         var dataLayerContainer = content.append('div')
 
35115             .attr('class', 'data-data-layers')
 
35116             .style('display', 'block');
 
35120         content.append('a')
 
35121             .text(t('map_data.fill_area'))
 
35123             .classed('hide-toggle', true)
 
35124             .classed('expanded', false)
 
35125             .on('click', function() {
 
35126                 var exp = d3.select(this).classed('expanded');
 
35127                 fillContainer.style('display', exp ? 'none' : 'block');
 
35128                 d3.select(this).classed('expanded', !exp);
 
35129                 d3.event.preventDefault();
 
35132         var fillContainer = content.append('div')
 
35133             .attr('class', 'data-area-fills')
 
35134             .style('display', 'none');
 
35136         var fillList = fillContainer.append('ul')
 
35137             .attr('class', 'layer-list layer-fill-list');
 
35141         content.append('a')
 
35142             .text(t('map_data.map_features'))
 
35144             .classed('hide-toggle', true)
 
35145             .classed('expanded', false)
 
35146             .on('click', function() {
 
35147                 var exp = d3.select(this).classed('expanded');
 
35148                 featureContainer.style('display', exp ? 'none' : 'block');
 
35149                 d3.select(this).classed('expanded', !exp);
 
35150                 d3.event.preventDefault();
 
35153         var featureContainer = content.append('div')
 
35154             .attr('class', 'data-feature-filters')
 
35155             .style('display', 'none');
 
35157         var featureList = featureContainer.append('ul')
 
35158             .attr('class', 'layer-list layer-feature-list');
 
35162             .on('change.map_data-update', update);
 
35164         setFill(fillDefault);
 
35166         var keybinding = d3.keybinding('features')
 
35167             .on(key, togglePanel)
 
35168             .on('W', toggleWireframe)
 
35169             .on('B', hidePanel)
 
35170             .on('H', hidePanel);
 
35172         d3.select(document)
 
35175         context.surface().on('mousedown.map_data-outside', hidePanel);
 
35176         context.container().on('mousedown.map_data-outside', hidePanel);
 
35181 iD.ui.MapInMap = function(context) {
 
35184     function map_in_map(selection) {
 
35185         var backgroundLayer = iD.TileLayer(),
 
35186             overlayLayers = {},
 
35187             projection = iD.geo.RawMercator(),
 
35188             gpxLayer = iD.svg.Gpx(projection, context).showLabels(false),
 
35189             zoom = d3.behavior.zoom()
 
35190                 .scaleExtent([ztok(0.5), ztok(24)])
 
35191                 .on('zoom', zoomPan),
 
35192             transformed = false,
 
35195             zDiff = 6,    // by default, minimap renders at (main zoom - 6)
 
35196             tStart, tLast, tCurr, kLast, kCurr, tiles, svg, timeoutId;
 
35198         function ztok(z) { return 256 * Math.pow(2, z); }
 
35199         function ktoz(k) { return Math.log(k) / Math.LN2 - 8; }
 
35202         function startMouse() {
 
35203             context.surface().on('mouseup.map-in-map-outside', endMouse);
 
35204             context.container().on('mouseup.map-in-map-outside', endMouse);
 
35206             tStart = tLast = tCurr = projection.translate();
 
35211         function zoomPan() {
 
35212             var e = d3.event.sourceEvent,
 
35213                 t = d3.event.translate,
 
35214                 k = d3.event.scale,
 
35215                 zMain = ktoz(context.projection.scale() * 2 * Math.PI),
 
35218             // restrict minimap zoom to < (main zoom - 3)
 
35219             if (zMini > zMain - 3) {
 
35221                 zoom.scale(kCurr).translate(tCurr);  // restore last good values
 
35227             zDiff = zMain - zMini;
 
35229             var scale = kCurr / kLast,
 
35230                 tX = (tCurr[0] / scale - tLast[0]) * scale,
 
35231                 tY = (tCurr[1] / scale - tLast[1]) * scale;
 
35233             iD.util.setTransform(tiles, tX, tY, scale);
 
35234             iD.util.setTransform(svg, 0, 0, scale);
 
35235             transformed = true;
 
35239             e.preventDefault();
 
35240             e.stopPropagation();
 
35244         function endMouse() {
 
35245             context.surface().on('mouseup.map-in-map-outside', null);
 
35246             context.container().on('mouseup.map-in-map-outside', null);
 
35248             updateProjection();
 
35251             if (tCurr[0] !== tStart[0] && tCurr[1] !== tStart[1]) {
 
35252                 var dMini = wrap.dimensions(),
 
35253                     cMini = [ dMini[0] / 2, dMini[1] / 2 ];
 
35255                 context.map().center(projection.invert(cMini));
 
35260         function updateProjection() {
 
35261             var loc = context.map().center(),
 
35262                 dMini = wrap.dimensions(),
 
35263                 cMini = [ dMini[0] / 2, dMini[1] / 2 ],
 
35264                 tMain = context.projection.translate(),
 
35265                 kMain = context.projection.scale(),
 
35266                 zMain = ktoz(kMain * 2 * Math.PI),
 
35267                 zMini = Math.max(zMain - zDiff, 0.5),
 
35268                 kMini = ztok(zMini);
 
35272                 .scale(kMini / (2 * Math.PI));
 
35274             var s = projection(loc),
 
35275                 mouse = panning ? [ tCurr[0] - tStart[0], tCurr[1] - tStart[1] ] : [0, 0],
 
35277                     cMini[0] - s[0] + tMain[0] + mouse[0],
 
35278                     cMini[1] - s[1] + tMain[1] + mouse[1]
 
35283                 .clipExtent([[0, 0], dMini]);
 
35290             tLast = tCurr = tMini;
 
35291             kLast = kCurr = kMini;
 
35294                 iD.util.setTransform(tiles, 0, 0);
 
35295                 iD.util.setTransform(svg, 0, 0);
 
35296                 transformed = false;
 
35301         function redraw() {
 
35302             if (hidden) return;
 
35304             updateProjection();
 
35306             var dMini = wrap.dimensions(),
 
35307                 zMini = ktoz(projection.scale() * 2 * Math.PI);
 
35309             // setup tile container
 
35311                 .selectAll('.map-in-map-tiles')
 
35317                 .attr('class', 'map-in-map-tiles');
 
35319             // redraw background
 
35321                 .source(context.background().baseLayerSource())
 
35322                 .projection(projection)
 
35323                 .dimensions(dMini);
 
35325             var background = tiles
 
35326                 .selectAll('.map-in-map-background')
 
35331                 .attr('class', 'map-in-map-background');
 
35334                 .call(backgroundLayer);
 
35338             var overlaySources = context.background().overlayLayerSources();
 
35339             var activeOverlayLayers = [];
 
35340             for (var i = 0; i < overlaySources.length; i++) {
 
35341                 if (overlaySources[i].validZoom(zMini)) {
 
35342                     if (!overlayLayers[i]) overlayLayers[i] = iD.TileLayer();
 
35343                     activeOverlayLayers.push(overlayLayers[i]
 
35344                         .source(overlaySources[i])
 
35345                         .projection(projection)
 
35346                         .dimensions(dMini));
 
35350             var overlay = tiles
 
35351                 .selectAll('.map-in-map-overlay')
 
35356                 .attr('class', 'map-in-map-overlay');
 
35358             var overlays = overlay
 
35360                 .data(activeOverlayLayers, function(d) { return d.source().name(); });
 
35362             overlays.enter().append('div');
 
35363             overlays.each(function(layer) {
 
35364                 d3.select(this).call(layer);
 
35372                 .selectAll('.map-in-map-gpx')
 
35373                 .data(gpxLayer.enabled() ? [0] : []);
 
35377                 .attr('class', 'map-in-map-gpx');
 
35382             gpx.call(gpxLayer);
 
35385             // redraw bounding box
 
35387                 var getPath = d3.geo.path().projection(projection),
 
35388                     bbox = { type: 'Polygon', coordinates: [context.map().extent().polygon()] };
 
35390                 svg = wrap.selectAll('.map-in-map-svg')
 
35395                     .attr('class', 'map-in-map-svg');
 
35397                 var path = svg.selectAll('.map-in-map-bbox')
 
35402                     .attr('class', 'map-in-map-bbox');
 
35405                     .attr('d', getPath)
 
35406                     .classed('thick', function(d) { return getPath.area(d) < 30; });
 
35411         function queueRedraw() {
 
35412             clearTimeout(timeoutId);
 
35413             timeoutId = setTimeout(function() { redraw(); }, 300);
 
35417         function toggle() {
 
35418             if (d3.event) d3.event.preventDefault();
 
35422             var label = d3.select('.minimap-toggle');
 
35423             label.classed('active', !hidden)
 
35424                 .select('input').property('checked', !hidden);
 
35428                     .style('display', 'block')
 
35429                     .style('opacity', 1)
 
35432                     .style('opacity', 0)
 
35433                     .each('end', function() {
 
35434                         d3.select(this).style('display', 'none');
 
35438                     .style('display', 'block')
 
35439                     .style('opacity', 0)
 
35442                     .style('opacity', 1);
 
35448         iD.ui.MapInMap.toggle = toggle;
 
35450         var wrap = selection.selectAll('.map-in-map')
 
35455             .attr('class', 'map-in-map')
 
35456             .style('display', (hidden ? 'none' : 'block'))
 
35457             .on('mousedown.map-in-map', startMouse)
 
35458             .on('mouseup.map-in-map', endMouse)
 
35460             .on('dblclick.zoom', null);
 
35463             .on('drawn.map-in-map', function(drawn) {
 
35464                 if (drawn.full === true) redraw();
 
35469         var keybinding = d3.keybinding('map-in-map')
 
35472         d3.select(document)
 
35478 iD.ui.modal = function(selection, blocking) {
 
35480     var previous = selection.select('div.modal');
 
35481     var animate = previous.empty();
 
35483     previous.transition()
 
35485         .style('opacity', 0)
 
35488     var shaded = selection
 
35490         .attr('class', 'shaded')
 
35491         .style('opacity', 0);
 
35493     shaded.close = function() {
 
35497             .style('opacity',0)
 
35502             .style('top','0px');
 
35506     var keybinding = d3.keybinding('modal')
 
35507         .on('⌫', shaded.close)
 
35508         .on('⎋', shaded.close);
 
35510     d3.select(document).call(keybinding);
 
35512     var modal = shaded.append('div')
 
35513         .attr('class', 'modal fillL col6');
 
35515         shaded.on('click.remove-modal', function() {
 
35516             if (d3.event.target === this && !blocking) shaded.close();
 
35519     modal.append('button')
 
35520         .attr('class', 'close')
 
35521         .on('click', function() {
 
35522             if (!blocking) shaded.close();
 
35525             .attr('class','icon close');
 
35527     modal.append('div')
 
35528         .attr('class', 'content');
 
35531         shaded.transition().style('opacity', 1);
 
35533         shaded.style('opacity', 1);
 
35538 iD.ui.Modes = function(context) {
 
35540         iD.modes.AddPoint(context),
 
35541         iD.modes.AddLine(context),
 
35542         iD.modes.AddArea(context)];
 
35544     function editable() {
 
35545         return context.editable() && context.mode().id !== 'save';
 
35548     return function(selection) {
 
35549         var buttons = selection.selectAll('button.add-button')
 
35552        buttons.enter().append('button')
 
35553            .attr('tabindex', -1)
 
35554            .attr('class', function(mode) { return mode.id + ' add-button col4'; })
 
35555            .on('click.mode-buttons', function(mode) {
 
35556                if (mode.id === context.mode().id) {
 
35557                    context.enter(iD.modes.Browse(context));
 
35559                    context.enter(mode);
 
35562            .call(bootstrap.tooltip()
 
35563                .placement('bottom')
 
35565                .title(function(mode) {
 
35566                    return iD.ui.tooltipHtml(mode.description, mode.key);
 
35570             .on('move.modes', _.debounce(update, 500));
 
35573             .on('enter.modes', update);
 
35575         buttons.each(function(d) {
 
35577                 .call(iD.svg.Icon('#icon-' + d.button, 'pre-text'));
 
35580         buttons.append('span')
 
35581             .attr('class', 'label')
 
35582             .text(function(mode) { return mode.title; });
 
35584         context.on('enter.editor', function(entered) {
 
35585             buttons.classed('active', function(mode) { return entered.button === mode.button; });
 
35586             context.container()
 
35587                 .classed('mode-' + entered.id, true);
 
35590         context.on('exit.editor', function(exited) {
 
35591             context.container()
 
35592                 .classed('mode-' + exited.id, false);
 
35595         var keybinding = d3.keybinding('mode-buttons');
 
35597         modes.forEach(function(m) {
 
35598             keybinding.on(m.key, function() { if (editable()) context.enter(m); });
 
35601         d3.select(document)
 
35604         function update() {
 
35605             buttons.property('disabled', !editable());
 
35609 iD.ui.Notice = function(context) {
 
35610     return function(selection) {
 
35611         var div = selection.append('div')
 
35612             .attr('class', 'notice');
 
35614         var button = div.append('button')
 
35615             .attr('class', 'zoom-to notice')
 
35616             .on('click', function() { context.map().zoom(context.minEditableZoom()); });
 
35619             .call(iD.svg.Icon('#icon-plus', 'pre-text'))
 
35621             .attr('class', 'label')
 
35622             .text(t('zoom_in_edit'));
 
35624         function disableTooHigh() {
 
35625             div.style('display', context.editable() ? 'none' : 'block');
 
35629             .on('move.notice', _.debounce(disableTooHigh, 500));
 
35634 iD.ui.PresetIcon = function() {
 
35635     var preset, geometry;
 
35637     function presetIcon(selection) {
 
35638         selection.each(render);
 
35641     function render() {
 
35642         var selection = d3.select(this),
 
35643             p = preset.apply(this, arguments),
 
35644             geom = geometry.apply(this, arguments),
 
35645             icon = p.icon || (geom === 'line' ? 'other-line' : 'marker-stroked'),
 
35646             maki = iD.data.featureIcons.hasOwnProperty(icon + '-24');
 
35648         if (icon === 'dentist') maki = true;  // workaround for dentist icon missing in `maki-sprite.json`
 
35650         function tag_classes(p) {
 
35652             for (var i in p.tags) {
 
35654                 if (p.tags[i] !== '*') {
 
35655                     s += ' tag-' + i + '-' + p.tags[i];
 
35661         var $fill = selection.selectAll('.preset-icon-fill')
 
35664         $fill.enter().append('div');
 
35666         $fill.attr('class', function() {
 
35667             return 'preset-icon-fill preset-icon-fill-' + geom + tag_classes(p);
 
35670         var $frame = selection.selectAll('.preset-icon-frame')
 
35675             .call(iD.svg.Icon('#preset-icon-frame'));
 
35677         $frame.attr('class', function() {
 
35678             return 'preset-icon-frame ' + (geom === 'area' ? '' : 'hide');
 
35682         var $icon = selection.selectAll('.preset-icon')
 
35687             .attr('class', 'preset-icon')
 
35688             .call(iD.svg.Icon(''));
 
35691             .attr('class', 'preset-icon preset-icon-' + (maki ? '32' : (geom === 'area' ? '44' : '60')));
 
35693         $icon.selectAll('svg')
 
35694             .attr('class', function() {
 
35695                 return 'icon ' + icon + tag_classes(p);
 
35698         $icon.selectAll('use')       // workaround: maki parking-24 broken?
 
35699             .attr('href', '#' + icon + (maki ? ( icon === 'parking' ? '-18' : '-24') : ''));
 
35702     presetIcon.preset = function(_) {
 
35703         if (!arguments.length) return preset;
 
35704         preset = d3.functor(_);
 
35708     presetIcon.geometry = function(_) {
 
35709         if (!arguments.length) return geometry;
 
35710         geometry = d3.functor(_);
 
35716 iD.ui.preset = function(context) {
 
35717     var event = d3.dispatch('change'),
 
35724     function UIField(field, entity, show) {
 
35725         field = _.clone(field);
 
35727         field.input = iD.ui.preset[field.type](field, context)
 
35728             .on('change', event.change);
 
35730         if (field.input.entity) field.input.entity(entity);
 
35732         field.keys = field.keys || [field.key];
 
35736         field.shown = function() {
 
35737             return field.id === 'name' || field.show || _.any(field.keys, function(key) { return !!tags[key]; });
 
35740         field.modified = function() {
 
35741             var original = context.graph().base().entities[entity.id];
 
35742             return _.any(field.keys, function(key) {
 
35743                 return original ? tags[key] !== original.tags[key] : tags[key];
 
35747         field.revert = function() {
 
35748             var original = context.graph().base().entities[entity.id],
 
35750             field.keys.forEach(function(key) {
 
35751                 t[key] = original ? original.tags[key] : undefined;
 
35756         field.present = function() {
 
35757             return _.any(field.keys, function(key) {
 
35762         field.remove = function() {
 
35764             field.keys.forEach(function(key) {
 
35765                 t[key] = undefined;
 
35773     function fieldKey(field) {
 
35777     function presets(selection) {
 
35778         selection.call(iD.ui.Disclosure()
 
35779             .title(t('inspector.all_fields'))
 
35780             .expanded(context.storage('preset_fields.expanded') !== 'false')
 
35781             .on('toggled', toggled)
 
35782             .content(content));
 
35784         function toggled(expanded) {
 
35785             context.storage('preset_fields.expanded', expanded);
 
35789     function content(selection) {
 
35791             var entity = context.entity(id),
 
35792                 geometry = context.geometry(id);
 
35794             fields = [UIField(context.presets().field('name'), entity)];
 
35796             preset.fields.forEach(function(field) {
 
35797                 if (field.matchGeometry(geometry)) {
 
35798                     fields.push(UIField(field, entity, true));
 
35802             if (entity.isHighwayIntersection(context.graph())) {
 
35803                 fields.push(UIField(context.presets().field('restrictions'), entity, true));
 
35806             context.presets().universal().forEach(function(field) {
 
35807                 if (preset.fields.indexOf(field) < 0) {
 
35808                     fields.push(UIField(field, entity));
 
35813         var shown = fields.filter(function(field) { return field.shown(); }),
 
35814             notShown = fields.filter(function(field) { return !field.shown(); });
 
35816         var $form = selection.selectAll('.preset-form')
 
35819         $form.enter().append('div')
 
35820             .attr('class', 'preset-form inspector-inner fillL3');
 
35822         var $fields = $form.selectAll('.form-field')
 
35823             .data(shown, fieldKey);
 
35827         var $enter = $fields.enter()
 
35829             .attr('class', function(field) {
 
35830                 return 'form-field form-field-' + field.id;
 
35833         var $label = $enter.append('label')
 
35834             .attr('class', 'form-label')
 
35835             .attr('for', function(field) { return 'preset-input-' + field.id; })
 
35836             .text(function(field) { return field.label(); });
 
35838         var wrap = $label.append('div')
 
35839             .attr('class', 'form-label-button-wrap');
 
35841         wrap.append('button')
 
35842             .attr('class', 'remove-icon')
 
35843             .call(iD.svg.Icon('#operation-delete'));
 
35845         wrap.append('button')
 
35846             .attr('class', 'modified-icon')
 
35847             .attr('tabindex', -1)
 
35848             .call(iD.svg.Icon('#icon-undo'));
 
35852         $fields.select('.form-label-button-wrap .remove-icon')
 
35853             .on('click', remove);
 
35855         $fields.select('.modified-icon')
 
35856             .on('click', revert);
 
35860             .classed('modified', function(field) {
 
35861                 return field.modified();
 
35863             .classed('present', function(field) {
 
35864                 return field.present();
 
35866             .each(function(field) {
 
35867                 var reference = iD.ui.TagReference(field.reference || {key: field.key}, context);
 
35869                 if (state === 'hover') {
 
35870                     reference.showing(false);
 
35875                     .selectAll('input')
 
35876                     .on('keydown', function() {
 
35877                         if (d3.event.keyCode === 13) {  // enter
 
35878                             context.enter(iD.modes.Browse(context));
 
35881                     .call(reference.body)
 
35882                     .select('.form-label-button-wrap')
 
35883                     .call(reference.button);
 
35885                 field.input.tags(tags);
 
35891         notShown = notShown.map(function(field) {
 
35893                 title: field.label(),
 
35894                 value: field.label(),
 
35899         var $more = selection.selectAll('.more-fields')
 
35900             .data((notShown.length > 0) ? [0] : []);
 
35902         $more.enter().append('div')
 
35903             .attr('class', 'more-fields')
 
35905                 .text(t('inspector.add_fields'));
 
35907         var $input = $more.selectAll('.value')
 
35910         $input.enter().append('input')
 
35911             .attr('class', 'value')
 
35912             .attr('type', 'text');
 
35915             .attr('placeholder', function() {
 
35916                 var placeholder = [];
 
35917                 for (var field in notShown) {
 
35918                     placeholder.push(notShown[field].title);
 
35920                 return placeholder.slice(0,3).join(', ') + ((placeholder.length > 3) ? '…' : '');
 
35922             .call(d3.combobox().data(notShown)
 
35924                 .on('accept', show));
 
35932         function show(field) {
 
35933             field = field.field;
 
35935             content(selection);
 
35936             field.input.focus();
 
35939         function revert(field) {
 
35940             d3.event.stopPropagation();
 
35941             d3.event.preventDefault();
 
35942             event.change(field.revert());
 
35945         function remove(field) {
 
35946             d3.event.stopPropagation();
 
35947             d3.event.preventDefault();
 
35948             event.change(field.remove());
 
35952     presets.preset = function(_) {
 
35953         if (!arguments.length) return preset;
 
35954         if (preset && preset.id === _.id) return presets;
 
35960     presets.state = function(_) {
 
35961         if (!arguments.length) return state;
 
35966     presets.tags = function(_) {
 
35967         if (!arguments.length) return tags;
 
35969         // Don't reset fields here.
 
35973     presets.entityID = function(_) {
 
35974         if (!arguments.length) return id;
 
35975         if (id === _) return presets;
 
35981     return d3.rebind(presets, event, 'on');
 
35983 iD.ui.PresetList = function(context) {
 
35984     var event = d3.dispatch('choose'),
 
35989     function presetList(selection) {
 
35990         var geometry = context.geometry(id),
 
35991             presets = context.presets().matchGeometry(geometry);
 
35993         selection.html('');
 
35995         var messagewrap = selection.append('div')
 
35996             .attr('class', 'header fillL cf');
 
35998         var message = messagewrap.append('h3')
 
35999             .text(t('inspector.choose'));
 
36001         if (context.entity(id).isUsed(context.graph())) {
 
36002             messagewrap.append('button')
 
36003                 .attr('class', 'preset-choose')
 
36004                 .on('click', function() { event.choose(currentPreset); })
 
36008             messagewrap.append('button')
 
36009                 .attr('class', 'close')
 
36010                 .on('click', function() {
 
36011                     context.enter(iD.modes.Browse(context));
 
36013                 .call(iD.svg.Icon('#icon-close'));
 
36016         function keydown() {
 
36017             // hack to let delete shortcut work when search is autofocused
 
36018             if (search.property('value').length === 0 &&
 
36019                 (d3.event.keyCode === d3.keybinding.keyCodes['⌫'] ||
 
36020                  d3.event.keyCode === d3.keybinding.keyCodes['⌦'])) {
 
36021                 d3.event.preventDefault();
 
36022                 d3.event.stopPropagation();
 
36023                 iD.operations.Delete([id], context)();
 
36024             } else if (search.property('value').length === 0 &&
 
36025                 (d3.event.ctrlKey || d3.event.metaKey) &&
 
36026                 d3.event.keyCode === d3.keybinding.keyCodes.z) {
 
36027                 d3.event.preventDefault();
 
36028                 d3.event.stopPropagation();
 
36030             } else if (!d3.event.ctrlKey && !d3.event.metaKey) {
 
36031                 d3.select(this).on('keydown', null);
 
36035         function keypress() {
 
36037             var value = search.property('value');
 
36038             if (d3.event.keyCode === 13 && value.length) {
 
36039                 list.selectAll('.preset-list-item:first-child').datum().choose();
 
36043         function inputevent() {
 
36044             var value = search.property('value');
 
36045             list.classed('filtered', value.length);
 
36046             if (value.length) {
 
36047                 var results = presets.search(value, geometry);
 
36048                 message.text(t('inspector.results', {
 
36049                     n: results.collection.length,
 
36052                 list.call(drawList, results);
 
36054                 list.call(drawList, context.presets().defaults(geometry, 36));
 
36055                 message.text(t('inspector.choose'));
 
36059         var searchWrap = selection.append('div')
 
36060             .attr('class', 'search-header');
 
36062         var search = searchWrap.append('input')
 
36063             .attr('class', 'preset-search-input')
 
36064             .attr('placeholder', t('inspector.search'))
 
36065             .attr('type', 'search')
 
36066             .on('keydown', keydown)
 
36067             .on('keypress', keypress)
 
36068             .on('input', inputevent);
 
36071             .call(iD.svg.Icon('#icon-search', 'pre-text'));
 
36074             search.node().focus();
 
36077         var listWrap = selection.append('div')
 
36078             .attr('class', 'inspector-body');
 
36080         var list = listWrap.append('div')
 
36081             .attr('class', 'preset-list fillL cf')
 
36082             .call(drawList, context.presets().defaults(geometry, 36));
 
36085     function drawList(list, presets) {
 
36086         var collection = presets.collection.map(function(preset) {
 
36087             return preset.members ? CategoryItem(preset) : PresetItem(preset);
 
36090         var items = list.selectAll('.preset-list-item')
 
36091             .data(collection, function(d) { return d.preset.id; });
 
36093         items.enter().append('div')
 
36094             .attr('class', function(item) { return 'preset-list-item preset-' + item.preset.id.replace('/', '-'); })
 
36095             .classed('current', function(item) { return item.preset === currentPreset; })
 
36096             .each(function(item) {
 
36097                 d3.select(this).call(item);
 
36099             .style('opacity', 0)
 
36101             .style('opacity', 1);
 
36109     function CategoryItem(preset) {
 
36110         var box, sublist, shown = false;
 
36112         function item(selection) {
 
36113             var wrap = selection.append('div')
 
36114                 .attr('class', 'preset-list-button-wrap category col12');
 
36116             wrap.append('button')
 
36117                 .attr('class', 'preset-list-button')
 
36118                 .classed('expanded', false)
 
36119                 .call(iD.ui.PresetIcon()
 
36120                     .geometry(context.geometry(id))
 
36122                 .on('click', function() {
 
36123                     var isExpanded = d3.select(this).classed('expanded');
 
36124                     var triangle = isExpanded ? '▶ ' :  '▼ ';
 
36125                     d3.select(this).classed('expanded', !isExpanded);
 
36126                     d3.select(this).selectAll('.label').text(triangle + preset.name());
 
36130                 .attr('class', 'label')
 
36132                   return '▶ ' + preset.name();
 
36135             box = selection.append('div')
 
36136                 .attr('class', 'subgrid col12')
 
36137                 .style('max-height', '0px')
 
36138                 .style('opacity', 0);
 
36141                 .attr('class', 'arrow');
 
36143             sublist = box.append('div')
 
36144                 .attr('class', 'preset-list fillL3 cf fl');
 
36147         item.choose = function() {
 
36148             if (!box || !sublist) return;
 
36154                     .style('opacity', '0')
 
36155                     .style('max-height', '0px')
 
36156                     .style('padding-bottom', '0px');
 
36159                 sublist.call(drawList, preset.members);
 
36162                     .style('opacity', '1')
 
36163                     .style('max-height', 200 + preset.members.collection.length * 80 + 'px')
 
36164                     .style('padding-bottom', '20px');
 
36168         item.preset = preset;
 
36173     function PresetItem(preset) {
 
36174         function item(selection) {
 
36175             var wrap = selection.append('div')
 
36176                 .attr('class', 'preset-list-button-wrap col12');
 
36178             wrap.append('button')
 
36179                 .attr('class', 'preset-list-button')
 
36180                 .call(iD.ui.PresetIcon()
 
36181                     .geometry(context.geometry(id))
 
36183                 .on('click', item.choose)
 
36185                 .attr('class', 'label')
 
36186                 .text(preset.name());
 
36188             wrap.call(item.reference.button);
 
36189             selection.call(item.reference.body);
 
36192         item.choose = function() {
 
36193             context.presets().choose(preset);
 
36196                 iD.actions.ChangePreset(id, currentPreset, preset),
 
36197                 t('operations.change_tags.annotation'));
 
36199             event.choose(preset);
 
36202         item.help = function() {
 
36203             d3.event.stopPropagation();
 
36204             item.reference.toggle();
 
36207         item.preset = preset;
 
36208         item.reference = iD.ui.TagReference(preset.reference(context.geometry(id)), context);
 
36213     presetList.autofocus = function(_) {
 
36214         if (!arguments.length) return autofocus;
 
36219     presetList.entityID = function(_) {
 
36220         if (!arguments.length) return id;
 
36222         presetList.preset(context.presets().match(context.entity(id), context.graph()));
 
36226     presetList.preset = function(_) {
 
36227         if (!arguments.length) return currentPreset;
 
36232     return d3.rebind(presetList, event, 'on');
 
36234 iD.ui.RadialMenu = function(context, operations) {
 
36239     var radialMenu = function(selection) {
 
36240         if (!operations.length)
 
36243         selection.node().parentNode.focus();
 
36245         function click(operation) {
 
36246             d3.event.stopPropagation();
 
36247             if (operation.disabled())
 
36250             radialMenu.close();
 
36253         menu = selection.append('g')
 
36254             .attr('class', 'radial-menu')
 
36255             .attr('transform', 'translate(' + center + ')')
 
36256             .attr('opacity', 0);
 
36259             .attr('opacity', 1);
 
36264             a1 = a0 + (operations.length - 1) * a;
 
36266         menu.append('path')
 
36267             .attr('class', 'radial-menu-background')
 
36268             .attr('d', 'M' + r * Math.sin(a0) + ',' +
 
36270                       ' A' + r + ',' + r + ' 0 ' + (operations.length > 5 ? '1' : '0') + ',0 ' +
 
36271                              (r * Math.sin(a1) + 1e-3) + ',' +
 
36272                              (r * Math.cos(a1) + 1e-3)) // Force positive-length path (#1305)
 
36273             .attr('stroke-width', 50)
 
36274             .attr('stroke-linecap', 'round');
 
36276         var button = menu.selectAll()
 
36280             .attr('class', function(d) { return 'radial-menu-item radial-menu-item-' + d.id; })
 
36281             .classed('disabled', function(d) { return d.disabled(); })
 
36282             .attr('transform', function(d, i) {
 
36283                 return 'translate(' + iD.geo.roundCoords([
 
36284                         r * Math.sin(a0 + i * a),
 
36285                         r * Math.cos(a0 + i * a)]).join(',') + ')';
 
36288         button.append('circle')
 
36290             .on('click', click)
 
36291             .on('mousedown', mousedown)
 
36292             .on('mouseover', mouseover)
 
36293             .on('mouseout', mouseout);
 
36295         button.append('use')
 
36296             .attr('transform', 'translate(-10,-10)')
 
36297             .attr('width', '20')
 
36298             .attr('height', '20')
 
36299             .attr('xlink:href', function(d) { return '#operation-' + d.id; });
 
36301         tooltip = d3.select(document.body)
 
36303             .attr('class', 'tooltip-inner radial-menu-tooltip');
 
36305         function mousedown() {
 
36306             d3.event.stopPropagation(); // https://github.com/openstreetmap/iD/issues/1869
 
36309         function mouseover(d, i) {
 
36310             var rect = context.surfaceRect(),
 
36311                 angle = a0 + i * a,
 
36312                 top = rect.top + (r + 25) * Math.cos(angle) + center[1] + 'px',
 
36313                 left = rect.left + (r + 25) * Math.sin(angle) + center[0] + 'px',
 
36314                 bottom = rect.height - (r + 25) * Math.cos(angle) - center[1] + 'px',
 
36315                 right = rect.width - (r + 25) * Math.sin(angle) - center[0] + 'px';
 
36318                 .style('top', null)
 
36319                 .style('left', null)
 
36320                 .style('bottom', null)
 
36321                 .style('right', null)
 
36322                 .style('display', 'block')
 
36323                 .html(iD.ui.tooltipHtml(d.tooltip(), d.keys[0]));
 
36327                     .style('right', right)
 
36328                     .style('top', top);
 
36329             } else if (i >= 4) {
 
36331                     .style('left', left)
 
36332                     .style('bottom', bottom);
 
36335                     .style('left', left)
 
36336                     .style('top', top);
 
36340         function mouseout() {
 
36341             tooltip.style('display', 'none');
 
36345     radialMenu.close = function() {
 
36348                 .style('pointer-events', 'none')
 
36350                 .attr('opacity', 0)
 
36359     radialMenu.center = function(_) {
 
36360         if (!arguments.length) return center;
 
36367 iD.ui.RawMemberEditor = function(context) {
 
36370     function selectMember(d) {
 
36371         d3.event.preventDefault();
 
36372         context.enter(iD.modes.Select(context, [d.id]));
 
36375     function changeRole(d) {
 
36376         var role = d3.select(this).property('value');
 
36378             iD.actions.ChangeMember(d.relation.id, _.extend({}, d.id, {role: role}), d.index),
 
36379             t('operations.change_role.annotation'));
 
36382     function deleteMember(d) {
 
36384             iD.actions.DeleteMember(d.relation.id, d.index),
 
36385             t('operations.delete_member.annotation'));
 
36387         if (!context.hasEntity(d.relation.id)) {
 
36388             context.enter(iD.modes.Browse(context));
 
36392     function rawMemberEditor(selection) {
 
36393         var entity = context.entity(id),
 
36396         entity.members.forEach(function(member, index) {
 
36402                 member: context.hasEntity(member.id)
 
36406         selection.call(iD.ui.Disclosure()
 
36407             .title(t('inspector.all_members') + ' (' + memberships.length + ')')
 
36409             .on('toggled', toggled)
 
36410             .content(content));
 
36412         function toggled(expanded) {
 
36414                 selection.node().parentNode.scrollTop += 200;
 
36418         function content($wrap) {
 
36419             var $list = $wrap.selectAll('.member-list')
 
36422             $list.enter().append('ul')
 
36423                 .attr('class', 'member-list');
 
36425             var $items = $list.selectAll('li')
 
36426                 .data(memberships, function(d) {
 
36427                     return iD.Entity.key(d.relation) + ',' + d.index + ',' +
 
36428                         (d.member ? iD.Entity.key(d.member) : 'incomplete');
 
36431             var $enter = $items.enter().append('li')
 
36432                 .attr('class', 'member-row form-field')
 
36433                 .classed('member-incomplete', function(d) { return !d.member; });
 
36435             $enter.each(function(d) {
 
36437                     var $label = d3.select(this).append('label')
 
36438                         .attr('class', 'form-label')
 
36441                         .on('click', selectMember);
 
36443                     $label.append('span')
 
36444                         .attr('class', 'member-entity-type')
 
36445                         .text(function(d) { return context.presets().match(d.member, context.graph()).name(); });
 
36447                     $label.append('span')
 
36448                         .attr('class', 'member-entity-name')
 
36449                         .text(function(d) { return iD.util.displayName(d.member); });
 
36452                     d3.select(this).append('label')
 
36453                         .attr('class', 'form-label')
 
36454                         .text(t('inspector.incomplete'));
 
36458             $enter.append('input')
 
36459                 .attr('class', 'member-role')
 
36460                 .property('type', 'text')
 
36461                 .attr('maxlength', 255)
 
36462                 .attr('placeholder', t('inspector.role'))
 
36463                 .property('value', function(d) { return d.role; })
 
36464                 .on('change', changeRole);
 
36466             $enter.append('button')
 
36467                 .attr('tabindex', -1)
 
36468                 .attr('class', 'remove button-input-action member-delete minor')
 
36469                 .on('click', deleteMember)
 
36470                 .call(iD.svg.Icon('#operation-delete'));
 
36477     rawMemberEditor.entityID = function(_) {
 
36478         if (!arguments.length) return id;
 
36480         return rawMemberEditor;
 
36483     return rawMemberEditor;
 
36485 iD.ui.RawMembershipEditor = function(context) {
 
36488     function selectRelation(d) {
 
36489         d3.event.preventDefault();
 
36490         context.enter(iD.modes.Select(context, [d.relation.id]));
 
36493     function changeRole(d) {
 
36494         var role = d3.select(this).property('value');
 
36496             iD.actions.ChangeMember(d.relation.id, _.extend({}, d.member, {role: role}), d.index),
 
36497             t('operations.change_role.annotation'));
 
36500     function addMembership(d, role) {
 
36505                 iD.actions.AddMember(d.relation.id, {id: id, type: context.entity(id).type, role: role}),
 
36506                 t('operations.add_member.annotation'));
 
36509             var relation = iD.Relation();
 
36512                 iD.actions.AddEntity(relation),
 
36513                 iD.actions.AddMember(relation.id, {id: id, type: context.entity(id).type, role: role}),
 
36514                 t('operations.add.annotation.relation'));
 
36516             context.enter(iD.modes.Select(context, [relation.id]));
 
36520     function deleteMembership(d) {
 
36522             iD.actions.DeleteMember(d.relation.id, d.index),
 
36523             t('operations.delete_member.annotation'));
 
36526     function relations(q) {
 
36527         var newRelation = {
 
36529                 value: t('inspector.new_relation')
 
36532             graph = context.graph();
 
36534         context.intersects(context.extent()).forEach(function(entity) {
 
36535             if (entity.type !== 'relation' || entity.id === id)
 
36538             var presetName = context.presets().match(entity, graph).name(),
 
36539                 entityName = iD.util.displayName(entity) || '';
 
36541             var value = presetName + ' ' + entityName;
 
36542             if (q && value.toLowerCase().indexOf(q.toLowerCase()) === -1)
 
36551         result.sort(function(a, b) {
 
36552             return iD.Relation.creationOrder(a.relation, b.relation);
 
36554         result.unshift(newRelation);
 
36559     function rawMembershipEditor(selection) {
 
36560         var entity = context.entity(id),
 
36563         context.graph().parentRelations(entity).forEach(function(relation) {
 
36564             relation.members.forEach(function(member, index) {
 
36565                 if (member.id === entity.id) {
 
36566                     memberships.push({relation: relation, member: member, index: index});
 
36571         selection.call(iD.ui.Disclosure()
 
36572             .title(t('inspector.all_relations') + ' (' + memberships.length + ')')
 
36574             .on('toggled', toggled)
 
36575             .content(content));
 
36577         function toggled(expanded) {
 
36579                 selection.node().parentNode.scrollTop += 200;
 
36583         function content($wrap) {
 
36584             var $list = $wrap.selectAll('.member-list')
 
36587             $list.enter().append('ul')
 
36588                 .attr('class', 'member-list');
 
36590             var $items = $list.selectAll('li.member-row-normal')
 
36591                 .data(memberships, function(d) { return iD.Entity.key(d.relation) + ',' + d.index; });
 
36593             var $enter = $items.enter().append('li')
 
36594                 .attr('class', 'member-row member-row-normal form-field');
 
36596             var $label = $enter.append('label')
 
36597                 .attr('class', 'form-label')
 
36600                 .on('click', selectRelation);
 
36602             $label.append('span')
 
36603                 .attr('class', 'member-entity-type')
 
36604                 .text(function(d) { return context.presets().match(d.relation, context.graph()).name(); });
 
36606             $label.append('span')
 
36607                 .attr('class', 'member-entity-name')
 
36608                 .text(function(d) { return iD.util.displayName(d.relation); });
 
36610             $enter.append('input')
 
36611                 .attr('class', 'member-role')
 
36612                 .property('type', 'text')
 
36613                 .attr('maxlength', 255)
 
36614                 .attr('placeholder', t('inspector.role'))
 
36615                 .property('value', function(d) { return d.member.role; })
 
36616                 .on('change', changeRole);
 
36618             $enter.append('button')
 
36619                 .attr('tabindex', -1)
 
36620                 .attr('class', 'remove button-input-action member-delete minor')
 
36621                 .on('click', deleteMembership)
 
36622                 .call(iD.svg.Icon('#operation-delete'));
 
36628                 var $new = $list.selectAll('.member-row-new')
 
36631                 $enter = $new.enter().append('li')
 
36632                     .attr('class', 'member-row member-row-new form-field');
 
36634                 $enter.append('input')
 
36635                     .attr('type', 'text')
 
36636                     .attr('class', 'member-entity-input')
 
36637                     .call(d3.combobox()
 
36639                         .fetcher(function(value, callback) {
 
36640                             callback(relations(value));
 
36642                         .on('accept', function(d) {
 
36643                             addMembership(d, $new.select('.member-role').property('value'));
 
36646                 $enter.append('input')
 
36647                     .attr('class', 'member-role')
 
36648                     .property('type', 'text')
 
36649                     .attr('maxlength', 255)
 
36650                     .attr('placeholder', t('inspector.role'))
 
36651                     .on('change', changeRole);
 
36653                 $enter.append('button')
 
36654                     .attr('tabindex', -1)
 
36655                     .attr('class', 'remove button-input-action member-delete minor')
 
36656                     .on('click', deleteMembership)
 
36657                     .call(iD.svg.Icon('#operation-delete'));
 
36660                 $list.selectAll('.member-row-new')
 
36664             var $add = $wrap.selectAll('.add-relation')
 
36669                 .attr('class', 'add-relation')
 
36670                 .call(iD.svg.Icon('#icon-plus', 'light'));
 
36672             $wrap.selectAll('.add-relation')
 
36673                 .on('click', function() {
 
36676                     $list.selectAll('.member-entity-input').node().focus();
 
36681     rawMembershipEditor.entityID = function(_) {
 
36682         if (!arguments.length) return id;
 
36684         return rawMembershipEditor;
 
36687     return rawMembershipEditor;
 
36689 iD.ui.RawTagEditor = function(context) {
 
36690     var event = d3.dispatch('change'),
 
36697     function rawTagEditor(selection) {
 
36698         var count = Object.keys(tags).filter(function(d) { return d; }).length;
 
36700         selection.call(iD.ui.Disclosure()
 
36701             .title(t('inspector.all_tags') + ' (' + count + ')')
 
36702             .expanded(context.storage('raw_tag_editor.expanded') === 'true' || preset.isFallback())
 
36703             .on('toggled', toggled)
 
36704             .content(content));
 
36706         function toggled(expanded) {
 
36707             context.storage('raw_tag_editor.expanded', expanded);
 
36709                 selection.node().parentNode.scrollTop += 200;
 
36714     function content($wrap) {
 
36715         var entries = d3.entries(tags);
 
36717         if (!entries.length || showBlank) {
 
36719             entries.push({key: '', value: ''});
 
36722         var $list = $wrap.selectAll('.tag-list')
 
36725         $list.enter().append('ul')
 
36726             .attr('class', 'tag-list');
 
36728         var $newTag = $wrap.selectAll('.add-tag')
 
36733             .attr('class', 'add-tag')
 
36734             .call(iD.svg.Icon('#icon-plus', 'light'));
 
36736         $newTag.on('click', addTag);
 
36738         var $items = $list.selectAll('li')
 
36739             .data(entries, function(d) { return d.key; });
 
36743         var $enter = $items.enter().append('li')
 
36744             .attr('class', 'tag-row cf');
 
36746         $enter.append('div')
 
36747             .attr('class', 'key-wrap')
 
36749             .property('type', 'text')
 
36750             .attr('class', 'key')
 
36751             .attr('maxlength', 255);
 
36753         $enter.append('div')
 
36754             .attr('class', 'input-wrap-position')
 
36756             .property('type', 'text')
 
36757             .attr('class', 'value')
 
36758             .attr('maxlength', 255);
 
36760         $enter.append('button')
 
36761             .attr('tabindex', -1)
 
36762             .attr('class', 'remove minor')
 
36763             .call(iD.svg.Icon('#operation-delete'));
 
36765         if (context.taginfo()) {
 
36766             $enter.each(bindTypeahead);
 
36773         $items.each(function(tag) {
 
36774             var isRelation = (context.entity(id).type === 'relation'),
 
36776             if (isRelation && tag.key === 'type')
 
36777                 reference = iD.ui.TagReference({rtype: tag.value}, context);
 
36779                 reference = iD.ui.TagReference({key: tag.key, value: tag.value}, context);
 
36781             if (state === 'hover') {
 
36782                 reference.showing(false);
 
36786                 .call(reference.button)
 
36787                 .call(reference.body);
 
36790         $items.select('input.key')
 
36791             .value(function(d) { return d.key; })
 
36792             .on('blur', keyChange)
 
36793             .on('change', keyChange);
 
36795         $items.select('input.value')
 
36796             .value(function(d) { return d.value; })
 
36797             .on('blur', valueChange)
 
36798             .on('change', valueChange)
 
36799             .on('keydown.push-more', pushMore);
 
36801         $items.select('button.remove')
 
36802             .on('click', removeTag);
 
36808         function pushMore() {
 
36809             if (d3.event.keyCode === 9 && !d3.event.shiftKey &&
 
36810                 $list.selectAll('li:last-child input.value').node() === this) {
 
36815         function bindTypeahead() {
 
36816             var row = d3.select(this),
 
36817                 key = row.selectAll('input.key'),
 
36818                 value = row.selectAll('input.value');
 
36820             function sort(value, data) {
 
36821                 var sameletter = [],
 
36823                 for (var i = 0; i < data.length; i++) {
 
36824                     if (data[i].value.substring(0, value.length) === value) {
 
36825                         sameletter.push(data[i]);
 
36827                         other.push(data[i]);
 
36830                 return sameletter.concat(other);
 
36833             key.call(d3.combobox()
 
36834                 .fetcher(function(value, callback) {
 
36835                     context.taginfo().keys({
 
36837                         geometry: context.geometry(id),
 
36839                     }, function(err, data) {
 
36840                         if (!err) callback(sort(value, data));
 
36844             value.call(d3.combobox()
 
36845                 .fetcher(function(value, callback) {
 
36846                     context.taginfo().values({
 
36849                         geometry: context.geometry(id),
 
36851                     }, function(err, data) {
 
36852                         if (!err) callback(sort(value, data));
 
36857         function unbind() {
 
36858             var row = d3.select(this);
 
36860             row.selectAll('input.key')
 
36861                 .call(d3.combobox.off);
 
36863             row.selectAll('input.value')
 
36864                 .call(d3.combobox.off);
 
36867         function keyChange(d) {
 
36869                 kNew = this.value.trim(),
 
36872             if (kNew && kNew !== kOld) {
 
36873                 var match = kNew.match(/^(.*?)(?:_(\d+))?$/),
 
36875                     suffix = +(match[2] || 1);
 
36876                 while (tags[kNew]) {  // rename key if already in use
 
36877                     kNew = base + '_' + suffix++;
 
36880             tag[kOld] = undefined;
 
36881             tag[kNew] = d.value;
 
36882             d.key = kNew; // Maintain DOM identity through the subsequent update.
 
36887         function valueChange(d) {
 
36889             tag[d.key] = this.value;
 
36893         function removeTag(d) {
 
36895             tag[d.key] = undefined;
 
36897             d3.select(this.parentNode).remove();
 
36900         function addTag() {
 
36901             // Wrapped in a setTimeout in case it's being called from a blur
 
36902             // handler. Without the setTimeout, the call to `content` would
 
36903             // wipe out the pending value change.
 
36904             setTimeout(function() {
 
36907                 $list.selectAll('li:last-child input.key').node().focus();
 
36912     rawTagEditor.state = function(_) {
 
36913         if (!arguments.length) return state;
 
36915         return rawTagEditor;
 
36918     rawTagEditor.preset = function(_) {
 
36919         if (!arguments.length) return preset;
 
36921         return rawTagEditor;
 
36924     rawTagEditor.tags = function(_) {
 
36925         if (!arguments.length) return tags;
 
36927         return rawTagEditor;
 
36930     rawTagEditor.entityID = function(_) {
 
36931         if (!arguments.length) return id;
 
36933         return rawTagEditor;
 
36936     return d3.rebind(rawTagEditor, event, 'on');
 
36938 iD.ui.Restore = function(context) {
 
36939     return function(selection) {
 
36940         if (!context.history().lock() || !context.history().restorableChanges())
 
36943         var modal = iD.ui.modal(selection);
 
36945         modal.select('.modal')
 
36946             .attr('class', 'modal fillL col6');
 
36948         var introModal = modal.select('.content');
 
36950         introModal.attr('class','cf');
 
36952         introModal.append('div')
 
36953             .attr('class', 'modal-section')
 
36955             .text(t('restore.heading'));
 
36957         introModal.append('div')
 
36958             .attr('class','modal-section')
 
36960             .text(t('restore.description'));
 
36962         var buttonWrap = introModal.append('div')
 
36963             .attr('class', 'modal-actions cf');
 
36965         var restore = buttonWrap.append('button')
 
36966             .attr('class', 'restore col6')
 
36967             .text(t('restore.restore'))
 
36968             .on('click', function() {
 
36969                 context.history().restore();
 
36973         buttonWrap.append('button')
 
36974             .attr('class', 'reset col6')
 
36975             .text(t('restore.reset'))
 
36976             .on('click', function() {
 
36977                 context.history().clearSaved();
 
36981         restore.node().focus();
 
36984 iD.ui.Save = function(context) {
 
36985     var history = context.history(),
 
36986         key = iD.ui.cmd('⌘S');
 
36988     function saving() {
 
36989         return context.mode().id === 'save';
 
36993         d3.event.preventDefault();
 
36994         if (!context.inIntro() && !saving() && history.hasChanges()) {
 
36995             context.enter(iD.modes.Save(context));
 
36999     return function(selection) {
 
37000         var tooltip = bootstrap.tooltip()
 
37001             .placement('bottom')
 
37003             .title(iD.ui.tooltipHtml(t('save.no_changes'), key));
 
37005         var button = selection.append('button')
 
37006             .attr('class', 'save col12 disabled')
 
37007             .attr('tabindex', -1)
 
37011         button.append('span')
 
37012             .attr('class', 'label')
 
37013             .text(t('save.title'));
 
37015         button.append('span')
 
37016             .attr('class', 'count')
 
37019         var keybinding = d3.keybinding('undo-redo')
 
37020             .on(key, save, true);
 
37022         d3.select(document)
 
37025         var numChanges = 0;
 
37027         context.history().on('change.save', function() {
 
37028             var _ = history.difference().summary().length;
 
37029             if (_ === numChanges)
 
37033             tooltip.title(iD.ui.tooltipHtml(t(numChanges > 0 ?
 
37034                     'save.help' : 'save.no_changes'), key));
 
37037                 .classed('disabled', numChanges === 0)
 
37038                 .classed('has-count', numChanges > 0);
 
37040             button.select('span.count')
 
37044         context.on('enter.save', function() {
 
37045             button.property('disabled', saving());
 
37046             if (saving()) button.call(tooltip.hide);
 
37050 iD.ui.Scale = function(context) {
 
37051     var projection = context.projection,
 
37055     function scaleDefs(loc1, loc2) {
 
37056         var lat = (loc2[1] + loc1[1]) / 2,
 
37057             imperial = (iD.detect().locale.toLowerCase() === 'en-us'),
 
37058             conversion = (imperial ? 3.28084 : 1),
 
37059             dist = iD.geo.lonToMeters(loc2[0] - loc1[0], lat) * conversion,
 
37060             scale = { dist: 0, px: 0, text: '' },
 
37061             buckets, i, val, dLon;
 
37064             buckets = [5280000, 528000, 52800, 5280, 500, 50, 5, 1];
 
37066             buckets = [5000000, 500000, 50000, 5000, 500, 50, 5, 1];
 
37069         // determine a user-friendly endpoint for the scale
 
37070         for (i = 0; i < buckets.length; i++) {
 
37073                 scale.dist = Math.floor(dist / val) * val;
 
37078         dLon = iD.geo.metersToLon(scale.dist / conversion, lat);
 
37079         scale.px = Math.round(projection([loc1[0] + dLon, loc1[1]])[0]);
 
37082             if (scale.dist >= 5280) {
 
37083                 scale.dist /= 5280;
 
37084                 scale.text = String(scale.dist) + ' mi';
 
37086                 scale.text = String(scale.dist) + ' ft';
 
37089             if (scale.dist >= 1000) {
 
37090                 scale.dist /= 1000;
 
37091                 scale.text = String(scale.dist) + ' km';
 
37093                 scale.text = String(scale.dist) + ' m';
 
37100     function update(selection) {
 
37101         // choose loc1, loc2 along bottom of viewport (near where the scale will be drawn)
 
37102         var dims = context.map().dimensions(),
 
37103             loc1 = projection.invert([0, dims[1]]),
 
37104             loc2 = projection.invert([maxLength, dims[1]]),
 
37105             scale = scaleDefs(loc1, loc2);
 
37107         selection.select('#scalepath')
 
37108             .attr('d', 'M0.5,0.5v' + tickHeight + 'h' + scale.px + 'v-' + tickHeight);
 
37110         selection.select('#scaletext')
 
37111             .attr('x', scale.px + 8)
 
37112             .attr('y', tickHeight)
 
37116     return function(selection) {
 
37117         var g = selection.append('svg')
 
37118             .attr('id', 'scale')
 
37120             .attr('transform', 'translate(10,11)');
 
37122         g.append('path').attr('id', 'scalepath');
 
37123         g.append('text').attr('id', 'scaletext');
 
37127         context.map().on('move.scale', function() {
 
37132 iD.ui.SelectionList = function(context, selectedIDs) {
 
37134     function selectEntity(entity) {
 
37135         context.enter(iD.modes.Select(context, [entity.id]).suppressMenu(true));
 
37139     function selectionList(selection) {
 
37140         selection.classed('selection-list-pane', true);
 
37142         var header = selection.append('div')
 
37143             .attr('class', 'header fillL cf');
 
37145         header.append('h3')
 
37146             .text(t('inspector.multiselect'));
 
37148         var listWrap = selection.append('div')
 
37149             .attr('class', 'inspector-body');
 
37151         var list = listWrap.append('div')
 
37152             .attr('class', 'feature-list cf');
 
37154         context.history().on('change.selection-list', drawList);
 
37157         function drawList() {
 
37158             var entities = selectedIDs
 
37159                 .map(function(id) { return context.hasEntity(id); })
 
37160                 .filter(function(entity) { return entity; });
 
37162             var items = list.selectAll('.feature-list-item')
 
37163                 .data(entities, iD.Entity.key);
 
37165             var enter = items.enter().append('button')
 
37166                 .attr('class', 'feature-list-item')
 
37167                 .on('click', selectEntity);
 
37170             var label = enter.append('div')
 
37171                 .attr('class', 'label')
 
37172                 .call(iD.svg.Icon('', 'pre-text'));
 
37174             label.append('span')
 
37175                 .attr('class', 'entity-type');
 
37177             label.append('span')
 
37178                 .attr('class', 'entity-name');
 
37181             items.selectAll('use')
 
37182                 .attr('href', function() {
 
37183                     var entity = this.parentNode.parentNode.__data__;
 
37184                     return '#icon-' + context.geometry(entity.id);
 
37187             items.selectAll('.entity-type')
 
37188                 .text(function(entity) { return context.presets().match(entity, context.graph()).name(); });
 
37190             items.selectAll('.entity-name')
 
37191                 .text(function(entity) { return iD.util.displayName(entity); });
 
37199     return selectionList;
 
37202 iD.ui.Sidebar = function(context) {
 
37203     var inspector = iD.ui.Inspector(context),
 
37206     function sidebar(selection) {
 
37207         var featureListWrap = selection.append('div')
 
37208             .attr('class', 'feature-list-pane')
 
37209             .call(iD.ui.FeatureList(context));
 
37211         selection.call(iD.ui.Notice(context));
 
37213         var inspectorWrap = selection.append('div')
 
37214             .attr('class', 'inspector-hidden inspector-wrap fr');
 
37216         function hover(id) {
 
37217             if (!current && context.hasEntity(id)) {
 
37218                 featureListWrap.classed('inspector-hidden', true);
 
37219                 inspectorWrap.classed('inspector-hidden', false)
 
37220                     .classed('inspector-hover', true);
 
37222                 if (inspector.entityID() !== id || inspector.state() !== 'hover') {
 
37227                     inspectorWrap.call(inspector);
 
37229             } else if (!current) {
 
37230                 featureListWrap.classed('inspector-hidden', false);
 
37231                 inspectorWrap.classed('inspector-hidden', true);
 
37232                 inspector.state('hide');
 
37236         sidebar.hover = _.throttle(hover, 200);
 
37238         sidebar.select = function(id, newFeature) {
 
37239             if (!current && id) {
 
37240                 featureListWrap.classed('inspector-hidden', true);
 
37241                 inspectorWrap.classed('inspector-hidden', false)
 
37242                     .classed('inspector-hover', false);
 
37244                 if (inspector.entityID() !== id || inspector.state() !== 'select') {
 
37248                         .newFeature(newFeature);
 
37250                     inspectorWrap.call(inspector);
 
37252             } else if (!current) {
 
37253                 featureListWrap.classed('inspector-hidden', false);
 
37254                 inspectorWrap.classed('inspector-hidden', true);
 
37255                 inspector.state('hide');
 
37259         sidebar.show = function(component) {
 
37260             featureListWrap.classed('inspector-hidden', true);
 
37261             inspectorWrap.classed('inspector-hidden', true);
 
37262             if (current) current.remove();
 
37263             current = selection.append('div')
 
37264                 .attr('class', 'sidebar-component')
 
37268         sidebar.hide = function() {
 
37269             featureListWrap.classed('inspector-hidden', false);
 
37270             inspectorWrap.classed('inspector-hidden', true);
 
37271             if (current) current.remove();
 
37276     sidebar.hover = function() {};
 
37277     sidebar.hover.cancel = function() {};
 
37278     sidebar.select = function() {};
 
37279     sidebar.show = function() {};
 
37280     sidebar.hide = function() {};
 
37284 iD.ui.SourceSwitch = function(context) {
 
37288         d3.event.preventDefault();
 
37290         if (context.history().hasChanges() &&
 
37291             !window.confirm(t('source_switch.lose_changes'))) return;
 
37293         var live = d3.select(this)
 
37296         context.connection()
 
37297             .switch(live ? keys[1] : keys[0]);
 
37299         context.enter(iD.modes.Browse(context));
 
37303             .text(live ? t('source_switch.dev') : t('source_switch.live'))
 
37304             .classed('live', !live);
 
37307     var sourceSwitch = function(selection) {
 
37308         selection.append('a')
 
37310             .text(t('source_switch.live'))
 
37311             .classed('live', true)
 
37312             .attr('tabindex', -1)
 
37313             .on('click', click);
 
37316     sourceSwitch.keys = function(_) {
 
37317         if (!arguments.length) return keys;
 
37319         return sourceSwitch;
 
37322     return sourceSwitch;
 
37324 iD.ui.Spinner = function(context) {
 
37325     var connection = context.connection();
 
37327     return function(selection) {
 
37328         var img = selection.append('img')
 
37329             .attr('src', context.imagePath('loader-black.gif'))
 
37330             .style('opacity', 0);
 
37332         connection.on('loading.spinner', function() {
 
37334                 .style('opacity', 1);
 
37337         connection.on('loaded.spinner', function() {
 
37339                 .style('opacity', 0);
 
37343 iD.ui.Splash = function(context) {
 
37344     return function(selection) {
 
37345         if (context.storage('sawSplash'))
 
37348         context.storage('sawSplash', true);
 
37350         var modal = iD.ui.modal(selection);
 
37352         modal.select('.modal')
 
37353             .attr('class', 'modal-splash modal col6');
 
37355         var introModal = modal.select('.content')
 
37357             .attr('class', 'fillL');
 
37359         introModal.append('div')
 
37360             .attr('class','modal-section cf')
 
37361             .append('h3').text(t('splash.welcome'));
 
37363         introModal.append('div')
 
37364             .attr('class','modal-section')
 
37366             .html(t('splash.text', {
 
37367                 version: iD.version,
 
37368                 website: '<a href="http://ideditor.com/">ideditor.com</a>',
 
37369                 github: '<a href="https://github.com/openstreetmap/iD">github.com</a>'
 
37372         var buttons = introModal.append('div').attr('class', 'modal-actions cf');
 
37374         buttons.append('button')
 
37375             .attr('class', 'col6 walkthrough')
 
37376             .text(t('splash.walkthrough'))
 
37377             .on('click', function() {
 
37378                 d3.select(document.body).call(iD.ui.intro(context));
 
37382         buttons.append('button')
 
37383             .attr('class', 'col6 start')
 
37384             .text(t('splash.start'))
 
37385             .on('click', modal.close);
 
37387         modal.select('button.close').attr('class','hide');
 
37391 iD.ui.Status = function(context) {
 
37392     var connection = context.connection(),
 
37395     return function(selection) {
 
37397         function update() {
 
37399             connection.status(function(err, apiStatus) {
 
37401                 selection.html('');
 
37403                 if (err && errCount++ < 2) return;
 
37406                     selection.text(t('status.error'));
 
37408                 } else if (apiStatus === 'readonly') {
 
37409                     selection.text(t('status.readonly'));
 
37411                 } else if (apiStatus === 'offline') {
 
37412                     selection.text(t('status.offline'));
 
37415                 selection.attr('class', 'api-status ' + (err ? 'error' : apiStatus));
 
37416                 if (!err) errCount = 0;
 
37421         connection.on('auth', function() { update(selection); });
 
37422         window.setInterval(update, 90000);
 
37426 iD.ui.Success = function(context) {
 
37427     var dispatch = d3.dispatch('cancel'),
 
37430     function success(selection) {
 
37431         var message = (changeset.comment || t('success.edited_osm')).substring(0, 130) +
 
37432             ' ' + context.connection().changesetURL(changeset.id);
 
37434         var header = selection.append('div')
 
37435             .attr('class', 'header fillL');
 
37437         header.append('button')
 
37438             .attr('class', 'fr')
 
37439             .on('click', function() { dispatch.cancel(); })
 
37440             .call(iD.svg.Icon('#icon-close'));
 
37442         header.append('h3')
 
37443             .text(t('success.just_edited'));
 
37445         var body = selection.append('div')
 
37446             .attr('class', 'body save-success fillL');
 
37449             .html(t('success.help_html'));
 
37452             .attr('class', 'details')
 
37453             .attr('target', '_blank')
 
37454             .attr('tabindex', -1)
 
37455             .call(iD.svg.Icon('#icon-out-link', 'inline'))
 
37456             .attr('href', t('success.help_link_url'))
 
37458             .text(t('success.help_link_text'));
 
37460         var changesetURL = context.connection().changesetURL(changeset.id);
 
37463             .attr('class', 'button col12 osm')
 
37464             .attr('target', '_blank')
 
37465             .attr('href', changesetURL)
 
37466             .text(t('success.view_on_osm'));
 
37469             facebook: 'https://facebook.com/sharer/sharer.php?u=' + encodeURIComponent(changesetURL),
 
37470             twitter: 'https://twitter.com/intent/tweet?source=webclient&text=' + encodeURIComponent(message),
 
37471             google: 'https://plus.google.com/share?url=' + encodeURIComponent(changesetURL)
 
37474         body.selectAll('.button.social')
 
37475             .data(d3.entries(sharing))
 
37478             .attr('class', 'button social col4')
 
37479             .attr('target', '_blank')
 
37480             .attr('href', function(d) { return d.value; })
 
37481             .call(bootstrap.tooltip()
 
37482                 .title(function(d) { return t('success.' + d.key); })
 
37483                 .placement('bottom'))
 
37484             .each(function(d) { d3.select(this).call(iD.svg.Icon('#logo-' + d.key, 'social')); });
 
37487     success.changeset = function(_) {
 
37488         if (!arguments.length) return changeset;
 
37493     return d3.rebind(success, dispatch, 'on');
 
37495 iD.ui.TagReference = function(tag, context) {
 
37496     var tagReference = {},
 
37502     function findLocal(data) {
 
37503         var locale = iD.detect().locale.toLowerCase(),
 
37506         localized = _.find(data, function(d) {
 
37507             return d.lang.toLowerCase() === locale;
 
37509         if (localized) return localized;
 
37511         // try the non-regional version of a language, like
 
37512         // 'en' if the language is 'en-US'
 
37513         if (locale.indexOf('-') !== -1) {
 
37514             var first = locale.split('-')[0];
 
37515             localized = _.find(data, function(d) {
 
37516                 return d.lang.toLowerCase() === first;
 
37518             if (localized) return localized;
 
37521         // finally fall back to english
 
37522         return _.find(data, function(d) {
 
37523             return d.lang.toLowerCase() === 'en';
 
37527     function load(param) {
 
37528         button.classed('tag-reference-loading', true);
 
37530         context.taginfo().docs(param, function show(err, data) {
 
37532             if (!err && data) {
 
37533                 docs = findLocal(data);
 
37538             if (!docs || !docs.description) {
 
37539                 if (param.hasOwnProperty('value')) {
 
37540                     load(_.omit(param, 'value'));   // retry with key only
 
37542                     body.append('p').text(t('inspector.no_documentation_key'));
 
37548             if (docs.image && docs.image.thumb_url_prefix) {
 
37551                     .attr('class', 'wiki-image')
 
37552                     .attr('src', docs.image.thumb_url_prefix + '100' + docs.image.thumb_url_suffix)
 
37553                     .on('load', function() { done(); })
 
37554                     .on('error', function() { d3.select(this).remove(); done(); });
 
37561                 .text(docs.description);
 
37565                 .attr('target', '_blank')
 
37566                 .attr('href', 'https://wiki.openstreetmap.org/wiki/' + docs.title)
 
37567                 .call(iD.svg.Icon('#icon-out-link', 'inline'))
 
37569                 .text(t('inspector.reference'));
 
37576         button.classed('tag-reference-loading', false);
 
37580             .style('max-height', '200px')
 
37581             .style('opacity', '1');
 
37586     function hide(selection) {
 
37587         selection = selection || body.transition().duration(200);
 
37590             .style('max-height', '0px')
 
37591             .style('opacity', '0');
 
37596     tagReference.button = function(selection) {
 
37597         button = selection.selectAll('.tag-reference-button')
 
37602             .attr('class', 'tag-reference-button')
 
37603             .attr('tabindex', -1)
 
37604             .call(iD.svg.Icon('#icon-inspect'));
 
37606         button.on('click', function () {
 
37607             d3.event.stopPropagation();
 
37608             d3.event.preventDefault();
 
37611             } else if (loaded) {
 
37614                 if (context.taginfo()) {
 
37621     tagReference.body = function(selection) {
 
37622         body = selection.selectAll('.tag-reference-body')
 
37625         body.enter().append('div')
 
37626             .attr('class', 'tag-reference-body cf')
 
37627             .style('max-height', '0')
 
37628             .style('opacity', '0');
 
37630         if (showing === false) {
 
37635     tagReference.showing = function(_) {
 
37636         if (!arguments.length) return showing;
 
37638         return tagReference;
 
37641     return tagReference;
 
37643 // toggles the visibility of ui elements, using a combination of the
 
37644 // hide class, which sets display=none, and a d3 transition for opacity.
 
37645 // this will cause blinking when called repeatedly, so check that the
 
37646 // value actually changes between calls.
 
37647 iD.ui.Toggle = function(show, callback) {
 
37648     return function(selection) {
 
37650             .style('opacity', show ? 0 : 1)
 
37651             .classed('hide', false)
 
37653             .style('opacity', show ? 1 : 0)
 
37654             .each('end', function() {
 
37656                     .classed('hide', !show)
 
37657                     .style('opacity', null);
 
37658                 if (callback) callback.apply(this);
 
37662 iD.ui.UndoRedo = function(context) {
 
37665         cmd: iD.ui.cmd('⌘Z'),
 
37666         action: function() { if (!(context.inIntro() || saving())) context.undo(); },
 
37667         annotation: function() { return context.history().undoAnnotation(); }
 
37670         cmd: iD.ui.cmd('⌘⇧Z'),
 
37671         action: function() {if (!(context.inIntro() || saving())) context.redo(); },
 
37672         annotation: function() { return context.history().redoAnnotation(); }
 
37675     function saving() {
 
37676         return context.mode().id === 'save';
 
37679     return function(selection) {
 
37680         var tooltip = bootstrap.tooltip()
 
37681             .placement('bottom')
 
37683             .title(function (d) {
 
37684                 return iD.ui.tooltipHtml(d.annotation() ?
 
37685                     t(d.id + '.tooltip', {action: d.annotation()}) :
 
37686                     t(d.id + '.nothing'), d.cmd);
 
37689         var buttons = selection.selectAll('button')
 
37691             .enter().append('button')
 
37692             .attr('class', 'col6 disabled')
 
37693             .on('click', function(d) { return d.action(); })
 
37696         buttons.each(function(d) {
 
37698                 .call(iD.svg.Icon('#icon-' + d.id));
 
37701         var keybinding = d3.keybinding('undo')
 
37702             .on(commands[0].cmd, function() { d3.event.preventDefault(); commands[0].action(); })
 
37703             .on(commands[1].cmd, function() { d3.event.preventDefault(); commands[1].action(); });
 
37705         d3.select(document)
 
37709             .on('change.undo_redo', update);
 
37712             .on('enter.undo_redo', update);
 
37714         function update() {
 
37716                 .property('disabled', saving())
 
37717                 .classed('disabled', function(d) { return !d.annotation(); })
 
37719                     var selection = d3.select(this);
 
37720                     if (selection.property('tooltipVisible')) {
 
37721                         selection.call(tooltip.show);
 
37727 iD.ui.ViewOnOSM = function(context) {
 
37730     function viewOnOSM(selection) {
 
37731         var entity = context.entity(id);
 
37733         selection.style('display', entity.isNew() ? 'none' : null);
 
37735         var $link = selection.selectAll('.view-on-osm')
 
37740             .attr('class', 'view-on-osm')
 
37741             .attr('target', '_blank')
 
37742             .call(iD.svg.Icon('#icon-out-link', 'inline'))
 
37744             .text(t('inspector.view_on_osm'));
 
37747             .attr('href', context.connection().entityURL(entity));
 
37750     viewOnOSM.entityID = function(_) {
 
37751         if (!arguments.length) return id;
 
37758 iD.ui.Zoom = function(context) {
 
37762         title: t('zoom.in'),
 
37763         action: context.zoomIn,
 
37768         title: t('zoom.out'),
 
37769         action: context.zoomOut,
 
37773     function zoomIn() {
 
37774         d3.event.preventDefault();
 
37775         if (!context.inIntro()) context.zoomIn();
 
37778     function zoomOut() {
 
37779         d3.event.preventDefault();
 
37780         if (!context.inIntro()) context.zoomOut();
 
37783     function zoomInFurther() {
 
37784         d3.event.preventDefault();
 
37785         if (!context.inIntro()) context.zoomInFurther();
 
37788     function zoomOutFurther() {
 
37789         d3.event.preventDefault();
 
37790         if (!context.inIntro()) context.zoomOutFurther();
 
37794     return function(selection) {
 
37795         var button = selection.selectAll('button')
 
37797             .enter().append('button')
 
37798             .attr('tabindex', -1)
 
37799             .attr('class', function(d) { return d.id; })
 
37800             .on('click.editor', function(d) { d.action(); })
 
37801             .call(bootstrap.tooltip()
 
37804                 .title(function(d) {
 
37805                     return iD.ui.tooltipHtml(d.title, d.key);
 
37808         button.each(function(d) {
 
37810                 .call(iD.svg.Icon('#icon-' + d.icon, 'light'));
 
37813         var keybinding = d3.keybinding('zoom');
 
37815         _.each(['=','ffequals','plus','ffplus'], function(key) {
 
37816             keybinding.on(key, zoomIn);
 
37817             keybinding.on('⇧' + key, zoomIn);
 
37818             keybinding.on(iD.ui.cmd('⌘' + key), zoomInFurther);
 
37819             keybinding.on(iD.ui.cmd('⌘⇧' + key), zoomInFurther);
 
37821         _.each(['-','ffminus','_','dash'], function(key) {
 
37822             keybinding.on(key, zoomOut);
 
37823             keybinding.on('⇧' + key, zoomOut);
 
37824             keybinding.on(iD.ui.cmd('⌘' + key), zoomOutFurther);
 
37825             keybinding.on(iD.ui.cmd('⌘⇧' + key), zoomOutFurther);
 
37828         d3.select(document)
 
37832 iD.ui.preset.access = function(field) {
 
37833     var dispatch = d3.dispatch('change'),
 
37836     function access(selection) {
 
37837         var wrap = selection.selectAll('.preset-input-wrap')
 
37840         wrap.enter().append('div')
 
37841             .attr('class', 'cf preset-input-wrap')
 
37844         items = wrap.select('ul').selectAll('li')
 
37849         var enter = items.enter().append('li')
 
37850             .attr('class', function(d) { return 'cf preset-access-' + d; });
 
37852         enter.append('span')
 
37853             .attr('class', 'col6 label preset-label-access')
 
37854             .attr('for', function(d) { return 'preset-input-access-' + d; })
 
37855             .text(function(d) { return field.t('types.' + d); });
 
37857         enter.append('div')
 
37858             .attr('class', 'col6 preset-input-access-wrap')
 
37860             .attr('type', 'text')
 
37861             .attr('class', 'preset-input-access')
 
37862             .attr('id', function(d) { return 'preset-input-access-' + d; })
 
37863             .each(function(d) {
 
37865                     .call(d3.combobox()
 
37866                         .data(access.options(d)));
 
37871         wrap.selectAll('.preset-input-access')
 
37872             .on('change', change)
 
37873             .on('blur', change);
 
37876     function change(d) {
 
37878         tag[d] = d3.select(this).value() || undefined;
 
37879         dispatch.change(tag);
 
37882     access.options = function(type) {
 
37883         var options = ['no', 'permissive', 'private', 'destination'];
 
37885         if (type !== 'access') {
 
37886             options.unshift('yes');
 
37887             options.push('designated');
 
37889             if (type === 'bicycle') {
 
37890                 options.push('dismount');
 
37894         return options.map(function(option) {
 
37896                 title: field.t('options.' + option + '.description'),
 
37902     var placeholders = {
 
37904             foot: 'designated',
 
37905             motor_vehicle: 'no'
 
37909             motor_vehicle: 'no',
 
37915             motor_vehicle: 'no'
 
37918             motor_vehicle: 'no',
 
37919             bicycle: 'designated'
 
37922             motor_vehicle: 'no',
 
37923             horse: 'designated'
 
37927             motor_vehicle: 'no',
 
37933             motor_vehicle: 'yes',
 
37938             motor_vehicle: 'yes'
 
37942             motor_vehicle: 'yes',
 
37948             motor_vehicle: 'yes',
 
37954             motor_vehicle: 'yes',
 
37960             motor_vehicle: 'yes',
 
37966             motor_vehicle: 'yes',
 
37972             motor_vehicle: 'yes',
 
37978             motor_vehicle: 'yes',
 
37983             motor_vehicle: 'yes'
 
37987             motor_vehicle: 'yes',
 
37993             motor_vehicle: 'yes',
 
37999             motor_vehicle: 'yes',
 
38005     access.tags = function(tags) {
 
38006         items.selectAll('.preset-input-access')
 
38007             .value(function(d) { return tags[d] || ''; })
 
38008             .attr('placeholder', function() {
 
38009                 return tags.access ? tags.access : field.placeholder();
 
38012         // items.selectAll('#preset-input-access-access')
 
38013         //     .attr('placeholder', 'yes');
 
38015         _.forEach(placeholders[tags.highway], function(v, k) {
 
38016             items.selectAll('#preset-input-access-' + k)
 
38017                 .attr('placeholder', function() { return (tags.access || v); });
 
38021     access.focus = function() {
 
38022         items.selectAll('.preset-input-access')
 
38026     return d3.rebind(access, dispatch, 'on');
 
38028 iD.ui.preset.address = function(field, context) {
 
38029     var dispatch = d3.dispatch('init', 'change'),
 
38042     function getStreets() {
 
38043         var extent = entity.extent(context.graph()),
 
38044             l = extent.center(),
 
38045             box = iD.geo.Extent(l).padByMeters(200);
 
38047         return context.intersects(box)
 
38048             .filter(isAddressable)
 
38050                 var loc = context.projection([
 
38051                     (extent[0][0] + extent[1][0]) / 2,
 
38052                     (extent[0][1] + extent[1][1]) / 2]),
 
38053                     choice = iD.geo.chooseEdge(context.childNodes(d), loc, context.projection);
 
38055                     title: d.tags.name,
 
38056                     value: d.tags.name,
 
38057                     dist: choice.distance
 
38059             }).sort(function(a, b) {
 
38060                 return a.dist - b.dist;
 
38063         function isAddressable(d) {
 
38064             return d.tags.highway && d.tags.name && d.type === 'way';
 
38068     function getCities() {
 
38069         var extent = entity.extent(context.graph()),
 
38070             l = extent.center(),
 
38071             box = iD.geo.Extent(l).padByMeters(200);
 
38073         return context.intersects(box)
 
38074             .filter(isAddressable)
 
38077                     title: d.tags['addr:city'] || d.tags.name,
 
38078                     value: d.tags['addr:city'] || d.tags.name,
 
38079                     dist: iD.geo.sphericalDistance(d.extent(context.graph()).center(), l)
 
38081             }).sort(function(a, b) {
 
38082                 return a.dist - b.dist;
 
38085         function isAddressable(d) {
 
38087                 (d.tags.admin_level === '8' || d.tags.border_type === 'city'))
 
38090             if (d.tags.place && d.tags.name && (
 
38091                     d.tags.place === 'city' ||
 
38092                     d.tags.place === 'town' ||
 
38093                     d.tags.place === 'village'))
 
38096             if (d.tags['addr:city']) return true;
 
38102     function getPostCodes() {
 
38103         var extent = entity.extent(context.graph()),
 
38104             l = extent.center(),
 
38105             box = iD.geo.Extent(l).padByMeters(200);
 
38107         return context.intersects(box)
 
38108             .filter(isAddressable)
 
38111                     title: d.tags['addr:postcode'],
 
38112                     value: d.tags['addr:postcode'],
 
38113                     dist: iD.geo.sphericalDistance(d.extent(context.graph()).center(), l)
 
38115             }).sort(function(a, b) {
 
38116                 return a.dist - b.dist;
 
38119         function isAddressable(d) {
 
38120             return d.tags['addr:postcode'];
 
38124     function address(selection) {
 
38125         isInitialized = false;
 
38127         wrap = selection.selectAll('.preset-input-wrap')
 
38134             .attr('class', 'preset-input-wrap');
 
38136         var center = entity.extent(context.graph()).center(),
 
38139         iD.services.nominatim().countryCode(center, function (err, countryCode) {
 
38140             addressFormat = _.find(iD.data.addressFormats, function (a) {
 
38141                 return a && a.countryCodes && _.contains(a.countryCodes, countryCode);
 
38142             }) || _.first(iD.data.addressFormats);
 
38145                 // Normalize widths.
 
38146                 var total = _.reduce(r, function(sum, field) {
 
38147                     return sum + (widths[field] || 0.5);
 
38150                 return r.map(function (field) {
 
38153                         width: (widths[field] || 0.5) / total
 
38158             wrap.selectAll('div')
 
38159                 .data(addressFormat.format)
 
38162                 .attr('class', 'addr-row')
 
38163                 .selectAll('input')
 
38167                 .property('type', 'text')
 
38168                 .attr('placeholder', function (d) { return field.t('placeholders.' + d.id); })
 
38169                 .attr('class', function (d) { return 'addr-' + d.id; })
 
38170                 .style('width', function (d) { return d.width * 100 + '%'; });
 
38174             wrap.selectAll('.addr-street')
 
38175                 .call(d3.combobox()
 
38176                     .fetcher(function(value, callback) {
 
38177                         callback(getStreets());
 
38180             wrap.selectAll('.addr-city')
 
38181                 .call(d3.combobox()
 
38182                     .fetcher(function(value, callback) {
 
38183                         callback(getCities());
 
38186             wrap.selectAll('.addr-postcode')
 
38187                 .call(d3.combobox()
 
38188                     .fetcher(function(value, callback) {
 
38189                         callback(getPostCodes());
 
38192             wrap.selectAll('input')
 
38193                 .on('blur', change())
 
38194                 .on('change', change());
 
38196             wrap.selectAll('input:not(.combobox-input)')
 
38197                 .on('input', change(true));
 
38200             isInitialized = true;
 
38204     function change(onInput) {
 
38205         return function() {
 
38208             wrap.selectAll('input')
 
38209                 .each(function (field) {
 
38210                     tags['addr:' + field.id] = this.value || undefined;
 
38213             dispatch.change(tags, onInput);
 
38217     function updateTags(tags) {
 
38218         wrap.selectAll('input')
 
38219             .value(function (field) {
 
38220                 return tags['addr:' + field.id] || '';
 
38224     address.entity = function(_) {
 
38225         if (!arguments.length) return entity;
 
38230     address.tags = function(tags) {
 
38231         if (isInitialized) {
 
38234             dispatch.on('init', function () {
 
38240     address.focus = function() {
 
38241         var node = wrap.selectAll('input').node();
 
38242         if (node) node.focus();
 
38245     return d3.rebind(address, dispatch, 'on');
 
38247 iD.ui.preset.check =
 
38248 iD.ui.preset.defaultcheck = function(field) {
 
38249     var dispatch = d3.dispatch('change'),
 
38250         options = field.strings && field.strings.options,
 
38253         entity, value, box, text, label;
 
38256         for (var k in options) {
 
38257             values.push(k === 'undefined' ? undefined : k);
 
38258             texts.push(field.t('options.' + k, { 'default': options[k] }));
 
38261         values = [undefined, 'yes'];
 
38262         texts = [t('inspector.unknown'), t('inspector.check.yes')];
 
38263         if (field.type === 'check') {
 
38265             texts.push(t('inspector.check.no'));
 
38269     var check = function(selection) {
 
38270         // hack: pretend oneway field is a oneway_yes field
 
38271         // where implied oneway tag exists (e.g. `junction=roundabout`) #2220, #1841
 
38272         if (field.id === 'oneway') {
 
38273             for (var key in entity.tags) {
 
38274                 if (key in iD.oneWayTags && (entity.tags[key] in iD.oneWayTags[key])) {
 
38275                     texts[0] = t('presets.fields.oneway_yes.options.undefined');
 
38281         selection.classed('checkselect', 'true');
 
38283         label = selection.selectAll('.preset-input-wrap')
 
38286         var enter = label.enter().append('label')
 
38287             .attr('class', 'preset-input-wrap');
 
38289         enter.append('input')
 
38290             .property('indeterminate', field.type === 'check')
 
38291             .attr('type', 'checkbox')
 
38292             .attr('id', 'preset-input-' + field.id);
 
38294         enter.append('span')
 
38296             .attr('class', 'value');
 
38298         box = label.select('input')
 
38299             .on('click', function() {
 
38301                 t[field.key] = values[(values.indexOf(value) + 1) % values.length];
 
38302                 dispatch.change(t);
 
38303                 d3.event.stopPropagation();
 
38306         text = label.select('span.value');
 
38309     check.entity = function(_) {
 
38310         if (!arguments.length) return entity;
 
38315     check.tags = function(tags) {
 
38316         value = tags[field.key];
 
38317         box.property('indeterminate', field.type === 'check' && !value);
 
38318         box.property('checked', value === 'yes');
 
38319         text.text(texts[values.indexOf(value)]);
 
38320         label.classed('set', !!value);
 
38323     check.focus = function() {
 
38324         box.node().focus();
 
38327     return d3.rebind(check, dispatch, 'on');
 
38329 iD.ui.preset.combo =
 
38330 iD.ui.preset.typeCombo = function(field, context) {
 
38331     var dispatch = d3.dispatch('change'),
 
38332         optstrings = field.strings && field.strings.options,
 
38333         optarray = field.options,
 
38334         snake_case = (field.snake_case || (field.snake_case === undefined)),
 
38338     function snake(s) {
 
38339         return s.replace(/\s+/g, '_');
 
38342     function unsnake(s) {
 
38343         return s.replace(/_+/g, ' ');
 
38346     function clean(s) {
 
38347         return s.split(';')
 
38348             .map(function(s) { return s.trim(); })
 
38352     function optString() {
 
38353         return _.find(_.keys(strings), function(k) {
 
38354                 return strings[k] === input.value();
 
38358     function combo(selection) {
 
38359         var combobox = d3.combobox();
 
38361         input = selection.selectAll('input')
 
38364         var enter = input.enter()
 
38366             .attr('type', 'text')
 
38367             .attr('id', 'preset-input-' + field.id);
 
38369         if (optstrings) { enter.attr('readonly', 'readonly'); }
 
38373             .on('change', change)
 
38374             .on('blur', change)
 
38377                     _.each(optstrings, function(v, k) {
 
38378                         strings[k] = field.t('options.' + k, { 'default': v });
 
38381                 } else if (optarray) {
 
38382                     _.each(optarray, function(k) {
 
38383                         strings[k] = (snake_case ? unsnake(k) : k);
 
38386                 } else if (context.taginfo()) {
 
38387                     context.taginfo().values({key: field.key}, function(err, data) {
 
38389                             _.each(_.pluck(data, 'value'), function(k) {
 
38390                                 strings[k] = (snake_case ? unsnake(k) : k);
 
38398         function stringsLoaded() {
 
38399             var keys = _.keys(strings),
 
38403             combobox.data(keys.map(function(k) {
 
38404                 var s = strings[k],
 
38406                 o.title = o.value = s;
 
38407                 if (s.length < 20) { strs.push(s); }
 
38411             placeholders = strs.length > 1 ? strs : keys;
 
38412             input.attr('placeholder', field.placeholder() ||
 
38413                 (placeholders.slice(0, 3).join(', ') + '...'));
 
38417     function change() {
 
38418         var value = optString() || clean(input.value());
 
38421             value = snake(value);
 
38423         if (field.type === 'typeCombo' && !value) {
 
38428         t[field.key] = value || undefined;
 
38429         dispatch.change(t);
 
38432     combo.tags = function(tags) {
 
38433         var key = tags[field.key],
 
38434             optstring = optString(),
 
38435             value = strings[key] || key || '';
 
38437         if (field.type === 'typeCombo' && value.toLowerCase() === 'yes') {
 
38440         if (!optstring && snake_case) {
 
38441             value = unsnake(value);
 
38443         input.value(value);
 
38446     combo.focus = function() {
 
38447         input.node().focus();
 
38450     return d3.rebind(combo, dispatch, 'on');
 
38452 iD.ui.preset.cycleway = function(field) {
 
38453     var dispatch = d3.dispatch('change'),
 
38456     function cycleway(selection) {
 
38457         var wrap = selection.selectAll('.preset-input-wrap')
 
38460         wrap.enter().append('div')
 
38461             .attr('class', 'cf preset-input-wrap')
 
38464         items = wrap.select('ul').selectAll('li')
 
38469         var enter = items.enter().append('li')
 
38470             .attr('class', function(d) { return 'cf preset-cycleway-' + d; });
 
38472         enter.append('span')
 
38473             .attr('class', 'col6 label preset-label-cycleway')
 
38474             .attr('for', function(d) { return 'preset-input-cycleway-' + d; })
 
38475             .text(function(d) { return field.t('types.' + d); });
 
38477         enter.append('div')
 
38478             .attr('class', 'col6 preset-input-cycleway-wrap')
 
38480             .attr('type', 'text')
 
38481             .attr('class', 'preset-input-cycleway')
 
38482             .attr('id', function(d) { return 'preset-input-cycleway-' + d; })
 
38483             .each(function(d) {
 
38485                     .call(d3.combobox()
 
38486                         .data(cycleway.options(d)));
 
38491         wrap.selectAll('.preset-input-cycleway')
 
38492             .on('change', change)
 
38493             .on('blur', change);
 
38496     function change() {
 
38497         var inputs = d3.selectAll('.preset-input-cycleway')[0],
 
38498             left = d3.select(inputs[0]).value(),
 
38499             right = d3.select(inputs[1]).value(),
 
38501         if (left === 'none' || left === '') { left = undefined; }
 
38502         if (right === 'none' || right === '') { right = undefined; }
 
38504         // Always set both left and right as changing one can affect the other
 
38506             cycleway: undefined,
 
38507             'cycleway:left': left,
 
38508             'cycleway:right': right
 
38511         // If the left and right tags match, use the cycleway tag to tag both
 
38512         // sides the same way
 
38513         if (left === right) {
 
38516                 'cycleway:left': undefined,
 
38517                 'cycleway:right': undefined
 
38521         dispatch.change(tag);
 
38524     cycleway.options = function() {
 
38525         return d3.keys(field.strings.options).map(function(option) {
 
38527                 title: field.t('options.' + option + '.description'),
 
38533     cycleway.tags = function(tags) {
 
38534         items.selectAll('.preset-input-cycleway')
 
38535             .value(function(d) {
 
38536                 // If cycleway is set, always return that
 
38537                 if (tags.cycleway) {
 
38538                     return tags.cycleway;
 
38540                 return tags[d] || '';
 
38542             .attr('placeholder', field.placeholder());
 
38545     cycleway.focus = function() {
 
38546         items.selectAll('.preset-input-cycleway')
 
38550     return d3.rebind(cycleway, dispatch, 'on');
 
38552 iD.ui.preset.text =
 
38553 iD.ui.preset.number =
 
38555 iD.ui.preset.email =
 
38556 iD.ui.preset.url = function(field) {
 
38558     var dispatch = d3.dispatch('change'),
 
38561     function i(selection) {
 
38562         input = selection.selectAll('input')
 
38565         input.enter().append('input')
 
38566             .attr('type', field.type)
 
38567             .attr('id', 'preset-input-' + field.id)
 
38568             .attr('placeholder', field.placeholder() || t('inspector.unknown'));
 
38571             .on('input', change(true))
 
38572             .on('blur', change())
 
38573             .on('change', change());
 
38575         if (field.type === 'number') {
 
38576             input.attr('type', 'text');
 
38578             var spinControl = selection.selectAll('.spin-control')
 
38581             var enter = spinControl.enter().append('div')
 
38582                 .attr('class', 'spin-control');
 
38584             enter.append('button')
 
38586                 .attr('class', 'increment');
 
38588             enter.append('button')
 
38590                 .attr('class', 'decrement');
 
38592             spinControl.selectAll('button')
 
38593                 .on('click', function(d) {
 
38594                     d3.event.preventDefault();
 
38595                     var num = parseInt(input.node().value || 0, 10);
 
38596                     if (!isNaN(num)) input.node().value = num + d;
 
38602     function change(onInput) {
 
38603         return function() {
 
38605             t[field.key] = input.value() || undefined;
 
38606             dispatch.change(t, onInput);
 
38610     i.tags = function(tags) {
 
38611         input.value(tags[field.key] || '');
 
38614     i.focus = function() {
 
38615         input.node().focus();
 
38618     return d3.rebind(i, dispatch, 'on');
 
38620 iD.ui.preset.localized = function(field, context) {
 
38621     var dispatch = d3.dispatch('change', 'input'),
 
38622         wikipedia = iD.services.wikipedia(),
 
38623         input, localizedInputs, wikiTitles,
 
38626     function i(selection) {
 
38627         input = selection.selectAll('.localized-main')
 
38630         input.enter().append('input')
 
38631             .attr('type', 'text')
 
38632             .attr('id', 'preset-input-' + field.id)
 
38633             .attr('class', 'localized-main')
 
38634             .attr('placeholder', field.placeholder());
 
38636         if (field.id === 'name') {
 
38637             var preset = context.presets().match(entity, context.graph());
 
38638             input.call(d3.combobox().fetcher(
 
38639                 iD.util.SuggestNames(preset, iD.data.suggestions)
 
38644             .on('input', change(true))
 
38645             .on('blur', change())
 
38646             .on('change', change());
 
38648         var translateButton = selection.selectAll('.localized-add')
 
38651         translateButton.enter()
 
38653             .attr('class', 'button-input-action localized-add minor')
 
38654             .call(iD.svg.Icon('#icon-plus'))
 
38655             .call(bootstrap.tooltip()
 
38656                 .title(t('translate.translate'))
 
38657                 .placement('left'));
 
38660             .on('click', addNew);
 
38662         localizedInputs = selection.selectAll('.localized-wrap')
 
38665         localizedInputs.enter().append('div')
 
38666             .attr('class', 'localized-wrap');
 
38669     function addNew() {
 
38670         d3.event.preventDefault();
 
38671         var data = localizedInputs.selectAll('div.entry').data();
 
38672         var defaultLang = iD.detect().locale.toLowerCase().split('-')[0];
 
38673         var langExists = _.find(data, function(datum) { return datum.lang === defaultLang;});
 
38674         var isLangEn = defaultLang.indexOf('en') > -1;
 
38675         if (isLangEn || langExists) {
 
38678         data.push({ lang: defaultLang, value: '' });
 
38679         localizedInputs.call(render, data);
 
38682     function change(onInput) {
 
38683         return function() {
 
38685             t[field.key] = d3.select(this).value() || undefined;
 
38686             dispatch.change(t, onInput);
 
38690     function key(lang) { return field.key + ':' + lang; }
 
38692     function changeLang(d) {
 
38693         var lang = d3.select(this).value(),
 
38695             language = _.find(iD.data.wikipedia, function(d) {
 
38696                 return d[0].toLowerCase() === lang.toLowerCase() ||
 
38697                     d[1].toLowerCase() === lang.toLowerCase();
 
38700         if (language) lang = language[2];
 
38702         if (d.lang && d.lang !== lang) {
 
38703             t[key(d.lang)] = undefined;
 
38706         var value = d3.select(this.parentNode)
 
38707             .selectAll('.localized-value')
 
38710         if (lang && value) {
 
38711             t[key(lang)] = value;
 
38712         } else if (lang && wikiTitles && wikiTitles[d.lang]) {
 
38713             t[key(lang)] = wikiTitles[d.lang];
 
38717         dispatch.change(t);
 
38720     function changeValue(d) {
 
38721         if (!d.lang) return;
 
38723         t[key(d.lang)] = d3.select(this).value() || undefined;
 
38724         dispatch.change(t);
 
38727     function fetcher(value, cb) {
 
38728         var v = value.toLowerCase();
 
38730         cb(iD.data.wikipedia.filter(function(d) {
 
38731             return d[0].toLowerCase().indexOf(v) >= 0 ||
 
38732             d[1].toLowerCase().indexOf(v) >= 0 ||
 
38733             d[2].toLowerCase().indexOf(v) >= 0;
 
38734         }).map(function(d) {
 
38735             return { value: d[1] };
 
38739     function render(selection, data) {
 
38740         var wraps = selection.selectAll('div.entry').
 
38741             data(data, function(d) { return d.lang; });
 
38743         var innerWrap = wraps.enter()
 
38744             .insert('div', ':first-child');
 
38746         innerWrap.attr('class', 'entry')
 
38748                 var wrap = d3.select(this);
 
38749                 var langcombo = d3.combobox().fetcher(fetcher);
 
38751                 var label = wrap.append('label')
 
38752                     .attr('class','form-label')
 
38753                     .text(t('translate.localized_translation_label'))
 
38754                     .attr('for','localized-lang');
 
38756                 label.append('button')
 
38757                     .attr('class', 'minor remove')
 
38758                     .on('click', function(d){
 
38759                         d3.event.preventDefault();
 
38761                         t[key(d.lang)] = undefined;
 
38762                         dispatch.change(t);
 
38763                         d3.select(this.parentNode.parentNode)
 
38765                             .style('max-height','240px')
 
38767                             .style('opacity', '0')
 
38768                             .style('max-height','0px')
 
38771                     .call(iD.svg.Icon('#operation-delete'));
 
38773                 wrap.append('input')
 
38774                     .attr('class', 'localized-lang')
 
38775                     .attr('type', 'text')
 
38776                     .attr('placeholder',t('translate.localized_translation_language'))
 
38777                     .on('blur', changeLang)
 
38778                     .on('change', changeLang)
 
38781                 wrap.append('input')
 
38782                     .on('blur', changeValue)
 
38783                     .on('change', changeValue)
 
38784                     .attr('type', 'text')
 
38785                     .attr('placeholder', t('translate.localized_translation_name'))
 
38786                     .attr('class', 'localized-value');
 
38790             .style('margin-top', '0px')
 
38791             .style('max-height', '0px')
 
38792             .style('opacity', '0')
 
38795             .style('margin-top', '10px')
 
38796             .style('max-height', '240px')
 
38797             .style('opacity', '1')
 
38798             .each('end', function() {
 
38800                     .style('max-height', '')
 
38801                     .style('overflow', 'visible');
 
38807             .style('max-height','0px')
 
38808             .style('opacity', '0')
 
38809             .style('top','-10px')
 
38812         var entry = selection.selectAll('.entry');
 
38814         entry.select('.localized-lang')
 
38815             .value(function(d) {
 
38816                 var lang = _.find(iD.data.wikipedia, function(lang) { return lang[2] === d.lang; });
 
38817                 return lang ? lang[1] : d.lang;
 
38820         entry.select('.localized-value')
 
38821             .value(function(d) { return d.value; });
 
38824     i.tags = function(tags) {
 
38825         // Fetch translations from wikipedia
 
38826         if (tags.wikipedia && !wikiTitles) {
 
38828             var wm = tags.wikipedia.match(/([^:]+):(.+)/);
 
38829             if (wm && wm[0] && wm[1]) {
 
38830                 wikipedia.translations(wm[1], wm[2], function(d) {
 
38836         input.value(tags[field.key] || '');
 
38838         var postfixed = [], k, m;
 
38840             m = k.match(/^(.*):([a-zA-Z_-]+)$/);
 
38841             if (m && m[1] === field.key && m[2]) {
 
38842                 postfixed.push({ lang: m[2], value: tags[k] });
 
38846         localizedInputs.call(render, postfixed.reverse());
 
38849     i.focus = function() {
 
38850         input.node().focus();
 
38853     i.entity = function(_) {
 
38857     return d3.rebind(i, dispatch, 'on');
 
38859 iD.ui.preset.maxspeed = function(field, context) {
 
38860     var dispatch = d3.dispatch('change'),
 
38867     var metricValues = [20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120],
 
38868         imperialValues = [20, 25, 30, 35, 40, 45, 50, 55, 65, 70];
 
38870     function maxspeed(selection) {
 
38871         combobox = d3.combobox();
 
38872         var unitCombobox = d3.combobox().data(['km/h', 'mph'].map(comboValues));
 
38874         input = selection.selectAll('#preset-input-' + field.id)
 
38877         input.enter().append('input')
 
38878             .attr('type', 'text')
 
38879             .attr('id', 'preset-input-' + field.id)
 
38880             .attr('placeholder', field.placeholder());
 
38884             .on('change', change)
 
38885             .on('blur', change);
 
38887         var childNodes = context.graph().childNodes(context.entity(entity.id)),
 
38888             loc = childNodes[~~(childNodes.length/2)].loc;
 
38890         imperial = _.any(iD.data.imperial.features, function(f) {
 
38891             return _.any(f.geometry.coordinates, function(d) {
 
38892                 return iD.geo.pointInPolygon(loc, d[0]);
 
38896         unitInput = selection.selectAll('input.maxspeed-unit')
 
38899         unitInput.enter().append('input')
 
38900             .attr('type', 'text')
 
38901             .attr('class', 'maxspeed-unit');
 
38904             .on('blur', changeUnits)
 
38905             .on('change', changeUnits)
 
38906             .call(unitCombobox);
 
38908         function changeUnits() {
 
38909             imperial = unitInput.value() === 'mph';
 
38910             unitInput.value(imperial ? 'mph' : 'km/h');
 
38917     function setSuggestions() {
 
38918         combobox.data((imperial ? imperialValues : metricValues).map(comboValues));
 
38919         unitInput.value(imperial ? 'mph' : 'km/h');
 
38922     function comboValues(d) {
 
38924             value: d.toString(),
 
38925             title: d.toString()
 
38929     function change() {
 
38931             value = input.value();
 
38934             tag[field.key] = undefined;
 
38935         } else if (isNaN(value) || !imperial) {
 
38936             tag[field.key] = value;
 
38938             tag[field.key] = value + ' mph';
 
38941         dispatch.change(tag);
 
38944     maxspeed.tags = function(tags) {
 
38945         var value = tags[field.key];
 
38947         if (value && value.indexOf('mph') >= 0) {
 
38948             value = parseInt(value, 10);
 
38950         } else if (value) {
 
38956         input.value(value || '');
 
38959     maxspeed.focus = function() {
 
38960         input.node().focus();
 
38963     maxspeed.entity = function(_) {
 
38967     return d3.rebind(maxspeed, dispatch, 'on');
 
38969 iD.ui.preset.radio = function(field) {
 
38970     var dispatch = d3.dispatch('change'),
 
38971         labels, radios, placeholder;
 
38973     function radio(selection) {
 
38974         selection.classed('preset-radio', true);
 
38976         var wrap = selection.selectAll('.preset-input-wrap')
 
38979         var buttonWrap = wrap.enter().append('div')
 
38980             .attr('class', 'preset-input-wrap toggle-list');
 
38982         buttonWrap.append('span')
 
38983             .attr('class', 'placeholder');
 
38985         placeholder = selection.selectAll('.placeholder');
 
38987         labels = wrap.selectAll('label')
 
38988             .data(field.options || field.keys);
 
38990         var enter = labels.enter().append('label');
 
38992         enter.append('input')
 
38993             .attr('type', 'radio')
 
38994             .attr('name', field.id)
 
38995             .attr('value', function(d) { return field.t('options.' + d, { 'default': d }); })
 
38996             .attr('checked', false);
 
38998         enter.append('span')
 
38999             .text(function(d) { return field.t('options.' + d, { 'default': d }); });
 
39001         radios = labels.selectAll('input')
 
39002             .on('change', change);
 
39005     function change() {
 
39007         if (field.key) t[field.key] = undefined;
 
39008         radios.each(function(d) {
 
39009             var active = d3.select(this).property('checked');
 
39011                 if (active) t[field.key] = d;
 
39013                 t[d] = active ? 'yes' : undefined;
 
39016         dispatch.change(t);
 
39019     radio.tags = function(tags) {
 
39020         function checked(d) {
 
39022                 return tags[field.key] === d;
 
39024                 return !!(tags[d] && tags[d] !== 'no');
 
39028         labels.classed('active', checked);
 
39029         radios.property('checked', checked);
 
39030         var selection = radios.filter(function() { return this.checked; });
 
39031         if (selection.empty()) {
 
39032             placeholder.text(t('inspector.none'));
 
39034             placeholder.text(selection.attr('value'));
 
39038     radio.focus = function() {
 
39039         radios.node().focus();
 
39042     return d3.rebind(radio, dispatch, 'on');
 
39044 iD.ui.preset.restrictions = function(field, context) {
 
39045     var dispatch = d3.dispatch('change'),
 
39046         hover = iD.behavior.Hover(context),
 
39051     function restrictions(selection) {
 
39052         // if form field is hidden or has detached from dom, clean up.
 
39053         if (!d3.select('.inspector-wrap.inspector-hidden').empty() || !selection.node().parentNode) {
 
39054             selection.call(restrictions.off);
 
39058         var wrap = selection.selectAll('.preset-input-wrap')
 
39061         var enter = wrap.enter()
 
39063             .attr('class', 'preset-input-wrap');
 
39067             .attr('class', 'restriction-help');
 
39070         var intersection = iD.geo.Intersection(context.graph(), vertexID),
 
39071             graph = intersection.graph,
 
39072             vertex = graph.entity(vertexID),
 
39073             filter = d3.functor(true),
 
39074             extent = iD.geo.Extent(),
 
39075             projection = iD.geo.RawMercator();
 
39077         var d = wrap.dimensions(),
 
39078             c = [d[0] / 2, d[1] / 2],
 
39082             .scale(256 * Math.pow(2, z) / (2 * Math.PI));
 
39084         var s = projection(vertex.loc);
 
39087             .translate([c[0] - s[0], c[1] - s[1]])
 
39088             .clipExtent([[0, 0], d]);
 
39090         var drawLayers = iD.svg.Layers(projection, context).only('osm').dimensions(d),
 
39091             drawVertices = iD.svg.Vertices(projection, context),
 
39092             drawLines = iD.svg.Lines(projection, context),
 
39093             drawTurns = iD.svg.Turns(projection, context);
 
39097             .selectAll('.surface')
 
39101         var surface = wrap.selectAll('.surface');
 
39105             .call(drawVertices, graph, [vertex], filter, extent, z)
 
39106             .call(drawLines, graph, intersection.ways, filter)
 
39107             .call(drawTurns, graph, intersection.turns(fromNodeID));
 
39110             .on('click.restrictions', click)
 
39111             .on('mouseover.restrictions', mouseover)
 
39112             .on('mouseout.restrictions', mouseout);
 
39115             .selectAll('.selected')
 
39116             .classed('selected', false);
 
39120                 .selectAll('.' + intersection.highways[fromNodeID].id)
 
39121                 .classed('selected', true);
 
39127             .on('change.restrictions', render);
 
39130             .on('resize.restrictions', function() {
 
39131                 wrap.dimensions(null);
 
39136             var datum = d3.event.target.__data__;
 
39137             if (datum instanceof iD.Entity) {
 
39138                 fromNodeID = intersection.adjacentNodeId(datum.id);
 
39140             } else if (datum instanceof iD.geo.Turn) {
 
39141                 if (datum.restriction) {
 
39143                         iD.actions.UnrestrictTurn(datum, projection),
 
39144                         t('operations.restriction.annotation.delete'));
 
39147                         iD.actions.RestrictTurn(datum, projection),
 
39148                         t('operations.restriction.annotation.create'));
 
39153         function mouseover() {
 
39154             var datum = d3.event.target.__data__;
 
39155             if (datum instanceof iD.geo.Turn) {
 
39156                 var graph = context.graph(),
 
39157                     presets = context.presets(),
 
39160                 if (datum.restriction) {
 
39161                     preset = presets.match(graph.entity(datum.restriction), graph);
 
39163                     preset = presets.item('type/restriction/' +
 
39164                         iD.geo.inferRestriction(
 
39172                 wrap.selectAll('.restriction-help')
 
39173                     .text(t('operations.restriction.help.' +
 
39174                         (datum.restriction ? 'toggle_off' : 'toggle_on'),
 
39175                         {restriction: preset.name()}));
 
39179         function mouseout() {
 
39180             wrap.selectAll('.restriction-help')
 
39181                 .text(t('operations.restriction.help.' +
 
39182                     (fromNodeID ? 'toggle' : 'select')));
 
39185         function render() {
 
39186             if (context.hasEntity(vertexID)) {
 
39187                 restrictions(selection);
 
39192     restrictions.entity = function(_) {
 
39193         if (!vertexID || vertexID !== _.id) {
 
39199     restrictions.tags = function() {};
 
39200     restrictions.focus = function() {};
 
39202     restrictions.off = function(selection) {
 
39203         selection.selectAll('.surface')
 
39205             .on('click.restrictions', null)
 
39206             .on('mouseover.restrictions', null)
 
39207             .on('mouseout.restrictions', null);
 
39210             .on('change.restrictions', null);
 
39213             .on('resize.restrictions', null);
 
39216     return d3.rebind(restrictions, dispatch, 'on');
 
39218 iD.ui.preset.textarea = function(field) {
 
39219     var dispatch = d3.dispatch('change'),
 
39222     function i(selection) {
 
39223         input = selection.selectAll('textarea')
 
39226         input.enter().append('textarea')
 
39227             .attr('id', 'preset-input-' + field.id)
 
39228             .attr('placeholder', field.placeholder() || t('inspector.unknown'))
 
39229             .attr('maxlength', 255);
 
39232             .on('input', change(true))
 
39233             .on('blur', change())
 
39234             .on('change', change());
 
39237     function change(onInput) {
 
39238         return function() {
 
39240             t[field.key] = input.value() || undefined;
 
39241             dispatch.change(t, onInput);
 
39245     i.tags = function(tags) {
 
39246         input.value(tags[field.key] || '');
 
39249     i.focus = function() {
 
39250         input.node().focus();
 
39253     return d3.rebind(i, dispatch, 'on');
 
39255 iD.ui.preset.wikipedia = function(field, context) {
 
39256     var dispatch = d3.dispatch('change'),
 
39257         wikipedia = iD.services.wikipedia(),
 
39258         link, entity, lang, title;
 
39260     function i(selection) {
 
39261         var langcombo = d3.combobox()
 
39262             .fetcher(function(value, cb) {
 
39263                 var v = value.toLowerCase();
 
39265                 cb(iD.data.wikipedia.filter(function(d) {
 
39266                     return d[0].toLowerCase().indexOf(v) >= 0 ||
 
39267                         d[1].toLowerCase().indexOf(v) >= 0 ||
 
39268                         d[2].toLowerCase().indexOf(v) >= 0;
 
39269                 }).map(function(d) {
 
39270                     return { value: d[1] };
 
39274         var titlecombo = d3.combobox()
 
39275             .fetcher(function(value, cb) {
 
39277                 if (!value) value = context.entity(entity.id).tags.name || '';
 
39278                 var searchfn = value.length > 7 ? wikipedia.search : wikipedia.suggestions;
 
39280                 searchfn(language()[2], value, function(query, data) {
 
39281                     cb(data.map(function(d) {
 
39282                         return { value: d };
 
39287         lang = selection.selectAll('input.wiki-lang')
 
39290         lang.enter().append('input')
 
39291             .attr('type', 'text')
 
39292             .attr('class', 'wiki-lang')
 
39297             .on('blur', changeLang)
 
39298             .on('change', changeLang);
 
39300         title = selection.selectAll('input.wiki-title')
 
39303         title.enter().append('input')
 
39304             .attr('type', 'text')
 
39305             .attr('class', 'wiki-title')
 
39306             .attr('id', 'preset-input-' + field.id);
 
39310             .on('blur', change)
 
39311             .on('change', change);
 
39313         link = selection.selectAll('a.wiki-link')
 
39316         link.enter().append('a')
 
39317             .attr('class', 'wiki-link button-input-action minor')
 
39318             .attr('target', '_blank')
 
39319             .call(iD.svg.Icon('#icon-out-link', 'inline'));
 
39322     function language() {
 
39323         var value = lang.value().toLowerCase();
 
39324         var locale = iD.detect().locale.toLowerCase();
 
39325         var localeLanguage;
 
39326         return _.find(iD.data.wikipedia, function(d) {
 
39327             if (d[2] === locale) localeLanguage = d;
 
39328             return d[0].toLowerCase() === value ||
 
39329                 d[1].toLowerCase() === value ||
 
39331         }) || localeLanguage || ['English', 'English', 'en'];
 
39334     function changeLang() {
 
39335         lang.value(language()[1]);
 
39339     function change() {
 
39340         var value = title.value(),
 
39341             m = value.match(/https?:\/\/([-a-z]+)\.wikipedia\.org\/(?:wiki|\1-[-a-z]+)\/([^#]+)(?:#(.+))?/),
 
39342             l = m && _.find(iD.data.wikipedia, function(d) { return m[1] === d[2]; }),
 
39346             // Normalize title http://www.mediawiki.org/wiki/API:Query#Title_normalization
 
39347             value = decodeURIComponent(m[2]).replace(/_/g, ' ');
 
39350                     // Best-effort `anchordecode:` implementation
 
39351                     anchor = decodeURIComponent(m[3].replace(/\.([0-9A-F]{2})/g, '%$1'));
 
39353                     anchor = decodeURIComponent(m[3]);
 
39355                 value += '#' + anchor.replace(/_/g, ' ');
 
39357             value = value.slice(0, 1).toUpperCase() + value.slice(1);
 
39359             title.value(value);
 
39363         t[field.key] = value ? language()[2] + ':' + value : undefined;
 
39364         dispatch.change(t);
 
39367     i.tags = function(tags) {
 
39368         var value = tags[field.key] || '',
 
39369             m = value.match(/([^:]+):([^#]+)(?:#(.+))?/),
 
39370             l = m && _.find(iD.data.wikipedia, function(d) { return m[1] === d[2]; }),
 
39371             anchor = m && m[3];
 
39373         // value in correct format
 
39376             title.value(m[2] + (anchor ? ('#' + anchor) : ''));
 
39379                     // Best-effort `anchorencode:` implementation
 
39380                     anchor = encodeURIComponent(anchor.replace(/ /g, '_')).replace(/%/g, '.');
 
39382                     anchor = anchor.replace(/ /g, '_');
 
39385             link.attr('href', 'https://' + m[1] + '.wikipedia.org/wiki/' +
 
39386                       m[2].replace(/ /g, '_') + (anchor ? ('#' + anchor) : ''));
 
39388         // unrecognized value format
 
39390             title.value(value);
 
39391             link.attr('href', 'https://en.wikipedia.org/wiki/Special:Search?search=' + value);
 
39395     i.entity = function(_) {
 
39399     i.focus = function() {
 
39400         title.node().focus();
 
39403     return d3.rebind(i, dispatch, 'on');
 
39405 iD.ui.intro.area = function(context, reveal) {
 
39406     var event = d3.dispatch('done'),
 
39410         title: 'intro.areas.title'
 
39413     step.enter = function() {
 
39414         var playground = [-85.63552, 41.94159],
 
39415             corner = [-85.63565411045074, 41.9417715536927];
 
39416         context.map().centerZoom(playground, 19);
 
39417         reveal('button.add-area',
 
39418             t('intro.areas.add', { button: iD.ui.intro.icon('#icon-area', 'pre-text') }),
 
39419             { tooltipClass: 'intro-areas-add' });
 
39421         context.on('enter.intro', addArea);
 
39423         function addArea(mode) {
 
39424             if (mode.id !== 'add-area') return;
 
39425             context.on('enter.intro', drawArea);
 
39427             var padding = 120 * Math.pow(2, context.map().zoom() - 19);
 
39428             var pointBox = iD.ui.intro.pad(corner, padding, context);
 
39429             reveal(pointBox, t('intro.areas.corner'));
 
39431             context.map().on('move.intro', function() {
 
39432                 padding = 120 * Math.pow(2, context.map().zoom() - 19);
 
39433                 pointBox = iD.ui.intro.pad(corner, padding, context);
 
39434                 reveal(pointBox, t('intro.areas.corner'), {duration: 0});
 
39438         function drawArea(mode) {
 
39439             if (mode.id !== 'draw-area') return;
 
39440             context.on('enter.intro', enterSelect);
 
39442             var padding = 150 * Math.pow(2, context.map().zoom() - 19);
 
39443             var pointBox = iD.ui.intro.pad(playground, padding, context);
 
39444             reveal(pointBox, t('intro.areas.place'));
 
39446             context.map().on('move.intro', function() {
 
39447                 padding = 150 * Math.pow(2, context.map().zoom() - 19);
 
39448                 pointBox = iD.ui.intro.pad(playground, padding, context);
 
39449                 reveal(pointBox, t('intro.areas.place'), {duration: 0});
 
39453         function enterSelect(mode) {
 
39454             if (mode.id !== 'select') return;
 
39455             context.map().on('move.intro', null);
 
39456             context.on('enter.intro', null);
 
39458             timeout = setTimeout(function() {
 
39459                 reveal('.preset-search-input',
 
39460                     t('intro.areas.search',
 
39461                     { name: context.presets().item('leisure/playground').name() }));
 
39462                 d3.select('.preset-search-input').on('keyup.intro', keySearch);
 
39466         function keySearch() {
 
39467             var first = d3.select('.preset-list-item:first-child');
 
39468             if (first.classed('preset-leisure-playground')) {
 
39469                 reveal(first.select('.preset-list-button').node(), t('intro.areas.choose'));
 
39470                 d3.selection.prototype.one.call(context.history(), 'change.intro', selectedPreset);
 
39471                 d3.select('.preset-search-input').on('keyup.intro', null);
 
39475         function selectedPreset() {
 
39477                 t('intro.areas.describe', { button: iD.ui.intro.icon('#icon-apply', 'pre-text') }));
 
39478             context.on('exit.intro', event.done);
 
39482     step.exit = function() {
 
39483         window.clearTimeout(timeout);
 
39484         context.on('enter.intro', null);
 
39485         context.on('exit.intro', null);
 
39486         context.history().on('change.intro', null);
 
39487         context.map().on('move.intro', null);
 
39488         d3.select('.preset-search-input').on('keyup.intro', null);
 
39491     return d3.rebind(step, event, 'on');
 
39493 iD.ui.intro.line = function(context, reveal) {
 
39494     var event = d3.dispatch('done'),
 
39498         title: 'intro.lines.title'
 
39501     function timeout(f, t) {
 
39502         timeouts.push(window.setTimeout(f, t));
 
39505     function eventCancel() {
 
39506         d3.event.stopPropagation();
 
39507         d3.event.preventDefault();
 
39510     step.enter = function() {
 
39511         var centroid = [-85.62830, 41.95699];
 
39512         var midpoint = [-85.62975395449628, 41.95787501510204];
 
39513         var start = [-85.6297754121684, 41.95805253325314];
 
39514         var intersection = [-85.62974496187628, 41.95742515554585];
 
39516         context.map().centerZoom(start, 18);
 
39517         reveal('button.add-line',
 
39518             t('intro.lines.add', { button: iD.ui.intro.icon('#icon-line', 'pre-text') }),
 
39519             { tooltipClass: 'intro-lines-add' });
 
39521         context.on('enter.intro', addLine);
 
39523         function addLine(mode) {
 
39524             if (mode.id !== 'add-line') return;
 
39525             context.on('enter.intro', drawLine);
 
39527             var padding = 150 * Math.pow(2, context.map().zoom() - 18);
 
39528             var pointBox = iD.ui.intro.pad(start, padding, context);
 
39529             reveal(pointBox, t('intro.lines.start'));
 
39531             context.map().on('move.intro', function() {
 
39532                 padding = 150 * Math.pow(2, context.map().zoom() - 18);
 
39533                 pointBox = iD.ui.intro.pad(start, padding, context);
 
39534                 reveal(pointBox, t('intro.lines.start'), {duration: 0});
 
39538         function drawLine(mode) {
 
39539             if (mode.id !== 'draw-line') return;
 
39540             context.history().on('change.intro', addIntersection);
 
39541             context.on('enter.intro', retry);
 
39543             var padding = 300 * Math.pow(2, context.map().zoom() - 19);
 
39544             var pointBox = iD.ui.intro.pad(midpoint, padding, context);
 
39545             reveal(pointBox, t('intro.lines.intersect', {name: t('intro.graph.flower_st')}));
 
39547             context.map().on('move.intro', function() {
 
39548                 padding = 300 * Math.pow(2, context.map().zoom() - 19);
 
39549                 pointBox = iD.ui.intro.pad(midpoint, padding, context);
 
39550                 reveal(pointBox, t('intro.lines.intersect', {name: t('intro.graph.flower_st')}), {duration: 0});
 
39554         // ended line before creating intersection
 
39555         function retry(mode) {
 
39556             if (mode.id !== 'select') return;
 
39557             var pointBox = iD.ui.intro.pad(intersection, 30, context),
 
39558                 ids = mode.selectedIDs();
 
39559             reveal(pointBox, t('intro.lines.restart', {name: t('intro.graph.flower_st')}));
 
39560             d3.select(window).on('mousedown.intro', eventCancel, true);
 
39562             timeout(function() {
 
39563                 context.replace(iD.actions.DeleteMultiple(ids));
 
39569         function addIntersection(changes) {
 
39570             if ( _.any(changes.created(), function(d) {
 
39571                 return d.type === 'node' && context.graph().parentWays(d).length > 1;
 
39573                 context.history().on('change.intro', null);
 
39574                 context.on('enter.intro', enterSelect);
 
39576                 var padding = 900 * Math.pow(2, context.map().zoom() - 19);
 
39577                 var pointBox = iD.ui.intro.pad(centroid, padding, context);
 
39578                 reveal(pointBox, t('intro.lines.finish'));
 
39580                 context.map().on('move.intro', function() {
 
39581                     padding = 900 * Math.pow(2, context.map().zoom() - 19);
 
39582                     pointBox = iD.ui.intro.pad(centroid, padding, context);
 
39583                     reveal(pointBox, t('intro.lines.finish'), {duration: 0});
 
39588         function enterSelect(mode) {
 
39589             if (mode.id !== 'select') return;
 
39590             context.map().on('move.intro', null);
 
39591             context.on('enter.intro', null);
 
39592             d3.select('#curtain').style('pointer-events', 'all');
 
39597         function presetCategory() {
 
39598             timeout(function() {
 
39599                 d3.select('#curtain').style('pointer-events', 'none');
 
39600                 var road = d3.select('.preset-category-road .preset-list-button');
 
39601                 reveal(road.node(), t('intro.lines.road'));
 
39602                 road.one('click.intro', roadCategory);
 
39606         function roadCategory() {
 
39607             timeout(function() {
 
39608                 var grid = d3.select('.subgrid');
 
39609                 reveal(grid.node(), t('intro.lines.residential'));
 
39610                 grid.selectAll(':not(.preset-highway-residential) .preset-list-button')
 
39611                     .one('click.intro', retryPreset);
 
39612                 grid.selectAll('.preset-highway-residential .preset-list-button')
 
39613                     .one('click.intro', roadDetails);
 
39617         // selected wrong road type
 
39618         function retryPreset() {
 
39619             timeout(function() {
 
39620                 var preset = d3.select('.entity-editor-pane .preset-list-button');
 
39621                 reveal(preset.node(), t('intro.lines.wrong_preset'));
 
39622                 preset.one('click.intro', presetCategory);
 
39626         function roadDetails() {
 
39628                 t('intro.lines.describe', { button: iD.ui.intro.icon('#icon-apply', 'pre-text') }));
 
39629             context.on('exit.intro', event.done);
 
39634     step.exit = function() {
 
39635         d3.select(window).on('mousedown.intro', null, true);
 
39636         d3.select('#curtain').style('pointer-events', 'none');
 
39637         timeouts.forEach(window.clearTimeout);
 
39638         context.on('enter.intro', null);
 
39639         context.on('exit.intro', null);
 
39640         context.map().on('move.intro', null);
 
39641         context.history().on('change.intro', null);
 
39644     return d3.rebind(step, event, 'on');
 
39646 iD.ui.intro.navigation = function(context, reveal) {
 
39647     var event = d3.dispatch('done'),
 
39651         title: 'intro.navigation.title'
 
39654     function set(f, t) {
 
39655         timeouts.push(window.setTimeout(f, t));
 
39658     function eventCancel() {
 
39659         d3.event.stopPropagation();
 
39660         d3.event.preventDefault();
 
39663     step.enter = function() {
 
39664         var rect = context.surfaceRect(),
 
39666                 left: rect.left + 10,
 
39667                 top: rect.top + 70,
 
39668                 width: rect.width - 70,
 
39669                 height: rect.height - 170
 
39672         context.map().centerZoom([-85.63591, 41.94285], 19);
 
39674         reveal(map, t('intro.navigation.drag'));
 
39676         context.map().on('move.intro', _.debounce(function() {
 
39677             context.map().on('move.intro', null);
 
39679             context.on('enter.intro', inspectTownHall);
 
39682         function townhall() {
 
39683             var hall = [-85.63645945147184, 41.942986488012565];
 
39685             var point = context.projection(hall);
 
39686             if (point[0] < 0 || point[0] > rect.width ||
 
39687                 point[1] < 0 || point[1] > rect.height) {
 
39688                 context.map().center(hall);
 
39691             var box = iD.ui.intro.pointBox(hall, context);
 
39692             reveal(box, t('intro.navigation.select'));
 
39694             context.map().on('move.intro', function() {
 
39695                 var box = iD.ui.intro.pointBox(hall, context);
 
39696                 reveal(box, t('intro.navigation.select'), {duration: 0});
 
39700         function inspectTownHall(mode) {
 
39701             if (mode.id !== 'select') return;
 
39702             context.on('enter.intro', null);
 
39703             context.map().on('move.intro', null);
 
39705                 reveal('.entity-editor-pane',
 
39706                     t('intro.navigation.pane', { button: iD.ui.intro.icon('#icon-close', 'pre-text') }));
 
39707                 context.on('exit.intro', streetSearch);
 
39711         function streetSearch() {
 
39712             context.on('exit.intro', null);
 
39713             reveal('.search-header input',
 
39714                 t('intro.navigation.search', { name: t('intro.graph.spring_st') }));
 
39715             d3.select('.search-header input').on('keyup.intro', searchResult);
 
39718         function searchResult() {
 
39719             var first = d3.select('.feature-list-item:nth-child(0n+2)'),  // skip No Results item
 
39720                 firstName = first.select('.entity-name'),
 
39721                 name = t('intro.graph.spring_st');
 
39723             if (!firstName.empty() && firstName.text() === name) {
 
39724                 reveal(first.node(), t('intro.navigation.choose', { name: name }));
 
39725                 context.on('exit.intro', selectedStreet);
 
39726                 d3.select('.search-header input')
 
39727                     .on('keydown.intro', eventCancel, true)
 
39728                     .on('keyup.intro', null);
 
39732         function selectedStreet() {
 
39733             var springSt = [-85.63585099140167, 41.942506848938926];
 
39734             context.map().center(springSt);
 
39735             context.on('exit.intro', event.done);
 
39737                 reveal('.entity-editor-pane',
 
39738                     t('intro.navigation.chosen', {
 
39739                         name: t('intro.graph.spring_st'),
 
39740                         button: iD.ui.intro.icon('#icon-close', 'pre-text')
 
39746     step.exit = function() {
 
39747         timeouts.forEach(window.clearTimeout);
 
39748         context.map().on('move.intro', null);
 
39749         context.on('enter.intro', null);
 
39750         context.on('exit.intro', null);
 
39751         d3.select('.search-header input')
 
39752             .on('keydown.intro', null)
 
39753             .on('keyup.intro', null);
 
39756     return d3.rebind(step, event, 'on');
 
39758 iD.ui.intro.point = function(context, reveal) {
 
39759     var event = d3.dispatch('done'),
 
39763         title: 'intro.points.title'
 
39766     function setTimeout(f, t) {
 
39767         timeouts.push(window.setTimeout(f, t));
 
39770     function eventCancel() {
 
39771         d3.event.stopPropagation();
 
39772         d3.event.preventDefault();
 
39775     step.enter = function() {
 
39776         context.map().centerZoom([-85.63279, 41.94394], 19);
 
39777         reveal('button.add-point',
 
39778             t('intro.points.add', { button: iD.ui.intro.icon('#icon-point', 'pre-text') }),
 
39779             { tooltipClass: 'intro-points-add' });
 
39781         var corner = [-85.632481,41.944094];
 
39783         context.on('enter.intro', addPoint);
 
39785         function addPoint(mode) {
 
39786             if (mode.id !== 'add-point') return;
 
39787             context.on('enter.intro', enterSelect);
 
39789             var pointBox = iD.ui.intro.pad(corner, 150, context);
 
39790             reveal(pointBox, t('intro.points.place'));
 
39792             context.map().on('move.intro', function() {
 
39793                 pointBox = iD.ui.intro.pad(corner, 150, context);
 
39794                 reveal(pointBox, t('intro.points.place'), {duration: 0});
 
39798         function enterSelect(mode) {
 
39799             if (mode.id !== 'select') return;
 
39800             context.map().on('move.intro', null);
 
39801             context.on('enter.intro', null);
 
39803             setTimeout(function() {
 
39804                 reveal('.preset-search-input',
 
39805                     t('intro.points.search', {name: context.presets().item('amenity/cafe').name()}));
 
39806                 d3.select('.preset-search-input').on('keyup.intro', keySearch);
 
39810         function keySearch() {
 
39811             var first = d3.select('.preset-list-item:first-child');
 
39812             if (first.classed('preset-amenity-cafe')) {
 
39813                 reveal(first.select('.preset-list-button').node(), t('intro.points.choose'));
 
39814                 d3.selection.prototype.one.call(context.history(), 'change.intro', selectedPreset);
 
39815                 d3.select('.preset-search-input')
 
39816                     .on('keydown.intro', eventCancel, true)
 
39817                     .on('keyup.intro', null);
 
39821         function selectedPreset() {
 
39822             setTimeout(function() {
 
39823                 reveal('.entity-editor-pane', t('intro.points.describe'), {tooltipClass: 'intro-points-describe'});
 
39824                 context.history().on('change.intro', closeEditor);
 
39825                 context.on('exit.intro', selectPoint);
 
39829         function closeEditor() {
 
39830             d3.select('.preset-search-input').on('keydown.intro', null);
 
39831             context.history().on('change.intro', null);
 
39832             reveal('.entity-editor-pane',
 
39833                 t('intro.points.close', { button: iD.ui.intro.icon('#icon-apply', 'pre-text') }));
 
39836         function selectPoint() {
 
39837             context.on('exit.intro', null);
 
39838             context.history().on('change.intro', null);
 
39839             context.on('enter.intro', enterReselect);
 
39841             var pointBox = iD.ui.intro.pad(corner, 150, context);
 
39842             reveal(pointBox, t('intro.points.reselect'));
 
39844             context.map().on('move.intro', function() {
 
39845                 pointBox = iD.ui.intro.pad(corner, 150, context);
 
39846                 reveal(pointBox, t('intro.points.reselect'), {duration: 0});
 
39850         function enterReselect(mode) {
 
39851             if (mode.id !== 'select') return;
 
39852             context.map().on('move.intro', null);
 
39853             context.on('enter.intro', null);
 
39855             setTimeout(function() {
 
39856                 reveal('.entity-editor-pane',
 
39857                     t('intro.points.fixname', { button: iD.ui.intro.icon('#icon-apply', 'pre-text') }));
 
39858                 context.on('exit.intro', deletePoint);
 
39862         function deletePoint() {
 
39863             context.on('exit.intro', null);
 
39864             context.on('enter.intro', enterDelete);
 
39866             var pointBox = iD.ui.intro.pad(corner, 150, context);
 
39867             reveal(pointBox, t('intro.points.reselect_delete'));
 
39869             context.map().on('move.intro', function() {
 
39870                 pointBox = iD.ui.intro.pad(corner, 150, context);
 
39871                 reveal(pointBox, t('intro.points.reselect_delete'), {duration: 0});
 
39875         function enterDelete(mode) {
 
39876             if (mode.id !== 'select') return;
 
39877             context.map().on('move.intro', null);
 
39878             context.on('enter.intro', null);
 
39879             context.on('exit.intro', deletePoint);
 
39880             context.map().on('move.intro', deletePoint);
 
39881             context.history().on('change.intro', deleted);
 
39883             setTimeout(function() {
 
39884                 var node = d3.select('.radial-menu-item-delete').node();
 
39885                 var pointBox = iD.ui.intro.pad(node.getBoundingClientRect(), 50, context);
 
39887                     t('intro.points.delete', { button: iD.ui.intro.icon('#operation-delete', 'pre-text') }));
 
39891         function deleted(changed) {
 
39892             if (changed.deleted().length) event.done();
 
39897     step.exit = function() {
 
39898         timeouts.forEach(window.clearTimeout);
 
39899         context.on('exit.intro', null);
 
39900         context.on('enter.intro', null);
 
39901         context.map().on('move.intro', null);
 
39902         context.history().on('change.intro', null);
 
39903         d3.select('.preset-search-input')
 
39904             .on('keyup.intro', null)
 
39905             .on('keydown.intro', null);
 
39908     return d3.rebind(step, event, 'on');
 
39910 iD.ui.intro.startEditing = function(context, reveal) {
 
39911     var event = d3.dispatch('done', 'startEditing'),
 
39916         title: 'intro.startediting.title'
 
39919     function timeout(f, t) {
 
39920         timeouts.push(window.setTimeout(f, t));
 
39923     step.enter = function() {
 
39924         reveal('.map-control.help-control',
 
39925             t('intro.startediting.help', { button: iD.ui.intro.icon('#icon-help', 'pre-text') }));
 
39927         timeout(function() {
 
39928             reveal('#bar button.save', t('intro.startediting.save'));
 
39931         timeout(function() {
 
39932             reveal('#surface');
 
39935         timeout(function() {
 
39936             modal = iD.ui.modal(context.container());
 
39938             modal.select('.modal')
 
39939                 .attr('class', 'modal-splash modal col6');
 
39941             modal.selectAll('.close').remove();
 
39943             var startbutton = modal.select('.content')
 
39944                 .attr('class', 'fillL')
 
39946                         .attr('class', 'modal-section huge-modal-button')
 
39947                         .on('click', function() {
 
39951                 startbutton.append('div')
 
39952                     .attr('class','illustration');
 
39953                 startbutton.append('h2')
 
39954                     .text(t('intro.startediting.start'));
 
39956             event.startEditing();
 
39960     step.exit = function() {
 
39961         if (modal) modal.remove();
 
39962         timeouts.forEach(window.clearTimeout);
 
39965     return d3.rebind(step, event, 'on');
 
39967 iD.presets = function() {
 
39969     // an iD.presets.Collection with methods for
 
39970     // loading new data and returning defaults
 
39972     var all = iD.presets.Collection([]),
 
39973         defaults = { area: all, line: all, point: all, vertex: all, relation: all },
 
39976         recent = iD.presets.Collection([]);
 
39978     // Index of presets by (geometry, tag key).
 
39987     all.match = function(entity, resolver) {
 
39988         var geometry = entity.geometry(resolver),
 
39989             geometryMatches = index[geometry],
 
39993         for (var k in entity.tags) {
 
39994             var keyMatches = geometryMatches[k];
 
39995             if (!keyMatches) continue;
 
39997             for (var i = 0; i < keyMatches.length; i++) {
 
39998                 var score = keyMatches[i].matchScore(entity);
 
39999                 if (score > best) {
 
40001                     match = keyMatches[i];
 
40006         return match || all.item(geometry);
 
40009     // Because of the open nature of tagging, iD will never have a complete
 
40010     // list of tags used in OSM, so we want it to have logic like "assume
 
40011     // that a closed way with an amenity tag is an area, unless the amenity
 
40012     // is one of these specific types". This function computes a structure
 
40013     // that allows testing of such conditions, based on the presets designated
 
40014     // as as supporting (or not supporting) the area geometry.
 
40016     // The returned object L is a whitelist/blacklist of tags. A closed way
 
40017     // with a tag (k, v) is considered to be an area if `k in L && !(v in L[k])`
 
40018     // (see `iD.Way#isArea()`). In other words, the keys of L form the whitelist,
 
40019     // and the subkeys form the blacklist.
 
40020     all.areaKeys = function() {
 
40022             ignore = ['barrier', 'highway', 'footway', 'railway', 'type'],
 
40023             presets = _.reject(all.collection, 'suggestion');
 
40026         presets.forEach(function(d) {
 
40027             for (var key in d.tags) break;
 
40029             if (ignore.indexOf(key) !== -1) return;
 
40031             if (d.geometry.indexOf('area') !== -1) {
 
40032                 areaKeys[key] = areaKeys[key] || {};
 
40037         presets.forEach(function(d) {
 
40038             for (var key in d.tags) break;
 
40040             if (ignore.indexOf(key) !== -1) return;
 
40042             var value = d.tags[key];
 
40043             if (d.geometry.indexOf('area') === -1 && key in areaKeys && value !== '*') {
 
40044                 areaKeys[key][value] = true;
 
40051     all.load = function(d) {
 
40054             _.forEach(d.fields, function(d, id) {
 
40055                 fields[id] = iD.presets.Field(id, d);
 
40056                 if (d.universal) universal.push(fields[id]);
 
40061             _.forEach(d.presets, function(d, id) {
 
40062                 all.collection.push(iD.presets.Preset(id, d, fields));
 
40066         if (d.categories) {
 
40067             _.forEach(d.categories, function(d, id) {
 
40068                 all.collection.push(iD.presets.Category(id, d, all));
 
40073             var getItem = _.bind(all.item, all);
 
40075                 area: iD.presets.Collection(d.defaults.area.map(getItem)),
 
40076                 line: iD.presets.Collection(d.defaults.line.map(getItem)),
 
40077                 point: iD.presets.Collection(d.defaults.point.map(getItem)),
 
40078                 vertex: iD.presets.Collection(d.defaults.vertex.map(getItem)),
 
40079                 relation: iD.presets.Collection(d.defaults.relation.map(getItem))
 
40083         for (var i = 0; i < all.collection.length; i++) {
 
40084             var preset = all.collection[i],
 
40085                 geometry = preset.geometry;
 
40087             for (var j = 0; j < geometry.length; j++) {
 
40088                 var g = index[geometry[j]];
 
40089                 for (var k in preset.tags) {
 
40090                     (g[k] = g[k] || []).push(preset);
 
40098     all.field = function(id) {
 
40102     all.universal = function() {
 
40106     all.defaults = function(geometry, n) {
 
40107         var rec = recent.matchGeometry(geometry).collection.slice(0, 4),
 
40108             def = _.uniq(rec.concat(defaults[geometry].collection)).slice(0, n - 1);
 
40109         return iD.presets.Collection(_.unique(rec.concat(def).concat(all.item(geometry))));
 
40112     all.choose = function(preset) {
 
40113         if (!preset.isFallback()) {
 
40114             recent = iD.presets.Collection(_.unique([preset].concat(recent.collection)));
 
40121 iD.presets.Category = function(id, category, all) {
 
40122     category = _.clone(category);
 
40126     category.members = iD.presets.Collection(category.members.map(function(id) {
 
40127         return all.item(id);
 
40130     category.matchGeometry = function(geometry) {
 
40131         return category.geometry.indexOf(geometry) >= 0;
 
40134     category.matchScore = function() { return -1; };
 
40136     category.name = function() {
 
40137         return t('presets.categories.' + id + '.name', {'default': id});
 
40140     category.terms = function() {
 
40146 iD.presets.Collection = function(collection) {
 
40148     var maxSearchResults = 50,
 
40149         maxSuggestionResults = 10;
 
40153         collection: collection,
 
40155         item: function(id) {
 
40156             return _.find(collection, function(d) {
 
40157                 return d.id === id;
 
40161         matchGeometry: function(geometry) {
 
40162             return iD.presets.Collection(collection.filter(function(d) {
 
40163                 return d.matchGeometry(geometry);
 
40167         search: function(value, geometry) {
 
40168             if (!value) return this;
 
40170             value = value.toLowerCase();
 
40172             var searchable = _.filter(collection, function(a) {
 
40173                     return a.searchable !== false && a.suggestion !== true;
 
40175                 suggestions = _.filter(collection, function(a) {
 
40176                     return a.suggestion === true;
 
40179             function leading(a) {
 
40180                 var index = a.indexOf(value);
 
40181                 return index === 0 || a[index - 1] === ' ';
 
40184             // matches value to preset.name
 
40185             var leading_name = _.filter(searchable, function(a) {
 
40186                     return leading(a.name().toLowerCase());
 
40187                 }).sort(function(a, b) {
 
40188                     var i = a.name().toLowerCase().indexOf(value) - b.name().toLowerCase().indexOf(value);
 
40189                     if (i === 0) return a.name().length - b.name().length;
 
40193             // matches value to preset.terms values
 
40194             var leading_terms = _.filter(searchable, function(a) {
 
40195                     return _.any(a.terms() || [], leading);
 
40198             // matches value to preset.tags values
 
40199             var leading_tag_values = _.filter(searchable, function(a) {
 
40200                     return _.any(_.without(_.values(a.tags || {}), '*'), leading);
 
40204             // finds close matches to value in preset.name
 
40205             var levenstein_name = searchable.map(function(a) {
 
40208                         dist: iD.util.editDistance(value, a.name().toLowerCase())
 
40210                 }).filter(function(a) {
 
40211                     return a.dist + Math.min(value.length - a.preset.name().length, 0) < 3;
 
40212                 }).sort(function(a, b) {
 
40213                     return a.dist - b.dist;
 
40214                 }).map(function(a) {
 
40218             // finds close matches to value in preset.terms
 
40219             var leventstein_terms = _.filter(searchable, function(a) {
 
40220                     return _.any(a.terms() || [], function(b) {
 
40221                         return iD.util.editDistance(value, b) + Math.min(value.length - b.length, 0) < 3;
 
40225             function suggestionName(name) {
 
40226                 var nameArray = name.split(' - ');
 
40227                 if (nameArray.length > 1) {
 
40228                     name = nameArray.slice(0, nameArray.length-1).join(' - ');
 
40230                 return name.toLowerCase();
 
40233             var leading_suggestions = _.filter(suggestions, function(a) {
 
40234                     return leading(suggestionName(a.name()));
 
40235                 }).sort(function(a, b) {
 
40236                     a = suggestionName(a.name());
 
40237                     b = suggestionName(b.name());
 
40238                     var i = a.indexOf(value) - b.indexOf(value);
 
40239                     if (i === 0) return a.length - b.length;
 
40243             var leven_suggestions = suggestions.map(function(a) {
 
40246                         dist: iD.util.editDistance(value, suggestionName(a.name()))
 
40248                 }).filter(function(a) {
 
40249                     return a.dist + Math.min(value.length - suggestionName(a.preset.name()).length, 0) < 1;
 
40250                 }).sort(function(a, b) {
 
40251                     return a.dist - b.dist;
 
40252                 }).map(function(a) {
 
40256             var other = presets.item(geometry);
 
40258             var results = leading_name.concat(
 
40260                             leading_tag_values,
 
40261                             leading_suggestions.slice(0, maxSuggestionResults+5),
 
40264                             leven_suggestions.slice(0, maxSuggestionResults)
 
40265                         ).slice(0, maxSearchResults-1);
 
40267             return iD.presets.Collection(_.unique(
 
40268                     results.concat(other)
 
40275 iD.presets.Field = function(id, field) {
 
40276     field = _.clone(field);
 
40280     field.matchGeometry = function(geometry) {
 
40281         return !field.geometry || field.geometry === geometry;
 
40284     field.t = function(scope, options) {
 
40285         return t('presets.fields.' + id + '.' + scope, options);
 
40288     field.label = function() {
 
40289         return field.t('label', {'default': id});
 
40292     var placeholder = field.placeholder;
 
40293     field.placeholder = function() {
 
40294         return field.t('placeholder', {'default': placeholder});
 
40299 iD.presets.Preset = function(id, preset, fields) {
 
40300     preset = _.clone(preset);
 
40303     preset.fields = (preset.fields || []).map(getFields);
 
40304     preset.geometry = (preset.geometry || []);
 
40306     function getFields(f) {
 
40310     preset.matchGeometry = function(geometry) {
 
40311         return preset.geometry.indexOf(geometry) >= 0;
 
40314     var matchScore = preset.matchScore || 1;
 
40315     preset.matchScore = function(entity) {
 
40316         var tags = preset.tags,
 
40319         for (var t in tags) {
 
40320             if (entity.tags[t] === tags[t]) {
 
40321                 score += matchScore;
 
40322             } else if (tags[t] === '*' && t in entity.tags) {
 
40323                 score += matchScore / 2;
 
40332     preset.t = function(scope, options) {
 
40333         return t('presets.presets.' + id + '.' + scope, options);
 
40336     var name = preset.name;
 
40337     preset.name = function() {
 
40338         if (preset.suggestion) {
 
40339             id = id.split('/');
 
40340             id = id[0] + '/' + id[1];
 
40341             return name + ' - ' + t('presets.presets.' + id + '.name');
 
40343         return preset.t('name', {'default': name});
 
40346     preset.terms = function() {
 
40347         return preset.t('terms', {'default': ''}).toLowerCase().trim().split(/\s*,+\s*/);
 
40350     preset.isFallback = function() {
 
40351         var tagCount = Object.keys(preset.tags).length;
 
40352         return tagCount === 0 || (tagCount === 1 && preset.tags.hasOwnProperty('area'));
 
40355     preset.reference = function(geometry) {
 
40356         var key = Object.keys(preset.tags)[0],
 
40357             value = preset.tags[key];
 
40359         if (geometry === 'relation' && key === 'type') {
 
40360             return { rtype: value };
 
40361         } else if (value === '*') {
 
40362             return { key: key };
 
40364             return { key: key, value: value };
 
40368     var removeTags = preset.removeTags || preset.tags;
 
40369     preset.removeTags = function(tags, geometry) {
 
40370         tags = _.omit(tags, _.keys(removeTags));
 
40372         for (var f in preset.fields) {
 
40373             var field = preset.fields[f];
 
40374             if (field.matchGeometry(geometry) && field.default === tags[field.key]) {
 
40375                 delete tags[field.key];
 
40383     var applyTags = preset.addTags || preset.tags;
 
40384     preset.applyTags = function(tags, geometry) {
 
40387         tags = _.clone(tags);
 
40389         for (k in applyTags) {
 
40390             if (applyTags[k] === '*') {
 
40393                 tags[k] = applyTags[k];
 
40397         // Add area=yes if necessary.
 
40398         // This is necessary if the geometry is already an area (e.g. user drew an area) AND any of:
 
40399         // 1. chosen preset could be either an area or a line (`barrier=city_wall`)
 
40400         // 2. chosen preset doesn't have a key in areaKeys (`railway=station`)
 
40401         if (geometry === 'area') {
 
40402             var needsAreaTag = true;
 
40403             if (preset.geometry.indexOf('line') === -1) {
 
40404                 for (k in applyTags) {
 
40405                     if (k in iD.areaKeys) {
 
40406                         needsAreaTag = false;
 
40411             if (needsAreaTag) {
 
40416         for (var f in preset.fields) {
 
40417             var field = preset.fields[f];
 
40418             if (field.matchGeometry(geometry) && field.key && !tags[field.key] && field.default) {
 
40419                 tags[field.key] = field.default;
 
40428 iD.validations = {};
 
40429 iD.validations.DeprecatedTag = function() {
 
40431     var validation = function(changes) {
 
40433         for (var i = 0; i < changes.created.length; i++) {
 
40434             var change = changes.created[i],
 
40435                 deprecatedTags = change.deprecatedTags();
 
40437             if (!_.isEmpty(deprecatedTags)) {
 
40438                 var tags = iD.util.tagText({ tags: deprecatedTags });
 
40440                     id: 'deprecated_tags',
 
40441                     message: t('validations.deprecated_tags', { tags: tags }),
 
40451 iD.validations.ManyDeletions = function() {
 
40452     var threshold = 100;
 
40454     var validation = function(changes) {
 
40456         if (changes.deleted.length > threshold) {
 
40458                 id: 'many_deletions',
 
40459                 message: t('validations.many_deletions', { n: changes.deleted.length })
 
40467 iD.validations.MissingTag = function() {
 
40469     var validation = function(changes, graph) {
 
40471         for (var i = 0; i < changes.created.length; i++) {
 
40472             var change = changes.created[i],
 
40473                 geometry = change.geometry(graph);
 
40475             if ((geometry === 'point' || geometry === 'line' || geometry === 'area') && !change.isUsed(graph)) {
 
40478                     message: t('validations.untagged_' + geometry),
 
40479                     tooltip: t('validations.untagged_' + geometry + '_tooltip'),
 
40489 iD.validations.TagSuggestsArea = function() {
 
40491     // https://github.com/openstreetmap/josm/blob/mirror/src/org/
 
40492     // openstreetmap/josm/data/validation/tests/UnclosedWays.java#L80
 
40493     function tagSuggestsArea(tags) {
 
40494         if (_.isEmpty(tags)) return false;
 
40496         var presence = ['landuse', 'amenities', 'tourism', 'shop'];
 
40497         for (var i = 0; i < presence.length; i++) {
 
40498             if (tags[presence[i]] !== undefined) {
 
40499                 return presence[i] + '=' + tags[presence[i]];
 
40503         if (tags.building && tags.building === 'yes') return 'building=yes';
 
40506     var validation = function(changes, graph) {
 
40508         for (var i = 0; i < changes.created.length; i++) {
 
40509             var change = changes.created[i],
 
40510                 geometry = change.geometry(graph),
 
40511                 suggestion = (geometry === 'line' ? tagSuggestsArea(change.tags) : undefined);
 
40515                     id: 'tag_suggests_area',
 
40516                     message: t('validations.tag_suggests_area', { tag: suggestion }),
 
40527 window.locale = { _current: 'en' };
 
40529 locale.current = function(_) {
 
40530     if (!arguments.length) return locale._current;
 
40531     if (locale[_] !== undefined) locale._current = _;
 
40532     else if (locale[_.split('-')[0]]) locale._current = _.split('-')[0];
 
40536 function t(s, o, loc) {
 
40537     loc = loc || locale._current;
 
40539     var path = s.split(".").reverse(),
 
40542     while (rep !== undefined && path.length) rep = rep[path.pop()];
 
40544     if (rep !== undefined) {
 
40545         if (o) for (var k in o) rep = rep.replace('{' + k + '}', o[k]);
 
40549     if (loc !== 'en') {
 
40550         return t(s, o, 'en');
 
40553     if (o && 'default' in o) {
 
40554         return o['default'];
 
40557     var missing = 'Missing ' + loc + ' translation: ' + s;
 
40558     if (typeof console !== "undefined") console.error(missing);
 
40562 iD.introGraph = '{"n185954700":{"id":"n185954700","loc":[-85.642244,41.939081]},"n185964961":{"id":"n185964961","loc":[-85.6406588,41.942601]},"n185964962":{"id":"n185964962","loc":[-85.6394548,41.94261]},"n185970607":{"id":"n185970607","loc":[-85.641094,41.94006]},"n185970614":{"id":"n185970614","loc":[-85.641825,41.941316]},"n185970616":{"id":"n185970616","loc":[-85.641838,41.941556]},"n185973650":{"id":"n185973650","loc":[-85.639918,41.940064]},"n185973660":{"id":"n185973660","loc":[-85.640645,41.941339]},"n185973659":{"id":"n185973659","loc":[-85.6406115,41.9400658]},"n185974479":{"id":"n185974479","loc":[-85.639402,41.941344]},"n185974481":{"id":"n185974481","loc":[-85.643071,41.941288]},"n185976259":{"id":"n185976259","loc":[-85.642213,41.940043]},"n185976261":{"id":"n185976261","loc":[-85.643056,41.94001]},"n185964959":{"id":"n185964959","loc":[-85.6431031,41.9425754]},"n185964960":{"id":"n185964960","loc":[-85.6418749,41.9425864]},"n185981481":{"id":"n185981481","loc":[-85.6386827,41.9400828]},"n185981482":{"id":"n185981482","loc":[-85.6393664,41.9400854]},"n2138493844":{"id":"n2138493844","loc":[-85.6427969,41.940522]},"n2138493845":{"id":"n2138493845","loc":[-85.6425891,41.9405228]},"n2138493846":{"id":"n2138493846","loc":[-85.6425868,41.9402875]},"n2138493847":{"id":"n2138493847","loc":[-85.6427969,41.9402858]},"n2138493848":{"id":"n2138493848","loc":[-85.6425708,41.9405234]},"n2138493849":{"id":"n2138493849","loc":[-85.642568,41.9402855]},"n2138493850":{"id":"n2138493850","loc":[-85.6423157,41.9402886]},"n2138493851":{"id":"n2138493851","loc":[-85.6423212,41.9404362]},"n2138493852":{"id":"n2138493852","loc":[-85.6422923,41.9404578]},"n2138493853":{"id":"n2138493853","loc":[-85.6422868,41.9404834]},"n2138493854":{"id":"n2138493854","loc":[-85.6423226,41.9405091]},"n2138493855":{"id":"n2138493855","loc":[-85.6423847,41.9405111]},"n2138493856":{"id":"n2138493856","loc":[-85.6424081,41.9405265]},"n2140155811":{"id":"n2140155811","loc":[-85.6419547,41.9410956]},"n2140155814":{"id":"n2140155814","loc":[-85.6427577,41.9410884]},"n2140155816":{"id":"n2140155816","loc":[-85.6427545,41.9410052]},"n2140155818":{"id":"n2140155818","loc":[-85.6428057,41.9410028]},"n2140155821":{"id":"n2140155821","loc":[-85.6427993,41.9407339]},"n2140155823":{"id":"n2140155823","loc":[-85.6427385,41.9407339]},"n2140155825":{"id":"n2140155825","loc":[-85.6427417,41.9406435]},"n2140155827":{"id":"n2140155827","loc":[-85.6419515,41.9406482]},"n2140155828":{"id":"n2140155828","loc":[-85.6429368,41.9412407]},"n2140155829":{"id":"n2140155829","loc":[-85.6417756,41.9412526]},"n2140155830":{"id":"n2140155830","loc":[-85.641766,41.9405983]},"n2140155831":{"id":"n2140155831","loc":[-85.6419803,41.9405983]},"n2140155832":{"id":"n2140155832","loc":[-85.6419611,41.9401366]},"n2140155833":{"id":"n2140155833","loc":[-85.6429336,41.94012]},"n2140155834":{"id":"n2140155834","loc":[-85.6430697,41.9411732]},"n2140155835":{"id":"n2140155835","loc":[-85.6428411,41.9409974]},"n2140155837":{"id":"n2140155837","loc":[-85.6428388,41.9407211]},"n2140155839":{"id":"n2140155839","loc":[-85.6430624,41.9405521]},"n2140155840":{"id":"n2140155840","loc":[-85.6427323,41.9412396]},"n2140155842":{"id":"n2140155842","loc":[-85.6418147,41.9412457]},"n2140155844":{"id":"n2140155844","loc":[-85.641813,41.9411319]},"n2140155845":{"id":"n2140155845","loc":[-85.6418394,41.9411111]},"n2140155847":{"id":"n2140155847","loc":[-85.6418838,41.9410977]},"n2140155849":{"id":"n2140155849","loc":[-85.6427324,41.9410921]},"n2140155851":{"id":"n2140155851","loc":[-85.6427798,41.9412945]},"n2140155852":{"id":"n2140155852","loc":[-85.6427701,41.9411777]},"n2140155854":{"id":"n2140155854","loc":[-85.6427323,41.9411572]},"n2140155856":{"id":"n2140155856","loc":[-85.6418478,41.9411666]},"n2165942818":{"id":"n2165942818","loc":[-85.6437533,41.9415029]},"n2165942819":{"id":"n2165942819","loc":[-85.6437623,41.9421195]},"n2168510551":{"id":"n2168510551","loc":[-85.6423795,41.9422615]},"n2168510552":{"id":"n2168510552","loc":[-85.6423744,41.9419439]},"n2168510553":{"id":"n2168510553","loc":[-85.642518,41.9419427]},"n2168510554":{"id":"n2168510554","loc":[-85.6425186,41.9419801]},"n2168510555":{"id":"n2168510555","loc":[-85.6428314,41.9419773]},"n2168510556":{"id":"n2168510556","loc":[-85.6428368,41.9423116]},"n2168510557":{"id":"n2168510557","loc":[-85.6424947,41.9423146]},"n2168510558":{"id":"n2168510558","loc":[-85.6424938,41.9422605]},"n2189046007":{"id":"n2189046007","loc":[-85.6410866,41.9424327]},"n2189046009":{"id":"n2189046009","loc":[-85.6410805,41.9420061]},"n2189046011":{"id":"n2189046011","loc":[-85.6412443,41.9420048]},"n2189046012":{"id":"n2189046012","loc":[-85.6412505,41.9424314]},"n2189046014":{"id":"n2189046014","loc":[-85.6413311,41.942968]},"n2189046016":{"id":"n2189046016","loc":[-85.6413281,41.942713]},"n2189046018":{"id":"n2189046018","loc":[-85.641521,41.9427117]},"n2189046021":{"id":"n2189046021","loc":[-85.6415234,41.9429236]},"n2189046022":{"id":"n2189046022","loc":[-85.6415045,41.9429238]},"n2189046025":{"id":"n2189046025","loc":[-85.641505,41.9429668]},"n2189046053":{"id":"n2189046053","loc":[-85.6385988,41.942412]},"n2189046054":{"id":"n2189046054","loc":[-85.6385985,41.9423311]},"n2189046055":{"id":"n2189046055","loc":[-85.6387617,41.9423308]},"n2189046056":{"id":"n2189046056","loc":[-85.6387616,41.9423026]},"n2189046058":{"id":"n2189046058","loc":[-85.6388215,41.9423025]},"n2189046059":{"id":"n2189046059","loc":[-85.6388219,41.9424115]},"n2189046060":{"id":"n2189046060","loc":[-85.6391096,41.9424486]},"n2189046061":{"id":"n2189046061","loc":[-85.6391105,41.9423673]},"n2189046063":{"id":"n2189046063","loc":[-85.6392911,41.9423684]},"n2189046065":{"id":"n2189046065","loc":[-85.6392903,41.9424497]},"n2189046067":{"id":"n2189046067","loc":[-85.6397927,41.9423876]},"n2189046069":{"id":"n2189046069","loc":[-85.6397897,41.9422981]},"n2189046070":{"id":"n2189046070","loc":[-85.6399702,41.9422947]},"n2189046072":{"id":"n2189046072","loc":[-85.6399732,41.9423843]},"n2189046074":{"id":"n2189046074","loc":[-85.6396331,41.9430227]},"n2189046075":{"id":"n2189046075","loc":[-85.6398673,41.9430189]},"n2189046077":{"id":"n2189046077","loc":[-85.6398656,41.9429637]},"n2189046079":{"id":"n2189046079","loc":[-85.6398885,41.9429633]},"n2189046082":{"id":"n2189046082","loc":[-85.6398832,41.942779]},"n2189046083":{"id":"n2189046083","loc":[-85.6398513,41.9427796]},"n2189046085":{"id":"n2189046085","loc":[-85.6398502,41.9427401]},"n2189046087":{"id":"n2189046087","loc":[-85.6397889,41.9427411]},"n2189046089":{"id":"n2189046089","loc":[-85.6397892,41.942753]},"n2189046090":{"id":"n2189046090","loc":[-85.6396983,41.9427544]},"n2189046092":{"id":"n2189046092","loc":[-85.6396993,41.9427882]},"n2189046094":{"id":"n2189046094","loc":[-85.6396746,41.9427886]},"n2189046096":{"id":"n2189046096","loc":[-85.6396758,41.9428296]},"n2189046097":{"id":"n2189046097","loc":[-85.6397007,41.9428292]},"n2189046099":{"id":"n2189046099","loc":[-85.6397018,41.9428686]},"n2189046103":{"id":"n2189046103","loc":[-85.6396289,41.9428697]},"n2189046112":{"id":"n2189046112","loc":[-85.6435683,41.9429457]},"n2189046113":{"id":"n2189046113","loc":[-85.643568,41.9427766]},"n2189046115":{"id":"n2189046115","loc":[-85.6434011,41.9427767]},"n2189046116":{"id":"n2189046116","loc":[-85.6434012,41.9428631]},"n2189046117":{"id":"n2189046117","loc":[-85.643448,41.9428631]},"n2189046118":{"id":"n2189046118","loc":[-85.6434481,41.9429457]},"n2189046119":{"id":"n2189046119","loc":[-85.6428363,41.9429809]},"n2189046120":{"id":"n2189046120","loc":[-85.6429171,41.9429791]},"n2189046121":{"id":"n2189046121","loc":[-85.642914,41.9429041]},"n2189046122":{"id":"n2189046122","loc":[-85.6429385,41.9429035]},"n2189046123":{"id":"n2189046123","loc":[-85.6429348,41.9428126]},"n2189046124":{"id":"n2189046124","loc":[-85.6427746,41.9428163]},"n2189046125":{"id":"n2189046125","loc":[-85.6427783,41.942906]},"n2189046126":{"id":"n2189046126","loc":[-85.6428332,41.9429047]},"n2189046127":{"id":"n2189046127","loc":[-85.6423018,41.9428859]},"n2189046128":{"id":"n2189046128","loc":[-85.6422987,41.9427208]},"n2189046130":{"id":"n2189046130","loc":[-85.6424218,41.9427195]},"n2189046131":{"id":"n2189046131","loc":[-85.6424246,41.9428684]},"n2189046132":{"id":"n2189046132","loc":[-85.6423845,41.9428689]},"n2189046133":{"id":"n2189046133","loc":[-85.6423848,41.942885]},"n2189046134":{"id":"n2189046134","loc":[-85.641533,41.9429392]},"n2189046135":{"id":"n2189046135","loc":[-85.6416096,41.9428768]},"n2189046137":{"id":"n2189046137","loc":[-85.6416763,41.9429221]},"n2189046138":{"id":"n2189046138","loc":[-85.6415997,41.9429845]},"n2189046139":{"id":"n2189046139","loc":[-85.6420598,41.9428016]},"n2189046140":{"id":"n2189046140","loc":[-85.6420593,41.9427415]},"n2189046141":{"id":"n2189046141","loc":[-85.6421957,41.9427409]},"n2189046142":{"id":"n2189046142","loc":[-85.6421963,41.9428182]},"n2189046143":{"id":"n2189046143","loc":[-85.6421281,41.9428185]},"n2189046144":{"id":"n2189046144","loc":[-85.6421279,41.9428013]},"n2189046145":{"id":"n2189046145","loc":[-85.6409429,41.9429345]},"n2189046146":{"id":"n2189046146","loc":[-85.6410354,41.9429334]},"n2189046147":{"id":"n2189046147","loc":[-85.6410325,41.9427972]},"n2189046148":{"id":"n2189046148","loc":[-85.640997,41.9427976]},"n2189046149":{"id":"n2189046149","loc":[-85.6409963,41.9427643]},"n2189046150":{"id":"n2189046150","loc":[-85.6408605,41.9427659]},"n2189046152":{"id":"n2189046152","loc":[-85.6408623,41.9428482]},"n2189046153":{"id":"n2189046153","loc":[-85.640941,41.9428473]},"n2189152992":{"id":"n2189152992","loc":[-85.6437661,41.9422257]},"n2189152993":{"id":"n2189152993","loc":[-85.643768,41.9424067]},"n2189152994":{"id":"n2189152994","loc":[-85.6432176,41.9417705]},"n2189152995":{"id":"n2189152995","loc":[-85.6432097,41.941327]},"n2189152996":{"id":"n2189152996","loc":[-85.6436493,41.9413226]},"n2189152997":{"id":"n2189152997","loc":[-85.6436563,41.9417164]},"n2189152998":{"id":"n2189152998","loc":[-85.6435796,41.9417171]},"n2189152999":{"id":"n2189152999","loc":[-85.6435805,41.9417669]},"n2189153000":{"id":"n2189153000","loc":[-85.6438202,41.9414953]},"n2189153001":{"id":"n2189153001","loc":[-85.6438173,41.9413175]},"n2189153004":{"id":"n2189153004","loc":[-85.6432535,41.9418466]},"n2189153005":{"id":"n2189153005","loc":[-85.6433935,41.9418599]},"n2189153006":{"id":"n2189153006","loc":[-85.6434831,41.9418986]},"n2189153007":{"id":"n2189153007","loc":[-85.6435678,41.9419774]},"n2189153008":{"id":"n2189153008","loc":[-85.6435987,41.9420282]},"n2189153009":{"id":"n2189153009","loc":[-85.643438,41.9419573]},"n2189153010":{"id":"n2189153010","loc":[-85.6435284,41.9424676]},"n2189153011":{"id":"n2189153011","loc":[-85.6436207,41.9423631]},"n2189153012":{"id":"n2189153012","loc":[-85.6434957,41.9422973]},"n2189153013":{"id":"n2189153013","loc":[-85.6434457,41.9422458]},"n2189153014":{"id":"n2189153014","loc":[-85.6433976,41.9421772]},"n2189153015":{"id":"n2189153015","loc":[-85.6433861,41.9420785]},"n2189153016":{"id":"n2189153016","loc":[-85.6433765,41.9420313]},"n2189153017":{"id":"n2189153017","loc":[-85.6432207,41.9420284]},"n2189153018":{"id":"n2189153018","loc":[-85.6432245,41.9422759]},"n2189153019":{"id":"n2189153019","loc":[-85.6432649,41.9423474]},"n2189153020":{"id":"n2189153020","loc":[-85.6433226,41.9424132]},"n2189153021":{"id":"n2189153021","loc":[-85.6434111,41.9424704]},"n2189153022":{"id":"n2189153022","loc":[-85.6434591,41.9424347]},"n2189153025":{"id":"n2189153025","loc":[-85.6437669,41.9423073]},"n2189153026":{"id":"n2189153026","loc":[-85.6436611,41.942293]},"n2189153027":{"id":"n2189153027","loc":[-85.6435784,41.9422473]},"n2189153028":{"id":"n2189153028","loc":[-85.6435245,41.9421443]},"n2189153029":{"id":"n2189153029","loc":[-85.6435149,41.9420613]},"n2189153030":{"id":"n2189153030","loc":[-85.6433528,41.9419269]},"n2189153031":{"id":"n2189153031","loc":[-85.6432535,41.9419191]},"n2189153032":{"id":"n2189153032","loc":[-85.6430868,41.9419198]},"n2189153033":{"id":"n2189153033","loc":[-85.6434894,41.9420033]},"n2189153034":{"id":"n2189153034","loc":[-85.6432974,41.9419225]},"n2189153035":{"id":"n2189153035","loc":[-85.6433055,41.9421632]},"n2189153036":{"id":"n2189153036","loc":[-85.6433538,41.9422849]},"n2189153037":{"id":"n2189153037","loc":[-85.6434718,41.9423887]},"n2189153038":{"id":"n2189153038","loc":[-85.6436134,41.9422667]},"n2189153040":{"id":"n2189153040","loc":[-85.6438759,41.9414017]},"n2189153041":{"id":"n2189153041","loc":[-85.6438181,41.9413687]},"n2189153042":{"id":"n2189153042","loc":[-85.6436821,41.9413044]},"n2189153043":{"id":"n2189153043","loc":[-85.6435899,41.9412862]},"n2189153044":{"id":"n2189153044","loc":[-85.6433169,41.9417268]},"n2189153045":{"id":"n2189153045","loc":[-85.643301,41.9412859]},"n2189153046":{"id":"n2189153046","loc":[-85.6435531,41.9416981]},"n2189153047":{"id":"n2189153047","loc":[-85.6435427,41.9412863]},"n185948706":{"id":"n185948706","loc":[-85.6369439,41.940122]},"n185949348":{"id":"n185949348","loc":[-85.640039,41.931135]},"n185949870":{"id":"n185949870","loc":[-85.643195,41.949261]},"n185954680":{"id":"n185954680","loc":[-85.6337802,41.9401143]},"n185954784":{"id":"n185954784","loc":[-85.6487485,41.942527]},"n185958670":{"id":"n185958670","loc":[-85.637255,41.940104]},"n185958672":{"id":"n185958672","loc":[-85.636996,41.941355]},"n185960207":{"id":"n185960207","loc":[-85.634992,41.940118]},"n185963163":{"id":"n185963163","loc":[-85.638831,41.93398]},"n185963165":{"id":"n185963165","loc":[-85.640073,41.933968]},"n185963167":{"id":"n185963167","loc":[-85.641225,41.933972]},"n185963168":{"id":"n185963168","loc":[-85.642386,41.933952]},"n185964695":{"id":"n185964695","loc":[-85.6443608,41.9425645]},"n185964697":{"id":"n185964697","loc":[-85.644384,41.939941]},"n185964963":{"id":"n185964963","loc":[-85.6382347,41.9426146]},"n185964965":{"id":"n185964965","loc":[-85.637022,41.942622]},"n185964967":{"id":"n185964967","loc":[-85.6363706,41.9426606]},"n185964968":{"id":"n185964968","loc":[-85.6357988,41.9427748]},"n185964969":{"id":"n185964969","loc":[-85.6355409,41.9428465]},"n185964970":{"id":"n185964970","loc":[-85.6348729,41.9430443]},"n185966958":{"id":"n185966958","loc":[-85.641946,41.946413]},"n185966960":{"id":"n185966960","loc":[-85.643148,41.946389]},"n185967774":{"id":"n185967774","loc":[-85.641889,41.943852]},"n185967775":{"id":"n185967775","loc":[-85.641922,41.945121]},"n185967776":{"id":"n185967776","loc":[-85.641927,41.947544]},"n185967777":{"id":"n185967777","loc":[-85.641982,41.947622]},"n185969289":{"id":"n185969289","loc":[-85.63928,41.929221]},"n185969704":{"id":"n185969704","loc":[-85.6388186,41.9350099]},"n185969706":{"id":"n185969706","loc":[-85.6400709,41.9349957]},"n185969708":{"id":"n185969708","loc":[-85.6412214,41.9349827]},"n185969710":{"id":"n185969710","loc":[-85.6423509,41.934974]},"n185970602":{"id":"n185970602","loc":[-85.641293,41.931817]},"n185970604":{"id":"n185970604","loc":[-85.641258,41.932705]},"n185970605":{"id":"n185970605","loc":[-85.641148,41.936984]},"n185970606":{"id":"n185970606","loc":[-85.641112,41.938169]},"n185970906":{"id":"n185970906","loc":[-85.639454,41.943871]},"n185970908":{"id":"n185970908","loc":[-85.6394635,41.9450504]},"n185970909":{"id":"n185970909","loc":[-85.6394914,41.9451911]},"n185971368":{"id":"n185971368","loc":[-85.635769,41.940122]},"n185971978":{"id":"n185971978","loc":[-85.640003,41.936988]},"n185971980":{"id":"n185971980","loc":[-85.642299,41.936988]},"n185973633":{"id":"n185973633","loc":[-85.639023,41.92861]},"n185973635":{"id":"n185973635","loc":[-85.639153,41.928969]},"n185973637":{"id":"n185973637","loc":[-85.639213,41.929088]},"n185973639":{"id":"n185973639","loc":[-85.63935,41.929396]},"n185973641":{"id":"n185973641","loc":[-85.640143,41.931462]},"n185973644":{"id":"n185973644","loc":[-85.64019,41.931788]},"n185973646":{"id":"n185973646","loc":[-85.6401365,41.9327199]},"n185973648":{"id":"n185973648","loc":[-85.639983,41.938174]},"n185974477":{"id":"n185974477","loc":[-85.638206,41.941331]},"n185975928":{"id":"n185975928","loc":[-85.640683,41.94513]},"n185975930":{"id":"n185975930","loc":[-85.643102,41.945103]},"n185976255":{"id":"n185976255","loc":[-85.642424,41.931817]},"n185976257":{"id":"n185976257","loc":[-85.64242,41.932699]},"n185976258":{"id":"n185976258","loc":[-85.6422621,41.9381489]},"n185977452":{"id":"n185977452","loc":[-85.6457497,41.9398834]},"n185978772":{"id":"n185978772","loc":[-85.646656,41.939869]},"n185981472":{"id":"n185981472","loc":[-85.6388962,41.9321266]},"n185981474":{"id":"n185981474","loc":[-85.6388769,41.9327334]},"n185981476":{"id":"n185981476","loc":[-85.638829,41.934116]},"n185981478":{"id":"n185981478","loc":[-85.63876,41.937002]},"n185981480":{"id":"n185981480","loc":[-85.638682,41.93819]},"n185981999":{"id":"n185981999","loc":[-85.638194,41.9400866]},"n185982001":{"id":"n185982001","loc":[-85.646302,41.93988]},"n185982877":{"id":"n185982877","loc":[-85.640676,41.943867]},"n185982879":{"id":"n185982879","loc":[-85.640734,41.945887]},"n185985823":{"id":"n185985823","loc":[-85.643106,41.943841]},"n185985824":{"id":"n185985824","loc":[-85.643145,41.947641]},"n185985825":{"id":"n185985825","loc":[-85.643219,41.950829]},"n1475301385":{"id":"n1475301385","loc":[-85.6360612,41.9427042]},"n1475301397":{"id":"n1475301397","loc":[-85.6366651,41.9426328]},"n2139795811":{"id":"n2139795811","loc":[-85.6469154,41.9425427]},"n2139795830":{"id":"n2139795830","loc":[-85.6443194,41.9399444]},"n2139795834":{"id":"n2139795834","loc":[-85.6453506,41.9399002]},"n2139795837":{"id":"n2139795837","loc":[-85.645806,41.9398831]},"n2139858932":{"id":"n2139858932","loc":[-85.6351721,41.9429557]},"n2140019000":{"id":"n2140019000","loc":[-85.6359935,41.9427224]},"n2165942817":{"id":"n2165942817","loc":[-85.6442017,41.9414993]},"n2165942820":{"id":"n2165942820","loc":[-85.6442107,41.9421159]},"n2189152990":{"id":"n2189152990","loc":[-85.6442328,41.942404]},"n2189152991":{"id":"n2189152991","loc":[-85.6442309,41.9422229]},"n2189153002":{"id":"n2189153002","loc":[-85.6441329,41.9413147]},"n2189153003":{"id":"n2189153003","loc":[-85.6441357,41.9414925]},"n2189153023":{"id":"n2189153023","loc":[-85.6443453,41.9423074]},"n2189153024":{"id":"n2189153024","loc":[-85.6442318,41.9423045]},"n2189153039":{"id":"n2189153039","loc":[-85.6441343,41.9414025]},"w208643102":{"id":"w208643102","tags":{"highway":"service","service":"parking_aisle"},"nodes":["n2189153034","n2189153035","n2189153036","n2189153037","n2189153038"]},"w17966942":{"id":"w17966942","tags":{"highway":"residential","name":"Millard St"},"nodes":["n185954680","n185960207","n185971368","n185948706","n185958670","n185981999","n185981481","n185981482","n185973650","n185973659","n185970607","n185976259","n185976261","n2139795830","n185964697","n2139795834","n185977452","n2139795837","n185982001","n185978772"]},"w208643105":{"id":"w208643105","tags":{"highway":"service","service":"parking_aisle"},"nodes":["n2189153046","n2189153047"]},"w208631637":{"id":"w208631637","tags":{"area":"yes","building":"yes"},"nodes":["n2189046014","n2189046016","n2189046018","n2189046021","n2189046022","n2189046025","n2189046014"]},"w208643096":{"id":"w208643096","tags":{"amenity":"parking","area":"yes","fee":"no"},"nodes":["n2189152990","n2189153024","n2189152991","n2189152992","n2189153025","n2189152993","n2189152990"]},"w208631656":{"id":"w208631656","tags":{"area":"yes","building":"yes"},"nodes":["n2189046134","n2189046135","n2189046137","n2189046138","n2189046134"]},"w204003417":{"id":"w204003417","tags":{"area":"yes","building":"school"},"nodes":["n2140155811","n2140155814","n2140155816","n2140155818","n2140155821","n2140155823","n2140155825","n2140155827","n2140155811"]},"w208631654":{"id":"w208631654","tags":{"area":"yes","building":"yes"},"nodes":["n2189046127","n2189046128","n2189046130","n2189046131","n2189046132","n2189046133","n2189046127"]},"w17966327":{"id":"w17966327","tags":{"highway":"residential","name":"S Douglas Ave"},"nodes":["n185976261","n2140155839","n2140155834","n185974481","n2189153032","n185964959"]},"w41785752":{"id":"w41785752","tags":{"highway":"primary","name":"West Michigan Avenue","old_ref":"US 131","ref":"US 131 Business;M 60","access":"yes"},"nodes":["n185954784","n2139795811","n185964695","n185964959","n185964960","n185964961","n185964962","n185964963","n185964965","n1475301397","n185964967","n1475301385","n2140019000","n185964968","n185964969","n2139858932","n185964970"]},"w203841842":{"id":"w203841842","tags":{"area":"yes","leisure":"playground"},"nodes":["n2138493848","n2138493849","n2138493850","n2138493851","n2138493852","n2138493853","n2138493854","n2138493855","n2138493856","n2138493848"]},"w208643103":{"id":"w208643103","tags":{"highway":"service"},"nodes":["n2189153039","n2189153040","n2189153041","n2189153042","n2189153043","n2189153047","n2189153045","n185974481"]},"w208643098":{"id":"w208643098","tags":{"amenity":"parking","area":"yes"},"nodes":["n2189153000","n2189153041","n2189153001","n2189153002","n2189153039","n2189153003","n2189153000"]},"w208631646":{"id":"w208631646","tags":{"area":"yes","building":"yes"},"nodes":["n2189046067","n2189046069","n2189046070","n2189046072","n2189046067"]},"w208631653":{"id":"w208631653","tags":{"area":"yes","building":"yes"},"nodes":["n2189046119","n2189046120","n2189046121","n2189046122","n2189046123","n2189046124","n2189046125","n2189046126","n2189046119"]},"w17966041":{"id":"w17966041","tags":{"highway":"residential","name":"S Lincoln Ave"},"nodes":["n185973659","n185973660","n185964961"]},"w208631645":{"id":"w208631645","tags":{"area":"yes","building":"yes"},"nodes":["n2189046060","n2189046061","n2189046063","n2189046065","n2189046060"]},"w206803397":{"id":"w206803397","tags":{"area":"yes","building":"yes"},"nodes":["n2168510551","n2168510552","n2168510553","n2168510554","n2168510555","n2168510556","n2168510557","n2168510558","n2168510551"]},"w17965792":{"id":"w17965792","tags":{"highway":"residential","name":"N Hooker Ave"},"nodes":["n185964962","n185970906","n185970908","n185970909"]},"w208631651":{"id":"w208631651","tags":{"area":"yes","building":"yes"},"nodes":["n2189046112","n2189046113","n2189046115","n2189046116","n2189046117","n2189046118","n2189046112"]},"w208631643":{"id":"w208631643","tags":{"area":"yes","building":"yes"},"nodes":["n2189046053","n2189046054","n2189046055","n2189046056","n2189046058","n2189046059","n2189046053"]},"w17966878":{"id":"w17966878","tags":{"highway":"residential","name":"S Hooker Ave"},"nodes":["n185981472","n185981474","n185963163","n185981476","n185969704","n185981478","n185981480","n185981481"]},"w17966102":{"id":"w17966102","tags":{"highway":"residential","name":"South St"},"nodes":["n185958672","n185974477","n185974479","n185973660","n185970614"]},"w208631660":{"id":"w208631660","tags":{"area":"yes","building":"yes"},"nodes":["n2189046145","n2189046146","n2189046147","n2189046148","n2189046149","n2189046150","n2189046152","n2189046153","n2189046145"]},"w208643101":{"id":"w208643101","tags":{"highway":"service"},"nodes":["n2189153023","n2189153024","n2189153025","n2189153026","n2189153038","n2189153027","n2189153028","n2189153029","n2189153033","n2189153009","n2189153030","n2189153034","n2189153031","n2189153032"]},"w204000205":{"id":"w204000205","tags":{"highway":"residential","name":"South St","oneway":"yes"},"nodes":["n185974481","n2140155851","n185970614"]},"w203841841":{"id":"w203841841","tags":{"area":"yes","leisure":"pitch","pitch":"basketball"},"nodes":["n2138493844","n2138493845","n2138493846","n2138493847","n2138493844"]},"w17965444":{"id":"w17965444","tags":{"highway":"residential","name":"N Grant Ave"},"nodes":["n185964960","n185967774","n185967775","n185966958","n185967776","n185967777"]},"w208631648":{"id":"w208631648","tags":{"area":"yes","building":"yes"},"nodes":["n2189046074","n2189046075","n2189046077","n2189046079","n2189046082","n2189046083","n2189046085","n2189046087","n2189046089","n2189046090","n2189046092","n2189046094","n2189046096","n2189046097","n2189046099","n2189046103","n2189046074"]},"w208643100":{"id":"w208643100","tags":{"amenity":"parking","area":"yes"},"nodes":["n2189153010","n2189153011","n2189153012","n2189153013","n2189153014","n2189153015","n2189153016","n2189153017","n2189153018","n2189153019","n2189153020","n2189153021","n2189153022","n2189153010"]},"w17965749":{"id":"w17965749","tags":{"highway":"residential","name":"S Grant Ave"},"nodes":["n185970614","n185970616","n185964960"]},"w206574482":{"id":"w206574482","tags":{"amenity":"library","area":"yes","building":"yes","name":"Three Rivers Public Library"},"nodes":["n2165942817","n2165942818","n2165942819","n2165942820","n2165942817"]},"w208643097":{"id":"w208643097","tags":{"amenity":"parking","area":"yes"},"nodes":["n2189152994","n2189152995","n2189152996","n2189152997","n2189152998","n2189152999","n2189152994"]},"w17966879":{"id":"w17966879","tags":{"highway":"residential","name":"S Hooker Ave"},"nodes":["n185981482","n185974479","n185964962"]},"w17966325":{"id":"w17966325","tags":{"highway":"residential","name":"S Douglas Ave"},"nodes":["n185976255","n185976257","n185963168","n185969710","n185971980","n185976258","n185954700","n185976259"]},"w17967390":{"id":"w17967390","tags":{"highway":"residential","name":"N Douglas Ave"},"nodes":["n185964959","n185985823","n185975930","n185966960","n185985824","n185949870","n185985825"]},"w208631635":{"id":"w208631635","tags":{"area":"yes","building":"yes"},"nodes":["n2189046007","n2189046009","n2189046011","n2189046012","n2189046007"]},"w208643099":{"id":"w208643099","tags":{"amenity":"parking","area":"yes"},"nodes":["n2189153031","n2189153004","n2189153005","n2189153006","n2189153007","n2189153008","n2189153029","n2189153033","n2189153009","n2189153030","n2189153031"]},"w208631658":{"id":"w208631658","tags":{"area":"yes","building":"yes"},"nodes":["n2189046139","n2189046140","n2189046141","n2189046142","n2189046143","n2189046144","n2189046139"]},"w208643104":{"id":"w208643104","tags":{"highway":"service","service":"parking_aisle"},"nodes":["n2189153044","n2189153045"]},"w17966039":{"id":"w17966039","tags":{"highway":"residential","name":"S Lincoln Ave"},"nodes":["n185973633","n185973635","n185973637","n185969289","n185973639","n185949348","n185973641","n185973644","n185973646","n185963165","n185969706","n185971978","n185973648","n185973650"]},"w204003420":{"id":"w204003420","tags":{"amenity":"parking","area":"yes"},"nodes":["n2140155840","n2140155842","n2140155844","n2140155845","n2140155847","n2140155849","n2140155854","n2140155840"]},"w204003419":{"id":"w204003419","tags":{"highway":"service"},"nodes":["n2140155834","n2140155835","n2140155837","n2140155839"]},"w204003418":{"id":"w204003418","tags":{"amenity":"school","area":"yes","name":"Andrews Elementary School"},"nodes":["n2140155828","n2140155829","n2140155830","n2140155831","n2140155832","n2140155833","n2140155828"]},"w17965747":{"id":"w17965747","tags":{"highway":"residential","name":"S Grant Ave"},"nodes":["n185970602","n185970604","n185963167","n185969708","n185970605","n185970606","n185970607"]},"w17967073":{"id":"w17967073","tags":{"highway":"residential","name":"N Lincoln Ave"},"nodes":["n185964961","n185982877","n185975928","n185982879"]},"w204003421":{"id":"w204003421","tags":{"highway":"service","service":"parking_aisle"},"nodes":["n2140155851","n2140155852","n2140155854","n2140155856"]},"r1943857":{"id":"r1943857","tags":{"modifier":"Business","name":"US 131 Business (Three Rivers, MI)","network":"US:US","ref":"131","route":"road","type":"route"},"members":[{"id":"w17966509","type":"way","role":"forward"},{"id":"w143497377","type":"way","role":""},{"id":"w134150811","type":"way","role":""},{"id":"w134150800","type":"way","role":""},{"id":"w134150789","type":"way","role":""},{"id":"w134150795","type":"way","role":""},{"id":"w41785752","type":"way","role":""},{"id":"w17965146","type":"way","role":"forward"},{"id":"w17964031","type":"way","role":"forward"}]},"r270277":{"id":"r270277","tags":{"network":"US:MI","ref":"60","route":"road","state_id":"MI","type":"route","url":"http://en.wikipedia.org/wiki/M-60_%28Michigan_highway%29"},"members":[{"id":"w17751087","type":"way","role":"east"},{"id":"w117148312","type":"way","role":"east"},{"id":"w40942155","type":"way","role":"west"},{"id":"w17751017","type":"way","role":""},{"id":"w17751083","type":"way","role":""},{"id":"w17747780","type":"way","role":""},{"id":"w41068082","type":"way","role":""},{"id":"w197025212","type":"way","role":""},{"id":"w17743874","type":"way","role":""},{"id":"w17751044","type":"way","role":""},{"id":"w17752167","type":"way","role":""},{"id":"w17751089","type":"way","role":""},{"id":"w17743879","type":"way","role":""},{"id":"w17751064","type":"way","role":""},{"id":"w197057073","type":"way","role":""},{"id":"w167699963","type":"way","role":""},{"id":"w167699972","type":"way","role":""},{"id":"w17967584","type":"way","role":""},{"id":"w167699964","type":"way","role":""},{"id":"w17967582","type":"way","role":"west"},{"id":"w41260270","type":"way","role":"west"},{"id":"w17965146","type":"way","role":"west"},{"id":"w41785752","type":"way","role":""},{"id":"w134150795","type":"way","role":""},{"id":"w134150789","type":"way","role":""},{"id":"w134150800","type":"way","role":""},{"id":"w134150811","type":"way","role":""},{"id":"w134150836","type":"way","role":""},{"id":"w134150802","type":"way","role":""},{"id":"w41074896","type":"way","role":""},{"id":"w17966773","type":"way","role":""},{"id":"w17967415","type":"way","role":""},{"id":"w41074899","type":"way","role":""},{"id":"w17967581","type":"way","role":""},{"id":"w41074902","type":"way","role":""},{"id":"w41074906","type":"way","role":""},{"id":"w209707997","type":"way","role":""},{"id":"w209707998","type":"way","role":""},{"id":"w17964798","type":"way","role":""},{"id":"w17966034","type":"way","role":""},{"id":"w17967593","type":"way","role":""},{"id":"w41074888","type":"way","role":""},{"id":"w17733772","type":"way","role":""},{"id":"w41074813","type":"way","role":""},{"id":"w17742213","type":"way","role":""},{"id":"w17746863","type":"way","role":""},{"id":"w17745772","type":"way","role":""},{"id":"w17742222","type":"way","role":""},{"id":"w17745922","type":"way","role":""},{"id":"w17742198","type":"way","role":""},{"id":"w17747675","type":"way","role":""},{"id":"w17739927","type":"way","role":""},{"id":"w17745708","type":"way","role":""},{"id":"w41006323","type":"way","role":""},{"id":"w17744233","type":"way","role":""},{"id":"w17739436","type":"way","role":""},{"id":"w17742201","type":"way","role":""},{"id":"w151418616","type":"way","role":""},{"id":"w17750062","type":"way","role":""},{"id":"w17742227","type":"way","role":"east"},{"id":"w41006348","type":"way","role":"east"},{"id":"w41260984","type":"way","role":""},{"id":"w17832427","type":"way","role":""},{"id":"w17838408","type":"way","role":""},{"id":"w17835846","type":"way","role":""},{"id":"w17832923","type":"way","role":""},{"id":"w17839388","type":"way","role":""},{"id":"w17838390","type":"way","role":""},{"id":"w17831272","type":"way","role":""},{"id":"w17828581","type":"way","role":""},{"id":"w38240686","type":"way","role":""},{"id":"w17838405","type":"way","role":"east"},{"id":"w123323711","type":"way","role":"east"},{"id":"w17830167","type":"way","role":"east"},{"id":"w99011909","type":"way","role":"east"},{"id":"w41911361","type":"way","role":"east"},{"id":"w41911355","type":"way","role":"east"},{"id":"w41911356","type":"way","role":"east"},{"id":"w117148326","type":"way","role":"west"},{"id":"w41911352","type":"way","role":"west"},{"id":"w41911353","type":"way","role":"west"},{"id":"w41911354","type":"way","role":"west"},{"id":"w41911360","type":"way","role":"west"},{"id":"w38240676","type":"way","role":"west"},{"id":"w123323710","type":"way","role":"west"},{"id":"w41260271","type":"way","role":"east"},{"id":"w41260273","type":"way","role":"east"},{"id":"w17964031","type":"way","role":"east"},{"id":"w41006344","type":"way","role":"west"},{"id":"w41006351","type":"way","role":"west"}]},"n367813436":{"id":"n367813436","loc":[-85.63605205663384,41.94305506683346],"tags":{"amenity":"fire_station","name":"Three Rivers Fire Department"}},"n185948708":{"id":"n185948708","loc":[-85.6369828,41.9408789]},"n185948710":{"id":"n185948710","loc":[-85.6370184,41.9411346]},"n185954691":{"id":"n185954691","loc":[-85.634476,41.941475]},"n185954692":{"id":"n185954692","loc":[-85.635008,41.941846]},"n185954693":{"id":"n185954693","loc":[-85.635362,41.941962]},"n185954695":{"id":"n185954695","loc":[-85.63578,41.941978]},"n185972903":{"id":"n185972903","loc":[-85.63295,41.9430062]},"n185964971":{"id":"n185964971","loc":[-85.6346811,41.9431023]},"n1819805854":{"id":"n1819805854","loc":[-85.6331275,41.9404837]},"n1819805918":{"id":"n1819805918","loc":[-85.6331168,41.942798]},"n1819805762":{"id":"n1819805762","loc":[-85.6333034,41.9424123]},"n1819805907":{"id":"n1819805907","loc":[-85.6334819,41.9419121]},"n1819805915":{"id":"n1819805915","loc":[-85.6334554,41.9413588]},"n1819848888":{"id":"n1819848888","loc":[-85.6331625,41.942679]},"n1819848930":{"id":"n1819848930","loc":[-85.6338684,41.9431252]},"n1819858505":{"id":"n1819858505","loc":[-85.6346782,41.9429092]},"n1819858507":{"id":"n1819858507","loc":[-85.6339003,41.9414534]},"n1819858508":{"id":"n1819858508","loc":[-85.6345709,41.9427742]},"n1819858509":{"id":"n1819858509","loc":[-85.63419,41.9417322]},"n1819858511":{"id":"n1819858511","loc":[-85.6340666,41.9415652]},"n1819858512":{"id":"n1819858512","loc":[-85.6343295,41.9423027]},"n1819858514":{"id":"n1819858514","loc":[-85.6343241,41.942207]},"n1819858521":{"id":"n1819858521","loc":[-85.633391,41.941231]},"n1819858528":{"id":"n1819858528","loc":[-85.6343027,41.9419716]},"n185954683":{"id":"n185954683","loc":[-85.6335412,41.940147]},"n185954685":{"id":"n185954685","loc":[-85.6334296,41.9403023]},"n185954687":{"id":"n185954687","loc":[-85.6333988,41.9404704]},"n185954689":{"id":"n185954689","loc":[-85.6335511,41.9410225]},"n185954690":{"id":"n185954690","loc":[-85.6336721,41.9411669]},"n1820938802":{"id":"n1820938802","loc":[-85.6330671,41.941845]},"n1821006702":{"id":"n1821006702","loc":[-85.6344047,41.9395496]},"n2130304133":{"id":"n2130304133","loc":[-85.6349025,41.9427659]},"n2130304136":{"id":"n2130304136","loc":[-85.6346027,41.9422017]},"n2130304138":{"id":"n2130304138","loc":[-85.6348577,41.9421517]},"n2130304140":{"id":"n2130304140","loc":[-85.6348419,41.9422694]},"n2130304142":{"id":"n2130304142","loc":[-85.6349071,41.9423135]},"n2130304144":{"id":"n2130304144","loc":[-85.6350495,41.9423312]},"n2130304146":{"id":"n2130304146","loc":[-85.6351009,41.9422812]},"n2130304147":{"id":"n2130304147","loc":[-85.6351227,41.9421532]},"n2130304148":{"id":"n2130304148","loc":[-85.635526,41.9421547]},"n2130304149":{"id":"n2130304149","loc":[-85.6355339,41.9425768]},"n2130304150":{"id":"n2130304150","loc":[-85.6351582,41.9426562]},"n2130304151":{"id":"n2130304151","loc":[-85.6351207,41.9427032]},"n2138493807":{"id":"n2138493807","loc":[-85.6350923,41.9415216]},"n2138493808":{"id":"n2138493808","loc":[-85.6353603,41.9411061]},"n2138493809":{"id":"n2138493809","loc":[-85.6354421,41.9410942]},"n2138493810":{"id":"n2138493810","loc":[-85.6355079,41.9411044]},"n2138493811":{"id":"n2138493811","loc":[-85.6355693,41.9411246]},"n2138493812":{"id":"n2138493812","loc":[-85.6355829,41.9411061]},"n2138493813":{"id":"n2138493813","loc":[-85.6355624,41.9409777]},"n2138493814":{"id":"n2138493814","loc":[-85.6355011,41.9409152]},"n2138493815":{"id":"n2138493815","loc":[-85.635383,41.9409219]},"n2138493816":{"id":"n2138493816","loc":[-85.635299,41.9409658]},"n2138493817":{"id":"n2138493817","loc":[-85.6351695,41.941204]},"n2138493818":{"id":"n2138493818","loc":[-85.6348879,41.9415166]},"n2138493819":{"id":"n2138493819","loc":[-85.634897,41.9415757]},"n2138493820":{"id":"n2138493820","loc":[-85.6349606,41.9416399]},"n2138493821":{"id":"n2138493821","loc":[-85.6350219,41.9416669]},"n2138493822":{"id":"n2138493822","loc":[-85.6351241,41.9416314]},"n2138493823":{"id":"n2138493823","loc":[-85.6350855,41.9415622]},"n2138493824":{"id":"n2138493824","loc":[-85.6350401,41.9413603]},"n2138493825":{"id":"n2138493825","loc":[-85.6352206,41.9410765]},"n2138493826":{"id":"n2138493826","loc":[-85.6343865,41.9415594]},"n2138493827":{"id":"n2138493827","loc":[-85.6343506,41.9415873]},"n2138493828":{"id":"n2138493828","loc":[-85.6344158,41.9417557]},"n2138493829":{"id":"n2138493829","loc":[-85.6344614,41.9417968]},"n2138493830":{"id":"n2138493830","loc":[-85.6345005,41.9418186]},"n2138493831":{"id":"n2138493831","loc":[-85.6345965,41.9418162]},"n2138493832":{"id":"n2138493832","loc":[-85.6347317,41.9417242]},"n2138493833":{"id":"n2138493833","loc":[-85.6346722,41.941775]},"n2139858909":{"id":"n2139858909","loc":[-85.633403,41.9391006]},"n2139858910":{"id":"n2139858910","loc":[-85.6332973,41.9393967]},"n2139858911":{"id":"n2139858911","loc":[-85.633205,41.9396742]},"n2139858912":{"id":"n2139858912","loc":[-85.6332203,41.9397772]},"n2139858913":{"id":"n2139858913","loc":[-85.6333453,41.939936]},"n2139858914":{"id":"n2139858914","loc":[-85.6333761,41.9400018]},"n2139858915":{"id":"n2139858915","loc":[-85.63328,41.9402249]},"n2139858916":{"id":"n2139858916","loc":[-85.6332357,41.9403523]},"n2139858917":{"id":"n2139858917","loc":[-85.6332838,41.9405831]},"n2139858918":{"id":"n2139858918","loc":[-85.6333643,41.9408744]},"n2139858919":{"id":"n2139858919","loc":[-85.6334394,41.9410519]},"n2139858920":{"id":"n2139858920","loc":[-85.6335815,41.9411717]},"n2139858921":{"id":"n2139858921","loc":[-85.6337478,41.9412734]},"n2139858922":{"id":"n2139858922","loc":[-85.6343174,41.9415268]},"n2139858923":{"id":"n2139858923","loc":[-85.6343886,41.9417397]},"n2139858924":{"id":"n2139858924","loc":[-85.6344407,41.9418015]},"n2139858925":{"id":"n2139858925","loc":[-85.6345139,41.9418366]},"n2139858926":{"id":"n2139858926","loc":[-85.6344846,41.942005]},"n2139858927":{"id":"n2139858927","loc":[-85.6345775,41.9422218]},"n2139858928":{"id":"n2139858928","loc":[-85.6348771,41.9427814]},"n2139858929":{"id":"n2139858929","loc":[-85.6349487,41.9427995]},"n2139858930":{"id":"n2139858930","loc":[-85.6350415,41.9427874]},"n2139858931":{"id":"n2139858931","loc":[-85.6351246,41.9428589]},"n2139858978":{"id":"n2139858978","loc":[-85.6349658,41.9431481]},"n2139858979":{"id":"n2139858979","loc":[-85.6350081,41.9431287]},"n2139858980":{"id":"n2139858980","loc":[-85.6349967,41.9430997]},"n2139858981":{"id":"n2139858981","loc":[-85.6352158,41.9430352]},"n2139858982":{"id":"n2139858982","loc":[-85.6348174,41.94267]},"n2139858983":{"id":"n2139858983","loc":[-85.6346142,41.9425989]},"n2139858984":{"id":"n2139858984","loc":[-85.6344938,41.9423809]},"n2139858985":{"id":"n2139858985","loc":[-85.6344856,41.9422997]},"n2139870380":{"id":"n2139870380","loc":[-85.6346707,41.9417955]},"n2139870381":{"id":"n2139870381","loc":[-85.6345949,41.9418311]},"n2139870382":{"id":"n2139870382","loc":[-85.6343322,41.9418659]},"n2139870383":{"id":"n2139870383","loc":[-85.6342072,41.941885]},"n2139870384":{"id":"n2139870384","loc":[-85.6341325,41.9418919]},"n2139870385":{"id":"n2139870385","loc":[-85.6341314,41.9422028]},"n2139870386":{"id":"n2139870386","loc":[-85.6340472,41.9423271]},"n2139870387":{"id":"n2139870387","loc":[-85.6342185,41.9427933]},"n2139870388":{"id":"n2139870388","loc":[-85.6340605,41.9423924]},"n2139870389":{"id":"n2139870389","loc":[-85.6339889,41.9424069]},"n2139870390":{"id":"n2139870390","loc":[-85.633971,41.942356]},"n2139870391":{"id":"n2139870391","loc":[-85.63361,41.9424235]},"n2139870392":{"id":"n2139870392","loc":[-85.6337137,41.9426819]},"n2139870393":{"id":"n2139870393","loc":[-85.6336977,41.9428632]},"n2139870394":{"id":"n2139870394","loc":[-85.6338823,41.9428647]},"n2139870395":{"id":"n2139870395","loc":[-85.6339412,41.9430069]},"n2139870396":{"id":"n2139870396","loc":[-85.6338873,41.9430353]},"n2139870397":{"id":"n2139870397","loc":[-85.6337676,41.942815]},"n2139870398":{"id":"n2139870398","loc":[-85.6336822,41.9423505]},"n2139870399":{"id":"n2139870399","loc":[-85.634037,41.9422725]},"n2139870400":{"id":"n2139870400","loc":[-85.6340294,41.9422518]},"n2139870401":{"id":"n2139870401","loc":[-85.6336726,41.9423312]},"n2139870402":{"id":"n2139870402","loc":[-85.6342188,41.9425715]},"n2139870403":{"id":"n2139870403","loc":[-85.6342524,41.942565]},"n2139870404":{"id":"n2139870404","loc":[-85.6341438,41.942299]},"n2139870405":{"id":"n2139870405","loc":[-85.6341149,41.9423061]},"n2139870407":{"id":"n2139870407","loc":[-85.6340846,41.9431458]},"n2139870408":{"id":"n2139870408","loc":[-85.6339436,41.9429032]},"n2139870409":{"id":"n2139870409","loc":[-85.6343143,41.9428207]},"n2139870410":{"id":"n2139870410","loc":[-85.6343507,41.94277]},"n2139870411":{"id":"n2139870411","loc":[-85.6341527,41.942254]},"n2139870412":{"id":"n2139870412","loc":[-85.6340925,41.9422199]},"n2139870413":{"id":"n2139870413","loc":[-85.6335435,41.9423433]},"n2139870414":{"id":"n2139870414","loc":[-85.6335023,41.9423975]},"n2139870415":{"id":"n2139870415","loc":[-85.6335086,41.9424552]},"n2139870416":{"id":"n2139870416","loc":[-85.6336296,41.942665]},"n2139870417":{"id":"n2139870417","loc":[-85.6341396,41.9428596]},"n2139870418":{"id":"n2139870418","loc":[-85.6339701,41.9424487]},"n2139870419":{"id":"n2139870419","loc":[-85.6335514,41.9425294]},"n2139870420":{"id":"n2139870420","loc":[-85.6337406,41.9424929]},"n2139870421":{"id":"n2139870421","loc":[-85.6338939,41.9428687]},"n2139870422":{"id":"n2139870422","loc":[-85.6341323,41.9419538]},"n2139870423":{"id":"n2139870423","loc":[-85.6340321,41.9420376]},"n2139870424":{"id":"n2139870424","loc":[-85.6337648,41.942238]},"n2139870425":{"id":"n2139870425","loc":[-85.6337604,41.9422685]},"n2139870426":{"id":"n2139870426","loc":[-85.6337682,41.9422928]},"n2139870427":{"id":"n2139870427","loc":[-85.6338086,41.9423862]},"n2139870428":{"id":"n2139870428","loc":[-85.6349465,41.9416631]},"n2139870429":{"id":"n2139870429","loc":[-85.6351097,41.9416973]},"n2139870430":{"id":"n2139870430","loc":[-85.6353371,41.9416798]},"n2139870431":{"id":"n2139870431","loc":[-85.6349627,41.9422506]},"n2139870432":{"id":"n2139870432","loc":[-85.634979,41.9421815]},"n2139870433":{"id":"n2139870433","loc":[-85.634885,41.9421679]},"n2139870434":{"id":"n2139870434","loc":[-85.6348689,41.9422377]},"n2139870435":{"id":"n2139870435","loc":[-85.6349779,41.9419486]},"n2139870436":{"id":"n2139870436","loc":[-85.6349505,41.9418933]},"n2139870437":{"id":"n2139870437","loc":[-85.6347327,41.9419505]},"n2139870438":{"id":"n2139870438","loc":[-85.6347614,41.9420087]},"n2139870439":{"id":"n2139870439","loc":[-85.6351889,41.9416912]},"n2139870440":{"id":"n2139870440","loc":[-85.6351092,41.9418426]},"n2139870441":{"id":"n2139870441","loc":[-85.635086,41.9419659]},"n2139870442":{"id":"n2139870442","loc":[-85.6350584,41.9421466]},"n2139870443":{"id":"n2139870443","loc":[-85.6350993,41.9421606]},"n2139870444":{"id":"n2139870444","loc":[-85.6350993,41.9422132]},"n2139870445":{"id":"n2139870445","loc":[-85.6350794,41.9422855]},"n2139870446":{"id":"n2139870446","loc":[-85.6350474,41.9423159]},"n2139870447":{"id":"n2139870447","loc":[-85.6349251,41.9422998]},"n2139870448":{"id":"n2139870448","loc":[-85.634911,41.9422755]},"n2139870449":{"id":"n2139870449","loc":[-85.6349157,41.9422553]},"n2139870450":{"id":"n2139870450","loc":[-85.6347213,41.9419324]},"n2139870451":{"id":"n2139870451","loc":[-85.6349535,41.9418771]},"n2139870452":{"id":"n2139870452","loc":[-85.6350135,41.9419421]},"n2139870453":{"id":"n2139870453","loc":[-85.6348584,41.9418997]},"n2139870454":{"id":"n2139870454","loc":[-85.6348113,41.9418101]},"n2139870455":{"id":"n2139870455","loc":[-85.6347306,41.9417449]},"n2139870456":{"id":"n2139870456","loc":[-85.6349123,41.941776]},"n2139870457":{"id":"n2139870457","loc":[-85.6349423,41.9421448]},"n2139870458":{"id":"n2139870458","loc":[-85.6349436,41.9420652]},"n2139870459":{"id":"n2139870459","loc":[-85.6349136,41.9419963]},"n2139870460":{"id":"n2139870460","loc":[-85.6349814,41.9419789]},"n2139989328":{"id":"n2139989328","loc":[-85.6334188,41.9421725]},"n2139989330":{"id":"n2139989330","loc":[-85.6335087,41.9416308]},"n2139989335":{"id":"n2139989335","loc":[-85.6336856,41.9429371]},"n2139989337":{"id":"n2139989337","loc":[-85.6333713,41.9427217]},"n2139989339":{"id":"n2139989339","loc":[-85.6332912,41.9425383]},"n2139989341":{"id":"n2139989341","loc":[-85.6339369,41.9409198]},"n2139989344":{"id":"n2139989344","loc":[-85.634097,41.9409469]},"n2139989346":{"id":"n2139989346","loc":[-85.634137,41.9412852]},"n2139989348":{"id":"n2139989348","loc":[-85.6344536,41.9414151]},"n2139989350":{"id":"n2139989350","loc":[-85.6350794,41.9412392]},"n2139989351":{"id":"n2139989351","loc":[-85.6352541,41.9409387]},"n2139989353":{"id":"n2139989353","loc":[-85.6357198,41.9408007]},"n2139989355":{"id":"n2139989355","loc":[-85.6357235,41.9427088]},"n2139989357":{"id":"n2139989357","loc":[-85.6337119,41.9421256]},"n2139989359":{"id":"n2139989359","loc":[-85.6336913,41.9420655]},"n2139989360":{"id":"n2139989360","loc":[-85.633582,41.9420867]},"n2139989362":{"id":"n2139989362","loc":[-85.6336058,41.9421491]},"n2139989364":{"id":"n2139989364","loc":[-85.6339685,41.9410995]},"n2139989366":{"id":"n2139989366","loc":[-85.6339067,41.9411383]},"n2139989368":{"id":"n2139989368","loc":[-85.6339685,41.9411972]},"n2139989370":{"id":"n2139989370","loc":[-85.6340398,41.9411619]},"n2139870379":{"id":"n2139870379","loc":[-85.6348391,41.9416651]},"n2140006363":{"id":"n2140006363","loc":[-85.6353144,41.9430345]},"n2140006364":{"id":"n2140006364","loc":[-85.6349191,41.9431422]},"n2140018997":{"id":"n2140018997","loc":[-85.63645945147184,41.942986488012565],"tags":{"amenity":"townhall","name":"Three Rivers City Hall"}},"n2140018998":{"id":"n2140018998","loc":[-85.6370319,41.9427919]},"n2140018999":{"id":"n2140018999","loc":[-85.6360687,41.9427808]},"n2199856288":{"id":"n2199856288","loc":[-85.6344968,41.9407307]},"n2199856289":{"id":"n2199856289","loc":[-85.634492,41.9406036]},"n2199856290":{"id":"n2199856290","loc":[-85.634891,41.9406001]},"n2199856291":{"id":"n2199856291","loc":[-85.6348894,41.9405288]},"n2199856292":{"id":"n2199856292","loc":[-85.6349166,41.94053]},"n2199856293":{"id":"n2199856293","loc":[-85.6349166,41.9404956]},"n2199856294":{"id":"n2199856294","loc":[-85.6350219,41.9404956]},"n2199856295":{"id":"n2199856295","loc":[-85.6350251,41.94053]},"n2199856296":{"id":"n2199856296","loc":[-85.6350538,41.9405288]},"n2199856297":{"id":"n2199856297","loc":[-85.6350602,41.94079]},"n2199856298":{"id":"n2199856298","loc":[-85.6351703,41.9407912]},"n2199856299":{"id":"n2199856299","loc":[-85.6351688,41.9409171]},"n2199856300":{"id":"n2199856300","loc":[-85.6347889,41.9409135]},"n2199856301":{"id":"n2199856301","loc":[-85.6347921,41.94079]},"n2199856302":{"id":"n2199856302","loc":[-85.6348942,41.9407888]},"n2199856303":{"id":"n2199856303","loc":[-85.6348926,41.9407283]},"n185951869":{"id":"n185951869","loc":[-85.6387639,41.957288]},"n185958643":{"id":"n185958643","loc":[-85.636746,41.929221]},"n185958645":{"id":"n185958645","loc":[-85.636791,41.929363]},"n185958647":{"id":"n185958647","loc":[-85.6375975,41.9314987]},"n185958649":{"id":"n185958649","loc":[-85.637669,41.931667]},"n185958651":{"id":"n185958651","loc":[-85.637728,41.931901]},"n185958653":{"id":"n185958653","loc":[-85.637724,41.932187]},"n185958656":{"id":"n185958656","loc":[-85.637732,41.932761]},"n185958658":{"id":"n185958658","loc":[-85.637688,41.93398]},"n185958660":{"id":"n185958660","loc":[-85.637685,41.934223]},"n185958662":{"id":"n185958662","loc":[-85.6376468,41.9350232]},"n185958664":{"id":"n185958664","loc":[-85.637564,41.937028]},"n185958666":{"id":"n185958666","loc":[-85.637458,41.938197]},"n185958668":{"id":"n185958668","loc":[-85.637424,41.938692]},"n185964972":{"id":"n185964972","loc":[-85.6341901,41.9432732]},"n185971361":{"id":"n185971361","loc":[-85.635762,41.938208]},"n185971364":{"id":"n185971364","loc":[-85.635732,41.9384]},"n185971366":{"id":"n185971366","loc":[-85.635736,41.938697]},"n185972775":{"id":"n185972775","loc":[-85.635638,42.070357]},"n185972777":{"id":"n185972777","loc":[-85.635724,42.069929]},"n185972779":{"id":"n185972779","loc":[-85.635804,42.069248]},"n185972781":{"id":"n185972781","loc":[-85.635869,42.068361]},"n185972783":{"id":"n185972783","loc":[-85.635883,42.067582]},"n185972785":{"id":"n185972785","loc":[-85.635875,42.067114]},"n185972787":{"id":"n185972787","loc":[-85.635778,42.065359]},"n185972788":{"id":"n185972788","loc":[-85.635728,42.063416]},"n185972789":{"id":"n185972789","loc":[-85.635665,42.062491]},"n185972790":{"id":"n185972790","loc":[-85.635617,42.061928]},"n185972791":{"id":"n185972791","loc":[-85.635614,42.061898]},"n185972793":{"id":"n185972793","loc":[-85.635379,42.060288]},"n185972795":{"id":"n185972795","loc":[-85.635092,42.05799]},"n185972797":{"id":"n185972797","loc":[-85.634843,42.055781]},"n185972798":{"id":"n185972798","loc":[-85.634817,42.055549]},"n185972800":{"id":"n185972800","loc":[-85.634708,42.053942]},"n185972802":{"id":"n185972802","loc":[-85.634447,42.051809]},"n185972805":{"id":"n185972805","loc":[-85.634241,42.04946]},"n185972807":{"id":"n185972807","loc":[-85.633787,42.045926]},"n185972809":{"id":"n185972809","loc":[-85.633811,42.045645]},"n185972811":{"id":"n185972811","loc":[-85.63373,42.043626]},"n185972813":{"id":"n185972813","loc":[-85.633698,42.042184]},"n185972814":{"id":"n185972814","loc":[-85.63369,42.04181]},"n185972815":{"id":"n185972815","loc":[-85.633681,42.040714]},"n185972816":{"id":"n185972816","loc":[-85.633571,42.036322]},"n185972817":{"id":"n185972817","loc":[-85.633537,42.034044]},"n185972819":{"id":"n185972819","loc":[-85.633481,42.030785]},"n185972821":{"id":"n185972821","loc":[-85.633452,42.027538]},"n185972824":{"id":"n185972824","loc":[-85.633438,42.027427]},"n185972826":{"id":"n185972826","loc":[-85.633342,42.022656]},"n185972830":{"id":"n185972830","loc":[-85.63327,42.020724]},"n185972832":{"id":"n185972832","loc":[-85.633198,42.019106]},"n185972834":{"id":"n185972834","loc":[-85.633249,42.018363]},"n185972835":{"id":"n185972835","loc":[-85.633139,42.012944]},"n185972836":{"id":"n185972836","loc":[-85.63309,42.008284]},"n185972839":{"id":"n185972839","loc":[-85.63298,42.00005]},"n185972845":{"id":"n185972845","loc":[-85.6325369,41.9764959]},"n185972847":{"id":"n185972847","loc":[-85.6327549,41.9750005]},"n185972849":{"id":"n185972849","loc":[-85.6329374,41.9742527]},"n185972851":{"id":"n185972851","loc":[-85.6331387,41.9736039]},"n185972862":{"id":"n185972862","loc":[-85.6383589,41.9585023]},"n185972868":{"id":"n185972868","loc":[-85.6393633,41.9551716]},"n185972878":{"id":"n185972878","loc":[-85.639377,41.95335]},"n185972882":{"id":"n185972882","loc":[-85.6389179,41.9516944]},"n185972885":{"id":"n185972885","loc":[-85.6387444,41.9512105]},"n185972891":{"id":"n185972891","loc":[-85.636421,41.946392]},"n185972895":{"id":"n185972895","loc":[-85.635965,41.945809]},"n185972897":{"id":"n185972897","loc":[-85.635683,41.945449]},"n185972899":{"id":"n185972899","loc":[-85.635281,41.9450252]},"n185972905":{"id":"n185972905","loc":[-85.6324428,41.9425743]},"n185985217":{"id":"n185985217","loc":[-85.638243,41.943674]},"n185985219":{"id":"n185985219","loc":[-85.638228,41.943747]},"n185985221":{"id":"n185985221","loc":[-85.638163,41.943797]},"n185985222":{"id":"n185985222","loc":[-85.638089,41.943832]},"n185985223":{"id":"n185985223","loc":[-85.637969,41.943841]},"n185985225":{"id":"n185985225","loc":[-85.637841,41.943833]},"n185985227":{"id":"n185985227","loc":[-85.637601,41.943789]},"n185985229":{"id":"n185985229","loc":[-85.637449,41.943754]},"n185985231":{"id":"n185985231","loc":[-85.637342,41.943734]},"n185985233":{"id":"n185985233","loc":[-85.637218,41.943703]},"n185985235":{"id":"n185985235","loc":[-85.637151,41.943663]},"n185985238":{"id":"n185985238","loc":[-85.637118,41.943615]},"n185985240":{"id":"n185985240","loc":[-85.637073,41.943494]},"n185990434":{"id":"n185990434","loc":[-85.6329028,41.9984292],"tags":{"railway":"level_crossing"}},"n1475284023":{"id":"n1475284023","loc":[-85.6336163,41.9435806],"tags":{"railway":"level_crossing"}},"n1475293222":{"id":"n1475293222","loc":[-85.6394045,41.953658],"tags":{"railway":"level_crossing"}},"n1475293226":{"id":"n1475293226","loc":[-85.6364975,41.9638663],"tags":{"railway":"level_crossing"}},"n1475293234":{"id":"n1475293234","loc":[-85.6390449,41.9565145]},"n1475293240":{"id":"n1475293240","loc":[-85.636943,41.9473114]},"n1475293252":{"id":"n1475293252","loc":[-85.6392115,41.9559003]},"n1475293254":{"id":"n1475293254","loc":[-85.6348931,41.9685127],"tags":{"railway":"level_crossing"}},"n1475293260":{"id":"n1475293260","loc":[-85.6375999,41.9485401]},"n1475293261":{"id":"n1475293261","loc":[-85.6391256,41.9523817],"tags":{"railway":"level_crossing"}},"n1475293264":{"id":"n1475293264","loc":[-85.6394155,41.9546493],"tags":{"railway":"level_crossing"}},"n1819805614":{"id":"n1819805614","loc":[-85.6345652,41.9363097]},"n1819805618":{"id":"n1819805618","loc":[-85.6295334,41.9426862]},"n1819805622":{"id":"n1819805622","loc":[-85.6308208,41.9430773]},"n1819805626":{"id":"n1819805626","loc":[-85.6274734,41.9406592]},"n1819805629":{"id":"n1819805629","loc":[-85.6296943,41.9430533]},"n1819805632":{"id":"n1819805632","loc":[-85.6340931,41.9354477]},"n1819805636":{"id":"n1819805636","loc":[-85.6304131,41.9436598]},"n1819805639":{"id":"n1819805639","loc":[-85.6304882,41.9426623]},"n1819805641":{"id":"n1819805641","loc":[-85.6336103,41.9367487]},"n1819805643":{"id":"n1819805643","loc":[-85.6300376,41.9418084]},"n1819805645":{"id":"n1819805645","loc":[-85.6365286,41.9336679]},"n1819805647":{"id":"n1819805647","loc":[-85.632016,41.9429221]},"n1819805666":{"id":"n1819805666","loc":[-85.6314753,41.9442663]},"n1819805669":{"id":"n1819805669","loc":[-85.6268619,41.9402203]},"n1819805673":{"id":"n1819805673","loc":[-85.6296728,41.9412099]},"n1819805676":{"id":"n1819805676","loc":[-85.6354557,41.932766]},"n1819805680":{"id":"n1819805680","loc":[-85.632752,41.9431012]},"n1819805683":{"id":"n1819805683","loc":[-85.631147,41.9432014]},"n1819805687":{"id":"n1819805687","loc":[-85.635284,41.9343942]},"n1819805690":{"id":"n1819805690","loc":[-85.6249736,41.9405794]},"n1819805694":{"id":"n1819805694","loc":[-85.6294153,41.9417925]},"n1819805698":{"id":"n1819805698","loc":[-85.6323486,41.9426986]},"n1819805702":{"id":"n1819805702","loc":[-85.6340287,41.9373871]},"n1819805707":{"id":"n1819805707","loc":[-85.6353698,41.9316326]},"n1819805711":{"id":"n1819805711","loc":[-85.6284176,41.940356]},"n1819805715":{"id":"n1819805715","loc":[-85.6291471,41.9412897]},"n1819805718":{"id":"n1819805718","loc":[-85.6311105,41.943979]},"n1819805722":{"id":"n1819805722","loc":[-85.6320868,41.9400128]},"n1819805724":{"id":"n1819805724","loc":[-85.635166,41.9324627]},"n1819805727":{"id":"n1819805727","loc":[-85.6344686,41.9350567]},"n1819805728":{"id":"n1819805728","loc":[-85.6357132,41.9332369]},"n1819805731":{"id":"n1819805731","loc":[-85.629984,41.9434444]},"n1819805760":{"id":"n1819805760","loc":[-85.6330996,41.9378784]},"n1819805766":{"id":"n1819805766","loc":[-85.625274,41.9411141]},"n1819805770":{"id":"n1819805770","loc":[-85.6326321,41.9412173]},"n1819805774":{"id":"n1819805774","loc":[-85.6347047,41.9312096]},"n1819805777":{"id":"n1819805777","loc":[-85.6363569,41.9339552]},"n1819805780":{"id":"n1819805780","loc":[-85.6327392,41.941926]},"n1819805783":{"id":"n1819805783","loc":[-85.6357239,41.9338435]},"n1819805786":{"id":"n1819805786","loc":[-85.6356595,41.9346576]},"n1819805789":{"id":"n1819805789","loc":[-85.6316469,41.9436598]},"n1819805792":{"id":"n1819805792","loc":[-85.6350587,41.9354557]},"n1819805795":{"id":"n1819805795","loc":[-85.6360028,41.9322791]},"n1819805798":{"id":"n1819805798","loc":[-85.63125,41.9443062]},"n1819805802":{"id":"n1819805802","loc":[-85.6263362,41.9408109]},"n1819805805":{"id":"n1819805805","loc":[-85.6315075,41.9438753]},"n1819805808":{"id":"n1819805808","loc":[-85.6340008,41.9316051]},"n1819805810":{"id":"n1819805810","loc":[-85.6345545,41.9320557]},"n1819805812":{"id":"n1819805812","loc":[-85.6250809,41.9408587]},"n1819805814":{"id":"n1819805814","loc":[-85.6257783,41.9400926]},"n1819805834":{"id":"n1819805834","loc":[-85.6326408,41.9424363]},"n1819805838":{"id":"n1819805838","loc":[-85.6365607,41.9334365]},"n1819805842":{"id":"n1819805842","loc":[-85.6288253,41.9410343]},"n1819805846":{"id":"n1819805846","loc":[-85.6279133,41.9402921]},"n1819805849":{"id":"n1819805849","loc":[-85.6289433,41.9405156]},"n1819805852":{"id":"n1819805852","loc":[-85.6313787,41.9439152]},"n1819805858":{"id":"n1819805858","loc":[-85.6300805,41.9420398]},"n1819805861":{"id":"n1819805861","loc":[-85.6321941,41.9396297]},"n1819805864":{"id":"n1819805864","loc":[-85.6329129,41.9393903]},"n1819805868":{"id":"n1819805868","loc":[-85.632001,41.9434922]},"n1819805870":{"id":"n1819805870","loc":[-85.6314903,41.9431535]},"n1819805873":{"id":"n1819805873","loc":[-85.6251667,41.9401166]},"n1819805876":{"id":"n1819805876","loc":[-85.63287,41.939941]},"n1819805878":{"id":"n1819805878","loc":[-85.6307886,41.9437317]},"n1819805880":{"id":"n1819805880","loc":[-85.6321727,41.940348]},"n1819805883":{"id":"n1819805883","loc":[-85.6265872,41.940113]},"n1819805885":{"id":"n1819805885","loc":[-85.6268404,41.9406672]},"n1819805887":{"id":"n1819805887","loc":[-85.6325267,41.9389035]},"n1819805889":{"id":"n1819805889","loc":[-85.6364964,41.933189]},"n1819805911":{"id":"n1819805911","loc":[-85.6248663,41.9401804]},"n1819805922":{"id":"n1819805922","loc":[-85.633267,41.9387199]},"n1819805925":{"id":"n1819805925","loc":[-85.6293402,41.9408428]},"n1819848849":{"id":"n1819848849","loc":[-85.6464957,41.9695178]},"n1819848850":{"id":"n1819848850","loc":[-85.6497642,41.9611355]},"n1819848851":{"id":"n1819848851","loc":[-85.6480943,41.9624818]},"n1819848854":{"id":"n1819848854","loc":[-85.6500362,41.9657367]},"n1819848855":{"id":"n1819848855","loc":[-85.6493673,41.9783496]},"n1819848856":{"id":"n1819848856","loc":[-85.6457409,41.9548007]},"n1819848857":{"id":"n1819848857","loc":[-85.651313,41.9760426]},"n1819848858":{"id":"n1819848858","loc":[-85.6495819,41.9784772]},"n1819848859":{"id":"n1819848859","loc":[-85.6495105,41.9833722]},"n1819848860":{"id":"n1819848860","loc":[-85.6405053,41.9492792]},"n1819848863":{"id":"n1819848863","loc":[-85.6502293,41.9786826]},"n1819848865":{"id":"n1819848865","loc":[-85.6406877,41.9495106]},"n1819848870":{"id":"n1819848870","loc":[-85.6493136,41.9704611]},"n1819848871":{"id":"n1819848871","loc":[-85.6372249,41.9441284]},"n1819848873":{"id":"n1819848873","loc":[-85.6512379,41.9659441]},"n1819848875":{"id":"n1819848875","loc":[-85.6508087,41.9650187]},"n1819848877":{"id":"n1819848877","loc":[-85.6487166,41.9605352]},"n1819848878":{"id":"n1819848878","loc":[-85.6506478,41.9760665]},"n1819848879":{"id":"n1819848879","loc":[-85.651431,41.9758512]},"n1819848886":{"id":"n1819848886","loc":[-85.6477617,41.9563945]},"n1819848889":{"id":"n1819848889","loc":[-85.6497895,41.9832286]},"n1819848892":{"id":"n1819848892","loc":[-85.6504868,41.9791931]},"n1819848893":{"id":"n1819848893","loc":[-85.6498002,41.9615085]},"n1819848894":{"id":"n1819848894","loc":[-85.6404302,41.9502846]},"n1819848901":{"id":"n1819848901","loc":[-85.6354412,41.9439886]},"n1819848903":{"id":"n1819848903","loc":[-85.6472145,41.9698528]},"n1819848904":{"id":"n1819848904","loc":[-85.6401979,41.9486233]},"n1819848905":{"id":"n1819848905","loc":[-85.6475042,41.963503]},"n1819848909":{"id":"n1819848909","loc":[-85.6343405,41.94358]},"n1819848914":{"id":"n1819848914","loc":[-85.6503474,41.9737773]},"n1819848915":{"id":"n1819848915","loc":[-85.6389533,41.9470992]},"n1819848916":{"id":"n1819848916","loc":[-85.6483625,41.9577907]},"n1819848917":{"id":"n1819848917","loc":[-85.6484768,41.9617419]},"n1819848918":{"id":"n1819848918","loc":[-85.644078,41.9545693]},"n1819848919":{"id":"n1819848919","loc":[-85.6437169,41.9543041]},"n1819848920":{"id":"n1819848920","loc":[-85.6478331,41.9627949]},"n1819848922":{"id":"n1819848922","loc":[-85.6499144,41.9785889]},"n1819848924":{"id":"n1819848924","loc":[-85.647633,41.9720066]},"n1819848926":{"id":"n1819848926","loc":[-85.6487987,41.978868]},"n1819848927":{"id":"n1819848927","loc":[-85.6495105,41.9730355]},"n1819848928":{"id":"n1819848928","loc":[-85.648223,41.9829654]},"n1819848929":{"id":"n1819848929","loc":[-85.6514846,41.9659122]},"n1819848931":{"id":"n1819848931","loc":[-85.6498753,41.9731871]},"n1819848932":{"id":"n1819848932","loc":[-85.640906,41.9508575]},"n1819848933":{"id":"n1819848933","loc":[-85.649775,41.9799767]},"n1819848934":{"id":"n1819848934","loc":[-85.6507014,41.9739927]},"n1819848937":{"id":"n1819848937","loc":[-85.6479763,41.9840899]},"n1819848938":{"id":"n1819848938","loc":[-85.6501113,41.9600884]},"n1819848939":{"id":"n1819848939","loc":[-85.6389962,41.9478253]},"n1819848941":{"id":"n1819848941","loc":[-85.637469,41.9445791]},"n1819848942":{"id":"n1819848942","loc":[-85.6494569,41.9601682]},"n1819848943":{"id":"n1819848943","loc":[-85.6368803,41.9439351]},"n1819848945":{"id":"n1819848945","loc":[-85.6474398,41.9724213]},"n1819848946":{"id":"n1819848946","loc":[-85.6382629,41.9463666]},"n1819848948":{"id":"n1819848948","loc":[-85.6489633,41.9830771]},"n1819848952":{"id":"n1819848952","loc":[-85.6488882,41.9600326]},"n1819848953":{"id":"n1819848953","loc":[-85.6488094,41.9774324]},"n1819848954":{"id":"n1819848954","loc":[-85.6491135,41.9600485]},"n1819848955":{"id":"n1819848955","loc":[-85.6501435,41.9734583]},"n1819848956":{"id":"n1819848956","loc":[-85.6495534,41.960958]},"n1819848958":{"id":"n1819848958","loc":[-85.6474683,41.9561491]},"n1819848959":{"id":"n1819848959","loc":[-85.6401083,41.9485451]},"n1819848960":{"id":"n1819848960","loc":[-85.6481764,41.9678686]},"n1819848961":{"id":"n1819848961","loc":[-85.6484017,41.967382]},"n1819848962":{"id":"n1819848962","loc":[-85.6501328,41.959897]},"n1819848964":{"id":"n1819848964","loc":[-85.6403695,41.9504586]},"n1819848966":{"id":"n1819848966","loc":[-85.6398975,41.9491499]},"n1819848967":{"id":"n1819848967","loc":[-85.6412455,41.9510187]},"n1819848968":{"id":"n1819848968","loc":[-85.6482622,41.9619493]},"n1819848969":{"id":"n1819848969","loc":[-85.6405841,41.9501474]},"n1819848970":{"id":"n1819848970","loc":[-85.6478583,41.9703394]},"n1819848971":{"id":"n1819848971","loc":[-85.6493388,41.9832845]},"n1819848972":{"id":"n1819848972","loc":[-85.6485664,41.9829415]},"n1819848974":{"id":"n1819848974","loc":[-85.6491457,41.9779887]},"n1819848975":{"id":"n1819848975","loc":[-85.6468889,41.9697033]},"n1819848976":{"id":"n1819848976","loc":[-85.6452726,41.9546072]},"n1819848977":{"id":"n1819848977","loc":[-85.6448435,41.9546072]},"n1819848979":{"id":"n1819848979","loc":[-85.6485342,41.9763138]},"n1819848980":{"id":"n1819848980","loc":[-85.6495282,41.9664087]},"n1819848986":{"id":"n1819848986","loc":[-85.6486307,41.9603278]},"n1819848987":{"id":"n1819848987","loc":[-85.6492278,41.9791871]},"n1819848990":{"id":"n1819848990","loc":[-85.6501934,41.9800724]},"n1819848992":{"id":"n1819848992","loc":[-85.6482445,41.9819685]},"n1819848993":{"id":"n1819848993","loc":[-85.6481871,41.9704451]},"n1819848994":{"id":"n1819848994","loc":[-85.6371364,41.9457602]},"n1819848996":{"id":"n1819848996","loc":[-85.6500362,41.9801023]},"n1819849000":{"id":"n1819849000","loc":[-85.639007,41.9485914]},"n1819849001":{"id":"n1819849001","loc":[-85.6488882,41.9669253]},"n1819849002":{"id":"n1819849002","loc":[-85.6484698,41.9565062]},"n1819849004":{"id":"n1819849004","loc":[-85.6510769,41.9761064]},"n1819849005":{"id":"n1819849005","loc":[-85.6503581,41.9799029]},"n1819849006":{"id":"n1819849006","loc":[-85.6489381,41.9703893]},"n1819849008":{"id":"n1819849008","loc":[-85.6497457,41.9833588]},"n1819849011":{"id":"n1819849011","loc":[-85.6497358,41.9717593]},"n1819849012":{"id":"n1819849012","loc":[-85.6494676,41.9796796]},"n1819849019":{"id":"n1819849019","loc":[-85.6486093,41.9771034]},"n1819849021":{"id":"n1819849021","loc":[-85.6504546,41.9796556]},"n1819849022":{"id":"n1819849022","loc":[-85.6371294,41.9454154]},"n1819849023":{"id":"n1819849023","loc":[-85.6503436,41.9759249]},"n1819849025":{"id":"n1819849025","loc":[-85.6462382,41.9693822]},"n1819849026":{"id":"n1819849026","loc":[-85.6497573,41.983093]},"n1819849028":{"id":"n1819849028","loc":[-85.6497465,41.9602799]},"n1819849029":{"id":"n1819849029","loc":[-85.6374728,41.9460698]},"n1819849030":{"id":"n1819849030","loc":[-85.6486592,41.9566039]},"n1819849031":{"id":"n1819849031","loc":[-85.6515989,41.9654993]},"n1819849032":{"id":"n1819849032","loc":[-85.6387028,41.9482658]},"n1819849033":{"id":"n1819849033","loc":[-85.6464742,41.9688398]},"n1819849034":{"id":"n1819849034","loc":[-85.6495212,41.9589236]},"n1819849035":{"id":"n1819849035","loc":[-85.6490599,41.9790096]},"n1819849036":{"id":"n1819849036","loc":[-85.6489918,41.9800724]},"n1819849038":{"id":"n1819849038","loc":[-85.6499182,41.9659042]},"n1819849040":{"id":"n1819849040","loc":[-85.639758,41.9490143]},"n1819849041":{"id":"n1819849041","loc":[-85.6514846,41.9755241]},"n1819849042":{"id":"n1819849042","loc":[-85.6436633,41.9540647]},"n1819849045":{"id":"n1819849045","loc":[-85.6475541,41.9726387]},"n1819849046":{"id":"n1819849046","loc":[-85.6488308,41.9718331]},"n1819849047":{"id":"n1819849047","loc":[-85.6377694,41.9460953]},"n1819849048":{"id":"n1819849048","loc":[-85.6490706,41.9804452]},"n1819849049":{"id":"n1819849049","loc":[-85.6485449,41.9766248]},"n1819849051":{"id":"n1819849051","loc":[-85.6483625,41.9790256]},"n1819849052":{"id":"n1819849052","loc":[-85.6490706,41.9585167]},"n1819849053":{"id":"n1819849053","loc":[-85.6425008,41.9522874]},"n1819849054":{"id":"n1819849054","loc":[-85.6475793,41.9632158]},"n1819849055":{"id":"n1819849055","loc":[-85.6408631,41.9499399]},"n1819849056":{"id":"n1819849056","loc":[-85.6483373,41.9814681]},"n1819849057":{"id":"n1819849057","loc":[-85.6313548,41.9442876]},"n1819849058":{"id":"n1819849058","loc":[-85.6432663,41.9529796]},"n1819849059":{"id":"n1819849059","loc":[-85.6487128,41.9582873]},"n1819849060":{"id":"n1819849060","loc":[-85.6482338,41.9817612]},"n1819849062":{"id":"n1819849062","loc":[-85.6485664,41.9788661]},"n1819849063":{"id":"n1819849063","loc":[-85.6373081,41.9448824]},"n1819849064":{"id":"n1819849064","loc":[-85.6472215,41.9557582]},"n1819849065":{"id":"n1819849065","loc":[-85.6348984,41.9440414]},"n1819849066":{"id":"n1819849066","loc":[-85.6501972,41.9647315]},"n1819849067":{"id":"n1819849067","loc":[-85.6489741,41.9808281]},"n1819849068":{"id":"n1819849068","loc":[-85.6420111,41.9515034]},"n1819849069":{"id":"n1819849069","loc":[-85.6397972,41.9488882]},"n1819849070":{"id":"n1819849070","loc":[-85.6499718,41.9593465]},"n1819849071":{"id":"n1819849071","loc":[-85.6486844,41.9811311]},"n1819849072":{"id":"n1819849072","loc":[-85.6390392,41.9474663]},"n1819849074":{"id":"n1819849074","loc":[-85.6495642,41.9616362]},"n1819849075":{"id":"n1819849075","loc":[-85.6483518,41.9791931]},"n1819849076":{"id":"n1819849076","loc":[-85.6478974,41.9833104]},"n1819849077":{"id":"n1819849077","loc":[-85.640155,41.948719]},"n1819849078":{"id":"n1819849078","loc":[-85.6399366,41.9487845]},"n1819849079":{"id":"n1819849079","loc":[-85.6492959,41.9825348]},"n1819849080":{"id":"n1819849080","loc":[-85.6505083,41.9648352]},"n1819849081":{"id":"n1819849081","loc":[-85.6492959,41.9645241]},"n1819849082":{"id":"n1819849082","loc":[-85.6402049,41.9491835]},"n1819849083":{"id":"n1819849083","loc":[-85.6495175,41.9826963]},"n1819849084":{"id":"n1819849084","loc":[-85.6480836,41.9728361]},"n1819849085":{"id":"n1819849085","loc":[-85.6374349,41.9443425]},"n1819849086":{"id":"n1819849086","loc":[-85.6478331,41.9681238]},"n1819849089":{"id":"n1819849089","loc":[-85.639368,41.9486169]},"n1819849092":{"id":"n1819849092","loc":[-85.6503581,41.9788022]},"n1819849093":{"id":"n1819849093","loc":[-85.64862,41.9568014]},"n1819849094":{"id":"n1819849094","loc":[-85.6496999,41.9828877]},"n1819849095":{"id":"n1819849095","loc":[-85.647472,41.972198]},"n1819849096":{"id":"n1819849096","loc":[-85.6485771,41.9644523]},"n1819849097":{"id":"n1819849097","loc":[-85.6388353,41.9480488]},"n1819849099":{"id":"n1819849099","loc":[-85.6472752,41.9683312]},"n1819849104":{"id":"n1819849104","loc":[-85.6479548,41.9836035]},"n1819849105":{"id":"n1819849105","loc":[-85.6462489,41.9691668]},"n1819849107":{"id":"n1819849107","loc":[-85.6511912,41.9746328]},"n1819849108":{"id":"n1819849108","loc":[-85.6498646,41.9714881]},"n1819849111":{"id":"n1819849111","loc":[-85.6488239,41.961684]},"n1819849112":{"id":"n1819849112","loc":[-85.6469356,41.9553812]},"n1819849114":{"id":"n1819849114","loc":[-85.6479548,41.9640853]},"n1819849119":{"id":"n1819849119","loc":[-85.6491565,41.961692]},"n1819849121":{"id":"n1819849121","loc":[-85.651667,41.9656728]},"n1819849124":{"id":"n1819849124","loc":[-85.6388423,41.9484414]},"n1819849126":{"id":"n1819849126","loc":[-85.6371686,41.9450978]},"n1819849127":{"id":"n1819849127","loc":[-85.6502615,41.9656728]},"n1819849129":{"id":"n1819849129","loc":[-85.6498501,41.9613031]},"n1819849131":{"id":"n1819849131","loc":[-85.6513881,41.9653298]},"n1819849133":{"id":"n1819849133","loc":[-85.639883,41.9485291]},"n1819849139":{"id":"n1819849139","loc":[-85.6508693,41.9658264]},"n1819849140":{"id":"n1819849140","loc":[-85.6486806,41.9761642]},"n1819849141":{"id":"n1819849141","loc":[-85.6483159,41.9717613]},"n1819849144":{"id":"n1819849144","loc":[-85.6443714,41.9546232]},"n1819849146":{"id":"n1819849146","loc":[-85.641775,41.9513359]},"n1819849147":{"id":"n1819849147","loc":[-85.6495604,41.9757335]},"n1819849148":{"id":"n1819849148","loc":[-85.6465671,41.9551678]},"n1819849150":{"id":"n1819849150","loc":[-85.6485127,41.9794084]},"n1819849151":{"id":"n1819849151","loc":[-85.6499144,41.9757096]},"n1819849152":{"id":"n1819849152","loc":[-85.6433736,41.9531072]},"n1819849154":{"id":"n1819849154","loc":[-85.6489741,41.9607426]},"n1819849155":{"id":"n1819849155","loc":[-85.640627,41.9507697]},"n1819849156":{"id":"n1819849156","loc":[-85.6509659,41.9743058]},"n1819849157":{"id":"n1819849157","loc":[-85.6486844,41.9704431]},"n1819849158":{"id":"n1819849158","loc":[-85.6498538,41.9711132]},"n1819849159":{"id":"n1819849159","loc":[-85.6358937,41.943719]},"n1819849160":{"id":"n1819849160","loc":[-85.6497358,41.9707702]},"n1819849161":{"id":"n1819849161","loc":[-85.6480476,41.9564842]},"n1819849162":{"id":"n1819849162","loc":[-85.6482982,41.9574556]},"n1819849163":{"id":"n1819849163","loc":[-85.6501757,41.9757794]},"n1819849164":{"id":"n1819849164","loc":[-85.6372973,41.9459916]},"n1819849165":{"id":"n1819849165","loc":[-85.6513773,41.9750775]},"n1819849166":{"id":"n1819849166","loc":[-85.6436418,41.9537455]},"n1819849167":{"id":"n1819849167","loc":[-85.6483625,41.9571524]},"n1819849169":{"id":"n1819849169","loc":[-85.647751,41.9727962]},"n1819849170":{"id":"n1819849170","loc":[-85.6504546,41.9656808]},"n1819849171":{"id":"n1819849171","loc":[-85.6479977,41.971839]},"n1819849172":{"id":"n1819849172","loc":[-85.6482767,41.9642449]},"n1819849174":{"id":"n1819849174","loc":[-85.6414317,41.9512086]},"n1819849176":{"id":"n1819849176","loc":[-85.6469034,41.9685287]},"n1819849179":{"id":"n1819849179","loc":[-85.6408631,41.9497564]},"n1819849182":{"id":"n1819849182","loc":[-85.6476721,41.96384]},"n1819849183":{"id":"n1819849183","loc":[-85.6479725,41.983111]},"n1819849184":{"id":"n1819849184","loc":[-85.640788,41.9500516]},"n1819849185":{"id":"n1819849185","loc":[-85.6427798,41.9528778]},"n1819849186":{"id":"n1819849186","loc":[-85.6435308,41.9534124]},"n1819849187":{"id":"n1819849187","loc":[-85.6483733,41.9821998]},"n1819849189":{"id":"n1819849189","loc":[-85.6351752,41.9440796]},"n1819849191":{"id":"n1819849191","loc":[-85.6487021,41.9601463]},"n1819849192":{"id":"n1819849192","loc":[-85.6363811,41.9437605]},"n1819849193":{"id":"n1819849193","loc":[-85.6490883,41.9759728]},"n1819849194":{"id":"n1819849194","loc":[-85.6423292,41.9520081]},"n1819849195":{"id":"n1819849195","loc":[-85.6500003,41.960242]},"n1819849196":{"id":"n1819849196","loc":[-85.6385778,41.9466443]},"n1819849197":{"id":"n1819849197","loc":[-85.6494032,41.9718789]},"n1819849198":{"id":"n1819849198","loc":[-85.6404339,41.9506501]},"n1819849199":{"id":"n1819849199","loc":[-85.6426226,41.9527083]},"n1819849200":{"id":"n1819849200","loc":[-85.6439101,41.9545035]},"n1819849201":{"id":"n1819849201","loc":[-85.6516563,41.9657845]},"n1819849202":{"id":"n1819849202","loc":[-85.6473395,41.9699585]},"n1819858501":{"id":"n1819858501","loc":[-85.6361263,41.9437126]},"n1819858503":{"id":"n1819858503","loc":[-85.6350068,41.944034]},"n1819858513":{"id":"n1819858513","loc":[-85.6371402,41.9453282]},"n1819858518":{"id":"n1819858518","loc":[-85.6348713,41.9432923]},"n1819858523":{"id":"n1819858523","loc":[-85.6357047,41.943799]},"n1819858526":{"id":"n1819858526","loc":[-85.6349947,41.9435756]},"n1819858531":{"id":"n1819858531","loc":[-85.6350376,41.943827]},"n1820937508":{"id":"n1820937508","loc":[-85.1026013,42.0881722]},"n1820937509":{"id":"n1820937509","loc":[-85.0558088,42.102493]},"n1820937511":{"id":"n1820937511","loc":[-85.3030116,41.9724451]},"n1820937513":{"id":"n1820937513","loc":[-85.0353221,42.1027398]},"n1820937514":{"id":"n1820937514","loc":[-85.0835468,42.1015469]},"n1820937515":{"id":"n1820937515","loc":[-85.2421298,42.0106305]},"n1820937517":{"id":"n1820937517","loc":[-85.0090632,42.0910452]},"n1820937518":{"id":"n1820937518","loc":[-85.086626,42.0948838]},"n1820937520":{"id":"n1820937520","loc":[-85.2552039,42.0015448]},"n1820937521":{"id":"n1820937521","loc":[-85.3739614,41.9969917]},"n1820937522":{"id":"n1820937522","loc":[-85.4831166,41.993898]},"n1820937523":{"id":"n1820937523","loc":[-85.0341084,42.0977657]},"n1820937524":{"id":"n1820937524","loc":[-85.3272802,41.9710333]},"n1820937525":{"id":"n1820937525","loc":[-85.2125568,42.0414521]},"n1820937526":{"id":"n1820937526","loc":[-85.3798022,41.9992458]},"n1820937527":{"id":"n1820937527","loc":[-85.2652021,41.999768]},"n1820937528":{"id":"n1820937528","loc":[-85.3852739,42.0004896]},"n1820937529":{"id":"n1820937529","loc":[-85.3911919,42.0030513]},"n1820937530":{"id":"n1820937530","loc":[-85.5440349,41.9717109]},"n1820937531":{"id":"n1820937531","loc":[-85.2790155,41.9911764]},"n1820937532":{"id":"n1820937532","loc":[-85.4723277,41.9950518]},"n1820937533":{"id":"n1820937533","loc":[-85.5690546,41.9653931]},"n1820937535":{"id":"n1820937535","loc":[-85.5674882,41.9649623]},"n1820937536":{"id":"n1820937536","loc":[-85.6362815,41.9189165]},"n1820937537":{"id":"n1820937537","loc":[-85.5659003,41.963638]},"n1820937539":{"id":"n1820937539","loc":[-85.6391353,41.9122262]},"n1820937540":{"id":"n1820937540","loc":[-85.4834385,41.9894803]},"n1820937541":{"id":"n1820937541","loc":[-85.6399078,41.9160744]},"n1820937542":{"id":"n1820937542","loc":[-85.632874,41.941031]},"n1820937543":{"id":"n1820937543","loc":[-85.1307591,42.0726961]},"n1820937544":{"id":"n1820937544","loc":[-85.6444397,41.9128378]},"n1820937545":{"id":"n1820937545","loc":[-85.6197204,41.9420365]},"n1820937546":{"id":"n1820937546","loc":[-85.1164857,42.0864631]},"n1820937547":{"id":"n1820937547","loc":[-85.6476111,41.9142222]},"n1820937548":{"id":"n1820937548","loc":[-85.2915747,41.9774223]},"n1820937549":{"id":"n1820937549","loc":[-85.6430192,41.9102461]},"n1820937550":{"id":"n1820937550","loc":[-85.1597495,42.0639017]},"n1820937551":{"id":"n1820937551","loc":[-85.5504079,41.9701793]},"n1820937553":{"id":"n1820937553","loc":[-85.2781317,41.9948951]},"n1820937555":{"id":"n1820937555","loc":[-85.3724594,41.997518]},"n1820937556":{"id":"n1820937556","loc":[-85.5629434,41.9665155]},"n1820937557":{"id":"n1820937557","loc":[-85.3791971,41.9990808]},"n1820937558":{"id":"n1820937558","loc":[-85.001891,42.0878843]},"n1820937560":{"id":"n1820937560","loc":[-85.3140838,41.9709056]},"n1820937561":{"id":"n1820937561","loc":[-85.2468032,42.0146987]},"n1820937563":{"id":"n1820937563","loc":[-85.0877378,42.097255]},"n1820937564":{"id":"n1820937564","loc":[-85.2442498,42.0150654]},"n1820937566":{"id":"n1820937566","loc":[-85.3108973,41.9701478]},"n1820937568":{"id":"n1820937568","loc":[-85.0344584,42.1016572]},"n1820937569":{"id":"n1820937569","loc":[-85.2331025,42.0297387]},"n1820937570":{"id":"n1820937570","loc":[-85.5058446,41.9746996]},"n1820937571":{"id":"n1820937571","loc":[-85.5622739,41.9676427]},"n1820937572":{"id":"n1820937572","loc":[-85.2792687,41.9890337]},"n1820937574":{"id":"n1820937574","loc":[-84.9909302,42.08695]},"n1820937575":{"id":"n1820937575","loc":[-85.6218233,41.9418609]},"n1820937576":{"id":"n1820937576","loc":[-85.3577437,41.9931062]},"n1820937577":{"id":"n1820937577","loc":[-85.639028,41.9165853]},"n1820937578":{"id":"n1820937578","loc":[-84.9956576,42.0865348]},"n1820937579":{"id":"n1820937579","loc":[-85.4828376,41.990198]},"n1820937580":{"id":"n1820937580","loc":[-85.3244478,41.9720543]},"n1820937582":{"id":"n1820937582","loc":[-85.0517479,42.1035159]},"n1820937583":{"id":"n1820937583","loc":[-85.225646,42.0338025]},"n1820937584":{"id":"n1820937584","loc":[-84.9941019,42.0862163]},"n1820937586":{"id":"n1820937586","loc":[-85.1051762,42.0879452]},"n1820937587":{"id":"n1820937587","loc":[-85.1245203,42.0753162]},"n1820937588":{"id":"n1820937588","loc":[-85.3250808,41.9719506]},"n1820937589":{"id":"n1820937589","loc":[-85.2720109,41.997933]},"n1820937590":{"id":"n1820937590","loc":[-85.2556653,42.0027248]},"n1820937591":{"id":"n1820937591","loc":[-85.0872483,42.0943544]},"n1820937592":{"id":"n1820937592","loc":[-85.2778353,41.9955023]},"n1820937593":{"id":"n1820937593","loc":[-85.2984733,41.9735538]},"n1820937594":{"id":"n1820937594","loc":[-85.101578,42.0889552]},"n1820937595":{"id":"n1820937595","loc":[-85.3888745,42.0016959]},"n1820937596":{"id":"n1820937596","loc":[-84.9903508,42.0870654]},"n1820937597":{"id":"n1820937597","loc":[-85.6405558,41.9146261]},"n1820937598":{"id":"n1820937598","loc":[-85.6460704,41.9141311]},"n1820937599":{"id":"n1820937599","loc":[-85.0377468,42.1037428]},"n1820937600":{"id":"n1820937600","loc":[-85.2298345,42.0312899]},"n1820937601":{"id":"n1820937601","loc":[-85.1080958,42.0861964]},"n1820937602":{"id":"n1820937602","loc":[-85.6325307,41.9402329]},"n1820937603":{"id":"n1820937603","loc":[-85.1165984,42.0832184]},"n1820937604":{"id":"n1820937604","loc":[-85.6354446,41.9190602]},"n1820937605":{"id":"n1820937605","loc":[-85.1114592,42.0862959]},"n1820937606":{"id":"n1820937606","loc":[-85.0858763,42.1001646]},"n1820937607":{"id":"n1820937607","loc":[-85.0472083,42.1015151]},"n1820937608":{"id":"n1820937608","loc":[-85.0802477,42.1027609]},"n1820937610":{"id":"n1820937610","loc":[-85.0924585,42.0928564]},"n1820937611":{"id":"n1820937611","loc":[-85.0329617,42.09827]},"n1820937612":{"id":"n1820937612","loc":[-85.2814617,41.993465]},"n1820937613":{"id":"n1820937613","loc":[-85.3097708,41.9700282]},"n1820937614":{"id":"n1820937614","loc":[-85.2809427,41.993695]},"n1820937615":{"id":"n1820937615","loc":[-85.0583233,42.1026494]},"n1820937617":{"id":"n1820937617","loc":[-85.2801592,41.9840021]},"n1820937619":{"id":"n1820937619","loc":[-85.1064154,42.0863449]},"n1820937620":{"id":"n1820937620","loc":[-85.0423173,42.1014662]},"n1820937621":{"id":"n1820937621","loc":[-85.2168913,42.0398107]},"n1820937622":{"id":"n1820937622","loc":[-85.2798481,41.9833401]},"n1820937623":{"id":"n1820937623","loc":[-85.0575468,42.1028672]},"n1820937625":{"id":"n1820937625","loc":[-85.0130369,42.0893067]},"n1820937626":{"id":"n1820937626","loc":[-85.0346985,42.1018256]},"n1820937627":{"id":"n1820937627","loc":[-85.2231569,42.0372768]},"n1820937628":{"id":"n1820937628","loc":[-85.2956195,41.9732268]},"n1820937629":{"id":"n1820937629","loc":[-85.1052312,42.086893]},"n1820937630":{"id":"n1820937630","loc":[-85.4813356,41.9958436]},"n1820937631":{"id":"n1820937631","loc":[-85.0961599,42.0914672]},"n1820937632":{"id":"n1820937632","loc":[-85.308419,41.9704749]},"n1820937633":{"id":"n1820937633","loc":[-85.295952,41.9715119]},"n1820937634":{"id":"n1820937634","loc":[-85.3310933,41.9703923]},"n1820937635":{"id":"n1820937635","loc":[-85.2940745,41.9739686]},"n1820937636":{"id":"n1820937636","loc":[-85.3803343,42.000484]},"n1820937637":{"id":"n1820937637","loc":[-85.1174231,42.0845533]},"n1820937638":{"id":"n1820937638","loc":[-85.0095836,42.089839]},"n1820937639":{"id":"n1820937639","loc":[-85.3179354,41.9705866]},"n1820937640":{"id":"n1820937640","loc":[-85.257708,42.0001189]},"n1820937641":{"id":"n1820937641","loc":[-85.2563522,42.0002771]},"n1820937642":{"id":"n1820937642","loc":[-85.3181929,41.970419]},"n1820937643":{"id":"n1820937643","loc":[-85.2911884,41.9757154]},"n1820937644":{"id":"n1820937644","loc":[-85.2714423,41.9975862]},"n1820937645":{"id":"n1820937645","loc":[-85.0193669,42.089888]},"n1820937646":{"id":"n1820937646","loc":[-85.3889818,42.0039921]},"n1820937647":{"id":"n1820937647","loc":[-85.3408093,41.9853965]},"n1820937648":{"id":"n1820937648","loc":[-85.1258091,42.0748332]},"n1820937649":{"id":"n1820937649","loc":[-85.5722561,41.962782]},"n1820937650":{"id":"n1820937650","loc":[-85.3266902,41.9721819]},"n1820937651":{"id":"n1820937651","loc":[-85.1473255,42.065192]},"n1820937652":{"id":"n1820937652","loc":[-85.1462526,42.0655106]},"n1820937653":{"id":"n1820937653","loc":[-85.4641051,42.0013929]},"n1820937654":{"id":"n1820937654","loc":[-85.5620379,41.9700677]},"n1820937655":{"id":"n1820937655","loc":[-85.3226025,41.971121]},"n1820937656":{"id":"n1820937656","loc":[-85.0200965,42.0899516]},"n1820937657":{"id":"n1820937657","loc":[-85.0624714,42.1044711]},"n1820937658":{"id":"n1820937658","loc":[-85.5649562,41.9637178]},"n1820937659":{"id":"n1820937659","loc":[-85.2360315,42.0253315]},"n1820937660":{"id":"n1820937660","loc":[-85.3881449,41.9994475]},"n1820937661":{"id":"n1820937661","loc":[-85.5032911,41.976263]},"n1820937662":{"id":"n1820937662","loc":[-85.481297,41.9871414]},"n1820937663":{"id":"n1820937663","loc":[-85.1167056,42.0841898]},"n1820937664":{"id":"n1820937664","loc":[-85.2891714,41.9787223]},"n1820937665":{"id":"n1820937665","loc":[-85.4393429,42.0058736]},"n1820937666":{"id":"n1820937666","loc":[-85.0077007,42.0895762]},"n1820937667":{"id":"n1820937667","loc":[-85.2736202,41.9979171]},"n1820937668":{"id":"n1820937668","loc":[-84.9935332,42.0859296]},"n1820937669":{"id":"n1820937669","loc":[-85.0622769,42.1046713]},"n1820937670":{"id":"n1820937670","loc":[-85.2309031,42.0311249]},"n1820937671":{"id":"n1820937671","loc":[-85.0343726,42.10069]},"n1820937672":{"id":"n1820937672","loc":[-85.0596551,42.1048612]},"n1820937673":{"id":"n1820937673","loc":[-85.1338597,42.0707449]},"n1820937674":{"id":"n1820937674","loc":[-85.3117663,41.9689194]},"n1820937675":{"id":"n1820937675","loc":[-85.0705649,42.1057499]},"n1820937676":{"id":"n1820937676","loc":[-85.2441425,42.0180944]},"n1820937677":{"id":"n1820937677","loc":[-85.1171174,42.0862692]},"n1820937678":{"id":"n1820937678","loc":[-85.0346824,42.1005519]},"n1820937680":{"id":"n1820937680","loc":[-85.2389927,42.0229245]},"n1820937681":{"id":"n1820937681","loc":[-85.0834892,42.1018642]},"n1820937682":{"id":"n1820937682","loc":[-85.0619443,42.1049459]},"n1820937683":{"id":"n1820937683","loc":[-85.2845366,41.9811868]},"n1820937684":{"id":"n1820937684","loc":[-85.210411,42.0394123]},"n1820937685":{"id":"n1820937685","loc":[-85.4377383,42.0055942]},"n1820937686":{"id":"n1820937686","loc":[-85.2882058,41.9789138]},"n1820937687":{"id":"n1820937687","loc":[-85.2741191,41.9955808]},"n1820937688":{"id":"n1820937688","loc":[-85.3442211,41.9903575]},"n1820937689":{"id":"n1820937689","loc":[-85.2641413,41.9995237]},"n1820937690":{"id":"n1820937690","loc":[-85.2804489,41.9829174]},"n1820937691":{"id":"n1820937691","loc":[-85.5593342,41.9729074]},"n1820937692":{"id":"n1820937692","loc":[-85.3590912,41.9932601]},"n1820937694":{"id":"n1820937694","loc":[-85.4826445,41.9957479]},"n1820937695":{"id":"n1820937695","loc":[-85.4539127,42.0063041]},"n1820937696":{"id":"n1820937696","loc":[-85.2456767,42.0153683]},"n1820937697":{"id":"n1820937697","loc":[-85.5794015,41.9489631]},"n1820937698":{"id":"n1820937698","loc":[-85.4108686,42.0078507]},"n1820937699":{"id":"n1820937699","loc":[-85.0616386,42.1051529]},"n1820937700":{"id":"n1820937700","loc":[-85.4977979,41.978241]},"n1820937701":{"id":"n1820937701","loc":[-85.2488417,42.0086319]},"n1820937702":{"id":"n1820937702","loc":[-85.5588836,41.9728116]},"n1820937703":{"id":"n1820937703","loc":[-85.4557366,42.0051241]},"n1820937705":{"id":"n1820937705","loc":[-85.0723151,42.1056094]},"n1820937706":{"id":"n1820937706","loc":[-85.0057909,42.0887323]},"n1820937707":{"id":"n1820937707","loc":[-85.0756786,42.105677]},"n1820937708":{"id":"n1820937708","loc":[-85.0901504,42.0940001]},"n1820937709":{"id":"n1820937709","loc":[-85.0979999,42.0910213]},"n1820937710":{"id":"n1820937710","loc":[-85.2376301,42.0239686]},"n1820937711":{"id":"n1820937711","loc":[-85.2780671,41.9902299]},"n1820937712":{"id":"n1820937712","loc":[-85.251481,42.0113188]},"n1820937713":{"id":"n1820937713","loc":[-85.3114767,41.9690311]},"n1820937714":{"id":"n1820937714","loc":[-85.2649621,41.9975662]},"n1820937715":{"id":"n1820937715","loc":[-85.283807,41.9813383]},"n1820937716":{"id":"n1820937716","loc":[-85.5515451,41.9703867]},"n1820937717":{"id":"n1820937717","loc":[-85.1176605,42.0850896]},"n1820937718":{"id":"n1820937718","loc":[-85.1069317,42.0862441]},"n1820937719":{"id":"n1820937719","loc":[-85.2739314,41.9976938]},"n1820937720":{"id":"n1820937720","loc":[-85.5550212,41.9702112]},"n1820937721":{"id":"n1820937721","loc":[-85.3076679,41.9719904]},"n1820937722":{"id":"n1820937722","loc":[-85.592319,41.9440316]},"n1820937723":{"id":"n1820937723","loc":[-85.3139979,41.9704031]},"n1820937724":{"id":"n1820937724","loc":[-85.0421134,42.1013149]},"n1820937725":{"id":"n1820937725","loc":[-85.2508373,42.0102741]},"n1820937726":{"id":"n1820937726","loc":[-85.0830922,42.1038821]},"n1820937727":{"id":"n1820937727","loc":[-85.6342473,41.9360031]},"n1820937730":{"id":"n1820937730","loc":[-85.0500192,42.1024942]},"n1820937731":{"id":"n1820937731","loc":[-85.3498644,41.9926221]},"n1820937732":{"id":"n1820937732","loc":[-85.0234117,42.0918903]},"n1820937733":{"id":"n1820937733","loc":[-85.0464425,42.1009408]},"n1820937734":{"id":"n1820937734","loc":[-85.033938,42.099886]},"n1820937736":{"id":"n1820937736","loc":[-85.0152752,42.0886009]},"n1820937737":{"id":"n1820937737","loc":[-85.0441894,42.1012671]},"n1820937738":{"id":"n1820937738","loc":[-85.4668731,41.9979804]},"n1820937739":{"id":"n1820937739","loc":[-85.4407377,42.006033]},"n1820937740":{"id":"n1820937740","loc":[-85.2262253,42.0344878]},"n1820937741":{"id":"n1820937741","loc":[-85.2550001,42.0033706]},"n1820937742":{"id":"n1820937742","loc":[-85.3071422,41.9722617]},"n1820937743":{"id":"n1820937743","loc":[-85.6147852,41.942228]},"n1820937744":{"id":"n1820937744","loc":[-85.0183853,42.0901825]},"n1820937745":{"id":"n1820937745","loc":[-85.6323161,41.9228489]},"n1820937746":{"id":"n1820937746","loc":[-85.0095568,42.0901376]},"n1820937747":{"id":"n1820937747","loc":[-85.2524037,42.0113826]},"n1820937748":{"id":"n1820937748","loc":[-85.3186864,41.9708578]},"n1820937749":{"id":"n1820937749","loc":[-85.2805669,41.9870883]},"n1820937750":{"id":"n1820937750","loc":[-85.0585768,42.1038144]},"n1820937751":{"id":"n1820937751","loc":[-85.2970786,41.9715358]},"n1820937752":{"id":"n1820937752","loc":[-85.1315758,42.0723445]},"n1820937753":{"id":"n1820937753","loc":[-85.2448291,42.0175444]},"n1820937754":{"id":"n1820937754","loc":[-85.2446468,42.0174248]},"n1820937755":{"id":"n1820937755","loc":[-85.229165,42.032129]},"n1820937756":{"id":"n1820937756","loc":[-85.5612654,41.9724926]},"n1820937757":{"id":"n1820937757","loc":[-85.2331776,42.030854]},"n1820937758":{"id":"n1820937758","loc":[-85.2271909,42.0334519]},"n1820937759":{"id":"n1820937759","loc":[-85.1032396,42.0879214]},"n1820937760":{"id":"n1820937760","loc":[-85.0638447,42.1044154]},"n1820937761":{"id":"n1820937761","loc":[-85.1260706,42.0745556]},"n1820937762":{"id":"n1820937762","loc":[-85.3454485,41.99132]},"n1820937763":{"id":"n1820937763","loc":[-85.2639321,41.9980088]},"n1820937764":{"id":"n1820937764","loc":[-85.0837681,42.1013746]},"n1820937765":{"id":"n1820937765","loc":[-85.2808137,41.9869368]},"n1820937766":{"id":"n1820937766","loc":[-85.6338997,41.9309373]},"n1820937767":{"id":"n1820937767","loc":[-85.2267403,42.0332766]},"n1820937768":{"id":"n1820937768","loc":[-85.0605831,42.1052074]},"n1820937769":{"id":"n1820937769","loc":[-85.0259021,42.0930037]},"n1820937770":{"id":"n1820937770","loc":[-85.232963,42.0313162]},"n1820937771":{"id":"n1820937771","loc":[-85.2404947,42.0125381]},"n1820937772":{"id":"n1820937772","loc":[-85.0910892,42.0935742]},"n1820937773":{"id":"n1820937773","loc":[-85.2554829,42.0019435]},"n1820937774":{"id":"n1820937774","loc":[-85.2799339,41.9867773]},"n1820937775":{"id":"n1820937775","loc":[-85.1075432,42.0852767]},"n1820937776":{"id":"n1820937776","loc":[-85.1176927,42.0854001]},"n1820937777":{"id":"n1820937777","loc":[-85.1067064,42.0863357]},"n1820937778":{"id":"n1820937778","loc":[-85.2517492,42.0106333]},"n1820937779":{"id":"n1820937779","loc":[-85.0987174,42.0909031]},"n1820937780":{"id":"n1820937780","loc":[-85.1160083,42.0863994]},"n1820937781":{"id":"n1820937781","loc":[-85.1268645,42.0739703]},"n1820937782":{"id":"n1820937782","loc":[-85.0454702,42.1002852]},"n1820937783":{"id":"n1820937783","loc":[-85.1334145,42.0705418]},"n1820937784":{"id":"n1820937784","loc":[-85.5866542,41.947431]},"n1820937786":{"id":"n1820937786","loc":[-85.2359886,42.0250366]},"n1820937787":{"id":"n1820937787","loc":[-85.3138048,41.9698527]},"n1820937788":{"id":"n1820937788","loc":[-85.1274291,42.0733081]},"n1820937790":{"id":"n1820937790","loc":[-85.6292905,41.9411267]},"n1820937791":{"id":"n1820937791","loc":[-85.5958809,41.9417333]},"n1820937792":{"id":"n1820937792","loc":[-85.1271019,42.0737581]},"n1820937793":{"id":"n1820937793","loc":[-85.2312679,42.0314437]},"n1820937794":{"id":"n1820937794","loc":[-85.1081387,42.0863516]},"n1820937795":{"id":"n1820937795","loc":[-85.2424473,42.0212109]},"n1820937796":{"id":"n1820937796","loc":[-85.2710654,41.9975236]},"n1820937797":{"id":"n1820937797","loc":[-85.4798408,41.9863223]},"n1820937798":{"id":"n1820937798","loc":[-85.035939,42.104296]},"n1820937799":{"id":"n1820937799","loc":[-85.2178139,42.0395398]},"n1820937800":{"id":"n1820937800","loc":[-85.0630709,42.1042614]},"n1820937801":{"id":"n1820937801","loc":[-85.0440124,42.1014861]},"n1820937802":{"id":"n1820937802","loc":[-85.1321874,42.0720458]},"n1820937804":{"id":"n1820937804","loc":[-85.079427,42.1029121]},"n1820937805":{"id":"n1820937805","loc":[-85.2962632,41.9738968]},"n1820937806":{"id":"n1820937806","loc":[-85.6334748,41.9274627]},"n1820937807":{"id":"n1820937807","loc":[-85.1057341,42.0872804]},"n1820937808":{"id":"n1820937808","loc":[-85.4960169,41.9778263]},"n1820937809":{"id":"n1820937809","loc":[-85.2821226,41.9910273]},"n1820937810":{"id":"n1820937810","loc":[-85.0013868,42.0885054]},"n1820937811":{"id":"n1820937811","loc":[-85.2952547,41.9729795]},"n1820937812":{"id":"n1820937812","loc":[-85.1298375,42.0667842]},"n1820937813":{"id":"n1820937813","loc":[-85.1339201,42.0710025]},"n1820937814":{"id":"n1820937814","loc":[-85.0374356,42.103691]},"n1820937815":{"id":"n1820937815","loc":[-85.0061115,42.0880607]},"n1820937817":{"id":"n1820937817","loc":[-85.2398402,42.0226934]},"n1820937818":{"id":"n1820937818","loc":[-85.123501,42.076236]},"n1820937819":{"id":"n1820937819","loc":[-85.1209489,42.0791294]},"n1820937820":{"id":"n1820937820","loc":[-85.0818624,42.1025778]},"n1820937821":{"id":"n1820937821","loc":[-85.4428835,42.0054749]},"n1820937822":{"id":"n1820937822","loc":[-85.4710359,41.9961147]},"n1820937823":{"id":"n1820937823","loc":[-85.4253354,42.006198]},"n1820937824":{"id":"n1820937824","loc":[-85.5486483,41.9709451]},"n1820937825":{"id":"n1820937825","loc":[-85.2303238,42.0310452]},"n1820937826":{"id":"n1820937826","loc":[-85.6450405,41.9136361]},"n1820937828":{"id":"n1820937828","loc":[-85.2606853,41.9964073]},"n1820937830":{"id":"n1820937830","loc":[-85.097383,42.0911447]},"n1820937831":{"id":"n1820937831","loc":[-85.0498207,42.102136]},"n1820937832":{"id":"n1820937832","loc":[-85.1232435,42.0763793]},"n1820937833":{"id":"n1820937833","loc":[-85.394093,42.0055921]},"n1820937834":{"id":"n1820937834","loc":[-85.3566665,41.9928295]},"n1820937835":{"id":"n1820937835","loc":[-85.3543276,41.9920002]},"n1820937837":{"id":"n1820937837","loc":[-85.084668,42.1034932]},"n1820937838":{"id":"n1820937838","loc":[-85.4400296,42.0060649]},"n1820937839":{"id":"n1820937839","loc":[-85.2362246,42.025714]},"n1820937840":{"id":"n1820937840","loc":[-85.0409225,42.1012791]},"n1820937841":{"id":"n1820937841","loc":[-85.2442283,42.019832]},"n1820937842":{"id":"n1820937842","loc":[-85.1123001,42.084824]},"n1820937843":{"id":"n1820937843","loc":[-85.1603074,42.0638061]},"n1820937844":{"id":"n1820937844","loc":[-85.1359744,42.0650646]},"n1820937845":{"id":"n1820937845","loc":[-85.1757569,42.053849]},"n1820937846":{"id":"n1820937846","loc":[-85.5200925,41.9716686]},"n1820937848":{"id":"n1820937848","loc":[-85.5525322,41.9701315]},"n1820937849":{"id":"n1820937849","loc":[-85.0406489,42.10149]},"n1820937850":{"id":"n1820937850","loc":[-85.0142547,42.088825]},"n1820937851":{"id":"n1820937851","loc":[-85.343749,41.9881884]},"n1820937852":{"id":"n1820937852","loc":[-85.074996,42.1060205]},"n1820937853":{"id":"n1820937853","loc":[-85.2436275,42.0136864]},"n1820937854":{"id":"n1820937854","loc":[-85.2641453,41.9980897]},"n1820937856":{"id":"n1820937856","loc":[-85.2802343,41.9870086]},"n1820937857":{"id":"n1820937857","loc":[-85.0099256,42.0909946]},"n1820937858":{"id":"n1820937858","loc":[-85.493957,41.9786079]},"n1820937859":{"id":"n1820937859","loc":[-85.0739405,42.1059795]},"n1820937860":{"id":"n1820937860","loc":[-85.2331605,42.0301423]},"n1820937862":{"id":"n1820937862","loc":[-85.2035231,42.0438425]},"n1820937863":{"id":"n1820937863","loc":[-85.0884928,42.0986971]},"n1820937864":{"id":"n1820937864","loc":[-85.131597,42.0690142]},"n1820937865":{"id":"n1820937865","loc":[-85.3937454,42.0052677]},"n1820937866":{"id":"n1820937866","loc":[-85.2212729,42.0378561]},"n1820937867":{"id":"n1820937867","loc":[-85.0886068,42.0982421]},"n1820937868":{"id":"n1820937868","loc":[-85.0875004,42.0968064]},"n1820937869":{"id":"n1820937869","loc":[-85.0771323,42.1042642]},"n1820937870":{"id":"n1820937870","loc":[-85.0164554,42.0894887]},"n1820937871":{"id":"n1820937871","loc":[-85.6069102,41.9415577]},"n1820937872":{"id":"n1820937872","loc":[-85.3273875,41.9704908]},"n1820937873":{"id":"n1820937873","loc":[-85.3890891,41.9997983]},"n1820937875":{"id":"n1820937875","loc":[-85.5091276,41.9723705]},"n1820937876":{"id":"n1820937876","loc":[-85.0770626,42.1047696]},"n1820937877":{"id":"n1820937877","loc":[-85.612575,41.9419567]},"n1820937878":{"id":"n1820937878","loc":[-85.3868146,42.0036094]},"n1820937879":{"id":"n1820937879","loc":[-85.2722738,41.9981204]},"n1820937880":{"id":"n1820937880","loc":[-85.3064878,41.9723733]},"n1820937882":{"id":"n1820937882","loc":[-85.1270845,42.0727678]},"n1820937884":{"id":"n1820937884","loc":[-85.3316512,41.97923]},"n1820937885":{"id":"n1820937885","loc":[-85.3932519,42.0042472]},"n1820937886":{"id":"n1820937886","loc":[-85.2457411,42.0175444]},"n1820937887":{"id":"n1820937887","loc":[-85.1397509,42.0648415]},"n1820937891":{"id":"n1820937891","loc":[-85.3196735,41.9719665]},"n1820937892":{"id":"n1820937892","loc":[-85.3372473,41.9845033]},"n1820937894":{"id":"n1820937894","loc":[-85.3254778,41.9719745]},"n1820937897":{"id":"n1820937897","loc":[-85.3185148,41.9691268]},"n1820937899":{"id":"n1820937899","loc":[-85.5419106,41.9714556]},"n1820937901":{"id":"n1820937901","loc":[-85.3293509,41.9748368]},"n1820937903":{"id":"n1820937903","loc":[-85.0798078,42.1028365]},"n1820937905":{"id":"n1820937905","loc":[-85.3954191,42.0056025]},"n1820937909":{"id":"n1820937909","loc":[-85.3417534,41.9857155]},"n1820937913":{"id":"n1820937913","loc":[-84.9927822,42.0857107]},"n1820937915":{"id":"n1820937915","loc":[-85.5444212,41.9712801]},"n1820937917":{"id":"n1820937917","loc":[-85.259088,41.9981682]},"n1820937921":{"id":"n1820937921","loc":[-85.2784576,41.9876358]},"n1820937922":{"id":"n1820937922","loc":[-84.9971918,42.087753]},"n1820937924":{"id":"n1820937924","loc":[-85.5310688,41.966899]},"n1820937928":{"id":"n1820937928","loc":[-85.3766436,41.9979326]},"n1820937930":{"id":"n1820937930","loc":[-85.5494852,41.9704346]},"n1820937933":{"id":"n1820937933","loc":[-85.5548281,41.9695412]},"n1820937935":{"id":"n1820937935","loc":[-85.0768588,42.105088]},"n1820937937":{"id":"n1820937937","loc":[-85.2646885,41.9978054]},"n1820937939":{"id":"n1820937939","loc":[-85.2441532,42.0176082]},"n1820937941":{"id":"n1820937941","loc":[-85.105553,42.0877928]},"n1820937943":{"id":"n1820937943","loc":[-85.0879457,42.0958909]},"n1820937944":{"id":"n1820937944","loc":[-85.3187015,41.9704402]},"n1820937945":{"id":"n1820937945","loc":[-85.5624456,41.970626]},"n1820937946":{"id":"n1820937946","loc":[-85.0580176,42.1028644]},"n1820937948":{"id":"n1820937948","loc":[-85.3016061,41.9726286]},"n1820937949":{"id":"n1820937949","loc":[-85.4310388,42.0069418]},"n1820937950":{"id":"n1820937950","loc":[-85.2945144,41.9740723]},"n1820937951":{"id":"n1820937951","loc":[-85.1170222,42.082657]},"n1820937952":{"id":"n1820937952","loc":[-85.0864503,42.0947632]},"n1820937953":{"id":"n1820937953","loc":[-85.4285926,42.0059533]},"n1820937970":{"id":"n1820937970","loc":[-85.3629965,41.9938023]},"n1820937972":{"id":"n1820937972","loc":[-85.2438099,42.0199755]},"n1820937974":{"id":"n1820937974","loc":[-85.1327654,42.0699285]},"n1820937977":{"id":"n1820937977","loc":[-85.1515956,42.0611935]},"n1820937978":{"id":"n1820937978","loc":[-85.0107369,42.0896638]},"n1820937979":{"id":"n1820937979","loc":[-85.1152626,42.0862083]},"n1820937980":{"id":"n1820937980","loc":[-85.4531831,42.0062881]},"n1820937981":{"id":"n1820937981","loc":[-85.0341473,42.0985924]},"n1820937982":{"id":"n1820937982","loc":[-85.0877485,42.0960171]},"n1820937983":{"id":"n1820937983","loc":[-85.2756373,41.9951742]},"n1820937984":{"id":"n1820937984","loc":[-85.2965421,41.9714401]},"n1820937985":{"id":"n1820937985","loc":[-85.2409775,42.0226934]},"n1820937986":{"id":"n1820937986","loc":[-85.0170723,42.0900579]},"n1820937987":{"id":"n1820937987","loc":[-85.1034663,42.0880555]},"n1820937988":{"id":"n1820937988","loc":[-85.0585071,42.1031577]},"n1820937990":{"id":"n1820937990","loc":[-85.0819174,42.1032373]},"n1820937992":{"id":"n1820937992","loc":[-85.0546608,42.1030542]},"n1820937993":{"id":"n1820937993","loc":[-85.0100811,42.0906125]},"n1820937995":{"id":"n1820937995","loc":[-85.6304278,41.9432655]},"n1820937997":{"id":"n1820937997","loc":[-85.0255628,42.092778]},"n1820938011":{"id":"n1820938011","loc":[-85.2316756,42.0317146]},"n1820938012":{"id":"n1820938012","loc":[-85.4067917,42.008042]},"n1820938013":{"id":"n1820938013","loc":[-85.390398,42.0028759]},"n1820938014":{"id":"n1820938014","loc":[-85.0161604,42.0886527]},"n1820938015":{"id":"n1820938015","loc":[-85.125337,42.0744589]},"n1820938016":{"id":"n1820938016","loc":[-85.2151317,42.0404801]},"n1820938017":{"id":"n1820938017","loc":[-85.3165085,41.9706025]},"n1820938018":{"id":"n1820938018","loc":[-85.5641193,41.9640688]},"n1820938019":{"id":"n1820938019","loc":[-85.147583,42.0642203]},"n1820938022":{"id":"n1820938022","loc":[-85.2803781,41.9947886]},"n1820938024":{"id":"n1820938024","loc":[-85.2692469,41.9982053]},"n1820938026":{"id":"n1820938026","loc":[-85.4321975,42.0067505]},"n1820938028":{"id":"n1820938028","loc":[-85.572535,41.9633405]},"n1820938030":{"id":"n1820938030","loc":[-85.3237505,41.9716475]},"n1820938032":{"id":"n1820938032","loc":[-85.6487698,41.9141583]},"n1820938033":{"id":"n1820938033","loc":[-85.0526371,42.1038315]},"n1820938034":{"id":"n1820938034","loc":[-85.088069,42.0978731]},"n1820938035":{"id":"n1820938035","loc":[-85.2516312,42.0102267]},"n1820938039":{"id":"n1820938039","loc":[-85.2731374,41.9982958]},"n1820938040":{"id":"n1820938040","loc":[-85.5453224,41.9713439]},"n1820938041":{"id":"n1820938041","loc":[-85.4480548,42.0049647]},"n1820938043":{"id":"n1820938043","loc":[-85.2504081,42.010322]},"n1820938045":{"id":"n1820938045","loc":[-85.2663447,41.99919]},"n1820938046":{"id":"n1820938046","loc":[-85.0507287,42.102907]},"n1820938047":{"id":"n1820938047","loc":[-85.0408246,42.1024743]},"n1820938048":{"id":"n1820938048","loc":[-85.2796335,41.9866099]},"n1820938050":{"id":"n1820938050","loc":[-85.452475,42.0061127]},"n1820938051":{"id":"n1820938051","loc":[-85.2410569,42.0128147]},"n1820938052":{"id":"n1820938052","loc":[-85.0413302,42.1011477]},"n1820938053":{"id":"n1820938053","loc":[-85.6327409,41.9197627]},"n1820938056":{"id":"n1820938056","loc":[-85.1072039,42.0857994]},"n1820938057":{"id":"n1820938057","loc":[-85.2001114,42.0448145]},"n1820938058":{"id":"n1820938058","loc":[-85.2655347,41.9978186]},"n1820938059":{"id":"n1820938059","loc":[-85.2330918,42.0304874]},"n1820938060":{"id":"n1820938060","loc":[-85.2601113,41.9966545]},"n1820938061":{"id":"n1820938061","loc":[-85.5397863,41.9708494]},"n1820938062":{"id":"n1820938062","loc":[-85.2702085,41.9977217]},"n1820938063":{"id":"n1820938063","loc":[-85.2219982,42.03699]},"n1820938064":{"id":"n1820938064","loc":[-85.0668957,42.105121]},"n1820938065":{"id":"n1820938065","loc":[-85.2328665,42.0270769]},"n1820938066":{"id":"n1820938066","loc":[-85.3189654,41.9694778]},"n1820938067":{"id":"n1820938067","loc":[-85.3814115,42.0022915]},"n1820938068":{"id":"n1820938068","loc":[-85.2759108,41.9956008]},"n1820938069":{"id":"n1820938069","loc":[-85.0391938,42.1034853]},"n1820938070":{"id":"n1820938070","loc":[-85.2850623,41.9810353]},"n1820938071":{"id":"n1820938071","loc":[-85.538074,41.970855]},"n1820938073":{"id":"n1820938073","loc":[-85.1319661,42.0670932]},"n1820938074":{"id":"n1820938074","loc":[-85.2816763,41.9913678]},"n1820938075":{"id":"n1820938075","loc":[-85.3182144,41.9700282]},"n1820938076":{"id":"n1820938076","loc":[-85.5909028,41.9458989]},"n1820938077":{"id":"n1820938077","loc":[-85.4057617,42.0074361]},"n1820938078":{"id":"n1820938078","loc":[-85.2620438,41.9967729]},"n1820938079":{"id":"n1820938079","loc":[-85.1122143,42.0851107]},"n1820938080":{"id":"n1820938080","loc":[-85.2443785,42.0174567]},"n1820938081":{"id":"n1820938081","loc":[-85.0319733,42.0953853]},"n1820938082":{"id":"n1820938082","loc":[-85.0878276,42.09443]},"n1820938083":{"id":"n1820938083","loc":[-85.0271789,42.0935809]},"n1820938084":{"id":"n1820938084","loc":[-85.0326399,42.0974222]},"n1820938085":{"id":"n1820938085","loc":[-85.3989167,42.0065592]},"n1820938086":{"id":"n1820938086","loc":[-85.3263361,41.9721261]},"n1820938087":{"id":"n1820938087","loc":[-85.2547855,42.0037134]},"n1820938088":{"id":"n1820938088","loc":[-85.4373259,42.005746]},"n1820938089":{"id":"n1820938089","loc":[-85.3094275,41.9699245]},"n1820938090":{"id":"n1820938090","loc":[-85.2783246,41.9872793]},"n1820938092":{"id":"n1820938092","loc":[-85.0815633,42.1025169]},"n1820938093":{"id":"n1820938093","loc":[-85.1788511,42.0522134]},"n1820938095":{"id":"n1820938095","loc":[-85.2830345,41.9816733]},"n1820938096":{"id":"n1820938096","loc":[-85.0744984,42.1059835]},"n1820938097":{"id":"n1820938097","loc":[-85.2788396,41.9879333]},"n1820938098":{"id":"n1820938098","loc":[-85.3640093,41.9946531]},"n1820938099":{"id":"n1820938099","loc":[-85.291167,41.9787463]},"n1820938100":{"id":"n1820938100","loc":[-85.0772436,42.1038156]},"n1820938101":{"id":"n1820938101","loc":[-85.00563,42.0887482]},"n1820938102":{"id":"n1820938102","loc":[-85.0326881,42.0961245]},"n1820938104":{"id":"n1820938104","loc":[-85.0530448,42.1038634]},"n1820938105":{"id":"n1820938105","loc":[-85.2625266,41.9970639]},"n1820938106":{"id":"n1820938106","loc":[-85.2827556,41.9823512]},"n1820938107":{"id":"n1820938107","loc":[-85.2784319,41.9910752]},"n1820938108":{"id":"n1820938108","loc":[-85.0882099,42.094393]},"n1820938109":{"id":"n1820938109","loc":[-85.5718484,41.9645371]},"n1820938110":{"id":"n1820938110","loc":[-85.2559764,42.0099317]},"n1820938111":{"id":"n1820938111","loc":[-85.2969284,41.973179]},"n1820938113":{"id":"n1820938113","loc":[-85.3875055,42.0019726]},"n1820938114":{"id":"n1820938114","loc":[-85.4250779,42.0068199]},"n1820938115":{"id":"n1820938115","loc":[-85.0645367,42.104889]},"n1820938116":{"id":"n1820938116","loc":[-85.1636762,42.0623724]},"n1820938117":{"id":"n1820938117","loc":[-85.0757322,42.1055935]},"n1820938118":{"id":"n1820938118","loc":[-85.3695197,41.9981559]},"n1820938120":{"id":"n1820938120","loc":[-85.1297516,42.0671027]},"n1820938121":{"id":"n1820938121","loc":[-85.1057448,42.0875551]},"n1820938122":{"id":"n1820938122","loc":[-85.2805175,41.9943182]},"n1820938123":{"id":"n1820938123","loc":[-85.2545173,42.0040722]},"n1820938124":{"id":"n1820938124","loc":[-84.9966607,42.0871319]},"n1820938125":{"id":"n1820938125","loc":[-85.0099899,42.0904612]},"n1820938126":{"id":"n1820938126","loc":[-85.2489919,42.0091102]},"n1820938127":{"id":"n1820938127","loc":[-85.0342706,42.0979476]},"n1820938128":{"id":"n1820938128","loc":[-85.1080891,42.0855884]},"n1820938129":{"id":"n1820938129","loc":[-85.0128183,42.0905356]},"n1820938130":{"id":"n1820938130","loc":[-85.631608,41.9434251]},"n1820938131":{"id":"n1820938131","loc":[-85.2551975,42.0008524]},"n1820938132":{"id":"n1820938132","loc":[-85.6421823,41.9096233]},"n1820938133":{"id":"n1820938133","loc":[-85.0125059,42.0906284]},"n1820938134":{"id":"n1820938134","loc":[-85.5499358,41.9701793]},"n1820938135":{"id":"n1820938135","loc":[-85.5472107,41.9712323]},"n1820938136":{"id":"n1820938136","loc":[-85.2760758,41.9958691]},"n1820938137":{"id":"n1820938137","loc":[-85.276678,41.9960433]},"n1820938138":{"id":"n1820938138","loc":[-85.0570319,42.1024731]},"n1820938140":{"id":"n1820938140","loc":[-85.2394325,42.0227492]},"n1820938142":{"id":"n1820938142","loc":[-85.5666341,41.9638829]},"n1820938144":{"id":"n1820938144","loc":[-85.258101,41.9996353]},"n1820938147":{"id":"n1820938147","loc":[-85.2129645,42.0413565]},"n1820938149":{"id":"n1820938149","loc":[-84.9962369,42.0868373]},"n1820938151":{"id":"n1820938151","loc":[-85.2570386,42.0084968]},"n1820938153":{"id":"n1820938153","loc":[-85.3971142,42.0050285]},"n1820938155":{"id":"n1820938155","loc":[-85.1072093,42.0855566]},"n1820938157":{"id":"n1820938157","loc":[-85.2840323,41.9920959]},"n1820938159":{"id":"n1820938159","loc":[-85.1187924,42.0816458]},"n1820938161":{"id":"n1820938161","loc":[-85.2681324,41.9985788]},"n1820938163":{"id":"n1820938163","loc":[-85.0887034,42.0984969]},"n1820938165":{"id":"n1820938165","loc":[-85.4133405,42.0073141]},"n1820938166":{"id":"n1820938166","loc":[-85.0097445,42.0902888]},"n1820938167":{"id":"n1820938167","loc":[-85.0828133,42.1037388]},"n1820938168":{"id":"n1820938168","loc":[-85.0549599,42.1030833]},"n1820938169":{"id":"n1820938169","loc":[-85.4571528,42.0010421]},"n1820938178":{"id":"n1820938178","loc":[-85.2706644,41.9975941]},"n1820938180":{"id":"n1820938180","loc":[-85.2258606,42.0335794]},"n1820938182":{"id":"n1820938182","loc":[-85.2832276,41.9814659]},"n1820938184":{"id":"n1820938184","loc":[-85.1082299,42.0860928]},"n1820938185":{"id":"n1820938185","loc":[-85.3839392,42.0022381]},"n1820938186":{"id":"n1820938186","loc":[-85.2772131,41.995905]},"n1820938187":{"id":"n1820938187","loc":[-85.1044895,42.0879214]},"n1820938188":{"id":"n1820938188","loc":[-85.2135267,42.0407087]},"n1820938189":{"id":"n1820938189","loc":[-85.2543993,42.0044628]},"n1820938190":{"id":"n1820938190","loc":[-85.1501793,42.0617351]},"n1820938191":{"id":"n1820938191","loc":[-85.3350587,41.9820469]},"n1820938192":{"id":"n1820938192","loc":[-85.1350731,42.0655735]},"n1820938193":{"id":"n1820938193","loc":[-85.0404008,42.1028843]},"n1820938194":{"id":"n1820938194","loc":[-85.6323161,41.943042]},"n1820938195":{"id":"n1820938195","loc":[-85.1259593,42.0742837]},"n1820938196":{"id":"n1820938196","loc":[-85.4562988,42.0033758]},"n1820938197":{"id":"n1820938197","loc":[-85.256824,42.0056826]},"n1820938198":{"id":"n1820938198","loc":[-85.2742103,41.9963862]},"n1820938199":{"id":"n1820938199","loc":[-85.0380888,42.1037877]},"n1820938200":{"id":"n1820938200","loc":[-85.47404,41.9944721]},"n1820938201":{"id":"n1820938201","loc":[-85.103021,42.087948]},"n1820938202":{"id":"n1820938202","loc":[-85.4030151,42.0065113]},"n1820938203":{"id":"n1820938203","loc":[-85.2113981,42.040735]},"n1820938204":{"id":"n1820938204","loc":[-85.2603433,41.9965137]},"n1820938206":{"id":"n1820938206","loc":[-85.1669378,42.0607634]},"n1820938207":{"id":"n1820938207","loc":[-85.0642027,42.1046076]},"n1820938208":{"id":"n1820938208","loc":[-85.2812428,41.9915696]},"n1820938209":{"id":"n1820938209","loc":[-85.0839559,42.1038343]},"n1820938210":{"id":"n1820938210","loc":[-85.1239946,42.0769368]},"n1820938211":{"id":"n1820938211","loc":[-85.2311177,42.0283042]},"n1820938212":{"id":"n1820938212","loc":[-85.2791614,41.9882682]},"n1820938213":{"id":"n1820938213","loc":[-85.2674941,41.9987582]},"n1820938214":{"id":"n1820938214","loc":[-85.352787,41.9919579]},"n1820938215":{"id":"n1820938215","loc":[-85.0874146,42.0952182]},"n1820938216":{"id":"n1820938216","loc":[-85.0069711,42.0877092]},"n1820938217":{"id":"n1820938217","loc":[-85.2059049,42.0404004]},"n1820938218":{"id":"n1820938218","loc":[-85.2403552,42.0227332]},"n1820938219":{"id":"n1820938219","loc":[-85.2492923,42.0098915]},"n1820938220":{"id":"n1820938220","loc":[-85.269778,41.9979541]},"n1820938221":{"id":"n1820938221","loc":[-85.2097673,42.0389024]},"n1820938222":{"id":"n1820938222","loc":[-85.0845942,42.1032015]},"n1820938223":{"id":"n1820938223","loc":[-84.993206,42.0858142]},"n1820938224":{"id":"n1820938224","loc":[-85.2108187,42.0402729]},"n1820938225":{"id":"n1820938225","loc":[-84.9893959,42.0873043]},"n1820938226":{"id":"n1820938226","loc":[-85.2952332,41.9719984]},"n1820938227":{"id":"n1820938227","loc":[-85.4100961,42.0081536]},"n1820938228":{"id":"n1820938228","loc":[-85.3299088,41.9785696]},"n1820938229":{"id":"n1820938229","loc":[-85.2258176,42.0340097]},"n1820938230":{"id":"n1820938230","loc":[-85.3146739,41.9711449]},"n1820938231":{"id":"n1820938231","loc":[-85.5447645,41.9712801]},"n1820938232":{"id":"n1820938232","loc":[-85.5510087,41.9705941]},"n1820938233":{"id":"n1820938233","loc":[-85.5122389,41.9703445]},"n1820938234":{"id":"n1820938234","loc":[-85.2792687,41.9865381]},"n1820938235":{"id":"n1820938235","loc":[-85.1475229,42.0630151]},"n1820938237":{"id":"n1820938237","loc":[-85.0332889,42.0996034]},"n1820938238":{"id":"n1820938238","loc":[-85.2588882,41.9986877]},"n1820938239":{"id":"n1820938239","loc":[-85.0656458,42.1050892]},"n1820938240":{"id":"n1820938240","loc":[-84.9913915,42.086098]},"n1820938241":{"id":"n1820938241","loc":[-85.4752416,41.9944402]},"n1820938242":{"id":"n1820938242","loc":[-85.1214304,42.0791147]},"n1820938243":{"id":"n1820938243","loc":[-85.0075183,42.0886925]},"n1820938244":{"id":"n1820938244","loc":[-85.1052888,42.0872087]},"n1820938245":{"id":"n1820938245","loc":[-85.3104252,41.9703393]},"n1820938246":{"id":"n1820938246","loc":[-85.232109,42.0318158]},"n1820938247":{"id":"n1820938247","loc":[-85.0756075,42.1059528]},"n1820938248":{"id":"n1820938248","loc":[-85.0075612,42.0890866]},"n1820938249":{"id":"n1820938249","loc":[-85.1013312,42.0897474]},"n1820938250":{"id":"n1820938250","loc":[-85.1168076,42.0828919]},"n1820938251":{"id":"n1820938251","loc":[-85.2951367,41.9723334]},"n1820938252":{"id":"n1820938252","loc":[-85.0879363,42.0976053]},"n1820938253":{"id":"n1820938253","loc":[-85.0354763,42.1021838]},"n1820938254":{"id":"n1820938254","loc":[-85.2379627,42.0236339]},"n1820938255":{"id":"n1820938255","loc":[-85.1308245,42.0685364]},"n1820938256":{"id":"n1820938256","loc":[-85.0914446,42.0934774]},"n1820938257":{"id":"n1820938257","loc":[-85.2436812,42.014069]},"n1820938258":{"id":"n1820938258","loc":[-85.0682529,42.1056106]},"n1820938259":{"id":"n1820938259","loc":[-85.290652,41.9766805]},"n1820938260":{"id":"n1820938260","loc":[-85.0133494,42.0897434]},"n1820938261":{"id":"n1820938261","loc":[-85.2753047,41.9949429]},"n1820938262":{"id":"n1820938262","loc":[-85.0314691,42.0950788]},"n1820938263":{"id":"n1820938263","loc":[-85.3444786,41.9908359]},"n1820938264":{"id":"n1820938264","loc":[-85.0443115,42.1009061]},"n1820938265":{"id":"n1820938265","loc":[-85.0634853,42.1043159]},"n1820938267":{"id":"n1820938267","loc":[-85.3978223,42.0053952]},"n1820938268":{"id":"n1820938268","loc":[-85.0228659,42.0911885]},"n1820938269":{"id":"n1820938269","loc":[-85.0220237,42.0906272]},"n1820938270":{"id":"n1820938270","loc":[-85.1061525,42.0863369]},"n1820938271":{"id":"n1820938271","loc":[-85.2382309,42.0233708]},"n1820938272":{"id":"n1820938272","loc":[-85.310672,41.9702755]},"n1820938273":{"id":"n1820938273","loc":[-85.1448192,42.0652613]},"n1820938274":{"id":"n1820938274","loc":[-85.6036057,41.9403766]},"n1820938275":{"id":"n1820938275","loc":[-85.0778941,42.1032413]},"n1820938276":{"id":"n1820938276","loc":[-85.1279374,42.0723974]},"n1820938277":{"id":"n1820938277","loc":[-85.2806635,41.9847836]},"n1820938278":{"id":"n1820938278","loc":[-85.2653201,41.9976352]},"n1820938279":{"id":"n1820938279","loc":[-85.0351665,42.1001805]},"n1820938280":{"id":"n1820938280","loc":[-85.0718269,42.1056253]},"n1820938281":{"id":"n1820938281","loc":[-85.2574248,42.0075322]},"n1820938282":{"id":"n1820938282","loc":[-85.126666,42.0740778]},"n1820938283":{"id":"n1820938283","loc":[-85.077705,42.1034733]},"n1820938284":{"id":"n1820938284","loc":[-85.3535552,41.9919045]},"n1820938286":{"id":"n1820938286","loc":[-85.2810711,41.9866657]},"n1820938287":{"id":"n1820938287","loc":[-85.4567494,42.0019885]},"n1820938288":{"id":"n1820938288","loc":[-85.2642419,41.9992936]},"n1820938289":{"id":"n1820938289","loc":[-85.2643344,41.9980925]},"n1820938290":{"id":"n1820938290","loc":[-85.3270335,41.9776125]},"n1820938291":{"id":"n1820938291","loc":[-85.1200584,42.0795077]},"n1820938292":{"id":"n1820938292","loc":[-85.2290792,42.0340256]},"n1820938293":{"id":"n1820938293","loc":[-85.6015887,41.9401372]},"n1820938294":{"id":"n1820938294","loc":[-85.5370869,41.970488]},"n1820938295":{"id":"n1820938295","loc":[-85.3108866,41.9698048]},"n1820938297":{"id":"n1820938297","loc":[-85.1556511,42.0628184]},"n1820938298":{"id":"n1820938298","loc":[-85.0027922,42.0875221]},"n1820938300":{"id":"n1820938300","loc":[-85.3873338,42.0040614]},"n1820938301":{"id":"n1820938301","loc":[-85.0350753,42.1004034]},"n1820938302":{"id":"n1820938302","loc":[-85.6239476,41.9411906]},"n1820938304":{"id":"n1820938304","loc":[-85.0118246,42.0897964]},"n1820938306":{"id":"n1820938306","loc":[-85.4796877,41.995275]},"n1820938307":{"id":"n1820938307","loc":[-85.5388636,41.9707856]},"n1820938309":{"id":"n1820938309","loc":[-85.2971902,41.9727773]},"n1820938310":{"id":"n1820938310","loc":[-85.5426831,41.9715513]},"n1820938311":{"id":"n1820938311","loc":[-85.2798373,41.9836671]},"n1820938312":{"id":"n1820938312","loc":[-85.2432198,42.0104017]},"n1820938313":{"id":"n1820938313","loc":[-85.2650412,41.9987554]},"n1820938317":{"id":"n1820938317","loc":[-85.0015423,42.0882386]},"n1820938318":{"id":"n1820938318","loc":[-85.1409783,42.064879]},"n1820938319":{"id":"n1820938319","loc":[-85.1691908,42.058995]},"n1820938320":{"id":"n1820938320","loc":[-85.1059165,42.0864882]},"n1820938321":{"id":"n1820938321","loc":[-85.3664941,41.9965771]},"n1820938323":{"id":"n1820938323","loc":[-85.3143198,41.9710971]},"n1820938324":{"id":"n1820938324","loc":[-85.0016067,42.0880675]},"n1820938325":{"id":"n1820938325","loc":[-85.0148139,42.0887164]},"n1820938326":{"id":"n1820938326","loc":[-85.0324682,42.0959056]},"n1820938327":{"id":"n1820938327","loc":[-85.0898661,42.0939921]},"n1820938328":{"id":"n1820938328","loc":[-85.2556427,42.0004936]},"n1820938329":{"id":"n1820938329","loc":[-85.6287112,41.9407437]},"n1820938330":{"id":"n1820938330","loc":[-84.9913392,42.0866701]},"n1820938331":{"id":"n1820938331","loc":[-85.2685777,41.9984632]},"n1820938332":{"id":"n1820938332","loc":[-85.0078884,42.0901614]},"n1820938333":{"id":"n1820938333","loc":[-84.999642,42.0878616]},"n1820938334":{"id":"n1820938334","loc":[-85.0188909,42.0899186]},"n1820938335":{"id":"n1820938335","loc":[-85.2830238,41.9819843]},"n1820938336":{"id":"n1820938336","loc":[-85.2491421,42.0096204]},"n1820938337":{"id":"n1820938337","loc":[-85.0585701,42.1034295]},"n1820938338":{"id":"n1820938338","loc":[-85.0651965,42.1051636]},"n1820938339":{"id":"n1820938339","loc":[-85.0583944,42.104292]},"n1820938340":{"id":"n1820938340","loc":[-85.119876,42.0801567]},"n1820938341":{"id":"n1820938341","loc":[-85.0943937,42.0931323]},"n1820938342":{"id":"n1820938342","loc":[-85.1504583,42.0613209]},"n1820938343":{"id":"n1820938343","loc":[-85.0425426,42.1019836]},"n1820938345":{"id":"n1820938345","loc":[-84.9991391,42.0878206]},"n1820938346":{"id":"n1820938346","loc":[-85.2563841,42.0094614]},"n1820938347":{"id":"n1820938347","loc":[-85.0515387,42.103297]},"n1820938348":{"id":"n1820938348","loc":[-85.0857261,42.1003636]},"n1820938349":{"id":"n1820938349","loc":[-85.078971,42.1029241]},"n1820938350":{"id":"n1820938350","loc":[-85.5699558,41.958931]},"n1820938351":{"id":"n1820938351","loc":[-85.3181285,41.9696533]},"n1820938352":{"id":"n1820938352","loc":[-85.5998506,41.9402329]},"n1820938353":{"id":"n1820938353","loc":[-85.2567277,42.000317]},"n1820938354":{"id":"n1820938354","loc":[-85.3082795,41.9708338]},"n1820938355":{"id":"n1820938355","loc":[-85.3127856,41.9692784]},"n1820938356":{"id":"n1820938356","loc":[-85.0340775,42.1010721]},"n1820938357":{"id":"n1820938357","loc":[-85.3158111,41.9706583]},"n1820938359":{"id":"n1820938359","loc":[-85.2312035,42.0280412]},"n1820938360":{"id":"n1820938360","loc":[-85.2448613,42.018477]},"n1820938361":{"id":"n1820938361","loc":[-85.29077,41.9759068]},"n1820938364":{"id":"n1820938364","loc":[-85.3677387,41.9976615]},"n1820938365":{"id":"n1820938365","loc":[-85.0785204,42.1030355]},"n1820938366":{"id":"n1820938366","loc":[-85.2262039,42.0333722]},"n1820938367":{"id":"n1820938367","loc":[-85.1226011,42.0780902]},"n1820938368":{"id":"n1820938368","loc":[-85.3229673,41.971129]},"n1820938369":{"id":"n1820938369","loc":[-85.385334,42.0000056]},"n1820938370":{"id":"n1820938370","loc":[-85.000098,42.0879094]},"n1820938372":{"id":"n1820938372","loc":[-85.3852481,42.0025091]},"n1820938373":{"id":"n1820938373","loc":[-85.3770513,41.9982515]},"n1820938374":{"id":"n1820938374","loc":[-85.6278314,41.9405362]},"n1820938375":{"id":"n1820938375","loc":[-85.6355133,41.9344068]},"n1820938376":{"id":"n1820938376","loc":[-85.635642,41.9324753]},"n1820938377":{"id":"n1820938377","loc":[-85.3154463,41.970778]},"n1820938378":{"id":"n1820938378","loc":[-85.0920334,42.093411]},"n1820938379":{"id":"n1820938379","loc":[-85.3269155,41.9722297]},"n1820938381":{"id":"n1820938381","loc":[-85.1134334,42.0849184]},"n1820938382":{"id":"n1820938382","loc":[-85.005968,42.088585]},"n1820938384":{"id":"n1820938384","loc":[-85.1245203,42.0757183]},"n1820938385":{"id":"n1820938385","loc":[-85.020704,42.0905396]},"n1820938386":{"id":"n1820938386","loc":[-85.119585,42.0808984]},"n1820938387":{"id":"n1820938387","loc":[-85.0072447,42.0880117]},"n1820938388":{"id":"n1820938388","loc":[-85.2742908,41.9960273]},"n1820938389":{"id":"n1820938389","loc":[-85.3275807,41.9696852]},"n1820938390":{"id":"n1820938390","loc":[-85.2385635,42.0231556]},"n1820938392":{"id":"n1820938392","loc":[-85.0202856,42.0900778]},"n1820938393":{"id":"n1820938393","loc":[-85.2067847,42.0395398]},"n1820938394":{"id":"n1820938394","loc":[-85.5183544,41.9713495]},"n1820938396":{"id":"n1820938396","loc":[-85.5073037,41.9736787]},"n1820938397":{"id":"n1820938397","loc":[-85.2519638,42.0114225]},"n1820938398":{"id":"n1820938398","loc":[-85.287487,41.9793285]},"n1820938399":{"id":"n1820938399","loc":[-85.2298088,42.0336431]},"n1820938400":{"id":"n1820938400","loc":[-85.229444,42.0339141]},"n1820938401":{"id":"n1820938401","loc":[-85.2421791,42.0220239]},"n1820938402":{"id":"n1820938402","loc":[-85.2976687,41.9737612]},"n1820938403":{"id":"n1820938403","loc":[-85.3622069,41.993473]},"n1820938404":{"id":"n1820938404","loc":[-85.2465458,42.014906]},"n1820938405":{"id":"n1820938405","loc":[-85.5724663,41.9639412]},"n1820938406":{"id":"n1820938406","loc":[-85.3708501,41.9982037]},"n1820938408":{"id":"n1820938408","loc":[-85.2564592,42.0055311]},"n1820938409":{"id":"n1820938409","loc":[-85.1192846,42.0810856]},"n1820938410":{"id":"n1820938410","loc":[-85.5623812,41.971663]},"n1820938411":{"id":"n1820938411","loc":[-85.3221948,41.9719665]},"n1820938412":{"id":"n1820938412","loc":[-85.5168738,41.9710305]},"n1820938413":{"id":"n1820938413","loc":[-85.4546852,42.0061127]},"n1820938414":{"id":"n1820938414","loc":[-85.5896153,41.9463617]},"n1820938415":{"id":"n1820938415","loc":[-85.2978189,41.9722138]},"n1820938416":{"id":"n1820938416","loc":[-85.1021681,42.0883581]},"n1820938417":{"id":"n1820938417","loc":[-85.2797193,41.9912984]},"n1820938419":{"id":"n1820938419","loc":[-85.2362461,42.0248533]},"n1820938420":{"id":"n1820938420","loc":[-85.4833639,41.9846252]},"n1820938422":{"id":"n1820938422","loc":[-85.3281064,41.9689433]},"n1820938424":{"id":"n1820938424","loc":[-85.2416963,42.0130088]},"n1820938425":{"id":"n1820938425","loc":[-85.5718655,41.9564577]},"n1820938426":{"id":"n1820938426","loc":[-85.0512812,42.1030701]},"n1820938427":{"id":"n1820938427","loc":[-85.1273527,42.0723616]},"n1820938428":{"id":"n1820938428","loc":[-85.0215033,42.0904083]},"n1820938429":{"id":"n1820938429","loc":[-85.6169953,41.942228]},"n1820938430":{"id":"n1820938430","loc":[-85.2829165,41.9907243]},"n1820938431":{"id":"n1820938431","loc":[-85.2240796,42.0374203]},"n1820938432":{"id":"n1820938432","loc":[-85.0167598,42.0898442]},"n1820938433":{"id":"n1820938433","loc":[-85.2132649,42.0411334]},"n1820938434":{"id":"n1820938434","loc":[-85.2293839,42.031513]},"n1820938435":{"id":"n1820938435","loc":[-85.1203374,42.0792608]},"n1820938436":{"id":"n1820938436","loc":[-85.109571,42.086268]},"n1820938437":{"id":"n1820938437","loc":[-85.1079026,42.0853842]},"n1820938438":{"id":"n1820938438","loc":[-85.109237,42.0862413]},"n1820938439":{"id":"n1820938439","loc":[-85.2259936,42.0350831]},"n1820938440":{"id":"n1820938440","loc":[-85.3669705,41.99679]},"n1820938441":{"id":"n1820938441","loc":[-85.2418143,42.0223507]},"n1820938442":{"id":"n1820938442","loc":[-85.3101248,41.9702515]},"n1820938443":{"id":"n1820938443","loc":[-85.069315,42.1059688]},"n1820938444":{"id":"n1820938444","loc":[-85.205862,42.0410378]},"n1820938445":{"id":"n1820938445","loc":[-85.0388076,42.1036604]},"n1820938446":{"id":"n1820938446","loc":[-85.2225389,42.0370115]},"n1820938447":{"id":"n1820938447","loc":[-85.3241474,41.9719346]},"n1820938448":{"id":"n1820938448","loc":[-85.3125496,41.9690789]},"n1820938449":{"id":"n1820938449","loc":[-85.1146497,42.0857039]},"n1820938450":{"id":"n1820938450","loc":[-85.1333944,42.0714963]},"n1820938451":{"id":"n1820938451","loc":[-85.5619306,41.9720937]},"n1820938452":{"id":"n1820938452","loc":[-85.2553651,42.0006479]},"n1820938453":{"id":"n1820938453","loc":[-85.3151137,41.9710093]},"n1820938454":{"id":"n1820938454","loc":[-85.2592315,41.9977947]},"n1820938455":{"id":"n1820938455","loc":[-85.2655723,41.9995966]},"n1820938456":{"id":"n1820938456","loc":[-85.4820652,41.9959233]},"n1820938459":{"id":"n1820938459","loc":[-85.450737,42.0055068]},"n1820938460":{"id":"n1820938460","loc":[-85.2428658,42.0205573]},"n1820938461":{"id":"n1820938461","loc":[-85.0835576,42.1021559]},"n1820938462":{"id":"n1820938462","loc":[-85.244636,42.0194733]},"n1820938463":{"id":"n1820938463","loc":[-85.5702562,41.9581332]},"n1820938465":{"id":"n1820938465","loc":[-85.5680031,41.9659515]},"n1820938467":{"id":"n1820938467","loc":[-85.2798752,41.9948353]},"n1820938468":{"id":"n1820938468","loc":[-85.0477407,42.1015537]},"n1820938469":{"id":"n1820938469","loc":[-85.6403842,41.913732]},"n1820938470":{"id":"n1820938470","loc":[-85.0396029,42.103289]},"n1820938471":{"id":"n1820938471","loc":[-85.2824702,41.9907777]},"n1820938472":{"id":"n1820938472","loc":[-85.2969284,41.9735538]},"n1820938474":{"id":"n1820938474","loc":[-85.401041,42.0070853]},"n1820938475":{"id":"n1820938475","loc":[-85.4116625,42.0073883]},"n1820938476":{"id":"n1820938476","loc":[-85.0437764,42.1016214]},"n1820938477":{"id":"n1820938477","loc":[-85.3643269,41.9958436]},"n1820938478":{"id":"n1820938478","loc":[-85.3895182,42.0009465]},"n1820938479":{"id":"n1820938479","loc":[-85.636157,41.9333373]},"n1820938480":{"id":"n1820938480","loc":[-85.2811355,41.9858044]},"n1820938481":{"id":"n1820938481","loc":[-85.0239052,42.092153]},"n1820938482":{"id":"n1820938482","loc":[-85.2558798,42.0053557]},"n1820938483":{"id":"n1820938483","loc":[-85.2544422,42.0047339]},"n1820938484":{"id":"n1820938484","loc":[-85.4864683,41.9843183]},"n1820938485":{"id":"n1820938485","loc":[-85.2554185,42.0031075]},"n1820938486":{"id":"n1820938486","loc":[-85.3082795,41.9712486]},"n1820938487":{"id":"n1820938487","loc":[-85.2433378,42.0133436]},"n1820938488":{"id":"n1820938488","loc":[-85.0216696,42.0904162]},"n1820938489":{"id":"n1820938489","loc":[-85.2546138,42.0050289]},"n1820938490":{"id":"n1820938490","loc":[-85.2717521,41.9977349]},"n1820938491":{"id":"n1820938491","loc":[-85.0100489,42.0908195]},"n1820938492":{"id":"n1820938492","loc":[-85.207879,42.0392211]},"n1820938493":{"id":"n1820938493","loc":[-85.0007363,42.0882836]},"n1820938494":{"id":"n1820938494","loc":[-85.5775303,41.9504097]},"n1820938495":{"id":"n1820938495","loc":[-85.1131584,42.0847683]},"n1820938496":{"id":"n1820938496","loc":[-85.0887825,42.0941633]},"n1820938497":{"id":"n1820938497","loc":[-85.1185926,42.0818938]},"n1820938498":{"id":"n1820938498","loc":[-85.2748487,41.9948712]},"n1820938499":{"id":"n1820938499","loc":[-85.2566952,42.0090788]},"n1820938500":{"id":"n1820938500","loc":[-85.0774757,42.1036234]},"n1820938501":{"id":"n1820938501","loc":[-85.4190869,42.008903]},"n1820938502":{"id":"n1820938502","loc":[-85.1140395,42.0850577]},"n1820938503":{"id":"n1820938503","loc":[-85.1136104,42.0848627]},"n1820938504":{"id":"n1820938504","loc":[-85.5828089,41.9480638]},"n1820938505":{"id":"n1820938505","loc":[-85.625514,41.9405202]},"n1820938506":{"id":"n1820938506","loc":[-85.2063384,42.0398322]},"n1820938507":{"id":"n1820938507","loc":[-85.3395476,41.9851636]},"n1820938508":{"id":"n1820938508","loc":[-85.0328853,42.0963606]},"n1820938510":{"id":"n1820938510","loc":[-85.1170369,42.0843702]},"n1820938511":{"id":"n1820938511","loc":[-85.2784748,41.9868487]},"n1820938512":{"id":"n1820938512","loc":[-85.6310501,41.9435528]},"n1820938514":{"id":"n1820938514","loc":[-85.0334284,42.0981028]},"n1820938515":{"id":"n1820938515","loc":[-84.9912091,42.0868226]},"n1820938516":{"id":"n1820938516","loc":[-85.2806141,41.9940351]},"n1820938517":{"id":"n1820938517","loc":[-85.1233025,42.0776734]},"n1820938518":{"id":"n1820938518","loc":[-85.2047891,42.0429023]},"n1820938519":{"id":"n1820938519","loc":[-85.1475443,42.0648312]},"n1820938520":{"id":"n1820938520","loc":[-85.2644685,41.9990891]},"n1820938521":{"id":"n1820938521","loc":[-85.1056281,42.0872553]},"n1820938522":{"id":"n1820938522","loc":[-85.4813184,41.9930105]},"n1820938523":{"id":"n1820938523","loc":[-85.321551,41.9722936]},"n1820938524":{"id":"n1820938524","loc":[-85.1564664,42.0631211]},"n1820938525":{"id":"n1820938525","loc":[-85.4149885,42.0079144]},"n1820938527":{"id":"n1820938527","loc":[-85.2861888,41.9803653]},"n1820938528":{"id":"n1820938528","loc":[-85.1301379,42.0682178]},"n1820938529":{"id":"n1820938529","loc":[-85.4156537,42.0084247]},"n1820938530":{"id":"n1820938530","loc":[-85.245151,42.0176082]},"n1820938531":{"id":"n1820938531","loc":[-85.457818,42.0001651]},"n1820938532":{"id":"n1820938532","loc":[-85.310951,41.9694538]},"n1820938533":{"id":"n1820938533","loc":[-85.1509089,42.0611298]},"n1820938534":{"id":"n1820938534","loc":[-85.1108249,42.086321]},"n1820938535":{"id":"n1820938535","loc":[-85.1260344,42.0740687]},"n1820938536":{"id":"n1820938536","loc":[-85.4561228,42.0042791]},"n1820938537":{"id":"n1820938537","loc":[-85.2805082,41.9945761]},"n1820938538":{"id":"n1820938538","loc":[-85.273352,41.9981921]},"n1820938539":{"id":"n1820938539","loc":[-85.1084216,42.0864364]},"n1820938540":{"id":"n1820938540","loc":[-85.5009737,41.9773637]},"n1820938541":{"id":"n1820938541","loc":[-85.3960843,42.0051879]},"n1820938542":{"id":"n1820938542","loc":[-85.3425088,41.9865034]},"n1820938545":{"id":"n1820938545","loc":[-84.9937907,42.0860849]},"n1820938546":{"id":"n1820938546","loc":[-85.1084176,42.086065]},"n1820938547":{"id":"n1820938547","loc":[-85.3492851,41.9924786]},"n1820938548":{"id":"n1820938548","loc":[-85.2512235,42.0101147]},"n1820938549":{"id":"n1820938549","loc":[-85.3717298,41.9979326]},"n1820938551":{"id":"n1820938551","loc":[-85.2573712,42.0064081]},"n1820938552":{"id":"n1820938552","loc":[-85.2514596,42.010139]},"n1820938553":{"id":"n1820938553","loc":[-85.416512,42.0088073]},"n1820938554":{"id":"n1820938554","loc":[-85.4365964,42.0061606]},"n1820938555":{"id":"n1820938555","loc":[-85.4552431,42.0057301]},"n1820938556":{"id":"n1820938556","loc":[-85.2916283,41.9778769]},"n1820938557":{"id":"n1820938557","loc":[-85.100709,42.0902968]},"n1820938558":{"id":"n1820938558","loc":[-85.4703064,41.9965771]},"n1820938559":{"id":"n1820938559","loc":[-85.3134722,41.9696134]},"n1820938560":{"id":"n1820938560","loc":[-85.4834213,41.9885768]},"n1820938561":{"id":"n1820938561","loc":[-85.2740641,41.9975236]},"n1820938562":{"id":"n1820938562","loc":[-85.148334,42.0623405]},"n1820938563":{"id":"n1820938563","loc":[-85.2358598,42.0263675]},"n1820938565":{"id":"n1820938565","loc":[-85.2902979,41.9790892]},"n1820938566":{"id":"n1820938566","loc":[-85.2528865,42.0112869]},"n1820938567":{"id":"n1820938567","loc":[-85.2595319,41.9973003]},"n1820938568":{"id":"n1820938568","loc":[-85.071151,42.105689]},"n1820938570":{"id":"n1820938570","loc":[-85.299278,41.9732188]},"n1820938571":{"id":"n1820938571","loc":[-85.0354669,42.1024771]},"n1820938583":{"id":"n1820938583","loc":[-85.3313937,41.972562]},"n1820938585":{"id":"n1820938585","loc":[-85.0756933,42.1058334]},"n1820938587":{"id":"n1820938587","loc":[-85.3130324,41.9694219]},"n1820938590":{"id":"n1820938590","loc":[-85.0934227,42.0931681]},"n1820938592":{"id":"n1820938592","loc":[-85.3517956,41.9922553]},"n1820938593":{"id":"n1820938593","loc":[-85.4023971,42.0065169]},"n1820938594":{"id":"n1820938594","loc":[-85.3506798,41.9925583]},"n1820938595":{"id":"n1820938595","loc":[-85.3673524,41.9971193]},"n1820938596":{"id":"n1820938596","loc":[-85.1073608,42.0853523]},"n1820938597":{"id":"n1820938597","loc":[-85.2976579,41.972477]},"n1820938598":{"id":"n1820938598","loc":[-85.5616517,41.9694295]},"n1820938599":{"id":"n1820938599","loc":[-85.3552074,41.9921915]},"n1820938600":{"id":"n1820938600","loc":[-85.4665126,41.9999953]},"n1820938601":{"id":"n1820938601","loc":[-85.2740695,41.9966226]},"n1820938602":{"id":"n1820938602","loc":[-85.279376,41.9886669]},"n1820938603":{"id":"n1820938603","loc":[-85.0771109,42.1040413]},"n1820938604":{"id":"n1820938604","loc":[-85.2636049,41.9977895]},"n1820938605":{"id":"n1820938605","loc":[-85.3762145,41.9976456]},"n1820938606":{"id":"n1820938606","loc":[-85.2321369,42.0289577]},"n1820938620":{"id":"n1820938620","loc":[-85.4947724,41.9776189]},"n1820938622":{"id":"n1820938622","loc":[-85.1547069,42.0622768]},"n1820938624":{"id":"n1820938624","loc":[-85.0005056,42.0880249]},"n1820938626":{"id":"n1820938626","loc":[-85.0735596,42.1059357]},"n1820938628":{"id":"n1820938628","loc":[-85.4665298,41.99932]},"n1820938629":{"id":"n1820938629","loc":[-85.434515,42.0065273]},"n1820938630":{"id":"n1820938630","loc":[-85.117462,42.0823823]},"n1820938631":{"id":"n1820938631","loc":[-85.0131777,42.0890707]},"n1820938632":{"id":"n1820938632","loc":[-85.0875326,42.0961934]},"n1820938634":{"id":"n1820938634","loc":[-85.6433839,41.9112042]},"n1820938635":{"id":"n1820938635","loc":[-85.1366181,42.064969]},"n1820938636":{"id":"n1820938636","loc":[-85.073109,42.1057925]},"n1820938638":{"id":"n1820938638","loc":[-85.161406,42.0632541]},"n1820938640":{"id":"n1820938640","loc":[-85.6343932,41.9188845]},"n1820938642":{"id":"n1820938642","loc":[-85.2500004,42.010306]},"n1820938644":{"id":"n1820938644","loc":[-85.291918,41.9753166]},"n1820938663":{"id":"n1820938663","loc":[-85.2841611,41.9916812]},"n1820938664":{"id":"n1820938664","loc":[-85.1052955,42.0868134]},"n1820938665":{"id":"n1820938665","loc":[-85.4606118,42.0005534]},"n1820938666":{"id":"n1820938666","loc":[-85.5672736,41.9642922]},"n1820938667":{"id":"n1820938667","loc":[-85.6348481,41.9316932]},"n1820938668":{"id":"n1820938668","loc":[-85.0224904,42.0909576]},"n1820938669":{"id":"n1820938669","loc":[-85.0133856,42.0899755]},"n1820938670":{"id":"n1820938670","loc":[-85.344779,41.991139]},"n1820938671":{"id":"n1820938671","loc":[-85.632874,41.9425313]},"n1820938673":{"id":"n1820938673","loc":[-85.4941501,41.9779698]},"n1820938675":{"id":"n1820938675","loc":[-85.0862559,42.0997519]},"n1820938676":{"id":"n1820938676","loc":[-85.0097874,42.0898032]},"n1820938678":{"id":"n1820938678","loc":[-84.9913553,42.0863675]},"n1820938680":{"id":"n1820938680","loc":[-85.0533666,42.1038315]},"n1820938682":{"id":"n1820938682","loc":[-85.2950294,41.9743914]},"n1820938684":{"id":"n1820938684","loc":[-85.2517385,42.0104499]},"n1820938686":{"id":"n1820938686","loc":[-85.0247971,42.0922514]},"n1820938688":{"id":"n1820938688","loc":[-85.0807037,42.1026017]},"n1820938690":{"id":"n1820938690","loc":[-85.52462,41.9722748]},"n1820938694":{"id":"n1820938694","loc":[-85.2586535,41.9988818]},"n1820938695":{"id":"n1820938695","loc":[-85.0931612,42.092948]},"n1820938697":{"id":"n1820938697","loc":[-85.2470822,42.016564]},"n1820938698":{"id":"n1820938698","loc":[-85.4143018,42.0075158]},"n1820938699":{"id":"n1820938699","loc":[-85.0771484,42.104487]},"n1820938700":{"id":"n1820938700","loc":[-85.0291208,42.0942775]},"n1820938701":{"id":"n1820938701","loc":[-85.6367964,41.9185971]},"n1820938702":{"id":"n1820938702","loc":[-85.085419,42.1010693]},"n1820938703":{"id":"n1820938703","loc":[-85.0583877,42.1040584]},"n1820938705":{"id":"n1820938705","loc":[-85.2573379,42.0003182]},"n1820938706":{"id":"n1820938706","loc":[-85.2655937,41.9981575]},"n1820938707":{"id":"n1820938707","loc":[-85.023181,42.0915758]},"n1820938708":{"id":"n1820938708","loc":[-85.2318687,42.0274674]},"n1820938709":{"id":"n1820938709","loc":[-85.1056389,42.0866184]},"n1820938710":{"id":"n1820938710","loc":[-85.5276265,41.9700978]},"n1820938711":{"id":"n1820938711","loc":[-85.0864128,42.0945761]},"n1820938712":{"id":"n1820938712","loc":[-84.9897071,42.0871888]},"n1820938714":{"id":"n1820938714","loc":[-85.1328845,42.0665611]},"n1820938715":{"id":"n1820938715","loc":[-85.0336537,42.0991377]},"n1820938716":{"id":"n1820938716","loc":[-85.087597,42.0986692]},"n1820938717":{"id":"n1820938717","loc":[-85.1241394,42.0761882]},"n1820938718":{"id":"n1820938718","loc":[-85.1176002,42.0847723]},"n1820938719":{"id":"n1820938719","loc":[-85.2423615,42.0216572]},"n1820938721":{"id":"n1820938721","loc":[-85.2196378,42.0387908]},"n1820938722":{"id":"n1820938722","loc":[-85.0164272,42.0890082]},"n1820938723":{"id":"n1820938723","loc":[-85.5917182,41.9451807]},"n1820938724":{"id":"n1820938724","loc":[-85.2458806,42.0086638]},"n1820938725":{"id":"n1820938725","loc":[-85.1264474,42.0740527]},"n1820938726":{"id":"n1820938726","loc":[-85.1961631,42.04738]},"n1820938727":{"id":"n1820938727","loc":[-85.2784643,41.9943648]},"n1820938728":{"id":"n1820938728","loc":[-85.2905554,41.9763216]},"n1820938729":{"id":"n1820938729","loc":[-85.2913386,41.9771511]},"n1820938730":{"id":"n1820938730","loc":[-85.0112519,42.0895683]},"n1820938732":{"id":"n1820938732","loc":[-85.4290261,42.0064531]},"n1820938733":{"id":"n1820938733","loc":[-85.3867073,42.0031629]},"n1820938734":{"id":"n1820938734","loc":[-85.4943647,41.9836005]},"n1820938735":{"id":"n1820938735","loc":[-85.4900303,41.9860728]},"n1820938736":{"id":"n1820938736","loc":[-85.0866153,42.0944539]},"n1820938737":{"id":"n1820938737","loc":[-85.0869532,42.0990911]},"n1820938738":{"id":"n1820938738","loc":[-85.6321659,41.9208851]},"n1820938739":{"id":"n1820938739","loc":[-85.5930485,41.9433453]},"n1820938740":{"id":"n1820938740","loc":[-85.0406851,42.102733]},"n1820938741":{"id":"n1820938741","loc":[-85.1051131,42.0869846]},"n1820938742":{"id":"n1820938742","loc":[-85.1377554,42.0648893]},"n1820938743":{"id":"n1820938743","loc":[-85.2795694,41.994604]},"n1820938745":{"id":"n1820938745","loc":[-85.4948153,41.9826594]},"n1820938746":{"id":"n1820938746","loc":[-85.4488916,42.0050923]},"n1820938747":{"id":"n1820938747","loc":[-85.1052526,42.0866144]},"n1820938748":{"id":"n1820938748","loc":[-85.1468749,42.0653991]},"n1820938749":{"id":"n1820938749","loc":[-85.0856886,42.1006104]},"n1820938750":{"id":"n1820938750","loc":[-85.2144022,42.0404004]},"n1820938751":{"id":"n1820938751","loc":[-85.277771,41.9907458]},"n1820938752":{"id":"n1820938752","loc":[-85.1474542,42.0636149]},"n1820938753":{"id":"n1820938753","loc":[-85.0820515,42.1028075]},"n1820938754":{"id":"n1820938754","loc":[-85.1122948,42.08525]},"n1820938756":{"id":"n1820938756","loc":[-85.0173352,42.0901933]},"n1820938757":{"id":"n1820938757","loc":[-85.2259721,42.0354018]},"n1820938758":{"id":"n1820938758","loc":[-85.0872389,42.0987795]},"n1820938759":{"id":"n1820938759","loc":[-85.2291436,42.031874]},"n1820938760":{"id":"n1820938760","loc":[-85.3802485,42.0016002]},"n1820938761":{"id":"n1820938761","loc":[-85.3945822,42.0057938]},"n1820938762":{"id":"n1820938762","loc":[-85.5273237,41.9713017]},"n1820938763":{"id":"n1820938763","loc":[-85.2868862,41.9798629]},"n1820938764":{"id":"n1820938764","loc":[-85.2516677,42.0107899]},"n1820938766":{"id":"n1820938766","loc":[-85.3183002,41.9693103]},"n1820938768":{"id":"n1820938768","loc":[-85.2159042,42.0401932]},"n1820938770":{"id":"n1820938770","loc":[-85.0094481,42.0911141]},"n1820938771":{"id":"n1820938771","loc":[-85.0244538,42.0922155]},"n1820938772":{"id":"n1820938772","loc":[-85.231697,42.028862]},"n1820938773":{"id":"n1820938773","loc":[-85.2102394,42.0390617]},"n1820938774":{"id":"n1820938774","loc":[-85.2463419,42.0151212]},"n1820938775":{"id":"n1820938775","loc":[-85.0726195,42.1056424]},"n1820938776":{"id":"n1820938776","loc":[-85.0060431,42.0883262]},"n1820938778":{"id":"n1820938778","loc":[-85.425889,42.0056982]},"n1820938779":{"id":"n1820938779","loc":[-85.1183042,42.0820638]},"n1820938780":{"id":"n1820938780","loc":[-85.441596,42.0058257]},"n1820938781":{"id":"n1820938781","loc":[-85.1124879,42.0847086]},"n1820938782":{"id":"n1820938782","loc":[-85.2452733,42.0153894]},"n1820938783":{"id":"n1820938783","loc":[-85.2741191,41.9969244]},"n1820938784":{"id":"n1820938784","loc":[-85.2829487,41.9822236]},"n1820938785":{"id":"n1820938785","loc":[-85.3202743,41.972142]},"n1820938786":{"id":"n1820938786","loc":[-85.2345402,42.0266465]},"n1820938787":{"id":"n1820938787","loc":[-85.3037626,41.9724611]},"n1820938789":{"id":"n1820938789","loc":[-85.2474792,42.0161973]},"n1820938790":{"id":"n1820938790","loc":[-85.2951045,41.9727323]},"n1820938791":{"id":"n1820938791","loc":[-85.322345,41.9712726]},"n1820938792":{"id":"n1820938792","loc":[-85.2402372,42.0110394]},"n1820938793":{"id":"n1820938793","loc":[-85.5135693,41.9698659]},"n1820938794":{"id":"n1820938794","loc":[-85.4695339,41.9967366]},"n1820938796":{"id":"n1820938796","loc":[-85.0418492,42.1011131]},"n1820938797":{"id":"n1820938797","loc":[-85.3334107,41.9806337]},"n1820938798":{"id":"n1820938798","loc":[-85.5625314,41.9711685]},"n1820938799":{"id":"n1820938799","loc":[-85.3755707,41.9973585]},"n1820938800":{"id":"n1820938800","loc":[-85.5227532,41.9722429]},"n1820938801":{"id":"n1820938801","loc":[-85.4267687,42.0052836]},"n1820938803":{"id":"n1820938803","loc":[-85.0284704,42.0940837]},"n1820938804":{"id":"n1820938804","loc":[-85.015585,42.0885305]},"n1820938805":{"id":"n1820938805","loc":[-85.0765905,42.1053865]},"n1820938806":{"id":"n1820938806","loc":[-85.2614953,41.9964551]},"n1820938808":{"id":"n1820938808","loc":[-85.0307355,42.0947313]},"n1820938810":{"id":"n1820938810","loc":[-85.3894753,42.0003565]},"n1820938812":{"id":"n1820938812","loc":[-85.0868848,42.095006]},"n1820938813":{"id":"n1820938813","loc":[-85.3854198,42.0009465]},"n1820938814":{"id":"n1820938814","loc":[-85.2659692,41.9993534]},"n1820938815":{"id":"n1820938815","loc":[-85.1234259,42.0765266]},"n1820938816":{"id":"n1820938816","loc":[-85.1426906,42.0648893]},"n1820938818":{"id":"n1820938818","loc":[-85.1014533,42.0893067]},"n1820938819":{"id":"n1820938819","loc":[-85.0883064,42.098067]},"n1820938820":{"id":"n1820938820","loc":[-85.0503156,42.102704]},"n1820938821":{"id":"n1820938821","loc":[-85.1179649,42.0821884]},"n1820938822":{"id":"n1820938822","loc":[-85.3484697,41.9921596]},"n1820938823":{"id":"n1820938823","loc":[-85.3732962,41.9970874]},"n1820938824":{"id":"n1820938824","loc":[-85.2784104,41.9898312]},"n1820938825":{"id":"n1820938825","loc":[-85.4441709,42.0052198]},"n1820938826":{"id":"n1820938826","loc":[-85.3925438,42.0038326]},"n1820938829":{"id":"n1820938829","loc":[-85.5717582,41.9621861]},"n1820938830":{"id":"n1820938830","loc":[-85.0866314,42.0995051]},"n1820938831":{"id":"n1820938831","loc":[-85.576672,41.9522769]},"n1820938832":{"id":"n1820938832","loc":[-85.1587238,42.0636205]},"n1820938833":{"id":"n1820938833","loc":[-85.3804245,41.9999155]},"n1820938834":{"id":"n1820938834","loc":[-85.280083,41.9948843]},"n1820938836":{"id":"n1820938836","loc":[-85.561892,41.9686693]},"n1820938837":{"id":"n1820938837","loc":[-85.0158975,42.0885253]},"n1820938838":{"id":"n1820938838","loc":[-85.4248204,42.007633]},"n1820938839":{"id":"n1820938839","loc":[-85.0352738,42.1039657]},"n1820938840":{"id":"n1820938840","loc":[-85.211956,42.0411812]},"n1820938841":{"id":"n1820938841","loc":[-85.4816575,41.9908997]},"n1820938842":{"id":"n1820938842","loc":[-85.3807635,42.0020308]},"n1820938843":{"id":"n1820938843","loc":[-85.0100865,42.0898521]},"n1820938844":{"id":"n1820938844","loc":[-85.0103936,42.0897434]},"n1820938848":{"id":"n1820938848","loc":[-85.2430052,42.0131363]},"n1820938849":{"id":"n1820938849","loc":[-85.112559,42.0853723]},"n1820938851":{"id":"n1820938851","loc":[-85.3641553,41.9952535]},"n1820938852":{"id":"n1820938852","loc":[-85.2087373,42.0390777]},"n1820938853":{"id":"n1820938853","loc":[-85.2473933,42.0148263]},"n1820938854":{"id":"n1820938854","loc":[-85.0213464,42.090509]},"n1820938855":{"id":"n1820938855","loc":[-85.0673208,42.1052353]},"n1820938856":{"id":"n1820938856","loc":[-85.1003053,42.0905528]},"n1820938857":{"id":"n1820938857","loc":[-85.2617367,41.9965389]},"n1820938858":{"id":"n1820938858","loc":[-85.280363,41.9916015]},"n1820938859":{"id":"n1820938859","loc":[-85.0038866,42.0873469]},"n1820938860":{"id":"n1820938860","loc":[-85.2476401,42.0151451]},"n1820938861":{"id":"n1820938861","loc":[-85.193717,42.0499294]},"n1820938862":{"id":"n1820938862","loc":[-85.3478689,41.9917609]},"n1820938863":{"id":"n1820938863","loc":[-85.5638017,41.9648881]},"n1820938864":{"id":"n1820938864","loc":[-85.4356308,42.0064476]},"n1820938865":{"id":"n1820938865","loc":[-85.0561722,42.1023509]},"n1820938867":{"id":"n1820938867","loc":[-85.2256031,42.0356034]},"n1820938868":{"id":"n1820938868","loc":[-85.6102576,41.9420844]},"n1820938869":{"id":"n1820938869","loc":[-85.2285213,42.0339938]},"n1820938870":{"id":"n1820938870","loc":[-85.0326238,42.0978003]},"n1820938871":{"id":"n1820938871","loc":[-85.0131389,42.0903736]},"n1820938872":{"id":"n1820938872","loc":[-85.2550859,42.0012259]},"n1820938873":{"id":"n1820938873","loc":[-85.1130029,42.0846966]},"n1820938874":{"id":"n1820938874","loc":[-85.1579041,42.06336]},"n1820938875":{"id":"n1820938875","loc":[-85.0430522,42.1020234]},"n1820938876":{"id":"n1820938876","loc":[-85.2786679,41.9865935]},"n1820938877":{"id":"n1820938877","loc":[-85.1221666,42.0788706]},"n1820938878":{"id":"n1820938878","loc":[-85.2554614,42.0103303]},"n1820938879":{"id":"n1820938879","loc":[-85.2349801,42.0265748]},"n1820938880":{"id":"n1820938880","loc":[-85.0997434,42.0907864]},"n1820938881":{"id":"n1820938881","loc":[-85.0045464,42.0878167]},"n1820938882":{"id":"n1820938882","loc":[-85.2728048,41.9982519]},"n1820938883":{"id":"n1820938883","loc":[-85.3111333,41.9691587]},"n1820938884":{"id":"n1820938884","loc":[-85.3219802,41.9721899]},"n1820938885":{"id":"n1820938885","loc":[-85.3091378,41.9699325]},"n1820938887":{"id":"n1820938887","loc":[-85.4242367,42.0085203]},"n1820938888":{"id":"n1820938888","loc":[-84.9968377,42.0874504]},"n1820938890":{"id":"n1820938890","loc":[-85.5443139,41.9714078]},"n1820938891":{"id":"n1820938891","loc":[-85.6404013,41.9154676]},"n1820938892":{"id":"n1820938892","loc":[-85.3644986,41.9962582]},"n1820938893":{"id":"n1820938893","loc":[-85.0496772,42.1018323]},"n1820938894":{"id":"n1820938894","loc":[-85.297261,41.9737373]},"n1820938895":{"id":"n1820938895","loc":[-85.0327096,42.098071]},"n1820938896":{"id":"n1820938896","loc":[-85.3856773,41.9996867]},"n1820938897":{"id":"n1820938897","loc":[-85.0493862,42.1015509]},"n1820938898":{"id":"n1820938898","loc":[-84.9969879,42.0876614]},"n1820938899":{"id":"n1820938899","loc":[-85.0848625,42.1013587]},"n1820938900":{"id":"n1820938900","loc":[-85.5853195,41.9479201]},"n1820938901":{"id":"n1820938901","loc":[-85.6329169,41.9387964]},"n1820938902":{"id":"n1820938902","loc":[-85.0843046,42.1029468]},"n1820938903":{"id":"n1820938903","loc":[-85.1228747,42.0778474]},"n1820938904":{"id":"n1820938904","loc":[-85.4855456,41.984095]},"n1820938905":{"id":"n1820938905","loc":[-85.0573269,42.1026801]},"n1820938906":{"id":"n1820938906","loc":[-85.2425868,42.0131523]},"n1820938907":{"id":"n1820938907","loc":[-85.1149622,42.0860053]},"n1820938908":{"id":"n1820938908","loc":[-85.4833097,41.9951578]},"n1820938909":{"id":"n1820938909","loc":[-85.075979,42.1056372]},"n1820938910":{"id":"n1820938910","loc":[-85.0338509,42.0977139]},"n1820938911":{"id":"n1820938911","loc":[-85.6384272,41.9115715]},"n1820938912":{"id":"n1820938912","loc":[-85.0458363,42.1004074]},"n1820938913":{"id":"n1820938913","loc":[-85.0592138,42.1048305]},"n1820938914":{"id":"n1820938914","loc":[-85.2807493,41.9916653]},"n1820938915":{"id":"n1820938915","loc":[-85.1103274,42.0864193]},"n1820938916":{"id":"n1820938916","loc":[-85.6267156,41.9404404]},"n1820938918":{"id":"n1820938918","loc":[-85.0331374,42.0982911]},"n1820938919":{"id":"n1820938919","loc":[-85.5637331,41.965409]},"n1820938920":{"id":"n1820938920","loc":[-85.5457515,41.9714237]},"n1820938922":{"id":"n1820938922","loc":[-85.082073,42.1030104]},"n1820938923":{"id":"n1820938923","loc":[-85.0780765,42.103102]},"n1820938924":{"id":"n1820938924","loc":[-85.4208035,42.0089508]},"n1820938925":{"id":"n1820938925","loc":[-85.3469934,41.9914795]},"n1820938926":{"id":"n1820938926","loc":[-85.0322,42.095619]},"n1820938927":{"id":"n1820938927","loc":[-85.4784431,41.9949401]},"n1820938928":{"id":"n1820938928","loc":[-85.1303095,42.0667523]},"n1820938929":{"id":"n1820938929","loc":[-85.2463784,42.0084781]},"n1820938930":{"id":"n1820938930","loc":[-85.6299986,41.9427707]},"n1820938931":{"id":"n1820938931","loc":[-85.6325907,41.9238499]},"n1820938932":{"id":"n1820938932","loc":[-85.4808464,41.9914476]},"n1820938934":{"id":"n1820938934","loc":[-85.2411599,42.0105292]},"n1820938935":{"id":"n1820938935","loc":[-85.0163213,42.0892379]},"n1820938936":{"id":"n1820938936","loc":[-85.3290934,41.9682322]},"n1820938937":{"id":"n1820938937","loc":[-85.4925623,41.9853231]},"n1820938938":{"id":"n1820938938","loc":[-85.0338294,42.09892]},"n1820938940":{"id":"n1820938940","loc":[-85.4174561,42.008903]},"n1820938941":{"id":"n1820938941","loc":[-85.1165595,42.0838845]},"n1820938942":{"id":"n1820938942","loc":[-85.2954585,41.9717192]},"n1820938943":{"id":"n1820938943","loc":[-85.6330199,41.9257338]},"n1820938944":{"id":"n1820938944","loc":[-85.2294654,42.0324478]},"n1820938945":{"id":"n1820938945","loc":[-85.5601282,41.9728914]},"n1820938946":{"id":"n1820938946","loc":[-85.1176324,42.08568]},"n1820938947":{"id":"n1820938947","loc":[-85.0210245,42.0906005]},"n1820938948":{"id":"n1820938948","loc":[-85.0251887,42.09253]},"n1820938949":{"id":"n1820938949","loc":[-85.0895832,42.0939551]},"n1820938950":{"id":"n1820938950","loc":[-84.9915109,42.085842]},"n1820938951":{"id":"n1820938951","loc":[-85.2187366,42.0393486]},"n1820938952":{"id":"n1820938952","loc":[-85.006605,42.087579]},"n1820938953":{"id":"n1820938953","loc":[-85.046641,42.1012393]},"n1820938954":{"id":"n1820938954","loc":[-85.052102,42.103695]},"n1820938955":{"id":"n1820938955","loc":[-85.283925,41.9912825]},"n1820938956":{"id":"n1820938956","loc":[-85.2326626,42.0316349]},"n1820938957":{"id":"n1820938957","loc":[-85.1174298,42.0859694]},"n1820938958":{"id":"n1820938958","loc":[-85.3802056,41.9994794]},"n1820938959":{"id":"n1820938959","loc":[-85.4586334,41.9999737]},"n1820938960":{"id":"n1820938960","loc":[-85.4302234,42.0069418]},"n1820938961":{"id":"n1820938961","loc":[-85.092201,42.0930674]},"n1820938962":{"id":"n1820938962","loc":[-85.3684511,41.9979382]},"n1820938963":{"id":"n1820938963","loc":[-85.4618735,42.0011856]},"n1820938964":{"id":"n1820938964","loc":[-85.4828205,41.9877793]},"n1820938965":{"id":"n1820938965","loc":[-85.0837789,42.1025726]},"n1820938966":{"id":"n1820938966","loc":[-85.0176195,42.090253]},"n1820938967":{"id":"n1820938967","loc":[-85.3801627,42.001074]},"n1820938968":{"id":"n1820938968","loc":[-85.4767007,41.994488]},"n1820938969":{"id":"n1820938969","loc":[-85.274268,41.9957495]},"n1820938970":{"id":"n1820938970","loc":[-85.2977438,41.9719506]},"n1820938971":{"id":"n1820938971","loc":[-85.2425546,42.0208682]},"n1820938972":{"id":"n1820938972","loc":[-85.2557082,42.002382]},"n1820938973":{"id":"n1820938973","loc":[-85.3187937,41.9691986]},"n1820938975":{"id":"n1820938975","loc":[-85.2448077,42.0153045]},"n1820938977":{"id":"n1820938977","loc":[-85.0343015,42.0997718]},"n1820938978":{"id":"n1820938978","loc":[-85.2449364,42.01874]},"n1820938979":{"id":"n1820938979","loc":[-85.2598391,41.9969602]},"n1820938980":{"id":"n1820938980","loc":[-85.4294724,42.0067665]},"n1820938981":{"id":"n1820938981","loc":[-85.428082,42.0055124]},"n1820938983":{"id":"n1820938983","loc":[-85.5436315,41.9717484]},"n1820938985":{"id":"n1820938985","loc":[-85.5978336,41.9407437]},"n1820938986":{"id":"n1820938986","loc":[-85.491661,41.9860249]},"n1820938987":{"id":"n1820938987","loc":[-85.4942789,41.9801392]},"n1820938988":{"id":"n1820938988","loc":[-85.0416306,42.1010841]},"n1820938989":{"id":"n1820938989","loc":[-85.2653644,41.9984433]},"n1820938990":{"id":"n1820938990","loc":[-85.1028266,42.0881124]},"n1820938991":{"id":"n1820938991","loc":[-85.0163146,42.0887932]},"n1820938992":{"id":"n1820938992","loc":[-85.5282209,41.9678112]},"n1820938993":{"id":"n1820938993","loc":[-85.5442752,41.9715888]},"n1820938994":{"id":"n1820938994","loc":[-85.5634327,41.9658558]},"n1820938995":{"id":"n1820938995","loc":[-85.0384227,42.1037627]},"n1820938996":{"id":"n1820938996","loc":[-85.1144258,42.0854439]},"n1820938997":{"id":"n1820938997","loc":[-85.1870651,42.0506305]},"n1820938998":{"id":"n1820938998","loc":[-85.1256159,42.0747376]},"n1820938999":{"id":"n1820938999","loc":[-85.3272695,41.9715836]},"n1820939000":{"id":"n1820939000","loc":[-85.0543067,42.103098]},"n1820939001":{"id":"n1820939001","loc":[-85.4678173,41.9973585]},"n1820939003":{"id":"n1820939003","loc":[-85.0266626,42.0933154]},"n1820939004":{"id":"n1820939004","loc":[-85.0353046,42.1019728]},"n1820939005":{"id":"n1820939005","loc":[-85.1237961,42.0762798]},"n1820939006":{"id":"n1820939006","loc":[-85.2812214,41.9826702]},"n1820939007":{"id":"n1820939007","loc":[-85.2927763,41.9747343]},"n1820939008":{"id":"n1820939008","loc":[-85.3270979,41.9720862]},"n1820939009":{"id":"n1820939009","loc":[-85.488657,41.9856581]},"n1820939010":{"id":"n1820939010","loc":[-85.3087301,41.9701399]},"n1820939011":{"id":"n1820939011","loc":[-85.0276939,42.093768]},"n1820939012":{"id":"n1820939012","loc":[-85.2956516,41.9748779]},"n1820939013":{"id":"n1820939013","loc":[-85.1298579,42.0726443]},"n1820939014":{"id":"n1820939014","loc":[-85.105144,42.0870893]},"n1820939015":{"id":"n1820939015","loc":[-85.0677486,42.1053917]},"n1820939016":{"id":"n1820939016","loc":[-85.0333681,42.0993459]},"n1820939017":{"id":"n1820939017","loc":[-85.6384272,41.910805]},"n1820939018":{"id":"n1820939018","loc":[-85.399496,42.006894]},"n1820939019":{"id":"n1820939019","loc":[-85.2648427,41.9998318]},"n1820939020":{"id":"n1820939020","loc":[-85.1237424,42.0766779]},"n1820939021":{"id":"n1820939021","loc":[-85.2515025,42.0109442]},"n1820939022":{"id":"n1820939022","loc":[-85.5566306,41.9718385]},"n1820939023":{"id":"n1820939023","loc":[-85.090644,42.0938369]},"n1820939024":{"id":"n1820939024","loc":[-85.1245525,42.074914]},"n1820939025":{"id":"n1820939025","loc":[-85.1099934,42.0863926]},"n1820939026":{"id":"n1820939026","loc":[-85.1251653,42.0744589]},"n1820939027":{"id":"n1820939027","loc":[-85.401792,42.0068143]},"n1820939028":{"id":"n1820939028","loc":[-85.0094763,42.0899584]},"n1820939029":{"id":"n1820939029","loc":[-85.1330779,42.0705605]},"n1820939030":{"id":"n1820939030","loc":[-85.4935064,41.984398]},"n1820939031":{"id":"n1820939031","loc":[-85.5713334,41.9613939]},"n1820939032":{"id":"n1820939032","loc":[-85.0873945,42.0964669]},"n1820939033":{"id":"n1820939033","loc":[-85.0886497,42.0986481]},"n1820939034":{"id":"n1820939034","loc":[-85.3276343,41.9758897]},"n1820939035":{"id":"n1820939035","loc":[-85.1304386,42.0727387]},"n1820939036":{"id":"n1820939036","loc":[-85.2551932,42.0052999]},"n1820939037":{"id":"n1820939037","loc":[-85.2206936,42.0384458]},"n1820939038":{"id":"n1820939038","loc":[-85.2313645,42.0286389]},"n1820939039":{"id":"n1820939039","loc":[-85.0754586,42.1059835]},"n1820939040":{"id":"n1820939040","loc":[-85.0663324,42.1050812]},"n1820939041":{"id":"n1820939041","loc":[-85.2406234,42.0106887]},"n1820939042":{"id":"n1820939042","loc":[-85.0685962,42.1058175]},"n1820939043":{"id":"n1820939043","loc":[-85.0689462,42.1059437]},"n1820939044":{"id":"n1820939044","loc":[-85.0586144,42.1046144]},"n1820939045":{"id":"n1820939045","loc":[-85.3650565,41.9965452]},"n1820939047":{"id":"n1820939047","loc":[-85.5752558,41.9536014]},"n1820939048":{"id":"n1820939048","loc":[-85.5110159,41.9710624]},"n1820939050":{"id":"n1820939050","loc":[-85.2832641,41.9926477]},"n1820939051":{"id":"n1820939051","loc":[-85.0078402,42.0898947]},"n1820939052":{"id":"n1820939052","loc":[-85.3882737,42.0017916]},"n1820939053":{"id":"n1820939053","loc":[-85.1718945,42.0564937]},"n1820939054":{"id":"n1820939054","loc":[-85.0947048,42.0929293]},"n1820939055":{"id":"n1820939055","loc":[-85.4456944,42.0051082]},"n1820939056":{"id":"n1820939056","loc":[-85.3139872,41.9706903]},"n1820939057":{"id":"n1820939057","loc":[-85.3893895,42.0034021]},"n1820939058":{"id":"n1820939058","loc":[-85.2425332,42.0106089]},"n1820939059":{"id":"n1820939059","loc":[-85.6085624,41.9420844]},"n1820939060":{"id":"n1820939060","loc":[-85.210411,42.0397789]},"n1820939061":{"id":"n1820939061","loc":[-85.2762542,41.9960473]},"n1820939062":{"id":"n1820939062","loc":[-85.4686584,41.9969973]},"n1820939063":{"id":"n1820939063","loc":[-85.3860421,42.0018394]},"n1820939064":{"id":"n1820939064","loc":[-85.5636944,41.9644414]},"n1820939065":{"id":"n1820939065","loc":[-85.3267331,41.9766554]},"n1820939066":{"id":"n1820939066","loc":[-85.0868996,42.0943822]},"n1820939067":{"id":"n1820939067","loc":[-85.104861,42.0880038]},"n1820939068":{"id":"n1820939068","loc":[-85.5537123,41.9695093]},"n1820939069":{"id":"n1820939069","loc":[-85.6325092,41.9396743]},"n1820939070":{"id":"n1820939070","loc":[-85.3869648,42.0024454]},"n1820939071":{"id":"n1820939071","loc":[-85.2775349,41.9957335]},"n1820939072":{"id":"n1820939072","loc":[-85.2055616,42.0421533]},"n1820939073":{"id":"n1820939073","loc":[-85.4731431,41.9946531]},"n1820939074":{"id":"n1820939074","loc":[-85.0399609,42.1030833]},"n1820939075":{"id":"n1820939075","loc":[-85.3055758,41.9725169]},"n1820939076":{"id":"n1820939076","loc":[-85.4834599,41.994488]},"n1820939077":{"id":"n1820939077","loc":[-85.3819866,42.0023018]},"n1820939078":{"id":"n1820939078","loc":[-85.1218756,42.0789992]},"n1820939079":{"id":"n1820939079","loc":[-85.2793159,41.9944458]},"n1820939080":{"id":"n1820939080","loc":[-85.2495498,42.0101466]},"n1820939081":{"id":"n1820939081","loc":[-85.0035969,42.0872434]},"n1820939082":{"id":"n1820939082","loc":[-85.1054243,42.0865626]},"n1820939083":{"id":"n1820939083","loc":[-85.0917665,42.0934774]},"n1820939084":{"id":"n1820939084","loc":[-85.3442211,41.988938]},"n1820939086":{"id":"n1820939086","loc":[-85.273989,41.9953588]},"n1820939087":{"id":"n1820939087","loc":[-85.1142541,42.0852488]},"n1820939089":{"id":"n1820939089","loc":[-85.1526684,42.0615758]},"n1820939090":{"id":"n1820939090","loc":[-85.2538843,42.0110159]},"n1820939091":{"id":"n1820939091","loc":[-85.28341,41.9909635]},"n1820939092":{"id":"n1820939092","loc":[-85.3963178,42.0050217]},"n1820939093":{"id":"n1820939093","loc":[-85.0851682,42.1012472]},"n1820939095":{"id":"n1820939095","loc":[-85.2811784,41.986243]},"n1820939096":{"id":"n1820939096","loc":[-85.4274125,42.0052995]},"n1820939097":{"id":"n1820939097","loc":[-85.0871262,42.0951652]},"n1820939099":{"id":"n1820939099","loc":[-85.1314253,42.0671665]},"n1820939100":{"id":"n1820939100","loc":[-85.2778997,41.991001]},"n1820939101":{"id":"n1820939101","loc":[-85.112107,42.0862812]},"n1820939102":{"id":"n1820939102","loc":[-85.299911,41.9729955]},"n1820939103":{"id":"n1820939103","loc":[-85.639822,41.9094796]},"n1820939104":{"id":"n1820939104","loc":[-85.122294,42.0785334]},"n1820939105":{"id":"n1820939105","loc":[-85.2476294,42.015719]},"n1820939106":{"id":"n1820939106","loc":[-85.4946007,41.9814631]},"n1820939107":{"id":"n1820939107","loc":[-85.0879524,42.0986919]},"n1820939108":{"id":"n1820939108","loc":[-85.0342814,42.098274]},"n1820939109":{"id":"n1820939109","loc":[-85.2450695,42.0095463]},"n1820939110":{"id":"n1820939110","loc":[-85.3847546,42.0024135]},"n1820939111":{"id":"n1820939111","loc":[-85.2961344,41.9742558]},"n1820939112":{"id":"n1820939112","loc":[-85.27899,41.994317]},"n1820939114":{"id":"n1820939114","loc":[-85.1017644,42.0886618]},"n1820939115":{"id":"n1820939115","loc":[-85.076215,42.1056333]},"n1820939116":{"id":"n1820939116","loc":[-85.1198009,42.0805349]},"n1820939117":{"id":"n1820939117","loc":[-85.11988,42.0798513]},"n1820939118":{"id":"n1820939118","loc":[-85.147819,42.0625476]},"n1820939119":{"id":"n1820939119","loc":[-85.0585969,42.1029042]},"n1820939120":{"id":"n1820939120","loc":[-85.1248596,42.0745744]},"n1820939121":{"id":"n1820939121","loc":[-85.3023786,41.9725249]},"n1820939123":{"id":"n1820939123","loc":[-85.0119332,42.0900699]},"n1820939124":{"id":"n1820939124","loc":[-85.2466852,42.0170343]},"n1820939125":{"id":"n1820939125","loc":[-85.0033019,42.0872792]},"n1820939126":{"id":"n1820939126","loc":[-85.0042084,42.0875778]},"n1820939128":{"id":"n1820939128","loc":[-85.0052961,42.0885424]},"n1820939130":{"id":"n1820939130","loc":[-85.0647942,42.10508]},"n1820939131":{"id":"n1820939131","loc":[-85.2824123,41.9825107]},"n1820939132":{"id":"n1820939132","loc":[-85.3210039,41.9723255]},"n1820939133":{"id":"n1820939133","loc":[-85.0491033,42.1014184]},"n1820939134":{"id":"n1820939134","loc":[-85.1127776,42.0855168]},"n1820939135":{"id":"n1820939135","loc":[-85.1243768,42.0759322]},"n1820939137":{"id":"n1820939137","loc":[-85.125974,42.0747547]},"n1820939138":{"id":"n1820939138","loc":[-85.1071248,42.0859973]},"n1820939139":{"id":"n1820939139","loc":[-85.5326175,41.9674833]},"n1820939140":{"id":"n1820939140","loc":[-85.1338715,42.0660833]},"n1820939142":{"id":"n1820939142","loc":[-85.649671,41.9135675]},"n1820939144":{"id":"n1820939144","loc":[-85.0236545,42.0920444]},"n1820939145":{"id":"n1820939145","loc":[-85.1084391,42.0859376]},"n1820939146":{"id":"n1820939146","loc":[-85.1539988,42.0618626]},"n1820939147":{"id":"n1820939147","loc":[-85.2354521,42.026511]},"n1820939148":{"id":"n1820939148","loc":[-85.2362246,42.0260408]},"n1820939149":{"id":"n1820939149","loc":[-85.2401342,42.0115233]},"n1820939150":{"id":"n1820939150","loc":[-85.295319,41.9747423]},"n1820939151":{"id":"n1820939151","loc":[-85.1164696,42.0835409]},"n1820939152":{"id":"n1820939152","loc":[-85.3232891,41.9712885]},"n1820939153":{"id":"n1820939153","loc":[-85.2574463,42.0068944]},"n1820939155":{"id":"n1820939155","loc":[-85.5704064,41.9598246]},"n1820939156":{"id":"n1820939156","loc":[-85.0349077,42.0998116]},"n1820939157":{"id":"n1820939157","loc":[-85.0949529,42.0925619]},"n1820939159":{"id":"n1820939159","loc":[-85.0179829,42.0902343]},"n1820939160":{"id":"n1820939160","loc":[-85.0405832,42.1016942]},"n1820939161":{"id":"n1820939161","loc":[-85.2534015,42.0111833]},"n1820939162":{"id":"n1820939162","loc":[-85.0839881,42.102708]},"n1820939163":{"id":"n1820939163","loc":[-85.0341996,42.1008385]},"n1820939164":{"id":"n1820939164","loc":[-85.1037761,42.0879731]},"n1820939173":{"id":"n1820939173","loc":[-85.0460616,42.1005786]},"n1820939177":{"id":"n1820939177","loc":[-85.0061651,42.0878059]},"n1820939181":{"id":"n1820939181","loc":[-85.1456775,42.0654684]},"n1820939183":{"id":"n1820939183","loc":[-85.1325508,42.0718439]},"n1820939185":{"id":"n1820939185","loc":[-85.2485842,42.008329]},"n1820939187":{"id":"n1820939187","loc":[-85.2744128,41.9949322]},"n1820939189":{"id":"n1820939189","loc":[-85.2579025,41.9999542]},"n1820939191":{"id":"n1820939191","loc":[-85.3358998,41.9828987]},"n1820939193":{"id":"n1820939193","loc":[-85.3192658,41.9716714]},"n1820939194":{"id":"n1820939194","loc":[-85.6400795,41.9130725]},"n1820939195":{"id":"n1820939195","loc":[-85.3278489,41.9780591]},"n1820939196":{"id":"n1820939196","loc":[-85.2800197,41.983061]},"n1820939197":{"id":"n1820939197","loc":[-85.3278167,41.9692943]},"n1820939198":{"id":"n1820939198","loc":[-85.3366894,41.9838653]},"n1820939199":{"id":"n1820939199","loc":[-85.0328383,42.0969923]},"n1820939201":{"id":"n1820939201","loc":[-85.3259284,41.9720383]},"n1820939217":{"id":"n1820939217","loc":[-85.1840181,42.0503277]},"n1820939220":{"id":"n1820939220","loc":[-85.422563,42.0089986]},"n1820939222":{"id":"n1820939222","loc":[-85.555386,41.9707856]},"n1820939224":{"id":"n1820939224","loc":[-85.3830809,42.002254]},"n1820939226":{"id":"n1820939226","loc":[-84.9917938,42.0857517]},"n1820939227":{"id":"n1820939227","loc":[-85.2936775,41.9740484]},"n1820939228":{"id":"n1820939228","loc":[-85.2632133,41.9975024]},"n1820939229":{"id":"n1820939229","loc":[-85.2809424,41.9853259]},"n1820939230":{"id":"n1820939230","loc":[-85.242104,42.0131204]},"n1820939232":{"id":"n1820939232","loc":[-85.2610246,41.9963901]},"n1820939233":{"id":"n1820939233","loc":[-85.2335531,42.0268378]},"n1820939234":{"id":"n1820939234","loc":[-85.3188839,41.9713575]},"n1820939235":{"id":"n1820939235","loc":[-85.2413637,42.0225658]},"n1820939237":{"id":"n1820939237","loc":[-85.0010796,42.0887215]},"n1820939239":{"id":"n1820939239","loc":[-85.2241697,42.0362624]},"n1820939243":{"id":"n1820939243","loc":[-85.0368456,42.1040134]},"n1820939244":{"id":"n1820939244","loc":[-85.1327986,42.069524]},"n1820939260":{"id":"n1820939260","loc":[-85.5408163,41.9711206]},"n1820939261":{"id":"n1820939261","loc":[-85.2959199,41.9746546]},"n1820939262":{"id":"n1820939262","loc":[-85.3298659,41.9683598]},"n1820939263":{"id":"n1820939263","loc":[-85.2240581,42.0358425]},"n1820939264":{"id":"n1820939264","loc":[-85.2438206,42.0101944]},"n1820939265":{"id":"n1820939265","loc":[-85.3984489,42.0059589]},"n1820939266":{"id":"n1820939266","loc":[-85.2330811,42.0294279]},"n1820939268":{"id":"n1820939268","loc":[-85.1126877,42.0857704]},"n1820939271":{"id":"n1820939271","loc":[-85.254925,42.0106253]},"n1820939273":{"id":"n1820939273","loc":[-85.4328046,42.0064662]},"n1820939277":{"id":"n1820939277","loc":[-85.289622,41.9789616]},"n1820939279":{"id":"n1820939279","loc":[-85.4574532,42.0004043]},"n1820939281":{"id":"n1820939281","loc":[-85.4803486,41.9867211]},"n1820939283":{"id":"n1820939283","loc":[-85.157475,42.0631848]},"n1820939285":{"id":"n1820939285","loc":[-85.2571458,42.0059935]},"n1820939287":{"id":"n1820939287","loc":[-85.2818544,41.9825984]},"n1820939289":{"id":"n1820939289","loc":[-85.2298302,42.0328781]},"n1820939291":{"id":"n1820939291","loc":[-85.4819523,41.984821]},"n1820939301":{"id":"n1820939301","loc":[-85.3139765,41.9701159]},"n1820939304":{"id":"n1820939304","loc":[-85.0424447,42.101742]},"n1820939306":{"id":"n1820939306","loc":[-85.6360283,41.9338482]},"n1820939310":{"id":"n1820939310","loc":[-85.3463025,41.9913622]},"n1820939312":{"id":"n1820939312","loc":[-85.4664869,41.9988097]},"n1820939314":{"id":"n1820939314","loc":[-85.149364,42.0622449]},"n1820939316":{"id":"n1820939316","loc":[-85.2460415,42.0153125]},"n1820939318":{"id":"n1820939318","loc":[-85.4806103,41.9924523]},"n1820939320":{"id":"n1820939320","loc":[-85.2449042,42.0190987]},"n1820939322":{"id":"n1820939322","loc":[-85.5280165,41.9689263]},"n1820939324":{"id":"n1820939324","loc":[-85.0051204,42.0882625]},"n1820939326":{"id":"n1820939326","loc":[-85.1240925,42.0771546]},"n1820939329":{"id":"n1820939329","loc":[-85.2261653,42.0342225]},"n1820939331":{"id":"n1820939331","loc":[-85.5259933,41.972211]},"n1820939333":{"id":"n1820939333","loc":[-85.0074754,42.0883183]},"n1820939335":{"id":"n1820939335","loc":[-85.0764014,42.1055549]},"n1820939336":{"id":"n1820939336","loc":[-85.2908773,41.9769597]},"n1820939337":{"id":"n1820939337","loc":[-85.4095382,42.0083449]},"n1820939346":{"id":"n1820939346","loc":[-85.2514166,42.0111753]},"n1820939348":{"id":"n1820939348","loc":[-85.0030377,42.0873799]},"n1820939350":{"id":"n1820939350","loc":[-85.3659362,41.9964974]},"n1820939352":{"id":"n1820939352","loc":[-85.226058,42.0348281]},"n1820939355":{"id":"n1820939355","loc":[-85.1902408,42.0507101]},"n1820939357":{"id":"n1820939357","loc":[-85.2781854,41.9946001]},"n1820939359":{"id":"n1820939359","loc":[-85.2139988,42.0405175]},"n1820939361":{"id":"n1820939361","loc":[-85.0086609,42.0908262]},"n1820939363":{"id":"n1820939363","loc":[-85.0627128,42.1043398]},"n1820939365":{"id":"n1820939365","loc":[-85.1311346,42.072501]},"n1820939369":{"id":"n1820939369","loc":[-85.248198,42.0082652]},"n1820939370":{"id":"n1820939370","loc":[-84.99792,42.087794]},"n1820939371":{"id":"n1820939371","loc":[-85.2786775,41.9942783]},"n1820939372":{"id":"n1820939372","loc":[-85.0342103,42.1013957]},"n1820939373":{"id":"n1820939373","loc":[-85.2022357,42.0444799]},"n1820939374":{"id":"n1820939374","loc":[-85.2279205,42.0337388]},"n1820939375":{"id":"n1820939375","loc":[-85.1337699,42.0712614]},"n1820939376":{"id":"n1820939376","loc":[-85.317517,41.9707062]},"n1820939377":{"id":"n1820939377","loc":[-85.1326326,42.070218]},"n1820939394":{"id":"n1820939394","loc":[-85.0197746,42.0899118]},"n1820939397":{"id":"n1820939397","loc":[-85.2590076,41.9984632]},"n1820939399":{"id":"n1820939399","loc":[-85.2469964,42.0083449]},"n1820939400":{"id":"n1820939400","loc":[-85.2470929,42.0146668]},"n1820939401":{"id":"n1820939401","loc":[-84.9984095,42.0878087]},"n1820939402":{"id":"n1820939402","loc":[-85.2372653,42.0243273]},"n1820939403":{"id":"n1820939403","loc":[-85.2454986,42.0091955]},"n1820939404":{"id":"n1820939404","loc":[-85.0539205,42.1035995]},"n1820939405":{"id":"n1820939405","loc":[-85.550601,41.9706101]},"n1820939406":{"id":"n1820939406","loc":[-85.0351343,42.0999656]},"n1820939407":{"id":"n1820939407","loc":[-85.0082908,42.0905755]},"n1820939408":{"id":"n1820939408","loc":[-85.0132904,42.0902251]},"n1820939410":{"id":"n1820939410","loc":[-85.0892546,42.094012]},"n1820939412":{"id":"n1820939412","loc":[-85.0350793,42.1030315]},"n1820939416":{"id":"n1820939416","loc":[-85.0012406,42.0886777]},"n1820939418":{"id":"n1820939418","loc":[-85.0577453,42.1029229]},"n1820939420":{"id":"n1820939420","loc":[-85.1230786,42.0776722]},"n1820939422":{"id":"n1820939422","loc":[-85.571136,41.9649304]},"n1820939436":{"id":"n1820939436","loc":[-85.1137968,42.0848997]},"n1820939437":{"id":"n1820939437","loc":[-85.3559584,41.9925105]},"n1820939438":{"id":"n1820939438","loc":[-85.0080172,42.0903565]},"n1820939439":{"id":"n1820939439","loc":[-85.0048897,42.0880913]},"n1820939441":{"id":"n1820939441","loc":[-85.0406959,42.1018574]},"n1820939443":{"id":"n1820939443","loc":[-85.3897328,42.0029078]},"n1820939445":{"id":"n1820939445","loc":[-85.122349,42.0782814]},"n1820939448":{"id":"n1820939448","loc":[-85.4872193,41.985036]},"n1820939450":{"id":"n1820939450","loc":[-85.0120459,42.0904919]},"n1820939452":{"id":"n1820939452","loc":[-85.6320543,41.921982]},"n1820939456":{"id":"n1820939456","loc":[-85.0844749,42.1036843]},"n1820939458":{"id":"n1820939458","loc":[-85.0968037,42.091296]},"n1820939463":{"id":"n1820939463","loc":[-85.5339747,41.9681841]},"n1820939465":{"id":"n1820939465","loc":[-85.4125423,42.0072129]},"n1820939467":{"id":"n1820939467","loc":[-85.6335563,41.9303626]},"n1820939469":{"id":"n1820939469","loc":[-85.2821014,41.9932126]},"n1820939471":{"id":"n1820939471","loc":[-85.374691,41.9969917]},"n1820939485":{"id":"n1820939485","loc":[-85.4471321,42.0049806]},"n1820939487":{"id":"n1820939487","loc":[-85.3752532,41.9972206]},"n1820939489":{"id":"n1820939489","loc":[-85.4517283,42.005927]},"n1820939492":{"id":"n1820939492","loc":[-85.4662552,42.0005693]},"n1820939494":{"id":"n1820939494","loc":[-85.0120083,42.0902928]},"n1820939496":{"id":"n1820939496","loc":[-85.044463,42.1004631]},"n1820939498":{"id":"n1820939498","loc":[-85.418293,42.0089667]},"n1820939500":{"id":"n1820939500","loc":[-85.0554762,42.1027358]},"n1820939504":{"id":"n1820939504","loc":[-85.1246289,42.0746858]},"n1820939507":{"id":"n1820939507","loc":[-85.0408139,42.1021838]},"n1820939508":{"id":"n1820939508","loc":[-85.1236204,42.0775169]},"n1820939509":{"id":"n1820939509","loc":[-85.0350109,42.1037428]},"n1820939510":{"id":"n1820939510","loc":[-85.0551583,42.1029878]},"n1820939511":{"id":"n1820939511","loc":[-85.0956771,42.0916662]},"n1820939512":{"id":"n1820939512","loc":[-85.2323408,42.0273638]},"n1820939513":{"id":"n1820939513","loc":[-85.1232771,42.0762388]},"n1820939531":{"id":"n1820939531","loc":[-85.264608,41.9997828]},"n1820939533":{"id":"n1820939533","loc":[-85.4198808,42.0087914]},"n1820939535":{"id":"n1820939535","loc":[-85.3080864,41.9715677]},"n1820939536":{"id":"n1820939536","loc":[-85.1189426,42.0812596]},"n1820939537":{"id":"n1820939537","loc":[-85.2642741,41.9996764]},"n1820939538":{"id":"n1820939538","loc":[-85.2572531,42.0079627]},"n1820939539":{"id":"n1820939539","loc":[-85.2907807,41.9790174]},"n1820939540":{"id":"n1820939540","loc":[-85.3171415,41.9707301]},"n1820939541":{"id":"n1820939541","loc":[-85.08777,42.0953841]},"n1820939542":{"id":"n1820939542","loc":[-85.1239262,42.0773218]},"n1820939543":{"id":"n1820939543","loc":[-84.9973956,42.0877968]},"n1820939544":{"id":"n1820939544","loc":[-85.011606,42.0896161]},"n1820939545":{"id":"n1820939545","loc":[-85.4077358,42.0082971]},"n1820939546":{"id":"n1820939546","loc":[-85.3614945,41.9933717]},"n1820939547":{"id":"n1820939547","loc":[-85.3189118,41.9697649]},"n1820939550":{"id":"n1820939550","loc":[-85.1262691,42.0740221]},"n1820939551":{"id":"n1820939551","loc":[-85.3863639,41.9994635]},"n1820939552":{"id":"n1820939552","loc":[-85.2836034,41.9923953]},"n1820939554":{"id":"n1820939554","loc":[-85.3222377,41.9715916]},"n1820939555":{"id":"n1820939555","loc":[-85.0122658,42.0906312]},"n1820939556":{"id":"n1820939556","loc":[-85.0022652,42.0877581]},"n1820939557":{"id":"n1820939557","loc":[-85.1011314,42.0899954]},"n1820939559":{"id":"n1820939559","loc":[-85.0008181,42.0885293]},"n1820939561":{"id":"n1820939561","loc":[-85.3637046,41.9942488]},"n1820939562":{"id":"n1820939562","loc":[-85.4500117,42.0052892]},"n1820939563":{"id":"n1820939563","loc":[-85.0537636,42.1036365]},"n1820939565":{"id":"n1820939565","loc":[-85.2367503,42.0246939]},"n1820939566":{"id":"n1820939566","loc":[-85.0448479,42.1002653]},"n1820939567":{"id":"n1820939567","loc":[-85.6337065,41.9295006]},"n1820939568":{"id":"n1820939568","loc":[-85.0879792,42.095623]},"n1820939569":{"id":"n1820939569","loc":[-85.6347623,41.9352369]},"n1820939570":{"id":"n1820939570","loc":[-85.1497931,42.0620378]},"n1820939571":{"id":"n1820939571","loc":[-85.5676169,41.9656324]},"n1820939572":{"id":"n1820939572","loc":[-85.638041,41.9166971]},"n1820939573":{"id":"n1820939573","loc":[-85.4993429,41.9781293]},"n1820939574":{"id":"n1820939574","loc":[-85.5352831,41.9692127]},"n1820939575":{"id":"n1820939575","loc":[-84.9924429,42.0857118]},"n1820939577":{"id":"n1820939577","loc":[-85.0581101,42.1026721]},"n1820939578":{"id":"n1820939578","loc":[-85.641088,41.9094477]},"n1820939579":{"id":"n1820939579","loc":[-85.2548821,42.0052282]},"n1820939580":{"id":"n1820939580","loc":[-85.1124463,42.0859734]},"n1820939581":{"id":"n1820939581","loc":[-85.1083479,42.0857624]},"n1820939583":{"id":"n1820939583","loc":[-85.1387424,42.0648893]},"n1820939584":{"id":"n1820939584","loc":[-85.5152645,41.9700892]},"n1820939585":{"id":"n1820939585","loc":[-85.5463738,41.9713439]},"n1820939586":{"id":"n1820939586","loc":[-85.360207,41.9933717]},"n1820939587":{"id":"n1820939587","loc":[-85.2402372,42.0120917]},"n1820939588":{"id":"n1820939588","loc":[-85.3936381,42.0047255]},"n1820939589":{"id":"n1820939589","loc":[-85.3310246,41.973784]},"n1820939590":{"id":"n1820939590","loc":[-85.0329403,42.096642]},"n1820939591":{"id":"n1820939591","loc":[-85.0097271,42.0910981]},"n1820939593":{"id":"n1820939593","loc":[-85.0446562,42.1003437]},"n1820939595":{"id":"n1820939595","loc":[-85.0856671,42.1008452]},"n1820939596":{"id":"n1820939596","loc":[-85.4087228,42.0083449]},"n1820939597":{"id":"n1820939597","loc":[-85.0609519,42.1052564]},"n1820939598":{"id":"n1820939598","loc":[-85.3432126,41.9874548]},"n1820939599":{"id":"n1820939599","loc":[-85.4041738,42.0067027]},"n1820939600":{"id":"n1820939600","loc":[-85.0825437,42.1035768]},"n1820939601":{"id":"n1820939601","loc":[-85.048422,42.101498]},"n1820939602":{"id":"n1820939602","loc":[-85.0336256,42.0999031]},"n1820939603":{"id":"n1820939603","loc":[-85.046818,42.1014104]},"n1820939605":{"id":"n1820939605","loc":[-85.2856524,41.98078]},"n1820939607":{"id":"n1820939607","loc":[-85.1118173,42.0864245]},"n1820939609":{"id":"n1820939609","loc":[-85.0443397,42.1006263]},"n1820939610":{"id":"n1820939610","loc":[-85.0336698,42.0978361]},"n1820939611":{"id":"n1820939611","loc":[-85.4630322,42.0014248]},"n1820939612":{"id":"n1820939612","loc":[-85.0613127,42.1052353]},"n1820939613":{"id":"n1820939613","loc":[-85.0137571,42.0887801]},"n1820939614":{"id":"n1820939614","loc":[-85.272487,41.9982013]},"n1820939616":{"id":"n1820939616","loc":[-85.4665727,41.9983791]},"n1820939617":{"id":"n1820939617","loc":[-85.1288078,42.0725476]},"n1820939618":{"id":"n1820939618","loc":[-85.4653282,42.00109]},"n1820939619":{"id":"n1820939619","loc":[-85.2314717,42.0276746]},"n1820939620":{"id":"n1820939620","loc":[-85.255982,42.0003569]},"n1820939621":{"id":"n1820939621","loc":[-85.2886779,41.9787223]},"n1820939622":{"id":"n1820939622","loc":[-85.22438,42.0367509]},"n1820939623":{"id":"n1820939623","loc":[-85.0334713,42.0998382]},"n1820939624":{"id":"n1820939624","loc":[-85.2236504,42.037484]},"n1820939625":{"id":"n1820939625","loc":[-85.636908,41.9175162]},"n1820939627":{"id":"n1820939627","loc":[-85.2669187,41.9989707]},"n1820939628":{"id":"n1820939628","loc":[-85.3247268,41.9720702]},"n1820939629":{"id":"n1820939629","loc":[-85.3785104,41.9987299]},"n1820939630":{"id":"n1820939630","loc":[-85.5267658,41.9720515]},"n1820939631":{"id":"n1820939631","loc":[-85.2445116,42.0098811]},"n1820939632":{"id":"n1820939632","loc":[-85.1271448,42.0725077]},"n1820939633":{"id":"n1820939633","loc":[-85.0345751,42.099724]},"n1820939634":{"id":"n1820939634","loc":[-85.4217476,42.0089986]},"n1820939635":{"id":"n1820939635","loc":[-85.3121848,41.9689433]},"n1820939636":{"id":"n1820939636","loc":[-85.2826419,41.9929985]},"n1820939637":{"id":"n1820939637","loc":[-85.3160257,41.9706344]},"n1820939638":{"id":"n1820939638","loc":[-85.5684967,41.9657919]},"n1820939640":{"id":"n1820939640","loc":[-85.225131,42.0356194]},"n1820939642":{"id":"n1820939642","loc":[-85.1324124,42.0693328]},"n1820939644":{"id":"n1820939644","loc":[-84.9994073,42.0878843]},"n1820939645":{"id":"n1820939645","loc":[-85.1087596,42.0863329]},"n1820939646":{"id":"n1820939646","loc":[-85.2915532,41.9782996]},"n1820939647":{"id":"n1820939647","loc":[-84.9988708,42.0877808]},"n1820939648":{"id":"n1820939648","loc":[-85.2243628,42.0356728]},"n1820939649":{"id":"n1820939649","loc":[-85.0427397,42.1020524]},"n1820939650":{"id":"n1820939650","loc":[-85.6388392,41.9100752]},"n1820939651":{"id":"n1820939651","loc":[-85.0133709,42.0888557]},"n1820939652":{"id":"n1820939652","loc":[-85.318798,41.9701211]},"n1820939653":{"id":"n1820939653","loc":[-85.6335778,41.9190602]},"n1820939654":{"id":"n1820939654","loc":[-85.6338396,41.9370247]},"n1820939655":{"id":"n1820939655","loc":[-85.0939069,42.0931988]},"n1820939656":{"id":"n1820939656","loc":[-85.5702347,41.9651378]},"n1820939657":{"id":"n1820939657","loc":[-85.4235286,42.0088392]},"n1820939658":{"id":"n1820939658","loc":[-85.2740856,41.9972206]},"n1820939659":{"id":"n1820939659","loc":[-85.4824299,41.9934195]},"n1820939660":{"id":"n1820939660","loc":[-85.3857846,42.0014408]},"n1820939661":{"id":"n1820939661","loc":[-85.0451658,42.10028]},"n1820939662":{"id":"n1820939662","loc":[-85.3893036,42.001377]},"n1820939664":{"id":"n1820939664","loc":[-85.2455845,42.0088607]},"n1820939665":{"id":"n1820939665","loc":[-85.2741071,41.9951116]},"n1820939666":{"id":"n1820939666","loc":[-85.1298375,42.0677718]},"n1820939667":{"id":"n1820939667","loc":[-85.5491848,41.9707377]},"n1820939669":{"id":"n1820939669","loc":[-85.2780298,41.995238]},"n1820939670":{"id":"n1820939670","loc":[-85.1330068,42.0716926]},"n1820939671":{"id":"n1820939671","loc":[-85.0811342,42.1025129]},"n1820939672":{"id":"n1820939672","loc":[-85.2325124,42.0290135]},"n1820939673":{"id":"n1820939673","loc":[-85.2975077,41.9716953]},"n1820939674":{"id":"n1820939674","loc":[-85.0951729,42.0922394]},"n1820939676":{"id":"n1820939676","loc":[-85.0363252,42.1043119]},"n1820939677":{"id":"n1820939677","loc":[-85.2960057,41.97349]},"n1820939678":{"id":"n1820939678","loc":[-85.3701849,41.9982515]},"n1820939679":{"id":"n1820939679","loc":[-85.3381486,41.9848861]},"n1820939680":{"id":"n1820939680","loc":[-85.2058448,42.0417286]},"n1820939682":{"id":"n1820939682","loc":[-85.0819335,42.1034443]},"n1820939683":{"id":"n1820939683","loc":[-85.3872223,41.9993359]},"n1820939684":{"id":"n1820939684","loc":[-85.095366,42.091909]},"n1820939685":{"id":"n1820939685","loc":[-85.2327914,42.0291888]},"n1820939686":{"id":"n1820939686","loc":[-85.0433459,42.1018773]},"n1820939687":{"id":"n1820939687","loc":[-85.0585339,42.1027318]},"n1820939688":{"id":"n1820939688","loc":[-85.0062885,42.0876347]},"n1820939689":{"id":"n1820939689","loc":[-85.246299,42.017377]},"n1820939690":{"id":"n1820939690","loc":[-85.2932376,41.9742877]},"n1820939691":{"id":"n1820939691","loc":[-85.2962846,41.9736815]},"n1820939692":{"id":"n1820939692","loc":[-85.6052365,41.9409193]},"n1820939693":{"id":"n1820939693","loc":[-85.2570536,42.0003341]},"n1820939694":{"id":"n1820939694","loc":[-85.0488458,42.1014064]},"n1820939695":{"id":"n1820939695","loc":[-85.4050321,42.0069578]},"n1820939696":{"id":"n1820939696","loc":[-85.4847517,41.9845894]},"n1820939697":{"id":"n1820939697","loc":[-85.0844655,42.1013826]},"n1820939698":{"id":"n1820939698","loc":[-85.1437206,42.0650008]},"n1820939699":{"id":"n1820939699","loc":[-85.1168183,42.0864034]},"n1820939700":{"id":"n1820939700","loc":[-85.5479831,41.9711366]},"n1820939701":{"id":"n1820939701","loc":[-85.0349948,42.1034124]},"n1820939702":{"id":"n1820939702","loc":[-85.0835589,42.1038821]},"n1820939703":{"id":"n1820939703","loc":[-85.0203875,42.0902649]},"n1820939704":{"id":"n1820939704","loc":[-85.0371191,42.1038184]},"n1820939705":{"id":"n1820939705","loc":[-85.1273312,42.0735681]},"n1820939707":{"id":"n1820939707","loc":[-85.1272239,42.0730226]},"n1820939710":{"id":"n1820939710","loc":[-85.0349881,42.1019012]},"n1820939712":{"id":"n1820939712","loc":[-85.2440459,42.0178313]},"n1820939713":{"id":"n1820939713","loc":[-85.2444751,42.0182618]},"n1820939714":{"id":"n1820939714","loc":[-85.0539996,42.1032863]},"n1820939715":{"id":"n1820939715","loc":[-85.2215905,42.0373246]},"n1820939716":{"id":"n1820939716","loc":[-85.0649712,42.1051994]},"n1820939717":{"id":"n1820939717","loc":[-85.0927146,42.0927581]},"n1820939718":{"id":"n1820939718","loc":[-85.3884668,42.0042312]},"n1820939719":{"id":"n1820939719","loc":[-85.0840672,42.1013241]},"n1820939720":{"id":"n1820939720","loc":[-85.304739,41.9725408]},"n1820939721":{"id":"n1820939721","loc":[-85.2243585,42.0371334]},"n1820939722":{"id":"n1820939722","loc":[-85.0599823,42.1049686]},"n1820939723":{"id":"n1820939723","loc":[-85.0298825,42.0944288]},"n1820939724":{"id":"n1820939724","loc":[-85.0366095,42.1042443]},"n1820939725":{"id":"n1820939725","loc":[-85.0698783,42.1058135]},"n1820939726":{"id":"n1820939726","loc":[-85.1054551,42.0873361]},"n1820939727":{"id":"n1820939727","loc":[-84.9952324,42.0864285]},"n1820939728":{"id":"n1820939728","loc":[-85.3442211,41.9897993]},"n1820939729":{"id":"n1820939729","loc":[-85.4386134,42.0056822]},"n1820939730":{"id":"n1820939730","loc":[-85.2438528,42.0146589]},"n1820939731":{"id":"n1820939731","loc":[-85.0355581,42.1041846]},"n1820939732":{"id":"n1820939732","loc":[-85.557682,41.9724447]},"n1820939734":{"id":"n1820939734","loc":[-85.2299418,42.033314]},"n1820939735":{"id":"n1820939735","loc":[-85.6297412,41.9419088]},"n1820939736":{"id":"n1820939736","loc":[-85.2645101,41.9980259]},"n1820939738":{"id":"n1820939738","loc":[-85.082195,42.1035649]},"n1820939739":{"id":"n1820939739","loc":[-85.234272,42.0267102]},"n1820939740":{"id":"n1820939740","loc":[-85.0130758,42.0895006]},"n1820939741":{"id":"n1820939741","loc":[-85.4594702,42.0000375]},"n1820939742":{"id":"n1820939742","loc":[-84.9946745,42.0863687]},"n1820939743":{"id":"n1820939743","loc":[-85.6438775,41.9120186]},"n1820939744":{"id":"n1820939744","loc":[-85.6372685,41.9168089]},"n1820939745":{"id":"n1820939745","loc":[-85.2789468,41.9893208]},"n1820939747":{"id":"n1820939747","loc":[-85.3775019,41.998427]},"n1820939749":{"id":"n1820939749","loc":[-85.0993571,42.0909178]},"n1820939750":{"id":"n1820939750","loc":[-85.1308503,42.0669339]},"n1820939751":{"id":"n1820939751","loc":[-85.4802566,41.9856659]},"n1820939752":{"id":"n1820939752","loc":[-85.2543563,42.0108804]},"n1820939753":{"id":"n1820939753","loc":[-85.1041033,42.0878815]},"n1820939755":{"id":"n1820939755","loc":[-85.4000969,42.0071651]},"n1820939757":{"id":"n1820939757","loc":[-85.3858275,42.0022381]},"n1820939758":{"id":"n1820939758","loc":[-85.3653998,41.996609]},"n1820939759":{"id":"n1820939759","loc":[-85.2432949,42.0202305]},"n1820939760":{"id":"n1820939760","loc":[-85.3878874,42.0042472]},"n1820939761":{"id":"n1820939761","loc":[-85.2516741,42.0114145]},"n1820939762":{"id":"n1820939762","loc":[-85.2788825,41.9865142]},"n1820939763":{"id":"n1820939763","loc":[-85.0009147,42.0886686]},"n1820939764":{"id":"n1820939764","loc":[-85.3918142,42.003434]},"n1820939765":{"id":"n1820939765","loc":[-85.5532832,41.9696848]},"n1820939766":{"id":"n1820939766","loc":[-85.5545063,41.969254]},"n1820939768":{"id":"n1820939768","loc":[-85.1327989,42.0704769]},"n1820939770":{"id":"n1820939770","loc":[-85.0588558,42.1047696]},"n1820939772":{"id":"n1820939772","loc":[-85.555798,41.9713017]},"n1820939773":{"id":"n1820939773","loc":[-85.0565853,42.1023589]},"n1820939774":{"id":"n1820939774","loc":[-85.2582941,41.9992765]},"n1820939775":{"id":"n1820939775","loc":[-85.3007264,41.9727642]},"n1820939776":{"id":"n1820939776","loc":[-85.2477045,42.0082652]},"n1820939777":{"id":"n1820939777","loc":[-85.2415247,42.0104973]},"n1821006698":{"id":"n1821006698","loc":[-85.6345227,41.9382009]},"n1821006700":{"id":"n1821006700","loc":[-85.6344894,41.938975]},"n1821006704":{"id":"n1821006704","loc":[-85.6351181,41.9370157]},"n1821006706":{"id":"n1821006706","loc":[-85.6357554,41.9361657]},"n1821006708":{"id":"n1821006708","loc":[-85.6351235,41.9368481]},"n1821006710":{"id":"n1821006710","loc":[-85.6352844,41.9364211]},"n1821006712":{"id":"n1821006712","loc":[-85.6351503,41.937307]},"n1821006716":{"id":"n1821006716","loc":[-85.6350366,41.9379774]},"n1821006725":{"id":"n1821006725","loc":[-85.6352147,41.9375903]},"n1821137607":{"id":"n1821137607","loc":[-85.5297057,41.9669915]},"n1821137608":{"id":"n1821137608","loc":[-85.5288598,41.9673094]},"n1821139530":{"id":"n1821139530","loc":[-85.4832228,41.9881686]},"n1821139531":{"id":"n1821139531","loc":[-85.4812101,41.9851258]},"n1821139532":{"id":"n1821139532","loc":[-85.4799127,41.9860244]},"n1821139533":{"id":"n1821139533","loc":[-85.4800313,41.9865555]},"n1841425201":{"id":"n1841425201","loc":[-85.4334577,42.0063713]},"n1841425222":{"id":"n1841425222","loc":[-85.4382449,42.0055785]},"n1914861007":{"id":"n1914861007","loc":[-85.394959,42.0057472]},"n1914861057":{"id":"n1914861057","loc":[-85.3967185,42.0049695]},"n1914861112":{"id":"n1914861112","loc":[-85.394179,42.0056906]},"n1914861306":{"id":"n1914861306","loc":[-85.3900226,42.0028488]},"n2114807565":{"id":"n2114807565","loc":[-85.6385979,41.9577824]},"n2114807568":{"id":"n2114807568","loc":[-85.6325097,41.9775713]},"n2114807572":{"id":"n2114807572","loc":[-85.6328996,41.9980965]},"n2114807578":{"id":"n2114807578","loc":[-85.6344818,41.9696956]},"n2114807583":{"id":"n2114807583","loc":[-85.6326289,41.9757853]},"n2114807593":{"id":"n2114807593","loc":[-85.6360828,41.9650674]},"n2130304159":{"id":"n2130304159","loc":[-85.6352537,41.9450015],"tags":{"railway":"level_crossing"}},"n2139795852":{"id":"n2139795852","loc":[-85.6374708,41.9311633]},"n2139858882":{"id":"n2139858882","loc":[-85.635178,41.9356158]},"n2139858883":{"id":"n2139858883","loc":[-85.63533,41.9355886]},"n2139858884":{"id":"n2139858884","loc":[-85.6353819,41.93556]},"n2139858885":{"id":"n2139858885","loc":[-85.6353665,41.9355157]},"n2139858886":{"id":"n2139858886","loc":[-85.6353165,41.9354971]},"n2139858887":{"id":"n2139858887","loc":[-85.6352454,41.9355328]},"n2139858888":{"id":"n2139858888","loc":[-85.6350184,41.9357846]},"n2139858889":{"id":"n2139858889","loc":[-85.634978,41.9359448]},"n2139858890":{"id":"n2139858890","loc":[-85.6347723,41.9361523]},"n2139858891":{"id":"n2139858891","loc":[-85.6347165,41.9362667]},"n2139858892":{"id":"n2139858892","loc":[-85.6346992,41.9364312]},"n2139858893":{"id":"n2139858893","loc":[-85.634603,41.9366329]},"n2139858894":{"id":"n2139858894","loc":[-85.6345973,41.9367488]},"n2139858895":{"id":"n2139858895","loc":[-85.6345127,41.9369734]},"n2139858896":{"id":"n2139858896","loc":[-85.634478,41.9371923]},"n2139858897":{"id":"n2139858897","loc":[-85.6344838,41.9373768]},"n2139858898":{"id":"n2139858898","loc":[-85.6346242,41.9375299]},"n2139858899":{"id":"n2139858899","loc":[-85.6347723,41.9376357]},"n2139858900":{"id":"n2139858900","loc":[-85.6347607,41.9377788]},"n2139858901":{"id":"n2139858901","loc":[-85.6346204,41.9379533]},"n2139858902":{"id":"n2139858902","loc":[-85.6344184,41.9380105]},"n2139858903":{"id":"n2139858903","loc":[-85.6341627,41.9380406]},"n2139858904":{"id":"n2139858904","loc":[-85.634005,41.9381679]},"n2139858905":{"id":"n2139858905","loc":[-85.63393,41.9383353]},"n2139858906":{"id":"n2139858906","loc":[-85.6338588,41.9384597]},"n2139858907":{"id":"n2139858907","loc":[-85.6336627,41.9387759]},"n2139858908":{"id":"n2139858908","loc":[-85.6335127,41.9389361]},"n2139858933":{"id":"n2139858933","loc":[-85.6353118,41.9432646]},"n2139858934":{"id":"n2139858934","loc":[-85.6353952,41.9433002]},"n2139858935":{"id":"n2139858935","loc":[-85.6356496,41.9433255]},"n2139858936":{"id":"n2139858936","loc":[-85.6363128,41.9433373]},"n2139858937":{"id":"n2139858937","loc":[-85.6365467,41.9433779]},"n2139858938":{"id":"n2139858938","loc":[-85.6368692,41.9435265]},"n2139858939":{"id":"n2139858939","loc":[-85.6370986,41.9437039]},"n2139858940":{"id":"n2139858940","loc":[-85.6372371,41.9437732]},"n2139858941":{"id":"n2139858941","loc":[-85.6374756,41.9438171]},"n2139858942":{"id":"n2139858942","loc":[-85.6376164,41.9439286]},"n2139858943":{"id":"n2139858943","loc":[-85.6377504,41.944138]},"n2139858944":{"id":"n2139858944","loc":[-85.6384204,41.9443137]},"n2139858945":{"id":"n2139858945","loc":[-85.6385726,41.9444506]},"n2139858946":{"id":"n2139858946","loc":[-85.638702,41.9445739]},"n2139858947":{"id":"n2139858947","loc":[-85.6387179,41.9446516]},"n2139858948":{"id":"n2139858948","loc":[-85.6387088,41.9447985]},"n2139858949":{"id":"n2139858949","loc":[-85.6387656,41.9449877]},"n2139858950":{"id":"n2139858950","loc":[-85.638777,41.9451448]},"n2139858951":{"id":"n2139858951","loc":[-85.6387088,41.9452631]},"n2139858964":{"id":"n2139858964","loc":[-85.6383346,41.9442912]},"n2139858966":{"id":"n2139858966","loc":[-85.6384724,41.9443605]},"n2139858967":{"id":"n2139858967","loc":[-85.6354078,41.9434285]},"n2139858968":{"id":"n2139858968","loc":[-85.635271,41.943654]},"n2139858969":{"id":"n2139858969","loc":[-85.6352657,41.9437437]},"n2139858970":{"id":"n2139858970","loc":[-85.635271,41.9438195]},"n2139858971":{"id":"n2139858971","loc":[-85.6351563,41.9438906]},"n2139858972":{"id":"n2139858972","loc":[-85.6351384,41.9438882]},"n2139858973":{"id":"n2139858973","loc":[-85.6351514,41.9438034]},"n2139858974":{"id":"n2139858974","loc":[-85.6351237,41.9436641]},"n2139858975":{"id":"n2139858975","loc":[-85.6351498,41.9436108]},"n2139858976":{"id":"n2139858976","loc":[-85.6351058,41.9435345]},"n2139858977":{"id":"n2139858977","loc":[-85.6349641,41.9432051]},"n2139858986":{"id":"n2139858986","loc":[-85.6341205,41.9380746]},"n2139858990":{"id":"n2139858990","loc":[-85.6345671,41.9381816]},"n2139858995":{"id":"n2139858995","loc":[-85.6339783,41.9382273]},"n2139859003":{"id":"n2139859003","loc":[-85.6340477,41.9373489]},"n2139859004":{"id":"n2139859004","loc":[-85.6339784,41.9374752]},"n2139870406":{"id":"n2139870406","loc":[-85.6342265,41.9432605]},"n2139877106":{"id":"n2139877106","loc":[-85.6346323,41.9438746]},"n2139982399":{"id":"n2139982399","loc":[-85.6324055,41.9408537]},"n2139982400":{"id":"n2139982400","loc":[-85.632488,41.941063],"tags":{"leisure":"slipway"}},"n2139982401":{"id":"n2139982401","loc":[-85.6327261,41.9415366]},"n2139982402":{"id":"n2139982402","loc":[-85.6326391,41.9413598]},"n2139982403":{"id":"n2139982403","loc":[-85.6327041,41.9414391]},"n2139982405":{"id":"n2139982405","loc":[-85.6322891,41.9406009]},"n2139982406":{"id":"n2139982406","loc":[-85.6325412,41.9425257]},"n2139989333":{"id":"n2139989333","loc":[-85.6340584,41.9431731]},"n2140006331":{"id":"n2140006331","loc":[-85.6361751,41.9459744]},"n2140006334":{"id":"n2140006334","loc":[-85.636528,41.9459751]},"n2140006336":{"id":"n2140006336","loc":[-85.6370918,41.9458926]},"n2140006338":{"id":"n2140006338","loc":[-85.6378806,41.9456474]},"n2140006340":{"id":"n2140006340","loc":[-85.6385831,41.9454343]},"n2140006342":{"id":"n2140006342","loc":[-85.639341,41.945157]},"n2140006344":{"id":"n2140006344","loc":[-85.6393497,41.9450232]},"n2140006346":{"id":"n2140006346","loc":[-85.6388245,41.9450145]},"n2140006348":{"id":"n2140006348","loc":[-85.6388167,41.9441739]},"n2140006351":{"id":"n2140006351","loc":[-85.6382915,41.9441797]},"n2140006353":{"id":"n2140006353","loc":[-85.63828,41.9438109]},"n2140006355":{"id":"n2140006355","loc":[-85.6381949,41.9436009]},"n2140006357":{"id":"n2140006357","loc":[-85.6371904,41.9435918]},"n2140006359":{"id":"n2140006359","loc":[-85.6366966,41.9432727]},"n2140006361":{"id":"n2140006361","loc":[-85.6353755,41.9432744]},"n2140006365":{"id":"n2140006365","loc":[-85.6350906,41.9435472]},"n2140006366":{"id":"n2140006366","loc":[-85.6343461,41.9441573]},"n2140006395":{"id":"n2140006395","loc":[-85.6351171,41.9437175]},"n2140006397":{"id":"n2140006397","loc":[-85.635352,41.9450206]},"n2140006399":{"id":"n2140006399","loc":[-85.6358194,41.9454937]},"n2140006401":{"id":"n2140006401","loc":[-85.6348693,41.9445739]},"n2140006431":{"id":"n2140006431","loc":[-85.6376737,41.9438023]},"n2140006437":{"id":"n2140006437","loc":[-85.6382631,41.9442724]},"n2189123379":{"id":"n2189123379","loc":[-85.6342671,41.9352665]},"w203974076":{"id":"w203974076","tags":{"highway":"footway"},"nodes":["n2139870442","n2139870457","n2139870458","n2139870459","n2139870460","n2139870452"]},"w170989131":{"id":"w170989131","tags":{"name":"St Joseph River","waterway":"river"},"nodes":["n1820938225","n1820938712","n1820937596","n1820937574","n1820938515","n1820938330","n1820938678","n1820938240","n1820938950","n1820939226","n1820939575","n1820937913","n1820938223","n1820937668","n1820938545","n1820937584","n1820939742","n1820939727","n1820937578","n1820938149","n1820938124","n1820938888","n1820938898","n1820937922","n1820939543","n1820939370","n1820939401","n1820939647","n1820938345","n1820939644","n1820938333","n1820938370","n1820938624","n1820938493","n1820939559","n1820939763","n1820939237","n1820939416","n1820937810","n1820938317","n1820938324","n1820937558","n1820939556","n1820938298","n1820939348","n1820939125","n1820939081","n1820938859","n1820939126","n1820938881","n1820939439","n1820939324","n1820939128","n1820938101","n1820937706","n1820938382","n1820938776","n1820937815","n1820939177","n1820939688","n1820938952","n1820938216","n1820938387","n1820939333","n1820938243","n1820938248","n1820937666","n1820939051","n1820938332","n1820939438","n1820939407","n1820939361","n1820937517","n1820938770","n1820939591","n1820937857","n1820938491","n1820937993","n1820938125","n1820938166","n1820937746","n1820939028","n1820937638","n1820938676","n1820938843","n1820938844","n1820937978","n1820938730","n1820939544","n1820938304","n1820939123","n1820939494","n1820939450","n1820939555","n1820938133","n1820938129","n1820938871","n1820939408","n1820938669","n1820938260","n1820939740","n1820937625","n1820938631","n1820939651","n1820939613","n1820937850","n1820938325","n1820937736","n1820938804","n1820938837","n1820938014","n1820938991","n1820938722","n1820938935","n1820937870","n1820938432","n1820937986","n1820938756","n1820938966","n1820939159","n1820937744","n1820938334","n1820937645","n1820939394","n1820937656","n1820938392","n1820939703","n1820938385","n1820938947","n1820938854","n1820938428","n1820938488","n1820938269","n1820938668","n1820938268","n1820938707","n1820937732","n1820939144","n1820938481","n1820938771","n1820938686","n1820938948","n1820937997","n1820937769","n1820939003","n1820938083","n1820939011","n1820938803","n1820938700","n1820939723","n1820938808","n1820938262","n1820938081","n1820938926","n1820938326","n1820938102","n1820938508","n1820939590","n1820939199","n1820938084","n1820938870","n1820938895","n1820937611","n1820938918","n1820938514","n1820939610","n1820938910","n1820937523","n1820938127","n1820939108","n1820937981","n1820938938","n1820938715","n1820939016","n1820938237","n1820939623","n1820939602","n1820937734","n1820938977","n1820939633","n1820939156","n1820939406","n1820938279","n1820938301","n1820937678","n1820937671","n1820939163","n1820938356","n1820939372","n1820937568","n1820937626","n1820939710","n1820939004","n1820938253","n1820938571","n1820937513","n1820939412","n1820939701","n1820939509","n1820938839","n1820939731","n1820937798","n1820939676","n1820939724","n1820939243","n1820939704","n1820937814","n1820937599","n1820938199","n1820938995","n1820938445","n1820938069","n1820938470","n1820939074","n1820938193","n1820938740","n1820938047","n1820939507","n1820939441","n1820939160","n1820937849","n1820937840","n1820938052","n1820938988","n1820938796","n1820937724","n1820937620","n1820939304","n1820938343","n1820939649","n1820938875","n1820939686","n1820938476","n1820937801","n1820937737","n1820938264","n1820939609","n1820939496","n1820939593","n1820939566","n1820939661","n1820937782","n1820938912","n1820939173","n1820937733","n1820938953","n1820939603","n1820937607","n1820938468","n1820939601","n1820939694","n1820939133","n1820938897","n1820938893","n1820937831","n1820937730","n1820938820","n1820938046","n1820938426","n1820938347","n1820937582","n1820938954","n1820938033","n1820938104","n1820938680","n1820939563","n1820939404","n1820939714","n1820939000","n1820937992","n1820938168","n1820939510","n1820939500","n1820937509","n1820938865","n1820939773","n1820938138","n1820938905","n1820937623","n1820939418","n1820937946","n1820939577","n1820937615","n1820939687","n1820939119","n1820937988","n1820938337","n1820937750","n1820938703","n1820938339","n1820939044","n1820939770","n1820938913","n1820937672","n1820939722","n1820937768","n1820939597","n1820939612","n1820937699","n1820937682","n1820937669","n1820937657","n1820939363","n1820937800","n1820938265","n1820937760","n1820938207","n1820938115","n1820939130","n1820939716","n1820938338","n1820938239","n1820939040","n1820938064","n1820938855","n1820939015","n1820938258","n1820939042","n1820939043","n1820938443","n1820939725","n1820937675","n1820938568","n1820938280","n1820937705","n1820938775","n1820938636","n1820938626","n1820937859","n1820938096","n1820937852","n1820939039","n1820938247","n1820938585","n1820937707","n1820938117","n1820938909","n1820939115","n1820939335","n1820938805","n1820937935","n1820937876","n1820938699","n1820937869","n1820938603","n1820938100","n1820938500","n1820938283","n1820938275","n1820938923","n1820938365","n1820938349","n1820937804","n1820937903","n1820937608","n1820938688","n1820939671","n1820938092","n1820937820","n1820938753","n1820938922","n1820937990","n1820939682","n1820939738","n1820939600","n1820938167","n1820937726","n1820939702","n1820938209","n1820939456","n1820937837","n1820938222","n1820938902","n1820939162","n1820938965","n1820938461","n1820937681","n1820937514","n1820937764","n1820939719","n1820939697","n1820938899","n1820939093","n1820938702","n1820939595","n1820938749","n1820938348","n1820937606","n1820938675","n1820938830","n1820938737","n1820938758","n1820938716","n1820939107","n1820937863","n1820939033","n1820938163","n1820937867","n1820938819","n1820938034","n1820938252","n1820937563","n1820937868","n1820939032","n1820938632","n1820937982","n1820937943","n1820939568","n1820939541","n1820938215","n1820939097","n1820938812","n1820937518","n1820937952","n1820938711","n1820938736","n1820939066","n1820937591","n1820938082","n1820938108","n1820938496","n1820939410","n1820938949","n1820938327","n1820937708","n1820939023","n1820937772","n1820938256","n1820939083","n1820938378","n1820938961","n1820937610","n1820939717","n1820938695","n1820938590","n1820939655","n1820938341","n1820939054","n1820939157","n1820939674","n1820939684","n1820939511","n1820937631","n1820939458","n1820937830","n1820937709","n1820937779","n1820939749","n1820938880","n1820938856","n1820938557","n1820939557","n1820938249","n1820938818","n1820937594","n1820939114","n1820938416","n1820937508","n1820938990","n1820938201","n1820937759","n1820937987","n1820939164","n1820939753","n1820938187","n1820939067","n1820937586","n1820937941","n1820938121","n1820937807","n1820938521","n1820939726","n1820938244","n1820939014","n1820938741","n1820937629","n1820938664","n1820938747","n1820939082","n1820938709","n1820938320","n1820938270","n1820937619","n1820937777","n1820937718","n1820939138","n1820938056","n1820938155","n1820938596","n1820937775","n1820938437","n1820938128","n1820939581","n1820939145","n1820938546","n1820938184","n1820937601","n1820937794","n1820938539","n1820939645","n1820938438","n1820938436","n1820939025","n1820938915","n1820938534","n1820937605","n1820939607","n1820939101","n1820939580","n1820939268","n1820939134","n1820938849","n1820938754","n1820938079","n1820937842","n1820938781","n1820938873","n1820938495","n1820938381","n1820938503","n1820939436","n1820938502","n1820939087","n1820938996","n1820938449","n1820938907","n1820937979","n1820937780","n1820937546","n1820939699","n1820937677","n1820938957","n1820938946","n1820937776","n1820937717","n1820938718","n1820937637","n1820938510","n1820937663","n1820938941","n1820939151","n1820937603","n1820938250","n1820937951","n1820938630","n1820938821","n1820938779","n1820938497","n1820938159","n1820939536","n1820938409","n1820938386","n1820939116","n1820938340","n1820939117","n1820938291","n1820938435","n1820937819","n1820938242","n1820939078","n1820938877","n1820939104","n1820939445","n1820938367","n1820938903","n1820939420","n1820938517","n1820939508","n1820939542","n1820939326","n1820938210","n1820939020","n1820938815","n1820937832","n1820939513","n1820937818","n1820939005","n1820938717","n1820939135","n1820938384","n1820937587","n1820939024","n1820939504","n1820939120","n1820939026","n1820938015","n1820938998","n1820937648","n1820939137","n1820937761","n1820938195","n1820938535","n1820939550","n1820938725","n1820938282","n1820937781","n1820937792","n1820939705","n1820937788","n1820939707","n1820937882","n1820939632","n1820938427","n1820938276","n1820939617","n1820939013","n1820939035","n1820937543","n1820939365","n1820937752","n1820937802","n1820939183","n1820939670","n1820938450","n1820939375","n1820937813","n1820937673","n1820937783","n1820939029","n1820939768","n1820939377","n1820937974","n1820939244","n1820939642","n1820937864","n1820938255","n1820938528","n1820939666","n1820938120","n1820937812","n1820938928","n1820939750","n1820939099","n1820938073","n1820938714","n1820939140","n1820938192","n1820937844","n1820938635","n1820938742","n1820939583","n1820937887","n1820938318","n1820938816","n1820939698","n1820938273","n1820939181","n1820937652","n1820938748","n1820937651","n1820938519","n1820938019","n1820938752","n1820938235","n1820939118","n1820938562","n1820939314","n1820939570","n1820938190","n1820938342","n1820938533","n1820937977","n1820939089","n1820939146","n1820938622","n1820938297","n1820938524","n1820939283","n1820938874","n1820938832","n1820937550","n1820937843","n1820938638","n1820938116","n1820938206","n1820938319","n1820939053","n1820937845","n1820938093","n1820939217","n1820938997","n1820939355","n1820938861","n1820938726","n1820938057","n1820939373","n1820937862","n1820938518","n1820939072","n1820939680","n1820938444","n1820938217","n1820938506","n1820938393","n1820938492","n1820938852","n1820938221","n1820938773","n1820937684","n1820939060","n1820938224","n1820938203","n1820938840","n1820937525","n1820938147","n1820938433","n1820938188","n1820939359","n1820938750","n1820938016","n1820938768","n1820937621","n1820937799","n1820938951","n1820938721","n1820939037","n1820937866","n1820939715","n1820938063","n1820938446","n1820937627","n1820939624","n1820938431","n1820939721","n1820939622","n1820939239","n1820939263","n1820939648","n1820939640","n1820938867","n1820938757","n1820938439","n1820939352","n1820937740","n1820939329","n1820938229","n1820937583","n1820938180","n1820938366","n1820937767","n1820937758","n1820939374","n1820938869","n1820938292","n1820938400","n1820938399","n1820939734","n1820939289","n1820938944","n1820937755","n1820938759","n1820938434","n1820937600","n1820937825","n1820937670","n1820937793","n1820938011","n1820938246","n1820938956","n1820937770","n1820937757","n1820938059","n1820937860","n1820937569","n1820939266","n1820939685","n1820939672","n1820938606","n1820938772","n1820939038","n1820938211","n1820938359","n1820939619","n1820938708","n1820939512","n1820938065","n1820939233","n1820939739","n1820938786","n1820938879","n1820939147","n1820938563","n1820939148","n1820937839","n1820937659","n1820937786","n1820938419","n1820939565","n1820939402","n1820937710","n1820938254","n1820938271","n1820938390","n1820937680","n1820938140","n1820937817","n1820938218","n1820937985","n1820939235","n1820938441","n1820938401","n1820938719","n1820937795","n1820938971","n1820938460","n1820939759","n1820937972","n1820937841","n1820938462","n1820939320","n1820938978","n1820938360","n1820939713","n1820937676","n1820939712","n1820937939","n1820938080","n1820937754","n1820937753","n1820938530","n1820937886","n1820939689","n1820939124","n1820938697","n1820938789","n1820939105","n1820938860","n1820938853","n1820939400","n1820937561","n1820938404","n1820938774","n1820939316","n1820937696","n1820938782","n1820938975","n1820937564","n1820939730","n1820938257","n1820937853","n1820938487","n1820938848","n1820938906","n1820939230","n1820938424","n1820938051","n1820937771","n1820939587","n1820939149","n1820938792","n1820939041","n1820938934","n1820939777","n1820937515","n1820939058","n1820938312","n1820939264","n1820939631","n1820939109","n1820939403","n1820939664","n1820938724","n1820938929","n1820939399","n1820939776","n1820939369","n1820939185","n1820937701","n1820938126","n1820938336","n1820938219","n1820939080","n1820938642","n1820938043","n1820937725","n1820938548","n1820938552","n1820938035","n1820938684","n1820937778","n1820938764","n1820939021","n1820939346","n1820937712","n1820939761","n1820938397","n1820937747","n1820938566","n1820939161","n1820939090","n1820939752","n1820939271","n1820938878","n1820938110","n1820938346","n1820938499","n1820938151","n1820939538","n1820938281","n1820939153","n1820938551","n1820939285","n1820938197","n1820938408","n1820938482","n1820939036","n1820939579","n1820938489","n1820938483","n1820938189","n1820938123","n1820938087","n1820937741","n1820938485","n1820937590","n1820938972","n1820937773","n1820937520","n1820938872","n1820938131","n1820938452","n1820938328","n1820939620","n1820937641","n1820938353","n1820939693","n1820938705","n1820937640","n1820939189","n1820938144","n1820939774","n1820938694","n1820938238","n1820939397","n1820937917","n1820938454","n1820938567","n1820938979","n1820938060","n1820938204","n1820937828","n1820939232","n1820938806","n1820938857","n1820938078","n1820938105","n1820939228","n1820938604","n1820937763","n1820937854","n1820938289","n1820939736","n1820937937","n1820937714","n1820938278","n1820938058","n1820938706","n1820938989","n1820938313","n1820938520","n1820938288","n1820937689","n1820939537","n1820939531","n1820939019","n1820937527","n1820938455","n1820938814","n1820938045","n1820939627","n1820938213","n1820938161","n1820938331","n1820938024","n1820938220","n1820938062","n1820938178","n1820937796","n1820937644","n1820938490","n1820937589","n1820937879","n1820939614","n1820938882","n1820938039","n1820938538","n1820937667","n1820937719","n1820938561","n1820939658","n1820938783","n1820938601","n1820938198","n1820938388","n1820938969","n1820937687","n1820939086","n1820939665","n1820939187","n1820938498","n1820938261","n1820937983","n1820938068","n1820938136","n1820939061","n1820938137","n1820938186","n1820939071","n1820937592","n1820939669","n1820937553","n1820939357","n1820938727","n1820939371","n1820939112","n1820939079","n1820938743","n1820938467","n1820938834","n1820938022","n1820938537","n1820938122","n1820938516","n1820937614","n1820937612","n1820939469","n1820939636","n1820939050","n1820939552","n1820938157","n1820938663","n1820938955","n1820939091","n1820938430","n1820938471","n1820937809","n1820938074","n1820938208","n1820938914","n1820938858","n1820938417","n1820937531","n1820938107","n1820939100","n1820938751","n1820937711","n1820938824","n1820939745","n1820937572","n1820938602","n1820938212","n1820938097","n1820937921","n1820938090","n1820938511","n1820938876","n1820939762","n1820938234","n1820938048","n1820937774","n1820937856","n1820937749","n1820937765","n1820938286","n1820939095","n1820938480","n1820939229","n1820938277","n1820937617","n1820938311","n1820937622","n1820939196","n1820937690","n1820939006","n1820939287","n1820939131","n1820938106","n1820938784","n1820938335","n1820938095","n1820938182","n1820937715","n1820937683","n1820938070","n1820939605","n1820938527","n1820938763","n1820938398","n1820937686","n1820939621","n1820937664","n1820939277","n1820938565","n1820939539","n1820938099","n1820939646","n1820938556","n1820937548","n1820938729","n1820939336","n1820938259","n1820938728","n1820938361","n1820937643","n1820938644","n1820939007","n1820939690","n1820939227","n1820937635","n1820937950","n1820938682","n1820939150","n1820939012","n1820939261","n1820939111","n1820937805","n1820939691","n1820939677","n1820937628","n1820937811","n1820938790","n1820938251","n1820938226","n1820938942","n1820937633","n1820937984","n1820937751","n1820939673","n1820938970","n1820938415","n1820938597","n1820938309","n1820938111","n1820938472","n1820938894","n1820938402","n1820937593","n1820938570","n1820939102","n1820939775","n1820937948","n1820939121","n1820937511","n1820938787","n1820939720","n1820939075","n1820937880","n1820937742","n1820937721","n1820939535","n1820938486","n1820938354","n1820937632","n1820939010","n1820938885","n1820938089","n1820937613","n1820938442","n1820938245","n1820938272","n1820937566","n1820938295","n1820938532","n1820938883","n1820937713","n1820937674","n1820939635","n1820938448","n1820938355","n1820938587","n1820938559","n1820937787","n1820939301","n1820937723","n1820939056","n1820937560","n1820938323","n1820938230","n1820938453","n1820938377","n1820938357","n1820939637","n1820938017","n1820939540","n1820939376","n1820937639","n1820937642","n1820938075","n1820938351","n1820938766","n1820937897","n1820938973","n1820938066","n1820939547","n1820939652","n1820937944","n1820937748","n1820939234","n1820939193","n1820937891","n1820938785","n1820939132","n1820938523","n1820938884","n1820938411","n1820939554","n1820938791","n1820937655","n1820938368","n1820939152","n1820938030","n1820938447","n1820937580","n1820939628","n1820937588","n1820937894","n1820939201","n1820938086","n1820937650","n1820938379","n1820939008","n1820938999","n1820937524","n1820937872","n1820938389","n1820939197","n1820938422","n1820938936","n1820939262","n1820937634","n1820938583","n1820939589","n1820937901","n1820939034","n1820939065","n1820938290","n1820939195","n1820938228","n1820937884","n1820938797","n1820938191","n1820939191","n1820939198","n1820937892","n1820939679","n1820938507","n1820937647","n1820937909","n1820938542","n1820939598","n1820937851","n1820939084","n1820939728","n1820937688","n1820938263","n1820938670","n1820937762","n1820939310","n1820938925","n1820938862","n1820938822","n1820938547","n1820937731","n1820938594","n1820938592","n1820938214","n1820938284","n1820937835","n1820938599","n1820939437","n1820937834","n1820937576","n1820937692","n1820939586","n1820939546","n1820938403","n1820937970","n1820939561","n1820938098","n1820938851","n1820938477","n1820938892","n1820939045","n1820939758","n1820939350","n1820938321","n1820938440","n1820938595","n1820938364","n1820938962","n1820938118","n1820939678","n1820938406","n1820938549","n1820937555","n1820938823","n1820937521","n1820939471","n1820939487","n1820938799","n1820938605","n1820937928","n1820938373","n1820939747","n1820939629","n1820937557","n1820937526","n1820938958","n1820938833","n1820937636","n1820938967","n1820938760","n1820938842","n1820938067","n1820939077","n1820939224","n1820938185","n1820939110","n1820938372","n1820939757","n1820939063","n1820939660","n1820938813","n1820937528","n1820938369","n1820938896","n1820939551","n1820939683","n1820937660","n1820937873","n1820938810","n1820938478","n1820939662","n1820937595","n1820939052","n1820938113","n1820939070","n1820938733","n1820937878","n1820938300","n1820939760","n1820939718","n1820937646","n1820939057","n1820939443","n1914861306","n1820938013","n1820937529","n1820939764","n1820938826","n1820937885","n1820939588","n1820937865","n1820937833","n1914861112","n1820938761","n1914861007","n1820937905","n1820938541","n1820939092","n1914861057","n1820938153","n1820938267","n1820939265","n1820938085","n1820939018","n1820939755","n1820938474","n1820939027","n1820938593","n1820938202","n1820939599","n1820939695","n1820938077","n1820938012","n1820939545","n1820939596","n1820939337","n1820938227","n1820937698","n1820938475","n1820939465","n1820938165","n1820938698","n1820938525","n1820938529","n1820938553","n1820938940","n1820939498","n1820938501","n1820939533","n1820938924","n1820939634","n1820939220","n1820939657","n1820938887","n1820938838","n1820938114","n1820937823","n1820938778","n1820938801","n1820939096","n1820938981","n1820937953","n1820938732","n1820938980","n1820938960","n1820937949","n1820938026","n1820939273","n1841425201","n1820938629","n1820938864","n1820938554","n1820938088","n1820937685","n1841425222","n1820939729","n1820937665","n1820937838","n1820937739","n1820938780","n1820937821","n1820938825","n1820939055","n1820939485","n1820938041","n1820938746","n1820939562","n1820938459","n1820939489","n1820938050","n1820937980","n1820937695","n1820938413","n1820938555","n1820937703","n1820938536","n1820938196","n1820938287","n1820938169","n1820939279","n1820938531","n1820938959","n1820939741","n1820938665","n1820938963","n1820939611","n1820937653","n1820939618","n1820939492","n1820938600","n1820938628","n1820939312","n1820939616","n1820937738","n1820939001","n1820939062","n1820938794","n1820938558","n1820937822","n1820937532","n1820939073","n1820938200","n1820938241","n1820938968","n1820938927","n1820938306","n1820937630","n1820938456","n1820937694","n1820938908","n1820939076","n1820937522","n1820939659","n1820938522","n1820939318","n1820938932","n1820938841","n1820937579","n1820937540","n1820938560","n1821139530","n1820938964","n1820937662","n1820939281","n1821139533","n1820937797","n1821139532","n1820939751","n1821139531","n1820939291","n1820938420","n1820939696","n1820938904","n1820938484","n1820939448","n1820939009","n1820938735","n1820938986","n1820938937","n1820939030","n1820938734","n1820938745","n1820939106","n1820938987","n1820937858","n1820938673","n1820938620","n1820937808","n1820937700","n1820939573","n1820938540","n1820937661","n1820937570","n1820938396","n1820937875","n1820939048","n1820938233","n1820938793","n1820939584","n1820938412","n1820938394","n1820937846","n1820938800","n1820938690","n1820939331","n1820939630","n1820938762","n1820938710","n1820939322","n1820938992","n1821137608","n1821137607","n1820937924","n1820939139","n1820939463","n1820939574","n1820938294","n1820938071","n1820938307","n1820938061","n1820939260","n1820937899","n1820938310","n1820938983","n1820937530","n1820938993","n1820938890","n1820937915","n1820938231","n1820938040","n1820938920","n1820939585","n1820938135","n1820939700","n1820937824","n1820939667","n1820937930","n1820938134","n1820937551","n1820939405","n1820938232","n1820937716","n1820937848","n1820939765","n1820939068","n1820939766","n1820937933","n1820937720","n1820939222","n1820939772","n1820939022","n1820939732","n1820937702","n1820937691","n1820938945","n1820937756","n1820938451","n1820938410","n1820938798","n1820937945","n1820937654","n1820938598","n1820938836","n1820937571","n1820937556","n1820938994","n1820938919","n1820938863","n1820939064","n1820938018","n1820937658","n1820937537","n1820938142","n1820938666","n1820937535","n1820939571","n1820938465","n1820939638","n1820937533","n1820939656","n1820939422","n1820938109","n1820938405","n1820938028","n1820937649","n1820938829","n1820939031","n1820939155","n1820938350","n1820938463","n1820938425","n1820939047","n1820938831","n1820938494","n1820937697","n1820938504","n1820938900","n1820937784","n1820938414","n1820938076","n1820938723","n1820937722","n1820938739","n1820937791","n1820938985","n1820938352","n1820938293","n1820938274","n1820939692","n1820937871","n1820939059","n1820938868","n1820937877","n1820937743","n1820938429","n1820937545","n1820937575","n1820938302","n1820938505","n1820938916","n1820938374","n1820938329","n1820937790","n1820939735","n1820938930","n1820937995","n1820938512","n1820938130","n1820938194","n1820938671","n1820938802","n1820937542","n1820937602","n1820939069","n1820938901","n1820939654","n1820937727","n1820939569","n1820938375","n1820939306","n1820938479","n1820938376","n1820938667","n1820937766","n1820939467","n1820939567","n1820937806","n1820938943","n1820938931","n1820937745","n1820939452","n1820938738","n1820938053","n1820939653","n1820938640","n1820937604","n1820937536","n1820938701","n1820939625","n1820939744","n1820939572","n1820937577","n1820937541","n1820938891","n1820937597","n1820938469","n1820939194","n1820937539","n1820938911","n1820939017","n1820939650","n1820939103","n1820939578","n1820938132","n1820937549","n1820938634","n1820939743","n1820937544","n1820937826","n1820937598","n1820937547","n1820938032","n1820939142"]},"w17963021":{"id":"w17963021","tags":{"highway":"residential"},"nodes":["n185948706","n185948708","n185948710"]},"w203974069":{"id":"w203974069","tags":{"amenity":"shelter","area":"yes","building":"yes","shelter_type":"picnic_shelter"},"nodes":["n2139870431","n2139870432","n2139870433","n2139870434","n2139870431"]},"w209816575":{"id":"w209816575","tags":{"area":"yes","building":"yes"},"nodes":["n2199856288","n2199856289","n2199856290","n2199856291","n2199856292","n2199856293","n2199856294","n2199856295","n2199856296","n2199856297","n2199856298","n2199856299","n2199856300","n2199856301","n2199856302","n2199856303","n2199856288"]},"w203841838":{"id":"w203841838","tags":{"area":"yes","natural":"water"},"nodes":["n2138493826","n2138493827","n2138493828","n2138493829","n2138493830","n2138493831","n2138493833","n2138493832","n2138493826"]},"w203972937":{"id":"w203972937","tags":{"highway":"path","name":"Riverwalk Trail","surface":"asphalt","width":"3"},"nodes":["n2139858882","n2139858883","n2139858884","n2139858885","n2139858886","n2139858887","n2139858882","n2139858888","n2139858889","n2139858890","n2139858891","n2139858892","n2139858893","n2139858894","n2139858895","n2139858896","n2139858897","n2139858898","n2139858899","n2139858900","n2139858901","n2139858902","n2139858903","n2139858986","n2139858904","n2139858995","n2139858905","n2139858906","n2139858907","n2139858908","n2139858909","n2139858910","n2139858911","n2139858912","n2139858913","n2139858914","n2139858915","n2139858916","n2139858917","n2139858918","n2139858919","n2139858920","n2139858921","n2139858922","n2139858923","n2139858924","n2139858925","n2139858926","n2139858927","n2139858982","n2139858928","n2139858929","n2139858930","n2139858931","n2139858932","n2139858981","n2139858933","n2139858934","n2139858935","n2139858936","n2139858937","n2139858938","n2139858939","n2139858940","n2139858941","n2139858942","n2139858943","n2140006437","n2139858964","n2139858944","n2139858966","n2139858945","n2139858946","n2139858947","n2139858948","n2139858949","n2139858950","n2139858951"]},"w17964015":{"id":"w17964015","tags":{"highway":"residential"},"nodes":["n185954680","n185954683","n185954685","n185954687","n185954689","n185954690","n185954691","n2139870379","n2139870456","n185954692","n185954693","n185954695"]},"w17967315":{"id":"w17967315","tags":{"highway":"residential","name":"South Andrews Street"},"nodes":["n185981999","n185974477","n185964963"]},"w203974071":{"id":"w203974071","tags":{"highway":"footway"},"nodes":["n2139870439","n2139870440","n2139870441","n2139870442","n2139870443","n2139870444","n2139870445","n2139870446","n2139870447","n2139870448","n2139870449"]},"w170848824":{"id":"w170848824","tags":{"name":"Rocky River","waterway":"river"},"nodes":["n1819858503","n1819858531","n1819858526","n1819858518","n1819858505","n1819858508","n1819858512","n1819858514","n1819858528","n1819858509","n1819858511","n1819858507","n1819858521"]},"w203986458":{"id":"w203986458","tags":{"amenity":"shelter","area":"yes","shelter_type":"picnic_shelter"},"nodes":["n2139989357","n2139989359","n2139989360","n2139989362","n2139989357"]},"w170844917":{"id":"w170844917","tags":{"waterway":"riverbank"},"nodes":["n1819805911","n1819805690","n1819805812","n1819805766","n1819805802","n1819805885","n1819805626","n1819805842","n1819805715","n1819805694","n1819805618","n1819805629","n1819805731","n1819805636","n1819805878","n1819805718","n1819805798","n1819849057","n1819805666","n1819805852","n1819805805","n1819805789","n1819805868","n1819805680","n1819805918","n1819848888","n1819805762","n2139989328","n1819805907","n2139989330","n1819805915","n1819858521","n1819805854","n1819805876","n1819805864","n1819805922","n2139859004","n1819805702","n2139859003","n1819805614","n1819805792","n1819805786","n1819805777","n1819805645","n1819805838","n1819805889","n1819805795","n1819805707","n1819805774","n1819805808","n1819805810","n1819805724","n1819805676","n1819805728","n1819805783","n1819805687","n1819805727","n2189123379","n1819805632","n1819805641","n1819805760","n1819805887","n1819805861","n1819805722","n1819805880","n2139982405","n2139982399","n2139982400","n1819805770","n2139982402","n2139982403","n2139982401","n1819805780","n1819805834","n2139982406","n1819805698","n1819805647","n1819805870","n1819805683","n1819805622","n1819805639","n1819805858","n1819805643","n1819805673","n1819805925","n1819805849","n1819805711","n1819805846","n1819805669","n1819805883","n1819805814","n1819805873","n1819805911"]},"w17967326":{"id":"w17967326","tags":{"highway":"residential","name":"North Constantine Street"},"nodes":["n185985217","n185985219","n185985221","n185985222","n185985223","n185985225","n2140006431","n185985227","n185985229","n185985231","n185985233","n185985235","n185985238","n185985240","n2140018998","n185964965"]},"w134150789":{"id":"w134150789","tags":{"highway":"primary","name":"West Michigan Avenue","old_ref":"US 131","ref":"US 131 Business;M 60"},"nodes":["n185964971","n2139870406","n185964972"]},"w17966400":{"id":"w17966400","tags":{"highway":"tertiary","name":"South Constantine Street"},"nodes":["n185958672","n185964965"]},"w203974066":{"id":"w203974066","tags":{"highway":"service","service":"parking_aisle"},"nodes":["n2139870417","n2139870418","n2139870420","n2139870419"]},"w17965998":{"id":"w17965998","tags":{"name":"Conrail Railroad","railway":"rail"},"nodes":["n185972775","n185972777","n185972779","n185972781","n185972783","n185972785","n185972787","n185972788","n185972789","n185972790","n185972791","n185972793","n185972795","n185972797","n185972798","n185972800","n185972802","n185972805","n185972807","n185972809","n185972811","n185972813","n185972814","n185972815","n185972816","n185972817","n185972819","n185972821","n185972824","n185972826","n185972830","n185972832","n185972834","n185972835","n185972836","n185972839","n185990434","n2114807572","n2114807568","n185972845","n2114807583","n185972847","n185972849","n185972851","n2114807578","n1475293254","n2114807593","n1475293226","n185972862","n2114807565","n185951869","n1475293234","n1475293252","n185972868","n1475293264","n1475293222","n185972878","n1475293261","n185972882","n185972885","n1475293260","n1475293240","n185972891","n185972895","n185972897","n185972899","n2130304159","n1475284023","n185972903"]},"w134150795":{"id":"w134150795","tags":{"bridge":"yes","highway":"primary","name":"West Michigan Avenue","old_ref":"US 131","ref":"US 131 Business;M 60"},"nodes":["n185964970","n185964971"]},"w203974067":{"id":"w203974067","tags":{"highway":"service","service":"parking_aisle"},"nodes":["n2139870420","n2139870421"]},"w170995908":{"id":"w170995908","tags":{"highway":"residential","name":"Thomas Street"},"nodes":["n1821006702","n1821006700","n1821006698","n2139858990","n1821006716","n1821006725","n1821006712","n1821006704","n1821006708","n1821006710","n1821006706"]},"w17965834":{"id":"w17965834","tags":{"highway":"residential","name":"Spring Street"},"nodes":["n185971361","n185971364","n185971366","n185971368","n185954695","n185964968"]},"w203974070":{"id":"w203974070","tags":{"amenity":"shelter","area":"yes","building":"yes","shelter_type":"picnic_shelter"},"nodes":["n2139870435","n2139870436","n2139870437","n2139870438","n2139870435"]},"w203989879":{"id":"w203989879","tags":{"highway":"service"},"nodes":["n2140018998","n2140018999","n2140019000"]},"w203974062":{"id":"w203974062","tags":{"amenity":"parking","area":"yes"},"nodes":["n2139870387","n2139870388","n2139870389","n2139870390","n2139870391","n2139870392","n2139870397","n2139870393","n2139870396","n2139870395","n2139870394","n2139870387"]},"w203974061":{"id":"w203974061","tags":{"bridge":"yes","highway":"footway"},"nodes":["n2139870382","n2139870383"]},"w203049587":{"id":"w203049587","tags":{"area":"yes","name":"Scidmore Park Petting Zoo","tourism":"zoo","zoo":"petting_zoo"},"nodes":["n2130304133","n2130304136","n2130304138","n2130304140","n2130304142","n2130304144","n2130304146","n2130304147","n2130304148","n2130304149","n2130304150","n2130304151","n2130304133"]},"w203972941":{"id":"w203972941","tags":{"highway":"path"},"nodes":["n2139858982","n2139858983","n2139858984","n2139858985","n2139858927"]},"w203974065":{"id":"w203974065","tags":{"highway":"service"},"nodes":["n2139870406","n2139870407","n2139870408","n2139870417","n2139870409","n2139870410","n2139870411","n2139870412","n2139870426","n2139870413","n2139870414","n2139870415","n2139870419","n2139870416","n2139870421","n2139870408"]},"w203972940":{"id":"w203972940","tags":{"highway":"path","name":"Riverwalk Trail"},"nodes":["n2139858934","n2139858967","n2139858968","n2139858969","n2139858970","n2139858971","n2139858972","n2139858973","n2139858974","n2139858975","n2139858976","n2139858977","n2139858978","n2139858979","n2139858980","n2139858981"]},"w203974072":{"id":"w203974072","tags":{"highway":"footway"},"nodes":["n2139858925","n2139870450","n2139870453","n2139870451","n2139870452","n2139870441"]},"w203974074":{"id":"w203974074","tags":{"highway":"footway"},"nodes":["n2139870454","n2139870456","n2139870429"]},"w203974060":{"id":"w203974060","tags":{"highway":"footway"},"nodes":["n2139870383","n2139870384","n2139870422","n2139870385","n2139870386","n2139870388"]},"w203841837":{"id":"w203841837","tags":{"area":"yes","natural":"water"},"nodes":["n2138493807","n2138493808","n2138493809","n2138493810","n2138493811","n2138493812","n2138493813","n2138493814","n2138493815","n2138493816","n2138493825","n2138493817","n2138493824","n2138493818","n2138493819","n2138493820","n2138493821","n2138493822","n2138493823","n2138493807"]},"w134150845":{"id":"w134150845","tags":{"bridge":"yes","name":"Conrail Railroad","railway":"rail"},"nodes":["n185972903","n185972905"]},"w203974059":{"id":"w203974059","tags":{"highway":"footway"},"nodes":["n2139870430","n2139870439","n2139870429","n2139870428","n2139870379","n2139870455","n2139870380","n2139870381","n2139858925","n2139870382"]},"w203986457":{"id":"w203986457","tags":{"area":"yes","leisure":"park","name":"Scidmore Park"},"nodes":["n2139989333","n2139989335","n2139989337","n2139989339","n1819805762","n2139989328","n1819805907","n2139989330","n1819805915","n2139989341","n2139989344","n2139989346","n2139989348","n2139989350","n2139989351","n2139989353","n2139989355","n2139989333"]},"w170848331":{"id":"w170848331","tags":{"name":"Rocky River","waterway":"river"},"nodes":["n1819848937","n1819849104","n1819849076","n1819849183","n1819848928","n1819848972","n1819848948","n1819848971","n1819848859","n1819849008","n1819848889","n1819849026","n1819849094","n1819849083","n1819849079","n1819849187","n1819848992","n1819849060","n1819849056","n1819849071","n1819849067","n1819849048","n1819849036","n1819849150","n1819849075","n1819849051","n1819849062","n1819848926","n1819849035","n1819848987","n1819849012","n1819848933","n1819848996","n1819848990","n1819849005","n1819849021","n1819848892","n1819849092","n1819848863","n1819848922","n1819848858","n1819848855","n1819848974","n1819848953","n1819849019","n1819849049","n1819848979","n1819849140","n1819849193","n1819849147","n1819849151","n1819849163","n1819849023","n1819848878","n1819849004","n1819848857","n1819848879","n1819849041","n1819849165","n1819849107","n1819849156","n1819848934","n1819848914","n1819848955","n1819848931","n1819848927","n1819849084","n1819849169","n1819849045","n1819848945","n1819849095","n1819848924","n1819849171","n1819849141","n1819849046","n1819849197","n1819849011","n1819849108","n1819849158","n1819849160","n1819848870","n1819849006","n1819849157","n1819848993","n1819848970","n1819849202","n1819848903","n1819848975","n1819848849","n1819849025","n1819849105","n1819849033","n1819849176","n1819849099","n1819849086","n1819848960","n1819848961","n1819849001","n1819848980","n1819849038","n1819848854","n1819849127","n1819849170","n1819849139","n1819848873","n1819848929","n1819849201","n1819849121","n1819849031","n1819849131","n1819848875","n1819849080","n1819849066","n1819849081","n1819849096","n1819849172","n1819849114","n1819849182","n1819848905","n1819849054","n1819848920","n1819848851","n1819848968","n1819848917","n1819849111","n1819849119","n1819849074","n1819848893","n1819849129","n1819848850","n1819848956","n1819849154","n1819848877","n1819848986","n1819849191","n1819848952","n1819848954","n1819848942","n1819849028","n1819849195","n1819848938","n1819848962","n1819849070","n1819849034","n1819849052","n1819849059","n1819848916","n1819849162","n1819849167","n1819849093","n1819849030","n1819849002","n1819849161","n1819848886","n1819848958","n1819849064","n1819849112","n1819849148","n1819848856","n1819848976","n1819848977","n1819849144","n1819848918","n1819849200","n1819848919","n1819849042","n1819849166","n1819849186","n1819849152","n1819849058","n1819849185","n1819849199","n1819849053","n1819849194","n1819849068","n1819849146","n1819849174","n1819848967","n1819848932","n1819849155","n1819849198","n1819848964","n1819848894","n1819848969","n1819849184","n1819849055","n1819849179","n1819848865","n1819848860","n1819849082","n1819848966","n1819849040","n1819849069","n1819849078","n1819849077","n1819848904","n1819848959","n1819849133","n1819849089","n1819849000","n1819849124","n1819849032","n1819849097","n1819848939","n1819849072","n1819848915","n1819849196","n1819848946","n1819849047","n1819849029","n1819849164","n1819848994","n1819849022","n1819858513","n1819849126","n1819849063","n1819848941","n1819849085","n1819848871","n1819848943","n1819849192","n1819858501","n1819849159","n1819858523","n1819848901","n1819849189","n1819858503","n1819849065","n2139877106","n1819848909","n1819848930","n1819848888"]},"w17967397":{"id":"w17967397","tags":{"highway":"residential","name":"North Andrews Street"},"nodes":["n185964963","n185985217"]},"w17964497":{"id":"w17964497","tags":{"highway":"tertiary","name":"Constantine St"},"nodes":["n185958643","n185958645","n2139795852","n185958647","n185958649","n185958651","n185958653","n185958656","n185958658","n185958660","n185958662","n185958664","n185958666","n185958668","n185958670","n185948710","n185958672"]},"w203974068":{"id":"w203974068","tags":{"highway":"footway"},"nodes":["n2139870422","n2139870423","n2139870424","n2139870425","n2139870426","n2139870427"]},"w203974063":{"id":"w203974063","tags":{"amenity":"parking","area":"yes"},"nodes":["n2139870398","n2139870399","n2139870400","n2139870401","n2139870398"]},"w203986459":{"id":"w203986459","tags":{"amenity":"shelter","area":"yes","shelter_type":"picnic_shelter"},"nodes":["n2139989364","n2139989366","n2139989368","n2139989370","n2139989364"]},"w203988286":{"id":"w203988286","tags":{"area":"yes","leisure":"park","name":"Memory Isle Park"},"nodes":["n2140006331","n2140006334","n2140006336","n2140006338","n2140006340","n2140006342","n2140006344","n2140006346","n2140006348","n2140006351","n2140006353","n2140006355","n2140006357","n2140006359","n2140006361","n2140006363","n2140006364","n2140006365","n2140006395","n2140006366","n2140006401","n2140006397","n2140006399","n2140006331"]},"w203974073":{"id":"w203974073","tags":{"highway":"footway"},"nodes":["n2139870453","n2139870454","n2139870455"]},"w203974064":{"id":"w203974064","tags":{"amenity":"parking","area":"yes"},"nodes":["n2139870402","n2139870403","n2139870404","n2139870405","n2139870402"]},"n185966959":{"id":"n185966959","loc":[-85.642185,41.946411]},"n1475283980":{"id":"n1475283980","loc":[-85.6398249,41.9451425]},"n1475284013":{"id":"n1475284013","loc":[-85.6396448,41.9451666]},"n1475284042":{"id":"n1475284042","loc":[-85.6386382,41.9454789]},"n185975925":{"id":"n185975925","loc":[-85.6393332,41.9452388]},"n185975919":{"id":"n185975919","loc":[-85.6391279,41.9453044]},"n185975917":{"id":"n185975917","loc":[-85.6389034,41.9453872]},"n2140006369":{"id":"n2140006369","loc":[-85.6386163,41.9451631]},"n2140006370":{"id":"n2140006370","loc":[-85.6385144,41.9449357]},"n2140006417":{"id":"n2140006417","loc":[-85.6385785,41.9450299]},"n2140006419":{"id":"n2140006419","loc":[-85.6385781,41.9452152]},"n2189123361":{"id":"n2189123361","loc":[-85.6404948,41.947015]},"n2189123363":{"id":"n2189123363","loc":[-85.6395765,41.946495]},"n2189123365":{"id":"n2189123365","loc":[-85.6389347,41.9460875]},"n185966962":{"id":"n185966962","loc":[-85.644417,41.946364]},"n185975911":{"id":"n185975911","loc":[-85.637532,41.9458276]},"n185975913":{"id":"n185975913","loc":[-85.6376323,41.9457936]},"n185975915":{"id":"n185975915","loc":[-85.6383596,41.9455425]},"n185975932":{"id":"n185975932","loc":[-85.644403,41.945088]},"n185975934":{"id":"n185975934","loc":[-85.645486,41.945084]},"n185979974":{"id":"n185979974","loc":[-85.644381,41.943831]},"n2139795809":{"id":"n2139795809","loc":[-85.6464756,41.9450813]},"n2139795810":{"id":"n2139795810","loc":[-85.6466646,41.945174]},"n2139858952":{"id":"n2139858952","loc":[-85.6383567,41.9454039]},"n2139858953":{"id":"n2139858953","loc":[-85.6380506,41.9455301]},"n2139858954":{"id":"n2139858954","loc":[-85.6377321,41.9455546]},"n2139858955":{"id":"n2139858955","loc":[-85.6376571,41.9455245]},"n2139858956":{"id":"n2139858956","loc":[-85.6375859,41.9454544]},"n2139858957":{"id":"n2139858957","loc":[-85.6376686,41.9453185]},"n2139858958":{"id":"n2139858958","loc":[-85.6378936,41.9451712]},"n2139858959":{"id":"n2139858959","loc":[-85.6379225,41.9450825]},"n2139858960":{"id":"n2139858960","loc":[-85.6379302,41.9447564]},"n2139858961":{"id":"n2139858961","loc":[-85.6379763,41.9446963]},"n2139858962":{"id":"n2139858962","loc":[-85.6380436,41.9446706]},"n2139858963":{"id":"n2139858963","loc":[-85.6381286,41.9445969]},"n2139858965":{"id":"n2139858965","loc":[-85.6382523,41.9444134]},"n2140006367":{"id":"n2140006367","loc":[-85.6380923,41.9454418]},"n2140006368":{"id":"n2140006368","loc":[-85.6384089,41.9453146]},"n2140006372":{"id":"n2140006372","loc":[-85.6383252,41.9447706]},"n2140006374":{"id":"n2140006374","loc":[-85.6381033,41.9447436]},"n2140006376":{"id":"n2140006376","loc":[-85.6379759,41.9447815]},"n2140006378":{"id":"n2140006378","loc":[-85.6379832,41.9448654]},"n2140006380":{"id":"n2140006380","loc":[-85.6380632,41.9450738]},"n2140006382":{"id":"n2140006382","loc":[-85.6380414,41.9452064]},"n2140006389":{"id":"n2140006389","loc":[-85.6379068,41.9453092]},"n2140006391":{"id":"n2140006391","loc":[-85.637925,41.9453904]},"n2140006393":{"id":"n2140006393","loc":[-85.6379977,41.94545]},"n2189123275":{"id":"n2189123275","loc":[-85.6371346,41.9462544]},"n2189123278":{"id":"n2189123278","loc":[-85.6368371,41.9466153]},"n2189123280":{"id":"n2189123280","loc":[-85.6379537,41.9489088]},"n2189123282":{"id":"n2189123282","loc":[-85.6383816,41.9497858]},"n2189123285":{"id":"n2189123285","loc":[-85.6393673,41.9512417]},"n2189123287":{"id":"n2189123287","loc":[-85.640554,41.9517766]},"n2189123289":{"id":"n2189123289","loc":[-85.6411,41.9522344]},"n2189123291":{"id":"n2189123291","loc":[-85.6417418,41.9526574]},"n2189123293":{"id":"n2189123293","loc":[-85.642321,41.9529407]},"n2189123295":{"id":"n2189123295","loc":[-85.6427697,41.9532278]},"n2189123297":{"id":"n2189123297","loc":[-85.6433332,41.9538254]},"n2189123300":{"id":"n2189123300","loc":[-85.6435785,41.9543648]},"n2189123301":{"id":"n2189123301","loc":[-85.6444394,41.9541048]},"n2189123303":{"id":"n2189123303","loc":[-85.6450603,41.954]},"n2189123312":{"id":"n2189123312","loc":[-85.6454829,41.9539108]},"n2189123314":{"id":"n2189123314","loc":[-85.6460464,41.9538526]},"n2189123315":{"id":"n2189123315","loc":[-85.6463178,41.9537167]},"n2189123316":{"id":"n2189123316","loc":[-85.646276,41.9534141]},"n2189123317":{"id":"n2189123317","loc":[-85.6459995,41.9531541]},"n2189123318":{"id":"n2189123318","loc":[-85.645222,41.9531929]},"n2189123319":{"id":"n2189123319","loc":[-85.6447316,41.9531813]},"n2189123320":{"id":"n2189123320","loc":[-85.6440637,41.9532977]},"n2189123321":{"id":"n2189123321","loc":[-85.6438185,41.9531774]},"n2189123322":{"id":"n2189123322","loc":[-85.6440011,41.9528398]},"n2189123323":{"id":"n2189123323","loc":[-85.6442672,41.9525914]},"n2189123324":{"id":"n2189123324","loc":[-85.6442881,41.9523276]},"n2189123326":{"id":"n2189123326","loc":[-85.644262,41.952153]},"n2189123328":{"id":"n2189123328","loc":[-85.6441681,41.9520404]},"n2189123330":{"id":"n2189123330","loc":[-85.6442098,41.9517494]},"n2189123333":{"id":"n2189123333","loc":[-85.6438498,41.9515864]},"n2189123336":{"id":"n2189123336","loc":[-85.6435889,41.9513225]},"n2189123339":{"id":"n2189123339","loc":[-85.6425349,41.9510315]},"n2189123342":{"id":"n2189123342","loc":[-85.6422688,41.9508802]},"n2189123345":{"id":"n2189123345","loc":[-85.6418775,41.9508142]},"n2189123348":{"id":"n2189123348","loc":[-85.6415488,41.9508064]},"n2189123351":{"id":"n2189123351","loc":[-85.6411027,41.9505488]},"n2189123353":{"id":"n2189123353","loc":[-85.6410374,41.9498208]},"n2189123355":{"id":"n2189123355","loc":[-85.6410061,41.9494327]},"n2189123357":{"id":"n2189123357","loc":[-85.6411522,41.9482569]},"n2189123359":{"id":"n2189123359","loc":[-85.6410548,41.9473036]},"n2189123368":{"id":"n2189123368","loc":[-85.6380216,41.9458974]},"n2189123370":{"id":"n2189123370","loc":[-85.6386721,41.9507782]},"w17968193":{"id":"w17968193","tags":{"highway":"residential","name":"French St"},"nodes":["n185970906","n185982877","n185967774","n185985823","n185979974"]},"w203972939":{"id":"w203972939","tags":{"highway":"path"},"nodes":["n2139858965","n2139858966"]},"w203988289":{"id":"w203988289","tags":{"area":"yes","natural":"water"},"nodes":["n2140006367","n2140006368","n2140006419","n2140006369","n2140006417","n2140006370","n2140006372","n2140006374","n2140006376","n2140006378","n2140006380","n2140006382","n2140006389","n2140006391","n2140006393","n2140006367"]},"w208640157":{"id":"w208640157","tags":{"area":"yes","natural":"wetland"},"nodes":["n1819849029","n2189123275","n2189123278","n2189123280","n2189123282","n2189123370","n2189123285","n2189123287","n2189123289","n2189123291","n2189123293","n2189123295","n2189123297","n2189123300","n2189123301","n2189123303","n2189123312","n2189123314","n2189123315","n2189123316","n2189123317","n2189123318","n2189123319","n2189123320","n2189123321","n2189123322","n2189123323","n2189123324","n2189123326","n2189123328","n2189123330","n2189123333","n2189123336","n2189123339","n2189123342","n2189123345","n2189123348","n2189123351","n2189123353","n2189123355","n2189123357","n2189123359","n2189123361","n2189123363","n2189123365","n2189123368","n1819849029"]},"w17966281":{"id":"w17966281","tags":{"highway":"residential","name":"Pealer St"},"nodes":["n185975911","n185975913","n185975915","n1475284042","n185975917","n185975919","n185975925","n185970909","n1475284013","n1475283980","n185975928","n185967775","n185975930","n185975932","n185975934","n2139795809","n2139795810"]},"w17965353":{"id":"w17965353","tags":{"highway":"residential","name":"Yauney St"},"nodes":["n185966958","n185966959","n185966960","n185966962"]},"w203972938":{"id":"w203972938","tags":{"highway":"path","name":"Riverwalk Trail"},"nodes":["n2139858964","n2139858965","n2139858963","n2139858962","n2139858961","n2139858960","n2139858959","n2139858958","n2139858957","n2139858956","n2139858955","n2139858954","n2139858953","n2139858952","n2139858951"]},"n354002665":{"id":"n354002665","loc":[-85.6366599,41.9444923],"tags":{"name":"Memory Isle","place":"island"}},"n354031301":{"id":"n354031301","loc":[-85.635,41.9463889],"tags":{"amenity":"post_office","name":"Three Rivers Post Office"}},"n185963454":{"id":"n185963454","loc":[-85.633686,41.946072]},"n185963455":{"id":"n185963455","loc":[-85.633815,41.946131]},"n185963456":{"id":"n185963456","loc":[-85.633951,41.946174]},"n185978375":{"id":"n185978375","loc":[-85.634385,41.94559]},"n185978377":{"id":"n185978377","loc":[-85.634544,41.945725]},"n185978379":{"id":"n185978379","loc":[-85.634573,41.945764]},"n185978381":{"id":"n185978381","loc":[-85.634616,41.945849]},"n185978383":{"id":"n185978383","loc":[-85.634629,41.945893]},"n185984011":{"id":"n185984011","loc":[-85.636058,41.946201]},"n185984013":{"id":"n185984013","loc":[-85.636112,41.946366]},"n185984015":{"id":"n185984015","loc":[-85.636143,41.946551]},"n185988237":{"id":"n185988237","loc":[-85.6354162,41.946044]},"n185988969":{"id":"n185988969","loc":[-85.635374,41.945325]},"n185988971":{"id":"n185988971","loc":[-85.635643,41.945585]},"n185988972":{"id":"n185988972","loc":[-85.635853,41.94586]},"n1475283992":{"id":"n1475283992","loc":[-85.6372968,41.9459007]},"n1475284011":{"id":"n1475284011","loc":[-85.6359415,41.9459797]},"n1475284019":{"id":"n1475284019","loc":[-85.6364433,41.9460423]},"n185984009":{"id":"n185984009","loc":[-85.6360524,41.9460485]},"n185988239":{"id":"n185988239","loc":[-85.6358187,41.9460423]},"n185988243":{"id":"n185988243","loc":[-85.6366156,41.9460282]},"n185988244":{"id":"n185988244","loc":[-85.6368316,41.9460046]},"n185988245":{"id":"n185988245","loc":[-85.6370133,41.9459704]},"n185988241":{"id":"n185988241","loc":[-85.636291,41.9460461]},"n185964976":{"id":"n185964976","loc":[-85.633923,41.9434157]},"n185964980":{"id":"n185964980","loc":[-85.6333656,41.9437293]},"n185978388":{"id":"n185978388","loc":[-85.6346449,41.9460571]},"n1819858504":{"id":"n1819858504","loc":[-85.6365343,41.9447926]},"n1819858506":{"id":"n1819858506","loc":[-85.6370546,41.9451882]},"n1819858516":{"id":"n1819858516","loc":[-85.6358369,41.9444654]},"n1819858519":{"id":"n1819858519","loc":[-85.6361534,41.9446176]},"n1819858525":{"id":"n1819858525","loc":[-85.6368025,41.9449442]},"n1819858527":{"id":"n1819858527","loc":[-85.6334199,41.9457495]},"n185963452":{"id":"n185963452","loc":[-85.633564,41.9458519]},"n185963453":{"id":"n185963453","loc":[-85.6336152,41.9459804]},"n185963451":{"id":"n185963451","loc":[-85.6332888,41.9456871]},"n2130304152":{"id":"n2130304152","loc":[-85.6359466,41.9454599]},"n2130304153":{"id":"n2130304153","loc":[-85.6362773,41.9452683]},"n2130304154":{"id":"n2130304154","loc":[-85.6352028,41.9442868]},"n2130304155":{"id":"n2130304155","loc":[-85.6348756,41.9444769]},"n2130304156":{"id":"n2130304156","loc":[-85.6349723,41.9444207]},"n2130304157":{"id":"n2130304157","loc":[-85.6338698,41.9434443]},"n2130304158":{"id":"n2130304158","loc":[-85.635094,41.9451026]},"n2130304160":{"id":"n2130304160","loc":[-85.6353716,41.9449322]},"n2130304162":{"id":"n2130304162","loc":[-85.6365942,41.9459352]},"n2130304163":{"id":"n2130304163","loc":[-85.6369006,41.9457469]},"n2130304164":{"id":"n2130304164","loc":[-85.6363292,41.9452278]},"n2130304165":{"id":"n2130304165","loc":[-85.6360248,41.9454175]},"n2139824683":{"id":"n2139824683","loc":[-85.6339825,41.9446441]},"n2139824689":{"id":"n2139824689","loc":[-85.6340437,41.9446925]},"n2139824702":{"id":"n2139824702","loc":[-85.6340961,41.9447551]},"n2139824705":{"id":"n2139824705","loc":[-85.6337467,41.944809]},"n2139824707":{"id":"n2139824707","loc":[-85.6341598,41.9448129]},"n2139824710":{"id":"n2139824710","loc":[-85.6342771,41.9448223]},"n2139824712":{"id":"n2139824712","loc":[-85.6346058,41.944841]},"n2139824713":{"id":"n2139824713","loc":[-85.633808,41.9448574]},"n2139824714":{"id":"n2139824714","loc":[-85.6340889,41.9448589]},"n2139824716":{"id":"n2139824716","loc":[-85.6343335,41.944871]},"n2139824717":{"id":"n2139824717","loc":[-85.6343341,41.9448717]},"n2139824720":{"id":"n2139824720","loc":[-85.6338757,41.9449069]},"n2139824721":{"id":"n2139824721","loc":[-85.6341445,41.9449071]},"n2139824724":{"id":"n2139824724","loc":[-85.6334787,41.9449262]},"n2139824726":{"id":"n2139824726","loc":[-85.6347119,41.9449332]},"n2139824727":{"id":"n2139824727","loc":[-85.6347175,41.9449418]},"n2139824728":{"id":"n2139824728","loc":[-85.6344284,41.9449538]},"n2139824729":{"id":"n2139824729","loc":[-85.6339339,41.9449573]},"n2139824730":{"id":"n2139824730","loc":[-85.6339179,41.9449682]},"n2139824732":{"id":"n2139824732","loc":[-85.6335472,41.9449895]},"n2139824733":{"id":"n2139824733","loc":[-85.6339736,41.9450164]},"n2139824735":{"id":"n2139824735","loc":[-85.6336034,41.9450415]},"n2139824736":{"id":"n2139824736","loc":[-85.6348317,41.945043]},"n2139824737":{"id":"n2139824737","loc":[-85.63403,41.9450651]},"n2139824738":{"id":"n2139824738","loc":[-85.6336611,41.9450949]},"n2139824740":{"id":"n2139824740","loc":[-85.6336582,41.9450966]},"n2139824744":{"id":"n2139824744","loc":[-85.6331702,41.9451107]},"n2139824745":{"id":"n2139824745","loc":[-85.6333388,41.9451142]},"n2139824746":{"id":"n2139824746","loc":[-85.6337131,41.9451341]},"n2139824747":{"id":"n2139824747","loc":[-85.6337021,41.9451372]},"n2139824748":{"id":"n2139824748","loc":[-85.6341244,41.9451472]},"n2139824749":{"id":"n2139824749","loc":[-85.6333952,41.945166]},"n2139824750":{"id":"n2139824750","loc":[-85.633395,41.9451661]},"n2139824751":{"id":"n2139824751","loc":[-85.6346258,41.9451725]},"n2139824752":{"id":"n2139824752","loc":[-85.6332387,41.9451741]},"n2139824753":{"id":"n2139824753","loc":[-85.6346901,41.9451853]},"n2139824754":{"id":"n2139824754","loc":[-85.6346611,41.9452035]},"n2139824755":{"id":"n2139824755","loc":[-85.6346574,41.9452059]},"n2139824756":{"id":"n2139824756","loc":[-85.6345611,41.9452133]},"n2139824757":{"id":"n2139824757","loc":[-85.633453,41.9452194]},"n2139824758":{"id":"n2139824758","loc":[-85.6335508,41.9452283]},"n2139824759":{"id":"n2139824759","loc":[-85.6347424,41.9452312]},"n2139824760":{"id":"n2139824760","loc":[-85.6342305,41.9452395]},"n2139824761":{"id":"n2139824761","loc":[-85.6342319,41.9452449]},"n2139824762":{"id":"n2139824762","loc":[-85.6334969,41.94526]},"n2139824763":{"id":"n2139824763","loc":[-85.63468,41.9452706]},"n2139824764":{"id":"n2139824764","loc":[-85.6346772,41.9452724]},"n2139824765":{"id":"n2139824765","loc":[-85.6338611,41.9452763]},"n2139824766":{"id":"n2139824766","loc":[-85.6347811,41.9452939]},"n2139824767":{"id":"n2139824767","loc":[-85.6347375,41.9453211]},"n2139824768":{"id":"n2139824768","loc":[-85.6339171,41.9453301]},"n2139824769":{"id":"n2139824769","loc":[-85.6348307,41.9453377]},"n2139824770":{"id":"n2139824770","loc":[-85.6347067,41.9453405]},"n2139824771":{"id":"n2139824771","loc":[-85.6343461,41.9453461]},"n2139824772":{"id":"n2139824772","loc":[-85.6343481,41.9453475]},"n2139824773":{"id":"n2139824773","loc":[-85.634805,41.9453538]},"n2139824774":{"id":"n2139824774","loc":[-85.6336997,41.9453692]},"n2139824775":{"id":"n2139824775","loc":[-85.6339709,41.9453818]},"n2139824776":{"id":"n2139824776","loc":[-85.6336229,41.9454134]},"n2139824777":{"id":"n2139824777","loc":[-85.6349022,41.9454141]},"n2139824778":{"id":"n2139824778","loc":[-85.6348854,41.9454246]},"n2139824779":{"id":"n2139824779","loc":[-85.6340286,41.9454373]},"n2139824780":{"id":"n2139824780","loc":[-85.6336963,41.9454572]},"n2139824781":{"id":"n2139824781","loc":[-85.6336789,41.9454672]},"n2139824782":{"id":"n2139824782","loc":[-85.6344933,41.945475]},"n2139824783":{"id":"n2139824783","loc":[-85.6340854,41.9454918]},"n2139824784":{"id":"n2139824784","loc":[-85.6350036,41.9455034]},"n2139824785":{"id":"n2139824785","loc":[-85.6337501,41.9455089]},"n2139824786":{"id":"n2139824786","loc":[-85.6337497,41.9455091]},"n2139824787":{"id":"n2139824787","loc":[-85.6345425,41.9455186]},"n2139824788":{"id":"n2139824788","loc":[-85.6341459,41.9455372]},"n2139824789":{"id":"n2139824789","loc":[-85.6341376,41.945542]},"n2139824790":{"id":"n2139824790","loc":[-85.6338394,41.9455462]},"n2139824791":{"id":"n2139824791","loc":[-85.6349171,41.9455588]},"n2139824792":{"id":"n2139824792","loc":[-85.6338074,41.9455646]},"n2139824793":{"id":"n2139824793","loc":[-85.6346229,41.9455894]},"n2139824794":{"id":"n2139824794","loc":[-85.6338983,41.9455995]},"n2139824795":{"id":"n2139824795","loc":[-85.6338962,41.9456007]},"n2139824796":{"id":"n2139824796","loc":[-85.6342475,41.9456348]},"n2139824797":{"id":"n2139824797","loc":[-85.6339505,41.9456497]},"n2139824798":{"id":"n2139824798","loc":[-85.6347243,41.9456788]},"n2139824799":{"id":"n2139824799","loc":[-85.635057,41.9456831]},"n2139824800":{"id":"n2139824800","loc":[-85.635287,41.9457056]},"n2139824801":{"id":"n2139824801","loc":[-85.6350753,41.9457068]},"n2139824802":{"id":"n2139824802","loc":[-85.6347753,41.9457252]},"n2139824803":{"id":"n2139824803","loc":[-85.6340521,41.9457473]},"n2139824804":{"id":"n2139824804","loc":[-85.6352875,41.9457611]},"n2139824805":{"id":"n2139824805","loc":[-85.6352941,41.9457611]},"n2139824806":{"id":"n2139824806","loc":[-85.6350758,41.9457623]},"n2139824807":{"id":"n2139824807","loc":[-85.6348194,41.9457638]},"n2139824808":{"id":"n2139824808","loc":[-85.635296,41.9459428]},"n2139824809":{"id":"n2139824809","loc":[-85.6348212,41.9459455]},"n2139832635":{"id":"n2139832635","loc":[-85.6354612,41.9448791]},"n2139832636":{"id":"n2139832636","loc":[-85.6360241,41.9453844]},"n2139832637":{"id":"n2139832637","loc":[-85.6361452,41.9453121]},"n2139832639":{"id":"n2139832639","loc":[-85.6355997,41.944797]},"n2139832641":{"id":"n2139832641","loc":[-85.6351346,41.9443541]},"n2139832647":{"id":"n2139832647","loc":[-85.6329883,41.9453692]},"n2139832653":{"id":"n2139832653","loc":[-85.6333643,41.9456293]},"n2139832663":{"id":"n2139832663","loc":[-85.6335394,41.9455339]},"n2139832665":{"id":"n2139832665","loc":[-85.6332375,41.9452476]},"n2139832667":{"id":"n2139832667","loc":[-85.6331664,41.9452161]},"n2139832669":{"id":"n2139832669","loc":[-85.6331144,41.9451875]},"n2139832671":{"id":"n2139832671","loc":[-85.6330779,41.9451274]},"n2139832673":{"id":"n2139832673","loc":[-85.6330664,41.9450802]},"n2139832678":{"id":"n2139832678","loc":[-85.6332218,41.9453585]},"n2139832686":{"id":"n2139832686","loc":[-85.6334246,41.945541]},"n2139832691":{"id":"n2139832691","loc":[-85.6329898,41.9454997]},"n2139832693":{"id":"n2139832693","loc":[-85.6343554,41.9443274]},"n2139832694":{"id":"n2139832694","loc":[-85.6336339,41.9437089]},"n2139832696":{"id":"n2139832696","loc":[-85.633532,41.9437708]},"n2139832697":{"id":"n2139832697","loc":[-85.6338316,41.9440868]},"n2139832698":{"id":"n2139832698","loc":[-85.6342258,41.9444141]},"n2139832699":{"id":"n2139832699","loc":[-85.6339164,41.9442166]},"n2139832700":{"id":"n2139832700","loc":[-85.6341389,41.944384]},"n2139832701":{"id":"n2139832701","loc":[-85.634235,41.9443259]},"n2139832702":{"id":"n2139832702","loc":[-85.633613,41.9437875]},"n2139832703":{"id":"n2139832703","loc":[-85.633915,41.9436132]},"n2139832704":{"id":"n2139832704","loc":[-85.6340019,41.9435613]},"n2139832706":{"id":"n2139832706","loc":[-85.6343197,41.9438427]},"n2139832708":{"id":"n2139832708","loc":[-85.6342361,41.9438936]},"n2139832709":{"id":"n2139832709","loc":[-85.6353839,41.9460401]},"n2139832710":{"id":"n2139832710","loc":[-85.6354032,41.9456763]},"n2139832711":{"id":"n2139832711","loc":[-85.6356839,41.9459252]},"n2139832712":{"id":"n2139832712","loc":[-85.6356109,41.945735]},"n2139832713":{"id":"n2139832713","loc":[-85.6353997,41.9457421]},"n2139832714":{"id":"n2139832714","loc":[-85.6353895,41.9459347]},"n2139832715":{"id":"n2139832715","loc":[-85.6334777,41.9436628]},"n2139832716":{"id":"n2139832716","loc":[-85.6333137,41.9435382]},"n2139832717":{"id":"n2139832717","loc":[-85.6330938,41.9435406]},"n2139832721":{"id":"n2139832721","loc":[-85.6333023,41.9434922]},"n2139832722":{"id":"n2139832722","loc":[-85.6330466,41.943623]},"n2139832723":{"id":"n2139832723","loc":[-85.6332746,41.9435624]},"n2139832724":{"id":"n2139832724","loc":[-85.6333511,41.9435176]},"n2139832725":{"id":"n2139832725","loc":[-85.6332241,41.9434001]},"n2139832726":{"id":"n2139832726","loc":[-85.6332355,41.9433686]},"n2139870373":{"id":"n2139870373","loc":[-85.6351783,41.9439117]},"n2139870374":{"id":"n2139870374","loc":[-85.6351431,41.9439217]},"n2139870375":{"id":"n2139870375","loc":[-85.6348853,41.9439117]},"n2139870376":{"id":"n2139870376","loc":[-85.6348317,41.9439105]},"n2139870377":{"id":"n2139870377","loc":[-85.6346384,41.944007]},"n2139870378":{"id":"n2139870378","loc":[-85.6345563,41.9440523]},"n2140006403":{"id":"n2140006403","loc":[-85.6359942,41.9450097]},"n2140006405":{"id":"n2140006405","loc":[-85.6363884,41.9446079]},"n2140006407":{"id":"n2140006407","loc":[-85.6362148,41.9447874]},"n2140006409":{"id":"n2140006409","loc":[-85.6379476,41.9445869]},"n2140006411":{"id":"n2140006411","loc":[-85.6378485,41.9445674]},"n2140006413":{"id":"n2140006413","loc":[-85.6378952,41.9444547]},"n2140006415":{"id":"n2140006415","loc":[-85.6379962,41.944477]},"n2140006421":{"id":"n2140006421","loc":[-85.6355248,41.9433702]},"n2140006423":{"id":"n2140006423","loc":[-85.6378471,41.9439233]},"n2140006425":{"id":"n2140006425","loc":[-85.6378913,41.9441238]},"n2140006426":{"id":"n2140006426","loc":[-85.6381674,41.9442289]},"n2140006427":{"id":"n2140006427","loc":[-85.6382359,41.9440975]},"n2140006428":{"id":"n2140006428","loc":[-85.6382071,41.9440252]},"n2140006429":{"id":"n2140006429","loc":[-85.6381409,41.9439973]},"n2140006430":{"id":"n2140006430","loc":[-85.6380569,41.9440153]},"n2140006433":{"id":"n2140006433","loc":[-85.6379071,41.9442467]},"n2140006435":{"id":"n2140006435","loc":[-85.6381634,41.9443125]},"n2140006436":{"id":"n2140006436","loc":[-85.6382407,41.944301]},"n2140006438":{"id":"n2140006438","loc":[-85.6382761,41.9442188]},"n2140006439":{"id":"n2140006439","loc":[-85.6382429,41.9441761]},"n2140006440":{"id":"n2140006440","loc":[-85.6382016,41.9441632]},"n2140006441":{"id":"n2140006441","loc":[-85.6378185,41.9439835]},"n2166205688":{"id":"n2166205688","loc":[-85.6349963,41.9444392]},"n2168544780":{"id":"n2168544780","loc":[-85.633944,41.945807]},"n2168544781":{"id":"n2168544781","loc":[-85.6340783,41.9458621]},"n2168544782":{"id":"n2168544782","loc":[-85.6338184,41.9457548]},"n2168544783":{"id":"n2168544783","loc":[-85.6339925,41.9459777]},"n2168544784":{"id":"n2168544784","loc":[-85.6337317,41.9458698]},"n2168544785":{"id":"n2168544785","loc":[-85.6337297,41.9460042]},"n2168544786":{"id":"n2168544786","loc":[-85.633919,41.9460797]},"n2168544787":{"id":"n2168544787","loc":[-85.6338672,41.9459263]},"n2168544788":{"id":"n2168544788","loc":[-85.6338246,41.9459853]},"n2168544789":{"id":"n2168544789","loc":[-85.6337615,41.9459601]},"n2168544790":{"id":"n2168544790","loc":[-85.6342079,41.9460399]},"n2168544791":{"id":"n2168544791","loc":[-85.6343346,41.9458503]},"n2168544792":{"id":"n2168544792","loc":[-85.6343759,41.9458116]},"n2168544793":{"id":"n2168544793","loc":[-85.6344394,41.9458109]},"n2168544795":{"id":"n2168544795","loc":[-85.6344827,41.945851]},"n2168544797":{"id":"n2168544797","loc":[-85.6344807,41.945969]},"n2168544798":{"id":"n2168544798","loc":[-85.6344404,41.9459697]},"n2168544799":{"id":"n2168544799","loc":[-85.6344413,41.9460333]},"n2168544800":{"id":"n2168544800","loc":[-85.6342173,41.9460705]},"n2168544801":{"id":"n2168544801","loc":[-85.6342162,41.9460392]},"n2168544802":{"id":"n2168544802","loc":[-85.6344251,41.9460351]},"n2168544805":{"id":"n2168544805","loc":[-85.6344257,41.9460507]},"n2168544807":{"id":"n2168544807","loc":[-85.6344721,41.9460498]},"n2168544809":{"id":"n2168544809","loc":[-85.6344754,41.9461427]},"n2168544811":{"id":"n2168544811","loc":[-85.6344311,41.9461435]},"n2168544813":{"id":"n2168544813","loc":[-85.6344317,41.9461592]},"n2168544815":{"id":"n2168544815","loc":[-85.6343708,41.9461604]},"n2168544817":{"id":"n2168544817","loc":[-85.6343715,41.9461786]},"n2168544819":{"id":"n2168544819","loc":[-85.6343229,41.9461795]},"n2168544821":{"id":"n2168544821","loc":[-85.6343222,41.9461606]},"n2168544823":{"id":"n2168544823","loc":[-85.6342476,41.9461621]},"n2168544825":{"id":"n2168544825","loc":[-85.6342444,41.94607]},"n2168544827":{"id":"n2168544827","loc":[-85.634138,41.9461632]},"n2168544829":{"id":"n2168544829","loc":[-85.6342016,41.9460703]},"n2168544830":{"id":"n2168544830","loc":[-85.6332929,41.9463092]},"n2168544831":{"id":"n2168544831","loc":[-85.633122,41.946239]},"n2168544832":{"id":"n2168544832","loc":[-85.6332954,41.9460055]},"n2168544833":{"id":"n2168544833","loc":[-85.6333954,41.9460466]},"n2168544834":{"id":"n2168544834","loc":[-85.6334044,41.9460345]},"n2168544835":{"id":"n2168544835","loc":[-85.6334594,41.9460571]},"n2168544836":{"id":"n2168544836","loc":[-85.6333871,41.9461544]},"n2168544837":{"id":"n2168544837","loc":[-85.633403,41.9461609]},"n2168544838":{"id":"n2168544838","loc":[-85.6341683,41.9464167]},"n2168544839":{"id":"n2168544839","loc":[-85.6341711,41.9463411]},"n2168544840":{"id":"n2168544840","loc":[-85.6344471,41.9463469]},"n2168544841":{"id":"n2168544841","loc":[-85.6344441,41.9464243]},"n2168544842":{"id":"n2168544842","loc":[-85.6343622,41.9464226]},"n2168544843":{"id":"n2168544843","loc":[-85.6343593,41.9464989]},"n2168544844":{"id":"n2168544844","loc":[-85.6342812,41.9464973]},"n2168544845":{"id":"n2168544845","loc":[-85.634283,41.9464504]},"n2168544846":{"id":"n2168544846","loc":[-85.6342609,41.9464499]},"n2168544847":{"id":"n2168544847","loc":[-85.6342621,41.9464187]},"n2168544848":{"id":"n2168544848","loc":[-85.6348414,41.9463396]},"n2168544849":{"id":"n2168544849","loc":[-85.6348387,41.9461872]},"n2168544850":{"id":"n2168544850","loc":[-85.6351186,41.9461844]},"n2168544851":{"id":"n2168544851","loc":[-85.635119,41.9462112]},"n2168544852":{"id":"n2168544852","loc":[-85.6351918,41.9462104]},"n2168544853":{"id":"n2168544853","loc":[-85.6351944,41.9463515]},"n2168544854":{"id":"n2168544854","loc":[-85.6351049,41.9463524]},"n2168544855":{"id":"n2168544855","loc":[-85.6351046,41.946337]},"n2189153180":{"id":"n2189153180","loc":[-85.6340369,41.9469572]},"n2189153181":{"id":"n2189153181","loc":[-85.6342531,41.946953]},"n2189153183":{"id":"n2189153183","loc":[-85.6348115,41.9465468]},"n2189153184":{"id":"n2189153184","loc":[-85.6348105,41.9464569]},"n2189153185":{"id":"n2189153185","loc":[-85.6351431,41.9464549]},"n2189153186":{"id":"n2189153186","loc":[-85.6351441,41.9465448]},"n2189153187":{"id":"n2189153187","loc":[-85.6350077,41.9465456]},"n2189153188":{"id":"n2189153188","loc":[-85.635008,41.9465721]},"n2189153189":{"id":"n2189153189","loc":[-85.6348965,41.9465727]},"n2189153190":{"id":"n2189153190","loc":[-85.6348962,41.9465463]},"n2189153191":{"id":"n2189153191","loc":[-85.6348963,41.9471586]},"n2189153192":{"id":"n2189153192","loc":[-85.6348944,41.947032]},"n2189153193":{"id":"n2189153193","loc":[-85.6350241,41.947031]},"n2189153194":{"id":"n2189153194","loc":[-85.635026,41.9471575]},"n2189153195":{"id":"n2189153195","loc":[-85.6352328,41.9471053]},"n2189153196":{"id":"n2189153196","loc":[-85.6352359,41.9469906]},"n2189153197":{"id":"n2189153197","loc":[-85.6353694,41.9469925]},"n2189153198":{"id":"n2189153198","loc":[-85.6353664,41.9471072]},"n2189153199":{"id":"n2189153199","loc":[-85.6348241,41.9469287]},"n2189153200":{"id":"n2189153200","loc":[-85.6348248,41.9468185]},"n2189153201":{"id":"n2189153201","loc":[-85.6351199,41.9468195]},"n2189153202":{"id":"n2189153202","loc":[-85.6351192,41.9469298]},"n2189153203":{"id":"n2189153203","loc":[-85.6347965,41.9468057]},"n2189153204":{"id":"n2189153204","loc":[-85.634792,41.9466044]},"n2189153205":{"id":"n2189153205","loc":[-85.6349483,41.9466025]},"n2189153206":{"id":"n2189153206","loc":[-85.6349493,41.9466448]},"n2189153207":{"id":"n2189153207","loc":[-85.6349753,41.9466445]},"n2189153208":{"id":"n2189153208","loc":[-85.6349743,41.9465995]},"n2189153209":{"id":"n2189153209","loc":[-85.6351173,41.9465977]},"n2189153210":{"id":"n2189153210","loc":[-85.6351219,41.9468015]},"n2189153211":{"id":"n2189153211","loc":[-85.6349806,41.9468032]},"n2189153212":{"id":"n2189153212","loc":[-85.6349794,41.9467519]},"n2189153213":{"id":"n2189153213","loc":[-85.6349521,41.9467523]},"n2189153214":{"id":"n2189153214","loc":[-85.6349532,41.9468037]},"n2189153215":{"id":"n2189153215","loc":[-85.6346302,41.9468381]},"n2189153216":{"id":"n2189153216","loc":[-85.6343028,41.9468449]},"n2189153217":{"id":"n2189153217","loc":[-85.6342006,41.9468297]},"n2189153218":{"id":"n2189153218","loc":[-85.6336698,41.9465918]},"n2189153219":{"id":"n2189153219","loc":[-85.6344663,41.9466639]},"n2189153220":{"id":"n2189153220","loc":[-85.6344639,41.9466015]},"n2189153221":{"id":"n2189153221","loc":[-85.6342283,41.9466065]},"n2189153222":{"id":"n2189153222","loc":[-85.6342303,41.9466587]},"n2189153223":{"id":"n2189153223","loc":[-85.6342843,41.9466575]},"n2189153224":{"id":"n2189153224","loc":[-85.6342851,41.9466794]},"n2189153225":{"id":"n2189153225","loc":[-85.6343475,41.9466781]},"n2189153226":{"id":"n2189153226","loc":[-85.634347,41.9466664]},"n2189153227":{"id":"n2189153227","loc":[-85.6354428,41.9470148]},"n2189153228":{"id":"n2189153228","loc":[-85.6354432,41.9468005]},"n2189153229":{"id":"n2189153229","loc":[-85.6360277,41.9468011]},"n2189153230":{"id":"n2189153230","loc":[-85.6360273,41.9470154]},"n2189153231":{"id":"n2189153231","loc":[-85.6354565,41.9465823]},"n2189153232":{"id":"n2189153232","loc":[-85.6354496,41.946218]},"n2189153233":{"id":"n2189153233","loc":[-85.6356355,41.9465788]},"n2189153234":{"id":"n2189153234","loc":[-85.6357155,41.9468008]},"n2189153235":{"id":"n2189153235","loc":[-85.6359539,41.9467969]},"n2189153236":{"id":"n2189153236","loc":[-85.6359561,41.9463036]},"n2189153237":{"id":"n2189153237","loc":[-85.6360129,41.9464793]},"n2189153238":{"id":"n2189153238","loc":[-85.6360152,41.9463898]},"n2189153239":{"id":"n2189153239","loc":[-85.6359607,41.9464928]},"n2189153240":{"id":"n2189153240","loc":[-85.6356903,41.9462227]},"n2189153242":{"id":"n2189153242","loc":[-85.6354163,41.946142]},"n2189153243":{"id":"n2189153243","loc":[-85.6357546,41.9462214]},"n2189153244":{"id":"n2189153244","loc":[-85.6357937,41.9462542]},"n2189153245":{"id":"n2189153245","loc":[-85.6358723,41.9467048]},"n2189153246":{"id":"n2189153246","loc":[-85.6361494,41.946757]},"n2189153247":{"id":"n2189153247","loc":[-85.6354173,41.9469082]},"n2189153248":{"id":"n2189153248","loc":[-85.635443,41.9469079]},"n2189153249":{"id":"n2189153249","loc":[-85.6360275,41.9469093]},"n2189153250":{"id":"n2189153250","loc":[-85.6361542,41.946915]},"n2189153251":{"id":"n2189153251","loc":[-85.6358654,41.9464843]},"n2189153252":{"id":"n2189153252","loc":[-85.6359549,41.9467499]},"n2189153253":{"id":"n2189153253","loc":[-85.6357172,41.9466335]},"n2189153254":{"id":"n2189153254","loc":[-85.6355644,41.9461768]},"n2189153255":{"id":"n2189153255","loc":[-85.6355655,41.946528]},"n2189153256":{"id":"n2189153256","loc":[-85.6357055,41.9465971]},"n2189153257":{"id":"n2189153257","loc":[-85.635869,41.9465971]},"n2189153259":{"id":"n2189153259","loc":[-85.6354561,41.9470278]},"n2189153260":{"id":"n2189153260","loc":[-85.6357961,41.9470233]},"n2189153261":{"id":"n2189153261","loc":[-85.6357977,41.9470907]},"n2189153262":{"id":"n2189153262","loc":[-85.6357297,41.9470916]},"n2189153263":{"id":"n2189153263","loc":[-85.635733,41.947233]},"n2189153264":{"id":"n2189153264","loc":[-85.6362674,41.9468637]},"n2189153265":{"id":"n2189153265","loc":[-85.6362646,41.9467047]},"n2189153266":{"id":"n2189153266","loc":[-85.6363267,41.9467047]},"n2189153267":{"id":"n2189153267","loc":[-85.6362633,41.9465848]},"n2189153268":{"id":"n2189153268","loc":[-85.6363805,41.9465468]},"n2189153269":{"id":"n2189153269","loc":[-85.6364604,41.9466842]},"n2189153270":{"id":"n2189153270","loc":[-85.6364604,41.9468647]},"n2199109756":{"id":"n2199109756","loc":[-85.6337134,41.9471841]},"n2199109757":{"id":"n2199109757","loc":[-85.6336514,41.94716]},"n2199109758":{"id":"n2199109758","loc":[-85.6337043,41.9470847]},"n2199109759":{"id":"n2199109759","loc":[-85.6335997,41.9470441]},"n2199109760":{"id":"n2199109760","loc":[-85.6335064,41.9471771]},"n185960195":{"id":"n185960195","loc":[-85.6295992,41.9524346]},"n185960796":{"id":"n185960796","loc":[-85.634723,41.953681]},"n185961396":{"id":"n185961396","loc":[-85.634767,41.959009]},"n185962625":{"id":"n185962625","loc":[-85.635175,41.97201]},"n185964982":{"id":"n185964982","loc":[-85.632799,41.9440543]},"n185965289":{"id":"n185965289","loc":[-85.634621,41.947323]},"n185965291":{"id":"n185965291","loc":[-85.636166,41.947296]},"n185965399":{"id":"n185965399","loc":[-85.634776,41.959834]},"n185966937":{"id":"n185966937","loc":[-85.633183,41.947315]},"n185966948":{"id":"n185966948","loc":[-85.626406,41.957188]},"n185967422":{"id":"n185967422","loc":[-85.6320229,41.9490123]},"n185967917":{"id":"n185967917","loc":[-85.634763,41.958292]},"n185967918":{"id":"n185967918","loc":[-85.636271,41.958311]},"n185968100":{"id":"n185968100","loc":[-85.630835,41.950656]},"n185970515":{"id":"n185970515","loc":[-85.634832,41.963866]},"n185971578":{"id":"n185971578","loc":[-85.634641,41.948627]},"n185971580":{"id":"n185971580","loc":[-85.6361818,41.9486135]},"n185971631":{"id":"n185971631","loc":[-85.634729,41.954667]},"n185971632":{"id":"n185971632","loc":[-85.636236,41.954656]},"n185972155":{"id":"n185972155","loc":[-85.623333,41.961987]},"n185974583":{"id":"n185974583","loc":[-85.634686,41.951158]},"n185974585":{"id":"n185974585","loc":[-85.6362059,41.9511457]},"n185975064":{"id":"n185975064","loc":[-85.636218,41.953667]},"n185975735":{"id":"n185975735","loc":[-85.634923,41.969269]},"n185978390":{"id":"n185978390","loc":[-85.634668,41.949875]},"n185978392":{"id":"n185978392","loc":[-85.634686,41.952415]},"n185978394":{"id":"n185978394","loc":[-85.634726,41.955921]},"n185978399":{"id":"n185978399","loc":[-85.6347861,41.9606613]},"n185978402":{"id":"n185978402","loc":[-85.634806,41.961485]},"n185978406":{"id":"n185978406","loc":[-85.6348298,41.964783]},"n185978410":{"id":"n185978410","loc":[-85.6348766,41.9677088]},"n185978414":{"id":"n185978414","loc":[-85.634938,41.971566]},"n185978415":{"id":"n185978415","loc":[-85.634942,41.971611]},"n185978417":{"id":"n185978417","loc":[-85.634952,41.971655]},"n185978419":{"id":"n185978419","loc":[-85.634989,41.971741]},"n185978420":{"id":"n185978420","loc":[-85.635063,41.971864]},"n185978787":{"id":"n185978787","loc":[-85.627936,41.954693]},"n185978790":{"id":"n185978790","loc":[-85.626832,41.954677]},"n185978967":{"id":"n185978967","loc":[-85.632278,41.948613]},"n185980735":{"id":"n185980735","loc":[-85.628639,41.953725]},"n185982163":{"id":"n185982163","loc":[-85.636233,41.952398]},"n185982193":{"id":"n185982193","loc":[-85.6313855,41.9499125]},"n185982195":{"id":"n185982195","loc":[-85.6304857,41.9511945]},"n185982196":{"id":"n185982196","loc":[-85.626336,41.957291]},"n185982197":{"id":"n185982197","loc":[-85.625578,41.958664]},"n185982198":{"id":"n185982198","loc":[-85.624619,41.960145]},"n185982200":{"id":"n185982200","loc":[-85.624494,41.960338]},"n185984017":{"id":"n185984017","loc":[-85.636163,41.947382]},"n185984020":{"id":"n185984020","loc":[-85.636188,41.9498803]},"n185984022":{"id":"n185984022","loc":[-85.636276,41.955919]},"n185984024":{"id":"n185984024","loc":[-85.636279,41.956901]},"n185988036":{"id":"n185988036","loc":[-85.631422,41.948294]},"n185988867":{"id":"n185988867","loc":[-85.63102,41.948805]},"n185988869":{"id":"n185988869","loc":[-85.630773,41.949209]},"n185988871":{"id":"n185988871","loc":[-85.63005,41.95016]},"n185988872":{"id":"n185988872","loc":[-85.629423,41.951016]},"n185988873":{"id":"n185988873","loc":[-85.629252,41.951256]},"n185988875":{"id":"n185988875","loc":[-85.629126,41.951489]},"n185988877":{"id":"n185988877","loc":[-85.628991,41.951704]},"n185988878":{"id":"n185988878","loc":[-85.628689,41.952112]},"n185988879":{"id":"n185988879","loc":[-85.628313,41.952666]},"n185988880":{"id":"n185988880","loc":[-85.627687,41.953529]},"n185988882":{"id":"n185988882","loc":[-85.627394,41.953947]},"n185988884":{"id":"n185988884","loc":[-85.627287,41.954128]},"n1819858502":{"id":"n1819858502","loc":[-85.6328435,41.9455473]},"n1819858510":{"id":"n1819858510","loc":[-85.6324841,41.9453438]},"n1819858515":{"id":"n1819858515","loc":[-85.6318511,41.9446409]},"n1819858520":{"id":"n1819858520","loc":[-85.6326558,41.9454708]},"n1819858522":{"id":"n1819858522","loc":[-85.6319048,41.9447407]},"n1819858524":{"id":"n1819858524","loc":[-85.6317718,41.9443666]},"n1819858530":{"id":"n1819858530","loc":[-85.632055,41.9449128]},"n2139795768":{"id":"n2139795768","loc":[-85.6243023,41.9606102]},"n2139832645":{"id":"n2139832645","loc":[-85.6324455,41.9448607]},"n2139832649":{"id":"n2139832649","loc":[-85.6328043,41.9454773]},"n2139832651":{"id":"n2139832651","loc":[-85.6322547,41.9449621]},"n2139832675":{"id":"n2139832675","loc":[-85.6327356,41.944757]},"n2139832677":{"id":"n2139832677","loc":[-85.6325433,41.9448599]},"n2139832680":{"id":"n2139832680","loc":[-85.6328885,41.9455614]},"n2139832682":{"id":"n2139832682","loc":[-85.6320913,41.9449492]},"n2139832684":{"id":"n2139832684","loc":[-85.6325366,41.9447133]},"n2139832688":{"id":"n2139832688","loc":[-85.6322786,41.94485]},"n2139832718":{"id":"n2139832718","loc":[-85.6327486,41.9432475]},"n2139832719":{"id":"n2139832719","loc":[-85.6327926,41.9431773]},"n2139832720":{"id":"n2139832720","loc":[-85.6329033,41.943153]},"n2139832727":{"id":"n2139832727","loc":[-85.6328975,41.9430783]},"n2139844839":{"id":"n2139844839","loc":[-85.6326261,41.9432308]},"n2189015992":{"id":"n2189015992","loc":[-85.6347706,41.9593383]},"n2189153179":{"id":"n2189153179","loc":[-85.6340476,41.9472565]},"n2189153182":{"id":"n2189153182","loc":[-85.6342638,41.9472522]},"n2189153241":{"id":"n2189153241","loc":[-85.6354184,41.9473091]},"n2189153258":{"id":"n2189153258","loc":[-85.6354611,41.9472366]},"n2189153277":{"id":"n2189153277","loc":[-85.6328948,41.9462374]},"n2199109755":{"id":"n2199109755","loc":[-85.6336729,41.9472417]},"w203970139":{"id":"w203970139","tags":{"building":"yes"},"nodes":["n2139824793","n2139824787","n2139824773","n2139824778","n2139824793"]},"w203970098":{"id":"w203970098","tags":{"building":"yes"},"nodes":["n2139824748","n2139824712","n2139824726","n2139824760","n2139824748"]},"w208643132":{"id":"w208643132","tags":{"area":"yes","building":"yes"},"nodes":["n2189153195","n2189153196","n2189153197","n2189153198","n2189153195"]},"w203970094":{"id":"w203970094","tags":{"building":"yes"},"nodes":["n2139824755","n2139824753","n2139824759","n2139824764","n2139824763","n2139824767","n2139824770","n2139824782","n2139824772","n2139824756","n2139824751","n2139824754","n2139824755"]},"w208643138":{"id":"w208643138","tags":{"amenity":"parking","area":"yes"},"nodes":["n2189153231","n2189153232","n2189153240","n2189153244","n2189153236","n2189153238","n2189153237","n2189153239","n2189153252","n2189153235","n2189153234","n2189153253","n2189153233","n2189153231"]},"w203970125":{"id":"w203970125","tags":{"building":"yes"},"nodes":["n2139824735","n2139824738","n2139824757","n2139824749","n2139824735"]},"w170848823":{"id":"w170848823","tags":{"name":"Rocky River","waterway":"river"},"nodes":["n1819849189","n1819858516","n1819858519","n1819858504","n1819858525","n1819858506","n1819858513"]},"w203970898":{"id":"w203970898","tags":{"amenity":"parking","area":"yes"},"nodes":["n2139832645","n2139832647","n2139832649","n2139832651","n2139832645"]},"w203970134":{"id":"w203970134","tags":{"building":"yes"},"nodes":["n2139824796","n2139824803","n2139824797","n2139824788","n2139824796"]},"w203970104":{"id":"w203970104","tags":{"building":"yes"},"nodes":["n2139824733","n2139824730","n2139824714","n2139824721","n2139824733"]},"w206805245":{"id":"w206805245","tags":{"area":"yes","building":"yes"},"nodes":["n2168544780","n2168544781","n2139824796","n2139824803","n2168544780"]},"w206805252":{"id":"w206805252","tags":{"area":"yes","building":"yes"},"nodes":["n2168544838","n2168544839","n2168544840","n2168544841","n2168544842","n2168544843","n2168544844","n2168544845","n2168544846","n2168544847","n2168544838"]},"w203970099":{"id":"w203970099","tags":{"building":"yes"},"nodes":["n2139824783","n2139824795","n2139824790","n2139824779","n2139824783"]},"w17967730":{"id":"w17967730","tags":{"highway":"residential","name":"Water St"},"nodes":["n185963451","n2189153277","n185988036","n185988867","n185988869","n185988871","n185988872","n185988873","n185988875","n185988877","n185988878","n185988879","n185988880","n185988882","n185988884","n185978790"]},"w208643133":{"id":"w208643133","tags":{"area":"yes","building":"yes"},"nodes":["n2189153199","n2189153200","n2189153201","n2189153202","n2189153199"]},"w203970127":{"id":"w203970127","tags":{"building":"yes"},"nodes":["n2139824794","n2139824783","n2139824789","n2139824797","n2139824794"]},"w208643139":{"id":"w208643139","tags":{"highway":"service"},"nodes":["n185988237","n2189153242","n2189153247","n2189153241"]},"w203988297":{"id":"w203988297","tags":{"amenity":"parking","area":"yes"},"nodes":["n2140006423","n2140006441","n2140006425","n2140006426","n2140006440","n2140006427","n2140006428","n2140006429","n2140006430","n2140006423"]},"w206805250":{"id":"w206805250","tags":{"area":"yes","building":"yes"},"nodes":["n2168544827","n2168544823","n2168544825","n2168544800","n2168544829","n2168544827"]},"w208643140":{"id":"w208643140","tags":{"highway":"service","service":"parking_aisle"},"nodes":["n2189153242","n2189153254","n2189153243","n2189153244","n2189153251","n2189153257","n2189153245","n2189153252","n2189153246"]},"w203974055":{"id":"w203974055","tags":{"bridge":"yes","highway":"path","name":"Riverwalk Trail"},"nodes":["n2139870376","n2139870377"]},"w206805247":{"id":"w206805247","tags":{"area":"yes","building":"yes"},"nodes":["n2168544785","n2168544786","n2168544783","n2168544787","n2168544788","n2168544789","n2168544785"]},"w17964996":{"id":"w17964996","tags":{"highway":"residential","name":"Foster St"},"nodes":["n1819858524","n1819858515","n1819858522","n1819858530","n2139832682","n1819858510","n1819858520","n1819858502","n2139832680","n185963451","n1819858527","n185963452","n185963453","n185963454","n185963455","n185963456"]},"w208643144":{"id":"w208643144","tags":{"area":"yes","building":"yes"},"nodes":["n2189153264","n2189153265","n2189153266","n2189153267","n2189153268","n2189153269","n2189153270","n2189153264"]},"w203970914":{"id":"w203970914","tags":{"amenity":"parking","area":"yes"},"nodes":["n2139832722","n2139832723","n2139832724","n2139832725","n2139832726","n2139832727","n2139844839","n2139832722"]},"w208643143":{"id":"w208643143","tags":{"area":"yes","building":"yes"},"nodes":["n2189153258","n2189153259","n2189153260","n2189153261","n2189153262","n2189153263","n2189153258"]},"w203049590":{"id":"w203049590","tags":{"amenity":"parking","area":"yes"},"nodes":["n2130304152","n2130304153","n2140006403","n2130304154","n2130304156","n2130304155","n2130304160","n2130304152"]},"w203974054":{"id":"w203974054","tags":{"highway":"path","name":"Riverwalk Trail"},"nodes":["n2139858971","n2139870373","n2139870374"]},"w203049595":{"id":"w203049595","tags":{"highway":"service"},"nodes":["n2130304158","n2130304159","n2130304160","n2139832635","n2139832639"]},"w203970913":{"id":"w203970913","tags":{"highway":"service","service":"parking_aisle"},"nodes":["n2139832715","n2139832716","n2139832717","n2139832718","n2139832719","n2139832720","n2139832721","n2139832716"]},"w208643134":{"id":"w208643134","tags":{"area":"yes","building":"yes"},"nodes":["n2189153203","n2189153204","n2189153205","n2189153206","n2189153207","n2189153208","n2189153209","n2189153210","n2189153211","n2189153212","n2189153213","n2189153214","n2189153203"]},"w134150808":{"id":"w134150808","tags":{"bridge":"yes","highway":"residential","name":"Moore St"},"nodes":["n185988239","n185984009","n185988241","n1475284019"]},"w203970115":{"id":"w203970115","tags":{"building":"yes"},"nodes":["n2139824761","n2139824727","n2139824736","n2139824771","n2139824761"]},"w208643130":{"id":"w208643130","tags":{"area":"yes","building":"yes"},"nodes":["n2189153183","n2189153184","n2189153185","n2189153186","n2189153187","n2189153188","n2189153189","n2189153190","n2189153183"]},"w206805246":{"id":"w206805246","tags":{"area":"yes","building":"yes"},"nodes":["n2168544782","n2168544780","n2168544781","n2168544783","n2168544787","n2168544784","n2168544782"]},"w203970138":{"id":"w203970138","tags":{"building":"yes"},"nodes":["n2139824729","n2139824720","n2139824702","n2139824707","n2139824729"]},"w203970133":{"id":"w203970133","tags":{"building":"yes"},"nodes":["n2139824748","n2139824737","n2139824717","n2139824728","n2139824748"]},"w203970907":{"id":"w203970907","tags":{"highway":"service","service":"parking_aisle"},"nodes":["n2139832700","n2139832701","n2139832702"]},"w203974056":{"id":"w203974056","tags":{"highway":"path","name":"Riverwalk Trail"},"nodes":["n2139870377","n2139870378"]},"w203970897":{"id":"w203970897","tags":{"highway":"service","service":"parking_aisle"},"nodes":["n2130304156","n2166205688","n2139832635","n2139832636","n2139832637","n2139832639","n2139832641","n2166205688"]},"w203974057":{"id":"w203974057","tags":{"highway":"path","name":"Riverwalk Trail"},"nodes":["n2139870375","n2139870376"]},"w203049594":{"id":"w203049594","tags":{"highway":"service"},"nodes":["n2130304156","n2139870378","n2139832706","n2139832704","n2130304157"]},"w203970122":{"id":"w203970122","tags":{"building":"yes"},"nodes":["n2139824757","n2139824740","n2139824747","n2139824762","n2139824757"]},"w208643136":{"id":"w208643136","tags":{"area":"yes","building":"yes"},"nodes":["n2189153219","n2189153220","n2189153221","n2189153222","n2189153223","n2189153224","n2189153225","n2189153226","n2189153219"]},"w203970128":{"id":"w203970128","tags":{"building":"yes"},"nodes":["n2139824732","n2139824752","n2139824744","n2139824724","n2139824732"]},"w203970097":{"id":"w203970097","tags":{"building":"yes"},"nodes":["n2139824737","n2139824733","n2139824710","n2139824716","n2139824737"]},"w203970137":{"id":"w203970137","tags":{"building":"yes"},"nodes":["n2139824765","n2139824774","n2139824758","n2139824746","n2139824765"]},"w134150840":{"id":"w134150840","tags":{"highway":"residential","name":"Moore St"},"nodes":["n1475284019","n185988243","n185988244","n185988245"]},"w17967628":{"id":"w17967628","tags":{"highway":"residential","name":"Moore St"},"nodes":["n185978388","n2139832709","n185988237","n185988239"]},"w203988292":{"id":"w203988292","tags":{"bridge":"yes","highway":"footway"},"nodes":["n2140006407","n2140006405"]},"w203970118":{"id":"w203970118","tags":{"building":"yes"},"nodes":["n2139824775","n2139824785","n2139824780","n2139824768","n2139824775"]},"w203970121":{"id":"w203970121","tags":{"building":"yes"},"nodes":["n2139824768","n2139824781","n2139824776","n2139824765","n2139824768"]},"w17967752":{"id":"w17967752","tags":{"highway":"residential","name":"Railroad Drive"},"nodes":["n185964980","n2139832699","n2139832700","n2130304158","n185988969","n185988971","n185988972","n1475284011"]},"w203970136":{"id":"w203970136","tags":{"building":"yes"},"nodes":["n2139824798","n2139824793","n2139824777","n2139824784","n2139824798"]},"w203970142":{"id":"w203970142","tags":{"building":"yes"},"nodes":["n2139824808","n2139824809","n2139824807","n2139824806","n2139824801","n2139824800","n2139824804","n2139824805","n2139824808"]},"w208643137":{"id":"w208643137","tags":{"amenity":"parking","area":"yes"},"nodes":["n2189153227","n2189153248","n2189153228","n2189153234","n2189153235","n2189153229","n2189153249","n2189153230","n2189153227"]},"w208643129":{"id":"w208643129","tags":{"area":"yes","building":"yes"},"nodes":["n2189153179","n2189153180","n2189153181","n2189153182","n2189153179"]},"w203970909":{"id":"w203970909","tags":{"amenity":"parking","area":"yes"},"nodes":["n2139832703","n2139832704","n2139832706","n2139832708","n2139832703"]},"w203970905":{"id":"w203970905","tags":{"highway":"service","service":"parking_aisle"},"nodes":["n2139832688","n2139832691"]},"w203988298":{"id":"w203988298","tags":{"highway":"service"},"nodes":["n2140006431","n2140006433","n2140006435","n2140006436","n2140006437","n2140006438","n2140006439","n2140006440"]},"w203970106":{"id":"w203970106","tags":{"building":"yes"},"nodes":["n2139824798","n2139824791","n2139824799","n2139824802","n2139824798"]},"w203970129":{"id":"w203970129","tags":{"building":"yes"},"nodes":["n2139824787","n2139824782","n2139824766","n2139824769","n2139824787"]},"w208643131":{"id":"w208643131","tags":{"area":"yes","building":"yes"},"nodes":["n2189153191","n2189153192","n2189153193","n2189153194","n2189153191"]},"w206805249":{"id":"w206805249","tags":{"area":"yes","building":"yes"},"nodes":["n2168544800","n2168544801","n2168544802","n2168544805","n2168544807","n2168544809","n2168544811","n2168544813","n2168544815","n2168544817","n2168544819","n2168544821","n2168544823","n2168544825","n2168544800"]},"w134150800":{"id":"w134150800","tags":{"bridge":"yes","highway":"primary","name":"W Michigan Ave","old_ref":"US 131","ref":"US 131 Business;M 60"},"nodes":["n185964972","n185964976"]},"w17966984":{"id":"w17966984","tags":{"highway":"residential","name":"Portage Avenue"},"nodes":["n185978375","n185963456","n2189153218","n185966937","n185978967","n185967422","n185982193","n185968100","n185982195","n185960195","n185980735","n185978787","n185966948","n185982196","n185982197","n185982198","n185982200","n2139795768","n185972155"]},"w203988294":{"id":"w203988294","tags":{"amenity":"shelter","area":"yes","building":"yes","shelter_type":"picnic_shelter"},"nodes":["n2140006409","n2140006411","n2140006413","n2140006415","n2140006409"]},"w203970912":{"id":"w203970912","tags":{"amenity":"parking","area":"yes"},"nodes":["n2139832711","n2139832712","n2139832713","n2139832714","n2139832711"]},"w203970119":{"id":"w203970119","tags":{"building":"yes"},"nodes":["n2139824713","n2139824705","n2139824683","n2139824689","n2139824713"]},"w203970114":{"id":"w203970114","tags":{"building":"yes"},"nodes":["n2139824735","n2139824750","n2139824745","n2139824732","n2139824735"]},"w208643142":{"id":"w208643142","tags":{"highway":"service","service":"parking_aisle"},"nodes":["n2189153254","n2189153255","n2189153256","n2189153257"]},"w206805253":{"id":"w206805253","tags":{"area":"yes","building":"yes"},"nodes":["n2168544848","n2168544849","n2168544850","n2168544851","n2168544852","n2168544853","n2168544854","n2168544855","n2168544848"]},"w143497377":{"id":"w143497377","tags":{"highway":"primary","name":"North Main Street","old_ref":"US 131","ref":"US 131 Business"},"nodes":["n185962625","n185978420","n185978419","n185978417","n185978415","n185978414","n185975735","n1475293254","n185978410","n185978406","n185970515","n185978402","n185978399","n185965399","n2189015992","n185961396","n185967917","n185978394","n185971631","n185960796","n185978392","n185974583","n185978390","n185971578","n185965289","n2189153215","n185978388","n185978383","n185978381","n185978379","n185978377","n185978375","n185964982"]},"w134150811":{"id":"w134150811","tags":{"highway":"primary","name":"West Michigan Avenue","old_ref":"US 131","ref":"US 131 Business;M 60"},"nodes":["n185964976","n2130304157","n1475284023","n2139832715","n185964980","n185964982"]},"w208643135":{"id":"w208643135","tags":{"highway":"service","service":"parking_aisle"},"nodes":["n2189153215","n2189153216","n2189153217","n2189153218"]},"w17967183":{"id":"w17967183","tags":{"highway":"residential","name":"West Street"},"nodes":["n1475284011","n185984011","n185984013","n185984015","n2189153246","n2189153250","n185965291","n185984017","n185971580","n185984020","n185974585","n185982163","n185975064","n185971632","n185984022","n185984024","n185967918"]},"w134150778":{"id":"w134150778","tags":{"bridge":"yes","highway":"residential","name":"Moore St"},"nodes":["n185988245","n1475283992","n185975911"]},"w206805248":{"id":"w206805248","tags":{"area":"yes","building":"yes"},"nodes":["n2168544790","n2168544791","n2168544792","n2168544793","n2168544795","n2168544797","n2168544798","n2168544799","n2168544802","n2168544801","n2168544790"]},"w203974058":{"id":"w203974058","tags":{"bridge":"yes","highway":"path","name":"Riverwalk Trail"},"nodes":["n2139870374","n2139870375"]},"w203970902":{"id":"w203970902","tags":{"highway":"service"},"nodes":["n2139832678","n2139832691","n2139832680"]},"w203988296":{"id":"w203988296","tags":{"highway":"path"},"nodes":["n2139858967","n2140006421","n2139858935"]},"w206805251":{"id":"w206805251","tags":{"area":"yes","building":"yes"},"nodes":["n2168544830","n2168544831","n2168544832","n2168544833","n2168544834","n2168544835","n2168544836","n2168544837","n2168544830"]},"w203970906":{"id":"w203970906","tags":{"amenity":"parking","area":"yes"},"nodes":["n2139832693","n2139832694","n2139832696","n2139832697","n2139832698","n2139832693"]},"w203049598":{"id":"w203049598","tags":{"area":"yes","leisure":"pitch","sport":"tennis"},"nodes":["n2130304162","n2130304163","n2130304164","n2130304165","n2130304162"]},"w203970911":{"id":"w203970911","tags":{"highway":"service"},"nodes":["n2139832709","n2139832714","n2139832713","n2139832710","n185988971"]},"w203970105":{"id":"w203970105","tags":{"building":"yes"},"nodes":["n2139824779","n2139824792","n2139824786","n2139824775","n2139824779"]},"w203988290":{"id":"w203988290","tags":{"highway":"footway"},"nodes":["n2140006403","n2140006407"]},"w203970900":{"id":"w203970900","tags":{"amenity":"parking","area":"yes"},"nodes":["n2139832653","n2139832663","n2139832665","n2139832667","n2139832669","n2139832671","n2139832673","n2139832675","n2139832677","n2139832653"]},"w209717048":{"id":"w209717048","tags":{"area":"yes","building":"yes"},"nodes":["n2199109755","n2199109756","n2199109757","n2199109758","n2199109759","n2199109760","n2199109755"]},"w208643141":{"id":"w208643141","tags":{"highway":"service","service":"parking_aisle"},"nodes":["n2189153247","n2189153248","n2189153249","n2189153250"]},"w203970903":{"id":"w203970903","tags":{"highway":"service","service":"parking_aisle"},"nodes":["n2139832682","n2139832688","n2139832684","n2139832678","n2139832686"]},"n354002527":{"id":"n354002527","loc":[-85.6236039,41.9458813],"tags":{"amenity":"school","name":"Barrows School"}},"n185963396":{"id":"n185963396","loc":[-85.627401,41.943496]},"n185963397":{"id":"n185963397","loc":[-85.627403,41.943625]},"n185965101":{"id":"n185965101","loc":[-85.626409,41.943215]},"n185971474":{"id":"n185971474","loc":[-85.624884,41.943508]},"n185971475":{"id":"n185971475","loc":[-85.625191,41.943509]},"n185971482":{"id":"n185971482","loc":[-85.624882,41.94382]},"n185983135":{"id":"n185983135","loc":[-85.624893,41.945616]},"n185983137":{"id":"n185983137","loc":[-85.624912,41.946524]},"n185988027":{"id":"n185988027","loc":[-85.622721,41.946535]},"n185963398":{"id":"n185963398","loc":[-85.6273993,41.9446899]},"n185983238":{"id":"n185983238","loc":[-85.6227157,41.9456321]},"n185980374":{"id":"n185980374","loc":[-85.6248856,41.9447242]},"n185980373":{"id":"n185980373","loc":[-85.6226744,41.9447371]},"n2196831342":{"id":"n2196831342","loc":[-85.6250924,41.945063]},"n2196831343":{"id":"n2196831343","loc":[-85.6252335,41.9450636]},"n2196831344":{"id":"n2196831344","loc":[-85.6252286,41.9448707]},"n2196831345":{"id":"n2196831345","loc":[-85.6250661,41.9448707]},"n2196831346":{"id":"n2196831346","loc":[-85.6250243,41.9449012]},"n2196831347":{"id":"n2196831347","loc":[-85.6250251,41.9449244]},"n2196831348":{"id":"n2196831348","loc":[-85.6250867,41.9449257]},"n2196831349":{"id":"n2196831349","loc":[-85.625349,41.9445058]},"n2196831350":{"id":"n2196831350","loc":[-85.6253471,41.9443882]},"n2196831351":{"id":"n2196831351","loc":[-85.6251516,41.94439]},"n2196831352":{"id":"n2196831352","loc":[-85.6251522,41.9444308]},"n2196831353":{"id":"n2196831353","loc":[-85.6251344,41.9444309]},"n2196831354":{"id":"n2196831354","loc":[-85.6251356,41.9445077]},"n2196831355":{"id":"n2196831355","loc":[-85.6232357,41.9463406]},"n2196831356":{"id":"n2196831356","loc":[-85.6232409,41.9460668]},"n2196831357":{"id":"n2196831357","loc":[-85.6232072,41.9460665]},"n2196831358":{"id":"n2196831358","loc":[-85.6232117,41.9458272]},"n2196831359":{"id":"n2196831359","loc":[-85.6229808,41.9458248]},"n2196831360":{"id":"n2196831360","loc":[-85.6229763,41.9460627]},"n2196831361":{"id":"n2196831361","loc":[-85.623006,41.946063]},"n2196831362":{"id":"n2196831362","loc":[-85.6230023,41.9462557]},"n2196831363":{"id":"n2196831363","loc":[-85.6230755,41.9462565]},"n2196831364":{"id":"n2196831364","loc":[-85.6230739,41.9463389]},"n185947349":{"id":"n185947349","loc":[-85.618327,41.945607]},"n185947359":{"id":"n185947359","loc":[-85.615453,41.945597]},"n185947378":{"id":"n185947378","loc":[-85.617231,41.945603]},"n185947474":{"id":"n185947474","loc":[-85.616136,41.945602]},"n185948972":{"id":"n185948972","loc":[-85.615273,41.945637]},"n185955019":{"id":"n185955019","loc":[-85.620172,41.945627]},"n185960682":{"id":"n185960682","loc":[-85.622759,41.951845]},"n185961369":{"id":"n185961369","loc":[-85.622758,41.947444]},"n185961371":{"id":"n185961371","loc":[-85.624908,41.947416]},"n185963392":{"id":"n185963392","loc":[-85.6270462,41.9409953]},"n185963393":{"id":"n185963393","loc":[-85.627295,41.941304]},"n185963394":{"id":"n185963394","loc":[-85.627352,41.94148]},"n185963395":{"id":"n185963395","loc":[-85.62737,41.942261]},"n185965099":{"id":"n185965099","loc":[-85.6264,41.942263]},"n185965108":{"id":"n185965108","loc":[-85.622769,41.949224]},"n185965110":{"id":"n185965110","loc":[-85.624937,41.949237]},"n185966295":{"id":"n185966295","loc":[-85.6299942,41.9446689]},"n185966342":{"id":"n185966342","loc":[-85.624873,41.942022]},"n185970222":{"id":"n185970222","loc":[-85.622761,41.948357]},"n185970224":{"id":"n185970224","loc":[-85.624924,41.9483338]},"n185971477":{"id":"n185971477","loc":[-85.620051,41.94383]},"n185971478":{"id":"n185971478","loc":[-85.621219,41.943801]},"n185971481":{"id":"n185971481","loc":[-85.621812,41.943807]},"n185973866":{"id":"n185973866","loc":[-85.627629,41.946498]},"n185974699":{"id":"n185974699","loc":[-85.6227688,41.950119]},"n185978800":{"id":"n185978800","loc":[-85.623953,41.954684]},"n185980372":{"id":"n185980372","loc":[-85.621459,41.944756]},"n185980378":{"id":"n185980378","loc":[-85.6286375,41.9446764]},"n185980380":{"id":"n185980380","loc":[-85.630139,41.944661]},"n185980382":{"id":"n185980382","loc":[-85.630298,41.944635]},"n185980384":{"id":"n185980384","loc":[-85.630759,41.94454]},"n185980386":{"id":"n185980386","loc":[-85.6312369,41.9444548]},"n185983133":{"id":"n185983133","loc":[-85.6248672,41.9415903]},"n185983139":{"id":"n185983139","loc":[-85.624951,41.950239]},"n185983140":{"id":"n185983140","loc":[-85.624934,41.950681]},"n185983141":{"id":"n185983141","loc":[-85.624813,41.950983]},"n185983143":{"id":"n185983143","loc":[-85.6246225,41.951591]},"n185983144":{"id":"n185983144","loc":[-85.623908,41.9539165]},"n185983145":{"id":"n185983145","loc":[-85.6238903,41.9540956]},"n185983146":{"id":"n185983146","loc":[-85.623898,41.95431]},"n185983236":{"id":"n185983236","loc":[-85.628481,41.945611]},"n185985914":{"id":"n185985914","loc":[-85.620072,41.946538]},"n185986812":{"id":"n185986812","loc":[-85.6227785,41.9510005]},"n185988028":{"id":"n185988028","loc":[-85.6281401,41.9469632]},"n185988030":{"id":"n185988030","loc":[-85.6282451,41.9470314]},"n185988032":{"id":"n185988032","loc":[-85.6283312,41.9470656]},"w17964989":{"id":"w17964989","tags":{"highway":"residential","name":"Middle St"},"nodes":["n185963392","n185963393","n185963394","n185963395","n185963396","n185963397","n185963398"]},"w17965158":{"id":"w17965158","tags":{"access":"private","highway":"service","name":"Battle St"},"nodes":["n185965099","n185965101"]},"w41074896":{"id":"w41074896","tags":{"highway":"secondary","name":"East Michigan Avenue","name_1":"State Highway 60","ref":"M 60"},"nodes":["n185980372","n185980373","n185980374","n185963398","n185980378","n185966295","n185980380","n185980382","n185980384","n185980386"]},"w17965846":{"id":"w17965846","tags":{"highway":"residential","name":"2nd Ave"},"nodes":["n185971477","n185971478","n185971481","n185971482"]},"w209470306":{"id":"w209470306","tags":{"area":"yes","building":"yes"},"nodes":["n2196831349","n2196831350","n2196831351","n2196831352","n2196831353","n2196831354","n2196831349"]},"w17965845":{"id":"w17965845","tags":{"highway":"residential","name":"2nd Ave"},"nodes":["n185971474","n185971475","n185963396"]},"w209470307":{"id":"w209470307","tags":{"area":"yes","building":"yes"},"nodes":["n2196831355","n2196831356","n2196831357","n2196831358","n2196831359","n2196831360","n2196831361","n2196831362","n2196831363","n2196831364","n2196831355"]},"w17968192":{"id":"w17968192","tags":{"highway":"residential","name":"Washington St"},"nodes":["n185980373","n185983238","n185988027","n185961369","n185970222","n185965108","n185974699","n185986812","n185960682"]},"w17967603":{"id":"w17967603","tags":{"highway":"residential","name":"5th Ave"},"nodes":["n185985914","n185988027","n185983137","n185973866","n185988028","n185988030","n185988032"]},"w209470305":{"id":"w209470305","tags":{"area":"yes","building":"yes"},"nodes":["n2196831342","n2196831343","n2196831344","n2196831345","n2196831346","n2196831347","n2196831348","n2196831342"]},"w17967092":{"id":"w17967092","tags":{"highway":"residential","name":"Wood St"},"nodes":["n185983133","n185966342","n185971474","n185971482","n185980374","n185983135","n185983137","n185961371","n185970224","n185965110","n185983139","n185983140","n185983141","n185983143","n185983144","n185983145","n185983146","n185978800"]},"w17967107":{"id":"w17967107","tags":{"highway":"residential","name":"4th Ave"},"nodes":["n185983236","n185983135","n185983238","n185955019","n185947349","n185947378","n185947474","n185947359","n185948972"]},"n354030330":{"id":"n354030330","loc":[-85.6297222,41.9444444],"tags":{"leisure":"park","name":"Scouter Park"}},"n185966296":{"id":"n185966296","loc":[-85.629998,41.944078]},"n185966298":{"id":"n185966298","loc":[-85.629972,41.943927]},"n185966300":{"id":"n185966300","loc":[-85.629948,41.943783]},"n185980391":{"id":"n185980391","loc":[-85.6322992,41.9442766]},"n185980393":{"id":"n185980393","loc":[-85.6324925,41.9442136]},"n185980389":{"id":"n185980389","loc":[-85.6320272,41.9443281]},"n185980388":{"id":"n185980388","loc":[-85.6315778,41.9443959]},"n354031320":{"id":"n354031320","loc":[-85.6280556,41.9447222],"tags":{"amenity":"place_of_worship","name":"Riverside Church","religion":"christian"}},"n185987309":{"id":"n185987309","loc":[-85.6286497,41.9453531]},"n185987311":{"id":"n185987311","loc":[-85.6285942,41.9454805]},"n185988034":{"id":"n185988034","loc":[-85.6285815,41.9471692]},"n185988896":{"id":"n185988896","loc":[-85.6318433,41.9437929]},"n185977764":{"id":"n185977764","loc":[-85.6322988,41.943472]},"n1819848852":{"id":"n1819848852","loc":[-85.6315188,41.9448808]},"n1819848912":{"id":"n1819848912","loc":[-85.6284289,41.9472189]},"n1819848925":{"id":"n1819848925","loc":[-85.6314501,41.9451617]},"n1819848949":{"id":"n1819848949","loc":[-85.6309394,41.9455192]},"n1819848951":{"id":"n1819848951","loc":[-85.6290297,41.9457187]},"n1819848963":{"id":"n1819848963","loc":[-85.630521,41.9455591]},"n1819848981":{"id":"n1819848981","loc":[-85.6292936,41.9455846]},"n1819848989":{"id":"n1819848989","loc":[-85.6298451,41.9455431]},"n1819848998":{"id":"n1819848998","loc":[-85.6314973,41.9446254]},"n1819849018":{"id":"n1819849018","loc":[-85.6302807,41.9455527]},"n1819849043":{"id":"n1819849043","loc":[-85.6285533,41.9469731]},"n1819849087":{"id":"n1819849087","loc":[-85.6314501,41.9453532]},"n1819849090":{"id":"n1819849090","loc":[-85.628843,41.9461033]},"n1819849109":{"id":"n1819849109","loc":[-85.6311926,41.9454729]},"n1819849116":{"id":"n1819849116","loc":[-85.6288967,41.9459437]},"n1819849177":{"id":"n1819849177","loc":[-85.6287894,41.9464544]},"n1819858529":{"id":"n1819858529","loc":[-85.6325485,41.9445625]},"n2189112797":{"id":"n2189112797","loc":[-85.6275271,41.944555]},"n2189112798":{"id":"n2189112798","loc":[-85.6275196,41.9437258]},"n2189112799":{"id":"n2189112799","loc":[-85.6278937,41.943723]},"n2189112800":{"id":"n2189112800","loc":[-85.6278969,41.9439191]},"n2189112801":{"id":"n2189112801","loc":[-85.6279907,41.9439345]},"n2189112802":{"id":"n2189112802","loc":[-85.6280817,41.9439663]},"n2189112803":{"id":"n2189112803","loc":[-85.6281768,41.9440145]},"n2189112804":{"id":"n2189112804","loc":[-85.6281933,41.9440483]},"n2189112805":{"id":"n2189112805","loc":[-85.6281671,41.9440535]},"n2189112806":{"id":"n2189112806","loc":[-85.6281933,41.9440935]},"n2189112807":{"id":"n2189112807","loc":[-85.6282126,41.9441437]},"n2189112808":{"id":"n2189112808","loc":[-85.628214,41.9441991]},"n2189112809":{"id":"n2189112809","loc":[-85.6283298,41.944196]},"n2189112810":{"id":"n2189112810","loc":[-85.6283285,41.9442616]},"n2189112811":{"id":"n2189112811","loc":[-85.6281727,41.9442616]},"n2189112812":{"id":"n2189112812","loc":[-85.6281713,41.9442934]},"n2189112813":{"id":"n2189112813","loc":[-85.6280386,41.9442963]},"n2189112814":{"id":"n2189112814","loc":[-85.6280405,41.9443292]},"n2189112815":{"id":"n2189112815","loc":[-85.627829,41.9443349]},"n2189112816":{"id":"n2189112816","loc":[-85.6278347,41.9445495]},"n2189153271":{"id":"n2189153271","loc":[-85.6321053,41.9460342]},"n2189153272":{"id":"n2189153272","loc":[-85.632278,41.9457841]},"n2189153273":{"id":"n2189153273","loc":[-85.632823,41.9459936]},"n2189153274":{"id":"n2189153274","loc":[-85.6326845,41.9461963]},"n2189153275":{"id":"n2189153275","loc":[-85.6325664,41.9461507]},"n2189153276":{"id":"n2189153276","loc":[-85.6325323,41.946198]},"n2189153278":{"id":"n2189153278","loc":[-85.6321916,41.9459733]},"n2189153279":{"id":"n2189153279","loc":[-85.6322598,41.9458703]},"n2189153280":{"id":"n2189153280","loc":[-85.6327208,41.9460358]},"n2189153281":{"id":"n2189153281","loc":[-85.6326413,41.9461422]},"n185959079":{"id":"n185959079","loc":[-85.6293702,41.9474668]},"n185966301":{"id":"n185966301","loc":[-85.629692,41.943136]},"n185966304":{"id":"n185966304","loc":[-85.629565,41.942916]},"n185966308":{"id":"n185966308","loc":[-85.629501,41.942751]},"n185966315":{"id":"n185966315","loc":[-85.629472,41.942578]},"n185966319":{"id":"n185966319","loc":[-85.629444,41.942414]},"n185966321":{"id":"n185966321","loc":[-85.629391,41.94205]},"n185966323":{"id":"n185966323","loc":[-85.629369,41.941858]},"n185966327":{"id":"n185966327","loc":[-85.629297,41.941604]},"n185966331":{"id":"n185966331","loc":[-85.629233,41.941549]},"n185966336":{"id":"n185966336","loc":[-85.628504,41.941364]},"n185966338":{"id":"n185966338","loc":[-85.628275,41.941303]},"n185966340":{"id":"n185966340","loc":[-85.6269038,41.9410983]},"n185973867":{"id":"n185973867","loc":[-85.626843,41.947333]},"n185977762":{"id":"n185977762","loc":[-85.6318441,41.9429453]},"n1819848853":{"id":"n1819848853","loc":[-85.625854,41.9492218]},"n1819848861":{"id":"n1819848861","loc":[-85.6251459,41.9552376]},"n1819848874":{"id":"n1819848874","loc":[-85.6267445,41.9482961]},"n1819848882":{"id":"n1819848882","loc":[-85.6257209,41.9552396]},"n1819848883":{"id":"n1819848883","loc":[-85.624706,41.9523173]},"n1819848907":{"id":"n1819848907","loc":[-85.62609,41.9561471]},"n1819848908":{"id":"n1819848908","loc":[-85.6244013,41.9549284]},"n1819848911":{"id":"n1819848911","loc":[-85.6265578,41.9553672]},"n1819848923":{"id":"n1819848923","loc":[-85.6246802,41.9550959]},"n1819848936":{"id":"n1819848936","loc":[-85.6241588,41.9539291]},"n1819848940":{"id":"n1819848940","loc":[-85.62506,41.9511129]},"n1819848944":{"id":"n1819848944","loc":[-85.624942,41.9515912]},"n1819848950":{"id":"n1819848950","loc":[-85.6273989,41.9475461]},"n1819848957":{"id":"n1819848957","loc":[-85.627695,41.947404]},"n1819849009":{"id":"n1819849009","loc":[-85.6259248,41.94896]},"n1819849037":{"id":"n1819849037","loc":[-85.6257252,41.9502112]},"n1819849061":{"id":"n1819849061","loc":[-85.6270084,41.9479626]},"n1819849073":{"id":"n1819849073","loc":[-85.6243734,41.9534583]},"n1819849091":{"id":"n1819849091","loc":[-85.6241373,41.9543918]},"n1819849130":{"id":"n1819849130","loc":[-85.6282572,41.9473067]},"n1819849143":{"id":"n1819849143","loc":[-85.625281,41.9506596]},"n1819849153":{"id":"n1819849153","loc":[-85.6258647,41.9498043]},"n1819849168":{"id":"n1819849168","loc":[-85.6265084,41.9559317]},"n1819849173":{"id":"n1819849173","loc":[-85.6263325,41.9552156]},"n1819849175":{"id":"n1819849175","loc":[-85.6266372,41.9556764]},"n1819849178":{"id":"n1819849178","loc":[-85.6242232,41.9545993]},"n1819849181":{"id":"n1819849181","loc":[-85.6262187,41.9486712]},"n1819849188":{"id":"n1819849188","loc":[-85.6245558,41.9530434]},"n1819849190":{"id":"n1819849190","loc":[-85.6255982,41.9563017]},"n2168544738":{"id":"n2168544738","loc":[-85.6245707,41.9529711]},"w208643145":{"id":"w208643145","tags":{"amenity":"parking","area":"yes"},"nodes":["n2189153271","n2189153272","n2189153273","n2189153274","n2189153275","n2189153276","n2189153271"]},"w17967561":{"id":"w17967561","tags":{"highway":"residential","name":"Garden St"},"nodes":["n185980378","n185987309","n185987311","n185983236","n185973866"]},"w134150802":{"id":"w134150802","tags":{"bridge":"yes","highway":"secondary","name":"East Michigan Avenue","name_1":"State Highway 60","ref":"M 60"},"nodes":["n185980386","n185980388"]},"w208639462":{"id":"w208639462","tags":{"area":"yes","building":"yes"},"nodes":["n2189112797","n2189112798","n2189112799","n2189112800","n2189112801","n2189112802","n2189112803","n2189112804","n2189112805","n2189112806","n2189112807","n2189112808","n2189112809","n2189112810","n2189112811","n2189112812","n2189112813","n2189112814","n2189112815","n2189112816","n2189112797"]},"w134150830":{"id":"w134150830","tags":{"bridge":"yes","highway":"secondary","name":"South Main Street","old_ref":"US 131","ref":"M 86"},"nodes":["n185977762","n185977764"]},"w134150801":{"id":"w134150801","tags":{"highway":"secondary","name":"South Main Street","old_ref":"US 131","ref":"M 86"},"nodes":["n185977764","n185964982"]},"w208643146":{"id":"w208643146","tags":{"highway":"service","service":"parking_aisle"},"nodes":["n2189153277","n2189153281","n2189153278","n2189153279","n2189153280","n2189153281"]},"w17966061":{"id":"w17966061","tags":{"highway":"residential","name":"John Glenn Ct"},"nodes":["n185973866","n185973867"]},"w134150772":{"id":"w134150772","tags":{"highway":"residential","name":"5th Ave"},"nodes":["n185988034","n185959079","n185988036","n185978967"]},"w134150836":{"id":"w134150836","tags":{"highway":"secondary","name":"East Michigan Avenue","name_1":"State Highway 60","ref":"M 60"},"nodes":["n185980388","n1819858524","n185980389","n185980391","n185980393","n185964982"]},"w17967734":{"id":"w17967734","tags":{"highway":"residential","name":"Water Street"},"nodes":["n185988896","n185980391","n1819858529"]},"w17965305":{"id":"w17965305","tags":{"highway":"residential","name":"River Dr"},"nodes":["n185966295","n185966296","n185966298","n185966300","n185966301","n185966304","n185966308","n185966315","n185966319","n185966321","n185966323","n185966327","n185966331","n185966336","n185966338","n185963392","n185966340","n185966342"]},"w134150826":{"id":"w134150826","tags":{"bridge":"yes","highway":"residential","name":"5th Ave"},"nodes":["n185988032","n185988034"]},"w170848330":{"id":"w170848330","tags":{"name":"Portage River","waterway":"river"},"nodes":["n1819849190","n1819848907","n1819849168","n1819849175","n1819848911","n1819849173","n1819848882","n1819848861","n1819848923","n1819848908","n1819849178","n1819849091","n1819848936","n1819849073","n1819849188","n2168544738","n1819848883","n1819848944","n1819848940","n1819849143","n1819849037","n1819849153","n1819848853","n1819849009","n1819849181","n1819848874","n1819849061","n1819848950","n1819848957","n1819849130","n1819848912","n1819849043","n1819849177","n1819849090","n1819849116","n1819848951","n1819848981","n1819848989","n1819849018","n1819848963","n1819848949","n1819849109","n1819849087","n1819848925","n1819848852","n1819848998","n1819849057"]},"r270264":{"id":"r270264","tags":{"network":"US:MI","ref":"86","route":"road","state_id":"MI","type":"route","url":"http://en.wikipedia.org/wiki/M-86_%28Michigan_highway%29"},"members":[{"id":"w17737723","type":"way","role":""},{"id":"w17735949","type":"way","role":""},{"id":"w17740404","type":"way","role":""},{"id":"w17966273","type":"way","role":""},{"id":"w17964745","type":"way","role":""},{"id":"w151538068","type":"way","role":""},{"id":"w151538067","type":"way","role":""},{"id":"w17964960","type":"way","role":""},{"id":"w17966099","type":"way","role":""},{"id":"w17968009","type":"way","role":""},{"id":"w41259499","type":"way","role":""},{"id":"w151540401","type":"way","role":""},{"id":"w151540418","type":"way","role":""},{"id":"w17967997","type":"way","role":""},{"id":"w17966029","type":"way","role":""},{"id":"w17964801","type":"way","role":""},{"id":"w41259496","type":"way","role":""},{"id":"w151540399","type":"way","role":""},{"id":"w17968004","type":"way","role":""},{"id":"w17966462","type":"way","role":""},{"id":"w134150830","type":"way","role":""},{"id":"w134150801","type":"way","role":""},{"id":"w17732295","type":"way","role":""}]},"n185980093":{"id":"n185980093","loc":[-85.6271414,41.9407274]},"n185964330":{"id":"n185964330","loc":[-85.6235688,41.9399111]},"n185964328":{"id":"n185964328","loc":[-85.6235609,41.9391301]},"n185958034":{"id":"n185958034","loc":[-85.627102,41.939125]},"n185964331":{"id":"n185964331","loc":[-85.623571,41.940124]},"n185964329":{"id":"n185964329","loc":[-85.623562,41.9392411]},"n185972756":{"id":"n185972756","loc":[-85.623802,41.939102]},"n185972757":{"id":"n185972757","loc":[-85.623584,41.93913]},"n185975325":{"id":"n185975325","loc":[-85.624835,41.939318]},"n185975326":{"id":"n185975326","loc":[-85.624811,41.939435]},"n185975327":{"id":"n185975327","loc":[-85.624635,41.939703]},"n185975328":{"id":"n185975328","loc":[-85.624366,41.940055]},"n185975330":{"id":"n185975330","loc":[-85.624287,41.940113]},"n185975332":{"id":"n185975332","loc":[-85.624215,41.940134]},"n185980088":{"id":"n185980088","loc":[-85.627127,41.940086]},"n185988943":{"id":"n185988943","loc":[-85.622643,41.940128]},"n185988961":{"id":"n185988961","loc":[-85.627263,41.940082]},"n185990192":{"id":"n185990192","loc":[-85.622933,41.939224]},"n185990194":{"id":"n185990194","loc":[-85.621976,41.939203]},"n185991378":{"id":"n185991378","loc":[-85.622643,41.940635]},"n1475283999":{"id":"n1475283999","loc":[-85.6271165,41.9408429]},"n185980090":{"id":"n185980090","loc":[-85.6271315,41.9402001]},"n185958036":{"id":"n185958036","loc":[-85.6248366,41.9391615]},"n1819800188":{"id":"n1819800188","loc":[-85.6246947,41.9401644]},"n1819800199":{"id":"n1819800199","loc":[-85.6233686,41.9430896]},"n1819800204":{"id":"n1819800204","loc":[-85.6223236,41.9408587]},"n1819800213":{"id":"n1819800213","loc":[-85.6247526,41.9414138]},"n1819800216":{"id":"n1819800216","loc":[-85.6230961,41.9407151]},"n1819800218":{"id":"n1819800218","loc":[-85.621991,41.9429336]},"n1819800221":{"id":"n1819800221","loc":[-85.6246088,41.9424708]},"n1819800227":{"id":"n1819800227","loc":[-85.6241368,41.9403081]},"n1819800230":{"id":"n1819800230","loc":[-85.6226776,41.9431012]},"n1819800231":{"id":"n1819800231","loc":[-85.6243728,41.9401644]},"n1819800232":{"id":"n1819800232","loc":[-85.6249629,41.9408907]},"n1819800248":{"id":"n1819800248","loc":[-85.6238685,41.9405555]},"n1819800266":{"id":"n1819800266","loc":[-85.6246882,41.9418367]},"n1819800271":{"id":"n1819800271","loc":[-85.62492,41.9413695]},"n1819800294":{"id":"n1819800294","loc":[-85.6243556,41.9427465]},"n1819800304":{"id":"n1819800304","loc":[-85.6251453,41.94117]},"n1819800325":{"id":"n1819800325","loc":[-85.6248234,41.9405714]},"n1819800362":{"id":"n1819800362","loc":[-85.6239544,41.9429416]},"n1819800368":{"id":"n1819800368","loc":[-85.6243406,41.9402283]},"n1819800375":{"id":"n1819800375","loc":[-85.6226562,41.940755]},"n1819800377":{"id":"n1819800377","loc":[-85.6232033,41.9406512]},"n185945133":{"id":"n185945133","loc":[-85.623501,41.933232]},"n185945135":{"id":"n185945135","loc":[-85.624776,41.933205]},"n185945395":{"id":"n185945395","loc":[-85.624741,41.93019]},"n185952239":{"id":"n185952239","loc":[-85.615166,41.9382]},"n185954490":{"id":"n185954490","loc":[-85.624721,41.929278]},"n185957831":{"id":"n185957831","loc":[-85.625041,41.938662]},"n185958030":{"id":"n185958030","loc":[-85.629033,41.93913]},"n185958032":{"id":"n185958032","loc":[-85.628429,41.939143]},"n185958498":{"id":"n185958498","loc":[-85.621605,41.940143]},"n185961186":{"id":"n185961186","loc":[-85.624792,41.935214]},"n185963099":{"id":"n185963099","loc":[-85.6204461,41.9401485]},"n185963698":{"id":"n185963698","loc":[-85.6297342,41.9400783]},"n185964320":{"id":"n185964320","loc":[-85.623511,41.934216]},"n185964322":{"id":"n185964322","loc":[-85.6235312,41.9362084]},"n185964324":{"id":"n185964324","loc":[-85.6235488,41.9371726]},"n185964326":{"id":"n185964326","loc":[-85.6235512,41.9381718]},"n185967077":{"id":"n185967077","loc":[-85.617359,41.940161]},"n185967634":{"id":"n185967634","loc":[-85.6248039,41.9362012]},"n185970833":{"id":"n185970833","loc":[-85.6248019,41.9381684]},"n185972752":{"id":"n185972752","loc":[-85.624582,41.938848]},"n185972754":{"id":"n185972754","loc":[-85.6242,41.939008]},"n185973251":{"id":"n185973251","loc":[-85.602727,41.936012]},"n185974509":{"id":"n185974509","loc":[-85.62478,41.93217]},"n185975315":{"id":"n185975315","loc":[-85.624703,41.925597]},"n185975316":{"id":"n185975316","loc":[-85.624716,41.927359]},"n185975317":{"id":"n185975317","loc":[-85.62475,41.93119]},"n185975318":{"id":"n185975318","loc":[-85.624782,41.934218]},"n185975320":{"id":"n185975320","loc":[-85.6247949,41.9371708]},"n185977754":{"id":"n185977754","loc":[-85.6276,41.937412]},"n185980075":{"id":"n185980075","loc":[-85.627451,41.937549]},"n185980077":{"id":"n185980077","loc":[-85.627375,41.937618]},"n185980078":{"id":"n185980078","loc":[-85.627278,41.937728]},"n185980079":{"id":"n185980079","loc":[-85.627199,41.937842]},"n185980081":{"id":"n185980081","loc":[-85.627141,41.937981]},"n185980083":{"id":"n185980083","loc":[-85.627109,41.938153]},"n185980085":{"id":"n185980085","loc":[-85.627101,41.938699]},"n185981173":{"id":"n185981173","loc":[-85.61433,41.940167]},"n185987021":{"id":"n185987021","loc":[-85.628311,41.942261]},"n185988963":{"id":"n185988963","loc":[-85.628439,41.940086]},"n185990195":{"id":"n185990195","loc":[-85.621225,41.939143]},"n185990196":{"id":"n185990196","loc":[-85.620576,41.939033]},"n185990198":{"id":"n185990198","loc":[-85.619081,41.938804]},"n185990200":{"id":"n185990200","loc":[-85.617593,41.938552]},"n185990202":{"id":"n185990202","loc":[-85.617372,41.938535]},"n185990204":{"id":"n185990204","loc":[-85.616087,41.93832]},"n185990206":{"id":"n185990206","loc":[-85.615754,41.938289]},"n185990209":{"id":"n185990209","loc":[-85.615438,41.938251]},"n185990211":{"id":"n185990211","loc":[-85.613469,41.937867]},"n185990212":{"id":"n185990212","loc":[-85.610172,41.937298]},"n185990213":{"id":"n185990213","loc":[-85.605537,41.936497]},"n185990214":{"id":"n185990214","loc":[-85.604014,41.936234]},"n1819800180":{"id":"n1819800180","loc":[-85.588775,41.9455032]},"n1819800181":{"id":"n1819800181","loc":[-85.6074212,41.9408827]},"n1819800182":{"id":"n1819800182","loc":[-85.6131397,41.9427022]},"n1819800183":{"id":"n1819800183","loc":[-85.6171523,41.9416807]},"n1819800184":{"id":"n1819800184","loc":[-85.602465,41.9397415]},"n1819800185":{"id":"n1819800185","loc":[-85.6109296,41.9410583]},"n1819800186":{"id":"n1819800186","loc":[-85.6165729,41.9418004]},"n1819800189":{"id":"n1819800189","loc":[-85.5866293,41.9458224]},"n1819800191":{"id":"n1819800191","loc":[-85.5853311,41.9466603]},"n1819800201":{"id":"n1819800201","loc":[-85.6101142,41.9433406]},"n1819800202":{"id":"n1819800202","loc":[-85.600963,41.9428618]},"n1819800206":{"id":"n1819800206","loc":[-85.6154357,41.9427501]},"n1819800207":{"id":"n1819800207","loc":[-85.6040309,41.9414094]},"n1819800209":{"id":"n1819800209","loc":[-85.6113694,41.943189]},"n1819800211":{"id":"n1819800211","loc":[-85.618032,41.9416408]},"n1819800214":{"id":"n1819800214","loc":[-85.5959419,41.9402602]},"n1819800219":{"id":"n1819800219","loc":[-85.5972117,41.9420043]},"n1819800223":{"id":"n1819800223","loc":[-85.6117171,41.9430019]},"n1819800224":{"id":"n1819800224","loc":[-85.5977873,41.9395579]},"n1819800226":{"id":"n1819800226","loc":[-85.5917362,41.9432209]},"n1819800228":{"id":"n1819800228","loc":[-85.6055759,41.9419122]},"n1819800229":{"id":"n1819800229","loc":[-85.6203395,41.9425595]},"n1819800233":{"id":"n1819800233","loc":[-85.6107579,41.9433007]},"n1819800234":{"id":"n1819800234","loc":[-85.6039773,41.9412498]},"n1819800235":{"id":"n1819800235","loc":[-85.6000977,41.9412861]},"n1819800236":{"id":"n1819800236","loc":[-85.6026689,41.9407231]},"n1819800237":{"id":"n1819800237","loc":[-85.615161,41.9428662]},"n1819800238":{"id":"n1819800238","loc":[-85.5878953,41.9454314]},"n1819800239":{"id":"n1819800239","loc":[-85.6035267,41.941569]},"n1819800240":{"id":"n1819800240","loc":[-85.5929738,41.9450208]},"n1819800241":{"id":"n1819800241","loc":[-85.6186329,41.9416488]},"n1819800242":{"id":"n1819800242","loc":[-85.5881136,41.9483963]},"n1819800243":{"id":"n1819800243","loc":[-85.5909208,41.9466922]},"n1819800244":{"id":"n1819800244","loc":[-85.5997721,41.9394941]},"n1819800245":{"id":"n1819800245","loc":[-85.6202064,41.9425712]},"n1819800246":{"id":"n1819800246","loc":[-85.591071,41.9448808]},"n1819800247":{"id":"n1819800247","loc":[-85.5866078,41.9490622]},"n1819800250":{"id":"n1819800250","loc":[-85.602383,41.9420841]},"n1819800251":{"id":"n1819800251","loc":[-85.5957418,41.9426906]},"n1819800255":{"id":"n1819800255","loc":[-85.6157039,41.9416727]},"n1819800256":{"id":"n1819800256","loc":[-85.6080328,41.9410982]},"n1819800258":{"id":"n1819800258","loc":[-85.6192551,41.9414892]},"n1819800260":{"id":"n1819800260","loc":[-85.6104253,41.94117]},"n1819800261":{"id":"n1819800261","loc":[-85.6204503,41.9425709]},"n1819800263":{"id":"n1819800263","loc":[-85.5872194,41.9455431]},"n1819800264":{"id":"n1819800264","loc":[-85.616176,41.9418244]},"n1819800268":{"id":"n1819800268","loc":[-85.6120883,41.9426703]},"n1819800269":{"id":"n1819800269","loc":[-85.5894547,41.9474946]},"n1819800272":{"id":"n1819800272","loc":[-85.6209181,41.9425027]},"n1819800274":{"id":"n1819800274","loc":[-85.6122814,41.9412817]},"n1819800276":{"id":"n1819800276","loc":[-85.5895153,41.9452798]},"n1819800277":{"id":"n1819800277","loc":[-85.5884317,41.9455272]},"n1819800279":{"id":"n1819800279","loc":[-85.5884103,41.9480966]},"n1819800287":{"id":"n1819800287","loc":[-85.5904917,41.9453915]},"n1819800288":{"id":"n1819800288","loc":[-85.6212292,41.9412977]},"n1819800289":{"id":"n1819800289","loc":[-85.5954377,41.9406832]},"n1819800290":{"id":"n1819800290","loc":[-85.593721,41.9420957]},"n1819800291":{"id":"n1819800291","loc":[-85.6162832,41.9427102]},"n1819800292":{"id":"n1819800292","loc":[-85.605018,41.9401804]},"n1819800293":{"id":"n1819800293","loc":[-85.6086443,41.941146]},"n1819800296":{"id":"n1819800296","loc":[-85.6204675,41.9413775]},"n1819800297":{"id":"n1819800297","loc":[-85.612496,41.9424947]},"n1819800299":{"id":"n1819800299","loc":[-85.6065629,41.9423431]},"n1819800301":{"id":"n1819800301","loc":[-85.6036125,41.9398452]},"n1819800303":{"id":"n1819800303","loc":[-85.6114767,41.94117]},"n1819800306":{"id":"n1819800306","loc":[-85.592616,41.9428139]},"n1819800308":{"id":"n1819800308","loc":[-85.6023041,41.9419521]},"n1819800310":{"id":"n1819800310","loc":[-85.6218944,41.9411061]},"n1819800311":{"id":"n1819800311","loc":[-85.6097816,41.941162]},"n1819800312":{"id":"n1819800312","loc":[-85.5922549,41.9457869]},"n1819800313":{"id":"n1819800313","loc":[-85.5986027,41.9417206]},"n1819800314":{"id":"n1819800314","loc":[-85.5918687,41.946138]},"n1819800315":{"id":"n1819800315","loc":[-85.5872875,41.948883]},"n1819800316":{"id":"n1819800316","loc":[-85.594272,41.9436642]},"n1819800317":{"id":"n1819800317","loc":[-85.6176351,41.941577]},"n1819800318":{"id":"n1819800318","loc":[-85.6137834,41.9430853]},"n1819800319":{"id":"n1819800319","loc":[-85.6195383,41.942622],"tags":{"leisure":"slipway"}},"n1819800320":{"id":"n1819800320","loc":[-85.5971006,41.9398053]},"n1819800321":{"id":"n1819800321","loc":[-85.601714,41.9406752]},"n1819800322":{"id":"n1819800322","loc":[-85.5908028,41.9453117]},"n1819800323":{"id":"n1819800323","loc":[-85.6062732,41.9404597]},"n1819800324":{"id":"n1819800324","loc":[-85.62124,41.9425905]},"n1819800327":{"id":"n1819800327","loc":[-85.6008664,41.942766]},"n1819800328":{"id":"n1819800328","loc":[-85.6179355,41.9428538]},"n1819800330":{"id":"n1819800330","loc":[-85.6045566,41.9415131]},"n1819800331":{"id":"n1819800331","loc":[-85.5944935,41.9414653]},"n1819800333":{"id":"n1819800333","loc":[-85.6088911,41.943181]},"n1819800334":{"id":"n1819800334","loc":[-85.5946367,41.943369]},"n1819800336":{"id":"n1819800336","loc":[-85.6150494,41.9429656]},"n1819800343":{"id":"n1819800343","loc":[-85.6096099,41.9433326]},"n1819800345":{"id":"n1819800345","loc":[-85.5915216,41.9435401]},"n1819800347":{"id":"n1819800347","loc":[-85.607786,41.9428698]},"n1819800349":{"id":"n1819800349","loc":[-85.6187616,41.9426623]},"n1819800350":{"id":"n1819800350","loc":[-85.6012527,41.9426064]},"n1819800352":{"id":"n1819800352","loc":[-85.6214867,41.9428379]},"n1819800354":{"id":"n1819800354","loc":[-85.61338,41.94293]},"n1819800355":{"id":"n1819800355","loc":[-85.5923156,41.9428139]},"n1819800357":{"id":"n1819800357","loc":[-85.5901591,41.9453197]},"n1819800359":{"id":"n1819800359","loc":[-85.6033979,41.9408827]},"n1819800360":{"id":"n1819800360","loc":[-85.6186543,41.9414653]},"n1819800363":{"id":"n1819800363","loc":[-85.6128607,41.9425665]},"n1819800365":{"id":"n1819800365","loc":[-85.614234,41.9412977]},"n1819800367":{"id":"n1819800367","loc":[-85.6089662,41.9410902]},"n1819800369":{"id":"n1819800369","loc":[-85.6197379,41.9413695]},"n1819800370":{"id":"n1819800370","loc":[-85.6037348,41.941733]},"n1819800371":{"id":"n1819800371","loc":[-85.5993467,41.9415654]},"n1819800372":{"id":"n1819800372","loc":[-85.598077,41.94196]},"n1819800373":{"id":"n1819800373","loc":[-85.5984203,41.9394781]},"n1819800374":{"id":"n1819800374","loc":[-85.6013315,41.9427066]},"n1819800376":{"id":"n1819800376","loc":[-85.5934673,41.944167]},"n1819800378":{"id":"n1819800378","loc":[-85.6011062,41.9407753]},"n1819800379":{"id":"n1819800379","loc":[-85.6150602,41.9415131]},"n1819800380":{"id":"n1819800380","loc":[-85.6132148,41.9412338]},"n1819800381":{"id":"n1819800381","loc":[-85.5889038,41.9453835]},"n2139966621":{"id":"n2139966621","loc":[-85.6198719,41.9426184]},"n2139966622":{"id":"n2139966622","loc":[-85.6197551,41.9426123]},"n2139966623":{"id":"n2139966623","loc":[-85.6196467,41.9426279]},"n2139966624":{"id":"n2139966624","loc":[-85.6191519,41.9426221]},"n2139966625":{"id":"n2139966625","loc":[-85.6194153,41.9426256]},"n2139966626":{"id":"n2139966626","loc":[-85.6200497,41.9425812]},"n2139966629":{"id":"n2139966629","loc":[-85.6192123,41.9426229]},"n2203933101":{"id":"n2203933101","loc":[-85.6030009,41.9360592]},"w17967539":{"id":"w17967539","tags":{"highway":"residential","name":"1st Ave"},"nodes":["n185965099","n185963395","n185987021"]},"w17967751":{"id":"w17967751","tags":{"highway":"residential","name":"River St"},"nodes":["n185980088","n185988961","n185988963","n185963698"]},"w17965088":{"id":"w17965088","tags":{"highway":"residential","name":"9th St"},"nodes":["n185945133","n185964320","n185964322","n185964324","n185964326","n185964328","n185964329","n185964330","n185964331"]},"w17964467":{"id":"w17964467","tags":{"highway":"residential","name":"Mechanic St"},"nodes":["n185958030","n185958032","n185958034","n185958036"]},"w134150842":{"id":"w134150842","tags":{"bridge":"yes","highway":"residential","name":"6th St"},"nodes":["n185980090","n185980093"]},"w17966740":{"id":"w17966740","tags":{"highway":"residential","name":"6th St"},"nodes":["n185977754","n185980075","n185980077","n185980078","n185980079","n185980081","n185980083","n185980085","n185958034","n185980088","n185980090"]},"w170844765":{"id":"w170844765","tags":{"waterway":"dam"},"nodes":["n1819800304","n1819800232","n1819800325","n1819800188"]},"w17967745":{"id":"w17967745","tags":{"highway":"residential","name":"River St"},"nodes":["n185981173","n185967077","n185963099","n185958498","n185988943","n185964331","n185975332"]},"w17968113":{"id":"w17968113","tags":{"highway":"residential","name":"Green St"},"nodes":["n185988943","n185991378"]},"w134150833":{"id":"w134150833","tags":{"highway":"residential","name":"6th St"},"nodes":["n185980093","n1475283999","n185963392"]},"w17967935":{"id":"w17967935","tags":{"name":"Michigan Central Railroad","railway":"abandoned"},"nodes":["n185972757","n185990192","n185990194","n185990195","n185990196","n185990198","n185990200","n185990202","n185990204","n185990206","n185990209","n185952239","n185990211","n185990212","n185990213","n185990214","n2203933101","n185973251"]},"w17965993":{"id":"w17965993","tags":{"name":"Conrail Railroad","railway":"abandoned"},"nodes":["n185957831","n185972752","n185972754","n185972756","n185972757"]},"w17966211":{"id":"w17966211","tags":{"highway":"residential","name":"8th St"},"nodes":["n185975315","n185975316","n185954490","n185945395","n185975317","n185974509","n185945135","n185975318","n185961186","n185967634","n185975320","n185970833","n185958036","n185975325","n185975326","n185975327","n185975328","n185975330","n185975332"]},"w170844766":{"id":"w170844766","tags":{"waterway":"riverbank"},"nodes":["n1819800229","n1819800245","n2139966626","n2139966621","n2139966622","n2139966623","n1819800319","n2139966625","n2139966629","n2139966624","n1819800349","n1819800328","n1819800291","n1819800206","n1819800237","n1819800336","n1819800318","n1819800354","n1819800182","n1819800363","n1819800297","n1819800268","n1819800223","n1819800209","n1819800233","n1819800201","n1819800343","n1819800333","n1819800347","n1819800299","n1819800228","n1819800330","n1819800370","n1819800250","n1819800374","n1819800202","n1819800327","n1819800350","n1819800308","n1819800239","n1819800207","n1819800234","n1819800359","n1819800236","n1819800321","n1819800378","n1819800235","n1819800371","n1819800313","n1819800372","n1819800219","n1819800251","n1819800334","n1819800316","n1819800376","n1819800240","n1819800312","n1819800314","n1819800243","n1819800269","n1819800279","n1819800242","n1819800315","n1819800247","n1819800191","n1819800189","n1819800263","n1819800238","n1819800277","n1819800180","n1819800381","n1819800276","n1819800357","n1819800287","n1819800322","n1819800246","n1819800345","n1819800226","n1819800355","n1819800306","n1819800290","n1819800331","n1819800289","n1819800214","n1819800320","n1819800224","n1819800373","n1819800244","n1819800184","n1819800301","n1819800292","n1819800323","n1819800181","n1819800256","n1819800293","n1819800367","n1819800311","n1819800260","n1819800185","n1819800303","n1819800274","n1819800380","n1819800365","n1819800379","n1819800255","n1819800264","n1819800186","n1819800183","n1819800317","n1819800211","n1819800241","n1819800360","n1819800258","n1819800369","n1819800296","n1819800288","n1819800310","n1819800204","n1819800375","n1819800216","n1819800377","n1819800248","n1819800227","n1819800368","n1819800231","n1819800188","n1819800325","n1819800232","n1819800304","n1819800271","n1819800213","n1819800266","n1819800221","n1819800294","n1819800362","n1819800199","n1819800230","n1819800218","n1819800352","n1819800324","n1819800272","n1819800261","n1819800229"]},"n1875654132":{"id":"n1875654132","loc":[-85.6297439,41.939808]},"n1475293263":{"id":"n1475293263","loc":[-85.6296235,41.939922]},"n185947850":{"id":"n185947850","loc":[-85.631594,41.942613]},"n185952745":{"id":"n185952745","loc":[-85.630986,41.941786]},"n185972907":{"id":"n185972907","loc":[-85.631797,41.9420055]},"n185972911":{"id":"n185972911","loc":[-85.6309723,41.9411623]},"n185972915":{"id":"n185972915","loc":[-85.6295971,41.939267]},"n1475293223":{"id":"n1475293223","loc":[-85.6313962,41.9416114],"tags":{"railway":"level_crossing"}},"n1475293231":{"id":"n1475293231","loc":[-85.6318779,41.9415447]},"n1475293241":{"id":"n1475293241","loc":[-85.6304613,41.9405499]},"n1475293246":{"id":"n1475293246","loc":[-85.6297512,41.9395393],"tags":{"railway":"level_crossing"}},"n1475293251":{"id":"n1475293251","loc":[-85.6316633,41.9415128]},"n2139982404":{"id":"n2139982404","loc":[-85.6313283,41.9413748]},"n2139982407":{"id":"n2139982407","loc":[-85.6325545,41.9417787]},"n2139982408":{"id":"n2139982408","loc":[-85.6324499,41.9417693]},"n2139982409":{"id":"n2139982409","loc":[-85.6324753,41.9416444]},"n2139982410":{"id":"n2139982410","loc":[-85.6325814,41.9416538]},"n2139982411":{"id":"n2139982411","loc":[-85.6319572,41.9413515]},"n2139982412":{"id":"n2139982412","loc":[-85.6322925,41.941139]},"n2139982413":{"id":"n2139982413","loc":[-85.6323153,41.941153]},"n2139982414":{"id":"n2139982414","loc":[-85.6323019,41.9412617]},"n2139982415":{"id":"n2139982415","loc":[-85.6323703,41.9412667]},"n2139982416":{"id":"n2139982416","loc":[-85.6323555,41.941538]},"n2139982417":{"id":"n2139982417","loc":[-85.6321343,41.9416777]},"n2139982418":{"id":"n2139982418","loc":[-85.6319425,41.9416866]},"n2139982419":{"id":"n2139982419","loc":[-85.6320303,41.9416941]},"n2139982420":{"id":"n2139982420","loc":[-85.6321665,41.9415554]},"n2139982421":{"id":"n2139982421","loc":[-85.632412,41.9414164]},"n2139982422":{"id":"n2139982422","loc":[-85.6324801,41.9413421]},"n2139982423":{"id":"n2139982423","loc":[-85.6325023,41.9412585]},"n2139982424":{"id":"n2139982424","loc":[-85.6324532,41.9411607]},"n2139982425":{"id":"n2139982425","loc":[-85.6323502,41.941103]},"n2139982426":{"id":"n2139982426","loc":[-85.6322362,41.9411183]},"n2139982427":{"id":"n2139982427","loc":[-85.6318941,41.9413551]},"n2139982428":{"id":"n2139982428","loc":[-85.6318592,41.9414105]},"n2139982429":{"id":"n2139982429","loc":[-85.6320111,41.9415866]},"n2139982430":{"id":"n2139982430","loc":[-85.632446,41.9413792]},"n2139982431":{"id":"n2139982431","loc":[-85.6325112,41.941416]},"n2139982432":{"id":"n2139982432","loc":[-85.6325449,41.9416345]},"n2139982433":{"id":"n2139982433","loc":[-85.6326122,41.94164]},"n2139982434":{"id":"n2139982434","loc":[-85.6325954,41.9421966]},"n2139982435":{"id":"n2139982435","loc":[-85.6325655,41.9422411]},"n2139982436":{"id":"n2139982436","loc":[-85.632515,41.9422564]},"n2139982437":{"id":"n2139982437","loc":[-85.6324495,41.94223]},"n2139982438":{"id":"n2139982438","loc":[-85.6324009,41.9421743]},"n2139982439":{"id":"n2139982439","loc":[-85.6323915,41.9421145]},"n2139982440":{"id":"n2139982440","loc":[-85.6320287,41.9418585]},"n2139982441":{"id":"n2139982441","loc":[-85.6318285,41.9416387]},"n1475293258":{"id":"n1475293258","loc":[-85.6318289,41.9415077]},"n2168544754":{"id":"n2168544754","loc":[-85.6312814,41.9431198]},"n2168544755":{"id":"n2168544755","loc":[-85.6314212,41.9430646]},"n2168544756":{"id":"n2168544756","loc":[-85.6313387,41.942949]},"n2168544757":{"id":"n2168544757","loc":[-85.6311989,41.9430041]},"n2168544758":{"id":"n2168544758","loc":[-85.6311024,41.9429313]},"n2168544759":{"id":"n2168544759","loc":[-85.6310087,41.9428087]},"n2168544760":{"id":"n2168544760","loc":[-85.6313831,41.9426504]},"n2168544761":{"id":"n2168544761","loc":[-85.6314768,41.9427729]},"n2168544762":{"id":"n2168544762","loc":[-85.6306376,41.942809]},"n2168544763":{"id":"n2168544763","loc":[-85.6307378,41.9429427]},"n2168544764":{"id":"n2168544764","loc":[-85.630841,41.9428998]},"n2168544765":{"id":"n2168544765","loc":[-85.6307408,41.9427662]},"n2168544766":{"id":"n2168544766","loc":[-85.6305404,41.9426029]},"n2168544767":{"id":"n2168544767","loc":[-85.6304976,41.9426194]},"n2168544768":{"id":"n2168544768","loc":[-85.6305673,41.9427184]},"n2168544769":{"id":"n2168544769","loc":[-85.6306164,41.9426984]},"n2168544770":{"id":"n2168544770","loc":[-85.6306418,41.9427302]},"n2168544771":{"id":"n2168544771","loc":[-85.6306861,41.9427137]},"n2168544772":{"id":"n2168544772","loc":[-85.6307146,41.9427537]},"n2168544773":{"id":"n2168544773","loc":[-85.6308999,41.9426807]},"n2168544774":{"id":"n2168544774","loc":[-85.6308429,41.9426053]},"n2168544775":{"id":"n2168544775","loc":[-85.6308999,41.9425806]},"n2168544776":{"id":"n2168544776","loc":[-85.6308318,41.9424875]},"n2168544777":{"id":"n2168544777","loc":[-85.6307732,41.9425087]},"n2168544778":{"id":"n2168544778","loc":[-85.6307178,41.9424357]},"n2168544779":{"id":"n2168544779","loc":[-85.630485,41.942524]},"n2189099387":{"id":"n2189099387","loc":[-85.631203,41.9393371]},"n2189099404":{"id":"n2189099404","loc":[-85.6301963,41.9391363]},"n2189099405":{"id":"n2189099405","loc":[-85.6304447,41.9391352]},"n2189099406":{"id":"n2189099406","loc":[-85.6304463,41.9393391]},"n2189099407":{"id":"n2189099407","loc":[-85.6308435,41.9393373]},"n2189099408":{"id":"n2189099408","loc":[-85.6308418,41.9391251]},"n2189099409":{"id":"n2189099409","loc":[-85.6310929,41.939124]},"n2189099410":{"id":"n2189099410","loc":[-85.6310946,41.9393376]},"n2189112720":{"id":"n2189112720","loc":[-85.6314677,41.9412327]},"n2189112721":{"id":"n2189112721","loc":[-85.6313337,41.9411397]},"n2189112722":{"id":"n2189112722","loc":[-85.6320521,41.9405678]},"n2189112723":{"id":"n2189112723","loc":[-85.6321899,41.9406633]},"n2189112724":{"id":"n2189112724","loc":[-85.6313229,41.9408344]},"n2189112725":{"id":"n2189112725","loc":[-85.6311223,41.9410018]},"n2189112726":{"id":"n2189112726","loc":[-85.6313205,41.9411333]},"n2189112727":{"id":"n2189112727","loc":[-85.6315211,41.9409659]},"n2189112728":{"id":"n2189112728","loc":[-85.6311035,41.9402529]},"n2189112729":{"id":"n2189112729","loc":[-85.631226,41.9402107]},"n2189112730":{"id":"n2189112730","loc":[-85.6315966,41.9408051]},"n2189112731":{"id":"n2189112731","loc":[-85.6314741,41.9408473]},"n2189112732":{"id":"n2189112732","loc":[-85.6318114,41.940534]},"n2189112733":{"id":"n2189112733","loc":[-85.631588,41.94061]},"n2189112734":{"id":"n2189112734","loc":[-85.6314379,41.940366]},"n2189112735":{"id":"n2189112735","loc":[-85.6316613,41.94029]},"n2189112736":{"id":"n2189112736","loc":[-85.6306214,41.9400415]},"n2189112737":{"id":"n2189112737","loc":[-85.6304362,41.9397728]},"n2189112738":{"id":"n2189112738","loc":[-85.6305899,41.9397142]},"n2189112739":{"id":"n2189112739","loc":[-85.6307751,41.9399828]},"n2189112740":{"id":"n2189112740","loc":[-85.6304695,41.9401673]},"n2189112741":{"id":"n2189112741","loc":[-85.6301298,41.9396855]},"n2189112742":{"id":"n2189112742","loc":[-85.6303016,41.9396184]},"n2189112743":{"id":"n2189112743","loc":[-85.6306413,41.9401003]},"n2189112744":{"id":"n2189112744","loc":[-85.6309656,41.9406189]},"n2189112745":{"id":"n2189112745","loc":[-85.6308738,41.940493]},"n2189112746":{"id":"n2189112746","loc":[-85.6309333,41.940469]},"n2189112747":{"id":"n2189112747","loc":[-85.6307634,41.9402358]},"n2189112748":{"id":"n2189112748","loc":[-85.6308798,41.9401889]},"n2189112749":{"id":"n2189112749","loc":[-85.6311416,41.940548]},"n2189112750":{"id":"n2189112750","loc":[-85.6309577,41.9408708]},"n2189112751":{"id":"n2189112751","loc":[-85.630874,41.9407777]},"n2189112752":{"id":"n2189112752","loc":[-85.6310622,41.9406841]},"n2189112753":{"id":"n2189112753","loc":[-85.6311459,41.9407772]},"n2189112754":{"id":"n2189112754","loc":[-85.6320308,41.9405747]},"n2189112755":{"id":"n2189112755","loc":[-85.6317769,41.9401857]},"n2189112756":{"id":"n2189112756","loc":[-85.6313462,41.9401785]},"n2189112757":{"id":"n2189112757","loc":[-85.6313423,41.9401199]},"n2189112758":{"id":"n2189112758","loc":[-85.6318308,41.9401184]},"n2189112759":{"id":"n2189112759","loc":[-85.6321154,41.9405433]},"n2189112760":{"id":"n2189112760","loc":[-85.6310307,41.941683]},"n2189112761":{"id":"n2189112761","loc":[-85.6309808,41.9416078]},"n2189112762":{"id":"n2189112762","loc":[-85.6312094,41.9415156]},"n2189112763":{"id":"n2189112763","loc":[-85.6312636,41.9415865]},"n2189112764":{"id":"n2189112764","loc":[-85.6309384,41.94155]},"n2189112765":{"id":"n2189112765","loc":[-85.631156,41.9414619]},"n2189112766":{"id":"n2189112766","loc":[-85.6311968,41.94152]},"n2189112767":{"id":"n2189112767","loc":[-85.6308946,41.9414851]},"n2189112768":{"id":"n2189112768","loc":[-85.6308237,41.9413888]},"n2189112769":{"id":"n2189112769","loc":[-85.6309858,41.9413228]},"n2189112770":{"id":"n2189112770","loc":[-85.6310567,41.9414192]},"n2189112771":{"id":"n2189112771","loc":[-85.6307774,41.9413276]},"n2189112772":{"id":"n2189112772","loc":[-85.6309068,41.9412735]},"n2189112773":{"id":"n2189112773","loc":[-85.6309531,41.9413347]},"n2189112774":{"id":"n2189112774","loc":[-85.6307975,41.9412466]},"n2189112775":{"id":"n2189112775","loc":[-85.6307006,41.9411699]},"n2189112776":{"id":"n2189112776","loc":[-85.6308289,41.941113]},"n2189112777":{"id":"n2189112777","loc":[-85.6308997,41.9412012]},"n2189112778":{"id":"n2189112778","loc":[-85.630765,41.9412062]},"n2189112779":{"id":"n2189112779","loc":[-85.630739,41.9412177]},"n2189112780":{"id":"n2189112780","loc":[-85.6305822,41.9410391]},"n2189112781":{"id":"n2189112781","loc":[-85.6304117,41.9408177]},"n2189112782":{"id":"n2189112782","loc":[-85.6305086,41.9407769]},"n2189112783":{"id":"n2189112783","loc":[-85.6306779,41.9410044]},"n2189112784":{"id":"n2189112784","loc":[-85.6307734,41.9421663]},"n2189112785":{"id":"n2189112785","loc":[-85.630708,41.9420741]},"n2189112786":{"id":"n2189112786","loc":[-85.630863,41.9420133]},"n2189112787":{"id":"n2189112787","loc":[-85.6309285,41.9421055]},"n2189112788":{"id":"n2189112788","loc":[-85.6307014,41.9420263]},"n2189112789":{"id":"n2189112789","loc":[-85.6306648,41.941971]},"n2189112790":{"id":"n2189112790","loc":[-85.6307927,41.9419178]},"n2189112791":{"id":"n2189112791","loc":[-85.6308366,41.9419696]},"n2189112792":{"id":"n2189112792","loc":[-85.6307574,41.9418708]},"n2189112793":{"id":"n2189112793","loc":[-85.6306288,41.9419231]},"n2189112794":{"id":"n2189112794","loc":[-85.6306943,41.9417835]},"n2189112795":{"id":"n2189112795","loc":[-85.6305344,41.9418474]},"n2189112796":{"id":"n2189112796","loc":[-85.6305981,41.9419355]},"n2189123410":{"id":"n2189123410","loc":[-85.6315476,41.9393801]},"n2189123412":{"id":"n2189123412","loc":[-85.6315247,41.9399188]},"n2189123415":{"id":"n2189123415","loc":[-85.6316484,41.9400433]},"n185945138":{"id":"n185945138","loc":[-85.627073,41.93319]},"n185945142":{"id":"n185945142","loc":[-85.6296891,41.9331674]},"n185945401":{"id":"n185945401","loc":[-85.6269,41.930199]},"n185945405":{"id":"n185945405","loc":[-85.6296598,41.9301676]},"n185956891":{"id":"n185956891","loc":[-85.6251617,41.9255049]},"n185959979":{"id":"n185959979","loc":[-85.626333,41.928347]},"n185959983":{"id":"n185959983","loc":[-85.6296419,41.9283288]},"n185961192":{"id":"n185961192","loc":[-85.627053,41.9352031]},"n185961200":{"id":"n185961200","loc":[-85.6297088,41.9351902]},"n185963655":{"id":"n185963655","loc":[-85.6296112,41.9273948]},"n185963665":{"id":"n185963665","loc":[-85.626047,41.92737]},"n185963688":{"id":"n185963688","loc":[-85.6296503,41.9292199]},"n185963689":{"id":"n185963689","loc":[-85.6296694,41.931157]},"n185963690":{"id":"n185963690","loc":[-85.6296791,41.9321485]},"n185963691":{"id":"n185963691","loc":[-85.6296991,41.9341973]},"n185967638":{"id":"n185967638","loc":[-85.627089,41.9361884]},"n185972917":{"id":"n185972917","loc":[-85.6293759,41.9388605]},"n185972919":{"id":"n185972919","loc":[-85.6290337,41.9380234]},"n185972921":{"id":"n185972921","loc":[-85.628424,41.936212]},"n185972923":{"id":"n185972923","loc":[-85.628367,41.936029]},"n185974511":{"id":"n185974511","loc":[-85.627064,41.932169]},"n185977728":{"id":"n185977728","loc":[-85.625605,41.925842]},"n185977729":{"id":"n185977729","loc":[-85.625685,41.926163]},"n185977731":{"id":"n185977731","loc":[-85.6257845,41.9264872]},"n185977733":{"id":"n185977733","loc":[-85.62663,41.929251]},"n185977734":{"id":"n185977734","loc":[-85.627008,41.930642]},"n185977736":{"id":"n185977736","loc":[-85.627029,41.930775]},"n185977738":{"id":"n185977738","loc":[-85.627041,41.930946]},"n185977739":{"id":"n185977739","loc":[-85.6270379,41.9311746]},"n185977742":{"id":"n185977742","loc":[-85.627055,41.934206]},"n185977744":{"id":"n185977744","loc":[-85.627084,41.936804]},"n185977746":{"id":"n185977746","loc":[-85.627104,41.936914]},"n185977748":{"id":"n185977748","loc":[-85.627156,41.937026]},"n185977750":{"id":"n185977750","loc":[-85.6272406,41.9371672]},"n185977752":{"id":"n185977752","loc":[-85.627317,41.93723]},"n185977753":{"id":"n185977753","loc":[-85.627422,41.937312]},"n185977755":{"id":"n185977755","loc":[-85.627754,41.937504]},"n185977757":{"id":"n185977757","loc":[-85.627883,41.937623]},"n185977761":{"id":"n185977761","loc":[-85.627984,41.93773]},"n1475283996":{"id":"n1475283996","loc":[-85.6270514,41.9317122],"tags":{"railway":"level_crossing"}},"n1475284004":{"id":"n1475284004","loc":[-85.6278177,41.9342117],"tags":{"railway":"level_crossing"}},"n1475284014":{"id":"n1475284014","loc":[-85.6251877,41.9255913],"tags":{"railway":"level_crossing"}},"n1475284017":{"id":"n1475284017","loc":[-85.6274992,41.9331816],"tags":{"railway":"level_crossing"}},"n1475284021":{"id":"n1475284021","loc":[-85.6297108,41.9353939],"tags":{"railway":"level_crossing"}},"n1475284027":{"id":"n1475284027","loc":[-85.62811,41.935198],"tags":{"railway":"level_crossing"}},"n1475284035":{"id":"n1475284035","loc":[-85.626888,41.9311757],"tags":{"railway":"level_crossing"}},"n1475293245":{"id":"n1475293245","loc":[-85.6286047,41.9367881]},"n1875654302":{"id":"n1875654302","loc":[-85.6296367,41.927491]},"n2189099388":{"id":"n2189099388","loc":[-85.6312007,41.9389988]},"n2189099389":{"id":"n2189099389","loc":[-85.6311003,41.9389992]},"n2189099390":{"id":"n2189099390","loc":[-85.6310988,41.9387847]},"n2189099391":{"id":"n2189099391","loc":[-85.6312165,41.9387843]},"n2189099392":{"id":"n2189099392","loc":[-85.6312152,41.9385857]},"n2189099393":{"id":"n2189099393","loc":[-85.6310877,41.9385862]},"n2189099394":{"id":"n2189099394","loc":[-85.6310858,41.9383161]},"n2189099395":{"id":"n2189099395","loc":[-85.6302002,41.9383196]},"n2189099396":{"id":"n2189099396","loc":[-85.6302011,41.9384472]},"n2189099397":{"id":"n2189099397","loc":[-85.6301018,41.9384476]},"n2189099398":{"id":"n2189099398","loc":[-85.6301025,41.9385419]},"n2189099399":{"id":"n2189099399","loc":[-85.6299275,41.9385427]},"n2189099400":{"id":"n2189099400","loc":[-85.62993,41.9388653]},"n2189099401":{"id":"n2189099401","loc":[-85.630107,41.9388645]},"n2189099402":{"id":"n2189099402","loc":[-85.6301079,41.9389908]},"n2189099403":{"id":"n2189099403","loc":[-85.6301951,41.9389904]},"n2189123382":{"id":"n2189123382","loc":[-85.6336279,41.9354365]},"n2189123384":{"id":"n2189123384","loc":[-85.6328492,41.9355177]},"n2189123387":{"id":"n2189123387","loc":[-85.6323762,41.9357396]},"n2189123388":{"id":"n2189123388","loc":[-85.6315174,41.9358966]},"n2189123389":{"id":"n2189123389","loc":[-85.6304331,41.936124]},"n2189123390":{"id":"n2189123390","loc":[-85.6302075,41.9364271]},"n2189123391":{"id":"n2189123391","loc":[-85.6303458,41.9367953]},"n2189123392":{"id":"n2189123392","loc":[-85.6299601,41.9369739]},"n2189123393":{"id":"n2189123393","loc":[-85.6299164,41.9374882]},"n2189123394":{"id":"n2189123394","loc":[-85.6299455,41.9378022]},"n2189123395":{"id":"n2189123395","loc":[-85.6299771,41.9379053]},"n2189123396":{"id":"n2189123396","loc":[-85.6301597,41.9379091]},"n2189123397":{"id":"n2189123397","loc":[-85.6308042,41.9377913]},"n2189123398":{"id":"n2189123398","loc":[-85.6316885,41.9378082]},"n2189123399":{"id":"n2189123399","loc":[-85.6316848,41.9380079]},"n2189123400":{"id":"n2189123400","loc":[-85.6318449,41.9381161]},"n2189123401":{"id":"n2189123401","loc":[-85.6320705,41.9381811]},"n2189123402":{"id":"n2189123402","loc":[-85.6321433,41.9383706]},"n2189123404":{"id":"n2189123404","loc":[-85.632056,41.9384355]},"n2189123406":{"id":"n2189123406","loc":[-85.6317867,41.9384572]},"n2189123409":{"id":"n2189123409","loc":[-85.6316572,41.9387281]},"n2189123417":{"id":"n2189123417","loc":[-85.6315946,41.93775]},"n2189123419":{"id":"n2189123419","loc":[-85.6302641,41.9378393]},"w208640158":{"id":"w208640158","tags":{"area":"yes","natural":"wetland"},"nodes":["n2189123379","n2189123382","n2189123384","n2189123387","n2189123388","n2189123389","n2189123390","n2189123391","n2189123392","n2189123393","n2189123394","n2189123395","n2189123396","n2189123419","n2189123397","n2189123417","n2189123398","n2189123399","n2189123400","n2189123401","n2189123402","n2189123404","n2189123406","n2189123409","n2189123410","n2189123412","n2189123415","n1819805722","n1819805861","n1819805887","n1819805760","n1819805641","n1819805632","n2189123379"]},"w134150787":{"id":"w134150787","tags":{"name":"Conrail Railroad","railway":"rail"},"nodes":["n185972905","n185972907","n1475293223","n185972911","n1475293241","n1475293246","n185972915","n185972917","n185972919","n1475293245","n185972921","n185972923","n1475284027","n1475284004","n1475284017","n1475283996","n1475284035","n1475284014","n185956891"]},"w208639443":{"id":"w208639443","tags":{"area":"yes","building":"yes"},"nodes":["n2189112720","n2189112721","n2189112722","n2189112723","n2189112720"]},"w17966462":{"id":"w17966462","tags":{"highway":"secondary","name":"South Main Street","old_ref":"US 131","ref":"M 86"},"nodes":["n185977728","n185977729","n185977731","n185963665","n185959979","n185977733","n185945401","n185977734","n185977736","n185977738","n185977739","n1475283996","n185974511","n185945138","n185977742","n185961192","n185967638","n185977744","n185977746","n185977748","n185977750","n185977752","n185977753","n185977754","n185977755","n185977757","n185977761","n185958030","n1475293263","n185963698","n185952745","n185947850","n185977762"]},"w203985741":{"id":"w203985741","tags":{"area":"yes","leisure":"park","name":"Conservation Park"},"nodes":["n2139982404","n2139982405","n2139982399","n2139982400","n1819805770","n2139982402","n2139982403","n2139982401","n1819805780","n1819805834","n2139982406","n2139982404"]},"w17963676":{"id":"w17963676","tags":{"highway":"service"},"nodes":["n1475293258","n2139982428","n2139982427","n2139982426","n2139982425","n2139982424","n2139982423","n2139982422","n2139982430","n2139982421","n2139982420","n2139982429","n1475293231","n1475293258","n1475293251","n1475293223","n185952745"]},"w203985745":{"id":"w203985745","tags":{"highway":"footway"},"nodes":["n2139982430","n2139982431","n2139982432","n2139982433","n2139982434","n2139982435","n2139982436","n2139982437","n2139982438","n2139982439","n2139982440","n2139982441","n1475293231"]},"w208639451":{"id":"w208639451","tags":{"area":"yes","building":"yes"},"nodes":["n2189112754","n2189112755","n2189112756","n2189112757","n2189112758","n2189112759","n2189112754"]},"w208639452":{"id":"w208639452","tags":{"area":"yes","building":"yes"},"nodes":["n2189112760","n2189112761","n2189112766","n2189112762","n2189112763","n2189112760"]},"w206805244":{"id":"w206805244","tags":{"area":"yes","building":"yes"},"nodes":["n2168544766","n2168544767","n2168544768","n2168544769","n2168544770","n2168544771","n2168544772","n2168544773","n2168544774","n2168544775","n2168544776","n2168544777","n2168544778","n2168544779","n2168544766"]},"w208639444":{"id":"w208639444","tags":{"area":"yes","building":"yes"},"nodes":["n2189112724","n2189112725","n2189112726","n2189112727","n2189112724"]},"w208639450":{"id":"w208639450","tags":{"area":"yes","building":"yes"},"nodes":["n2189112750","n2189112751","n2189112752","n2189112753","n2189112750"]},"w208639448":{"id":"w208639448","tags":{"area":"yes","building":"yes"},"nodes":["n2189112740","n2189112741","n2189112742","n2189112743","n2189112740"]},"w208637859":{"id":"w208637859","tags":{"area":"yes","building":"yes"},"nodes":["n2189099387","n2189099388","n2189099389","n2189099390","n2189099391","n2189099392","n2189099393","n2189099394","n2189099395","n2189099396","n2189099397","n2189099398","n2189099399","n2189099400","n2189099401","n2189099402","n2189099403","n2189099404","n2189099405","n2189099406","n2189099407","n2189099408","n2189099409","n2189099410","n2189099387"]},"w208639453":{"id":"w208639453","tags":{"area":"yes","building":"yes"},"nodes":["n2189112764","n2189112765","n2189112766","n2189112761","n2189112764"]},"w208639456":{"id":"w208639456","tags":{"area":"yes","building":"yes"},"nodes":["n2189112774","n2189112778","n2189112779","n2189112775","n2189112776","n2189112777","n2189112774"]},"w208639445":{"id":"w208639445","tags":{"area":"yes","building":"yes"},"nodes":["n2189112728","n2189112729","n2189112730","n2189112731","n2189112728"]},"w17967776":{"id":"w17967776","tags":{"highway":"residential","name":"5th St"},"nodes":["n185958032","n185988963"]},"w208639461":{"id":"w208639461","tags":{"area":"yes","building":"yes"},"nodes":["n2189112792","n2189112794","n2189112795","n2189112796","n2189112793","n2189112792"]},"w206805241":{"id":"w206805241","tags":{"area":"yes","building":"yes"},"nodes":["n2168544754","n2168544755","n2168544756","n2168544757","n2168544754"]},"w208639449":{"id":"w208639449","tags":{"area":"yes","building":"yes"},"nodes":["n2189112744","n2189112745","n2189112746","n2189112747","n2189112748","n2189112749","n2189112744"]},"w208639455":{"id":"w208639455","tags":{"area":"yes","building":"yes"},"nodes":["n2189112771","n2189112772","n2189112773","n2189112768","n2189112771"]},"w208639457":{"id":"w208639457","tags":{"area":"yes","building":"yes"},"nodes":["n2189112780","n2189112781","n2189112782","n2189112783","n2189112780"]},"w208639446":{"id":"w208639446","tags":{"area":"yes","building":"yes"},"nodes":["n2189112732","n2189112733","n2189112734","n2189112735","n2189112732"]},"w208639454":{"id":"w208639454","tags":{"area":"yes","building":"yes"},"nodes":["n2189112767","n2189112768","n2189112773","n2189112769","n2189112770","n2189112767"]},"w203985743":{"id":"w203985743","tags":{"amenity":"parking","area":"yes"},"nodes":["n2139982411","n2139982412","n2139982413","n2139982414","n2139982415","n2139982416","n2139982417","n2139982419","n2139982418","n2139982411"]},"w17965023":{"id":"w17965023","tags":{"highway":"residential","name":"4th St"},"nodes":["n185963655","n1875654302","n185959983","n185963688","n185945405","n185963689","n185963690","n185945142","n185963691","n185961200","n1475284021","n1475293246","n1875654132","n1475293263"]},"w206805242":{"id":"w206805242","tags":{"area":"yes","building":"yes"},"nodes":["n2168544758","n2168544759","n2168544760","n2168544761","n2168544758"]},"w208639460":{"id":"w208639460","tags":{"area":"yes","building":"yes"},"nodes":["n2189112792","n2189112793","n2189112789","n2189112790","n2189112792"]},"w208639447":{"id":"w208639447","tags":{"area":"yes","building":"yes"},"nodes":["n2189112736","n2189112737","n2189112738","n2189112739","n2189112736"]},"w208639458":{"id":"w208639458","tags":{"area":"yes","building":"yes"},"nodes":["n2189112784","n2189112785","n2189112786","n2189112787","n2189112784"]},"w203985744":{"id":"w203985744","tags":{"highway":"service"},"nodes":["n2139982425","n2139982400"]},"w208639459":{"id":"w208639459","tags":{"area":"yes","building":"yes"},"nodes":["n2189112788","n2189112789","n2189112790","n2189112791","n2189112788"]},"w203985742":{"id":"w203985742","tags":{"amenity":"shelter","area":"yes","shelter_type":"picnic_shelter"},"nodes":["n2139982407","n2139982408","n2139982409","n2139982410","n2139982407"]},"w206805243":{"id":"w206805243","tags":{"area":"yes","building":"yes"},"nodes":["n2168544762","n2168544763","n2168544764","n2168544765","n2168544762"]},"n185959081":{"id":"n185959081","loc":[-85.628469,41.948674]},"n185967427":{"id":"n185967427","loc":[-85.632054,41.951174]},"n185967424":{"id":"n185967424","loc":[-85.6320391,41.9499109]},"n185968101":{"id":"n185968101","loc":[-85.6308395,41.9511969]},"n185960792":{"id":"n185960792","loc":[-85.632074,41.953707]},"n185961389":{"id":"n185961389","loc":[-85.630935,41.959037]},"n185961391":{"id":"n185961391","loc":[-85.632169,41.959025]},"n185965395":{"id":"n185965395","loc":[-85.63216,41.959859]},"n185966953":{"id":"n185966953","loc":[-85.630894,41.957428]},"n185966955":{"id":"n185966955","loc":[-85.632122,41.957427]},"n185967430":{"id":"n185967430","loc":[-85.632077,41.952453]},"n185967432":{"id":"n185967432","loc":[-85.632095,41.954685]},"n185967434":{"id":"n185967434","loc":[-85.632121,41.955914]},"n185967436":{"id":"n185967436","loc":[-85.632128,41.9583]},"n185967438":{"id":"n185967438","loc":[-85.632187,41.960681]},"n185967440":{"id":"n185967440","loc":[-85.632182,41.961493]},"n185968102":{"id":"n185968102","loc":[-85.630855,41.952452]},"n185968104":{"id":"n185968104","loc":[-85.630887,41.953714]},"n185968106":{"id":"n185968106","loc":[-85.630883,41.954692]},"n185968108":{"id":"n185968108","loc":[-85.630904,41.955913]},"n185968110":{"id":"n185968110","loc":[-85.630904,41.958058]},"n185968112":{"id":"n185968112","loc":[-85.630952,41.960667]},"n185968114":{"id":"n185968114","loc":[-85.630972,41.961495]},"n185968116":{"id":"n185968116","loc":[-85.630962,41.961967]},"n185978969":{"id":"n185978969","loc":[-85.633214,41.948618]},"n185985812":{"id":"n185985812","loc":[-85.633274,41.951159]},"n185986155":{"id":"n185986155","loc":[-85.633258,41.949893]},"n2208608826":{"id":"n2208608826","loc":[-85.6339222,41.9486225]},"w17964531":{"id":"w17964531","tags":{"highway":"residential","name":"Willow Dr"},"nodes":["n185959079","n185959081"]},"w17967386":{"id":"w17967386","tags":{"highway":"residential","name":"East Armitage Street"},"nodes":["n185982195","n185968101","n185967427","n185985812","n185974583"]},"w17965502":{"id":"w17965502","tags":{"highway":"residential","name":"Elm Street"},"nodes":["n185968100","n185968101","n185968102","n185968104","n185968106","n185968108","n185966953","n185968110","n185961389","n185968112","n185968114","n185968116"]},"w17967844":{"id":"w17967844","tags":{"highway":"residential","name":"East Bennett Street"},"nodes":["n185982193","n185967424","n185986155","n185978390"]},"w17966581":{"id":"w17966581","tags":{"highway":"residential","name":"E Kelsey St"},"nodes":["n185978967","n185978969","n2208608826","n185971578"]},"w17965402":{"id":"w17965402","tags":{"highway":"residential","name":"Walnut Street"},"nodes":["n185967422","n185967424","n185967427","n185967430","n185960792","n185967432","n185967434","n185966955","n185967436","n185961391","n185965395","n185967438","n185967440"]},"n2199093506":{"id":"n2199093506","loc":[-85.6251879,41.9478322]},"n2199093505":{"id":"n2199093505","loc":[-85.6252076,41.9477749]},"n2199093504":{"id":"n2199093504","loc":[-85.6252289,41.9477602]},"n2199093503":{"id":"n2199093503","loc":[-85.625201,41.9477492]},"n2199093502":{"id":"n2199093502","loc":[-85.6251682,41.9477066]},"n2199093501":{"id":"n2199093501","loc":[-85.6251715,41.947609]},"n2199093500":{"id":"n2199093500","loc":[-85.6252125,41.9475639]},"n2199093499":{"id":"n2199093499","loc":[-85.6252896,41.9475602]},"n2199093498":{"id":"n2199093498","loc":[-85.6253027,41.9475334]},"n2199093497":{"id":"n2199093497","loc":[-85.6253437,41.9474822]},"n2199093496":{"id":"n2199093496","loc":[-85.6254421,41.9474675]},"n2199093495":{"id":"n2199093495","loc":[-85.6256503,41.9474944]},"n2199093494":{"id":"n2199093494","loc":[-85.6257257,41.9476127]},"n2199093493":{"id":"n2199093493","loc":[-85.6257028,41.9477285]},"n2199093492":{"id":"n2199093492","loc":[-85.6255339,41.9478102]},"n2199093491":{"id":"n2199093491","loc":[-85.6253912,41.9478224]},"n2199093490":{"id":"n2199093490","loc":[-85.6253043,41.947859]},"n2199093489":{"id":"n2199093489","loc":[-85.6252027,41.9478846]},"n2199093458":{"id":"n2199093458","loc":[-85.6246876,41.9486617]},"n2199093457":{"id":"n2199093457","loc":[-85.6243127,41.9486583]},"n2199093456":{"id":"n2199093456","loc":[-85.624306,41.9490569]},"n2199093455":{"id":"n2199093455","loc":[-85.624681,41.9490603]},"n2199093514":{"id":"n2199093514","loc":[-85.6236228,41.9496059]},"n2199093513":{"id":"n2199093513","loc":[-85.6236231,41.9496997]},"n2199093512":{"id":"n2199093512","loc":[-85.623357,41.9497002]},"n2199093511":{"id":"n2199093511","loc":[-85.6233567,41.9496136]},"n2199093508":{"id":"n2199093508","loc":[-85.6239735,41.9494287]},"n2199093507":{"id":"n2199093507","loc":[-85.6239741,41.9496052]},"n2199093488":{"id":"n2199093488","loc":[-85.624497,41.9512286]},"n2199093487":{"id":"n2199093487","loc":[-85.6244966,41.9511259]},"n2199093486":{"id":"n2199093486","loc":[-85.6243151,41.9511263]},"n2199093485":{"id":"n2199093485","loc":[-85.6243154,41.951229]},"n2199093484":{"id":"n2199093484","loc":[-85.6241205,41.9508665]},"n2199093483":{"id":"n2199093483","loc":[-85.624115,41.9505249]},"n2199093482":{"id":"n2199093482","loc":[-85.6243149,41.9505231]},"n2199093481":{"id":"n2199093481","loc":[-85.6243203,41.9508648]},"n2199093480":{"id":"n2199093480","loc":[-85.624393,41.9508668]},"n2199093479":{"id":"n2199093479","loc":[-85.6243904,41.9505956]},"n2199093478":{"id":"n2199093478","loc":[-85.6246727,41.950594]},"n2199093477":{"id":"n2199093477","loc":[-85.624675,41.9508203]},"n2199093476":{"id":"n2199093476","loc":[-85.6245097,41.9508212]},"n2199093475":{"id":"n2199093475","loc":[-85.6245101,41.9508662]},"n2199093474":{"id":"n2199093474","loc":[-85.6241008,41.9493459]},"n2199093473":{"id":"n2199093473","loc":[-85.6242442,41.9493459]},"n2199093472":{"id":"n2199093472","loc":[-85.6242442,41.9493681]},"n2199093471":{"id":"n2199093471","loc":[-85.6243397,41.9493681]},"n2199093470":{"id":"n2199093470","loc":[-85.6243417,41.9493511]},"n2199093469":{"id":"n2199093469","loc":[-85.6247251,41.9493485]},"n2199093468":{"id":"n2199093468","loc":[-85.6247548,41.9504949]},"n2199093467":{"id":"n2199093467","loc":[-85.6241214,41.9505017]},"n2199093466":{"id":"n2199093466","loc":[-85.6254398,41.950174]},"n2199093465":{"id":"n2199093465","loc":[-85.6254412,41.9499872]},"n2199093464":{"id":"n2199093464","loc":[-85.6255363,41.9499876]},"n2199093463":{"id":"n2199093463","loc":[-85.6255374,41.9498439]},"n2199093462":{"id":"n2199093462","loc":[-85.6255638,41.949844]},"n2199093461":{"id":"n2199093461","loc":[-85.6255652,41.9496672]},"n2199093460":{"id":"n2199093460","loc":[-85.6251823,41.9496656]},"n2199093459":{"id":"n2199093459","loc":[-85.6251785,41.9501729]},"n2199093510":{"id":"n2199093510","loc":[-85.6229922,41.9496143]},"n2199093509":{"id":"n2199093509","loc":[-85.6229915,41.9494306]},"n185948903":{"id":"n185948903","loc":[-85.616514,41.947449]},"n185955120":{"id":"n185955120","loc":[-85.620103,41.951]},"n185955143":{"id":"n185955143","loc":[-85.619784,41.94746]},"n185960124":{"id":"n185960124","loc":[-85.615238,41.947468]},"n185961362":{"id":"n185961362","loc":[-85.617437,41.947451]},"n185961364":{"id":"n185961364","loc":[-85.61861,41.947456]},"n185961367":{"id":"n185961367","loc":[-85.620088,41.947458]},"n185965105":{"id":"n185965105","loc":[-85.620087,41.94924]},"n185970220":{"id":"n185970220","loc":[-85.62156,41.948333]},"n185974697":{"id":"n185974697","loc":[-85.6201059,41.950132]},"n2138420778":{"id":"n2138420778","loc":[-85.616948,41.9474499]},"w17967535":{"id":"w17967535","tags":{"highway":"residential","name":"10th Ave"},"nodes":["n185955120","n185986812","n185983141"]},"w209716130":{"id":"w209716130","tags":{"area":"yes","building":"yes"},"nodes":["n2199093485","n2199093486","n2199093487","n2199093488","n2199093485"]},"w17964788":{"id":"w17964788","tags":{"highway":"residential","name":"6th Ave"},"nodes":["n185960124","n185948903","n2138420778","n185961362","n185961364","n185955143","n185961367","n185961369","n185961371"]},"w17965159":{"id":"w17965159","tags":{"highway":"residential","name":"8th Ave"},"nodes":["n185965105","n185965108","n185965110"]},"w209716125":{"id":"w209716125","tags":{"area":"yes","building":"yes"},"nodes":["n2199093459","n2199093460","n2199093461","n2199093462","n2199093463","n2199093464","n2199093465","n2199093466","n2199093459"]},"w17965699":{"id":"w17965699","tags":{"highway":"residential","name":"7th Ave"},"nodes":["n185970220","n185970222","n185970224"]},"w209716132":{"id":"w209716132","tags":{"area":"yes","building":"yes"},"nodes":["n2199093507","n2199093508","n2199093509","n2199093510","n2199093511","n2199093512","n2199093513","n2199093514","n2199093507"]},"w17966129":{"id":"w17966129","tags":{"highway":"residential","name":"9th Ave"},"nodes":["n185974697","n185974699"]},"w209716127":{"id":"w209716127","tags":{"area":"yes","building":"yes"},"nodes":["n2199093475","n2199093476","n2199093477","n2199093478","n2199093479","n2199093480","n2199093475"]},"w209716131":{"id":"w209716131","tags":{"area":"yes","natural":"water","water":"pond"},"nodes":["n2199093489","n2199093490","n2199093491","n2199093492","n2199093493","n2199093494","n2199093495","n2199093496","n2199093497","n2199093498","n2199093499","n2199093500","n2199093501","n2199093502","n2199093503","n2199093504","n2199093505","n2199093506","n2199093489"]},"w209716126":{"id":"w209716126","tags":{"area":"yes","building":"yes"},"nodes":["n2199093467","n2199093468","n2199093469","n2199093470","n2199093471","n2199093472","n2199093473","n2199093474","n2199093467"]},"w209716124":{"id":"w209716124","tags":{"area":"yes","building":"yes"},"nodes":["n2199093455","n2199093456","n2199093457","n2199093458","n2199093455"]},"w209716128":{"id":"w209716128","tags":{"area":"yes","building":"yes"},"nodes":["n2199093481","n2199093482","n2199093483","n2199093484","n2199093481"]},"n185949872":{"id":"n185949872","loc":[-85.643009,41.949264]},"n185949875":{"id":"n185949875","loc":[-85.642598,41.94929]},"n185949877":{"id":"n185949877","loc":[-85.642127,41.949382]},"n185949881":{"id":"n185949881","loc":[-85.64169,41.949936]},"n185988165":{"id":"n185988165","loc":[-85.642167,41.947657]},"n185988167":{"id":"n185988167","loc":[-85.642347,41.947662]},"n185988169":{"id":"n185988169","loc":[-85.642621,41.947659]},"n185965019":{"id":"n185965019","loc":[-85.6385084,41.951127]},"n1475293248":{"id":"n1475293248","loc":[-85.6386095,41.9512214]},"n185962639":{"id":"n185962639","loc":[-85.649669,41.949161]},"n185962810":{"id":"n185962810","loc":[-85.649907,41.949157]},"n185964355":{"id":"n185964355","loc":[-85.637412,41.9511359]},"n185965021":{"id":"n185965021","loc":[-85.638661,41.952386]},"n185965023":{"id":"n185965023","loc":[-85.638654,41.953665]},"n185965025":{"id":"n185965025","loc":[-85.638694,41.954649]},"n185965027":{"id":"n185965027","loc":[-85.638724,41.955913]},"n185971415":{"id":"n185971415","loc":[-85.644466,41.949246]},"n185971417":{"id":"n185971417","loc":[-85.647021,41.949193]},"n185971420":{"id":"n185971420","loc":[-85.648476,41.949169]},"n185979975":{"id":"n185979975","loc":[-85.644429,41.947633]},"n185988171":{"id":"n185988171","loc":[-85.645377,41.947622]},"w17963211":{"id":"w17963211","tags":{"highway":"residential"},"nodes":["n185949870","n185949872","n185949875","n185949877","n185949881"]},"w17965839":{"id":"w17965839","tags":{"highway":"residential","name":"Arnold St"},"nodes":["n185949870","n185971415","n185971417","n185971420","n185962639","n185962810"]},"w17967618":{"id":"w17967618","tags":{"highway":"residential","name":"Pierson St"},"nodes":["n185967777","n185988165","n185988167","n185988169","n185985824","n185979975","n185988171"]},"w17965149":{"id":"w17965149","tags":{"highway":"residential","name":"Oak St"},"nodes":["n185965019","n1475293248","n185965021","n185965023","n185965025","n185965027"]},"w17966118":{"id":"w17966118","tags":{"highway":"residential","name":"West Armitage Street"},"nodes":["n185974583","n185974585","n185964355","n185965019"]},"n2208608800":{"id":"n2208608800","loc":[-85.6354294,41.9486201]},"n2199109806":{"id":"n2199109806","loc":[-85.6350474,41.9477884]},"n2199109804":{"id":"n2199109804","loc":[-85.6350476,41.9477962]},"n2199109802":{"id":"n2199109802","loc":[-85.635002,41.9477969]},"n2199109799":{"id":"n2199109799","loc":[-85.6350018,41.9477883]},"n2199109797":{"id":"n2199109797","loc":[-85.6349141,41.9477897]},"n2199109795":{"id":"n2199109795","loc":[-85.6349131,41.9477535]},"n2199109793":{"id":"n2199109793","loc":[-85.6349395,41.9477531]},"n2199109791":{"id":"n2199109791","loc":[-85.6349382,41.9477077]},"n2199109789":{"id":"n2199109789","loc":[-85.6351236,41.9477049]},"n2199109787":{"id":"n2199109787","loc":[-85.6351259,41.9477872]},"n2199109785":{"id":"n2199109785","loc":[-85.634972,41.9475992]},"n2199109783":{"id":"n2199109783","loc":[-85.6349206,41.9475997]},"n2199109770":{"id":"n2199109770","loc":[-85.6348499,41.9475461]},"n2199109768":{"id":"n2199109768","loc":[-85.6348499,41.9475084]},"n2199109765":{"id":"n2199109765","loc":[-85.6349241,41.9474569]},"n2199109763":{"id":"n2199109763","loc":[-85.634967,41.9474564]},"n2199109762":{"id":"n2199109762","loc":[-85.6350405,41.9475121]},"n2199109761":{"id":"n2199109761","loc":[-85.6350405,41.9475419]},"n2199109753":{"id":"n2199109753","loc":[-85.6342443,41.9478391]},"n2199109751":{"id":"n2199109751","loc":[-85.6342427,41.9477927]},"n2199109745":{"id":"n2199109745","loc":[-85.6342439,41.9476859]},"n2199109743":{"id":"n2199109743","loc":[-85.6342429,41.9476575]},"n2199109741":{"id":"n2199109741","loc":[-85.6344615,41.9476533]},"n2199109739":{"id":"n2199109739","loc":[-85.6344678,41.9478348]},"n2199109737":{"id":"n2199109737","loc":[-85.634416,41.9480059]},"n2199109735":{"id":"n2199109735","loc":[-85.6344145,41.9478983]},"n2199109733":{"id":"n2199109733","loc":[-85.6342749,41.9478993]},"n2199109731":{"id":"n2199109731","loc":[-85.6342753,41.9479272]},"n2199109729":{"id":"n2199109729","loc":[-85.6342498,41.9479274]},"n2199109727":{"id":"n2199109727","loc":[-85.6342505,41.9479762]},"n2199109725":{"id":"n2199109725","loc":[-85.6342743,41.947976]},"n2199109723":{"id":"n2199109723","loc":[-85.6342747,41.948007]},"n2199109721":{"id":"n2199109721","loc":[-85.6343415,41.9476355]},"n2199109719":{"id":"n2199109719","loc":[-85.6343391,41.9474973]},"n2199109717":{"id":"n2199109717","loc":[-85.6343133,41.9474798]},"n2199109715":{"id":"n2199109715","loc":[-85.6342874,41.9474737]},"n2199109709":{"id":"n2199109709","loc":[-85.6349804,41.94815]},"n2199109707":{"id":"n2199109707","loc":[-85.6348915,41.9481505]},"n2199109705":{"id":"n2199109705","loc":[-85.6348917,41.9481692]},"n2199109702":{"id":"n2199109702","loc":[-85.6348522,41.9481694]},"n2199109700":{"id":"n2199109700","loc":[-85.6348532,41.9482679]},"n2199109698":{"id":"n2199109698","loc":[-85.6348315,41.948268]},"n2199109696":{"id":"n2199109696","loc":[-85.6348318,41.9482955]},"n2199109694":{"id":"n2199109694","loc":[-85.6349653,41.9482946]},"n2199109692":{"id":"n2199109692","loc":[-85.6349656,41.9483211]},"n2199109690":{"id":"n2199109690","loc":[-85.634999,41.9483209]},"n2199109688":{"id":"n2199109688","loc":[-85.6349987,41.9482947]},"n2199109686":{"id":"n2199109686","loc":[-85.6351753,41.9482935]},"n2199109684":{"id":"n2199109684","loc":[-85.6351749,41.9482617]},"n2199109682":{"id":"n2199109682","loc":[-85.6351588,41.9482618]},"n2199109680":{"id":"n2199109680","loc":[-85.6351575,41.9481518]},"n2199109678":{"id":"n2199109678","loc":[-85.6350671,41.9481524]},"n2199109676":{"id":"n2199109676","loc":[-85.6350649,41.9479659]},"n2199109674":{"id":"n2199109674","loc":[-85.6349785,41.9479665]},"n2199109671":{"id":"n2199109671","loc":[-85.6343069,41.9483263]},"n2199109669":{"id":"n2199109669","loc":[-85.6343052,41.9482981]},"n2199109658":{"id":"n2199109658","loc":[-85.6343314,41.9480549]},"n2199109656":{"id":"n2199109656","loc":[-85.6343305,41.9480461]},"n2199109654":{"id":"n2199109654","loc":[-85.634435,41.9480468]},"n2199109652":{"id":"n2199109652","loc":[-85.6344342,41.9483746]},"n2199109650":{"id":"n2199109650","loc":[-85.6344629,41.9483727]},"n2199109648":{"id":"n2199109648","loc":[-85.6344637,41.9484561]},"n2199109645":{"id":"n2199109645","loc":[-85.63443,41.9484567]},"n2199109642":{"id":"n2199109642","loc":[-85.6344317,41.948505]},"n185964352":{"id":"n185964352","loc":[-85.6373958,41.9489943]},"n185964351":{"id":"n185964351","loc":[-85.637113,41.9486]},"n2208608825":{"id":"n2208608825","loc":[-85.6354483,41.9494241]},"n2208608823":{"id":"n2208608823","loc":[-85.6360418,41.949416]},"n2208608821":{"id":"n2208608821","loc":[-85.6360458,41.9495802]},"n2208608811":{"id":"n2208608811","loc":[-85.6357458,41.9495843]},"n2208608808":{"id":"n2208608808","loc":[-85.6357508,41.9497835]},"n2208608806":{"id":"n2208608806","loc":[-85.6354573,41.9497875]},"n2208608795":{"id":"n2208608795","loc":[-85.6354595,41.9498778]},"n2199109638":{"id":"n2199109638","loc":[-85.6349605,41.949749]},"n2199109636":{"id":"n2199109636","loc":[-85.6349605,41.9497639]},"n2199109634":{"id":"n2199109634","loc":[-85.6349061,41.94971]},"n2199109632":{"id":"n2199109632","loc":[-85.6349048,41.9496569]},"n2199109630":{"id":"n2199109630","loc":[-85.6348835,41.9496571]},"n2199109628":{"id":"n2199109628","loc":[-85.6348829,41.9497103]},"n2199109626":{"id":"n2199109626","loc":[-85.635227,41.9497738]},"n2199109624":{"id":"n2199109624","loc":[-85.6352184,41.9497787]},"n2199109622":{"id":"n2199109622","loc":[-85.6351181,41.9497806]},"n2199109620":{"id":"n2199109620","loc":[-85.6351181,41.9497456]},"n2199109618":{"id":"n2199109618","loc":[-85.6348842,41.9497651]},"n2199109616":{"id":"n2199109616","loc":[-85.6348827,41.9496238]},"n2199109615":{"id":"n2199109615","loc":[-85.6351268,41.9496206]},"n2199109614":{"id":"n2199109614","loc":[-85.6351261,41.9495891]},"n2199109613":{"id":"n2199109613","loc":[-85.6351957,41.9495881]},"n2199109612":{"id":"n2199109612","loc":[-85.6351924,41.9494515]},"n2199109611":{"id":"n2199109611","loc":[-85.6353997,41.9494488]},"n2199109610":{"id":"n2199109610","loc":[-85.6354074,41.9497715]},"n2189015681":{"id":"n2189015681","loc":[-85.6344229,41.9509639]},"n2189015677":{"id":"n2189015677","loc":[-85.634424,41.9507396]},"n2138493843":{"id":"n2138493843","loc":[-85.6343935,41.9502836]},"n2138493840":{"id":"n2138493840","loc":[-85.634398,41.9506264]},"n354002838":{"id":"n354002838","loc":[-85.6345197,41.9510631]},"n2114807590":{"id":"n2114807590","loc":[-85.634511,41.9499767]},"n185964353":{"id":"n185964353","loc":[-85.6374092,41.9498755]},"n1819849180":{"id":"n1819849180","loc":[-85.6348236,41.94996]},"n1819849115":{"id":"n1819849115","loc":[-85.6354372,41.9499538]},"n1819848921":{"id":"n1819848921","loc":[-85.6348439,41.951064]},"n1819848885":{"id":"n1819848885","loc":[-85.6354575,41.9510578]},"n185984281":{"id":"n185984281","loc":[-85.638075,41.949872]},"n2208608827":{"id":"n2208608827","loc":[-85.6339169,41.9473191]},"n2199109749":{"id":"n2199109749","loc":[-85.6342082,41.9477934]},"n2199109747":{"id":"n2199109747","loc":[-85.6342045,41.9476867]},"n2199109713":{"id":"n2199109713","loc":[-85.6342404,41.9474746]},"n2199109711":{"id":"n2199109711","loc":[-85.6342404,41.9476355]},"n2199109673":{"id":"n2199109673","loc":[-85.6340886,41.9483282]},"n2199109667":{"id":"n2199109667","loc":[-85.6342403,41.9482988]},"n2199109665":{"id":"n2199109665","loc":[-85.6342386,41.9482116]},"n2199109662":{"id":"n2199109662","loc":[-85.6340861,41.9482135]},"n2199109660":{"id":"n2199109660","loc":[-85.6340802,41.9480562]},"n2199109640":{"id":"n2199109640","loc":[-85.6340928,41.9485063]},"n354031366":{"id":"n354031366","loc":[-85.6341667,41.9477778],"tags":{"amenity":"place_of_worship","name":"Faith Tabernacle Church","religion":"christian"}},"n2189015686":{"id":"n2189015686","loc":[-85.6337798,41.95099]},"n2189015684":{"id":"n2189015684","loc":[-85.6337794,41.9509674]},"n2189015673":{"id":"n2189015673","loc":[-85.6337501,41.9507457]},"n2189015669":{"id":"n2189015669","loc":[-85.6337501,41.9506974]},"n2189015665":{"id":"n2189015665","loc":[-85.6339034,41.9506959]},"n2189015662":{"id":"n2189015662","loc":[-85.6339015,41.950436]},"n2189015658":{"id":"n2189015658","loc":[-85.6334916,41.9504376]},"n2189015655":{"id":"n2189015655","loc":[-85.6334939,41.9507558]},"n2189015650":{"id":"n2189015650","loc":[-85.6334543,41.950756]},"n2189015649":{"id":"n2189015649","loc":[-85.633456,41.9509915]},"n2138493842":{"id":"n2138493842","loc":[-85.6339937,41.9502836]},"n2138493841":{"id":"n2138493841","loc":[-85.6339983,41.9506281]},"n2114807579":{"id":"n2114807579","loc":[-85.6333644,41.9510682]},"n2114807573":{"id":"n2114807573","loc":[-85.6333557,41.9499819]},"n354031330":{"id":"n354031330","loc":[-85.6341667,41.9497222],"tags":{"amenity":"place_of_worship","name":"Trinity Episcopal Church","religion":"christian"}},"n185960794":{"id":"n185960794","loc":[-85.633307,41.9537]},"n185964357":{"id":"n185964357","loc":[-85.637432,41.952399]},"n185964358":{"id":"n185964358","loc":[-85.637452,41.953665]},"n185964359":{"id":"n185964359","loc":[-85.63746,41.954658]},"n185964360":{"id":"n185964360","loc":[-85.637473,41.95592]},"n185964361":{"id":"n185964361","loc":[-85.637468,41.956906]},"n185964362":{"id":"n185964362","loc":[-85.637483,41.958313]},"n185966957":{"id":"n185966957","loc":[-85.633361,41.957422]},"n185975351":{"id":"n185975351","loc":[-85.63334,41.9559]},"n185978784":{"id":"n185978784","loc":[-85.633311,41.954679]},"n185986157":{"id":"n185986157","loc":[-85.633287,41.952426]},"n185986158":{"id":"n185986158","loc":[-85.6333607,41.9582301],"tags":{"highway":"turning_circle"}},"w17965182":{"id":"w17965182","tags":{"highway":"residential","name":"W Prutzman St"},"nodes":["n185965289","n2189153241","n185965291"]},"w208627205":{"id":"w208627205","tags":{"area":"yes","building":"yes"},"nodes":["n2189015649","n2189015650","n2189015655","n2189015658","n2189015662","n2189015665","n2189015669","n2189015673","n2189015677","n2189015681","n2189015684","n2189015686","n2189015649"]},"w209717042":{"id":"w209717042","tags":{"amenity":"place_of_worship","area":"yes","building":"yes","denomination":"presbyterian","name":"First Presbyterian Church","religion":"christian"},"nodes":["n2199109610","n2199109611","n2199109612","n2199109613","n2199109614","n2199109615","n2199109616","n2199109630","n2199109632","n2199109634","n2199109628","n2199109618","n2199109636","n2199109638","n2199109620","n2199109622","n2199109624","n2199109626","n2199109610"]},"w209717045":{"id":"w209717045","tags":{"area":"yes","building":"yes"},"nodes":["n2199109711","n2199109713","n2199109715","n2199109717","n2199109719","n2199109721","n2199109711"]},"w209717047":{"id":"w209717047","tags":{"area":"yes","building":"yes"},"nodes":["n2199109739","n2199109741","n2199109743","n2199109745","n2199109747","n2199109749","n2199109751","n2199109753","n2199109739"]},"w209717044":{"id":"w209717044","tags":{"area":"yes","building":"yes"},"nodes":["n2199109674","n2199109676","n2199109678","n2199109680","n2199109682","n2199109684","n2199109686","n2199109688","n2199109690","n2199109692","n2199109694","n2199109696","n2199109698","n2199109700","n2199109702","n2199109705","n2199109707","n2199109709","n2199109674"]},"w210822776":{"id":"w210822776","tags":{"highway":"service","service":"alley","surface":"unpaved"},"nodes":["n2208608795","n2208608806","n2208608825","n2208608800","n2189153241"]},"w210822778":{"id":"w210822778","tags":{"highway":"service","service":"alley"},"nodes":["n2208608826","n2208608827"]},"w209717050":{"id":"w209717050","tags":{"area":"yes","building":"yes"},"nodes":["n2199109787","n2199109789","n2199109791","n2199109793","n2199109795","n2199109797","n2199109799","n2199109802","n2199109804","n2199109806","n2199109787"]},"w17965097":{"id":"w17965097","tags":{"highway":"residential","name":"Maple Street"},"nodes":["n185964351","n185964352","n185964353","n185964355","n185964357","n185964358","n185964359","n185964360","n185964361","n185964362"]},"w17965856":{"id":"w17965856","tags":{"highway":"residential","name":"W Kelsey St"},"nodes":["n185971578","n2208608800","n185971580","n185964351"]},"w17967444":{"id":"w17967444","tags":{"highway":"residential","name":"East Street"},"nodes":["n185966937","n185978969","n185986155","n185985812","n185986157","n185960794","n185978784","n185975351","n185966957","n185986158"]},"w17967764":{"id":"w17967764","tags":{"highway":"residential","name":"Rock River Ave"},"nodes":["n185984017","n185964351"]},"w170848329":{"id":"w170848329","tags":{"leisure":"park","name":"LaFayette Park"},"nodes":["n1819849180","n1819849115","n1819848885","n1819848921","n1819849180"]},"w17967208":{"id":"w17967208","tags":{"highway":"residential","name":"West Bennett Street"},"nodes":["n185978390","n2208608795","n185984020","n185964353","n185984281"]},"w17965349":{"id":"w17965349","tags":{"highway":"residential","name":"E Prutzman St"},"nodes":["n185966937","n2208608827","n185965289"]},"w209717049":{"id":"w209717049","tags":{"area":"yes","building":"yes"},"nodes":["n2199109761","n2199109762","n2199109763","n2199109765","n2199109768","n2199109770","n2199109783","n2199109785","n2199109761"]},"w203841840":{"id":"w203841840","tags":{"area":"yes","leisure":"playground"},"nodes":["n2138493840","n2138493841","n2138493842","n2138493843","n2138493840"]},"w209717043":{"id":"w209717043","tags":{"amenity":"place_of_worship","area":"yes","building":"church","denomination":"methodist","name":"First United Methodist Church","religion":"christian"},"nodes":["n2199109640","n2199109642","n2199109645","n2199109648","n2199109650","n2199109652","n2199109654","n2199109656","n2199109658","n2199109660","n2199109662","n2199109665","n2199109667","n2199109669","n2199109671","n2199109673","n2199109640"]},"w201484341":{"id":"w201484341","tags":{"amenity":"school","name":"Hoppin School"},"nodes":["n354002838","n2114807579","n2114807573","n2114807590","n354002838"]},"w209717046":{"id":"w209717046","tags":{"area":"yes","building":"yes"},"nodes":["n2199109723","n2199109725","n2199109727","n2199109729","n2199109731","n2199109733","n2199109735","n2199109737","n2199109723"]},"w210822777":{"id":"w210822777","tags":{"amenity":"parking","area":"yes"},"nodes":["n2208608806","n2208608808","n2208608811","n2208608821","n2208608823","n2208608825","n2208608806"]},"n185954965":{"id":"n185954965","loc":[-85.6191189,41.9441922]},"n185954968":{"id":"n185954968","loc":[-85.6194384,41.9442405]},"n185954970":{"id":"n185954970","loc":[-85.6196543,41.9443252]},"n185954972":{"id":"n185954972","loc":[-85.6197862,41.9444539]},"n354002931":{"id":"n354002931","loc":[-85.6198991,41.9455269]},"n354030853":{"id":"n354030853","loc":[-85.6219444,41.9455556],"tags":{"amenity":"place_of_worship","name":"Grant Chapel","religion":"christian"}},"n367815963":{"id":"n367815963","loc":[-85.6202778,41.9461111],"tags":{"building":"yes","name":"George Washington Carver Community Center"}},"n185947331":{"id":"n185947331","loc":[-85.618779,41.943269]},"n185947333":{"id":"n185947333","loc":[-85.618795,41.943511]},"n185947336":{"id":"n185947336","loc":[-85.618711,41.94413]},"n185947338":{"id":"n185947338","loc":[-85.618704,41.944189]},"n185947339":{"id":"n185947339","loc":[-85.618597,41.944337]},"n185947340":{"id":"n185947340","loc":[-85.618485,41.944528]},"n185947343":{"id":"n185947343","loc":[-85.618442,41.944716]},"n185947345":{"id":"n185947345","loc":[-85.618457,41.945107]},"n185947347":{"id":"n185947347","loc":[-85.618296,41.945338]},"n185947374":{"id":"n185947374","loc":[-85.616748,41.944453]},"n185947375":{"id":"n185947375","loc":[-85.616813,41.944646]},"n185947376":{"id":"n185947376","loc":[-85.616859,41.945196]},"n185947377":{"id":"n185947377","loc":[-85.616941,41.945352]},"n185947406":{"id":"n185947406","loc":[-85.618184,41.944227]},"n185947409":{"id":"n185947409","loc":[-85.617911,41.943875]},"n185947410":{"id":"n185947410","loc":[-85.617579,41.943682]},"n185947411":{"id":"n185947411","loc":[-85.61713,41.943589]},"n185947412":{"id":"n185947412","loc":[-85.616549,41.943559]},"n185947414":{"id":"n185947414","loc":[-85.616482,41.943556]},"n185947464":{"id":"n185947464","loc":[-85.616526,41.943788]},"n185947466":{"id":"n185947466","loc":[-85.616504,41.944002]},"n185948863":{"id":"n185948863","loc":[-85.619017,41.943391]},"n185948865":{"id":"n185948865","loc":[-85.619059,41.943368]},"n185955022":{"id":"n185955022","loc":[-85.620088,41.945571]},"n185955025":{"id":"n185955025","loc":[-85.620051,41.945505]},"n185955028":{"id":"n185955028","loc":[-85.62001,41.94541]},"n185980371":{"id":"n185980371","loc":[-85.620982,41.944742]},"n185980398":{"id":"n185980398","loc":[-85.621305,41.944782]},"n185980401":{"id":"n185980401","loc":[-85.621174,41.944819]},"n185980403":{"id":"n185980403","loc":[-85.621029,41.944871]},"n185980405":{"id":"n185980405","loc":[-85.620741,41.945011]},"n185980407":{"id":"n185980407","loc":[-85.620616,41.945085]},"n185980409":{"id":"n185980409","loc":[-85.620506,41.945172]},"n185980411":{"id":"n185980411","loc":[-85.620394,41.945273]},"n185980413":{"id":"n185980413","loc":[-85.620316,41.94536]},"n185980415":{"id":"n185980415","loc":[-85.620257,41.945452]},"n185980417":{"id":"n185980417","loc":[-85.620212,41.945535]},"n185985910":{"id":"n185985910","loc":[-85.620101,41.945811]},"n185985912":{"id":"n185985912","loc":[-85.620081,41.945937]},"n1475283972":{"id":"n1475283972","loc":[-85.6198991,41.9437179]},"n1475283982":{"id":"n1475283982","loc":[-85.6195022,41.9433463]},"n1475284007":{"id":"n1475284007","loc":[-85.6193037,41.9433383]},"n1475284040":{"id":"n1475284040","loc":[-85.6197329,41.9434121]},"n1475284044":{"id":"n1475284044","loc":[-85.6198756,41.9435363]},"n1475284050":{"id":"n1475284050","loc":[-85.6199689,41.9432106]},"n1475284053":{"id":"n1475284053","loc":[-85.6198943,41.9432921]},"n185954974":{"id":"n185954974","loc":[-85.6198296,41.94473]},"n185954977":{"id":"n185954977","loc":[-85.6200474,41.9447384]},"n2196831365":{"id":"n2196831365","loc":[-85.6202259,41.9460883]},"n2196831366":{"id":"n2196831366","loc":[-85.6202245,41.9458642]},"n2196831367":{"id":"n2196831367","loc":[-85.6205184,41.9458631]},"n2196831368":{"id":"n2196831368","loc":[-85.6205189,41.9459437]},"n2196831369":{"id":"n2196831369","loc":[-85.6203879,41.9459441]},"n2196831370":{"id":"n2196831370","loc":[-85.6203888,41.9460878]},"n2196831371":{"id":"n2196831371","loc":[-85.6184046,41.9465663]},"n2196831372":{"id":"n2196831372","loc":[-85.6191563,41.9465618]},"n2196831373":{"id":"n2196831373","loc":[-85.6191536,41.946319]},"n2196831374":{"id":"n2196831374","loc":[-85.6187356,41.9463216]},"n2196831375":{"id":"n2196831375","loc":[-85.6187334,41.9461197]},"n2196831376":{"id":"n2196831376","loc":[-85.6193167,41.9461162]},"n2196831377":{"id":"n2196831377","loc":[-85.6193156,41.9460229]},"n2196831378":{"id":"n2196831378","loc":[-85.619622,41.946021]},"n2196831379":{"id":"n2196831379","loc":[-85.6196237,41.9461712]},"n2196831380":{"id":"n2196831380","loc":[-85.6197702,41.9461703]},"n2196831381":{"id":"n2196831381","loc":[-85.6197685,41.9460202]},"n2196831382":{"id":"n2196831382","loc":[-85.6197323,41.9460204]},"n2196831383":{"id":"n2196831383","loc":[-85.6197305,41.9458563]},"n2196831384":{"id":"n2196831384","loc":[-85.6196165,41.945857]},"n2196831385":{"id":"n2196831385","loc":[-85.6196156,41.9457764]},"n2196831386":{"id":"n2196831386","loc":[-85.6194472,41.9457775]},"n2196831387":{"id":"n2196831387","loc":[-85.6194151,41.9457777]},"n2196831388":{"id":"n2196831388","loc":[-85.6183779,41.9457883]},"n2196831389":{"id":"n2196831389","loc":[-85.6183842,41.9461317]},"n2196831390":{"id":"n2196831390","loc":[-85.6185026,41.9461304]},"n2196831391":{"id":"n2196831391","loc":[-85.6185061,41.9463194]},"n2196831392":{"id":"n2196831392","loc":[-85.6184001,41.9463205]},"n2196831393":{"id":"n2196831393","loc":[-85.6182482,41.9464163]},"n2196831394":{"id":"n2196831394","loc":[-85.6182467,41.9463193]},"n2196831395":{"id":"n2196831395","loc":[-85.6180389,41.946321]},"n2196831397":{"id":"n2196831397","loc":[-85.6180404,41.946418]},"n185947303":{"id":"n185947303","loc":[-85.611074,41.943389]},"n185947304":{"id":"n185947304","loc":[-85.611332,41.943267]},"n185947305":{"id":"n185947305","loc":[-85.611635,41.943218]},"n185947306":{"id":"n185947306","loc":[-85.612762,41.943311]},"n185947308":{"id":"n185947308","loc":[-85.613027,41.943327]},"n185947310":{"id":"n185947310","loc":[-85.615377,41.942996]},"n185947312":{"id":"n185947312","loc":[-85.615701,41.943007]},"n185947314":{"id":"n185947314","loc":[-85.61604,41.943067]},"n185947315":{"id":"n185947315","loc":[-85.61626,41.943083]},"n185947316":{"id":"n185947316","loc":[-85.616507,41.943048]},"n185947319":{"id":"n185947319","loc":[-85.616702,41.94299]},"n185947321":{"id":"n185947321","loc":[-85.617078,41.942918]},"n185947322":{"id":"n185947322","loc":[-85.617366,41.942973]},"n185947323":{"id":"n185947323","loc":[-85.617601,41.943033]},"n185947325":{"id":"n185947325","loc":[-85.617799,41.943027]},"n185947327":{"id":"n185947327","loc":[-85.618264,41.942961]},"n185947328":{"id":"n185947328","loc":[-85.618508,41.942972]},"n185947329":{"id":"n185947329","loc":[-85.618707,41.943076]},"n185947361":{"id":"n185947361","loc":[-85.615356,41.944922]},"n185947363":{"id":"n185947363","loc":[-85.61536,41.944893]},"n185947365":{"id":"n185947365","loc":[-85.615406,41.944547]},"n185947367":{"id":"n185947367","loc":[-85.61548,41.944351]},"n185947369":{"id":"n185947369","loc":[-85.615805,41.94419]},"n185947371":{"id":"n185947371","loc":[-85.616166,41.944156]},"n185947373":{"id":"n185947373","loc":[-85.616411,41.944197]},"n185947416":{"id":"n185947416","loc":[-85.616335,41.94343]},"n185947417":{"id":"n185947417","loc":[-85.616069,41.943293]},"n185947419":{"id":"n185947419","loc":[-85.615803,41.943249]},"n185947420":{"id":"n185947420","loc":[-85.615524,41.943342]},"n185947421":{"id":"n185947421","loc":[-85.615311,41.94353]},"n185947422":{"id":"n185947422","loc":[-85.614338,41.943558]},"n185947423":{"id":"n185947423","loc":[-85.61422,41.94369]},"n185947425":{"id":"n185947425","loc":[-85.614221,41.944224]},"n185947427":{"id":"n185947427","loc":[-85.614198,41.944888]},"n185947429":{"id":"n185947429","loc":[-85.614221,41.945439]},"n185947468":{"id":"n185947468","loc":[-85.615908,41.944756]},"n185947470":{"id":"n185947470","loc":[-85.615871,41.944888]},"n185947472":{"id":"n185947472","loc":[-85.615878,41.94507]},"n185955153":{"id":"n185955153","loc":[-85.620087,41.947701]},"n185960690":{"id":"n185960690","loc":[-85.620141,41.951901]},"n185978817":{"id":"n185978817","loc":[-85.617193,41.954706]},"n185985916":{"id":"n185985916","loc":[-85.620088,41.94758]},"n185985918":{"id":"n185985918","loc":[-85.620133,41.951538]},"n185985919":{"id":"n185985919","loc":[-85.62013,41.952104]},"n185985920":{"id":"n185985920","loc":[-85.620104,41.952305]},"n185985921":{"id":"n185985921","loc":[-85.620062,41.952499]},"n185985922":{"id":"n185985922","loc":[-85.619993,41.952702]},"n185985925":{"id":"n185985925","loc":[-85.619879,41.952986]},"n185985927":{"id":"n185985927","loc":[-85.619689,41.95329]},"n185985928":{"id":"n185985928","loc":[-85.619508,41.953521]},"n185985929":{"id":"n185985929","loc":[-85.619286,41.953728]},"n185985930":{"id":"n185985930","loc":[-85.618925,41.954007]},"n185985931":{"id":"n185985931","loc":[-85.618638,41.954189]},"n185985932":{"id":"n185985932","loc":[-85.61831,41.954358]},"n185985934":{"id":"n185985934","loc":[-85.618015,41.954485]},"n185985936":{"id":"n185985936","loc":[-85.617606,41.954611]},"n1475283975":{"id":"n1475283975","loc":[-85.6150935,41.9434118]},"n1475283979":{"id":"n1475283979","loc":[-85.6193367,41.9430252]},"n1475283989":{"id":"n1475283989","loc":[-85.6104771,41.9455269]},"n1475283990":{"id":"n1475283990","loc":[-85.6104771,41.9437179]},"n1475283994":{"id":"n1475283994","loc":[-85.6198042,41.9429763]},"n1475283998":{"id":"n1475283998","loc":[-85.6192101,41.9426716]},"n1475284000":{"id":"n1475284000","loc":[-85.6198622,41.942836]},"n1475284002":{"id":"n1475284002","loc":[-85.6163262,41.9427688]},"n1475284006":{"id":"n1475284006","loc":[-85.6179527,41.9429168]},"n1475284029":{"id":"n1475284029","loc":[-85.6197195,41.9427278]},"n1475284038":{"id":"n1475284038","loc":[-85.6194405,41.9427837]},"n1475284052":{"id":"n1475284052","loc":[-85.6153225,41.942841]},"n1475284055":{"id":"n1475284055","loc":[-85.6129233,41.9437179]},"n2139966627":{"id":"n2139966627","loc":[-85.61958,41.9427558]},"w17966773":{"id":"w17966773","tags":{"highway":"secondary","name":"E Michigan Ave","ref":"M 60"},"nodes":["n185980372","n185980398","n185980401","n185980403","n185980405","n185980407","n185980409","n185980411","n185980413","n185980415","n185980417","n185955019"]},"w17964043":{"id":"w17964043","tags":{"highway":"residential"},"nodes":["n185955019","n185955022","n185955025","n185955028","n185954977","n185971477","n1475284050","n1475284000","n1475284029","n2139966627","n1475284038"]},"w17962834":{"id":"w17962834","tags":{"highway":"service"},"nodes":["n185947316","n185947414","n185947464","n185947466","n185947373","n185947468","n185947470","n185947472","n185947474"]},"w209470310":{"id":"w209470310","tags":{"area":"yes","building":"yes"},"nodes":["n2196831393","n2196831394","n2196831395","n2196831397","n2196831393"]},"w17963058":{"id":"w17963058","tags":{"highway":"service"},"nodes":["n185947333","n185948863","n185948865","n1475284007","n1475283982","n1475284040","n1475284044"]},"w17962823":{"id":"w17962823","tags":{"highway":"service"},"nodes":["n185947359","n185947361","n185947363","n185947365","n185947367","n185947369","n185947371","n185947373","n185947374","n185947375","n185947376","n185947377","n185947378"]},"w17962821":{"id":"w17962821","tags":{"highway":"service"},"nodes":["n185947303","n185947304","n185947305","n185947306","n185947308","n185947310","n185947312","n185947314","n185947315","n185947316","n185947319","n185947321","n185947322","n185947323","n185947325","n185947327","n185947328","n185947329","n185947331","n185947333","n185947336","n185947338","n185947339","n185947340","n185947343","n185947345","n185947347","n185947349"]},"w134150798":{"id":"w134150798","tags":{"amenity":"grave_yard","name":"Riverside Cemetery"},"nodes":["n354002931","n1475283972","n1475284053","n1475283994","n1475283979","n1475283998","n1475284006","n1475284002","n1475284052","n1475283975","n1475284055","n1475283990","n1475283989","n354002931"]},"w17964040":{"id":"w17964040","tags":{"highway":"service"},"nodes":["n185947336","n185954965","n185954968","n185954970","n185954972","n185954974","n185954977"]},"w209470308":{"id":"w209470308","tags":{"area":"yes","building":"yes"},"nodes":["n2196831365","n2196831366","n2196831367","n2196831368","n2196831369","n2196831370","n2196831365"]},"w17962828":{"id":"w17962828","tags":{"highway":"service"},"nodes":["n185947340","n185947406","n185947409","n185947410","n185947411","n185947412","n185947414","n185947416","n185947417","n185947419","n185947420","n185947421","n185947422","n185947423","n185947425","n185947427","n185947429"]},"w209470309":{"id":"w209470309","tags":{"area":"yes","building":"yes"},"nodes":["n2196831371","n2196831372","n2196831373","n2196831374","n2196831375","n2196831376","n2196831377","n2196831378","n2196831379","n2196831380","n2196831381","n2196831382","n2196831383","n2196831384","n2196831385","n2196831386","n2196831387","n2196831388","n2196831389","n2196831390","n2196831391","n2196831392","n2196831371"]},"w17967415":{"id":"w17967415","tags":{"highway":"secondary","name":"Jefferson St","name_1":"State Highway 60","ref":"M 60"},"nodes":["n185955019","n185985910","n185985912","n185985914","n185961367","n185985916","n185955153","n185965105","n185974697","n185955120","n185985918","n185960690","n185985919","n185985920","n185985921","n185985922","n185985925","n185985927","n185985928","n185985929","n185985930","n185985931","n185985932","n185985934","n185985936","n185978817"]},"w17966772":{"id":"w17966772","tags":{"highway":"unclassified","name":"E Michigan Ave","name_1":"State Highway 60"},"nodes":["n185954977","n185980371","n185980372"]},"n185958500":{"id":"n185958500","loc":[-85.621591,41.941075]},"n185963110":{"id":"n185963110","loc":[-85.6204416,41.9408882]},"n2139966628":{"id":"n2139966628","loc":[-85.6196431,41.9426467],"tags":{"leisure":"fishing"}},"n2139966630":{"id":"n2139966630","loc":[-85.6199354,41.9429616]},"n2199127051":{"id":"n2199127051","loc":[-85.6170556,41.939696]},"n2199127052":{"id":"n2199127052","loc":[-85.6170536,41.9392909]},"n2199127053":{"id":"n2199127053","loc":[-85.6172067,41.9392905]},"n2199127054":{"id":"n2199127054","loc":[-85.6172061,41.9391853]},"n2199127055":{"id":"n2199127055","loc":[-85.6171481,41.9391854]},"n2199127060":{"id":"n2199127060","loc":[-85.6167389,41.9392896]},"n2199127061":{"id":"n2199127061","loc":[-85.6168728,41.9392892]},"n2199127062":{"id":"n2199127062","loc":[-85.6168747,41.9396965]},"n2199127071":{"id":"n2199127071","loc":[-85.620196,41.9399446]},"n2199127072":{"id":"n2199127072","loc":[-85.620193,41.9397316]},"n2199127073":{"id":"n2199127073","loc":[-85.6200381,41.9397328]},"n2199127074":{"id":"n2199127074","loc":[-85.6200412,41.9399458]},"n2199127075":{"id":"n2199127075","loc":[-85.6203606,41.9399939]},"n2199127076":{"id":"n2199127076","loc":[-85.6205527,41.9399922]},"n2199127077":{"id":"n2199127077","loc":[-85.6205482,41.9397115]},"n2199127078":{"id":"n2199127078","loc":[-85.6204132,41.9397124]},"n2199127079":{"id":"n2199127079","loc":[-85.6204144,41.9396341]},"n2199127080":{"id":"n2199127080","loc":[-85.6205699,41.9396324]},"n2199127081":{"id":"n2199127081","loc":[-85.6205722,41.939498]},"n2199127082":{"id":"n2199127082","loc":[-85.6204064,41.9394997]},"n2199127083":{"id":"n2199127083","loc":[-85.6204087,41.939561]},"n2199127084":{"id":"n2199127084","loc":[-85.6203103,41.9395618]},"n2199127085":{"id":"n2199127085","loc":[-85.620308,41.9396069]},"n2199127086":{"id":"n2199127086","loc":[-85.6200347,41.9396086]},"n2199127087":{"id":"n2199127087","loc":[-85.6200382,41.9397141]},"n2199127088":{"id":"n2199127088","loc":[-85.6202257,41.9397149]},"n2199127089":{"id":"n2199127089","loc":[-85.6202269,41.9399182]},"n2199127090":{"id":"n2199127090","loc":[-85.6203595,41.9399199]},"n2199127091":{"id":"n2199127091","loc":[-85.6212335,41.939688]},"n2199127092":{"id":"n2199127092","loc":[-85.6212328,41.939595]},"n2199127093":{"id":"n2199127093","loc":[-85.6208807,41.9395966]},"n2199127094":{"id":"n2199127094","loc":[-85.6208815,41.9396896]},"n2199127095":{"id":"n2199127095","loc":[-85.6208676,41.9396872]},"n2199127096":{"id":"n2199127096","loc":[-85.6208583,41.9393539]},"n2199127097":{"id":"n2199127097","loc":[-85.6207006,41.9393563]},"n2199127098":{"id":"n2199127098","loc":[-85.6207099,41.9396896]},"n185967054":{"id":"n185967054","loc":[-85.6173384,41.9356126]},"n185967063":{"id":"n185967063","loc":[-85.617371,41.936243]},"n185967065":{"id":"n185967065","loc":[-85.617337,41.936299]},"n185967068":{"id":"n185967068","loc":[-85.617321,41.936373]},"n185967070":{"id":"n185967070","loc":[-85.6173562,41.9366969]},"n185967074":{"id":"n185967074","loc":[-85.6173635,41.9377414]},"n185967075":{"id":"n185967075","loc":[-85.6173696,41.9381886]},"n185967076":{"id":"n185967076","loc":[-85.617372,41.938535]},"n2199127056":{"id":"n2199127056","loc":[-85.617147,41.9389616]},"n2199127057":{"id":"n2199127057","loc":[-85.6172136,41.9389614]},"n2199127058":{"id":"n2199127058","loc":[-85.6172123,41.9386909]},"n2199127059":{"id":"n2199127059","loc":[-85.616736,41.9386922]},"n2203921041":{"id":"n2203921041","loc":[-85.6173018,41.9346369]},"w203983952":{"id":"w203983952","tags":{"highway":"service"},"nodes":["n2139966627","n1819800319"]},"w209718301":{"id":"w209718301","tags":{"area":"yes","building":"yes"},"nodes":["n2199127051","n2199127052","n2199127053","n2199127054","n2199127055","n2199127056","n2199127057","n2199127058","n2199127059","n2199127060","n2199127061","n2199127062","n2199127051"]},"w209718304":{"id":"w209718304","tags":{"area":"yes","building":"yes"},"nodes":["n2199127071","n2199127072","n2199127073","n2199127074","n2199127071"]},"w17964961":{"id":"w17964961","tags":{"highway":"residential","name":"Whipple St"},"nodes":["n185963099","n185963110"]},"w17964489":{"id":"w17964489","tags":{"highway":"residential","name":"Jackson St"},"nodes":["n185958498","n185958500"]},"w203983953":{"id":"w203983953","tags":{"area":"yes","leisure":"park","name":"Marina Park"},"nodes":["n1475283994","n1475283979","n1475283998","n2139966629","n2139966625","n1819800319","n2139966623","n2139966622","n2139966621","n2139966630","n1475283994"]},"w17965366":{"id":"w17965366","tags":{"highway":"residential","name":"14th St"},"nodes":["n2203921041","n185967054","n185967063","n185967065","n185967068","n185967070","n185967074","n185967075","n185967076","n185967077"]},"w209718306":{"id":"w209718306","tags":{"area":"yes","building":"yes"},"nodes":["n2199127091","n2199127092","n2199127093","n2199127094","n2199127091"]},"w209718307":{"id":"w209718307","tags":{"area":"yes","building":"yes"},"nodes":["n2199127095","n2199127096","n2199127097","n2199127098","n2199127095"]},"w209718305":{"id":"w209718305","tags":{"area":"yes","building":"yes"},"nodes":["n2199127075","n2199127076","n2199127077","n2199127078","n2199127079","n2199127080","n2199127081","n2199127082","n2199127083","n2199127084","n2199127085","n2199127086","n2199127087","n2199127088","n2199127089","n2199127090","n2199127075"]},"n185960199":{"id":"n185960199","loc":[-85.62965,41.95469]},"n185980737":{"id":"n185980737","loc":[-85.629083,41.953725]},"n2114807561":{"id":"n2114807561","loc":[-85.6297681,41.9524688]},"n2114807597":{"id":"n2114807597","loc":[-85.6296517,41.952563]},"n185960197":{"id":"n185960197","loc":[-85.629676,41.9537314]},"n185978791":{"id":"n185978791","loc":[-85.6244542,41.9547066]},"w17967573":{"id":"w17967573","tags":{"highway":"residential","name":"E Wheeler St"},"nodes":["n185960195","n2114807561","n185968102","n185967430","n185986157","n185978392"]},"w17966553":{"id":"w17966553","tags":{"highway":"residential","name":"East Hoffman Street"},"nodes":["n185971631","n185978784","n185967432","n185968106","n185960199","n185978787","n185978790","n185978791"]},"w17966787":{"id":"w17966787","tags":{"highway":"residential","name":"East Cushman Street"},"nodes":["n185980735","n185980737","n185960197","n185968104","n185960792"]},"w17964723":{"id":"w17964723","tags":{"highway":"residential","name":"Cushman Street"},"nodes":["n185960792","n185960794","n185960796"]},"w17964654":{"id":"w17964654","tags":{"highway":"residential","name":"Pine Street"},"nodes":["n185960195","n2114807597","n185960197","n185960199"]},"n1819848862":{"id":"n1819848862","loc":[-85.6346087,41.9545845]},"n1819848935":{"id":"n1819848935","loc":[-85.6345948,41.9537717]},"n1819848973":{"id":"n1819848973","loc":[-85.6334247,41.9537827]},"n1819848997":{"id":"n1819848997","loc":[-85.6334386,41.9545956]},"n2189015861":{"id":"n2189015861","loc":[-85.6375906,41.954836]},"n2189015865":{"id":"n2189015865","loc":[-85.6383307,41.9548291]},"n2189015867":{"id":"n2189015867","loc":[-85.6383337,41.9550072]},"n2189015868":{"id":"n2189015868","loc":[-85.6380986,41.9550094]},"n2189015869":{"id":"n2189015869","loc":[-85.6381005,41.9551226]},"n2199109808":{"id":"n2199109808","loc":[-85.6372702,41.9522894]},"n2199109810":{"id":"n2199109810","loc":[-85.6372677,41.9521583]},"n2199109812":{"id":"n2199109812","loc":[-85.6369505,41.9521617]},"n2199109814":{"id":"n2199109814","loc":[-85.636953,41.9522927]},"n185952156":{"id":"n185952156","loc":[-85.640983,41.9546557]},"n185953423":{"id":"n185953423","loc":[-85.641871,41.954652]},"n185971637":{"id":"n185971637","loc":[-85.641583,41.95465]},"n185971639":{"id":"n185971639","loc":[-85.6421344,41.9546444]},"n185971642":{"id":"n185971642","loc":[-85.6428264,41.9545612]},"n185971648":{"id":"n185971648","loc":[-85.6436023,41.9544262]},"n185975066":{"id":"n185975066","loc":[-85.640532,41.953638]},"n185975067":{"id":"n185975067","loc":[-85.64079,41.953638]},"n185982166":{"id":"n185982166","loc":[-85.6399012,41.9523817]},"n2189015858":{"id":"n2189015858","loc":[-85.6376104,41.9560138]},"n2189015870":{"id":"n2189015870","loc":[-85.6386794,41.9551172]},"n2189015871":{"id":"n2189015871","loc":[-85.6386817,41.955256]},"n2189015873":{"id":"n2189015873","loc":[-85.6385437,41.9552573]},"n2189015876":{"id":"n2189015876","loc":[-85.638555,41.9559278]},"n2189015879":{"id":"n2189015879","loc":[-85.6384954,41.9559283]},"n2189015882":{"id":"n2189015882","loc":[-85.6384965,41.9559935]},"n2189015885":{"id":"n2189015885","loc":[-85.6383533,41.9559949]},"n2189015888":{"id":"n2189015888","loc":[-85.638351,41.9558607]},"n2189015891":{"id":"n2189015891","loc":[-85.6382178,41.9558619]},"n2189015894":{"id":"n2189015894","loc":[-85.6382203,41.956008]},"w208627223":{"id":"w208627223","tags":{"area":"yes","building":"yes"},"nodes":["n2189015858","n2189015861","n2189015865","n2189015867","n2189015868","n2189015869","n2189015870","n2189015871","n2189015873","n2189015876","n2189015879","n2189015882","n2189015885","n2189015888","n2189015891","n2189015894","n2189015858"]},"w170848328":{"id":"w170848328","tags":{"leisure":"park","name":"Bowman Park"},"nodes":["n1819848935","n1819848973","n1819848997","n1819848862","n1819848935"]},"w17965866":{"id":"w17965866","tags":{"highway":"residential","name":"West Hoffman Street"},"nodes":["n185971631","n185971632","n185964359","n185965025","n1475293264","n185952156","n185971637","n185953423","n185971639","n185971642","n185971648"]},"w209717051":{"id":"w209717051","tags":{"amenity":"place_of_worship","area":"yes","building":"yes","denomination":"baptist","name":"Calvary Missionary Baptist Church","religion":"christian"},"nodes":["n2199109808","n2199109810","n2199109812","n2199109814","n2199109808"]},"w17966172":{"id":"w17966172","tags":{"highway":"residential","name":"West Cushman Street"},"nodes":["n185960796","n185975064","n185964358","n185965023","n1475293222","n185975066","n185975067"]},"w17966975":{"id":"w17966975","tags":{"highway":"residential","name":"W Wheeler St"},"nodes":["n185978392","n185982163","n185964357","n185965021","n1475293261","n185982166"]},"n185960684":{"id":"n185960684","loc":[-85.622687,41.951885]},"n185960686":{"id":"n185960686","loc":[-85.622492,41.951901]},"n185978795":{"id":"n185978795","loc":[-85.6240991,41.954708]},"n185978803":{"id":"n185978803","loc":[-85.623348,41.954547]},"n185978806":{"id":"n185978806","loc":[-85.623123,41.954502]},"n185978808":{"id":"n185978808","loc":[-85.622923,41.954469]},"n185978810":{"id":"n185978810","loc":[-85.622787,41.954457]},"n185978811":{"id":"n185978811","loc":[-85.622612,41.954458]},"n185978813":{"id":"n185978813","loc":[-85.622368,41.954472]},"n1819790545":{"id":"n1819790545","loc":[-85.6240295,41.9548949]},"n1819790621":{"id":"n1819790621","loc":[-85.6235789,41.954855]},"n1819790664":{"id":"n1819790664","loc":[-85.6238363,41.9549507]},"n1819790683":{"id":"n1819790683","loc":[-85.6224727,41.9545921]},"n1819790730":{"id":"n1819790730","loc":[-85.6227527,41.9545795]},"n1819790740":{"id":"n1819790740","loc":[-85.6240402,41.9550784]},"n1819790831":{"id":"n1819790831","loc":[-85.624126,41.9549986]},"n1819790861":{"id":"n1819790861","loc":[-85.6231712,41.9546872]},"n1819790887":{"id":"n1819790887","loc":[-85.6242762,41.955206]},"n2168544739":{"id":"n2168544739","loc":[-85.6249102,41.952801]},"n2168544740":{"id":"n2168544740","loc":[-85.6251859,41.9527564]},"n2168544741":{"id":"n2168544741","loc":[-85.6255515,41.9527921]},"n2168544742":{"id":"n2168544742","loc":[-85.626001,41.9529481]},"n2168544743":{"id":"n2168544743","loc":[-85.6265284,41.9529838]},"n2168544744":{"id":"n2168544744","loc":[-85.626942,41.9528857]},"n2168544745":{"id":"n2168544745","loc":[-85.6270918,41.9526851]},"n2168544746":{"id":"n2168544746","loc":[-85.6272117,41.95244]},"n2168544747":{"id":"n2168544747","loc":[-85.6271578,41.952226]},"n2168544748":{"id":"n2168544748","loc":[-85.6270019,41.9519719]},"n2168544749":{"id":"n2168544749","loc":[-85.6268221,41.9518382]},"n2168544750":{"id":"n2168544750","loc":[-85.6265284,41.951807]},"n2168544751":{"id":"n2168544751","loc":[-85.6256534,41.9518516]},"n2168544752":{"id":"n2168544752","loc":[-85.6253477,41.9518338]},"n2168544753":{"id":"n2168544753","loc":[-85.6251139,41.9517669]},"n185955747":{"id":"n185955747","loc":[-85.620674,41.954709]},"n185960688":{"id":"n185960688","loc":[-85.621032,41.951913]},"n185972054":{"id":"n185972054","loc":[-85.6186728,41.9547335]},"n185978814":{"id":"n185978814","loc":[-85.6201708,41.9547403]},"n1819790532":{"id":"n1819790532","loc":[-85.6244908,41.9555731]},"n1819790536":{"id":"n1819790536","loc":[-85.6217925,41.9583135]},"n1819790538":{"id":"n1819790538","loc":[-85.6233954,41.9600014]},"n1819790539":{"id":"n1819790539","loc":[-85.6204611,41.9562117]},"n1819790546":{"id":"n1819790546","loc":[-85.6210898,41.9567657]},"n1819790548":{"id":"n1819790548","loc":[-85.6202465,41.9562237]},"n1819790550":{"id":"n1819790550","loc":[-85.6250165,41.9560677]},"n1819790551":{"id":"n1819790551","loc":[-85.6227946,41.9597023]},"n1819790553":{"id":"n1819790553","loc":[-85.6215726,41.9584571]},"n1819790556":{"id":"n1819790556","loc":[-85.6196306,41.9573002]},"n1819790557":{"id":"n1819790557","loc":[-85.6209503,41.9563109]},"n1819790558":{"id":"n1819790558","loc":[-85.6196939,41.9574085]},"n1819790561":{"id":"n1819790561","loc":[-85.621079,41.957751]},"n1819790562":{"id":"n1819790562","loc":[-85.6224255,41.9611417]},"n1819790565":{"id":"n1819790565","loc":[-85.6232506,41.9604841]},"n1819790566":{"id":"n1819790566","loc":[-85.6190835,41.9562909]},"n1819790567":{"id":"n1819790567","loc":[-85.622227,41.9593028]},"n1819790569":{"id":"n1819790569","loc":[-85.620976,41.9591039]},"n1819790571":{"id":"n1819790571","loc":[-85.6212078,41.9565303]},"n1819790572":{"id":"n1819790572","loc":[-85.6235306,41.9595102]},"n1819790581":{"id":"n1819790581","loc":[-85.6235563,41.9579351]},"n1819790584":{"id":"n1819790584","loc":[-85.6230371,41.9574598]},"n1819790586":{"id":"n1819790586","loc":[-85.6211748,41.9564272]},"n1819790588":{"id":"n1819790588","loc":[-85.6226508,41.9601086]},"n1819790591":{"id":"n1819790591","loc":[-85.6218032,41.9607468]},"n1819790593":{"id":"n1819790593","loc":[-85.6207915,41.9618735]},"n1819790596":{"id":"n1819790596","loc":[-85.6252955,41.9567858]},"n1819790598":{"id":"n1819790598","loc":[-85.6196618,41.9568939]},"n1819790600":{"id":"n1819790600","loc":[-85.6224416,41.9587084]},"n1819790602":{"id":"n1819790602","loc":[-85.6217442,41.9558641]},"n1819790603":{"id":"n1819790603","loc":[-85.6213355,41.9592116]},"n1819790604":{"id":"n1819790604","loc":[-85.622801,41.9573042]},"n1819790608":{"id":"n1819790608","loc":[-85.6199729,41.9574325]},"n1819790610":{"id":"n1819790610","loc":[-85.6195555,41.9557165]},"n1819790611":{"id":"n1819790611","loc":[-85.622978,41.9586007]},"n1819790613":{"id":"n1819790613","loc":[-85.6253963,41.9562636]},"n1819790614":{"id":"n1819790614","loc":[-85.6235252,41.9580342]},"n1819790616":{"id":"n1819790616","loc":[-85.6232988,41.9596305]},"n1819790617":{"id":"n1819790617","loc":[-85.6226776,41.9598732]},"n1819790619":{"id":"n1819790619","loc":[-85.625553,41.9561794]},"n1819790620":{"id":"n1819790620","loc":[-85.6235574,41.959231]},"n1819790624":{"id":"n1819790624","loc":[-85.6228429,41.9573726]},"n1819790626":{"id":"n1819790626","loc":[-85.6193785,41.9556766]},"n1819790628":{"id":"n1819790628","loc":[-85.620092,41.9554253]},"n1819790630":{"id":"n1819790630","loc":[-85.6226658,41.9604402]},"n1819790638":{"id":"n1819790638","loc":[-85.6219964,41.9602561]},"n1819790640":{"id":"n1819790640","loc":[-85.6232731,41.9599969]},"n1819790643":{"id":"n1819790643","loc":[-85.6247698,41.9568895]},"n1819790650":{"id":"n1819790650","loc":[-85.6216412,41.9550149]},"n1819790652":{"id":"n1819790652","loc":[-85.6224952,41.9603918]},"n1819790656":{"id":"n1819790656","loc":[-85.61918,41.9555649]},"n1819790661":{"id":"n1819790661","loc":[-85.6200169,41.955505]},"n1819790662":{"id":"n1819790662","loc":[-85.6217389,41.9563149]},"n1819790666":{"id":"n1819790666","loc":[-85.6229566,41.9598373]},"n1819790667":{"id":"n1819790667","loc":[-85.6209117,41.9609189]},"n1819790669":{"id":"n1819790669","loc":[-85.6252311,41.9562353]},"n1819790670":{"id":"n1819790670","loc":[-85.6209758,41.961868]},"n1819790672":{"id":"n1819790672","loc":[-85.6209557,41.9589078]},"n1819790673":{"id":"n1819790673","loc":[-85.6190352,41.9561393]},"n1819790675":{"id":"n1819790675","loc":[-85.6236432,41.9586685]},"n1819790676":{"id":"n1819790676","loc":[-85.6194901,41.9565389]},"n1819790678":{"id":"n1819790678","loc":[-85.6219266,41.9582417]},"n1819790680":{"id":"n1819790680","loc":[-85.6208258,41.9557211]},"n1819790681":{"id":"n1819790681","loc":[-85.6212024,41.9613212]},"n1819790682":{"id":"n1819790682","loc":[-85.624877,41.9559401]},"n1819790684":{"id":"n1819790684","loc":[-85.6206499,41.9583693]},"n1819790699":{"id":"n1819790699","loc":[-85.6215243,41.956279]},"n1819790701":{"id":"n1819790701","loc":[-85.6246625,41.9559321]},"n1819790703":{"id":"n1819790703","loc":[-85.6230478,41.9585089]},"n1819790708":{"id":"n1819790708","loc":[-85.6211102,41.9575402]},"n1819790710":{"id":"n1819790710","loc":[-85.6215082,41.9548468]},"n1819790711":{"id":"n1819790711","loc":[-85.6206552,41.9586007]},"n1819790713":{"id":"n1819790713","loc":[-85.6215404,41.9549705]},"n1819790715":{"id":"n1819790715","loc":[-85.6216906,41.955521]},"n1819790717":{"id":"n1819790717","loc":[-85.6215404,41.9547391]},"n1819790722":{"id":"n1819790722","loc":[-85.6219964,41.9599131]},"n1819790723":{"id":"n1819790723","loc":[-85.622286,41.9606989]},"n1819790725":{"id":"n1819790725","loc":[-85.6228439,41.9572005]},"n1819790727":{"id":"n1819790727","loc":[-85.6202518,41.9554458]},"n1819790728":{"id":"n1819790728","loc":[-85.623434,41.9575276]},"n1819790729":{"id":"n1819790729","loc":[-85.6234287,41.9568576]},"n1819790732":{"id":"n1819790732","loc":[-85.6229566,41.9571369]},"n1819790733":{"id":"n1819790733","loc":[-85.6225543,41.9590275]},"n1819790734":{"id":"n1819790734","loc":[-85.6232892,41.9583135]},"n1819790736":{"id":"n1819790736","loc":[-85.622977,41.9608551]},"n1819790737":{"id":"n1819790737","loc":[-85.624008,41.9569533]},"n1819790741":{"id":"n1819790741","loc":[-85.6212775,41.9608545]},"n1819790742":{"id":"n1819790742","loc":[-85.6231282,41.9569932]},"n1819790743":{"id":"n1819790743","loc":[-85.6224523,41.9591831]},"n1819790744":{"id":"n1819790744","loc":[-85.6210951,41.9610819]},"n1819790745":{"id":"n1819790745","loc":[-85.6220114,41.960544]},"n1819790755":{"id":"n1819790755","loc":[-85.6216369,41.9553854]},"n1819790757":{"id":"n1819790757","loc":[-85.6209986,41.9592709]},"n1819790758":{"id":"n1819790758","loc":[-85.6200437,41.9563468]},"n1819790764":{"id":"n1819790764","loc":[-85.6219363,41.9596823]},"n1819790765":{"id":"n1819790765","loc":[-85.6237612,41.9568496]},"n1819790769":{"id":"n1819790769","loc":[-85.6212389,41.9593433]},"n1819790771":{"id":"n1819790771","loc":[-85.6210726,41.9560123]},"n1819790772":{"id":"n1819790772","loc":[-85.6212711,41.9561838]},"n1819790776":{"id":"n1819790776","loc":[-85.6234437,41.9577795]},"n1819790777":{"id":"n1819790777","loc":[-85.6212502,41.9618599]},"n1819790783":{"id":"n1819790783","loc":[-85.6216895,41.9610585]},"n1819790784":{"id":"n1819790784","loc":[-85.6200115,41.9556367]},"n1819790785":{"id":"n1819790785","loc":[-85.6210576,41.9573002]},"n1819790786":{"id":"n1819790786","loc":[-85.621138,41.9576632]},"n1819790788":{"id":"n1819790788","loc":[-85.6207733,41.9578946]},"n1819790789":{"id":"n1819790789","loc":[-85.6200705,41.9571566]},"n1819790790":{"id":"n1819790790","loc":[-85.6245337,41.9558443]},"n1819790792":{"id":"n1819790792","loc":[-85.621932,41.9608066]},"n1819790793":{"id":"n1819790793","loc":[-85.6233578,41.9581385]},"n1819790794":{"id":"n1819790794","loc":[-85.6204557,41.9555136]},"n1819790797":{"id":"n1819790797","loc":[-85.6235038,41.9576074]},"n1819790800":{"id":"n1819790800","loc":[-85.6214438,41.9607508]},"n1819790801":{"id":"n1819790801","loc":[-85.623492,41.9602129]},"n1819790802":{"id":"n1819790802","loc":[-85.6216691,41.9546553]},"n1819790803":{"id":"n1819790803","loc":[-85.6231057,41.9586851]},"n1819790804":{"id":"n1819790804","loc":[-85.6209224,41.9578673]},"n1819790813":{"id":"n1819790813","loc":[-85.620092,41.9572962]},"n1819790814":{"id":"n1819790814","loc":[-85.6216691,41.9552218]},"n1819790816":{"id":"n1819790816","loc":[-85.6216144,41.9609668]},"n1819790818":{"id":"n1819790818","loc":[-85.6216906,41.9557324]},"n1819790820":{"id":"n1819790820","loc":[-85.6192069,41.9564186]},"n1819790823":{"id":"n1819790823","loc":[-85.6211155,41.9566027]},"n1819790825":{"id":"n1819790825","loc":[-85.6233106,41.9569294]},"n1819790839":{"id":"n1819790839","loc":[-85.625671,41.9564986]},"n1819790842":{"id":"n1819790842","loc":[-85.6235252,41.9567379]},"n1819790844":{"id":"n1819790844","loc":[-85.6253813,41.9566342]},"n1819790847":{"id":"n1819790847","loc":[-85.6200963,41.9567702]},"n1819790849":{"id":"n1819790849","loc":[-85.6238031,41.9587449]},"n1819790851":{"id":"n1819790851","loc":[-85.6234984,41.9584571]},"n1819790856":{"id":"n1819790856","loc":[-85.6242226,41.9570092]},"n1819790865":{"id":"n1819790865","loc":[-85.6200265,41.9569458]},"n1819790869":{"id":"n1819790869","loc":[-85.6230049,41.9601245]},"n1819790871":{"id":"n1819790871","loc":[-85.6190727,41.9558322]},"n1819790873":{"id":"n1819790873","loc":[-85.6217442,41.9550104]},"n1819790875":{"id":"n1819790875","loc":[-85.6208044,41.9587808]},"n1819790879":{"id":"n1819790879","loc":[-85.6198444,41.9574484]},"n1819790883":{"id":"n1819790883","loc":[-85.623713,41.9588719]},"n1819790885":{"id":"n1819790885","loc":[-85.6223289,41.9605075]},"n1819790889":{"id":"n1819790889","loc":[-85.6208044,41.9562437]},"n1819790893":{"id":"n1819790893","loc":[-85.6218183,41.9559684]},"n1819790906":{"id":"n1819790906","loc":[-85.6214052,41.958697]},"n1819790913":{"id":"n1819790913","loc":[-85.6209981,41.9609957]},"n1819790917":{"id":"n1819790917","loc":[-85.6216208,41.9604436]},"n1819790919":{"id":"n1819790919","loc":[-85.6209406,41.9616373]},"n1819790920":{"id":"n1819790920","loc":[-85.6221948,41.9583334]},"n1819790922":{"id":"n1819790922","loc":[-85.6216681,41.9615292]},"n1819790924":{"id":"n1819790924","loc":[-85.6210147,41.9570489]},"n1819790929":{"id":"n1819790929","loc":[-85.6193678,41.955521]},"w17964707":{"id":"w17964707","tags":{"highway":"residential","name":"11th Ave"},"nodes":["n185960682","n185960684","n185960686","n185960688","n185960690"]},"w201484345":{"id":"w201484345","tags":{"bridge":"yes","highway":"residential","name":"E Hoffman St"},"nodes":["n185978791","n185978795"]},"w201484348":{"id":"w201484348","tags":{"highway":"residential","name":"E Hoffman St"},"nodes":["n185978795","n185978800","n185978803","n185978806","n185978808","n185978810","n185978811","n185978813","n185955747","n185978814","n185972054","n185978817"]},"w170843845":{"id":"w170843845","tags":{"landuse":"reservoir","name":"Hoffman Pond","natural":"water"},"nodes":["n1819790732","n1819790742","n1819790825","n1819790729","n1819790842","n1819790765","n1819790737","n1819790856","n1819790643","n1819790596","n1819790844","n1819790839","n1819849190","n1819790619","n1819790613","n1819790669","n1819790550","n1819790682","n1819790701","n1819790790","n1819790532","n1819790887","n1819790740","n1819790831","n1819790545","n1819790664","n1819790621","n1819790861","n1819790730","n1819790683","n1819790802","n1819790717","n1819790710","n1819790713","n1819790650","n1819790873","n1819790814","n1819790755","n1819790715","n1819790818","n1819790602","n1819790893","n1819790662","n1819790699","n1819790772","n1819790771","n1819790680","n1819790794","n1819790727","n1819790628","n1819790661","n1819790784","n1819790610","n1819790626","n1819790929","n1819790656","n1819790871","n1819790673","n1819790566","n1819790820","n1819790676","n1819790598","n1819790556","n1819790558","n1819790879","n1819790608","n1819790813","n1819790789","n1819790865","n1819790847","n1819790758","n1819790548","n1819790539","n1819790889","n1819790557","n1819790586","n1819790571","n1819790823","n1819790546","n1819790924","n1819790785","n1819790708","n1819790786","n1819790561","n1819790804","n1819790788","n1819790684","n1819790711","n1819790875","n1819790672","n1819790569","n1819790757","n1819790769","n1819790603","n1819790906","n1819790553","n1819790536","n1819790678","n1819790920","n1819790600","n1819790733","n1819790743","n1819790567","n1819790764","n1819790722","n1819790638","n1819790917","n1819790800","n1819790741","n1819790667","n1819790913","n1819790744","n1819790816","n1819790591","n1819790745","n1819790885","n1819790652","n1819790588","n1819790617","n1819790551","n1819790666","n1819790869","n1819790630","n1819790723","n1819790792","n1819790783","n1819790681","n1819790919","n1819790593","n1819790670","n1819790777","n1819790922","n1819790562","n1819790736","n1819790565","n1819790801","n1819790538","n1819790640","n1819790616","n1819790572","n1819790620","n1819790883","n1819790849","n1819790675","n1819790851","n1819790803","n1819790611","n1819790703","n1819790734","n1819790793","n1819790614","n1819790581","n1819790776","n1819790797","n1819790728","n1819790584","n1819790624","n1819790604","n1819790725","n1819790732"]},"w206805240":{"id":"w206805240","tags":{"waterway":"river"},"nodes":["n2168544738","n2168544739","n2168544740","n2168544741","n2168544742","n2168544743","n2168544744","n2168544745","n2168544746","n2168544747","n2168544748","n2168544749","n2168544750","n2168544751","n2168544752","n2168544753","n1819848944"]},"n394490429":{"id":"n394490429","loc":[-85.643883,41.954365]},"n185953421":{"id":"n185953421","loc":[-85.641876,41.954946]},"n185953417":{"id":"n185953417","loc":[-85.6418306,41.9551597]},"n185977233":{"id":"n185977233","loc":[-85.642987,41.95486]},"n185977232":{"id":"n185977232","loc":[-85.642894,41.9547842]},"n1475293244":{"id":"n1475293244","loc":[-85.63974,41.9521543]},"n1819848890":{"id":"n1819848890","loc":[-85.6410004,41.9552822]},"n1819848965":{"id":"n1819848965","loc":[-85.6409795,41.9553892]},"n2189015846":{"id":"n2189015846","loc":[-85.6420457,41.9549528]},"n2189015849":{"id":"n2189015849","loc":[-85.6425867,41.9551392]},"n2189015852":{"id":"n2189015852","loc":[-85.6426877,41.9549771]},"n2199109816":{"id":"n2199109816","loc":[-85.6399215,41.9540925]},"n2199109818":{"id":"n2199109818","loc":[-85.6399182,41.9538236]},"n2199109820":{"id":"n2199109820","loc":[-85.6402201,41.9538216]},"n2199109822":{"id":"n2199109822","loc":[-85.640222,41.9539771]},"n2199109825":{"id":"n2199109825","loc":[-85.6402904,41.9539766]},"n2199109827":{"id":"n2199109827","loc":[-85.6402918,41.95409]},"n2199109829":{"id":"n2199109829","loc":[-85.6395845,41.9544626]},"n2199109831":{"id":"n2199109831","loc":[-85.6395792,41.9540671]},"n2199109833":{"id":"n2199109833","loc":[-85.6397173,41.9540661]},"n2199109835":{"id":"n2199109835","loc":[-85.6397226,41.9544616]},"n2199109837":{"id":"n2199109837","loc":[-85.6399641,41.9545058]},"n2199109839":{"id":"n2199109839","loc":[-85.6399637,41.9541859]},"n2199109841":{"id":"n2199109841","loc":[-85.6401098,41.9541858]},"n2199109843":{"id":"n2199109843","loc":[-85.64011,41.9543272]},"n2199109845":{"id":"n2199109845","loc":[-85.6400783,41.9543273]},"n2199109847":{"id":"n2199109847","loc":[-85.6400785,41.9545058]},"n2199109853":{"id":"n2199109853","loc":[-85.6396184,41.9554049]},"n2199109855":{"id":"n2199109855","loc":[-85.6396825,41.9553713]},"n185949745":{"id":"n185949745","loc":[-85.6442727,41.9553112]},"n185949748":{"id":"n185949748","loc":[-85.6448804,41.9555238]},"n185949755":{"id":"n185949755","loc":[-85.6420011,41.9603536]},"n185949763":{"id":"n185949763","loc":[-85.6408843,41.9555822]},"n185949765":{"id":"n185949765","loc":[-85.6414548,41.9557751]},"n185952158":{"id":"n185952158","loc":[-85.640066,41.956854]},"n185952160":{"id":"n185952160","loc":[-85.639848,41.957229]},"n185952161":{"id":"n185952161","loc":[-85.6396089,41.9576192]},"n185952163":{"id":"n185952163","loc":[-85.63892,41.957957]},"n185953413":{"id":"n185953413","loc":[-85.64162,41.955475]},"n185971651":{"id":"n185971651","loc":[-85.6440766,41.9543462]},"n185977234":{"id":"n185977234","loc":[-85.645044,41.955581]},"n394490395":{"id":"n394490395","loc":[-85.657336,41.936762]},"n394490396":{"id":"n394490396","loc":[-85.653896,41.936978]},"n394490397":{"id":"n394490397","loc":[-85.653732,41.937386]},"n394490398":{"id":"n394490398","loc":[-85.65182,41.937378]},"n394490399":{"id":"n394490399","loc":[-85.651843,41.938445]},"n394490400":{"id":"n394490400","loc":[-85.652536,41.938447]},"n394490401":{"id":"n394490401","loc":[-85.652533,41.938901]},"n394490402":{"id":"n394490402","loc":[-85.652084,41.9389]},"n394490403":{"id":"n394490403","loc":[-85.6521,41.939627]},"n394490404":{"id":"n394490404","loc":[-85.652301,41.939628]},"n394490405":{"id":"n394490405","loc":[-85.652302,41.939755]},"n394490406":{"id":"n394490406","loc":[-85.652783,41.939747]},"n394490407":{"id":"n394490407","loc":[-85.652835,41.94112]},"n394490408":{"id":"n394490408","loc":[-85.651968,41.941123]},"n394490409":{"id":"n394490409","loc":[-85.651983,41.941969]},"n394490410":{"id":"n394490410","loc":[-85.652908,41.941961]},"n394490411":{"id":"n394490411","loc":[-85.65292,41.94278]},"n394490412":{"id":"n394490412","loc":[-85.651698,41.942816]},"n394490413":{"id":"n394490413","loc":[-85.651509,41.942823]},"n394490414":{"id":"n394490414","loc":[-85.651272,41.942837]},"n394490415":{"id":"n394490415","loc":[-85.651272,41.943325]},"n394490416":{"id":"n394490416","loc":[-85.65122,41.944053]},"n394490417":{"id":"n394490417","loc":[-85.651193,41.944449]},"n394490418":{"id":"n394490418","loc":[-85.651088,41.944969]},"n394490419":{"id":"n394490419","loc":[-85.650949,41.945554]},"n394490420":{"id":"n394490420","loc":[-85.650907,41.945719]},"n394490421":{"id":"n394490421","loc":[-85.650808,41.946016]},"n394490422":{"id":"n394490422","loc":[-85.650712,41.946516]},"n394490423":{"id":"n394490423","loc":[-85.650493,41.947166]},"n394490424":{"id":"n394490424","loc":[-85.650626,41.947213]},"n394490425":{"id":"n394490425","loc":[-85.650201,41.948109]},"n394490426":{"id":"n394490426","loc":[-85.649868,41.948797]},"n394490427":{"id":"n394490427","loc":[-85.649669,41.949161]},"n394490428":{"id":"n394490428","loc":[-85.64659,41.954067]},"n394490430":{"id":"n394490430","loc":[-85.644034,41.95444]},"n394490431":{"id":"n394490431","loc":[-85.644248,41.954507]},"n394490432":{"id":"n394490432","loc":[-85.64491,41.954481]},"n394490433":{"id":"n394490433","loc":[-85.645213,41.954433]},"n394490434":{"id":"n394490434","loc":[-85.645426,41.954477]},"n394490435":{"id":"n394490435","loc":[-85.6458,41.954704]},"n394490436":{"id":"n394490436","loc":[-85.64605,41.954804]},"n394490437":{"id":"n394490437","loc":[-85.646125,41.954817]},"n394490438":{"id":"n394490438","loc":[-85.646002,41.954997]},"n394490439":{"id":"n394490439","loc":[-85.645764,41.955366]},"n394490440":{"id":"n394490440","loc":[-85.645525,41.955734]},"n394490441":{"id":"n394490441","loc":[-85.64443,41.957424]},"n394490442":{"id":"n394490442","loc":[-85.641712,41.961723]},"n394490443":{"id":"n394490443","loc":[-85.640747,41.963246]},"n394490444":{"id":"n394490444","loc":[-85.637803,41.967894]},"n394490445":{"id":"n394490445","loc":[-85.637673,41.967861]},"n394490446":{"id":"n394490446","loc":[-85.636637,41.969275]},"n394490447":{"id":"n394490447","loc":[-85.634923,41.969269]},"n394490448":{"id":"n394490448","loc":[-85.634893,41.968537]},"n394490449":{"id":"n394490449","loc":[-85.634544,41.96927]},"n394490450":{"id":"n394490450","loc":[-85.630835,41.969274]},"n394490451":{"id":"n394490451","loc":[-85.630834,41.968348]},"n394490452":{"id":"n394490452","loc":[-85.630857,41.968179]},"n394490453":{"id":"n394490453","loc":[-85.630924,41.968044]},"n394490454":{"id":"n394490454","loc":[-85.631004,41.967925]},"n394490455":{"id":"n394490455","loc":[-85.631143,41.967811]},"n394490456":{"id":"n394490456","loc":[-85.631311,41.967736]},"n394490457":{"id":"n394490457","loc":[-85.631595,41.967693]},"n394490458":{"id":"n394490458","loc":[-85.63325,41.967702]},"n394490459":{"id":"n394490459","loc":[-85.633247,41.967021]},"n394490460":{"id":"n394490460","loc":[-85.634858,41.967021]},"n394490461":{"id":"n394490461","loc":[-85.634865,41.967711]},"n394490462":{"id":"n394490462","loc":[-85.634884,41.968231]},"n394490463":{"id":"n394490463","loc":[-85.636559,41.963867]},"n394490464":{"id":"n394490464","loc":[-85.634832,41.963866]},"n394490465":{"id":"n394490465","loc":[-85.63481,41.961899]},"n394490466":{"id":"n394490466","loc":[-85.637219,41.961842]},"n394490467":{"id":"n394490467","loc":[-85.637837,41.960019]},"n394490468":{"id":"n394490468","loc":[-85.637459,41.960022]},"n394490469":{"id":"n394490469","loc":[-85.635295,41.959987]},"n394490470":{"id":"n394490470","loc":[-85.634783,41.959979]},"n394490471":{"id":"n394490471","loc":[-85.634776,41.959834]},"n394490472":{"id":"n394490472","loc":[-85.634767,41.959009]},"n394490473":{"id":"n394490473","loc":[-85.634763,41.958292]},"n394490474":{"id":"n394490474","loc":[-85.633346,41.958287]},"n394490475":{"id":"n394490475","loc":[-85.632128,41.9583]},"n394490476":{"id":"n394490476","loc":[-85.631414,41.958318]},"n394490477":{"id":"n394490477","loc":[-85.63137,41.959033]},"n394490478":{"id":"n394490478","loc":[-85.631325,41.959753]},"n394490479":{"id":"n394490479","loc":[-85.631494,41.95977]},"n394490480":{"id":"n394490480","loc":[-85.631456,41.960673]},"n394490481":{"id":"n394490481","loc":[-85.631421,41.961494]},"n394490482":{"id":"n394490482","loc":[-85.631404,41.961887]},"n394490483":{"id":"n394490483","loc":[-85.631401,41.961968]},"n394490484":{"id":"n394490484","loc":[-85.630962,41.961967]},"n394490485":{"id":"n394490485","loc":[-85.6299,41.961973]},"n394490486":{"id":"n394490486","loc":[-85.624929,41.962002]},"n394490487":{"id":"n394490487","loc":[-85.623333,41.961987]},"n394490488":{"id":"n394490488","loc":[-85.621894,41.963956]},"n394490489":{"id":"n394490489","loc":[-85.62131,41.963727]},"n394490490":{"id":"n394490490","loc":[-85.621216,41.963868]},"n394490491":{"id":"n394490491","loc":[-85.620356,41.965119]},"n394490492":{"id":"n394490492","loc":[-85.620848,41.965341]},"n394490493":{"id":"n394490493","loc":[-85.620684,41.965558]},"n394490494":{"id":"n394490494","loc":[-85.620621,41.965658]},"n394490495":{"id":"n394490495","loc":[-85.618165,41.965759]},"n394490496":{"id":"n394490496","loc":[-85.618071,41.965759]},"n394490497":{"id":"n394490497","loc":[-85.617986,41.965759]},"n394490498":{"id":"n394490498","loc":[-85.605673,41.965764]},"n394490499":{"id":"n394490499","loc":[-85.605668,41.963548]},"n394490500":{"id":"n394490500","loc":[-85.605664,41.962094]},"n394490501":{"id":"n394490501","loc":[-85.595828,41.962159]},"n394490502":{"id":"n394490502","loc":[-85.587869,41.962169]},"n394490503":{"id":"n394490503","loc":[-85.586289,41.962179]},"n394490504":{"id":"n394490504","loc":[-85.583774,41.962178]},"n394490505":{"id":"n394490505","loc":[-85.583774,41.961789]},"n394490506":{"id":"n394490506","loc":[-85.581303,41.961783]},"n394490507":{"id":"n394490507","loc":[-85.581304,41.961616]},"n394490508":{"id":"n394490508","loc":[-85.581292,41.961616]},"n394490509":{"id":"n394490509","loc":[-85.581247,41.959244]},"n394490510":{"id":"n394490510","loc":[-85.581245,41.958394]},"n394490511":{"id":"n394490511","loc":[-85.581276,41.958372]},"n394490512":{"id":"n394490512","loc":[-85.581302,41.958353]},"n394490513":{"id":"n394490513","loc":[-85.581376,41.9583]},"n394490514":{"id":"n394490514","loc":[-85.582256,41.957663]},"n394490515":{"id":"n394490515","loc":[-85.585299,41.955483]},"n394490516":{"id":"n394490516","loc":[-85.585588,41.955331]},"n394490517":{"id":"n394490517","loc":[-85.586053,41.955163]},"n394490518":{"id":"n394490518","loc":[-85.58632,41.955076]},"n394490519":{"id":"n394490519","loc":[-85.586478,41.955025]},"n394490520":{"id":"n394490520","loc":[-85.58692,41.954947]},"n394490521":{"id":"n394490521","loc":[-85.587327,41.954914]},"n394490522":{"id":"n394490522","loc":[-85.587345,41.954913]},"n394490523":{"id":"n394490523","loc":[-85.587358,41.954913]},"n394490524":{"id":"n394490524","loc":[-85.58963,41.954877]},"n394490525":{"id":"n394490525","loc":[-85.591077,41.954865]},"n394490526":{"id":"n394490526","loc":[-85.594824,41.954843]},"n394490527":{"id":"n394490527","loc":[-85.594804,41.95331]},"n394490528":{"id":"n394490528","loc":[-85.599336,41.95331]},"n394490529":{"id":"n394490529","loc":[-85.599336,41.954825]},"n394490530":{"id":"n394490530","loc":[-85.597828,41.954839]},"n394490531":{"id":"n394490531","loc":[-85.597833,41.95614]},"n394490532":{"id":"n394490532","loc":[-85.596586,41.956151]},"n394490533":{"id":"n394490533","loc":[-85.596586,41.956394]},"n394490534":{"id":"n394490534","loc":[-85.595933,41.956394]},"n394490535":{"id":"n394490535","loc":[-85.595933,41.958176]},"n394490536":{"id":"n394490536","loc":[-85.597635,41.958179]},"n394490537":{"id":"n394490537","loc":[-85.597717,41.958177]},"n394490538":{"id":"n394490538","loc":[-85.601671,41.958194]},"n394490539":{"id":"n394490539","loc":[-85.605619,41.958194]},"n394490540":{"id":"n394490540","loc":[-85.608054,41.958187]},"n394490542":{"id":"n394490542","loc":[-85.6080762,41.9547864]},"n394490545":{"id":"n394490545","loc":[-85.6104354,41.9548263]},"n394490546":{"id":"n394490546","loc":[-85.610274,41.951106]},"n394490547":{"id":"n394490547","loc":[-85.610278,41.950829]},"n394490548":{"id":"n394490548","loc":[-85.610309,41.948377]},"n394490549":{"id":"n394490549","loc":[-85.610314,41.947986]},"n394490550":{"id":"n394490550","loc":[-85.610464,41.947985]},"n394490551":{"id":"n394490551","loc":[-85.610447,41.947468]},"n394490552":{"id":"n394490552","loc":[-85.612469,41.947471]},"n394490553":{"id":"n394490553","loc":[-85.612494,41.945576]},"n394490554":{"id":"n394490554","loc":[-85.610292,41.94558]},"n394490555":{"id":"n394490555","loc":[-85.608412,41.945625]},"n394490556":{"id":"n394490556","loc":[-85.608412,41.943036]},"n394490557":{"id":"n394490557","loc":[-85.608702,41.943087]},"n394490558":{"id":"n394490558","loc":[-85.609196,41.943224]},"n394490559":{"id":"n394490559","loc":[-85.609571,41.943263]},"n394490560":{"id":"n394490560","loc":[-85.610116,41.943295]},"n394490561":{"id":"n394490561","loc":[-85.610273,41.943275]},"n394490562":{"id":"n394490562","loc":[-85.611339,41.943075]},"n394490563":{"id":"n394490563","loc":[-85.611575,41.942997]},"n394490564":{"id":"n394490564","loc":[-85.611847,41.942849]},"n394490565":{"id":"n394490565","loc":[-85.612164,41.942568]},"n394490566":{"id":"n394490566","loc":[-85.612341,41.942529]},"n394490567":{"id":"n394490567","loc":[-85.612562,41.942524]},"n394490568":{"id":"n394490568","loc":[-85.612768,41.942546]},"n394490569":{"id":"n394490569","loc":[-85.612938,41.942633]},"n394490570":{"id":"n394490570","loc":[-85.6131,41.942782]},"n394490571":{"id":"n394490571","loc":[-85.613299,41.942919]},"n394490572":{"id":"n394490572","loc":[-85.613498,41.942996]},"n394490573":{"id":"n394490573","loc":[-85.614698,41.942842]},"n394490574":{"id":"n394490574","loc":[-85.615288,41.942698]},"n394490575":{"id":"n394490575","loc":[-85.616054,41.942693]},"n394490576":{"id":"n394490576","loc":[-85.61603,41.942175]},"n394490577":{"id":"n394490577","loc":[-85.616004,41.941741]},"n394490578":{"id":"n394490578","loc":[-85.615994,41.940156]},"n394490579":{"id":"n394490579","loc":[-85.615144,41.940159]},"n394490580":{"id":"n394490580","loc":[-85.614915,41.940161]},"n394490582":{"id":"n394490582","loc":[-85.614875,41.938532]},"n394490583":{"id":"n394490583","loc":[-85.616167,41.938787]},"n394490585":{"id":"n394490585","loc":[-85.616176,41.938589]},"n394490586":{"id":"n394490586","loc":[-85.614537,41.938282]},"n394490588":{"id":"n394490588","loc":[-85.610141,41.937459]},"n394490589":{"id":"n394490589","loc":[-85.610172,41.937298]},"n394490590":{"id":"n394490590","loc":[-85.609918,41.935495]},"n394490592":{"id":"n394490592","loc":[-85.610092,41.935451]},"n394490594":{"id":"n394490594","loc":[-85.610681,41.935247]},"n394490595":{"id":"n394490595","loc":[-85.611446,41.934955]},"n394490596":{"id":"n394490596","loc":[-85.612057,41.934696]},"n394490598":{"id":"n394490598","loc":[-85.613256,41.934084]},"n394490599":{"id":"n394490599","loc":[-85.613948,41.933682]},"n394490601":{"id":"n394490601","loc":[-85.61436,41.933417]},"n394490602":{"id":"n394490602","loc":[-85.614638,41.933212]},"n394490604":{"id":"n394490604","loc":[-85.615249,41.9332]},"n394490605":{"id":"n394490605","loc":[-85.618218,41.933223]},"n394490607":{"id":"n394490607","loc":[-85.618241,41.933479]},"n394490608":{"id":"n394490608","loc":[-85.618257,41.93365]},"n394490609":{"id":"n394490609","loc":[-85.618298,41.935067]},"n394490611":{"id":"n394490611","loc":[-85.619791,41.935067]},"n394490612":{"id":"n394490612","loc":[-85.619794,41.933301]},"n394490613":{"id":"n394490613","loc":[-85.619795,41.932692]},"n394490614":{"id":"n394490614","loc":[-85.619729,41.929517]},"n394490615":{"id":"n394490615","loc":[-85.619801,41.929305]},"n394490616":{"id":"n394490616","loc":[-85.619809,41.927391]},"n394490617":{"id":"n394490617","loc":[-85.620883,41.927378]},"n394490618":{"id":"n394490618","loc":[-85.620988,41.927368]},"n394490619":{"id":"n394490619","loc":[-85.621076,41.927368]},"n394490620":{"id":"n394490620","loc":[-85.621156,41.927376]},"n394490621":{"id":"n394490621","loc":[-85.621685,41.92737]},"n394490622":{"id":"n394490622","loc":[-85.624716,41.927359]},"n394490623":{"id":"n394490623","loc":[-85.625308,41.92737]},"n394490624":{"id":"n394490624","loc":[-85.625655,41.927377]},"n394490625":{"id":"n394490625","loc":[-85.625093,41.925591]},"n394490626":{"id":"n394490626","loc":[-85.625174,41.92559]},"n394490627":{"id":"n394490627","loc":[-85.625249,41.925597]},"n394490628":{"id":"n394490628","loc":[-85.625532,41.925604]},"n394490629":{"id":"n394490629","loc":[-85.625761,41.925597]},"n394490630":{"id":"n394490630","loc":[-85.625955,41.926153]},"n394490631":{"id":"n394490631","loc":[-85.626209,41.926155]},"n394490632":{"id":"n394490632","loc":[-85.627757,41.926151]},"n394490633":{"id":"n394490633","loc":[-85.627825,41.926298]},"n394490634":{"id":"n394490634","loc":[-85.627994,41.926315]},"n394490635":{"id":"n394490635","loc":[-85.628049,41.927196]},"n394490636":{"id":"n394490636","loc":[-85.62949,41.927221]},"n394490637":{"id":"n394490637","loc":[-85.629602,41.927277]},"n394490638":{"id":"n394490638","loc":[-85.6297102,41.9273279]},"n394490639":{"id":"n394490639","loc":[-85.630958,41.927398]},"n394490699":{"id":"n394490699","loc":[-85.632741,41.927388]},"n394490700":{"id":"n394490700","loc":[-85.632997,41.927391]},"n394490701":{"id":"n394490701","loc":[-85.633149,41.927393]},"n394490702":{"id":"n394490702","loc":[-85.633334,41.927393]},"n394490703":{"id":"n394490703","loc":[-85.633468,41.927561]},"n394490704":{"id":"n394490704","loc":[-85.633563,41.927755]},"n394490705":{"id":"n394490705","loc":[-85.633662,41.928192]},"n394490706":{"id":"n394490706","loc":[-85.633679,41.928807]},"n394490707":{"id":"n394490707","loc":[-85.633687,41.929107]},"n394490708":{"id":"n394490708","loc":[-85.633927,41.929109]},"n394490709":{"id":"n394490709","loc":[-85.634126,41.929111]},"n394490710":{"id":"n394490710","loc":[-85.634207,41.92911]},"n394490711":{"id":"n394490711","loc":[-85.634323,41.929111]},"n394490712":{"id":"n394490712","loc":[-85.636712,41.929128]},"n394490713":{"id":"n394490713","loc":[-85.63808,41.9291]},"n394490714":{"id":"n394490714","loc":[-85.639213,41.929088]},"n394490715":{"id":"n394490715","loc":[-85.639189,41.92852]},"n394490716":{"id":"n394490716","loc":[-85.639204,41.925488]},"n394490717":{"id":"n394490717","loc":[-85.644204,41.925452]},"n394490718":{"id":"n394490718","loc":[-85.651425,41.925406]},"n394490719":{"id":"n394490719","loc":[-85.651449,41.926321]},"n394490720":{"id":"n394490720","loc":[-85.651451,41.926969]},"n394490721":{"id":"n394490721","loc":[-85.651458,41.928052]},"n394490722":{"id":"n394490722","loc":[-85.651446,41.928892]},"n394490723":{"id":"n394490723","loc":[-85.651456,41.929447]},"n394490724":{"id":"n394490724","loc":[-85.651707,41.929454]},"n394490725":{"id":"n394490725","loc":[-85.652369,41.929473]},"n394490726":{"id":"n394490726","loc":[-85.6525,41.929452]},"n394490727":{"id":"n394490727","loc":[-85.654066,41.92946]},"n394490728":{"id":"n394490728","loc":[-85.654816,41.92946]},"n394490729":{"id":"n394490729","loc":[-85.654816,41.930337]},"n394490730":{"id":"n394490730","loc":[-85.654587,41.930337]},"n394490731":{"id":"n394490731","loc":[-85.654548,41.931072]},"n394490732":{"id":"n394490732","loc":[-85.654538,41.931701]},"n394490733":{"id":"n394490733","loc":[-85.654898,41.931689]},"n394490734":{"id":"n394490734","loc":[-85.654898,41.932505]},"n394490735":{"id":"n394490735","loc":[-85.654854,41.932514]},"n394490736":{"id":"n394490736","loc":[-85.655497,41.932499]},"n394490737":{"id":"n394490737","loc":[-85.656405,41.932493]},"n394490738":{"id":"n394490738","loc":[-85.656422,41.933416]},"n394490739":{"id":"n394490739","loc":[-85.657322,41.933438]},"n1475293233":{"id":"n1475293233","loc":[-85.6385522,41.9585167]},"n1475293242":{"id":"n1475293242","loc":[-85.64609,41.9540815]},"n1475293249":{"id":"n1475293249","loc":[-85.6358079,41.9692721]},"n1475293256":{"id":"n1475293256","loc":[-85.6387369,41.9581583]},"n1475293259":{"id":"n1475293259","loc":[-85.6455882,41.9541138]},"n1475293266":{"id":"n1475293266","loc":[-85.6451008,41.9541821]},"n1819800253":{"id":"n1819800253","loc":[-85.6134286,41.9429692]},"n2114807558":{"id":"n2114807558","loc":[-85.6365609,41.963866],"tags":{"railway":"level_crossing"}},"n2189015728":{"id":"n2189015728","loc":[-85.6383956,41.9590576]},"n2189015838":{"id":"n2189015838","loc":[-85.6435144,41.9563705]},"n2189015842":{"id":"n2189015842","loc":[-85.6415782,41.9557035]},"n2189015855":{"id":"n2189015855","loc":[-85.6440829,41.9554577]},"n2199109849":{"id":"n2199109849","loc":[-85.6393434,41.9565591]},"n2199109851":{"id":"n2199109851","loc":[-85.6393208,41.9565002]},"n2199109857":{"id":"n2199109857","loc":[-85.6401986,41.955545]},"n2199109859":{"id":"n2199109859","loc":[-85.6402362,41.955587]},"n2199109861":{"id":"n2199109861","loc":[-85.6395958,41.9565675]},"n2199109863":{"id":"n2199109863","loc":[-85.639528,41.9566011]},"w209717053":{"id":"w209717053","tags":{"area":"yes","building":"yes"},"nodes":["n2199109829","n2199109831","n2199109833","n2199109835","n2199109829"]},"w17966415":{"id":"w17966415","tags":{"access":"private","highway":"service","name":"Manufacturing Way"},"nodes":["n185971642","n185977232","n185977233","n185949745","n185949748","n185977234"]},"w209717054":{"id":"w209717054","tags":{"area":"yes","building":"yes"},"nodes":["n2199109837","n2199109839","n2199109841","n2199109843","n2199109845","n2199109847","n2199109837"]},"w208627214":{"id":"w208627214","tags":{"highway":"service"},"nodes":["n185949755","n2189015728","n1475293233","n1475293256","n185952163","n185952161","n185952160","n185952158","n185949763","n1819848965","n1819848890","n185952156"]},"w17963817":{"id":"w17963817","tags":{"access":"private","highway":"service"},"nodes":["n185949765","n185953413","n185953417","n185953421","n185953423"]},"w34369809":{"id":"w34369809","tags":{"admin_level":"8","boundary":"administrative","landuse":"residential"},"nodes":["n394490395","n394490396","n394490397","n394490398","n394490399","n394490400","n394490401","n394490402","n394490403","n394490404","n394490405","n394490406","n394490407","n394490408","n394490409","n394490410","n394490411","n394490412","n394490413","n394490414","n394490415","n394490416","n394490417","n394490418","n394490419","n394490420","n394490421","n394490422","n394490423","n394490424","n394490425","n394490426","n394490427","n394490428","n1475293242","n1475293259","n1475293266","n394490429","n394490430","n394490431","n394490432","n394490433","n394490434","n394490435","n394490436","n394490437","n394490438","n394490439","n394490440","n394490441","n394490442","n394490443","n394490444","n394490445","n394490446","n1475293249","n394490447","n394490448","n394490449","n394490450","n394490451","n394490452","n394490453","n394490454","n394490455","n394490456","n394490457","n394490458","n394490459","n394490460","n394490461","n394490462","n2114807558","n394490463","n1475293226","n394490464","n394490465","n394490466","n394490467","n394490468","n394490469","n394490470","n394490471","n394490472","n394490473","n394490474","n394490475","n394490476","n394490477","n394490478","n394490479","n394490480","n394490481","n394490482","n394490483","n394490484","n394490485","n394490486","n394490487","n394490488","n394490489","n394490490","n394490491","n394490492","n394490493","n394490494","n394490495","n394490496","n394490497","n394490498","n394490499","n394490500","n394490501","n394490502","n394490503","n394490504","n394490505","n394490506","n394490507","n394490508","n394490509","n394490510","n394490511","n394490512","n394490513","n394490514","n394490515","n394490516","n394490517","n394490518","n394490519","n394490520","n394490521","n394490522","n394490523","n394490524","n394490525","n394490526","n394490527","n394490528","n394490529","n394490530","n394490531","n394490532","n394490533","n394490534","n394490535","n394490536","n394490537","n394490538","n394490539","n394490540","n394490542","n394490545","n394490546","n394490547","n394490548","n394490549","n394490550","n394490551","n394490552","n394490553","n394490554","n394490555","n394490556","n394490557","n394490558","n394490559","n394490560","n394490561","n394490562","n394490563","n394490564","n394490565","n394490566","n394490567","n394490568","n394490569","n394490570","n394490571","n1819800253","n394490572","n394490573","n394490574","n394490575","n394490576","n394490577","n394490578","n394490579","n394490580","n394490582","n394490583","n394490585","n394490586","n394490588","n394490589","n394490590","n394490592","n394490594","n394490595","n394490596","n394490598","n394490599","n394490601","n394490602","n394490604","n394490605","n394490607","n394490608","n394490609","n394490611","n394490612","n394490613","n394490614","n394490615","n394490616","n394490617","n394490618","n394490619","n394490620","n394490621","n394490622","n394490623","n394490624","n394490625","n394490626","n394490627","n394490628","n394490629","n394490630","n394490631","n394490632","n394490633","n394490634","n394490635","n394490636","n394490637","n394490638","n394490639","n394490699","n394490700","n394490701","n394490702","n394490703","n394490704","n394490705","n394490706","n394490707","n394490708","n394490709","n394490710","n394490711","n394490712","n394490713","n394490714","n394490715","n394490716","n394490717","n394490718","n394490719","n394490720","n394490721","n394490722","n394490723","n394490724","n394490725","n394490726","n394490727","n394490728","n394490729","n394490730","n394490731","n394490732","n394490733","n394490734","n394490735","n394490736","n394490737","n394490738","n394490739","n394490395"]},"w208627221":{"id":"w208627221","tags":{"amenity":"parking","area":"yes"},"nodes":["n2189015838","n2189015842","n2189015846","n2189015849","n2189015852","n2189015855","n2189015838"]},"w209717052":{"id":"w209717052","tags":{"area":"yes","building":"yes"},"nodes":["n2199109816","n2199109818","n2199109820","n2199109822","n2199109825","n2199109827","n2199109816"]},"w134151784":{"id":"w134151784","tags":{"bridge":"yes","highway":"residential","name":"W Hoffman St"},"nodes":["n185971648","n185971651"]},"w209717055":{"id":"w209717055","tags":{"area":"yes","landuse":"basin"},"nodes":["n2199109849","n2199109851","n2199109853","n2199109855","n2199109857","n2199109859","n2199109861","n2199109863","n2199109849"]},"w17967763":{"id":"w17967763","tags":{"highway":"residential","name":"Rock River Ave"},"nodes":["n1475293244","n185982166","n185975067","n185971637"]},"r134949":{"id":"r134949","tags":{"admin_level":"8","border_type":"city","boundary":"administrative","name":"Three Rivers","place":"city","type":"boundary"},"members":[{"id":"w34369809","type":"way","role":"outer"},{"id":"w34369821","type":"way","role":"outer"},{"id":"w34369822","type":"way","role":"outer"},{"id":"w34369823","type":"way","role":"outer"},{"id":"w34369824","type":"way","role":"outer"},{"id":"w34369825","type":"way","role":"outer"},{"id":"w34369826","type":"way","role":"outer"},{"id":"w34369810","type":"way","role":"inner"},{"id":"w34369811","type":"way","role":"inner"},{"id":"w34369812","type":"way","role":"inner"},{"id":"w34367079","type":"way","role":"inner"},{"id":"w34369814","type":"way","role":"inner"},{"id":"w34367080","type":"way","role":"inner"},{"id":"w34369815","type":"way","role":"inner"},{"id":"w34369820","type":"way","role":"inner"}]},"n1819848881":{"id":"n1819848881","loc":[-85.638562,41.9569965]},"n1819848947":{"id":"n1819848947","loc":[-85.6384348,41.9576565]},"n1819849044":{"id":"n1819849044","loc":[-85.6385749,41.9573345]},"n2114807547":{"id":"n2114807547","loc":[-85.6384626,41.9583756]},"n2114807564":{"id":"n2114807564","loc":[-85.638535,41.9581283]},"n2189015691":{"id":"n2189015691","loc":[-85.6435584,41.9565243]},"n2189015696":{"id":"n2189015696","loc":[-85.6435805,41.9566049]},"n2189015722":{"id":"n2189015722","loc":[-85.6435035,41.9567438]},"n2189015744":{"id":"n2189015744","loc":[-85.6437991,41.9569582]},"n2189015747":{"id":"n2189015747","loc":[-85.6433042,41.9567742]},"n2189015750":{"id":"n2189015750","loc":[-85.6433827,41.9566844]},"n2189015753":{"id":"n2189015753","loc":[-85.6430447,41.9565588]},"n2189015756":{"id":"n2189015756","loc":[-85.6431111,41.956451]},"n2189015759":{"id":"n2189015759","loc":[-85.6420247,41.956083]},"n2189015760":{"id":"n2189015760","loc":[-85.6419945,41.9561369]},"n2189015764":{"id":"n2189015764","loc":[-85.6413729,41.9558945]},"n2189015766":{"id":"n2189015766","loc":[-85.6412884,41.9560606]},"n2189015770":{"id":"n2189015770","loc":[-85.6411798,41.9560112]},"n2189015771":{"id":"n2189015771","loc":[-85.6410651,41.9562132]},"n2189015774":{"id":"n2189015774","loc":[-85.6409504,41.9561728]},"n2189015778":{"id":"n2189015778","loc":[-85.6407996,41.9564241]},"n2189015781":{"id":"n2189015781","loc":[-85.6406889,41.9563892]},"n2189015785":{"id":"n2189015785","loc":[-85.6404857,41.9567024]},"n2189015789":{"id":"n2189015789","loc":[-85.6406909,41.9567877]},"n2189015793":{"id":"n2189015793","loc":[-85.6405642,41.9570165]},"n2189015796":{"id":"n2189015796","loc":[-85.6415359,41.9573711]},"n2189015800":{"id":"n2189015800","loc":[-85.6411738,41.9579501]},"n2189015804":{"id":"n2189015804","loc":[-85.6411119,41.957921]},"n2189015808":{"id":"n2189015808","loc":[-85.6403186,41.9591751]},"n2189015909":{"id":"n2189015909","loc":[-85.6389293,41.9564636]},"n2189015926":{"id":"n2189015926","loc":[-85.6385431,41.9564617]},"n2189015929":{"id":"n2189015929","loc":[-85.6385457,41.9561823]},"n2189015932":{"id":"n2189015932","loc":[-85.6389319,41.9561843]},"n2199109865":{"id":"n2199109865","loc":[-85.6400768,41.956776]},"n2199109867":{"id":"n2199109867","loc":[-85.639902,41.9567153]},"n2199109869":{"id":"n2199109869","loc":[-85.640004,41.956553]},"n2199109871":{"id":"n2199109871","loc":[-85.6401788,41.9566137]},"n2199109873":{"id":"n2199109873","loc":[-85.6399316,41.9564506],"tags":{"man_made":"water_tower"}},"n2199109876":{"id":"n2199109876","loc":[-85.6397689,41.9572354]},"n2199109878":{"id":"n2199109878","loc":[-85.6399229,41.9569826]},"n2199109880":{"id":"n2199109880","loc":[-85.639706,41.9569095]},"n2199109882":{"id":"n2199109882","loc":[-85.639552,41.9571623]},"n2199109884":{"id":"n2199109884","loc":[-85.6391028,41.9569517]},"n2199109886":{"id":"n2199109886","loc":[-85.6392876,41.956646]},"n2199109888":{"id":"n2199109888","loc":[-85.639484,41.9567117]},"n2199109889":{"id":"n2199109889","loc":[-85.6394322,41.9567973]},"n2199109890":{"id":"n2199109890","loc":[-85.6393718,41.9567771]},"n2199109891":{"id":"n2199109891","loc":[-85.6392387,41.9569972]},"n1819848900":{"id":"n1819848900","loc":[-85.638281,41.9576578]},"n1819848978":{"id":"n1819848978","loc":[-85.6377186,41.9580867]},"n1819849039":{"id":"n1819849039","loc":[-85.6384217,41.9573405]},"n1819849050":{"id":"n1819849050","loc":[-85.6377011,41.9570042]},"n1819849088":{"id":"n1819849088","loc":[-85.6382879,41.9580817]},"n2114807549":{"id":"n2114807549","loc":[-85.6362551,41.96473]},"n2114807587":{"id":"n2114807587","loc":[-85.6368694,41.9629829]},"n2189015725":{"id":"n2189015725","loc":[-85.644156,41.9569753]},"n2189015741":{"id":"n2189015741","loc":[-85.6419825,41.9597632]},"w208627217":{"id":"w208627217","tags":{"area":"yes","building":"yes"},"nodes":["n2189015741","n2189015744","n2189015747","n2189015750","n2189015753","n2189015756","n2189015759","n2189015760","n2189015764","n2189015766","n2189015770","n2189015771","n2189015774","n2189015778","n2189015781","n2189015785","n2189015789","n2189015793","n2189015796","n2189015800","n2189015804","n2189015808","n2189015741"]},"w208627212":{"id":"w208627212","tags":{"highway":"service"},"nodes":["n2189015691","n2189015696","n2189015722","n2189015725"]},"w209717057":{"id":"w209717057","tags":{"area":"yes","building":"yes"},"nodes":["n2199109876","n2199109878","n2199109880","n2199109882","n2199109876"]},"w209717056":{"id":"w209717056","tags":{"area":"yes","building":"yes"},"nodes":["n2199109865","n2199109867","n2199109869","n2199109871","n2199109865"]},"w208627231":{"id":"w208627231","tags":{"area":"yes","building":"yes"},"nodes":["n2189015909","n2189015926","n2189015929","n2189015932","n2189015909"]},"w170848326":{"id":"w170848326","tags":{"building":"yes"},"nodes":["n1819848881","n1819849050","n1819848978","n1819849088","n1819848900","n1819848947","n1819849039","n1819849044","n1819848881"]},"w17963182":{"id":"w17963182","tags":{"highway":"service"},"nodes":["n185949763","n185949765","n2189015691","n185949745"]},"w201484340":{"id":"w201484340","tags":{"railway":"rail","service":"siding"},"nodes":["n2114807565","n2114807564","n2114807547","n2114807587","n2114807558","n2114807549","n2114807593"]},"w209717058":{"id":"w209717058","tags":{"area":"yes","building":"yes"},"nodes":["n2199109884","n2199109886","n2199109888","n2199109889","n2199109890","n2199109891","n2199109884"]},"n185954650":{"id":"n185954650","loc":[-85.627331,41.957439]},"n185966949":{"id":"n185966949","loc":[-85.626868,41.957314]},"n185989335":{"id":"n185989335","loc":[-85.62529,41.958568]},"n185989337":{"id":"n185989337","loc":[-85.624962,41.958453]},"n185989339":{"id":"n185989339","loc":[-85.624832,41.958399]},"n185989340":{"id":"n185989340","loc":[-85.624707,41.958325]},"n185989342":{"id":"n185989342","loc":[-85.624636,41.958251]},"n185989345":{"id":"n185989345","loc":[-85.624578,41.95818]},"n185989347":{"id":"n185989347","loc":[-85.624533,41.958099]},"n185989349":{"id":"n185989349","loc":[-85.624507,41.957985]},"n185989351":{"id":"n185989351","loc":[-85.624495,41.957807]},"n185989353":{"id":"n185989353","loc":[-85.624514,41.957663]},"n185989354":{"id":"n185989354","loc":[-85.624577,41.957593]},"n185989356":{"id":"n185989356","loc":[-85.624685,41.95754]},"n185989357":{"id":"n185989357","loc":[-85.624802,41.957523]},"n185989359":{"id":"n185989359","loc":[-85.624996,41.957524]},"n185989361":{"id":"n185989361","loc":[-85.625409,41.957515]},"n185989364":{"id":"n185989364","loc":[-85.625634,41.957496]},"n185989367":{"id":"n185989367","loc":[-85.625832,41.957453]},"n185989368":{"id":"n185989368","loc":[-85.626044,41.957394]},"n354031352":{"id":"n354031352","loc":[-85.6252778,41.9586111],"tags":{"amenity":"place_of_worship","denomination":"baptist","name":"First Baptist Church","religion":"christian"}},"n2199109892":{"id":"n2199109892","loc":[-85.6261578,41.9589963]},"n2199109893":{"id":"n2199109893","loc":[-85.6263191,41.9586865]},"n2199109894":{"id":"n2199109894","loc":[-85.6261186,41.9586288]},"n2199109895":{"id":"n2199109895","loc":[-85.6260644,41.9587329]},"n2199109896":{"id":"n2199109896","loc":[-85.6261547,41.9587589]},"n2199109898":{"id":"n2199109898","loc":[-85.6260476,41.9589646]},"n185966951":{"id":"n185966951","loc":[-85.628404,41.957438]},"w17965351":{"id":"w17965351","tags":{"highway":"residential","name":"Flower Street"},"nodes":["n185966948","n185966949","n185954650","n185966951","n185966953","n185966955","n185966957"]},"w17967809":{"id":"w17967809","tags":{"highway":"residential","name":"Azaleamum Drive"},"nodes":["n185982197","n185989335","n185989337","n185989339","n185989340","n185989342","n185989345","n185989347","n185989349","n185989351","n185989353","n185989354","n185989356","n185989357","n185989359","n185989361","n185989364","n185989367","n185989368","n185982196"]},"w209717059":{"id":"w209717059","tags":{"area":"yes","building":"yes"},"nodes":["n2199109892","n2199109893","n2199109894","n2199109895","n2199109896","n2199109898","n2199109892"]},"n185961390":{"id":"n185961390","loc":[-85.63137,41.959033]},"n185961393":{"id":"n185961393","loc":[-85.634315,41.959017]},"w17966214":{"id":"w17966214","tags":{"highway":"residential","name":"East Adams Street"},"nodes":["n185975351","n185967434","n185968108"]},"w17964793":{"id":"w17964793","tags":{"highway":"residential","name":"Morris Ave"},"nodes":["n185961389","n185961390","n185961391","n185961393","n185961396"]},"n185952166":{"id":"n185952166","loc":[-85.638174,41.95831]},"n2114807552":{"id":"n2114807552","loc":[-85.6383526,41.9593788]},"n2114807591":{"id":"n2114807591","loc":[-85.6383741,41.9593968]},"n2189015731":{"id":"n2189015731","loc":[-85.6368404,41.9592785]},"n2189015734":{"id":"n2189015734","loc":[-85.6368404,41.9585918]},"n2189015737":{"id":"n2189015737","loc":[-85.6376009,41.9585918]},"n2189015738":{"id":"n2189015738","loc":[-85.6376009,41.9592785]},"n2189015897":{"id":"n2189015897","loc":[-85.6376839,41.9566137]},"n2189015900":{"id":"n2189015900","loc":[-85.6376831,41.9564865]},"n2189015903":{"id":"n2189015903","loc":[-85.6381161,41.9564851]},"n2189015906":{"id":"n2189015906","loc":[-85.6381168,41.9566122]},"n2189015937":{"id":"n2189015937","loc":[-85.6364789,41.9590634]},"n2189015940":{"id":"n2189015940","loc":[-85.6361137,41.9590672]},"n2189015943":{"id":"n2189015943","loc":[-85.6361169,41.9594033]},"n2189015945":{"id":"n2189015945","loc":[-85.6363456,41.9594021]},"n2189015952":{"id":"n2189015952","loc":[-85.636112,41.958892]},"n2189015955":{"id":"n2189015955","loc":[-85.6364757,41.9588894]},"n2189015957":{"id":"n2189015957","loc":[-85.6364729,41.9586747]},"n2189015958":{"id":"n2189015958","loc":[-85.6361103,41.9586765]},"n2189015959":{"id":"n2189015959","loc":[-85.6364719,41.9585562]},"n2189015960":{"id":"n2189015960","loc":[-85.6361093,41.958558]},"n2189015961":{"id":"n2189015961","loc":[-85.6355494,41.9586403]},"n2189015962":{"id":"n2189015962","loc":[-85.635549,41.9584711]},"n2189015963":{"id":"n2189015963","loc":[-85.6351831,41.9584715]},"n2189015964":{"id":"n2189015964","loc":[-85.6351834,41.9586408]},"n2189015966":{"id":"n2189015966","loc":[-85.6359579,41.9586359]},"n2189015968":{"id":"n2189015968","loc":[-85.6359561,41.9585465]},"n2189015971":{"id":"n2189015971","loc":[-85.6355476,41.9585509]},"n2189015974":{"id":"n2189015974","loc":[-85.6359516,41.9592934]},"n2189015977":{"id":"n2189015977","loc":[-85.635949,41.9586697]},"n2189015980":{"id":"n2189015980","loc":[-85.6351329,41.9586716]},"n2189015983":{"id":"n2189015983","loc":[-85.6351318,41.9583949]},"n2189015986":{"id":"n2189015986","loc":[-85.6349148,41.9583954]},"n2189015989":{"id":"n2189015989","loc":[-85.6349186,41.9592958]},"n2189015995":{"id":"n2189015995","loc":[-85.6360173,41.9593286]},"n2189015998":{"id":"n2189015998","loc":[-85.6360278,41.9583079]},"n2114807550":{"id":"n2114807550","loc":[-85.6383392,41.9595404]},"n2114807551":{"id":"n2114807551","loc":[-85.6375855,41.9616107]},"n2114807559":{"id":"n2114807559","loc":[-85.6373978,41.9621273]},"n2114807562":{"id":"n2114807562","loc":[-85.6373361,41.9622609]},"n2114807563":{"id":"n2114807563","loc":[-85.6376472,41.9613953]},"n2114807574":{"id":"n2114807574","loc":[-85.636974,41.9627695]},"n2114807589":{"id":"n2114807589","loc":[-85.6383017,41.9595005]},"n2114807592":{"id":"n2114807592","loc":[-85.6377169,41.9613494]},"n2114807595":{"id":"n2114807595","loc":[-85.6371081,41.962574]},"n2189015934":{"id":"n2189015934","loc":[-85.6364855,41.9595098]},"n2189015949":{"id":"n2189015949","loc":[-85.6363466,41.9595105]},"w208627244":{"id":"w208627244","tags":{"highway":"service"},"nodes":["n2189015992","n2189015995","n2189015998"]},"w208627240":{"id":"w208627240","tags":{"area":"yes","building":"yes"},"nodes":["n2189015961","n2189015971","n2189015962","n2189015963","n2189015964","n2189015961"]},"w17967437":{"id":"w17967437","tags":{"highway":"residential","name":"Lyman St"},"nodes":["n185964361","n185984024"]},"w208627237":{"id":"w208627237","tags":{"area":"yes","building":"yes"},"nodes":["n2189015955","n2189015957","n2189015958","n2189015952","n2189015955"]},"w17967465":{"id":"w17967465","tags":{"highway":"residential","name":"W Adams St"},"nodes":["n185978394","n185984022","n185964360"]},"w208627228":{"id":"w208627228","tags":{"area":"yes","building":"yes"},"nodes":["n2189015897","n2189015900","n2189015903","n2189015906","n2189015897"]},"w201484351":{"id":"w201484351","tags":{"railway":"rail","service":"siding"},"nodes":["n2114807587","n2114807574","n2114807595","n2114807562","n2114807559","n2114807551","n2114807563","n2114807589","n2114807552"]},"w208627239":{"id":"w208627239","tags":{"area":"yes","building":"yes"},"nodes":["n2189015957","n2189015959","n2189015960","n2189015958","n2189015957"]},"w208627233":{"id":"w208627233","tags":{"area":"yes","building":"yes"},"nodes":["n2189015934","n2189015937","n2189015940","n2189015943","n2189015945","n2189015949","n2189015934"]},"w208627241":{"id":"w208627241","tags":{"area":"yes","building":"yes"},"nodes":["n2189015961","n2189015966","n2189015968","n2189015971","n2189015961"]},"w17967970":{"id":"w17967970","tags":{"highway":"residential","name":"Adams St"},"nodes":["n185975351","n185978394"]},"w208627235":{"id":"w208627235","tags":{"area":"yes","building":"yes"},"nodes":["n2189015940","n2189015952","n2189015955","n2189015937","n2189015940"]},"w17965468":{"id":"w17965468","tags":{"highway":"residential","name":"Armstrong Blvd"},"nodes":["n185967917","n2189015998","n185967918","n185964362","n185952166"]},"w201484346":{"id":"w201484346","tags":{"railway":"rail","service":"siding"},"nodes":["n2114807551","n2114807592","n2114807550","n2114807591"]},"w208627242":{"id":"w208627242","tags":{"amenity":"parking","area":"yes"},"nodes":["n2189015974","n2189015977","n2189015980","n2189015983","n2189015986","n2189015989","n2189015974"]},"w208627216":{"id":"w208627216","tags":{"area":"yes","building":"yes"},"nodes":["n2189015731","n2189015734","n2189015737","n2189015738","n2189015731"]},"n185984309":{"id":"n185984309","loc":[-85.631421,41.961494]},"n185987987":{"id":"n185987987","loc":[-85.631456,41.960673]},"n185965397":{"id":"n185965397","loc":[-85.634603,41.959838]},"w17965196":{"id":"w17965196","tags":{"highway":"residential","name":"Burke Ave"},"nodes":["n185965395","n185965397","n185965399"]},"w17967215":{"id":"w17967215","tags":{"highway":"residential","name":"Kellogg Ave"},"nodes":["n185968114","n185984309","n185967440","n185978402"]},"w17967597":{"id":"w17967597","tags":{"highway":"residential","name":"Barnard Ave"},"nodes":["n185968112","n185987987","n185967438","n185978399"]},"n394490857":{"id":"n394490857","loc":[-85.633952,41.960664]},"n394490858":{"id":"n394490858","loc":[-85.633938,41.960227]},"n394490859":{"id":"n394490859","loc":[-85.634794,41.960212]},"n394490860":{"id":"n394490860","loc":[-85.634815,41.960662]},"n394490861":{"id":"n394490861","loc":[-85.634103,41.961268]},"n394490862":{"id":"n394490862","loc":[-85.634103,41.961001]},"n394490863":{"id":"n394490863","loc":[-85.634504,41.961003]},"n394490864":{"id":"n394490864","loc":[-85.634561,41.961269]},"n1057629869":{"id":"n1057629869","loc":[-85.6382599,41.9612134]},"n1057629937":{"id":"n1057629937","loc":[-85.6380035,41.9616137]},"n2189016014":{"id":"n2189016014","loc":[-85.6360365,41.9626496]},"n2189016017":{"id":"n2189016017","loc":[-85.6360374,41.9623228]},"n2189016020":{"id":"n2189016020","loc":[-85.6367557,41.9623239]},"n2189016022":{"id":"n2189016022","loc":[-85.6367566,41.9619919]},"n2189016025":{"id":"n2189016025","loc":[-85.6351794,41.9619893]},"n2189016028":{"id":"n2189016028","loc":[-85.6351788,41.9622011]},"n2189016031":{"id":"n2189016031","loc":[-85.6350855,41.9622009]},"n2189016034":{"id":"n2189016034","loc":[-85.6350845,41.962527]},"n2189016037":{"id":"n2189016037","loc":[-85.6352732,41.9625273]},"n2189016039":{"id":"n2189016039","loc":[-85.6352738,41.9623178]},"n2189016042":{"id":"n2189016042","loc":[-85.6357712,41.9623186]},"n2189016044":{"id":"n2189016044","loc":[-85.6357702,41.9626492]},"n1057629880":{"id":"n1057629880","loc":[-85.638817,41.9619017]},"n1057629923":{"id":"n1057629923","loc":[-85.6390733,41.9615014]},"w91092312":{"id":"w91092312","tags":{"power":"station"},"nodes":["n1057629923","n1057629869","n1057629937","n1057629880","n1057629923"]},"w34369826":{"id":"w34369826","tags":{"admin_level":"8","boundary":"administrative"},"nodes":["n394490861","n394490862","n394490863","n394490864","n394490861"]},"w34369825":{"id":"w34369825","tags":{"admin_level":"8","boundary":"administrative"},"nodes":["n394490857","n394490858","n394490859","n394490860","n394490857"]},"w208627248":{"id":"w208627248","tags":{"area":"yes","building":"yes"},"nodes":["n2189016014","n2189016017","n2189016020","n2189016022","n2189016025","n2189016028","n2189016031","n2189016034","n2189016037","n2189016039","n2189016042","n2189016044","n2189016014"]},"n394490766":{"id":"n394490766","loc":[-85.616777,41.955642]},"n394490768":{"id":"n394490768","loc":[-85.617239,41.955644]},"n394490792":{"id":"n394490792","loc":[-85.619034,41.95543]},"n185972055":{"id":"n185972055","loc":[-85.6185905,41.9568211]},"n185972057":{"id":"n185972057","loc":[-85.6186688,41.9570086]},"n185972059":{"id":"n185972059","loc":[-85.6186924,41.9581453]},"n185972060":{"id":"n185972060","loc":[-85.6187082,41.9588211],"tags":{"highway":"turning_circle"}},"n1819790724":{"id":"n1819790724","loc":[-85.6182155,41.9555703]},"n1819790735":{"id":"n1819790735","loc":[-85.6184059,41.9566188]},"n1819790799":{"id":"n1819790799","loc":[-85.6182372,41.9563771]},"n1819790896":{"id":"n1819790896","loc":[-85.6181431,41.9557227]},"n185971405":{"id":"n185971405","loc":[-85.6186766,41.9577468]},"n185971565":{"id":"n185971565","loc":[-85.6181613,41.9560879]},"n185967985":{"id":"n185967985","loc":[-85.6186798,41.9585791]},"n185955753":{"id":"n185955753","loc":[-85.620773,41.9555854]},"n185955755":{"id":"n185955755","loc":[-85.6212652,41.9559891]},"n185955748":{"id":"n185955748","loc":[-85.620722,41.954858]},"n185955751":{"id":"n185955751","loc":[-85.6206912,41.955367]},"n185967987":{"id":"n185967987","loc":[-85.6159351,41.9585809]},"n185971407":{"id":"n185971407","loc":[-85.6159142,41.9577578]},"n185971570":{"id":"n185971570","loc":[-85.6162248,41.95603]},"n185971572":{"id":"n185971572","loc":[-85.6160402,41.9560749]},"n185971574":{"id":"n185971574","loc":[-85.61593,41.956201]},"n185981301":{"id":"n185981301","loc":[-85.6158973,41.9581601]},"n394490762":{"id":"n394490762","loc":[-85.617193,41.954706]},"n394490764":{"id":"n394490764","loc":[-85.616773,41.954737]},"n394490787":{"id":"n394490787","loc":[-85.618972,41.954737]},"n394490790":{"id":"n394490790","loc":[-85.619046,41.954929]},"n394490794":{"id":"n394490794","loc":[-85.619922,41.955296]},"n394490796":{"id":"n394490796","loc":[-85.61991,41.95501]},"n394490798":{"id":"n394490798","loc":[-85.619974,41.954751]},"n1819790677":{"id":"n1819790677","loc":[-85.6187031,41.9550522]},"n1819790787":{"id":"n1819790787","loc":[-85.6186436,41.9552022]},"n1819790828":{"id":"n1819790828","loc":[-85.6185127,41.9553393]},"w17966857":{"id":"w17966857","tags":{"access":"private","highway":"service","name":"Sable River Rd"},"nodes":["n185972059","n185981301"]},"w34369814":{"id":"w34369814","tags":{"admin_level":"8","boundary":"administrative"},"nodes":["n394490787","n394490790","n394490792","n394490794","n394490796","n394490798","n394490787"]},"w17964176":{"id":"w17964176","tags":{"highway":"residential"},"nodes":["n185955747","n185955748","n185955751","n185955753","n185955755"]},"w17965838":{"id":"w17965838","tags":{"access":"private","highway":"service","name":"Pine River Rd"},"nodes":["n185971405","n185971407"]},"w17965476":{"id":"w17965476","tags":{"access":"private","highway":"service","name":"Raisin River Rd"},"nodes":["n185967985","n185967987"]},"w17965913":{"id":"w17965913","tags":{"access":"private","highway":"service","name":"Shiawassee River Rd"},"nodes":["n185972054","n1819790677","n1819790787","n1819790828","n1819790724","n1819790896","n185971565","n1819790799","n1819790735","n185972055","n185972057","n185971405","n185972059","n185967985","n185972060"]},"w34369811":{"id":"w34369811","tags":{"admin_level":"8","boundary":"administrative"},"nodes":["n394490762","n394490764","n394490766","n394490768","n394490762"]},"w17965854":{"id":"w17965854","tags":{"access":"private","highway":"service","name":"Sturgeon River Rd"},"nodes":["n185971565","n185971570","n185971572","n185971574"]},"n2139795769":{"id":"n2139795769","loc":[-85.6250804,41.9608796]},"n2139795770":{"id":"n2139795770","loc":[-85.6250315,41.9613684]},"n2139795771":{"id":"n2139795771","loc":[-85.6249671,41.9614362]},"n2139795772":{"id":"n2139795772","loc":[-85.6249698,41.961522]},"n2139795773":{"id":"n2139795773","loc":[-85.6250798,41.9615838]},"n2139795774":{"id":"n2139795774","loc":[-85.6252273,41.9615639]},"n2139795775":{"id":"n2139795775","loc":[-85.6252863,41.9614622]},"n2139795776":{"id":"n2139795776","loc":[-85.6252273,41.9613764]},"n2139795777":{"id":"n2139795777","loc":[-85.6251227,41.9613525]},"n2139795778":{"id":"n2139795778","loc":[-85.6249564,41.9612527]},"n2139795779":{"id":"n2139795779","loc":[-85.6249846,41.9610254]},"n2139795780":{"id":"n2139795780","loc":[-85.6266725,41.9599647]},"n2139795781":{"id":"n2139795781","loc":[-85.6259162,41.9599711]},"n2139795782":{"id":"n2139795782","loc":[-85.6257185,41.960019]},"n2139795783":{"id":"n2139795783","loc":[-85.6255509,41.9601213]},"n185963539":{"id":"n185963539","loc":[-85.615718,41.983893]},"n185964418":{"id":"n185964418","loc":[-85.616626,42.049512]},"n185966614":{"id":"n185966614","loc":[-85.615514,41.976603]},"n185966635":{"id":"n185966635","loc":[-85.616118,42.013017]},"n185969040":{"id":"n185969040","loc":[-85.615632,41.972357]},"n185969070":{"id":"n185969070","loc":[-85.619145,41.967648]},"n185972156":{"id":"n185972156","loc":[-85.621894,41.963956]},"n185972157":{"id":"n185972157","loc":[-85.621806,41.964077]},"n185972158":{"id":"n185972158","loc":[-85.620848,41.965341]},"n185972159":{"id":"n185972159","loc":[-85.620684,41.965558]},"n185972160":{"id":"n185972160","loc":[-85.620621,41.965658]},"n185972161":{"id":"n185972161","loc":[-85.617844,41.969359]},"n185972162":{"id":"n185972162","loc":[-85.616843,41.97068]},"n185972164":{"id":"n185972164","loc":[-85.616714,41.970839]},"n185972166":{"id":"n185972166","loc":[-85.615879,41.971969]},"n185972168":{"id":"n185972168","loc":[-85.615748,41.972159]},"n185972170":{"id":"n185972170","loc":[-85.615589,41.972502]},"n185972172":{"id":"n185972172","loc":[-85.615542,41.972733]},"n185972175":{"id":"n185972175","loc":[-85.615524,41.972947]},"n185972177":{"id":"n185972177","loc":[-85.615512,41.973715]},"n185972179":{"id":"n185972179","loc":[-85.615513,41.976496]},"n185972180":{"id":"n185972180","loc":[-85.615538,41.977246]},"n185972181":{"id":"n185972181","loc":[-85.61558,41.982139]},"n185972184":{"id":"n185972184","loc":[-85.61557,41.983317]},"n185972186":{"id":"n185972186","loc":[-85.615591,41.983463]},"n185972188":{"id":"n185972188","loc":[-85.615763,41.984146]},"n185972190":{"id":"n185972190","loc":[-85.615814,41.98435]},"n185972192":{"id":"n185972192","loc":[-85.615965,41.998453]},"n185972194":{"id":"n185972194","loc":[-85.615982,42.001237]},"n185972195":{"id":"n185972195","loc":[-85.616055,42.00555]},"n185972197":{"id":"n185972197","loc":[-85.616134,42.014887]},"n185972199":{"id":"n185972199","loc":[-85.616177,42.018465]},"n185972201":{"id":"n185972201","loc":[-85.616298,42.027627]},"n185972203":{"id":"n185972203","loc":[-85.616513,42.042212]},"w203968015":{"id":"w203968015","tags":{"highway":"residential"},"nodes":["n2139795768","n2139795769"]},"w17965932":{"id":"w17965932","tags":{"highway":"residential","name":"Buckhorn Road","name_1":"County Highway 122"},"nodes":["n185972155","n185972156","n185972157","n185972158","n185972159","n185972160","n185969070","n185972161","n185972162","n185972164","n185972166","n185972168","n185969040","n185972170","n185972172","n185972175","n185972177","n185972179","n185966614","n185972180","n185972181","n185972184","n185972186","n185963539","n185972188","n185972190","n185972192","n185972194","n185972195","n185966635","n185972197","n185972199","n185972201","n185972203","n185964418"]},"w203968016":{"id":"w203968016","tags":{"highway":"residential","name":"New Jersey Court"},"nodes":["n2139795770","n2139795771","n2139795772","n2139795773","n2139795774","n2139795775","n2139795776","n2139795777","n2139795770","n2139795778","n2139795779","n2139795769"]},"w203968017":{"id":"w203968017","tags":{"highway":"residential","name":"Oklahoma Drive"},"nodes":["n2139795780","n2139795781","n2139795782","n2139795783","n2139795769"]},"n1819790528":{"id":"n1819790528","loc":[-85.6184827,41.960025]},"n1819790530":{"id":"n1819790530","loc":[-85.6168626,41.9605834]},"n1819790534":{"id":"n1819790534","loc":[-85.6197379,41.9617163]},"n1819790541":{"id":"n1819790541","loc":[-85.6198881,41.9620833]},"n1819790543":{"id":"n1819790543","loc":[-85.619695,41.9619397]},"n1819790547":{"id":"n1819790547","loc":[-85.6190298,41.9609504]},"n1819790555":{"id":"n1819790555","loc":[-85.6180471,41.9609788]},"n1819790559":{"id":"n1819790559","loc":[-85.6203817,41.9605436]},"n1819790583":{"id":"n1819790583","loc":[-85.6201564,41.9603282]},"n1819790590":{"id":"n1819790590","loc":[-85.617045,41.9598894]},"n1819790609":{"id":"n1819790609","loc":[-85.6177638,41.9598495]},"n1819790618":{"id":"n1819790618","loc":[-85.6195234,41.9610143]},"n1819790642":{"id":"n1819790642","loc":[-85.6181179,41.9627933]},"n1819790659":{"id":"n1819790659","loc":[-85.6174634,41.962897]},"n1819790665":{"id":"n1819790665","loc":[-85.6170343,41.9630885]},"n1819790674":{"id":"n1819790674","loc":[-85.6194697,41.9601925]},"n1819790685":{"id":"n1819790685","loc":[-85.6207722,41.9610665]},"n1819790687":{"id":"n1819790687","loc":[-85.6202315,41.9622109]},"n1819790697":{"id":"n1819790697","loc":[-85.6184505,41.9624662]},"n1819790726":{"id":"n1819790726","loc":[-85.6178926,41.9628492]},"n1819790738":{"id":"n1819790738","loc":[-85.6173347,41.9598016]},"n1819790762":{"id":"n1819790762","loc":[-85.6186221,41.9609105]},"n1819790774":{"id":"n1819790774","loc":[-85.6175922,41.9608308]},"n1819790781":{"id":"n1819790781","loc":[-85.6167768,41.9633198]},"n1819790796":{"id":"n1819790796","loc":[-85.619856,41.961461]},"n1819790811":{"id":"n1819790811","loc":[-85.6208215,41.9620195]},"n1819790833":{"id":"n1819790833","loc":[-85.618311,41.9612536]},"n1819790854":{"id":"n1819790854","loc":[-85.6183646,41.9626417]},"n1819790863":{"id":"n1819790863","loc":[-85.6204997,41.9608547]},"n1819790867":{"id":"n1819790867","loc":[-85.6184934,41.9621391]},"n1819790877":{"id":"n1819790877","loc":[-85.6206928,41.9621152]},"n1819790881":{"id":"n1819790881","loc":[-85.6170879,41.960735]},"n1819790891":{"id":"n1819790891","loc":[-85.6168304,41.9601207]},"n1819790898":{"id":"n1819790898","loc":[-85.619813,41.9612297]},"n1819790909":{"id":"n1819790909","loc":[-85.6167982,41.960376]},"n1819790912":{"id":"n1819790912","loc":[-85.6205855,41.9610462]},"n1819790544":{"id":"n1819790544","loc":[-85.612968,41.9707781]},"n1819790549":{"id":"n1819790549","loc":[-85.614395,41.9697172]},"n1819790552":{"id":"n1819790552","loc":[-85.6180535,41.9655536]},"n1819790554":{"id":"n1819790554","loc":[-85.6111227,41.9703713]},"n1819790560":{"id":"n1819790560","loc":[-85.6112729,41.9701958]},"n1819790563":{"id":"n1819790563","loc":[-85.6137512,41.9689917]},"n1819790564":{"id":"n1819790564","loc":[-85.6181072,41.9659205]},"n1819790595":{"id":"n1819790595","loc":[-85.6170021,41.9666863]},"n1819790605":{"id":"n1819790605","loc":[-85.6168948,41.9644527]},"n1819790606":{"id":"n1819790606","loc":[-85.6128071,41.9701081]},"n1819790607":{"id":"n1819790607","loc":[-85.6129251,41.9704032]},"n1819790612":{"id":"n1819790612","loc":[-85.6177638,41.9663912]},"n1819790615":{"id":"n1819790615","loc":[-85.6152533,41.9670373]},"n1819790622":{"id":"n1819790622","loc":[-85.6146739,41.9673804]},"n1819790623":{"id":"n1819790623","loc":[-85.6180428,41.9661838]},"n1819790625":{"id":"n1819790625","loc":[-85.6172918,41.9646202]},"n1819790645":{"id":"n1819790645","loc":[-85.6178067,41.965043]},"n1819790647":{"id":"n1819790647","loc":[-85.6143306,41.9712488]},"n1819790649":{"id":"n1819790649","loc":[-85.6147383,41.9707702]},"n1819790654":{"id":"n1819790654","loc":[-85.6157361,41.9668459]},"n1819790657":{"id":"n1819790657","loc":[-85.6145666,41.9710733]},"n1819790668":{"id":"n1819790668","loc":[-85.6166909,41.9642692]},"n1819790671":{"id":"n1819790671","loc":[-85.6141482,41.9696538]},"n1819790679":{"id":"n1819790679","loc":[-85.6148349,41.9705388]},"n1819790686":{"id":"n1819790686","loc":[-85.6139551,41.9695501]},"n1819790696":{"id":"n1819790696","loc":[-85.6119703,41.9699087]},"n1819790704":{"id":"n1819790704","loc":[-85.6140731,41.9684174]},"n1819790706":{"id":"n1819790706","loc":[-85.6124745,41.9699246]},"n1819790718":{"id":"n1819790718","loc":[-85.6165407,41.9636868]},"n1819790720":{"id":"n1819790720","loc":[-85.61388,41.9687365]},"n1819790731":{"id":"n1819790731","loc":[-85.6165193,41.9639421]},"n1819790739":{"id":"n1819790739","loc":[-85.6146739,41.9699964]},"n1819790753":{"id":"n1819790753","loc":[-85.6173883,41.9665747]},"n1819790760":{"id":"n1819790760","loc":[-85.6133221,41.9712089]},"n1819790767":{"id":"n1819790767","loc":[-85.6116698,41.9699246]},"n1819790779":{"id":"n1819790779","loc":[-85.6130753,41.9710573]},"n1819790791":{"id":"n1819790791","loc":[-85.6137083,41.9692869]},"n1819790795":{"id":"n1819790795","loc":[-85.6141482,41.9679627]},"n1819790798":{"id":"n1819790798","loc":[-85.6137727,41.9694305]},"n1819790836":{"id":"n1819790836","loc":[-85.6143842,41.9676037]},"n1819790915":{"id":"n1819790915","loc":[-85.6148456,41.9702756]},"n1819790926":{"id":"n1819790926","loc":[-85.6138371,41.9713525]},"n1819790927":{"id":"n1819790927","loc":[-85.6141053,41.9713525]},"n1819790931":{"id":"n1819790931","loc":[-85.6162832,41.966814]},"n1821014625":{"id":"n1821014625","loc":[-85.5960611,41.9808498]},"n1821014627":{"id":"n1821014627","loc":[-85.5565843,42.010982]},"n1821014629":{"id":"n1821014629","loc":[-85.5971541,41.9805808]},"n1821014632":{"id":"n1821014632","loc":[-85.6061837,41.9725907]},"n1821014633":{"id":"n1821014633","loc":[-85.5247773,42.025766]},"n1821014635":{"id":"n1821014635","loc":[-85.5908938,41.9902384]},"n1821014636":{"id":"n1821014636","loc":[-85.5917682,41.9860637]},"n1821014637":{"id":"n1821014637","loc":[-85.5456556,42.0166797]},"n1821014638":{"id":"n1821014638","loc":[-85.5795749,42.0032352]},"n1821014639":{"id":"n1821014639","loc":[-85.6103988,41.9723456]},"n1821014642":{"id":"n1821014642","loc":[-85.5818816,42.0022466]},"n1821014643":{"id":"n1821014643","loc":[-85.5570604,42.0091586]},"n1821014644":{"id":"n1821014644","loc":[-85.5952886,41.9803792]},"n1821014645":{"id":"n1821014645","loc":[-85.5780366,42.0040343]},"n1821014646":{"id":"n1821014646","loc":[-85.6050505,41.9751971]},"n1821014647":{"id":"n1821014647","loc":[-85.5854435,41.9946162]},"n1821014648":{"id":"n1821014648","loc":[-85.5452278,42.0168768]},"n1821014649":{"id":"n1821014649","loc":[-85.6023254,41.9780166]},"n1821014651":{"id":"n1821014651","loc":[-85.5761899,42.0046783]},"n1821014653":{"id":"n1821014653","loc":[-85.5897351,41.9876707]},"n1821014657":{"id":"n1821014657","loc":[-85.5963601,41.9808998]},"n1821014658":{"id":"n1821014658","loc":[-85.5892952,41.9951983]},"n1821014660":{"id":"n1821014660","loc":[-85.5778328,42.0037194]},"n1821014661":{"id":"n1821014661","loc":[-85.5541475,42.0125705]},"n1821014663":{"id":"n1821014663","loc":[-85.5914047,41.9856469]},"n1821014664":{"id":"n1821014664","loc":[-85.6101681,41.9727723]},"n1821014665":{"id":"n1821014665","loc":[-85.5910172,41.9854696]},"n1821014666":{"id":"n1821014666","loc":[-85.5398688,42.0187699]},"n1821014667":{"id":"n1821014667","loc":[-85.5218752,42.0282884]},"n1821014668":{"id":"n1821014668","loc":[-85.5159582,42.0329384]},"n1821014669":{"id":"n1821014669","loc":[-85.5898102,41.9847319]},"n1821014670":{"id":"n1821014670","loc":[-85.5734809,42.0066235]},"n1821014671":{"id":"n1821014671","loc":[-85.5922939,41.980852]},"n1821014672":{"id":"n1821014672","loc":[-85.6023629,41.9781163]},"n1821014674":{"id":"n1821014674","loc":[-85.5409953,42.0191724]},"n1821014676":{"id":"n1821014676","loc":[-85.584435,41.9949909]},"n1821014677":{"id":"n1821014677","loc":[-85.5972399,41.9783835]},"n1821014678":{"id":"n1821014678","loc":[-85.5616738,42.0071337]},"n1821014681":{"id":"n1821014681","loc":[-85.5202994,42.0310755]},"n1821014682":{"id":"n1821014682","loc":[-85.5915912,41.9857767]},"n1821014684":{"id":"n1821014684","loc":[-85.6022288,41.977897]},"n1821014687":{"id":"n1821014687","loc":[-85.5933024,41.9846362]},"n1821014688":{"id":"n1821014688","loc":[-85.5846871,41.9956169]},"n1821014689":{"id":"n1821014689","loc":[-85.5898209,41.99037]},"n1821014691":{"id":"n1821014691","loc":[-85.5448939,42.0149261]},"n1821014692":{"id":"n1821014692","loc":[-85.5977763,41.9786348]},"n1821014694":{"id":"n1821014694","loc":[-85.5767706,42.0034523]},"n1821014695":{"id":"n1821014695","loc":[-85.6103559,41.9726766]},"n1821014697":{"id":"n1821014697","loc":[-85.5922134,41.9809876]},"n1821014698":{"id":"n1821014698","loc":[-85.5935277,41.9831728]},"n1821014700":{"id":"n1821014700","loc":[-85.5674674,42.0078273]},"n1821014703":{"id":"n1821014703","loc":[-85.6021,41.9778053]},"n1821014704":{"id":"n1821014704","loc":[-85.5756763,42.0053737]},"n1821014705":{"id":"n1821014705","loc":[-85.5887695,41.9895207]},"n1821014707":{"id":"n1821014707","loc":[-85.6061073,41.9746866]},"n1821014708":{"id":"n1821014708","loc":[-85.6033446,41.9751692]},"n1821014710":{"id":"n1821014710","loc":[-85.5180986,42.0322332]},"n1821014711":{"id":"n1821014711","loc":[-85.543365,42.0163569]},"n1821014712":{"id":"n1821014712","loc":[-85.6030656,41.9753646]},"n1821014713":{"id":"n1821014713","loc":[-85.6104417,41.9704792]},"n1821014714":{"id":"n1821014714","loc":[-85.5205716,42.030998]},"n1821014716":{"id":"n1821014716","loc":[-85.516382,42.032536]},"n1821014717":{"id":"n1821014717","loc":[-85.5932863,41.9820882]},"n1821014718":{"id":"n1821014718","loc":[-85.5361928,42.0194974]},"n1821014720":{"id":"n1821014720","loc":[-85.6011613,41.9773586]},"n1821014721":{"id":"n1821014721","loc":[-85.554287,42.0109124]},"n1821014722":{"id":"n1821014722","loc":[-85.5577524,42.0103425]},"n1821014725":{"id":"n1821014725","loc":[-85.5867256,41.9921004]},"n1821014726":{"id":"n1821014726","loc":[-85.5856045,41.9968807]},"n1821014727":{"id":"n1821014727","loc":[-85.5545445,42.0106454]},"n1821014728":{"id":"n1821014728","loc":[-85.5923797,41.9842534]},"n1821014729":{"id":"n1821014729","loc":[-85.5696346,42.0081462]},"n1821014730":{"id":"n1821014730","loc":[-85.5998322,41.9786884]},"n1821014735":{"id":"n1821014735","loc":[-85.5337426,42.0218266]},"n1821014736":{"id":"n1821014736","loc":[-85.5847944,41.994672]},"n1821014740":{"id":"n1821014740","loc":[-85.5315271,42.0238669]},"n1821014741":{"id":"n1821014741","loc":[-85.5248846,42.027085]},"n1821014742":{"id":"n1821014742","loc":[-85.5853376,41.997018]},"n1821014743":{"id":"n1821014743","loc":[-85.5894883,41.988811]},"n1821014745":{"id":"n1821014745","loc":[-85.6095311,41.9726226]},"n1821014746":{"id":"n1821014746","loc":[-85.5531511,42.0133416]},"n1821014747":{"id":"n1821014747","loc":[-85.5735882,42.007058]},"n1821014749":{"id":"n1821014749","loc":[-85.5428554,42.0164366]},"n1821014751":{"id":"n1821014751","loc":[-85.5395255,42.0186304]},"n1821014752":{"id":"n1821014752","loc":[-85.571378,42.0083176]},"n1821014754":{"id":"n1821014754","loc":[-85.5541918,42.0113925]},"n1821014755":{"id":"n1821014755","loc":[-85.5278029,42.0250806]},"n1821014756":{"id":"n1821014756","loc":[-85.5936725,41.9827102]},"n1821014757":{"id":"n1821014757","loc":[-85.5176266,42.0346677]},"n1821014758":{"id":"n1821014758","loc":[-85.6096692,41.9714245]},"n1821014759":{"id":"n1821014759","loc":[-85.5770321,42.0034266]},"n1821014761":{"id":"n1821014761","loc":[-85.5988921,41.9779369]},"n1821014762":{"id":"n1821014762","loc":[-85.5811788,42.0024499]},"n1821014763":{"id":"n1821014763","loc":[-85.5154003,42.0381101]},"n1821014764":{"id":"n1821014764","loc":[-85.5155827,42.0374089]},"n1821014765":{"id":"n1821014765","loc":[-85.5891249,41.9884978]},"n1821014766":{"id":"n1821014766","loc":[-85.5313863,42.0238293]},"n1821014768":{"id":"n1821014768","loc":[-85.593297,41.9833363]},"n1821014769":{"id":"n1821014769","loc":[-85.5849446,41.9957245]},"n1821014770":{"id":"n1821014770","loc":[-85.5537774,42.0130847]},"n1821014771":{"id":"n1821014771","loc":[-85.6111766,41.9706069]},"n1821014772":{"id":"n1821014772","loc":[-85.5585477,42.008989]},"n1821014774":{"id":"n1821014774","loc":[-85.5928142,41.9852623]},"n1821014777":{"id":"n1821014777","loc":[-85.5891933,41.9882608]},"n1821014778":{"id":"n1821014778","loc":[-85.5926909,41.9817532]},"n1821014779":{"id":"n1821014779","loc":[-85.5260272,42.0252201]},"n1821014781":{"id":"n1821014781","loc":[-85.5894615,41.9950468]},"n1821014782":{"id":"n1821014782","loc":[-85.5461063,42.0143242]},"n1821014783":{"id":"n1821014783","loc":[-85.5711527,42.0085886]},"n1821014784":{"id":"n1821014784","loc":[-85.5329379,42.0218624]},"n1821014786":{"id":"n1821014786","loc":[-85.583047,42.0020252]},"n1821014787":{"id":"n1821014787","loc":[-85.5758962,42.0054095]},"n1821014788":{"id":"n1821014788","loc":[-85.5626354,42.0077733]},"n1821014789":{"id":"n1821014789","loc":[-85.6029852,41.9755999]},"n1821014790":{"id":"n1821014790","loc":[-85.5892362,41.9886755]},"n1821014791":{"id":"n1821014791","loc":[-85.5157597,42.0372017]},"n1821014793":{"id":"n1821014793","loc":[-85.6054582,41.9751094]},"n1821014794":{"id":"n1821014794","loc":[-85.5986936,41.9778412]},"n1821014795":{"id":"n1821014795","loc":[-85.5880775,41.98976]},"n1821014796":{"id":"n1821014796","loc":[-85.5858727,41.9963624]},"n1821014798":{"id":"n1821014798","loc":[-85.5792543,42.0035958]},"n1821014799":{"id":"n1821014799","loc":[-85.5921665,41.9838326]},"n1821014801":{"id":"n1821014801","loc":[-85.599214,41.9782599]},"n1821014802":{"id":"n1821014802","loc":[-85.5571905,42.0090967]},"n1821014803":{"id":"n1821014803","loc":[-85.5426891,42.0173612]},"n1821014804":{"id":"n1821014804","loc":[-85.5889626,41.9896404]},"n1821014805":{"id":"n1821014805","loc":[-85.5491264,42.0141648]},"n1821014806":{"id":"n1821014806","loc":[-85.5618897,42.0072631]},"n1821014808":{"id":"n1821014808","loc":[-85.5573501,42.0109802]},"n1821014809":{"id":"n1821014809","loc":[-85.5983463,41.9778031]},"n1821014810":{"id":"n1821014810","loc":[-85.5885173,41.9895128]},"n1821014811":{"id":"n1821014811","loc":[-85.6084998,41.9721143]},"n1821014812":{"id":"n1821014812","loc":[-85.5737598,42.0056389]},"n1821014814":{"id":"n1821014814","loc":[-85.5542173,42.0118132]},"n1821014816":{"id":"n1821014816","loc":[-85.5277868,42.024451]},"n1821014817":{"id":"n1821014817","loc":[-85.5403999,42.0191724]},"n1821014819":{"id":"n1821014819","loc":[-85.5983879,41.9791452]},"n1821014820":{"id":"n1821014820","loc":[-85.5891302,41.9897578]},"n1821014822":{"id":"n1821014822","loc":[-85.5930731,41.9805108]},"n1821014824":{"id":"n1821014824","loc":[-85.515395,42.0378471]},"n1821014825":{"id":"n1821014825","loc":[-85.5352755,42.0205136]},"n1821014826":{"id":"n1821014826","loc":[-85.5502744,42.0133398]},"n1821014828":{"id":"n1821014828","loc":[-85.5701295,42.0088256]},"n1821014830":{"id":"n1821014830","loc":[-85.5888929,41.9953099]},"n1821014832":{"id":"n1821014832","loc":[-85.5880077,41.9901547]},"n1821014833":{"id":"n1821014833","loc":[-85.5451192,42.0157072]},"n1821014834":{"id":"n1821014834","loc":[-85.6096478,41.9711932]},"n1821014835":{"id":"n1821014835","loc":[-85.5806424,42.0026532]},"n1821014836":{"id":"n1821014836","loc":[-85.5911674,41.9868732]},"n1821014838":{"id":"n1821014838","loc":[-85.5930302,41.9836571]},"n1821014839":{"id":"n1821014839","loc":[-85.588925,41.9938148]},"n1821014840":{"id":"n1821014840","loc":[-85.6111874,41.9705311]},"n1821014841":{"id":"n1821014841","loc":[-85.5680843,42.0075842]},"n1821014842":{"id":"n1821014842","loc":[-85.6012793,41.9775062]},"n1821014843":{"id":"n1821014843","loc":[-85.5855562,41.9989777]},"n1821014844":{"id":"n1821014844","loc":[-85.5506137,42.0131662]},"n1821014845":{"id":"n1821014845","loc":[-85.5270049,42.025457]},"n1821014846":{"id":"n1821014846","loc":[-85.5257054,42.025244]},"n1821014847":{"id":"n1821014847","loc":[-85.6011184,41.9771832]},"n1821014848":{"id":"n1821014848","loc":[-85.515534,42.0389234]},"n1821014850":{"id":"n1821014850","loc":[-85.5847032,42.0010347]},"n1821014853":{"id":"n1821014853","loc":[-85.5361499,42.019063]},"n1821014854":{"id":"n1821014854","loc":[-85.5439176,42.0165721]},"n1821014855":{"id":"n1821014855","loc":[-85.5838825,42.0017284]},"n1821014857":{"id":"n1821014857","loc":[-85.5542173,42.0122317]},"n1821014859":{"id":"n1821014859","loc":[-85.5708201,42.0089195]},"n1821014860":{"id":"n1821014860","loc":[-85.5844833,41.9954415]},"n1821014862":{"id":"n1821014862","loc":[-85.5223204,42.0295396]},"n1821014863":{"id":"n1821014863","loc":[-85.5777898,42.0035918]},"n1821014864":{"id":"n1821014864","loc":[-85.591044,41.9898078]},"n1821014865":{"id":"n1821014865","loc":[-85.5973204,41.980182]},"n1821014866":{"id":"n1821014866","loc":[-85.5699578,42.0085825]},"n1821014867":{"id":"n1821014867","loc":[-85.5210598,42.0305278]},"n1821014868":{"id":"n1821014868","loc":[-85.5929108,41.9819008]},"n1821014869":{"id":"n1821014869","loc":[-85.5279799,42.0242995]},"n1821014870":{"id":"n1821014870","loc":[-85.5196114,42.0320539]},"n1821014871":{"id":"n1821014871","loc":[-85.5785449,42.0040883]},"n1821014872":{"id":"n1821014872","loc":[-85.588292,41.9895766]},"n1821014873":{"id":"n1821014873","loc":[-85.5160172,42.0331775]},"n1821014874":{"id":"n1821014874","loc":[-85.5688849,42.0077016]},"n1821014876":{"id":"n1821014876","loc":[-85.5857976,41.9996036]},"n1821014879":{"id":"n1821014879","loc":[-85.5990906,41.9780765]},"n1821014881":{"id":"n1821014881","loc":[-85.5483647,42.0144279]},"n1821014883":{"id":"n1821014883","loc":[-85.5691209,42.0077972]},"n1821014885":{"id":"n1821014885","loc":[-85.6076844,41.9721103]},"n1821014886":{"id":"n1821014886","loc":[-85.6015489,41.9766147]},"n1821014887":{"id":"n1821014887","loc":[-85.574822,42.0052802]},"n1821014888":{"id":"n1821014888","loc":[-85.5880024,41.9899593]},"n1821014890":{"id":"n1821014890","loc":[-85.5909421,41.9893772]},"n1821014892":{"id":"n1821014892","loc":[-85.5497326,42.0138141]},"n1821014893":{"id":"n1821014893","loc":[-85.5167106,42.0357811]},"n1821014895":{"id":"n1821014895","loc":[-85.5844404,41.9952501]},"n1821014896":{"id":"n1821014896","loc":[-85.5362465,42.0192662]},"n1821014898":{"id":"n1821014898","loc":[-85.5906095,41.9889147]},"n1821014899":{"id":"n1821014899","loc":[-85.5590667,42.0089354]},"n1821014900":{"id":"n1821014900","loc":[-85.5921598,41.9844209]},"n1821014902":{"id":"n1821014902","loc":[-85.5778971,42.0039266]},"n1821014903":{"id":"n1821014903","loc":[-85.603012,41.9761981]},"n1821014904":{"id":"n1821014904","loc":[-85.6108977,41.9706787]},"n1821014905":{"id":"n1821014905","loc":[-85.5685738,42.0076139]},"n1821014906":{"id":"n1821014906","loc":[-85.5392787,42.0186304]},"n1821014907":{"id":"n1821014907","loc":[-85.5227885,42.0274972]},"n1821014908":{"id":"n1821014908","loc":[-85.5857547,41.9961431]},"n1821014910":{"id":"n1821014910","loc":[-85.5610354,42.0072812]},"n1821014911":{"id":"n1821014911","loc":[-85.5209632,42.0308705]},"n1821014912":{"id":"n1821014912","loc":[-85.5709757,42.0087959]},"n1821014913":{"id":"n1821014913","loc":[-85.59231,41.9839344]},"n1821014914":{"id":"n1821014914","loc":[-85.5375245,42.0185865]},"n1821014916":{"id":"n1821014916","loc":[-85.5901548,41.9839841]},"n1821014917":{"id":"n1821014917","loc":[-85.5611213,42.0086405]},"n1821014918":{"id":"n1821014918","loc":[-85.5360426,42.0198122]},"n1821014919":{"id":"n1821014919","loc":[-85.5862817,41.9948691]},"n1821014921":{"id":"n1821014921","loc":[-85.5469807,42.0144438]},"n1821014922":{"id":"n1821014922","loc":[-85.5761309,42.0053838]},"n1821014924":{"id":"n1821014924","loc":[-85.516264,42.0332971]},"n1821014925":{"id":"n1821014925","loc":[-85.5277224,42.0246661]},"n1821014926":{"id":"n1821014926","loc":[-85.5980016,41.9798231]},"n1821014928":{"id":"n1821014928","loc":[-85.5924548,41.9806965]},"n1821014930":{"id":"n1821014930","loc":[-85.5899121,41.985023]},"n1821014931":{"id":"n1821014931","loc":[-85.5706015,42.0089492]},"n1821014932":{"id":"n1821014932","loc":[-85.515926,42.033046]},"n1821014933":{"id":"n1821014933","loc":[-85.5982377,41.9796796]},"n1821014936":{"id":"n1821014936","loc":[-85.5475721,42.0145253]},"n1821014938":{"id":"n1821014938","loc":[-85.5895701,41.9902323]},"n1821014939":{"id":"n1821014939","loc":[-85.6030495,41.9759947]},"n1821014942":{"id":"n1821014942","loc":[-85.6094721,41.9724989]},"n1821014944":{"id":"n1821014944","loc":[-85.5921973,41.9811112]},"n1821014945":{"id":"n1821014945","loc":[-85.5223526,42.0291332]},"n1821014946":{"id":"n1821014946","loc":[-85.5965103,41.9808998]},"n1821014948":{"id":"n1821014948","loc":[-85.517766,42.0349227]},"n1821014950":{"id":"n1821014950","loc":[-85.5889894,41.990996]},"n1821014951":{"id":"n1821014951","loc":[-85.5601932,42.0092902]},"n1821014954":{"id":"n1821014954","loc":[-85.6028135,41.9764055]},"n1821014955":{"id":"n1821014955","loc":[-85.5520621,42.0130666]},"n1821014956":{"id":"n1821014956","loc":[-85.593002,41.9839344]},"n1821014957":{"id":"n1821014957","loc":[-85.515926,42.0369666]},"n1821014960":{"id":"n1821014960","loc":[-85.5761255,42.003877]},"n1821014961":{"id":"n1821014961","loc":[-85.5716355,42.007911]},"n1821014962":{"id":"n1821014962","loc":[-85.5575378,42.0109045]},"n1821014963":{"id":"n1821014963","loc":[-85.5735667,42.0068188]},"n1821014964":{"id":"n1821014964","loc":[-85.5915214,41.9865861]},"n1821014965":{"id":"n1821014965","loc":[-85.5866344,41.9923157]},"n1821014967":{"id":"n1821014967","loc":[-85.5283138,42.0242256]},"n1821014968":{"id":"n1821014968","loc":[-85.5177875,42.0355801]},"n1821014969":{"id":"n1821014969","loc":[-85.548071,42.0144934]},"n1821014972":{"id":"n1821014972","loc":[-85.5611159,42.0088557]},"n1821014973":{"id":"n1821014973","loc":[-85.541686,42.0188757]},"n1821014974":{"id":"n1821014974","loc":[-85.5917628,41.9862631]},"n1821014975":{"id":"n1821014975","loc":[-85.5854864,41.9959478]},"n1821014977":{"id":"n1821014977","loc":[-85.609102,41.9722317]},"n1821014980":{"id":"n1821014980","loc":[-85.5761202,42.0042438]},"n1821014982":{"id":"n1821014982","loc":[-85.5465944,42.0143601]},"n1821014983":{"id":"n1821014983","loc":[-85.5173261,42.0342732]},"n1821014984":{"id":"n1821014984","loc":[-85.5897297,41.9888509]},"n1821014985":{"id":"n1821014985","loc":[-85.5856688,41.999181]},"n1821014986":{"id":"n1821014986","loc":[-85.5344011,42.0217251]},"n1821014987":{"id":"n1821014987","loc":[-85.601467,41.9768203]},"n1821014988":{"id":"n1821014988","loc":[-85.5457254,42.0165123]},"n1821014989":{"id":"n1821014989","loc":[-85.6023482,41.9784332]},"n1821014991":{"id":"n1821014991","loc":[-85.5361606,42.01823]},"n1821014992":{"id":"n1821014992","loc":[-85.5178465,42.0351139]},"n1821014995":{"id":"n1821014995","loc":[-85.5634293,42.0078092]},"n1821014996":{"id":"n1821014996","loc":[-85.573497,42.0072015]},"n1821014997":{"id":"n1821014997","loc":[-85.5976328,41.9799725]},"n1821014998":{"id":"n1821014998","loc":[-85.5210651,42.0303166]},"n1821015003":{"id":"n1821015003","loc":[-85.5222131,42.0288064]},"n1821015004":{"id":"n1821015004","loc":[-85.5897941,41.984405]},"n1821015005":{"id":"n1821015005","loc":[-85.5975725,41.9776099]},"n1821015006":{"id":"n1821015006","loc":[-85.5765708,42.0034903]},"n1821015007":{"id":"n1821015007","loc":[-85.5250187,42.026559]},"n1821015009":{"id":"n1821015009","loc":[-85.5426998,42.0166279]},"n1821015010":{"id":"n1821015010","loc":[-85.5957606,41.9806584]},"n1821015011":{"id":"n1821015011","loc":[-85.5262753,42.0252497]},"n1821015012":{"id":"n1821015012","loc":[-85.5266455,42.0253374]},"n1821015014":{"id":"n1821015014","loc":[-85.5515632,42.0130187]},"n1821015015":{"id":"n1821015015","loc":[-85.6024058,41.9765212]},"n1821015017":{"id":"n1821015017","loc":[-85.5175032,42.0357156]},"n1821015018":{"id":"n1821015018","loc":[-85.5302718,42.0236039]},"n1821015019":{"id":"n1821015019","loc":[-85.6024005,41.9782759]},"n1821015020":{"id":"n1821015020","loc":[-85.5907758,41.9890821]},"n1821015021":{"id":"n1821015021","loc":[-85.6019445,41.9777215]},"n1821015022":{"id":"n1821015022","loc":[-85.5942854,41.9800881]},"n1821015024":{"id":"n1821015024","loc":[-85.5325826,42.0222711]},"n1821015029":{"id":"n1821015029","loc":[-85.555093,42.0105316]},"n1821015033":{"id":"n1821015033","loc":[-85.5249704,42.0270372]},"n1821015034":{"id":"n1821015034","loc":[-85.5243965,42.0272205]},"n1821015038":{"id":"n1821015038","loc":[-85.5413426,42.0190749]},"n1821015039":{"id":"n1821015039","loc":[-85.5920431,41.9848175]},"n1821015041":{"id":"n1821015041","loc":[-85.5577685,42.0106015]},"n1821015042":{"id":"n1821015042","loc":[-85.5453606,42.0158866]},"n1821015045":{"id":"n1821015045","loc":[-85.5333228,42.0217889]},"n1821015046":{"id":"n1821015046","loc":[-85.5426891,42.0175924]},"n1821015048":{"id":"n1821015048","loc":[-85.5886836,41.9936474]},"n1821015050":{"id":"n1821015050","loc":[-85.6001152,41.9786467]},"n1821015051":{"id":"n1821015051","loc":[-85.6094064,41.9723655]},"n1821015053":{"id":"n1821015053","loc":[-85.605721,41.9749738]},"n1821015055":{"id":"n1821015055","loc":[-85.6106791,41.9705048]},"n1821015057":{"id":"n1821015057","loc":[-85.5210437,42.0307071]},"n1821015059":{"id":"n1821015059","loc":[-85.5995694,41.9786725]},"n1821015060":{"id":"n1821015060","loc":[-85.5371638,42.0182938]},"n1821015062":{"id":"n1821015062","loc":[-85.6111766,41.9704593]},"n1821015065":{"id":"n1821015065","loc":[-85.577704,42.0034921]},"n1821015067":{"id":"n1821015067","loc":[-85.5570067,42.0093699]},"n1821015068":{"id":"n1821015068","loc":[-85.5920364,41.9845525]},"n1821015069":{"id":"n1821015069","loc":[-85.5252065,42.0253954]},"n1821015072":{"id":"n1821015072","loc":[-85.5664159,42.0088517]},"n1821015073":{"id":"n1821015073","loc":[-85.5880399,41.991905]},"n1821015075":{"id":"n1821015075","loc":[-85.6099871,41.9727861]},"n1821015076":{"id":"n1821015076","loc":[-85.5319603,42.0231478]},"n1821015078":{"id":"n1821015078","loc":[-85.6036088,41.9751112]},"n1821015080":{"id":"n1821015080","loc":[-85.5983128,41.9789179]},"n1821015082":{"id":"n1821015082","loc":[-85.5614069,42.0071395]},"n1821015083":{"id":"n1821015083","loc":[-85.60968,41.9709738]},"n1821015086":{"id":"n1821015086","loc":[-85.5914195,41.9837351]},"n1821015087":{"id":"n1821015087","loc":[-85.5895473,41.9948036]},"n1821015090":{"id":"n1821015090","loc":[-85.5929913,41.9851905]},"n1821015093":{"id":"n1821015093","loc":[-85.5907396,41.9838485]},"n1821015095":{"id":"n1821015095","loc":[-85.5893864,41.9880176]},"n1821015096":{"id":"n1821015096","loc":[-85.5788024,42.0039807]},"n1821015097":{"id":"n1821015097","loc":[-85.5630592,42.0078411]},"n1821015098":{"id":"n1821015098","loc":[-85.5350609,42.0211274]},"n1821015099":{"id":"n1821015099","loc":[-85.5967195,41.9808679]},"n1821015100":{"id":"n1821015100","loc":[-85.5666734,42.0088119]},"n1821015101":{"id":"n1821015101","loc":[-85.564694,42.0077675]},"n1821015103":{"id":"n1821015103","loc":[-85.6066544,41.9726527]},"n1821015104":{"id":"n1821015104","loc":[-85.6011827,41.9769838]},"n1821015105":{"id":"n1821015105","loc":[-85.5972131,41.9776697]},"n1821015106":{"id":"n1821015106","loc":[-85.5880828,41.9903341]},"n1821015107":{"id":"n1821015107","loc":[-85.5510268,42.0130626]},"n1821015108":{"id":"n1821015108","loc":[-85.6102164,41.970543]},"n1821015109":{"id":"n1821015109","loc":[-85.5905344,41.9853899]},"n1821015111":{"id":"n1821015111","loc":[-85.5888821,41.9913429]},"n1821015112":{"id":"n1821015112","loc":[-85.606295,41.9741921]},"n1821015114":{"id":"n1821015114","loc":[-85.5969556,41.9807443]},"n1821015115":{"id":"n1821015115","loc":[-85.5882223,41.9934081]},"n1821015116":{"id":"n1821015116","loc":[-85.6104471,41.9724971]},"n1821015118":{"id":"n1821015118","loc":[-85.5406091,42.0192162]},"n1821015120":{"id":"n1821015120","loc":[-85.589955,41.9888429]},"n1821015121":{"id":"n1821015121","loc":[-85.5598821,42.0092304]},"n1821015122":{"id":"n1821015122","loc":[-85.545598,42.0144097]},"n1821015123":{"id":"n1821015123","loc":[-85.5649528,42.0079965]},"n1821015125":{"id":"n1821015125","loc":[-85.5883993,41.9917814]},"n1821015126":{"id":"n1821015126","loc":[-85.5295785,42.0239967]},"n1821015129":{"id":"n1821015129","loc":[-85.5648723,42.0078809]},"n1821015132":{"id":"n1821015132","loc":[-85.564989,42.0081103]},"n1821015133":{"id":"n1821015133","loc":[-85.5946127,41.9800841]},"n1821015134":{"id":"n1821015134","loc":[-85.583448,42.0019078]},"n1821015135":{"id":"n1821015135","loc":[-85.5905934,41.9871842]},"n1821015137":{"id":"n1821015137","loc":[-85.610608,41.9704752]},"n1821015138":{"id":"n1821015138","loc":[-85.5752257,42.0052939]},"n1821015139":{"id":"n1821015139","loc":[-85.5893864,41.9943491]},"n1821015140":{"id":"n1821015140","loc":[-85.5426247,42.0169866]},"n1821015141":{"id":"n1821015141","loc":[-85.562001,42.0074526]},"n1821015142":{"id":"n1821015142","loc":[-85.5212046,42.0301094]},"n1821015143":{"id":"n1821015143","loc":[-85.602214,41.9784531]},"n1821015144":{"id":"n1821015144","loc":[-85.5858687,41.9948293]},"n1821015145":{"id":"n1821015145","loc":[-85.5608477,42.0074805]},"n1821015146":{"id":"n1821015146","loc":[-85.5651607,42.0083614]},"n1821015147":{"id":"n1821015147","loc":[-85.5288288,42.0242495]},"n1821015149":{"id":"n1821015149","loc":[-85.5450334,42.0146989]},"n1821015151":{"id":"n1821015151","loc":[-85.5578275,42.0092304]},"n1821015154":{"id":"n1821015154","loc":[-85.6056634,41.9724511]},"n1821015155":{"id":"n1821015155","loc":[-85.5902179,41.9852742]},"n1821015156":{"id":"n1821015156","loc":[-85.5156256,42.0387157]},"n1821015157":{"id":"n1821015157","loc":[-85.5734433,42.0059459]},"n1821015158":{"id":"n1821015158","loc":[-85.6050773,41.9731273]},"n1821015160":{"id":"n1821015160","loc":[-85.5223419,42.0275233]},"n1821015163":{"id":"n1821015163","loc":[-85.6053562,41.972525]},"n1821015164":{"id":"n1821015164","loc":[-85.5850412,41.9946082]},"n1821015165":{"id":"n1821015165","loc":[-85.5359031,42.0186326]},"n1821015166":{"id":"n1821015166","loc":[-85.5608745,42.0077635]},"n1821015169":{"id":"n1821015169","loc":[-85.572876,42.0073189]},"n1821015171":{"id":"n1821015171","loc":[-85.5875424,41.9919188]},"n1821015172":{"id":"n1821015172","loc":[-85.5240116,42.0272581]},"n1821015173":{"id":"n1821015173","loc":[-85.5318369,42.0236818]},"n1821015174":{"id":"n1821015174","loc":[-85.566888,42.0086923]},"n1821015175":{"id":"n1821015175","loc":[-85.5931522,41.9850669]},"n1821015176":{"id":"n1821015176","loc":[-85.5604842,42.0093199]},"n1821015177":{"id":"n1821015177","loc":[-85.5868168,41.9927543]},"n1821015178":{"id":"n1821015178","loc":[-85.6052275,41.9732549]},"n1821015179":{"id":"n1821015179","loc":[-85.5910118,41.9900431]},"n1821015182":{"id":"n1821015182","loc":[-85.5610032,42.0082897]},"n1821015183":{"id":"n1821015183","loc":[-85.5425443,42.0179431]},"n1821015184":{"id":"n1821015184","loc":[-85.5843277,42.0014055]},"n1821015186":{"id":"n1821015186","loc":[-85.5733307,42.0063564]},"n1821015188":{"id":"n1821015188","loc":[-85.5277385,42.0248694]},"n1821015189":{"id":"n1821015189","loc":[-85.5558427,42.0108168]},"n1821015190":{"id":"n1821015190","loc":[-85.5650587,42.0082618]},"n1821015191":{"id":"n1821015191","loc":[-85.5660351,42.0088278]},"n1821015192":{"id":"n1821015192","loc":[-85.5849768,41.9980049]},"n1821015194":{"id":"n1821015194","loc":[-85.5359139,42.0188199]},"n1821015195":{"id":"n1821015195","loc":[-85.593238,41.9849194]},"n1821015197":{"id":"n1821015197","loc":[-85.5850841,41.9983239]},"n1821015199":{"id":"n1821015199","loc":[-85.5983396,41.9794283]},"n1821015204":{"id":"n1821015204","loc":[-85.5452801,42.0145355]},"n1821015205":{"id":"n1821015205","loc":[-85.5340685,42.0218407]},"n1821015207":{"id":"n1821015207","loc":[-85.5773272,42.0034186]},"n1821015209":{"id":"n1821015209","loc":[-85.5535212,42.0132419]},"n1821015211":{"id":"n1821015211","loc":[-85.6107703,41.9706045]},"n1821015212":{"id":"n1821015212","loc":[-85.6030066,41.9758193]},"n1821015213":{"id":"n1821015213","loc":[-85.5359943,42.0184213]},"n1821015214":{"id":"n1821015214","loc":[-85.5922993,41.9813305]},"n1821015215":{"id":"n1821015215","loc":[-85.5672689,42.0080465]},"n1821015217":{"id":"n1821015217","loc":[-85.5160494,42.0365682]},"n1821015218":{"id":"n1821015218","loc":[-85.5401142,42.0190351]},"n1821015219":{"id":"n1821015219","loc":[-85.5607632,42.0092282]},"n1821015220":{"id":"n1821015220","loc":[-85.5866197,41.9947894]},"n1821015221":{"id":"n1821015221","loc":[-85.6017889,41.9765132]},"n1821015222":{"id":"n1821015222","loc":[-85.5595978,42.009059]},"n1821015226":{"id":"n1821015226","loc":[-85.5871494,41.9929018]},"n1821015227":{"id":"n1821015227","loc":[-85.5857708,41.9998866]},"n1821015228":{"id":"n1821015228","loc":[-85.5317135,42.0238094]},"n1821015231":{"id":"n1821015231","loc":[-85.5733521,42.0061372]},"n1821015233":{"id":"n1821015233","loc":[-85.5855991,42.0001936]},"n1821015234":{"id":"n1821015234","loc":[-85.5213924,42.029962]},"n1821015235":{"id":"n1821015235","loc":[-85.6052221,41.9726567]},"n1821015236":{"id":"n1821015236","loc":[-85.5763723,42.0035422]},"n1821015237":{"id":"n1821015237","loc":[-85.5858512,41.9966215]},"n1821015238":{"id":"n1821015238","loc":[-85.567061,42.008439]},"n1821015239":{"id":"n1821015239","loc":[-85.5250563,42.0269057]},"n1821015240":{"id":"n1821015240","loc":[-85.5347551,42.0214263]},"n1821015241":{"id":"n1821015241","loc":[-85.6098463,41.9707066]},"n1821015242":{"id":"n1821015242","loc":[-85.5676927,42.0076519]},"n1821015243":{"id":"n1821015243","loc":[-85.516775,42.0322669]},"n1821015244":{"id":"n1821015244","loc":[-85.5762275,42.0036538]},"n1821015245":{"id":"n1821015245","loc":[-85.5583639,42.0090949]},"n1821015246":{"id":"n1821015246","loc":[-85.5554041,42.0106432]},"n1821015247":{"id":"n1821015247","loc":[-85.5973364,41.9776099]},"n1821015248":{"id":"n1821015248","loc":[-85.6098945,41.9717513]},"n1821015249":{"id":"n1821015249","loc":[-85.6045315,41.9751511]},"n1821015250":{"id":"n1821015250","loc":[-85.5579938,42.0092264]},"n1821015253":{"id":"n1821015253","loc":[-85.6058873,41.9724652]},"n1821015254":{"id":"n1821015254","loc":[-85.5869456,41.9947517]},"n1821015255":{"id":"n1821015255","loc":[-85.5936565,41.9823713]},"n1821015256":{"id":"n1821015256","loc":[-85.5218269,42.0278102]},"n1821015258":{"id":"n1821015258","loc":[-85.5887802,41.9905534]},"n1821015259":{"id":"n1821015259","loc":[-85.5901924,41.9904515]},"n1821015263":{"id":"n1821015263","loc":[-85.5249222,42.0255787]},"n1821015265":{"id":"n1821015265","loc":[-85.5175206,42.0321672]},"n1821015266":{"id":"n1821015266","loc":[-85.5275722,42.0254034]},"n1821015267":{"id":"n1821015267","loc":[-85.6016226,41.9765451]},"n1821015269":{"id":"n1821015269","loc":[-85.5569316,42.011032]},"n1821015271":{"id":"n1821015271","loc":[-85.6010714,41.9785209]},"n1821015272":{"id":"n1821015272","loc":[-85.6050666,41.9729917]},"n1821015273":{"id":"n1821015273","loc":[-85.5891235,41.99529]},"n1821015274":{"id":"n1821015274","loc":[-85.515454,42.0376439]},"n1821015276":{"id":"n1821015276","loc":[-85.5776021,42.0034443]},"n1821015277":{"id":"n1821015277","loc":[-85.6041707,41.9751453]},"n1821015278":{"id":"n1821015278","loc":[-85.5444701,42.0167435]},"n1821015280":{"id":"n1821015280","loc":[-85.5923274,41.9852202]},"n1821015283":{"id":"n1821015283","loc":[-85.5893649,41.9900271]},"n1821015284":{"id":"n1821015284","loc":[-85.5933453,41.9804412]},"n1821015285":{"id":"n1821015285","loc":[-85.5247237,42.026017]},"n1821015286":{"id":"n1821015286","loc":[-85.5286182,42.0242477]},"n1821015287":{"id":"n1821015287","loc":[-85.5904003,41.9888549]},"n1821015288":{"id":"n1821015288","loc":[-85.6062146,41.9739369]},"n1821015290":{"id":"n1821015290","loc":[-85.5762596,42.0052602]},"n1821015292":{"id":"n1821015292","loc":[-85.5849715,41.9975465]},"n1821015293":{"id":"n1821015293","loc":[-85.585229,42.0006241]},"n1821015294":{"id":"n1821015294","loc":[-85.5926922,41.9805946]},"n1821015295":{"id":"n1821015295","loc":[-85.5703387,42.0089133]},"n1821015299":{"id":"n1821015299","loc":[-85.5789955,42.0038611]},"n1821015301":{"id":"n1821015301","loc":[-85.6072888,41.9721918]},"n1821015302":{"id":"n1821015302","loc":[-85.5356349,42.0200992]},"n1821015304":{"id":"n1821015304","loc":[-85.5891772,41.994066]},"n1821015306":{"id":"n1821015306","loc":[-85.606295,41.9744952]},"n1821015307":{"id":"n1821015307","loc":[-85.538871,42.0186583]},"n1821015308":{"id":"n1821015308","loc":[-85.587997,41.994971]},"n1821015311":{"id":"n1821015311","loc":[-85.606869,41.9725809]},"n1821015312":{"id":"n1821015312","loc":[-85.5171974,42.0339943]},"n1821015314":{"id":"n1821015314","loc":[-85.5327435,42.0220479]},"n1821015315":{"id":"n1821015315","loc":[-85.5383439,42.0187282]},"n1821015316":{"id":"n1821015316","loc":[-85.5248095,42.0263119]},"n1821015318":{"id":"n1821015318","loc":[-85.5732502,42.0073051]},"n1821015319":{"id":"n1821015319","loc":[-85.5924226,41.9852663]},"n1821015321":{"id":"n1821015321","loc":[-85.5179001,42.0353052]},"n1821015322":{"id":"n1821015322","loc":[-85.5456771,42.0162413]},"n1821015323":{"id":"n1821015323","loc":[-85.5936618,41.9829096]},"n1821015325":{"id":"n1821015325","loc":[-85.5656931,42.0086582]},"n1821015326":{"id":"n1821015326","loc":[-85.5448456,42.0150975]},"n1821015327":{"id":"n1821015327","loc":[-85.5220039,42.027615]},"n1821015329":{"id":"n1821015329","loc":[-85.517884,42.0354885]},"n1821015330":{"id":"n1821015330","loc":[-85.5576666,42.0101671]},"n1821015332":{"id":"n1821015332","loc":[-85.5368754,42.0181402]},"n1821015333":{"id":"n1821015333","loc":[-85.5367078,42.0181145]},"n1821015334":{"id":"n1821015334","loc":[-85.5903909,41.9904316]},"n1821015335":{"id":"n1821015335","loc":[-85.5430767,42.0163587]},"n1821015336":{"id":"n1821015336","loc":[-85.5277492,42.0252878]},"n1821015337":{"id":"n1821015337","loc":[-85.5312146,42.0236898]},"n1821015338":{"id":"n1821015338","loc":[-85.5886568,41.991614]},"n1821015339":{"id":"n1821015339","loc":[-85.5782498,42.0040883]},"n1821015341":{"id":"n1821015341","loc":[-85.562233,42.0076457]},"n1821015342":{"id":"n1821015342","loc":[-85.588626,41.9952479]},"n1821015343":{"id":"n1821015343","loc":[-85.5762865,42.005033]},"n1821015344":{"id":"n1821015344","loc":[-85.5850841,41.9971478]},"n1821015346":{"id":"n1821015346","loc":[-85.5643144,42.0076936]},"n1821015347":{"id":"n1821015347","loc":[-85.5164893,42.0359467]},"n1821015348":{"id":"n1821015348","loc":[-85.5906846,41.9903541]},"n1821015349":{"id":"n1821015349","loc":[-85.557688,42.0107769]},"n1821015350":{"id":"n1821015350","loc":[-85.5363698,42.0181424]},"n1821015351":{"id":"n1821015351","loc":[-85.5939636,41.9801918]},"n1821015352":{"id":"n1821015352","loc":[-85.5524041,42.0131644]},"n1821015354":{"id":"n1821015354","loc":[-85.5308606,42.0236221]},"n1821015355":{"id":"n1821015355","loc":[-85.5877449,41.9932367]},"n1821015356":{"id":"n1821015356","loc":[-85.519885,42.0318586]},"n1821015357":{"id":"n1821015357","loc":[-85.5454035,42.0168431]},"n1821015358":{"id":"n1821015358","loc":[-85.5970629,41.9781881]},"n1821015359":{"id":"n1821015359","loc":[-85.5932541,41.9844767]},"n1821015360":{"id":"n1821015360","loc":[-85.5970736,41.9778252]},"n1821015361":{"id":"n1821015361","loc":[-85.537031,42.0181601]},"n1821015362":{"id":"n1821015362","loc":[-85.5548355,42.0105156]},"n1821015363":{"id":"n1821015363","loc":[-85.5168648,42.0336158]},"n1821015365":{"id":"n1821015365","loc":[-85.5870435,41.9919507]},"n1821015366":{"id":"n1821015366","loc":[-85.5719681,42.0075443]},"n1821015367":{"id":"n1821015367","loc":[-85.5969985,41.9780446]},"n1821015368":{"id":"n1821015368","loc":[-85.5926761,41.98528]},"n1821015369":{"id":"n1821015369","loc":[-85.5224009,42.0293444]},"n1821015371":{"id":"n1821015371","loc":[-85.518737,42.0322651]},"n1821015372":{"id":"n1821015372","loc":[-85.6064573,41.9726465]},"n1821015373":{"id":"n1821015373","loc":[-85.5201103,42.0313088]},"n1821015375":{"id":"n1821015375","loc":[-85.5378182,42.0186844]},"n1821015376":{"id":"n1821015376","loc":[-85.6109741,41.9706882]},"n1821015377":{"id":"n1821015377","loc":[-85.5993333,41.9785488]},"n1821015378":{"id":"n1821015378","loc":[-85.5889787,41.9907368]},"n1821015380":{"id":"n1821015380","loc":[-85.6060161,41.9737375]},"n1821015381":{"id":"n1821015381","loc":[-85.5743016,42.0053679]},"n1821015382":{"id":"n1821015382","loc":[-85.6014724,41.9776099]},"n1821015383":{"id":"n1821015383","loc":[-85.5574426,42.0091644]},"n1821015385":{"id":"n1821015385","loc":[-85.5208613,42.0309302]},"n1821015386":{"id":"n1821015386","loc":[-85.5919023,41.9837789]},"n1821015387":{"id":"n1821015387","loc":[-85.5455484,42.0160221]},"n1821015392":{"id":"n1821015392","loc":[-85.5801757,42.0028964]},"n1821015395":{"id":"n1821015395","loc":[-85.5493785,42.0139974]},"n1821015396":{"id":"n1821015396","loc":[-85.5449475,42.015488]},"n1821015398":{"id":"n1821015398","loc":[-85.611123,41.9706627]},"n1821015400":{"id":"n1821015400","loc":[-85.5935706,41.9822477]},"n1821015401":{"id":"n1821015401","loc":[-85.5724254,42.0073508]},"n1821015403":{"id":"n1821015403","loc":[-85.5486812,42.0143442]},"n1821015404":{"id":"n1821015404","loc":[-85.5161835,42.0327711]},"n1821015406":{"id":"n1821015406","loc":[-85.5921705,41.9851107]},"n1821015407":{"id":"n1821015407","loc":[-85.531912,42.0234069]},"n1821015410":{"id":"n1821015410","loc":[-85.5292566,42.024176]},"n1821015411":{"id":"n1821015411","loc":[-85.5845316,41.9948315]},"n1821015413":{"id":"n1821015413","loc":[-85.5217947,42.0280413]},"n1821015414":{"id":"n1821015414","loc":[-85.5527367,42.013272]},"n1821015415":{"id":"n1821015415","loc":[-85.5191179,42.0321973]},"n1821015416":{"id":"n1821015416","loc":[-85.5540241,42.0128655]},"n1821015418":{"id":"n1821015418","loc":[-85.5272892,42.0254849]},"n1821015419":{"id":"n1821015419","loc":[-85.5449744,42.016867]},"n1821015420":{"id":"n1821015420","loc":[-85.5852665,41.9986787]},"n1821015421":{"id":"n1821015421","loc":[-85.6102701,41.972186]},"n1821015423":{"id":"n1821015423","loc":[-85.6026365,41.9764972]},"n1821015427":{"id":"n1821015427","loc":[-85.5898692,41.9841498]},"n1821015429":{"id":"n1821015429","loc":[-85.5422546,42.0183855]},"n1821015430":{"id":"n1821015430","loc":[-85.5866505,41.9925549]},"n1821015431":{"id":"n1821015431","loc":[-85.5234376,42.0273577]},"n1821015432":{"id":"n1821015432","loc":[-85.6096746,41.9727284]},"n1821015433":{"id":"n1821015433","loc":[-85.5824891,42.0021567]},"n1821015434":{"id":"n1821015434","loc":[-85.5923905,41.9841139]},"n1821015435":{"id":"n1821015435","loc":[-85.5874565,41.9948014]},"n1821015437":{"id":"n1821015437","loc":[-85.6055279,41.9734423]},"n1821015438":{"id":"n1821015438","loc":[-85.5299379,42.0237376]},"n1821015439":{"id":"n1821015439","loc":[-85.5155022,42.0383651]},"n1821015442":{"id":"n1821015442","loc":[-85.527422,42.0254711]},"n1821015443":{"id":"n1821015443","loc":[-85.5920699,41.9849291]},"n1821015444":{"id":"n1821015444","loc":[-85.5639711,42.0077494]},"n1821015445":{"id":"n1821015445","loc":[-85.5162586,42.0361777]},"n1821015446":{"id":"n1821015446","loc":[-85.5220039,42.029695]},"n1821015448":{"id":"n1821015448","loc":[-85.5176641,42.0356956]},"n1821015449":{"id":"n1821015449","loc":[-85.5930556,41.9841577]},"n1821015451":{"id":"n1821015451","loc":[-85.5320783,42.0228848]},"n1821015452":{"id":"n1821015452","loc":[-85.5170096,42.0357235]},"n1821015453":{"id":"n1821015453","loc":[-85.5571355,42.009613]},"n1821015454":{"id":"n1821015454","loc":[-85.5609979,42.009059]},"n1821015455":{"id":"n1821015455","loc":[-85.6097336,41.9708342]},"n1821015456":{"id":"n1821015456","loc":[-85.5884476,41.9904218]},"w170843846":{"id":"w170843846","tags":{"waterway":"river"},"nodes":["n1819790555","n1819790762","n1819790547","n1819790618","n1819790898","n1819790796","n1819790534","n1819790543","n1819790541","n1819790687","n1819790877","n1819790811","n1819790670"]},"w209083541":{"id":"w209083541","tags":{"name":"Portage River","waterway":"river"},"nodes":["n1821014848","n1821015156","n1821015439","n1821014763","n1821014824","n1821015274","n1821014764","n1821014791","n1821014957","n1821015217","n1821015445","n1821015347","n1821014893","n1821015452","n1821015017","n1821015448","n1821014968","n1821015329","n1821015321","n1821014992","n1821014948","n1821014757","n1821014983","n1821015312","n1821015363","n1821014924","n1821014873","n1821014932","n1821014668","n1821015404","n1821014716","n1821015243","n1821015265","n1821014710","n1821015371","n1821015415","n1821014870","n1821015356","n1821015373","n1821014681","n1821014714","n1821015385","n1821014911","n1821015057","n1821014867","n1821014998","n1821015142","n1821015234","n1821015446","n1821014862","n1821015369","n1821014945","n1821015003","n1821014667","n1821015413","n1821015256","n1821015327","n1821015160","n1821014907","n1821015431","n1821015172","n1821015034","n1821014741","n1821015033","n1821015239","n1821015007","n1821015316","n1821015285","n1821014633","n1821015263","n1821015069","n1821014846","n1821014779","n1821015011","n1821015012","n1821014845","n1821015418","n1821015442","n1821015266","n1821015336","n1821014755","n1821015188","n1821014925","n1821014816","n1821014869","n1821014967","n1821015286","n1821015147","n1821015410","n1821015126","n1821015438","n1821015018","n1821015354","n1821015337","n1821014766","n1821014740","n1821015228","n1821015173","n1821015407","n1821015076","n1821015451","n1821015024","n1821015314","n1821014784","n1821015045","n1821014735","n1821015205","n1821014986","n1821015240","n1821015098","n1821014825","n1821015302","n1821014918","n1821014718","n1821014896","n1821014853","n1821015194","n1821015165","n1821015213","n1821014991","n1821015350","n1821015333","n1821015332","n1821015361","n1821015060","n1821014914","n1821015375","n1821015315","n1821015307","n1821014906","n1821014751","n1821014666","n1821015218","n1821014817","n1821015118","n1821014674","n1821015038","n1821014973","n1821015429","n1821015183","n1821015046","n1821014803","n1821015140","n1821015009","n1821014749","n1821015335","n1821014711","n1821014854","n1821015278","n1821015419","n1821014648","n1821015357","n1821014637","n1821014988","n1821015322","n1821015387","n1821015042","n1821014833","n1821015396","n1821015326","n1821014691","n1821015149","n1821015204","n1821015122","n1821014782","n1821014982","n1821014921","n1821014936","n1821014969","n1821014881","n1821015403","n1821014805","n1821015395","n1821014892","n1821014826","n1821014844","n1821015107","n1821015014","n1821014955","n1821015352","n1821015414","n1821014746","n1821015209","n1821014770","n1821015416","n1821014661","n1821014857","n1821014814","n1821014754","n1821014721","n1821014727","n1821015362","n1821015029","n1821015246","n1821015189","n1821014627","n1821015269","n1821014808","n1821014962","n1821015349","n1821015041","n1821014722","n1821015330","n1821015453","n1821015067","n1821014643","n1821014802","n1821015383","n1821015151","n1821015250","n1821015245","n1821014772","n1821014899","n1821015222","n1821015121","n1821014951","n1821015176","n1821015219","n1821015454","n1821014972","n1821014917","n1821015182","n1821015166","n1821015145","n1821014910","n1821015082","n1821014678","n1821014806","n1821015141","n1821015341","n1821014788","n1821015097","n1821014995","n1821015444","n1821015346","n1821015101","n1821015129","n1821015123","n1821015132","n1821015190","n1821015146","n1821015325","n1821015191","n1821015072","n1821015100","n1821015174","n1821015238","n1821015215","n1821014700","n1821015242","n1821014841","n1821014905","n1821014874","n1821014883","n1821014729","n1821014866","n1821014828","n1821015295","n1821014931","n1821014859","n1821014912","n1821014783","n1821014752","n1821014961","n1821015366","n1821015401","n1821015169","n1821015318","n1821014996","n1821014747","n1821014963","n1821014670","n1821015186","n1821015231","n1821015157","n1821014812","n1821015381","n1821014887","n1821015138","n1821014704","n1821014787","n1821014922","n1821015290","n1821015343","n1821014651","n1821014980","n1821014960","n1821015244","n1821015236","n1821015006","n1821014694","n1821014759","n1821015207","n1821015276","n1821015065","n1821014863","n1821014660","n1821014902","n1821014645","n1821015339","n1821014871","n1821015096","n1821015299","n1821014798","n1821014638","n1821015392","n1821014835","n1821014762","n1821014642","n1821015433","n1821014786","n1821015134","n1821014855","n1821015184","n1821014850","n1821015293","n1821015233","n1821015227","n1821014876","n1821014985","n1821014843","n1821015420","n1821015197","n1821015192","n1821015292","n1821015344","n1821014742","n1821014726","n1821015237","n1821014796","n1821014908","n1821014975","n1821014769","n1821014688","n1821014860","n1821014895","n1821014676","n1821015411","n1821014736","n1821015164","n1821014647","n1821015144","n1821014919","n1821015220","n1821015254","n1821015435","n1821015308","n1821015342","n1821014830","n1821015273","n1821014658","n1821014781","n1821015087","n1821015139","n1821015304","n1821014839","n1821015048","n1821015115","n1821015355","n1821015226","n1821015177","n1821015430","n1821014965","n1821014725","n1821015365","n1821015171","n1821015073","n1821015125","n1821015338","n1821015111","n1821014950","n1821015378","n1821015258","n1821015456","n1821015106","n1821014832","n1821014888","n1821014795","n1821014872","n1821014810","n1821014705","n1821014804","n1821014820","n1821015283","n1821014938","n1821014689","n1821015259","n1821015334","n1821015348","n1821014635","n1821015179","n1821014864","n1821014890","n1821015020","n1821014898","n1821015287","n1821015120","n1821014984","n1821014743","n1821014790","n1821014765","n1821014777","n1821015095","n1821014653","n1821015135","n1821014836","n1821014964","n1821014974","n1821014636","n1821014682","n1821014663","n1821014665","n1821015109","n1821015155","n1821014930","n1821014669","n1821015004","n1821015427","n1821014916","n1821015093","n1821015086","n1821015386","n1821014799","n1821014913","n1821015434","n1821014728","n1821014900","n1821015068","n1821015039","n1821015443","n1821015406","n1821015280","n1821015319","n1821015368","n1821014774","n1821015090","n1821015175","n1821015195","n1821014687","n1821015359","n1821015449","n1821014956","n1821014838","n1821014768","n1821014698","n1821015323","n1821014756","n1821015255","n1821015400","n1821014717","n1821014868","n1821014778","n1821015214","n1821014944","n1821014697","n1821014671","n1821014928","n1821015294","n1821014822","n1821015284","n1821015351","n1821015022","n1821015133","n1821014644","n1821015010","n1821014625","n1821014657","n1821014946","n1821015099","n1821015114","n1821014629","n1821014865","n1821014997","n1821014926","n1821014933","n1821015199","n1821014819","n1821015080","n1821014692","n1821014677","n1821015358","n1821015367","n1821015360","n1821015105","n1821015247","n1821015005","n1821014809","n1821014794","n1821014761","n1821014879","n1821014801","n1821015377","n1821015059","n1821014730","n1821015050","n1821015271","n1821015143","n1821014989","n1821015019","n1821014672","n1821014649","n1821014684","n1821014703","n1821015021","n1821015382","n1821014842","n1821014720","n1821014847","n1821015104","n1821014987","n1821014886","n1821015267","n1821015221","n1821015015","n1821015423","n1821014954","n1821014903","n1821014939","n1821015212","n1821014789","n1821014712","n1821014708","n1821015078","n1821015277","n1821015249","n1821014646","n1821014793","n1821015053","n1821014707","n1821015306","n1821015112","n1821015288","n1821015380","n1821015437","n1821015178","n1821015158","n1821015272","n1821015235","n1821015163","n1821015154","n1821015253","n1821014632","n1821015372","n1821015103","n1821015311","n1821015301","n1821014885","n1821014811","n1821014977","n1821015051","n1821014942","n1821014745","n1821015432","n1821015075","n1821014664","n1821014695","n1821015116","n1821014639","n1821015421","n1821015248","n1821014758","n1821014834","n1821015083","n1821015455","n1821015241","n1821015108","n1821014713","n1821015137","n1821015055","n1821015211","n1821014904","n1821015376","n1821015398","n1821014771","n1821014840","n1821015062","n1819790554","n1819790560","n1819790767","n1819790696","n1819790706","n1819790606","n1819790607","n1819790544","n1819790779","n1819790760","n1819790926","n1819790927","n1819790647","n1819790657","n1819790649","n1819790679","n1819790915","n1819790739","n1819790549","n1819790671","n1819790686","n1819790798","n1819790791","n1819790563","n1819790720","n1819790704","n1819790795","n1819790836","n1819790622","n1819790615","n1819790654","n1819790931","n1819790595","n1819790753","n1819790612","n1819790623","n1819790564","n1819790552","n1819790645","n1819790625","n1819790605","n1819790668","n1819790731","n1819790718","n1819790781","n1819790665","n1819790659","n1819790726","n1819790642","n1819790854","n1819790697","n1819790867","n1819790833","n1819790555","n1819790774","n1819790881","n1819790530","n1819790909","n1819790891","n1819790590","n1819790738","n1819790609","n1819790528","n1819790674","n1819790583","n1819790559","n1819790863","n1819790912","n1819790685","n1819790913"]},"n185955128":{"id":"n185955128","loc":[-85.6189367,41.9519432]},"n185948818":{"id":"n185948818","loc":[-85.616755,41.952231]},"n185978819":{"id":"n185978819","loc":[-85.616773,41.954737]},"n185978821":{"id":"n185978821","loc":[-85.616699,41.954742]},"n2138420714":{"id":"n2138420714","loc":[-85.6176304,41.9515154]},"n2138420715":{"id":"n2138420715","loc":[-85.6177355,41.9515717]},"n2138420716":{"id":"n2138420716","loc":[-85.6192901,41.951573]},"n2138420718":{"id":"n2138420718","loc":[-85.6171481,41.9513579]},"n2138420719":{"id":"n2138420719","loc":[-85.6165981,41.9519199]},"n2138420720":{"id":"n2138420720","loc":[-85.6165719,41.9519922]},"n2138420721":{"id":"n2138420721","loc":[-85.6165832,41.9520757]},"n2138420722":{"id":"n2138420722","loc":[-85.6166355,41.9521453]},"n2138420723":{"id":"n2138420723","loc":[-85.6169161,41.9522788]},"n2138420724":{"id":"n2138420724","loc":[-85.6170882,41.9522538]},"n2138420725":{"id":"n2138420725","loc":[-85.6189204,41.9514674]},"n2138420726":{"id":"n2138420726","loc":[-85.6180346,41.9514735]},"n2138420727":{"id":"n2138420727","loc":[-85.6180362,41.9515719]},"n2138420728":{"id":"n2138420728","loc":[-85.6189204,41.9515727]},"n2138420744":{"id":"n2138420744","loc":[-85.618919,41.9519571]},"n2138420745":{"id":"n2138420745","loc":[-85.6194575,41.9522374]},"n2138420746":{"id":"n2138420746","loc":[-85.6181777,41.9536179]},"n2138420747":{"id":"n2138420747","loc":[-85.6176582,41.9533658]},"n2138420748":{"id":"n2138420748","loc":[-85.6179871,41.9530242]},"n2138420749":{"id":"n2138420749","loc":[-85.618429,41.9532476]},"n2138420750":{"id":"n2138420750","loc":[-85.6185538,41.9531194]},"n2138420751":{"id":"n2138420751","loc":[-85.6180765,41.9528677]},"n2138420752":{"id":"n2138420752","loc":[-85.6180394,41.9528855]},"n2138420753":{"id":"n2138420753","loc":[-85.6193752,41.9521695]},"n2138420754":{"id":"n2138420754","loc":[-85.6181374,41.9535376]},"n2138420755":{"id":"n2138420755","loc":[-85.6179898,41.9535545]},"n2138420756":{"id":"n2138420756","loc":[-85.6177286,41.9534228]},"n2138420757":{"id":"n2138420757","loc":[-85.6181011,41.9530292]},"n2138420759":{"id":"n2138420759","loc":[-85.6185158,41.9531194]},"n2138420760":{"id":"n2138420760","loc":[-85.6191318,41.9520425]},"n2138420761":{"id":"n2138420761","loc":[-85.6182348,41.9529815]},"n2138420762":{"id":"n2138420762","loc":[-85.6184853,41.9524248]},"n2138420763":{"id":"n2138420763","loc":[-85.6186764,41.9525193]},"n2138420764":{"id":"n2138420764","loc":[-85.6189421,41.9526483]},"n2138420765":{"id":"n2138420765","loc":[-85.6182875,41.9531222]},"n2138420766":{"id":"n2138420766","loc":[-85.6179141,41.9535163]},"n2138420767":{"id":"n2138420767","loc":[-85.6178363,41.9535735]},"n185948824":{"id":"n185948824","loc":[-85.6165667,41.9529715]},"n2138420758":{"id":"n2138420758","loc":[-85.6184408,41.953201]},"n2138422349":{"id":"n2138422349","loc":[-85.6175136,41.9533346]},"n2138422350":{"id":"n2138422350","loc":[-85.6171867,41.9531679]},"n2138422351":{"id":"n2138422351","loc":[-85.61722,41.9531305]},"n2138422352":{"id":"n2138422352","loc":[-85.6171889,41.9531158]},"n2138422353":{"id":"n2138422353","loc":[-85.6171733,41.9531284]},"n2138422354":{"id":"n2138422354","loc":[-85.616765,41.9529207]},"n2138422355":{"id":"n2138422355","loc":[-85.6167565,41.9529355]},"n2138422356":{"id":"n2138422356","loc":[-85.6164772,41.9527911]},"n2138422357":{"id":"n2138422357","loc":[-85.6168227,41.9524261]},"n2138422358":{"id":"n2138422358","loc":[-85.6171913,41.9526158]},"n2138422359":{"id":"n2138422359","loc":[-85.6172403,41.9525589]},"n2138422360":{"id":"n2138422360","loc":[-85.6172097,41.952542]},"n2138422361":{"id":"n2138422361","loc":[-85.6173948,41.9523512]},"n2138422362":{"id":"n2138422362","loc":[-85.6174256,41.9523678]},"n2138422363":{"id":"n2138422363","loc":[-85.6174831,41.9523086]},"n2138422364":{"id":"n2138422364","loc":[-85.6173316,41.9522289]},"n2138422365":{"id":"n2138422365","loc":[-85.6174507,41.9521024]},"n2138422366":{"id":"n2138422366","loc":[-85.6174773,41.9521155]},"n2138422367":{"id":"n2138422367","loc":[-85.6176577,41.9519232]},"n2138422368":{"id":"n2138422368","loc":[-85.6176336,41.9519105]},"n2138422369":{"id":"n2138422369","loc":[-85.617747,41.9517861]},"n2138422370":{"id":"n2138422370","loc":[-85.6182675,41.9520559]},"n2138422371":{"id":"n2138422371","loc":[-85.6182105,41.9521219]},"n2138422372":{"id":"n2138422372","loc":[-85.6183863,41.9522203]},"n2138422373":{"id":"n2138422373","loc":[-85.6180984,41.9525266]},"n2138422374":{"id":"n2138422374","loc":[-85.6179159,41.9524295]},"n2138422375":{"id":"n2138422375","loc":[-85.617854,41.9524979]},"n2138422376":{"id":"n2138422376","loc":[-85.6177686,41.9524531]},"n2138422377":{"id":"n2138422377","loc":[-85.6174716,41.9527765]},"n2138422378":{"id":"n2138422378","loc":[-85.6178545,41.9529756]},"n2138425424":{"id":"n2138425424","loc":[-85.6171736,41.9536385]},"n2138425425":{"id":"n2138425425","loc":[-85.6180159,41.9535782]},"n2138425426":{"id":"n2138425426","loc":[-85.6181068,41.9536282]},"n2138425427":{"id":"n2138425427","loc":[-85.6180673,41.9542678]},"n2138425428":{"id":"n2138425428","loc":[-85.6178636,41.9542634]},"n2138425429":{"id":"n2138425429","loc":[-85.6176204,41.9542046]},"n2138425430":{"id":"n2138425430","loc":[-85.6174366,41.9541031]},"n2138425431":{"id":"n2138425431","loc":[-85.6172942,41.9539781]},"n2138425432":{"id":"n2138425432","loc":[-85.6172171,41.9538399]},"n2138425433":{"id":"n2138425433","loc":[-85.6168138,41.9543266]},"n2138425434":{"id":"n2138425434","loc":[-85.6167779,41.9538098]},"n2138425435":{"id":"n2138425435","loc":[-85.6165849,41.9537073]},"n2138425441":{"id":"n2138425441","loc":[-85.616458,41.9543184]},"n2138425442":{"id":"n2138425442","loc":[-85.6166428,41.954345]},"n2138425445":{"id":"n2138425445","loc":[-85.6181332,41.9514117]},"n2138425446":{"id":"n2138425446","loc":[-85.6183263,41.9514111]},"n2138425447":{"id":"n2138425447","loc":[-85.6185033,41.9514102]},"n2138425449":{"id":"n2138425449","loc":[-85.6186809,41.9514093]},"n2138425451":{"id":"n2138425451","loc":[-85.6188681,41.9514082]},"n2138436008":{"id":"n2138436008","loc":[-85.6170474,41.9513604]},"n2138436009":{"id":"n2138436009","loc":[-85.6164937,41.9519586]},"n2138436010":{"id":"n2138436010","loc":[-85.616497,41.9520725]},"n2138436011":{"id":"n2138436011","loc":[-85.6165654,41.9521645]},"n2138436012":{"id":"n2138436012","loc":[-85.6166631,41.9522178]},"n2138436013":{"id":"n2138436013","loc":[-85.6167327,41.9522554]},"n2138436014":{"id":"n2138436014","loc":[-85.6172383,41.9525125]},"n2138439319":{"id":"n2138439319","loc":[-85.6170432,41.9524057]},"n2138439320":{"id":"n2138439320","loc":[-85.617691,41.9517107]},"n2138439321":{"id":"n2138439321","loc":[-85.6177727,41.9516794]},"n2138439322":{"id":"n2138439322","loc":[-85.619085,41.9516811]},"n2138439323":{"id":"n2138439323","loc":[-85.6179432,41.952895]},"n2138439324":{"id":"n2138439324","loc":[-85.6180389,41.9529384]},"n2138439325":{"id":"n2138439325","loc":[-85.6176303,41.9533604]},"n2138439326":{"id":"n2138439326","loc":[-85.6175538,41.9534396]},"n2138439327":{"id":"n2138439327","loc":[-85.6173806,41.9523658]},"n2138439328":{"id":"n2138439328","loc":[-85.6171841,41.9522542]},"n2138439329":{"id":"n2138439329","loc":[-85.6172077,41.9524958]},"n2138439330":{"id":"n2138439330","loc":[-85.6171235,41.9525809]},"n2138439331":{"id":"n2138439331","loc":[-85.6180938,41.9527349]},"n2138439332":{"id":"n2138439332","loc":[-85.6177023,41.9525253]},"n2138439333":{"id":"n2138439333","loc":[-85.6175543,41.9526865]},"n2138439334":{"id":"n2138439334","loc":[-85.6179589,41.9528783]},"n185948820":{"id":"n185948820","loc":[-85.6163249,41.952701]},"n185948822":{"id":"n185948822","loc":[-85.6163757,41.952855]},"n185955123":{"id":"n185955123","loc":[-85.6198103,41.9510408]},"n185958839":{"id":"n185958839","loc":[-85.611651,41.954761]},"n185965033":{"id":"n185965033","loc":[-85.614195,41.954754]},"n185976502":{"id":"n185976502","loc":[-85.617375,41.947559]},"n185976504":{"id":"n185976504","loc":[-85.6174164,41.9510804]},"n185978828":{"id":"n185978828","loc":[-85.613542,41.954756]},"n185978830":{"id":"n185978830","loc":[-85.610373,41.954774]},"n2138420713":{"id":"n2138420713","loc":[-85.6174641,41.9506942]},"n2138420717":{"id":"n2138420717","loc":[-85.6173027,41.9512895]},"n2138420768":{"id":"n2138420768","loc":[-85.61745,41.9501974]},"n2138420773":{"id":"n2138420773","loc":[-85.6174135,41.9489136]},"n2138425436":{"id":"n2138425436","loc":[-85.6159148,41.9538036]},"n2138425437":{"id":"n2138425437","loc":[-85.6159534,41.9539677]},"n2138425438":{"id":"n2138425438","loc":[-85.6160306,41.9540846]},"n2138425439":{"id":"n2138425439","loc":[-85.6161354,41.954181]},"n2138425440":{"id":"n2138425440","loc":[-85.6162733,41.954263]},"n2138425443":{"id":"n2138425443","loc":[-85.6183273,41.9510826]},"n2138425444":{"id":"n2138425444","loc":[-85.6181354,41.9510835]},"n2138425448":{"id":"n2138425448","loc":[-85.6185033,41.9510816]},"n2138425450":{"id":"n2138425450","loc":[-85.6186816,41.9510808]},"n2138425452":{"id":"n2138425452","loc":[-85.6188641,41.9510818]},"n2138435984":{"id":"n2138435984","loc":[-85.6167607,41.9501009]},"n2138436000":{"id":"n2138436000","loc":[-85.6173169,41.947558]},"n2138436001":{"id":"n2138436001","loc":[-85.6173362,41.948883]},"n2138436002":{"id":"n2138436002","loc":[-85.6167791,41.9492952]},"n2138436003":{"id":"n2138436003","loc":[-85.6167543,41.949349]},"n2138436004":{"id":"n2138436004","loc":[-85.6167648,41.9509125]},"n2138436005":{"id":"n2138436005","loc":[-85.6168832,41.9510412]},"n2138436006":{"id":"n2138436006","loc":[-85.6170045,41.9511417]},"n2138436007":{"id":"n2138436007","loc":[-85.6170624,41.9512483]},"n2138436017":{"id":"n2138436017","loc":[-85.6168094,41.9492729]},"n2138436021":{"id":"n2138436021","loc":[-85.6167553,41.9494886]},"n2138436023":{"id":"n2138436023","loc":[-85.6167585,41.9499707]},"n2138436025":{"id":"n2138436025","loc":[-85.6167567,41.9497018]},"w203838284":{"id":"w203838284","tags":{"area":"yes","leisure":"pitch","sport":"baseball"},"nodes":["n2138425424","n2138425425","n2138425426","n2138425427","n2138425428","n2138425429","n2138425430","n2138425431","n2138425432","n2138425424"]},"w203837928":{"id":"w203837928","tags":{"highway":"service"},"nodes":["n2138420717","n2138420718","n2138420719","n2138420720","n2138420721","n2138420722","n185948818","n2138420723","n2138420724","n2138420715"]},"w203839364":{"id":"w203839364","tags":{"highway":"footway"},"nodes":["n2138439331","n2138439332"]},"w203837932":{"id":"w203837932","tags":{"amenity":"parking","area":"yes"},"nodes":["n2138420744","n2138420745","n2138420746","n2138420747","n2138420748","n2138420749","n2138420750","n2138420751","n2138420744"]},"w203839362":{"id":"w203839362","tags":{"highway":"footway"},"nodes":["n2138439327","n2138439328"]},"w203839363":{"id":"w203839363","tags":{"highway":"footway"},"nodes":["n2138439329","n2138439330"]},"w203837933":{"id":"w203837933","tags":{"highway":"service","service":"parking_aisle"},"nodes":["n185955128","n2138420760","n2138420753","n2138420764","n2138420759","n2138420758","n2138420754","n2138420755","n2138420766","n2138420756"]},"w203837936":{"id":"w203837936","tags":{"highway":"service","service":"parking_aisle"},"nodes":["n2138420765","n2138420766"]},"w17966364":{"id":"w17966364","tags":{"access":"private","highway":"service","name":"Collins Dr"},"nodes":["n185961362","n185976502","n2138420773","n2138420768","n2138420713","n185976504","n2138420717","n2138420714","n2138420715","n2138420727","n2138420728","n2138420716"]},"w203838040":{"id":"w203838040","tags":{"amenity":"school","area":"yes","building":"yes","name":"Three Rivers Middle School"},"nodes":["n2138422349","n2138422350","n2138422351","n2138422352","n2138422353","n2138422354","n2138422355","n2138422356","n2138422357","n2138439330","n2138422358","n2138422359","n2138422360","n2138436014","n2138439327","n2138422361","n2138422362","n2138422363","n2138422364","n2138422365","n2138422366","n2138422367","n2138422368","n2138422369","n2138422370","n2138422371","n2138422372","n2138422373","n2138422374","n2138422375","n2138422376","n2138439332","n2138439333","n2138422377","n2138422378","n2138422349"]},"w17964049":{"id":"w17964049","tags":{"highway":"service"},"nodes":["n185955120","n185955123","n2138420716","n185955128","n2138420762","n2138420752","n2138420761","n2138420759"]},"w41074899":{"id":"w41074899","tags":{"highway":"secondary","name":"E Hoffman St","ref":"M 60"},"nodes":["n185978817","n185978819","n185978821","n185965033","n185978828","n185958839","n185978830"]},"w203839365":{"id":"w203839365","tags":{"highway":"footway"},"nodes":["n2138439333","n2138439334"]},"w203837935":{"id":"w203837935","tags":{"highway":"service","service":"parking_aisle"},"nodes":["n2138420762","n2138420763","n2138420764"]},"w203838287":{"id":"w203838287","tags":{"area":"yes","leisure":"pitch","sport":"tennis"},"nodes":["n2138425446","n2138425447","n2138425448","n2138425443","n2138425446"]},"w203837934":{"id":"w203837934","tags":{"highway":"service","service":"parking_aisle"},"nodes":["n2138420760","n2138420763","n2138420761"]},"w203838289":{"id":"w203838289","tags":{"area":"yes","leisure":"pitch","sport":"tennis"},"nodes":["n2138425449","n2138425451","n2138425452","n2138425450","n2138425449"]},"w17963047":{"id":"w17963047","tags":{"highway":"service"},"nodes":["n185948818","n2138436013","n185948820","n185948822","n185948824","n2138439326","n2138420767","n2138420766"]},"w203839091":{"id":"w203839091","tags":{"highway":"footway"},"nodes":["n185976502","n2138436000","n2138436001","n2138436017","n2138436002","n2138436003","n2138436021","n2138436025","n2138436023","n2138435984","n2138436004","n2138436005","n2138436006","n2138436007","n2138436008","n2138436009","n2138436010","n2138436011","n2138436012","n2138436013","n2138439319","n2138439329","n2138436014"]},"w204830797":{"id":"w204830797","tags":{"highway":"service","service":"parking_aisle"},"nodes":["n2138420756","n2138420757","n2138420765","n2138420758"]},"w203838288":{"id":"w203838288","tags":{"area":"yes","leisure":"pitch","sport":"tennis"},"nodes":["n2138425447","n2138425449","n2138425450","n2138425448","n2138425447"]},"w203838285":{"id":"w203838285","tags":{"area":"yes","leisure":"pitch","sport":"baseball"},"nodes":["n2138425433","n2138425434","n2138425435","n2138425436","n2138425437","n2138425438","n2138425439","n2138425440","n2138425441","n2138425442","n2138425433"]},"w203838286":{"id":"w203838286","tags":{"area":"yes","leisure":"pitch","sport":"tennis"},"nodes":["n2138425443","n2138425444","n2138425445","n2138425446","n2138425443"]},"w203837929":{"id":"w203837929","tags":{"amenity":"parking","area":"yes"},"nodes":["n2138420725","n2138420726","n2138420727","n2138420728","n2138420725"]},"w203839361":{"id":"w203839361","tags":{"highway":"footway"},"nodes":["n2138439319","n2138439328","n2138439320","n2138439321","n2138439322","n2138439331","n2138439334","n2138439323","n2138439324","n2138439325","n2138439326"]},"n394381698":{"id":"n394381698","loc":[-85.614471,41.954755]},"n394381699":{"id":"n394381699","loc":[-85.6152,41.954744]},"n394381700":{"id":"n394381700","loc":[-85.615201,41.954081]},"n394381701":{"id":"n394381701","loc":[-85.614426,41.954042]},"n394381702":{"id":"n394381702","loc":[-85.616319,41.954749]},"n394381704":{"id":"n394381704","loc":[-85.616152,41.954752]},"n394381706":{"id":"n394381706","loc":[-85.615201,41.95483]},"n394490775":{"id":"n394490775","loc":[-85.613971,41.954839]},"n394490782":{"id":"n394490782","loc":[-85.614372,41.954841]},"n185958835":{"id":"n185958835","loc":[-85.611615,41.953704]},"n185958837":{"id":"n185958837","loc":[-85.611636,41.953938]},"n185958842":{"id":"n185958842","loc":[-85.611187,41.951686]},"n185958844":{"id":"n185958844","loc":[-85.611087,41.951741]},"n185958845":{"id":"n185958845","loc":[-85.611034,41.951852]},"n185958847":{"id":"n185958847","loc":[-85.611016,41.95196]},"n185958849":{"id":"n185958849","loc":[-85.610989,41.95328]},"n185958851":{"id":"n185958851","loc":[-85.611021,41.953484]},"n185958852":{"id":"n185958852","loc":[-85.611091,41.953603]},"n185958853":{"id":"n185958853","loc":[-85.6112,41.953661]},"n185958855":{"id":"n185958855","loc":[-85.611364,41.953686]},"n185965031":{"id":"n185965031","loc":[-85.614204,41.953696]},"n185965032":{"id":"n185965032","loc":[-85.6142,41.953978]},"n185965062":{"id":"n185965062","loc":[-85.614617,41.951639]},"n185965064":{"id":"n185965064","loc":[-85.61463,41.951852]},"n185965066":{"id":"n185965066","loc":[-85.614642,41.953436]},"n185965068":{"id":"n185965068","loc":[-85.6146,41.953551]},"n185965071":{"id":"n185965071","loc":[-85.614487,41.95363]},"n185965073":{"id":"n185965073","loc":[-85.614354,41.953672]},"n185966288":{"id":"n185966288","loc":[-85.61179,41.953695]},"n185966290":{"id":"n185966290","loc":[-85.612232,41.953685]},"n185966293":{"id":"n185966293","loc":[-85.613438,41.953677]},"n185966349":{"id":"n185966349","loc":[-85.611323,41.951653]},"n185966351":{"id":"n185966351","loc":[-85.611892,41.951642]},"n185966352":{"id":"n185966352","loc":[-85.612216,41.951641]},"n185966353":{"id":"n185966353","loc":[-85.613111,41.951639]},"n185966354":{"id":"n185966354","loc":[-85.613396,41.95164]},"n185966355":{"id":"n185966355","loc":[-85.614221,41.95164]},"n185973839":{"id":"n185973839","loc":[-85.61341,41.951919]},"n185973840":{"id":"n185973840","loc":[-85.613438,41.953308]},"n185980222":{"id":"n185980222","loc":[-85.613781,41.955164]},"n185980223":{"id":"n185980223","loc":[-85.613815,41.955237]},"n185980225":{"id":"n185980225","loc":[-85.613837,41.955316]},"n185990345":{"id":"n185990345","loc":[-85.612211,41.951977]},"n185955743":{"id":"n185955743","loc":[-85.613873,41.95635]},"n185980227":{"id":"n185980227","loc":[-85.613851,41.955415]},"n185980229":{"id":"n185980229","loc":[-85.613918,41.957134]},"n394381703":{"id":"n394381703","loc":[-85.616287,41.955674]},"n394381705":{"id":"n394381705","loc":[-85.615164,41.955676]},"n394490777":{"id":"n394490777","loc":[-85.613973,41.955979]},"n394490780":{"id":"n394490780","loc":[-85.614364,41.955987]},"w17965307":{"id":"w17965307","tags":{"highway":"residential","name":"Bates Ave"},"nodes":["n185958842","n185966349","n185966351","n185966352","n185966353","n185966354","n185966355","n185965062"]},"w17967957":{"id":"w17967957","tags":{"highway":"residential","name":"Krum Ave"},"nodes":["n185966352","n185990345","n185966290"]},"w17964508":{"id":"w17964508","tags":{"highway":"residential","name":"Blossom Dr"},"nodes":["n185958842","n185958844","n185958845","n185958847","n185958849","n185958851","n185958852","n185958853","n185958855","n185958835"]},"w17964507":{"id":"w17964507","tags":{"highway":"residential","name":"Blossom Dr"},"nodes":["n185958835","n185958837","n185958839"]},"w34367080":{"id":"w34367080","tags":{"admin_level":"8","boundary":"administrative"},"nodes":["n394381699","n394381706","n394381705","n394381703","n394381702","n394381704","n394381699"]},"w17965302":{"id":"w17965302","tags":{"highway":"residential","name":"Clausen Ave"},"nodes":["n185958835","n185966288","n185966290","n185966293","n185965031"]},"w17965156":{"id":"w17965156","tags":{"highway":"residential","name":"Orchard Dr"},"nodes":["n185965062","n185965064","n185965066","n185965068","n185965071","n185965073","n185965031"]},"w34369812":{"id":"w34369812","tags":{"admin_level":"8","boundary":"administrative"},"nodes":["n394490775","n394490777","n394490780","n394490782","n394490775"]},"w17965151":{"id":"w17965151","tags":{"highway":"residential","name":"Orchard Dr"},"nodes":["n185965031","n185965032","n185965033"]},"w17966756":{"id":"w17966756","tags":{"access":"private","highway":"service","name":"Lockport Dr"},"nodes":["n185978828","n185980222","n185980223","n185980225","n185980227","n185955743","n185980229"]},"w17966056":{"id":"w17966056","tags":{"highway":"residential","name":"Angell Ave"},"nodes":["n185966354","n185973839","n185973840","n185966293"]},"w34367079":{"id":"w34367079","tags":{"admin_level":"8","boundary":"administrative"},"nodes":["n394381700","n394381701","n394381698","n394381699","n394381700"]},"n185955744":{"id":"n185955744","loc":[-85.611753,41.956208]},"n185988932":{"id":"n185988932","loc":[-85.6159,41.956336]},"n185988934":{"id":"n185988934","loc":[-85.6159158,41.9590646]},"n185988935":{"id":"n185988935","loc":[-85.6157358,41.959364],"tags":{"highway":"turning_circle"}},"n2138447007":{"id":"n2138447007","loc":[-85.6130784,41.9590689]},"n2138447008":{"id":"n2138447008","loc":[-85.6133328,41.9593805]},"n2138447003":{"id":"n2138447003","loc":[-85.610238,41.9547745]},"n2138447004":{"id":"n2138447004","loc":[-85.6102652,41.9566041]},"n2138447005":{"id":"n2138447005","loc":[-85.610325,41.9568823]},"n2138447006":{"id":"n2138447006","loc":[-85.6105644,41.9571383]},"n2138447009":{"id":"n2138447009","loc":[-85.6135946,41.959948]},"n2138447010":{"id":"n2138447010","loc":[-85.6136071,41.9629372]},"n2138447011":{"id":"n2138447011","loc":[-85.6134392,41.9633182]},"n2138447012":{"id":"n2138447012","loc":[-85.6130151,41.9636073]},"n2138447013":{"id":"n2138447013","loc":[-85.6122729,41.9637125]},"n2138447014":{"id":"n2138447014","loc":[-85.6056682,41.963752]},"w17964174":{"id":"w17964174","tags":{"access":"private","highway":"service"},"nodes":["n185955743","n185955744"]},"w17967743":{"id":"w17967743","tags":{"access":"private","highway":"service","name":"Manistee River Rd"},"nodes":["n185971574","n185988932","n185971407","n185981301","n185967987","n185988934","n185988935"]},"w203839666":{"id":"w203839666","tags":{"highway":"residential","name":"Hov Aire Drive"},"nodes":["n2138447003","n2138447004","n2138447005","n2138447006","n2138447007","n2138447008","n2138447009","n2138447010","n2138447011","n2138447012","n2138447013","n2138447014"]}}';iD.data = {"deprecated":[{"old":{"amenity":"firepit"},"replace":{"leisure":"firepit"}},{"old":{"barrier":"wire_fence"},"replace":{"barrier":"fence","fence_type":"chain"}},{"old":{"barrier":"wood_fence"},"replace":{"barrier":"fence","fence_type":"wood"}},{"old":{"highway":"ford"},"replace":{"ford":"yes"}},{"old":{"highway":"stile"},"replace":{"barrier":"stile"}},{"old":{"highway":"incline"},"replace":{"highway":"road","incline":"up"}},{"old":{"highway":"incline_steep"},"replace":{"highway":"road","incline":"up"}},{"old":{"highway":"unsurfaced"},"replace":{"highway":"road","incline":"unpaved"}},{"old":{"landuse":"wood"},"replace":{"landuse":"forest","natural":"wood"}},{"old":{"natural":"marsh"},"replace":{"natural":"wetland","wetland":"marsh"}},{"old":{"power_source":"*"},"replace":{"generator:source":"$1"}},{"old":{"power_rating":"*"},"replace":{"generator:output":"$1"}},{"old":{"shop":"organic"},"replace":{"shop":"supermarket","organic":"only"}}],"discarded":["created_by","odbl","odbl:note","tiger:upload_uuid","tiger:tlid","tiger:source","tiger:separated","geobase:datasetName","geobase:uuid","sub_sea:type","KSJ2:ADS","KSJ2:ARE","KSJ2:AdminArea","KSJ2:COP_label","KSJ2:DFD","KSJ2:INT","KSJ2:INT_label","KSJ2:LOC","KSJ2:LPN","KSJ2:OPC","KSJ2:PubFacAdmin","KSJ2:RAC","KSJ2:RAC_label","KSJ2:RIC","KSJ2:RIN","KSJ2:WSC","KSJ2:coordinate","KSJ2:curve_id","KSJ2:curve_type","KSJ2:filename","KSJ2:lake_id","KSJ2:lat","KSJ2:long","KSJ2:river_id","yh:LINE_NAME","yh:LINE_NUM","yh:STRUCTURE","yh:TOTYUMONO","yh:TYPE","yh:WIDTH","yh:WIDTH_RANK","SK53_bulk:load"],"wikipedia":[["Abkhazian","Аҧсшәа","ab"],["Achinese","Acèh","ace"],["Afrikaans","Afrikaans","af"],["Akan","Akan","ak"],["Alemannisch","Alemannisch","als"],["Amharic","አማርኛ","am"],["Aragonese","aragonés","an"],["Old English","Ænglisc","ang"],["Arabic","العربية","ar"],["Aramaic","ܐܪܡܝܐ","arc"],["Egyptian Arabic","مصرى","arz"],["Assamese","অসমীয়া","as"],["Asturian","asturianu","ast"],["Avaric","авар","av"],["Aymara","Aymar aru","ay"],["Azerbaijani","azərbaycanca","az"],["South Azerbaijani","تۆرکجه","azb"],["Bashkir","башҡортса","ba"],["Bavarian","Boarisch","bar"],["Samogitian","žemaitėška","bat-smg"],["Bikol Central","Bikol Central","bcl"],["Belarusian","беларуская","be"],["беларуская (тарашкевіца)","беларуская (тарашкевіца)","be-x-old"],["Bulgarian","български","bg"],["भोजपुरी","भोजपुरी","bh"],["Bislama","Bislama","bi"],["Banjar","Bahasa Banjar","bjn"],["Bambara","bamanankan","bm"],["Bengali","বাংলা","bn"],["Tibetan","བོད་ཡིག","bo"],["Bishnupriya","বিষ্ণুপ্রিয়া মণিপুরী","bpy"],["Breton","brezhoneg","br"],["Bosnian","bosanski","bs"],["Buginese","ᨅᨔ ᨕᨘᨁᨗ","bug"],["буряад","буряад","bxr"],["Catalan","català","ca"],["Chavacano de Zamboanga","Chavacano de Zamboanga","cbk-zam"],["Min Dong Chinese","Mìng-dĕ̤ng-ngṳ̄","cdo"],["Chechen","нохчийн","ce"],["Cebuano","Cebuano","ceb"],["Chamorro","Chamoru","ch"],["Cherokee","ᏣᎳᎩ","chr"],["Cheyenne","Tsetsêhestâhese","chy"],["Central Kurdish","کوردیی ناوەندی","ckb"],["Corsican","corsu","co"],["Cree","Nēhiyawēwin / ᓀᐦᐃᔭᐍᐏᐣ","cr"],["Crimean Turkish","qırımtatarca","crh"],["Czech","čeština","cs"],["Kashubian","kaszëbsczi","csb"],["Church Slavic","словѣньскъ / ⰔⰎⰑⰂⰡⰐⰠⰔⰍⰟ","cu"],["Chuvash","Чӑвашла","cv"],["Welsh","Cymraeg","cy"],["Danish","dansk","da"],["German","Deutsch","de"],["Zazaki","Zazaki","diq"],["Lower Sorbian","dolnoserbski","dsb"],["Divehi","ދިވެހިބަސް","dv"],["Dzongkha","ཇོང་ཁ","dz"],["Ewe","eʋegbe","ee"],["Greek","Ελληνικά","el"],["Emiliano-Romagnolo","emiliàn e rumagnòl","eml"],["English","English","en"],["Esperanto","Esperanto","eo"],["Spanish","español","es"],["Estonian","eesti","et"],["Basque","euskara","eu"],["Extremaduran","estremeñu","ext"],["Persian","فارسی","fa"],["Fulah","Fulfulde","ff"],["Finnish","suomi","fi"],["Võro","Võro","fiu-vro"],["Fijian","Na Vosa Vakaviti","fj"],["Faroese","føroyskt","fo"],["French","français","fr"],["Arpitan","arpetan","frp"],["Northern Frisian","Nordfriisk","frr"],["Friulian","furlan","fur"],["Western Frisian","Frysk","fy"],["Irish","Gaeilge","ga"],["Gagauz","Gagauz","gag"],["Gan Chinese","贛語","gan"],["Scottish Gaelic","Gàidhlig","gd"],["Galician","galego","gl"],["Gilaki","گیلکی","glk"],["Guarani","Avañe'ẽ","gn"],["Goan Konkani","गोवा कोंकणी / Gova Konknni","gom"],["Gothic","𐌲𐌿𐍄𐌹𐍃𐌺","got"],["Gujarati","ગુજરાતી","gu"],["Manx","Gaelg","gv"],["Hausa","Hausa","ha"],["Hakka Chinese","客家語/Hak-kâ-ngî","hak"],["Hawaiian","Hawai`i","haw"],["Hebrew","עברית","he"],["Hindi","हिन्दी","hi"],["Fiji Hindi","Fiji Hindi","hif"],["Croatian","hrvatski","hr"],["Upper Sorbian","hornjoserbsce","hsb"],["Haitian","Kreyòl ayisyen","ht"],["Hungarian","magyar","hu"],["Armenian","Հայերեն","hy"],["Interlingua","interlingua","ia"],["Indonesian","Bahasa Indonesia","id"],["Interlingue","Interlingue","ie"],["Igbo","Igbo","ig"],["Inupiaq","Iñupiak","ik"],["Iloko","Ilokano","ilo"],["Ido","Ido","io"],["Icelandic","íslenska","is"],["Italian","italiano","it"],["Inuktitut","ᐃᓄᒃᑎᑐᑦ/inuktitut","iu"],["Japanese","日本語","ja"],["Lojban","Lojban","jbo"],["Javanese","Basa Jawa","jv"],["Georgian","ქართული","ka"],["Kara-Kalpak","Qaraqalpaqsha","kaa"],["Kabyle","Taqbaylit","kab"],["Kabardian","Адыгэбзэ","kbd"],["Kongo","Kongo","kg"],["Kikuyu","Gĩkũyũ","ki"],["Kazakh","қазақша","kk"],["Kalaallisut","kalaallisut","kl"],["Khmer","ភាសាខ្មែរ","km"],["Kannada","ಕನ್ನಡ","kn"],["Korean","한국어","ko"],["Komi-Permyak","Перем Коми","koi"],["Karachay-Balkar","къарачай-малкъар","krc"],["Kashmiri","कॉशुर / کٲشُر","ks"],["Colognian","Ripoarisch","ksh"],["Kurdish","Kurdî","ku"],["Komi","коми","kv"],["Cornish","kernowek","kw"],["Kyrgyz","Кыргызча","ky"],["Latin","Latina","la"],["Ladino","Ladino","lad"],["Luxembourgish","Lëtzebuergesch","lb"],["лакку","лакку","lbe"],["Lezghian","лезги","lez"],["Ganda","Luganda","lg"],["Limburgish","Limburgs","li"],["Ligurian","Ligure","lij"],["Lombard","lumbaart","lmo"],["Lingala","lingála","ln"],["Lao","ລາວ","lo"],["Northern Luri","لۊری شومالی","lrc"],["Lithuanian","lietuvių","lt"],["Latgalian","latgaļu","ltg"],["Latvian","latviešu","lv"],["Maithili","मैथिली","mai"],["Basa Banyumasan","Basa Banyumasan","map-bms"],["Moksha","мокшень","mdf"],["Malagasy","Malagasy","mg"],["Eastern Mari","олык марий","mhr"],["Maori","Māori","mi"],["Minangkabau","Baso Minangkabau","min"],["Macedonian","македонски","mk"],["Malayalam","മലയാളം","ml"],["Mongolian","монгол","mn"],["Marathi","मराठी","mr"],["Western Mari","кырык мары","mrj"],["Malay","Bahasa Melayu","ms"],["Maltese","Malti","mt"],["Mirandese","Mirandés","mwl"],["Burmese","မြန်မာဘာသာ","my"],["Erzya","эрзянь","myv"],["Mazanderani","مازِرونی","mzn"],["Nauru","Dorerin Naoero","na"],["Nāhuatl","Nāhuatl","nah"],["Neapolitan","Napulitano","nap"],["Low German","Plattdüütsch","nds"],["Low Saxon (Netherlands)","Nedersaksies","nds-nl"],["Nepali","नेपाली","ne"],["Newari","नेपाल भाषा","new"],["Dutch","Nederlands","nl"],["Norwegian Nynorsk","norsk nynorsk","nn"],["Norwegian","norsk bokmål","no"],["Novial","Novial","nov"],["Nouormand","Nouormand","nrm"],["Northern Sotho","Sesotho sa Leboa","nso"],["Navajo","Diné bizaad","nv"],["Nyanja","Chi-Chewa","ny"],["Occitan","occitan","oc"],["Oromo","Oromoo","om"],["Oriya","ଓଡ଼ିଆ","or"],["Ossetic","Ирон","os"],["Punjabi","ਪੰਜਾਬੀ","pa"],["Pangasinan","Pangasinan","pag"],["Pampanga","Kapampangan","pam"],["Papiamento","Papiamentu","pap"],["Picard","Picard","pcd"],["Pennsylvania German","Deitsch","pdc"],["Palatine German","Pälzisch","pfl"],["Pali","पालि","pi"],["Norfuk / Pitkern","Norfuk / Pitkern","pih"],["Polish","polski","pl"],["Piedmontese","Piemontèis","pms"],["Western Punjabi","پنجابی","pnb"],["Pontic","Ποντιακά","pnt"],["Pashto","پښتو","ps"],["Portuguese","português","pt"],["Quechua","Runa Simi","qu"],["Romansh","rumantsch","rm"],["Romani","Romani","rmy"],["Rundi","Kirundi","rn"],["Romanian","română","ro"],["Aromanian","armãneashti","roa-rup"],["tarandíne","tarandíne","roa-tara"],["Russian","русский","ru"],["Rusyn","русиньскый","rue"],["Kinyarwanda","Kinyarwanda","rw"],["Sanskrit","संस्कृतम्","sa"],["Sakha","саха тыла","sah"],["Sardinian","sardu","sc"],["Sicilian","sicilianu","scn"],["Scots","Scots","sco"],["Sindhi","سنڌي","sd"],["Northern Sami","sámegiella","se"],["Sango","Sängö","sg"],["Serbo-Croatian","srpskohrvatski / српскохрватски","sh"],["Sinhala","සිංහල","si"],["Simple English","Simple English","simple"],["Slovak","slovenčina","sk"],["Slovenian","slovenščina","sl"],["Samoan","Gagana Samoa","sm"],["Shona","chiShona","sn"],["Somali","Soomaaliga","so"],["Albanian","shqip","sq"],["Serbian","српски / srpski","sr"],["Sranan Tongo","Sranantongo","srn"],["Swati","SiSwati","ss"],["Southern Sotho","Sesotho","st"],["Saterland Frisian","Seeltersk","stq"],["Sundanese","Basa Sunda","su"],["Swedish","svenska","sv"],["Swahili","Kiswahili","sw"],["Silesian","ślůnski","szl"],["Tamil","தமிழ்","ta"],["Telugu","తెలుగు","te"],["Tetum","tetun","tet"],["Tajik","тоҷикӣ","tg"],["Thai","ไทย","th"],["Tigrinya","ትግርኛ","ti"],["Turkmen","Türkmençe","tk"],["Tagalog","Tagalog","tl"],["Tswana","Setswana","tn"],["Tongan","lea faka-Tonga","to"],["Tok Pisin","Tok Pisin","tpi"],["Turkish","Türkçe","tr"],["Tsonga","Xitsonga","ts"],["Tatar","татарча/tatarça","tt"],["Tumbuka","chiTumbuka","tum"],["Twi","Twi","tw"],["Tahitian","reo tahiti","ty"],["Tuvinian","тыва дыл","tyv"],["Udmurt","удмурт","udm"],["Uyghur","ئۇيغۇرچە / Uyghurche","ug"],["Ukrainian","українська","uk"],["Urdu","اردو","ur"],["Uzbek","oʻzbekcha/ўзбекча","uz"],["Venda","Tshivenda","ve"],["Venetian","vèneto","vec"],["Veps","vepsän kel’","vep"],["Vietnamese","Tiếng Việt","vi"],["West Flemish","West-Vlams","vls"],["Volapük","Volapük","vo"],["Walloon","walon","wa"],["Waray","Winaray","war"],["Wolof","Wolof","wo"],["Wu Chinese","吴语","wuu"],["Kalmyk","хальмг","xal"],["Xhosa","isiXhosa","xh"],["Mingrelian","მარგალური","xmf"],["Yiddish","ייִדיש","yi"],["Yoruba","Yorùbá","yo"],["Zhuang","Vahcuengh","za"],["Zeelandic","Zeêuws","zea"],["Chinese","中文","zh"],["Classical Chinese","文言","zh-classical"],["Chinese (Min Nan)","Bân-lâm-gú","zh-min-nan"],["Cantonese","粵語","zh-yue"],["Zulu","isiZulu","zu"]],"imperial":{"type":"FeatureCollection","features":[{"type":"Feature","properties":{"id":0},"geometry":{"type":"MultiPolygon","coordinates":[[[[-1.426496,50.639342],[-1.445953,50.648139],[-1.452789,50.654283],[-1.485951,50.669338],[-1.497426,50.672309],[-1.535146,50.669379],[-1.551503,50.665107],[-1.569488,50.658026],[-1.545318,50.686103],[-1.50593,50.707709],[-1.418691,50.733791],[-1.420888,50.730455],[-1.423451,50.7237],[-1.425364,50.72012],[-1.400868,50.721991],[-1.377553,50.734198],[-1.343495,50.761054],[-1.318512,50.772162],[-1.295766,50.773179],[-1.144276,50.733791],[-1.119537,50.734198],[-1.10912,50.732856],[-1.097035,50.726955],[-1.096425,50.724433],[-1.097646,50.71601],[-1.097035,50.713324],[-1.094228,50.712633],[-1.085561,50.714016],[-1.082753,50.713324],[-1.062327,50.692816],[-1.062327,50.685289],[-1.066965,50.685248],[-1.069651,50.683498],[-1.071889,50.680976],[-1.075307,50.678534],[-1.112701,50.671454],[-1.128651,50.666449],[-1.156361,50.650784],[-1.162221,50.645982],[-1.164703,50.640937],[-1.164666,50.639543],[-1.426496,50.639342]]],[[[-7.240314,55.050389],[-7.013736,55.1615],[-6.958913,55.20349],[-6.571562,55.268366],[-6.509633,55.31398],[-6.226158,55.344406],[-6.07105,55.25001],[-5.712696,55.017635],[-5.242021,54.415204],[-5.695554,54.14284],[-5.72473,54.07455],[-6.041633,54.006238],[-6.153953,54.054931],[-6.220539,54.098803],[-6.242502,54.099758],[-6.263661,54.104682],[-6.269887,54.097927],[-6.28465,54.105226],[-6.299585,54.104037],[-6.313796,54.099696],[-6.327128,54.097888],[-6.338962,54.102952],[-6.346662,54.109877],[-6.354827,54.110652],[-6.368108,54.097319],[-6.369348,54.091118],[-6.367643,54.083418],[-6.366919,54.075098],[-6.371157,54.066778],[-6.377513,54.063264],[-6.401026,54.060887],[-6.426761,54.05541],[-6.433892,54.055306],[-6.4403,54.057993],[-6.446243,54.062438],[-6.450222,54.066675],[-6.450894,54.068432],[-6.47854,54.067709],[-6.564013,54.04895],[-6.571868,54.049519],[-6.587164,54.053343],[-6.595071,54.052412],[-6.60029,54.04895],[-6.605217,54.044475],[-6.610987,54.039235],[-6.616465,54.037271],[-6.630624,54.041819],[-6.657289,54.061146],[-6.672534,54.068432],[-6.657082,54.091945],[-6.655791,54.103314],[-6.666436,54.114786],[-6.643957,54.131839],[-6.634552,54.150133],[-6.640339,54.168013],[-6.648448,54.173665],[-6.663025,54.183826],[-6.683954,54.194368],[-6.694651,54.197985],[-6.706537,54.198915],[-6.717234,54.195143],[-6.724779,54.188631],[-6.73284,54.183567],[-6.744777,54.184187],[-6.766481,54.192352],[-6.787824,54.202998],[-6.807358,54.21633],[-6.823946,54.23235],[-6.829733,54.242375],[-6.833196,54.25209],[-6.837743,54.260513],[-6.846683,54.266456],[-6.882185,54.277257],[-6.864667,54.282734],[-6.856657,54.292811],[-6.858414,54.307332],[-6.870015,54.326001],[-6.879705,54.341594],[-6.885957,54.345624],[-6.897895,54.346193],[-6.905956,54.349035],[-6.915051,54.365933],[-6.922028,54.372703],[-6.984091,54.403089],[-7.017836,54.413166],[-7.049255,54.411512],[-7.078504,54.394717],[-7.127028,54.349759],[-7.159894,54.335186],[-7.168059,54.335031],[-7.185629,54.336943],[-7.18947,54.335692],[-7.19245,54.334721],[-7.193949,54.329967],[-7.191468,54.323869],[-7.187644,54.318804],[-7.185009,54.317254],[-7.184647,54.316634],[-7.192399,54.307384],[-7.193691,54.307539],[-7.199168,54.303457],[-7.206661,54.304903],[-7.211467,54.30418],[-7.209038,54.293431],[-7.1755,54.283664],[-7.181495,54.269763],[-7.14589,54.25209],[-7.159739,54.24067],[-7.153331,54.224237],[-7.174725,54.216072],[-7.229502,54.207545],[-7.240871,54.202326],[-7.249088,54.197416],[-7.255496,54.190854],[-7.261128,54.18088],[-7.256322,54.176901],[-7.247021,54.17225],[-7.24578,54.166979],[-7.265366,54.16114],[-7.26087,54.151166],[-7.263505,54.140986],[-7.27074,54.132253],[-7.280042,54.126155],[-7.293788,54.122021],[-7.297353,54.125896],[-7.29632,54.134991],[-7.296423,54.146515],[-7.295028,54.155404],[-7.292134,54.162638],[-7.295545,54.165119],[-7.325982,54.154577],[-7.333165,54.149409],[-7.333165,54.142743],[-7.310324,54.114683],[-7.316489,54.11428],[-7.326964,54.113597],[-7.375488,54.123312],[-7.390216,54.121194],[-7.39466,54.121917],[-7.396624,54.126258],[-7.403962,54.135043],[-7.41223,54.136438],[-7.422255,54.135456],[-7.425769,54.136955],[-7.414659,54.145688],[-7.439619,54.146929],[-7.480753,54.127653],[-7.502302,54.125121],[-7.609014,54.139901],[-7.620796,54.144965],[-7.624052,54.153336],[-7.625706,54.162173],[-7.632682,54.168529],[-7.70477,54.200362],[-7.722599,54.202326],[-7.782078,54.2],[-7.836959,54.204341],[-7.856441,54.211421],[-7.86967,54.226872],[-7.873649,54.271055],[-7.880264,54.287023],[-7.894966,54.293586],[-7.93411,54.297049],[-7.942075,54.298873],[-7.950802,54.300873],[-7.96801,54.31219],[-7.981033,54.326556],[-8.002194,54.357923],[-8.03134,54.358027],[-8.05648,54.365882],[-8.079941,54.380196],[-8.122419,54.415233],[-8.146346,54.430736],[-8.156035,54.439055],[-8.158128,54.447117],[-8.161177,54.454817],[-8.173837,54.461741],[-8.168467,54.463477],[-8.15017,54.46939],[-8.097046,54.478588],[-8.072448,54.487063],[-8.060976,54.493316],[-8.05586,54.497553],[-8.043561,54.512229],[-8.023278,54.529696],[-8.002194,54.543442],[-7.926411,54.533055],[-7.887137,54.532125],[-7.848844,54.54091],[-7.749264,54.596152],[-7.707871,54.604162],[-7.707944,54.604708],[-7.707951,54.604763],[-7.710558,54.624264],[-7.721204,54.625866],[-7.736758,54.619251],[-7.753553,54.614497],[-7.769159,54.618011],[-7.801199,54.634806],[-7.814996,54.639457],[-7.822541,54.638113],[-7.838044,54.63124],[-7.846416,54.631447],[-7.85427,54.636408],[-7.864347,54.649069],[-7.872771,54.652221],[-7.890082,54.655063],[-7.906619,54.661316],[-7.914835,54.671651],[-7.907135,54.686689],[-7.913233,54.688653],[-7.929666,54.696714],[-7.880109,54.711029],[-7.845899,54.731027],[-7.832153,54.730614],[-7.803576,54.716145],[-7.770503,54.706016],[-7.736603,54.707463],[-7.70229,54.718883],[-7.667512,54.738779],[-7.649683,54.744877],[-7.61537,54.739347],[-7.585398,54.744722],[-7.566639,54.738675],[-7.556149,54.738365],[-7.543075,54.741673],[-7.543023,54.743791],[-7.548398,54.747202],[-7.551705,54.754695],[-7.549741,54.779603],[-7.543385,54.793091],[-7.470831,54.845284],[-7.45507,54.863009],[-7.444735,54.884455],[-7.444735,54.894893],[-7.448972,54.920318],[-7.445251,54.932152],[-7.436983,54.938301],[-7.417139,54.943056],[-7.415755,54.944372],[-7.408665,54.951117],[-7.407424,54.959437],[-7.413109,54.984965],[-7.409078,54.992045],[-7.403755,54.99313],[-7.40112,54.994836],[-7.405254,55.003569],[-7.376987,55.02889],[-7.366962,55.035557],[-7.355024,55.040931],[-7.291152,55.046615],[-7.282987,55.051835],[-7.275288,55.058863],[-7.266503,55.065167],[-7.247097,55.069328],[-7.2471,55.069322],[-7.256744,55.050686],[-7.240956,55.050279],[-7.240314,55.050389]]],[[[-13.688588,57.596259],[-13.690419,57.596259],[-13.691314,57.596503],[-13.691314,57.597154],[-13.690419,57.597805],[-13.688588,57.597805],[-13.687652,57.597154],[-13.687652,57.596869],[-13.688588,57.596259]]],[[[-4.839121,54.469789],[-4.979941,54.457977],[-5.343644,54.878637],[-5.308469,55.176452],[-6.272566,55.418443],[-8.690528,57.833706],[-6.344705,59.061083],[-4.204785,58.63305],[-2.31566,60.699068],[-1.695335,60.76432],[-1.58092,60.866001],[-0.17022,60.897204],[-0.800508,59.770037],[-1.292368,57.732574],[-1.850077,55.766368],[-1.73054,55.782219],[1.892395,52.815229],[1.742775,51.364209],[1.080173,50.847526],[0.000774,50.664982],[-0.162997,50.752401],[-0.725152,50.731879],[-0.768853,50.741516],[-0.770985,50.736884],[-0.789947,50.730048],[-0.812815,50.734768],[-0.877742,50.761156],[-0.942879,50.758338],[-0.992581,50.737379],[-1.18513,50.766989],[-1.282741,50.792353],[-1.375004,50.772063],[-1.523427,50.719605],[-1.630649,50.695128],[-1.663617,50.670508],[-1.498021,50.40831],[-4.097427,49.735486],[-6.825199,49.700905],[-5.541541,51.446591],[-6.03361,51.732369],[-4.791746,52.635365],[-4.969244,52.637413],[-5.049473,53.131209],[-4.787393,53.409491],[-4.734148,53.424866],[-4.917096,53.508212],[-4.839121,54.469789]]]]}},{"type":"Feature","properties":{"id":0},"geometry":{"type":"MultiPolygon","coordinates":[[[[-157.018938,19.300864],[-179.437336,27.295312],[-179.480084,28.991459],[-168.707465,26.30325],[-163.107414,24.60499],[-153.841679,20.079306],[-154.233846,19.433391],[-153.61725,18.900587],[-154.429471,18.171036],[-156.780638,18.718492],[-157.018938,19.300864]]],[[[-78.91269,43.037032],[-78.964351,42.976393],[-78.981718,42.979043],[-78.998055,42.991111],[-79.01189,43.004358],[-79.022046,43.010539],[-79.023076,43.017015],[-79.00983,43.050867],[-79.011449,43.065291],[-78.993051,43.066174],[-78.975536,43.069707],[-78.958905,43.070884],[-78.943304,43.065291],[-78.917399,43.058521],[-78.908569,43.049396],[-78.91269,43.037032]]],[[[-123.03529,48.992515],[-123.035308,48.992499],[-123.045277,48.984361],[-123.08849,48.972235],[-123.089345,48.987982],[-123.090484,48.992499],[-123.090488,48.992515],[-123.035306,48.992515],[-123.03529,48.992515]]],[[[-103.837038,29.279906],[-103.864121,29.281366],[-103.928122,29.293019],[-104.01915,29.32033],[-104.057313,29.339037],[-104.105424,29.385675],[-104.139789,29.400584],[-104.161648,29.416759],[-104.194514,29.448927],[-104.212291,29.484661],[-104.218698,29.489829],[-104.227148,29.493033],[-104.251022,29.508588],[-104.267171,29.526571],[-104.292751,29.532824],[-104.320604,29.532255],[-104.338484,29.524013],[-104.349026,29.537578],[-104.430443,29.582795],[-104.437832,29.58543],[-104.444008,29.589203],[-104.448555,29.597678],[-104.452069,29.607109],[-104.455222,29.613387],[-104.469381,29.625402],[-104.516639,29.654315],[-104.530824,29.667906],[-104.535036,29.677802],[-104.535191,29.687853],[-104.537103,29.702116],[-104.543666,29.71643],[-104.561391,29.745421],[-104.570279,29.787511],[-104.583586,29.802575],[-104.601207,29.81477],[-104.619682,29.833064],[-104.623764,29.841487],[-104.637588,29.887996],[-104.656346,29.908201],[-104.660635,29.918433],[-104.663478,29.923084],[-104.676526,29.93683],[-104.680479,29.942308],[-104.682469,29.952126],[-104.680117,29.967784],[-104.680479,29.976466],[-104.699108,30.03145],[-104.701589,30.055324],[-104.698592,30.075271],[-104.684639,30.111135],[-104.680479,30.134131],[-104.67867,30.170356],[-104.681564,30.192939],[-104.695853,30.208441],[-104.715231,30.243995],[-104.724585,30.252211],[-104.742155,30.25986],[-104.74939,30.264459],[-104.761689,30.284199],[-104.774143,30.311588],[-104.788767,30.335927],[-104.807732,30.346418],[-104.8129,30.350707],[-104.814967,30.360577],[-104.816001,30.371997],[-104.818274,30.380524],[-104.824269,30.38719],[-104.83755,30.394063],[-104.844939,30.40104],[-104.853259,30.41215],[-104.855016,30.417473],[-104.853621,30.423984],[-104.852432,30.438867],[-104.854655,30.448737],[-104.864473,30.462018],[-104.866695,30.473025],[-104.865248,30.479898],[-104.859615,30.491112],[-104.859254,30.497261],[-104.863026,30.502377],[-104.879718,30.510852],[-104.882146,30.520929],[-104.884007,30.541858],[-104.886591,30.551883],[-104.898166,30.569401],[-104.928242,30.599529],[-104.93434,30.610536],[-104.941057,30.61405],[-104.972735,30.618029],[-104.98276,30.620716],[-104.989117,30.629553],[-104.991649,30.640301],[-104.992941,30.651464],[-104.995783,30.661747],[-105.008495,30.676992],[-105.027977,30.690117],[-105.049475,30.699264],[-105.06813,30.702675],[-105.087043,30.709806],[-105.133604,30.757917],[-105.140425,30.750476],[-105.153241,30.763188],[-105.157788,30.76572],[-105.160889,30.764118],[-105.162698,30.774919],[-105.167297,30.781171],[-105.17479,30.783962],[-105.185125,30.784634],[-105.195306,30.787941],[-105.204917,30.80241],[-105.2121,30.805718],[-105.21825,30.806803],[-105.229257,30.810214],[-105.232874,30.809128],[-105.239851,30.801532],[-105.243985,30.799103],[-105.249049,30.798845],[-105.259488,30.802979],[-105.265844,30.808405],[-105.270753,30.814348],[-105.277006,30.819412],[-105.334315,30.843803],[-105.363771,30.850366],[-105.376173,30.859565],[-105.41555,30.902456],[-105.496682,30.95651],[-105.530789,30.991701],[-105.555955,31.002605],[-105.565722,31.016661],[-105.578641,31.052163],[-105.59094,31.071438],[-105.605875,31.081928],[-105.623496,31.090351],[-105.643805,31.103684],[-105.668042,31.127869],[-105.675225,31.131951],[-105.692278,31.137635],[-105.76819,31.18001],[-105.777854,31.192722],[-105.78483,31.211016],[-105.861983,31.288376],[-105.880147,31.300881],[-105.896994,31.305997],[-105.897149,31.309511],[-105.908802,31.317004],[-105.928052,31.326461],[-105.934563,31.335504],[-105.941772,31.352351],[-105.948515,31.361239],[-105.961202,31.371006],[-106.004739,31.396948],[-106.021147,31.402167],[-106.046261,31.404648],[-106.065304,31.410952],[-106.099385,31.428884],[-106.141113,31.439167],[-106.164316,31.447797],[-106.174471,31.460251],[-106.209249,31.477305],[-106.215424,31.483919],[-106.21744,31.488725],[-106.218731,31.494616],[-106.222891,31.50459],[-106.232658,31.519938],[-106.274749,31.562622],[-106.286298,31.580141],[-106.312292,31.648612],[-106.331309,31.68215],[-106.35849,31.717548],[-106.39177,31.745919],[-106.428951,31.758476],[-106.473135,31.755065],[-106.492797,31.759044],[-106.501425,31.766344],[-106.506052,31.770258],[-106.517189,31.773824],[-106.558969,31.773876],[-106.584859,31.773927],[-106.610697,31.773979],[-106.636587,31.774082],[-106.662477,31.774134],[-106.688315,31.774237],[-106.714205,31.774237],[-106.740095,31.774289],[-106.765933,31.774392],[-106.791823,31.774444],[-106.817713,31.774496],[-106.843603,31.774547],[-106.869441,31.774599],[-106.895331,31.774702],[-106.921221,31.774702],[-106.947111,31.774754],[-106.973001,31.774857],[-106.998891,31.774909],[-107.02478,31.774961],[-107.05067,31.775013],[-107.076509,31.775064],[-107.102398,31.775168],[-107.128288,31.775168],[-107.154127,31.775219],[-107.180016,31.775374],[-107.205906,31.775374],[-107.231796,31.775426],[-107.257634,31.775478],[-107.283524,31.775529],[-107.309414,31.775633],[-107.335252,31.775684],[-107.361142,31.775788],[-107.387032,31.775788],[-107.412896,31.775839],[-107.438786,31.775943],[-107.464676,31.775994],[-107.490566,31.776098],[-107.516404,31.776149],[-107.542294,31.776201],[-107.568184,31.776253],[-107.594074,31.776304],[-107.619964,31.776408],[-107.645854,31.776459],[-107.671744,31.776459],[-107.697633,31.776563],[-107.723472,31.776614],[-107.749362,31.776666],[-107.775251,31.776718],[-107.801141,31.77677],[-107.82698,31.776873],[-107.852869,31.776925],[-107.878759,31.776925],[-107.904598,31.777028],[-107.930487,31.77708],[-107.956377,31.777131],[-107.982216,31.777183],[-108.008105,31.777235],[-108.033995,31.777338],[-108.059885,31.77739],[-108.085723,31.77739],[-108.111613,31.777545],[-108.137503,31.777545],[-108.163341,31.777648],[-108.189283,31.7777],[-108.215121,31.777751],[-108.215121,31.770723],[-108.215121,31.763695],[-108.215121,31.756667],[-108.215121,31.749639],[-108.215121,31.74256],[-108.215121,31.735583],[-108.215121,31.728555],[-108.215121,31.721476],[-108.215121,31.714396],[-108.215121,31.70742],[-108.215121,31.700392],[-108.215121,31.693312],[-108.215121,31.686284],[-108.215121,31.679256],[-108.215121,31.672176],[-108.21507,31.665148],[-108.215018,31.658172],[-108.215018,31.651092],[-108.215018,31.644064],[-108.215018,31.637036],[-108.215018,31.630008],[-108.215018,31.62298],[-108.215018,31.615952],[-108.215018,31.608873],[-108.215018,31.601845],[-108.215018,31.594817],[-108.215018,31.587789],[-108.215018,31.580761],[-108.215018,31.573733],[-108.215018,31.566653],[-108.215018,31.559625],[-108.214966,31.552597],[-108.214966,31.545569],[-108.214966,31.538489],[-108.214966,31.531461],[-108.214966,31.524485],[-108.214966,31.517405],[-108.214966,31.510378],[-108.214966,31.503401],[-108.214966,31.496322],[-108.214966,31.489242],[-108.214966,31.482214],[-108.214966,31.475238],[-108.214966,31.468158],[-108.214966,31.46113],[-108.214966,31.454102],[-108.214966,31.447074],[-108.214915,31.440046],[-108.214863,31.432966],[-108.214863,31.425938],[-108.214863,31.41891],[-108.214863,31.411882],[-108.214863,31.404803],[-108.214863,31.397826],[-108.214863,31.390798],[-108.214863,31.383719],[-108.214863,31.376639],[-108.214863,31.369663],[-108.214863,31.362635],[-108.214863,31.355555],[-108.214863,31.348527],[-108.214863,31.341551],[-108.214863,31.334471],[-108.214811,31.327443],[-108.257573,31.327391],[-108.300336,31.327391],[-108.34302,31.327391],[-108.385731,31.327391],[-108.428442,31.327391],[-108.471152,31.327391],[-108.513837,31.327391],[-108.556547,31.327391],[-108.59931,31.327391],[-108.64202,31.327391],[-108.684757,31.327391],[-108.727467,31.327391],[-108.770178,31.327391],[-108.812914,31.327391],[-108.855625,31.327391],[-108.898335,31.327391],[-108.941046,31.327391],[-108.968282,31.327391],[-108.983731,31.327391],[-109.026493,31.327391],[-109.04743,31.327391],[-109.069203,31.327391],[-109.111914,31.327391],[-109.154599,31.327391],[-109.197361,31.327391],[-109.240072,31.32734],[-109.282782,31.32734],[-109.325519,31.32734],[-109.368229,31.32734],[-109.410914,31.32734],[-109.45365,31.32734],[-109.496387,31.32734],[-109.539071,31.32734],[-109.581808,31.32734],[-109.624493,31.32734],[-109.667177,31.32734],[-109.709965,31.32734],[-109.75265,31.32734],[-109.795335,31.32734],[-109.838123,31.32734],[-109.880808,31.32734],[-109.923596,31.327288],[-109.96628,31.327236],[-110.008965,31.327236],[-110.051702,31.327236],[-110.094386,31.327236],[-110.137071,31.327236],[-110.179807,31.327236],[-110.222544,31.327236],[-110.265229,31.327236],[-110.308017,31.327236],[-110.350753,31.327236],[-110.39349,31.327236],[-110.436174,31.327236],[-110.478859,31.327236],[-110.521595,31.327236],[-110.56428,31.327236],[-110.606965,31.327236],[-110.649727,31.327236],[-110.692438,31.327236],[-110.7352,31.327236],[-110.777885,31.327236],[-110.820595,31.327236],[-110.863358,31.327236],[-110.906068,31.327236],[-110.948753,31.327185],[-111.006269,31.327185],[-111.067118,31.333644],[-111.094455,31.342532],[-111.145924,31.359069],[-111.197446,31.375554],[-111.248864,31.392142],[-111.300333,31.40873],[-111.351803,31.425318],[-111.403299,31.441855],[-111.454768,31.458339],[-111.506238,31.474979],[-111.915464,31.601431],[-112.324715,31.727987],[-112.733967,31.854543],[-113.143218,31.981046],[-113.552444,32.107602],[-113.961696,32.234132],[-114.370921,32.360687],[-114.780147,32.487243],[-114.816785,32.498534],[-114.819373,32.499363],[-114.822108,32.50024],[-114.809447,32.511324],[-114.795546,32.552226],[-114.794203,32.574111],[-114.802678,32.594497],[-114.786813,32.621033],[-114.781542,32.628061],[-114.758804,32.64483],[-114.751156,32.65222],[-114.739477,32.669066],[-114.731209,32.686636],[-114.723871,32.711519],[-114.724284,32.712835],[-114.724285,32.712836],[-114.764541,32.709839],[-114.838076,32.704206],[-114.911612,32.698703],[-114.985199,32.693122],[-115.058734,32.687567],[-115.13227,32.681986],[-115.205806,32.676456],[-115.27929,32.670823],[-115.352851,32.665346],[-115.426386,32.659765],[-115.499922,32.654209],[-115.573535,32.648654],[-115.647019,32.643073],[-115.720529,32.637518],[-115.794064,32.631963],[-115.8676,32.626408],[-115.941213,32.620827],[-116.014748,32.615271],[-116.088232,32.609664],[-116.161742,32.604161],[-116.235329,32.598554],[-116.308891,32.593025],[-116.382426,32.587469],[-116.455962,32.581888],[-116.529472,32.576333],[-116.603007,32.570804],[-116.676543,32.565223],[-116.750104,32.559667],[-116.82364,32.554086],[-116.897201,32.548531],[-116.970737,32.542976],[-117.044221,32.537421],[-117.125121,32.531669],[-117.125969,32.538258],[-117.239623,32.531308],[-120.274098,32.884264],[-121.652736,34.467248],[-124.367265,37.662798],[-126.739806,41.37928],[-126.996297,45.773888],[-124.770704,48.44258],[-123.734053,48.241906],[-123.1663,48.27837],[-123.193018,48.501035],[-123.176987,48.65482],[-122.912481,48.753561],[-122.899122,48.897797],[-122.837671,48.97502],[-122.743986,48.980582],[-122.753,48.992499],[-122.753012,48.992515],[-122.653258,48.992515],[-122.433375,48.992515],[-122.213517,48.992515],[-121.993763,48.992515],[-121.773958,48.992515],[-121.554152,48.992515],[-121.33432,48.992515],[-121.114515,48.992515],[-95.396937,48.99267],[-95.177106,48.99267],[-95.168527,48.995047],[-95.161887,49.001145],[-95.159329,49.01179],[-95.159665,49.10951],[-95.160027,49.223353],[-95.160337,49.313012],[-95.160569,49.369494],[-95.102821,49.35394],[-94.982518,49.356162],[-94.926087,49.345568],[-94.856195,49.318283],[-94.839142,49.308878],[-94.827256,49.292858],[-94.819892,49.252034],[-94.810358,49.229606],[-94.806121,49.210899],[-94.811185,49.166561],[-94.803743,49.146407],[-94.792039,49.12646],[-94.753772,49.026156],[-94.711217,48.914586],[-94.711734,48.862755],[-94.712147,48.842446],[-94.713284,48.823843],[-94.710907,48.807513],[-94.701786,48.790098],[-94.688893,48.778832],[-94.592852,48.726433],[-94.519161,48.70447],[-94.4795,48.700698],[-94.311577,48.713927],[-94.292586,48.711912],[-94.284034,48.709069],[-94.274499,48.704108],[-94.265482,48.697752],[-94.258454,48.690828],[-94.255767,48.683541],[-94.252459,48.662405],[-94.251038,48.65729],[-94.23215,48.652019],[-94.03485,48.643311],[-93.874885,48.636206],[-93.835741,48.617137],[-93.809386,48.543576],[-93.778664,48.519468],[-93.756779,48.516549],[-93.616297,48.531302],[-93.599889,48.526341],[-93.566584,48.538279],[-93.491756,48.542309],[-93.459924,48.557399],[-93.45225,48.572721],[-93.453774,48.586958],[-93.451475,48.597422],[-93.417316,48.604114],[-93.385716,48.614863],[-93.25774,48.630314],[-93.131701,48.62463],[-92.97972,48.61768],[-92.955588,48.612228],[-92.884197,48.579878],[-92.72555,48.548692],[-92.648604,48.536263],[-92.630181,48.519468],[-92.627468,48.502777],[-92.646743,48.497428],[-92.691366,48.489858],[-92.710641,48.482882],[-92.718909,48.459782],[-92.704052,48.445158],[-92.677129,48.441747],[-92.657053,48.438233],[-92.570521,48.446656],[-92.526932,48.445623],[-92.490629,48.433117],[-92.474532,48.410483],[-92.467581,48.394282],[-92.467064,48.353225],[-92.462465,48.329299],[-92.451381,48.312685],[-92.41823,48.282041],[-92.38464,48.232406],[-92.371851,48.222587],[-92.353815,48.222897],[-92.327874,48.229435],[-92.303663,48.239279],[-92.291029,48.249562],[-92.292062,48.270336],[-92.301416,48.290645],[-92.303095,48.310928],[-92.281598,48.33178],[-92.259118,48.339635],[-92.154732,48.350125],[-92.070499,48.346714],[-92.043421,48.334596],[-92.030114,48.313176],[-92.021355,48.287441],[-92.007997,48.262482],[-91.992158,48.247909],[-91.975492,48.236566],[-91.957302,48.228323],[-91.852244,48.195974],[-91.764988,48.187344],[-91.744137,48.179593],[-91.727575,48.168327],[-91.695509,48.13758],[-91.716438,48.112051],[-91.692512,48.097866],[-91.618615,48.089572],[-91.597479,48.090399],[-91.589676,48.088332],[-91.581098,48.080942],[-91.579806,48.070969],[-91.585129,48.06084],[-91.586989,48.052572],[-91.574845,48.048205],[-91.487098,48.053476],[-91.464722,48.048955],[-91.446274,48.040738],[-91.427929,48.036449],[-91.3654,48.057843],[-91.276362,48.064768],[-91.23807,48.082648],[-91.203963,48.107659],[-91.071103,48.170859],[-91.02816,48.184838],[-91.008109,48.194372],[-90.923153,48.227109],[-90.873802,48.234344],[-90.840678,48.220107],[-90.837939,48.210547],[-90.848843,48.198713],[-90.849721,48.189566],[-90.843003,48.176983],[-90.83427,48.171789],[-90.823883,48.168327],[-90.812307,48.160989],[-90.803057,48.147166],[-90.796701,48.117064],[-90.786469,48.10045],[-90.750347,48.083991],[-90.701307,48.08456],[-90.611079,48.103499],[-90.586843,48.104817],[-90.573872,48.097892],[-90.562194,48.088849],[-90.542014,48.083733],[-90.531601,48.08456],[-90.501887,48.094275],[-90.490493,48.096239],[-90.483465,48.094482],[-90.477858,48.091536],[-90.470623,48.089882],[-90.178625,48.116444],[-90.120386,48.115359],[-90.073257,48.101199],[-90.061036,48.091019],[-90.008222,48.029731],[-89.995329,48.018595],[-89.980317,48.010094],[-89.92045,47.98746],[-89.902441,47.985909],[-89.803454,48.013763],[-89.780975,48.017199],[-89.763302,48.017303],[-89.745964,48.013763],[-89.724596,48.005908],[-89.712788,48.003376],[-89.678656,48.008699],[-89.65659,48.007975],[-89.593105,47.996503],[-89.581753,47.996333],[-89.586724,47.992938],[-89.310872,47.981097],[-89.072861,48.046842],[-88.49789,48.212841],[-88.286621,48.156675],[-85.939935,47.280501],[-84.784644,46.770068],[-84.516909,46.435083],[-84.489712,46.446652],[-84.491052,46.457658],[-84.478301,46.466467],[-84.465408,46.478172],[-84.448096,46.489722],[-84.42324,46.511581],[-84.389702,46.520262],[-84.352469,46.522743],[-84.30534,46.501607],[-84.242011,46.526464],[-84.197285,46.546359],[-84.147676,46.541346],[-84.110443,46.526464],[-84.158812,46.433343],[-84.147676,46.399882],[-84.129046,46.375026],[-84.10543,46.347741],[-84.105944,46.346374],[-84.117195,46.347157],[-84.117489,46.338326],[-84.122361,46.331922],[-84.112061,46.287102],[-84.092672,46.227469],[-84.111983,46.20337],[-84.015118,46.149712],[-83.957038,46.045736],[-83.676821,46.15388],[-83.429449,46.086221],[-83.523049,45.892052],[-83.574563,45.890259],[-82.551615,44.857931],[-82.655591,43.968545],[-82.440632,43.096285],[-82.460131,43.084392],[-82.458894,43.083247],[-82.431813,43.039387],[-82.424748,43.02408],[-82.417242,43.01731],[-82.416369,43.01742],[-82.416412,43.017143],[-82.414603,42.983243],[-82.430442,42.951307],[-82.453179,42.918983],[-82.464781,42.883637],[-82.468036,42.863974],[-82.482325,42.835113],[-82.485271,42.818524],[-82.473618,42.798164],[-82.470982,42.790568],[-82.471344,42.779845],[-82.476951,42.761474],[-82.48341,42.719254],[-82.511264,42.646675],[-82.526224,42.619906],[-82.549246,42.590941],[-82.575833,42.571795],[-82.608467,42.561098],[-82.644331,42.557817],[-82.644698,42.557533],[-82.644932,42.561634],[-82.637132,42.568405],[-82.60902,42.579296],[-82.616673,42.582828],[-82.636985,42.599607],[-82.625357,42.616092],[-82.629331,42.626394],[-82.638751,42.633459],[-82.644344,42.640524],[-82.644166,42.641056],[-82.716083,42.617461],[-82.777592,42.408506],[-82.888693,42.406093],[-82.889991,42.403266],[-82.905739,42.387665],[-82.923842,42.374419],[-82.937972,42.366176],[-82.947686,42.363527],[-82.979624,42.359406],[-83.042618,42.340861],[-83.061899,42.32732],[-83.081622,42.30907],[-83.11342,42.279619],[-83.145306,42.066968],[-83.177398,41.960666],[-83.21512,41.794493],[-82.219051,41.516445],[-80.345329,42.13344],[-80.316455,42.123137],[-79.270266,42.591872],[-79.221058,42.582892],[-78.871842,42.860012],[-78.875011,42.867184],[-78.896205,42.897209],[-78.901651,42.908101],[-78.90901,42.952255],[-78.913426,42.957848],[-78.932118,42.9708],[-78.936386,42.979631],[-78.927997,43.002003],[-78.893114,43.029379],[-78.887963,43.051456],[-78.914897,43.076477],[-79.026167,43.086485],[-79.065231,43.10573],[-79.065273,43.105897],[-79.065738,43.120237],[-79.061423,43.130288],[-79.055583,43.138427],[-79.051604,43.146851],[-79.04933,43.159847],[-79.048607,43.170622],[-79.053775,43.260358],[-79.058425,43.277799],[-79.058631,43.2782],[-78.990696,43.286947],[-78.862059,43.324332],[-78.767813,43.336418],[-78.516117,43.50645],[-76.363317,43.943219],[-76.396746,44.106667],[-76.364697,44.111631],[-76.366146,44.117349],[-76.357462,44.131478],[-76.183493,44.223025],[-76.162644,44.229888],[-76.176117,44.30795],[-76.046414,44.354817],[-75.928746,44.391137],[-75.852508,44.381639],[-75.849095,44.386103],[-75.847623,44.392579],[-75.84674,44.398172],[-75.845415,44.40141],[-75.780803,44.432318],[-75.770205,44.446153],[-75.772266,44.463815],[-75.779184,44.48236],[-75.791496,44.496513],[-75.791183,44.496768],[-75.754622,44.527567],[-75.69969,44.581673],[-75.578199,44.661513],[-75.455958,44.741766],[-75.341831,44.816749],[-75.270233,44.863774],[-75.129647,44.925166],[-75.075594,44.935501],[-75.058721,44.941031],[-75.0149,44.96599],[-74.998647,44.972398],[-74.940201,44.987746],[-74.903744,45.005213],[-74.88651,45.009398],[-74.868474,45.010122],[-74.741557,44.998857],[-74.712961,44.999254],[-74.695875,44.99803],[-74.596114,44.998495],[-74.496352,44.999012],[-74.197146,45.000458],[-71.703551,45.012757],[-71.603816,45.013274],[-71.505848,45.013731],[-71.50408,45.013739],[-71.506613,45.037045],[-71.504752,45.052962],[-71.497259,45.066553],[-71.45659,45.110994],[-71.451215,45.121691],[-71.445996,45.140295],[-71.441604,45.150682],[-71.413026,45.186184],[-71.406567,45.204942],[-71.42269,45.217189],[-71.449045,45.226905],[-71.438813,45.233468],[-71.394888,45.241529],[-71.381245,45.250779],[-71.3521,45.278323],[-71.334323,45.28871],[-71.311534,45.294136],[-71.293396,45.292327],[-71.20937,45.254758],[-71.185133,45.248557],[-71.160329,45.245767],[-71.141725,45.252329],[-71.111029,45.287108],[-71.095242,45.300905],[-71.085553,45.304213],[-71.084952,45.304293],[-71.064211,45.307055],[-71.054418,45.310362],[-71.036667,45.323385],[-71.027598,45.33465],[-71.016539,45.343125],[-70.993155,45.347827],[-70.968118,45.34452],[-70.951608,45.332014],[-70.906908,45.246232],[-70.892412,45.234604],[-70.874351,45.245663],[-70.870605,45.255275],[-70.872491,45.274189],[-70.870243,45.283129],[-70.862621,45.290363],[-70.842389,45.301215],[-70.835258,45.309794],[-70.83208,45.328552],[-70.835465,45.373097],[-70.833837,45.393096],[-70.825982,45.410459],[-70.812986,45.42343],[-70.794873,45.430406],[-70.771877,45.430045],[-70.75255,45.422345],[-70.718004,45.397282],[-70.696739,45.388652],[-70.675785,45.388704],[-70.65359,45.395473],[-70.641316,45.408496],[-70.650257,45.427461],[-70.668162,45.439036],[-70.707385,45.4564],[-70.722836,45.470921],[-70.732009,45.491591],[-70.730329,45.507973],[-70.686792,45.572723],[-70.589614,45.651788],[-70.572406,45.662279],[-70.514735,45.681709],[-70.484763,45.699641],[-70.4728,45.703568],[-70.450424,45.703723],[-70.439132,45.705893],[-70.419315,45.716901],[-70.407351,45.731525],[-70.402442,45.749663],[-70.403941,45.771161],[-70.408282,45.781651],[-70.413682,45.787697],[-70.41717,45.793795],[-70.415232,45.804389],[-70.409935,45.810745],[-70.389807,45.825059],[-70.312654,45.867641],[-70.283173,45.890482],[-70.262528,45.923038],[-70.255939,45.948876],[-70.263148,45.956834],[-70.280434,45.959315],[-70.303947,45.968616],[-70.316298,45.982982],[-70.316892,45.999002],[-70.306143,46.035331],[-70.303637,46.038483],[-70.294309,46.044943],[-70.29201,46.048663],[-70.293017,46.054038],[-70.296092,46.057862],[-70.300795,46.061737],[-70.304774,46.065975],[-70.311362,46.071866],[-70.312629,46.079566],[-70.30033,46.089281],[-70.26444,46.106593],[-70.24948,46.120597],[-70.244002,46.141009],[-70.249247,46.162765],[-70.263329,46.183229],[-70.284801,46.191859],[-70.280899,46.211857],[-70.253407,46.251493],[-70.236173,46.288339],[-70.223693,46.300793],[-70.201886,46.305495],[-70.199509,46.315262],[-70.197028,46.336863],[-70.188398,46.358412],[-70.167418,46.368179],[-70.153052,46.372829],[-70.074323,46.419545],[-70.061817,46.445409],[-70.050086,46.511271],[-70.032723,46.609766],[-70.023628,46.661287],[-70.007763,46.704075],[-69.989961,46.721697],[-69.899708,46.811562],[-69.809403,46.901299],[-69.719099,46.991086],[-69.628794,47.080797],[-69.538464,47.17061],[-69.448159,47.260346],[-69.357906,47.350134],[-69.267628,47.439844],[-69.25091,47.452919],[-69.237268,47.45881],[-69.221972,47.459688],[-69.069655,47.431886],[-69.054023,47.418399],[-69.054333,47.389253],[-69.066193,47.32967],[-69.065134,47.296339],[-69.06356,47.290809],[-69.057486,47.269467],[-69.0402,47.249055],[-68.906229,47.190221],[-68.889718,47.190609],[-68.761819,47.23704],[-68.71779,47.245231],[-68.668801,47.243422],[-68.644203,47.245283],[-68.6256,47.255205],[-68.607926,47.269829],[-68.58524,47.28249],[-68.539662,47.299853],[-68.518009,47.304762],[-68.492016,47.307553],[-68.466746,47.305692],[-68.435327,47.291275],[-68.422563,47.293109],[-68.410212,47.297424],[-68.385614,47.301713],[-68.383392,47.307139],[-68.384839,47.315873],[-68.382049,47.32781],[-68.347839,47.358506],[-68.299728,47.367833],[-68.24645,47.360573],[-68.197047,47.341401],[-68.184335,47.333133],[-68.156068,47.306674],[-68.145061,47.301455],[-68.115398,47.292282],[-68.101446,47.286185],[-68.039382,47.245231],[-67.993184,47.223217],[-67.962436,47.197689],[-67.953703,47.18663],[-67.949982,47.172936],[-67.943419,47.164538],[-67.899132,47.138778],[-67.870607,47.107358],[-67.854742,47.09785],[-67.813556,47.081908],[-67.808699,47.075138],[-67.805185,47.035631],[-67.802549,46.901247],[-67.800017,46.766785],[-67.797433,46.632297],[-67.794849,46.497861],[-67.792317,46.363476],[-67.789733,46.229014],[-67.78715,46.094552],[-67.784566,45.960142],[-67.782757,45.95053],[-67.776556,45.942933],[-67.767461,45.935957],[-67.759658,45.928567],[-67.757849,45.919472],[-67.769425,45.903969],[-67.787356,45.890017],[-67.799242,45.875651],[-67.792627,45.858907],[-67.776091,45.840821],[-67.772835,45.828057],[-67.779863,45.815706],[-67.794126,45.799169],[-67.80627,45.781754],[-67.811127,45.76651],[-67.810816,45.762414],[-67.817811,45.754896],[-67.821785,45.740767],[-67.827673,45.739001],[-67.868884,45.744593],[-67.856815,45.723694],[-67.835768,45.703971],[-67.793821,45.676301],[-67.733034,45.651869],[-67.723173,45.645393],[-67.711546,45.642155],[-67.697564,45.64922],[-67.66695,45.620077],[-67.649435,45.611247],[-67.603073,45.605948],[-67.561862,45.596234],[-67.54052,45.593879],[-67.442056,45.603593],[-67.440939,45.604586],[-67.431306,45.597941],[-67.422107,45.568796],[-67.42619,45.533449],[-67.443036,45.522184],[-67.467531,45.508283],[-67.493214,45.493142],[-67.48231,45.455521],[-67.428825,45.38705],[-67.434561,45.350308],[-67.459056,45.318424],[-67.468668,45.301835],[-67.475024,45.282353],[-67.471303,45.266282],[-67.427585,45.236568],[-67.390533,45.193108],[-67.356272,45.165926],[-67.31922,45.153886],[-67.284648,45.169699],[-67.279584,45.179052],[-67.279222,45.187372],[-67.277207,45.195072],[-67.267336,45.202513],[-67.254986,45.205045],[-67.242428,45.202565],[-67.219071,45.192126],[-67.206166,45.189401],[-67.176015,45.178656],[-67.191274,45.180365],[-67.204376,45.178209],[-67.204724,45.177791],[-67.152423,45.148932],[-67.048033,45.043407],[-66.962727,45.047088],[-66.857192,44.968696],[-66.897268,44.817275],[-67.2159,44.593511],[-67.122366,44.423624],[-67.68447,44.192544],[-67.459678,40.781645],[-76.607854,32.495823],[-76.798479,32.713735],[-78.561892,29.037718],[-78.892446,29.039659],[-79.762295,26.719312],[-80.026352,24.932961],[-82.368794,23.994833],[-83.806281,29.068506],[-87.460772,29.089961],[-87.922646,28.666131],[-90.461001,28.246758],[-91.787336,29.11536],[-93.311871,29.12431],[-96.423449,26.057857],[-97.129057,25.991017],[-97.129509,25.966833],[-97.139358,25.965876],[-97.202171,25.960893],[-97.202176,25.960857],[-97.204941,25.960639],[-97.253051,25.963481],[-97.266358,25.960639],[-97.2692,25.944361],[-97.287649,25.928651],[-97.310981,25.922088],[-97.328447,25.933302],[-97.351107,25.918419],[-97.355112,25.912786],[-97.35227,25.894493],[-97.345165,25.871704],[-97.345733,25.852222],[-97.36599,25.843902],[-97.376015,25.846744],[-97.380124,25.853203],[-97.383121,25.860541],[-97.389891,25.865657],[-97.397823,25.865812],[-97.399476,25.861162],[-97.39989,25.855115],[-97.404179,25.851395],[-97.425418,25.854857],[-97.435727,25.869275],[-97.441309,25.884933],[-97.448259,25.892322],[-97.469421,25.892943],[-97.486319,25.895733],[-97.502209,25.901883],[-97.52027,25.912786],[-97.565177,25.954748],[-97.594322,25.966375],[-97.604787,25.979966],[-97.613055,25.995985],[-97.622641,26.00906],[-97.641451,26.022495],[-97.659874,26.03066],[-97.679614,26.034639],[-97.766948,26.039652],[-97.780306,26.043218],[-97.782321,26.058617],[-97.80201,26.063733],[-97.878181,26.063733],[-97.941666,26.056809],[-97.999233,26.064302],[-98.013057,26.063682],[-98.044166,26.048799],[-98.065457,26.042184],[-98.075146,26.046628],[-98.083311,26.070916],[-98.103103,26.074947],[-98.150232,26.063682],[-98.185062,26.065232],[-98.222656,26.075412],[-98.300429,26.111431],[-98.309809,26.121094],[-98.333037,26.15303],[-98.339264,26.159851],[-98.365774,26.160161],[-98.377272,26.163572],[-98.377272,26.173649],[-98.36934,26.19401],[-98.397193,26.201141],[-98.428845,26.217729],[-98.456544,26.225946],[-98.472383,26.207652],[-98.49295,26.230596],[-98.521527,26.240932],[-98.552791,26.248321],[-98.581627,26.262274],[-98.640564,26.24181],[-98.653663,26.244291],[-98.664696,26.250647],[-98.685289,26.268475],[-98.693325,26.270542],[-98.702239,26.271628],[-98.704255,26.27664],[-98.691465,26.290231],[-98.701413,26.299119],[-98.713169,26.303357],[-98.726217,26.30439],[-98.739911,26.303253],[-98.735932,26.320048],[-98.746397,26.332141],[-98.780839,26.351674],[-98.795851,26.368314],[-98.801329,26.372138],[-98.810295,26.372448],[-98.817323,26.368521],[-98.825023,26.366454],[-98.836081,26.372138],[-98.842334,26.365834],[-98.850835,26.364077],[-98.860524,26.366299],[-98.870214,26.372138],[-98.893029,26.367849],[-98.9299,26.39224],[-98.945377,26.378288],[-98.954136,26.393946],[-98.962844,26.399527],[-98.986951,26.400095],[-99.004056,26.393842],[-99.010515,26.392602],[-99.016432,26.394462],[-99.022995,26.403351],[-99.027878,26.406245],[-99.047645,26.406968],[-99.066351,26.404746],[-99.085498,26.40764],[-99.106427,26.423039],[-99.108907,26.434253],[-99.102525,26.446966],[-99.09374,26.459781],[-99.089373,26.47115],[-99.091492,26.484018],[-99.10299,26.512078],[-99.115108,26.525617],[-99.140946,26.531405],[-99.164873,26.540448],[-99.17128,26.563961],[-99.171548,26.56583],[-99.213953,26.568537],[-99.242801,26.579723],[-99.254575,26.6018],[-99.258844,26.614752],[-99.277683,26.638007],[-99.281951,26.649781],[-99.277389,26.657729],[-99.26635,26.653314],[-99.252662,26.644483],[-99.240299,26.639184],[-99.244861,26.652431],[-99.240299,26.697763],[-99.242507,26.713658],[-99.252368,26.743683],[-99.254575,26.75899],[-99.252368,26.799024],[-99.254575,26.810504],[-99.257666,26.813153],[-99.262229,26.814036],[-99.266497,26.817863],[-99.268263,26.827872],[-99.271649,26.832876],[-99.289458,26.84465],[-99.308444,26.830521],[-99.316539,26.822279],[-99.323457,26.810504],[-99.328166,26.797258],[-99.329197,26.789016],[-99.331699,26.78254],[-99.340383,26.77312],[-99.366728,26.761345],[-99.380269,26.777241],[-99.391896,26.796963],[-99.412207,26.796963],[-99.410883,26.808149],[-99.405437,26.818452],[-99.396606,26.824928],[-99.384979,26.824928],[-99.377178,26.816686],[-99.374823,26.804028],[-99.374234,26.791076],[-99.371291,26.783128],[-99.360694,26.780479],[-99.359369,26.790487],[-99.36452,26.810504],[-99.357897,26.822279],[-99.351274,26.83111],[-99.346123,26.840824],[-99.344062,26.855247],[-99.348772,26.899696],[-99.355101,26.920302],[-99.36452,26.934726],[-99.403377,26.952093],[-99.413974,26.964162],[-99.401758,26.985651],[-99.399991,26.999192],[-99.418831,27.007728],[-99.441938,27.013615],[-99.453271,27.019797],[-99.455332,27.025979],[-99.464751,27.039225],[-99.466959,27.047467],[-99.462544,27.057181],[-99.461635,27.056839],[-99.461728,27.056954],[-99.442039,27.089614],[-99.439404,27.098347],[-99.441419,27.107494],[-99.445734,27.114728],[-99.450178,27.120465],[-99.452452,27.125012],[-99.450333,27.145166],[-99.435786,27.188419],[-99.431988,27.207591],[-99.434029,27.22697],[-99.440902,27.244798],[-99.451832,27.26118],[-99.46612,27.276527],[-99.468963,27.278233],[-99.480409,27.283297],[-99.482941,27.286708],[-99.484879,27.294821],[-99.486584,27.297611],[-99.493199,27.30128],[-99.521362,27.311254],[-99.5148,27.321796],[-99.497591,27.338798],[-99.494026,27.348203],[-99.492889,27.358848],[-99.487721,27.37187],[-99.484621,27.391766],[-99.475706,27.414762],[-99.472916,27.426647],[-99.473639,27.463803],[-99.472916,27.468299],[-99.47643,27.48251],[-99.480409,27.490778],[-99.48829,27.494654],[-99.503689,27.495584],[-99.509503,27.500028],[-99.510071,27.510518],[-99.507074,27.533437],[-99.507203,27.57377],[-99.515006,27.588601],[-99.535031,27.604828],[-99.55503,27.613509],[-99.572264,27.61847],[-99.578232,27.622811],[-99.590247,27.642061],[-99.600169,27.646427],[-99.612442,27.643637],[-99.633526,27.633069],[-99.644869,27.632733],[-99.648642,27.636919],[-99.658693,27.654024],[-99.664739,27.659398],[-99.70037,27.659191],[-99.705692,27.66317],[-99.710674,27.670116],[-99.723056,27.687381],[-99.730652,27.691825],[-99.734037,27.702031],[-99.736311,27.713607],[-99.740445,27.722159],[-99.747344,27.726009],[-99.765198,27.731177],[-99.774577,27.735828],[-99.78685,27.748488],[-99.795428,27.761924],[-99.806963,27.771423],[-99.808167,27.772414],[-99.83292,27.776755],[-99.832971,27.782181],[-99.844779,27.793576],[-99.858241,27.803524],[-99.863357,27.804661],[-99.864727,27.814324],[-99.861858,27.83608],[-99.863357,27.845666],[-99.870928,27.854477],[-99.880204,27.859231],[-99.888007,27.864812],[-99.891288,27.876026],[-99.882684,27.89158],[-99.878808,27.901838],[-99.88134,27.906463],[-99.896766,27.912923],[-99.914336,27.928245],[-99.929916,27.946331],[-99.939683,27.961085],[-99.928289,27.975761],[-99.940717,27.983254],[-99.961852,27.987492],[-99.976606,27.992453],[-99.991127,28.007801],[-100.000584,28.02041],[-100.007457,28.033561],[-100.014123,28.050459],[-100.013503,28.056971],[-100.010506,28.063611],[-100.010196,28.068882],[-100.017585,28.070949],[-100.031538,28.081801],[-100.045077,28.095289],[-100.048023,28.102523],[-100.048901,28.115959],[-100.056498,28.137922],[-100.074895,28.154407],[-100.172873,28.198538],[-100.189203,28.201329],[-100.197626,28.207168],[-100.201192,28.220346],[-100.202949,28.234428],[-100.205946,28.242877],[-100.212819,28.245073],[-100.240724,28.249698],[-100.257932,28.260524],[-100.275089,28.277242],[-100.284339,28.296517],[-100.277931,28.314888],[-100.278551,28.331088],[-100.293899,28.353413],[-100.322631,28.386899],[-100.331675,28.422013],[-100.336326,28.458574],[-100.340201,28.464259],[-100.348315,28.470253],[-100.355549,28.478185],[-100.35679,28.489322],[-100.351622,28.496711],[-100.322631,28.510406],[-100.364024,28.524797],[-100.38423,28.537174],[-100.397769,28.557586],[-100.398751,28.568645],[-100.397097,28.592726],[-100.401438,28.60226],[-100.411463,28.609314],[-100.434821,28.619133],[-100.44619,28.626497],[-100.444898,28.643782],[-100.481381,28.686054],[-100.493939,28.708378],[-100.519054,28.804961],[-100.524996,28.814831],[-100.529285,28.819947],[-100.534453,28.830231],[-100.538639,28.835631],[-100.54515,28.83899],[-100.559671,28.839378],[-100.566234,28.842504],[-100.569696,28.84961],[-100.56334,28.86209],[-100.566234,28.869789],[-100.571763,28.8732],[-100.586543,28.879789],[-100.58954,28.883458],[-100.594966,28.899322],[-100.606955,28.910123],[-100.618841,28.917926],[-100.624318,28.924721],[-100.624783,28.93777],[-100.626696,28.948338],[-100.630778,28.956683],[-100.637909,28.962884],[-100.628918,28.98433],[-100.632793,29.005156],[-100.652224,29.044817],[-100.660854,29.102669],[-100.668967,29.116208],[-100.678165,29.119412],[-100.690826,29.121014],[-100.70204,29.12365],[-100.706846,29.130187],[-100.70974,29.135561],[-100.762501,29.173776],[-100.770098,29.187289],[-100.762088,29.208658],[-100.783172,29.243074],[-100.796143,29.257673],[-100.81609,29.270773],[-100.86389,29.290616],[-100.871797,29.296456],[-100.891227,29.318547],[-100.91474,29.337048],[-100.987397,29.366322],[-100.998301,29.372472],[-101.008068,29.380585],[-101.016232,29.390068],[-101.022175,29.40048],[-101.025948,29.414356],[-101.029617,29.442984],[-101.037782,29.460063],[-101.039026,29.460452],[-101.040188,29.457132],[-101.045487,29.451245],[-101.060205,29.449184],[-101.067711,29.45095],[-101.076101,29.453894],[-101.085962,29.454483],[-101.098031,29.449184],[-101.113043,29.466552],[-101.142774,29.475383],[-101.174124,29.475971],[-101.193699,29.469495],[-101.198703,29.473911],[-101.198851,29.476854],[-101.184132,29.497754],[-101.184868,29.512767],[-101.195171,29.521892],[-101.214157,29.518065],[-101.245213,29.493044],[-101.265818,29.487157],[-101.290545,29.49746],[-101.297315,29.503936],[-101.300995,29.512767],[-101.294372,29.520715],[-101.273177,29.524247],[-101.259195,29.533372],[-101.243888,29.554861],[-101.231966,29.580176],[-101.227845,29.599899],[-101.239178,29.616677],[-101.26052,29.613439],[-101.281272,29.597249],[-101.290545,29.575761],[-101.295255,29.570168],[-101.306146,29.574583],[-101.317626,29.584003],[-101.323955,29.592539],[-101.323661,29.603137],[-101.318804,29.616383],[-101.311445,29.628158],[-101.303497,29.634045],[-101.303669,29.631411],[-101.302727,29.633851],[-101.301073,29.649509],[-101.30978,29.654548],[-101.336239,29.654315],[-101.349029,29.660103],[-101.357684,29.667441],[-101.364351,29.676665],[-101.376624,29.700643],[-101.383368,29.718497],[-101.39962,29.740718],[-101.406545,29.752888],[-101.409309,29.765781],[-101.405098,29.778442],[-101.414012,29.774411],[-101.424218,29.771414],[-101.435096,29.770122],[-101.446103,29.771052],[-101.455689,29.77591],[-101.462433,29.788932],[-101.470908,29.791516],[-101.490286,29.785547],[-101.505763,29.773894],[-101.521809,29.765936],[-101.542893,29.771052],[-101.539689,29.779191],[-101.530516,29.796477],[-101.528604,29.801438],[-101.531912,29.811101],[-101.539172,29.817974],[-101.546458,29.820145],[-101.549766,29.815701],[-101.553977,29.796684],[-101.564907,29.786478],[-101.580281,29.781568],[-101.632216,29.775651],[-101.794531,29.795857],[-101.80298,29.801438],[-101.805978,29.811928],[-101.812695,29.812032],[-101.82409,29.805184],[-101.857602,29.805184],[-101.877524,29.810843],[-101.88742,29.81229],[-101.895455,29.808621],[-101.90238,29.803247],[-101.910881,29.799888],[-101.920157,29.798182],[-101.929613,29.797717],[-101.942662,29.803608],[-101.957054,29.814047],[-101.972246,29.818181],[-101.98793,29.805184],[-102.014595,29.810998],[-102.109344,29.80211],[-102.145647,29.815701],[-102.157248,29.824537],[-102.203679,29.846138],[-102.239775,29.849135],[-102.253444,29.855285],[-102.258276,29.873475],[-102.276181,29.869547],[-102.289023,29.878126],[-102.302175,29.889391],[-102.321011,29.893939],[-102.330235,29.888926],[-102.339769,29.870633],[-102.351061,29.866602],[-102.36323,29.864276],[-102.370723,29.857765],[-102.374547,29.848102],[-102.376589,29.821488],[-102.380051,29.811386],[-102.404132,29.780793],[-102.406096,29.777279],[-102.515288,29.784721],[-102.523066,29.782318],[-102.531127,29.769915],[-102.54154,29.762474],[-102.543349,29.760123],[-102.546578,29.757875],[-102.553141,29.756738],[-102.558309,29.759089],[-102.562882,29.769347],[-102.566758,29.771052],[-102.58531,29.764696],[-102.621225,29.747281],[-102.638743,29.743715],[-102.676054,29.74449],[-102.683469,29.743715],[-102.69104,29.736817],[-102.693624,29.729401],[-102.694709,29.720616],[-102.697758,29.709557],[-102.726748,29.664495],[-102.73127,29.650594],[-102.735507,29.649509],[-102.751656,29.622457],[-102.75176,29.620157],[-102.761346,29.603414],[-102.767598,29.59729],[-102.779665,29.592303],[-102.774084,29.579617],[-102.776461,29.575948],[-102.785892,29.571814],[-102.78075,29.558249],[-102.786512,29.550497],[-102.795478,29.54427],[-102.827311,29.470502],[-102.833951,29.461355],[-102.839067,29.45195],[-102.841134,29.438308],[-102.838705,29.426939],[-102.834984,29.415699],[-102.835191,29.403839],[-102.844545,29.390533],[-102.845578,29.384719],[-102.838033,29.370534],[-102.837672,29.366322],[-102.84656,29.361749],[-102.853872,29.361],[-102.859867,29.361155],[-102.864957,29.359527],[-102.876972,29.350871],[-102.883069,29.343766],[-102.885188,29.333379],[-102.885498,29.314801],[-102.899399,29.276095],[-102.899709,29.2639],[-102.892139,29.254391],[-102.867954,29.240387],[-102.858781,29.229147],[-102.869866,29.224781],[-102.896893,29.220285],[-102.942265,29.190209],[-102.947536,29.182018],[-102.969757,29.192845],[-102.988386,29.177135],[-103.015826,29.126776],[-103.024275,29.116157],[-103.032621,29.110214],[-103.072541,29.091404],[-103.080758,29.085203],[-103.085589,29.07572],[-103.091532,29.057866],[-103.095356,29.060294],[-103.104684,29.057866],[-103.109205,29.023372],[-103.122771,28.996474],[-103.147989,28.985105],[-103.187108,28.990221],[-103.241756,29.003502],[-103.301545,29.002365],[-103.316247,29.010065],[-103.311514,29.026043],[-103.309994,29.031175],[-103.3248,29.026808],[-103.330484,29.023733],[-103.342602,29.041226],[-103.351671,29.039417],[-103.360534,29.029831],[-103.372083,29.023733],[-103.38663,29.028798],[-103.414639,29.052414],[-103.423605,29.057866],[-103.435697,29.061121],[-103.478537,29.08205],[-103.529748,29.126776],[-103.535588,29.135122],[-103.538223,29.142408],[-103.541711,29.148816],[-103.550238,29.154656],[-103.558015,29.156206],[-103.58499,29.154656],[-103.673125,29.173569],[-103.702477,29.187858],[-103.749476,29.222972],[-103.759062,29.226848],[-103.770767,29.229845],[-103.777718,29.235297],[-103.769424,29.257543],[-103.774229,29.267517],[-103.78366,29.274803],[-103.794177,29.277594],[-103.837038,29.279906]]],[[[178.301106,52.056551],[179.595462,52.142083],[179.825447,51.992849],[179.661729,51.485763],[179.723231,51.459963],[179.408066,51.209841],[178.411463,51.523605],[177.698335,51.877899],[177.16784,51.581866],[176.487008,52.175325],[174.484678,52.08716],[172.866263,52.207379],[172.825506,52.716846],[172.747012,52.654022],[172.08261,52.952695],[172.942925,53.183013],[173.029416,52.993628],[173.127208,52.99494],[173.143321,52.990383],[173.175059,52.971747],[173.182932,52.968373],[176.45233,52.628178],[176.468135,52.488358],[177.900385,52.488358],[178.007601,52.179677],[178.301106,52.056551]]],[[[-168.899607,65.747626],[-168.909861,65.739569],[-168.926218,65.739895],[-168.942128,65.74372],[-168.951731,65.75316],[-168.942983,65.764716],[-168.920115,65.768866],[-168.907908,65.768297],[-168.902781,65.761542],[-168.899607,65.747626]]],[[[-131.160718,54.787192],[-132.853508,54.482536],[-134.77719,54.717786],[-142.6966,55.845503],[-142.861997,49.948308],[-155.675916,51.109976],[-164.492732,50.603976],[-164.691217,50.997975],[-171.246993,49.948308],[-171.215436,50.576636],[-173.341669,50.968826],[-173.362022,51.082198],[-177.799603,51.272899],[-179.155463,50.982285],[-179.476076,52.072632],[-177.11459,52.248701],[-177.146284,52.789384],[-174.777218,52.443779],[-174.773743,52.685853],[-173.653194,52.704099],[-173.790528,53.469081],[-171.063371,53.604473],[-170.777733,59.291898],[-174.324884,60.332184],[-171.736408,62.68026],[-172.315705,62.725352],[-171.995091,63.999658],[-168.501424,65.565173],[-168.714145,65.546708],[-168.853077,68.370871],[-161.115601,72.416214],[-146.132257,70.607941],[-140.692512,69.955349],[-141.145395,69.671641],[-141.015207,69.654202],[-141.006459,69.651272],[-141.005564,69.650946],[-141.005549,69.650941],[-141.005471,69.505164],[-141.001208,60.466879],[-141.001156,60.321074],[-140.994929,60.304382],[-140.979555,60.295804],[-140.909146,60.28366],[-140.768457,60.259269],[-140.660505,60.24051],[-140.533743,60.218548],[-140.518705,60.22387],[-140.506664,60.236324],[-140.475323,60.276477],[-140.462791,60.289138],[-140.447805,60.29446],[-140.424111,60.293168],[-140.32497,60.267537],[-140.169243,60.227229],[-140.01579,60.187387],[-139.967757,60.188369],[-139.916933,60.207851],[-139.826318,60.256478],[-139.728417,60.309033],[-139.679816,60.32681],[-139.628346,60.334096],[-139.517965,60.336732],[-139.413992,60.339212],[-139.262193,60.342778],[-139.101608,60.346602],[-139.079465,60.341021],[-139.06869,60.322056],[-139.073186,60.299835],[-139.113468,60.226816],[-139.149615,60.161187],[-139.183231,60.100157],[-139.182146,60.073389],[-139.112305,60.031376],[-139.060207,60.000059],[-139.051611,59.994892],[-139.003759,59.977219],[-138.842425,59.937686],[-138.742586,59.913192],[-138.704888,59.898464],[-138.697188,59.89371],[-138.692098,59.886888],[-138.654349,59.805498],[-138.63745,59.784052],[-138.59921,59.753822],[-138.488881,59.696357],[-138.363617,59.631142],[-138.219543,59.556004],[-138.067614,59.476991],[-137.91057,59.395187],[-137.758305,59.315915],[-137.611363,59.239331],[-137.594181,59.225275],[-137.582088,59.206568],[-137.5493,59.134531],[-137.521007,59.072364],[-137.484394,58.991904],[-137.507752,58.939969],[-137.50876,58.914906],[-137.486875,58.900075],[-137.453466,58.899145],[-137.423106,58.907723],[-137.338098,58.955472],[-137.2819,58.98715],[-137.172346,59.027148],[-137.062367,59.067572],[-137.047109,59.07331],[-136.942282,59.11107],[-136.840816,59.148174],[-136.785496,59.157217],[-136.671911,59.150809],[-136.613491,59.15422],[-136.569489,59.172152],[-136.484791,59.2538],[-136.483551,59.257469],[-136.466549,59.287803],[-136.467092,59.38449],[-136.467557,59.461643],[-136.415958,59.452238],[-136.36684,59.449551],[-136.319995,59.459059],[-136.275036,59.486448],[-136.244728,59.528202],[-136.258474,59.556107],[-136.29935,59.575745],[-136.350329,59.592384],[-136.2585,59.621582],[-136.145406,59.636826],[-136.02686,59.652846],[-135.923818,59.666747],[-135.830955,59.693257],[-135.641251,59.747362],[-135.482759,59.792475],[-135.465137,59.789685],[-135.404392,59.753305],[-135.345791,59.731032],[-135.259879,59.698218],[-135.221897,59.675273],[-135.192028,59.64711],[-135.157792,59.623287],[-135.106684,59.613158],[-135.087874,59.606544],[-135.032942,59.573109],[-135.018524,59.559363],[-135.016198,59.543447],[-135.01948,59.493166],[-135.023252,59.477146],[-135.037489,59.461591],[-135.078598,59.438337],[-135.095754,59.418855],[-134.993254,59.381906],[-135.00483,59.367127],[-135.014441,59.35152],[-135.016198,59.336173],[-134.979973,59.297415],[-134.95783,59.280982],[-134.932431,59.270647],[-134.839465,59.258141],[-134.74345,59.245119],[-134.70552,59.240106],[-134.692084,59.235249],[-134.68286,59.223001],[-134.671439,59.193752],[-134.66038,59.181298],[-134.610771,59.144556],[-134.582788,59.128847],[-134.556717,59.123059],[-134.509072,59.122801],[-134.477575,59.114946],[-134.451013,59.097893],[-134.398019,59.051952],[-134.387167,59.036863],[-134.385591,59.018828],[-134.399389,58.974954],[-134.343423,58.968857],[-134.329651,58.963017],[-134.320039,58.952682],[-134.32314,58.949168],[-134.330323,58.945344],[-134.333036,58.93413],[-134.327403,58.916457],[-134.316939,58.903796],[-134.22219,58.842714],[-134.108838,58.808246],[-133.983109,58.769902],[-133.87123,58.735899],[-133.831129,58.718019],[-133.796402,58.693421],[-133.700077,58.59937],[-133.626283,58.546402],[-133.547063,58.505577],[-133.463089,58.462221],[-133.392241,58.403878],[-133.43012,58.372097],[-133.41503,58.330549],[-133.374567,58.290965],[-133.257262,58.210298],[-133.165588,58.147305],[-133.142127,58.120588],[-133.094843,58.0331],[-133.075154,58.007882],[-132.99335,57.941917],[-132.917153,57.880499],[-132.83212,57.791564],[-132.70944,57.663303],[-132.629057,57.579277],[-132.552447,57.499075],[-132.455735,57.420992],[-132.362304,57.3457],[-132.304684,57.280355],[-132.230994,57.19682],[-132.276366,57.14889],[-132.34122,57.080393],[-132.16229,57.050317],[-132.031859,57.028406],[-132.107384,56.858753],[-131.871558,56.79346],[-131.865874,56.785708],[-131.872411,56.77297],[-131.882617,56.759146],[-131.887966,56.747958],[-131.886028,56.737055],[-131.880705,56.728838],[-131.864789,56.71349],[-131.838976,56.682278],[-131.830424,56.664759],[-131.826574,56.644606],[-131.832103,56.603368],[-131.825592,56.593343],[-131.799108,56.587658],[-131.692293,56.585074],[-131.585891,56.595048],[-131.560363,56.594066],[-131.536437,56.585229],[-131.491659,56.560166],[-131.345699,56.503271],[-131.215604,56.45255],[-131.100546,56.407669],[-131.016934,56.38705],[-130.839089,56.372452],[-130.760334,56.345192],[-130.645768,56.261942],[-130.602256,56.247059],[-130.495518,56.232434],[-130.47229,56.22489],[-130.458053,56.210653],[-130.427926,56.143964],[-130.418159,56.129702],[-130.403974,56.121898],[-130.290311,56.10097],[-130.243156,56.092391],[-130.211246,56.089962],[-130.116756,56.105646],[-130.094328,56.101486],[-130.071539,56.084123],[-130.039319,56.045521],[-130.026632,56.024101],[-130.01901,56.002216],[-130.014695,55.963252],[-130.016788,55.918913],[-130.019612,55.907978],[-130.019618,55.907952],[-130.022817,55.901353],[-130.049387,55.871405],[-130.104726,55.825263],[-130.136627,55.806464],[-130.148834,55.795356],[-130.163482,55.771145],[-130.167307,55.766262],[-130.170806,55.759833],[-130.173655,55.749498],[-130.170806,55.740953],[-130.163808,55.734565],[-130.160064,55.727118],[-130.167388,55.715399],[-130.155914,55.700141],[-130.142893,55.689521],[-130.131825,55.676581],[-130.126454,55.653998],[-130.12857,55.63642],[-130.135121,55.619127],[-130.153147,55.58511],[-130.148671,55.578192],[-130.146881,55.569322],[-130.146962,55.547187],[-130.112172,55.509345],[-130.101674,55.481147],[-130.095082,55.472113],[-130.065419,55.446112],[-130.057525,55.434882],[-130.052561,55.414008],[-130.054311,55.366645],[-130.05012,55.345445],[-130.039296,55.330756],[-129.989247,55.284003],[-130.031239,55.26435],[-130.050038,55.252875],[-130.067494,55.239],[-130.078236,55.233791],[-130.100494,55.230292],[-130.104726,55.225653],[-130.105702,55.211127],[-130.10912,55.200751],[-130.115793,55.191596],[-130.126454,55.180976],[-130.151967,55.163275],[-130.159983,55.153713],[-130.167592,55.129584],[-130.173695,55.117743],[-130.200266,55.104153],[-130.211781,55.084133],[-130.228871,55.04385],[-130.238678,55.03441],[-130.261342,55.022895],[-130.269846,55.016547],[-130.275706,55.006985],[-130.286366,54.983222],[-130.294342,54.971869],[-130.326568,54.952094],[-130.335561,54.938707],[-130.365387,54.907294],[-130.385243,54.896552],[-130.430816,54.881252],[-130.488759,54.844184],[-130.580312,54.806383],[-130.597485,54.803391],[-130.71074,54.733215],[-131.160718,54.787192]]]]}}]},"featureIcons":{"circle-stroked-24":{"x":0,"y":0,"width":24,"height":24},"circle-stroked-18":{"x":24,"y":0,"width":18,"height":18},"circle-stroked-12":{"x":42,"y":0,"width":12,"height":12},"circle-24":{"x":54,"y":0,"width":24,"height":24},"circle-18":{"x":78,"y":0,"width":18,"height":18},"circle-12":{"x":96,"y":0,"width":12,"height":12},"square-stroked-24":{"x":108,"y":0,"width":24,"height":24},"square-stroked-18":{"x":132,"y":0,"width":18,"height":18},"square-stroked-12":{"x":150,"y":0,"width":12,"height":12},"square-24":{"x":162,"y":0,"width":24,"height":24},"square-18":{"x":186,"y":0,"width":18,"height":18},"square-12":{"x":204,"y":0,"width":12,"height":12},"triangle-stroked-24":{"x":216,"y":0,"width":24,"height":24},"triangle-stroked-18":{"x":240,"y":0,"width":18,"height":18},"triangle-stroked-12":{"x":258,"y":0,"width":12,"height":12},"triangle-24":{"x":0,"y":24,"width":24,"height":24},"triangle-18":{"x":24,"y":24,"width":18,"height":18},"triangle-12":{"x":42,"y":24,"width":12,"height":12},"star-stroked-24":{"x":54,"y":24,"width":24,"height":24},"star-stroked-18":{"x":78,"y":24,"width":18,"height":18},"star-stroked-12":{"x":96,"y":24,"width":12,"height":12},"star-24":{"x":108,"y":24,"width":24,"height":24},"star-18":{"x":132,"y":24,"width":18,"height":18},"star-12":{"x":150,"y":24,"width":12,"height":12},"cross-24":{"x":162,"y":24,"width":24,"height":24},"cross-18":{"x":186,"y":24,"width":18,"height":18},"cross-12":{"x":204,"y":24,"width":12,"height":12},"marker-stroked-24":{"x":216,"y":24,"width":24,"height":24},"marker-stroked-18":{"x":240,"y":24,"width":18,"height":18},"marker-stroked-12":{"x":258,"y":24,"width":12,"height":12},"marker-24":{"x":0,"y":48,"width":24,"height":24},"marker-18":{"x":24,"y":48,"width":18,"height":18},"marker-12":{"x":42,"y":48,"width":12,"height":12},"religious-jewish-24":{"x":54,"y":48,"width":24,"height":24},"religious-jewish-18":{"x":78,"y":48,"width":18,"height":18},"religious-jewish-12":{"x":96,"y":48,"width":12,"height":12},"religious-christian-24":{"x":108,"y":48,"width":24,"height":24},"religious-christian-18":{"x":132,"y":48,"width":18,"height":18},"religious-christian-12":{"x":150,"y":48,"width":12,"height":12},"religious-muslim-24":{"x":162,"y":48,"width":24,"height":24},"religious-muslim-18":{"x":186,"y":48,"width":18,"height":18},"religious-muslim-12":{"x":204,"y":48,"width":12,"height":12},"cemetery-24":{"x":216,"y":48,"width":24,"height":24},"cemetery-18":{"x":240,"y":48,"width":18,"height":18},"cemetery-12":{"x":258,"y":48,"width":12,"height":12},"rocket-24":{"x":0,"y":72,"width":24,"height":24},"rocket-18":{"x":24,"y":72,"width":18,"height":18},"rocket-12":{"x":42,"y":72,"width":12,"height":12},"airport-24":{"x":54,"y":72,"width":24,"height":24},"airport-18":{"x":78,"y":72,"width":18,"height":18},"airport-12":{"x":96,"y":72,"width":12,"height":12},"heliport-24":{"x":108,"y":72,"width":24,"height":24},"heliport-18":{"x":132,"y":72,"width":18,"height":18},"heliport-12":{"x":150,"y":72,"width":12,"height":12},"rail-24":{"x":162,"y":72,"width":24,"height":24},"rail-18":{"x":186,"y":72,"width":18,"height":18},"rail-12":{"x":204,"y":72,"width":12,"height":12},"rail-metro-24":{"x":216,"y":72,"width":24,"height":24},"rail-metro-18":{"x":240,"y":72,"width":18,"height":18},"rail-metro-12":{"x":258,"y":72,"width":12,"height":12},"rail-light-24":{"x":0,"y":96,"width":24,"height":24},"rail-light-18":{"x":24,"y":96,"width":18,"height":18},"rail-light-12":{"x":42,"y":96,"width":12,"height":12},"bus-24":{"x":54,"y":96,"width":24,"height":24},"bus-18":{"x":78,"y":96,"width":18,"height":18},"bus-12":{"x":96,"y":96,"width":12,"height":12},"fuel-24":{"x":108,"y":96,"width":24,"height":24},"fuel-18":{"x":132,"y":96,"width":18,"height":18},"fuel-12":{"x":150,"y":96,"width":12,"height":12},"parking-24":{"x":162,"y":96,"width":24,"height":24},"parking-18":{"x":186,"y":96,"width":18,"height":18},"parking-12":{"x":204,"y":96,"width":12,"height":12},"parking-garage-24":{"x":216,"y":96,"width":24,"height":24},"parking-garage-18":{"x":240,"y":96,"width":18,"height":18},"parking-garage-12":{"x":258,"y":96,"width":12,"height":12},"airfield-24":{"x":0,"y":120,"width":24,"height":24},"airfield-18":{"x":24,"y":120,"width":18,"height":18},"airfield-12":{"x":42,"y":120,"width":12,"height":12},"roadblock-24":{"x":54,"y":120,"width":24,"height":24},"roadblock-18":{"x":78,"y":120,"width":18,"height":18},"roadblock-12":{"x":96,"y":120,"width":12,"height":12},"ferry-24":{"x":108,"y":120,"width":24,"height":24},"ferry-18":{"x":132,"y":120,"width":18,"height":18},"ferry-12":{"x":150,"y":120,"width":12,"height":12},"harbor-24":{"x":162,"y":120,"width":24,"height":24},"harbor-18":{"x":186,"y":120,"width":18,"height":18},"harbor-12":{"x":204,"y":120,"width":12,"height":12},"bicycle-24":{"x":216,"y":120,"width":24,"height":24},"bicycle-18":{"x":240,"y":120,"width":18,"height":18},"bicycle-12":{"x":258,"y":120,"width":12,"height":12},"park-24":{"x":0,"y":144,"width":24,"height":24},"park-18":{"x":24,"y":144,"width":18,"height":18},"park-12":{"x":42,"y":144,"width":12,"height":12},"park2-24":{"x":54,"y":144,"width":24,"height":24},"park2-18":{"x":78,"y":144,"width":18,"height":18},"park2-12":{"x":96,"y":144,"width":12,"height":12},"museum-24":{"x":108,"y":144,"width":24,"height":24},"museum-18":{"x":132,"y":144,"width":18,"height":18},"museum-12":{"x":150,"y":144,"width":12,"height":12},"lodging-24":{"x":162,"y":144,"width":24,"height":24},"lodging-18":{"x":186,"y":144,"width":18,"height":18},"lodging-12":{"x":204,"y":144,"width":12,"height":12},"monument-24":{"x":216,"y":144,"width":24,"height":24},"monument-18":{"x":240,"y":144,"width":18,"height":18},"monument-12":{"x":258,"y":144,"width":12,"height":12},"zoo-24":{"x":0,"y":168,"width":24,"height":24},"zoo-18":{"x":24,"y":168,"width":18,"height":18},"zoo-12":{"x":42,"y":168,"width":12,"height":12},"garden-24":{"x":54,"y":168,"width":24,"height":24},"garden-18":{"x":78,"y":168,"width":18,"height":18},"garden-12":{"x":96,"y":168,"width":12,"height":12},"campsite-24":{"x":108,"y":168,"width":24,"height":24},"campsite-18":{"x":132,"y":168,"width":18,"height":18},"campsite-12":{"x":150,"y":168,"width":12,"height":12},"theatre-24":{"x":162,"y":168,"width":24,"height":24},"theatre-18":{"x":186,"y":168,"width":18,"height":18},"theatre-12":{"x":204,"y":168,"width":12,"height":12},"art-gallery-24":{"x":216,"y":168,"width":24,"height":24},"art-gallery-18":{"x":240,"y":168,"width":18,"height":18},"art-gallery-12":{"x":258,"y":168,"width":12,"height":12},"pitch-24":{"x":0,"y":192,"width":24,"height":24},"pitch-18":{"x":24,"y":192,"width":18,"height":18},"pitch-12":{"x":42,"y":192,"width":12,"height":12},"soccer-24":{"x":54,"y":192,"width":24,"height":24},"soccer-18":{"x":78,"y":192,"width":18,"height":18},"soccer-12":{"x":96,"y":192,"width":12,"height":12},"america-football-24":{"x":108,"y":192,"width":24,"height":24},"america-football-18":{"x":132,"y":192,"width":18,"height":18},"america-football-12":{"x":150,"y":192,"width":12,"height":12},"tennis-24":{"x":162,"y":192,"width":24,"height":24},"tennis-18":{"x":186,"y":192,"width":18,"height":18},"tennis-12":{"x":204,"y":192,"width":12,"height":12},"basketball-24":{"x":216,"y":192,"width":24,"height":24},"basketball-18":{"x":240,"y":192,"width":18,"height":18},"basketball-12":{"x":258,"y":192,"width":12,"height":12},"baseball-24":{"x":0,"y":216,"width":24,"height":24},"baseball-18":{"x":24,"y":216,"width":18,"height":18},"baseball-12":{"x":42,"y":216,"width":12,"height":12},"golf-24":{"x":54,"y":216,"width":24,"height":24},"golf-18":{"x":78,"y":216,"width":18,"height":18},"golf-12":{"x":96,"y":216,"width":12,"height":12},"swimming-24":{"x":108,"y":216,"width":24,"height":24},"swimming-18":{"x":132,"y":216,"width":18,"height":18},"swimming-12":{"x":150,"y":216,"width":12,"height":12},"cricket-24":{"x":162,"y":216,"width":24,"height":24},"cricket-18":{"x":186,"y":216,"width":18,"height":18},"cricket-12":{"x":204,"y":216,"width":12,"height":12},"skiing-24":{"x":216,"y":216,"width":24,"height":24},"skiing-18":{"x":240,"y":216,"width":18,"height":18},"skiing-12":{"x":258,"y":216,"width":12,"height":12},"school-24":{"x":0,"y":240,"width":24,"height":24},"school-18":{"x":24,"y":240,"width":18,"height":18},"school-12":{"x":42,"y":240,"width":12,"height":12},"college-24":{"x":54,"y":240,"width":24,"height":24},"college-18":{"x":78,"y":240,"width":18,"height":18},"college-12":{"x":96,"y":240,"width":12,"height":12},"library-24":{"x":108,"y":240,"width":24,"height":24},"library-18":{"x":132,"y":240,"width":18,"height":18},"library-12":{"x":150,"y":240,"width":12,"height":12},"post-24":{"x":162,"y":240,"width":24,"height":24},"post-18":{"x":186,"y":240,"width":18,"height":18},"post-12":{"x":204,"y":240,"width":12,"height":12},"fire-station-24":{"x":216,"y":240,"width":24,"height":24},"fire-station-18":{"x":240,"y":240,"width":18,"height":18},"fire-station-12":{"x":258,"y":240,"width":12,"height":12},"town-hall-24":{"x":0,"y":264,"width":24,"height":24},"town-hall-18":{"x":24,"y":264,"width":18,"height":18},"town-hall-12":{"x":42,"y":264,"width":12,"height":12},"police-24":{"x":54,"y":264,"width":24,"height":24},"police-18":{"x":78,"y":264,"width":18,"height":18},"police-12":{"x":96,"y":264,"width":12,"height":12},"prison-24":{"x":108,"y":264,"width":24,"height":24},"prison-18":{"x":132,"y":264,"width":18,"height":18},"prison-12":{"x":150,"y":264,"width":12,"height":12},"embassy-24":{"x":162,"y":264,"width":24,"height":24},"embassy-18":{"x":186,"y":264,"width":18,"height":18},"embassy-12":{"x":204,"y":264,"width":12,"height":12},"beer-24":{"x":216,"y":264,"width":24,"height":24},"beer-18":{"x":240,"y":264,"width":18,"height":18},"beer-12":{"x":258,"y":264,"width":12,"height":12},"restaurant-24":{"x":0,"y":288,"width":24,"height":24},"restaurant-18":{"x":24,"y":288,"width":18,"height":18},"restaurant-12":{"x":42,"y":288,"width":12,"height":12},"cafe-24":{"x":54,"y":288,"width":24,"height":24},"cafe-18":{"x":78,"y":288,"width":18,"height":18},"cafe-12":{"x":96,"y":288,"width":12,"height":12},"shop-24":{"x":108,"y":288,"width":24,"height":24},"shop-18":{"x":132,"y":288,"width":18,"height":18},"shop-12":{"x":150,"y":288,"width":12,"height":12},"fast-food-24":{"x":162,"y":288,"width":24,"height":24},"fast-food-18":{"x":186,"y":288,"width":18,"height":18},"fast-food-12":{"x":204,"y":288,"width":12,"height":12},"bar-24":{"x":216,"y":288,"width":24,"height":24},"bar-18":{"x":240,"y":288,"width":18,"height":18},"bar-12":{"x":258,"y":288,"width":12,"height":12},"bank-24":{"x":0,"y":312,"width":24,"height":24},"bank-18":{"x":24,"y":312,"width":18,"height":18},"bank-12":{"x":42,"y":312,"width":12,"height":12},"grocery-24":{"x":54,"y":312,"width":24,"height":24},"grocery-18":{"x":78,"y":312,"width":18,"height":18},"grocery-12":{"x":96,"y":312,"width":12,"height":12},"cinema-24":{"x":108,"y":312,"width":24,"height":24},"cinema-18":{"x":132,"y":312,"width":18,"height":18},"cinema-12":{"x":150,"y":312,"width":12,"height":12},"pharmacy-24":{"x":162,"y":312,"width":24,"height":24},"pharmacy-18":{"x":186,"y":312,"width":18,"height":18},"pharmacy-12":{"x":204,"y":312,"width":12,"height":12},"hospital-24":{"x":216,"y":312,"width":24,"height":24},"hospital-18":{"x":240,"y":312,"width":18,"height":18},"hospital-12":{"x":258,"y":312,"width":12,"height":12},"danger-24":{"x":0,"y":336,"width":24,"height":24},"danger-18":{"x":24,"y":336,"width":18,"height":18},"danger-12":{"x":42,"y":336,"width":12,"height":12},"industrial-24":{"x":54,"y":336,"width":24,"height":24},"industrial-18":{"x":78,"y":336,"width":18,"height":18},"industrial-12":{"x":96,"y":336,"width":12,"height":12},"warehouse-24":{"x":108,"y":336,"width":24,"height":24},"warehouse-18":{"x":132,"y":336,"width":18,"height":18},"warehouse-12":{"x":150,"y":336,"width":12,"height":12},"commercial-24":{"x":162,"y":336,"width":24,"height":24},"commercial-18":{"x":186,"y":336,"width":18,"height":18},"commercial-12":{"x":204,"y":336,"width":12,"height":12},"building-24":{"x":216,"y":336,"width":24,"height":24},"building-18":{"x":240,"y":336,"width":18,"height":18},"building-12":{"x":258,"y":336,"width":12,"height":12},"place-of-worship-24":{"x":0,"y":360,"width":24,"height":24},"place-of-worship-18":{"x":24,"y":360,"width":18,"height":18},"place-of-worship-12":{"x":42,"y":360,"width":12,"height":12},"alcohol-shop-24":{"x":54,"y":360,"width":24,"height":24},"alcohol-shop-18":{"x":78,"y":360,"width":18,"height":18},"alcohol-shop-12":{"x":96,"y":360,"width":12,"height":12},"logging-24":{"x":108,"y":360,"width":24,"height":24},"logging-18":{"x":132,"y":360,"width":18,"height":18},"logging-12":{"x":150,"y":360,"width":12,"height":12},"oil-well-24":{"x":162,"y":360,"width":24,"height":24},"oil-well-18":{"x":186,"y":360,"width":18,"height":18},"oil-well-12":{"x":204,"y":360,"width":12,"height":12},"slaughterhouse-24":{"x":216,"y":360,"width":24,"height":24},"slaughterhouse-18":{"x":240,"y":360,"width":18,"height":18},"slaughterhouse-12":{"x":258,"y":360,"width":12,"height":12},"dam-24":{"x":0,"y":384,"width":24,"height":24},"dam-18":{"x":24,"y":384,"width":18,"height":18},"dam-12":{"x":42,"y":384,"width":12,"height":12},"water-24":{"x":54,"y":384,"width":24,"height":24},"water-18":{"x":78,"y":384,"width":18,"height":18},"water-12":{"x":96,"y":384,"width":12,"height":12},"wetland-24":{"x":108,"y":384,"width":24,"height":24},"wetland-18":{"x":132,"y":384,"width":18,"height":18},"wetland-12":{"x":150,"y":384,"width":12,"height":12},"disability-24":{"x":162,"y":384,"width":24,"height":24},"disability-18":{"x":186,"y":384,"width":18,"height":18},"disability-12":{"x":204,"y":384,"width":12,"height":12},"telephone-24":{"x":216,"y":384,"width":24,"height":24},"telephone-18":{"x":240,"y":384,"width":18,"height":18},"telephone-12":{"x":258,"y":384,"width":12,"height":12},"emergency-telephone-24":{"x":0,"y":408,"width":24,"height":24},"emergency-telephone-18":{"x":24,"y":408,"width":18,"height":18},"emergency-telephone-12":{"x":42,"y":408,"width":12,"height":12},"toilets-24":{"x":54,"y":408,"width":24,"height":24},"toilets-18":{"x":78,"y":408,"width":18,"height":18},"toilets-12":{"x":96,"y":408,"width":12,"height":12},"waste-basket-24":{"x":108,"y":408,"width":24,"height":24},"waste-basket-18":{"x":132,"y":408,"width":18,"height":18},"waste-basket-12":{"x":150,"y":408,"width":12,"height":12},"music-24":{"x":162,"y":408,"width":24,"height":24},"music-18":{"x":186,"y":408,"width":18,"height":18},"music-12":{"x":204,"y":408,"width":12,"height":12},"land-use-24":{"x":216,"y":408,"width":24,"height":24},"land-use-18":{"x":240,"y":408,"width":18,"height":18},"land-use-12":{"x":258,"y":408,"width":12,"height":12},"city-24":{"x":0,"y":432,"width":24,"height":24},"city-18":{"x":24,"y":432,"width":18,"height":18},"city-12":{"x":42,"y":432,"width":12,"height":12},"town-24":{"x":54,"y":432,"width":24,"height":24},"town-18":{"x":78,"y":432,"width":18,"height":18},"town-12":{"x":96,"y":432,"width":12,"height":12},"village-24":{"x":108,"y":432,"width":24,"height":24},"village-18":{"x":132,"y":432,"width":18,"height":18},"village-12":{"x":150,"y":432,"width":12,"height":12},"farm-24":{"x":162,"y":432,"width":24,"height":24},"farm-18":{"x":186,"y":432,"width":18,"height":18},"farm-12":{"x":204,"y":432,"width":12,"height":12},"bakery-24":{"x":216,"y":432,"width":24,"height":24},"bakery-18":{"x":240,"y":432,"width":18,"height":18},"bakery-12":{"x":258,"y":432,"width":12,"height":12},"dog-park-24":{"x":0,"y":456,"width":24,"height":24},"dog-park-18":{"x":24,"y":456,"width":18,"height":18},"dog-park-12":{"x":42,"y":456,"width":12,"height":12},"lighthouse-24":{"x":54,"y":456,"width":24,"height":24},"lighthouse-18":{"x":78,"y":456,"width":18,"height":18},"lighthouse-12":{"x":96,"y":456,"width":12,"height":12},"clothing-store-24":{"x":108,"y":456,"width":24,"height":24},"clothing-store-18":{"x":132,"y":456,"width":18,"height":18},"clothing-store-12":{"x":150,"y":456,"width":12,"height":12},"polling-place-24":{"x":162,"y":456,"width":24,"height":24},"polling-place-18":{"x":186,"y":456,"width":18,"height":18},"polling-place-12":{"x":204,"y":456,"width":12,"height":12},"playground-24":{"x":216,"y":456,"width":24,"height":24},"playground-18":{"x":240,"y":456,"width":18,"height":18},"playground-12":{"x":258,"y":456,"width":12,"height":12},"entrance-24":{"x":0,"y":480,"width":24,"height":24},"entrance-18":{"x":24,"y":480,"width":18,"height":18},"entrance-12":{"x":42,"y":480,"width":12,"height":12},"heart-24":{"x":54,"y":480,"width":24,"height":24},"heart-18":{"x":78,"y":480,"width":18,"height":18},"heart-12":{"x":96,"y":480,"width":12,"height":12},"london-underground-24":{"x":108,"y":480,"width":24,"height":24},"london-underground-18":{"x":132,"y":480,"width":18,"height":18},"london-underground-12":{"x":150,"y":480,"width":12,"height":12},"minefield-24":{"x":162,"y":480,"width":24,"height":24},"minefield-18":{"x":186,"y":480,"width":18,"height":18},"minefield-12":{"x":204,"y":480,"width":12,"height":12},"rail-underground-24":{"x":216,"y":480,"width":24,"height":24},"rail-underground-18":{"x":240,"y":480,"width":18,"height":18},"rail-underground-12":{"x":258,"y":480,"width":12,"height":12},"rail-above-24":{"x":0,"y":504,"width":24,"height":24},"rail-above-18":{"x":24,"y":504,"width":18,"height":18},"rail-above-12":{"x":42,"y":504,"width":12,"height":12},"camera-24":{"x":54,"y":504,"width":24,"height":24},"camera-18":{"x":78,"y":504,"width":18,"height":18},"camera-12":{"x":96,"y":504,"width":12,"height":12},"laundry-24":{"x":108,"y":504,"width":24,"height":24},"laundry-18":{"x":132,"y":504,"width":18,"height":18},"laundry-12":{"x":150,"y":504,"width":12,"height":12},"car-24":{"x":162,"y":504,"width":24,"height":24},"car-18":{"x":186,"y":504,"width":18,"height":18},"car-12":{"x":204,"y":504,"width":12,"height":12},"suitcase-24":{"x":216,"y":504,"width":24,"height":24},"suitcase-18":{"x":240,"y":504,"width":18,"height":18},"suitcase-12":{"x":258,"y":504,"width":12,"height":12},"hairdresser-24":{"x":0,"y":528,"width":24,"height":24},"hairdresser-18":{"x":24,"y":528,"width":18,"height":18},"hairdresser-12":{"x":42,"y":528,"width":12,"height":12},"chemist-24":{"x":54,"y":528,"width":24,"height":24},"chemist-18":{"x":78,"y":528,"width":18,"height":18},"chemist-12":{"x":96,"y":528,"width":12,"height":12},"mobilephone-24":{"x":108,"y":528,"width":24,"height":24},"mobilephone-18":{"x":132,"y":528,"width":18,"height":18},"mobilephone-12":{"x":150,"y":528,"width":12,"height":12},"scooter-24":{"x":162,"y":528,"width":24,"height":24},"scooter-18":{"x":186,"y":528,"width":18,"height":18},"scooter-12":{"x":204,"y":528,"width":12,"height":12},"gift-24":{"x":216,"y":528,"width":24,"height":24},"gift-18":{"x":240,"y":528,"width":18,"height":18},"gift-12":{"x":258,"y":528,"width":12,"height":12},"ice-cream-24":{"x":0,"y":552,"width":24,"height":24},"ice-cream-18":{"x":24,"y":552,"width":18,"height":18},"ice-cream-12":{"x":42,"y":552,"width":12,"height":12}},"locales":["af","sq","ar","ar-AA","hy","ast","bn","bs","bg-BG","ca","zh","zh-CN","zh-HK","zh-TW","yue","hr","cs","da","nl","en-GB","eo","et","fi","fr","gl","de","el","hi","hu","is","id","it","ja","kn","ko","lv","lij","lt","no","fa","pl","pt","pt-BR","ro","ru","sc","sr","si","sk","sl","es","sv","tl","ta","te","th","tr","uk","vi"],"en":{"modes":{"add_area":{"title":"Area","description":"Add parks, buildings, lakes or other areas to the map.","tail":"Click on the map to start drawing an area, like a park, lake, or building."},"add_line":{"title":"Line","description":"Add highways, streets, pedestrian paths, canals or other lines to the map.","tail":"Click on the map to start drawing a road, path, or route."},"add_point":{"title":"Point","description":"Add restaurants, monuments, postal boxes or other points to the map.","tail":"Click on the map to add a point."},"browse":{"title":"Browse","description":"Pan and zoom the map."},"draw_area":{"tail":"Click to add nodes to your area. Click the first node to finish the area."},"draw_line":{"tail":"Click to add more nodes to the line. Click on other lines to connect to them, and double-click to end the line."}},"operations":{"add":{"annotation":{"point":"Added a point.","vertex":"Added a node to a way.","relation":"Added a relation."}},"start":{"annotation":{"line":"Started a line.","area":"Started an area."}},"continue":{"key":"A","title":"Continue","description":"Continue this line.","not_eligible":"No line can be continued here.","multiple":"Several lines can be continued here. To choose a line, press the Shift key and click on it to select it.","annotation":{"line":"Continued a line.","area":"Continued an area."}},"cancel_draw":{"annotation":"Canceled drawing."},"change_role":{"annotation":"Changed the role of a relation member."},"change_tags":{"annotation":"Changed tags."},"circularize":{"title":"Circularize","description":{"line":"Make this line circular.","area":"Make this area circular."},"key":"O","annotation":{"line":"Made a line circular.","area":"Made an area circular."},"not_closed":"This can't be made circular because it's not a loop.","too_large":"This can't be made circular because not enough of it is currently visible.","connected_to_hidden":"This can't be made circular because it is connected to a hidden feature."},"orthogonalize":{"title":"Square","description":{"line":"Square the corners of this line.","area":"Square the corners of this area."},"key":"S","annotation":{"line":"Squared the corners of a line.","area":"Squared the corners of an area."},"not_squarish":"This can't be made square because it is not squarish.","too_large":"This can't be made square because not enough of it is currently visible.","connected_to_hidden":"This can't be made square because it is connected to a hidden feature."},"straighten":{"title":"Straighten","description":"Straighten this line.","key":"S","annotation":"Straightened a line.","too_bendy":"This can't be straightened because it bends too much.","connected_to_hidden":"This line can't be straightened because it is connected to a hidden feature."},"delete":{"title":"Delete","description":"Delete object permanently.","annotation":{"point":"Deleted a point.","vertex":"Deleted a node from a way.","line":"Deleted a line.","area":"Deleted an area.","relation":"Deleted a relation.","multiple":"Deleted {n} objects."},"incomplete_relation":"This feature can't be deleted because it hasn't been fully downloaded.","part_of_relation":"This feature can't be deleted because it's part of a larger relation. You must remove it from the relation first.","connected_to_hidden":"This can't be deleted because it is connected to a hidden feature."},"add_member":{"annotation":"Added a member to a relation."},"delete_member":{"annotation":"Removed a member from a relation."},"connect":{"annotation":{"point":"Connected a way to a point.","vertex":"Connected a way to another.","line":"Connected a way to a line.","area":"Connected a way to an area."}},"disconnect":{"title":"Disconnect","description":"Disconnect these lines/areas from each other.","key":"D","annotation":"Disconnected lines/areas.","not_connected":"There aren't enough lines/areas here to disconnect.","connected_to_hidden":"This can't be disconnected because it is connected to a hidden feature.","relation":"This can't be disconnected because it connects members of a relation."},"merge":{"title":"Merge","description":"Merge these features.","key":"C","annotation":"Merged {n} features.","not_eligible":"These features can't be merged.","not_adjacent":"These features can't be merged because they aren't connected.","restriction":"These features can't be merged because at least one is a member of a \"{relation}\" relation.","incomplete_relation":"These features can't be merged because at least one hasn't been fully downloaded.","conflicting_tags":"These features can't be merged because some of their tags have conflicting values."},"move":{"title":"Move","description":"Move this to a different location.","key":"M","annotation":{"point":"Moved a point.","vertex":"Moved a node in a way.","line":"Moved a line.","area":"Moved an area.","multiple":"Moved multiple objects."},"incomplete_relation":"This feature can't be moved because it hasn't been fully downloaded.","too_large":"This can't be moved because not enough of it is currently visible.","connected_to_hidden":"This can't be moved because it is connected to a hidden feature."},"rotate":{"title":"Rotate","description":"Rotate this object around its center point.","key":"R","annotation":{"line":"Rotated a line.","area":"Rotated an area."},"too_large":"This can't be rotated because not enough of it is currently visible.","connected_to_hidden":"This can't be rotated because it is connected to a hidden feature."},"reverse":{"title":"Reverse","description":"Make this line go in the opposite direction.","key":"V","annotation":"Reversed a line."},"split":{"title":"Split","description":{"line":"Split this line into two at this node.","area":"Split the boundary of this area into two.","multiple":"Split the lines/area boundaries at this node into two."},"key":"X","annotation":{"line":"Split a line.","area":"Split an area boundary.","multiple":"Split {n} lines/area boundaries."},"not_eligible":"Lines can't be split at their beginning or end.","multiple_ways":"There are too many lines here to split.","connected_to_hidden":"This can't be split because it is connected to a hidden feature."},"restriction":{"help":{"select":"Click to select a road segment.","toggle":"Click to toggle turn restrictions.","toggle_on":"Click to add a \"{restriction}\" restriction.","toggle_off":"Click to remove the \"{restriction}\" restriction."},"annotation":{"create":"Added a turn restriction","delete":"Deleted a turn restriction"}}},"undo":{"tooltip":"Undo: {action}","nothing":"Nothing to undo."},"redo":{"tooltip":"Redo: {action}","nothing":"Nothing to redo."},"tooltip_keyhint":"Shortcut:","browser_notice":"This editor is supported in Firefox, Chrome, Safari, Opera, and Internet Explorer 11 and above. Please upgrade your browser or use Potlatch 2 to edit the map.","translate":{"translate":"Translate","localized_translation_label":"Multilingual name","localized_translation_language":"Choose language","localized_translation_name":"Name"},"zoom_in_edit":"Zoom in to Edit","logout":"logout","loading_auth":"Connecting to OpenStreetMap...","report_a_bug":"Report a bug","help_translate":"Help translate","feature_info":{"hidden_warning":"{count} hidden features","hidden_details":"These features are currently hidden: {details}"},"status":{"error":"Unable to connect to API.","offline":"The API is offline. Please try editing later.","readonly":"The API is read-only. You will need to wait to save your changes."},"commit":{"title":"Save Changes","description_placeholder":"Brief description of your contributions","message_label":"Changeset comment","upload_explanation":"The changes you upload will be visible on all maps that use OpenStreetMap data.","upload_explanation_with_user":"The changes you upload as {user} will be visible on all maps that use OpenStreetMap data.","save":"Save","cancel":"Cancel","changes":"{count} Changes","warnings":"Warnings","modified":"Modified","deleted":"Deleted","created":"Created","about_changeset_comments":"About changeset comments","about_changeset_comments_link":"//wiki.openstreetmap.org/wiki/Good_changeset_comments"},"contributors":{"list":"Edits by {users}","truncated_list":"Edits by {users} and {count} others"},"infobox":{"selected":"{n} selected","geometry":"Geometry","closed":"closed","center":"Center","perimeter":"Perimeter","length":"Length","area":"Area","centroid":"Centroid","location":"Location","metric":"Metric","imperial":"Imperial"},"geometry":{"point":"point","vertex":"vertex","line":"line","area":"area","relation":"relation"},"geocoder":{"search":"Search worldwide...","no_results_visible":"No results in visible map area","no_results_worldwide":"No results found"},"geolocate":{"title":"Show My Location"},"inspector":{"no_documentation_combination":"There is no documentation available for this tag combination","no_documentation_key":"There is no documentation available for this key","show_more":"Show More","view_on_osm":"View on openstreetmap.org","all_fields":"All fields","all_tags":"All tags","all_members":"All members","all_relations":"All relations","new_relation":"New relation...","role":"Role","choose":"Select feature type","results":"{n} results for {search}","reference":"View on OpenStreetMap Wiki","back_tooltip":"Change feature","remove":"Remove","search":"Search","multiselect":"Selected items","unknown":"Unknown","incomplete":"<not downloaded>","feature_list":"Search features","edit":"Edit feature","check":{"yes":"Yes","no":"No"},"none":"None","node":"Node","way":"Way","relation":"Relation","location":"Location","add_fields":"Add field:"},"background":{"title":"Background","description":"Background settings","percent_brightness":"{opacity}% brightness","none":"None","best_imagery":"Best known imagery source for this location","custom":"Custom","custom_button":"Edit custom background","custom_prompt":"Enter a tile URL template. Valid tokens are {z}, {x}, {y} for Z/X/Y scheme and {u} for quadtile scheme.","fix_misalignment":"Fix alignment","imagery_source_faq":"Where does this imagery come from?","reset":"reset","minimap":{"description":"Minimap","tooltip":"Show a zoomed out map to help locate the area currently displayed."}},"map_data":{"title":"Map Data","description":"Map Data","data_layers":"Data Layers","fill_area":"Fill Areas","map_features":"Map Features","autohidden":"These features have been automatically hidden because too many would be shown on the screen.  You can zoom in to edit them."},"feature":{"points":{"description":"Points","tooltip":"Points of Interest"},"major_roads":{"description":"Major Roads","tooltip":"Highways, Streets, etc."},"minor_roads":{"description":"Minor Roads","tooltip":"Service Roads, Parking Aisles, Tracks, etc."},"paths":{"description":"Paths","tooltip":"Sidewalks, Foot Paths, Cycle Paths, etc."},"buildings":{"description":"Buildings","tooltip":"Buildings, Shelters, Garages, etc."},"landuse":{"description":"Landuse Features","tooltip":"Forests, Farmland, Parks, Residential, Commercial, etc."},"boundaries":{"description":"Boundaries","tooltip":"Administrative Boundaries"},"water":{"description":"Water Features","tooltip":"Rivers, Lakes, Ponds, Basins, etc."},"rail":{"description":"Rail Features","tooltip":"Railways"},"power":{"description":"Power Features","tooltip":"Power Lines, Power Plants, Substations, etc."},"past_future":{"description":"Past/Future","tooltip":"Proposed, Construction, Abandoned, Demolished, etc."},"others":{"description":"Others","tooltip":"Everything Else"}},"area_fill":{"wireframe":{"description":"No Fill (Wireframe)","tooltip":"Enabling wireframe mode makes it easy to see the background imagery."},"partial":{"description":"Partial Fill","tooltip":"Areas are drawn with fill only around their inner edges. (Recommended for beginner mappers)"},"full":{"description":"Full Fill","tooltip":"Areas are drawn fully filled."}},"restore":{"heading":"You have unsaved changes","description":"Do you wish to restore unsaved changes from a previous editing session?","restore":"Restore","reset":"Reset"},"save":{"title":"Save","help":"Save changes to OpenStreetMap, making them visible to other users.","no_changes":"No changes to save.","error":"Errors occurred while trying to save","status_code":"Server returned status code {code}","unknown_error_details":"Please ensure you are connected to the internet.","uploading":"Uploading changes to OpenStreetMap.","unsaved_changes":"You have unsaved changes","conflict":{"header":"Resolve conflicting edits","count":"Conflict {num} of {total}","previous":"< Previous","next":"Next >","keep_local":"Keep mine","keep_remote":"Use theirs","restore":"Restore","delete":"Leave Deleted","download_changes":"Or download your changes.","done":"All conflicts resolved!","help":"Another user changed some of the same map features you changed.\nClick on each item below for more details about the conflict, and choose whether to keep\nyour changes or the other user's changes.\n"}},"merge_remote_changes":{"conflict":{"deleted":"This object has been deleted by {user}.","location":"This object was moved by both you and {user}.","nodelist":"Nodes were changed by both you and {user}.","memberlist":"Relation members were changed by both you and {user}.","tags":"You changed the <b>{tag}</b> tag to \"{local}\" and {user} changed it to \"{remote}\"."}},"success":{"edited_osm":"Edited OSM!","just_edited":"You just edited OpenStreetMap!","view_on_osm":"View on OSM","facebook":"Share on Facebook","twitter":"Share on Twitter","google":"Share on Google+","help_html":"Your changes should appear in the \"Standard\" layer in a few minutes. Other layers, and certain features, may take longer.","help_link_text":"Details","help_link_url":"https://wiki.openstreetmap.org/wiki/FAQ#I_have_just_made_some_changes_to_the_map._How_do_I_get_to_see_my_changes.3F"},"confirm":{"okay":"Okay","cancel":"Cancel"},"splash":{"welcome":"Welcome to the iD OpenStreetMap editor","text":"iD is a friendly but powerful tool for contributing to the world's best free world map. This is version {version}. For more information see {website} and report bugs at {github}.","walkthrough":"Start the Walkthrough","start":"Edit Now"},"source_switch":{"live":"live","lose_changes":"You have unsaved changes. Switching the map server will discard them. Are you sure you want to switch servers?","dev":"dev"},"tag_reference":{"description":"Description","on_wiki":"{tag} on wiki.osm.org","used_with":"used with {type}"},"validations":{"untagged_point":"Untagged point","untagged_line":"Untagged line","untagged_area":"Untagged area","many_deletions":"You're deleting {n} objects. Are you sure you want to do this? This will delete them from the map that everyone else sees on openstreetmap.org.","tag_suggests_area":"The tag {tag} suggests line should be area, but it is not an area","untagged_point_tooltip":"Select a feature type that describes what this point is.","untagged_line_tooltip":"Select a feature type that describes what this line is.","untagged_area_tooltip":"Select a feature type that describes what this area is.","deprecated_tags":"Deprecated tags: {tags}"},"zoom":{"in":"Zoom In","out":"Zoom Out"},"cannot_zoom":"Cannot zoom out further in current mode.","full_screen":"Toggle Full Screen","gpx":{"local_layer":"Local GPX file","drag_drop":"Drag and drop a .gpx file on the page, or click the button to the right to browse","zoom":"Zoom to GPX track","browse":"Browse for a .gpx file"},"mapillary_images":{"tooltip":"Street-level photos from Mapillary","title":"Photo Overlay (Mapillary)"},"mapillary_signs":{"tooltip":"Traffic signs from Mapillary","title":"Traffic Sign Overlay (Mapillary)"},"mapillary":{"view_on_mapillary":"View this image on Mapillary"},"help":{"title":"Help","help":"# Help\n\nThis is an editor for [OpenStreetMap](http://www.openstreetmap.org/), the\nfree and editable map of the world. You can use it to add and update\ndata in your area, making an open-source and open-data map of the world\nbetter for everyone.\n\nEdits that you make on this map will be visible to everyone who uses\nOpenStreetMap. In order to make an edit, you'll need to\n[log in](https://www.openstreetmap.org/login).\n\nThe [iD editor](http://ideditor.com/) is a collaborative project with [source\ncode available on GitHub](https://github.com/openstreetmap/iD).\n","editing_saving":"# Editing & Saving\n\nThis editor is designed to work primarily online, and you're accessing\nit through a website right now.\n\n### Selecting Features\n\nTo select a map feature, like a road or point of interest, click\non it on the map. This will highlight the selected feature, open a panel with\ndetails about it, and show a menu of things you can do with the feature.\n\nTo select multiple features, hold down the 'Shift' key. Then either click\non the features you want to select, or drag on the map to draw a rectangle.\nThis will draw a box and select all the points within it.\n\n### Saving Edits\n\nWhen you make changes like editing roads, buildings, and places, these are\nstored locally until you save them to the server. Don't worry if you make\na mistake - you can undo changes by clicking the undo button, and redo\nchanges by clicking the redo button.\n\nClick 'Save' to finish a group of edits - for instance, if you've completed\nan area of town and would like to start on a new area. You'll have a chance\nto review what you've done, and the editor supplies helpful suggestions\nand warnings if something doesn't seem right about the changes.\n\nIf everything looks good, you can enter a short comment explaining the change\nyou made, and click 'Save' again to post the changes\nto [OpenStreetMap.org](http://www.openstreetmap.org/), where they are visible\nto all other users and available for others to build and improve upon.\n\nIf you can't finish your edits in one sitting, you can leave the editor\nwindow and come back (on the same browser and computer), and the\neditor application will offer to restore your work.\n\n### Using the editor\n\nA list of available keyboard shortcuts can be found [here](http://wiki.openstreetmap.org/wiki/ID/Shortcuts).\n","roads":"# Roads\n\nYou can create, fix, and delete roads with this editor. Roads can be all\nkinds: paths, highways, trails, cycleways, and more - any often-crossed\nsegment should be mappable.\n\n### Selecting\n\nClick on a road to select it. An outline should become visible, along\nwith a small tools menu on the map and a sidebar showing more information\nabout the road.\n\n### Modifying\n\nOften you'll see roads that aren't aligned to the imagery behind them\nor to a GPS track. You can adjust these roads so they are in the correct\nplace.\n\nFirst click on the road you want to change. This will highlight it and show\ncontrol points along it that you can drag to better locations. If\nyou want to add new control points for more detail, double-click a part\nof the road without a node, and one will be added.\n\nIf the road connects to another road, but doesn't properly connect on\nthe map, you can drag one of its control points onto the other road in\norder to join them. Having roads connect is important for the map\nand essential for providing driving directions.\n\nYou can also click the 'Move' tool or press the `M` shortcut key to move the entire road at\none time, and then click again to save that movement.\n\n### Deleting\n\nIf a road is entirely incorrect - you can see that it doesn't exist in satellite\nimagery and ideally have confirmed locally that it's not present - you can delete\nit, which removes it from the map. Be cautious when deleting features -\nlike any other edit, the results are seen by everyone and satellite imagery\nis often out of date, so the road could simply be newly built.\n\nYou can delete a road by clicking on it to select it, then clicking the\ntrash can icon or pressing the 'Delete' key.\n\n### Creating\n\nFound somewhere there should be a road but there isn't? Click the 'Line'\nicon in the top-left of the editor or press the shortcut key `2` to start drawing\na line.\n\nClick on the start of the road on the map to start drawing. If the road\nbranches off from an existing road, start by clicking on the place where they connect.\n\nThen click on points along the road so that it follows the right path, according\nto satellite imagery or GPS. If the road you are drawing crosses another road, connect\nit by clicking on the intersection point. When you're done drawing, double-click\nor press 'Return' or 'Enter' on your keyboard.\n","gps":"# GPS\n\nCollected GPS traces are one valuable source of data for OpenStreetMap. This editor\nsupports local traces - `.gpx` files on your local computer. You can collect\nthis kind of GPS trace with a number of smartphone applications as well as\npersonal GPS hardware.\n\nFor information on how to perform a GPS survey, read\n[Mapping with a smartphone, GPS, or paper](http://learnosm.org/en/mobile-mapping/).\n\nTo use a GPX track for mapping, drag and drop the GPX file onto the map\neditor. If it's recognized, it will be added to the map as a bright purple\nline. Click on the 'Map Data' menu on the right side to enable,\ndisable, or zoom to this new GPX-powered layer.\n\nThe GPX track isn't directly uploaded to OpenStreetMap - the best way to\nuse it is to draw on the map, using it as a guide for the new features that\nyou add, and also to [upload it to OpenStreetMap](http://www.openstreetmap.org/trace/create)\nfor other users to use.\n","imagery":"# Imagery\n\nAerial imagery is an important resource for mapping. A combination of\nairplane flyovers, satellite views, and freely-compiled sources are available\nin the editor under the 'Background Settings' menu on the right.\n\nBy default a [Bing Maps](http://www.bing.com/maps/) satellite layer is\npresented in the editor, but as you pan and zoom the map to new geographical\nareas, new sources will become available. Some countries, like the United\nStates, France, and Denmark have very high-quality imagery available for some areas.\n\nImagery is sometimes offset from the map data because of a mistake on the\nimagery provider's side. If you see a lot of roads shifted from the background,\ndon't immediately move them all to match the background. Instead you can adjust\nthe imagery so that it matches the existing data by clicking 'Fix alignment' at\nthe bottom of the Background Settings UI.\n","addresses":"# Addresses\n\nAddresses are some of the most useful information for the map.\n\nAlthough addresses are often represented as parts of streets, in OpenStreetMap\nthey're recorded as attributes of buildings and places along streets.\n\nYou can add address information to places mapped as building outlines\nas well as those mapped as single points. The optimal source of address\ndata is from an on-the-ground survey or personal knowledge - as with any\nother feature, copying from commercial sources like Google Maps is strictly\nforbidden.\n","inspector":"# Using the Inspector\n\nThe inspector is the section on the left side of the page that allows you to\nedit the details of the selected feature.\n\n### Selecting a Feature Type\n\nAfter you add a point, line, or area, you can choose what type of feature it\nis, like whether it's a highway or residential road, supermarket or cafe.\nThe inspector will display buttons for common feature types, and you can\nfind others by typing what you're looking for in the search box.\n\nClick the 'i' in the bottom-right-hand corner of a feature type button to\nlearn more about it. Click a button to choose that type.\n\n### Using Forms and Editing Tags\n\nAfter you choose a feature type, or when you select a feature that already\nhas a type assigned, the inspector will display fields with details about\nthe feature like its name and address.\n\nBelow the fields you see, you can click the 'Add field' dropdown to add\nother details, like a Wikipedia link, wheelchair access, and more.\n\nAt the bottom of the inspector, click 'Additional tags' to add arbitrary\nother tags to the element. [Taginfo](http://taginfo.openstreetmap.org/) is a\ngreat resource for learn more about popular tag combinations.\n\nChanges you make in the inspector are automatically applied to the map.\nYou can undo them at any time by clicking the 'Undo' button.\n","buildings":"# Buildings\n\nOpenStreetMap is the world's largest database of buildings. You can create\nand improve this database.\n\n### Selecting\n\nYou can select a building by clicking on its border. This will highlight the\nbuilding and open a small tools menu and a sidebar showing more information\nabout the building.\n\n### Modifying\n\nSometimes buildings are incorrectly placed or have incorrect tags.\n\nTo move an entire building, select it, then click the 'Move' tool. Move your\nmouse to shift the building, and click when it's correctly placed.\n\nTo fix the specific shape of a building, click and drag the nodes that form\nits border into better places.\n\n### Creating\n\nOne of the main questions around adding buildings to the map is that\nOpenStreetMap records buildings both as shapes and points. The rule of thumb\nis to _map a building as a shape whenever possible_, and map companies, homes,\namenities, and other things that operate out of buildings as points placed\nwithin the building shape.\n\nStart drawing a building as a shape by clicking the 'Area' button in the top\nleft of the interface, and end it either by pressing 'Return' on your keyboard\nor clicking on the first node drawn to close the shape.\n\n### Deleting\n\nIf a building is entirely incorrect - you can see that it doesn't exist in satellite\nimagery and ideally have confirmed locally that it's not present - you can delete\nit, which removes it from the map. Be cautious when deleting features -\nlike any other edit, the results are seen by everyone and satellite imagery\nis often out of date, so the building could simply be newly built.\n\nYou can delete a building by clicking on it to select it, then clicking the\ntrash can icon or pressing the 'Delete' key.\n","relations":"# Relations\n\nA relation is a special type of feature in OpenStreetMap that groups together\nother features. For example, two common types of relations are *route relations*,\nwhich group together sections of road that belong to a specific freeway or\nhighway, and *multipolygons*, which group together several lines that define\na complex area (one with several pieces or holes in it like a donut).\n\nThe group of features in a relation are called *members*. In the sidebar, you can\nsee which relations a feature is a member of, and click on a relation there\nto select the it. When the relation is selected, you can see all of its\nmembers listed in the sidebar and highlighted on the map.\n\nFor the most part, iD will take care of maintaining relations automatically\nwhile you edit. The main thing you should be aware of is that if you delete a\nsection of road to redraw it more accurately, you should make sure that the\nnew section is a member of the same relations as the original.\n\n## Editing Relations\n\nIf you want to edit relations, here are the basics.\n\nTo add a feature to a relation, select the feature, click the \"+\" button in the\n\"All relations\" section of the sidebar, and select or type the name of the relation.\n\nTo create a new relation, select the first feature that should be a member,\nclick the \"+\" button in the \"All relations\" section, and select \"New relation...\".\n\nTo remove a feature from a relation, select the feature and click the trash\nbutton next to the relation you want to remove it from.\n\nYou can create multipolygons with holes using the \"Merge\" tool. Draw two areas (inner\nand outer), hold the Shift key and click on each of them to select them both, and then\nclick the \"Merge\" (+) button.\n"},"intro":{"graph":{"city_hall":"Three Rivers City Hall","fire_department":"Three Rivers Fire Department","memory_isle_park":"Memory Isle Park","riverwalk_trail":"Riverwalk Trail","w_michigan_ave":"West Michigan Avenue","e_michigan_ave":"East Michigan Avenue","spring_st":"Spring Street","scidmore_park":"Scidmore Park","petting_zoo":"Scidmore Park Petting Zoo","n_andrews_st":"North Andrews Street","s_andrews_st":"South Andrews Street","n_constantine_st":"North Constantine Street","s_constantine_st":"South Constantine Street","rocky_river":"Rocky River","railroad_dr":"Railroad Drive","conrail_rr":"Conrail Railroad","st_joseph_river":"Saint Joseph River","n_main_st":"North Main Street","s_main_st":"South Main Street","water_st":"Water Street","foster_st":"Foster Street","portage_river":"Portage River","flower_st":"Flower Street","elm_st":"Elm Street","walnut_st":"Walnut Street","morris_ave":"Morris Avenue","east_st":"East Street","portage_ave":"Portage Avenue"},"navigation":{"title":"Navigation","drag":"The main map area shows OpenStreetMap data on top of a background. You can navigate by dragging and scrolling, just like any web map. **Drag the map!**","select":"Map features are represented three ways: using points, lines or areas. All features can be selected by clicking on them. **Click on the point to select it.**","pane":"When a feature is selected, the feature editor is displayed. The header shows us the feature type and the main pane shows the feature's attributes, such as its name and address. **Close the feature editor by pressing the {button} button in the top right.**","search":"You can also search for features in the current view, or worldwide. **Search for '{name}'**","choose":"**Choose {name} from the list to select it.**","chosen":"Great! {name} is now selected. **Close the feature editor by pressing the {button} button.**"},"points":{"title":"Points","add":"Points can be used to represent features such as shops, restaurants, and monuments. They mark a specific location, and describe what's there. **Click the {button} Point button to add a new point.**","place":"The point can be placed by clicking on the map. **Click the map to place the new point on top of the building.**","search":"There are many different features that can be represented by points. The point you just added is a Cafe. **Search for '{name}'**","choose":"**Choose Cafe from the list.**","describe":"The point is now marked as a cafe. Using the feature editor, we can add more information about the feature. **Add a name**","close":"The feature editor will remember all of your changes automatically.  When you change a feature, the close button will change to a checkmark. **Click the {button} button to close the feature editor**","reselect":"Often points will already exist, but have mistakes or be incomplete. We can edit existing points. **Click to select the point you just created.**","fixname":"**Change the name, then click the {button} button to close the feature editor.**","reselect_delete":"All features on the map can be deleted. **Click to select the point you created.**","delete":"The menu around the point contains operations that can be performed on it, including delete. **Click on the {button} button to delete the point.**"},"areas":{"title":"Areas","add":"Areas are used to show the boundaries of features like lakes, buildings, and residential areas. They can be also be used for more detailed mapping of many features you might normally map as points. **Click the {button} Area button to add a new area.**","corner":"Areas are drawn by placing nodes that mark the boundary of the area. **Click to place a starting node on one of the corners of the playground.**","place":"Draw the area by placing more nodes. Finish the area by clicking on the starting node. **Draw an area for the playground.**","search":"**Search for '{name}'.**","choose":"**Choose Playground from the list.**","describe":"**Add a name, then click the {button} button to close the feature editor**"},"lines":{"title":"Lines","add":"Lines are used to represent features such as roads, railroads, and rivers. **Click the {button} Line button to add a new line.**","start":"**Start the line by clicking on the end of the road.**","intersect":"Click to add more nodes to the line. You can drag the map while drawing if necessary. Roads, and many other types of lines, are part of a larger network. It is important for these lines to be connected properly in order for routing applications to work. **Click on {name} to create an intersection connecting the two lines.**","finish":"Lines can be finished by clicking on the last node again. **Finish drawing the road.**","road":"**Select Road from the list**","residential":"There are different types of roads, the most common of which is Residential. **Choose the Residential road type**","describe":"**Name the road, then click the {button} button to close the feature editor.**","restart":"The road needs to intersect {name}.","wrong_preset":"You didn't select the Residential road type. **Click here to choose again**"},"startediting":{"title":"Start Editing","help":"You can replay this walkthrough or view more documentation by clicking the {button} Help button.","save":"Don't forget to regularly save your changes!","start":"Start mapping!"}},"presets":{"categories":{"category-building":{"name":"Building Features"},"category-golf":{"name":"Golf Features"},"category-landuse":{"name":"Land Use Features"},"category-path":{"name":"Path Features"},"category-rail":{"name":"Rail Features"},"category-restriction":{"name":"Restriction Features"},"category-road":{"name":"Road Features"},"category-route":{"name":"Route Features"},"category-water-area":{"name":"Water Features"},"category-water-line":{"name":"Water Features"}},"fields":{"access":{"label":"Allowed Access","placeholder":"Not Specified","types":{"access":"All","foot":"Foot","motor_vehicle":"Motor Vehicles","bicycle":"Bicycles","horse":"Horses"},"options":{"yes":{"title":"Allowed","description":"Access permitted by law; a right of way"},"no":{"title":"Prohibited","description":"Access not permitted to the general public"},"permissive":{"title":"Permissive","description":"Access permitted until such time as the owner revokes the permission"},"private":{"title":"Private","description":"Access permitted only with permission of the owner on an individual basis"},"designated":{"title":"Designated","description":"Access permitted according to signs or specific local laws"},"destination":{"title":"Destination","description":"Access permitted only to reach a destination"},"dismount":{"title":"Dismount","description":"Access permitted but rider must dismount"}}},"access_simple":{"label":"Allowed Access","placeholder":"yes"},"access_toilets":{"label":"Access"},"address":{"label":"Address","placeholders":{"housename":"Housename","housenumber":"123","conscriptionnumber":"123","street":"Street","city":"City","postcode":"Postcode","place":"Place","hamlet":"Hamlet","suburb":"Suburb","subdistrict":"Subdistrict","district":"District","province":"Province","state":"State","country":"Country"}},"admin_level":{"label":"Admin Level"},"aerialway":{"label":"Type"},"aerialway/access":{"label":"Access","options":{"entry":"Entry","exit":"Exit","both":"Both"}},"aerialway/bubble":{"label":"Bubble"},"aerialway/capacity":{"label":"Capacity (per hour)","placeholder":"500, 2500, 5000..."},"aerialway/duration":{"label":"Duration (minutes)","placeholder":"1, 2, 3..."},"aerialway/heating":{"label":"Heated"},"aerialway/occupancy":{"label":"Occupancy","placeholder":"2, 4, 8..."},"aerialway/summer/access":{"label":"Access (summer)","options":{"entry":"Entry","exit":"Exit","both":"Both"}},"aeroway":{"label":"Type"},"amenity":{"label":"Type"},"area/highway":{"label":"Type"},"artist":{"label":"Artist"},"artwork_type":{"label":"Type"},"atm":{"label":"ATM"},"backrest":{"label":"Backrest"},"barrier":{"label":"Type"},"bench":{"label":"Bench"},"bicycle_parking":{"label":"Type"},"boundary":{"label":"Type"},"brand":{"label":"Brand"},"building":{"label":"Building"},"building_area":{"label":"Building"},"capacity":{"label":"Capacity","placeholder":"50, 100, 200..."},"cardinal_direction":{"label":"Direction","options":{"N":"North","E":"East","S":"South","W":"West","NE":"Northeast","SE":"Southeast","SW":"Southwest","NW":"Northwest","NNE":"North-northeast","ENE":"East-northeast","ESE":"East-southeast","SSE":"South-southeast","SSW":"South-southwest","WSW":"West-southwest","WNW":"West-northwest","NNW":"North-northwest"}},"clock_direction":{"label":"Direction","options":{"clockwise":"Clockwise","anticlockwise":"Counterclockwise"}},"collection_times":{"label":"Collection Times"},"construction":{"label":"Type"},"content":{"label":"Contents"},"country":{"label":"Country"},"covered":{"label":"Covered"},"craft":{"label":"Type"},"crop":{"label":"Crop"},"crossing":{"label":"Type"},"cuisine":{"label":"Cuisine"},"cycleway":{"label":"Bike Lanes","placeholder":"none","types":{"cycleway:left":"Left side","cycleway:right":"Right side"},"options":{"none":{"title":"None","description":"No bike lane"},"lane":{"title":"Standard bike lane","description":"A bike lane separated from auto traffic by a painted line"},"shared_lane":{"title":"Shared bike lane","description":"A bike lane with no separation from auto traffic"},"track":{"title":"Bike track","description":"A bike lane separated from traffic by a physical barrier"},"share_busway":{"title":"Bike lane shared with bus","description":"A bike lane shared with a bus lane"},"opposite_lane":{"title":"Opposite bike lane","description":"A bike lane that travels in the opposite direction of traffic"},"opposite":{"title":"Contraflow bike lane","description":"A bike lane that travels in both directions on a one-way street"}}},"delivery":{"label":"Delivery"},"denomination":{"label":"Denomination"},"denotation":{"label":"Denotation"},"description":{"label":"Description"},"diaper":{"label":"Diaper Changing Available"},"dock":{"label":"Type"},"drive_through":{"label":"Drive-Through"},"electrified":{"label":"Electrification","placeholder":"Contact Line, Electrified Rail...","options":{"contact_line":"Contact Line","rail":"Electrified Rail","yes":"Yes (unspecified)","no":"No"}},"elevation":{"label":"Elevation"},"emergency":{"label":"Emergency"},"entrance":{"label":"Type"},"except":{"label":"Exceptions"},"fax":{"label":"Fax","placeholder":"+31 42 123 4567"},"fee":{"label":"Fee"},"fire_hydrant/type":{"label":"Type","options":{"pillar":"Pillar/Aboveground","underground":"Underground","wall":"Wall","pond":"Pond"}},"fixme":{"label":"Fix Me"},"fuel":{"label":"Fuel"},"fuel/biodiesel":{"label":"Sells Biodiesel"},"fuel/diesel":{"label":"Sells Diesel"},"fuel/e10":{"label":"Sells E10"},"fuel/e85":{"label":"Sells E85"},"fuel/lpg":{"label":"Sells Propane"},"fuel/octane_100":{"label":"Sells Racing Gasoline"},"fuel/octane_91":{"label":"Sells Regular Gasoline"},"fuel/octane_95":{"label":"Sells Midgrade Gasoline"},"fuel/octane_98":{"label":"Sells Premium Gasoline"},"gauge":{"label":"Gauge"},"gender":{"label":"Gender","placeholder":"Unknown","options":{"male":"Male","female":"Female","unisex":"Unisex"}},"generator/method":{"label":"Method"},"generator/source":{"label":"Source"},"generator/type":{"label":"Type"},"golf_hole":{"label":"Reference","placeholder":"Hole number (1-18)"},"handicap":{"label":"Handicap","placeholder":"1-18"},"handrail":{"label":"Handrail"},"highway":{"label":"Type"},"historic":{"label":"Type"},"hoops":{"label":"Hoops","placeholder":"1, 2, 4..."},"iata":{"label":"IATA"},"icao":{"label":"ICAO"},"incline":{"label":"Incline"},"incline_steps":{"label":"Incline","options":{"up":"Up","down":"Down"}},"information":{"label":"Type"},"internet_access":{"label":"Internet Access","options":{"yes":"Yes","no":"No","wlan":"Wifi","wired":"Wired","terminal":"Terminal"}},"lamp_type":{"label":"Type"},"landuse":{"label":"Type"},"lanes":{"label":"Lanes","placeholder":"1, 2, 3..."},"layer":{"label":"Layer"},"leaf_cycle":{"label":"Leaf Cycle","options":{"evergreen":"Evergreen","deciduous":"Deciduous","semi_evergreen":"Semi-Evergreen","semi_deciduous":"Semi-Deciduous","mixed":"Mixed"}},"leaf_cycle_singular":{"label":"Leaf Cycle","options":{"evergreen":"Evergreen","deciduous":"Deciduous","semi_evergreen":"Semi-Evergreen","semi_deciduous":"Semi-Deciduous"}},"leaf_type":{"label":"Leaf Type","options":{"broadleaved":"Broadleaved","needleleaved":"Needleleaved","mixed":"Mixed","leafless":"Leafless"}},"leaf_type_singular":{"label":"Leaf Type","options":{"broadleaved":"Broadleaved","needleleaved":"Needleleaved","leafless":"Leafless"}},"leisure":{"label":"Type"},"length":{"label":"Length (Meters)"},"level":{"label":"Level"},"levels":{"label":"Levels","placeholder":"2, 4, 6..."},"lit":{"label":"Lit"},"location":{"label":"Location"},"man_made":{"label":"Type"},"maxspeed":{"label":"Speed Limit","placeholder":"40, 50, 60..."},"maxstay":{"label":"Max Stay"},"mtb/scale":{"label":"Mountain Biking Difficulty","placeholder":"0, 1, 2, 3...","options":{"0":"0: Solid gravel/packed earth, no obstacles, wide curves","1":"1: Some loose surface, small obstacles, wide curves","2":"2: Much loose surface, large obstacles, easy hairpins","3":"3: Slippery surface, large obstacles, tight hairpins","4":"4: Loose surface or boulders, dangerous hairpins","5":"5: Maximum difficulty, boulder fields, landslides","6":"6: Not rideable except by the very best mountain bikers"}},"mtb/scale/imba":{"label":"IMBA Trail Difficulty","placeholder":"Easy, Medium, Difficult...","options":{"0":"Easiest (white circle)","1":"Easy (green circle)","2":"Medium (blue square)","3":"Difficult (black diamond)","4":"Extremely Difficult (double black diamond)"}},"mtb/scale/uphill":{"label":"Mountain Biking Uphill Difficulty","placeholder":"0, 1, 2, 3...","options":{"0":"0: Avg. incline <10%, gravel/packed earth, no obstacles","1":"1: Avg. incline <15%, gravel/packed earth, few small objects","2":"2: Avg. incline <20%, stable surface, fistsize rocks/roots","3":"3: Avg. incline <25%, variable surface, fistsize rocks/branches","4":"4: Avg. incline <30%, poor condition, big rocks/branches","5":"5: Very steep, bike generally needs to be pushed or carried"}},"name":{"label":"Name","placeholder":"Common name (if any)"},"natural":{"label":"Natural"},"network":{"label":"Network"},"note":{"label":"Note"},"office":{"label":"Type"},"oneway":{"label":"One Way","options":{"undefined":"Assumed to be No","yes":"Yes","no":"No"}},"oneway_yes":{"label":"One Way","options":{"undefined":"Assumed to be Yes","yes":"Yes","no":"No"}},"opening_hours":{"label":"Hours"},"operator":{"label":"Operator"},"par":{"label":"Par","placeholder":"3, 4, 5..."},"park_ride":{"label":"Park and Ride"},"parking":{"label":"Type","options":{"surface":"Surface","multi-storey":"Multilevel","underground":"Underground","sheds":"Sheds","carports":"Carports","garage_boxes":"Garage Boxes","lane":"Roadside Lane"}},"phone":{"label":"Phone","placeholder":"+31 42 123 4567"},"piste/difficulty":{"label":"Difficulty","placeholder":"Easy, Intermediate, Advanced...","options":{"novice":"Novice (instructional)","easy":"Easy (green circle)","intermediate":"Intermediate (blue square)","advanced":"Advanced (black diamond)","expert":"Expert (double black diamond)","freeride":"Freeride (off-piste)","extreme":"Extreme (climbing equipment required)"}},"piste/grooming":{"label":"Grooming","options":{"classic":"Classic","mogul":"Mogul","backcountry":"Backcountry","classic+skating":"Classic and Skating","scooter":"Scooter/Snowmobile","skating":"Skating"}},"piste/type":{"label":"Type","options":{"downhill":"Downhill","nordic":"Nordic","skitour":"Skitour","sled":"Sled","hike":"Hike","sleigh":"Sleigh","ice_skate":"Ice Skate","snow_park":"Snow Park","playground":"Playground"}},"place":{"label":"Type"},"population":{"label":"Population"},"power":{"label":"Type"},"power_supply":{"label":"Power Supply"},"railway":{"label":"Type"},"recycling/cans":{"label":"Accepts Cans"},"recycling/clothes":{"label":"Accepts Clothes"},"recycling/glass":{"label":"Accepts Glass"},"recycling/glass_bottles":{"label":"Accepts Glass Bottles"},"recycling/paper":{"label":"Accepts Paper"},"recycling/plastic":{"label":"Accepts Plastic"},"recycling/type":{"label":"Recycling Type","options":{"container":"Container","centre":"Recycling Center"}},"ref":{"label":"Reference"},"relation":{"label":"Type"},"religion":{"label":"Religion"},"restriction":{"label":"Type"},"restrictions":{"label":"Turn Restrictions"},"route":{"label":"Type"},"route_master":{"label":"Type"},"sac_scale":{"label":"Hiking Difficulty","placeholder":"Mountain Hiking, Alpine Hiking...","options":{"hiking":"T1: Hiking","mountain_hiking":"T2: Mountain Hiking","demanding_mountain_hiking":"T3: Demanding Mountain Hiking","alpine_hiking":"T4: Alpine Hiking","demanding_alpine_hiking":"T5: Demanding Alpine Hiking","difficult_alpine_hiking":"T6: Difficult Alpine Hiking"}},"sanitary_dump_station":{"label":"Toilet Disposal"},"seasonal":{"label":"Seasonal"},"service":{"label":"Type"},"service/bicycle/chain_tool":{"label":"Chain Tool","options":{"undefined":"Assumed to be No","yes":"Yes","no":"No"}},"service/bicycle/pump":{"label":"Air Pump","options":{"undefined":"Assumed to be No","yes":"Yes","no":"No"}},"service_rail":{"label":"Service Type","options":{"spur":"Spur","yard":"Yard","siding":"Siding","crossover":"Crossover"}},"shelter":{"label":"Shelter"},"shelter_type":{"label":"Type"},"shop":{"label":"Type"},"site":{"label":"Type"},"sloped_curb":{"label":"Sloped Curb"},"smoking":{"label":"Smoking","placeholder":"No, Separated, Yes...","options":{"no":"No smoking anywhere","separated":"In smoking areas, not physically isolated","isolated":"In smoking areas, physically isolated","outside":"Allowed outside","yes":"Allowed everywhere","dedicated":"Dedicated to smokers (e.g. smokers' club)"}},"smoothness":{"label":"Smoothness","placeholder":"Thin Rollers, Wheels, Off-Road...","options":{"excellent":"Thin Rollers: rollerblade, skateboard","good":"Thin Wheels: racing bike","intermediate":"Wheels: city bike, wheelchair, scooter","bad":"Robust Wheels: trekking bike, car, rickshaw","very_bad":"High Clearance: light duty off-road vehicle","horrible":"Off-Road: heavy duty off-road vehicle","very_horrible":"Specialized off-road: tractor, ATV","impassable":"Impassable / No wheeled vehicle"}},"social_facility_for":{"label":"People served","placeholder":"Homeless, Disabled, Child, etc"},"source":{"label":"Source"},"sport":{"label":"Sport"},"sport_ice":{"label":"Sport"},"sport_racing":{"label":"Sport"},"structure":{"label":"Structure","placeholder":"Unknown","options":{"bridge":"Bridge","tunnel":"Tunnel","embankment":"Embankment","cutting":"Cutting","ford":"Ford"}},"studio_type":{"label":"Type"},"substation":{"label":"Type"},"supervised":{"label":"Supervised"},"surface":{"label":"Surface"},"tactile_paving":{"label":"Tactile Paving"},"takeaway":{"label":"Takeaway","placeholder":"Yes, No, Takeaway Only...","options":{"yes":"Yes","no":"No","only":"Takeaway Only"}},"toilets/disposal":{"label":"Disposal","options":{"flush":"Flush","pitlatrine":"Pit/Latrine","chemical":"Chemical","bucket":"Bucket"}},"tourism":{"label":"Type"},"towertype":{"label":"Tower type"},"tracktype":{"label":"Track Type","placeholder":"Solid, Mostly Solid, Soft...","options":{"grade1":"Solid: paved or heavily compacted hardcore surface","grade2":"Mostly Solid: gravel/rock with some soft material mixed in","grade3":"Even mixture of hard and soft materials","grade4":"Mostly Soft: soil/sand/grass with some hard material mixed in","grade5":"Soft: soil/sand/grass"}},"traffic_signals":{"label":"Type"},"trail_visibility":{"label":"Trail Visibility","placeholder":"Excellent, Good, Bad...","options":{"excellent":"Excellent: unambiguous path or markers everywhere","good":"Good: markers visible, sometimes require searching","intermediate":"Intermediate: few markers, path mostly visible","bad":"Bad: no markers, path sometimes invisible/pathless","horrible":"Horrible: often pathless, some orientation skills required","no":"No: pathless, excellent orientation skills required"}},"trees":{"label":"Trees"},"tunnel":{"label":"Tunnel"},"vending":{"label":"Type of Goods"},"water":{"label":"Type"},"water_point":{"label":"Water Point"},"waterway":{"label":"Type"},"website":{"label":"Website","placeholder":"http://example.com/"},"wetland":{"label":"Type"},"wheelchair":{"label":"Wheelchair Access"},"width":{"label":"Width (Meters)"},"wikipedia":{"label":"Wikipedia"}},"presets":{"address":{"name":"Address","terms":""},"aerialway":{"name":"Aerialway","terms":"ski lift,funifor,funitel"},"aerialway/cable_car":{"name":"Cable Car","terms":"tramway,ropeway"},"aerialway/chair_lift":{"name":"Chair Lift","terms":""},"aerialway/gondola":{"name":"Gondola","terms":""},"aerialway/magic_carpet":{"name":"Magic Carpet Lift","terms":""},"aerialway/platter":{"name":"Platter Lift","terms":"button lift,poma lift"},"aerialway/pylon":{"name":"Aerialway Pylon","terms":""},"aerialway/rope_tow":{"name":"Rope Tow Lift","terms":"handle tow,bugel lift"},"aerialway/station":{"name":"Aerialway Station","terms":""},"aerialway/t-bar":{"name":"T-bar Lift","terms":""},"aeroway":{"name":"Aeroway","terms":""},"aeroway/aerodrome":{"name":"Airport","terms":"airplane,airport,aerodrome"},"aeroway/apron":{"name":"Apron","terms":"ramp"},"aeroway/gate":{"name":"Airport gate","terms":""},"aeroway/hangar":{"name":"Hangar","terms":""},"aeroway/helipad":{"name":"Helipad","terms":"helicopter,helipad,heliport"},"aeroway/runway":{"name":"Runway","terms":"landing strip"},"aeroway/taxiway":{"name":"Taxiway","terms":""},"aeroway/terminal":{"name":"Airport terminal","terms":"airport,aerodrome"},"amenity":{"name":"Amenity","terms":""},"amenity/arts_centre":{"name":"Arts Center","terms":""},"amenity/atm":{"name":"ATM","terms":"money,cash,machine"},"amenity/bank":{"name":"Bank","terms":"credit union,check,deposit,fund,investment,repository,reserve,safe,savings,stock,treasury,trust,vault"},"amenity/bar":{"name":"Bar","terms":"dive,beer,bier,booze"},"amenity/bbq":{"name":"Barbecue/Grill","terms":"bbq"},"amenity/bench":{"name":"Bench","terms":"seat"},"amenity/bicycle_parking":{"name":"Bicycle Parking","terms":"bike"},"amenity/bicycle_rental":{"name":"Bicycle Rental","terms":"bike"},"amenity/bicycle_repair_station":{"name":"Bicycle Repair Tool Stand","terms":"bike,repair,chain,pump"},"amenity/biergarten":{"name":"Beer Garden","terms":"beer,bier,booze"},"amenity/boat_rental":{"name":"Boat Rental","terms":""},"amenity/bureau_de_change":{"name":"Currency Exchange","terms":"bureau de change,money changer"},"amenity/bus_station":{"name":"Bus Station","terms":""},"amenity/cafe":{"name":"Cafe","terms":"bistro,coffee,tea"},"amenity/car_rental":{"name":"Car Rental","terms":""},"amenity/car_sharing":{"name":"Car Sharing","terms":""},"amenity/car_wash":{"name":"Car Wash","terms":""},"amenity/casino":{"name":"Casino","terms":"gambling,roulette,craps,poker,blackjack"},"amenity/charging_station":{"name":"Charging Station","terms":"EV,Electric Vehicle,Supercharger"},"amenity/childcare":{"name":"Nursery/Childcare","terms":"daycare,orphanage,playgroup"},"amenity/cinema":{"name":"Cinema","terms":"drive-in,film,flick,movie,theater,picture,show,screen"},"amenity/clinic":{"name":"Clinic","terms":"medical,urgentcare"},"amenity/clock":{"name":"Clock","terms":""},"amenity/college":{"name":"College Grounds","terms":"university"},"amenity/community_centre":{"name":"Community Center","terms":"event,hall"},"amenity/compressed_air":{"name":"Compressed Air","terms":""},"amenity/courthouse":{"name":"Courthouse","terms":""},"amenity/dentist":{"name":"Dentist","terms":"tooth,teeth"},"amenity/doctors":{"name":"Doctor","terms":"medic*"},"amenity/dojo":{"name":"Dojo / Martial Arts Academy","terms":"martial arts,dojang"},"amenity/drinking_water":{"name":"Drinking Water","terms":"fountain,potable"},"amenity/embassy":{"name":"Embassy","terms":""},"amenity/fast_food":{"name":"Fast Food","terms":"restaurant"},"amenity/ferry_terminal":{"name":"Ferry Terminal","terms":""},"amenity/fire_station":{"name":"Fire Station","terms":""},"amenity/fountain":{"name":"Fountain","terms":""},"amenity/fuel":{"name":"Gas Station","terms":"petrol,fuel,gasoline,propane,diesel,lng,cng,biodiesel"},"amenity/grave_yard":{"name":"Graveyard","terms":""},"amenity/grit_bin":{"name":"Grit Bin","terms":"salt,sand"},"amenity/hospital":{"name":"Hospital Grounds","terms":"clinic,doctor,emergency room,health service,hospice,infirmary,institution,nursing home,sanatorium,sanitarium,sick,surgery,ward"},"amenity/hunting_stand":{"name":"Hunting Stand","terms":""},"amenity/kindergarten":{"name":"Preschool/Kindergarten Grounds","terms":"kindergarden,pre-school"},"amenity/library":{"name":"Library","terms":"book"},"amenity/marketplace":{"name":"Marketplace","terms":""},"amenity/motorcycle_parking":{"name":"Motorcycle Parking","terms":""},"amenity/nightclub":{"name":"Nightclub","terms":"disco*,night club,dancing,dance club"},"amenity/parking":{"name":"Car Parking","terms":""},"amenity/parking_entrance":{"name":"Parking Garage Entrance/Exit","terms":""},"amenity/parking_space":{"name":"Parking Space","terms":""},"amenity/pharmacy":{"name":"Pharmacy","terms":"drug,medicine"},"amenity/place_of_worship":{"name":"Place of Worship","terms":"abbey,basilica,bethel,cathedral,chancel,chantry,chapel,church,fold,house of God,house of prayer,house of worship,minster,mission,mosque,oratory,parish,sacellum,sanctuary,shrine,synagogue,tabernacle,temple"},"amenity/place_of_worship/buddhist":{"name":"Buddhist Temple","terms":"stupa,vihara,monastery,temple,pagoda,zendo,dojo"},"amenity/place_of_worship/christian":{"name":"Church","terms":"christian,abbey,basilica,bethel,cathedral,chancel,chantry,chapel,fold,house of God,house of prayer,house of worship,minster,mission,oratory,parish,sacellum,sanctuary,shrine,tabernacle,temple"},"amenity/place_of_worship/jewish":{"name":"Synagogue","terms":"jewish"},"amenity/place_of_worship/muslim":{"name":"Mosque","terms":"muslim"},"amenity/police":{"name":"Police","terms":"badge,constable,constabulary,cop,detective,fed,law,enforcement,officer,patrol"},"amenity/post_box":{"name":"Mailbox","terms":"letter,post"},"amenity/post_office":{"name":"Post Office","terms":"letter,mail"},"amenity/pub":{"name":"Pub","terms":"dive,beer,bier,booze"},"amenity/public_bookcase":{"name":"Public Bookcase","terms":"library,bookcrossing"},"amenity/ranger_station":{"name":"Ranger Station","terms":"visitor center,visitor centre,permit center,permit centre,backcountry office,warden office,warden center"},"amenity/recycling":{"name":"Recycling","terms":"can,bottle,garbage,scrap,trash"},"amenity/register_office":{"name":"Register Office","terms":""},"amenity/restaurant":{"name":"Restaurant","terms":"bar,breakfast,cafe,café,canteen,coffee,dine,dining,dinner,drive-in,eat,grill,lunch,table"},"amenity/sanitary_dump_station":{"name":"RV Toilet Disposal","terms":"Motor Home,Camper,Sanitary,Dump Station,Elsan,CDP,CTDP,Chemical Toilet"},"amenity/school":{"name":"School Grounds","terms":"academy,elementary school,middle school,high school"},"amenity/shelter":{"name":"Shelter","terms":"lean-to,gazebo,picnic"},"amenity/social_facility":{"name":"Social Facility","terms":""},"amenity/social_facility/food_bank":{"name":"Food Bank","terms":""},"amenity/social_facility/group_home":{"name":"Elderly Group Home","terms":"old,senior,living"},"amenity/social_facility/homeless_shelter":{"name":"Homeless Shelter","terms":"houseless,unhoused,displaced"},"amenity/studio":{"name":"Studio","terms":"recording,radio,television"},"amenity/swimming_pool":{"name":"Swimming Pool","terms":""},"amenity/taxi":{"name":"Taxi Stand","terms":"cab"},"amenity/telephone":{"name":"Telephone","terms":"phone"},"amenity/theatre":{"name":"Theater","terms":"theatre,performance,play,musical"},"amenity/toilets":{"name":"Toilets","terms":"bathroom,restroom,outhouse,privy,head,lavatory,latrine,water closet,WC,W.C."},"amenity/townhall":{"name":"Town Hall","terms":"village,city,government,courthouse,municipal"},"amenity/university":{"name":"University Grounds","terms":"college"},"amenity/vending_machine/cigarettes":{"name":"Cigarette Vending Machine","terms":"cigarette"},"amenity/vending_machine/condoms":{"name":"Condom Vending Machine","terms":"condom"},"amenity/vending_machine/drinks":{"name":"Drink Vending Machine","terms":"drink,soda,beverage,juice,pop"},"amenity/vending_machine/excrement_bags":{"name":"Excrement Bag Vending Machine","terms":"excrement bags,poop,dog,animal"},"amenity/vending_machine/news_papers":{"name":"Newspaper Vending Machine","terms":"newspaper"},"amenity/vending_machine/parcel_pickup_dropoff":{"name":"Parcel Pickup/Dropoff Vending Machine","terms":"parcel,mail,pickup"},"amenity/vending_machine/parking_tickets":{"name":"Parking Ticket Vending Machine","terms":"parking,ticket"},"amenity/vending_machine/public_transport_tickets":{"name":"Transit Ticket Vending Machine","terms":"bus,train,ferry,rail,ticket,transportation"},"amenity/vending_machine/sweets":{"name":"Snack Vending Machine","terms":"candy,gum,chip,pretzel,cookie,cracker"},"amenity/vending_machine/vending_machine":{"name":"Vending Machine","terms":""},"amenity/veterinary":{"name":"Veterinary","terms":"pet clinic,veterinarian,animal hospital,pet doctor"},"amenity/waste_basket":{"name":"Waste Basket","terms":"bin,rubbish,litter,trash,garbage"},"amenity/waste_disposal":{"name":"Garbage Dumpster","terms":"rubbish,litter,trash"},"amenity/water_point":{"name":"RV Drinking Water","terms":""},"area":{"name":"Area","terms":""},"area/highway":{"name":"Road Surface","terms":""},"barrier":{"name":"Barrier","terms":""},"barrier/block":{"name":"Block","terms":""},"barrier/bollard":{"name":"Bollard","terms":""},"barrier/cattle_grid":{"name":"Cattle Grid","terms":""},"barrier/city_wall":{"name":"City Wall","terms":""},"barrier/cycle_barrier":{"name":"Cycle Barrier","terms":""},"barrier/ditch":{"name":"Ditch","terms":""},"barrier/entrance":{"name":"Entrance","terms":""},"barrier/fence":{"name":"Fence","terms":""},"barrier/gate":{"name":"Gate","terms":""},"barrier/hedge":{"name":"Hedge","terms":""},"barrier/kissing_gate":{"name":"Kissing Gate","terms":""},"barrier/lift_gate":{"name":"Lift Gate","terms":""},"barrier/retaining_wall":{"name":"Retaining Wall","terms":""},"barrier/stile":{"name":"Stile","terms":""},"barrier/toll_booth":{"name":"Toll Booth","terms":""},"barrier/wall":{"name":"Wall","terms":""},"boundary/administrative":{"name":"Administrative Boundary","terms":""},"building":{"name":"Building","terms":""},"building/apartments":{"name":"Apartments","terms":""},"building/barn":{"name":"Barn","terms":""},"building/bunker":{"name":"Bunker","terms":""},"building/cabin":{"name":"Cabin","terms":""},"building/cathedral":{"name":"Cathedral Building","terms":""},"building/chapel":{"name":"Chapel Building","terms":""},"building/church":{"name":"Church Building","terms":""},"building/college":{"name":"College Building","terms":"university"},"building/commercial":{"name":"Commercial Building","terms":""},"building/construction":{"name":"Building Under Construction","terms":""},"building/detached":{"name":"Detached House","terms":"home,single,family,residence,dwelling"},"building/dormitory":{"name":"Dormitory","terms":""},"building/entrance":{"name":"Entrance/Exit","terms":""},"building/garage":{"name":"Garage","terms":""},"building/garages":{"name":"Garages","terms":""},"building/greenhouse":{"name":"Greenhouse","terms":""},"building/hospital":{"name":"Hospital Building","terms":""},"building/hotel":{"name":"Hotel Building","terms":""},"building/house":{"name":"House","terms":"home,family,residence,dwelling"},"building/hut":{"name":"Hut","terms":""},"building/industrial":{"name":"Industrial Building","terms":""},"building/kindergarten":{"name":"Preschool/Kindergarten Building","terms":"kindergarden,pre-school"},"building/public":{"name":"Public Building","terms":""},"building/residential":{"name":"Residential Building","terms":""},"building/retail":{"name":"Retail Building","terms":""},"building/roof":{"name":"Roof","terms":""},"building/school":{"name":"School Building","terms":"academy,elementary school,middle school,high school"},"building/semidetached_house":{"name":"Semi-Detached House","terms":"home,double,duplex,twin,family,residence,dwelling"},"building/shed":{"name":"Shed","terms":""},"building/stable":{"name":"Stable","terms":""},"building/static_caravan":{"name":"Static Mobile Home","terms":""},"building/terrace":{"name":"Row Houses","terms":"home,terrace,brownstone,family,residence,dwelling"},"building/train_station":{"name":"Train Station","terms":""},"building/university":{"name":"University Building","terms":"college"},"building/warehouse":{"name":"Warehouse","terms":""},"craft":{"name":"Craft","terms":""},"craft/basket_maker":{"name":"Basket Maker","terms":""},"craft/beekeeper":{"name":"Beekeeper","terms":""},"craft/blacksmith":{"name":"Blacksmith","terms":""},"craft/boatbuilder":{"name":"Boat Builder","terms":""},"craft/bookbinder":{"name":"Bookbinder","terms":"book repair"},"craft/brewery":{"name":"Brewery","terms":"beer,bier"},"craft/carpenter":{"name":"Carpenter","terms":"woodworker"},"craft/carpet_layer":{"name":"Carpet Layer","terms":""},"craft/caterer":{"name":"Caterer","terms":""},"craft/clockmaker":{"name":"Clockmaker","terms":""},"craft/confectionery":{"name":"Confectionery","terms":"sweets,candy"},"craft/dressmaker":{"name":"Dressmaker","terms":"seamstress"},"craft/electrician":{"name":"Electrician","terms":"power,wire"},"craft/gardener":{"name":"Gardener","terms":"landscaper,grounds keeper"},"craft/glaziery":{"name":"Glaziery","terms":"glass,stained-glass,window"},"craft/handicraft":{"name":"Handicraft","terms":""},"craft/hvac":{"name":"HVAC","terms":"heat*,vent*,air conditioning"},"craft/insulator":{"name":"Insulator","terms":""},"craft/jeweler":{"name":"Jeweler","terms":""},"craft/key_cutter":{"name":"Key Cutter","terms":""},"craft/locksmith":{"name":"Locksmith","terms":""},"craft/metal_construction":{"name":"Metal Construction","terms":""},"craft/optician":{"name":"Optician","terms":""},"craft/painter":{"name":"Painter","terms":""},"craft/photographer":{"name":"Photographer","terms":""},"craft/photographic_laboratory":{"name":"Photographic Laboratory","terms":"film"},"craft/plasterer":{"name":"Plasterer","terms":""},"craft/plumber":{"name":"Plumber","terms":"pipe"},"craft/pottery":{"name":"Pottery","terms":"ceramic"},"craft/rigger":{"name":"Rigger","terms":""},"craft/roofer":{"name":"Roofer","terms":""},"craft/saddler":{"name":"Saddler","terms":""},"craft/sailmaker":{"name":"Sailmaker","terms":""},"craft/sawmill":{"name":"Sawmill","terms":"lumber"},"craft/scaffolder":{"name":"Scaffolder","terms":""},"craft/sculpter":{"name":"Sculpter","terms":""},"craft/shoemaker":{"name":"Shoemaker","terms":"cobbler"},"craft/stonemason":{"name":"Stonemason","terms":"masonry"},"craft/sweep":{"name":"Chimney Sweep","terms":""},"craft/tailor":{"name":"Tailor","terms":"clothes,suit"},"craft/tiler":{"name":"Tiler","terms":""},"craft/tinsmith":{"name":"Tinsmith","terms":""},"craft/upholsterer":{"name":"Upholsterer","terms":""},"craft/watchmaker":{"name":"Watchmaker","terms":""},"craft/window_construction":{"name":"Window Construction","terms":"glass"},"craft/winery":{"name":"Winery","terms":""},"embankment":{"name":"Embankment","terms":""},"emergency/ambulance_station":{"name":"Ambulance Station","terms":"EMS,EMT,rescue"},"emergency/fire_hydrant":{"name":"Fire Hydrant","terms":""},"emergency/phone":{"name":"Emergency Phone","terms":""},"entrance":{"name":"Entrance/Exit","terms":""},"footway/crossing":{"name":"Street Crossing","terms":""},"footway/crosswalk":{"name":"Pedestrian Crosswalk","terms":"zebra crossing"},"footway/sidewalk":{"name":"Sidewalk","terms":""},"ford":{"name":"Ford","terms":""},"golf/bunker":{"name":"Sand Trap","terms":"hazard,bunker"},"golf/fairway":{"name":"Fairway","terms":""},"golf/green":{"name":"Putting Green","terms":""},"golf/hole":{"name":"Golf Hole","terms":""},"golf/lateral_water_hazard":{"name":"Lateral Water Hazard","terms":""},"golf/rough":{"name":"Rough","terms":""},"golf/tee":{"name":"Tee Box","terms":"teeing ground"},"golf/water_hazard":{"name":"Water Hazard","terms":""},"highway":{"name":"Highway","terms":""},"highway/bridleway":{"name":"Bridle Path","terms":"bridleway,equestrian,horse"},"highway/bus_stop":{"name":"Bus Stop","terms":""},"highway/corridor":{"name":"Indoor Corridor","terms":"gallery,hall,hallway,indoor,passage,passageway"},"highway/crossing":{"name":"Street Crossing","terms":""},"highway/crosswalk":{"name":"Pedestrian Crosswalk","terms":"zebra crossing"},"highway/cycleway":{"name":"Cycle Path","terms":"bike"},"highway/footway":{"name":"Foot Path","terms":"hike,hiking,trackway,trail,walk"},"highway/living_street":{"name":"Living Street","terms":""},"highway/mini_roundabout":{"name":"Mini-Roundabout","terms":""},"highway/motorway":{"name":"Motorway","terms":""},"highway/motorway_junction":{"name":"Motorway Junction / Exit","terms":""},"highway/motorway_link":{"name":"Motorway Link","terms":"ramp,on ramp,off ramp"},"highway/path":{"name":"Path","terms":"hike,hiking,trackway,trail,walk"},"highway/pedestrian":{"name":"Pedestrian Street","terms":""},"highway/primary":{"name":"Primary Road","terms":""},"highway/primary_link":{"name":"Primary Link","terms":"ramp,on ramp,off ramp"},"highway/raceway":{"name":"Motor Raceway","terms":"auto*,race*,nascar"},"highway/residential":{"name":"Residential Road","terms":""},"highway/rest_area":{"name":"Rest Area","terms":"rest stop"},"highway/road":{"name":"Unknown Road","terms":""},"highway/secondary":{"name":"Secondary Road","terms":""},"highway/secondary_link":{"name":"Secondary Link","terms":"ramp,on ramp,off ramp"},"highway/service":{"name":"Service Road","terms":""},"highway/service/alley":{"name":"Alley","terms":""},"highway/service/drive-through":{"name":"Drive-Through","terms":""},"highway/service/driveway":{"name":"Driveway","terms":""},"highway/service/emergency_access":{"name":"Emergency Access","terms":""},"highway/service/parking_aisle":{"name":"Parking Aisle","terms":""},"highway/services":{"name":"Service Area","terms":"services,travel plaza,service station"},"highway/steps":{"name":"Steps","terms":"stairs,staircase"},"highway/stop":{"name":"Stop Sign","terms":"stop sign"},"highway/street_lamp":{"name":"Street Lamp","terms":"streetlight,street light,lamp,light,gaslight"},"highway/tertiary":{"name":"Tertiary Road","terms":""},"highway/tertiary_link":{"name":"Tertiary Link","terms":"ramp,on ramp,off ramp"},"highway/track":{"name":"Unmaintained Track Road","terms":"woods road,forest road,logging road,fire road,farm road,agricultural road,ranch road,carriage road,primitive,unmaintained,rut,offroad,4wd,4x4,four wheel drive,atv,quad,jeep,double track,two track"},"highway/traffic_signals":{"name":"Traffic Signals","terms":"light,stoplight,traffic light"},"highway/trunk":{"name":"Trunk Road","terms":""},"highway/trunk_link":{"name":"Trunk Link","terms":"ramp,on ramp,off ramp"},"highway/turning_circle":{"name":"Turning Circle","terms":"cul-de-sac"},"highway/unclassified":{"name":"Minor Road","terms":""},"historic":{"name":"Historic Site","terms":""},"historic/archaeological_site":{"name":"Archaeological Site","terms":""},"historic/boundary_stone":{"name":"Boundary Stone","terms":""},"historic/castle":{"name":"Castle","terms":""},"historic/memorial":{"name":"Memorial","terms":""},"historic/monument":{"name":"Monument","terms":""},"historic/ruins":{"name":"Ruins","terms":""},"historic/wayside_cross":{"name":"Wayside Cross","terms":""},"historic/wayside_shrine":{"name":"Wayside Shrine","terms":""},"junction":{"name":"Junction","terms":""},"landuse":{"name":"Land Use","terms":""},"landuse/allotments":{"name":"Community Garden","terms":"allotment,garden"},"landuse/basin":{"name":"Basin","terms":""},"landuse/cemetery":{"name":"Cemetery","terms":""},"landuse/churchyard":{"name":"Churchyard","terms":""},"landuse/commercial":{"name":"Commercial Area","terms":""},"landuse/construction":{"name":"Construction","terms":""},"landuse/farm":{"name":"Farmland","terms":""},"landuse/farmland":{"name":"Farmland","terms":""},"landuse/farmyard":{"name":"Farmyard","terms":""},"landuse/forest":{"name":"Forest","terms":"tree"},"landuse/garages":{"name":"Garages","terms":""},"landuse/grass":{"name":"Grass","terms":""},"landuse/industrial":{"name":"Industrial Area","terms":""},"landuse/landfill":{"name":"Landfill","terms":"dump"},"landuse/meadow":{"name":"Meadow","terms":""},"landuse/military":{"name":"Military Area","terms":""},"landuse/orchard":{"name":"Orchard","terms":""},"landuse/plant_nursery":{"name":"Plant Nursery","terms":"vivero"},"landuse/quarry":{"name":"Quarry","terms":""},"landuse/residential":{"name":"Residential Area","terms":""},"landuse/retail":{"name":"Retail Area","terms":""},"landuse/vineyard":{"name":"Vineyard","terms":""},"leisure":{"name":"Leisure","terms":""},"leisure/adult_gaming_centre":{"name":"Adult Gaming Center","terms":"gambling,slot machine"},"leisure/bowling_alley":{"name":"Bowling Alley","terms":""},"leisure/common":{"name":"Common","terms":"open space"},"leisure/dog_park":{"name":"Dog Park","terms":""},"leisure/firepit":{"name":"Firepit","terms":"fireplace,campfire"},"leisure/garden":{"name":"Garden","terms":""},"leisure/golf_course":{"name":"Golf Course","terms":"links"},"leisure/ice_rink":{"name":"Ice Rink","terms":"hockey,skating,curling"},"leisure/marina":{"name":"Marina","terms":"boat"},"leisure/nature_reserve":{"name":"Nature Reserve","terms":"protected,wildlife"},"leisure/park":{"name":"Park","terms":"esplanade,estate,forest,garden,grass,green,grounds,lawn,lot,meadow,parkland,place,playground,plaza,pleasure garden,recreation area,square,tract,village green,woodland"},"leisure/picnic_table":{"name":"Picnic Table","terms":"bench"},"leisure/pitch":{"name":"Sport Pitch","terms":"field"},"leisure/pitch/american_football":{"name":"American Football Field","terms":""},"leisure/pitch/baseball":{"name":"Baseball Diamond","terms":""},"leisure/pitch/basketball":{"name":"Basketball Court","terms":""},"leisure/pitch/rugby_league":{"name":"Rugby League Field","terms":""},"leisure/pitch/rugby_union":{"name":"Rugby Union Field","terms":""},"leisure/pitch/skateboard":{"name":"Skate Park","terms":""},"leisure/pitch/soccer":{"name":"Soccer Field","terms":""},"leisure/pitch/tennis":{"name":"Tennis Court","terms":""},"leisure/pitch/volleyball":{"name":"Volleyball Court","terms":""},"leisure/playground":{"name":"Playground","terms":"jungle gym,play area"},"leisure/running_track":{"name":"Running Track","terms":""},"leisure/slipway":{"name":"Slipway","terms":"boat launch,boat ramp"},"leisure/sports_centre":{"name":"Sports Center / Gym","terms":"gym"},"leisure/sports_centre/swimming":{"name":"Swimming Pool Facility","terms":"dive,water"},"leisure/stadium":{"name":"Stadium","terms":""},"leisure/swimming_pool":{"name":"Swimming Pool","terms":"dive,water"},"leisure/track":{"name":"Racetrack (non-Motorsport)","terms":""},"leisure/water_park":{"name":"Water Park","terms":"swim,pool,dive"},"line":{"name":"Line","terms":""},"man_made":{"name":"Man Made","terms":""},"man_made/adit":{"name":"Adit","terms":"entrance,underground,mine,cave"},"man_made/breakwater":{"name":"Breakwater","terms":""},"man_made/chimney":{"name":"Chimney","terms":""},"man_made/cutline":{"name":"Cut line","terms":""},"man_made/embankment":{"name":"Embankment","terms":""},"man_made/flagpole":{"name":"Flagpole","terms":""},"man_made/gasometer":{"name":"Gasometer","terms":"gas holder"},"man_made/groyne":{"name":"Groyne","terms":""},"man_made/lighthouse":{"name":"Lighthouse","terms":""},"man_made/mast":{"name":"Radio Mast","terms":"broadcast tower,cell phone tower,cell tower,guyed tower,mobile phone tower,radio tower,television tower,transmission mast,transmission tower,tv tower"},"man_made/observation":{"name":"Observation Tower","terms":"lookout tower,fire tower"},"man_made/petroleum_well":{"name":"Oil Well","terms":"drilling rig,oil derrick,oil drill,oil horse,oil rig,oil pump,petroleum well,pumpjack"},"man_made/pier":{"name":"Pier","terms":""},"man_made/pipeline":{"name":"Pipeline","terms":""},"man_made/silo":{"name":"Silo","terms":"grain,corn,wheat"},"man_made/storage_tank":{"name":"Storage Tank","terms":"water,oil,gas,petrol"},"man_made/surveillance":{"name":"Surveillance","terms":""},"man_made/survey_point":{"name":"Survey Point","terms":""},"man_made/tower":{"name":"Tower","terms":""},"man_made/wastewater_plant":{"name":"Wastewater Plant","terms":"sewage*,water treatment plant,reclamation plant"},"man_made/water_tower":{"name":"Water Tower","terms":""},"man_made/water_well":{"name":"Water Well","terms":""},"man_made/water_works":{"name":"Water Works","terms":""},"man_made/works":{"name":"Works","terms":"car assembly plant,aluminium processing plant,brewery,furniture manufacture factory,oil refinery,plastic recycling"},"military/airfield":{"name":"Airfield","terms":""},"military/barracks":{"name":"Barracks","terms":""},"military/bunker":{"name":"Bunker","terms":""},"military/checkpoint":{"name":"Checkpoint","terms":""},"military/danger_area":{"name":"Danger Area","terms":""},"military/naval_base":{"name":"Naval Base","terms":""},"military/obstacle_course":{"name":"Obstacle Course","terms":""},"military/range":{"name":"Military Range","terms":""},"military/training_area":{"name":"Training area","terms":""},"natural":{"name":"Natural","terms":""},"natural/bay":{"name":"Bay","terms":""},"natural/beach":{"name":"Beach","terms":""},"natural/cave_entrance":{"name":"Cave Entrance","terms":"cavern,hollow,grotto,shelter,cavity"},"natural/cliff":{"name":"Cliff","terms":""},"natural/coastline":{"name":"Coastline","terms":"shore"},"natural/fell":{"name":"Fell","terms":""},"natural/glacier":{"name":"Glacier","terms":""},"natural/grassland":{"name":"Grassland","terms":""},"natural/heath":{"name":"Heath","terms":""},"natural/peak":{"name":"Peak","terms":"acme,aiguille,alp,climax,crest,crown,hill,mount,mountain,pinnacle,summit,tip,top"},"natural/saddle":{"name":"Saddle","terms":"pass,mountain pass,top"},"natural/scree":{"name":"Scree","terms":"loose rocks"},"natural/scrub":{"name":"Scrub","terms":"bush,shrubs"},"natural/spring":{"name":"Spring","terms":""},"natural/tree":{"name":"Tree","terms":""},"natural/tree_row":{"name":"Tree row","terms":""},"natural/volcano":{"name":"Volcano","terms":"mountain,crater"},"natural/water":{"name":"Water","terms":""},"natural/water/lake":{"name":"Lake","terms":"lakelet,loch,mere"},"natural/water/pond":{"name":"Pond","terms":"lakelet,millpond,tarn,pool,mere"},"natural/water/reservoir":{"name":"Reservoir","terms":""},"natural/wetland":{"name":"Wetland","terms":""},"natural/wood":{"name":"Wood","terms":"tree"},"office":{"name":"Office","terms":""},"office/accountant":{"name":"Accountant","terms":""},"office/administrative":{"name":"Administrative Office","terms":""},"office/architect":{"name":"Architect","terms":""},"office/company":{"name":"Company Office","terms":""},"office/educational_institution":{"name":"Educational Institution","terms":""},"office/employment_agency":{"name":"Employment Agency","terms":"job"},"office/estate_agent":{"name":"Real Estate Office","terms":""},"office/financial":{"name":"Financial Office","terms":""},"office/government":{"name":"Government Office","terms":""},"office/insurance":{"name":"Insurance Office","terms":""},"office/it":{"name":"IT Office","terms":""},"office/lawyer":{"name":"Law Office","terms":""},"office/newspaper":{"name":"Newspaper","terms":""},"office/ngo":{"name":"NGO Office","terms":""},"office/physician":{"name":"Physician","terms":""},"office/political_party":{"name":"Political Party","terms":""},"office/research":{"name":"Research Office","terms":""},"office/telecommunication":{"name":"Telecom Office","terms":""},"office/therapist":{"name":"Therapist","terms":""},"office/travel_agent":{"name":"Travel Agency","terms":""},"piste":{"name":"Piste/Ski Trail","terms":"ski,sled,sleigh,snowboard,nordic,downhill,snowmobile"},"place":{"name":"Place","terms":""},"place/city":{"name":"City","terms":""},"place/farm":{"name":"Farm","terms":""},"place/hamlet":{"name":"Hamlet","terms":""},"place/island":{"name":"Island","terms":"archipelago,atoll,bar,cay,isle,islet,key,reef"},"place/isolated_dwelling":{"name":"Isolated Dwelling","terms":""},"place/locality":{"name":"Locality","terms":""},"place/neighbourhood":{"name":"Neighborhood","terms":"neighbourhood"},"place/suburb":{"name":"Borough","terms":"Boro,Quarter"},"place/town":{"name":"Town","terms":""},"place/village":{"name":"Village","terms":""},"point":{"name":"Point","terms":""},"power":{"name":"Power","terms":""},"power/generator":{"name":"Power Generator","terms":""},"power/line":{"name":"Power Line","terms":""},"power/minor_line":{"name":"Minor Power Line","terms":""},"power/pole":{"name":"Power Pole","terms":""},"power/sub_station":{"name":"Substation","terms":""},"power/substation":{"name":"Substation","terms":""},"power/tower":{"name":"High-Voltage Tower","terms":""},"power/transformer":{"name":"Transformer","terms":""},"public_transport/platform":{"name":"Platform","terms":""},"public_transport/stop_position":{"name":"Stop Position","terms":""},"railway":{"name":"Railway","terms":""},"railway/abandoned":{"name":"Abandoned Railway","terms":""},"railway/disused":{"name":"Disused Railway","terms":""},"railway/funicular":{"name":"Funicular","terms":"venicular,cliff railway,cable car,cable railway,funicular railway"},"railway/halt":{"name":"Railway Halt","terms":"break,interrupt,rest,wait,interruption"},"railway/level_crossing":{"name":"Railway Crossing","terms":"crossing,railroad crossing,level crossing,grade crossing,road through railroad,train crossing"},"railway/monorail":{"name":"Monorail","terms":""},"railway/narrow_gauge":{"name":"Narrow Gauge Rail","terms":"narrow gauge railway,narrow gauge railroad"},"railway/platform":{"name":"Railway Platform","terms":""},"railway/rail":{"name":"Rail","terms":""},"railway/station":{"name":"Railway Station","terms":"train station,station"},"railway/subway":{"name":"Subway","terms":""},"railway/subway_entrance":{"name":"Subway Entrance","terms":""},"railway/tram":{"name":"Tram","terms":"streetcar"},"relation":{"name":"Relation","terms":""},"roundabout":{"name":"Roundabout","terms":""},"route/ferry":{"name":"Ferry Route","terms":""},"shop":{"name":"Shop","terms":""},"shop/alcohol":{"name":"Liquor Store","terms":"alcohol,beer,booze,wine"},"shop/anime":{"name":"Anime Shop","terms":""},"shop/antiques":{"name":"Antiques Shop","terms":""},"shop/art":{"name":"Art Store","terms":"art*,exhibit*,gallery"},"shop/baby_goods":{"name":"Baby Goods Store","terms":""},"shop/bag":{"name":"Bag/Luggage Store","terms":"handbag,purse"},"shop/bakery":{"name":"Bakery","terms":""},"shop/bathroom_furnishing":{"name":"Bathroom Furnishing Store","terms":""},"shop/beauty":{"name":"Beauty Shop","terms":"nail spa,spa,salon,tanning"},"shop/bed":{"name":"Bedding/Mattress Store","terms":""},"shop/beverages":{"name":"Beverage Store","terms":""},"shop/bicycle":{"name":"Bicycle Shop","terms":"bike,repair"},"shop/bookmaker":{"name":"Bookmaker","terms":""},"shop/books":{"name":"Book Store","terms":""},"shop/boutique":{"name":"Boutique","terms":""},"shop/butcher":{"name":"Butcher","terms":"meat"},"shop/candles":{"name":"Candle Shop","terms":""},"shop/car":{"name":"Car Dealership","terms":"auto"},"shop/car_parts":{"name":"Car Parts Store","terms":"auto"},"shop/car_repair":{"name":"Car Repair Shop","terms":"auto"},"shop/carpet":{"name":"Carpet Store","terms":"rug"},"shop/cheese":{"name":"Cheese Store","terms":""},"shop/chemist":{"name":"Chemist","terms":""},"shop/chocolate":{"name":"Chocolate Store","terms":""},"shop/clothes":{"name":"Clothing Store","terms":""},"shop/computer":{"name":"Computer Store","terms":""},"shop/confectionery":{"name":"Candy Store","terms":""},"shop/convenience":{"name":"Convenience Store","terms":""},"shop/copyshop":{"name":"Copy Store","terms":""},"shop/cosmetics":{"name":"Cosmetics Store","terms":""},"shop/craft":{"name":"Arts and Crafts Store","terms":"art*,paint*,frame"},"shop/curtain":{"name":"Curtain Store","terms":"drape*,window"},"shop/dairy":{"name":"Dairy Store","terms":"milk,egg,cheese"},"shop/deli":{"name":"Deli","terms":"lunch,meat,sandwich"},"shop/department_store":{"name":"Department Store","terms":""},"shop/doityourself":{"name":"DIY Store","terms":""},"shop/dry_cleaning":{"name":"Dry Cleaner","terms":""},"shop/electronics":{"name":"Electronics Store","terms":"appliance,audio,computer,tv"},"shop/erotic":{"name":"Erotic Store","terms":"sex,porn"},"shop/fabric":{"name":"Fabric Store","terms":"sew"},"shop/farm":{"name":"Produce Stand","terms":"farm shop,farm stand"},"shop/fashion":{"name":"Fashion Store","terms":""},"shop/fishmonger":{"name":"Fishmonger","terms":""},"shop/florist":{"name":"Florist","terms":"flower"},"shop/frame":{"name":"Framing Shop","terms":"art*,paint*,photo*,frame"},"shop/funeral_directors":{"name":"Funeral Home","terms":"undertaker,memorial home"},"shop/furnace":{"name":"Furnace Store","terms":"oven,stove"},"shop/furniture":{"name":"Furniture Store","terms":"chair,sofa,table"},"shop/garden_centre":{"name":"Garden Center","terms":"landscape,mulch,shrub,tree"},"shop/gift":{"name":"Gift Shop","terms":""},"shop/greengrocer":{"name":"Greengrocer","terms":"fruit,vegetable"},"shop/hairdresser":{"name":"Hairdresser","terms":""},"shop/hardware":{"name":"Hardware Store","terms":""},"shop/hearing_aids":{"name":"Hearing Aids Store","terms":""},"shop/herbalist":{"name":"Herbalist","terms":""},"shop/hifi":{"name":"Hifi Store","terms":"stereo,video"},"shop/houseware":{"name":"Houseware Store","terms":"home,household"},"shop/interior_decoration":{"name":"Interior Decoration Store","terms":""},"shop/jewelry":{"name":"Jeweler","terms":"diamond,gem,ring"},"shop/kiosk":{"name":"News Kiosk","terms":""},"shop/kitchen":{"name":"Kitchen Design Store","terms":""},"shop/laundry":{"name":"Laundry","terms":""},"shop/leather":{"name":"Leather Store","terms":""},"shop/locksmith":{"name":"Locksmith","terms":"key,lockpick"},"shop/lottery":{"name":"Lottery Shop","terms":""},"shop/mall":{"name":"Mall","terms":""},"shop/massage":{"name":"Massage Shop","terms":""},"shop/medical_supply":{"name":"Medical Supply Store","terms":""},"shop/mobile_phone":{"name":"Mobile Phone Store","terms":""},"shop/money_lender":{"name":"Money Lender","terms":""},"shop/motorcycle":{"name":"Motorcycle Dealership","terms":""},"shop/music":{"name":"Music Store","terms":"CD,vinyl"},"shop/musical_instrument":{"name":"Musical Instrument Store","terms":""},"shop/newsagent":{"name":"Newspaper/Magazine Shop","terms":""},"shop/optician":{"name":"Optician","terms":"eye,glasses"},"shop/organic":{"name":"Organic Goods Store","terms":""},"shop/outdoor":{"name":"Outdoors Store","terms":"camping,climbing,hiking"},"shop/paint":{"name":"Paint Store","terms":""},"shop/pawnbroker":{"name":"Pawn Shop","terms":""},"shop/pet":{"name":"Pet Store","terms":"cat,dog,fish"},"shop/photo":{"name":"Photography Store","terms":"camera,film"},"shop/pyrotechnics":{"name":"Fireworks Store","terms":""},"shop/radiotechnics":{"name":"Radio/Electronic Component Store","terms":""},"shop/religion":{"name":"Religious Store","terms":""},"shop/scuba_diving":{"name":"Scuba Diving Shop","terms":""},"shop/seafood":{"name":"Seafood Shop","terms":"fishmonger"},"shop/second_hand":{"name":"Consignment/Thrift Store","terms":"secondhand,second hand,resale,thrift,used"},"shop/shoes":{"name":"Shoe Store","terms":""},"shop/sports":{"name":"Sporting Goods Store","terms":""},"shop/stationery":{"name":"Stationery Store","terms":"card,paper"},"shop/storage_rental":{"name":"Storage Rental","terms":""},"shop/supermarket":{"name":"Supermarket","terms":"grocery,store,shop"},"shop/tailor":{"name":"Tailor","terms":"clothes,suit"},"shop/tattoo":{"name":"Tattoo Parlor","terms":""},"shop/tea":{"name":"Tea Store","terms":""},"shop/ticket":{"name":"Ticket Seller","terms":""},"shop/tobacco":{"name":"Tobacco Shop","terms":""},"shop/toys":{"name":"Toy Store","terms":""},"shop/travel_agency":{"name":"Travel Agency","terms":""},"shop/tyres":{"name":"Tire Store","terms":""},"shop/vacant":{"name":"Vacant Shop","terms":""},"shop/vacuum_cleaner":{"name":"Vacuum Cleaner Store","terms":""},"shop/variety_store":{"name":"Variety Store","terms":""},"shop/video":{"name":"Video Store","terms":"DVD"},"shop/video_games":{"name":"Video Game Store","terms":""},"shop/water_sports":{"name":"Watersport/Swim Shop","terms":""},"shop/weapons":{"name":"Weapon Shop","terms":"ammo,gun,knife,knives"},"shop/window_blind":{"name":"Window Blind Store","terms":""},"shop/wine":{"name":"Wine Shop","terms":""},"tourism":{"name":"Tourism","terms":""},"tourism/alpine_hut":{"name":"Alpine Hut","terms":""},"tourism/artwork":{"name":"Artwork","terms":"mural,sculpture,statue"},"tourism/attraction":{"name":"Tourist Attraction","terms":""},"tourism/camp_site":{"name":"Camp Site","terms":"Tent"},"tourism/caravan_site":{"name":"RV Park","terms":"Motor Home,Camper"},"tourism/chalet":{"name":"Chalet","terms":""},"tourism/gallery":{"name":"Art Gallery","terms":"art*,exhibit*,paint*,photo*,sculpt*"},"tourism/guest_house":{"name":"Guest House","terms":"B&B,Bed and Breakfast"},"tourism/hostel":{"name":"Hostel","terms":""},"tourism/hotel":{"name":"Hotel","terms":""},"tourism/information":{"name":"Information","terms":""},"tourism/motel":{"name":"Motel","terms":""},"tourism/museum":{"name":"Museum","terms":"art*,exhibit*,gallery,foundation,hall,institution,paint*,photo*,sculpt*"},"tourism/picnic_site":{"name":"Picnic Site","terms":"camp"},"tourism/theme_park":{"name":"Theme Park","terms":""},"tourism/viewpoint":{"name":"Viewpoint","terms":""},"tourism/zoo":{"name":"Zoo","terms":""},"traffic_calming/bump":{"name":"Speed Bump","terms":"speed hump"},"traffic_calming/hump":{"name":"Speed Hump","terms":"speed bump"},"traffic_calming/rumble_strip":{"name":"Rumble Strip","terms":"sleeper lines,audible lines,growlers"},"traffic_calming/table":{"name":"Raised Pedestrian Crossing","terms":"speed table,flat top hump"},"type/boundary":{"name":"Boundary","terms":""},"type/boundary/administrative":{"name":"Administrative Boundary","terms":""},"type/multipolygon":{"name":"Multipolygon","terms":""},"type/restriction":{"name":"Restriction","terms":""},"type/restriction/no_left_turn":{"name":"No Left Turn","terms":""},"type/restriction/no_right_turn":{"name":"No Right Turn","terms":""},"type/restriction/no_straight_on":{"name":"No Straight On","terms":""},"type/restriction/no_u_turn":{"name":"No U-turn","terms":""},"type/restriction/only_left_turn":{"name":"Left Turn Only","terms":""},"type/restriction/only_right_turn":{"name":"Right Turn Only","terms":""},"type/restriction/only_straight_on":{"name":"No Turns","terms":""},"type/route":{"name":"Route","terms":""},"type/route/bicycle":{"name":"Cycle Route","terms":""},"type/route/bus":{"name":"Bus Route","terms":""},"type/route/detour":{"name":"Detour Route","terms":""},"type/route/ferry":{"name":"Ferry Route","terms":""},"type/route/foot":{"name":"Foot Route","terms":""},"type/route/hiking":{"name":"Hiking Route","terms":""},"type/route/pipeline":{"name":"Pipeline Route","terms":""},"type/route/power":{"name":"Power Route","terms":""},"type/route/road":{"name":"Road Route","terms":""},"type/route/train":{"name":"Train Route","terms":""},"type/route/tram":{"name":"Tram Route","terms":""},"type/route_master":{"name":"Route Master","terms":""},"type/site":{"name":"Site","terms":""},"vertex":{"name":"Other","terms":""},"waterway":{"name":"Waterway","terms":""},"waterway/boatyard":{"name":"Boatyard","terms":""},"waterway/canal":{"name":"Canal","terms":""},"waterway/dam":{"name":"Dam","terms":""},"waterway/ditch":{"name":"Ditch","terms":""},"waterway/dock":{"name":"Dock","terms":""},"waterway/drain":{"name":"Drain","terms":""},"waterway/fuel":{"name":"Marine Fuel Station","terms":"petrol,gas,diesel,boat"},"waterway/river":{"name":"River","terms":"beck,branch,brook,course,creek,estuary,rill,rivulet,run,runnel,stream,tributary,watercourse"},"waterway/riverbank":{"name":"Riverbank","terms":""},"waterway/sanitary_dump_station":{"name":"Marine Toilet Disposal","terms":"Boat,Watercraft,Sanitary,Dump Station,Pumpout,Pump out,Elsan,CDP,CTDP,Chemical Toilet"},"waterway/stream":{"name":"Stream","terms":"beck,branch,brook,burn,course,creek,current,drift,flood,flow,freshet,race,rill,rindle,rivulet,run,runnel,rush,spate,spritz,surge,tide,torrent,tributary,watercourse"},"waterway/water_point":{"name":"Marine Drinking Water","terms":""},"waterway/weir":{"name":"Weir","terms":""}}}},"suggestions":{"amenity":{"fuel":{"76":{"count":314},"Neste":{"count":189},"BP":{"count":2511},"Shell":{"count":8380},"Agip":{"count":2651},"Migrol":{"count":65},"Avia":{"count":897},"Texaco":{"count":680},"Total":{"count":2607},"Statoil":{"count":596},"Esso":{"count":3652},"Jet":{"count":441},"Avanti":{"count":90},"Sainsbury's":{"count":58},"OMV":{"count":701},"Aral":{"count":1339},"Tesco":{"count":197},"JET":{"count":180},"Morrisons":{"count":111},"United":{"count":91},"Canadian Tire":{"count":66},"Mobil":{"count":613},"Caltex":{"count":1001},"Sunoco":{"count":355},"Q8":{"count":1161},"ABC":{"count":79},"ARAL":{"count":375},"CEPSA":{"count":1018},"BFT":{"count":89},"Petron":{"count":878},"Intermarché":{"count":434},"Total Access":{"count":51},"Super U":{"count":124},"Auchan":{"count":53},"Elf":{"count":129},"Carrefour":{"count":205},"Station Service E. Leclerc":{"count":530},"Shell Express":{"count":131},"Hess":{"count":127},"Flying V":{"count":129},"bft":{"count":168},"Gulf":{"count":199},"PTT":{"count":191},"St1":{"count":100},"Teboil":{"count":115},"HEM":{"count":212},"GALP":{"count":626},"OK":{"count":163},"ÖMV":{"count":101},"Tinq":{"count":215},"OKQ8":{"count":186},"Repsol":{"count":424},"Westfalen":{"count":96},"Esso Express":{"count":98},"Raiffeisenbank":{"count":117},"Tamoil":{"count":866},"Engen":{"count":241},"Sasol":{"count":59},"Topaz":{"count":78},"LPG":{"count":174},"Coop":{"count":62},"Orlen":{"count":598},"Oilibya":{"count":68},"Tango":{"count":122},"Star":{"count":319},"Петрол":{"count":84},"Cepsa":{"count":96},"OIL!":{"count":63},"Ultramar":{"count":125},"Irving":{"count":87},"Lukoil":{"count":701},"Petro-Canada":{"count":489},"7-Eleven":{"count":488},"Agrola":{"count":69},"Husky":{"count":126},"Slovnaft":{"count":219},"Sheetz":{"count":134},"Mol":{"count":61},"Petronas":{"count":159},"Газпромнефть":{"count":748},"Лукойл":{"count":1477},"Elan":{"count":112},"Роснефть":{"count":638},"Turmöl":{"count":57},"Neste A24":{"count":55},"Marathon":{"count":189},"Valero":{"count":366},"Eni":{"count":236},"Chevron":{"count":954},"ТНК":{"count":520},"REPSOL":{"count":1603},"MOL":{"count":228},"Bliska":{"count":150},"Api":{"count":302},"Arco":{"count":179},"Pemex":{"count":423},"Exxon":{"count":506},"Coles Express":{"count":115},"Petrom":{"count":259},"PETRONOR":{"count":207},"Rompetrol":{"count":174},"Lotos":{"count":178},"ОМВ":{"count":60},"BR":{"count":129},"Copec":{"count":505},"Petrobras":{"count":270},"Liberty":{"count":55},"IP":{"count":871},"Erg":{"count":596},"Eneos":{"count":97},"Citgo":{"count":279},"Metano":{"count":208},"Сургутнефтегаз":{"count":61},"EKO":{"count":59},"Eko":{"count":58},"Indipend.":{"count":172},"IES":{"count":63},"TotalErg":{"count":89},"Cenex":{"count":115},"ПТК":{"count":82},"HP":{"count":79},"Phillips 66":{"count":216},"CARREFOUR":{"count":74},"ERG":{"count":76},"Speedway":{"count":148},"Benzina":{"count":96},"Татнефть":{"count":264},"Terpel":{"count":259},"WOG":{"count":189},"Seaoil":{"count":54},"АЗС":{"count":1077},"Kwik Trip":{"count":108},"Wawa":{"count":89},"Pertamina":{"count":186},"COSMO":{"count":64},"Z":{"count":76},"Indian Oil":{"count":183},"АГЗС":{"count":494},"INA":{"count":121},"JOMO":{"count":62},"Holiday":{"count":97},"YPF":{"count":70},"IDEMITSU":{"count":87},"ENEOS":{"count":736},"Bharat Petroleum":{"count":64},"CAMPSA":{"count":615},"Casey's General Store":{"count":190},"Башнефть":{"count":60},"Kangaroo":{"count":60},"コスモ石油 (COSMO)":{"count":136},"MEROIL":{"count":77},"1-2-3":{"count":71},"出光":{"count":228,"tags":{"name:en":"IDEMITSU"}},"НК Альянс":{"count":88},"Sinclair":{"count":100},"Conoco":{"count":189},"SPBU":{"count":54},"Макпетрол":{"count":109},"Circle K":{"count":166},"Posto Ipiranga":{"count":70},"Posto Shell":{"count":54},"Phoenix":{"count":144},"Ipiranga":{"count":119},"OKKO":{"count":85},"ОККО":{"count":119},"บางจาก":{"count":60},"QuikTrip":{"count":105},"Stewart's":{"count":63},"Posto BR":{"count":68},"ป ต ท":{"count":152},"ปตท":{"count":88},"ANP":{"count":80},"Kum & Go":{"count":80},"Petrolimex":{"count":55},"Sokimex":{"count":66},"Tela":{"count":154},"Posto":{"count":71},"H-E-B":{"count":182},"Укрнафта":{"count":58},"Татнефтепродукт":{"count":54},"Afriquia":{"count":88},"Murphy USA":{"count":67},"昭和シェル (Showa-shell)":{"count":94},"エネオス":{"count":53},"CNG":{"count":94}},"pub":{"Kings Arms":{"count":67},"The Ship":{"count":89},"The White Horse":{"count":204},"The White Hart":{"count":226},"Royal Oak":{"count":150},"The Red Lion":{"count":233},"The Kings Arms":{"count":58},"The Star":{"count":73},"The Anchor":{"count":64},"The Cross Keys":{"count":55},"The Wheatsheaf":{"count":117},"The Crown Inn":{"count":67},"The Kings Head":{"count":53},"The Castle":{"count":62},"The Railway":{"count":102},"The White Lion":{"count":118},"The Bell":{"count":121},"The Bull":{"count":68},"The Plough":{"count":179},"The George":{"count":110},"The Royal Oak":{"count":209},"The Fox":{"count":74},"Prince of Wales":{"count":77},"The Rising Sun":{"count":71},"The Prince of Wales":{"count":51},"The Crown":{"count":244},"The Chequers":{"count":66},"The Swan":{"count":152},"Rose and Crown":{"count":79},"The Victoria":{"count":67},"New Inn":{"count":90},"Royal Hotel":{"count":57},"Red Lion":{"count":207},"Cross Keys":{"count":61},"The Greyhound":{"count":96},"The Black Horse":{"count":94},"The New Inn":{"count":105},"Kings Head":{"count":59},"The Albion":{"count":51},"The Angel":{"count":52},"The Queens Head":{"count":52},"The Ship Inn":{"count":83},"Rose & Crown":{"count":51},"Queens Head":{"count":52},"Irish Pub":{"count":76}},"fast_food":{"Quick":{"count":484},"McDonald's":{"count":12376,"tags":{"cuisine":"burger"}},"Subway":{"count":5576,"tags":{"cuisine":"sandwich"}},"Burger King":{"count":3734,"tags":{"cuisine":"burger"}},"Ali Baba":{"count":61},"Hungry Jacks":{"count":173,"tags":{"cuisine":"burger"}},"Red Rooster":{"count":148},"KFC":{"count":3198,"tags":{"cuisine":"chicken"}},"Domino's Pizza":{"count":985,"tags":{"cuisine":"pizza"}},"Chowking":{"count":142},"Jollibee":{"count":396},"Hesburger":{"count":102},"肯德基":{"count":86},"Wendy's":{"count":1621,"tags":{"cuisine":"burger"}},"Tim Hortons":{"count":323},"Steers":{"count":151},"Hardee's":{"count":268,"tags":{"cuisine":"burger"}},"Arby's":{"count":782},"A&W":{"count":283},"Dairy Queen":{"count":791},"Hallo Pizza":{"count":76},"Fish & Chips":{"count":93},"Harvey's":{"count":90},"麥當勞":{"count":65},"Pizza Pizza":{"count":215},"Kotipizza":{"count":74},"Jack in the Box":{"count":546,"tags":{"cuisine":"burger"}},"Istanbul":{"count":56},"Kochlöffel":{"count":68},"Döner":{"count":228},"Telepizza":{"count":201},"Sibylla":{"count":61},"Carl's Jr.":{"count":298,"tags":{"cuisine":"burger"}},"Quiznos":{"count":266,"tags":{"cuisine":"sandwich"}},"Wimpy":{"count":141},"Sonic":{"count":566,"tags":{"cuisine":"burger"}},"Taco Bell":{"count":1423,"tags":{"cuisine":"mexican"}},"Pizza Nova":{"count":63},"Papa John's":{"count":304,"tags":{"cuisine":"pizza"}},"Nordsee":{"count":159},"Mr. Sub":{"count":103},"Макдоналдс":{"count":324,"tags":{"name:en":"McDonald's"}},"Asia Imbiss":{"count":111},"Chipotle":{"count":290,"tags":{"cuisine":"mexican"}},"マクドナルド":{"count":692,"tags":{"name:en":"McDonald's","cuisine":"burger"}},"In-N-Out Burger":{"count":65},"Jimmy John's":{"count":141},"Jamba Juice":{"count":68},"Робин Сдобин":{"count":82},"Baskin Robbins":{"count":74},"ケンタッキーフライドチキン":{"count":164,"tags":{"name:en":"KFC","cuisine":"chicken"}},"吉野家":{"count":191},"Taco Time":{"count":88},"松屋":{"count":281,"tags":{"name:en":"Matsuya"}},"Little Caesars":{"count":81},"El Pollo Loco":{"count":63},"Del Taco":{"count":141},"White Castle":{"count":80},"Boston Market":{"count":66},"Chick-fil-A":{"count":257,"tags":{"cuisine":"chicken"}},"Panda Express":{"count":238,"tags":{"cuisine":"chinese"}},"Whataburger":{"count":364},"Taco John's":{"count":78},"Теремок":{"count":68},"Culver's":{"count":425},"Five Guys":{"count":141},"Church's Chicken":{"count":95},"Popeye's":{"count":167,"tags":{"cuisine":"chicken"}},"Long John Silver's":{"count":93},"Pollo Campero":{"count":62},"Zaxby's":{"count":51},"すき家":{"count":276,"tags":{"name:en":"SUKIYA"}},"モスバーガー":{"count":257,"tags":{"name:en":"MOS BURGER"}},"Русский Аппетит":{"count":69},"なか卯":{"count":63}},"restaurant":{"Pizza Hut":{"count":1180,"tags":{"cuisine":"pizza"}},"Little Chef":{"count":64},"Adler":{"count":158},"Zur Krone":{"count":90},"Deutsches Haus":{"count":90},"Krone":{"count":171},"Akropolis":{"count":152},"Schützenhaus":{"count":124},"Kreuz":{"count":74},"Waldschänke":{"count":55},"La Piazza":{"count":69},"Lamm":{"count":66},"Zur Sonne":{"count":73},"Zur Linde":{"count":204},"Poseidon":{"count":110},"Shanghai":{"count":82},"Red Lobster":{"count":235},"Zum Löwen":{"count":84},"Swiss Chalet":{"count":107},"Olympia":{"count":74},"Wagamama":{"count":64},"Frankie & Benny's":{"count":66},"Hooters":{"count":103},"Sternen":{"count":78},"Hirschen":{"count":79},"Denny's":{"count":450},"Athen":{"count":68},"Sonne":{"count":126},"Hirsch":{"count":79},"Ratskeller":{"count":150},"La Cantina":{"count":56},"Gasthaus Krone":{"count":56},"El Greco":{"count":86},"Gasthof zur Post":{"count":79},"Nando's":{"count":246},"Löwen":{"count":112},"La Pataterie":{"count":51},"Bella Napoli":{"count":53},"Pizza Express":{"count":262},"Mandarin":{"count":65},"Hong Kong":{"count":83},"Zizzi":{"count":68},"Cracker Barrel":{"count":183},"Rhodos":{"count":81},"Lindenhof":{"count":79},"Milano":{"count":54},"Dolce Vita":{"count":77},"Kirchenwirt":{"count":81},"Kantine":{"count":52},"Ochsen":{"count":95},"Spur":{"count":62},"Mykonos":{"count":59},"Lotus":{"count":66},"Applebee's":{"count":531},"Flunch":{"count":72},"Zur Post":{"count":116},"China Town":{"count":76},"La Dolce Vita":{"count":73},"Waffle House":{"count":207},"Delphi":{"count":88},"Linde":{"count":103},"Outback Steakhouse":{"count":218},"Dionysos":{"count":69},"Kelsey's":{"count":57},"Boston Pizza":{"count":165},"Bella Italia":{"count":132},"Sizzler":{"count":53},"Grüner Baum":{"count":116},"Taj Mahal":{"count":104},"Rössli":{"count":68},"Wimpy":{"count":51},"Traube":{"count":65},"Adria":{"count":52},"Red Robin":{"count":185},"Roma":{"count":61},"San Marco":{"count":67},"Hellas":{"count":55},"La Perla":{"count":67},"Vips":{"count":53},"Panera Bread":{"count":218},"Da Vinci":{"count":54},"Hippopotamus":{"count":96},"Prezzo":{"count":75},"Courtepaille":{"count":106},"Hard Rock Cafe":{"count":70},"Panorama":{"count":61},"デニーズ":{"count":82},"Sportheim":{"count":65},"餃子の王将":{"count":57},"Bären":{"count":60},"Alte Post":{"count":60},"Pizzeria Roma":{"count":51},"China Garden":{"count":66},"Vapiano":{"count":82},"Mamma Mia":{"count":64},"Schwarzer Adler":{"count":57},"IHOP":{"count":317},"Chili's":{"count":328},"Asia":{"count":51},"Olive Garden":{"count":279},"TGI Friday's":{"count":159},"Friendly's":{"count":78},"Buffalo Grill":{"count":202},"Texas Roadhouse":{"count":110},"ガスト":{"count":230,"tags":{"name:en":"Gusto"}},"Sakura":{"count":75},"Mensa":{"count":99},"The Keg":{"count":53},"サイゼリヤ":{"count":93},"La Strada":{"count":52},"Village Inn":{"count":92},"Buffalo Wild Wings":{"count":176},"Peking":{"count":59},"Boston Market":{"count":61},"Round Table Pizza":{"count":53},"Jimmy John's":{"count":69},"California Pizza Kitchen":{"count":61},"Якитория":{"count":77},"Golden Corral":{"count":101},"Perkins":{"count":105},"Ruby Tuesday":{"count":162},"Shari's":{"count":65},"Bob Evans":{"count":129},"바다횟집 (Bada Fish Restaurant)":{"count":55},"Mang Inasal":{"count":84},"Евразия":{"count":102},"ジョナサン":{"count":59},"Longhorn Steakhouse":{"count":66}},"bank":{"Chase":{"count":721},"Commonwealth Bank":{"count":232},"Citibank":{"count":277},"HSBC":{"count":1102},"Barclays":{"count":965},"Westpac":{"count":208},"NAB":{"count":131},"ANZ":{"count":218},"Lloyds Bank":{"count":547},"Landbank":{"count":81},"Sparkasse":{"count":4555},"UCPB":{"count":92},"PNB":{"count":244},"Metrobank":{"count":269},"BDO":{"count":290},"Volksbank":{"count":2591},"BPI":{"count":415},"Postbank":{"count":443},"NatWest":{"count":628},"Raiffeisenbank":{"count":2119},"Yorkshire Bank":{"count":63},"ABSA":{"count":95},"Standard Bank":{"count":109},"FNB":{"count":97},"Deutsche Bank":{"count":855},"SEB":{"count":133},"Commerzbank":{"count":806},"Targobank":{"count":166},"ABN AMRO":{"count":130},"Handelsbanken":{"count":184},"Swedbank":{"count":223},"Kreissparkasse":{"count":600},"UniCredit Bank":{"count":408},"Monte dei Paschi di Siena":{"count":132},"Caja Rural":{"count":99},"Dresdner Bank":{"count":66},"Sparda-Bank":{"count":320},"VÚB":{"count":107},"Slovenská sporiteľňa":{"count":134},"Bank of Montreal":{"count":118},"KBC":{"count":203},"Royal Bank of Scotland":{"count":111},"TSB":{"count":80},"US Bank":{"count":256},"HypoVereinsbank":{"count":561},"Bank Austria":{"count":176},"ING":{"count":496},"Erste Bank":{"count":180},"CIBC":{"count":326},"Scotiabank":{"count":413},"Caisse d'Épargne":{"count":882},"Santander":{"count":1323},"Bank of Scotland":{"count":89},"TD Canada Trust":{"count":450},"BMO":{"count":169},"Danske Bank":{"count":131},"OTP":{"count":192},"Crédit Agricole":{"count":1239},"LCL":{"count":553},"VR-Bank":{"count":430},"ČSOB":{"count":160},"Česká spořitelna":{"count":212},"BNP":{"count":112},"Royal Bank":{"count":65},"Nationwide":{"count":209},"Halifax":{"count":225},"BAWAG PSK":{"count":102},"National Bank":{"count":84},"Nedbank":{"count":80},"First National Bank":{"count":85},"Nordea":{"count":319},"Rabobank":{"count":609},"Sparkasse KölnBonn":{"count":69},"Tatra banka":{"count":67},"Berliner Sparkasse":{"count":62},"Berliner Volksbank":{"count":77},"Wells Fargo":{"count":874},"Credit Suisse":{"count":71},"Société Générale":{"count":634},"Osuuspankki":{"count":75},"Sparkasse Aachen":{"count":56},"Hamburger Sparkasse":{"count":156},"Cassa di Risparmio del Veneto":{"count":68},"BNP Paribas":{"count":617},"Banque Populaire":{"count":433},"BNP Paribas Fortis":{"count":209},"Banco Popular":{"count":291},"Bancaja":{"count":55},"Banesto":{"count":208},"La Caixa":{"count":583},"Santander Consumer Bank":{"count":88},"BRD":{"count":191},"BCR":{"count":143},"Banca Transilvania":{"count":141},"BW-Bank":{"count":97},"Komerční banka":{"count":132},"Banco Pastor":{"count":64},"Stadtsparkasse":{"count":86},"Ulster Bank":{"count":86},"Sberbank":{"count":58},"CIC":{"count":427},"Bancpost":{"count":56},"Caja Madrid":{"count":115},"Maybank":{"count":94},"中国银行":{"count":85},"Unicredit Banca":{"count":243},"Crédit Mutuel":{"count":690},"BBVA":{"count":647},"Intesa San Paolo":{"count":69},"TD Bank":{"count":206},"Belfius":{"count":231},"Bank of America":{"count":924},"RBC":{"count":230},"Alpha Bank":{"count":123},"Сбербанк":{"count":4794},"Россельхозбанк":{"count":201},"Crédit du Nord":{"count":96},"BancoEstado":{"count":80},"Millennium Bank":{"count":414},"State Bank of India":{"count":151},"Беларусбанк":{"count":242},"ING Bank Śląski":{"count":67},"Caixa Geral de Depósitos":{"count":129},"Kreissparkasse Köln":{"count":65},"Banco BCI":{"count":51},"Banco de Chile":{"count":98},"ВТБ24":{"count":326},"UBS":{"count":134},"PKO BP":{"count":265},"Chinabank":{"count":55},"PSBank":{"count":59},"Union Bank":{"count":124},"China Bank":{"count":66},"RCBC":{"count":122},"Unicaja":{"count":83},"BBK":{"count":79},"Ibercaja":{"count":69},"RBS":{"count":143},"Commercial Bank of Ceylon PLC":{"count":79},"Bank of Ireland":{"count":109},"BNL":{"count":87},"Banco Santander":{"count":138},"Banco Itaú":{"count":111},"AIB":{"count":72},"BZ WBK":{"count":77},"Banco do Brasil":{"count":557},"Caixa Econômica Federal":{"count":184},"Fifth Third Bank":{"count":84},"Banca Popolare di Vicenza":{"count":81},"Wachovia":{"count":58},"OLB":{"count":53},"みずほ銀行":{"count":78},"BES":{"count":72},"ICICI Bank":{"count":91},"HDFC Bank":{"count":91},"La Banque Postale":{"count":67},"Pekao SA":{"count":56},"Oberbank":{"count":90},"Bradesco":{"count":295},"Oldenburgische Landesbank":{"count":56},"Bendigo Bank":{"count":93},"Argenta":{"count":86},"AXA":{"count":68},"Axis Bank":{"count":61},"Banco Nación":{"count":67},"GE Money Bank":{"count":72},"Альфа-Банк":{"count":185},"Белагропромбанк":{"count":70},"Caja Círculo":{"count":65},"Banco Galicia":{"count":51},"Eurobank":{"count":97},"Banca Intesa":{"count":62},"Canara Bank":{"count":92},"Cajamar":{"count":77},"Banamex":{"count":149},"Crédit Mutuel de Bretagne":{"count":335},"Davivienda":{"count":83},"Bank Spółdzielczy":{"count":159},"Credit Agricole":{"count":157},"Bankinter":{"count":59},"Banque Nationale":{"count":63},"Bank of the West":{"count":96},"Key Bank":{"count":155},"Western Union":{"count":88},"Citizens Bank":{"count":115},"ПриватБанк":{"count":513},"Security Bank":{"count":78},"Millenium":{"count":60},"Bankia":{"count":149},"三菱東京UFJ銀行":{"count":159},"Caixa":{"count":117},"Banco de Costa Rica":{"count":63},"SunTrust Bank":{"count":73},"Itaú":{"count":338},"PBZ":{"count":52},"中国工商银行":{"count":51},"Bancolombia":{"count":89},"Райффайзен Банк Аваль":{"count":64},"Bancomer":{"count":115},"Banorte":{"count":80},"Alior Bank":{"count":81},"BOC":{"count":51},"Банк Москвы":{"count":118},"ВТБ":{"count":59},"Getin Bank":{"count":55},"Caja Duero":{"count":57},"Regions Bank":{"count":62},"Росбанк":{"count":177},"Banco Estado":{"count":72},"BCI":{"count":68},"SunTrust":{"count":68},"PNC Bank":{"count":254},"신한은행":{"count":217,"tags":{"name:en":"Sinhan Bank"}},"우리은행":{"count":291,"tags":{"name:en":"Uri Bank"}},"국민은행":{"count":165,"tags":{"name:en":"Gungmin Bank"}},"중소기업은행":{"count":52,"tags":{"name:en":"Industrial Bank of Korea"}},"광주은행":{"count":51,"tags":{"name:en":"Gwangju Bank"}},"Газпромбанк":{"count":100},"M&T Bank":{"count":92},"Caja de Burgos":{"count":51},"Santander Totta":{"count":69},"УкрСиббанк":{"count":192},"Ощадбанк":{"count":364},"Уралсиб":{"count":85},"りそな銀行":{"count":225,"tags":{"name:en":"Mizuho Bank"}},"Ecobank":{"count":66},"Cajero Automatico Bancared":{"count":145},"Промсвязьбанк":{"count":93},"三井住友銀行":{"count":129},"Banco Provincia":{"count":67},"BB&T":{"count":147},"Возрождение":{"count":59},"Capital One":{"count":59},"横浜銀行":{"count":51},"Bank Mandiri":{"count":62},"Banco de la Nación":{"count":92},"Banco G&T Continental":{"count":62},"Peoples Bank":{"count":60},"工商银行":{"count":51},"Совкомбанк":{"count":55},"Provincial":{"count":56},"Banco de Desarrollo Banrural":{"count":73},"Banco Bradesco":{"count":65},"Bicentenario":{"count":182},"ლიბერთი ბანკი":{"count":54,"tags":{"name:en":"Liberty Bank"}},"Banesco":{"count":108},"Mercantil":{"count":75},"Bank BRI":{"count":53},"Del Tesoro":{"count":91},"하나은행":{"count":77},"CityCommerce Bank":{"count":71},"De Venezuela":{"count":117}},"car_rental":{"Europcar":{"count":291},"Budget":{"count":92},"Sixt":{"count":161},"Avis":{"count":282},"Hertz":{"count":293},"Enterprise":{"count":199},"stadtmobil CarSharing-Station":{"count":148}},"pharmacy":{"Rowlands Pharmacy":{"count":71},"Boots":{"count":840},"Marien-Apotheke":{"count":314},"Mercury Drug":{"count":426},"Löwen-Apotheke":{"count":356},"Superdrug":{"count":117},"Sonnen-Apotheke":{"count":311},"Rathaus-Apotheke":{"count":132},"Engel-Apotheke":{"count":123},"Hirsch-Apotheke":{"count":83},"Stern-Apotheke":{"count":67},"Lloyds Pharmacy":{"count":295},"Rosen-Apotheke":{"count":208},"Stadt-Apotheke":{"count":302},"Markt-Apotheke":{"count":164},"Аптека":{"count":1989},"Pharmasave":{"count":64},"Brunnen-Apotheke":{"count":53},"Shoppers Drug Mart":{"count":430},"Apotheke am Markt":{"count":60},"Alte Apotheke":{"count":88},"Neue Apotheke":{"count":109},"Gintarinė vaistinė":{"count":101},"Rats-Apotheke":{"count":84},"Adler Apotheke":{"count":313},"Pharmacie Centrale":{"count":64},"Walgreens":{"count":1619},"Rite Aid":{"count":745},"Apotheke":{"count":165},"Linden-Apotheke":{"count":211},"Bahnhof-Apotheke":{"count":66},"Burg-Apotheke":{"count":55},"Jean Coutu":{"count":62},"Pharmaprix":{"count":60},"Farmacias Ahumada":{"count":104},"Farmacia Comunale":{"count":113},"Farmacias Cruz Verde":{"count":86},"Cruz Verde":{"count":99},"Hubertus Apotheke":{"count":52},"CVS":{"count":1560},"Farmacias SalcoBrand":{"count":133},"Фармация":{"count":120},"Bären-Apotheke":{"count":74},"Clicks":{"count":113},"セイジョー":{"count":53},"マツモトキヨシ":{"count":115},"Dr. Max":{"count":51},"Вита":{"count":106},"Радуга":{"count":70},"サンドラッグ":{"count":61},"Apteka":{"count":366},"Первая помощь":{"count":74},"Ригла":{"count":113},"Имплозия":{"count":63},"Kinney Drugs":{"count":68},"Классика":{"count":67},"Ljekarna":{"count":53},"SalcoBrand":{"count":88},"Аптека 36,6":{"count":224},"Фармакор":{"count":75},"スギ薬局":{"count":84},"Аптечный пункт":{"count":148},"Невис":{"count":60},"トモズ (Tomod's)":{"count":83},"Eurovaistinė":{"count":65},"Farmacity":{"count":68},"аптека":{"count":96},"The Generics Pharmacy":{"count":95},"Farmatodo":{"count":123},"Duane Reade":{"count":61},"H-E-B":{"count":262},"Фармленд":{"count":82},"ドラッグてらしま (Drug Terashima)":{"count":96},"Арніка":{"count":125},"ავერსი (Aversi)":{"count":62},"Farmahorro":{"count":58}},"cafe":{"Starbucks":{"count":4238,"tags":{"cuisine":"coffee_shop"}},"Cafeteria":{"count":115},"Costa":{"count":618},"Caffè Nero":{"count":169},"Кафе":{"count":226},"Café Central":{"count":61},"Second Cup":{"count":193},"Dunkin Donuts":{"count":428,"tags":{"cuisine":"donut"}},"Espresso House":{"count":53},"Segafredo":{"count":69},"Coffee Time":{"count":94},"Cafe Coffee Day":{"count":120},"Eiscafe Venezia":{"count":180},"スターバックス":{"count":251,"tags":{"name:en":"Starbucks"}},"Шоколадница":{"count":145},"Pret A Manger":{"count":119},"Столовая":{"count":391},"Jamba Juice":{"count":53},"ドトール":{"count":164,"tags":{"name:en":"DOUTOR"}},"Tchibo":{"count":100},"Кофе Хауз":{"count":104},"Caribou Coffee":{"count":100},"Уют":{"count":51},"Шашлычная":{"count":58},"คาเฟ่ อเมซอน":{"count":62},"Traveler's Coffee":{"count":60},"カフェ・ド・クリエ":{"count":67,"tags":{"name:en":"Cafe de CRIE"}},"Cafe Amazon":{"count":65}}},"shop":{"supermarket":{"Budgens":{"count":88},"Morrisons":{"count":411},"Interspar":{"count":142},"Merkur":{"count":107},"Sainsbury's":{"count":547},"Lidl":{"count":7130},"Edeka":{"count":2293},"Coles":{"count":400},"Iceland":{"count":315},"Coop":{"count":2100},"Tesco":{"count":1297},"Woolworths":{"count":541},"Zielpunkt":{"count":239},"Nahkauf":{"count":170},"Billa":{"count":1432},"Kaufland":{"count":1004},"Plus":{"count":120},"ALDI":{"count":5172},"Checkers":{"count":128},"Tesco Metro":{"count":137},"NP":{"count":153},"Penny":{"count":1759},"Norma":{"count":1068},"Asda":{"count":225},"Netto":{"count":4379},"Rewe":{"count":2645},"Aldi Süd":{"count":594},"Real":{"count":246},"Tesco Express":{"count":406},"King Soopers":{"count":72},"Kiwi":{"count":167},"Pick n Pay":{"count":241},"ICA":{"count":192},"Tengelmann":{"count":188},"Carrefour":{"count":1640},"Waitrose":{"count":258},"Spar":{"count":2386},"Hofer":{"count":442},"M-Preis":{"count":76},"tegut":{"count":210},"Sainsbury's Local":{"count":118},"E-Center":{"count":66},"Aldi Nord":{"count":210},"nahkauf":{"count":84},"Meijer":{"count":76},"Safeway":{"count":410},"Costco":{"count":152},"Albert":{"count":185},"Jumbo":{"count":194},"Shoprite":{"count":244},"MPreis":{"count":54},"Penny Market":{"count":429},"Tesco Extra":{"count":123},"Albert Heijn":{"count":476},"IGA":{"count":363},"Super U":{"count":488},"Metro":{"count":260},"Neukauf":{"count":77},"Migros":{"count":459},"Marktkauf":{"count":121},"Delikatesy Centrum":{"count":59},"C1000":{"count":307},"Hoogvliet":{"count":53},"Food Basics":{"count":75},"Casino":{"count":264},"Penny Markt":{"count":466},"Giant":{"count":191},"COOP Jednota":{"count":73},"Rema 1000":{"count":368},"Kaufpark":{"count":96},"ALDI SÜD":{"count":113},"Simply Market":{"count":330},"Konzum":{"count":230},"Carrefour Express":{"count":353},"Eurospar":{"count":270},"Mercator":{"count":125},"Famila":{"count":130},"Hemköp":{"count":82},"real,-":{"count":81},"Markant":{"count":88},"Volg":{"count":135},"Leader Price":{"count":267},"Treff 3000":{"count":94},"SuperBrugsen":{"count":67},"Kaiser's":{"count":256},"K+K":{"count":106},"Unimarkt":{"count":86},"Carrefour City":{"count":126},"Sobeys":{"count":122},"S-Market":{"count":109},"Combi":{"count":55},"Denner":{"count":276},"Konsum":{"count":133},"Franprix":{"count":312},"Monoprix":{"count":198},"Diska":{"count":69},"PENNY":{"count":79},"Dia":{"count":835},"Giant Eagle":{"count":85},"NORMA":{"count":115},"AD Delhaize":{"count":63},"Auchan":{"count":152},"Mercadona":{"count":769},"Consum":{"count":130},"Carrefour Market":{"count":80},"Whole Foods":{"count":210,"tags":{"shop":"supermarket"}},"Pam":{"count":56},"sky":{"count":105},"Despar":{"count":146},"Eroski":{"count":208},"Costcutter":{"count":63},"Maxi":{"count":108},"Colruyt":{"count":180},"The Co-operative":{"count":64},"Intermarché":{"count":1210},"Delhaize":{"count":207},"CBA":{"count":176},"Shopi":{"count":53},"Walmart":{"count":644},"Kroger":{"count":317},"Albertsons":{"count":242},"Trader Joe's":{"count":235},"Feneberg":{"count":58},"denn's Biomarkt":{"count":52},"dm":{"count":114},"Kvickly":{"count":55},"Makro":{"count":140},"Dico":{"count":53},"Nah & Frisch":{"count":73},"Champion":{"count":59},"ICA Supermarket":{"count":51},"Fakta":{"count":235},"Магнит":{"count":1760},"Caprabo":{"count":103},"Famiglia Cooperativa":{"count":64},"Народная 7Я семьЯ":{"count":154},"Esselunga":{"count":85},"Maxima":{"count":102},"Petit Casino":{"count":111},"Wasgau":{"count":60},"Pingo Doce":{"count":253},"Match":{"count":140},"Profi":{"count":60},"Lider":{"count":65},"Unimarc":{"count":177},"The Co-operative Food":{"count":190},"Santa Isabel":{"count":128},"Седьмой континент":{"count":79},"HIT":{"count":59},"Rimi":{"count":106},"Conad":{"count":304},"Фуршет":{"count":76},"Willys":{"count":56},"Farmfoods":{"count":64},"U Express":{"count":51},"Фора":{"count":52},"Dunnes Stores":{"count":73},"Сільпо":{"count":125},"マルエツ":{"count":59},"Piggly Wiggly":{"count":57},"Crai":{"count":54},"El Árbol":{"count":73},"Centre Commercial E. Leclerc":{"count":549},"Foodland":{"count":100},"Super Brugsen":{"count":67},"Дикси":{"count":683},"Пятёрочка":{"count":1344},"Publix":{"count":339},"Føtex":{"count":66},"coop":{"count":73},"Fressnapf":{"count":69},"Coop Konsum":{"count":79},"Carrefour Contact":{"count":83},"No Frills":{"count":105},"Plodine":{"count":52},"ADEG":{"count":68},"Minipreço":{"count":111},"Biedronka":{"count":1335},"Eurospin":{"count":155},"Семья":{"count":62},"Gadis":{"count":53},"Евроопт":{"count":68},"Centra":{"count":51},"Квартал":{"count":82},"New World":{"count":69},"Countdown":{"count":95},"Reliance Fresh":{"count":61},"Stokrotka":{"count":98},"Coop Jednota":{"count":74},"Fred Meyer":{"count":64},"Irma":{"count":58},"Continente":{"count":75},"Price Chopper":{"count":99},"Game":{"count":52},"Soriana":{"count":93},"Alimerka":{"count":64},"Piotr i Paweł":{"count":53},"Перекресток":{"count":312},"Maxima X":{"count":117},"Карусель":{"count":55},"ALDI Nord":{"count":51},"Condis":{"count":67},"Sam's Club":{"count":138},"Копейка":{"count":87},"Géant Casino":{"count":54},"ASDA":{"count":180},"Intermarche":{"count":115},"Stop & Shop":{"count":66},"Food Lion":{"count":216},"Harris Teeter":{"count":92},"Foodworks":{"count":62},"Polo Market":{"count":86},"Лента":{"count":51},"西友 (SEIYU)":{"count":58},"H-E-B":{"count":293},"Атак":{"count":53},"Полушка":{"count":139},"Extra":{"count":82},"Lewiatan":{"count":94},"Sigma":{"count":51},"АТБ":{"count":322},"Społem":{"count":55},"Bodega Aurrera":{"count":82},"Tesco Lotus":{"count":77},"Мария-Ра":{"count":108},"Магнолия":{"count":72},"Магазин":{"count":120},"Монетка":{"count":174},"Hy-Vee":{"count":75},"Walmart Supercenter":{"count":133},"Hannaford":{"count":57},"Wegmans":{"count":83},"業務スーパー":{"count":61},"Norfa XL":{"count":55},"ヨークマート (YorkMart)":{"count":64},"Leclerc Drive":{"count":76}},"electronics":{"Media Markt":{"count":285},"Maplin":{"count":65},"Best Buy":{"count":345},"Future Shop":{"count":73},"Saturn":{"count":134},"Currys":{"count":80},"Radio Shack":{"count":269},"Euronics":{"count":115},"Expert":{"count":123},"Эльдорадо":{"count":184},"Darty":{"count":74},"М.Видео":{"count":89},"ヤマダ電機":{"count":51}},"convenience":{"Shell":{"count":255},"Spar":{"count":1119},"McColl's":{"count":100},"Tesco Express":{"count":426},"Sainsbury's Local":{"count":104},"Aral":{"count":56},"One Stop":{"count":146},"The Co-operative Food":{"count":115},"Londis":{"count":352},"7-Eleven":{"count":4440},"CBA":{"count":135},"Coop":{"count":678},"Sale":{"count":80},"Statoil":{"count":69},"Sheetz":{"count":54},"Konzum":{"count":173},"Siwa":{"count":216},"Mercator":{"count":57},"Esso":{"count":67},"COOP Jednota":{"count":181},"Mac's":{"count":152},"Alepa":{"count":62},"Hasty Market":{"count":54},"K-Market":{"count":54},"Costcutter":{"count":292},"Valintatalo":{"count":62},"Casino":{"count":90},"Franprix":{"count":61},"Circle K":{"count":289},"セブンイレブン":{"count":3011,"tags":{"name:en":"7-Eleven"}},"ローソン":{"count":1596,"tags":{"name:en":"LAWSON"}},"BP":{"count":163},"Tesco":{"count":55},"Petit Casino":{"count":233},"Volg":{"count":116},"Mace":{"count":115},"Mini Market":{"count":272},"Nisa Local":{"count":77},"Dorfladen":{"count":75},"Продукты":{"count":4285},"Mini Stop":{"count":228},"LAWSON":{"count":419},"デイリーヤマザキ":{"count":141},"Biedronka":{"count":83},"Надежда":{"count":56},"Mobil":{"count":66},"Nisa":{"count":51},"Premier":{"count":129},"ABC":{"count":152},"ミニストップ":{"count":316,"tags":{"name:en":"MINISTOP"}},"サンクス":{"count":560,"tags":{"name:en":"sunkus"}},"スリーエフ":{"count":88},"8 à Huit":{"count":61},"Tchibo":{"count":56},"Żabka":{"count":546},"Almacen":{"count":229},"Vival":{"count":194},"FamilyMart":{"count":529},"ファミリーマート":{"count":1608,"tags":{"name:en":"FamilyMart"}},"Carrefour City":{"count":57},"Sunkus":{"count":62},"Casey's General Store":{"count":95},"セブンイレブン(Seven-Eleven)":{"count":65},"Jednota":{"count":58},"Магазин":{"count":915},"Гастроном":{"count":152},"Centra":{"count":111},"Магнит":{"count":701},"サークルK":{"count":538,"tags":{"name:en":"Circle K"}},"Wawa":{"count":135},"Proxi":{"count":123},"Универсам":{"count":78},"Перекресток":{"count":51},"Groszek":{"count":65},"Select":{"count":62},"Večerka":{"count":51},"Potraviny":{"count":249},"Смак":{"count":78},"Эконом":{"count":55},"Березка":{"count":77},"Społem":{"count":93},"Carrefour Express":{"count":84},"Cumberland Farms":{"count":63},"Chevron":{"count":59},"Coop Jednota":{"count":66},"Tesco Lotus Express":{"count":67},"Kiosk":{"count":55},"Sklep spożywczy":{"count":130},"24 часа":{"count":58},"Минимаркет":{"count":102},"Oxxo":{"count":669},"Пятёрочка":{"count":398},"abc":{"count":74},"7/11":{"count":51},"Stewart's":{"count":255},"Продукти":{"count":171},"ローソンストア100 (LAWSON STORE 100)":{"count":85},"Дикси":{"count":119},"Радуга":{"count":86},"ローソンストア100":{"count":76},"เซเว่นอีเลฟเว่น":{"count":185},"Delikatesy Centrum":{"count":53},"Citgo":{"count":62},"Фортуна":{"count":51},"Kum & Go":{"count":59},"Мария-Ра":{"count":76},"Picard":{"count":57},"Four Square":{"count":52},"Визит":{"count":57},"Авоська":{"count":55},"Dollar General":{"count":127},"Studenac":{"count":76},"Central Convenience Store":{"count":55},"Монетка":{"count":62},"продукты":{"count":114},"Теремок":{"count":56},"Kwik Trip":{"count":69},"Кулинария":{"count":55},"全家":{"count":90},"Мечта":{"count":54},"Epicerie":{"count":102},"Кировский":{"count":67},"Food Mart":{"count":117},"Delikatesy":{"count":81},"ポプラ":{"count":54},"Lewiatan":{"count":135},"Продуктовый магазин":{"count":149},"Продуктовый":{"count":84},"セイコーマート (Seicomart)":{"count":72},"Виктория":{"count":70},"Весна":{"count":57},"Mini Market Non-Stop":{"count":60},"QuikTrip":{"count":75},"Копеечка":{"count":51},"Royal Farms":{"count":51},"Alfamart":{"count":103},"Indomaret":{"count":141},"магазин":{"count":171},"全家便利商店":{"count":156},"Boutique":{"count":59},"მარკეტი (Market)":{"count":144},"Stores":{"count":61}},"chemist":{"dm":{"count":939},"Müller":{"count":212},"Schlecker":{"count":187},"Etos":{"count":467},"Bipa":{"count":289},"Rossmann":{"count":1669},"DM Drogeriemarkt":{"count":55},"Ihr Platz":{"count":73},"Douglas":{"count":62},"Kruidvat":{"count":123}},"car_repair":{"Peugeot":{"count":83},"Kwik Fit":{"count":128},"ATU":{"count":261},"Midas":{"count":202},"Feu Vert":{"count":113},"Norauto":{"count":152},"Speedy":{"count":115},"Автозапчасти":{"count":212},"Renault":{"count":171},"Pit Stop":{"count":58},"Jiffy Lube":{"count":198},"Шиномонтаж":{"count":1157},"СТО":{"count":395},"O'Reilly Auto Parts":{"count":81},"Carglass":{"count":112},"шиномонтаж":{"count":62},"Citroen":{"count":51},"Euromaster":{"count":87},"Firestone":{"count":88},"Автосервис":{"count":361},"Advance Auto Parts":{"count":52},"Roady":{"count":56}},"furniture":{"IKEA":{"count":169},"Jysk":{"count":109},"Roller":{"count":78},"Dänisches Bettenlager":{"count":309},"Conforama":{"count":99},"Matratzen Concord":{"count":52},"Мебель":{"count":210},"But":{"count":63}},"doityourself":{"Hornbach":{"count":123},"B&Q":{"count":225},"Hubo":{"count":77},"Mr Bricolage":{"count":88},"Gamma":{"count":111},"OBI":{"count":422},"Lowes":{"count":1152},"Wickes":{"count":123},"Hagebau":{"count":59},"Max Bahr":{"count":79},"Castorama":{"count":153},"Rona":{"count":61},"Home Depot":{"count":865},"Toom Baumarkt":{"count":71},"Homebase":{"count":225},"Baumax":{"count":95},"Lagerhaus":{"count":79},"Bauhaus":{"count":186},"Canadian Tire":{"count":97},"Leroy Merlin":{"count":209},"Hellweg":{"count":58},"Brico":{"count":98},"Bricomarché":{"count":235},"Toom":{"count":67},"Hagebaumarkt":{"count":107},"Praktiker":{"count":122},"Menards":{"count":70},"Weldom":{"count":73},"Bunnings Warehouse":{"count":91},"Ace Hardware":{"count":147},"Home Hardware":{"count":72},"Хозтовары":{"count":86},"Стройматериалы":{"count":197},"Bricorama":{"count":60},"Point P":{"count":59}},"stationery":{"Staples":{"count":299},"McPaper":{"count":83},"Office Depot":{"count":98},"Канцтовары":{"count":63}},"car":{"Skoda":{"count":97},"BMW":{"count":149},"Citroen":{"count":277},"Renault":{"count":382},"Mercedes-Benz":{"count":235},"Volvo":{"count":96},"Ford":{"count":239},"Volkswagen":{"count":217},"Mazda":{"count":105},"Mitsubishi":{"count":73},"Fiat":{"count":93},"Автозапчасти":{"count":277},"Opel":{"count":165},"Audi":{"count":121},"Toyota":{"count":271},"Nissan":{"count":189},"Suzuki":{"count":75},"Honda":{"count":157},"Peugeot":{"count":308},"Шиномонтаж":{"count":259},"Hyundai":{"count":166},"Subaru":{"count":58},"Chevrolet":{"count":86},"Автомагазин":{"count":72}},"clothes":{"Matalan":{"count":90},"KiK":{"count":1219},"H&M":{"count":658},"Urban Outfitters":{"count":63},"Vögele":{"count":132},"Zeeman":{"count":121},"Takko":{"count":515},"Adler":{"count":55},"C&A":{"count":506},"Zara":{"count":217},"Vero Moda":{"count":95},"NKD":{"count":486},"Ernsting's family":{"count":312},"Winners":{"count":65},"River Island":{"count":59},"Next":{"count":176},"Gap":{"count":81},"Adidas":{"count":92},"Woolworths":{"count":117},"Mr Price":{"count":88},"Jet":{"count":61},"Pep":{"count":134},"Edgars":{"count":110},"Ackermans":{"count":91},"Truworths":{"count":65},"Ross":{"count":93},"Burton":{"count":51},"Dorothy Perkins":{"count":53},"Deichmann":{"count":61},"Lindex":{"count":73},"s.Oliver":{"count":56},"Cecil":{"count":51},"Dress Barn":{"count":52},"Old Navy":{"count":174},"Jack & Jones":{"count":52},"Pimkie":{"count":73},"Esprit":{"count":231},"Primark":{"count":92},"Bonita":{"count":155},"Mexx":{"count":67},"Gerry Weber":{"count":71},"Tally Weijl":{"count":70},"Mango":{"count":133},"TK Maxx":{"count":84},"Benetton":{"count":101},"Ulla Popken":{"count":61},"AWG":{"count":66},"Tommy Hilfiger":{"count":75},"New Yorker":{"count":180},"Orsay":{"count":73},"Jeans Fritz":{"count":51},"Charles Vögele":{"count":69},"New Look":{"count":126},"Lacoste":{"count":78},"Etam":{"count":53},"Kiabi":{"count":148},"Jack Wolfskin":{"count":60},"American Apparel":{"count":57},"Men's Wearhouse":{"count":54},"Intimissimi":{"count":52},"United Colors of Benetton":{"count":96},"Jules":{"count":63},"Second Hand":{"count":53},"AOKI":{"count":57},"Calzedonia":{"count":68},"洋服の青山":{"count":100},"Levi's":{"count":63},"Celio":{"count":74},"TJ Maxx":{"count":57},"Promod":{"count":82},"Street One":{"count":72},"ユニクロ":{"count":59},"Banana Republic":{"count":57},"Одежда":{"count":75},"Marshalls":{"count":56},"La Halle":{"count":62},"Peacocks":{"count":89},"しまむら":{"count":60}},"books":{"Bruna":{"count":58},"Waterstones":{"count":90},"Libro":{"count":57},"Barnes & Noble":{"count":267},"Weltbild":{"count":74},"Thalia":{"count":121},"Книги":{"count":112}},"department_store":{"Debenhams":{"count":67},"Canadian Tire":{"count":75},"Karstadt":{"count":64},"Walmart":{"count":517},"Kmart":{"count":143},"Target":{"count":574},"Galeria Kaufhof":{"count":61},"Marks & Spencer":{"count":66},"Big W":{"count":57},"Woolworth":{"count":78},"Универмаг":{"count":72},"Sears":{"count":235},"Walmart Supercenter":{"count":101},"Kohl's":{"count":153},"Macy's":{"count":147},"Sam's Club":{"count":54},"JCPenney":{"count":66}},"alcohol":{"Alko":{"count":145},"The Beer Store":{"count":150},"Systembolaget":{"count":210},"LCBO":{"count":239},"Ароматный мир":{"count":62},"Bargain Booze":{"count":62},"Nicolas":{"count":119},"BWS":{"count":70},"Botilleria":{"count":77},"SAQ":{"count":72},"Gall & Gall":{"count":512},"Живое пиво":{"count":70}},"bakery":{"Kamps":{"count":252},"Banette":{"count":52},"Bäckerei Schmidt":{"count":57},"Anker":{"count":73},"Hofpfisterei":{"count":111},"Greggs":{"count":276},"Oebel":{"count":57},"Boulangerie":{"count":266},"Stadtbäckerei":{"count":57},"Steinecke":{"count":145},"Ihle":{"count":76},"Goldilocks":{"count":59},"Dat Backhus":{"count":67},"K&U":{"count":61},"Der Beck":{"count":96},"Thürmann":{"count":54},"Backwerk":{"count":95},"Schäfer's":{"count":51},"Panaderia":{"count":168},"Goeken backen":{"count":51},"Stadtbäckerei Junge":{"count":51},"Boulangerie Patisserie":{"count":119},"Paul":{"count":81},"Хлеб":{"count":89},"Пекарня":{"count":52},"Кулиничи":{"count":51}},"sports":{"Sports Direct":{"count":57},"Decathlon":{"count":309},"Intersport":{"count":283},"Sports Authority":{"count":75},"Спортмастер":{"count":87},"Sport 2000":{"count":90},"Dick's Sporting Goods":{"count":77}},"variety_store":{"Tedi":{"count":157},"Dollarama":{"count":103},"Family Dollar":{"count":61},"Dollar Tree":{"count":110},"Dollar General":{"count":80}},"pet":{"Fressnapf":{"count":318},"PetSmart":{"count":177},"Das Futterhaus":{"count":69},"Pets at Home":{"count":62},"Petco":{"count":101},"Зоомагазин":{"count":100}},"shoes":{"Deichmann":{"count":622},"Reno":{"count":183},"Ecco":{"count":55},"Clarks":{"count":109},"La Halle aux Chaussures":{"count":69},"Brantano":{"count":71},"Geox":{"count":51},"Salamander":{"count":51},"Обувь":{"count":100},"Payless Shoe Source":{"count":67},"Famous Footwear":{"count":59},"Quick Schuh":{"count":72},"Shoe Zone":{"count":55},"Foot Locker":{"count":82},"Bata":{"count":101},"ЦентрОбувь":{"count":51}},"toys":{"La Grande Récré":{"count":56},"Toys R Us":{"count":151,"tags":{"shop":"toys"}},"Intertoys":{"count":57},"Детский мир":{"count":86},"Игрушки":{"count":58}},"travel_agency":{"Flight Centre":{"count":92},"Thomas Cook":{"count":119}},"jewelry":{"Bijou Brigitte":{"count":57},"Christ":{"count":57},"Swarovski":{"count":74}},"optician":{"Fielmann":{"count":232},"Apollo Optik":{"count":150},"Vision Express":{"count":58},"Оптика":{"count":182},"Optic 2000":{"count":98},"Alain Afflelou":{"count":73},"Specsavers":{"count":124},"Krys":{"count":77},"Atol":{"count":55}},"video":{"Blockbuster":{"count":184},"World of Video":{"count":64}},"mobile_phone":{"Билайн":{"count":128},"ソフトバンクショップ (SoftBank shop)":{"count":255},"Vodafone":{"count":355},"O2":{"count":208},"Carphone Warehouse":{"count":127},"Orange":{"count":246},"Verizon Wireless":{"count":125},"Sprint":{"count":109},"T-Mobile":{"count":175},"МТС":{"count":352},"Евросеть":{"count":506},"Bell":{"count":190},"The Phone House":{"count":83},"SFR":{"count":71},"Связной":{"count":439},"Мегафон":{"count":251},"AT&T":{"count":124},"ドコモショップ (docomo shop)":{"count":114},"au":{"count":65},"Movistar":{"count":77},"Bitė":{"count":72}},"hifi":{},"computer":{"PC World":{"count":55},"DNS":{"count":128}},"hairdresser":{"Klier":{"count":119},"Supercuts":{"count":106},"Hairkiller":{"count":51},"Great Clips":{"count":182},"Парикмахерская":{"count":510},"Стиль":{"count":51},"Franck Provost":{"count":70},"Салон красоты":{"count":70}},"hardware":{"1000 мелочей":{"count":61},"Хозтовары":{"count":151},"Стройматериалы":{"count":54}},"motorcycle":{"Yamaha":{"count":67},"Honda":{"count":69}}}},"addressFormats":[{"format":[["housenumber","street"],["city","postcode"]]},{"countryCodes":["gb"],"format":[["housename"],["housenumber","street"],["city","postcode"]]},{"countryCodes":["ie"],"format":[["housename"],["housenumber","street"],["city"],["postcode"]]},{"countryCodes":["ad","at","ba","be","ch","cz","de","dk","es","fi","gr","hr","is","it","li","nl","no","pl","pt","se","si","sk","sm","va"],"format":[["street","housenumber"],["postcode","city"]]},{"countryCodes":["fr","lu","mo"],"format":[["housenumber","street"],["postcode","city"]]},{"countryCodes":["br"],"format":[["street"],["housenumber","suburb"],["city","postcode"]]},{"countryCodes":["vn"],"format":[["housenumber","street"],["subdistrict"],["district"],["city"],["province","postcode"]]},{"countryCodes":["us"],"format":[["housenumber","street"],["city","state","postcode"]]},{"countryCodes":["ca"],"format":[["housenumber","street"],["city","province","postcode"]]}]};